fuli-context 0.7.5 → 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 (48) hide show
  1. package/dist/web/assets/{AboutPage-ByCUor-j.js → AboutPage-sLV9WChi.js} +1 -1
  2. package/dist/web/assets/{ConnectionsPage-DkdkZ40Q.js → ConnectionsPage-BWn4ywGJ.js} +1 -1
  3. package/dist/web/assets/{KnowledgeEditDialog-DSe3Gwep.js → KnowledgeEditDialog-CZ5ziPrD.js} +1 -1
  4. package/dist/web/assets/{KnowledgeInspector-CYAjAb9J.js → KnowledgeInspector-CRQWOaos.js} +1 -1
  5. package/dist/web/assets/{KnowledgeOrganizerPage-CV4F54R_.js → KnowledgeOrganizerPage-Dfj3vIpU.js} +1 -1
  6. package/dist/web/assets/KnowledgePage-BRYC9S5Y.js +1 -0
  7. package/dist/web/assets/{KnowledgeWorkspace-z4u5mXOG.js → KnowledgeWorkspace-ChEB5Bwk.js} +1 -1
  8. package/dist/web/assets/{OverviewPage-BWOfeS6k.js → OverviewPage-Cd66M0RT.js} +1 -1
  9. package/dist/web/assets/{PersonalProfilePage-c3w4-h7a.js → PersonalProfilePage-RCFHL0Wz.js} +1 -1
  10. package/dist/web/assets/PersonalProjectsPage-DEh8XWby.js +1 -0
  11. package/dist/web/assets/ProjectAgentsPage-Crh7PrXa.css +1 -0
  12. package/dist/web/assets/ProjectAgentsPage-DPnaH-TR.js +11 -0
  13. package/dist/web/assets/{PublicProjectsPage-DdH0oGB3.js → PublicProjectsPage-mstPEjHe.js} +1 -1
  14. package/dist/web/assets/{ReviewPage-BYIpcIHG.js → ReviewPage-6Y1SmfZy.js} +1 -1
  15. package/dist/web/assets/{SearchableSelect-Dz13ClQb.js → SearchableSelect-D3HM8YF8.js} +1 -1
  16. package/dist/web/assets/{SettingsPage-2VkbXgZi.js → SettingsPage--LdTMUm7.js} +1 -1
  17. package/dist/web/assets/{WritingTastePage-BOPQZuva.js → WritingTastePage-CIpKswvs.js} +1 -1
  18. package/dist/web/assets/{console-BlAhujsH.js → console-BT1P2Db4.js} +1 -1
  19. package/dist/web/assets/{conversation-launcher-settings-DTYxiLJt.js → conversation-launcher-settings-DrJEotdf.js} +1 -1
  20. package/dist/web/assets/{i18n-Ci3heuiL.js → i18n-js6gfc7j.js} +2 -2
  21. package/dist/web/assets/{identity-4_-v6cB7.js → identity-CfDfanpa.js} +1 -1
  22. package/dist/web/assets/{index-C67Q0JY2.js → index-GqJf1xqg.js} +2 -2
  23. package/dist/web/assets/{model-yG0YqUyZ.js → model-DJkLAJsg.js} +1 -1
  24. package/dist/web/assets/{useApi-CROJJdhE-twhdZArA.js → useApi-CROJJdhE-BdSti7Y2.js} +1 -1
  25. package/dist/web/assets/{vue-router-C-wot_Di.js → vue-router-Kk67EaCP.js} +1 -1
  26. package/dist/web/index.html +5 -5
  27. package/graph-provider/fuli_graph/project_agent_coordination_models.py +22 -0
  28. package/graph-provider/fuli_graph/project_agent_routes.py +29 -0
  29. package/graph-provider/fuli_graph/project_agent_task_models.py +3 -0
  30. package/graph-provider/fuli_graph/store_project_agent_coordination_policy.py +122 -0
  31. package/graph-provider/fuli_graph/store_project_agent_task_recruitment.py +9 -3
  32. package/graph-provider/fuli_graph/store_project_agent_task_staffing.py +177 -0
  33. package/graph-provider/fuli_graph/store_project_agent_tasks.py +7 -0
  34. package/graph-provider/pyproject.toml +1 -1
  35. package/npm-shrinkwrap.json +2 -2
  36. package/package.json +1 -1
  37. package/src/agent-tools/graph-definitions.js +23 -0
  38. package/src/agent-tools/graph-handlers.js +4 -0
  39. package/src/graphiti/project-agent-control-plane.js +12 -0
  40. package/src/graphiti/project-agent-mapping.js +21 -0
  41. package/src/graphiti/project-agent-workflows.js +19 -0
  42. package/src/graphiti/provider-client.js +12 -0
  43. package/src/http/graph-api-router.js +12 -0
  44. package/src/mcp/tool-annotations.js +2 -0
  45. package/dist/web/assets/KnowledgePage-vYYXipOi.js +0 -1
  46. package/dist/web/assets/PersonalProjectsPage-B7AlLEwf.js +0 -1
  47. package/dist/web/assets/ProjectAgentsPage-CgftpIPB.css +0 -1
  48. package/dist/web/assets/ProjectAgentsPage-DTHcL_ox.js +0 -11
@@ -1,5 +1,7 @@
1
1
  """Agent assignment selection, history continuity, and parallel staffing."""
2
2
 
3
+ from datetime import datetime
4
+
3
5
  from fastapi import HTTPException
4
6
 
5
7
  from .project_agent_access import authorize_project_agent
@@ -50,6 +52,26 @@ class StoreProjectAgentTaskStaffing:
50
52
  else 'explicit_new_agent',
51
53
  ['user explicitly requested recruitment'],
52
54
  )
55
+ policy = await self.get_project_agent_coordination_policy(
56
+ actor,
57
+ request.personal_space_id,
58
+ request.personal_project_id,
59
+ )
60
+ if not policy.auto_reuse_previous_agent:
61
+ return [], rows, 'manual_agent_selection', [
62
+ 'project policy requires an explicit @Agent selection',
63
+ ]
64
+ continuity, project_history = await self._rank_project_continuity(
65
+ rows,
66
+ request,
67
+ )
68
+ if continuity:
69
+ selected = continuity[0]
70
+ return [selected], continuity, 'project_continuity', [
71
+ self._project_history_match_basis(
72
+ project_history.get(selected['agent_id']),
73
+ ),
74
+ ]
53
75
  normalized_work_kind = request.work_kind.casefold()
54
76
  required = {item.casefold() for item in request.required_capabilities}
55
77
  candidates, history = await self._rank_agent_candidates(rows, request)
@@ -75,6 +97,10 @@ class StoreProjectAgentTaskStaffing:
75
97
  'matching Agent is unavailable to source client: '
76
98
  f'{request.source_application or "other"}',
77
99
  ]
100
+ if len(rows) == 1:
101
+ return [rows[0]], rows, 'sole_active_assignment', [
102
+ 'the project has one active Agent assignment',
103
+ ]
78
104
  return [], rows, 'no_match', ['no active assignment matched exactly']
79
105
  selected = candidates[0]
80
106
  if normalized_work_kind in {
@@ -128,6 +154,107 @@ class StoreProjectAgentTaskStaffing:
128
154
  )
129
155
  return [item[1] for item in scored], history
130
156
 
157
+ async def _rank_project_continuity(self, rows, request):
158
+ """Prefer the last effective project lead before task-type matching."""
159
+
160
+ if not rows:
161
+ return [], {}
162
+ history = await self._historical_project_agent_outcomes(
163
+ request.personal_space_id,
164
+ request.personal_project_id,
165
+ [row['agent_id'] for row in rows],
166
+ )
167
+ candidates = [
168
+ row
169
+ for row in rows
170
+ if self._metric_int(
171
+ (history.get(row['agent_id']) or {}).get('participation_count')
172
+ ) > 0
173
+ ]
174
+ candidates.sort(
175
+ key=lambda row: (
176
+ *self._project_history_sort_key(history.get(row['agent_id'])),
177
+ row['assigned_at'],
178
+ row['agent_id'],
179
+ )
180
+ )
181
+ return candidates, history
182
+
183
+ async def _historical_project_agent_outcomes(
184
+ self,
185
+ personal_space_id,
186
+ personal_project_id,
187
+ agent_ids,
188
+ ):
189
+ """Read cross-work-kind lead history for sticky project continuity."""
190
+
191
+ if not agent_ids:
192
+ return {}
193
+ runtime = getattr(self, 'runtime', None)
194
+ driver = getattr(runtime, 'driver', None)
195
+ if driver is None:
196
+ return {}
197
+ records, _, _ = await driver.execute_query(
198
+ '''
199
+ MATCH (space:FuliSpace {id: $personal_space_id, kind: 'personal'})-
200
+ [:HAS_PROJECT_AGENT_TASK]->
201
+ (task:FuliProjectAgentTask {
202
+ personal_space_id: $personal_space_id,
203
+ personal_project_id: $personal_project_id
204
+ })-[participant:HAS_PARTICIPANT]->
205
+ (agent:FuliProjectAgent)
206
+ WHERE agent.agent_id IN $agent_ids
207
+ AND (participant.role = 'lead'
208
+ OR task.lead_agent_id = agent.agent_id)
209
+ OPTIONAL MATCH (task)-[:HAS_TASK_EVENT]->
210
+ (event:FuliProjectAgentTaskEvent)-[:EVENT_AGENT]->(agent)
211
+ RETURN agent.agent_id AS agent_id,
212
+ count(DISTINCT task.task_id) AS participation_count,
213
+ count(DISTINCT CASE
214
+ WHEN participant.status = 'completed'
215
+ OR event.status = 'completed'
216
+ THEN task.task_id END
217
+ ) AS completed_count,
218
+ count(DISTINCT CASE
219
+ WHEN participant.status = 'failed'
220
+ OR event.status = 'failed'
221
+ THEN task.task_id END
222
+ ) AS failed_count,
223
+ count(DISTINCT CASE
224
+ WHEN participant.status = 'cancelled'
225
+ OR event.status = 'cancelled'
226
+ THEN task.task_id END
227
+ ) AS cancelled_count,
228
+ max(task.updated_at) AS last_task_at,
229
+ max(CASE
230
+ WHEN participant.status = 'completed'
231
+ OR event.status = 'completed'
232
+ THEN coalesce(event.created_at, task.updated_at) END
233
+ ) AS last_completed_at
234
+ ''',
235
+ personal_space_id=personal_space_id,
236
+ personal_project_id=personal_project_id,
237
+ agent_ids=list(agent_ids),
238
+ routing_='r',
239
+ )
240
+ result = {}
241
+ for row in records or []:
242
+ raw = dict(row)
243
+ agent_id = raw.get('agent_id')
244
+ if not agent_id:
245
+ continue
246
+ result[agent_id] = {
247
+ 'participation_count': self._metric_int(
248
+ raw.get('participation_count')
249
+ ),
250
+ 'completed_count': self._metric_int(raw.get('completed_count')),
251
+ 'failed_count': self._metric_int(raw.get('failed_count')),
252
+ 'cancelled_count': self._metric_int(raw.get('cancelled_count')),
253
+ 'last_task_at': raw.get('last_task_at'),
254
+ 'last_completed_at': raw.get('last_completed_at'),
255
+ }
256
+ return result
257
+
131
258
  async def _historical_agent_outcomes(
132
259
  self,
133
260
  personal_space_id,
@@ -227,6 +354,56 @@ class StoreProjectAgentTaskStaffing:
227
354
  -participation,
228
355
  )
229
356
 
357
+ @classmethod
358
+ def _project_history_sort_key(cls, history):
359
+ history = history or {}
360
+ completed = cls._metric_int(history.get('completed_count'))
361
+ failed = cls._metric_int(history.get('failed_count'))
362
+ cancelled = cls._metric_int(history.get('cancelled_count'))
363
+ participation = cls._metric_int(history.get('participation_count'))
364
+ effective_time = (
365
+ history.get('last_completed_at')
366
+ if completed > 0
367
+ else history.get('last_task_at')
368
+ )
369
+ outcome_score = completed * 3 - failed * 2 - cancelled
370
+ return (
371
+ 0 if completed > 0 else 1,
372
+ -cls._history_timestamp(effective_time),
373
+ -outcome_score,
374
+ -participation,
375
+ )
376
+
377
+ @staticmethod
378
+ def _history_timestamp(value):
379
+ if value is None:
380
+ return 0.0
381
+ if hasattr(value, 'to_native'):
382
+ value = value.to_native()
383
+ if hasattr(value, 'timestamp'):
384
+ try:
385
+ return float(value.timestamp())
386
+ except (TypeError, ValueError, OSError):
387
+ return 0.0
388
+ try:
389
+ return datetime.fromisoformat(
390
+ str(value).replace('Z', '+00:00')
391
+ ).timestamp()
392
+ except (TypeError, ValueError, OSError):
393
+ return 0.0
394
+
395
+ @classmethod
396
+ def _project_history_match_basis(cls, history):
397
+ history = history or {}
398
+ participation = cls._metric_int(history.get('participation_count'))
399
+ completed = cls._metric_int(history.get('completed_count'))
400
+ if completed:
401
+ return (
402
+ 'last successful project lead continuity: '
403
+ f'{participation} prior task(s), {completed} completed'
404
+ )
405
+ return f'most recent project lead continuity: {participation} prior task(s)'
406
+
230
407
  @classmethod
231
408
  def _history_match_basis(cls, history, work_kind):
232
409
  if not history:
@@ -29,12 +29,16 @@ from .store_project_agents import SYSTEM_COORDINATOR_AGENT_ID
29
29
  from .store_project_agent_task_reads import StoreProjectAgentTaskReads
30
30
  from .store_project_agent_task_recruitment import StoreProjectAgentTaskRecruitment
31
31
  from .store_project_agent_task_staffing import StoreProjectAgentTaskStaffing
32
+ from .store_project_agent_coordination_policy import (
33
+ StoreProjectAgentCoordinationPolicy,
34
+ )
32
35
 
33
36
 
34
37
  TERMINAL_TASK_STATUSES = {'completed', 'failed', 'cancelled'}
35
38
 
36
39
 
37
40
  class StoreProjectAgentTasks(
41
+ StoreProjectAgentCoordinationPolicy,
38
42
  StoreProjectAgentTaskRecruitment,
39
43
  StoreProjectAgentTaskReads,
40
44
  # Keep the pre-existing base order ahead of the extracted implementation.
@@ -170,6 +174,9 @@ class StoreProjectAgentTasks(
170
174
  reason = 'explicit_unassigned'
171
175
  routing_outcome = 'unassigned'
172
176
  task_status = 'blocked'
177
+ elif reason == 'manual_agent_selection':
178
+ routing_outcome = 'unassigned'
179
+ task_status = 'blocked'
173
180
  elif not lead or request.staffing_intent in {'new_durable', 'temporary'}:
174
181
  recruitment, recruited = await self._open_recruitment(
175
182
  actor,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fuli-graph-provider"
3
- version = "0.7.5"
3
+ version = "0.7.6"
4
4
  description = "Graphiti-backed personal and shared project provider for Fuli."
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "fuli-context",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "fuli-context",
9
- "version": "0.7.5",
9
+ "version": "0.7.6",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@hono/node-server": "2.0.12",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fuli-context",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Local-first collaboration relationship graph for AI agents.",
5
5
  "type": "module",
6
6
  "files": [
@@ -780,6 +780,29 @@ export const GRAPH_TOOL_DEFINITIONS = [
780
780
  toDate: nullableStringSchema()
781
781
  }, ['personalSpaceId', 'agentId'])
782
782
  },
783
+ {
784
+ name: 'get_project_agent_coordination_policy',
785
+ title: 'READ · Get project Agent continuity policy',
786
+ description: 'Read the exact project policy for asking before recruitment and automatically reusing the previous effective Agent. Both switches default on.',
787
+ inputSchema: objectSchema({
788
+ personalSpaceId: id,
789
+ personalProjectId: id
790
+ }, ['personalSpaceId', 'personalProjectId'])
791
+ },
792
+ {
793
+ name: 'update_project_agent_coordination_policy',
794
+ title: 'WRITE · Set project Agent continuity policy',
795
+ description: 'Persist the exact project switches for asking before recruitment and automatically reusing its previous effective Agent. This changes policy only and never starts a worker.',
796
+ inputSchema: objectSchema({
797
+ personalSpaceId: id,
798
+ personalProjectId: id,
799
+ askBeforeRecruitment: booleanSchema(),
800
+ autoReusePreviousAgent: booleanSchema()
801
+ }, [
802
+ 'personalSpaceId', 'personalProjectId',
803
+ 'askBeforeRecruitment', 'autoReusePreviousAgent'
804
+ ])
805
+ },
783
806
  {
784
807
  name: 'get_project_agent_recruitment_policy',
785
808
  title: 'READ · Get recruitment policy',
@@ -92,6 +92,10 @@ const HANDLERS = Object.freeze({
92
92
  record_project_agent_task_activity: (app, input) =>
93
93
  app.recordProjectAgentTaskActivity(input),
94
94
  view_project_agent_activity: (app, input) => app.viewProjectAgentActivity(input),
95
+ get_project_agent_coordination_policy: (app, input) =>
96
+ app.getProjectAgentCoordinationPolicy(input),
97
+ update_project_agent_coordination_policy: (app, input) =>
98
+ app.updateProjectAgentCoordinationPolicy(input),
95
99
  get_project_agent_recruitment_policy: (app, input) =>
96
100
  app.getProjectAgentRecruitmentPolicy(input),
97
101
  update_project_agent_recruitment_policy: (app, input) =>
@@ -13,6 +13,7 @@ import {
13
13
  getExecutorRoutingRule as getExecutorRoutingRuleWorkflow,
14
14
  getProjectAgent as getProjectAgentWorkflow,
15
15
  getProjectAgentContext as getProjectAgentContextWorkflow,
16
+ getProjectAgentCoordinationPolicy as getProjectAgentCoordinationPolicyWorkflow,
16
17
  getProjectAgentRecruitmentPolicy as getProjectAgentRecruitmentPolicyWorkflow,
17
18
  ignoreProjectAgentRoutingLearning as ignoreProjectAgentRoutingLearningWorkflow,
18
19
  listCurrentProjectAgents as listCurrentProjectAgentsWorkflow,
@@ -32,6 +33,7 @@ import {
32
33
  resetProjectAgentRoutingLearning as resetProjectAgentRoutingLearningWorkflow,
33
34
  submitProjectAgentTask as submitProjectAgentTaskWorkflow,
34
35
  updateExecutorRoutingRule as updateExecutorRoutingRuleWorkflow,
36
+ updateProjectAgentCoordinationPolicy as updateProjectAgentCoordinationPolicyWorkflow,
35
37
  updateProjectAgentRecruitmentPolicy as updateProjectAgentRecruitmentPolicyWorkflow,
36
38
  upsertExecutor as upsertExecutorWorkflow,
37
39
  upsertExecutorRoutingRule as upsertExecutorRoutingRuleWorkflow,
@@ -134,6 +136,16 @@ export class ProjectAgentControlPlaneApplication {
134
136
  return viewProjectAgentActivityWorkflow(this, input);
135
137
  }
136
138
 
139
+ async getProjectAgentCoordinationPolicy(input) {
140
+ this.#assertSpace(input.personalSpaceId);
141
+ return getProjectAgentCoordinationPolicyWorkflow(this, input);
142
+ }
143
+
144
+ async updateProjectAgentCoordinationPolicy(input) {
145
+ this.#assertSpace(input.personalSpaceId);
146
+ return updateProjectAgentCoordinationPolicyWorkflow(this, input);
147
+ }
148
+
137
149
  async getProjectAgentRecruitmentPolicy(input) {
138
150
  this.#assertSpace(input.personalSpaceId);
139
151
  return getProjectAgentRecruitmentPolicyWorkflow(this, input);
@@ -612,6 +612,27 @@ export function projectAgentRecruitmentPolicyRecord(value = {}) {
612
612
  };
613
613
  }
614
614
 
615
+ export function projectAgentCoordinationPolicyRecord(value = {}) {
616
+ return {
617
+ personalSpaceId: value.personal_space_id,
618
+ personalProjectId: value.personal_project_id,
619
+ askBeforeRecruitment: value.ask_before_recruitment ?? true,
620
+ autoReusePreviousAgent: value.auto_reuse_previous_agent ?? true,
621
+ updatedAt: value.updated_at ?? null
622
+ };
623
+ }
624
+
625
+ export function providerProjectAgentCoordinationPolicy(input) {
626
+ return {
627
+ personal_space_id: input.personalSpaceId ?? input.personal_space_id,
628
+ personal_project_id: input.personalProjectId ?? input.personal_project_id,
629
+ ask_before_recruitment:
630
+ input.askBeforeRecruitment ?? input.ask_before_recruitment ?? true,
631
+ auto_reuse_previous_agent:
632
+ input.autoReusePreviousAgent ?? input.auto_reuse_previous_agent ?? true
633
+ };
634
+ }
635
+
615
636
  export function providerProjectAgentRecruitmentDecision(input) {
616
637
  return {
617
638
  personal_space_id: input.personalSpaceId ?? input.personal_space_id,
@@ -4,6 +4,7 @@ import {
4
4
  executorRoutingRuleRecord,
5
5
  projectAgentActivityRecord,
6
6
  projectAgentAssignmentRecord,
7
+ projectAgentCoordinationPolicyRecord,
7
8
  projectAgentRecruitmentPolicyRecord,
8
9
  projectAgentRecruitmentRecord,
9
10
  projectAgentTaskRecord,
@@ -20,6 +21,7 @@ import {
20
21
  providerProjectAgentAssignment,
21
22
  providerProjectAgentAssignmentEnd,
22
23
  providerProjectAgentAssignmentReplace,
24
+ providerProjectAgentCoordinationPolicy,
23
25
  providerProjectAgentRecruitmentDecision,
24
26
  providerProjectAgentTaskActivity,
25
27
  providerProjectAgentTaskOutcome,
@@ -272,6 +274,23 @@ export async function viewProjectAgentActivity(application, input) {
272
274
  return projectAgentActivityRecord(value);
273
275
  }
274
276
 
277
+ export async function getProjectAgentCoordinationPolicy(application, input) {
278
+ return projectAgentCoordinationPolicyRecord(
279
+ await application.personal.getProjectAgentCoordinationPolicy(
280
+ input.personalSpaceId,
281
+ input.personalProjectId
282
+ )
283
+ );
284
+ }
285
+
286
+ export async function updateProjectAgentCoordinationPolicy(application, input) {
287
+ return projectAgentCoordinationPolicyRecord(
288
+ await application.personal.updateProjectAgentCoordinationPolicy(
289
+ providerProjectAgentCoordinationPolicy(input)
290
+ )
291
+ );
292
+ }
293
+
275
294
  export async function getProjectAgentRecruitmentPolicy(application, input) {
276
295
  return projectAgentRecruitmentPolicyRecord(
277
296
  await application.personal.getProjectAgentRecruitmentPolicy(input.personalSpaceId)
@@ -200,6 +200,18 @@ export class GraphitiProviderClient {
200
200
  `/v1/project-agents/${encodeURIComponent(agentId)}/activity?${query}`
201
201
  );
202
202
  }
203
+ getProjectAgentCoordinationPolicy(personalSpaceId, personalProjectId) {
204
+ const query = new URLSearchParams({
205
+ personal_space_id: personalSpaceId,
206
+ personal_project_id: personalProjectId
207
+ });
208
+ return this.#request(`/v1/project-agent-coordination-policy?${query}`);
209
+ }
210
+ updateProjectAgentCoordinationPolicy(input) {
211
+ return this.#request('/v1/project-agent-coordination-policy', {
212
+ method: 'PUT', body: input
213
+ });
214
+ }
203
215
  getProjectAgentRecruitmentPolicy(personalSpaceId) {
204
216
  const query = new URLSearchParams({ personal_space_id: personalSpaceId });
205
217
  return this.#request(`/v1/project-agent-recruitment-policy?${query}`);
@@ -283,6 +283,18 @@ export async function handleGraphApiRequest({
283
283
  sendJson(response, 200, await app.recordProjectAgentTaskActivity(await readJson(request)));
284
284
  return true;
285
285
  }
286
+ if (url.pathname === '/api/project-agent-coordination-policy' && request.method === 'GET') {
287
+ sendJson(response, 200, await app.getProjectAgentCoordinationPolicy({
288
+ personalSpaceId: url.searchParams.get('personalSpaceId'),
289
+ personalProjectId: url.searchParams.get('personalProjectId')
290
+ }));
291
+ return true;
292
+ }
293
+ if (url.pathname === '/api/project-agent-coordination-policy' &&
294
+ (request.method === 'PUT' || request.method === 'PATCH')) {
295
+ sendJson(response, 200, await app.updateProjectAgentCoordinationPolicy(await readJson(request)));
296
+ return true;
297
+ }
286
298
  if (url.pathname === '/api/project-agent-recruitment-policy' && request.method === 'GET') {
287
299
  sendJson(response, 200, await app.getProjectAgentRecruitmentPolicy({
288
300
  personalSpaceId: url.searchParams.get('personalSpaceId')
@@ -13,6 +13,7 @@ const READ_TOOLS = new Set([
13
13
  'get_project_agent_context',
14
14
  'view_project_agent_task',
15
15
  'view_project_agent_activity',
16
+ 'get_project_agent_coordination_policy',
16
17
  'get_project_agent_recruitment_policy',
17
18
  'list_project_agent_recruitments',
18
19
  'list_executors',
@@ -61,6 +62,7 @@ const WRITE_TOOLS = new Set([
61
62
  'release_runtime_lease',
62
63
  'submit_project_agent_task',
63
64
  'record_project_agent_task_activity',
65
+ 'update_project_agent_coordination_policy',
64
66
  'update_project_agent_recruitment_policy',
65
67
  'decide_project_agent_recruitment',
66
68
  'upsert_executor',
@@ -1 +0,0 @@
1
- import{C as e,_ as t,j as n}from"./i18n-Ci3heuiL.js";import{t as r}from"./KnowledgeWorkspace-z4u5mXOG.js";var i=e({__name:`KnowledgePage`,setup(e){return(e,i)=>(n(),t(r))}});export{i as default};
@@ -1 +0,0 @@
1
- import{C as e,_ as t,j as n}from"./i18n-Ci3heuiL.js";import{t as r}from"./KnowledgeWorkspace-z4u5mXOG.js";var i=e({__name:`PersonalProjectsPage`,setup(e){return(e,i)=>(n(),t(r,{"personal-projects-only":``}))}});export{i as default};
@@ -1 +0,0 @@
1
- .project-agent-assignment-dialog[data-v-27954ba8]{background:0 0;border:0;border-radius:12px;width:min(620px,100vw - 32px);max-height:calc(100vh - 32px);padding:0}.project-agent-assignment-dialog-shell[data-v-27954ba8]{background:#fbfcfb;border:1px solid #d5dcd7;border-radius:12px;flex-direction:column;max-height:calc(100vh - 32px);display:flex;overflow:hidden;box-shadow:0 18px 48px #212d262e}.project-agent-assignment-dialog-header[data-v-27954ba8],.project-agent-assignment-dialog-actions[data-v-27954ba8]{justify-content:space-between;align-items:center;gap:16px;padding:16px 18px;display:flex}.project-agent-assignment-dialog-header[data-v-27954ba8]{border-bottom:1px solid #e1e6e2}.project-agent-assignment-dialog-header h3[data-v-27954ba8]{color:#283a31;font-size:16px}.project-agent-assignment-dialog-fields[data-v-27954ba8]{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;min-height:0;padding:18px;display:grid;overflow:auto}.project-agent-assignment-dialog-fields label[data-v-27954ba8]{color:#626d66;gap:6px;font-size:11px;font-weight:650;display:grid}.project-agent-assignment-dialog-fields input[data-v-27954ba8],.project-agent-assignment-dialog-fields textarea[data-v-27954ba8]{color:#28342d;background:#fff;border:1px solid #ccd5ce;border-radius:8px;width:100%;padding:8px 9px;font-size:12px;line-height:1.5}.project-agent-assignment-dialog-fields textarea[data-v-27954ba8]{resize:vertical}.project-agent-assignment-dialog-fields input[data-v-27954ba8]:focus-visible,.project-agent-assignment-dialog-fields textarea[data-v-27954ba8]:focus-visible{outline-offset:1px;outline:2px solid #91a398}.project-agent-assignment-wide-field[data-v-27954ba8]{grid-column:1/-1}.project-agent-assignment-dialog-error[data-v-27954ba8]{color:#8b3f38;margin:0 18px;font-size:11px}.project-agent-assignment-dialog-actions[data-v-27954ba8]{border-top:1px solid #e1e6e2;justify-content:flex-end}.project-agent-primary-action[data-v-27954ba8]{color:#fff;background:#344c3d;border:0;border-radius:8px;padding:8px 13px;font-size:11px;font-weight:700}.project-agent-primary-action[data-v-27954ba8]:focus-visible{outline-offset:2px;outline:2px solid #91a398}@media (width<=620px){.project-agent-assignment-dialog-fields[data-v-27954ba8]{grid-template-columns:1fr}.project-agent-assignment-wide-field[data-v-27954ba8]{grid-column:auto}}.project-agent-dialog-check[data-v-6b96c90d]{align-items:center;gap:7px!important;display:flex!important}.project-agent-dialog-check input[data-v-6b96c90d]{width:auto!important}.project-agent-dialog-note[data-v-6b96c90d]{color:#7b857e;font-size:10px;line-height:1.55}.project-agent-source-state[data-v-f174e20d]{color:#727d75;background:#f7f9f7;border:1px solid #e1e6e2;border-radius:8px;justify-content:space-between;align-items:center;gap:10px;margin-top:22px;padding:10px 12px;font-size:10px;display:flex}.project-agent-source-state.is-error[data-v-f174e20d]{color:#8c4f49;background:#fbf3f1;border-color:#ebd5d0}.project-agent-dialog[data-v-83825f22]{background:0 0;border:0;border-radius:12px;width:min(760px,100vw - 64px);max-height:calc(100vh - 64px);padding:0;overflow:hidden}.project-agent-dialog-shell[data-v-83825f22]{background:#fbfcfb;border:1px solid #d5dcd7;border-radius:12px;flex-direction:column;min-height:0;max-height:calc(100vh - 64px);display:flex;overflow:hidden;box-shadow:0 18px 48px #212d262e}.project-agent-dialog-header[data-v-83825f22],.project-agent-dialog-actions[data-v-83825f22]{justify-content:space-between;align-items:center;gap:16px;padding:18px 20px;display:flex}.project-agent-dialog-header[data-v-83825f22]{border-bottom:1px solid #e1e6e2}.project-agent-dialog-header h3[data-v-83825f22]{color:#283a31;font-size:17px}.project-agent-dialog-fields[data-v-83825f22]{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;min-height:0;padding:20px;display:grid;overflow:auto}.project-agent-dialog-fields label[data-v-83825f22]{color:#626d66;align-content:start;gap:6px;min-width:0;font-size:11px;font-weight:650;display:grid}.project-agent-dialog-fields input[data-v-83825f22],.project-agent-dialog-fields select[data-v-83825f22],.project-agent-dialog-fields textarea[data-v-83825f22]{color:#28342d;background:#fff;border:1px solid #ccd5ce;border-radius:8px;width:100%;padding:9px 10px;font-size:12px;line-height:1.5}.project-agent-dialog-fields textarea[data-v-83825f22]{resize:vertical}.project-agent-dialog-fields input[data-v-83825f22]:focus-visible,.project-agent-dialog-fields select[data-v-83825f22]:focus-visible,.project-agent-dialog-fields textarea[data-v-83825f22]:focus-visible{outline-offset:1px;outline:2px solid #91a398}.project-agent-wide-field[data-v-83825f22],.project-agent-id-note[data-v-83825f22]{grid-column:1/-1}.project-agent-strategy-fields[data-v-83825f22]{border:1px solid #dfe5e0;border-radius:9px;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;min-width:0;margin:0;padding:12px;display:grid}.project-agent-strategy-fields legend[data-v-83825f22]{color:#59665d;padding:0 5px;font-size:10px;font-weight:700}.project-agent-strategy-fields>small[data-v-83825f22]{color:#818a84;grid-column:1/-1;font-size:9px;line-height:1.5}.project-agent-id-note[data-v-83825f22]{color:#7b847e;margin-top:-8px;font-size:10px}.project-agent-dialog-error[data-v-83825f22]{color:#8b3f38;margin:0 20px;font-size:11px}.project-agent-dialog-actions[data-v-83825f22]{border-top:1px solid #e1e6e2;justify-content:flex-end}.project-agent-primary-action[data-v-83825f22]{color:#fff;background:#344c3d;border:0;border-radius:8px;padding:8px 14px;font-size:12px;font-weight:700}.project-agent-primary-action[data-v-83825f22]:hover{background:#2b4234}.project-agent-primary-action[data-v-83825f22]:focus-visible{outline-offset:2px;outline:2px solid #91a398}.project-agent-primary-action[data-v-83825f22]:disabled,.project-agent-dialog-fields[data-v-83825f22] :disabled{cursor:not-allowed;opacity:.6}@media (width<=720px){.project-agent-dialog-fields[data-v-83825f22]{grid-template-columns:1fr}.project-agent-wide-field[data-v-83825f22],.project-agent-id-note[data-v-83825f22]{grid-column:1}}.project-agents-view[data-v-7dd25330]{flex-direction:column;gap:12px;min-height:0;padding:18px 32px 20px;display:flex;overflow:hidden}.project-agents-header[data-v-7dd25330],.project-agent-section-heading[data-v-7dd25330],.project-agent-section-tools[data-v-7dd25330],.project-agent-detail-actions[data-v-7dd25330],.project-agent-assignment-card header[data-v-7dd25330],.project-agent-task-card header[data-v-7dd25330],.project-agent-learning-card header[data-v-7dd25330],.project-agent-day-detail header[data-v-7dd25330]{justify-content:space-between;align-items:center;gap:12px;display:flex}.project-agents-header h2[data-v-7dd25330]{color:#283a31;font-size:18px}.project-agents-header-meta[data-v-7dd25330]{color:#7a847d;font-size:10px}.project-agents-summary[data-v-7dd25330]{color:#737d76;background:#f9faf9;border:1px solid #d6ddd8;border-radius:10px;gap:18px;padding:9px 14px;font-size:11px;display:flex}.project-agents-summary span[data-v-7dd25330]:first-child{color:#2f493b;font-weight:700}.project-agent-add[data-v-7dd25330]{color:#fff;background:#344c3d;border:0;border-radius:8px;padding:8px 13px;font-size:11px;font-weight:700}.project-agent-add[data-v-7dd25330]:hover{background:#2b4234}.project-agent-add[data-v-7dd25330]:focus-visible,.quiet-button[data-v-7dd25330]:focus-visible{outline-offset:2px;outline:2px solid #91a398}.project-agent-add[data-v-7dd25330]:disabled{cursor:not-allowed;opacity:.55}.project-agents-toolbar[data-v-7dd25330]{grid-template-columns:minmax(220px,300px) minmax(240px,1fr) auto;align-items:center;gap:10px;display:grid}.project-agents-search input[data-v-7dd25330]{color:#2e3932;background:#fff;border:1px solid #cfd7d1;border-radius:8px;width:100%;min-height:34px;padding:7px 10px;font-size:11px}.project-agents-search input[data-v-7dd25330]:focus-visible{outline-offset:1px;outline:2px solid #91a398}.project-agents-status-filter[data-v-7dd25330]{background:#f5f7f5;border:1px solid #d8ded9;border-radius:8px;gap:3px;padding:3px;display:flex}.project-agents-status-filter button[data-v-7dd25330],.quiet-button[data-v-7dd25330]{color:#6d7770;background:0 0;border:0;border-radius:6px;padding:6px 9px;font-size:10px}.project-agents-status-filter button[aria-pressed=true][data-v-7dd25330]{color:#315440;background:#fff;font-weight:700;box-shadow:0 1px 3px #27392f1f}.project-agents-directory[data-v-7dd25330]{background:#fff;border:1px solid #cfd7d1;border-radius:10px;flex:1;grid-template-columns:minmax(360px,.94fr) minmax(390px,1.06fr);min-height:0;display:grid;overflow:hidden}.project-agent-list[data-v-7dd25330]{border-right:1px solid #dfe4e0;min-width:0;min-height:0;overflow:auto}.project-agent-row[data-v-7dd25330]{width:100%;color:inherit;text-align:left;background:#fff;border:0;border-bottom:1px solid #e6eae7;grid-template-columns:minmax(0,1fr) auto;gap:5px 14px;padding:14px 16px;display:grid}.project-agent-row[data-v-7dd25330]:hover{background:#f7f9f7}.project-agent-row.selected[data-v-7dd25330]{background:#edf3ef;box-shadow:inset 3px 0 #64816f}.project-agent-row[data-v-7dd25330]:focus-visible{z-index:1;outline-offset:-3px;outline:2px solid #91a398;position:relative}.project-agent-row-heading[data-v-7dd25330]{align-items:center;gap:7px;min-width:0;display:flex}.project-agent-occupation-emoji[data-v-7dd25330]{flex:none;justify-content:center;align-items:center;min-width:1.2em;font-size:15px;line-height:1;display:inline-flex}.project-agent-row-heading strong[data-v-7dd25330]{color:#293b31;text-overflow:ellipsis;white-space:nowrap;font-size:13px;overflow:hidden}.project-agent-row-heading i[data-v-7dd25330],.project-agent-assignment-card header i[data-v-7dd25330],.project-agent-task-card header i[data-v-7dd25330],.project-agent-learning-card header i[data-v-7dd25330]{color:#66716a;background:#e6eae7;border-radius:999px;flex:none;padding:2px 7px;font-size:9px;font-style:normal;font-weight:700}.project-agent-row-heading i.is-active[data-v-7dd25330]{color:#2f6947;background:#e1eee6}.project-agent-row-heading i.is-archived[data-v-7dd25330]{color:#75695d;background:#eeeae5}.project-agent-kind[data-v-7dd25330]{color:#53647b!important;background:#eef2f7!important}.project-agent-row-id[data-v-7dd25330]{color:#8a938d;overflow-wrap:anywhere;text-align:right;font-size:9px}.project-agent-row-projects[data-v-7dd25330]{flex-wrap:wrap;grid-column:1/-1;gap:4px;display:flex}.project-agent-row-projects b[data-v-7dd25330],.project-agent-tags span[data-v-7dd25330],.project-agent-inline-list span[data-v-7dd25330]{color:#5f6b64;background:#eef1ef;border-radius:999px;padding:3px 7px;font-size:9px;font-weight:650}.project-agent-row-projects em[data-v-7dd25330]{color:#8a938d;font-size:9px;font-style:normal}.project-agent-row-responsibility[data-v-7dd25330]{color:#59645d;text-overflow:ellipsis;white-space:nowrap;grid-column:1/-1;font-size:11px;line-height:1.5;overflow:hidden}.project-agent-row-work[data-v-7dd25330]{color:#59645d;grid-column:1/-1;font-size:10px;line-height:1.5}.project-agent-work-dot[data-v-7dd25330]{background:#4b8d63;border-radius:50%;width:6px;height:6px;margin-right:4px;display:inline-block}.project-agent-row-capabilities[data-v-7dd25330]{flex-wrap:wrap;grid-column:1/-1;gap:5px;min-height:20px;display:flex}.project-agent-row-capabilities b[data-v-7dd25330]{color:#68736c;background:#f1f3f1;border-radius:999px;padding:3px 7px;font-size:9px;font-weight:650}.project-agent-detail[data-v-7dd25330]{min-width:0;min-height:0;padding:20px;overflow:auto;container-type:inline-size}.project-agent-detail>header[data-v-7dd25330]{border-bottom:1px solid #e1e6e2;grid-template-columns:minmax(0,1fr) max-content;align-items:flex-start;gap:16px;padding-bottom:16px;display:grid}.project-agent-detail-heading[data-v-7dd25330]{min-width:0}.project-agent-detail h3[data-v-7dd25330]{color:#263b30;text-wrap:balance;font-size:17px;line-height:1.32}.project-agent-detail header p[data-v-7dd25330]{color:#7a847d;overflow-wrap:anywhere;max-width:72ch;margin-top:5px;font-size:10px;line-height:1.5}.project-agent-detail-actions[data-v-7dd25330]{grid-auto-columns:78px;grid-auto-flow:column;justify-content:end;gap:8px;display:grid}.project-agent-detail-actions .quiet-button[data-v-7dd25330]{white-space:nowrap;width:78px}.project-agent-detail-meta[data-v-7dd25330],.project-agent-compact-meta[data-v-7dd25330]{grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0 0;display:grid}.project-agent-detail-meta div[data-v-7dd25330],.project-agent-compact-meta div[data-v-7dd25330]{min-width:0}.project-agent-detail-meta dt[data-v-7dd25330],.project-agent-compact-meta dt[data-v-7dd25330],.project-agent-detail-section h4[data-v-7dd25330]{color:#7a847d;letter-spacing:.06em;text-transform:uppercase;font-size:9px;font-weight:700}.project-agent-detail-meta dd[data-v-7dd25330],.project-agent-compact-meta dd[data-v-7dd25330]{overflow-wrap:anywhere;color:#39483f;margin:4px 0 0;font-size:11px}.project-agent-detail-meta dd small[data-v-7dd25330]{color:#818a84;margin-top:3px;font-size:9px;line-height:1.4;display:block}.project-agent-detail-section[data-v-7dd25330]{margin-top:22px}.project-agent-detail-section.is-responsibility[data-v-7dd25330]{background:#f2f5f2;border-radius:10px;padding:14px}.project-agent-detail-section p[data-v-7dd25330],.project-agent-detail-section li[data-v-7dd25330]{color:#4f5c54;font-size:11px;line-height:1.65}.project-agent-tags[data-v-7dd25330],.project-agent-inline-list[data-v-7dd25330]{flex-wrap:wrap;gap:6px;margin-top:9px;display:flex}.project-agent-muted[data-v-7dd25330]{color:#8a928d!important}.project-agent-detail-notice[data-v-7dd25330]{background:#f5f5f1;border-radius:7px;margin:12px 0 0;padding:8px 10px;color:#6f705f!important}.project-agent-detail-placeholder[data-v-7dd25330],.project-agents-state[data-v-7dd25330]{color:#737d76;text-align:center;place-content:center;justify-items:center;gap:8px;min-height:240px;font-size:11px;display:grid}.project-agents-state[data-v-7dd25330]{background:#fafbfa;border:1px solid #d9dfda;border-radius:10px;flex:1}.project-agents-state strong[data-v-7dd25330]{color:#36473e;font-size:14px}.project-agents-state p[data-v-7dd25330]{max-width:52ch;line-height:1.6}.project-agents-state.is-error[data-v-7dd25330]{color:#8b3f38}.project-agent-assignment-list[data-v-7dd25330],.project-agent-task-list[data-v-7dd25330],.project-agent-learning-list[data-v-7dd25330],.project-agent-recruitment-list[data-v-7dd25330]{gap:8px;margin-top:9px;display:grid}.project-agent-execution-summary[data-v-7dd25330]{border-top:1px solid #dfe5e0;margin-top:13px;padding-top:12px}.project-agent-worker-event-evidence[data-v-7dd25330]{background:#f8faf8;border:1px dashed #d8dfd9;border-radius:8px;margin-top:13px;padding:10px 10px 0}.project-agent-execution-summary .project-agent-section-heading[data-v-7dd25330]{gap:8px}.project-agent-execution-summary h5[data-v-7dd25330]{color:#65736a;letter-spacing:.06em;text-transform:uppercase;margin:0;font-size:9px;font-weight:700}.project-agent-execution-summary-list[data-v-7dd25330]{margin:7px 0 0;padding:0;list-style:none;display:grid}.project-agent-execution-summary-row[data-v-7dd25330]{border-top:1px solid #e6ebe7;min-width:0;padding:10px 0}.project-agent-execution-summary-row[data-v-7dd25330]:first-child{border-top:0}.project-agent-execution-summary-row header[data-v-7dd25330]{align-items:flex-start}.project-agent-execution-summary-row header strong[data-v-7dd25330]{overflow-wrap:anywhere;color:#3f5647;align-items:center;gap:5px;min-width:0;font-size:10px;display:flex}.project-agent-execution-summary-row header strong small[data-v-7dd25330]{color:#89948c;margin:0;font-size:8px;font-weight:500;display:inline}.project-agent-execution-summary-row header i[data-v-7dd25330]{color:#66716a;background:#e6eae7;border-radius:999px;flex:none;padding:2px 6px;font-size:8px;font-style:normal;font-weight:700}.project-agent-execution-summary-row header i.is-completed[data-v-7dd25330]{color:#2f6947;background:#e1eee6}.project-agent-execution-summary-row header i.is-failed[data-v-7dd25330]{color:#8c4f49;background:#f7e9e6}.project-agent-execution-summary-row header i.is-cancelled[data-v-7dd25330]{color:#75695d;background:#eeeae5}.project-agent-execution-summary-meta[data-v-7dd25330]{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px 10px;margin:8px 0 0;display:grid}.project-agent-execution-summary-meta div[data-v-7dd25330]{min-width:0}.project-agent-execution-summary-meta dt[data-v-7dd25330]{color:#89948c;letter-spacing:.04em;text-transform:uppercase;font-size:8px;font-weight:700}.project-agent-execution-summary-meta dd[data-v-7dd25330]{overflow-wrap:anywhere;color:#4f5e54;margin:2px 0 0;font-size:9px;line-height:1.45}.project-agent-execution-summary-meta dd small[data-v-7dd25330]{color:#89948c;margin-top:2px;font-size:8px;display:block}.project-agent-assignment-card[data-v-7dd25330],.project-agent-task-card[data-v-7dd25330],.project-agent-learning-card[data-v-7dd25330],.project-agent-recruitment-card[data-v-7dd25330]{background:#fbfcfb;border:1px solid #e0e6e1;border-radius:9px;padding:11px 12px}.project-agent-assignment-card header strong[data-v-7dd25330],.project-agent-task-card header strong[data-v-7dd25330],.project-agent-learning-card header strong[data-v-7dd25330]{color:#33483a;font-size:11px}.project-agent-card-actions[data-v-7dd25330]{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:4px;display:flex}.project-agent-assignment-card p[data-v-7dd25330],.project-agent-task-card p[data-v-7dd25330],.project-agent-learning-card p[data-v-7dd25330]{margin:7px 0 0}.project-agent-assignment-card small[data-v-7dd25330],.project-agent-task-card small[data-v-7dd25330],.project-agent-learning-card small[data-v-7dd25330]{color:#818a84;margin-top:6px;font-size:9px;line-height:1.5;display:block}.project-agent-assignment-card header i.is-ended[data-v-7dd25330],.project-agent-assignment-card header i.is-replaced[data-v-7dd25330]{color:#75695d;background:#eeeae5}.project-agent-strategy-note[data-v-7dd25330],.project-agent-execution-line[data-v-7dd25330]{color:#7a847d;flex-wrap:wrap;align-items:baseline;gap:6px;margin-top:8px;font-size:9px;display:flex}.project-agent-strategy-note strong[data-v-7dd25330],.project-agent-execution-line strong[data-v-7dd25330]{color:#53685a;font-size:10px}.project-agent-strategy-note small[data-v-7dd25330]{color:#8c5d54;flex-basis:100%}.project-agent-routing-decision[data-v-7dd25330]{color:#65736a;background:#f3f7f3;border-left:3px solid #7c9c86;border-radius:0 7px 7px 0;gap:5px;margin-top:10px;padding:9px 10px;font-size:9px;display:grid}.project-agent-routing-decision .project-agent-section-heading[data-v-7dd25330]{align-items:baseline;gap:8px}.project-agent-routing-decision .project-agent-section-heading strong[data-v-7dd25330]{color:#3f604b;font-size:10px}.project-agent-routing-decision small[data-v-7dd25330]{color:#65736a;line-height:1.45}.project-agent-blocked[data-v-7dd25330]{color:#8c5d54!important}.project-agent-task-card header[data-v-7dd25330]{align-items:flex-start}.project-agent-task-card header small[data-v-7dd25330]{margin-top:3px}.project-agent-task-card header i[data-v-7dd25330]{color:#53647b;background:#eef2f7}.project-agent-task-card header i.is-completed[data-v-7dd25330]{color:#2f6947;background:#e1eee6}.project-agent-task-card header i.is-failed[data-v-7dd25330]{color:#8c4f49;background:#f7e9e6}.project-agent-task-card header i.is-cancelled[data-v-7dd25330]{color:#75695d;background:#eeeae5}.project-agent-heatmap-viewport[data-v-7dd25330]{contain:layout inline-size paint;min-width:0;max-width:100%;overflow-x:clip}.project-agent-heatmap[data-v-7dd25330]{grid-template-rows:repeat(7,minmax(10px,1fr));grid-auto-columns:minmax(10px,1fr);grid-auto-flow:column;gap:3px;width:100%;max-width:100%;margin-top:9px;padding:0;display:grid;overflow-x:auto}.project-agent-heat-cell[data-v-7dd25330]{appearance:none;box-sizing:border-box;aspect-ratio:1;background:#f2f4f2;border:1px solid #dfe6e0;border-radius:3px;min-width:9px;margin:0;padding:0}.project-agent-heat-cell.intensity-1[data-v-7dd25330]{background:#dce9df}.project-agent-heat-cell.intensity-2[data-v-7dd25330]{background:#b9d3bf}.project-agent-heat-cell.intensity-3[data-v-7dd25330]{background:#87b493}.project-agent-heat-cell.intensity-4[data-v-7dd25330]{background:#548466}.project-agent-heat-cell[data-v-7dd25330]:focus-visible,.project-agent-heat-cell.selected[data-v-7dd25330]{box-shadow:none;border:2px solid #2f5740;outline:none}.project-agent-day-detail[data-v-7dd25330]{background:#f6f8f6;border-radius:8px;margin-top:10px;padding:10px}.project-agent-day-detail ul[data-v-7dd25330]{margin:8px 0 0;padding-left:17px}.project-agent-day-detail li[data-v-7dd25330]{margin-top:6px}.project-agent-day-detail li strong[data-v-7dd25330],.project-agent-day-detail li span[data-v-7dd25330],.project-agent-day-detail li small[data-v-7dd25330]{display:block}.project-agent-day-detail li span[data-v-7dd25330]{color:#66736b;font-size:9px}.project-agent-day-detail li small[data-v-7dd25330]{color:#7e8981;font-size:9px}.project-agent-client-list[data-v-7dd25330],.project-agent-rule-list[data-v-7dd25330]{gap:5px;margin-top:9px;display:grid}.project-agent-client-row[data-v-7dd25330],.project-agent-rule-row[data-v-7dd25330]{color:#68736c;background:#f7f9f7;border-radius:7px;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:7px;padding:8px 10px;font-size:9px;display:grid}.project-agent-client-row strong[data-v-7dd25330],.project-agent-rule-row strong[data-v-7dd25330]{color:#43584a;font-size:10px}.project-agent-client-row small[data-v-7dd25330]{color:#8a938d;grid-column:1/-1}.project-agent-executor-list[data-v-7dd25330]{gap:5px;margin-top:9px;display:grid}.project-agent-executor-row[data-v-7dd25330]{color:#68736c;background:#f7f9f7;border-radius:7px;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:7px;padding:8px 10px;font-size:9px;display:grid}.project-agent-executor-row strong[data-v-7dd25330]{color:#43584a;font-size:10px}.project-agent-executor-row small[data-v-7dd25330]{color:#8a938d;grid-column:1/-1}.project-agent-learning-card header i[data-v-7dd25330]{color:#6c776f;background:#f1f3f1}.project-agent-evidence-list[data-v-7dd25330]{margin:8px 0 0;padding-left:17px}.project-agent-evidence-list li[data-v-7dd25330]{color:#768179;font-size:9px}.project-agent-learning-actions[data-v-7dd25330]{gap:6px;margin-top:8px;display:flex}.project-agent-note[data-v-7dd25330]{color:#818a84;margin-top:9px;font-size:9px;line-height:1.5;display:block}.sr-only[data-v-7dd25330]{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (width<=1180px){.project-agents-toolbar[data-v-7dd25330]{grid-template-columns:minmax(220px,280px) 1fr}.project-agents-status-filter[data-v-7dd25330]{grid-column:1/-1;justify-self:start}.project-agents-directory[data-v-7dd25330]{grid-template-columns:minmax(320px,.9fr) minmax(330px,1fr)}.project-agent-detail-meta[data-v-7dd25330],.project-agent-compact-meta[data-v-7dd25330]{grid-template-columns:repeat(2,minmax(0,1fr))}}@container (width<=420px){.project-agent-detail>header[data-v-7dd25330]{grid-template-columns:minmax(0,1fr)}.project-agent-detail-actions[data-v-7dd25330]{justify-content:start}}@media (width<=760px){.project-agents-view[data-v-7dd25330]{padding:14px 16px 18px;overflow:auto}.project-agents-header[data-v-7dd25330],.project-agents-summary[data-v-7dd25330],.project-agent-section-heading[data-v-7dd25330],.project-agent-assignment-card header[data-v-7dd25330]{flex-wrap:wrap;align-items:flex-start}.project-agents-toolbar[data-v-7dd25330]{grid-template-columns:minmax(0,1fr)}.project-agents-project-filter[data-v-7dd25330],.project-agents-search[data-v-7dd25330],.project-agents-status-filter[data-v-7dd25330]{grid-column:1}.project-agents-status-filter[data-v-7dd25330]{flex-wrap:wrap;justify-self:stretch;width:100%}.project-agents-directory[data-v-7dd25330]{flex:none;grid-template-columns:minmax(0,1fr);overflow:visible}.project-agent-list[data-v-7dd25330]{border-bottom:1px solid #dfe4e0;border-right:0;max-height:340px}.project-agent-detail[data-v-7dd25330]{min-height:520px;padding:16px}.project-agent-client-row[data-v-7dd25330],.project-agent-rule-row[data-v-7dd25330],.project-agent-executor-row[data-v-7dd25330]{grid-template-columns:minmax(0,1fr);align-items:start}.project-agent-client-row small[data-v-7dd25330],.project-agent-executor-row small[data-v-7dd25330]{grid-column:1}.project-agent-execution-summary-meta[data-v-7dd25330]{grid-template-columns:minmax(0,1fr)}.project-agent-execution-summary-row header[data-v-7dd25330]{gap:8px}}