fuli-context 0.7.4-beta.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -6
- package/README.zh-CN.md +69 -6
- package/compose.graphiti.yml +6 -6
- package/dist/web/assets/AboutPage-ByCUor-j.js +1 -0
- package/dist/web/assets/ConnectionsPage-DkdkZ40Q.js +1 -0
- package/dist/web/assets/KnowledgeEditDialog-DSe3Gwep.js +1 -0
- package/dist/web/assets/KnowledgeInspector-CYAjAb9J.js +1 -0
- package/dist/web/assets/KnowledgeOrganizerPage-CV4F54R_.js +1 -0
- package/dist/web/assets/KnowledgePage-vYYXipOi.js +1 -0
- package/dist/web/assets/KnowledgeWorkspace-z4u5mXOG.js +4 -0
- package/dist/web/assets/OverviewPage-BWOfeS6k.js +1 -0
- package/dist/web/assets/PersonalProfilePage-c3w4-h7a.js +1 -0
- package/dist/web/assets/PersonalProjectsPage-B7AlLEwf.js +1 -0
- package/dist/web/assets/ProjectAgentsPage-CgftpIPB.css +1 -0
- package/dist/web/assets/ProjectAgentsPage-DTHcL_ox.js +11 -0
- package/dist/web/assets/PublicProjectsPage-DdH0oGB3.js +1 -0
- package/dist/web/assets/ReviewPage-BYIpcIHG.js +1 -0
- package/dist/web/assets/SearchableSelect-Dz13ClQb.js +1 -0
- package/dist/web/assets/SettingsPage-2VkbXgZi.js +1 -0
- package/dist/web/assets/SettingsPage-CwZp2ka4.css +1 -0
- package/dist/web/assets/WritingTastePage-BOPQZuva.js +1 -0
- package/dist/web/assets/{console-D_2zC4lm.js → console-BlAhujsH.js} +1 -1
- package/dist/web/assets/{conversation-launcher-settings-DQmMH2j7.js → conversation-launcher-settings-DTYxiLJt.js} +1 -1
- package/dist/web/assets/i18n-Ci3heuiL.js +9 -0
- package/dist/web/assets/{identity-DmGcY3Y6.js → identity-4_-v6cB7.js} +1 -1
- package/dist/web/assets/index-BnH5mcZx.css +1 -0
- package/dist/web/assets/index-C67Q0JY2.js +2 -0
- package/dist/web/assets/{model-CVoOdRsL.js → model-yG0YqUyZ.js} +1 -1
- package/dist/web/assets/{useApi-CROJJdhE-CBNg4CdH.js → useApi-CROJJdhE-twhdZArA.js} +1 -1
- package/dist/web/assets/vue-router-C-wot_Di.js +1 -0
- package/dist/web/index.html +6 -6
- package/graph-provider/fuli_graph/app.py +8 -0
- package/graph-provider/fuli_graph/collaboration_context.py +69 -6
- package/graph-provider/fuli_graph/knowledge_search.py +84 -5
- package/graph-provider/fuli_graph/model_validation.py +130 -0
- package/graph-provider/fuli_graph/models.py +24 -5
- package/graph-provider/fuli_graph/project_agent_access.py +54 -0
- package/graph-provider/fuli_graph/project_agent_executor_models.py +635 -0
- package/graph-provider/fuli_graph/project_agent_models.py +278 -0
- package/graph-provider/fuli_graph/project_agent_routes.py +597 -0
- package/graph-provider/fuli_graph/project_agent_task_models.py +542 -0
- package/graph-provider/fuli_graph/runtime.py +259 -0
- package/graph-provider/fuli_graph/search_projection.py +3 -0
- package/graph-provider/fuli_graph/store.py +6 -0
- package/graph-provider/fuli_graph/store_knowledge.py +62 -9
- package/graph-provider/fuli_graph/store_project_agent_executor_learning.py +756 -0
- package/graph-provider/fuli_graph/store_project_agent_executor_routing.py +601 -0
- package/graph-provider/fuli_graph/store_project_agent_executors.py +1087 -0
- package/graph-provider/fuli_graph/store_project_agent_task_reads.py +458 -0
- package/graph-provider/fuli_graph/store_project_agent_task_recruitment.py +699 -0
- package/graph-provider/fuli_graph/store_project_agent_task_staffing.py +409 -0
- package/graph-provider/fuli_graph/store_project_agent_tasks.py +1144 -0
- package/graph-provider/fuli_graph/store_project_agents.py +965 -0
- package/graph-provider/pyproject.toml +2 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/capturing-session-knowledge/SKILL.md +39 -0
- package/src/adaptive-runtime/executor-pool.js +127 -0
- package/src/adaptive-runtime/graph-services.js +166 -0
- package/src/adaptive-runtime/lease-client.js +335 -0
- package/src/adaptive-runtime/runtime-broker.js +318 -0
- package/src/adaptive-runtime/settings.js +111 -0
- package/src/adaptive-runtime/state.js +74 -0
- package/src/agent-tools/graph-definitions.js +396 -0
- package/src/agent-tools/graph-handlers.js +61 -0
- package/src/agent-tools/project-agent-definitions.js +307 -0
- package/src/backup/graph-backup.js +289 -0
- package/src/backup/identity-reconciliation.js +208 -0
- package/src/backup/runtime-adapters.js +269 -0
- package/src/cli/command-registry.js +6 -2
- package/src/cli/graph-data-command.js +112 -0
- package/src/cli/local-runtime-command.js +16 -2
- package/src/cli/setup-command.js +19 -3
- package/src/cli/update-command.js +4 -0
- package/src/cli.js +6 -0
- package/src/graphiti/collaboration-preference-projection.js +29 -1
- package/src/graphiti/collaboration-preference-workflow.js +121 -0
- package/src/graphiti/federated-application.js +53 -90
- package/src/graphiti/project-agent-control-plane.js +263 -0
- package/src/graphiti/project-agent-mapping.js +1003 -0
- package/src/graphiti/project-agent-workflows.js +557 -0
- package/src/graphiti/provider-client.js +270 -1
- package/src/http/api-router.js +63 -9
- package/src/http/graph-api-router.js +278 -0
- package/src/local-runtime/lifecycle.js +46 -10
- package/src/mcp/context-resources.js +15 -6
- package/src/mcp/create-mcp-server.js +51 -16
- package/src/mcp/instructions.js +7 -5
- package/src/mcp/runtime.js +17 -5
- package/src/mcp/session-id.js +38 -1
- package/src/mcp/tool-annotations.js +69 -0
- package/src/mcp-server.js +23 -6
- package/src/native-runtime/runtime.js +717 -0
- package/src/server.js +6 -2
- package/src/setup/agent-installation-status.js +7 -1
- package/src/setup/agents.js +3 -1
- package/src/setup/claude-code-config.js +3 -1
- package/src/setup/codex-bootstrap.js +11 -10
- package/src/setup/codex-config.js +7 -1
- package/src/setup/cursor-config.js +3 -1
- package/src/setup/graph-runtime.js +158 -13
- package/src/setup/neo4j-memory-profile.js +43 -0
- package/src/setup/options.js +38 -2
- package/src/setup/paths.js +14 -0
- package/src/setup/setup.js +37 -1
- package/src/system/resource-monitor.js +181 -16
- package/src/system/runtime-settings.js +10 -1
- package/src/system/system-service.js +27 -2
- package/dist/web/assets/AboutPage-Dpf5fRWv.js +0 -1
- package/dist/web/assets/ConnectionsPage-D21aUDCP.js +0 -1
- package/dist/web/assets/KnowledgeEditDialog-u7lpfN3j.js +0 -1
- package/dist/web/assets/KnowledgeInspector-k4xnHtXd.js +0 -1
- package/dist/web/assets/KnowledgeOrganizerPage-Bdj7Rn84.js +0 -1
- package/dist/web/assets/KnowledgePage-UHVAbC1W.js +0 -1
- package/dist/web/assets/KnowledgeWorkspace-Lq3d-MeC.js +0 -4
- package/dist/web/assets/OverviewPage-CycAgA1V.js +0 -1
- package/dist/web/assets/PersonalProfilePage-U9oIV5FT.js +0 -1
- package/dist/web/assets/PersonalProjectsPage-C5RpXKcA.js +0 -1
- package/dist/web/assets/PublicProjectsPage-DiWxm35E.js +0 -1
- package/dist/web/assets/ReviewPage-jxRfGSJK.js +0 -1
- package/dist/web/assets/SearchableSelect-B3-5IPup.js +0 -1
- package/dist/web/assets/SettingsPage-BqfGDOho.js +0 -1
- package/dist/web/assets/SettingsPage-CAfz4qiV.css +0 -1
- package/dist/web/assets/WritingTastePage-BJxhMqJR.js +0 -1
- package/dist/web/assets/i18n-CwqXDI1C.js +0 -5
- package/dist/web/assets/index-IUGLt4lG.js +0 -2
- package/dist/web/assets/index-X2j29j8i.css +0 -1
- package/dist/web/assets/vue-router-CWSsUUio.js +0 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
from datetime import date, 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
|
+
from .project_agent_models import (
|
|
9
|
+
ProjectAgentExecutorPolicy,
|
|
10
|
+
ProjectAgentModelStrategy,
|
|
11
|
+
ProjectAgentProfile,
|
|
12
|
+
ProjectAgentRecord,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ProjectAgentTaskDuration = Literal['ongoing', 'one_off']
|
|
17
|
+
ProjectAgentStaffingIntent = Literal[
|
|
18
|
+
'reuse_preferred',
|
|
19
|
+
'new_durable',
|
|
20
|
+
'temporary',
|
|
21
|
+
'unassigned',
|
|
22
|
+
]
|
|
23
|
+
ProjectAgentTaskStatus = Literal[
|
|
24
|
+
'awaiting_recruitment',
|
|
25
|
+
'queued',
|
|
26
|
+
'running',
|
|
27
|
+
'paused',
|
|
28
|
+
'failed',
|
|
29
|
+
'awaiting_review',
|
|
30
|
+
'blocked',
|
|
31
|
+
'completed',
|
|
32
|
+
'cancelled',
|
|
33
|
+
]
|
|
34
|
+
ProjectAgentParticipantRole = Literal['lead', 'collaborator']
|
|
35
|
+
ProjectAgentRoutingOutcome = Literal[
|
|
36
|
+
'assigned_existing',
|
|
37
|
+
'recruited',
|
|
38
|
+
'unassigned',
|
|
39
|
+
'recruitment_required',
|
|
40
|
+
'blocked',
|
|
41
|
+
]
|
|
42
|
+
ProjectAgentRoutingReason = Literal[
|
|
43
|
+
'explicit_agent',
|
|
44
|
+
'exact_work_kind',
|
|
45
|
+
'exact_capability',
|
|
46
|
+
'no_match',
|
|
47
|
+
'agent_unavailable',
|
|
48
|
+
'explicit_new_agent',
|
|
49
|
+
'explicit_temporary_agent',
|
|
50
|
+
'explicit_unassigned',
|
|
51
|
+
'hr_unavailable',
|
|
52
|
+
]
|
|
53
|
+
ProjectAgentPositionKind = Literal['durable', 'temporary']
|
|
54
|
+
ProjectAgentRecruitmentStatus = Literal[
|
|
55
|
+
'awaiting_confirmation',
|
|
56
|
+
'requested',
|
|
57
|
+
'fulfilled',
|
|
58
|
+
'cancelled',
|
|
59
|
+
'blocked',
|
|
60
|
+
'no_hr',
|
|
61
|
+
]
|
|
62
|
+
ProjectAgentRecruitmentConfirmationMode = Literal[
|
|
63
|
+
'automatic',
|
|
64
|
+
'require_confirmation',
|
|
65
|
+
]
|
|
66
|
+
ProjectAgentTaskComplexity = Literal['simple', 'standard', 'complex']
|
|
67
|
+
ProjectAgentOptimizationPriority = Literal[
|
|
68
|
+
'quality_and_acceptance',
|
|
69
|
+
'token_and_cost',
|
|
70
|
+
'time',
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _unique_text(value: list[str], label: str) -> list[str]:
|
|
75
|
+
normalized = [item.strip() for item in value]
|
|
76
|
+
if any(not item or len(item) > 512 for item in normalized):
|
|
77
|
+
raise ValueError(f'{label} must contain 1 to 512 characters')
|
|
78
|
+
if len({item.casefold() for item in normalized}) != len(normalized):
|
|
79
|
+
raise ValueError(f'{label} must be unique')
|
|
80
|
+
return normalized
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class ProjectAgentParallelPlan(StrictModel):
|
|
84
|
+
enabled: bool = False
|
|
85
|
+
independent_verification: bool = False
|
|
86
|
+
conflict_free_scopes: bool = False
|
|
87
|
+
reason: str | None = Field(default=None, min_length=1, max_length=2048)
|
|
88
|
+
workstream_boundaries: list[str] = Field(default_factory=list, max_length=16)
|
|
89
|
+
|
|
90
|
+
@field_validator('workstream_boundaries')
|
|
91
|
+
@classmethod
|
|
92
|
+
def validate_boundaries(cls, value: list[str]) -> list[str]:
|
|
93
|
+
return _unique_text(value, 'parallel workstream boundaries')
|
|
94
|
+
|
|
95
|
+
@model_validator(mode='after')
|
|
96
|
+
def validate_parallel_plan(self):
|
|
97
|
+
if self.enabled and not (
|
|
98
|
+
self.independent_verification
|
|
99
|
+
and self.conflict_free_scopes
|
|
100
|
+
and self.reason
|
|
101
|
+
and len(self.workstream_boundaries) >= 2
|
|
102
|
+
):
|
|
103
|
+
raise ValueError(
|
|
104
|
+
'parallel work requires independent verification, conflict-free '
|
|
105
|
+
'scopes, a reason, and at least two workstream boundaries'
|
|
106
|
+
)
|
|
107
|
+
if not self.enabled and self.workstream_boundaries:
|
|
108
|
+
raise ValueError('disabled parallel plan cannot contain workstreams')
|
|
109
|
+
return self
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class ProjectAgentTaskSubmit(StrictModel):
|
|
113
|
+
personal_space_id: str = Field(min_length=1, max_length=128)
|
|
114
|
+
personal_project_id: str = Field(min_length=1, max_length=128)
|
|
115
|
+
idempotency_key: str = Field(min_length=8, max_length=256)
|
|
116
|
+
title: str = Field(min_length=1, max_length=160)
|
|
117
|
+
objective: str = Field(min_length=1, max_length=4096)
|
|
118
|
+
work_kind: str = Field(min_length=1, max_length=128)
|
|
119
|
+
required_capabilities: list[str] = Field(default_factory=list, max_length=16)
|
|
120
|
+
duration: ProjectAgentTaskDuration = 'ongoing'
|
|
121
|
+
staffing_intent: ProjectAgentStaffingIntent = 'reuse_preferred'
|
|
122
|
+
lead_agent_id: str | None = Field(default=None, min_length=1, max_length=128)
|
|
123
|
+
collaborator_agent_ids: list[str] = Field(default_factory=list, max_length=16)
|
|
124
|
+
coordinator_agent_id: str | None = Field(default=None, min_length=1, max_length=128)
|
|
125
|
+
complexity_hint: ProjectAgentTaskComplexity | None = None
|
|
126
|
+
parallel_plan: ProjectAgentParallelPlan = Field(
|
|
127
|
+
default_factory=ProjectAgentParallelPlan
|
|
128
|
+
)
|
|
129
|
+
model_strategy_override: ProjectAgentModelStrategy | None = None
|
|
130
|
+
executor_policy_override: ProjectAgentExecutorPolicy | None = None
|
|
131
|
+
# Compatibility spelling used by the task store's executor hook.
|
|
132
|
+
executor_override: ProjectAgentExecutorPolicy | None = None
|
|
133
|
+
source_application: SourceApplication | None = None
|
|
134
|
+
source_session_id: str | None = Field(default=None, min_length=1, max_length=256)
|
|
135
|
+
routing_reason: str = Field(min_length=1, max_length=2048)
|
|
136
|
+
recruitment_profile: ProjectAgentProfile | None = None
|
|
137
|
+
|
|
138
|
+
@field_validator('required_capabilities')
|
|
139
|
+
@classmethod
|
|
140
|
+
def validate_capabilities(cls, value: list[str]) -> list[str]:
|
|
141
|
+
return _unique_text(value, 'required capabilities')
|
|
142
|
+
|
|
143
|
+
@field_validator('collaborator_agent_ids')
|
|
144
|
+
@classmethod
|
|
145
|
+
def validate_collaborators(cls, value: list[str]) -> list[str]:
|
|
146
|
+
return _unique_text(value, 'collaborator Agent IDs')
|
|
147
|
+
|
|
148
|
+
@model_validator(mode='after')
|
|
149
|
+
def validate_staffing(self):
|
|
150
|
+
if self.lead_agent_id and self.staffing_intent not in {
|
|
151
|
+
'reuse_preferred',
|
|
152
|
+
}:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
'explicit lead Agent requires reuse_preferred staffing intent'
|
|
155
|
+
)
|
|
156
|
+
if self.lead_agent_id in self.collaborator_agent_ids:
|
|
157
|
+
raise ValueError('lead Agent cannot also be a collaborator')
|
|
158
|
+
# The coordinator may fill missing collaborators from qualified durable
|
|
159
|
+
# assignments; the final participant minimum is checked after routing.
|
|
160
|
+
if self.staffing_intent == 'temporary' and self.duration != 'one_off':
|
|
161
|
+
raise ValueError('temporary staffing requires a one-off task')
|
|
162
|
+
if (
|
|
163
|
+
self.recruitment_profile
|
|
164
|
+
and self.recruitment_profile.agent_type != 'durable'
|
|
165
|
+
):
|
|
166
|
+
raise ValueError('recruitment profile agent_type must be durable input')
|
|
167
|
+
if self.executor_policy_override and self.executor_override:
|
|
168
|
+
raise ValueError(
|
|
169
|
+
'executor_policy_override and executor_override are mutually exclusive'
|
|
170
|
+
)
|
|
171
|
+
reject_credentials(self, 'project Agent task')
|
|
172
|
+
return self
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class ProjectAgentTaskParticipantRecord(StrictModel):
|
|
176
|
+
agent_id: str
|
|
177
|
+
role: ProjectAgentParticipantRole
|
|
178
|
+
status: ProjectAgentTaskStatus
|
|
179
|
+
assignment_summary: str | None = None
|
|
180
|
+
joined_at: datetime
|
|
181
|
+
updated_at: datetime
|
|
182
|
+
ended_at: datetime | None = None
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class ProjectAgentTaskExecutionSummary(StrictModel):
|
|
186
|
+
"""Auditable execution evidence projected onto a real task participant.
|
|
187
|
+
|
|
188
|
+
The participant identity is durable Agent data; the optional worker fields
|
|
189
|
+
identify a concrete subagent run when a client reports one. None means the
|
|
190
|
+
provider did not observe that fact and must not infer it from routing
|
|
191
|
+
configuration.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
agent_id: str
|
|
195
|
+
agent_name: str | None = None
|
|
196
|
+
occupation_emoji: str | None = None
|
|
197
|
+
participant_role: ProjectAgentParticipantRole
|
|
198
|
+
executor: str | None = None
|
|
199
|
+
executor_id: str | None = None
|
|
200
|
+
source_application: SourceApplication | None = None
|
|
201
|
+
actual_model_provider: str | None = None
|
|
202
|
+
actual_model: str | None = None
|
|
203
|
+
work_summary: str | None = None
|
|
204
|
+
status: ProjectAgentTaskStatus
|
|
205
|
+
worker_id: str | None = None
|
|
206
|
+
worker_label: str | None = None
|
|
207
|
+
worker_occupation_emoji: str | None = None
|
|
208
|
+
|
|
209
|
+
@field_validator('occupation_emoji', 'worker_occupation_emoji', mode='before')
|
|
210
|
+
@classmethod
|
|
211
|
+
def validate_emojis(cls, value):
|
|
212
|
+
return validate_emoji_sequence(value, 'occupation emoji')
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class ProjectAgentTaskEventRecord(StrictModel):
|
|
216
|
+
event_id: str
|
|
217
|
+
task_id: str
|
|
218
|
+
agent_id: str | None = None
|
|
219
|
+
status: ProjectAgentTaskStatus
|
|
220
|
+
actor_kind: Literal['agent', 'human', 'system', 'hr']
|
|
221
|
+
summary: str
|
|
222
|
+
source_application: SourceApplication | None = None
|
|
223
|
+
source_session_id: str | None = None
|
|
224
|
+
actual_model_provider: str | None = None
|
|
225
|
+
actual_model: str | None = None
|
|
226
|
+
actual_executor_id: str | None = None
|
|
227
|
+
executor_rule_id: str | None = None
|
|
228
|
+
matched_executor_rule_id: str | None = None
|
|
229
|
+
executor_selection_reason: str | None = None
|
|
230
|
+
executor_fallback_reason: str | None = None
|
|
231
|
+
executor_blocked_reason: str | None = None
|
|
232
|
+
worker_id: str | None = Field(
|
|
233
|
+
default=None,
|
|
234
|
+
validation_alias=AliasChoices('worker_id', 'workerId'),
|
|
235
|
+
)
|
|
236
|
+
worker_label: str | None = Field(
|
|
237
|
+
default=None,
|
|
238
|
+
validation_alias=AliasChoices('worker_label', 'workerLabel'),
|
|
239
|
+
)
|
|
240
|
+
worker_occupation_emoji: str | None = Field(
|
|
241
|
+
default=None,
|
|
242
|
+
validation_alias=AliasChoices(
|
|
243
|
+
'worker_occupation_emoji',
|
|
244
|
+
'workerOccupationEmoji',
|
|
245
|
+
),
|
|
246
|
+
)
|
|
247
|
+
worker_status: ProjectAgentTaskStatus | None = Field(
|
|
248
|
+
default=None,
|
|
249
|
+
validation_alias=AliasChoices('worker_status', 'workerStatus'),
|
|
250
|
+
)
|
|
251
|
+
created_at: datetime
|
|
252
|
+
|
|
253
|
+
@field_validator('worker_occupation_emoji', mode='before')
|
|
254
|
+
@classmethod
|
|
255
|
+
def validate_worker_occupation_emoji(cls, value):
|
|
256
|
+
return validate_emoji_sequence(value, 'worker occupation emoji')
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class ProjectAgentRoutingDecisionRecord(StrictModel):
|
|
260
|
+
decision_id: str
|
|
261
|
+
task_id: str
|
|
262
|
+
coordinator_agent_id: str
|
|
263
|
+
complexity: ProjectAgentTaskComplexity
|
|
264
|
+
complexity_basis: list[str] = Field(default_factory=list)
|
|
265
|
+
selected_model_strategy: ProjectAgentModelStrategy | None = None
|
|
266
|
+
model_strategy_source: Literal['agent', 'assignment', 'task', 'coordinator']
|
|
267
|
+
outcome: ProjectAgentRoutingOutcome
|
|
268
|
+
reason: ProjectAgentRoutingReason
|
|
269
|
+
match_basis: list[str] = Field(default_factory=list)
|
|
270
|
+
candidate_agent_ids: list[str] = Field(default_factory=list)
|
|
271
|
+
optimization_priority: list[ProjectAgentOptimizationPriority] = Field(
|
|
272
|
+
default_factory=lambda: [
|
|
273
|
+
'quality_and_acceptance',
|
|
274
|
+
'token_and_cost',
|
|
275
|
+
'time',
|
|
276
|
+
]
|
|
277
|
+
)
|
|
278
|
+
parallel_plan: ProjectAgentParallelPlan = Field(
|
|
279
|
+
default_factory=ProjectAgentParallelPlan
|
|
280
|
+
)
|
|
281
|
+
selected_executor_id: str | None = None
|
|
282
|
+
executor_rule_id: str | None = None
|
|
283
|
+
matched_executor_rule_id: str | None = None
|
|
284
|
+
executor_selection_reason: str | None = None
|
|
285
|
+
executor_fallback_outcome: str | None = None
|
|
286
|
+
executor_blocked_reason: str | None = None
|
|
287
|
+
executor_decision: dict[str, object] | None = None
|
|
288
|
+
executor_policy: ProjectAgentExecutorPolicy = Field(
|
|
289
|
+
default_factory=ProjectAgentExecutorPolicy
|
|
290
|
+
)
|
|
291
|
+
created_at: datetime
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class ProjectAgentTaskRecord(StrictModel):
|
|
295
|
+
task_id: str
|
|
296
|
+
personal_space_id: str
|
|
297
|
+
personal_project_id: str
|
|
298
|
+
title: str
|
|
299
|
+
objective: str
|
|
300
|
+
work_kind: str
|
|
301
|
+
required_capabilities: list[str]
|
|
302
|
+
duration: ProjectAgentTaskDuration
|
|
303
|
+
staffing_intent: ProjectAgentStaffingIntent
|
|
304
|
+
status: ProjectAgentTaskStatus
|
|
305
|
+
revision: int = Field(ge=0)
|
|
306
|
+
routing_outcome: ProjectAgentRoutingOutcome
|
|
307
|
+
routing_reason: ProjectAgentRoutingReason
|
|
308
|
+
routing_explanation: str
|
|
309
|
+
match_basis: list[str] = Field(default_factory=list)
|
|
310
|
+
coordinator_agent_id: str
|
|
311
|
+
complexity: ProjectAgentTaskComplexity
|
|
312
|
+
complexity_basis: list[str] = Field(default_factory=list)
|
|
313
|
+
routing_decision: ProjectAgentRoutingDecisionRecord
|
|
314
|
+
lead_agent_id: str | None = None
|
|
315
|
+
participants: list[ProjectAgentTaskParticipantRecord] = Field(default_factory=list)
|
|
316
|
+
execution_summary: list[ProjectAgentTaskExecutionSummary] = Field(
|
|
317
|
+
default_factory=list,
|
|
318
|
+
validation_alias=AliasChoices('execution_summary', 'executionSummary'),
|
|
319
|
+
)
|
|
320
|
+
effective_model_strategy: ProjectAgentModelStrategy | None = None
|
|
321
|
+
model_strategy_source: Literal[
|
|
322
|
+
'agent',
|
|
323
|
+
'assignment',
|
|
324
|
+
'task',
|
|
325
|
+
'coordinator',
|
|
326
|
+
] = 'coordinator'
|
|
327
|
+
executor_policy: ProjectAgentExecutorPolicy = Field(
|
|
328
|
+
default_factory=ProjectAgentExecutorPolicy
|
|
329
|
+
)
|
|
330
|
+
selected_executor_id: str | None = None
|
|
331
|
+
executor_rule_id: str | None = None
|
|
332
|
+
actual_run_id: str | None = None
|
|
333
|
+
actual_executor_id: str | None = None
|
|
334
|
+
actual_model_provider: str | None = None
|
|
335
|
+
actual_model: str | None = None
|
|
336
|
+
matched_executor_rule_id: str | None = None
|
|
337
|
+
executor_selection_reason: str | None = None
|
|
338
|
+
executor_fallback_outcome: str | None = None
|
|
339
|
+
executor_fallback_reason: str | None = None
|
|
340
|
+
executor_blocked_reason: str | None = None
|
|
341
|
+
executor_decision: dict[str, object] | None = None
|
|
342
|
+
hr_agent_id: str | None = None
|
|
343
|
+
recruitment_id: str | None = None
|
|
344
|
+
source_application: SourceApplication | None = None
|
|
345
|
+
source_session_id: str | None = None
|
|
346
|
+
result_summary: str | None = None
|
|
347
|
+
failure_reason: str | None = None
|
|
348
|
+
created_at: datetime
|
|
349
|
+
updated_at: datetime
|
|
350
|
+
completed_at: datetime | None = None
|
|
351
|
+
events: list[ProjectAgentTaskEventRecord] = Field(default_factory=list)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
class ProjectAgentTaskActivityCreate(StrictModel):
|
|
355
|
+
personal_space_id: str = Field(min_length=1, max_length=128)
|
|
356
|
+
personal_project_id: str = Field(min_length=1, max_length=128)
|
|
357
|
+
task_id: str = Field(min_length=1, max_length=128)
|
|
358
|
+
idempotency_key: str = Field(min_length=8, max_length=256)
|
|
359
|
+
expected_revision: int | None = Field(default=None, ge=0)
|
|
360
|
+
status: ProjectAgentTaskStatus
|
|
361
|
+
summary: str = Field(min_length=1, max_length=4096)
|
|
362
|
+
agent_id: str | None = Field(default=None, min_length=1, max_length=128)
|
|
363
|
+
actor_kind: Literal['agent', 'human'] = 'agent'
|
|
364
|
+
source_application: SourceApplication | None = None
|
|
365
|
+
source_session_id: str | None = Field(default=None, min_length=1, max_length=256)
|
|
366
|
+
actual_model_provider: str | None = Field(default=None, min_length=1, max_length=128)
|
|
367
|
+
actual_model: str | None = Field(default=None, min_length=1, max_length=256)
|
|
368
|
+
actual_executor_id: str | None = Field(default=None, min_length=1, max_length=128)
|
|
369
|
+
matched_executor_rule_id: str | None = Field(
|
|
370
|
+
default=None,
|
|
371
|
+
min_length=1,
|
|
372
|
+
max_length=128,
|
|
373
|
+
)
|
|
374
|
+
executor_selection_reason: str | None = Field(
|
|
375
|
+
default=None,
|
|
376
|
+
min_length=1,
|
|
377
|
+
max_length=2048,
|
|
378
|
+
)
|
|
379
|
+
executor_fallback_reason: str | None = Field(
|
|
380
|
+
default=None,
|
|
381
|
+
min_length=1,
|
|
382
|
+
max_length=2048,
|
|
383
|
+
)
|
|
384
|
+
executor_blocked_reason: str | None = Field(
|
|
385
|
+
default=None,
|
|
386
|
+
min_length=1,
|
|
387
|
+
max_length=2048,
|
|
388
|
+
)
|
|
389
|
+
worker_id: str | None = Field(
|
|
390
|
+
default=None,
|
|
391
|
+
min_length=1,
|
|
392
|
+
max_length=128,
|
|
393
|
+
validation_alias=AliasChoices('worker_id', 'workerId'),
|
|
394
|
+
)
|
|
395
|
+
worker_label: str | None = Field(
|
|
396
|
+
default=None,
|
|
397
|
+
min_length=1,
|
|
398
|
+
max_length=160,
|
|
399
|
+
validation_alias=AliasChoices('worker_label', 'workerLabel'),
|
|
400
|
+
)
|
|
401
|
+
worker_occupation_emoji: str | None = Field(
|
|
402
|
+
default=None,
|
|
403
|
+
min_length=1,
|
|
404
|
+
max_length=32,
|
|
405
|
+
validation_alias=AliasChoices(
|
|
406
|
+
'worker_occupation_emoji',
|
|
407
|
+
'workerOccupationEmoji',
|
|
408
|
+
),
|
|
409
|
+
)
|
|
410
|
+
worker_status: ProjectAgentTaskStatus | None = Field(
|
|
411
|
+
default=None,
|
|
412
|
+
validation_alias=AliasChoices('worker_status', 'workerStatus'),
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
@field_validator('worker_occupation_emoji', mode='before')
|
|
416
|
+
@classmethod
|
|
417
|
+
def validate_worker_occupation_emoji(cls, value):
|
|
418
|
+
return validate_emoji_sequence(value, 'worker occupation emoji')
|
|
419
|
+
|
|
420
|
+
@model_validator(mode='after')
|
|
421
|
+
def validate_actual_model(self):
|
|
422
|
+
if self.status in {'completed', 'failed'} and not self.agent_id:
|
|
423
|
+
raise ValueError(
|
|
424
|
+
'completed or failed activity requires the participating Agent ID'
|
|
425
|
+
)
|
|
426
|
+
if bool(self.actual_model_provider) != bool(self.actual_model):
|
|
427
|
+
raise ValueError('actual model provider and model must be reported together')
|
|
428
|
+
if bool(self.actual_executor_id) != bool(self.actual_model):
|
|
429
|
+
raise ValueError(
|
|
430
|
+
'actual executor, model provider, and model must be reported together'
|
|
431
|
+
)
|
|
432
|
+
if self.actual_executor_id and not self.agent_id:
|
|
433
|
+
raise ValueError('actual execution report requires the participating Agent ID')
|
|
434
|
+
if self.worker_id and not self.agent_id:
|
|
435
|
+
raise ValueError('worker execution report requires the participating Agent ID')
|
|
436
|
+
if (self.worker_label or self.worker_occupation_emoji) and not self.worker_id:
|
|
437
|
+
raise ValueError(
|
|
438
|
+
'worker label or occupation emoji requires a worker ID'
|
|
439
|
+
)
|
|
440
|
+
reject_credentials(self, 'project Agent task activity')
|
|
441
|
+
return self
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
class ProjectAgentRecruitmentRecord(StrictModel):
|
|
445
|
+
recruitment_id: str
|
|
446
|
+
personal_space_id: str
|
|
447
|
+
personal_project_id: str
|
|
448
|
+
task_id: str
|
|
449
|
+
coordinator_agent_id: str
|
|
450
|
+
hr_agent_id: str | None = None
|
|
451
|
+
position_kind: ProjectAgentPositionKind
|
|
452
|
+
work_kind: str
|
|
453
|
+
required_capabilities: list[str]
|
|
454
|
+
reason_code: ProjectAgentRoutingReason
|
|
455
|
+
reason: str
|
|
456
|
+
status: ProjectAgentRecruitmentStatus
|
|
457
|
+
confirmation_mode: ProjectAgentRecruitmentConfirmationMode
|
|
458
|
+
proposed_agent_id: str
|
|
459
|
+
proposed_profile: ProjectAgentProfile
|
|
460
|
+
trigger_source_application: SourceApplication | None = None
|
|
461
|
+
trigger_source_session_id: str | None = None
|
|
462
|
+
revision: int = Field(ge=0)
|
|
463
|
+
recruited_agent_id: str | None = None
|
|
464
|
+
test_source: str | None = Field(default=None, min_length=1, max_length=256)
|
|
465
|
+
cleanup_eligible: bool = False
|
|
466
|
+
created_at: datetime
|
|
467
|
+
updated_at: datetime
|
|
468
|
+
fulfilled_at: datetime | None = None
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class ProjectAgentTaskRouteResult(StrictModel):
|
|
472
|
+
task: ProjectAgentTaskRecord
|
|
473
|
+
assigned_agent: ProjectAgentRecord | None = None
|
|
474
|
+
recruitment: ProjectAgentRecruitmentRecord | None = None
|
|
475
|
+
decision: Literal[
|
|
476
|
+
'reused',
|
|
477
|
+
'recruited',
|
|
478
|
+
'unassigned',
|
|
479
|
+
'awaiting_confirmation',
|
|
480
|
+
'blocked',
|
|
481
|
+
]
|
|
482
|
+
must_disclose_recruitment: bool = False
|
|
483
|
+
client_notice: str | None = None
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class ProjectAgentRecruitmentPolicyRecord(StrictModel):
|
|
487
|
+
personal_space_id: str
|
|
488
|
+
confirmation_mode: ProjectAgentRecruitmentConfirmationMode = 'automatic'
|
|
489
|
+
updated_at: datetime | None = None
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class ProjectAgentRecruitmentPolicyUpdate(StrictModel):
|
|
493
|
+
personal_space_id: str = Field(min_length=1, max_length=128)
|
|
494
|
+
confirmation_mode: ProjectAgentRecruitmentConfirmationMode
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class ProjectAgentRecruitmentDecision(StrictModel):
|
|
498
|
+
personal_space_id: str = Field(min_length=1, max_length=128)
|
|
499
|
+
personal_project_id: str = Field(min_length=1, max_length=128)
|
|
500
|
+
recruitment_id: str = Field(min_length=1, max_length=128)
|
|
501
|
+
expected_revision: int = Field(ge=0)
|
|
502
|
+
decision: Literal['approve', 'cancel']
|
|
503
|
+
reason: str = Field(min_length=1, max_length=4096)
|
|
504
|
+
|
|
505
|
+
@model_validator(mode='after')
|
|
506
|
+
def reject_sensitive_values(self):
|
|
507
|
+
reject_credentials(self, 'project Agent recruitment decision')
|
|
508
|
+
return self
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
class ProjectAgentActivityTask(StrictModel):
|
|
512
|
+
task_id: str
|
|
513
|
+
title: str
|
|
514
|
+
status: Literal['completed', 'failed', 'cancelled']
|
|
515
|
+
summary: str
|
|
516
|
+
occurred_at: datetime
|
|
517
|
+
source_application: SourceApplication | None = None
|
|
518
|
+
actual_model_provider: str | None = None
|
|
519
|
+
actual_model: str | None = None
|
|
520
|
+
actual_executor_id: str | None = None
|
|
521
|
+
matched_executor_rule_id: str | None = None
|
|
522
|
+
worker_id: str | None = None
|
|
523
|
+
worker_label: str | None = None
|
|
524
|
+
worker_occupation_emoji: str | None = None
|
|
525
|
+
worker_status: ProjectAgentTaskStatus | None = None
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
class ProjectAgentActivityDay(StrictModel):
|
|
529
|
+
date: date
|
|
530
|
+
completed: int = Field(default=0, ge=0)
|
|
531
|
+
failed: int = Field(default=0, ge=0)
|
|
532
|
+
cancelled: int = Field(default=0, ge=0)
|
|
533
|
+
total: int = Field(default=0, ge=0)
|
|
534
|
+
tasks: list[ProjectAgentActivityTask] = Field(default_factory=list)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
class ProjectAgentActivityResult(StrictModel):
|
|
538
|
+
agent_id: str
|
|
539
|
+
personal_space_id: str
|
|
540
|
+
from_date: date
|
|
541
|
+
to_date: date
|
|
542
|
+
days: list[ProjectAgentActivityDay] = Field(default_factory=list)
|