fuli-context 0.7.2 → 0.7.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 +3 -3
- package/dist/web/assets/{AboutPage-DfnZo7Lo.js → AboutPage-qeO_vm0T.js} +1 -1
- package/dist/web/assets/{ConnectionsPage-BloaSKmt.js → ConnectionsPage-DO0GR9Xg.js} +1 -1
- package/dist/web/assets/{KnowledgeInspector-QvNpv0_k.js → KnowledgeInspector-DEW5lA1m.js} +1 -1
- package/dist/web/assets/{KnowledgeOrganizerPage-DKq1jVD5.js → KnowledgeOrganizerPage-BkM568Ld.js} +1 -1
- package/dist/web/assets/KnowledgePage-BAT4aZIm.js +1 -0
- package/dist/web/assets/{KnowledgeWorkspace-Czq6aZ7b.js → KnowledgeWorkspace-DyGtBz--.js} +1 -1
- package/dist/web/assets/OverviewPage-CmCcDCAs.js +1 -0
- package/dist/web/assets/{PersonalProfilePage-tVChM9ik.js → PersonalProfilePage-C42mwKN8.js} +1 -1
- package/dist/web/assets/PersonalProjectsPage-BwaXR62K.js +1 -0
- package/dist/web/assets/{PublicProjectsPage-BPJSeREN.js → PublicProjectsPage-egKBulOq.js} +1 -1
- package/dist/web/assets/{ReviewPage-B7EN817i.js → ReviewPage-B3vnZ6gn.js} +1 -1
- package/dist/web/assets/{SearchableSelect-ClLN0rIb.js → SearchableSelect-ih69qbcS.js} +1 -1
- package/dist/web/assets/{SettingsPage-Chd_B3eH.js → SettingsPage-oLE8mNs5.js} +1 -1
- package/dist/web/assets/{console-CbDsKrsO.js → console-DE40hXGC.js} +1 -1
- package/dist/web/assets/{i18n-BQcns1PH.js → i18n-CDxBs1sz.js} +1 -1
- package/dist/web/assets/{identity-B8K4VYg6.js → identity-BCxb1mcy.js} +1 -1
- package/dist/web/assets/{index-CB8Xmsc2.js → index-BzhNfzU_.js} +2 -2
- package/dist/web/assets/index-CCOGfZzE.css +1 -0
- package/dist/web/assets/{model-eF52GgPF.js → model-CCMdt10Q.js} +1 -1
- package/dist/web/assets/{paths-hwz-Ac1g.js → paths-DwHeiGMT.js} +1 -1
- package/dist/web/assets/{useMinimumLoadingDisplay-wCgGDmHg.js → useMinimumLoadingDisplay-HdI7XAmu.js} +1 -1
- package/dist/web/assets/{vue-router-BsEp_XwI.js → vue-router-Drfl1F8i.js} +1 -1
- package/dist/web/index.html +6 -6
- package/graph-provider/fuli_graph/knowledge_review.py +49 -4
- package/graph-provider/fuli_graph/knowledge_review_models.py +11 -5
- package/graph-provider/pyproject.toml +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/flreview/SKILL.md +67 -40
- package/skills/flreview/agents/openai.yaml +2 -2
- package/src/agent-tools/graph-definitions.js +4 -4
- package/src/graphiti/federated-application.js +2 -1
- package/src/mcp/create-mcp-server.js +3 -1
- package/README.en.md +0 -5
- package/dist/web/assets/KnowledgePage-BWL0jT01.js +0 -1
- package/dist/web/assets/OverviewPage-5sJoO1Gh.js +0 -1
- package/dist/web/assets/PersonalProjectsPage-BPFrup4V.js +0 -1
- package/dist/web/assets/index-CZeuPh-U.css +0 -1
|
@@ -159,6 +159,12 @@ async def list_knowledge_review_candidates(
|
|
|
159
159
|
review_id=run.review_id,
|
|
160
160
|
routing_='r',
|
|
161
161
|
)
|
|
162
|
+
deferred_rows, _, _ = await store.runtime.driver.execute_query(
|
|
163
|
+
_DEFERRED_ITEM_QUERY,
|
|
164
|
+
space_id=space['id'],
|
|
165
|
+
review_id=run.review_id,
|
|
166
|
+
routing_='r',
|
|
167
|
+
)
|
|
162
168
|
candidates = build_review_candidates(
|
|
163
169
|
[dict(row) for row in [*entity_rows, *relationship_rows]],
|
|
164
170
|
scope=run.scope,
|
|
@@ -174,6 +180,12 @@ async def list_knowledge_review_candidates(
|
|
|
174
180
|
decided_candidate_keys={
|
|
175
181
|
row['candidate_key'] for row in decision_rows
|
|
176
182
|
},
|
|
183
|
+
deferred_candidate_keys={
|
|
184
|
+
key
|
|
185
|
+
for row in deferred_rows
|
|
186
|
+
for key in row.get('candidate_keys', [])
|
|
187
|
+
if key
|
|
188
|
+
},
|
|
177
189
|
)
|
|
178
190
|
selected = candidates[:request.limit]
|
|
179
191
|
return KnowledgeReviewCandidatePage(
|
|
@@ -272,7 +284,9 @@ def build_review_candidates(
|
|
|
272
284
|
review_cutoff_at: datetime | None = None,
|
|
273
285
|
conflict_item_keys: set[str],
|
|
274
286
|
decided_candidate_keys: set[str],
|
|
287
|
+
deferred_candidate_keys: set[str] | None = None,
|
|
275
288
|
) -> list[KnowledgeReviewCandidate]:
|
|
289
|
+
deferred_candidate_keys = deferred_candidate_keys or set()
|
|
276
290
|
prepared = []
|
|
277
291
|
for row in rows:
|
|
278
292
|
candidate_key = f"{row['item_kind']}:{row['item_id']}"
|
|
@@ -328,6 +342,7 @@ def build_review_candidates(
|
|
|
328
342
|
normalized,
|
|
329
343
|
previous_completed_at,
|
|
330
344
|
candidate_key in conflict_item_keys,
|
|
345
|
+
candidate_key in deferred_candidate_keys,
|
|
331
346
|
)
|
|
332
347
|
if not reasons:
|
|
333
348
|
continue
|
|
@@ -426,6 +441,7 @@ def _normalize_item_row(row: dict[str, Any]) -> dict[str, Any]:
|
|
|
426
441
|
'preference_project_id': row.get('preference_project_id'),
|
|
427
442
|
'project_ids': project_ids,
|
|
428
443
|
'confirmation_status': row.get('confirmation_status') or 'pending',
|
|
444
|
+
'current_quadrant': row.get('current_quadrant') or 'known_known',
|
|
429
445
|
'utility_score': _float_or_default(row.get('utility_score'), 0),
|
|
430
446
|
'confidence_score': _float_or_default(row.get('confidence_score'), 0.5),
|
|
431
447
|
'qualified_use_count': int(row.get('qualified_use_count') or 0),
|
|
@@ -471,12 +487,15 @@ def _candidate_reasons(
|
|
|
471
487
|
item: dict,
|
|
472
488
|
previous_completed_at: datetime | None,
|
|
473
489
|
has_conflict: bool,
|
|
490
|
+
was_deferred: bool,
|
|
474
491
|
) -> list[str]:
|
|
475
492
|
reasons = []
|
|
476
493
|
if previous_completed_at is None or (
|
|
477
494
|
item['changed_at'] is not None and item['changed_at'] > previous_completed_at
|
|
478
495
|
):
|
|
479
496
|
reasons.append('changed_since_last')
|
|
497
|
+
if was_deferred:
|
|
498
|
+
reasons.append('deferred_from_previous')
|
|
480
499
|
if (
|
|
481
500
|
has_conflict
|
|
482
501
|
or item['requires_attention']
|
|
@@ -496,6 +515,7 @@ def _candidate_reasons(
|
|
|
496
515
|
def _reason_priority(reason: str) -> int:
|
|
497
516
|
return {
|
|
498
517
|
'changed_since_last': 1,
|
|
518
|
+
'deferred_from_previous': 1,
|
|
499
519
|
'conflict_or_attention': 2,
|
|
500
520
|
'low_weight': 3,
|
|
501
521
|
'repeated_cross_session': 4,
|
|
@@ -539,6 +559,11 @@ RETURN item.uuid AS item_id,
|
|
|
539
559
|
item.fuli_profile_aspect AS profile_aspect,
|
|
540
560
|
item.fuli_preference_scope AS preference_scope,
|
|
541
561
|
item.fuli_preference_project_id AS preference_project_id,
|
|
562
|
+
coalesce(
|
|
563
|
+
item.fuli_current_quadrant,
|
|
564
|
+
item.fuli_origin_quadrant,
|
|
565
|
+
'known_known'
|
|
566
|
+
) AS current_quadrant,
|
|
542
567
|
collect(DISTINCT assignment.project_id) AS assigned_project_ids,
|
|
543
568
|
collect(DISTINCT episode.fuli_personal_project_id) AS evidence_project_ids,
|
|
544
569
|
collect(DISTINCT episode.fuli_session_id) AS session_ids,
|
|
@@ -576,6 +601,11 @@ RETURN item.uuid AS item_id,
|
|
|
576
601
|
item.fuli_profile_aspect AS profile_aspect,
|
|
577
602
|
item.fuli_preference_scope AS preference_scope,
|
|
578
603
|
item.fuli_preference_project_id AS preference_project_id,
|
|
604
|
+
coalesce(
|
|
605
|
+
item.fuli_current_quadrant,
|
|
606
|
+
item.fuli_origin_quadrant,
|
|
607
|
+
'known_known'
|
|
608
|
+
) AS current_quadrant,
|
|
579
609
|
collect(DISTINCT assignment.project_id) AS assigned_project_ids,
|
|
580
610
|
collect(DISTINCT episode.fuli_personal_project_id) AS evidence_project_ids,
|
|
581
611
|
collect(DISTINCT episode.fuli_session_id) AS session_ids,
|
|
@@ -605,8 +635,23 @@ WITH space, collect(DISTINCT 'entity:' + knowledge.item_id) +
|
|
|
605
635
|
AS knowledge_keys
|
|
606
636
|
OPTIONAL MATCH (space)-[:HAS_PREFERENCE_CONFLICT]->
|
|
607
637
|
(preference:FuliPreferenceConflict {status: 'ai_pending'})
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
638
|
+
WITH knowledge_keys,
|
|
639
|
+
collect(DISTINCT preference.left_item_kind + ':' + preference.left_item_id) +
|
|
640
|
+
collect(DISTINCT preference.right_item_kind + ':' + preference.right_item_id)
|
|
641
|
+
AS preference_keys
|
|
642
|
+
RETURN knowledge_keys + preference_keys AS candidate_keys
|
|
643
|
+
'''
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
_DEFERRED_ITEM_QUERY = '''
|
|
647
|
+
MATCH (:FuliSpace {id: $space_id, kind: 'personal'})-
|
|
648
|
+
[:HAS_KNOWLEDGE_REVIEW]->(past_run:FuliKnowledgeReviewRun)
|
|
649
|
+
WHERE past_run.id <> $review_id
|
|
650
|
+
MATCH (past_run)-[:HAS_REVIEW_DECISION]->
|
|
651
|
+
(decision:FuliKnowledgeReviewDecision)
|
|
652
|
+
WITH decision.candidate_key AS candidate_key, decision
|
|
653
|
+
ORDER BY decision.updated_at DESC, decision.id DESC
|
|
654
|
+
WITH candidate_key, collect(decision)[0] AS latest_decision
|
|
655
|
+
WHERE latest_decision.outcome = 'deferred'
|
|
656
|
+
RETURN collect(candidate_key) AS candidate_keys
|
|
612
657
|
'''
|
|
@@ -5,6 +5,7 @@ from pydantic import Field, model_validator
|
|
|
5
5
|
|
|
6
6
|
from .models import (
|
|
7
7
|
ConfirmationStatus,
|
|
8
|
+
EpistemicQuadrant,
|
|
8
9
|
KnowledgeFeedbackKind,
|
|
9
10
|
KnowledgeItemKind,
|
|
10
11
|
PersonalProfileAspect,
|
|
@@ -22,10 +23,11 @@ KnowledgeReviewScope = Literal[
|
|
|
22
23
|
KnowledgeReviewStatus = Literal['active', 'paused', 'completed']
|
|
23
24
|
KnowledgeReviewDisposition = Literal['paused', 'completed']
|
|
24
25
|
KnowledgeReviewOutcome = Literal[
|
|
25
|
-
'confirmed', 'updated', 'invalidated', '
|
|
26
|
+
'confirmed', 'updated', 'invalidated', 'deferred', 'delegated_to_ai'
|
|
26
27
|
]
|
|
27
28
|
KnowledgeReviewReason = Literal[
|
|
28
29
|
'changed_since_last',
|
|
30
|
+
'deferred_from_previous',
|
|
29
31
|
'conflict_or_attention',
|
|
30
32
|
'low_weight',
|
|
31
33
|
'repeated_cross_session',
|
|
@@ -68,11 +70,17 @@ class KnowledgeReviewCandidate(StrictModel):
|
|
|
68
70
|
item_kind: KnowledgeItemKind
|
|
69
71
|
title: str
|
|
70
72
|
content: str
|
|
73
|
+
# Keep the decision-critical ranking context near the front of the wire
|
|
74
|
+
# payload. Older MCP clients may project a bounded prefix of the Provider
|
|
75
|
+
# response, and the user must still see why a candidate was selected.
|
|
76
|
+
priority: int = Field(ge=1, le=4)
|
|
77
|
+
reasons: list[KnowledgeReviewReason]
|
|
78
|
+
confirmation_status: ConfirmationStatus
|
|
79
|
+
current_quadrant: EpistemicQuadrant
|
|
80
|
+
project_ids: list[str] = Field(default_factory=list)
|
|
71
81
|
profile_aspect: PersonalProfileAspect | None = None
|
|
72
82
|
preference_scope: PreferenceScope | None = None
|
|
73
83
|
preference_project_id: str | None = None
|
|
74
|
-
project_ids: list[str] = Field(default_factory=list)
|
|
75
|
-
confirmation_status: ConfirmationStatus
|
|
76
84
|
utility_score: float = Field(ge=0, le=1)
|
|
77
85
|
confidence_score: float = Field(ge=0, le=1)
|
|
78
86
|
qualified_use_count: int = Field(ge=0)
|
|
@@ -82,8 +90,6 @@ class KnowledgeReviewCandidate(StrictModel):
|
|
|
82
90
|
last_feedback_kind: KnowledgeFeedbackKind | None = None
|
|
83
91
|
distinct_session_count: int = Field(ge=0)
|
|
84
92
|
changed_at: datetime | None = None
|
|
85
|
-
priority: int = Field(ge=1, le=4)
|
|
86
|
-
reasons: list[KnowledgeReviewReason]
|
|
87
93
|
|
|
88
94
|
|
|
89
95
|
class KnowledgeReviewCandidateRequest(StrictModel):
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fuli-context",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "fuli-context",
|
|
9
|
-
"version": "0.7.
|
|
9
|
+
"version": "0.7.3",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@hono/node-server": "2.0.12",
|
package/package.json
CHANGED
package/skills/flreview/SKILL.md
CHANGED
|
@@ -5,69 +5,96 @@ description: Use when the user explicitly enters /flreview or explicitly asks to
|
|
|
5
5
|
|
|
6
6
|
# Fuli Knowledge Review
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
The invoking Agent owns each review session. FULI supplies durable knowledge, deterministic candidate ranking, and write tools; the Agent generates a fresh interactive review page for this invocation. There is no permanent **知识回顾** tab to open.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Start The Session
|
|
11
11
|
|
|
12
|
-
For every `/flreview
|
|
12
|
+
For every exact `/flreview` invocation or explicit request to run the Fuli knowledge review:
|
|
13
13
|
|
|
14
|
-
1.
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
14
|
+
1. Use `list_knowledge_spaces` to identify the active personal space, then call `list_personal_projects` so every project choice uses a real local personal project.
|
|
15
|
+
2. Use the `visualize` Skill to render an inline setup page in the current task. Collect scope and review depth in that page, not as serial chat questions. Ask patience first. If the user selects **完全没耐心**, hide mood, available-time, and token-budget fields and use a small highest-priority batch. Otherwise collect mood, available time, and token comfort together on the same setup page. These answers control only batch size and explanation depth, never Provider ranking. If the user's request already gives an exact scope and depth, skip setup.
|
|
16
|
+
3. On the setup page's explicit start action, call `start_knowledge_review` with the selected scope. Then call `list_knowledge_review_candidates` with a bounded page size matching the selected depth.
|
|
17
|
+
4. Generate all candidates from that batch on the same interactive page. Show all candidates at once; do not reveal them one at a time.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
The setup scope tree is:
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
- **全部** — global preferences plus every local personal project's knowledge and project-scoped preferences.
|
|
22
|
+
- **个人偏好** — global preferences or one selected local personal project's preferences.
|
|
23
|
+
- **个人项目** — one selected local personal project or all local personal projects. A project includes its knowledge and project-scoped preferences.
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
Never infer the current directory as the selected project. Never include subscribed or public projects.
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
A bounded page limit is a batch size, not a fixed total-question cap.
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
- Otherwise ask, concisely, about current mood, available time, and whether token budget is comfortable. Use the answers plus explicit requests such as “少问一点”, “多问一点”, or “直接开始” to choose page size and explanation depth.
|
|
28
|
-
- Do not impose a fixed total-question cap. A tool page limit controls only one retrieval batch, not the length of the review.
|
|
29
|
+
## Generated Review Page
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
Follow the `visualize` Skill's inline-artifact rules. The artifact must not use `fetch`, XHR, WebSocket, or a direct FULI API. Every submitted action must call:
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
```js
|
|
34
|
+
await window.openai.sendFollowUpMessage({ prompt, title })
|
|
35
|
+
```
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
The setup action envelope contains only `action`, `personal_space_id`, scope, optional project, and depth inputs. It must not invent a `review_id`, `candidate_key`, `item_id`, or `item_kind`. Every candidate action envelope contains `personal_space_id`, `review_id`, `candidate_key`, `item_id`, and `item_kind`, plus only the fields needed for that action. Treat a valid envelope as a continuation of the active review, not as a new `/flreview` invocation.
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
Each candidate card shows its content, current scope and source projects, confirmation state, `current_quadrant`, selection reasons, relevant evidence counts, utility, and confidence. Provider order is authoritative; do not invent a second score. Render these actions:
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
- **确认保留**
|
|
42
|
+
- **修改**
|
|
43
|
+
- **调整范围**
|
|
44
|
+
- **失效**
|
|
45
|
+
- **稍后处理**
|
|
46
|
+
- **交给 AI 判断**
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
Do not present the review as one candidate at a time in chat. Chat may contain only a concise status and the generated interactive artifact.
|
|
44
49
|
|
|
45
|
-
##
|
|
50
|
+
## Action Semantics
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
Do not mutate knowledge until the user submits an explicit visualization action. After any mutation, call `record_knowledge_review_progress` only after the write succeeds. If progress recording fails after a successful write, retry only progress; never repeat the mutation.
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
- **修改** — obtain the exact replacement text, apply `revise_personal_knowledge`, then record progress.
|
|
51
|
-
- **失效** — reconfirm the exact target, apply `revise_personal_knowledge` with `invalidate`, then record progress.
|
|
52
|
-
- **跳过** — do not ask again in this run; it may return in a later review.
|
|
53
|
-
- **稍后处理** — do not ask again in this run; intentionally return it in the next review.
|
|
54
|
+
### 确认保留
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
If the candidate is already confirmed, record `confirmed`. If it is pending, first call `revise_personal_knowledge` with `action: confirm`, an auditable user confirmation basis, and no content or taxonomy changes; then record `confirmed`.
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
### 修改
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
Collect the exact replacement content and a reason in the card. Call `revise_personal_knowledge` with `action: update`, then record `updated`.
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
### 调整范围
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
- For a global preference with exactly one source project, offer a one-click move to that source project. With multiple source projects, require a project selection. Call `set_personal_preference_scope` with `scope: project` and the selected source project.
|
|
65
|
+
- For a project-scoped preference, offer promotion to global and call `set_personal_preference_scope` with `scope: global`.
|
|
66
|
+
- Ordinary project knowledge is not a personal preference. Never offer to turn ordinary project knowledge into a global preference.
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
After a successful scope write, record `updated`. Never change scope automatically.
|
|
69
|
+
|
|
70
|
+
### 失效
|
|
71
|
+
|
|
72
|
+
Offer these preset reasons and a custom reason field:
|
|
73
|
+
|
|
74
|
+
- 不应该沉淀为一条复利知识
|
|
75
|
+
- 不知所云
|
|
76
|
+
- 过期了
|
|
77
|
+
- 只在当时生效
|
|
78
|
+
|
|
79
|
+
Selecting a preset or entering a non-empty custom reason is sufficient authorization. There is no second confirmation and no confirmation checkbox. Call `revise_personal_knowledge` with `action: invalidate`, then record `invalidated` with the exact reason.
|
|
80
|
+
|
|
81
|
+
### 稍后处理
|
|
82
|
+
|
|
83
|
+
Do not mutate the knowledge. Record `deferred` and remove it from the current page. FULI carries it into the next review as `deferred_from_previous` even if no other ranking threshold still matches.
|
|
84
|
+
|
|
85
|
+
### 交给 AI 判断
|
|
86
|
+
|
|
87
|
+
This action means the user cannot responsibly classify the item now. Call `revise_personal_knowledge` with `action: update`, `currentQuadrant: unknown_unknown`, and a short `reasoningSummary` stating that the user delegated judgment during knowledge review. Never send `originQuadrant`: discovery classification is immutable evidence. The required order is `revise_personal_knowledge` before `record_knowledge_review_progress`. After that write succeeds, record `delegated_to_ai` and remove the item from the current page.
|
|
88
|
+
|
|
89
|
+
## Continue, Pause, Or Complete
|
|
90
|
+
|
|
91
|
+
After each successful action, refresh the current review's remaining candidates and regenerate the interactive page. Load the next bounded batch when the current batch is exhausted.
|
|
92
|
+
|
|
93
|
+
Call `finish_knowledge_review` with `paused` when the user explicitly pauses. Call it with `completed` only when no candidates remain or the user explicitly finishes the selected scope. Only completion advances the last-completed watermark.
|
|
66
94
|
|
|
67
95
|
## Guardrails
|
|
68
96
|
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
- Never
|
|
72
|
-
-
|
|
73
|
-
- If a required Fuli review tool is unavailable, state that the installed integration needs updating; do not simulate persistence in prose.
|
|
97
|
+
- FULI-saved knowledge is the only candidate source. Never fabricate, mock, or supplement candidates from ordinary search.
|
|
98
|
+
- Keep original evidence and revision history intact.
|
|
99
|
+
- Never silently resolve conflicts, invalidate knowledge, or change scope.
|
|
100
|
+
- If a required FULI or visualization capability is unavailable, report the exact missing capability and stop safely.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Fuli Knowledge Review"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "Use $flreview to
|
|
3
|
+
short_description: "Generate an interactive FULI knowledge review"
|
|
4
|
+
default_prompt: "Use $flreview to generate my interactive FULI knowledge review."
|
|
5
5
|
policy:
|
|
6
6
|
allow_implicit_invocation: true
|
|
@@ -514,7 +514,7 @@ export const GRAPH_TOOL_DEFINITIONS = [
|
|
|
514
514
|
{
|
|
515
515
|
name: 'record_knowledge_review_progress',
|
|
516
516
|
title: 'WRITE · Record one review outcome',
|
|
517
|
-
description: 'Record one user-authorized candidate outcome after any required knowledge mutation succeeds. confirmed keeps the item, updated/invalidated follow successful writes,
|
|
517
|
+
description: 'Record one user-authorized candidate outcome after any required knowledge mutation succeeds. confirmed keeps the item, updated/invalidated follow successful writes, deferred carries it into the next review, and delegated_to_ai follows a successful current-quadrant change to unknown_unknown.',
|
|
518
518
|
inputSchema: objectSchema({
|
|
519
519
|
personalSpaceId: id,
|
|
520
520
|
reviewId: id,
|
|
@@ -523,7 +523,7 @@ export const GRAPH_TOOL_DEFINITIONS = [
|
|
|
523
523
|
pattern: '^(entity|relationship):.+'
|
|
524
524
|
},
|
|
525
525
|
outcome: enumSchema([
|
|
526
|
-
'confirmed', 'updated', 'invalidated', '
|
|
526
|
+
'confirmed', 'updated', 'invalidated', 'deferred', 'delegated_to_ai'
|
|
527
527
|
]),
|
|
528
528
|
note: nullableStringSchema()
|
|
529
529
|
}, ['personalSpaceId', 'reviewId', 'candidateKey', 'outcome'])
|
|
@@ -540,13 +540,13 @@ export const GRAPH_TOOL_DEFINITIONS = [
|
|
|
540
540
|
},
|
|
541
541
|
{
|
|
542
542
|
name: 'revise_personal_knowledge',
|
|
543
|
-
description: '
|
|
543
|
+
description: 'Confirm, correct, invalidate, or restore one personal entity or relationship while preserving revision history and original evidence. This is the same personal-only operation used by the management UI.',
|
|
544
544
|
inputSchema: objectSchema({
|
|
545
545
|
personalSpaceId: id,
|
|
546
546
|
personalProjectId: nullableStringSchema(),
|
|
547
547
|
itemKind: knowledgeItemKind,
|
|
548
548
|
itemId: id,
|
|
549
|
-
action: enumSchema(['update', 'invalidate', 'restore']),
|
|
549
|
+
action: enumSchema(['confirm', 'update', 'invalidate', 'restore']),
|
|
550
550
|
reason: shortText,
|
|
551
551
|
name: nullableStringSchema(),
|
|
552
552
|
summary: nullableStringSchema(),
|
|
@@ -789,7 +789,7 @@ export class FederatedGraphApplication {
|
|
|
789
789
|
}
|
|
790
790
|
|
|
791
791
|
async listKnowledgeSpaces() {
|
|
792
|
-
const [
|
|
792
|
+
const [availablePersonalSpaces, personalProjects, subscriptions, ...workspaceSpaces] = await Promise.all([
|
|
793
793
|
this.personal.listSpaces(),
|
|
794
794
|
this.personal.listPersonalProjects(this.config.personal.spaceId),
|
|
795
795
|
this.personal.listSubscriptions(this.config.personal.spaceId),
|
|
@@ -799,6 +799,7 @@ export class FederatedGraphApplication {
|
|
|
799
799
|
spaces: await safely(() => workspace.client.listSpaces(), [])
|
|
800
800
|
}))
|
|
801
801
|
]);
|
|
802
|
+
const personalSpaces = availablePersonalSpaces.filter(({ id }) => id === this.config.personal.spaceId);
|
|
802
803
|
return {
|
|
803
804
|
activePersonalSpaceId: this.config.personal.spaceId,
|
|
804
805
|
personalSpaces,
|
|
@@ -22,7 +22,9 @@ const TOOL_RESULT_LIMIT_BYTES = Object.freeze({
|
|
|
22
22
|
search_knowledge_graph: 32 * 1024,
|
|
23
23
|
search_connected_knowledge: 64 * 1024,
|
|
24
24
|
search_current_project_knowledge: 64 * 1024,
|
|
25
|
-
discover_common_knowledge_candidates: 32 * 1024
|
|
25
|
+
discover_common_knowledge_candidates: 32 * 1024,
|
|
26
|
+
list_personal_projects: 32 * 1024,
|
|
27
|
+
list_knowledge_review_candidates: 32 * 1024
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
export function createMcpServer(app) {
|
package/README.en.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{h as e,k as t,x as n}from"./i18n-BQcns1PH.js";import{t as r}from"./KnowledgeWorkspace-Czq6aZ7b.js";var i=n({__name:`KnowledgePage`,setup(n){return(n,i)=>(t(),e(r))}});export{i as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$ as e,Q as t,_ as n,a as r,k as i,m as a,p as o,tt as s,x as c}from"./i18n-BQcns1PH.js";import{t as l}from"./console-CbDsKrsO.js";var u={class:`view`},d={class:`intro-row`},f=[`aria-label`],p={class:`two-column`},m={class:`section-block`},h={class:`section-title`},g={class:`flow-list`},_={class:`section-block`},v={class:`provider-list`},y={class:`provider-row`},b={class:`provider-state`},x={class:`provider-row`},S={class:`provider-state`},C=c({__name:`OverviewPage`,setup(c){let C=l(),w=o(()=>C.state),T=o(()=>w.value?.providers?.workspaces??[]),E=o(()=>T.value.filter(({status:e})=>e===`ready`).length);return(o,c)=>(i(),n(`section`,u,[a(`div`,d,[a(`div`,null,[a(`h3`,null,s(t(r)(`pages.overview.introTitle`)),1),a(`p`,null,s(t(r)(`pages.overview.introCopy`)),1)]),c[0]||=a(`span`,{class:`mode-chip`},`Agent structured`,-1)]),a(`div`,{class:`metrics`,"aria-label":t(r)(`pages.overview.metricsAria`)},[a(`article`,null,[a(`strong`,null,s(w.value?.personalSpaces.length??0),1),a(`span`,null,s(t(r)(`pages.overview.personalGraphs`)),1)]),a(`article`,null,[a(`strong`,null,s(w.value?.projects.length??0),1),a(`span`,null,s(t(r)(`pages.overview.accessibleProjects`)),1)]),a(`article`,null,[a(`strong`,null,s(w.value?.subscriptions.length??0),1),a(`span`,null,s(t(r)(`pages.overview.subscriptions`)),1)]),a(`article`,null,[a(`strong`,null,s(w.value?.personalProjects?.length??0),1),a(`span`,null,s(t(r)(`pages.overview.personalProjects`)),1)])],8,f),a(`div`,p,[a(`section`,m,[a(`div`,h,[a(`h3`,null,s(t(r)(`pages.overview.dataFlow`)),1)]),a(`ol`,g,[a(`li`,null,[c[1]||=a(`span`,null,`1`,-1),a(`div`,null,[a(`strong`,null,s(t(r)(`pages.overview.flow.identifyTitle`)),1),a(`p`,null,s(t(r)(`pages.overview.flow.identifyCopy`)),1)])]),a(`li`,null,[c[2]||=a(`span`,null,`2`,-1),a(`div`,null,[a(`strong`,null,s(t(r)(`pages.overview.flow.structureTitle`)),1),a(`p`,null,s(t(r)(`pages.overview.flow.structureCopy`)),1)])]),a(`li`,null,[c[3]||=a(`span`,null,`3`,-1),a(`div`,null,[a(`strong`,null,s(t(r)(`pages.overview.flow.routeTitle`)),1),a(`p`,null,s(t(r)(`pages.overview.flow.routeCopy`)),1)])])])]),a(`section`,_,[c[5]||=a(`div`,{class:`section-title`},[a(`h3`,null,`Provider`)],-1),a(`div`,v,[a(`div`,y,[a(`i`,{class:e({error:w.value?.providers?.personal?.status!==`ready`})},null,2),a(`div`,null,[a(`strong`,null,s(t(r)(`pages.overview.localKnowledge`)),1),c[4]||=a(`span`,null,`Graphiti / Neo4j`,-1)]),a(`span`,b,s(w.value?.providers?.personal?.status===`ready`?t(r)(`common.status.connected`):t(r)(`common.status.connectionError`)),1)]),a(`div`,x,[a(`i`,{class:e(t(C).publicRuntimeStatus)},null,2),a(`div`,null,[a(`strong`,null,s(t(r)(`pages.overview.publicService`)),1),a(`span`,null,s(t(C).publicRuntimeStatus===`ready`?t(r)(`pages.overview.sharedServicesReady`,{count:E.value||T.value.length}):t(C).publicRuntimeStatus===`error`?t(r)(`pages.overview.publicTemporarilyUnavailable`):t(r)(`pages.overview.publicOfflineLocalUnaffected`)),1)]),a(`span`,S,s(t(C).publicRuntimeStatus===`ready`?t(r)(`common.status.connected`):t(C).publicRuntimeStatus===`error`?t(r)(`common.status.connectionError`):t(r)(`common.status.notConnected`)),1)])])])])]))}});export{C as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{h as e,k as t,x as n}from"./i18n-BQcns1PH.js";import{t as r}from"./KnowledgeWorkspace-Czq6aZ7b.js";var i=n({__name:`PersonalProjectsPage`,setup(n){return(n,i)=>(t(),e(r,{"personal-projects-only":``}))}});export{i as default};
|