fuli-context 0.7.4-beta.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -6
- package/README.zh-CN.md +69 -6
- package/compose.graphiti.yml +6 -6
- package/dist/web/assets/AboutPage-ByCUor-j.js +1 -0
- package/dist/web/assets/ConnectionsPage-DkdkZ40Q.js +1 -0
- package/dist/web/assets/KnowledgeEditDialog-DSe3Gwep.js +1 -0
- package/dist/web/assets/KnowledgeInspector-CYAjAb9J.js +1 -0
- package/dist/web/assets/KnowledgeOrganizerPage-CV4F54R_.js +1 -0
- package/dist/web/assets/KnowledgePage-vYYXipOi.js +1 -0
- package/dist/web/assets/KnowledgeWorkspace-z4u5mXOG.js +4 -0
- package/dist/web/assets/OverviewPage-BWOfeS6k.js +1 -0
- package/dist/web/assets/PersonalProfilePage-c3w4-h7a.js +1 -0
- package/dist/web/assets/PersonalProjectsPage-B7AlLEwf.js +1 -0
- package/dist/web/assets/ProjectAgentsPage-CgftpIPB.css +1 -0
- package/dist/web/assets/ProjectAgentsPage-DTHcL_ox.js +11 -0
- package/dist/web/assets/PublicProjectsPage-DdH0oGB3.js +1 -0
- package/dist/web/assets/ReviewPage-BYIpcIHG.js +1 -0
- package/dist/web/assets/SearchableSelect-Dz13ClQb.js +1 -0
- package/dist/web/assets/SettingsPage-2VkbXgZi.js +1 -0
- package/dist/web/assets/SettingsPage-CwZp2ka4.css +1 -0
- package/dist/web/assets/WritingTastePage-BOPQZuva.js +1 -0
- package/dist/web/assets/{console-D_2zC4lm.js → console-BlAhujsH.js} +1 -1
- package/dist/web/assets/{conversation-launcher-settings-DQmMH2j7.js → conversation-launcher-settings-DTYxiLJt.js} +1 -1
- package/dist/web/assets/i18n-Ci3heuiL.js +9 -0
- package/dist/web/assets/{identity-DmGcY3Y6.js → identity-4_-v6cB7.js} +1 -1
- package/dist/web/assets/index-BnH5mcZx.css +1 -0
- package/dist/web/assets/index-C67Q0JY2.js +2 -0
- package/dist/web/assets/{model-CVoOdRsL.js → model-yG0YqUyZ.js} +1 -1
- package/dist/web/assets/{useApi-CROJJdhE-CBNg4CdH.js → useApi-CROJJdhE-twhdZArA.js} +1 -1
- package/dist/web/assets/vue-router-C-wot_Di.js +1 -0
- package/dist/web/index.html +6 -6
- package/graph-provider/fuli_graph/app.py +8 -0
- package/graph-provider/fuli_graph/collaboration_context.py +69 -6
- package/graph-provider/fuli_graph/knowledge_search.py +84 -5
- package/graph-provider/fuli_graph/model_validation.py +130 -0
- package/graph-provider/fuli_graph/models.py +24 -5
- package/graph-provider/fuli_graph/project_agent_access.py +54 -0
- package/graph-provider/fuli_graph/project_agent_executor_models.py +635 -0
- package/graph-provider/fuli_graph/project_agent_models.py +278 -0
- package/graph-provider/fuli_graph/project_agent_routes.py +597 -0
- package/graph-provider/fuli_graph/project_agent_task_models.py +542 -0
- package/graph-provider/fuli_graph/runtime.py +259 -0
- package/graph-provider/fuli_graph/search_projection.py +3 -0
- package/graph-provider/fuli_graph/store.py +6 -0
- package/graph-provider/fuli_graph/store_knowledge.py +62 -9
- package/graph-provider/fuli_graph/store_project_agent_executor_learning.py +756 -0
- package/graph-provider/fuli_graph/store_project_agent_executor_routing.py +601 -0
- package/graph-provider/fuli_graph/store_project_agent_executors.py +1087 -0
- package/graph-provider/fuli_graph/store_project_agent_task_reads.py +458 -0
- package/graph-provider/fuli_graph/store_project_agent_task_recruitment.py +699 -0
- package/graph-provider/fuli_graph/store_project_agent_task_staffing.py +409 -0
- package/graph-provider/fuli_graph/store_project_agent_tasks.py +1144 -0
- package/graph-provider/fuli_graph/store_project_agents.py +965 -0
- package/graph-provider/pyproject.toml +2 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/capturing-session-knowledge/SKILL.md +39 -0
- package/src/adaptive-runtime/executor-pool.js +127 -0
- package/src/adaptive-runtime/graph-services.js +166 -0
- package/src/adaptive-runtime/lease-client.js +335 -0
- package/src/adaptive-runtime/runtime-broker.js +318 -0
- package/src/adaptive-runtime/settings.js +111 -0
- package/src/adaptive-runtime/state.js +74 -0
- package/src/agent-tools/graph-definitions.js +396 -0
- package/src/agent-tools/graph-handlers.js +61 -0
- package/src/agent-tools/project-agent-definitions.js +307 -0
- package/src/backup/graph-backup.js +289 -0
- package/src/backup/identity-reconciliation.js +208 -0
- package/src/backup/runtime-adapters.js +269 -0
- package/src/cli/command-registry.js +6 -2
- package/src/cli/graph-data-command.js +112 -0
- package/src/cli/local-runtime-command.js +16 -2
- package/src/cli/setup-command.js +19 -3
- package/src/cli/update-command.js +4 -0
- package/src/cli.js +6 -0
- package/src/graphiti/collaboration-preference-projection.js +29 -1
- package/src/graphiti/collaboration-preference-workflow.js +121 -0
- package/src/graphiti/federated-application.js +53 -90
- package/src/graphiti/project-agent-control-plane.js +263 -0
- package/src/graphiti/project-agent-mapping.js +1003 -0
- package/src/graphiti/project-agent-workflows.js +557 -0
- package/src/graphiti/provider-client.js +270 -1
- package/src/http/api-router.js +63 -9
- package/src/http/graph-api-router.js +278 -0
- package/src/local-runtime/lifecycle.js +46 -10
- package/src/mcp/context-resources.js +15 -6
- package/src/mcp/create-mcp-server.js +51 -16
- package/src/mcp/instructions.js +7 -5
- package/src/mcp/runtime.js +17 -5
- package/src/mcp/session-id.js +38 -1
- package/src/mcp/tool-annotations.js +69 -0
- package/src/mcp-server.js +23 -6
- package/src/native-runtime/runtime.js +717 -0
- package/src/server.js +6 -2
- package/src/setup/agent-installation-status.js +7 -1
- package/src/setup/agents.js +3 -1
- package/src/setup/claude-code-config.js +3 -1
- package/src/setup/codex-bootstrap.js +11 -10
- package/src/setup/codex-config.js +7 -1
- package/src/setup/cursor-config.js +3 -1
- package/src/setup/graph-runtime.js +158 -13
- package/src/setup/neo4j-memory-profile.js +43 -0
- package/src/setup/options.js +38 -2
- package/src/setup/paths.js +14 -0
- package/src/setup/setup.js +37 -1
- package/src/system/resource-monitor.js +181 -16
- package/src/system/runtime-settings.js +10 -1
- package/src/system/system-service.js +27 -2
- package/dist/web/assets/AboutPage-Dpf5fRWv.js +0 -1
- package/dist/web/assets/ConnectionsPage-D21aUDCP.js +0 -1
- package/dist/web/assets/KnowledgeEditDialog-u7lpfN3j.js +0 -1
- package/dist/web/assets/KnowledgeInspector-k4xnHtXd.js +0 -1
- package/dist/web/assets/KnowledgeOrganizerPage-Bdj7Rn84.js +0 -1
- package/dist/web/assets/KnowledgePage-UHVAbC1W.js +0 -1
- package/dist/web/assets/KnowledgeWorkspace-Lq3d-MeC.js +0 -4
- package/dist/web/assets/OverviewPage-CycAgA1V.js +0 -1
- package/dist/web/assets/PersonalProfilePage-U9oIV5FT.js +0 -1
- package/dist/web/assets/PersonalProjectsPage-C5RpXKcA.js +0 -1
- package/dist/web/assets/PublicProjectsPage-DiWxm35E.js +0 -1
- package/dist/web/assets/ReviewPage-jxRfGSJK.js +0 -1
- package/dist/web/assets/SearchableSelect-B3-5IPup.js +0 -1
- package/dist/web/assets/SettingsPage-BqfGDOho.js +0 -1
- package/dist/web/assets/SettingsPage-CAfz4qiV.css +0 -1
- package/dist/web/assets/WritingTastePage-BJxhMqJR.js +0 -1
- package/dist/web/assets/i18n-CwqXDI1C.js +0 -5
- package/dist/web/assets/index-IUGLt4lG.js +0 -2
- package/dist/web/assets/index-X2j29j8i.css +0 -1
- package/dist/web/assets/vue-router-CWSsUUio.js +0 -1
package/src/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
printHelp
|
|
8
8
|
} from './cli/command-registry.js';
|
|
9
9
|
import { runLocalRuntimeCommand } from './cli/local-runtime-command.js';
|
|
10
|
+
import { runGraphDataCommand } from './cli/graph-data-command.js';
|
|
10
11
|
import { runSetupCommand } from './cli/setup-command.js';
|
|
11
12
|
import { runUninstallCommand } from './cli/uninstall-command.js';
|
|
12
13
|
import { runUpdateCommand } from './cli/update-command.js';
|
|
@@ -29,6 +30,11 @@ export async function main(argv = process.argv.slice(2), env = process.env) {
|
|
|
29
30
|
await runSetupCommand(commandArgs, { env });
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
33
|
+
if (command === 'graph') {
|
|
34
|
+
assertSupportedNodeVersion();
|
|
35
|
+
const [action, ...graphArgs] = commandArgs;
|
|
36
|
+
return runGraphDataCommand(action, graphArgs, { env });
|
|
37
|
+
}
|
|
32
38
|
if (command === 'connect-workspace') {
|
|
33
39
|
assertSupportedNodeVersion();
|
|
34
40
|
return runWorkspaceConnectionCommand(commandArgs, { env });
|
|
@@ -10,6 +10,9 @@ export function agentCollaborationPreference(item) {
|
|
|
10
10
|
if (item.preference_project_id) {
|
|
11
11
|
preference.preference_project_id = item.preference_project_id;
|
|
12
12
|
}
|
|
13
|
+
if (item.preference_agent_id) {
|
|
14
|
+
preference.preference_agent_id = item.preference_agent_id;
|
|
15
|
+
}
|
|
13
16
|
for (const field of [
|
|
14
17
|
'attributes',
|
|
15
18
|
'weight',
|
|
@@ -27,10 +30,31 @@ export function agentCollaborationPreference(item) {
|
|
|
27
30
|
return preference;
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
export function activePreferenceConflicts(result) {
|
|
34
|
+
const items = [
|
|
35
|
+
...(result.global_preferences ?? []),
|
|
36
|
+
...(result.project_preferences ?? []),
|
|
37
|
+
...(result.agent_preferences ?? [])
|
|
38
|
+
];
|
|
39
|
+
const itemById = new Map(items.map((item) => [item.id, item]));
|
|
40
|
+
return (result.conflicts ?? []).map((conflict) => ({
|
|
41
|
+
preference_key: conflict.preference_key,
|
|
42
|
+
preference_scope: conflict.preference_scope,
|
|
43
|
+
preference_project_id: conflict.preference_project_id ?? null,
|
|
44
|
+
preference_agent_id: conflict.preference_agent_id ?? null,
|
|
45
|
+
alternatives: (conflict.item_ids ?? [])
|
|
46
|
+
.map((id) => itemById.get(id))
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.map(agentCollaborationPreference),
|
|
49
|
+
required_action: 'Do not apply any alternative until the conflict is resolved.'
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
|
|
30
53
|
export function deferredPreferenceConflicts(result, queuedConflicts) {
|
|
31
54
|
const items = [
|
|
32
55
|
...(result.global_preferences ?? []),
|
|
33
|
-
...(result.project_preferences ?? [])
|
|
56
|
+
...(result.project_preferences ?? []),
|
|
57
|
+
...(result.agent_preferences ?? [])
|
|
34
58
|
];
|
|
35
59
|
const itemById = new Map(items.map((item) => [item.id, item]));
|
|
36
60
|
const activeConflictPairs = new Set(
|
|
@@ -121,6 +145,9 @@ export function agentDeferredPreferenceConflict(conflict) {
|
|
|
121
145
|
...(conflict.preference_project_id
|
|
122
146
|
? { preference_project_id: conflict.preference_project_id }
|
|
123
147
|
: {}),
|
|
148
|
+
...(conflict.preference_agent_id
|
|
149
|
+
? { preference_agent_id: conflict.preference_agent_id }
|
|
150
|
+
: {}),
|
|
124
151
|
status: conflict.status,
|
|
125
152
|
deferred_at: conflict.deferred_at,
|
|
126
153
|
reason: conflict.reason,
|
|
@@ -142,6 +169,7 @@ function agentConflictPreference(item) {
|
|
|
142
169
|
};
|
|
143
170
|
for (const field of [
|
|
144
171
|
'preference_project_id',
|
|
172
|
+
'preference_agent_id',
|
|
145
173
|
'inherited_from_project_id',
|
|
146
174
|
'scope_distance',
|
|
147
175
|
'scope_path',
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
agentProjectResolution
|
|
3
|
+
} from './agent-knowledge-workflows.js';
|
|
4
|
+
import {
|
|
5
|
+
activePreferenceConflicts,
|
|
6
|
+
agentCollaborationPreference,
|
|
7
|
+
agentDeferredPreferenceConflict,
|
|
8
|
+
deferredPreferenceConflicts
|
|
9
|
+
} from './collaboration-preference-projection.js';
|
|
10
|
+
import {
|
|
11
|
+
recallTaskKnowledge,
|
|
12
|
+
TASK_KNOWLEDGE_RETRIEVAL_GUIDANCE
|
|
13
|
+
} from './task-knowledge-recall.js';
|
|
14
|
+
|
|
15
|
+
export async function getCollaborationPreferences(
|
|
16
|
+
application,
|
|
17
|
+
projectResolution,
|
|
18
|
+
{
|
|
19
|
+
projectAgentId = null,
|
|
20
|
+
taskPrompt = null,
|
|
21
|
+
limit = 100,
|
|
22
|
+
agentInvocation = false,
|
|
23
|
+
agentToolName = 'get_collaboration_preferences'
|
|
24
|
+
},
|
|
25
|
+
recordAgentViews
|
|
26
|
+
) {
|
|
27
|
+
const resolvedProjectId = projectResolution.personalProjectId;
|
|
28
|
+
const [result, queuedConflicts] = await Promise.all([
|
|
29
|
+
application.personal.collaborationPreferences(
|
|
30
|
+
application.config.personal.spaceId,
|
|
31
|
+
resolvedProjectId,
|
|
32
|
+
limit,
|
|
33
|
+
projectAgentId
|
|
34
|
+
),
|
|
35
|
+
application.personal.listPreferenceConflicts(
|
|
36
|
+
application.config.personal.spaceId,
|
|
37
|
+
'ai_pending',
|
|
38
|
+
limit
|
|
39
|
+
)
|
|
40
|
+
]);
|
|
41
|
+
const deferredConflicts = deferredPreferenceConflicts(
|
|
42
|
+
result,
|
|
43
|
+
queuedConflicts
|
|
44
|
+
);
|
|
45
|
+
const taskKnowledgeRecall = taskPrompt === null
|
|
46
|
+
? null
|
|
47
|
+
: await recallTaskKnowledge(application, projectResolution, taskPrompt);
|
|
48
|
+
if (agentInvocation) {
|
|
49
|
+
const items = [
|
|
50
|
+
...(result.global_preferences ?? []),
|
|
51
|
+
...(result.project_preferences ?? []),
|
|
52
|
+
...(result.agent_preferences ?? [])
|
|
53
|
+
];
|
|
54
|
+
await recordAgentViews(items.map(({ id, item_kind: itemKind }) => ({
|
|
55
|
+
item_id: id,
|
|
56
|
+
item_kind: itemKind
|
|
57
|
+
})), agentToolName);
|
|
58
|
+
}
|
|
59
|
+
const applicationGuidance = guidanceFor(
|
|
60
|
+
resolvedProjectId,
|
|
61
|
+
projectAgentId
|
|
62
|
+
);
|
|
63
|
+
if (!agentInvocation) {
|
|
64
|
+
return {
|
|
65
|
+
...result,
|
|
66
|
+
deferred_conflicts: deferredConflicts,
|
|
67
|
+
application_guidance: applicationGuidance,
|
|
68
|
+
project_resolution: agentProjectResolution(projectResolution),
|
|
69
|
+
...(taskKnowledgeRecall ? { task_knowledge_recall: taskKnowledgeRecall } : {})
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
effective_preferences: (result.effective_preferences ?? [])
|
|
74
|
+
.map(agentCollaborationPreference),
|
|
75
|
+
deferred_conflicts: deferredConflicts.map(agentDeferredPreferenceConflict),
|
|
76
|
+
active_conflicts: activePreferenceConflicts(result),
|
|
77
|
+
application_guidance: applicationGuidance,
|
|
78
|
+
...(taskKnowledgeRecall ? { task_knowledge_recall: taskKnowledgeRecall } : {}),
|
|
79
|
+
context: preferenceContext(result, deferredConflicts, projectResolution)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function guidanceFor(projectId, projectAgentId) {
|
|
84
|
+
return {
|
|
85
|
+
apply: 'effective_preferences',
|
|
86
|
+
global_scope: 'Apply personal-global preferences in every user task.',
|
|
87
|
+
project_scope: projectId
|
|
88
|
+
? `Also apply preferences scoped to ${projectId} and confirmed ancestor preferences whose descendants or selected-projects mode explicitly reaches it.`
|
|
89
|
+
: 'No exact personal project matched; do not apply project-scoped preferences.',
|
|
90
|
+
agent_scope: projectAgentId
|
|
91
|
+
? `Also apply preferences scoped to project Agent ${projectAgentId}; exclude every other project Agent.`
|
|
92
|
+
: 'No project Agent was selected; do not apply Agent-scoped preferences.',
|
|
93
|
+
inheritance: 'Project preference inheritance follows only PART_OF or USES_KNOWLEDGE_FROM for at most two hops. Preserve inherited_from_project_id, scope_path, and scope_distance. An exact item wins only after confirmation authority is compared; weight never expands scope or resolves a conflict.',
|
|
94
|
+
related_projects: 'RELATED_TO preferences never auto-apply. Use structured related-project suggestions to ask before a one-time read-only expansion.',
|
|
95
|
+
conflicts: 'Do not apply entries listed in conflicts until the user resolves them.',
|
|
96
|
+
deferred_conflicts: 'If the current task would use a deferred_conflict, call resolve_deferred_preference_conflict before applying either side. Ignore unrelated deferred conflicts. The resolution must preserve the AI audit marker.',
|
|
97
|
+
authority: 'Human or authoritative-source confirmed preferences outrank agent-confirmed preferences. Agent-confirmed preferences are usable but lower priority and remain explicitly marked.',
|
|
98
|
+
pending: 'Pending preferences are available only through on-demand knowledge search; invalid and unrelated-project preferences are excluded. Automatic preference injection does not count as usage evidence.',
|
|
99
|
+
knowledge_retrieval: TASK_KNOWLEDGE_RETRIEVAL_GUIDANCE
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function preferenceContext(result, deferredConflicts, projectResolution) {
|
|
104
|
+
return {
|
|
105
|
+
personal_space_id: result.personal_space_id,
|
|
106
|
+
personal_project_id: result.personal_project_id,
|
|
107
|
+
project_agent_id: result.project_agent_id ?? null,
|
|
108
|
+
global_preference_count: (result.global_preferences ?? []).length,
|
|
109
|
+
project_preference_count: (result.project_preferences ?? []).length,
|
|
110
|
+
inherited_project_preference_count: (result.project_preferences ?? [])
|
|
111
|
+
.filter(({ inherited_from_project_id: projectId }) => Boolean(projectId))
|
|
112
|
+
.length,
|
|
113
|
+
agent_preference_count: (result.agent_preferences ?? []).length,
|
|
114
|
+
conflict_count: (result.conflicts ?? []).length,
|
|
115
|
+
ai_deferred_conflict_count: deferredConflicts.length,
|
|
116
|
+
overridden_global_count: (result.overridden_global_ids ?? []).length,
|
|
117
|
+
overridden_project_count: (result.overridden_project_ids ?? []).length,
|
|
118
|
+
source_truncated: result.truncated === true,
|
|
119
|
+
project_resolution: agentProjectResolution(projectResolution)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -28,17 +28,12 @@ import {
|
|
|
28
28
|
createFuliSourceMarker,
|
|
29
29
|
sourceConsoleUrl
|
|
30
30
|
} from './source-marker.js';
|
|
31
|
-
import {
|
|
32
|
-
recallTaskKnowledge,
|
|
33
|
-
TASK_KNOWLEDGE_RETRIEVAL_GUIDANCE
|
|
34
|
-
} from './task-knowledge-recall.js';
|
|
35
31
|
import { resolvePersonalProjectPath } from './project-path-context.js';
|
|
36
32
|
import { mergeExternalKnowledgeProjection } from '../external-knowledge/graph-projection.js';
|
|
37
33
|
import { TaskContextRegistry } from '../mcp/task-context-registry.js';
|
|
38
34
|
import { attachExternalKnowledgeRuntime } from '../external-knowledge/runtime.js';
|
|
39
35
|
import { resolveSetupPaths } from '../setup/paths.js';
|
|
40
36
|
import {
|
|
41
|
-
agentProjectResolution,
|
|
42
37
|
beginTaskContext as beginTaskContextWorkflow,
|
|
43
38
|
checkpointTaskKnowledge as checkpointTaskKnowledgeWorkflow,
|
|
44
39
|
discoverCommonKnowledgeCandidates as discoverCommonKnowledgeCandidatesWorkflow,
|
|
@@ -60,6 +55,10 @@ import {
|
|
|
60
55
|
providerEpisode
|
|
61
56
|
} from './knowledge-provider-mapping.js';
|
|
62
57
|
import { providerProjectProfile } from './project-profile-mapping.js';
|
|
58
|
+
import {
|
|
59
|
+
ProjectAgentControlPlaneApplication,
|
|
60
|
+
projectAgentControlPlaneHooks
|
|
61
|
+
} from './project-agent-control-plane.js';
|
|
63
62
|
import {
|
|
64
63
|
finishKnowledgeReview as finishKnowledgeReviewWorkflow,
|
|
65
64
|
listKnowledgeReviewCandidates as listKnowledgeReviewCandidatesWorkflow,
|
|
@@ -77,10 +76,8 @@ import {
|
|
|
77
76
|
relatedProjectGuidance
|
|
78
77
|
} from './related-project-suggestions.js';
|
|
79
78
|
import {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
deferredPreferenceConflicts
|
|
83
|
-
} from './collaboration-preference-projection.js';
|
|
79
|
+
getCollaborationPreferences as getCollaborationPreferencesWorkflow
|
|
80
|
+
} from './collaboration-preference-workflow.js';
|
|
84
81
|
import { buildUserTasteSkill } from './user-taste-skill.js';
|
|
85
82
|
import { getWritingTasteProfile as getWritingTasteProfileWorkflow } from './writing-taste-profile-workflow.js';
|
|
86
83
|
import {
|
|
@@ -133,7 +130,7 @@ function providerRequestTimeoutFromEnv(env) {
|
|
|
133
130
|
return parsed;
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
export class FederatedGraphApplication {
|
|
133
|
+
export class FederatedGraphApplication extends ProjectAgentControlPlaneApplication {
|
|
137
134
|
constructor(config, {
|
|
138
135
|
fetchImpl = globalThis.fetch,
|
|
139
136
|
capturePolicyStore = new CapturePolicyStore(),
|
|
@@ -143,6 +140,7 @@ export class FederatedGraphApplication {
|
|
|
143
140
|
taskContextRegistry = new TaskContextRegistry(),
|
|
144
141
|
providerRequestTimeoutMs = undefined
|
|
145
142
|
} = {}) {
|
|
143
|
+
super();
|
|
146
144
|
this.graphiti = true;
|
|
147
145
|
this.config = config;
|
|
148
146
|
this.capturePolicyStore = capturePolicyStore;
|
|
@@ -203,10 +201,17 @@ export class FederatedGraphApplication {
|
|
|
203
201
|
const result = await this.personal.commit({
|
|
204
202
|
space_id: input.spaceId,
|
|
205
203
|
personal_project_id: input.personalProjectId ?? null,
|
|
204
|
+
project_agent_id: input.projectAgentId ?? null,
|
|
206
205
|
episode
|
|
207
206
|
});
|
|
208
207
|
return { route: 'personal', ...result };
|
|
209
208
|
}
|
|
209
|
+
if (input.projectAgentId) {
|
|
210
|
+
throw new ApplicationError(
|
|
211
|
+
ApplicationErrorCode.VALIDATION,
|
|
212
|
+
'Project Agent knowledge can only be captured in the personal graph'
|
|
213
|
+
);
|
|
214
|
+
}
|
|
210
215
|
if (episode.sensitivity !== 'normal') {
|
|
211
216
|
throw new ApplicationError(
|
|
212
217
|
ApplicationErrorCode.VALIDATION,
|
|
@@ -249,6 +254,7 @@ export class FederatedGraphApplication {
|
|
|
249
254
|
|
|
250
255
|
async getCollaborationPreferences({
|
|
251
256
|
personalProjectId = null,
|
|
257
|
+
projectAgentId = null,
|
|
252
258
|
projectPath = null,
|
|
253
259
|
taskPrompt = null,
|
|
254
260
|
limit = 100,
|
|
@@ -259,80 +265,18 @@ export class FederatedGraphApplication {
|
|
|
259
265
|
personalProjectId,
|
|
260
266
|
projectPath
|
|
261
267
|
});
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
)
|
|
274
|
-
]);
|
|
275
|
-
const deferredConflicts = deferredPreferenceConflicts(
|
|
276
|
-
result,
|
|
277
|
-
queuedConflicts
|
|
268
|
+
return getCollaborationPreferencesWorkflow(
|
|
269
|
+
this,
|
|
270
|
+
projectResolution,
|
|
271
|
+
{
|
|
272
|
+
projectAgentId,
|
|
273
|
+
taskPrompt,
|
|
274
|
+
limit,
|
|
275
|
+
agentInvocation,
|
|
276
|
+
agentToolName
|
|
277
|
+
},
|
|
278
|
+
(items, toolName) => this.#recordAgentViews(items, toolName)
|
|
278
279
|
);
|
|
279
|
-
const taskKnowledgeRecall = taskPrompt === null
|
|
280
|
-
? null
|
|
281
|
-
: await recallTaskKnowledge(this, projectResolution, taskPrompt);
|
|
282
|
-
if (agentInvocation) {
|
|
283
|
-
const items = [
|
|
284
|
-
...(result.global_preferences ?? []),
|
|
285
|
-
...(result.project_preferences ?? [])
|
|
286
|
-
];
|
|
287
|
-
await this.#recordAgentViews(items.map(({ id, item_kind: itemKind }) => ({
|
|
288
|
-
item_id: id,
|
|
289
|
-
item_kind: itemKind
|
|
290
|
-
})), agentToolName);
|
|
291
|
-
}
|
|
292
|
-
const applicationGuidance = {
|
|
293
|
-
apply: 'effective_preferences',
|
|
294
|
-
global_scope: 'Apply personal-global preferences in every user task.',
|
|
295
|
-
project_scope: resolvedProjectId
|
|
296
|
-
? `Also apply preferences scoped to ${resolvedProjectId} and confirmed ancestor preferences whose descendants or selected-projects mode explicitly reaches it.`
|
|
297
|
-
: 'No exact personal project matched; do not apply project-scoped preferences.',
|
|
298
|
-
inheritance: 'Project preference inheritance follows only PART_OF or USES_KNOWLEDGE_FROM for at most two hops. Preserve inherited_from_project_id, scope_path, and scope_distance. An exact item wins only after confirmation authority is compared; weight never expands scope or resolves a conflict.',
|
|
299
|
-
related_projects: 'RELATED_TO preferences never auto-apply. Use structured related-project suggestions to ask before a one-time read-only expansion.',
|
|
300
|
-
conflicts: 'Do not apply entries listed in conflicts until the user resolves them.',
|
|
301
|
-
deferred_conflicts: 'If the current task would use a deferred_conflict, call resolve_deferred_preference_conflict before applying either side. Ignore unrelated deferred conflicts. The resolution must preserve the AI audit marker.',
|
|
302
|
-
authority: 'Human or authoritative-source confirmed preferences outrank agent-confirmed preferences. Agent-confirmed preferences are usable but lower priority and remain explicitly marked.',
|
|
303
|
-
pending: 'Pending preferences are available only through on-demand knowledge search; invalid and unrelated-project preferences are excluded. Automatic preference injection never counts as usage evidence.',
|
|
304
|
-
knowledge_retrieval: TASK_KNOWLEDGE_RETRIEVAL_GUIDANCE
|
|
305
|
-
};
|
|
306
|
-
if (!agentInvocation) {
|
|
307
|
-
return {
|
|
308
|
-
...result,
|
|
309
|
-
deferred_conflicts: deferredConflicts,
|
|
310
|
-
application_guidance: applicationGuidance,
|
|
311
|
-
project_resolution: agentProjectResolution(projectResolution),
|
|
312
|
-
...(taskKnowledgeRecall ? { task_knowledge_recall: taskKnowledgeRecall } : {})
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
return {
|
|
316
|
-
effective_preferences: (result.effective_preferences ?? [])
|
|
317
|
-
.map(agentCollaborationPreference),
|
|
318
|
-
deferred_conflicts: deferredConflicts.map(agentDeferredPreferenceConflict),
|
|
319
|
-
application_guidance: applicationGuidance,
|
|
320
|
-
...(taskKnowledgeRecall ? { task_knowledge_recall: taskKnowledgeRecall } : {}),
|
|
321
|
-
context: {
|
|
322
|
-
personal_space_id: result.personal_space_id,
|
|
323
|
-
personal_project_id: result.personal_project_id,
|
|
324
|
-
global_preference_count: (result.global_preferences ?? []).length,
|
|
325
|
-
project_preference_count: (result.project_preferences ?? []).length,
|
|
326
|
-
inherited_project_preference_count: (result.project_preferences ?? [])
|
|
327
|
-
.filter(({ inherited_from_project_id: projectId }) => Boolean(projectId))
|
|
328
|
-
.length,
|
|
329
|
-
conflict_count: (result.conflicts ?? []).length,
|
|
330
|
-
ai_deferred_conflict_count: deferredConflicts.length,
|
|
331
|
-
overridden_global_count: (result.overridden_global_ids ?? []).length,
|
|
332
|
-
source_truncated: result.truncated === true,
|
|
333
|
-
project_resolution: agentProjectResolution(projectResolution)
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
280
|
}
|
|
337
281
|
|
|
338
282
|
async getUserTasteSkill({
|
|
@@ -415,6 +359,7 @@ export class FederatedGraphApplication {
|
|
|
415
359
|
query,
|
|
416
360
|
projectIds = [],
|
|
417
361
|
personalProjectId = null,
|
|
362
|
+
projectAgentId = null,
|
|
418
363
|
contextPersonalProjectIds = [],
|
|
419
364
|
personalProjectScope = 'bounded',
|
|
420
365
|
limit = 12,
|
|
@@ -429,6 +374,11 @@ export class FederatedGraphApplication {
|
|
|
429
374
|
if (!['bounded', 'all_local_confirmed'].includes(personalProjectScope)) {
|
|
430
375
|
throw new TypeError('Unknown personal project search scope');
|
|
431
376
|
}
|
|
377
|
+
if (projectAgentId && (!personalProjectId || personalProjectScope !== 'bounded')) {
|
|
378
|
+
throw new TypeError(
|
|
379
|
+
'Project Agent search requires one bounded active personal project'
|
|
380
|
+
);
|
|
381
|
+
}
|
|
432
382
|
const subscriptions = projectIds.length
|
|
433
383
|
? await this.personal.listSubscriptions(personalSpaceId)
|
|
434
384
|
: [];
|
|
@@ -447,21 +397,25 @@ export class FederatedGraphApplication {
|
|
|
447
397
|
)
|
|
448
398
|
: personalContextProjectIds(personalProjectId, contextPersonalProjectIds);
|
|
449
399
|
const personalSearches = personalProjectSearchBatches(selectedPersonalProjectIds)
|
|
450
|
-
.map((personalProjectIds, index) =>
|
|
400
|
+
.map((personalProjectIds, index) => {
|
|
401
|
+
const activePersonalProjectId = (
|
|
402
|
+
personalProjectScope === 'bounded' &&
|
|
403
|
+
personalProjectId &&
|
|
404
|
+
personalProjectIds.includes(personalProjectId)
|
|
405
|
+
) ? personalProjectId : null;
|
|
406
|
+
return this.personal.search({
|
|
451
407
|
space_ids: [personalSpaceId],
|
|
452
408
|
query,
|
|
453
409
|
limit,
|
|
454
410
|
include_historical: includeHistorical,
|
|
455
411
|
include_exploratory: includePending,
|
|
456
412
|
personal_project_ids: personalProjectIds,
|
|
457
|
-
active_personal_project_id:
|
|
458
|
-
|
|
459
|
-
personalProjectId &&
|
|
460
|
-
personalProjectIds.includes(personalProjectId)
|
|
461
|
-
) ? personalProjectId : null,
|
|
413
|
+
active_personal_project_id: activePersonalProjectId,
|
|
414
|
+
project_agent_id: activePersonalProjectId ? projectAgentId : null,
|
|
462
415
|
inherit_project_knowledge: personalProjectScope === 'bounded',
|
|
463
416
|
include_personal_global: index === 0
|
|
464
|
-
|
|
417
|
+
});
|
|
418
|
+
});
|
|
465
419
|
const grouped = groupSubscriptions(selectedSubscriptions);
|
|
466
420
|
const workspaceSearches = [...grouped.entries()].map(([providerUrl, items]) => {
|
|
467
421
|
const projectIdsForProvider = items.map(({ project_id: projectId }) => projectId);
|
|
@@ -549,6 +503,7 @@ export class FederatedGraphApplication {
|
|
|
549
503
|
entities,
|
|
550
504
|
personalGlobalIncluded: true,
|
|
551
505
|
personalProjectScope,
|
|
506
|
+
projectAgentId,
|
|
552
507
|
searchedPersonalProjectIds: selectedPersonalProjectIds,
|
|
553
508
|
requestedProjectIds,
|
|
554
509
|
searchedProjectIds,
|
|
@@ -1232,6 +1187,14 @@ export class FederatedGraphApplication {
|
|
|
1232
1187
|
}
|
|
1233
1188
|
}
|
|
1234
1189
|
|
|
1190
|
+
[projectAgentControlPlaneHooks.assertActivePersonalSpace](personalSpaceId) {
|
|
1191
|
+
this.#assertActivePersonalSpace(personalSpaceId);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
async [projectAgentControlPlaneHooks.resolvePreferenceProject](input) {
|
|
1195
|
+
return this.#resolvePreferenceProject(input);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1235
1198
|
#workspace(providerUrl) {
|
|
1236
1199
|
const requested = providerUrl
|
|
1237
1200
|
? canonicalProviderUrl(providerUrl)
|