fuli-context 0.20.0-beta.2 → 0.20.0-beta.3
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 +81 -22
- package/README.zh-CN.md +26 -12
- package/dist/web/assets/AboutPage-BkpqvBhp.css +1 -0
- package/dist/web/assets/AboutPage-BmX7l4yh.js +1 -0
- package/dist/web/assets/AgentName-DeHNVQ-r.js +1 -0
- package/dist/web/assets/AgentProfilePage-0ksQ58aV.css +1 -0
- package/dist/web/assets/AgentProfilePage-DbzxN3rz.js +1 -0
- package/dist/web/assets/AgentsDirectoryPage-DnvNg4s-.js +1 -0
- package/dist/web/assets/AgentsDirectoryPage-DoOXStj-.css +1 -0
- package/dist/web/assets/ConnectionsPage-C_-t36vt.js +1 -0
- package/dist/web/assets/CreateProjectDialog-78Sz76lL.js +2 -0
- package/dist/web/assets/CreateProjectDialog-t947qHxl.css +1 -0
- package/dist/web/assets/EmployeeRecruitDialog-BPT132zr.css +1 -0
- package/dist/web/assets/EmployeeRecruitDialog-CbakSlIK.js +1 -0
- package/dist/web/assets/EmployeeWorkbenchPage-BFSzzB5b.css +1 -0
- package/dist/web/assets/EmployeeWorkbenchPage-CZb36N9r.js +3 -0
- package/dist/web/assets/InboxPage-Bsa1NRSD.js +4 -0
- package/dist/web/assets/InboxPage-DiIA1trj.css +1 -0
- package/dist/web/assets/KnowledgeEditDialog-BXS3rlWg.css +1 -0
- package/dist/web/assets/KnowledgeEditDialog-CSjtslJS.js +1 -0
- package/dist/web/assets/KnowledgeInspector-DB9USgC0.js +1 -0
- package/dist/web/assets/KnowledgeInspector-DaknAv7P.css +1 -0
- package/dist/web/assets/KnowledgeOrganizerPage-CxICN_0p.css +1 -0
- package/dist/web/assets/KnowledgeOrganizerPage-DEucKWd7.js +1 -0
- package/dist/web/assets/KnowledgePage-tLziTkSU.js +1 -0
- package/dist/web/assets/KnowledgeWorkspace-B7ZiPf6n.js +4 -0
- package/dist/web/assets/KnowledgeWorkspace-BY_OoTDG.css +1 -0
- package/dist/web/assets/NotFoundPage-XPalsChA.js +1 -0
- package/dist/web/assets/OccupationsPage-BRdGXQ2P.js +1 -0
- package/dist/web/assets/OccupationsPage-BXCJPqBB.css +1 -0
- package/dist/web/assets/OverviewPage-C7OJfsL0.css +1 -0
- package/dist/web/assets/OverviewPage-x0ExTLqh.js +2 -0
- package/dist/web/assets/PersonalProfilePage-Cl2EQuuO.js +1 -0
- package/dist/web/assets/PersonalProfilePage-bKUVSOge.css +1 -0
- package/dist/web/assets/PersonalProjectsPage-C7k2sBQN.css +1 -0
- package/dist/web/assets/PersonalProjectsPage-Dh44vNQk.js +1 -0
- package/dist/web/assets/ProjectAgentFirstTask-BVNcBsw9.js +1 -0
- package/dist/web/assets/ProjectAgentFirstTask-D1RrWjaX.css +1 -0
- package/dist/web/assets/ProjectAgentsPage-BBo_ALw_.js +12 -0
- package/dist/web/assets/ProjectAgentsPage-DdooNyYs.css +1 -0
- package/dist/web/assets/ProjectScopePicker-CNN_sGrN.js +1 -0
- package/dist/web/assets/PublicProjectsPage-BEyOXwu-.js +1 -0
- package/dist/web/assets/PublicProjectsPage-DlmcjqGj.css +1 -0
- package/dist/web/assets/RoundtablesPage-CdfpgOnb.js +1 -0
- package/dist/web/assets/RoundtablesPage-ftnoDxpL.css +1 -0
- package/dist/web/assets/SettingsPage-CfyHImb3.css +1 -0
- package/dist/web/assets/SettingsPage-DdWrf4wR.js +1 -0
- package/dist/web/assets/SharedJefaReportPage-B5vPQ7QK.js +1 -0
- package/dist/web/assets/TaskExecutionPlan-BFVcb7KN.css +1 -0
- package/dist/web/assets/TaskExecutionPlan-CFM_14VC.js +2 -0
- package/dist/web/assets/TaskSchedulesPage-CISJAYZy.js +1 -0
- package/dist/web/assets/TaskSchedulesPage-fNCG8EWD.css +1 -0
- package/dist/web/assets/TextField-BVqz0DTp.js +1 -0
- package/dist/web/assets/UiDialog-CIyDfEYh.js +1 -0
- package/dist/web/assets/UiDisclosure-BIE3uXrx.js +1 -0
- package/dist/web/assets/UiIcon-EWCwhyKc.css +1 -0
- package/dist/web/assets/UiIcon-INPsGFvz.js +1 -0
- package/dist/web/assets/UiIconButton-CSFA7F4B.css +1 -0
- package/dist/web/assets/UiIconButton-w6pfBSda.js +1 -0
- package/dist/web/assets/UiSegmented-wN76K7F9.js +1 -0
- package/dist/web/assets/UiSelect-BaVTdhtR.js +1 -0
- package/dist/web/assets/UiSelect-CiSPw-7k.css +1 -0
- package/dist/web/assets/UiToggle-B2sPCVZe.css +1 -0
- package/dist/web/assets/UiToggle-Cs1CZzk6.js +1 -0
- package/dist/web/assets/UnassignedConversationsPanel-0y0YliA_.js +1 -0
- package/dist/web/assets/VirtualDirectoryList-nAWaJ2eM.js +1 -0
- package/dist/web/assets/Workbench3D-BxpszsXO.css +1 -0
- package/dist/web/assets/Workbench3D-CYCi_MRp.js +2 -0
- package/dist/web/assets/WritingTastePage-B9nMV49S.css +1 -0
- package/dist/web/assets/WritingTastePage-DfTuTJx2.js +1 -0
- package/dist/web/assets/agent-identity-color-RqpT7gtx.js +1 -0
- package/dist/web/assets/agent-occupation-Bke7eg11.js +1 -0
- package/dist/web/assets/agent-pins-DrG1uUDt.js +1 -0
- package/dist/web/assets/agent-profile-CU4YqRz_.css +1 -0
- package/dist/web/assets/agent-work-summary-C53Zfzk5.js +1 -0
- package/dist/web/assets/astro-avatar-GADWtfJX.webp +0 -0
- package/dist/web/assets/attention-store-Bg-rVsgG.js +1 -0
- package/dist/web/assets/{avatars-z6ANYG_r.js → avatars-CUyfvsKO.js} +1 -1
- package/dist/web/assets/catalog-CmHt1ONG.js +1 -0
- package/dist/web/assets/client-B_QrPkEy.css +1 -0
- package/dist/web/assets/client-DBYe0KzE.js +1 -0
- package/dist/web/assets/console-2nhA6IaV.js +1 -0
- package/dist/web/assets/conversation-launcher-settings-txCBZEle.js +1 -0
- package/dist/web/assets/date-time-DBa_h9cD.js +1 -0
- package/dist/web/assets/design-lab-ClOnEnF7.js +1 -0
- package/dist/web/assets/galaxy-scene-7sJk1pHo.js +1 -0
- package/dist/web/assets/i18n-DAeCdA8L.js +10 -0
- package/dist/web/assets/{identity-CAQk8V-Q.js → identity-bmKz-BGh.js} +1 -1
- package/dist/web/assets/index-DsqCEnEC.css +1 -0
- package/dist/web/assets/index-YZYwAHdd.js +2 -0
- package/dist/web/assets/judgment-types-C2vHfclm.js +1 -0
- package/dist/web/assets/layout-DCeMsVR8.js +1 -0
- package/dist/web/assets/model-VWzF8pT3.js +1 -0
- package/dist/web/assets/motion-preference-D3Aq7THt.js +1 -0
- package/dist/web/assets/occupation-catalog-DnevywIk.js +1 -0
- package/dist/web/assets/office-scene-CbmeA3ZZ.js +1 -0
- package/dist/web/assets/personal-profile-graph-CyRXX8b0.js +1 -0
- package/dist/web/assets/preload-helper-Czpn1I53.js +1 -0
- package/dist/web/assets/project-origin-KvE_J110.js +1 -0
- package/dist/web/assets/project-team-api-CXPeakuM.js +1 -0
- package/dist/web/assets/shared-report-BxeCmoU_.js +1 -0
- package/dist/web/assets/shared-report-NXHxLp5x.css +1 -0
- package/dist/web/assets/stage-CWdBY1y-.js +1 -0
- package/dist/web/assets/stage-D1RyodHo.js +3835 -0
- package/dist/web/assets/task-labels-C4t6U38E.js +1 -0
- package/dist/web/assets/task-updates-ChvjLQXV.js +1 -0
- package/dist/web/assets/ui-WHqcW6KK.js +1 -0
- package/dist/web/assets/ui-gkBKztsv.css +1 -0
- package/dist/web/assets/useAgentRecords-DotFATN2.js +1 -0
- package/dist/web/assets/{useApi-CROJJdhE-sOV3uq1T.js → useApi-CROJJdhE-BJn8l1Cb.js} +1 -1
- package/dist/web/assets/vue-router-YsTpOqqM.js +1 -0
- package/dist/web/assets/workbench-model-D9ytk327.js +1 -0
- package/dist/web/index.html +28 -19
- package/docs/agent-conversations-and-collaboration.md +6 -0
- package/docs/agent-interface-architecture.md +10 -0
- package/docs/agent-roundtable.md +42 -1
- package/docs/client-connections.md +158 -110
- package/docs/employee-agents.md +7 -3
- package/docs/project-agent-memory.md +24 -8
- package/graph-provider/fuli_graph/agent_confirmation_progress.py +58 -0
- package/graph-provider/fuli_graph/agent_conversation_models.py +1 -0
- package/graph-provider/fuli_graph/agent_conversation_routes.py +20 -0
- package/graph-provider/fuli_graph/app.py +8 -1
- package/graph-provider/fuli_graph/collaboration_context.py +48 -15
- package/graph-provider/fuli_graph/config.py +2 -0
- package/graph-provider/fuli_graph/conversation_context.py +74 -41
- package/graph-provider/fuli_graph/conversation_triage_models.py +35 -0
- package/graph-provider/fuli_graph/default_project_lead.py +3 -3
- package/graph-provider/fuli_graph/graph_models.py +26 -3
- package/graph-provider/fuli_graph/graph_query.py +36 -15
- package/graph-provider/fuli_graph/knowledge_search.py +3 -0
- package/graph-provider/fuli_graph/knowledge_weight.py +40 -0
- package/graph-provider/fuli_graph/knowledge_weight_models.py +9 -0
- package/graph-provider/fuli_graph/migrate_lead_occupation.py +165 -0
- package/graph-provider/fuli_graph/model_validation.py +10 -0
- package/graph-provider/fuli_graph/models.py +44 -3
- package/graph-provider/fuli_graph/occupation_catalog.py +116 -0
- package/graph-provider/fuli_graph/occupation_routes.py +25 -0
- package/graph-provider/fuli_graph/personal_global_preferences.py +6 -10
- package/graph-provider/fuli_graph/preference_conflicts.py +38 -0
- package/graph-provider/fuli_graph/project_agent_attention_models.py +7 -0
- package/graph-provider/fuli_graph/project_agent_coordination_models.py +57 -5
- package/graph-provider/fuli_graph/project_agent_delegations.py +129 -13
- package/graph-provider/fuli_graph/project_agent_executor_models.py +9 -18
- package/graph-provider/fuli_graph/project_agent_hierarchy.py +98 -0
- package/graph-provider/fuli_graph/project_agent_memory_routes.py +13 -1
- package/graph-provider/fuli_graph/project_agent_models.py +6 -1
- package/graph-provider/fuli_graph/project_agent_occupation_models.py +36 -0
- package/graph-provider/fuli_graph/project_agent_recruitment_occupation.py +74 -0
- package/graph-provider/fuli_graph/project_agent_recruitment_values.py +10 -1
- package/graph-provider/fuli_graph/project_agent_remote_origins.py +24 -11
- package/graph-provider/fuli_graph/project_agent_routes.py +40 -1
- package/graph-provider/fuli_graph/project_agent_task_models.py +31 -17
- package/graph-provider/fuli_graph/project_agent_worker_access.py +229 -0
- package/graph-provider/fuli_graph/project_agent_worker_models.py +59 -0
- package/graph-provider/fuli_graph/project_agent_worker_routes.py +88 -0
- package/graph-provider/fuli_graph/project_brief.py +46 -0
- package/graph-provider/fuli_graph/project_memory_usage.py +175 -0
- package/graph-provider/fuli_graph/project_memory_usage_projection.py +35 -0
- package/graph-provider/fuli_graph/project_memory_usage_routes.py +26 -0
- package/graph-provider/fuli_graph/provider_values.py +5 -0
- package/graph-provider/fuli_graph/runtime.py +6 -0
- package/graph-provider/fuli_graph/search_projection.py +6 -27
- package/graph-provider/fuli_graph/staffing_demand.py +74 -0
- package/graph-provider/fuli_graph/store.py +10 -0
- package/graph-provider/fuli_graph/store_agent_conversations.py +88 -16
- package/graph-provider/fuli_graph/store_conversation_triage.py +85 -0
- package/graph-provider/fuli_graph/store_knowledge.py +21 -6
- package/graph-provider/fuli_graph/store_occupation_catalog.py +142 -0
- package/graph-provider/fuli_graph/store_project_agent_attention.py +3 -0
- package/graph-provider/fuli_graph/store_project_agent_context.py +5 -2
- package/graph-provider/fuli_graph/store_project_agent_coordination_policy.py +19 -1
- package/graph-provider/fuli_graph/store_project_agent_executor_routing.py +1 -1
- package/graph-provider/fuli_graph/store_project_agent_executors.py +1 -1
- package/graph-provider/fuli_graph/store_project_agent_occupation.py +75 -0
- package/graph-provider/fuli_graph/store_project_agent_pages.py +84 -0
- package/graph-provider/fuli_graph/store_project_agent_task_activity.py +31 -1
- package/graph-provider/fuli_graph/store_project_agent_task_persistence.py +3 -1
- package/graph-provider/fuli_graph/store_project_agent_task_reads.py +15 -1
- package/graph-provider/fuli_graph/store_project_agent_task_recruitment.py +80 -137
- package/graph-provider/fuli_graph/store_project_agent_task_staffing.py +32 -7
- package/graph-provider/fuli_graph/store_project_agent_tasks.py +42 -4
- package/graph-provider/fuli_graph/store_project_agent_worker_runs.py +355 -0
- package/graph-provider/fuli_graph/store_project_agents.py +87 -3
- package/graph-provider/fuli_graph/store_projects.py +16 -1
- package/graph-provider/fuli_graph/store_recruitment_fulfillment.py +95 -0
- package/graph-provider/fuli_graph/store_task_contexts.py +189 -33
- package/graph-provider/fuli_graph/store_transcript_recovery.py +54 -0
- package/graph-provider/fuli_graph/system_agents.py +34 -3
- package/graph-provider/fuli_graph/task_activity_origin.py +70 -0
- package/graph-provider/fuli_graph/task_context_adoption.py +8 -5
- package/graph-provider/fuli_graph/task_context_auto_close.py +54 -0
- package/graph-provider/fuli_graph/task_context_coordination.py +114 -0
- package/graph-provider/fuli_graph/task_context_models.py +75 -1
- package/graph-provider/fuli_graph/task_context_routes.py +11 -1
- package/graph-provider/fuli_graph/task_participant_running.py +15 -0
- package/graph-provider/fuli_graph/task_worker_attribution.py +102 -0
- package/graph-provider/fuli_graph/worker_run_execution.py +48 -0
- package/graph-provider/fuli_graph/workflow_candidates.py +4 -9
- package/graph-provider/pyproject.toml +1 -1
- package/npm-shrinkwrap.json +85 -2
- package/package.json +5 -1
- package/skills/capturing-session-knowledge/SKILL.md +13 -355
- package/skills/capturing-session-knowledge/references/capture.md +145 -0
- package/skills/capturing-session-knowledge/references/coordination.md +70 -0
- package/skills/capturing-session-knowledge/references/retrieval.md +153 -0
- package/src/adaptive-runtime/graph-services.js +8 -34
- package/src/adaptive-runtime/settings.js +1 -8
- package/src/agent-peer/chat-coordinator.js +104 -0
- package/src/agent-peer/chat-port.js +78 -0
- package/src/agent-peer/coordinator-http.js +10 -0
- package/src/agent-peer/coordinator-service.js +25 -8
- package/src/agent-peer/coordinator-store.js +26 -6
- package/src/agent-peer/node-store.js +12 -6
- package/src/agent-peer/origin-proof.js +6 -4
- package/src/agent-peer/peer-port.js +30 -13
- package/src/agent-peer/peer-runtime.js +22 -11
- package/src/agent-peer/peer-transport.js +1 -1
- package/src/agent-peer/protocol.js +16 -2
- package/src/agent-peer/runner.js +18 -9
- package/src/agent-roundtable/attention-inbox-store.js +37 -0
- package/src/agent-roundtable/attention-inbox.js +48 -0
- package/src/agent-roundtable/chat-contract.js +49 -0
- package/src/agent-roundtable/chat-notifications.js +53 -0
- package/src/agent-roundtable/chat-service.js +132 -0
- package/src/agent-roundtable/chat-snapshot.js +52 -0
- package/src/agent-roundtable/chat-store.js +108 -0
- package/src/agent-roundtable/chat-updates.js +28 -0
- package/src/agent-roundtable/chat-wait.js +32 -0
- package/src/agent-roundtable/chat-wake.js +53 -0
- package/src/agent-roundtable/chat.js +98 -0
- package/src/agent-roundtable/discovery.js +12 -0
- package/src/agent-roundtable/http.js +30 -0
- package/src/agent-roundtable/memory-observation.js +25 -0
- package/src/agent-roundtable/project-target.js +43 -0
- package/src/agent-roundtable/service.js +183 -35
- package/src/agent-roundtable/store.js +102 -7
- package/src/agent-roundtable/task-context.js +109 -0
- package/src/agent-roundtable/tools.js +19 -5
- package/src/agent-roundtable/wake.js +106 -18
- package/src/agent-tools/agent-attention-definitions.js +5 -4
- package/src/agent-tools/agent-collaboration-definitions.js +6 -2
- package/src/agent-tools/checkpoint-definitions.js +30 -0
- package/src/agent-tools/employee-definitions.js +5 -4
- package/src/agent-tools/graph-definitions.js +51 -47
- package/src/agent-tools/graph-handlers.js +15 -6
- package/src/agent-tools/interface-catalog.js +18 -4
- package/src/agent-tools/interface-definitions.js +12 -3
- package/src/agent-tools/knowledge-usage-definitions.js +21 -0
- package/src/agent-tools/project-agent-definitions.js +14 -4
- package/src/agent-tools/project-agent-memory-definitions.js +2 -2
- package/src/agent-tools/schema.js +4 -0
- package/src/agent-tools/task-preference-definitions.js +13 -0
- package/src/agent-tools/task-run-definitions.js +11 -0
- package/src/agent-tools/task-schedule-definitions.js +15 -0
- package/src/agents/claude-code/host-notification.js +64 -0
- package/src/agents/claude-code/lifecycle-hook.js +36 -56
- package/src/agents/claude-code/native-session.js +9 -0
- package/src/agents/claude-code/preference-evidence.js +28 -0
- package/src/agents/claude-code/wake.js +1 -0
- package/src/agents/codex/acp-process.js +244 -0
- package/src/agents/codex/acp-session.js +190 -0
- package/src/agents/codex/acp-worker.js +54 -0
- package/src/agents/codex/lifecycle-hook.js +58 -63
- package/src/agents/codex/lifecycle-hooks.js +22 -5
- package/src/agents/codex/mcp-context.js +16 -0
- package/src/agents/codex/preference-evidence.js +21 -0
- package/src/agents/codex/token-usage.js +14 -2
- package/src/agents/codex/wake.js +7 -3
- package/src/agents/cursor/lifecycle-hook.js +6 -16
- package/src/agents/identity-receipt.js +74 -10
- package/src/agents/lifecycle-input.js +20 -0
- package/src/agents/lifecycle-message.js +4 -0
- package/src/agents/native-mcp-context.js +9 -0
- package/src/agents/native-session-env.js +10 -0
- package/src/agents/preference-evidence.js +21 -0
- package/src/agents/system-prompt.js +11 -0
- package/src/app/agent-request-context.js +14 -1
- package/src/app/application-error.js +4 -1
- package/src/backup/graph-census.js +57 -0
- package/src/backup/identity-reconciliation.js +15 -39
- package/src/backup/runtime-adapters.js +64 -27
- package/src/backup/runtime-migration.js +88 -0
- package/src/cli/command-registry.js +4 -1
- package/src/cli/connect-command.js +1 -1
- package/src/cli/graph-data-command.js +25 -4
- package/src/cli/graph-migrate-command.js +107 -0
- package/src/cli/local-runtime-command.js +1 -4
- package/src/cli/local-runtime-control.js +27 -0
- package/src/cli/mcp-command.js +33 -1
- package/src/cli/native-runtime-command.js +44 -0
- package/src/cli/remote-mcp-command.js +7 -0
- package/src/cli/setup-command.js +12 -22
- package/src/cli/terminal-io.js +17 -0
- package/src/cli/uninstall-command.js +17 -15
- package/src/cli/update-command.js +12 -20
- package/src/cli/update-installation.js +3 -3
- package/src/cli/worker-command.js +80 -0
- package/src/cli/workspace-connection-command.js +1 -4
- package/src/cli.js +11 -10
- package/src/conversations/capture-window.js +44 -0
- package/src/conversations/entry-rules.js +59 -0
- package/src/conversations/fallback-transcript-boundary.js +48 -0
- package/src/conversations/human-interaction.js +9 -0
- package/src/conversations/preference-evidence.js +88 -0
- package/src/conversations/preference-lifecycle.js +32 -0
- package/src/conversations/preference-session.js +119 -0
- package/src/conversations/preference-snapshot.js +93 -0
- package/src/conversations/preference-view.js +31 -0
- package/src/conversations/stop-auto-close.js +28 -0
- package/src/conversations/sync-transcript.js +21 -8
- package/src/conversations/task-context-view.js +123 -36
- package/src/conversations/transcript-append.js +38 -0
- package/src/conversations/transcript-guard-lock.js +59 -0
- package/src/conversations/transcript-guard.js +45 -17
- package/src/conversations/transcript-lifecycle.js +60 -0
- package/src/conversations/transcript-reader.js +24 -3
- package/src/desktop/windows-command-options.js +19 -0
- package/src/desktop/windows-controller.js +160 -0
- package/src/desktop/windows-install.js +55 -0
- package/src/desktop/windows-installation-context.js +49 -0
- package/src/desktop/windows-installation-switch.js +140 -0
- package/src/desktop/windows-installation.js +246 -0
- package/src/desktop/windows-rollback-command.js +24 -0
- package/src/desktop/windows-rollback.js +69 -0
- package/src/desktop/windows-uninstall-command.js +27 -0
- package/src/desktop/windows-uninstall.js +94 -0
- package/src/desktop/windows-update-command.js +29 -0
- package/src/desktop/windows-update-lock.js +38 -0
- package/src/desktop/windows-update-runtime.js +57 -0
- package/src/desktop/windows-update.js +92 -0
- package/src/employees/catalog/assistant.json +26 -0
- package/src/employees/manifest.js +2 -2
- package/src/employees/recruitment.js +5 -2
- package/src/external-knowledge/conflict-policy.js +1 -5
- package/src/external-knowledge/connected-search.js +3 -23
- package/src/external-knowledge/connectors/custom.js +1 -12
- package/src/external-knowledge/connectors/feishu.js +13 -44
- package/src/external-knowledge/connectors/mcp.js +2 -22
- package/src/external-knowledge/connectors/notion.js +6 -47
- package/src/external-knowledge/connectors/response-values.js +34 -0
- package/src/external-knowledge/connectors/retrieval-api.js +2 -32
- package/src/external-knowledge/document-mapping.js +1 -7
- package/src/external-knowledge/service.js +1 -14
- package/src/graphiti/agent-attention.js +35 -2
- package/src/graphiti/agent-collaboration.js +69 -21
- package/src/graphiti/agent-conversations.js +26 -20
- package/src/graphiti/agent-knowledge-workflows.js +124 -52
- package/src/graphiti/capture-policy.js +23 -0
- package/src/graphiti/checkpoint-human-interaction.js +16 -0
- package/src/graphiti/collaboration-preference-projection.js +5 -4
- package/src/graphiti/collaboration-preference-workflow.js +66 -29
- package/src/graphiti/conversation-triage.js +99 -0
- package/src/graphiti/execution-mode.js +27 -0
- package/src/graphiti/federated-application.js +62 -203
- package/src/graphiti/federated-search.js +186 -0
- package/src/graphiti/knowledge-provider-mapping.js +8 -0
- package/src/graphiti/knowledge-result-budget.js +188 -0
- package/src/graphiti/occupation-catalog.js +7 -0
- package/src/graphiti/occupation-staffing.js +21 -0
- package/src/graphiti/project-agent-control-plane.js +49 -4
- package/src/graphiti/project-agent-mapping.js +31 -30
- package/src/graphiti/project-agent-memory.js +1 -1
- package/src/graphiti/project-agent-run-control.js +64 -0
- package/src/graphiti/project-agent-task-entry.js +45 -19
- package/src/graphiti/project-agent-team-context.js +9 -5
- package/src/graphiti/project-agent-workflows.js +47 -7
- package/src/graphiti/project-brief.js +49 -0
- package/src/graphiti/project-memory-usage.js +44 -0
- package/src/graphiti/project-profile-mapping.js +1 -0
- package/src/graphiti/project-team-hierarchy.js +27 -0
- package/src/graphiti/project-team-view.js +14 -1
- package/src/graphiti/provider-client.js +165 -11
- package/src/graphiti/repository-project-registration.js +9 -2
- package/src/graphiti/runtime-config.js +19 -8
- package/src/graphiti/setup.js +2 -2
- package/src/graphiti/task-activity-origin.js +8 -0
- package/src/graphiti/task-agent-assignment.js +49 -0
- package/src/graphiti/task-collaboration-attribution.js +25 -0
- package/src/graphiti/task-entry-activity-origin.js +9 -0
- package/src/graphiti/task-entry-preferences.js +42 -28
- package/src/graphiti/task-entry-project-mention.js +113 -0
- package/src/graphiti/task-entry-project-scope.js +19 -16
- package/src/graphiti/task-experiences.js +53 -0
- package/src/graphiti/task-knowledge-recall.js +46 -9
- package/src/graphiti/task-knowledge-routing.js +130 -0
- package/src/graphiti/task-preference-pages.js +91 -0
- package/src/graphiti/task-preference-reader.js +118 -0
- package/src/graphiti/task-remember.js +100 -0
- package/src/graphiti/user-taste-skill.js +4 -15
- package/src/graphiti/worker-descriptor.js +42 -0
- package/src/graphiti/worker-plan-host.js +92 -0
- package/src/graphiti/worker-run-host.js +276 -0
- package/src/graphiti/worker-run-view.js +25 -0
- package/src/graphiti/worker-task-context.js +154 -0
- package/src/graphiti/workflow-observation.js +3 -13
- package/src/graphiti/writing-taste-profile.js +4 -15
- package/src/http/api-router.js +11 -0
- package/src/http/error-mapping.js +4 -0
- package/src/http/graph-api-router.js +60 -0
- package/src/http/occupation-api-router.js +19 -0
- package/src/http/request-policy.js +1 -1
- package/src/http/task-events-api-router.js +29 -2
- package/src/http/task-schedules-api-router.js +31 -0
- package/src/judgment/conversation.js +12 -0
- package/src/judgment/engine.js +15 -9
- package/src/judgment/routing.js +1 -0
- package/src/judgment/service.js +11 -1
- package/src/local-runtime/lifecycle.js +20 -15
- package/src/local-runtime/processes.js +19 -0
- package/src/local-runtime/provider-readiness.js +41 -0
- package/src/mcp/chat-listing.js +37 -0
- package/src/mcp/context-resources.js +13 -4
- package/src/mcp/create-mcp-server.js +138 -35
- package/src/mcp/direct-call.js +3 -5
- package/src/mcp/instructions.js +15 -1
- package/src/mcp/preference-delivery.js +70 -0
- package/src/mcp/process-registry.js +65 -0
- package/src/mcp/provider-task-context-registry.js +64 -4
- package/src/mcp/runtime.js +15 -3
- package/src/mcp/session-id.js +7 -0
- package/src/mcp/tool-annotations.js +5 -1
- package/src/mcp/tool-profiles.js +5 -19
- package/src/mcp/tool-result.js +69 -9
- package/src/native-runtime/java-runtime.js +47 -0
- package/src/native-runtime/macos-ports.js +41 -0
- package/src/native-runtime/neo4j-asset-state.js +101 -0
- package/src/native-runtime/neo4j-install.js +84 -0
- package/src/native-runtime/neo4j-lifecycle.js +151 -0
- package/src/native-runtime/neo4j-store-formats.js +36 -0
- package/src/native-runtime/runtime.js +246 -146
- package/src/native-runtime/windows-assets.js +70 -0
- package/src/native-runtime/windows-job-process.cs +169 -0
- package/src/native-runtime/windows-job-process.js +110 -0
- package/src/native-runtime/windows-processes.js +289 -0
- package/src/notifications/needs-person.js +75 -0
- package/src/publication/canonical-json.js +13 -7
- package/src/server/worker-plan-runtime.js +49 -0
- package/src/server.js +18 -3
- package/src/setup/agent-installation-status.js +9 -101
- package/src/setup/agents/adapter-contract.js +47 -0
- package/src/setup/agents/claude-code/adapter.test.js +34 -0
- package/src/setup/agents/claude-code/index.js +35 -0
- package/src/setup/agents/claude-desktop/adapter.test.js +34 -0
- package/src/setup/agents/claude-desktop/index.js +22 -0
- package/src/setup/agents/codex/adapter.test.js +34 -0
- package/src/setup/agents/codex/index.js +47 -0
- package/src/setup/agents/config-directory.js +7 -0
- package/src/setup/agents/cursor/adapter.test.js +50 -0
- package/src/setup/agents/cursor/index.js +35 -0
- package/src/setup/agents/gemini/adapter.test.js +32 -0
- package/src/setup/agents/gemini/index.js +14 -0
- package/src/setup/agents/json-mcp.js +66 -0
- package/src/setup/agents/kiro/adapter.test.js +12 -0
- package/src/setup/agents/kiro/index.js +14 -0
- package/src/setup/agents/opencode/adapter.test.js +39 -0
- package/src/setup/agents/opencode/index.js +19 -0
- package/src/setup/agents/qwen-code/adapter.test.js +14 -0
- package/src/setup/agents/qwen-code/index.js +14 -0
- package/src/setup/agents/registration.js +13 -0
- package/src/setup/agents/registry.js +15 -0
- package/src/setup/agents.js +13 -122
- package/src/setup/claude-code-config.js +18 -18
- package/src/setup/claude-desktop-config.js +9 -11
- package/src/setup/client-connection.js +1 -1
- package/src/setup/codex-bootstrap.js +10 -29
- package/src/setup/codex-config.js +59 -26
- package/src/setup/container-runtime.js +28 -29
- package/src/setup/cursor-config.js +10 -11
- package/src/setup/graph-runtime.js +18 -48
- package/src/setup/install-agent.js +77 -0
- package/src/setup/paths.js +8 -1
- package/src/setup/setup.js +17 -36
- package/src/setup/uninstall.js +13 -1
- package/src/storage/json-file.js +7 -1
- package/src/system/client-connection-install.js +27 -0
- package/src/system/client-connection-status.js +5 -3
- package/src/system/main-module.js +16 -0
- package/src/system/open-without-following.js +38 -0
- package/src/system/platform-path.js +8 -0
- package/src/system/runtime-settings.js +12 -7
- package/src/system/settings-apply.js +2 -6
- package/src/system/settings-guide.js +85 -0
- package/src/system/system-service.js +6 -2
- package/src/task-schedules/scheduler.js +32 -0
- package/src/task-schedules/service.js +174 -0
- package/src/task-schedules/store.js +92 -0
- package/src/text/single-line.js +4 -0
- package/src/validation/values.js +44 -0
- package/dist/web/assets/AboutPage-DC3Eu95G.js +0 -1
- package/dist/web/assets/AboutPage-c4dQpUiP.css +0 -1
- package/dist/web/assets/AgentHand-Bex3jrOr.js +0 -1
- package/dist/web/assets/AgentHand-Y83Oo36U.css +0 -1
- package/dist/web/assets/AgentName-E3TrVNIR.js +0 -1
- package/dist/web/assets/AgentProfilePage-pHzDx457.js +0 -1
- package/dist/web/assets/AgentsDirectoryPage-itsP9chX.js +0 -1
- package/dist/web/assets/AgentsDirectoryPage-kc3EgeGO.css +0 -1
- package/dist/web/assets/ConnectionsPage-D0L5VcbN.js +0 -1
- package/dist/web/assets/EmployeeRecruitDialog-CVbqCzHb.css +0 -1
- package/dist/web/assets/EmployeeRecruitDialog-DcYqq75q.js +0 -1
- package/dist/web/assets/EmployeeWorkbenchPage-BDN6whBV.js +0 -3
- package/dist/web/assets/EmployeeWorkbenchPage-BQes4L1f.css +0 -1
- package/dist/web/assets/KnowledgeEditDialog-BnFbCSK7.js +0 -1
- package/dist/web/assets/KnowledgeEditDialog-hT9znkoe.css +0 -1
- package/dist/web/assets/KnowledgeInspector-u0HypEW7.js +0 -1
- package/dist/web/assets/KnowledgeOrganizerPage-B3GoSV-E.js +0 -1
- package/dist/web/assets/KnowledgeOrganizerPage-ccgscrPd.css +0 -1
- package/dist/web/assets/KnowledgePage-DrRnvfrO.js +0 -1
- package/dist/web/assets/KnowledgeWorkspace-D4a7FcAb.css +0 -1
- package/dist/web/assets/KnowledgeWorkspace-_wWZQw_h.js +0 -4
- package/dist/web/assets/NotFoundPage-BcPx7tfG.js +0 -1
- package/dist/web/assets/OverviewPage-8LBN8Shi.css +0 -1
- package/dist/web/assets/OverviewPage-C2jrJWDc.js +0 -1
- package/dist/web/assets/PersonalProfilePage-B0_zIINs.css +0 -1
- package/dist/web/assets/PersonalProfilePage-DkOcops6.js +0 -1
- package/dist/web/assets/PersonalProjectsPage-uJXnueKw.js +0 -1
- package/dist/web/assets/ProjectAgentFirstTask-Bi1ZsTC1.css +0 -1
- package/dist/web/assets/ProjectAgentFirstTask-Cwto-bOU.js +0 -1
- package/dist/web/assets/ProjectAgentsPage-DDuhJnAH.js +0 -12
- package/dist/web/assets/ProjectAgentsPage-VYiEOpFJ.css +0 -1
- package/dist/web/assets/ProjectScopePicker-Bc7A6Rdj.js +0 -1
- package/dist/web/assets/PublicProjectsPage-DKamXDV9.css +0 -1
- package/dist/web/assets/PublicProjectsPage-KvmU4tDo.js +0 -1
- package/dist/web/assets/ReviewPage-BfKG8Hgw.js +0 -1
- package/dist/web/assets/RoundtablesPage-Drou-B81.css +0 -1
- package/dist/web/assets/RoundtablesPage-IXKQq62P.js +0 -1
- package/dist/web/assets/SettingsPage-6FZ7_3-X.css +0 -1
- package/dist/web/assets/SettingsPage-Clhe1bei.js +0 -1
- package/dist/web/assets/SharedJefaReportPage-B55966fF.js +0 -1
- package/dist/web/assets/TaskExecutionPlan-BuEIInIV.css +0 -1
- package/dist/web/assets/TaskExecutionPlan-ZoOE8Ltc.js +0 -2
- package/dist/web/assets/UiButton-DYcQLYXP.js +0 -1
- package/dist/web/assets/UiDialog-D70VuNpZ.js +0 -1
- package/dist/web/assets/UiDisclosure-CaeBp1mn.js +0 -1
- package/dist/web/assets/UiSegmented-DpXRULl-.js +0 -1
- package/dist/web/assets/UiSelect-Alpe2iY3.js +0 -1
- package/dist/web/assets/UiSelect-Bv6R0yr1.css +0 -1
- package/dist/web/assets/WritingTastePage-B_zYD1df.css +0 -1
- package/dist/web/assets/WritingTastePage-BwNCyys9.js +0 -1
- package/dist/web/assets/agent-pins-DbcPCnxU.js +0 -1
- package/dist/web/assets/agent-profile-DTn-2VAG.css +0 -1
- package/dist/web/assets/agent-work-summary-DRJy9v48.js +0 -1
- package/dist/web/assets/attention-store-AfhjzTC5.js +0 -1
- package/dist/web/assets/catalog-ykylXINx.js +0 -1
- package/dist/web/assets/client-CIuQ1icy.css +0 -1
- package/dist/web/assets/client-mT6kHxUd.js +0 -1
- package/dist/web/assets/console-CDOkjZU8.js +0 -1
- package/dist/web/assets/conversation-launcher-settings-CJfHOqqX.js +0 -1
- package/dist/web/assets/i18n-DUTWmrzf.js +0 -10
- package/dist/web/assets/index-DsExj49_.css +0 -1
- package/dist/web/assets/index-pO9miMus.js +0 -5
- package/dist/web/assets/judgment-types-aERVgHxJ.js +0 -1
- package/dist/web/assets/model-DiN6uWZA.js +0 -1
- package/dist/web/assets/personal-profile-graph-C6IZoTJK.js +0 -1
- package/dist/web/assets/project-team-api-B3dwwoUU.js +0 -1
- package/dist/web/assets/shared-report-CGlCpmNd.css +0 -1
- package/dist/web/assets/shared-report-n864kqhr.js +0 -1
- package/dist/web/assets/useAgentRoster-BF8eZGbq.js +0 -1
- package/dist/web/assets/vue-router-CBdnor1K.js +0 -1
- /package/dist/web/assets/{ConnectionsPage-CM9C-zEI.css → TextField-CM9C-zEI.css} +0 -0
- /package/dist/web/assets/{KnowledgeInspector-pgDELOEf.css → VirtualDirectoryList-pgDELOEf.css} +0 -0
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { nonEmptyText, requiredString, uniqueTextArray } from '../../validation/values.js';
|
|
2
|
+
import { onlineUrl, timeoutMilliseconds } from './response-values.js';
|
|
3
|
+
|
|
4
|
+
const HTTPS_ONLY = Object.freeze(['https:']);
|
|
5
|
+
|
|
1
6
|
const API_ROOTS = Object.freeze({
|
|
2
7
|
cn: 'https://open.feishu.cn',
|
|
3
8
|
global: 'https://open.larksuite.com'
|
|
@@ -217,7 +222,7 @@ function feishuRequester(fetchImpl, tokenCache) {
|
|
|
217
222
|
'Content-Type': 'application/json; charset=utf-8'
|
|
218
223
|
},
|
|
219
224
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
220
|
-
signal: AbortSignal.timeout(timeoutMilliseconds(context.config?.timeoutMs))
|
|
225
|
+
signal: AbortSignal.timeout(timeoutMilliseconds(context.config?.timeoutMs, 'Feishu timeoutMs'))
|
|
221
226
|
});
|
|
222
227
|
const payload = await response.json().catch(() => ({}));
|
|
223
228
|
if (!response.ok || payload.code !== 0) {
|
|
@@ -243,7 +248,7 @@ async function accessToken(context, fetchImpl, tokenCache) {
|
|
|
243
248
|
method: 'POST',
|
|
244
249
|
headers: { 'Content-Type': 'application/json; charset=utf-8' },
|
|
245
250
|
body: JSON.stringify({ app_id: appId, app_secret: appSecret }),
|
|
246
|
-
signal: AbortSignal.timeout(timeoutMilliseconds(context.config?.timeoutMs))
|
|
251
|
+
signal: AbortSignal.timeout(timeoutMilliseconds(context.config?.timeoutMs, 'Feishu timeoutMs'))
|
|
247
252
|
}
|
|
248
253
|
);
|
|
249
254
|
const payload = await response.json().catch(() => ({}));
|
|
@@ -298,9 +303,9 @@ async function searchWiki(context, request, source, query, pageToken, limit = 50
|
|
|
298
303
|
}
|
|
299
304
|
|
|
300
305
|
function feishuSource(source, { allowEmpty = false } = {}) {
|
|
301
|
-
const nodeTokens =
|
|
302
|
-
const spaceId =
|
|
303
|
-
const rootNodeToken =
|
|
306
|
+
const nodeTokens = uniqueTextArray(source?.nodeTokens, 'Feishu nodeTokens');
|
|
307
|
+
const spaceId = nonEmptyText(source?.spaceId);
|
|
308
|
+
const rootNodeToken = nonEmptyText(source?.rootNodeToken);
|
|
304
309
|
if (!allowEmpty && !nodeTokens.length && !spaceId) {
|
|
305
310
|
throw new TypeError('Feishu source requires nodeTokens or spaceId');
|
|
306
311
|
}
|
|
@@ -315,7 +320,7 @@ function nodeSummary(node) {
|
|
|
315
320
|
id: node.node_token ?? node.node_id,
|
|
316
321
|
title: node.title ?? node.node_token ?? node.node_id,
|
|
317
322
|
type: normalizedObjectType(node.obj_type),
|
|
318
|
-
url: onlineUrl(node.url),
|
|
323
|
+
url: onlineUrl(node.url, HTTPS_ONLY),
|
|
319
324
|
updatedAt: epochDateTime(node.obj_edit_time),
|
|
320
325
|
metadata: {
|
|
321
326
|
spaceId: node.space_id ?? null,
|
|
@@ -326,9 +331,9 @@ function nodeSummary(node) {
|
|
|
326
331
|
}
|
|
327
332
|
|
|
328
333
|
function nodeUrl(node, source) {
|
|
329
|
-
const direct = onlineUrl(node.url);
|
|
334
|
+
const direct = onlineUrl(node.url, HTTPS_ONLY);
|
|
330
335
|
if (direct) return direct;
|
|
331
|
-
const base = onlineUrl(source?.webBaseUrl);
|
|
336
|
+
const base = onlineUrl(source?.webBaseUrl, HTTPS_ONLY);
|
|
332
337
|
const token = node.node_token ?? node.node_id;
|
|
333
338
|
return base && token ? new URL(`/wiki/${encodeURIComponent(token)}`, base).toString() : null;
|
|
334
339
|
}
|
|
@@ -403,14 +408,6 @@ function environmentValue(env, name, label) {
|
|
|
403
408
|
return value;
|
|
404
409
|
}
|
|
405
410
|
|
|
406
|
-
function idArray(value, label) {
|
|
407
|
-
if (value === undefined || value === null) return [];
|
|
408
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || !item.trim())) {
|
|
409
|
-
throw new TypeError(`${label} must be an array of nonempty strings`);
|
|
410
|
-
}
|
|
411
|
-
return [...new Set(value.map((item) => item.trim()))];
|
|
412
|
-
}
|
|
413
|
-
|
|
414
411
|
function rawContentInterval(value) {
|
|
415
412
|
if (value === undefined || value === null) return 210;
|
|
416
413
|
if (!Number.isInteger(value) || value < 0 || value > 10_000) {
|
|
@@ -419,14 +416,6 @@ function rawContentInterval(value) {
|
|
|
419
416
|
return value;
|
|
420
417
|
}
|
|
421
418
|
|
|
422
|
-
function timeoutMilliseconds(value) {
|
|
423
|
-
if (value === undefined || value === null) return 30_000;
|
|
424
|
-
if (!Number.isInteger(value) || value < 1_000 || value > 120_000) {
|
|
425
|
-
throw new TypeError('Feishu timeoutMs must be between 1000 and 120000');
|
|
426
|
-
}
|
|
427
|
-
return value;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
419
|
function pageSize(value) {
|
|
431
420
|
if (value === undefined || value === null) return 50;
|
|
432
421
|
if (!Number.isInteger(value) || value <= 0) throw new TypeError('Feishu page size is invalid');
|
|
@@ -439,23 +428,3 @@ function epochDateTime(value) {
|
|
|
439
428
|
? new Date(seconds * 1_000).toISOString()
|
|
440
429
|
: null;
|
|
441
430
|
}
|
|
442
|
-
|
|
443
|
-
function onlineUrl(value) {
|
|
444
|
-
if (typeof value !== 'string') return null;
|
|
445
|
-
try {
|
|
446
|
-
const url = new URL(value);
|
|
447
|
-
return url.protocol === 'https:' && !url.username && !url.password ? url.toString() : null;
|
|
448
|
-
} catch {
|
|
449
|
-
return null;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
function optionalString(value) {
|
|
454
|
-
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function requiredString(value, label) {
|
|
458
|
-
const normalized = optionalString(value);
|
|
459
|
-
if (!normalized) throw new TypeError(`${label} is required`);
|
|
460
|
-
return normalized;
|
|
461
|
-
}
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
getDefaultEnvironment
|
|
5
5
|
} from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
6
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
7
|
+
import { requiredString } from '../../validation/values.js';
|
|
8
|
+
import { dateTimeOrNull, onlineUrl } from './response-values.js';
|
|
7
9
|
|
|
8
10
|
const LOCAL_CURSOR_PREFIX = 'fuli-mcp-v1:';
|
|
9
11
|
|
|
@@ -389,23 +391,6 @@ function mcpHttpUrl(value) {
|
|
|
389
391
|
return url;
|
|
390
392
|
}
|
|
391
393
|
|
|
392
|
-
function onlineUrl(value) {
|
|
393
|
-
if (typeof value !== 'string') return null;
|
|
394
|
-
try {
|
|
395
|
-
const url = new URL(value);
|
|
396
|
-
return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password
|
|
397
|
-
? url.toString()
|
|
398
|
-
: null;
|
|
399
|
-
} catch {
|
|
400
|
-
return null;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function dateTimeOrNull(value) {
|
|
405
|
-
if (typeof value !== 'string' || Number.isNaN(Date.parse(value))) return null;
|
|
406
|
-
return new Date(value).toISOString();
|
|
407
|
-
}
|
|
408
|
-
|
|
409
394
|
function plainObject(value) {
|
|
410
395
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
411
396
|
}
|
|
@@ -418,11 +403,6 @@ function stringArray(value) {
|
|
|
418
403
|
return value;
|
|
419
404
|
}
|
|
420
405
|
|
|
421
|
-
function requiredString(value, label) {
|
|
422
|
-
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${label} is required`);
|
|
423
|
-
return value.trim();
|
|
424
|
-
}
|
|
425
|
-
|
|
426
406
|
function assertEnvironmentName(value) {
|
|
427
407
|
if (typeof value !== 'string' || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(value)) {
|
|
428
408
|
throw new TypeError('Environment variable name is invalid');
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { requiredString, uniqueTextArray } from '../../validation/values.js';
|
|
2
|
+
import { dateTimeOrNull, jsonObject, onlineUrl, timeoutMilliseconds } from './response-values.js';
|
|
3
|
+
|
|
1
4
|
const NOTION_API_ROOT = 'https://api.notion.com';
|
|
2
5
|
const NOTION_API_VERSION = '2026-03-11';
|
|
3
6
|
|
|
@@ -123,7 +126,7 @@ function notionRequester(fetchImpl) {
|
|
|
123
126
|
...(body === undefined ? {} : { 'Content-Type': 'application/json' })
|
|
124
127
|
},
|
|
125
128
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
126
|
-
signal: AbortSignal.timeout(timeoutMilliseconds(context.config?.timeoutMs))
|
|
129
|
+
signal: AbortSignal.timeout(timeoutMilliseconds(context.config?.timeoutMs, 'Notion timeoutMs'))
|
|
127
130
|
});
|
|
128
131
|
const payload = await response.json().catch(() => ({}));
|
|
129
132
|
if (!response.ok) {
|
|
@@ -178,8 +181,8 @@ async function notionPageDocument(context, request, page) {
|
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
function notionSources(source, { allowEmpty = false } = {}) {
|
|
181
|
-
const pageIds =
|
|
182
|
-
const dataSourceIds =
|
|
184
|
+
const pageIds = uniqueTextArray(source?.pageIds, 'Notion pageIds');
|
|
185
|
+
const dataSourceIds = uniqueTextArray(source?.dataSourceIds, 'Notion dataSourceIds');
|
|
183
186
|
const sources = [
|
|
184
187
|
...pageIds.map((id) => ({ kind: 'page', id })),
|
|
185
188
|
...dataSourceIds.map((id) => ({ kind: 'data_source', id }))
|
|
@@ -256,52 +259,8 @@ function credentialFromEnvironment(context, key, label) {
|
|
|
256
259
|
return value;
|
|
257
260
|
}
|
|
258
261
|
|
|
259
|
-
function idArray(value, label) {
|
|
260
|
-
if (value === undefined || value === null) return [];
|
|
261
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || !item.trim())) {
|
|
262
|
-
throw new TypeError(`${label} must be an array of nonempty strings`);
|
|
263
|
-
}
|
|
264
|
-
return [...new Set(value.map((item) => item.trim()))];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
262
|
function pageSize(value) {
|
|
268
263
|
if (value === undefined || value === null) return 100;
|
|
269
264
|
if (!Number.isInteger(value) || value <= 0) throw new TypeError('Notion page size is invalid');
|
|
270
265
|
return Math.min(value, 100);
|
|
271
266
|
}
|
|
272
|
-
|
|
273
|
-
function timeoutMilliseconds(value) {
|
|
274
|
-
if (value === undefined || value === null) return 30_000;
|
|
275
|
-
if (!Number.isInteger(value) || value < 1_000 || value > 120_000) {
|
|
276
|
-
throw new TypeError('Notion timeoutMs must be between 1000 and 120000');
|
|
277
|
-
}
|
|
278
|
-
return value;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function requiredString(value, label) {
|
|
282
|
-
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${label} is required`);
|
|
283
|
-
return value.trim();
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function onlineUrl(value) {
|
|
287
|
-
if (typeof value !== 'string') return null;
|
|
288
|
-
try {
|
|
289
|
-
const url = new URL(value);
|
|
290
|
-
return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password
|
|
291
|
-
? url.toString()
|
|
292
|
-
: null;
|
|
293
|
-
} catch {
|
|
294
|
-
return null;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function dateTimeOrNull(value) {
|
|
299
|
-
if (typeof value !== 'string' || Number.isNaN(Date.parse(value))) return null;
|
|
300
|
-
return new Date(value).toISOString();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function jsonObject(value) {
|
|
304
|
-
return value && typeof value === 'object' && !Array.isArray(value)
|
|
305
|
-
? structuredClone(value)
|
|
306
|
-
: {};
|
|
307
|
-
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Shared readers for values that external knowledge sources return or accept.
|
|
2
|
+
|
|
3
|
+
const WEB_PROTOCOLS = Object.freeze(['http:', 'https:']);
|
|
4
|
+
|
|
5
|
+
// A browsable source link without embedded credentials, otherwise null.
|
|
6
|
+
export function onlineUrl(value, protocols = WEB_PROTOCOLS) {
|
|
7
|
+
if (typeof value !== 'string' || !value) return null;
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(value);
|
|
10
|
+
return protocols.includes(url.protocol) && !url.username && !url.password ? url.toString() : null;
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function dateTimeOrNull(value) {
|
|
17
|
+
if (typeof value !== 'string' || Number.isNaN(Date.parse(value))) return null;
|
|
18
|
+
return new Date(value).toISOString();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// A detached copy of a JSON object, or an empty object for anything else.
|
|
22
|
+
export function jsonObject(value) {
|
|
23
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
24
|
+
? structuredClone(value)
|
|
25
|
+
: {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function timeoutMilliseconds(value, label, fallback = 30_000) {
|
|
29
|
+
if (value === undefined || value === null) return fallback;
|
|
30
|
+
if (!Number.isInteger(value) || value < 1_000 || value > 120_000) {
|
|
31
|
+
throw new TypeError(`${label} must be between 1000 and 120000`);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { positiveInteger, requiredString } from '../../validation/values.js';
|
|
3
|
+
import { jsonObject, onlineUrl } from './response-values.js';
|
|
2
4
|
|
|
3
5
|
const DEFAULT_SCORE_THRESHOLD = 0.5;
|
|
4
6
|
const MAX_KNOWLEDGE_BASES = 32;
|
|
@@ -172,24 +174,6 @@ function optionalEnvironmentName(value, label) {
|
|
|
172
174
|
return value;
|
|
173
175
|
}
|
|
174
176
|
|
|
175
|
-
function jsonObject(value) {
|
|
176
|
-
return value && typeof value === 'object' && !Array.isArray(value)
|
|
177
|
-
? structuredClone(value)
|
|
178
|
-
: {};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function onlineUrl(value) {
|
|
182
|
-
if (!value) return null;
|
|
183
|
-
try {
|
|
184
|
-
const url = new URL(value);
|
|
185
|
-
return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password
|
|
186
|
-
? url.toString()
|
|
187
|
-
: null;
|
|
188
|
-
} catch {
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
177
|
function dateTime(value) {
|
|
194
178
|
return value && !Number.isNaN(Date.parse(value))
|
|
195
179
|
? new Date(value).toISOString()
|
|
@@ -206,17 +190,3 @@ function firstString(...values) {
|
|
|
206
190
|
}
|
|
207
191
|
return null;
|
|
208
192
|
}
|
|
209
|
-
|
|
210
|
-
function requiredString(value, label, maximum) {
|
|
211
|
-
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${label} is required`);
|
|
212
|
-
const normalized = value.trim();
|
|
213
|
-
if (normalized.length > maximum) throw new TypeError(`${label} is too long`);
|
|
214
|
-
return normalized;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function positiveInteger(value, label, maximum) {
|
|
218
|
-
if (!Number.isInteger(value) || value <= 0 || value > maximum) {
|
|
219
|
-
throw new TypeError(`${label} must be a positive integer no greater than ${maximum}`);
|
|
220
|
-
}
|
|
221
|
-
return value;
|
|
222
|
-
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
|
|
3
3
|
import { detectSensitiveContent } from '../security/sensitive-content.js';
|
|
4
|
+
import { requiredString } from '../validation/values.js';
|
|
4
5
|
|
|
5
6
|
const MAX_CHUNK_LENGTH = 6_000;
|
|
6
7
|
const MAX_EXCERPT_LENGTH = 2_048;
|
|
@@ -115,13 +116,6 @@ function shortHash(value) {
|
|
|
115
116
|
return createHash('sha256').update(value).digest('hex').slice(0, 24);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
function requiredString(value, label, maximum) {
|
|
119
|
-
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${label} is required`);
|
|
120
|
-
const normalized = value.trim();
|
|
121
|
-
if (normalized.length > maximum) throw new TypeError(`${label} is too long`);
|
|
122
|
-
return normalized;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
119
|
function optionalOnlineUrl(value) {
|
|
126
120
|
if (value === undefined || value === null || value === '') return null;
|
|
127
121
|
const url = new URL(value);
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from './document-mapping.js';
|
|
11
11
|
import { safeExternalSourceDiagnostic } from './safe-diagnostic.js';
|
|
12
12
|
import { ApplicationError } from '../app/application-error.js';
|
|
13
|
+
import { positiveInteger, requiredString } from '../validation/values.js';
|
|
13
14
|
|
|
14
15
|
const MODES = new Set(['hybrid', 'live', 'mirror']);
|
|
15
16
|
const MAX_TARGETS = 32;
|
|
@@ -780,25 +781,11 @@ function normalizedConfigurationKey(key) {
|
|
|
780
781
|
return key.toLocaleLowerCase().replace(/[^a-z0-9]/gu, '');
|
|
781
782
|
}
|
|
782
783
|
|
|
783
|
-
function requiredString(value, label, maximum) {
|
|
784
|
-
if (typeof value !== 'string' || !value.trim()) throw new TypeError(`${label} is required`);
|
|
785
|
-
const normalized = value.trim();
|
|
786
|
-
if (normalized.length > maximum) throw new TypeError(`${label} is too long`);
|
|
787
|
-
return normalized;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
784
|
function optionalString(value, label, maximum) {
|
|
791
785
|
if (value === undefined || value === null || value === '') return null;
|
|
792
786
|
return requiredString(value, label, maximum);
|
|
793
787
|
}
|
|
794
788
|
|
|
795
|
-
function positiveInteger(value, label, maximum) {
|
|
796
|
-
if (!Number.isInteger(value) || value <= 0 || value > maximum) {
|
|
797
|
-
throw new TypeError(`${label} must be a positive integer no greater than ${maximum}`);
|
|
798
|
-
}
|
|
799
|
-
return value;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
789
|
function isCredentialDocumentError(error) {
|
|
803
790
|
return error instanceof TypeError &&
|
|
804
791
|
error.message === 'Connector item contains credentials and cannot be retrieved or stored';
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { nativeChoiceInteraction } from '../conversations/human-interaction.js';
|
|
2
|
+
import { nonEmptyText } from '../validation/values.js';
|
|
3
|
+
|
|
1
4
|
const fields = {
|
|
2
5
|
personalSpaceId: 'personal_space_id', personalProjectId: 'personal_project_id',
|
|
3
6
|
agentId: 'agent_id', taskId: 'task_id', requestId: 'request_id',
|
|
@@ -18,9 +21,39 @@ export function attentionRecord(value) {
|
|
|
18
21
|
|
|
19
22
|
export async function listAgentAttention(application, input) {
|
|
20
23
|
const value = await application.personal.listAgentAttention(attentionInput(input));
|
|
21
|
-
|
|
24
|
+
const items = value.items.map(attentionRecord);
|
|
25
|
+
return { ...attentionInteraction(items.find(item => item.status === 'open')), ...value, items };
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export async function changeAgentAttention(application, operation, input) {
|
|
25
|
-
|
|
29
|
+
const record = attentionRecord(await application.personal.changeAgentAttention(operation, attentionInput(input)));
|
|
30
|
+
return { ...attentionInteraction(record), ...record };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// The console sends the chosen option and an optional note; the Provider keeps
|
|
34
|
+
// them as one response text, and the requesting Agent receives both.
|
|
35
|
+
export async function respondToAgentAttention(application, { choice, note, ...input }) {
|
|
36
|
+
const answer = { choice: nonEmptyText(choice), note: nonEmptyText(note) };
|
|
37
|
+
if (!answer.choice && !answer.note) throw new TypeError('An attention reply needs a choice or a note');
|
|
38
|
+
const record = await changeAgentAttention(application, 'respond', { ...input,
|
|
39
|
+
response: [answer.choice, answer.note].filter(Boolean).join('\n\n') });
|
|
40
|
+
return { ...record, delivery: await deliverAnswer(application, record, answer) };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// The reply is already recorded; a failed delivery leaves it readable through
|
|
44
|
+
// list_agent_attention and is reported, never hidden.
|
|
45
|
+
async function deliverAnswer(application, record, answer) {
|
|
46
|
+
const unavailable = { status: 'unavailable', agentId: record.agentId };
|
|
47
|
+
if (!application.roundtable) return unavailable;
|
|
48
|
+
try { return await application.roundtable.deliverAttentionReply(record, answer); }
|
|
49
|
+
catch { return unavailable; }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function attentionInteraction(record) {
|
|
53
|
+
if (record?.status !== 'open') return {};
|
|
54
|
+
return { human_interaction: nativeChoiceInteraction({
|
|
55
|
+
source: { kind: 'agent_attention', id: record.requestId, revision: record.revision,
|
|
56
|
+
personalSpaceId: record.personalSpaceId, personalProjectId: record.personalProjectId },
|
|
57
|
+
title: record.title, question: record.requestedAction, options: record.options
|
|
58
|
+
}) };
|
|
26
59
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { verificationPreference } from './verification-preference.js';
|
|
2
|
+
import { executionPlan } from './execution-mode.js';
|
|
3
|
+
import { dispatchTarget, subLeadIds, reportingParent } from './project-team-hierarchy.js';
|
|
2
4
|
const lower = values => (values ?? []).map(value => String(value).toLowerCase());
|
|
3
5
|
// Matches Provider staffing: a nonempty assignment list overrides the profile list.
|
|
4
6
|
const effective = (assignment, profile, field) => lower(assignment[field]?.length ? assignment[field] : profile?.[field]);
|
|
@@ -7,6 +9,7 @@ const verificationKinds = new Set(['test_validation', 'verification', 'code_revi
|
|
|
7
9
|
function matchCandidates(agents, task, input) {
|
|
8
10
|
const required = lower(input.requiredCapabilities);
|
|
9
11
|
const workKind = String(input.workKind).toLowerCase();
|
|
12
|
+
const occupation = input.occupation ? String(input.occupation).toLowerCase() : null;
|
|
10
13
|
const candidates = [];
|
|
11
14
|
for (const agent of Array.isArray(agents) ? agents : []) {
|
|
12
15
|
for (const assignment of agent.assignments ?? []) {
|
|
@@ -14,21 +17,27 @@ function matchCandidates(agents, task, input) {
|
|
|
14
17
|
const capabilities = effective(assignment, agent.profile, 'capabilities');
|
|
15
18
|
if (!required.every(value => capabilities.includes(value))) continue;
|
|
16
19
|
const workMatch = effective(assignment, agent.profile, 'work_kinds').includes(workKind);
|
|
17
|
-
|
|
20
|
+
// The lead assigns by occupation first; a matching occupation qualifies on its own.
|
|
21
|
+
const role = agent.occupation?.role ? String(agent.occupation.role).toLowerCase() : null;
|
|
22
|
+
const occupationMatch = Boolean(occupation) && role === occupation;
|
|
23
|
+
if (!workMatch && !occupationMatch && !required.length) continue;
|
|
18
24
|
candidates.push({ agentId: agent.agent_id, name: agent.profile?.display_name || agent.profile?.name,
|
|
19
25
|
projectId: assignment.personal_project_id, capabilities,
|
|
20
26
|
allowedClients: agent.profile?.allowed_clients ?? [],
|
|
21
27
|
clientAvailable: Boolean(agent.profile?.allowed_clients?.includes(input.sourceApplication)),
|
|
22
28
|
...(assignment.responsibility ? { responsibility: assignment.responsibility } : {}),
|
|
23
29
|
requiresLoan: assignment.personal_project_id !== task.personalProjectId,
|
|
30
|
+
...(role ? { occupation: role } : {}), occupationMatch,
|
|
24
31
|
workMatch, activeTasks: agent.open_task_count ?? 0 });
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
return candidates;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
function nextSteps(candidate, taskContextToken, sourceLeadId, personalProjectId) {
|
|
31
|
-
const
|
|
37
|
+
function nextSteps(candidate, taskContextToken, sourceLeadId, personalProjectId, hierarchy = null) {
|
|
38
|
+
const target = hierarchy && !candidate.requiresLoan
|
|
39
|
+
? dispatchTarget(hierarchy.policy, hierarchy.coordinatorAgentId, candidate.agentId) : candidate.agentId;
|
|
40
|
+
const steps = { ask: { tool: 'message_agent', arguments: { to: target }, advisoryOnly: true,
|
|
32
41
|
guidance: 'A roundtable answer is advice from a read-only session, not executed work.' } };
|
|
33
42
|
if (candidate.requiresLoan) {
|
|
34
43
|
steps.borrow = { tool: 'request_agent_loan', arguments: { sourceProjectId: candidate.projectId, specialistId: candidate.agentId },
|
|
@@ -36,7 +45,10 @@ function nextSteps(candidate, taskContextToken, sourceLeadId, personalProjectId)
|
|
|
36
45
|
guidance: 'Only the destination project lead may request. The source lead approves with decide_agent_loan in its own task context before any assignment or execution.' };
|
|
37
46
|
}
|
|
38
47
|
steps.execute = { tool: 'coordinate_project_agent_task',
|
|
39
|
-
arguments: { taskContextToken, personalProjectId,
|
|
48
|
+
arguments: { taskContextToken, personalProjectId, ...(hierarchy ? {
|
|
49
|
+
coordinatorAgentId: hierarchy.coordinatorAgentId, leadAgentId: target,
|
|
50
|
+
...(target !== candidate.agentId ? { workKind: 'delegation', requiredCapabilities: [] } : {})
|
|
51
|
+
} : { collaboratorAgentIds: [candidate.agentId] }) },
|
|
40
52
|
guidance: `${candidate.requiresLoan ? 'After the loan is approved, ' : ''}coordinate under the project lead with an authorized runtime; record the actual worker and result back to the lead.` };
|
|
41
53
|
return steps;
|
|
42
54
|
}
|
|
@@ -59,26 +71,49 @@ export async function planAgentCollaboration(application, input) {
|
|
|
59
71
|
const separated = input.taskSize !== 'small' && !verificationOnly;
|
|
60
72
|
const independent = separated && input.taskSize === 'complex' ? input.independentWork : null;
|
|
61
73
|
const verification = { workKind: input.verificationWorkKind ?? 'test_validation',
|
|
74
|
+
occupation: input.verificationOccupation ?? 'testing',
|
|
62
75
|
requiredCapabilities: input.verificationCapabilities ?? [] };
|
|
63
76
|
const pools = { main: matchCandidates(agents, task, input),
|
|
64
77
|
independent: independent ? matchCandidates(agents, task, { ...input, ...independent,
|
|
65
|
-
requiredCapabilities: independent.requiredCapabilities ?? [] }) : [],
|
|
78
|
+
requiredCapabilities: independent.requiredCapabilities ?? [], occupation: independent.occupation ?? null }) : [],
|
|
66
79
|
verification: separated ? matchCandidates(agents, task, { ...input, ...verification }) : [] };
|
|
67
80
|
// A loan needs the source project's lead, who itself cannot be borrowed.
|
|
68
81
|
const sourceProjects = [...new Set(Object.values(pools).flat().filter(item => item.requiresLoan).map(item => item.projectId))];
|
|
69
82
|
const sourceLeads = Object.fromEntries(await Promise.all(sourceProjects.map(async projectId => [projectId,
|
|
70
83
|
(await application.personal.getProjectAgentCoordinationPolicy(spaceId, projectId))?.team_lead_agent_id ?? null])));
|
|
71
84
|
const token = input.taskContextToken;
|
|
72
|
-
const
|
|
85
|
+
const subLeads = subLeadIds(policy);
|
|
86
|
+
const coordinatorAgentId = subLeads.has(task.projectAgentId) ? task.projectAgentId
|
|
87
|
+
: policy.team_lead_agent_id ?? task.projectAgentId;
|
|
88
|
+
const memberOwner = Boolean(policy.sub_teams?.length && task.projectAgentId !== policy.team_lead_agent_id
|
|
89
|
+
&& !subLeads.has(task.projectAgentId));
|
|
90
|
+
const hierarchy = policy.sub_teams?.length ? { policy, coordinatorAgentId } : null;
|
|
91
|
+
const candidateSteps = candidate => nextSteps(candidate, token, sourceLeads[candidate.projectId], task.personalProjectId, hierarchy);
|
|
92
|
+
const dispatchable = candidate => !policy.sub_teams?.length || (memberOwner ? candidate.agentId === task.projectAgentId : candidate.requiresLoan
|
|
93
|
+
? coordinatorAgentId === policy.team_lead_agent_id
|
|
94
|
+
: dispatchTarget(policy, coordinatorAgentId, candidate.agentId) !== null);
|
|
95
|
+
const throughLead = item => {
|
|
96
|
+
const target = hierarchy && !item.requiresLoan ? dispatchTarget(policy, coordinatorAgentId, item.agentId) : item.agentId;
|
|
97
|
+
if (target === item.agentId || !target) return item;
|
|
98
|
+
const lead = agents.find(agent => agent.agent_id === target && agent.profile?.status !== 'archived'
|
|
99
|
+
&& agent.assignments?.some(assignment => assignment.status === 'active' && assignment.personal_project_id === task.personalProjectId));
|
|
100
|
+
return { ...item, clientAvailable: item.clientAvailable && Boolean(lead?.profile?.allowed_clients?.includes(input.sourceApplication)),
|
|
101
|
+
dispatchAgentId: target };
|
|
102
|
+
};
|
|
103
|
+
const eligible = (pool, excluded = [], available = true) => pool.map(throughLead).filter(item => item.clientAvailable === available && !excluded.includes(item.agentId)
|
|
104
|
+
&& dispatchable(item)
|
|
105
|
+
&& !(subLeads.has(item.agentId) && item.agentId === coordinatorAgentId
|
|
106
|
+
&& !['planning', 'delegation', 'integration', 'reporting'].includes(input.workKind))
|
|
73
107
|
&& (!item.requiresLoan || (sourceLeads[item.projectId] && sourceLeads[item.projectId] !== item.agentId)))
|
|
74
|
-
.sort((a, b) => Number(
|
|
108
|
+
.sort((a, b) => Number(b.occupationMatch) - Number(a.occupationMatch)
|
|
109
|
+
|| Number(a.requiresLoan) - Number(b.requiresLoan) || Number(b.workMatch) - Number(a.workMatch)
|
|
75
110
|
|| a.activeTasks - b.activeTasks || a.agentId.localeCompare(b.agentId));
|
|
76
111
|
const authors = [...new Set([task.projectAgentId, ...(input.implementationAgentIds ?? [])])];
|
|
77
112
|
const mainCandidates = eligible(pools.main, independentAcceptance ? authors : []);
|
|
78
113
|
const unavailableCandidates = eligible(pools.main, independentAcceptance ? authors : [], false);
|
|
79
114
|
const shown = mainCandidates.slice(0, 8).map(item => ({ ...item,
|
|
80
115
|
...(item.requiresLoan ? { sourceLeadId: sourceLeads[item.projectId] } : {}),
|
|
81
|
-
nextSteps:
|
|
116
|
+
nextSteps: candidateSteps(item) }));
|
|
82
117
|
const preferencePrompt = verificationPreference({ executors, rules, projectId: task.personalProjectId,
|
|
83
118
|
lockedExecutorIds: currentAgent.profile?.executorPolicy?.mode === 'locked' ? currentAgent.profile.executorPolicy.lockedExecutorIds : null });
|
|
84
119
|
const judgmentPolicy = await application.judgment?.policy({ personalSpaceId: spaceId, personalProjectId: task.personalProjectId });
|
|
@@ -91,46 +126,59 @@ export async function planAgentCollaboration(application, input) {
|
|
|
91
126
|
const recruit = stream => ({ tool: 'coordinate_project_agent_task',
|
|
92
127
|
arguments: { taskContextToken: token, personalProjectId: task.personalProjectId,
|
|
93
128
|
workKind: stream.workKind, requiredCapabilities: stream.requiredCapabilities ?? [],
|
|
94
|
-
staffingIntent: 'new_durable'
|
|
129
|
+
staffingIntent: 'new_durable',
|
|
130
|
+
// Bole hires by the occupation the workstream asked for, not by guessing from its work kind.
|
|
131
|
+
...(stream.occupation ? { recruitmentOccupation: { role: stream.occupation, tags: [] } } : {}) },
|
|
95
132
|
requires: ['idempotencyKey', 'title', 'objective', 'routingReason', 'contextQueries'],
|
|
96
133
|
coordinatorAgentId: policy.team_lead_agent_id ?? null, askBeforeRecruitment: policy.ask_before_recruitment !== false,
|
|
97
134
|
guidance: 'Reuse one stable idempotencyKey for this staffing need so a retry reuses the same recruitment. When askBeforeRecruitment is true, AR only proposes a hire; confirm with the user before it is staffed. Recruiting executes nothing.' });
|
|
98
|
-
const
|
|
99
|
-
const
|
|
135
|
+
const subTeamCoordinator = subLeads.has(coordinatorAgentId) || memberOwner;
|
|
136
|
+
const recruitment = shown.length || unavailableCandidates.length || subTeamCoordinator ? null : recruit(input);
|
|
100
137
|
function workstream(id, spec, candidate, dependsOn = [], unavailable = []) {
|
|
101
|
-
const
|
|
102
|
-
const
|
|
138
|
+
const target = candidate && !candidate.requiresLoan ? dispatchTarget(policy, coordinatorAgentId, candidate.agentId) : candidate?.agentId;
|
|
139
|
+
const viaSubLead = Boolean(candidate && target !== coordinatorAgentId && subLeads.has(target));
|
|
140
|
+
const continuing = id === 'main' && !independentAcceptance && target === task.projectAgentId;
|
|
141
|
+
const scopeGap = !candidate && !unavailable.length && subTeamCoordinator;
|
|
142
|
+
const blocked = !candidate && (unavailable.length > 0 || scopeGap);
|
|
103
143
|
const dispatch = continuing || blocked ? null : candidate ? { tool: 'coordinate_project_agent_task',
|
|
104
144
|
arguments: { taskContextToken: token, workKind: spec.workKind, requiredCapabilities: spec.requiredCapabilities ?? [],
|
|
105
|
-
leadAgentId:
|
|
145
|
+
leadAgentId: target, ...(viaSubLead ? { workKind: 'delegation', requiredCapabilities: [] } : {}) },
|
|
106
146
|
requires: ['idempotencyKey', 'title', 'objective', 'contextQueries'] } : recruit(spec);
|
|
107
147
|
if (dispatch) Object.assign(dispatch.arguments, { personalProjectId: task.personalProjectId, coordinatorAgentId, contextLimitPerQuery: 3,
|
|
108
148
|
routingReason: `Bounded ${id} workstream; ${dependsOn.length ? 'independent acceptance after stable artifacts' : 'explicit scope'}; report evidence to the project lead.`,
|
|
109
149
|
...(spec.contextQueries ? { contextQueries: spec.contextQueries } : {}) });
|
|
110
|
-
return { id, workKind: spec.workKind, agentId:
|
|
150
|
+
return { id, workKind: spec.workKind, agentId: target ?? null,
|
|
151
|
+
...(viaSubLead ? { executionCandidateAgentId: candidate.agentId,
|
|
152
|
+
reportingGuidance: 'Send a bounded coordination brief to the sub-lead; it delegates within its group and reports to the project lead.' } : {}),
|
|
111
153
|
boundary: spec.boundary ?? (verificationOnly || id === 'verification'
|
|
112
154
|
? '独立检查约定产物与验收条件,返回问题、命令和结果;不改动主线实现。'
|
|
113
155
|
: '负责主线实施与集成;独立工作包之外的修改由此处统一处理。'),
|
|
114
156
|
action: continuing ? 'continue_current' : blocked ? 'blocked' : candidate?.requiresLoan ? 'request_loan' : candidate ? 'delegate' : 'recruit',
|
|
115
157
|
dependsOn, startWhen: dependsOn.length ? 'artifacts_ready' : 'now', dispatch,
|
|
116
|
-
...(
|
|
158
|
+
...(scopeGap ? { blockedReason: 'sub_team_scope_gap', reportToAgentId: reportingParent(policy, task.projectAgentId),
|
|
159
|
+
guidance: 'Report this staffing gap to the project lead; do not bypass your group or recruit a replacement.' }
|
|
160
|
+
: blocked ? { blockedReason: 'qualified_agent_client_unavailable', unavailableCandidates: unavailable,
|
|
117
161
|
guidance: 'A qualified FLA exists but cannot use this client. Select an already authorized eligible client with assess_agent_action or report the constraint; do not recruit a replacement or relax its allowed clients.' } : {}),
|
|
118
162
|
...(candidate?.requiresLoan ? { borrow: nextSteps(candidate, token, sourceLeads[candidate.projectId], task.personalProjectId).borrow } : {}) };
|
|
119
163
|
}
|
|
120
|
-
|
|
121
|
-
|
|
164
|
+
// The lead keeps the main work only when no other occupation was asked for.
|
|
165
|
+
// An explicitly requested occupation is a requirement: without such a member, Bole recruits one.
|
|
166
|
+
const pick = (list, occupation) => occupation ? list.find(candidate => candidate.occupationMatch) : list[0];
|
|
167
|
+
const main = !independentAcceptance && mainCandidates.find(candidate => candidate.agentId === task.projectAgentId
|
|
168
|
+
&& (!input.occupation || candidate.occupationMatch)) || pick(mainCandidates, input.occupation);
|
|
122
169
|
const workstreams = [workstream('main', input, main, [], unavailableCandidates)];
|
|
123
170
|
if (independent) {
|
|
124
171
|
const excluded = [...authors, main?.agentId];
|
|
125
|
-
workstreams.push(workstream('independent', independent, eligible(pools.independent, excluded)
|
|
172
|
+
workstreams.push(workstream('independent', independent, pick(eligible(pools.independent, excluded), independent.occupation), [],
|
|
126
173
|
eligible(pools.independent, excluded, false)));
|
|
127
174
|
}
|
|
128
175
|
if (separated) {
|
|
129
176
|
const excluded = [...authors, ...workstreams.map(stream => stream.agentId)];
|
|
130
|
-
workstreams.push(workstream('verification', verification, eligible(pools.verification, excluded)
|
|
177
|
+
workstreams.push(workstream('verification', verification, pick(eligible(pools.verification, excluded), input.verificationOccupation),
|
|
131
178
|
workstreams.map(stream => stream.id), eligible(pools.verification, excluded, false)));
|
|
132
179
|
}
|
|
133
180
|
const divisionPlan = { mode: separated ? 'separated' : 'single', coordinatorAgentId, workstreams,
|
|
181
|
+
execution: executionPlan(workstreams, input.hostExecutionModes, token),
|
|
134
182
|
reason: separated ? (independent ? '复杂任务有明确独立边界,拆为两个执行工作包和一份独立验收。'
|
|
135
183
|
: '主线延续当前上下文,另一个 FLA 在产物稳定后独立验收,减少重复阅读。')
|
|
136
184
|
: independentAcceptance ? '这是独立验收工作包,排除已知实现者,不再递归拆分。'
|
|
@@ -144,7 +192,7 @@ export async function planAgentCollaboration(application, input) {
|
|
|
144
192
|
candidates: shown, unavailableCandidates, recruitment, pendingLoans: loans.loans?.filter(loan => loan.status === 'requested') ?? [],
|
|
145
193
|
executionStarted: false,
|
|
146
194
|
preferencePrompt, divisionPlan,
|
|
147
|
-
guidance: 'Keep the project lead as owner. Choose a qualified specialist. Discovery and roundtable answers are advisory and are not executed work. For another project, the destination lead calls request_agent_loan; the source lead approves with decide_agent_loan in its own scoped task. Then coordinate_project_agent_task with the borrowed Agent. Share only the bounded task brief and authorized artifacts
|
|
195
|
+
guidance: 'Keep the project lead as user-facing owner. Choose a qualified specialist through its immediate reporting lead; each lead integrates reports upward. Discovery and roundtable answers are advisory and are not executed work. For another project, the destination lead calls request_agent_loan; the source lead approves with decide_agent_loan in its own scoped task. Then coordinate_project_agent_task with the borrowed Agent. Share only the bounded task brief and authorized artifacts; record actual workers. Verify each artifact; use record_agent_verification. Two failed attempts at one capability tier require escalation, not another identical retry. A selected model is not proof of execution or success.' };
|
|
148
196
|
}
|
|
149
197
|
|
|
150
198
|
export async function agentLoan(application, operation, input) {
|