noteconnection 1.6.8 → 1.8.0
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/LICENSE +674 -21
- package/README.md +258 -64
- package/dist/src/agent_workspace.contract.parity.test.js +475 -0
- package/dist/src/agent_workspace.frontend.test.js +9989 -0
- package/dist/src/agent_workspace.locale.contract.test.js +95 -0
- package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
- package/dist/src/copy.assets.contract.test.js +130 -0
- package/dist/src/core/PathBridge.js +28 -3
- package/dist/src/export/WorkspaceExportBundle.js +1130 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +1480 -0
- package/dist/src/export/index.js +18 -0
- package/dist/src/export/types.js +2 -0
- package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
- package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
- package/dist/src/foundation.release.evidence.contract.test.js +406 -0
- package/dist/src/foundation.sqlite.runtime.contract.test.js +82 -0
- package/dist/src/frontend/README.md +258 -64
- package/dist/src/frontend/agent_workspace.js +5353 -0
- package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
- package/dist/src/frontend/analysis.js +31 -4
- package/dist/src/frontend/app.js +3597 -141
- package/dist/src/frontend/focus_mode_interactions.js +33 -0
- package/dist/src/frontend/godot_future_path_renderer.js +540 -0
- package/dist/src/frontend/godot_tree_interactions.js +178 -0
- package/dist/src/frontend/graph_state.mjs +105 -0
- package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
- package/dist/src/frontend/i18n.mjs +186 -0
- package/dist/src/frontend/index.html +641 -266
- package/dist/src/frontend/layout_gpu.js +12 -4
- package/dist/src/frontend/locales/en.json +721 -5
- package/dist/src/frontend/locales/zh.json +721 -5
- package/dist/src/frontend/main.mjs +60 -0
- package/dist/src/frontend/markdown_runtime.js +827 -0
- package/dist/src/frontend/notemd.css +49 -0
- package/dist/src/frontend/notemd.html +7 -1
- package/dist/src/frontend/notemd.js +64 -0
- package/dist/src/frontend/path.html +107 -0
- package/dist/src/frontend/path_app.js +2189 -150
- package/dist/src/frontend/path_layout.mjs +143 -0
- package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
- package/dist/src/frontend/path_modules_bridge.js +486 -0
- package/dist/src/frontend/path_state.mjs +118 -0
- package/dist/src/frontend/path_styles.css +146 -0
- package/dist/src/frontend/path_worker_bridge.mjs +85 -0
- package/dist/src/frontend/reader.js +522 -27
- package/dist/src/frontend/runtime_bridge.js +67 -54
- package/dist/src/frontend/runtime_bridge.mjs +279 -0
- package/dist/src/frontend/settings.js +130 -12
- package/dist/src/frontend/simulationWorker.js +241 -6
- package/dist/src/frontend/source_manager.js +190 -21
- package/dist/src/frontend/styles.css +2853 -72
- package/dist/src/frontend/workbench_state.mjs +101 -0
- package/dist/src/frontend/workspace_panes.js +10168 -0
- package/dist/src/frontend.locale.contract.test.js +62 -0
- package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
- package/dist/src/indexing/IndexLifecycle.js +195 -0
- package/dist/src/indexing/IndexLifecycle.test.js +49 -0
- package/dist/src/indexing/SegmentBuilder.js +64 -0
- package/dist/src/indexing/UnitBuilder.js +48 -0
- package/dist/src/indexing/types.js +2 -0
- package/dist/src/knowledge.api.contract.test.js +170 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +10386 -0
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +327 -0
- package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +2971 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2974 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3928 -0
- package/dist/src/learning/answerReleaseReview.js +4319 -0
- package/dist/src/learning/answerReleaseReview.test.js +2888 -0
- package/dist/src/learning/api.js +2 -0
- package/dist/src/learning/conversationComposer.js +1480 -0
- package/dist/src/learning/conversationComposer.test.js +1817 -0
- package/dist/src/learning/domains/ConversationManager.js +53 -0
- package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
- package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
- package/dist/src/learning/domains/MasteryEngine.js +387 -0
- package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
- package/dist/src/learning/domains/QualityEvaluator.js +307 -0
- package/dist/src/learning/domains/TutorRouter.js +313 -0
- package/dist/src/learning/domains/index.js +33 -0
- package/dist/src/learning/domains/types.js +7 -0
- package/dist/src/learning/errors.js +29 -0
- package/dist/src/learning/evidenceContextAssembler.js +1176 -0
- package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
- package/dist/src/learning/graphContextAssembler.js +870 -0
- package/dist/src/learning/graphContextAssembler.test.js +1033 -0
- package/dist/src/learning/index.js +28 -0
- package/dist/src/learning/queryBackend.js +1898 -0
- package/dist/src/learning/queryBackend.test.js +955 -0
- package/dist/src/learning/ragContextPack.js +257 -0
- package/dist/src/learning/ragContextPack.test.js +160 -0
- package/dist/src/learning/ragPublicText.js +38 -0
- package/dist/src/learning/ragSufficiencyJudge.js +161 -0
- package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.js +227 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +156 -0
- package/dist/src/learning/requestNormalization.js +198 -0
- package/dist/src/learning/runtimeCapability.js +4677 -0
- package/dist/src/learning/runtimeCapability.test.js +3635 -0
- package/dist/src/learning/store.js +1240 -0
- package/dist/src/learning/store.test.js +1126 -0
- package/dist/src/learning/tutorAdapter.js +2 -0
- package/dist/src/learning/types.js +2 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +942 -0
- package/dist/src/learning/vectorAccelerationAdapter.test.js +382 -0
- package/dist/src/lfs.asset.policy.contract.test.js +153 -0
- package/dist/src/license.policy.contract.test.js +66 -0
- package/dist/src/memory/MemoryGovernance.js +74 -0
- package/dist/src/memory/MemoryGovernance.test.js +46 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
- package/dist/src/middleware/auth.js +17 -0
- package/dist/src/middleware/body-parser.js +45 -0
- package/dist/src/middleware/cors.js +44 -0
- package/dist/src/middleware/index.js +21 -0
- package/dist/src/middleware/request-trace.js +96 -0
- package/dist/src/notemd/AppConfigToml.js +6 -4
- package/dist/src/notemd/MermaidProcessor.js +400 -50
- package/dist/src/notemd/NotemdService.js +498 -13
- package/dist/src/notemd/PromptManager.js +15 -0
- package/dist/src/notemd/cli/commands.js +357 -0
- package/dist/src/notemd/cli/dispatcher.js +225 -0
- package/dist/src/notemd/cli/index.js +169 -0
- package/dist/src/notemd/cli/parser.js +68 -0
- package/dist/src/notemd/cli/types.js +2 -0
- package/dist/src/notemd/constants.js +43 -0
- package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
- package/dist/src/notemd/diagram/diagramSpec.js +79 -0
- package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
- package/dist/src/notemd/diagram/intent.js +95 -0
- package/dist/src/notemd/diagram/planner.js +71 -0
- package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
- package/dist/src/notemd/diagram/types.js +18 -0
- package/dist/src/notemd/index.js +26 -0
- package/dist/src/notemd/operations/capabilityManifest.js +23 -0
- package/dist/src/notemd/operations/cliContracts.js +17 -0
- package/dist/src/notemd/operations/configProfileCommands.js +85 -0
- package/dist/src/notemd/operations/registry.contract.test.js +95 -0
- package/dist/src/notemd/operations/registry.js +991 -0
- package/dist/src/notemd/operations/types.js +2 -0
- package/dist/src/notemd/providerDiagnostics.js +220 -0
- package/dist/src/notemd/providerProfiles.js +42 -0
- package/dist/src/notemd/providerTemplates.js +231 -0
- package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
- package/dist/src/notemd/search/SearchManager.js +13 -0
- package/dist/src/notemd/search/SearchProvider.js +2 -0
- package/dist/src/notemd/search/TavilyProvider.js +44 -0
- package/dist/src/notemd.agent.manifest.test.js +85 -0
- package/dist/src/notemd.api.contract.test.js +14 -1
- package/dist/src/notemd.app_config_toml.test.js +2 -1
- package/dist/src/notemd.batch.workflow.test.js +117 -0
- package/dist/src/notemd.cli.e2e.test.js +136 -0
- package/dist/src/notemd.core.test.js +51 -0
- package/dist/src/notemd.diagram.pipeline.test.js +233 -0
- package/dist/src/notemd.providerTemplates.test.js +34 -0
- package/dist/src/notemd.server.integration.test.js +143 -35
- package/dist/src/notemd.workflow.pipeline.test.js +162 -0
- package/dist/src/pathbridge.handshake.contract.test.js +16 -2
- package/dist/src/pathmode.background.contract.test.js +69 -0
- package/dist/src/pathmode.settings.api.contract.test.js +9 -0
- package/dist/src/pkg.sidecar.contract.test.js +9 -3
- package/dist/src/platform/ExportProfile.js +58 -0
- package/dist/src/platform/PlatformCapabilities.js +45 -0
- package/dist/src/platform/PlatformCapabilities.test.js +30 -0
- package/dist/src/platform/RenderMaterializer.js +33 -0
- package/dist/src/platform/RenderMaterializer.test.js +32 -0
- package/dist/src/query_backend.external_http.integration.test.js +410 -0
- package/dist/src/reader_renderer.js +404 -3
- package/dist/src/reader_renderer.test.js +87 -0
- package/dist/src/release.godot.mirror.contract.test.js +73 -0
- package/dist/src/resources/ResourceRegistry.js +223 -0
- package/dist/src/resources/ResourceRegistry.test.js +61 -0
- package/dist/src/resources/types.js +2 -0
- package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
- package/dist/src/routes/data.js +267 -0
- package/dist/src/routes/diagnostics.js +51 -0
- package/dist/src/routes/index.js +23 -0
- package/dist/src/routes/knowledge.js +968 -0
- package/dist/src/routes/markdown.js +287 -0
- package/dist/src/routes/notemd.js +565 -0
- package/dist/src/routes/registry.contract.test.js +130 -0
- package/dist/src/routes/render.js +285 -0
- package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
- package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
- package/dist/src/routes/settings.js +6 -0
- package/dist/src/routes/staticFiles.js +94 -0
- package/dist/src/routes/types.js +2 -0
- package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
- package/dist/src/server.js +11090 -1549
- package/dist/src/server.migration.test.js +193 -21
- package/dist/src/server.port.fallback.contract.test.js +63 -0
- package/dist/src/session/SessionStateStore.js +81 -0
- package/dist/src/session/SessionStateStore.test.js +58 -0
- package/dist/src/session/types.js +2 -0
- package/dist/src/settings.runtime.contract.test.js +50 -0
- package/dist/src/shared/types.contract.test.js +107 -0
- package/dist/src/shared/types.js +22 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +128 -0
- package/dist/src/sidecar.supply.readiness.contract.test.js +144 -0
- package/dist/src/source_manager.loadflow.test.js +46 -0
- package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
- package/dist/src/tauri.frontend.build.contract.test.js +60 -0
- package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
- package/dist/src/utils/RuntimePaths.js +4 -13
- package/dist/src/utils/platform.js +153 -0
- package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
- package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
- package/dist/src/workflows/types.js +2 -0
- package/dist/src/workspace/WorkspaceRegistry.js +122 -0
- package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
- package/dist/src/workspace/types.js +2 -0
- package/package.json +61 -10
|
@@ -0,0 +1,4434 @@
|
|
|
1
|
+
(
|
|
2
|
+
function bootstrapAgentWorkspaceRuntime(globalScope, factory) {
|
|
3
|
+
const runtimeModule = factory(globalScope);
|
|
4
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
5
|
+
module.exports = runtimeModule;
|
|
6
|
+
}
|
|
7
|
+
if (globalScope && typeof globalScope === 'object') {
|
|
8
|
+
globalScope.NoteConnectionAgentWorkspaceRuntime = runtimeModule;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
)(
|
|
12
|
+
typeof globalThis !== 'undefined'
|
|
13
|
+
? globalThis
|
|
14
|
+
: (typeof window !== 'undefined' ? window : this),
|
|
15
|
+
function agentWorkspaceRuntimeFactory(globalScope) {
|
|
16
|
+
const BODY_CLASS_ENABLED = 'agent-workspace-enabled';
|
|
17
|
+
const BODY_CLASS_PATH_VISIBLE = 'agent-workspace-path-visible';
|
|
18
|
+
const BODY_CLASS_PATH_FULLSCREEN = 'agent-workspace-path-fullscreen';
|
|
19
|
+
const PATH_DOCK_CLASS = 'agent-workspace-path-docked';
|
|
20
|
+
const MAX_ACTIVE_POINT_CONTEXTUAL_ACTIONS = 2;
|
|
21
|
+
const MAX_DIAGNOSTIC_TURNS = 120;
|
|
22
|
+
const MAX_DIAGNOSTIC_CAPABILITY_EVENTS = 120;
|
|
23
|
+
const DIAGNOSTIC_RUNBOOK_LINKS = Object.freeze([
|
|
24
|
+
Object.freeze({
|
|
25
|
+
id: 'development-progress-dashboard',
|
|
26
|
+
label: 'Development Progress Dashboard',
|
|
27
|
+
paths: Object.freeze({
|
|
28
|
+
en: 'docs/diataxis/en/explanation/development-progress-dashboard.md',
|
|
29
|
+
zh: 'docs/diataxis/zh/explanation/development-progress-dashboard.md',
|
|
30
|
+
}),
|
|
31
|
+
}),
|
|
32
|
+
Object.freeze({
|
|
33
|
+
id: 'agent-conversation-focus-mode-plan',
|
|
34
|
+
label: 'Agent Conversation + Focus Mode Delivery Plan',
|
|
35
|
+
paths: Object.freeze({
|
|
36
|
+
en: 'docs/diataxis/en/explanation/agent-conversation-focus-mode-plan.md',
|
|
37
|
+
zh: 'docs/diataxis/zh/explanation/agent-conversation-focus-mode-plan.md',
|
|
38
|
+
}),
|
|
39
|
+
}),
|
|
40
|
+
Object.freeze({
|
|
41
|
+
id: 'm7-direction-requirements',
|
|
42
|
+
label: 'Mainline CI Stabilization and M7 Direction Requirements',
|
|
43
|
+
paths: Object.freeze({
|
|
44
|
+
en: 'docs/brainstorms/2026-04-16-mainline-ci-stabilization-and-m7-direction-requirements.md',
|
|
45
|
+
zh: 'docs/brainstorms/2026-04-16-mainline-ci-stabilization-and-m7-direction-requirements.md',
|
|
46
|
+
}),
|
|
47
|
+
}),
|
|
48
|
+
Object.freeze({
|
|
49
|
+
id: 'foundation-reentry-readiness-checklist',
|
|
50
|
+
label: 'Foundation Re-entry Readiness Checklist',
|
|
51
|
+
paths: Object.freeze({
|
|
52
|
+
en: 'docs/diataxis/en/explanation/foundation-reentry-readiness-checklist.md',
|
|
53
|
+
zh: 'docs/diataxis/zh/explanation/foundation-reentry-readiness-checklist.md',
|
|
54
|
+
}),
|
|
55
|
+
}),
|
|
56
|
+
]);
|
|
57
|
+
const SUPPORTED_TUTOR_ACTION_KINDS = Object.freeze([
|
|
58
|
+
'generate_quiz',
|
|
59
|
+
'analyze_answer',
|
|
60
|
+
'follow_up',
|
|
61
|
+
'generate_transfer',
|
|
62
|
+
'generate_counterexample',
|
|
63
|
+
'recap',
|
|
64
|
+
]);
|
|
65
|
+
const SUPPORTED_MEMORY_POLICY_LAYERS = Object.freeze([
|
|
66
|
+
'session',
|
|
67
|
+
'unit',
|
|
68
|
+
'long_term',
|
|
69
|
+
]);
|
|
70
|
+
const SUPPORTED_MEMORY_POLICY_OPERATIONS = Object.freeze([
|
|
71
|
+
'read',
|
|
72
|
+
'snapshot',
|
|
73
|
+
'retrain_plan',
|
|
74
|
+
'write',
|
|
75
|
+
'evict',
|
|
76
|
+
]);
|
|
77
|
+
const SUPPORTED_READONLY_MEMORY_POLICY_OPERATIONS = Object.freeze([
|
|
78
|
+
'read',
|
|
79
|
+
'snapshot',
|
|
80
|
+
'retrain_plan',
|
|
81
|
+
]);
|
|
82
|
+
const MANAGED_CONVERSATION_ACTION_IDS = Object.freeze([
|
|
83
|
+
'inspect_managed_memory_state',
|
|
84
|
+
'write_memory_note',
|
|
85
|
+
'record_memory_correction',
|
|
86
|
+
'evict_memory_note',
|
|
87
|
+
]);
|
|
88
|
+
const STUDY_LOOP_ACTION_IDS = Object.freeze([
|
|
89
|
+
'generate_quiz',
|
|
90
|
+
'analyze_answer',
|
|
91
|
+
'recap',
|
|
92
|
+
'follow_up',
|
|
93
|
+
'generate_transfer',
|
|
94
|
+
'generate_counterexample',
|
|
95
|
+
'build_study_session',
|
|
96
|
+
]);
|
|
97
|
+
const MEMORY_ACTION_IDS = Object.freeze([
|
|
98
|
+
'inspect_memory_snapshot',
|
|
99
|
+
'inspect_unit_memory_snapshot',
|
|
100
|
+
'inspect_long_term_memory_snapshot',
|
|
101
|
+
'inspect_memory_retrain_plan',
|
|
102
|
+
'inspect_memory_read',
|
|
103
|
+
'inspect_long_term_memory_read',
|
|
104
|
+
'inspect_managed_memory_state',
|
|
105
|
+
'write_memory_note',
|
|
106
|
+
'record_memory_correction',
|
|
107
|
+
'evict_memory_note',
|
|
108
|
+
]);
|
|
109
|
+
const HISTORY_FOLLOW_UP_CANDIDATES_BY_ACTION_ID = Object.freeze({
|
|
110
|
+
open_learning_path: Object.freeze([
|
|
111
|
+
'open_focus_mode',
|
|
112
|
+
'build_study_session',
|
|
113
|
+
'recap',
|
|
114
|
+
'follow_up',
|
|
115
|
+
]),
|
|
116
|
+
build_study_session: Object.freeze([
|
|
117
|
+
'recap',
|
|
118
|
+
'follow_up',
|
|
119
|
+
'generate_transfer',
|
|
120
|
+
'generate_quiz',
|
|
121
|
+
'analyze_answer',
|
|
122
|
+
'open_learning_path',
|
|
123
|
+
'open_focus_mode',
|
|
124
|
+
]),
|
|
125
|
+
recap: Object.freeze([
|
|
126
|
+
'follow_up',
|
|
127
|
+
'generate_transfer',
|
|
128
|
+
'generate_counterexample',
|
|
129
|
+
'generate_quiz',
|
|
130
|
+
'build_study_session',
|
|
131
|
+
'open_learning_path',
|
|
132
|
+
'open_focus_mode',
|
|
133
|
+
]),
|
|
134
|
+
});
|
|
135
|
+
const DEFAULT_HISTORY_FOLLOW_UP_CANDIDATES = Object.freeze([
|
|
136
|
+
'build_study_session',
|
|
137
|
+
'recap',
|
|
138
|
+
'follow_up',
|
|
139
|
+
'open_learning_path',
|
|
140
|
+
'open_focus_mode',
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
function createEmptyMemoryPolicyLayerCounts() {
|
|
144
|
+
return {
|
|
145
|
+
session: 0,
|
|
146
|
+
unit: 0,
|
|
147
|
+
long_term: 0,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function createEmptyMemoryPolicyOperationCounts() {
|
|
152
|
+
return {
|
|
153
|
+
read: 0,
|
|
154
|
+
snapshot: 0,
|
|
155
|
+
retrain_plan: 0,
|
|
156
|
+
write: 0,
|
|
157
|
+
evict: 0,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function trimString(value) {
|
|
162
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function normalizeMemoryPolicyLayerForDiagnostics(rawLayer) {
|
|
166
|
+
const layer = trimString(rawLayer);
|
|
167
|
+
return SUPPORTED_MEMORY_POLICY_LAYERS.includes(layer) ? layer : '';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function normalizeMemoryPolicyOperationForDiagnostics(rawOperation) {
|
|
171
|
+
const operation = trimString(rawOperation);
|
|
172
|
+
return SUPPORTED_MEMORY_POLICY_OPERATIONS.includes(operation) ? operation : '';
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function isReadonlyMemoryPolicyOperation(rawOperation) {
|
|
176
|
+
const operation = normalizeMemoryPolicyOperationForDiagnostics(rawOperation);
|
|
177
|
+
return SUPPORTED_READONLY_MEMORY_POLICY_OPERATIONS.includes(operation);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function resolveTutorActionKind(rawActionKind) {
|
|
181
|
+
const actionKind = trimString(rawActionKind);
|
|
182
|
+
if (!actionKind) {
|
|
183
|
+
throw new Error('execute_tutor_action requires request.actionKind.');
|
|
184
|
+
}
|
|
185
|
+
if (!SUPPORTED_TUTOR_ACTION_KINDS.includes(actionKind)) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`Unsupported tutor actionKind "${actionKind}". Supported kinds: ${SUPPORTED_TUTOR_ACTION_KINDS.join(', ')}.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
return actionKind;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function resolveMemoryPolicyLayer(rawLayer) {
|
|
194
|
+
const layer = trimString(rawLayer) || 'session';
|
|
195
|
+
if (!SUPPORTED_MEMORY_POLICY_LAYERS.includes(layer)) {
|
|
196
|
+
throw new Error(
|
|
197
|
+
`Unsupported memory layer "${layer}". Supported layers: ${SUPPORTED_MEMORY_POLICY_LAYERS.join(', ')}.`
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
return layer;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function resolveMemoryPolicyOperation(rawOperation) {
|
|
204
|
+
const operation = trimString(rawOperation) || 'snapshot';
|
|
205
|
+
if (!SUPPORTED_MEMORY_POLICY_OPERATIONS.includes(operation)) {
|
|
206
|
+
throw new Error(
|
|
207
|
+
`Unsupported memory operation "${operation}". Supported operations: ${SUPPORTED_MEMORY_POLICY_OPERATIONS.join(', ')}.`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
return operation;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function resolveReadonlyMemoryPolicyOperation(rawOperation) {
|
|
214
|
+
const operation = resolveMemoryPolicyOperation(rawOperation);
|
|
215
|
+
if (!SUPPORTED_READONLY_MEMORY_POLICY_OPERATIONS.includes(operation)) {
|
|
216
|
+
throw new Error(
|
|
217
|
+
`Unsupported readonly memory operation "${operation}". Supported readonly operations: ${SUPPORTED_READONLY_MEMORY_POLICY_OPERATIONS.join(', ')}.`
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return operation;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function resolveStringArray(values) {
|
|
224
|
+
if (!Array.isArray(values)) {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
return Array.from(new Set(values
|
|
228
|
+
.map((value) => trimString(value))
|
|
229
|
+
.filter((value) => value.length > 0)));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function resolveMemoryPolicyLimit(rawLimit, fallback) {
|
|
233
|
+
const numericLimit = Number(rawLimit);
|
|
234
|
+
const numericFallback = Number(fallback);
|
|
235
|
+
const base = Number.isFinite(numericLimit) ? numericLimit : (Number.isFinite(numericFallback) ? numericFallback : 20);
|
|
236
|
+
return Math.max(1, Math.min(100, Math.floor(base)));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function cloneCapabilityResultPreview(resultPreview) {
|
|
240
|
+
if (!resultPreview || typeof resultPreview !== 'object') {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
return { ...resultPreview };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function cloneCapabilityEvent(event) {
|
|
247
|
+
if (!event || typeof event !== 'object') {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
const resultPreview = cloneCapabilityResultPreview(event.resultPreview);
|
|
251
|
+
return {
|
|
252
|
+
...event,
|
|
253
|
+
...(resultPreview ? { resultPreview } : {}),
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function formatMemoryKeyLabel(rawKey) {
|
|
258
|
+
const key = trimString(rawKey);
|
|
259
|
+
if (!key) {
|
|
260
|
+
return '';
|
|
261
|
+
}
|
|
262
|
+
if (key.startsWith('conversation_note:')) {
|
|
263
|
+
return 'note';
|
|
264
|
+
}
|
|
265
|
+
if (key.startsWith('conversation_correction:')) {
|
|
266
|
+
return 'correction';
|
|
267
|
+
}
|
|
268
|
+
const segments = key.split(':').map((segment) => trimString(segment)).filter((segment) => segment.length > 0);
|
|
269
|
+
return segments.length > 1 ? segments[segments.length - 1] : key;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function summarizeMemoryKeyLabels(keys) {
|
|
273
|
+
const labels = resolveStringArray(keys)
|
|
274
|
+
.map((key) => formatMemoryKeyLabel(key))
|
|
275
|
+
.filter((label) => label.length > 0);
|
|
276
|
+
return labels.length ? labels.join(', ') : 'none';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function resolveManagedConversationKeyLabels(keys) {
|
|
280
|
+
return Array.from(new Set(
|
|
281
|
+
resolveStringArray(keys)
|
|
282
|
+
.map((key) => formatMemoryKeyLabel(key))
|
|
283
|
+
.filter((label) => label === 'note' || label === 'correction')
|
|
284
|
+
));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function resolveManagedMemoryFollowUpKeyLabel(actionId) {
|
|
288
|
+
const normalizedActionId = trimString(actionId);
|
|
289
|
+
if (normalizedActionId === 'write_memory_note') {
|
|
290
|
+
return 'note';
|
|
291
|
+
}
|
|
292
|
+
if (normalizedActionId === 'record_memory_correction') {
|
|
293
|
+
return 'correction';
|
|
294
|
+
}
|
|
295
|
+
return '';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function resolveManagedConversationFollowUpActionIdsFromKeyCounts(counts) {
|
|
299
|
+
const actionIds = [];
|
|
300
|
+
if (Number(counts && counts.note) > 0) {
|
|
301
|
+
actionIds.push('write_memory_note');
|
|
302
|
+
}
|
|
303
|
+
if (Number(counts && counts.correction) > 0) {
|
|
304
|
+
actionIds.push('record_memory_correction');
|
|
305
|
+
}
|
|
306
|
+
return actionIds;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function resolveManagedConversationFollowUpActionIdsFromKeyLabels(keyLabels) {
|
|
310
|
+
return Array.from(new Set(
|
|
311
|
+
resolveManagedConversationKeyLabels(keyLabels)
|
|
312
|
+
.map((keyLabel) => {
|
|
313
|
+
if (keyLabel === 'note') {
|
|
314
|
+
return 'write_memory_note';
|
|
315
|
+
}
|
|
316
|
+
if (keyLabel === 'correction') {
|
|
317
|
+
return 'record_memory_correction';
|
|
318
|
+
}
|
|
319
|
+
return '';
|
|
320
|
+
})
|
|
321
|
+
.filter((actionId) => actionId.length > 0)
|
|
322
|
+
));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function resolveManagedConversationFollowUpActionLabels(actionIds) {
|
|
326
|
+
return Array.from(new Set(
|
|
327
|
+
resolveStringArray(actionIds)
|
|
328
|
+
.map((actionId) => {
|
|
329
|
+
const normalizedActionId = trimString(actionId);
|
|
330
|
+
if (normalizedActionId === 'write_memory_note') {
|
|
331
|
+
return getI18nText(
|
|
332
|
+
'agentWorkspace.actions.writeMemoryNote',
|
|
333
|
+
'Store Memory Note'
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
if (normalizedActionId === 'record_memory_correction') {
|
|
337
|
+
return getI18nText(
|
|
338
|
+
'agentWorkspace.actions.recordMemoryCorrection',
|
|
339
|
+
'Record Correction'
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
return normalizedActionId;
|
|
343
|
+
})
|
|
344
|
+
.filter((label) => trimString(label).length > 0)
|
|
345
|
+
));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function buildManagedConversationLastTransition(
|
|
349
|
+
atomId,
|
|
350
|
+
newerEvent,
|
|
351
|
+
olderEvent,
|
|
352
|
+
resolvedKeyLabels,
|
|
353
|
+
persistentKeyLabels
|
|
354
|
+
) {
|
|
355
|
+
const normalizedResolvedKeyLabels = resolveManagedConversationKeyLabels(resolvedKeyLabels);
|
|
356
|
+
const normalizedPersistentKeyLabels = resolveManagedConversationKeyLabels(persistentKeyLabels);
|
|
357
|
+
const keyLabels = normalizedResolvedKeyLabels.concat(
|
|
358
|
+
normalizedPersistentKeyLabels.filter((label) => !normalizedResolvedKeyLabels.includes(label))
|
|
359
|
+
);
|
|
360
|
+
const resolvedFollowUpActionIds = resolveManagedConversationFollowUpActionIdsFromKeyLabels(
|
|
361
|
+
normalizedResolvedKeyLabels
|
|
362
|
+
);
|
|
363
|
+
const resolvedFollowUpActionLabels = resolveManagedConversationFollowUpActionLabels(
|
|
364
|
+
resolvedFollowUpActionIds
|
|
365
|
+
);
|
|
366
|
+
const persistentFollowUpActionIds = resolveManagedConversationFollowUpActionIdsFromKeyLabels(
|
|
367
|
+
normalizedPersistentKeyLabels
|
|
368
|
+
);
|
|
369
|
+
const persistentFollowUpActionLabels = resolveManagedConversationFollowUpActionLabels(
|
|
370
|
+
persistentFollowUpActionIds
|
|
371
|
+
);
|
|
372
|
+
const followUpActionIds = Array.from(new Set(
|
|
373
|
+
resolvedFollowUpActionIds.concat(persistentFollowUpActionIds)
|
|
374
|
+
));
|
|
375
|
+
const followUpActionLabels = resolveManagedConversationFollowUpActionLabels(followUpActionIds);
|
|
376
|
+
const kind = normalizedResolvedKeyLabels.length > 0 && normalizedPersistentKeyLabels.length > 0
|
|
377
|
+
? 'mixed'
|
|
378
|
+
: normalizedResolvedKeyLabels.length > 0
|
|
379
|
+
? 'resolved'
|
|
380
|
+
: 'persistent';
|
|
381
|
+
return {
|
|
382
|
+
atomId,
|
|
383
|
+
keyLabels,
|
|
384
|
+
keyLabel: keyLabels.join(', '),
|
|
385
|
+
kind,
|
|
386
|
+
newerEventId: trimString(newerEvent && newerEvent.eventId),
|
|
387
|
+
olderEventId: trimString(olderEvent && olderEvent.eventId),
|
|
388
|
+
newerAt: trimString(newerEvent && newerEvent.at),
|
|
389
|
+
olderAt: trimString(olderEvent && olderEvent.at),
|
|
390
|
+
resolvedKeyLabels: normalizedResolvedKeyLabels,
|
|
391
|
+
resolvedKeyLabel: normalizedResolvedKeyLabels.join(', '),
|
|
392
|
+
persistentKeyLabels: normalizedPersistentKeyLabels,
|
|
393
|
+
persistentKeyLabel: normalizedPersistentKeyLabels.join(', '),
|
|
394
|
+
followUpActionId: followUpActionIds[0] || '',
|
|
395
|
+
followUpActionIds,
|
|
396
|
+
followUpActionLabel: followUpActionLabels[0] || '',
|
|
397
|
+
followUpActionLabels,
|
|
398
|
+
resolvedFollowUpActionIds,
|
|
399
|
+
resolvedFollowUpActionLabels,
|
|
400
|
+
persistentFollowUpActionIds,
|
|
401
|
+
persistentFollowUpActionLabels,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function isManagedMemoryStateActionId(actionId) {
|
|
406
|
+
return trimString(actionId) === 'inspect_managed_memory_state';
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function summarizeManagedMemoryFollowUpActions(keys) {
|
|
410
|
+
const labels = [];
|
|
411
|
+
resolveStringArray(keys).forEach((key) => {
|
|
412
|
+
if (key.startsWith('conversation_note:')) {
|
|
413
|
+
labels.push(
|
|
414
|
+
getI18nText(
|
|
415
|
+
'agentWorkspace.actions.writeMemoryNote',
|
|
416
|
+
'Store Memory Note'
|
|
417
|
+
)
|
|
418
|
+
);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (key.startsWith('conversation_correction:')) {
|
|
422
|
+
labels.push(
|
|
423
|
+
getI18nText(
|
|
424
|
+
'agentWorkspace.actions.recordMemoryCorrection',
|
|
425
|
+
'Record Correction'
|
|
426
|
+
)
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
return Array.from(new Set(labels)).join(', ');
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function resolveMisconceptionTopK(rawTopK, fallback) {
|
|
434
|
+
const numericTopK = Number(rawTopK);
|
|
435
|
+
const numericFallback = Number(fallback);
|
|
436
|
+
const base = Number.isFinite(numericTopK) ? numericTopK : (Number.isFinite(numericFallback) ? numericFallback : 5);
|
|
437
|
+
return Math.max(1, Math.min(20, Math.floor(base)));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function resolveQueryTopK(rawTopK, fallback) {
|
|
441
|
+
const numericTopK = Number(rawTopK);
|
|
442
|
+
const numericFallback = Number(fallback);
|
|
443
|
+
const base = Number.isFinite(numericTopK) ? numericTopK : (Number.isFinite(numericFallback) ? numericFallback : 4);
|
|
444
|
+
return Math.max(1, Math.min(8, Math.floor(base)));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function formatI18nTemplate(template, params) {
|
|
448
|
+
if (typeof template !== 'string' || !template) {
|
|
449
|
+
return '';
|
|
450
|
+
}
|
|
451
|
+
return template.replace(/\{(\w+)\}/g, (_match, token) => {
|
|
452
|
+
const value = params && Object.prototype.hasOwnProperty.call(params, token)
|
|
453
|
+
? params[token]
|
|
454
|
+
: '';
|
|
455
|
+
return value == null ? '' : String(value);
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function getI18nText(key, fallback, params) {
|
|
460
|
+
if (
|
|
461
|
+
globalScope
|
|
462
|
+
&& globalScope.i18n
|
|
463
|
+
&& typeof globalScope.i18n.t === 'function'
|
|
464
|
+
) {
|
|
465
|
+
const translated = globalScope.i18n.t(key, params || {});
|
|
466
|
+
if (typeof translated === 'string' && translated.trim().length > 0 && translated !== key) {
|
|
467
|
+
return translated;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return formatI18nTemplate(fallback, params);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function getContractApi() {
|
|
474
|
+
return (globalScope && globalScope.NoteConnectionAgentWorkspaceContract)
|
|
475
|
+
? globalScope.NoteConnectionAgentWorkspaceContract
|
|
476
|
+
: null;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async function requestJson(endpoint, payload, options = {}) {
|
|
480
|
+
const method = trimString(options.method || 'POST').toUpperCase() || 'POST';
|
|
481
|
+
const responseKey = trimString(options.responseKey || 'result') || 'result';
|
|
482
|
+
const headers = method === 'GET'
|
|
483
|
+
? {}
|
|
484
|
+
: {
|
|
485
|
+
'Content-Type': 'application/json',
|
|
486
|
+
};
|
|
487
|
+
const requestOptions = {
|
|
488
|
+
method,
|
|
489
|
+
headers,
|
|
490
|
+
};
|
|
491
|
+
if (method !== 'GET') {
|
|
492
|
+
requestOptions.body = JSON.stringify(payload || {});
|
|
493
|
+
}
|
|
494
|
+
const response = await fetch(endpoint, requestOptions);
|
|
495
|
+
const body = await response.json().catch(() => null);
|
|
496
|
+
if (!response.ok) {
|
|
497
|
+
const message = body && body.error
|
|
498
|
+
? body.error
|
|
499
|
+
: `Request failed (${response.status})`;
|
|
500
|
+
throw new Error(String(message));
|
|
501
|
+
}
|
|
502
|
+
if (!body || body.success !== true) {
|
|
503
|
+
const message = body && body.error
|
|
504
|
+
? body.error
|
|
505
|
+
: `API ${endpoint} returned unexpected response`;
|
|
506
|
+
throw new Error(String(message));
|
|
507
|
+
}
|
|
508
|
+
return body[responseKey];
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function resolveConversationPayload(input) {
|
|
512
|
+
const contractApi = getContractApi();
|
|
513
|
+
if (contractApi && typeof contractApi.createAgentConversationPayload === 'function') {
|
|
514
|
+
return contractApi.createAgentConversationPayload(input);
|
|
515
|
+
}
|
|
516
|
+
const userId = trimString(input && input.userId);
|
|
517
|
+
const message = trimString(input && input.message);
|
|
518
|
+
const topKRaw = Number(input && input.topK);
|
|
519
|
+
const topK = Number.isFinite(topKRaw) ? Math.max(1, Math.min(8, Math.floor(topKRaw))) : 4;
|
|
520
|
+
if (!userId) {
|
|
521
|
+
throw new Error('agent_workspace requires a non-empty userId for conversation payload.');
|
|
522
|
+
}
|
|
523
|
+
if (!message) {
|
|
524
|
+
throw new Error('agent_workspace requires a non-empty message for conversation payload.');
|
|
525
|
+
}
|
|
526
|
+
return { userId, message, topK };
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function resolveOperationPlan(capability) {
|
|
530
|
+
const contractApi = getContractApi();
|
|
531
|
+
if (contractApi && typeof contractApi.buildKnowledgeOperationRequestPayload === 'function') {
|
|
532
|
+
return contractApi.buildKnowledgeOperationRequestPayload(capability);
|
|
533
|
+
}
|
|
534
|
+
const execution = capability && capability.execution && typeof capability.execution === 'object'
|
|
535
|
+
? capability.execution
|
|
536
|
+
: {};
|
|
537
|
+
const request = capability && capability.request && typeof capability.request === 'object'
|
|
538
|
+
? capability.request
|
|
539
|
+
: {};
|
|
540
|
+
const operationId = trimString(execution.operationId);
|
|
541
|
+
if (operationId === 'build_learning_path') {
|
|
542
|
+
return {
|
|
543
|
+
operationId,
|
|
544
|
+
endpoint: '/api/knowledge/path',
|
|
545
|
+
method: 'POST',
|
|
546
|
+
resultPresentation: 'learning_path_card',
|
|
547
|
+
body: {
|
|
548
|
+
userId: trimString(request.userId),
|
|
549
|
+
focusAtomIds: [trimString(request.atomId)],
|
|
550
|
+
maxMasteryPaths: 3,
|
|
551
|
+
maxDivergencePaths: 2,
|
|
552
|
+
},
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
if (operationId === 'execute_tutor_action') {
|
|
556
|
+
const userId = trimString(request.userId);
|
|
557
|
+
const atomId = trimString(request.atomId);
|
|
558
|
+
if (!userId || !atomId) {
|
|
559
|
+
throw new Error('execute_tutor_action requires request.userId, request.atomId, and request.actionKind.');
|
|
560
|
+
}
|
|
561
|
+
const actionKind = resolveTutorActionKind(request.actionKind);
|
|
562
|
+
const answer = trimString(request.answer);
|
|
563
|
+
return {
|
|
564
|
+
operationId,
|
|
565
|
+
endpoint: '/api/knowledge/tutor/action',
|
|
566
|
+
method: 'POST',
|
|
567
|
+
resultPresentation: trimString(execution.resultPresentation) || 'assistant_message',
|
|
568
|
+
body: {
|
|
569
|
+
userId,
|
|
570
|
+
atomId,
|
|
571
|
+
actionKind,
|
|
572
|
+
prompt: trimString(request.message),
|
|
573
|
+
...(answer ? { answer } : {}),
|
|
574
|
+
},
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
if (operationId === 'build_study_session') {
|
|
578
|
+
return {
|
|
579
|
+
operationId,
|
|
580
|
+
endpoint: '/api/knowledge/session/plan',
|
|
581
|
+
method: 'POST',
|
|
582
|
+
resultPresentation: trimString(execution.resultPresentation) || 'study_session_card',
|
|
583
|
+
body: {
|
|
584
|
+
userId: trimString(request.userId),
|
|
585
|
+
focusAtomIds: [trimString(request.atomId)],
|
|
586
|
+
maxActions: 6,
|
|
587
|
+
includeDivergence: true,
|
|
588
|
+
includeRetrain: false,
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
if (operationId === 'query_knowledge') {
|
|
593
|
+
const query = trimString(request.query || request.message);
|
|
594
|
+
if (!query) {
|
|
595
|
+
throw new Error('query_knowledge requires request.query or request.message.');
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
operationId,
|
|
599
|
+
endpoint: '/api/knowledge/query',
|
|
600
|
+
method: 'POST',
|
|
601
|
+
resultPresentation: trimString(execution.resultPresentation) || 'query_trace_card',
|
|
602
|
+
body: {
|
|
603
|
+
query,
|
|
604
|
+
topK: resolveQueryTopK(request.topK, 4),
|
|
605
|
+
},
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
if (operationId === 'evaluate_ingest_guardrails') {
|
|
609
|
+
return {
|
|
610
|
+
operationId,
|
|
611
|
+
endpoint: '/api/knowledge/ingest/guardrails/evaluate',
|
|
612
|
+
method: 'POST',
|
|
613
|
+
resultPresentation: trimString(execution.resultPresentation) || 'ingest_guardrail_card',
|
|
614
|
+
body: {},
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
if (operationId === 'query_session_history') {
|
|
618
|
+
return {
|
|
619
|
+
operationId,
|
|
620
|
+
endpoint: '/api/knowledge/session/history',
|
|
621
|
+
method: 'POST',
|
|
622
|
+
resultPresentation: trimString(execution.resultPresentation) || 'session_history_card',
|
|
623
|
+
body: {
|
|
624
|
+
userId: trimString(request.userId),
|
|
625
|
+
limit: 5,
|
|
626
|
+
},
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
if (operationId === 'query_mastery_misconceptions') {
|
|
630
|
+
const atomId = trimString(request.atomId);
|
|
631
|
+
return {
|
|
632
|
+
operationId,
|
|
633
|
+
endpoint: '/api/knowledge/mastery/misconceptions',
|
|
634
|
+
method: 'POST',
|
|
635
|
+
resultPresentation: trimString(execution.resultPresentation) || 'mastery_misconceptions_card',
|
|
636
|
+
body: {
|
|
637
|
+
userId: trimString(request.userId),
|
|
638
|
+
topK: resolveMisconceptionTopK(request.topK, 5),
|
|
639
|
+
...(atomId ? { atomIds: [atomId] } : {}),
|
|
640
|
+
},
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
if (operationId === 'capture_learning_quality_snapshot') {
|
|
644
|
+
return {
|
|
645
|
+
operationId,
|
|
646
|
+
endpoint: '/api/knowledge/quality/snapshot',
|
|
647
|
+
method: 'POST',
|
|
648
|
+
resultPresentation: trimString(execution.resultPresentation) || 'learning_quality_snapshot_card',
|
|
649
|
+
body: {
|
|
650
|
+
userId: trimString(request.userId),
|
|
651
|
+
},
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
if (operationId === 'apply_memory_policy') {
|
|
655
|
+
const userId = trimString(request.userId);
|
|
656
|
+
if (!userId) {
|
|
657
|
+
throw new Error('apply_memory_policy requires request.userId.');
|
|
658
|
+
}
|
|
659
|
+
const layer = resolveMemoryPolicyLayer(request.memoryLayer || request.layer);
|
|
660
|
+
const operation = resolveMemoryPolicyOperation(request.memoryOperation || request.operation);
|
|
661
|
+
const query = trimString(request.memoryQuery || request.query);
|
|
662
|
+
const limit = resolveMemoryPolicyLimit(
|
|
663
|
+
request.memoryLimit || request.limit,
|
|
664
|
+
operation === 'retrain_plan' ? 8 : 20
|
|
665
|
+
);
|
|
666
|
+
if (operation === 'write') {
|
|
667
|
+
const atomId = trimString(request.atomId);
|
|
668
|
+
const memoryKey = trimString(request.memoryKey) || (atomId ? `conversation_note:${atomId}` : '');
|
|
669
|
+
if (!memoryKey) {
|
|
670
|
+
throw new Error('apply_memory_policy write requires request.memoryKey or request.atomId.');
|
|
671
|
+
}
|
|
672
|
+
const memoryValue = trimString(request.memoryValue);
|
|
673
|
+
const memoryTags = resolveStringArray(request.memoryTags);
|
|
674
|
+
const memoryReferences = Array.from(new Set([
|
|
675
|
+
...resolveStringArray(request.memoryReferences),
|
|
676
|
+
...(atomId ? [atomId] : []),
|
|
677
|
+
]));
|
|
678
|
+
const promptMessage = trimString(request.memoryPromptMessage);
|
|
679
|
+
return {
|
|
680
|
+
operationId,
|
|
681
|
+
endpoint: '/api/knowledge/memory/policy',
|
|
682
|
+
method: 'POST',
|
|
683
|
+
resultPresentation: trimString(execution.resultPresentation) || 'memory_policy_card',
|
|
684
|
+
body: {
|
|
685
|
+
userId,
|
|
686
|
+
layer,
|
|
687
|
+
operation,
|
|
688
|
+
...(memoryValue ? {
|
|
689
|
+
entries: [
|
|
690
|
+
{
|
|
691
|
+
key: memoryKey,
|
|
692
|
+
value: memoryValue,
|
|
693
|
+
tags: memoryTags,
|
|
694
|
+
references: memoryReferences,
|
|
695
|
+
},
|
|
696
|
+
],
|
|
697
|
+
} : {}),
|
|
698
|
+
},
|
|
699
|
+
...(!memoryValue ? {
|
|
700
|
+
promptConfig: {
|
|
701
|
+
kind: 'memory_write',
|
|
702
|
+
message: promptMessage,
|
|
703
|
+
entryTemplate: {
|
|
704
|
+
key: memoryKey,
|
|
705
|
+
tags: memoryTags,
|
|
706
|
+
references: memoryReferences,
|
|
707
|
+
},
|
|
708
|
+
},
|
|
709
|
+
} : {}),
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
if (operation === 'evict') {
|
|
713
|
+
const matchKeys = resolveStringArray(request.memoryMatchKeys);
|
|
714
|
+
return {
|
|
715
|
+
operationId,
|
|
716
|
+
endpoint: '/api/knowledge/memory/policy',
|
|
717
|
+
method: 'POST',
|
|
718
|
+
resultPresentation: trimString(execution.resultPresentation) || 'memory_policy_card',
|
|
719
|
+
body: {
|
|
720
|
+
userId,
|
|
721
|
+
layer,
|
|
722
|
+
operation,
|
|
723
|
+
...(matchKeys.length ? { matchKeys } : {}),
|
|
724
|
+
},
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
operationId,
|
|
729
|
+
endpoint: '/api/knowledge/memory/policy',
|
|
730
|
+
method: 'POST',
|
|
731
|
+
resultPresentation: trimString(execution.resultPresentation) || 'memory_policy_card',
|
|
732
|
+
body: {
|
|
733
|
+
userId,
|
|
734
|
+
layer,
|
|
735
|
+
operation,
|
|
736
|
+
...(operation === 'read' || operation === 'retrain_plan' ? { limit } : {}),
|
|
737
|
+
...(operation === 'read' && resolveStringArray(request.memoryMatchKeys).length > 0 ? {
|
|
738
|
+
matchKeys: resolveStringArray(request.memoryMatchKeys),
|
|
739
|
+
} : {}),
|
|
740
|
+
...(operation === 'read' && query ? { query } : {}),
|
|
741
|
+
},
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
throw new Error(`Unsupported knowledge operation: ${operationId || '<empty>'}`);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function createAgentWorkspaceRuntime(options = {}) {
|
|
748
|
+
const state = {
|
|
749
|
+
busy: false,
|
|
750
|
+
latestKnowledgePoints: [],
|
|
751
|
+
latestFocusAtomId: '',
|
|
752
|
+
latestPathAtomId: '',
|
|
753
|
+
latestPathRuntimeNodeId: '',
|
|
754
|
+
latestPathRuntimeNodeLabel: '',
|
|
755
|
+
expandedHistoryEventIdsByAtom: Object.create(null),
|
|
756
|
+
pathVisible: false,
|
|
757
|
+
pathFullscreen: false,
|
|
758
|
+
initialized: false,
|
|
759
|
+
};
|
|
760
|
+
const diagnostics = {
|
|
761
|
+
turnSequence: 0,
|
|
762
|
+
capabilityEventSequence: 0,
|
|
763
|
+
turnHistory: [],
|
|
764
|
+
capabilityEvents: [],
|
|
765
|
+
conversationRequests: 0,
|
|
766
|
+
replayCandidateTurns: 0,
|
|
767
|
+
userMessageFingerprintCounts: Object.create(null),
|
|
768
|
+
lastConversation: null,
|
|
769
|
+
lastFoundationReadiness: null,
|
|
770
|
+
lastFailure: null,
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
const dom = {
|
|
774
|
+
panel: null,
|
|
775
|
+
form: null,
|
|
776
|
+
userIdInput: null,
|
|
777
|
+
input: null,
|
|
778
|
+
sendButton: null,
|
|
779
|
+
messages: null,
|
|
780
|
+
knowledgeList: null,
|
|
781
|
+
openPathButton: null,
|
|
782
|
+
closePathButton: null,
|
|
783
|
+
pathFullscreenButton: null,
|
|
784
|
+
foundationReadinessButton: null,
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
function nowIso() {
|
|
788
|
+
return new Date().toISOString();
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function pushBounded(list, item, maxSize) {
|
|
792
|
+
list.push(item);
|
|
793
|
+
if (list.length > maxSize) {
|
|
794
|
+
list.splice(0, list.length - maxSize);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
function markUserMessageReplayCandidate(message) {
|
|
799
|
+
const fingerprint = trimString(message).toLowerCase();
|
|
800
|
+
if (!fingerprint) {
|
|
801
|
+
return {
|
|
802
|
+
fingerprint: '',
|
|
803
|
+
replayCandidate: false,
|
|
804
|
+
seenCount: 0,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
const previousCount = Number(diagnostics.userMessageFingerprintCounts[fingerprint] || 0);
|
|
808
|
+
const nextCount = previousCount + 1;
|
|
809
|
+
diagnostics.userMessageFingerprintCounts[fingerprint] = nextCount;
|
|
810
|
+
const replayCandidate = previousCount > 0;
|
|
811
|
+
if (replayCandidate) {
|
|
812
|
+
diagnostics.replayCandidateTurns += 1;
|
|
813
|
+
}
|
|
814
|
+
return {
|
|
815
|
+
fingerprint,
|
|
816
|
+
replayCandidate,
|
|
817
|
+
seenCount: nextCount,
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
function recordTurn(role, text, meta = {}) {
|
|
822
|
+
const content = trimString(text);
|
|
823
|
+
if (!content) {
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
pushBounded(
|
|
827
|
+
diagnostics.turnHistory,
|
|
828
|
+
{
|
|
829
|
+
turnId: `turn_${diagnostics.turnSequence + 1}`,
|
|
830
|
+
role,
|
|
831
|
+
text: content,
|
|
832
|
+
at: nowIso(),
|
|
833
|
+
...meta,
|
|
834
|
+
},
|
|
835
|
+
MAX_DIAGNOSTIC_TURNS
|
|
836
|
+
);
|
|
837
|
+
diagnostics.turnSequence += 1;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function recordCapabilityEvent(payload = {}) {
|
|
841
|
+
const durationMs = Number(payload.durationMs);
|
|
842
|
+
const memoryLayer = normalizeMemoryPolicyLayerForDiagnostics(payload.memoryLayer);
|
|
843
|
+
const memoryOperation = normalizeMemoryPolicyOperationForDiagnostics(payload.memoryOperation);
|
|
844
|
+
const managedKeyLabels = resolveManagedConversationKeyLabels(payload.managedKeyLabels);
|
|
845
|
+
const matchedManagedKeyLabels = resolveManagedConversationKeyLabels(payload.matchedManagedKeyLabels);
|
|
846
|
+
const missingManagedKeyLabels = resolveManagedConversationKeyLabels(payload.missingManagedKeyLabels);
|
|
847
|
+
const resultPreview = cloneCapabilityResultPreview(payload.resultPreview);
|
|
848
|
+
const event = {
|
|
849
|
+
eventId: `cap_${diagnostics.capabilityEventSequence + 1}`,
|
|
850
|
+
at: nowIso(),
|
|
851
|
+
phase: trimString(payload.phase) || 'event',
|
|
852
|
+
status: trimString(payload.status) || 'unknown',
|
|
853
|
+
actionId: trimString(payload.actionId),
|
|
854
|
+
operationId: trimString(payload.operationId),
|
|
855
|
+
resultPresentation: trimString(payload.resultPresentation),
|
|
856
|
+
atomId: trimString(payload.atomId),
|
|
857
|
+
durationMs: Number.isFinite(durationMs) ? Math.max(0, Math.floor(durationMs)) : undefined,
|
|
858
|
+
error: trimString(payload.error),
|
|
859
|
+
memoryLayer: memoryLayer || undefined,
|
|
860
|
+
memoryOperation: memoryOperation || undefined,
|
|
861
|
+
managedKeyLabels: managedKeyLabels.length > 0 ? managedKeyLabels : undefined,
|
|
862
|
+
matchedManagedKeyLabels: matchedManagedKeyLabels.length > 0 ? matchedManagedKeyLabels : undefined,
|
|
863
|
+
missingManagedKeyLabels: missingManagedKeyLabels.length > 0 ? missingManagedKeyLabels : undefined,
|
|
864
|
+
resultPreview: resultPreview || undefined,
|
|
865
|
+
};
|
|
866
|
+
pushBounded(diagnostics.capabilityEvents, event, MAX_DIAGNOSTIC_CAPABILITY_EVENTS);
|
|
867
|
+
diagnostics.capabilityEventSequence += 1;
|
|
868
|
+
return event;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function recordFailure(source, errorMessage) {
|
|
872
|
+
diagnostics.lastFailure = {
|
|
873
|
+
at: nowIso(),
|
|
874
|
+
source: trimString(source),
|
|
875
|
+
message: trimString(errorMessage) || 'unknown error',
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
function cloneRunbookLinks() {
|
|
880
|
+
return DIAGNOSTIC_RUNBOOK_LINKS.map((link) => ({
|
|
881
|
+
id: link.id,
|
|
882
|
+
label: link.label,
|
|
883
|
+
paths: {
|
|
884
|
+
en: link.paths.en,
|
|
885
|
+
zh: link.paths.zh,
|
|
886
|
+
},
|
|
887
|
+
}));
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
function resolvePrimaryRunbookAction() {
|
|
891
|
+
// M8.53: bounded primary runbook consumer adoption.
|
|
892
|
+
// Derives the primary recommendation from local diagnostics state
|
|
893
|
+
// using the same contract shape as the server-side AgentWorkspaceDiagnosticsRunbookAction.
|
|
894
|
+
// No new routes, persistence, or backend recomputation.
|
|
895
|
+
var managedSummary = computeManagedConversationSummary();
|
|
896
|
+
var capabilityStats = computeCapabilityOperationStats();
|
|
897
|
+
var hasPersistentGaps = (
|
|
898
|
+
managedSummary.continuitySummary.persistentKeyCounts.note > 0 ||
|
|
899
|
+
managedSummary.continuitySummary.persistentKeyCounts.correction > 0
|
|
900
|
+
);
|
|
901
|
+
var hasResolvedGaps = (
|
|
902
|
+
managedSummary.continuitySummary.resolvedKeyCounts.note > 0 ||
|
|
903
|
+
managedSummary.continuitySummary.resolvedKeyCounts.correction > 0
|
|
904
|
+
);
|
|
905
|
+
var hasFailures = capabilityStats.some(function (stat) {
|
|
906
|
+
return stat.failureCount > 0;
|
|
907
|
+
});
|
|
908
|
+
var primaryAction = null;
|
|
909
|
+
var secondaryActions = [];
|
|
910
|
+
|
|
911
|
+
if (hasPersistentGaps) {
|
|
912
|
+
primaryAction = {
|
|
913
|
+
actionId: 'inspect_managed_memory_state',
|
|
914
|
+
severity: 'warning',
|
|
915
|
+
title: 'Review persistent managed-memory gaps',
|
|
916
|
+
trigger: 'persistentManagedMemoryGap',
|
|
917
|
+
rationale: (
|
|
918
|
+
'Persistent managed-memory gaps remain for the current atom. ' +
|
|
919
|
+
'Missing note keys: ' + (managedSummary.continuitySummary.persistentKeyCounts.note || 0) +
|
|
920
|
+
', missing correction keys: ' + (managedSummary.continuitySummary.persistentKeyCounts.correction || 0) +
|
|
921
|
+
'. Recommended next step: Store Memory Note or Record Correction for this atom.'
|
|
922
|
+
),
|
|
923
|
+
runbookLinkIds: ['development-progress-dashboard'],
|
|
924
|
+
};
|
|
925
|
+
if (managedSummary.continuitySummary.persistentFollowUpActionIds.length > 0) {
|
|
926
|
+
secondaryActions.push({
|
|
927
|
+
actionId: managedSummary.continuitySummary.persistentFollowUpActionIds[0],
|
|
928
|
+
severity: 'info',
|
|
929
|
+
title: 'Execute pending follow-up: ' + (managedSummary.continuitySummary.persistentFollowUpActionLabels[0] || managedSummary.continuitySummary.persistentFollowUpActionIds[0]),
|
|
930
|
+
trigger: 'persistentFollowUp',
|
|
931
|
+
rationale: 'A deterministic follow-up action remains from the most recent managed-memory gap analysis.',
|
|
932
|
+
runbookLinkIds: ['development-progress-dashboard'],
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
} else if (hasFailures) {
|
|
936
|
+
var failedStats = capabilityStats.filter(function (stat) { return stat.failureCount > 0; });
|
|
937
|
+
var firstFailedOp = failedStats[0];
|
|
938
|
+
primaryAction = {
|
|
939
|
+
actionId: 'review_recent_failures',
|
|
940
|
+
severity: 'warning',
|
|
941
|
+
title: 'Review recent capability failures',
|
|
942
|
+
trigger: 'recentCapabilityFailure',
|
|
943
|
+
rationale: (
|
|
944
|
+
'Recent capability execution failures detected. ' +
|
|
945
|
+
'Operation: ' + (firstFailedOp ? firstFailedOp.operationId : 'unknown') +
|
|
946
|
+
', failures: ' + (firstFailedOp ? firstFailedOp.failureCount : 0) +
|
|
947
|
+
'. Review the diagnostics snapshot for failure details.'
|
|
948
|
+
),
|
|
949
|
+
runbookLinkIds: ['development-progress-dashboard'],
|
|
950
|
+
};
|
|
951
|
+
} else if (hasResolvedGaps) {
|
|
952
|
+
primaryAction = {
|
|
953
|
+
actionId: 'review_continuity_recovery',
|
|
954
|
+
severity: 'info',
|
|
955
|
+
title: 'Continuity recovery confirmed',
|
|
956
|
+
trigger: 'managedMemoryGapResolved',
|
|
957
|
+
rationale: (
|
|
958
|
+
'Previously missing managed-memory gaps have been resolved by adjacent operations. ' +
|
|
959
|
+
'Resolved note keys: ' + (managedSummary.continuitySummary.resolvedKeyCounts.note || 0) +
|
|
960
|
+
', resolved correction keys: ' + (managedSummary.continuitySummary.resolvedKeyCounts.correction || 0) +
|
|
961
|
+
'. No immediate corrective action needed.'
|
|
962
|
+
),
|
|
963
|
+
runbookLinkIds: ['development-progress-dashboard'],
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
var runbookActions = [];
|
|
968
|
+
if (primaryAction) {
|
|
969
|
+
runbookActions.push(primaryAction);
|
|
970
|
+
}
|
|
971
|
+
runbookActions = runbookActions.concat(secondaryActions);
|
|
972
|
+
|
|
973
|
+
return {
|
|
974
|
+
primaryRunbookAction: primaryAction,
|
|
975
|
+
runbookActions: runbookActions,
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
function computeCapabilityOperationStats() {
|
|
980
|
+
const byOperationId = Object.create(null);
|
|
981
|
+
diagnostics.capabilityEvents.forEach((event) => {
|
|
982
|
+
const operationId = trimString(event.operationId) || '__unknown__';
|
|
983
|
+
const status = trimString(event.status) || 'unknown';
|
|
984
|
+
const phase = trimString(event.phase) || 'event';
|
|
985
|
+
if (!byOperationId[operationId]) {
|
|
986
|
+
byOperationId[operationId] = {
|
|
987
|
+
operationId,
|
|
988
|
+
eventIds: [],
|
|
989
|
+
requestCount: 0,
|
|
990
|
+
resultCount: 0,
|
|
991
|
+
successCount: 0,
|
|
992
|
+
failureCount: 0,
|
|
993
|
+
pendingCount: 0,
|
|
994
|
+
unknownCount: 0,
|
|
995
|
+
durationTotalMs: 0,
|
|
996
|
+
durationSampleCount: 0,
|
|
997
|
+
latestStatus: '',
|
|
998
|
+
latestAt: '',
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
const stats = byOperationId[operationId];
|
|
1002
|
+
const eventId = trimString(event.eventId);
|
|
1003
|
+
if (eventId) {
|
|
1004
|
+
stats.eventIds.push(eventId);
|
|
1005
|
+
}
|
|
1006
|
+
if (phase === 'request') {
|
|
1007
|
+
stats.requestCount += 1;
|
|
1008
|
+
} else if (phase === 'result') {
|
|
1009
|
+
stats.resultCount += 1;
|
|
1010
|
+
}
|
|
1011
|
+
if (status === 'success') {
|
|
1012
|
+
stats.successCount += 1;
|
|
1013
|
+
} else if (status === 'failure' || status === 'error') {
|
|
1014
|
+
stats.failureCount += 1;
|
|
1015
|
+
} else if (status === 'pending') {
|
|
1016
|
+
stats.pendingCount += 1;
|
|
1017
|
+
} else {
|
|
1018
|
+
stats.unknownCount += 1;
|
|
1019
|
+
}
|
|
1020
|
+
const durationMs = Number(event.durationMs);
|
|
1021
|
+
if (Number.isFinite(durationMs)) {
|
|
1022
|
+
stats.durationTotalMs += Math.max(0, Math.floor(durationMs));
|
|
1023
|
+
stats.durationSampleCount += 1;
|
|
1024
|
+
}
|
|
1025
|
+
stats.latestStatus = status;
|
|
1026
|
+
stats.latestAt = trimString(event.at);
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
return Object.keys(byOperationId)
|
|
1030
|
+
.sort()
|
|
1031
|
+
.map((operationId) => {
|
|
1032
|
+
const stats = byOperationId[operationId];
|
|
1033
|
+
return {
|
|
1034
|
+
operationId: stats.operationId,
|
|
1035
|
+
eventIds: stats.eventIds.slice(),
|
|
1036
|
+
requestCount: stats.requestCount,
|
|
1037
|
+
resultCount: stats.resultCount,
|
|
1038
|
+
successCount: stats.successCount,
|
|
1039
|
+
failureCount: stats.failureCount,
|
|
1040
|
+
pendingCount: stats.pendingCount,
|
|
1041
|
+
unknownCount: stats.unknownCount,
|
|
1042
|
+
averageDurationMs: stats.durationSampleCount > 0
|
|
1043
|
+
? Math.round(stats.durationTotalMs / stats.durationSampleCount)
|
|
1044
|
+
: null,
|
|
1045
|
+
latestStatus: stats.latestStatus,
|
|
1046
|
+
latestAt: stats.latestAt,
|
|
1047
|
+
};
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
function computeTurnIndex() {
|
|
1052
|
+
const byTurnId = Object.create(null);
|
|
1053
|
+
const replayCandidateTurnIds = [];
|
|
1054
|
+
diagnostics.turnHistory.forEach((turn, index) => {
|
|
1055
|
+
const turnId = trimString(turn && turn.turnId);
|
|
1056
|
+
if (!turnId) {
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
const replayCandidate = Boolean(turn && turn.replayCandidate);
|
|
1060
|
+
if (replayCandidate) {
|
|
1061
|
+
replayCandidateTurnIds.push(turnId);
|
|
1062
|
+
}
|
|
1063
|
+
byTurnId[turnId] = {
|
|
1064
|
+
index,
|
|
1065
|
+
role: trimString(turn && turn.role),
|
|
1066
|
+
at: trimString(turn && turn.at),
|
|
1067
|
+
replayCandidate,
|
|
1068
|
+
userMessageFingerprint: trimString(turn && turn.userMessageFingerprint),
|
|
1069
|
+
};
|
|
1070
|
+
});
|
|
1071
|
+
return {
|
|
1072
|
+
byTurnId,
|
|
1073
|
+
replayCandidateTurnIds,
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
function computeMemoryPolicySummary() {
|
|
1078
|
+
const byLayer = createEmptyMemoryPolicyLayerCounts();
|
|
1079
|
+
const byOperation = createEmptyMemoryPolicyOperationCounts();
|
|
1080
|
+
let executionCount = 0;
|
|
1081
|
+
let readonlyExecutions = 0;
|
|
1082
|
+
let mutatingExecutions = 0;
|
|
1083
|
+
let successCount = 0;
|
|
1084
|
+
let failureCount = 0;
|
|
1085
|
+
let lastEvent = null;
|
|
1086
|
+
|
|
1087
|
+
diagnostics.capabilityEvents.forEach((event) => {
|
|
1088
|
+
if (trimString(event.operationId) !== 'apply_memory_policy') {
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
if (trimString(event.phase) !== 'result') {
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
executionCount += 1;
|
|
1096
|
+
const memoryLayer = normalizeMemoryPolicyLayerForDiagnostics(event.memoryLayer);
|
|
1097
|
+
const memoryOperation = normalizeMemoryPolicyOperationForDiagnostics(event.memoryOperation);
|
|
1098
|
+
const status = trimString(event.status);
|
|
1099
|
+
|
|
1100
|
+
if (memoryLayer) {
|
|
1101
|
+
byLayer[memoryLayer] += 1;
|
|
1102
|
+
}
|
|
1103
|
+
if (memoryOperation) {
|
|
1104
|
+
byOperation[memoryOperation] += 1;
|
|
1105
|
+
if (isReadonlyMemoryPolicyOperation(memoryOperation)) {
|
|
1106
|
+
readonlyExecutions += 1;
|
|
1107
|
+
} else {
|
|
1108
|
+
mutatingExecutions += 1;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
if (status === 'success') {
|
|
1112
|
+
successCount += 1;
|
|
1113
|
+
} else if (status === 'failure' || status === 'failed' || status === 'error') {
|
|
1114
|
+
failureCount += 1;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
lastEvent = { ...event };
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
return {
|
|
1121
|
+
executionCount,
|
|
1122
|
+
readonlyExecutions,
|
|
1123
|
+
mutatingExecutions,
|
|
1124
|
+
successCount,
|
|
1125
|
+
failureCount,
|
|
1126
|
+
byLayer,
|
|
1127
|
+
byOperation,
|
|
1128
|
+
lastEvent,
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
function createEmptyManagedConversationActionCounts() {
|
|
1133
|
+
return {
|
|
1134
|
+
inspect_managed_memory_state: 0,
|
|
1135
|
+
write_memory_note: 0,
|
|
1136
|
+
record_memory_correction: 0,
|
|
1137
|
+
evict_memory_note: 0,
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
function createEmptyManagedConversationKeyCounts() {
|
|
1142
|
+
return {
|
|
1143
|
+
note: 0,
|
|
1144
|
+
correction: 0,
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
function createEmptyManagedConversationContinuitySummary() {
|
|
1149
|
+
return {
|
|
1150
|
+
atomIds: [],
|
|
1151
|
+
atomCount: 0,
|
|
1152
|
+
readCount: 0,
|
|
1153
|
+
transitionCount: 0,
|
|
1154
|
+
resolvedKeyCounts: createEmptyManagedConversationKeyCounts(),
|
|
1155
|
+
resolvedFollowUpActionIds: [],
|
|
1156
|
+
resolvedFollowUpActionLabels: [],
|
|
1157
|
+
persistentKeyCounts: createEmptyManagedConversationKeyCounts(),
|
|
1158
|
+
persistentFollowUpActionIds: [],
|
|
1159
|
+
persistentFollowUpActionLabels: [],
|
|
1160
|
+
lastTransition: null,
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
function incrementManagedConversationKeyCounts(counts, labels) {
|
|
1165
|
+
resolveStringArray(labels).forEach((label) => {
|
|
1166
|
+
if (label === 'note' || label === 'correction') {
|
|
1167
|
+
counts[label] += 1;
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
function isManagedConversationActionId(actionId) {
|
|
1173
|
+
return MANAGED_CONVERSATION_ACTION_IDS.includes(trimString(actionId));
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
function hasManagedConversationKeyCounts(counts) {
|
|
1177
|
+
return Boolean(counts) && (
|
|
1178
|
+
Number(counts.note) > 0
|
|
1179
|
+
|| Number(counts.correction) > 0
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
function computeManagedConversationContinuitySummary(events, newestFirst = true) {
|
|
1184
|
+
const summary = createEmptyManagedConversationContinuitySummary();
|
|
1185
|
+
const sourceEvents = Array.isArray(events)
|
|
1186
|
+
? (newestFirst ? events.slice() : events.slice().reverse())
|
|
1187
|
+
: [];
|
|
1188
|
+
const eventsByAtomId = Object.create(null);
|
|
1189
|
+
|
|
1190
|
+
sourceEvents.forEach((event) => {
|
|
1191
|
+
const atomId = trimString(event && event.atomId);
|
|
1192
|
+
if (!atomId) {
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
if (trimString(event && event.actionId) !== 'inspect_managed_memory_state') {
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
if (trimString(event && event.phase) === 'request' || trimString(event && event.phase) === 'plan') {
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (trimString(event && event.status) !== 'success') {
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
if (!eventsByAtomId[atomId]) {
|
|
1205
|
+
eventsByAtomId[atomId] = [];
|
|
1206
|
+
}
|
|
1207
|
+
eventsByAtomId[atomId].push(event);
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
summary.atomIds = Object.keys(eventsByAtomId);
|
|
1211
|
+
summary.atomCount = summary.atomIds.length;
|
|
1212
|
+
|
|
1213
|
+
summary.atomIds.forEach((atomId) => {
|
|
1214
|
+
const atomEvents = eventsByAtomId[atomId];
|
|
1215
|
+
summary.readCount += atomEvents.length;
|
|
1216
|
+
for (let index = 0; index < atomEvents.length - 1; index += 1) {
|
|
1217
|
+
const newerEvent = atomEvents[index];
|
|
1218
|
+
const olderEvent = atomEvents[index + 1];
|
|
1219
|
+
const newerMissingManagedKeyLabels = resolveManagedConversationKeyLabels(
|
|
1220
|
+
newerEvent && newerEvent.missingManagedKeyLabels
|
|
1221
|
+
);
|
|
1222
|
+
const olderMissingManagedKeyLabels = resolveManagedConversationKeyLabels(
|
|
1223
|
+
olderEvent && olderEvent.missingManagedKeyLabels
|
|
1224
|
+
);
|
|
1225
|
+
const persistentKeyLabels = [];
|
|
1226
|
+
const resolvedKeyLabels = [];
|
|
1227
|
+
olderMissingManagedKeyLabels.forEach((label) => {
|
|
1228
|
+
if (newerMissingManagedKeyLabels.includes(label)) {
|
|
1229
|
+
persistentKeyLabels.push(label);
|
|
1230
|
+
summary.persistentKeyCounts[label] += 1;
|
|
1231
|
+
summary.transitionCount += 1;
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
resolvedKeyLabels.push(label);
|
|
1235
|
+
summary.resolvedKeyCounts[label] += 1;
|
|
1236
|
+
summary.transitionCount += 1;
|
|
1237
|
+
});
|
|
1238
|
+
if (!summary.lastTransition && (resolvedKeyLabels.length > 0 || persistentKeyLabels.length > 0)) {
|
|
1239
|
+
summary.lastTransition = buildManagedConversationLastTransition(
|
|
1240
|
+
atomId,
|
|
1241
|
+
newerEvent,
|
|
1242
|
+
olderEvent,
|
|
1243
|
+
resolvedKeyLabels,
|
|
1244
|
+
persistentKeyLabels
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1250
|
+
summary.resolvedFollowUpActionIds = resolveManagedConversationFollowUpActionIdsFromKeyCounts(
|
|
1251
|
+
summary.resolvedKeyCounts
|
|
1252
|
+
);
|
|
1253
|
+
summary.resolvedFollowUpActionLabels = resolveManagedConversationFollowUpActionLabels(
|
|
1254
|
+
summary.resolvedFollowUpActionIds
|
|
1255
|
+
);
|
|
1256
|
+
summary.persistentFollowUpActionIds = resolveManagedConversationFollowUpActionIdsFromKeyCounts(
|
|
1257
|
+
summary.persistentKeyCounts
|
|
1258
|
+
);
|
|
1259
|
+
summary.persistentFollowUpActionLabels = resolveManagedConversationFollowUpActionLabels(
|
|
1260
|
+
summary.persistentFollowUpActionIds
|
|
1261
|
+
);
|
|
1262
|
+
|
|
1263
|
+
return summary;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
function computeManagedConversationSummary() {
|
|
1267
|
+
const byActionId = createEmptyManagedConversationActionCounts();
|
|
1268
|
+
const matchedKeyCounts = createEmptyManagedConversationKeyCounts();
|
|
1269
|
+
const missingKeyCounts = createEmptyManagedConversationKeyCounts();
|
|
1270
|
+
const continuitySummary = computeManagedConversationContinuitySummary(diagnostics.capabilityEvents, false);
|
|
1271
|
+
let executionCount = 0;
|
|
1272
|
+
let successCount = 0;
|
|
1273
|
+
let failureCount = 0;
|
|
1274
|
+
let lastEvent = null;
|
|
1275
|
+
|
|
1276
|
+
diagnostics.capabilityEvents.forEach((event) => {
|
|
1277
|
+
const actionId = trimString(event && event.actionId);
|
|
1278
|
+
if (!isManagedConversationActionId(actionId) || trimString(event && event.phase) !== 'result') {
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
executionCount += 1;
|
|
1283
|
+
byActionId[actionId] += 1;
|
|
1284
|
+
incrementManagedConversationKeyCounts(matchedKeyCounts, event && event.matchedManagedKeyLabels);
|
|
1285
|
+
incrementManagedConversationKeyCounts(missingKeyCounts, event && event.missingManagedKeyLabels);
|
|
1286
|
+
|
|
1287
|
+
const status = trimString(event && event.status);
|
|
1288
|
+
if (status === 'success') {
|
|
1289
|
+
successCount += 1;
|
|
1290
|
+
} else if (status === 'failure' || status === 'failed' || status === 'error') {
|
|
1291
|
+
failureCount += 1;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
lastEvent = { ...event };
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1297
|
+
return {
|
|
1298
|
+
executionCount,
|
|
1299
|
+
successCount,
|
|
1300
|
+
failureCount,
|
|
1301
|
+
byActionId,
|
|
1302
|
+
matchedKeyCounts,
|
|
1303
|
+
missingKeyCounts,
|
|
1304
|
+
continuitySummary,
|
|
1305
|
+
lastEvent,
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
function computeManagedConversationActionStats() {
|
|
1310
|
+
const statsByActionId = Object.create(null);
|
|
1311
|
+
MANAGED_CONVERSATION_ACTION_IDS.forEach((actionId) => {
|
|
1312
|
+
statsByActionId[actionId] = {
|
|
1313
|
+
actionId,
|
|
1314
|
+
requestCount: 0,
|
|
1315
|
+
resultCount: 0,
|
|
1316
|
+
successCount: 0,
|
|
1317
|
+
failureCount: 0,
|
|
1318
|
+
pendingCount: 0,
|
|
1319
|
+
unknownCount: 0,
|
|
1320
|
+
targetKeyCounts: createEmptyManagedConversationKeyCounts(),
|
|
1321
|
+
matchedKeyCounts: createEmptyManagedConversationKeyCounts(),
|
|
1322
|
+
missingKeyCounts: createEmptyManagedConversationKeyCounts(),
|
|
1323
|
+
latestStatus: '',
|
|
1324
|
+
latestAt: '',
|
|
1325
|
+
};
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
diagnostics.capabilityEvents.forEach((event) => {
|
|
1329
|
+
const actionId = trimString(event && event.actionId);
|
|
1330
|
+
if (!isManagedConversationActionId(actionId)) {
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
const phase = trimString(event && event.phase) || 'event';
|
|
1335
|
+
const status = trimString(event && event.status) || 'unknown';
|
|
1336
|
+
const stats = statsByActionId[actionId];
|
|
1337
|
+
|
|
1338
|
+
if (phase === 'request') {
|
|
1339
|
+
stats.requestCount += 1;
|
|
1340
|
+
} else if (phase === 'result') {
|
|
1341
|
+
stats.resultCount += 1;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
if (status === 'success') {
|
|
1345
|
+
stats.successCount += 1;
|
|
1346
|
+
} else if (status === 'failure' || status === 'failed' || status === 'error') {
|
|
1347
|
+
stats.failureCount += 1;
|
|
1348
|
+
} else if (status === 'pending') {
|
|
1349
|
+
stats.pendingCount += 1;
|
|
1350
|
+
} else {
|
|
1351
|
+
stats.unknownCount += 1;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
incrementManagedConversationKeyCounts(stats.targetKeyCounts, event && event.managedKeyLabels);
|
|
1355
|
+
incrementManagedConversationKeyCounts(stats.matchedKeyCounts, event && event.matchedManagedKeyLabels);
|
|
1356
|
+
incrementManagedConversationKeyCounts(stats.missingKeyCounts, event && event.missingManagedKeyLabels);
|
|
1357
|
+
stats.latestStatus = status;
|
|
1358
|
+
stats.latestAt = trimString(event && event.at);
|
|
1359
|
+
});
|
|
1360
|
+
|
|
1361
|
+
const actionIds = MANAGED_CONVERSATION_ACTION_IDS.filter((actionId) => {
|
|
1362
|
+
const stats = statsByActionId[actionId];
|
|
1363
|
+
return stats.requestCount > 0 || stats.resultCount > 0;
|
|
1364
|
+
});
|
|
1365
|
+
|
|
1366
|
+
return {
|
|
1367
|
+
actionIds,
|
|
1368
|
+
byActionId: actionIds.reduce((accumulator, actionId) => {
|
|
1369
|
+
const stats = statsByActionId[actionId];
|
|
1370
|
+
accumulator[actionId] = {
|
|
1371
|
+
actionId: stats.actionId,
|
|
1372
|
+
requestCount: stats.requestCount,
|
|
1373
|
+
resultCount: stats.resultCount,
|
|
1374
|
+
successCount: stats.successCount,
|
|
1375
|
+
failureCount: stats.failureCount,
|
|
1376
|
+
pendingCount: stats.pendingCount,
|
|
1377
|
+
unknownCount: stats.unknownCount,
|
|
1378
|
+
targetKeyCounts: { ...stats.targetKeyCounts },
|
|
1379
|
+
matchedKeyCounts: { ...stats.matchedKeyCounts },
|
|
1380
|
+
missingKeyCounts: { ...stats.missingKeyCounts },
|
|
1381
|
+
latestStatus: stats.latestStatus,
|
|
1382
|
+
latestAt: stats.latestAt,
|
|
1383
|
+
};
|
|
1384
|
+
return accumulator;
|
|
1385
|
+
}, Object.create(null)),
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
function getDiagnosticsSnapshot() {
|
|
1390
|
+
const turnCounts = diagnostics.turnHistory.reduce(
|
|
1391
|
+
(accumulator, turn) => {
|
|
1392
|
+
if (turn.role === 'user') {
|
|
1393
|
+
accumulator.user += 1;
|
|
1394
|
+
} else if (turn.role === 'assistant') {
|
|
1395
|
+
accumulator.assistant += 1;
|
|
1396
|
+
} else if (turn.role === 'system') {
|
|
1397
|
+
accumulator.system += 1;
|
|
1398
|
+
}
|
|
1399
|
+
return accumulator;
|
|
1400
|
+
},
|
|
1401
|
+
{ user: 0, assistant: 0, system: 0 }
|
|
1402
|
+
);
|
|
1403
|
+
const latestCapabilityEvent = diagnostics.capabilityEvents.length > 0
|
|
1404
|
+
? diagnostics.capabilityEvents[diagnostics.capabilityEvents.length - 1]
|
|
1405
|
+
: null;
|
|
1406
|
+
const memoryPolicySummary = computeMemoryPolicySummary();
|
|
1407
|
+
const managedConversationSummary = computeManagedConversationSummary();
|
|
1408
|
+
return {
|
|
1409
|
+
generatedAt: nowIso(),
|
|
1410
|
+
conversationRequests: diagnostics.conversationRequests,
|
|
1411
|
+
replayCandidateTurns: diagnostics.replayCandidateTurns,
|
|
1412
|
+
turnCounts: {
|
|
1413
|
+
...turnCounts,
|
|
1414
|
+
total: diagnostics.turnHistory.length,
|
|
1415
|
+
},
|
|
1416
|
+
turns: diagnostics.turnHistory.map((turn) => ({ ...turn })),
|
|
1417
|
+
capabilityEvents: diagnostics.capabilityEvents.map((event) => cloneCapabilityEvent(event)),
|
|
1418
|
+
lastCapabilityEvent: latestCapabilityEvent ? cloneCapabilityEvent(latestCapabilityEvent) : null,
|
|
1419
|
+
lastConversation: diagnostics.lastConversation
|
|
1420
|
+
? { ...diagnostics.lastConversation }
|
|
1421
|
+
: null,
|
|
1422
|
+
lastFoundationReadiness: diagnostics.lastFoundationReadiness
|
|
1423
|
+
? { ...diagnostics.lastFoundationReadiness }
|
|
1424
|
+
: null,
|
|
1425
|
+
lastFailure: diagnostics.lastFailure
|
|
1426
|
+
? { ...diagnostics.lastFailure }
|
|
1427
|
+
: null,
|
|
1428
|
+
memoryPolicySummary: {
|
|
1429
|
+
...memoryPolicySummary,
|
|
1430
|
+
byLayer: { ...memoryPolicySummary.byLayer },
|
|
1431
|
+
byOperation: { ...memoryPolicySummary.byOperation },
|
|
1432
|
+
lastEvent: memoryPolicySummary.lastEvent
|
|
1433
|
+
? { ...memoryPolicySummary.lastEvent }
|
|
1434
|
+
: null,
|
|
1435
|
+
},
|
|
1436
|
+
managedConversationSummary: {
|
|
1437
|
+
...managedConversationSummary,
|
|
1438
|
+
byActionId: { ...managedConversationSummary.byActionId },
|
|
1439
|
+
matchedKeyCounts: { ...managedConversationSummary.matchedKeyCounts },
|
|
1440
|
+
missingKeyCounts: { ...managedConversationSummary.missingKeyCounts },
|
|
1441
|
+
continuitySummary: {
|
|
1442
|
+
...managedConversationSummary.continuitySummary,
|
|
1443
|
+
atomIds: managedConversationSummary.continuitySummary.atomIds.slice(),
|
|
1444
|
+
resolvedKeyCounts: { ...managedConversationSummary.continuitySummary.resolvedKeyCounts },
|
|
1445
|
+
resolvedFollowUpActionIds: managedConversationSummary.continuitySummary.resolvedFollowUpActionIds.slice(),
|
|
1446
|
+
resolvedFollowUpActionLabels: managedConversationSummary.continuitySummary.resolvedFollowUpActionLabels.slice(),
|
|
1447
|
+
persistentKeyCounts: { ...managedConversationSummary.continuitySummary.persistentKeyCounts },
|
|
1448
|
+
persistentFollowUpActionIds: managedConversationSummary.continuitySummary.persistentFollowUpActionIds.slice(),
|
|
1449
|
+
persistentFollowUpActionLabels: managedConversationSummary.continuitySummary.persistentFollowUpActionLabels.slice(),
|
|
1450
|
+
lastTransition: managedConversationSummary.continuitySummary.lastTransition
|
|
1451
|
+
? {
|
|
1452
|
+
...managedConversationSummary.continuitySummary.lastTransition,
|
|
1453
|
+
keyLabels: managedConversationSummary.continuitySummary.lastTransition.keyLabels.slice(),
|
|
1454
|
+
resolvedKeyLabels: managedConversationSummary.continuitySummary.lastTransition.resolvedKeyLabels.slice(),
|
|
1455
|
+
persistentKeyLabels: managedConversationSummary.continuitySummary.lastTransition.persistentKeyLabels.slice(),
|
|
1456
|
+
followUpActionIds: managedConversationSummary.continuitySummary.lastTransition.followUpActionIds.slice(),
|
|
1457
|
+
followUpActionLabels: managedConversationSummary.continuitySummary.lastTransition.followUpActionLabels.slice(),
|
|
1458
|
+
resolvedFollowUpActionIds: managedConversationSummary.continuitySummary.lastTransition.resolvedFollowUpActionIds.slice(),
|
|
1459
|
+
resolvedFollowUpActionLabels: managedConversationSummary.continuitySummary.lastTransition.resolvedFollowUpActionLabels.slice(),
|
|
1460
|
+
persistentFollowUpActionIds: managedConversationSummary.continuitySummary.lastTransition.persistentFollowUpActionIds.slice(),
|
|
1461
|
+
persistentFollowUpActionLabels: managedConversationSummary.continuitySummary.lastTransition.persistentFollowUpActionLabels.slice(),
|
|
1462
|
+
}
|
|
1463
|
+
: null,
|
|
1464
|
+
},
|
|
1465
|
+
lastEvent: managedConversationSummary.lastEvent
|
|
1466
|
+
? { ...managedConversationSummary.lastEvent }
|
|
1467
|
+
: null,
|
|
1468
|
+
},
|
|
1469
|
+
pathState: {
|
|
1470
|
+
visible: state.pathVisible,
|
|
1471
|
+
fullscreen: state.pathFullscreen,
|
|
1472
|
+
atomId: resolveCurrentPathAtomId(),
|
|
1473
|
+
targetId: trimString(state.latestPathRuntimeNodeId),
|
|
1474
|
+
targetLabel: trimString(state.latestPathRuntimeNodeLabel),
|
|
1475
|
+
},
|
|
1476
|
+
latestFocusAtomId: state.latestFocusAtomId,
|
|
1477
|
+
latestKnowledgePoints: Array.isArray(state.latestKnowledgePoints)
|
|
1478
|
+
? state.latestKnowledgePoints.length
|
|
1479
|
+
: 0,
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
function getDiagnosticsTrendSnapshot() {
|
|
1484
|
+
const operationStats = computeCapabilityOperationStats();
|
|
1485
|
+
const userTurnCount = diagnostics.turnHistory.reduce(
|
|
1486
|
+
(count, turn) => (turn.role === 'user' ? count + 1 : count),
|
|
1487
|
+
0
|
|
1488
|
+
);
|
|
1489
|
+
const replayCandidateRate = userTurnCount > 0
|
|
1490
|
+
? Number((diagnostics.replayCandidateTurns / userTurnCount).toFixed(4))
|
|
1491
|
+
: 0;
|
|
1492
|
+
return {
|
|
1493
|
+
generatedAt: nowIso(),
|
|
1494
|
+
window: {
|
|
1495
|
+
turns: diagnostics.turnHistory.length,
|
|
1496
|
+
capabilityEvents: diagnostics.capabilityEvents.length,
|
|
1497
|
+
},
|
|
1498
|
+
conversationRequests: diagnostics.conversationRequests,
|
|
1499
|
+
userTurns: userTurnCount,
|
|
1500
|
+
replayCandidateTurns: diagnostics.replayCandidateTurns,
|
|
1501
|
+
replayCandidateRate,
|
|
1502
|
+
operationStats: operationStats.map((stats) => ({
|
|
1503
|
+
operationId: stats.operationId,
|
|
1504
|
+
requestCount: stats.requestCount,
|
|
1505
|
+
resultCount: stats.resultCount,
|
|
1506
|
+
successCount: stats.successCount,
|
|
1507
|
+
failureCount: stats.failureCount,
|
|
1508
|
+
pendingCount: stats.pendingCount,
|
|
1509
|
+
unknownCount: stats.unknownCount,
|
|
1510
|
+
averageDurationMs: stats.averageDurationMs,
|
|
1511
|
+
latestStatus: stats.latestStatus,
|
|
1512
|
+
latestAt: stats.latestAt,
|
|
1513
|
+
})),
|
|
1514
|
+
lastFailure: diagnostics.lastFailure
|
|
1515
|
+
? { ...diagnostics.lastFailure }
|
|
1516
|
+
: null,
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
function getDiagnosticsIndexSnapshot() {
|
|
1521
|
+
const capabilityOperationStats = computeCapabilityOperationStats();
|
|
1522
|
+
const capabilityOperationIds = capabilityOperationStats.map((stats) => stats.operationId);
|
|
1523
|
+
const byOperationId = capabilityOperationStats.reduce((accumulator, stats) => {
|
|
1524
|
+
accumulator[stats.operationId] = {
|
|
1525
|
+
operationId: stats.operationId,
|
|
1526
|
+
eventIds: stats.eventIds.slice(),
|
|
1527
|
+
requestCount: stats.requestCount,
|
|
1528
|
+
resultCount: stats.resultCount,
|
|
1529
|
+
successCount: stats.successCount,
|
|
1530
|
+
failureCount: stats.failureCount,
|
|
1531
|
+
pendingCount: stats.pendingCount,
|
|
1532
|
+
unknownCount: stats.unknownCount,
|
|
1533
|
+
averageDurationMs: stats.averageDurationMs,
|
|
1534
|
+
latestStatus: stats.latestStatus,
|
|
1535
|
+
latestAt: stats.latestAt,
|
|
1536
|
+
};
|
|
1537
|
+
return accumulator;
|
|
1538
|
+
}, Object.create(null));
|
|
1539
|
+
const managedConversationActionStats = computeManagedConversationActionStats();
|
|
1540
|
+
const managedConversationSummary = computeManagedConversationSummary();
|
|
1541
|
+
|
|
1542
|
+
return {
|
|
1543
|
+
generatedAt: nowIso(),
|
|
1544
|
+
turnIndex: computeTurnIndex(),
|
|
1545
|
+
capabilityIndex: {
|
|
1546
|
+
operationIds: capabilityOperationIds,
|
|
1547
|
+
byOperationId,
|
|
1548
|
+
},
|
|
1549
|
+
managedConversationIndex: {
|
|
1550
|
+
actionIds: managedConversationActionStats.actionIds.slice(),
|
|
1551
|
+
byActionId: managedConversationActionStats.actionIds.reduce((accumulator, actionId) => {
|
|
1552
|
+
const stats = managedConversationActionStats.byActionId[actionId];
|
|
1553
|
+
accumulator[actionId] = {
|
|
1554
|
+
actionId: stats.actionId,
|
|
1555
|
+
requestCount: stats.requestCount,
|
|
1556
|
+
resultCount: stats.resultCount,
|
|
1557
|
+
successCount: stats.successCount,
|
|
1558
|
+
failureCount: stats.failureCount,
|
|
1559
|
+
pendingCount: stats.pendingCount,
|
|
1560
|
+
unknownCount: stats.unknownCount,
|
|
1561
|
+
targetKeyCounts: { ...stats.targetKeyCounts },
|
|
1562
|
+
matchedKeyCounts: { ...stats.matchedKeyCounts },
|
|
1563
|
+
missingKeyCounts: { ...stats.missingKeyCounts },
|
|
1564
|
+
latestStatus: stats.latestStatus,
|
|
1565
|
+
latestAt: stats.latestAt,
|
|
1566
|
+
};
|
|
1567
|
+
return accumulator;
|
|
1568
|
+
}, Object.create(null)),
|
|
1569
|
+
continuitySummary: {
|
|
1570
|
+
...managedConversationSummary.continuitySummary,
|
|
1571
|
+
atomIds: managedConversationSummary.continuitySummary.atomIds.slice(),
|
|
1572
|
+
resolvedKeyCounts: { ...managedConversationSummary.continuitySummary.resolvedKeyCounts },
|
|
1573
|
+
resolvedFollowUpActionIds: managedConversationSummary.continuitySummary.resolvedFollowUpActionIds.slice(),
|
|
1574
|
+
resolvedFollowUpActionLabels: managedConversationSummary.continuitySummary.resolvedFollowUpActionLabels.slice(),
|
|
1575
|
+
persistentKeyCounts: { ...managedConversationSummary.continuitySummary.persistentKeyCounts },
|
|
1576
|
+
persistentFollowUpActionIds: managedConversationSummary.continuitySummary.persistentFollowUpActionIds.slice(),
|
|
1577
|
+
persistentFollowUpActionLabels: managedConversationSummary.continuitySummary.persistentFollowUpActionLabels.slice(),
|
|
1578
|
+
lastTransition: managedConversationSummary.continuitySummary.lastTransition
|
|
1579
|
+
? {
|
|
1580
|
+
...managedConversationSummary.continuitySummary.lastTransition,
|
|
1581
|
+
keyLabels: managedConversationSummary.continuitySummary.lastTransition.keyLabels.slice(),
|
|
1582
|
+
resolvedKeyLabels: managedConversationSummary.continuitySummary.lastTransition.resolvedKeyLabels.slice(),
|
|
1583
|
+
persistentKeyLabels: managedConversationSummary.continuitySummary.lastTransition.persistentKeyLabels.slice(),
|
|
1584
|
+
followUpActionIds: managedConversationSummary.continuitySummary.lastTransition.followUpActionIds.slice(),
|
|
1585
|
+
followUpActionLabels: managedConversationSummary.continuitySummary.lastTransition.followUpActionLabels.slice(),
|
|
1586
|
+
resolvedFollowUpActionIds: managedConversationSummary.continuitySummary.lastTransition.resolvedFollowUpActionIds.slice(),
|
|
1587
|
+
resolvedFollowUpActionLabels: managedConversationSummary.continuitySummary.lastTransition.resolvedFollowUpActionLabels.slice(),
|
|
1588
|
+
persistentFollowUpActionIds: managedConversationSummary.continuitySummary.lastTransition.persistentFollowUpActionIds.slice(),
|
|
1589
|
+
persistentFollowUpActionLabels: managedConversationSummary.continuitySummary.lastTransition.persistentFollowUpActionLabels.slice(),
|
|
1590
|
+
}
|
|
1591
|
+
: null,
|
|
1592
|
+
},
|
|
1593
|
+
},
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
function exportDiagnosticsReport(options = {}) {
|
|
1598
|
+
const format = trimString(options && options.format).toLowerCase();
|
|
1599
|
+
const runbookResolution = resolvePrimaryRunbookAction();
|
|
1600
|
+
const report = {
|
|
1601
|
+
generatedAt: nowIso(),
|
|
1602
|
+
snapshot: getDiagnosticsSnapshot(),
|
|
1603
|
+
trend: getDiagnosticsTrendSnapshot(),
|
|
1604
|
+
index: getDiagnosticsIndexSnapshot(),
|
|
1605
|
+
runbookLinks: cloneRunbookLinks(),
|
|
1606
|
+
primaryRunbookAction: runbookResolution.primaryRunbookAction,
|
|
1607
|
+
runbookActions: runbookResolution.runbookActions,
|
|
1608
|
+
};
|
|
1609
|
+
if (format === 'json') {
|
|
1610
|
+
return JSON.stringify(report, null, 2);
|
|
1611
|
+
}
|
|
1612
|
+
return report;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
function resolveCapabilityResultPreviewData(presentation, result) {
|
|
1616
|
+
const normalizedPresentation = trimString(presentation);
|
|
1617
|
+
if (!normalizedPresentation) {
|
|
1618
|
+
return null;
|
|
1619
|
+
}
|
|
1620
|
+
if (normalizedPresentation === 'learning_path_card') {
|
|
1621
|
+
return {
|
|
1622
|
+
kind: 'learning_path',
|
|
1623
|
+
masteryPathCount: Array.isArray(result && result.masteryPaths) ? result.masteryPaths.length : 0,
|
|
1624
|
+
divergencePathCount: Array.isArray(result && result.divergencePaths) ? result.divergencePaths.length : 0,
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
if (normalizedPresentation === 'study_session_card') {
|
|
1628
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
1629
|
+
? result.summary
|
|
1630
|
+
: {};
|
|
1631
|
+
return {
|
|
1632
|
+
kind: 'study_session',
|
|
1633
|
+
totalActions: Number.isFinite(Number(summary.totalActions)) ? Number(summary.totalActions) : 0,
|
|
1634
|
+
totalEstimatedMinutes: Number.isFinite(Number(summary.totalEstimatedMinutes))
|
|
1635
|
+
? Number(summary.totalEstimatedMinutes)
|
|
1636
|
+
: 0,
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
if (normalizedPresentation === 'query_trace_card') {
|
|
1640
|
+
const retrievalModes = Array.isArray(result && result.trace && result.trace.retrievalModes)
|
|
1641
|
+
? result.trace.retrievalModes
|
|
1642
|
+
: [];
|
|
1643
|
+
return {
|
|
1644
|
+
kind: 'query_trace',
|
|
1645
|
+
itemsCount: Array.isArray(result && result.items) ? result.items.length : 0,
|
|
1646
|
+
retrievalModesCount: retrievalModes.length,
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
if (normalizedPresentation === 'ingest_guardrail_card') {
|
|
1650
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
1651
|
+
? result.summary
|
|
1652
|
+
: {};
|
|
1653
|
+
return {
|
|
1654
|
+
kind: 'ingest_guardrail',
|
|
1655
|
+
status: trimString(result && result.status) || trimString(summary.status) || 'unknown',
|
|
1656
|
+
failedGates: Number.isFinite(Number(summary.failedGates)) ? Number(summary.failedGates) : 0,
|
|
1657
|
+
totalGates: Number.isFinite(Number(summary.totalGates)) ? Number(summary.totalGates) : 0,
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
if (normalizedPresentation === 'session_history_card') {
|
|
1661
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
1662
|
+
? result.summary
|
|
1663
|
+
: {};
|
|
1664
|
+
return {
|
|
1665
|
+
kind: 'session_history',
|
|
1666
|
+
totalRecords: Number.isFinite(Number(summary.totalRecords)) ? Number(summary.totalRecords) : 0,
|
|
1667
|
+
totalExecutedActions: Number.isFinite(Number(summary.totalExecutedActions))
|
|
1668
|
+
? Number(summary.totalExecutedActions)
|
|
1669
|
+
: 0,
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
if (normalizedPresentation === 'mastery_misconceptions_card') {
|
|
1673
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
1674
|
+
? result.summary
|
|
1675
|
+
: {};
|
|
1676
|
+
return {
|
|
1677
|
+
kind: 'mastery_misconceptions',
|
|
1678
|
+
trackedTags: Number.isFinite(Number(summary.trackedTags)) ? Number(summary.trackedTags) : 0,
|
|
1679
|
+
totalObservations: Number.isFinite(Number(summary.totalObservations))
|
|
1680
|
+
? Number(summary.totalObservations)
|
|
1681
|
+
: 0,
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
if (normalizedPresentation === 'learning_quality_snapshot_card') {
|
|
1685
|
+
const snapshot = result && result.snapshot && typeof result.snapshot === 'object'
|
|
1686
|
+
? result.snapshot
|
|
1687
|
+
: {};
|
|
1688
|
+
return {
|
|
1689
|
+
kind: 'learning_quality',
|
|
1690
|
+
retestPassRatePct: Number.isFinite(Number(snapshot.retestPassRatePct))
|
|
1691
|
+
? Number(Number(snapshot.retestPassRatePct).toFixed(1))
|
|
1692
|
+
: 0,
|
|
1693
|
+
misconceptionRecurrenceRatePct: Number.isFinite(Number(snapshot.misconceptionRecurrenceRatePct))
|
|
1694
|
+
? Number(Number(snapshot.misconceptionRecurrenceRatePct).toFixed(1))
|
|
1695
|
+
: 0,
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
if (normalizedPresentation === 'memory_policy_card') {
|
|
1699
|
+
return {
|
|
1700
|
+
kind: 'memory_policy',
|
|
1701
|
+
layer: trimString(result && result.layer) || 'session',
|
|
1702
|
+
operation: trimString(result && result.operation) || 'snapshot',
|
|
1703
|
+
entriesCount: Array.isArray(result && result.entries) ? result.entries.length : 0,
|
|
1704
|
+
mutatedCount: Number.isFinite(Number(result && result.mutatedCount))
|
|
1705
|
+
? Number(result && result.mutatedCount)
|
|
1706
|
+
: Array.isArray(result && result.entries) ? result.entries.length : 0,
|
|
1707
|
+
evictedCount: Number.isFinite(Number(result && result.evictedCount)) ? Number(result && result.evictedCount) : 0,
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
if (normalizedPresentation === 'tutor_action_card' || normalizedPresentation === 'assistant_message') {
|
|
1711
|
+
return {
|
|
1712
|
+
kind: 'message',
|
|
1713
|
+
message: trimString(result && result.message),
|
|
1714
|
+
};
|
|
1715
|
+
}
|
|
1716
|
+
return null;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
async function persistDiagnosticsReport(options = {}) {
|
|
1720
|
+
const endpoint = trimString(options && options.endpoint)
|
|
1721
|
+
|| '/api/knowledge/operator/agent-workspace-diagnostics/report';
|
|
1722
|
+
const source = trimString(options && options.source) || 'agent-workspace-runtime';
|
|
1723
|
+
const report = exportDiagnosticsReport();
|
|
1724
|
+
return requestJson(endpoint, {
|
|
1725
|
+
source,
|
|
1726
|
+
report,
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
function resolveUserId() {
|
|
1731
|
+
const fallback = trimString(options.defaultUserId) || 'agent_user_default';
|
|
1732
|
+
const candidate = trimString(dom.userIdInput && dom.userIdInput.value);
|
|
1733
|
+
return candidate || fallback;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
function appendMessage(role, text, meta = {}) {
|
|
1737
|
+
if (!dom.messages) {
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
const content = trimString(text);
|
|
1741
|
+
if (!content) {
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
const item = document.createElement('div');
|
|
1745
|
+
item.className = `agent-workspace-message agent-workspace-message--${role}`;
|
|
1746
|
+
item.textContent = content;
|
|
1747
|
+
dom.messages.appendChild(item);
|
|
1748
|
+
dom.messages.scrollTop = dom.messages.scrollHeight;
|
|
1749
|
+
recordTurn(role, content, meta);
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
function setBusy(nextBusy) {
|
|
1753
|
+
state.busy = Boolean(nextBusy);
|
|
1754
|
+
if (dom.sendButton) {
|
|
1755
|
+
dom.sendButton.disabled = state.busy;
|
|
1756
|
+
}
|
|
1757
|
+
if (dom.form) {
|
|
1758
|
+
dom.form.classList.toggle('is-busy', state.busy);
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
function findKnowledgePoint(atomId) {
|
|
1763
|
+
const normalized = trimString(atomId);
|
|
1764
|
+
if (!normalized) {
|
|
1765
|
+
return null;
|
|
1766
|
+
}
|
|
1767
|
+
return state.latestKnowledgePoints.find((point) => trimString(point.atomId) === normalized) || null;
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
function normalizeRuntimeGraphNode(node) {
|
|
1771
|
+
if (!node || typeof node !== 'object') {
|
|
1772
|
+
return null;
|
|
1773
|
+
}
|
|
1774
|
+
const id = trimString(node.id) || trimString(node.nodeId) || trimString(node.key);
|
|
1775
|
+
if (!id) {
|
|
1776
|
+
return null;
|
|
1777
|
+
}
|
|
1778
|
+
return {
|
|
1779
|
+
id,
|
|
1780
|
+
label: trimString(node.label) || trimString(node.title) || trimString(node.name) || id,
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
function resolveGraphViewApi() {
|
|
1785
|
+
if (globalScope.NoteConnectionGraphView && typeof globalScope.NoteConnectionGraphView === 'object') {
|
|
1786
|
+
return globalScope.NoteConnectionGraphView;
|
|
1787
|
+
}
|
|
1788
|
+
if (
|
|
1789
|
+
globalScope.window
|
|
1790
|
+
&& globalScope.window.NoteConnectionGraphView
|
|
1791
|
+
&& typeof globalScope.window.NoteConnectionGraphView === 'object'
|
|
1792
|
+
) {
|
|
1793
|
+
return globalScope.window.NoteConnectionGraphView;
|
|
1794
|
+
}
|
|
1795
|
+
return null;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
function resolveGraphTargetForKnowledgePoint(point, capability, preferredAtomId) {
|
|
1799
|
+
const request = capability && capability.request && typeof capability.request === 'object'
|
|
1800
|
+
? capability.request
|
|
1801
|
+
: {};
|
|
1802
|
+
const atomId = trimString(preferredAtomId) || trimString(request.atomId) || trimString(point && point.atomId);
|
|
1803
|
+
const title = trimString(point && point.title)
|
|
1804
|
+
|| trimString(point && point.label)
|
|
1805
|
+
|| trimString(point && point.name)
|
|
1806
|
+
|| trimString(request.title)
|
|
1807
|
+
|| atomId;
|
|
1808
|
+
const explicitGraphNodeId = trimString(point && point.graphNodeId)
|
|
1809
|
+
|| trimString(point && point.graphTargetId)
|
|
1810
|
+
|| trimString(request.graphNodeId)
|
|
1811
|
+
|| trimString(request.graphTargetId);
|
|
1812
|
+
const graphView = resolveGraphViewApi();
|
|
1813
|
+
if (graphView && typeof graphView.resolveNodeByKnowledgePoint === 'function') {
|
|
1814
|
+
try {
|
|
1815
|
+
const resolvedNode = normalizeRuntimeGraphNode(graphView.resolveNodeByKnowledgePoint({
|
|
1816
|
+
atomId,
|
|
1817
|
+
title,
|
|
1818
|
+
label: title,
|
|
1819
|
+
documentId: trimString(point && point.documentId) || trimString(request.documentId),
|
|
1820
|
+
sourcePath: trimString(point && point.sourcePath) || trimString(request.sourcePath),
|
|
1821
|
+
relationPath: Array.isArray(point && point.relationPath)
|
|
1822
|
+
? point.relationPath.map((edge) => ({ ...edge }))
|
|
1823
|
+
: [],
|
|
1824
|
+
capability: capability && typeof capability === 'object' ? { ...capability } : null,
|
|
1825
|
+
}));
|
|
1826
|
+
if (resolvedNode) {
|
|
1827
|
+
return {
|
|
1828
|
+
atomId,
|
|
1829
|
+
graphNodeId: resolvedNode.id,
|
|
1830
|
+
graphNodeLabel: resolvedNode.label,
|
|
1831
|
+
runtimeResolved: true,
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
} catch (error) {
|
|
1835
|
+
console.warn('[AgentWorkspace] graph target resolver rejected runtime knowledge point:', error);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
if (graphView && typeof graphView.resolveNodeById === 'function') {
|
|
1840
|
+
const candidates = [explicitGraphNodeId, atomId, title].map(trimString).filter(Boolean);
|
|
1841
|
+
for (const candidate of candidates) {
|
|
1842
|
+
try {
|
|
1843
|
+
const resolvedNode = normalizeRuntimeGraphNode(graphView.resolveNodeById(candidate));
|
|
1844
|
+
if (resolvedNode) {
|
|
1845
|
+
return {
|
|
1846
|
+
atomId,
|
|
1847
|
+
graphNodeId: resolvedNode.id,
|
|
1848
|
+
graphNodeLabel: resolvedNode.label,
|
|
1849
|
+
runtimeResolved: true,
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
} catch (error) {
|
|
1853
|
+
console.warn('[AgentWorkspace] graph node id resolver rejected runtime candidate:', error);
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
const fallbackGraphNodeId = explicitGraphNodeId || atomId;
|
|
1859
|
+
return {
|
|
1860
|
+
atomId,
|
|
1861
|
+
graphNodeId: fallbackGraphNodeId,
|
|
1862
|
+
graphNodeLabel: title || fallbackGraphNodeId,
|
|
1863
|
+
runtimeResolved: false,
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
function focusAtom(atomId, point, capability) {
|
|
1868
|
+
const normalizedAtomId = trimString(atomId);
|
|
1869
|
+
if (!normalizedAtomId) {
|
|
1870
|
+
throw new Error('Missing atomId for focus action.');
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
const graphTarget = resolveGraphTargetForKnowledgePoint(
|
|
1874
|
+
point || findKnowledgePoint(normalizedAtomId),
|
|
1875
|
+
capability,
|
|
1876
|
+
normalizedAtomId
|
|
1877
|
+
);
|
|
1878
|
+
const runtimeNodeId = trimString(graphTarget.graphNodeId) || normalizedAtomId;
|
|
1879
|
+
const graphView = resolveGraphViewApi();
|
|
1880
|
+
let opened = false;
|
|
1881
|
+
if (
|
|
1882
|
+
graphTarget.runtimeResolved
|
|
1883
|
+
&& graphView
|
|
1884
|
+
&& typeof graphView.openFocusModeById === 'function'
|
|
1885
|
+
) {
|
|
1886
|
+
opened = graphView.openFocusModeById(runtimeNodeId) === true;
|
|
1887
|
+
}
|
|
1888
|
+
if (!opened && typeof globalScope.focusOnNode === 'function') {
|
|
1889
|
+
globalScope.focusOnNode(runtimeNodeId);
|
|
1890
|
+
opened = true;
|
|
1891
|
+
} else if (typeof globalScope.enterFocusMode === 'function') {
|
|
1892
|
+
globalScope.enterFocusMode(runtimeNodeId);
|
|
1893
|
+
opened = true;
|
|
1894
|
+
}
|
|
1895
|
+
if (!opened) {
|
|
1896
|
+
throw new Error('Focus runtime is unavailable. Ensure app.js is loaded.');
|
|
1897
|
+
}
|
|
1898
|
+
state.latestFocusAtomId = normalizedAtomId;
|
|
1899
|
+
appendMessage(
|
|
1900
|
+
'system',
|
|
1901
|
+
getI18nText('agentWorkspace.messages.focusModeOpened', `Focus mode opened for ${graphTarget.graphNodeLabel || normalizedAtomId}.`, {
|
|
1902
|
+
atomId: graphTarget.graphNodeLabel || normalizedAtomId,
|
|
1903
|
+
})
|
|
1904
|
+
);
|
|
1905
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
function resolveCurrentPathAtomId() {
|
|
1909
|
+
return trimString(state.latestPathAtomId);
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
function hidePathDock() {
|
|
1913
|
+
const body = document.body;
|
|
1914
|
+
const pathContainer = document.getElementById('path-container');
|
|
1915
|
+
body.classList.remove(BODY_CLASS_PATH_VISIBLE);
|
|
1916
|
+
body.classList.remove(BODY_CLASS_PATH_FULLSCREEN);
|
|
1917
|
+
if (pathContainer) {
|
|
1918
|
+
pathContainer.classList.remove(PATH_DOCK_CLASS);
|
|
1919
|
+
pathContainer.style.display = 'none';
|
|
1920
|
+
}
|
|
1921
|
+
state.pathVisible = false;
|
|
1922
|
+
state.pathFullscreen = false;
|
|
1923
|
+
state.latestPathAtomId = '';
|
|
1924
|
+
state.latestPathRuntimeNodeId = '';
|
|
1925
|
+
state.latestPathRuntimeNodeLabel = '';
|
|
1926
|
+
refreshToolbarButtons();
|
|
1927
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
1928
|
+
if (globalScope.pathApp && typeof globalScope.pathApp.requestBridgeWindowVisibility === 'function') {
|
|
1929
|
+
void globalScope.pathApp.requestBridgeWindowVisibility(false, {
|
|
1930
|
+
waitMs: 900,
|
|
1931
|
+
reason: 'agent-workspace-hide-godot-future-path',
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
globalScope.dispatchEvent(new Event('resize'));
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
function refreshToolbarButtons() {
|
|
1938
|
+
if (dom.closePathButton) {
|
|
1939
|
+
dom.closePathButton.disabled = !state.pathVisible;
|
|
1940
|
+
}
|
|
1941
|
+
if (dom.pathFullscreenButton) {
|
|
1942
|
+
dom.pathFullscreenButton.disabled = !state.pathVisible;
|
|
1943
|
+
dom.pathFullscreenButton.textContent = getI18nText(
|
|
1944
|
+
'agentWorkspace.actions.focusGodotFuturePath',
|
|
1945
|
+
'Focus Godot Future Path'
|
|
1946
|
+
);
|
|
1947
|
+
}
|
|
1948
|
+
if (dom.foundationReadinessButton) {
|
|
1949
|
+
dom.foundationReadinessButton.textContent = getI18nText(
|
|
1950
|
+
'agentWorkspace.actions.openFoundationReadiness',
|
|
1951
|
+
'Foundation Readiness'
|
|
1952
|
+
);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
function togglePathFullscreen() {
|
|
1957
|
+
if (!state.pathVisible) {
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
state.pathFullscreen = false;
|
|
1961
|
+
document.body.classList.remove(BODY_CLASS_PATH_FULLSCREEN);
|
|
1962
|
+
if (globalScope.pathApp && typeof globalScope.pathApp.requestBridgeWindowVisibility === 'function') {
|
|
1963
|
+
void globalScope.pathApp.requestBridgeWindowVisibility(true, {
|
|
1964
|
+
waitMs: 900,
|
|
1965
|
+
reason: 'agent-workspace-focus-godot-future-path',
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1968
|
+
refreshToolbarButtons();
|
|
1969
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
1970
|
+
globalScope.dispatchEvent(new Event('resize'));
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
function resolvePathAtomId(preferredAtomId) {
|
|
1974
|
+
const preferred = trimString(preferredAtomId);
|
|
1975
|
+
if (preferred) {
|
|
1976
|
+
return preferred;
|
|
1977
|
+
}
|
|
1978
|
+
if (trimString(state.latestFocusAtomId)) {
|
|
1979
|
+
return state.latestFocusAtomId;
|
|
1980
|
+
}
|
|
1981
|
+
const firstPoint = state.latestKnowledgePoints[0];
|
|
1982
|
+
return trimString(firstPoint && firstPoint.atomId);
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
function openLearningPathDock(preferredAtomId, point, capability) {
|
|
1986
|
+
const atomId = resolvePathAtomId(preferredAtomId);
|
|
1987
|
+
const graphTarget = resolveGraphTargetForKnowledgePoint(point || findKnowledgePoint(atomId), capability, atomId);
|
|
1988
|
+
const runtimeNodeId = trimString(graphTarget.graphNodeId) || atomId;
|
|
1989
|
+
const futurePathConfig = {
|
|
1990
|
+
mode: 'diffusion',
|
|
1991
|
+
strategy: 'core',
|
|
1992
|
+
layout: 'orbital',
|
|
1993
|
+
targetId: runtimeNodeId,
|
|
1994
|
+
target_id: runtimeNodeId,
|
|
1995
|
+
targetIds: runtimeNodeId ? [runtimeNodeId] : [],
|
|
1996
|
+
focus_mode: true,
|
|
1997
|
+
};
|
|
1998
|
+
const pathApp = globalScope.pathApp && typeof globalScope.pathApp === 'object'
|
|
1999
|
+
? globalScope.pathApp
|
|
2000
|
+
: null;
|
|
2001
|
+
if (pathApp) {
|
|
2002
|
+
if (!pathApp.runtimeConfig || typeof pathApp.runtimeConfig !== 'object') {
|
|
2003
|
+
pathApp.runtimeConfig = {};
|
|
2004
|
+
}
|
|
2005
|
+
pathApp.runtimeConfig.mode = 'diffusion';
|
|
2006
|
+
pathApp.runtimeConfig.strategy = 'core';
|
|
2007
|
+
pathApp.runtimeConfig.layout = 'orbital';
|
|
2008
|
+
pathApp.runtimeConfig.targetId = runtimeNodeId;
|
|
2009
|
+
pathApp.runtimeConfig.targetIds = runtimeNodeId ? [runtimeNodeId] : [];
|
|
2010
|
+
pathApp.currentTargetId = runtimeNodeId;
|
|
2011
|
+
pathApp.currentTargetIds = runtimeNodeId ? [runtimeNodeId] : [];
|
|
2012
|
+
pathApp.centralNodeId = runtimeNodeId;
|
|
2013
|
+
}
|
|
2014
|
+
const pathModeApi = globalScope.NoteConnectionPathMode;
|
|
2015
|
+
if (pathModeApi && typeof pathModeApi.openGodotFuturePathById === 'function') {
|
|
2016
|
+
void pathModeApi.openGodotFuturePathById(runtimeNodeId, {
|
|
2017
|
+
config: futurePathConfig,
|
|
2018
|
+
source: 'agent-workspace-runtime',
|
|
2019
|
+
});
|
|
2020
|
+
} else if (pathApp) {
|
|
2021
|
+
if (!globalScope.__NC_AGENT_GODOT_FUTURE_PATH_INITIALIZED && typeof pathApp.init === 'function') {
|
|
2022
|
+
pathApp.init(runtimeNodeId || null);
|
|
2023
|
+
globalScope.__NC_AGENT_GODOT_FUTURE_PATH_INITIALIZED = true;
|
|
2024
|
+
}
|
|
2025
|
+
if (typeof pathApp.applyRemoteConfigure === 'function') {
|
|
2026
|
+
pathApp.applyRemoteConfigure(futurePathConfig);
|
|
2027
|
+
}
|
|
2028
|
+
if (typeof pathApp._sendBridgeMessage === 'function') {
|
|
2029
|
+
pathApp._sendBridgeMessage('configure', futurePathConfig);
|
|
2030
|
+
}
|
|
2031
|
+
if (typeof pathApp.triggerUpdate === 'function') {
|
|
2032
|
+
pathApp.triggerUpdate();
|
|
2033
|
+
}
|
|
2034
|
+
if (typeof pathApp.requestBridgeWindowVisibility === 'function') {
|
|
2035
|
+
void pathApp.requestBridgeWindowVisibility(true, {
|
|
2036
|
+
waitMs: 1200,
|
|
2037
|
+
reason: 'agent-workspace-open-godot-future-path',
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
} else {
|
|
2041
|
+
throw new Error('Godot Path Mode runtime is unavailable. Ensure path_app.js and app.js are loaded.');
|
|
2042
|
+
}
|
|
2043
|
+
if (atomId) {
|
|
2044
|
+
state.latestFocusAtomId = atomId;
|
|
2045
|
+
state.latestPathAtomId = atomId;
|
|
2046
|
+
state.latestPathRuntimeNodeId = runtimeNodeId || atomId;
|
|
2047
|
+
state.latestPathRuntimeNodeLabel = trimString(graphTarget.graphNodeLabel) || runtimeNodeId || atomId;
|
|
2048
|
+
}
|
|
2049
|
+
state.pathVisible = true;
|
|
2050
|
+
state.pathFullscreen = false;
|
|
2051
|
+
document.body.classList.remove(BODY_CLASS_PATH_VISIBLE);
|
|
2052
|
+
document.body.classList.remove(BODY_CLASS_PATH_FULLSCREEN);
|
|
2053
|
+
appendMessage(
|
|
2054
|
+
'system',
|
|
2055
|
+
getI18nText('agentWorkspace.messages.learningPathOpened', `Godot Future Path opened${runtimeNodeId ? ` for ${graphTarget.graphNodeLabel || runtimeNodeId}` : ''}.`, {
|
|
2056
|
+
atomId: graphTarget.graphNodeLabel || runtimeNodeId || '',
|
|
2057
|
+
})
|
|
2058
|
+
);
|
|
2059
|
+
refreshToolbarButtons();
|
|
2060
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
2061
|
+
globalScope.dispatchEvent(new Event('resize'));
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
function hydrateTutorOperationPlan(operationPlan) {
|
|
2065
|
+
const normalizedOperationId = trimString(operationPlan && operationPlan.operationId);
|
|
2066
|
+
if (normalizedOperationId !== 'execute_tutor_action') {
|
|
2067
|
+
return operationPlan;
|
|
2068
|
+
}
|
|
2069
|
+
const body = operationPlan && operationPlan.body && typeof operationPlan.body === 'object'
|
|
2070
|
+
? operationPlan.body
|
|
2071
|
+
: {};
|
|
2072
|
+
const actionKind = trimString(body.actionKind);
|
|
2073
|
+
if (actionKind !== 'analyze_answer') {
|
|
2074
|
+
return operationPlan;
|
|
2075
|
+
}
|
|
2076
|
+
const existingAnswer = trimString(body.answer);
|
|
2077
|
+
if (existingAnswer) {
|
|
2078
|
+
return operationPlan;
|
|
2079
|
+
}
|
|
2080
|
+
const atomId = trimString(body.atomId);
|
|
2081
|
+
const promptText = getI18nText(
|
|
2082
|
+
'agentWorkspace.messages.analyzeAnswerPrompt',
|
|
2083
|
+
`Enter learner answer to analyze for ${atomId || 'target atom'}:`,
|
|
2084
|
+
{ atomId: atomId || 'target atom' }
|
|
2085
|
+
);
|
|
2086
|
+
const promptFn = globalScope && typeof globalScope.prompt === 'function'
|
|
2087
|
+
? globalScope.prompt.bind(globalScope)
|
|
2088
|
+
: null;
|
|
2089
|
+
const collectedAnswer = promptFn ? trimString(promptFn(promptText) || '') : '';
|
|
2090
|
+
if (!collectedAnswer) {
|
|
2091
|
+
throw new Error(
|
|
2092
|
+
getI18nText(
|
|
2093
|
+
'agentWorkspace.messages.analyzeAnswerRequired',
|
|
2094
|
+
'Analyze answer requires a non-empty learner answer.'
|
|
2095
|
+
)
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2098
|
+
return {
|
|
2099
|
+
...operationPlan,
|
|
2100
|
+
body: {
|
|
2101
|
+
...body,
|
|
2102
|
+
answer: collectedAnswer,
|
|
2103
|
+
},
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
function hydrateMemoryPolicyOperationPlan(operationPlan) {
|
|
2108
|
+
const normalizedOperationId = trimString(operationPlan && operationPlan.operationId);
|
|
2109
|
+
if (normalizedOperationId !== 'apply_memory_policy') {
|
|
2110
|
+
return operationPlan;
|
|
2111
|
+
}
|
|
2112
|
+
const body = operationPlan && operationPlan.body && typeof operationPlan.body === 'object'
|
|
2113
|
+
? operationPlan.body
|
|
2114
|
+
: {};
|
|
2115
|
+
const operation = trimString(body.operation);
|
|
2116
|
+
if (operation !== 'write') {
|
|
2117
|
+
return operationPlan;
|
|
2118
|
+
}
|
|
2119
|
+
const existingEntries = Array.isArray(body.entries) ? body.entries : [];
|
|
2120
|
+
if (existingEntries.length > 0) {
|
|
2121
|
+
return operationPlan;
|
|
2122
|
+
}
|
|
2123
|
+
const promptConfig = operationPlan && operationPlan.promptConfig && typeof operationPlan.promptConfig === 'object'
|
|
2124
|
+
? operationPlan.promptConfig
|
|
2125
|
+
: {};
|
|
2126
|
+
if (trimString(promptConfig.kind) !== 'memory_write') {
|
|
2127
|
+
throw new Error('Memory write operation requires prompt configuration or request.memoryValue.');
|
|
2128
|
+
}
|
|
2129
|
+
const promptFn = globalScope && typeof globalScope.prompt === 'function'
|
|
2130
|
+
? globalScope.prompt.bind(globalScope)
|
|
2131
|
+
: null;
|
|
2132
|
+
const promptMessage = trimString(promptConfig.message)
|
|
2133
|
+
|| getI18nText(
|
|
2134
|
+
'agentWorkspace.messages.memoryWritePrompt',
|
|
2135
|
+
'Enter memory note to store:',
|
|
2136
|
+
{}
|
|
2137
|
+
);
|
|
2138
|
+
const collectedValue = promptFn ? trimString(promptFn(promptMessage) || '') : '';
|
|
2139
|
+
if (!collectedValue) {
|
|
2140
|
+
throw new Error(
|
|
2141
|
+
getI18nText(
|
|
2142
|
+
'agentWorkspace.messages.memoryWriteRequired',
|
|
2143
|
+
'Memory write requires a non-empty note.'
|
|
2144
|
+
)
|
|
2145
|
+
);
|
|
2146
|
+
}
|
|
2147
|
+
const entryTemplate = promptConfig.entryTemplate && typeof promptConfig.entryTemplate === 'object'
|
|
2148
|
+
? promptConfig.entryTemplate
|
|
2149
|
+
: {};
|
|
2150
|
+
const nowIso = new Date().toISOString();
|
|
2151
|
+
return {
|
|
2152
|
+
...operationPlan,
|
|
2153
|
+
body: {
|
|
2154
|
+
...body,
|
|
2155
|
+
entries: [
|
|
2156
|
+
{
|
|
2157
|
+
key: trimString(entryTemplate.key) || `conversation_note:${Date.now()}`,
|
|
2158
|
+
value: collectedValue,
|
|
2159
|
+
tags: resolveStringArray(entryTemplate.tags),
|
|
2160
|
+
references: resolveStringArray(entryTemplate.references),
|
|
2161
|
+
createdAt: nowIso,
|
|
2162
|
+
updatedAt: nowIso,
|
|
2163
|
+
},
|
|
2164
|
+
],
|
|
2165
|
+
},
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
async function executeCapability(capability, knowledgePoint) {
|
|
2170
|
+
const actionId = trimString(capability && capability.actionId);
|
|
2171
|
+
const request = capability && capability.request && typeof capability.request === 'object'
|
|
2172
|
+
? capability.request
|
|
2173
|
+
: {};
|
|
2174
|
+
const atomId = trimString(request.atomId) || trimString(knowledgePoint && knowledgePoint.atomId);
|
|
2175
|
+
if (actionId === 'open_focus_mode') {
|
|
2176
|
+
focusAtom(atomId, knowledgePoint, capability);
|
|
2177
|
+
recordCapabilityEvent({
|
|
2178
|
+
phase: 'frontend',
|
|
2179
|
+
status: 'success',
|
|
2180
|
+
actionId,
|
|
2181
|
+
atomId,
|
|
2182
|
+
});
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
let operationPlan;
|
|
2187
|
+
try {
|
|
2188
|
+
operationPlan = resolveOperationPlan(capability);
|
|
2189
|
+
operationPlan = hydrateTutorOperationPlan(operationPlan);
|
|
2190
|
+
operationPlan = hydrateMemoryPolicyOperationPlan(operationPlan);
|
|
2191
|
+
} catch (error) {
|
|
2192
|
+
const errorMessage = trimString(error && error.message);
|
|
2193
|
+
recordCapabilityEvent({
|
|
2194
|
+
phase: 'plan',
|
|
2195
|
+
status: 'failed',
|
|
2196
|
+
actionId,
|
|
2197
|
+
atomId,
|
|
2198
|
+
error: errorMessage,
|
|
2199
|
+
});
|
|
2200
|
+
recordFailure('executeCapability:plan', errorMessage);
|
|
2201
|
+
appendMessage(
|
|
2202
|
+
'assistant',
|
|
2203
|
+
getI18nText('agentWorkspace.messages.operationPlanFailed', 'Unable to build operation request.', {})
|
|
2204
|
+
);
|
|
2205
|
+
throw error;
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
const operationStartedAt = Date.now();
|
|
2209
|
+
const plannedMemoryLayer = operationPlan.operationId === 'apply_memory_policy'
|
|
2210
|
+
? normalizeMemoryPolicyLayerForDiagnostics(operationPlan.body && operationPlan.body.layer)
|
|
2211
|
+
: '';
|
|
2212
|
+
const plannedMemoryOperation = operationPlan.operationId === 'apply_memory_policy'
|
|
2213
|
+
? normalizeMemoryPolicyOperationForDiagnostics(operationPlan.body && operationPlan.body.operation)
|
|
2214
|
+
: '';
|
|
2215
|
+
const plannedManagedKeyLabels = operationPlan.operationId === 'apply_memory_policy'
|
|
2216
|
+
? resolveManagedConversationKeyLabels([
|
|
2217
|
+
...resolveStringArray(operationPlan.body && operationPlan.body.matchKeys),
|
|
2218
|
+
...resolveStringArray(operationPlan.body && operationPlan.body.keys),
|
|
2219
|
+
...(
|
|
2220
|
+
Array.isArray(operationPlan.body && operationPlan.body.entries)
|
|
2221
|
+
? operationPlan.body.entries
|
|
2222
|
+
.map((entry) => trimString(entry && entry.key))
|
|
2223
|
+
.filter((key) => key.length > 0)
|
|
2224
|
+
: []
|
|
2225
|
+
),
|
|
2226
|
+
])
|
|
2227
|
+
: [];
|
|
2228
|
+
recordCapabilityEvent({
|
|
2229
|
+
phase: 'request',
|
|
2230
|
+
status: 'pending',
|
|
2231
|
+
actionId,
|
|
2232
|
+
atomId,
|
|
2233
|
+
operationId: operationPlan.operationId,
|
|
2234
|
+
resultPresentation: operationPlan.resultPresentation,
|
|
2235
|
+
memoryLayer: plannedMemoryLayer,
|
|
2236
|
+
memoryOperation: plannedMemoryOperation,
|
|
2237
|
+
managedKeyLabels: plannedManagedKeyLabels,
|
|
2238
|
+
});
|
|
2239
|
+
|
|
2240
|
+
let result;
|
|
2241
|
+
try {
|
|
2242
|
+
result = await requestJson(operationPlan.endpoint, operationPlan.body);
|
|
2243
|
+
} catch (error) {
|
|
2244
|
+
const errorMessage = trimString(error && error.message);
|
|
2245
|
+
recordCapabilityEvent({
|
|
2246
|
+
phase: 'result',
|
|
2247
|
+
status: 'failed',
|
|
2248
|
+
actionId,
|
|
2249
|
+
atomId,
|
|
2250
|
+
operationId: operationPlan.operationId,
|
|
2251
|
+
resultPresentation: operationPlan.resultPresentation,
|
|
2252
|
+
durationMs: Date.now() - operationStartedAt,
|
|
2253
|
+
error: errorMessage,
|
|
2254
|
+
memoryLayer: plannedMemoryLayer,
|
|
2255
|
+
memoryOperation: plannedMemoryOperation,
|
|
2256
|
+
managedKeyLabels: plannedManagedKeyLabels,
|
|
2257
|
+
});
|
|
2258
|
+
recordFailure('executeCapability:request', errorMessage);
|
|
2259
|
+
throw error;
|
|
2260
|
+
}
|
|
2261
|
+
const resultFilter = result && result.filter && typeof result.filter === 'object'
|
|
2262
|
+
? result.filter
|
|
2263
|
+
: {};
|
|
2264
|
+
recordCapabilityEvent({
|
|
2265
|
+
phase: 'result',
|
|
2266
|
+
status: 'success',
|
|
2267
|
+
actionId,
|
|
2268
|
+
atomId,
|
|
2269
|
+
operationId: operationPlan.operationId,
|
|
2270
|
+
resultPresentation: operationPlan.resultPresentation,
|
|
2271
|
+
durationMs: Date.now() - operationStartedAt,
|
|
2272
|
+
memoryLayer: operationPlan.operationId === 'apply_memory_policy'
|
|
2273
|
+
? normalizeMemoryPolicyLayerForDiagnostics(result && result.layer) || plannedMemoryLayer
|
|
2274
|
+
: '',
|
|
2275
|
+
memoryOperation: operationPlan.operationId === 'apply_memory_policy'
|
|
2276
|
+
? normalizeMemoryPolicyOperationForDiagnostics(result && result.operation) || plannedMemoryOperation
|
|
2277
|
+
: '',
|
|
2278
|
+
managedKeyLabels: plannedManagedKeyLabels,
|
|
2279
|
+
matchedManagedKeyLabels: resolveManagedConversationKeyLabels(resultFilter && resultFilter.matchedKeys),
|
|
2280
|
+
missingManagedKeyLabels: resolveManagedConversationKeyLabels(resultFilter && resultFilter.missingKeys),
|
|
2281
|
+
resultPreview: resolveCapabilityResultPreviewData(operationPlan.resultPresentation, result),
|
|
2282
|
+
});
|
|
2283
|
+
const presentation = trimString(operationPlan.resultPresentation);
|
|
2284
|
+
|
|
2285
|
+
if (presentation === 'learning_path_card') {
|
|
2286
|
+
const masteryPathCount = Array.isArray(result.masteryPaths) ? result.masteryPaths.length : 0;
|
|
2287
|
+
const divergencePathCount = Array.isArray(result.divergencePaths) ? result.divergencePaths.length : 0;
|
|
2288
|
+
appendMessage(
|
|
2289
|
+
'assistant',
|
|
2290
|
+
getI18nText(
|
|
2291
|
+
'agentWorkspace.messages.learningPathBuilt',
|
|
2292
|
+
`Learning path generated (mastery ${masteryPathCount}, divergence ${divergencePathCount}).`,
|
|
2293
|
+
{ masteryPathCount, divergencePathCount }
|
|
2294
|
+
)
|
|
2295
|
+
);
|
|
2296
|
+
openLearningPathDock(atomId, knowledgePoint, capability);
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
if (presentation === 'tutor_action_card') {
|
|
2301
|
+
const tutorMessage = trimString(result && result.message);
|
|
2302
|
+
appendMessage(
|
|
2303
|
+
'assistant',
|
|
2304
|
+
tutorMessage || getI18nText('agentWorkspace.messages.tutorActionCompleted', 'Tutor action completed.', {})
|
|
2305
|
+
);
|
|
2306
|
+
return;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
if (presentation === 'study_session_card') {
|
|
2310
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
2311
|
+
? result.summary
|
|
2312
|
+
: {};
|
|
2313
|
+
const totalActions = Number(summary.totalActions);
|
|
2314
|
+
const totalEstimatedMinutes = Number(summary.totalEstimatedMinutes);
|
|
2315
|
+
appendMessage(
|
|
2316
|
+
'assistant',
|
|
2317
|
+
getI18nText(
|
|
2318
|
+
'agentWorkspace.messages.studySessionBuilt',
|
|
2319
|
+
`Study session built (${Number.isFinite(totalActions) ? totalActions : 0} actions, ${Number.isFinite(totalEstimatedMinutes) ? totalEstimatedMinutes : 0} min).`,
|
|
2320
|
+
{
|
|
2321
|
+
totalActions: Number.isFinite(totalActions) ? totalActions : 0,
|
|
2322
|
+
totalEstimatedMinutes: Number.isFinite(totalEstimatedMinutes) ? totalEstimatedMinutes : 0,
|
|
2323
|
+
}
|
|
2324
|
+
)
|
|
2325
|
+
);
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
if (presentation === 'query_trace_card') {
|
|
2330
|
+
const trace = result && result.trace && typeof result.trace === 'object'
|
|
2331
|
+
? result.trace
|
|
2332
|
+
: {};
|
|
2333
|
+
const itemsCount = Array.isArray(result && result.items) ? result.items.length : 0;
|
|
2334
|
+
const retrievalModes = Array.isArray(trace.retrievalModes) ? trace.retrievalModes.join(', ') : '';
|
|
2335
|
+
const vectorAcceleration = trace.vectorAcceleration && typeof trace.vectorAcceleration === 'object'
|
|
2336
|
+
? trace.vectorAcceleration
|
|
2337
|
+
: null;
|
|
2338
|
+
const vectorMode = vectorAcceleration ? trimString(vectorAcceleration.mode) : '';
|
|
2339
|
+
const vectorStatus = vectorAcceleration ? trimString(vectorAcceleration.status) : '';
|
|
2340
|
+
const vectorCandidateCount = vectorAcceleration ? Number(vectorAcceleration.candidateCount) : NaN;
|
|
2341
|
+
const vectorAccelerationSummary = vectorMode && vectorStatus
|
|
2342
|
+
? `${vectorMode}/${vectorStatus}${Number.isFinite(vectorCandidateCount) ? `/${vectorCandidateCount}` : ''}`
|
|
2343
|
+
: 'n/a';
|
|
2344
|
+
const latencyMs = Number(trace.latencyMs);
|
|
2345
|
+
const evidenceCoverageRatio = Number(trace.evidenceCoverageRatio);
|
|
2346
|
+
appendMessage(
|
|
2347
|
+
'assistant',
|
|
2348
|
+
getI18nText(
|
|
2349
|
+
'agentWorkspace.messages.queryTraceLoaded',
|
|
2350
|
+
`Query trace loaded (${itemsCount} hits, modes ${retrievalModes || 'n/a'}, vector ${vectorAccelerationSummary}, latency ${Number.isFinite(latencyMs) ? latencyMs : 0} ms, evidence ${Number.isFinite(evidenceCoverageRatio) ? evidenceCoverageRatio.toFixed(2) : '0.00'}).`,
|
|
2351
|
+
{
|
|
2352
|
+
itemsCount,
|
|
2353
|
+
retrievalModes: retrievalModes || 'n/a',
|
|
2354
|
+
vectorAcceleration: vectorAccelerationSummary,
|
|
2355
|
+
latencyMs: Number.isFinite(latencyMs) ? latencyMs : 0,
|
|
2356
|
+
evidenceCoverageRatio: Number.isFinite(evidenceCoverageRatio) ? evidenceCoverageRatio.toFixed(2) : '0.00',
|
|
2357
|
+
}
|
|
2358
|
+
)
|
|
2359
|
+
);
|
|
2360
|
+
return;
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
if (presentation === 'ingest_guardrail_card') {
|
|
2364
|
+
const gates = Array.isArray(result && result.gates) ? result.gates : [];
|
|
2365
|
+
const totalGates = gates.length;
|
|
2366
|
+
const failedGates = gates.filter((gate) => gate && gate.passed === false).length;
|
|
2367
|
+
const overallPassed = Boolean(result && result.overallPassed);
|
|
2368
|
+
appendMessage(
|
|
2369
|
+
'assistant',
|
|
2370
|
+
getI18nText(
|
|
2371
|
+
'agentWorkspace.messages.ingestGuardrailLoaded',
|
|
2372
|
+
`Ingest guardrails evaluated (${overallPassed ? 'pass' : 'fail'}): ${failedGates}/${totalGates} gates failed.`,
|
|
2373
|
+
{
|
|
2374
|
+
status: overallPassed ? 'pass' : 'fail',
|
|
2375
|
+
failedGates,
|
|
2376
|
+
totalGates,
|
|
2377
|
+
}
|
|
2378
|
+
)
|
|
2379
|
+
);
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
if (presentation === 'session_history_card') {
|
|
2384
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
2385
|
+
? result.summary
|
|
2386
|
+
: {};
|
|
2387
|
+
const totalRecords = Number(summary.totalRecords);
|
|
2388
|
+
const totalExecutedActions = Number(summary.totalExecutedActions);
|
|
2389
|
+
appendMessage(
|
|
2390
|
+
'assistant',
|
|
2391
|
+
getI18nText(
|
|
2392
|
+
'agentWorkspace.messages.sessionHistoryLoaded',
|
|
2393
|
+
`Session history loaded (${Number.isFinite(totalRecords) ? totalRecords : 0} sessions, ${Number.isFinite(totalExecutedActions) ? totalExecutedActions : 0} actions).`,
|
|
2394
|
+
{
|
|
2395
|
+
totalRecords: Number.isFinite(totalRecords) ? totalRecords : 0,
|
|
2396
|
+
totalExecutedActions: Number.isFinite(totalExecutedActions) ? totalExecutedActions : 0,
|
|
2397
|
+
}
|
|
2398
|
+
)
|
|
2399
|
+
);
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
if (presentation === 'mastery_misconceptions_card') {
|
|
2404
|
+
const summary = result && result.summary && typeof result.summary === 'object'
|
|
2405
|
+
? result.summary
|
|
2406
|
+
: {};
|
|
2407
|
+
const trackedTags = Number(summary.trackedTags);
|
|
2408
|
+
const totalObservations = Number(summary.totalObservations);
|
|
2409
|
+
const topItem = Array.isArray(result && result.items) && result.items.length > 0
|
|
2410
|
+
? result.items[0]
|
|
2411
|
+
: null;
|
|
2412
|
+
const topErrorTag = trimString(topItem && topItem.errorTag);
|
|
2413
|
+
appendMessage(
|
|
2414
|
+
'assistant',
|
|
2415
|
+
getI18nText(
|
|
2416
|
+
'agentWorkspace.messages.masteryMisconceptionsLoaded',
|
|
2417
|
+
`Mastery misconceptions loaded (${Number.isFinite(trackedTags) ? trackedTags : 0} tags, ${Number.isFinite(totalObservations) ? totalObservations : 0} observations, top "${topErrorTag || 'n/a'}").`,
|
|
2418
|
+
{
|
|
2419
|
+
trackedTags: Number.isFinite(trackedTags) ? trackedTags : 0,
|
|
2420
|
+
totalObservations: Number.isFinite(totalObservations) ? totalObservations : 0,
|
|
2421
|
+
topErrorTag: topErrorTag || 'n/a',
|
|
2422
|
+
}
|
|
2423
|
+
)
|
|
2424
|
+
);
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
if (presentation === 'learning_quality_snapshot_card') {
|
|
2429
|
+
const snapshot = result && result.snapshot && typeof result.snapshot === 'object'
|
|
2430
|
+
? result.snapshot
|
|
2431
|
+
: {};
|
|
2432
|
+
const retestPassRatePct = Number(snapshot.retestPassRatePct);
|
|
2433
|
+
const misconceptionRecurrenceRatePct = Number(snapshot.misconceptionRecurrenceRatePct);
|
|
2434
|
+
appendMessage(
|
|
2435
|
+
'assistant',
|
|
2436
|
+
getI18nText(
|
|
2437
|
+
'agentWorkspace.messages.learningQualitySnapshotLoaded',
|
|
2438
|
+
`Learning quality snapshot loaded (retest ${Number.isFinite(retestPassRatePct) ? retestPassRatePct.toFixed(1) : '0.0'}%, recurrence ${Number.isFinite(misconceptionRecurrenceRatePct) ? misconceptionRecurrenceRatePct.toFixed(1) : '0.0'}%).`,
|
|
2439
|
+
{
|
|
2440
|
+
retestPassRatePct: Number.isFinite(retestPassRatePct) ? retestPassRatePct.toFixed(1) : '0.0',
|
|
2441
|
+
misconceptionRecurrenceRatePct: Number.isFinite(misconceptionRecurrenceRatePct)
|
|
2442
|
+
? misconceptionRecurrenceRatePct.toFixed(1)
|
|
2443
|
+
: '0.0',
|
|
2444
|
+
}
|
|
2445
|
+
)
|
|
2446
|
+
);
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
if (presentation === 'memory_policy_card') {
|
|
2451
|
+
const stats = result && result.stats && typeof result.stats === 'object'
|
|
2452
|
+
? result.stats
|
|
2453
|
+
: {};
|
|
2454
|
+
const filter = result && result.filter && typeof result.filter === 'object'
|
|
2455
|
+
? result.filter
|
|
2456
|
+
: {};
|
|
2457
|
+
const entriesCount = Array.isArray(result && result.entries) ? result.entries.length : 0;
|
|
2458
|
+
const recommendedActionsCount = Array.isArray(result && result.recommendedActions)
|
|
2459
|
+
? result.recommendedActions.length
|
|
2460
|
+
: 0;
|
|
2461
|
+
const evictedCount = Number(result && result.evictedCount);
|
|
2462
|
+
const mutatedCount = Number(result && result.mutatedCount);
|
|
2463
|
+
const removedKeysCount = Array.isArray(result && result.removedKeys)
|
|
2464
|
+
? result.removedKeys.length
|
|
2465
|
+
: 0;
|
|
2466
|
+
const sessionCount = Number(stats.session);
|
|
2467
|
+
const unitCount = Number(stats.unit);
|
|
2468
|
+
const longTermCount = Number(stats.longTerm);
|
|
2469
|
+
const layer = trimString(result && result.layer) || 'session';
|
|
2470
|
+
const operation = trimString(result && result.operation) || 'snapshot';
|
|
2471
|
+
const targetedMatchKeys = resolveStringArray(filter && filter.matchKeys);
|
|
2472
|
+
const matchedKeys = resolveStringArray(filter && filter.matchedKeys);
|
|
2473
|
+
const missingKeys = resolveStringArray(filter && filter.missingKeys);
|
|
2474
|
+
const followUpActionsSummary = summarizeManagedMemoryFollowUpActions(missingKeys);
|
|
2475
|
+
if (operation === 'write') {
|
|
2476
|
+
appendMessage(
|
|
2477
|
+
'assistant',
|
|
2478
|
+
getI18nText(
|
|
2479
|
+
'agentWorkspace.messages.memoryWriteLoaded',
|
|
2480
|
+
`Memory updated (${layer}/${operation}): wrote ${Number.isFinite(mutatedCount) ? mutatedCount : entriesCount} entry, totals session ${Number.isFinite(sessionCount) ? sessionCount : 0}, unit ${Number.isFinite(unitCount) ? unitCount : 0}, long-term ${Number.isFinite(longTermCount) ? longTermCount : 0}.`,
|
|
2481
|
+
{
|
|
2482
|
+
layer,
|
|
2483
|
+
operation,
|
|
2484
|
+
mutatedCount: Number.isFinite(mutatedCount) ? mutatedCount : entriesCount,
|
|
2485
|
+
sessionCount: Number.isFinite(sessionCount) ? sessionCount : 0,
|
|
2486
|
+
unitCount: Number.isFinite(unitCount) ? unitCount : 0,
|
|
2487
|
+
longTermCount: Number.isFinite(longTermCount) ? longTermCount : 0,
|
|
2488
|
+
}
|
|
2489
|
+
)
|
|
2490
|
+
);
|
|
2491
|
+
return;
|
|
2492
|
+
}
|
|
2493
|
+
if (operation === 'evict') {
|
|
2494
|
+
appendMessage(
|
|
2495
|
+
'assistant',
|
|
2496
|
+
getI18nText(
|
|
2497
|
+
'agentWorkspace.messages.memoryEvictLoaded',
|
|
2498
|
+
`Memory eviction completed (${layer}/${operation}): removed ${Number.isFinite(evictedCount) ? evictedCount : 0} entries, targeted keys ${removedKeysCount}, totals session ${Number.isFinite(sessionCount) ? sessionCount : 0}, unit ${Number.isFinite(unitCount) ? unitCount : 0}, long-term ${Number.isFinite(longTermCount) ? longTermCount : 0}.`,
|
|
2499
|
+
{
|
|
2500
|
+
layer,
|
|
2501
|
+
operation,
|
|
2502
|
+
evictedCount: Number.isFinite(evictedCount) ? evictedCount : 0,
|
|
2503
|
+
removedKeysCount,
|
|
2504
|
+
sessionCount: Number.isFinite(sessionCount) ? sessionCount : 0,
|
|
2505
|
+
unitCount: Number.isFinite(unitCount) ? unitCount : 0,
|
|
2506
|
+
longTermCount: Number.isFinite(longTermCount) ? longTermCount : 0,
|
|
2507
|
+
}
|
|
2508
|
+
)
|
|
2509
|
+
);
|
|
2510
|
+
return;
|
|
2511
|
+
}
|
|
2512
|
+
if (operation === 'read' && targetedMatchKeys.length > 0) {
|
|
2513
|
+
appendMessage(
|
|
2514
|
+
'assistant',
|
|
2515
|
+
getI18nText(
|
|
2516
|
+
followUpActionsSummary
|
|
2517
|
+
? 'agentWorkspace.messages.memoryTargetedReadLoadedWithNext'
|
|
2518
|
+
: 'agentWorkspace.messages.memoryTargetedReadLoaded',
|
|
2519
|
+
followUpActionsSummary
|
|
2520
|
+
? `Memory targeted read loaded (${layer}/${operation}): present ${summarizeMemoryKeyLabels(matchedKeys)}, missing ${summarizeMemoryKeyLabels(missingKeys)}, next ${followUpActionsSummary}, totals session ${Number.isFinite(sessionCount) ? sessionCount : 0}, unit ${Number.isFinite(unitCount) ? unitCount : 0}, long-term ${Number.isFinite(longTermCount) ? longTermCount : 0}.`
|
|
2521
|
+
: `Memory targeted read loaded (${layer}/${operation}): present ${summarizeMemoryKeyLabels(matchedKeys)}, missing ${summarizeMemoryKeyLabels(missingKeys)}, totals session ${Number.isFinite(sessionCount) ? sessionCount : 0}, unit ${Number.isFinite(unitCount) ? unitCount : 0}, long-term ${Number.isFinite(longTermCount) ? longTermCount : 0}.`,
|
|
2522
|
+
{
|
|
2523
|
+
layer,
|
|
2524
|
+
operation,
|
|
2525
|
+
matchedKeysSummary: summarizeMemoryKeyLabels(matchedKeys),
|
|
2526
|
+
missingKeysSummary: summarizeMemoryKeyLabels(missingKeys),
|
|
2527
|
+
nextActionsSummary: followUpActionsSummary,
|
|
2528
|
+
sessionCount: Number.isFinite(sessionCount) ? sessionCount : 0,
|
|
2529
|
+
unitCount: Number.isFinite(unitCount) ? unitCount : 0,
|
|
2530
|
+
longTermCount: Number.isFinite(longTermCount) ? longTermCount : 0,
|
|
2531
|
+
}
|
|
2532
|
+
)
|
|
2533
|
+
);
|
|
2534
|
+
return;
|
|
2535
|
+
}
|
|
2536
|
+
appendMessage(
|
|
2537
|
+
'assistant',
|
|
2538
|
+
getI18nText(
|
|
2539
|
+
'agentWorkspace.messages.memoryPolicyLoaded',
|
|
2540
|
+
`Memory snapshot loaded (${layer}/${operation}): ${entriesCount} entries, evicted ${Number.isFinite(evictedCount) ? evictedCount : 0}, totals session ${Number.isFinite(sessionCount) ? sessionCount : 0}, unit ${Number.isFinite(unitCount) ? unitCount : 0}, long-term ${Number.isFinite(longTermCount) ? longTermCount : 0}, recommended ${recommendedActionsCount} actions.`,
|
|
2541
|
+
{
|
|
2542
|
+
layer,
|
|
2543
|
+
operation,
|
|
2544
|
+
entriesCount,
|
|
2545
|
+
recommendedActionsCount,
|
|
2546
|
+
evictedCount: Number.isFinite(evictedCount) ? evictedCount : 0,
|
|
2547
|
+
sessionCount: Number.isFinite(sessionCount) ? sessionCount : 0,
|
|
2548
|
+
unitCount: Number.isFinite(unitCount) ? unitCount : 0,
|
|
2549
|
+
longTermCount: Number.isFinite(longTermCount) ? longTermCount : 0,
|
|
2550
|
+
}
|
|
2551
|
+
)
|
|
2552
|
+
);
|
|
2553
|
+
return;
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
appendMessage(
|
|
2557
|
+
'assistant',
|
|
2558
|
+
trimString(result && result.message)
|
|
2559
|
+
|| getI18nText('agentWorkspace.messages.operationCompleted', 'Operation completed.', {})
|
|
2560
|
+
);
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
function resolveCapabilityLabel(capability) {
|
|
2564
|
+
if (!capability || typeof capability !== 'object') {
|
|
2565
|
+
return getI18nText('agentWorkspace.actions.unknown', 'Action');
|
|
2566
|
+
}
|
|
2567
|
+
const fallback = trimString(capability.label) || getI18nText('agentWorkspace.actions.unknown', 'Action');
|
|
2568
|
+
const labelKey = trimString(capability.labelKey);
|
|
2569
|
+
if (!labelKey) {
|
|
2570
|
+
return fallback;
|
|
2571
|
+
}
|
|
2572
|
+
return getI18nText(labelKey, fallback);
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
function findCapabilityByActionId(point, actionId) {
|
|
2576
|
+
const normalizedActionId = trimString(actionId);
|
|
2577
|
+
if (!normalizedActionId) {
|
|
2578
|
+
return null;
|
|
2579
|
+
}
|
|
2580
|
+
const capabilities = Array.isArray(point && point.capabilities) ? point.capabilities : [];
|
|
2581
|
+
return capabilities.find((capability) => trimString(capability && capability.actionId) === normalizedActionId) || null;
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
function appendPointActionFailure(capability, point, error) {
|
|
2585
|
+
const fallback = trimString(capability && capability.failure && capability.failure.fallbackMessage)
|
|
2586
|
+
|| getI18nText('agentWorkspace.messages.operationFailed', 'Operation failed.');
|
|
2587
|
+
appendMessage('assistant', fallback.replace('{title}', trimString(point && point.title) || trimString(point && point.atomId)));
|
|
2588
|
+
console.error('[AgentWorkspace] capability execution failed:', error);
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
async function runCapabilityAction(capability, point) {
|
|
2592
|
+
try {
|
|
2593
|
+
setBusy(true);
|
|
2594
|
+
await executeCapability(capability, point);
|
|
2595
|
+
} catch (error) {
|
|
2596
|
+
appendPointActionFailure(capability, point, error);
|
|
2597
|
+
} finally {
|
|
2598
|
+
setBusy(false);
|
|
2599
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
async function runFallbackPointAction(actionId, point) {
|
|
2604
|
+
const normalizedActionId = trimString(actionId);
|
|
2605
|
+
try {
|
|
2606
|
+
setBusy(true);
|
|
2607
|
+
if (normalizedActionId === 'open_focus_mode') {
|
|
2608
|
+
focusKnowledgePoint(point);
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
if (normalizedActionId === 'open_learning_path') {
|
|
2612
|
+
openLearningPathDock(trimString(point && point.atomId), point);
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2615
|
+
throw new Error(`Unsupported point action "${normalizedActionId || '<empty>'}".`);
|
|
2616
|
+
} catch (error) {
|
|
2617
|
+
appendPointActionFailure(null, point, error);
|
|
2618
|
+
} finally {
|
|
2619
|
+
setBusy(false);
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
function triggerPointAction(actionId, point) {
|
|
2624
|
+
const capability = findCapabilityByActionId(point, actionId);
|
|
2625
|
+
if (capability) {
|
|
2626
|
+
void runCapabilityAction(capability, point);
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2629
|
+
void runFallbackPointAction(actionId, point);
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
function createPointActionButton(label, onClick) {
|
|
2633
|
+
const button = document.createElement('button');
|
|
2634
|
+
button.type = 'button';
|
|
2635
|
+
button.className = 'agent-workspace-action-button';
|
|
2636
|
+
button.textContent = trimString(label) || getI18nText('agentWorkspace.actions.unknown', 'Action');
|
|
2637
|
+
button.addEventListener('click', (event) => {
|
|
2638
|
+
event.preventDefault();
|
|
2639
|
+
event.stopPropagation();
|
|
2640
|
+
onClick();
|
|
2641
|
+
});
|
|
2642
|
+
return button;
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
function appendPointIdentity(container, point) {
|
|
2646
|
+
const title = document.createElement('h4');
|
|
2647
|
+
title.className = 'agent-workspace-point-title';
|
|
2648
|
+
title.textContent = trimString(point && point.title) || trimString(point && point.atomId) || 'Untitled';
|
|
2649
|
+
container.appendChild(title);
|
|
2650
|
+
|
|
2651
|
+
const snippetText = trimString(point && point.snippet);
|
|
2652
|
+
if (snippetText) {
|
|
2653
|
+
const snippet = document.createElement('p');
|
|
2654
|
+
snippet.className = 'agent-workspace-point-snippet';
|
|
2655
|
+
snippet.textContent = snippetText;
|
|
2656
|
+
container.appendChild(snippet);
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
const meta = document.createElement('div');
|
|
2660
|
+
meta.className = 'agent-workspace-point-meta';
|
|
2661
|
+
const score = Number(point && point.score);
|
|
2662
|
+
meta.textContent = Number.isFinite(score)
|
|
2663
|
+
? `${getI18nText('agentWorkspace.labels.score', 'Score')}: ${score.toFixed(3)}`
|
|
2664
|
+
: '';
|
|
2665
|
+
if (meta.textContent) {
|
|
2666
|
+
container.appendChild(meta);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
function createStatusBadge(label, extraClassName = '') {
|
|
2671
|
+
const badge = document.createElement('span');
|
|
2672
|
+
badge.className = extraClassName
|
|
2673
|
+
? `agent-workspace-status-badge ${extraClassName}`
|
|
2674
|
+
: 'agent-workspace-status-badge';
|
|
2675
|
+
badge.textContent = label;
|
|
2676
|
+
return badge;
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
function resolveActivePointContinuity(point) {
|
|
2680
|
+
const activeAtomId = trimString(point && point.atomId);
|
|
2681
|
+
const pathAtomId = resolveCurrentPathAtomId();
|
|
2682
|
+
if (!activeAtomId) {
|
|
2683
|
+
return {
|
|
2684
|
+
message: '',
|
|
2685
|
+
showPathBadge: false,
|
|
2686
|
+
pathBadgeLabel: '',
|
|
2687
|
+
};
|
|
2688
|
+
}
|
|
2689
|
+
if (!state.pathVisible || !pathAtomId) {
|
|
2690
|
+
return {
|
|
2691
|
+
message: getI18nText(
|
|
2692
|
+
'agentWorkspace.messages.activeAtomPathInactive',
|
|
2693
|
+
'Focus is ready for {atomId}. Open Learning Path to launch Godot Future Path for this atom.',
|
|
2694
|
+
{ atomId: activeAtomId }
|
|
2695
|
+
),
|
|
2696
|
+
showPathBadge: false,
|
|
2697
|
+
pathBadgeLabel: '',
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
if (pathAtomId === activeAtomId) {
|
|
2701
|
+
return {
|
|
2702
|
+
message: getI18nText(
|
|
2703
|
+
'agentWorkspace.messages.activeAtomFuturePathAligned',
|
|
2704
|
+
'Focus and Godot Future Path target are aligned on {atomId}.',
|
|
2705
|
+
{ atomId: activeAtomId }
|
|
2706
|
+
),
|
|
2707
|
+
showPathBadge: true,
|
|
2708
|
+
pathBadgeLabel: getI18nText('agentWorkspace.labels.godotFuturePathActive', 'Future Path'),
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
return {
|
|
2712
|
+
message: getI18nText(
|
|
2713
|
+
'agentWorkspace.messages.activeAtomFuturePathDrifted',
|
|
2714
|
+
'Focus is on {atomId}. Godot Future Path is still targeted at {pathAtomId}. Reopen Learning Path to realign.',
|
|
2715
|
+
{
|
|
2716
|
+
atomId: activeAtomId,
|
|
2717
|
+
pathAtomId,
|
|
2718
|
+
}
|
|
2719
|
+
),
|
|
2720
|
+
showPathBadge: true,
|
|
2721
|
+
pathBadgeLabel: getI18nText('agentWorkspace.labels.godotFuturePathPinned', 'Future Path Pinned'),
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
function appendActivePointStatus(container, point) {
|
|
2726
|
+
const normalizedAtomId = trimString(point && point.atomId);
|
|
2727
|
+
if (!normalizedAtomId) {
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2730
|
+
const continuity = resolveActivePointContinuity(point);
|
|
2731
|
+
const badges = document.createElement('div');
|
|
2732
|
+
badges.className = 'agent-workspace-status-badges';
|
|
2733
|
+
badges.appendChild(createStatusBadge(
|
|
2734
|
+
getI18nText('agentWorkspace.labels.active', 'Active')
|
|
2735
|
+
));
|
|
2736
|
+
badges.appendChild(createStatusBadge(
|
|
2737
|
+
getI18nText('agentWorkspace.labels.focusReady', 'Focus Ready')
|
|
2738
|
+
));
|
|
2739
|
+
if (continuity.showPathBadge && continuity.pathBadgeLabel) {
|
|
2740
|
+
badges.appendChild(createStatusBadge(
|
|
2741
|
+
continuity.pathBadgeLabel
|
|
2742
|
+
));
|
|
2743
|
+
}
|
|
2744
|
+
container.appendChild(badges);
|
|
2745
|
+
if (continuity.message) {
|
|
2746
|
+
const note = document.createElement('p');
|
|
2747
|
+
note.className = 'agent-workspace-active-point-note';
|
|
2748
|
+
note.textContent = continuity.message;
|
|
2749
|
+
container.appendChild(note);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
function resolveActivePointCapabilities(point) {
|
|
2754
|
+
const capabilities = Array.isArray(point && point.capabilities) ? point.capabilities : [];
|
|
2755
|
+
return capabilities
|
|
2756
|
+
.filter((capability) => {
|
|
2757
|
+
const actionId = trimString(capability && capability.actionId);
|
|
2758
|
+
return actionId && actionId !== 'open_focus_mode' && actionId !== 'open_learning_path';
|
|
2759
|
+
})
|
|
2760
|
+
.slice(0, MAX_ACTIVE_POINT_CONTEXTUAL_ACTIONS);
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
function resolveCapabilityCategory(capability) {
|
|
2764
|
+
const actionId = trimString(capability && capability.actionId);
|
|
2765
|
+
if (!actionId) {
|
|
2766
|
+
return 'other';
|
|
2767
|
+
}
|
|
2768
|
+
if (STUDY_LOOP_ACTION_IDS.includes(actionId)) {
|
|
2769
|
+
return 'study';
|
|
2770
|
+
}
|
|
2771
|
+
if (MEMORY_ACTION_IDS.includes(actionId)) {
|
|
2772
|
+
return 'memory';
|
|
2773
|
+
}
|
|
2774
|
+
if (actionId.startsWith('inspect_') || actionId.startsWith('compare_')) {
|
|
2775
|
+
return 'diagnostic';
|
|
2776
|
+
}
|
|
2777
|
+
return 'other';
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
function resolveActivePointCapabilitySummary(point) {
|
|
2781
|
+
const capabilities = Array.isArray(point && point.capabilities) ? point.capabilities : [];
|
|
2782
|
+
return capabilities.reduce((summary, capability) => {
|
|
2783
|
+
const category = resolveCapabilityCategory(capability);
|
|
2784
|
+
if (category === 'study') {
|
|
2785
|
+
summary.study.push(capability);
|
|
2786
|
+
} else if (category === 'memory') {
|
|
2787
|
+
summary.memory.push(capability);
|
|
2788
|
+
} else if (category === 'diagnostic') {
|
|
2789
|
+
summary.diagnostic.push(capability);
|
|
2790
|
+
} else {
|
|
2791
|
+
summary.other.push(capability);
|
|
2792
|
+
}
|
|
2793
|
+
return summary;
|
|
2794
|
+
}, {
|
|
2795
|
+
study: [],
|
|
2796
|
+
memory: [],
|
|
2797
|
+
diagnostic: [],
|
|
2798
|
+
other: [],
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
function resolveLatestCapabilityEventForAtom(atomId, category) {
|
|
2803
|
+
const normalizedAtomId = trimString(atomId);
|
|
2804
|
+
if (!normalizedAtomId) {
|
|
2805
|
+
return null;
|
|
2806
|
+
}
|
|
2807
|
+
for (let index = diagnostics.capabilityEvents.length - 1; index >= 0; index -= 1) {
|
|
2808
|
+
const event = diagnostics.capabilityEvents[index];
|
|
2809
|
+
if (trimString(event && event.atomId) !== normalizedAtomId) {
|
|
2810
|
+
continue;
|
|
2811
|
+
}
|
|
2812
|
+
if (trimString(event && event.status) !== 'success') {
|
|
2813
|
+
continue;
|
|
2814
|
+
}
|
|
2815
|
+
if (trimString(event && event.phase) === 'request') {
|
|
2816
|
+
continue;
|
|
2817
|
+
}
|
|
2818
|
+
if (category && resolveCapabilityCategory({ actionId: event && event.actionId }) !== category) {
|
|
2819
|
+
continue;
|
|
2820
|
+
}
|
|
2821
|
+
return event;
|
|
2822
|
+
}
|
|
2823
|
+
return null;
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
function resolveRecentCapabilityEventsForAtom(atomId, limit = 3) {
|
|
2827
|
+
const normalizedAtomId = trimString(atomId);
|
|
2828
|
+
const boundedLimit = Math.max(1, Math.floor(Number(limit) || 3));
|
|
2829
|
+
if (!normalizedAtomId) {
|
|
2830
|
+
return [];
|
|
2831
|
+
}
|
|
2832
|
+
const events = [];
|
|
2833
|
+
for (let index = diagnostics.capabilityEvents.length - 1; index >= 0; index -= 1) {
|
|
2834
|
+
const event = diagnostics.capabilityEvents[index];
|
|
2835
|
+
const actionId = trimString(event && event.actionId);
|
|
2836
|
+
const phase = trimString(event && event.phase);
|
|
2837
|
+
const operationId = trimString(event && event.operationId);
|
|
2838
|
+
if (trimString(event && event.atomId) !== normalizedAtomId) {
|
|
2839
|
+
continue;
|
|
2840
|
+
}
|
|
2841
|
+
if (trimString(event && event.status) !== 'success') {
|
|
2842
|
+
continue;
|
|
2843
|
+
}
|
|
2844
|
+
if (!actionId || actionId === 'open_focus_mode') {
|
|
2845
|
+
continue;
|
|
2846
|
+
}
|
|
2847
|
+
if (actionId === 'open_learning_path' && !operationId) {
|
|
2848
|
+
continue;
|
|
2849
|
+
}
|
|
2850
|
+
if (phase === 'request' || phase === 'plan') {
|
|
2851
|
+
continue;
|
|
2852
|
+
}
|
|
2853
|
+
events.push(event);
|
|
2854
|
+
if (events.length >= boundedLimit) {
|
|
2855
|
+
break;
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
return events;
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
function resolveCapabilityEventPreviewText(event) {
|
|
2862
|
+
const preview = event && event.resultPreview && typeof event.resultPreview === 'object'
|
|
2863
|
+
? event.resultPreview
|
|
2864
|
+
: null;
|
|
2865
|
+
if (!preview) {
|
|
2866
|
+
return '';
|
|
2867
|
+
}
|
|
2868
|
+
const kind = trimString(preview.kind);
|
|
2869
|
+
if (kind === 'learning_path') {
|
|
2870
|
+
return getI18nText(
|
|
2871
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewLearningPath',
|
|
2872
|
+
'mastery {masteryPathCount} divergence {divergencePathCount}',
|
|
2873
|
+
{
|
|
2874
|
+
masteryPathCount: Number.isFinite(Number(preview.masteryPathCount))
|
|
2875
|
+
? Number(preview.masteryPathCount)
|
|
2876
|
+
: 0,
|
|
2877
|
+
divergencePathCount: Number.isFinite(Number(preview.divergencePathCount))
|
|
2878
|
+
? Number(preview.divergencePathCount)
|
|
2879
|
+
: 0,
|
|
2880
|
+
}
|
|
2881
|
+
);
|
|
2882
|
+
}
|
|
2883
|
+
if (kind === 'study_session') {
|
|
2884
|
+
return getI18nText(
|
|
2885
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewStudySession',
|
|
2886
|
+
'{totalActions} actions {totalEstimatedMinutes} min',
|
|
2887
|
+
{
|
|
2888
|
+
totalActions: Number.isFinite(Number(preview.totalActions)) ? Number(preview.totalActions) : 0,
|
|
2889
|
+
totalEstimatedMinutes: Number.isFinite(Number(preview.totalEstimatedMinutes))
|
|
2890
|
+
? Number(preview.totalEstimatedMinutes)
|
|
2891
|
+
: 0,
|
|
2892
|
+
}
|
|
2893
|
+
);
|
|
2894
|
+
}
|
|
2895
|
+
if (kind === 'memory_policy') {
|
|
2896
|
+
const operation = trimString(preview.operation) || 'snapshot';
|
|
2897
|
+
if (operation === 'write') {
|
|
2898
|
+
return getI18nText(
|
|
2899
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewMemoryWrite',
|
|
2900
|
+
'{layer}/{operation} {mutatedCount} written',
|
|
2901
|
+
{
|
|
2902
|
+
layer: trimString(preview.layer) || 'session',
|
|
2903
|
+
operation,
|
|
2904
|
+
mutatedCount: Number.isFinite(Number(preview.mutatedCount)) ? Number(preview.mutatedCount) : 0,
|
|
2905
|
+
}
|
|
2906
|
+
);
|
|
2907
|
+
}
|
|
2908
|
+
if (operation === 'evict') {
|
|
2909
|
+
return getI18nText(
|
|
2910
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewMemoryEvict',
|
|
2911
|
+
'{layer}/{operation} {evictedCount} evicted',
|
|
2912
|
+
{
|
|
2913
|
+
layer: trimString(preview.layer) || 'session',
|
|
2914
|
+
operation,
|
|
2915
|
+
evictedCount: Number.isFinite(Number(preview.evictedCount)) ? Number(preview.evictedCount) : 0,
|
|
2916
|
+
}
|
|
2917
|
+
);
|
|
2918
|
+
}
|
|
2919
|
+
return getI18nText(
|
|
2920
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewMemoryPolicy',
|
|
2921
|
+
'{layer}/{operation} {entriesCount} entry',
|
|
2922
|
+
{
|
|
2923
|
+
layer: trimString(preview.layer) || 'session',
|
|
2924
|
+
operation,
|
|
2925
|
+
entriesCount: Number.isFinite(Number(preview.entriesCount)) ? Number(preview.entriesCount) : 0,
|
|
2926
|
+
}
|
|
2927
|
+
);
|
|
2928
|
+
}
|
|
2929
|
+
if (kind === 'query_trace') {
|
|
2930
|
+
return getI18nText(
|
|
2931
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewQueryTrace',
|
|
2932
|
+
'{itemsCount} hits {retrievalModesCount} modes',
|
|
2933
|
+
{
|
|
2934
|
+
itemsCount: Number.isFinite(Number(preview.itemsCount)) ? Number(preview.itemsCount) : 0,
|
|
2935
|
+
retrievalModesCount: Number.isFinite(Number(preview.retrievalModesCount))
|
|
2936
|
+
? Number(preview.retrievalModesCount)
|
|
2937
|
+
: 0,
|
|
2938
|
+
}
|
|
2939
|
+
);
|
|
2940
|
+
}
|
|
2941
|
+
if (kind === 'ingest_guardrail') {
|
|
2942
|
+
return getI18nText(
|
|
2943
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewIngestGuardrail',
|
|
2944
|
+
'{status} {failedGates}/{totalGates} failed',
|
|
2945
|
+
{
|
|
2946
|
+
status: trimString(preview.status) || 'unknown',
|
|
2947
|
+
failedGates: Number.isFinite(Number(preview.failedGates)) ? Number(preview.failedGates) : 0,
|
|
2948
|
+
totalGates: Number.isFinite(Number(preview.totalGates)) ? Number(preview.totalGates) : 0,
|
|
2949
|
+
}
|
|
2950
|
+
);
|
|
2951
|
+
}
|
|
2952
|
+
if (kind === 'session_history') {
|
|
2953
|
+
return getI18nText(
|
|
2954
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewSessionHistory',
|
|
2955
|
+
'{totalRecords} sessions {totalExecutedActions} actions',
|
|
2956
|
+
{
|
|
2957
|
+
totalRecords: Number.isFinite(Number(preview.totalRecords)) ? Number(preview.totalRecords) : 0,
|
|
2958
|
+
totalExecutedActions: Number.isFinite(Number(preview.totalExecutedActions))
|
|
2959
|
+
? Number(preview.totalExecutedActions)
|
|
2960
|
+
: 0,
|
|
2961
|
+
}
|
|
2962
|
+
);
|
|
2963
|
+
}
|
|
2964
|
+
if (kind === 'mastery_misconceptions') {
|
|
2965
|
+
return getI18nText(
|
|
2966
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewMasteryMisconceptions',
|
|
2967
|
+
'{trackedTags} tags {totalObservations} observations',
|
|
2968
|
+
{
|
|
2969
|
+
trackedTags: Number.isFinite(Number(preview.trackedTags)) ? Number(preview.trackedTags) : 0,
|
|
2970
|
+
totalObservations: Number.isFinite(Number(preview.totalObservations))
|
|
2971
|
+
? Number(preview.totalObservations)
|
|
2972
|
+
: 0,
|
|
2973
|
+
}
|
|
2974
|
+
);
|
|
2975
|
+
}
|
|
2976
|
+
if (kind === 'learning_quality') {
|
|
2977
|
+
return getI18nText(
|
|
2978
|
+
'agentWorkspace.messages.currentAtomHistoryPreviewLearningQuality',
|
|
2979
|
+
'retest {retestPassRatePct}% recurrence {misconceptionRecurrenceRatePct}%',
|
|
2980
|
+
{
|
|
2981
|
+
retestPassRatePct: Number.isFinite(Number(preview.retestPassRatePct))
|
|
2982
|
+
? Number(preview.retestPassRatePct).toFixed(1)
|
|
2983
|
+
: '0.0',
|
|
2984
|
+
misconceptionRecurrenceRatePct: Number.isFinite(Number(preview.misconceptionRecurrenceRatePct))
|
|
2985
|
+
? Number(preview.misconceptionRecurrenceRatePct).toFixed(1)
|
|
2986
|
+
: '0.0',
|
|
2987
|
+
}
|
|
2988
|
+
);
|
|
2989
|
+
}
|
|
2990
|
+
if (kind === 'message') {
|
|
2991
|
+
return trimString(preview.message);
|
|
2992
|
+
}
|
|
2993
|
+
return '';
|
|
2994
|
+
}
|
|
2995
|
+
|
|
2996
|
+
function resolveExpandedHistoryEventIdForAtom(atomId) {
|
|
2997
|
+
const normalizedAtomId = trimString(atomId);
|
|
2998
|
+
if (!normalizedAtomId) {
|
|
2999
|
+
return '';
|
|
3000
|
+
}
|
|
3001
|
+
return trimString(state.expandedHistoryEventIdsByAtom[normalizedAtomId]);
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
function toggleHistoryEventDetails(atomId, eventId) {
|
|
3005
|
+
const normalizedAtomId = trimString(atomId);
|
|
3006
|
+
const normalizedEventId = trimString(eventId);
|
|
3007
|
+
if (!normalizedAtomId || !normalizedEventId) {
|
|
3008
|
+
return;
|
|
3009
|
+
}
|
|
3010
|
+
const currentExpandedEventId = resolveExpandedHistoryEventIdForAtom(normalizedAtomId);
|
|
3011
|
+
if (currentExpandedEventId === normalizedEventId) {
|
|
3012
|
+
delete state.expandedHistoryEventIdsByAtom[normalizedAtomId];
|
|
3013
|
+
} else {
|
|
3014
|
+
state.expandedHistoryEventIdsByAtom[normalizedAtomId] = normalizedEventId;
|
|
3015
|
+
}
|
|
3016
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
function appendHistoryDetailLine(container, label, value) {
|
|
3020
|
+
const normalizedValue = trimString(value);
|
|
3021
|
+
if (!container || !label || !normalizedValue) {
|
|
3022
|
+
return;
|
|
3023
|
+
}
|
|
3024
|
+
const line = document.createElement('p');
|
|
3025
|
+
line.className = 'agent-workspace-history-detail-line';
|
|
3026
|
+
line.textContent = `${label}: ${normalizedValue}`;
|
|
3027
|
+
container.appendChild(line);
|
|
3028
|
+
}
|
|
3029
|
+
|
|
3030
|
+
function resolvePointActionLabelByActionId(point, actionId) {
|
|
3031
|
+
const capability = findCapabilityByActionId(point, actionId);
|
|
3032
|
+
if (capability) {
|
|
3033
|
+
return resolveCapabilityLabel(capability);
|
|
3034
|
+
}
|
|
3035
|
+
if (trimString(actionId) === 'open_focus_mode') {
|
|
3036
|
+
return getI18nText('agentWorkspace.actions.openFocusMode', 'Focus');
|
|
3037
|
+
}
|
|
3038
|
+
if (trimString(actionId) === 'open_learning_path') {
|
|
3039
|
+
return getI18nText('agentWorkspace.actions.openLearningPath', 'Learning Path');
|
|
3040
|
+
}
|
|
3041
|
+
return trimString(actionId) || getI18nText('agentWorkspace.actions.unknown', 'Action');
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
function isFallbackPointActionId(actionId) {
|
|
3045
|
+
const normalizedActionId = trimString(actionId);
|
|
3046
|
+
return normalizedActionId === 'open_focus_mode' || normalizedActionId === 'open_learning_path';
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
function canTriggerPointActionByActionId(point, actionId) {
|
|
3050
|
+
const normalizedActionId = trimString(actionId);
|
|
3051
|
+
if (!normalizedActionId) {
|
|
3052
|
+
return false;
|
|
3053
|
+
}
|
|
3054
|
+
if (findCapabilityByActionId(point, normalizedActionId)) {
|
|
3055
|
+
return true;
|
|
3056
|
+
}
|
|
3057
|
+
return isFallbackPointActionId(normalizedActionId);
|
|
3058
|
+
}
|
|
3059
|
+
|
|
3060
|
+
function resolvePointActionAvailabilityKind(point, actionId) {
|
|
3061
|
+
const normalizedActionId = trimString(actionId);
|
|
3062
|
+
if (!normalizedActionId) {
|
|
3063
|
+
return '';
|
|
3064
|
+
}
|
|
3065
|
+
if (findCapabilityByActionId(point, normalizedActionId)) {
|
|
3066
|
+
return 'typed';
|
|
3067
|
+
}
|
|
3068
|
+
if (isFallbackPointActionId(normalizedActionId)) {
|
|
3069
|
+
return 'fallback';
|
|
3070
|
+
}
|
|
3071
|
+
return '';
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
function resolveManagedMemoryMissingFollowUpActionIds(event) {
|
|
3075
|
+
const labels = resolveManagedConversationKeyLabels(event && event.missingManagedKeyLabels);
|
|
3076
|
+
const actionIds = [];
|
|
3077
|
+
labels.forEach((label) => {
|
|
3078
|
+
if (label === 'note') {
|
|
3079
|
+
actionIds.push('write_memory_note');
|
|
3080
|
+
} else if (label === 'correction') {
|
|
3081
|
+
actionIds.push('record_memory_correction');
|
|
3082
|
+
}
|
|
3083
|
+
});
|
|
3084
|
+
return actionIds;
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
function resolveHistoryFollowUpDescriptor(point, event) {
|
|
3088
|
+
const eventActionId = trimString(event && event.actionId);
|
|
3089
|
+
const eventIsManagedMemoryState = isManagedMemoryStateActionId(eventActionId);
|
|
3090
|
+
const missingManagedKeyLabels = resolveManagedConversationKeyLabels(event && event.missingManagedKeyLabels);
|
|
3091
|
+
const managedMemoryMissingActionIds = resolveManagedMemoryMissingFollowUpActionIds(event);
|
|
3092
|
+
const preferredCandidates = HISTORY_FOLLOW_UP_CANDIDATES_BY_ACTION_ID[eventActionId]
|
|
3093
|
+
|| DEFAULT_HISTORY_FOLLOW_UP_CANDIDATES;
|
|
3094
|
+
const actionIds = managedMemoryMissingActionIds.concat(preferredCandidates, DEFAULT_HISTORY_FOLLOW_UP_CANDIDATES);
|
|
3095
|
+
const moreRecentActionIds = new Set();
|
|
3096
|
+
const recentHistoryEvents = resolveRecentCapabilityEventsForAtom(point && point.atomId, 3);
|
|
3097
|
+
const targetEventId = trimString(event && event.eventId);
|
|
3098
|
+
for (let index = 0; index < recentHistoryEvents.length; index += 1) {
|
|
3099
|
+
const historyEvent = recentHistoryEvents[index];
|
|
3100
|
+
if (trimString(historyEvent && historyEvent.eventId) === targetEventId) {
|
|
3101
|
+
break;
|
|
3102
|
+
}
|
|
3103
|
+
const historyActionId = trimString(historyEvent && historyEvent.actionId);
|
|
3104
|
+
if (historyActionId) {
|
|
3105
|
+
moreRecentActionIds.add(historyActionId);
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
const visitedActionIds = new Set();
|
|
3109
|
+
const orderedValidActionIds = [];
|
|
3110
|
+
for (let index = 0; index < actionIds.length; index += 1) {
|
|
3111
|
+
const candidateActionId = trimString(actionIds[index]);
|
|
3112
|
+
if (!candidateActionId || candidateActionId === eventActionId) {
|
|
3113
|
+
continue;
|
|
3114
|
+
}
|
|
3115
|
+
if (visitedActionIds.has(candidateActionId)) {
|
|
3116
|
+
continue;
|
|
3117
|
+
}
|
|
3118
|
+
visitedActionIds.add(candidateActionId);
|
|
3119
|
+
if (!canTriggerPointActionByActionId(point, candidateActionId)) {
|
|
3120
|
+
continue;
|
|
3121
|
+
}
|
|
3122
|
+
orderedValidActionIds.push(candidateActionId);
|
|
3123
|
+
}
|
|
3124
|
+
const primaryActionId = orderedValidActionIds.find((actionId) => !moreRecentActionIds.has(actionId))
|
|
3125
|
+
|| orderedValidActionIds[0]
|
|
3126
|
+
|| '';
|
|
3127
|
+
const primaryIndex = orderedValidActionIds.indexOf(primaryActionId);
|
|
3128
|
+
const skippedRecentActionId = primaryIndex > 0
|
|
3129
|
+
? orderedValidActionIds
|
|
3130
|
+
.slice(0, primaryIndex)
|
|
3131
|
+
.find((actionId) => moreRecentActionIds.has(actionId))
|
|
3132
|
+
: '';
|
|
3133
|
+
const primaryRecentCoverage = Boolean(primaryActionId) && moreRecentActionIds.has(primaryActionId);
|
|
3134
|
+
const secondaryActionId = orderedValidActionIds.find(
|
|
3135
|
+
(actionId, index) => index !== primaryIndex && actionId !== primaryActionId && !moreRecentActionIds.has(actionId)
|
|
3136
|
+
) || orderedValidActionIds.find(
|
|
3137
|
+
(actionId, index) => index !== primaryIndex && actionId !== primaryActionId
|
|
3138
|
+
) || '';
|
|
3139
|
+
const primaryRank = primaryIndex >= 0 ? primaryIndex + 1 : 0;
|
|
3140
|
+
const secondaryIndex = orderedValidActionIds.indexOf(secondaryActionId);
|
|
3141
|
+
const secondaryRank = secondaryIndex >= 0 ? secondaryIndex + 1 : 0;
|
|
3142
|
+
const totalCandidates = orderedValidActionIds.length;
|
|
3143
|
+
const primaryIsFresh = Boolean(primaryActionId) && !primaryRecentCoverage;
|
|
3144
|
+
const secondaryRecentCoverage = Boolean(secondaryActionId) && moreRecentActionIds.has(secondaryActionId);
|
|
3145
|
+
const secondaryAvailabilityKind = resolvePointActionAvailabilityKind(point, secondaryActionId);
|
|
3146
|
+
|
|
3147
|
+
let rationaleText = '';
|
|
3148
|
+
if (primaryActionId) {
|
|
3149
|
+
if (managedMemoryMissingActionIds.includes(primaryActionId) && missingManagedKeyLabels.length > 0) {
|
|
3150
|
+
rationaleText = getI18nText(
|
|
3151
|
+
'agentWorkspace.messages.historyFollowUpReasonMissingManagedKey',
|
|
3152
|
+
'Managed state still misses {missingKey}, so {action} becomes next step.',
|
|
3153
|
+
{
|
|
3154
|
+
missingKey: summarizeMemoryKeyLabels(missingManagedKeyLabels),
|
|
3155
|
+
action: resolvePointActionLabelByActionId(point, primaryActionId),
|
|
3156
|
+
}
|
|
3157
|
+
);
|
|
3158
|
+
} else if (skippedRecentActionId) {
|
|
3159
|
+
rationaleText = getI18nText(
|
|
3160
|
+
'agentWorkspace.messages.historyFollowUpReasonSkippedRecent',
|
|
3161
|
+
'Recent activity already covered {action}.',
|
|
3162
|
+
{ action: resolvePointActionLabelByActionId(point, skippedRecentActionId) }
|
|
3163
|
+
);
|
|
3164
|
+
} else if (moreRecentActionIds.has(primaryActionId)) {
|
|
3165
|
+
rationaleText = getI18nText(
|
|
3166
|
+
'agentWorkspace.messages.historyFollowUpReasonBestAvailable',
|
|
3167
|
+
'Reusing {action} because no fresher alternative is available.',
|
|
3168
|
+
{ action: resolvePointActionLabelByActionId(point, primaryActionId) }
|
|
3169
|
+
);
|
|
3170
|
+
} else {
|
|
3171
|
+
rationaleText = getI18nText(
|
|
3172
|
+
'agentWorkspace.messages.historyFollowUpReasonTopRanked',
|
|
3173
|
+
'Top ranked next step after {action}.',
|
|
3174
|
+
{ action: resolvePointActionLabelByActionId(point, eventActionId) }
|
|
3175
|
+
);
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
|
|
3179
|
+
let tradeoffText = '';
|
|
3180
|
+
if (primaryActionId && secondaryActionId) {
|
|
3181
|
+
const primaryLabel = resolvePointActionLabelByActionId(point, primaryActionId);
|
|
3182
|
+
const secondaryLabel = resolvePointActionLabelByActionId(point, secondaryActionId);
|
|
3183
|
+
const eventLabel = resolvePointActionLabelByActionId(point, eventActionId);
|
|
3184
|
+
if (secondaryRecentCoverage) {
|
|
3185
|
+
tradeoffText = getI18nText(
|
|
3186
|
+
'agentWorkspace.messages.historyFollowUpTradeoffCoveredAlternative',
|
|
3187
|
+
'{primary} stays primary because recent activity already covered {secondary}.',
|
|
3188
|
+
{
|
|
3189
|
+
primary: primaryLabel,
|
|
3190
|
+
secondary: secondaryLabel,
|
|
3191
|
+
}
|
|
3192
|
+
);
|
|
3193
|
+
} else if (primaryRank > 0 && secondaryRank > 0) {
|
|
3194
|
+
const availabilityText = secondaryAvailabilityKind === 'typed'
|
|
3195
|
+
? getI18nText(
|
|
3196
|
+
'agentWorkspace.messages.historyFollowUpTradeoffTypedAlternative',
|
|
3197
|
+
'{secondary} remains available as a typed alternative.',
|
|
3198
|
+
{ secondary: secondaryLabel }
|
|
3199
|
+
)
|
|
3200
|
+
: secondaryAvailabilityKind === 'fallback'
|
|
3201
|
+
? getI18nText(
|
|
3202
|
+
'agentWorkspace.messages.historyFollowUpTradeoffFallbackAlternative',
|
|
3203
|
+
'{secondary} remains available as the fallback alternative.',
|
|
3204
|
+
{ secondary: secondaryLabel }
|
|
3205
|
+
)
|
|
3206
|
+
: '';
|
|
3207
|
+
tradeoffText = getI18nText(
|
|
3208
|
+
'agentWorkspace.messages.historyFollowUpTradeoffRankedAhead',
|
|
3209
|
+
'{primary} stays primary because it ranks ahead of {secondary} after {action}.',
|
|
3210
|
+
{
|
|
3211
|
+
primary: primaryLabel,
|
|
3212
|
+
secondary: secondaryLabel,
|
|
3213
|
+
action: eventLabel,
|
|
3214
|
+
}
|
|
3215
|
+
);
|
|
3216
|
+
if (availabilityText) {
|
|
3217
|
+
const joiner = /[\u4e00-\u9fff]/.test(`${tradeoffText}${availabilityText}`) ? '' : ' ';
|
|
3218
|
+
tradeoffText = `${tradeoffText}${joiner}${availabilityText}`;
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
const signalBadges = [];
|
|
3224
|
+
let confidenceText = '';
|
|
3225
|
+
if (primaryActionId) {
|
|
3226
|
+
if (primaryRank > 0 && totalCandidates > 0) {
|
|
3227
|
+
signalBadges.push(getI18nText(
|
|
3228
|
+
'agentWorkspace.labels.historyFollowUpSignalRank',
|
|
3229
|
+
'Rank {rank}/{total}',
|
|
3230
|
+
{ rank: primaryRank, total: totalCandidates }
|
|
3231
|
+
));
|
|
3232
|
+
}
|
|
3233
|
+
signalBadges.push(getI18nText(
|
|
3234
|
+
primaryIsFresh
|
|
3235
|
+
? 'agentWorkspace.labels.historyFollowUpSignalFresh'
|
|
3236
|
+
: 'agentWorkspace.labels.historyFollowUpSignalReused',
|
|
3237
|
+
primaryIsFresh ? 'Fresh' : 'Reused'
|
|
3238
|
+
));
|
|
3239
|
+
if (skippedRecentActionId) {
|
|
3240
|
+
signalBadges.push(getI18nText(
|
|
3241
|
+
'agentWorkspace.labels.historyFollowUpSignalSkippedRecent',
|
|
3242
|
+
'Skipped recent'
|
|
3243
|
+
));
|
|
3244
|
+
}
|
|
3245
|
+
missingManagedKeyLabels.forEach((label) => {
|
|
3246
|
+
signalBadges.push(getI18nText(
|
|
3247
|
+
label === 'note'
|
|
3248
|
+
? 'agentWorkspace.labels.historyFollowUpSignalMissingNote'
|
|
3249
|
+
: 'agentWorkspace.labels.historyFollowUpSignalMissingCorrection',
|
|
3250
|
+
label === 'note' ? 'Missing note' : 'Missing correction'
|
|
3251
|
+
));
|
|
3252
|
+
});
|
|
3253
|
+
if (secondaryActionId) {
|
|
3254
|
+
signalBadges.push(getI18nText(
|
|
3255
|
+
'agentWorkspace.labels.historyFollowUpSignalAlternativeReady',
|
|
3256
|
+
'Alt ready'
|
|
3257
|
+
));
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
if (skippedRecentActionId) {
|
|
3261
|
+
confidenceText = getI18nText(
|
|
3262
|
+
'agentWorkspace.messages.historyFollowUpConfidenceSkippedRecent',
|
|
3263
|
+
'Fresh candidate after skipping the more recent {action} repeat.',
|
|
3264
|
+
{ action: resolvePointActionLabelByActionId(point, skippedRecentActionId) }
|
|
3265
|
+
);
|
|
3266
|
+
} else if (primaryIsFresh) {
|
|
3267
|
+
confidenceText = getI18nText(
|
|
3268
|
+
'agentWorkspace.messages.historyFollowUpConfidenceFresh',
|
|
3269
|
+
'Fresh deterministic candidate with no newer overlap.'
|
|
3270
|
+
);
|
|
3271
|
+
} else {
|
|
3272
|
+
confidenceText = getI18nText(
|
|
3273
|
+
'agentWorkspace.messages.historyFollowUpConfidenceReused',
|
|
3274
|
+
'No fresh candidate remained, so the rail reused {action}.',
|
|
3275
|
+
{ action: resolvePointActionLabelByActionId(point, primaryActionId) }
|
|
3276
|
+
);
|
|
3277
|
+
}
|
|
3278
|
+
if (managedMemoryMissingActionIds.includes(primaryActionId) && missingManagedKeyLabels.length > 0) {
|
|
3279
|
+
const missingManagedKeyText = getI18nText(
|
|
3280
|
+
'agentWorkspace.messages.historyFollowUpConfidenceMissingManagedKey',
|
|
3281
|
+
'Targets missing {missingKey}.',
|
|
3282
|
+
{ missingKey: summarizeMemoryKeyLabels(missingManagedKeyLabels) }
|
|
3283
|
+
);
|
|
3284
|
+
if (confidenceText) {
|
|
3285
|
+
const joiner = /[\u4e00-\u9fff]/.test(`${confidenceText}${missingManagedKeyText}`) ? '' : ' ';
|
|
3286
|
+
confidenceText = `${confidenceText}${joiner}${missingManagedKeyText}`;
|
|
3287
|
+
} else {
|
|
3288
|
+
confidenceText = missingManagedKeyText;
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
let driftText = '';
|
|
3294
|
+
let stabilityText = '';
|
|
3295
|
+
let stabilityEventCount = 0;
|
|
3296
|
+
const targetEventIndex = recentHistoryEvents.findIndex(
|
|
3297
|
+
(historyEvent) => trimString(historyEvent && historyEvent.eventId) === targetEventId
|
|
3298
|
+
);
|
|
3299
|
+
if (primaryActionId && targetEventIndex > 0) {
|
|
3300
|
+
const primaryManagedKeyLabel = resolveManagedMemoryFollowUpKeyLabel(primaryActionId);
|
|
3301
|
+
const adjacentNewerEvent = recentHistoryEvents[targetEventIndex - 1];
|
|
3302
|
+
const adjacentDescriptor = adjacentNewerEvent
|
|
3303
|
+
? resolveHistoryFollowUpDescriptor(point, adjacentNewerEvent)
|
|
3304
|
+
: null;
|
|
3305
|
+
const adjacentPrimaryActionId = trimString(adjacentDescriptor && adjacentDescriptor.primaryActionId);
|
|
3306
|
+
const adjacentEventActionId = trimString(adjacentNewerEvent && adjacentNewerEvent.actionId);
|
|
3307
|
+
const adjacentIsManagedMemoryState = isManagedMemoryStateActionId(adjacentEventActionId);
|
|
3308
|
+
const adjacentMissingManagedKeyLabels = resolveManagedConversationKeyLabels(
|
|
3309
|
+
adjacentNewerEvent && adjacentNewerEvent.missingManagedKeyLabels
|
|
3310
|
+
);
|
|
3311
|
+
if (adjacentPrimaryActionId && adjacentPrimaryActionId !== primaryActionId) {
|
|
3312
|
+
const currentPrimaryLabel = resolvePointActionLabelByActionId(point, primaryActionId);
|
|
3313
|
+
const adjacentPrimaryLabel = resolvePointActionLabelByActionId(point, adjacentPrimaryActionId);
|
|
3314
|
+
const adjacentEventLabel = resolvePointActionLabelByActionId(point, adjacentNewerEvent && adjacentNewerEvent.actionId);
|
|
3315
|
+
const adjacentMoreRecentCoverage = Array.isArray(adjacentDescriptor && adjacentDescriptor.moreRecentActionIds)
|
|
3316
|
+
? adjacentDescriptor.moreRecentActionIds.includes(primaryActionId)
|
|
3317
|
+
: false;
|
|
3318
|
+
const managedKeyResolvedInAdjacent = Boolean(
|
|
3319
|
+
eventIsManagedMemoryState
|
|
3320
|
+
&& adjacentIsManagedMemoryState
|
|
3321
|
+
&& primaryManagedKeyLabel
|
|
3322
|
+
&& missingManagedKeyLabels.includes(primaryManagedKeyLabel)
|
|
3323
|
+
&& !adjacentMissingManagedKeyLabels.includes(primaryManagedKeyLabel)
|
|
3324
|
+
);
|
|
3325
|
+
driftText = managedKeyResolvedInAdjacent
|
|
3326
|
+
? getI18nText(
|
|
3327
|
+
'agentWorkspace.messages.historyFollowUpDriftManagedKeyResolved',
|
|
3328
|
+
'Newer managed state no longer misses {resolvedKey}, so the next step shifts from {previousPrimary} to {currentPrimary}.',
|
|
3329
|
+
{
|
|
3330
|
+
resolvedKey: primaryManagedKeyLabel,
|
|
3331
|
+
previousPrimary: currentPrimaryLabel,
|
|
3332
|
+
currentPrimary: adjacentPrimaryLabel,
|
|
3333
|
+
}
|
|
3334
|
+
)
|
|
3335
|
+
: adjacentMoreRecentCoverage
|
|
3336
|
+
? getI18nText(
|
|
3337
|
+
'agentWorkspace.messages.historyFollowUpDriftCoveredPrimary',
|
|
3338
|
+
'Newer {action} already covered {previousPrimary}, so the next step shifts to {currentPrimary}.',
|
|
3339
|
+
{
|
|
3340
|
+
action: adjacentEventLabel,
|
|
3341
|
+
previousPrimary: currentPrimaryLabel,
|
|
3342
|
+
currentPrimary: adjacentPrimaryLabel,
|
|
3343
|
+
}
|
|
3344
|
+
)
|
|
3345
|
+
: getI18nText(
|
|
3346
|
+
'agentWorkspace.messages.historyFollowUpDriftDifferentOrder',
|
|
3347
|
+
'Newer {action} shifts the next step from {previousPrimary} to {currentPrimary} because its follow-up order ranks {currentPrimary} earlier.',
|
|
3348
|
+
{
|
|
3349
|
+
action: adjacentEventLabel,
|
|
3350
|
+
previousPrimary: currentPrimaryLabel,
|
|
3351
|
+
currentPrimary: adjacentPrimaryLabel,
|
|
3352
|
+
}
|
|
3353
|
+
);
|
|
3354
|
+
}
|
|
3355
|
+
if (adjacentPrimaryActionId && adjacentPrimaryActionId === primaryActionId) {
|
|
3356
|
+
stabilityEventCount = 1;
|
|
3357
|
+
let managedKeyStableAcrossSeries = Boolean(
|
|
3358
|
+
eventIsManagedMemoryState
|
|
3359
|
+
&& primaryManagedKeyLabel
|
|
3360
|
+
&& missingManagedKeyLabels.includes(primaryManagedKeyLabel)
|
|
3361
|
+
);
|
|
3362
|
+
for (let index = targetEventIndex - 1; index >= 0; index -= 1) {
|
|
3363
|
+
const newerEvent = recentHistoryEvents[index];
|
|
3364
|
+
const newerDescriptor = index === targetEventIndex - 1
|
|
3365
|
+
? adjacentDescriptor
|
|
3366
|
+
: resolveHistoryFollowUpDescriptor(point, newerEvent);
|
|
3367
|
+
if (trimString(newerDescriptor && newerDescriptor.primaryActionId) !== primaryActionId) {
|
|
3368
|
+
break;
|
|
3369
|
+
}
|
|
3370
|
+
stabilityEventCount += 1;
|
|
3371
|
+
if (managedKeyStableAcrossSeries) {
|
|
3372
|
+
const newerEventActionId = trimString(newerEvent && newerEvent.actionId);
|
|
3373
|
+
const newerMissingManagedKeyLabels = resolveManagedConversationKeyLabels(
|
|
3374
|
+
newerEvent && newerEvent.missingManagedKeyLabels
|
|
3375
|
+
);
|
|
3376
|
+
if (
|
|
3377
|
+
!isManagedMemoryStateActionId(newerEventActionId)
|
|
3378
|
+
|| !newerMissingManagedKeyLabels.includes(primaryManagedKeyLabel)
|
|
3379
|
+
) {
|
|
3380
|
+
managedKeyStableAcrossSeries = false;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
if (stabilityEventCount > 1) {
|
|
3385
|
+
stabilityText = managedKeyStableAcrossSeries
|
|
3386
|
+
? getI18nText(
|
|
3387
|
+
'agentWorkspace.messages.historyFollowUpStabilityMissingManagedKey',
|
|
3388
|
+
'Newer managed state still misses {missingKey}, so {currentPrimary} stays next across {count} consecutive history events.',
|
|
3389
|
+
{
|
|
3390
|
+
missingKey: primaryManagedKeyLabel,
|
|
3391
|
+
currentPrimary: resolvePointActionLabelByActionId(point, primaryActionId),
|
|
3392
|
+
count: stabilityEventCount,
|
|
3393
|
+
}
|
|
3394
|
+
)
|
|
3395
|
+
: getI18nText(
|
|
3396
|
+
'agentWorkspace.messages.historyFollowUpStabilityKeptPrimary',
|
|
3397
|
+
'Newer {action} keeps {currentPrimary} ahead, so the next step stays stable across {count} consecutive history events.',
|
|
3398
|
+
{
|
|
3399
|
+
action: resolvePointActionLabelByActionId(point, adjacentNewerEvent && adjacentNewerEvent.actionId),
|
|
3400
|
+
currentPrimary: resolvePointActionLabelByActionId(point, primaryActionId),
|
|
3401
|
+
count: stabilityEventCount,
|
|
3402
|
+
}
|
|
3403
|
+
);
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
if (primaryActionId && stabilityEventCount > 1) {
|
|
3408
|
+
signalBadges.push(getI18nText(
|
|
3409
|
+
'agentWorkspace.labels.historyFollowUpSignalStableSeries',
|
|
3410
|
+
'Stable x{count}',
|
|
3411
|
+
{ count: stabilityEventCount }
|
|
3412
|
+
));
|
|
3413
|
+
const stabilityConfidenceText = getI18nText(
|
|
3414
|
+
'agentWorkspace.messages.historyFollowUpConfidenceStableSeries',
|
|
3415
|
+
'Reinforced across {count} consecutive history events.',
|
|
3416
|
+
{ count: stabilityEventCount }
|
|
3417
|
+
);
|
|
3418
|
+
if (stabilityConfidenceText) {
|
|
3419
|
+
if (confidenceText) {
|
|
3420
|
+
const joiner = /[\u4e00-\u9fff]/.test(`${confidenceText}${stabilityConfidenceText}`) ? '' : ' ';
|
|
3421
|
+
confidenceText = `${confidenceText}${joiner}${stabilityConfidenceText}`;
|
|
3422
|
+
} else {
|
|
3423
|
+
confidenceText = stabilityConfidenceText;
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
|
|
3428
|
+
return {
|
|
3429
|
+
primaryActionId,
|
|
3430
|
+
secondaryActionId,
|
|
3431
|
+
rationaleText,
|
|
3432
|
+
tradeoffText,
|
|
3433
|
+
stabilityText,
|
|
3434
|
+
signalBadges,
|
|
3435
|
+
confidenceText,
|
|
3436
|
+
driftText,
|
|
3437
|
+
moreRecentActionIds: Array.from(moreRecentActionIds),
|
|
3438
|
+
};
|
|
3439
|
+
}
|
|
3440
|
+
|
|
3441
|
+
function resolveHistoryFollowUpActionId(point, event) {
|
|
3442
|
+
return resolveHistoryFollowUpDescriptor(point, event).primaryActionId;
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3445
|
+
function createActivePointSummaryCard(title) {
|
|
3446
|
+
const card = document.createElement('section');
|
|
3447
|
+
card.className = 'agent-workspace-active-point-summary-card';
|
|
3448
|
+
const heading = document.createElement('h5');
|
|
3449
|
+
heading.className = 'agent-workspace-active-point-summary-heading';
|
|
3450
|
+
heading.textContent = title;
|
|
3451
|
+
card.appendChild(heading);
|
|
3452
|
+
return card;
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3455
|
+
function appendSummaryLine(card, text, extraClassName = '') {
|
|
3456
|
+
const line = document.createElement('p');
|
|
3457
|
+
line.className = extraClassName
|
|
3458
|
+
? `agent-workspace-active-point-summary-line ${extraClassName}`
|
|
3459
|
+
: 'agent-workspace-active-point-summary-line';
|
|
3460
|
+
line.textContent = text;
|
|
3461
|
+
card.appendChild(line);
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
function createHistoryEventItem(point, event, index) {
|
|
3465
|
+
const atomId = trimString(point && point.atomId);
|
|
3466
|
+
const eventId = trimString(event && event.eventId);
|
|
3467
|
+
const item = document.createElement('div');
|
|
3468
|
+
item.className = 'agent-workspace-history-item';
|
|
3469
|
+
if (!eventId) {
|
|
3470
|
+
return item;
|
|
3471
|
+
}
|
|
3472
|
+
|
|
3473
|
+
appendSummaryLine(
|
|
3474
|
+
item,
|
|
3475
|
+
`${index + 1}. ${resolvePointActionLabelByActionId(point, event.actionId)}`,
|
|
3476
|
+
'agent-workspace-active-point-summary-line--history-title'
|
|
3477
|
+
);
|
|
3478
|
+
|
|
3479
|
+
const previewText = resolveCapabilityEventPreviewText(event);
|
|
3480
|
+
if (previewText) {
|
|
3481
|
+
appendSummaryLine(
|
|
3482
|
+
item,
|
|
3483
|
+
previewText,
|
|
3484
|
+
'agent-workspace-active-point-summary-line--detail'
|
|
3485
|
+
);
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
const toggleButton = document.createElement('button');
|
|
3489
|
+
toggleButton.type = 'button';
|
|
3490
|
+
toggleButton.className = 'agent-workspace-history-toggle';
|
|
3491
|
+
const expanded = resolveExpandedHistoryEventIdForAtom(atomId) === eventId;
|
|
3492
|
+
toggleButton.textContent = expanded
|
|
3493
|
+
? getI18nText('agentWorkspace.actions.hideHistoryDetails', 'Hide details')
|
|
3494
|
+
: getI18nText('agentWorkspace.actions.showHistoryDetails', 'Show details');
|
|
3495
|
+
toggleButton.addEventListener('click', (clickEvent) => {
|
|
3496
|
+
clickEvent.preventDefault();
|
|
3497
|
+
clickEvent.stopPropagation();
|
|
3498
|
+
toggleHistoryEventDetails(atomId, eventId);
|
|
3499
|
+
});
|
|
3500
|
+
item.appendChild(toggleButton);
|
|
3501
|
+
|
|
3502
|
+
if (expanded) {
|
|
3503
|
+
const details = document.createElement('div');
|
|
3504
|
+
details.className = 'agent-workspace-history-details';
|
|
3505
|
+
appendHistoryDetailLine(
|
|
3506
|
+
details,
|
|
3507
|
+
getI18nText('agentWorkspace.labels.historyEventAt', 'At'),
|
|
3508
|
+
trimString(event && event.at)
|
|
3509
|
+
);
|
|
3510
|
+
appendHistoryDetailLine(
|
|
3511
|
+
details,
|
|
3512
|
+
getI18nText('agentWorkspace.labels.historyEventOperation', 'Operation'),
|
|
3513
|
+
trimString(event && event.operationId)
|
|
3514
|
+
);
|
|
3515
|
+
appendHistoryDetailLine(
|
|
3516
|
+
details,
|
|
3517
|
+
getI18nText('agentWorkspace.labels.historyEventSurface', 'Surface'),
|
|
3518
|
+
trimString(event && event.resultPresentation)
|
|
3519
|
+
);
|
|
3520
|
+
const durationMs = Number(event && event.durationMs);
|
|
3521
|
+
if (Number.isFinite(durationMs)) {
|
|
3522
|
+
appendHistoryDetailLine(
|
|
3523
|
+
details,
|
|
3524
|
+
getI18nText('agentWorkspace.labels.historyEventDuration', 'Duration'),
|
|
3525
|
+
`${Math.max(0, Math.floor(durationMs))} ms`
|
|
3526
|
+
);
|
|
3527
|
+
}
|
|
3528
|
+
const followUpDescriptor = resolveHistoryFollowUpDescriptor(point, event);
|
|
3529
|
+
if (followUpDescriptor.rationaleText) {
|
|
3530
|
+
const followUpReason = document.createElement('div');
|
|
3531
|
+
followUpReason.className = 'agent-workspace-history-follow-up-reason';
|
|
3532
|
+
const followUpReasonLabel = document.createElement('p');
|
|
3533
|
+
followUpReasonLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-reason-label';
|
|
3534
|
+
followUpReasonLabel.textContent = getI18nText('agentWorkspace.labels.historyFollowUpReason', 'Why this');
|
|
3535
|
+
const followUpReasonCopy = document.createElement('p');
|
|
3536
|
+
followUpReasonCopy.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-reason-copy';
|
|
3537
|
+
followUpReasonCopy.textContent = followUpDescriptor.rationaleText;
|
|
3538
|
+
followUpReason.appendChild(followUpReasonLabel);
|
|
3539
|
+
followUpReason.appendChild(followUpReasonCopy);
|
|
3540
|
+
details.appendChild(followUpReason);
|
|
3541
|
+
}
|
|
3542
|
+
if (followUpDescriptor.tradeoffText) {
|
|
3543
|
+
const followUpTradeoff = document.createElement('div');
|
|
3544
|
+
followUpTradeoff.className = 'agent-workspace-history-follow-up-tradeoff';
|
|
3545
|
+
const followUpTradeoffLabel = document.createElement('p');
|
|
3546
|
+
followUpTradeoffLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-tradeoff-label';
|
|
3547
|
+
followUpTradeoffLabel.textContent = getI18nText(
|
|
3548
|
+
'agentWorkspace.labels.historyFollowUpTradeoff',
|
|
3549
|
+
'Why not alternative'
|
|
3550
|
+
);
|
|
3551
|
+
const followUpTradeoffCopy = document.createElement('p');
|
|
3552
|
+
followUpTradeoffCopy.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-tradeoff-copy';
|
|
3553
|
+
followUpTradeoffCopy.textContent = followUpDescriptor.tradeoffText;
|
|
3554
|
+
followUpTradeoff.appendChild(followUpTradeoffLabel);
|
|
3555
|
+
followUpTradeoff.appendChild(followUpTradeoffCopy);
|
|
3556
|
+
details.appendChild(followUpTradeoff);
|
|
3557
|
+
}
|
|
3558
|
+
if (followUpDescriptor.driftText) {
|
|
3559
|
+
const followUpDrift = document.createElement('div');
|
|
3560
|
+
followUpDrift.className = 'agent-workspace-history-follow-up-drift';
|
|
3561
|
+
const followUpDriftLabel = document.createElement('p');
|
|
3562
|
+
followUpDriftLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-drift-label';
|
|
3563
|
+
followUpDriftLabel.textContent = getI18nText(
|
|
3564
|
+
'agentWorkspace.labels.historyFollowUpDrift',
|
|
3565
|
+
'Why it changed'
|
|
3566
|
+
);
|
|
3567
|
+
const followUpDriftCopy = document.createElement('p');
|
|
3568
|
+
followUpDriftCopy.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-drift-copy';
|
|
3569
|
+
followUpDriftCopy.textContent = followUpDescriptor.driftText;
|
|
3570
|
+
followUpDrift.appendChild(followUpDriftLabel);
|
|
3571
|
+
followUpDrift.appendChild(followUpDriftCopy);
|
|
3572
|
+
details.appendChild(followUpDrift);
|
|
3573
|
+
}
|
|
3574
|
+
if (followUpDescriptor.stabilityText) {
|
|
3575
|
+
const followUpStability = document.createElement('div');
|
|
3576
|
+
followUpStability.className = 'agent-workspace-history-follow-up-stability';
|
|
3577
|
+
const followUpStabilityLabel = document.createElement('p');
|
|
3578
|
+
followUpStabilityLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-stability-label';
|
|
3579
|
+
followUpStabilityLabel.textContent = getI18nText(
|
|
3580
|
+
'agentWorkspace.labels.historyFollowUpStability',
|
|
3581
|
+
'Why it held'
|
|
3582
|
+
);
|
|
3583
|
+
const followUpStabilityCopy = document.createElement('p');
|
|
3584
|
+
followUpStabilityCopy.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-stability-copy';
|
|
3585
|
+
followUpStabilityCopy.textContent = followUpDescriptor.stabilityText;
|
|
3586
|
+
followUpStability.appendChild(followUpStabilityLabel);
|
|
3587
|
+
followUpStability.appendChild(followUpStabilityCopy);
|
|
3588
|
+
details.appendChild(followUpStability);
|
|
3589
|
+
}
|
|
3590
|
+
if (followUpDescriptor.signalBadges.length > 0 || followUpDescriptor.confidenceText) {
|
|
3591
|
+
const followUpConfidence = document.createElement('div');
|
|
3592
|
+
followUpConfidence.className = 'agent-workspace-history-follow-up-confidence';
|
|
3593
|
+
const followUpConfidenceLabel = document.createElement('p');
|
|
3594
|
+
followUpConfidenceLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-confidence-label';
|
|
3595
|
+
followUpConfidenceLabel.textContent = getI18nText(
|
|
3596
|
+
'agentWorkspace.labels.historyFollowUpConfidence',
|
|
3597
|
+
'Confidence'
|
|
3598
|
+
);
|
|
3599
|
+
followUpConfidence.appendChild(followUpConfidenceLabel);
|
|
3600
|
+
if (followUpDescriptor.signalBadges.length > 0) {
|
|
3601
|
+
const signalBadges = document.createElement('div');
|
|
3602
|
+
signalBadges.className = 'agent-workspace-status-badges agent-workspace-history-follow-up-confidence-badges';
|
|
3603
|
+
followUpDescriptor.signalBadges.forEach((badgeLabel) => {
|
|
3604
|
+
signalBadges.appendChild(createStatusBadge(
|
|
3605
|
+
badgeLabel,
|
|
3606
|
+
'agent-workspace-status-badge--history-confidence'
|
|
3607
|
+
));
|
|
3608
|
+
});
|
|
3609
|
+
followUpConfidence.appendChild(signalBadges);
|
|
3610
|
+
}
|
|
3611
|
+
if (followUpDescriptor.confidenceText) {
|
|
3612
|
+
const followUpConfidenceCopy = document.createElement('p');
|
|
3613
|
+
followUpConfidenceCopy.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-confidence-copy';
|
|
3614
|
+
followUpConfidenceCopy.textContent = followUpDescriptor.confidenceText;
|
|
3615
|
+
followUpConfidence.appendChild(followUpConfidenceCopy);
|
|
3616
|
+
}
|
|
3617
|
+
details.appendChild(followUpConfidence);
|
|
3618
|
+
}
|
|
3619
|
+
if (followUpDescriptor.primaryActionId) {
|
|
3620
|
+
const followUp = document.createElement('div');
|
|
3621
|
+
followUp.className = 'agent-workspace-history-follow-up';
|
|
3622
|
+
const followUpLabel = document.createElement('p');
|
|
3623
|
+
followUpLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-label';
|
|
3624
|
+
followUpLabel.textContent = getI18nText('agentWorkspace.labels.historyFollowUp', 'Next step');
|
|
3625
|
+
followUp.appendChild(followUpLabel);
|
|
3626
|
+
followUp.appendChild(createPointActionButton(
|
|
3627
|
+
resolvePointActionLabelByActionId(point, followUpDescriptor.primaryActionId),
|
|
3628
|
+
() => triggerPointAction(followUpDescriptor.primaryActionId, point)
|
|
3629
|
+
));
|
|
3630
|
+
details.appendChild(followUp);
|
|
3631
|
+
}
|
|
3632
|
+
if (followUpDescriptor.secondaryActionId) {
|
|
3633
|
+
const alternatives = document.createElement('div');
|
|
3634
|
+
alternatives.className = 'agent-workspace-history-follow-up-alternatives';
|
|
3635
|
+
const alternativesLabel = document.createElement('p');
|
|
3636
|
+
alternativesLabel.className = 'agent-workspace-history-detail-line agent-workspace-history-follow-up-alternatives-label';
|
|
3637
|
+
alternativesLabel.textContent = getI18nText(
|
|
3638
|
+
'agentWorkspace.labels.historyFollowUpAlternatives',
|
|
3639
|
+
'Also available'
|
|
3640
|
+
);
|
|
3641
|
+
alternatives.appendChild(alternativesLabel);
|
|
3642
|
+
alternatives.appendChild(createPointActionButton(
|
|
3643
|
+
resolvePointActionLabelByActionId(point, followUpDescriptor.secondaryActionId),
|
|
3644
|
+
() => triggerPointAction(followUpDescriptor.secondaryActionId, point)
|
|
3645
|
+
));
|
|
3646
|
+
details.appendChild(alternatives);
|
|
3647
|
+
}
|
|
3648
|
+
item.appendChild(details);
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
return item;
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
function renderActivePointSummaryCards(point) {
|
|
3655
|
+
const summary = resolveActivePointCapabilitySummary(point);
|
|
3656
|
+
const wrapper = document.createElement('div');
|
|
3657
|
+
wrapper.className = 'agent-workspace-active-point-summaries';
|
|
3658
|
+
|
|
3659
|
+
const studyCard = createActivePointSummaryCard(
|
|
3660
|
+
getI18nText('agentWorkspace.labels.studyLoopSummary', 'Study Loop')
|
|
3661
|
+
);
|
|
3662
|
+
appendSummaryLine(
|
|
3663
|
+
studyCard,
|
|
3664
|
+
getI18nText(
|
|
3665
|
+
'agentWorkspace.messages.studyLoopReadyCount',
|
|
3666
|
+
'{count} ready',
|
|
3667
|
+
{ count: summary.study.length }
|
|
3668
|
+
),
|
|
3669
|
+
'agent-workspace-active-point-summary-line--metric'
|
|
3670
|
+
);
|
|
3671
|
+
if (summary.study.length > 0) {
|
|
3672
|
+
appendSummaryLine(
|
|
3673
|
+
studyCard,
|
|
3674
|
+
summary.study
|
|
3675
|
+
.map((capability) => resolveCapabilityLabel(capability))
|
|
3676
|
+
.join(', ')
|
|
3677
|
+
);
|
|
3678
|
+
} else {
|
|
3679
|
+
appendSummaryLine(
|
|
3680
|
+
studyCard,
|
|
3681
|
+
getI18nText('agentWorkspace.labels.noStudyActionYet', 'No study action yet')
|
|
3682
|
+
);
|
|
3683
|
+
}
|
|
3684
|
+
const latestStudyEvent = resolveLatestCapabilityEventForAtom(point && point.atomId, 'study');
|
|
3685
|
+
if (latestStudyEvent) {
|
|
3686
|
+
appendSummaryLine(
|
|
3687
|
+
studyCard,
|
|
3688
|
+
`${getI18nText('agentWorkspace.labels.lastAction', 'Last action')}: ${resolvePointActionLabelByActionId(point, latestStudyEvent.actionId)}`
|
|
3689
|
+
);
|
|
3690
|
+
appendSummaryLine(
|
|
3691
|
+
studyCard,
|
|
3692
|
+
getI18nText('agentWorkspace.labels.success', 'Success')
|
|
3693
|
+
);
|
|
3694
|
+
} else {
|
|
3695
|
+
appendSummaryLine(
|
|
3696
|
+
studyCard,
|
|
3697
|
+
getI18nText('agentWorkspace.labels.noStudyActionYet', 'No study action yet')
|
|
3698
|
+
);
|
|
3699
|
+
}
|
|
3700
|
+
wrapper.appendChild(studyCard);
|
|
3701
|
+
|
|
3702
|
+
const supportCard = createActivePointSummaryCard(
|
|
3703
|
+
getI18nText('agentWorkspace.labels.supportSurfaceSummary', 'Support Surface')
|
|
3704
|
+
);
|
|
3705
|
+
appendSummaryLine(
|
|
3706
|
+
supportCard,
|
|
3707
|
+
getI18nText(
|
|
3708
|
+
'agentWorkspace.messages.supportSurfaceCounts',
|
|
3709
|
+
'Memory {memoryCount} Diagnostics {diagnosticCount}',
|
|
3710
|
+
{
|
|
3711
|
+
memoryCount: summary.memory.length,
|
|
3712
|
+
diagnosticCount: summary.diagnostic.length,
|
|
3713
|
+
}
|
|
3714
|
+
),
|
|
3715
|
+
'agent-workspace-active-point-summary-line--metric'
|
|
3716
|
+
);
|
|
3717
|
+
wrapper.appendChild(supportCard);
|
|
3718
|
+
|
|
3719
|
+
const historyEvents = resolveRecentCapabilityEventsForAtom(point && point.atomId, 3);
|
|
3720
|
+
const historyCard = createActivePointSummaryCard(
|
|
3721
|
+
getI18nText('agentWorkspace.labels.currentAtomHistorySummary', 'Recent Activity')
|
|
3722
|
+
);
|
|
3723
|
+
appendSummaryLine(
|
|
3724
|
+
historyCard,
|
|
3725
|
+
getI18nText(
|
|
3726
|
+
'agentWorkspace.messages.currentAtomHistoryCount',
|
|
3727
|
+
'{count} recent results',
|
|
3728
|
+
{ count: historyEvents.length }
|
|
3729
|
+
),
|
|
3730
|
+
'agent-workspace-active-point-summary-line--metric'
|
|
3731
|
+
);
|
|
3732
|
+
const managedConversationContinuitySummary = computeManagedConversationContinuitySummary(historyEvents);
|
|
3733
|
+
if (managedConversationContinuitySummary.readCount > 1) {
|
|
3734
|
+
appendSummaryLine(
|
|
3735
|
+
historyCard,
|
|
3736
|
+
getI18nText(
|
|
3737
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityReads',
|
|
3738
|
+
'Managed continuity {readCount} reads',
|
|
3739
|
+
{ readCount: managedConversationContinuitySummary.readCount }
|
|
3740
|
+
),
|
|
3741
|
+
'agent-workspace-active-point-summary-line--metric'
|
|
3742
|
+
);
|
|
3743
|
+
if (hasManagedConversationKeyCounts(managedConversationContinuitySummary.resolvedKeyCounts)) {
|
|
3744
|
+
appendSummaryLine(
|
|
3745
|
+
historyCard,
|
|
3746
|
+
getI18nText(
|
|
3747
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityResolved',
|
|
3748
|
+
'resolved note {noteCount} correction {correctionCount}',
|
|
3749
|
+
{
|
|
3750
|
+
noteCount: managedConversationContinuitySummary.resolvedKeyCounts.note,
|
|
3751
|
+
correctionCount: managedConversationContinuitySummary.resolvedKeyCounts.correction,
|
|
3752
|
+
}
|
|
3753
|
+
)
|
|
3754
|
+
);
|
|
3755
|
+
if (Array.isArray(managedConversationContinuitySummary.resolvedFollowUpActionLabels)
|
|
3756
|
+
&& managedConversationContinuitySummary.resolvedFollowUpActionLabels.length > 0) {
|
|
3757
|
+
appendSummaryLine(
|
|
3758
|
+
historyCard,
|
|
3759
|
+
getI18nText(
|
|
3760
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityResolvedActions',
|
|
3761
|
+
'resolved no longer needs {actions}',
|
|
3762
|
+
{
|
|
3763
|
+
actions: managedConversationContinuitySummary.resolvedFollowUpActionLabels.join(', '),
|
|
3764
|
+
}
|
|
3765
|
+
)
|
|
3766
|
+
);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
if (hasManagedConversationKeyCounts(managedConversationContinuitySummary.persistentKeyCounts)) {
|
|
3770
|
+
appendSummaryLine(
|
|
3771
|
+
historyCard,
|
|
3772
|
+
getI18nText(
|
|
3773
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityPersistent',
|
|
3774
|
+
'persistent note {noteCount} correction {correctionCount}',
|
|
3775
|
+
{
|
|
3776
|
+
noteCount: managedConversationContinuitySummary.persistentKeyCounts.note,
|
|
3777
|
+
correctionCount: managedConversationContinuitySummary.persistentKeyCounts.correction,
|
|
3778
|
+
}
|
|
3779
|
+
)
|
|
3780
|
+
);
|
|
3781
|
+
}
|
|
3782
|
+
if (Array.isArray(managedConversationContinuitySummary.persistentFollowUpActionIds)
|
|
3783
|
+
&& managedConversationContinuitySummary.persistentFollowUpActionIds.length > 0) {
|
|
3784
|
+
appendSummaryLine(
|
|
3785
|
+
historyCard,
|
|
3786
|
+
getI18nText(
|
|
3787
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityNextActions',
|
|
3788
|
+
'persistent next {actions}',
|
|
3789
|
+
{
|
|
3790
|
+
actions: managedConversationContinuitySummary.persistentFollowUpActionLabels.join(', '),
|
|
3791
|
+
}
|
|
3792
|
+
)
|
|
3793
|
+
);
|
|
3794
|
+
}
|
|
3795
|
+
if (managedConversationContinuitySummary.lastTransition
|
|
3796
|
+
&& trimString(managedConversationContinuitySummary.lastTransition.keyLabel)) {
|
|
3797
|
+
const lastTransition = managedConversationContinuitySummary.lastTransition;
|
|
3798
|
+
const resolvedKeyLabelsSummary = resolveManagedConversationKeyLabels(
|
|
3799
|
+
lastTransition.resolvedKeyLabels
|
|
3800
|
+
).join(', ');
|
|
3801
|
+
const persistentKeyLabelsSummary = resolveManagedConversationKeyLabels(
|
|
3802
|
+
lastTransition.persistentKeyLabels
|
|
3803
|
+
).join(', ');
|
|
3804
|
+
const resolvedActionLabelsSummary = Array.isArray(lastTransition.resolvedFollowUpActionLabels)
|
|
3805
|
+
? lastTransition.resolvedFollowUpActionLabels.join(', ')
|
|
3806
|
+
: trimString(lastTransition.followUpActionLabel);
|
|
3807
|
+
const persistentActionLabelsSummary = Array.isArray(lastTransition.persistentFollowUpActionLabels)
|
|
3808
|
+
? lastTransition.persistentFollowUpActionLabels.join(', ')
|
|
3809
|
+
: trimString(lastTransition.followUpActionLabel);
|
|
3810
|
+
const lastTransitionActionLabel = trimString(lastTransition.followUpActionLabel);
|
|
3811
|
+
if (lastTransition.kind === 'mixed'
|
|
3812
|
+
&& resolvedKeyLabelsSummary
|
|
3813
|
+
&& persistentKeyLabelsSummary
|
|
3814
|
+
&& resolvedActionLabelsSummary
|
|
3815
|
+
&& persistentActionLabelsSummary) {
|
|
3816
|
+
appendSummaryLine(
|
|
3817
|
+
historyCard,
|
|
3818
|
+
getI18nText(
|
|
3819
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityLatestMixed',
|
|
3820
|
+
'latest transition resolved {resolvedKeyLabels}, retired {resolvedActions}; persistent {persistentKeyLabels}, next {persistentActions}',
|
|
3821
|
+
{
|
|
3822
|
+
resolvedKeyLabels: resolvedKeyLabelsSummary,
|
|
3823
|
+
resolvedActions: resolvedActionLabelsSummary,
|
|
3824
|
+
persistentKeyLabels: persistentKeyLabelsSummary,
|
|
3825
|
+
persistentActions: persistentActionLabelsSummary,
|
|
3826
|
+
}
|
|
3827
|
+
)
|
|
3828
|
+
);
|
|
3829
|
+
} else if (lastTransition.kind === 'resolved' && lastTransitionActionLabel) {
|
|
3830
|
+
appendSummaryLine(
|
|
3831
|
+
historyCard,
|
|
3832
|
+
getI18nText(
|
|
3833
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityLatestResolved',
|
|
3834
|
+
'latest transition resolved {keyLabel}, retired {action}',
|
|
3835
|
+
{
|
|
3836
|
+
keyLabel: resolvedKeyLabelsSummary || trimString(lastTransition.keyLabel),
|
|
3837
|
+
action: lastTransitionActionLabel,
|
|
3838
|
+
}
|
|
3839
|
+
)
|
|
3840
|
+
);
|
|
3841
|
+
} else if (lastTransition.kind === 'persistent' && lastTransitionActionLabel) {
|
|
3842
|
+
appendSummaryLine(
|
|
3843
|
+
historyCard,
|
|
3844
|
+
getI18nText(
|
|
3845
|
+
'agentWorkspace.messages.currentAtomHistoryManagedContinuityLatestPersistent',
|
|
3846
|
+
'latest transition persistent {keyLabel}, next {action}',
|
|
3847
|
+
{
|
|
3848
|
+
keyLabel: persistentKeyLabelsSummary || trimString(lastTransition.keyLabel),
|
|
3849
|
+
action: lastTransitionActionLabel,
|
|
3850
|
+
}
|
|
3851
|
+
)
|
|
3852
|
+
);
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
if (historyEvents.length > 0) {
|
|
3857
|
+
historyEvents.forEach((event, index) => {
|
|
3858
|
+
historyCard.appendChild(createHistoryEventItem(point, event, index));
|
|
3859
|
+
});
|
|
3860
|
+
} else {
|
|
3861
|
+
appendSummaryLine(
|
|
3862
|
+
historyCard,
|
|
3863
|
+
getI18nText('agentWorkspace.labels.noCurrentAtomHistoryYet', 'No current-atom history yet')
|
|
3864
|
+
);
|
|
3865
|
+
}
|
|
3866
|
+
wrapper.appendChild(historyCard);
|
|
3867
|
+
|
|
3868
|
+
return wrapper;
|
|
3869
|
+
}
|
|
3870
|
+
|
|
3871
|
+
function renderActivePointRail(point) {
|
|
3872
|
+
const atomId = trimString(point && point.atomId);
|
|
3873
|
+
if (!atomId) {
|
|
3874
|
+
return null;
|
|
3875
|
+
}
|
|
3876
|
+
const rail = document.createElement('section');
|
|
3877
|
+
rail.className = 'agent-workspace-active-point';
|
|
3878
|
+
rail.dataset.atomId = atomId;
|
|
3879
|
+
|
|
3880
|
+
const heading = document.createElement('h4');
|
|
3881
|
+
heading.className = 'agent-workspace-active-point-heading';
|
|
3882
|
+
heading.textContent = getI18nText('agentWorkspace.labels.activeAtom', 'Active Atom');
|
|
3883
|
+
rail.appendChild(heading);
|
|
3884
|
+
|
|
3885
|
+
appendActivePointStatus(rail, point);
|
|
3886
|
+
appendPointIdentity(rail, point);
|
|
3887
|
+
rail.appendChild(renderActivePointSummaryCards(point));
|
|
3888
|
+
|
|
3889
|
+
const actions = document.createElement('div');
|
|
3890
|
+
actions.className = 'agent-workspace-point-actions agent-workspace-active-point-actions';
|
|
3891
|
+
actions.appendChild(createPointActionButton(
|
|
3892
|
+
getI18nText('agentWorkspace.actions.openFocusMode', 'Focus'),
|
|
3893
|
+
() => triggerPointAction('open_focus_mode', point)
|
|
3894
|
+
));
|
|
3895
|
+
actions.appendChild(createPointActionButton(
|
|
3896
|
+
getI18nText('agentWorkspace.actions.openLearningPath', 'Learning Path'),
|
|
3897
|
+
() => triggerPointAction('open_learning_path', point)
|
|
3898
|
+
));
|
|
3899
|
+
resolveActivePointCapabilities(point).forEach((capability) => {
|
|
3900
|
+
actions.appendChild(createPointActionButton(
|
|
3901
|
+
resolveCapabilityLabel(capability),
|
|
3902
|
+
() => {
|
|
3903
|
+
void runCapabilityAction(capability, point);
|
|
3904
|
+
}
|
|
3905
|
+
));
|
|
3906
|
+
});
|
|
3907
|
+
rail.appendChild(actions);
|
|
3908
|
+
return rail;
|
|
3909
|
+
}
|
|
3910
|
+
|
|
3911
|
+
function focusKnowledgePoint(point) {
|
|
3912
|
+
const atomId = trimString(point && point.atomId);
|
|
3913
|
+
if (!atomId) {
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
focusAtom(atomId, point);
|
|
3917
|
+
}
|
|
3918
|
+
|
|
3919
|
+
function renderKnowledgePoints(knowledgePoints) {
|
|
3920
|
+
if (!dom.knowledgeList) {
|
|
3921
|
+
return;
|
|
3922
|
+
}
|
|
3923
|
+
dom.knowledgeList.innerHTML = '';
|
|
3924
|
+
if (!Array.isArray(knowledgePoints) || knowledgePoints.length === 0) {
|
|
3925
|
+
const emptyState = document.createElement('div');
|
|
3926
|
+
emptyState.className = 'agent-workspace-empty';
|
|
3927
|
+
emptyState.textContent = getI18nText(
|
|
3928
|
+
'agentWorkspace.messages.noKnowledgePoints',
|
|
3929
|
+
'No local knowledge points found for current query.'
|
|
3930
|
+
);
|
|
3931
|
+
dom.knowledgeList.appendChild(emptyState);
|
|
3932
|
+
return;
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
const activePoint = findKnowledgePoint(state.latestFocusAtomId);
|
|
3936
|
+
const activeRail = renderActivePointRail(activePoint);
|
|
3937
|
+
if (activeRail) {
|
|
3938
|
+
dom.knowledgeList.appendChild(activeRail);
|
|
3939
|
+
}
|
|
3940
|
+
|
|
3941
|
+
knowledgePoints.forEach((point) => {
|
|
3942
|
+
const card = document.createElement('article');
|
|
3943
|
+
card.className = 'agent-workspace-point-card';
|
|
3944
|
+
card.dataset.atomId = trimString(point && point.atomId);
|
|
3945
|
+
if (trimString(point && point.atomId) === trimString(state.latestFocusAtomId)) {
|
|
3946
|
+
card.classList.add('agent-workspace-point-card--active');
|
|
3947
|
+
}
|
|
3948
|
+
card.setAttribute('role', 'button');
|
|
3949
|
+
card.setAttribute('tabindex', '0');
|
|
3950
|
+
card.title = getI18nText(
|
|
3951
|
+
'agentWorkspace.messages.clickPointToFocus',
|
|
3952
|
+
'Click to open focus mode'
|
|
3953
|
+
);
|
|
3954
|
+
card.addEventListener('click', () => {
|
|
3955
|
+
try {
|
|
3956
|
+
focusKnowledgePoint(point);
|
|
3957
|
+
} catch (error) {
|
|
3958
|
+
appendMessage(
|
|
3959
|
+
'assistant',
|
|
3960
|
+
getI18nText('agentWorkspace.messages.operationFailed', 'Operation failed.')
|
|
3961
|
+
);
|
|
3962
|
+
console.error('[AgentWorkspace] point-focus failed:', error);
|
|
3963
|
+
}
|
|
3964
|
+
});
|
|
3965
|
+
card.addEventListener('keydown', (event) => {
|
|
3966
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
3967
|
+
event.preventDefault();
|
|
3968
|
+
card.click();
|
|
3969
|
+
}
|
|
3970
|
+
});
|
|
3971
|
+
|
|
3972
|
+
appendPointIdentity(card, point);
|
|
3973
|
+
|
|
3974
|
+
const actions = document.createElement('div');
|
|
3975
|
+
actions.className = 'agent-workspace-point-actions';
|
|
3976
|
+
const capabilities = Array.isArray(point.capabilities) ? point.capabilities : [];
|
|
3977
|
+
capabilities.forEach((capability) => {
|
|
3978
|
+
const button = createPointActionButton(resolveCapabilityLabel(capability), () => {
|
|
3979
|
+
void runCapabilityAction(capability, point);
|
|
3980
|
+
});
|
|
3981
|
+
actions.appendChild(button);
|
|
3982
|
+
});
|
|
3983
|
+
card.appendChild(actions);
|
|
3984
|
+
dom.knowledgeList.appendChild(card);
|
|
3985
|
+
});
|
|
3986
|
+
}
|
|
3987
|
+
|
|
3988
|
+
async function sendConversation() {
|
|
3989
|
+
if (!dom.input) {
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3992
|
+
const message = trimString(dom.input.value);
|
|
3993
|
+
if (!message || state.busy) {
|
|
3994
|
+
return;
|
|
3995
|
+
}
|
|
3996
|
+
const payload = resolveConversationPayload({
|
|
3997
|
+
userId: resolveUserId(),
|
|
3998
|
+
message,
|
|
3999
|
+
topK: options.defaultTopK || 4,
|
|
4000
|
+
});
|
|
4001
|
+
const replayMarker = markUserMessageReplayCandidate(payload.message);
|
|
4002
|
+
diagnostics.conversationRequests += 1;
|
|
4003
|
+
diagnostics.lastConversation = {
|
|
4004
|
+
requestedAt: nowIso(),
|
|
4005
|
+
respondedAt: '',
|
|
4006
|
+
userId: payload.userId,
|
|
4007
|
+
message: payload.message,
|
|
4008
|
+
status: 'pending',
|
|
4009
|
+
replayCandidate: replayMarker.replayCandidate,
|
|
4010
|
+
knowledgePoints: 0,
|
|
4011
|
+
};
|
|
4012
|
+
appendMessage('user', payload.message, {
|
|
4013
|
+
source: 'conversation',
|
|
4014
|
+
replayCandidate: replayMarker.replayCandidate,
|
|
4015
|
+
replaySeenCount: replayMarker.seenCount,
|
|
4016
|
+
fingerprint: replayMarker.fingerprint,
|
|
4017
|
+
});
|
|
4018
|
+
dom.input.value = '';
|
|
4019
|
+
|
|
4020
|
+
setBusy(true);
|
|
4021
|
+
try {
|
|
4022
|
+
const result = await requestJson('/api/knowledge/conversation', payload);
|
|
4023
|
+
const knowledgePoints = Array.isArray(result && result.knowledgePoints)
|
|
4024
|
+
? result.knowledgePoints
|
|
4025
|
+
: [];
|
|
4026
|
+
diagnostics.lastConversation = {
|
|
4027
|
+
requestedAt: diagnostics.lastConversation && diagnostics.lastConversation.requestedAt
|
|
4028
|
+
? diagnostics.lastConversation.requestedAt
|
|
4029
|
+
: nowIso(),
|
|
4030
|
+
respondedAt: nowIso(),
|
|
4031
|
+
userId: payload.userId,
|
|
4032
|
+
message: payload.message,
|
|
4033
|
+
status: 'success',
|
|
4034
|
+
replayCandidate: replayMarker.replayCandidate,
|
|
4035
|
+
knowledgePoints: knowledgePoints.length,
|
|
4036
|
+
retrievalModes: Array.isArray(result && result.trace && result.trace.retrievalModes)
|
|
4037
|
+
? result.trace.retrievalModes.slice()
|
|
4038
|
+
: [],
|
|
4039
|
+
vectorAcceleration: result && result.trace && result.trace.vectorAcceleration
|
|
4040
|
+
&& typeof result.trace.vectorAcceleration === 'object'
|
|
4041
|
+
? { ...result.trace.vectorAcceleration }
|
|
4042
|
+
: null,
|
|
4043
|
+
evidenceCoverageRatio: Number(result && result.trace && result.trace.evidenceCoverageRatio),
|
|
4044
|
+
};
|
|
4045
|
+
appendMessage('assistant', trimString(result && result.message));
|
|
4046
|
+
state.latestKnowledgePoints = knowledgePoints;
|
|
4047
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
4048
|
+
} catch (error) {
|
|
4049
|
+
const errorMessage = trimString(error && error.message);
|
|
4050
|
+
diagnostics.lastConversation = {
|
|
4051
|
+
requestedAt: diagnostics.lastConversation && diagnostics.lastConversation.requestedAt
|
|
4052
|
+
? diagnostics.lastConversation.requestedAt
|
|
4053
|
+
: nowIso(),
|
|
4054
|
+
respondedAt: nowIso(),
|
|
4055
|
+
userId: payload.userId,
|
|
4056
|
+
message: payload.message,
|
|
4057
|
+
status: 'failed',
|
|
4058
|
+
replayCandidate: replayMarker.replayCandidate,
|
|
4059
|
+
knowledgePoints: 0,
|
|
4060
|
+
};
|
|
4061
|
+
recordFailure('sendConversation', errorMessage);
|
|
4062
|
+
appendMessage(
|
|
4063
|
+
'assistant',
|
|
4064
|
+
getI18nText(
|
|
4065
|
+
'agentWorkspace.messages.conversationFailed',
|
|
4066
|
+
`Conversation failed: ${errorMessage || 'unknown error'}.`
|
|
4067
|
+
)
|
|
4068
|
+
);
|
|
4069
|
+
console.error('[AgentWorkspace] conversation request failed:', error);
|
|
4070
|
+
} finally {
|
|
4071
|
+
setBusy(false);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4075
|
+
async function loadFoundationReadiness() {
|
|
4076
|
+
if (state.busy) {
|
|
4077
|
+
return;
|
|
4078
|
+
}
|
|
4079
|
+
const requestedAt = nowIso();
|
|
4080
|
+
diagnostics.lastFoundationReadiness = {
|
|
4081
|
+
requestedAt,
|
|
4082
|
+
respondedAt: '',
|
|
4083
|
+
status: 'pending',
|
|
4084
|
+
decision: '',
|
|
4085
|
+
storeType: '',
|
|
4086
|
+
graphBackendStatus: '',
|
|
4087
|
+
graphBackendSignalKind: '',
|
|
4088
|
+
graphBackendIndependent: false,
|
|
4089
|
+
queryBackendDefaultMode: '',
|
|
4090
|
+
queryBackendScoreSignals: [],
|
|
4091
|
+
vectorAdapterStatus: '',
|
|
4092
|
+
vectorAdapterSignalKind: '',
|
|
4093
|
+
vectorAdapterIndependent: false,
|
|
4094
|
+
vectorAdapterLinkedIntoQueryBackend: false,
|
|
4095
|
+
repoRootSource: '',
|
|
4096
|
+
runtimeProjectRootAligned: false,
|
|
4097
|
+
mandatoryCheckIds: [],
|
|
4098
|
+
mandatoryChecks: [],
|
|
4099
|
+
promotionCriteriaPassed: 0,
|
|
4100
|
+
promotionCriteriaTotal: 0,
|
|
4101
|
+
mandatoryChecksCount: 0,
|
|
4102
|
+
promotionCriteriaSatisfiedIds: [],
|
|
4103
|
+
promotionCriteriaUnsatisfiedIds: [],
|
|
4104
|
+
promotionCriteria: [],
|
|
4105
|
+
promotionBlockerIds: [],
|
|
4106
|
+
promotionBlockers: [],
|
|
4107
|
+
promotionBlockersCount: 0,
|
|
4108
|
+
recommendations: [],
|
|
4109
|
+
recommendationsCount: 0,
|
|
4110
|
+
};
|
|
4111
|
+
setBusy(true);
|
|
4112
|
+
try {
|
|
4113
|
+
const readiness = await requestJson(
|
|
4114
|
+
'/api/knowledge/foundation/readiness',
|
|
4115
|
+
null,
|
|
4116
|
+
{
|
|
4117
|
+
method: 'GET',
|
|
4118
|
+
responseKey: 'readiness',
|
|
4119
|
+
}
|
|
4120
|
+
);
|
|
4121
|
+
const baseline = readiness && readiness.baseline && typeof readiness.baseline === 'object'
|
|
4122
|
+
? readiness.baseline
|
|
4123
|
+
: {};
|
|
4124
|
+
const recommendationsCount = Array.isArray(readiness && readiness.recommendations)
|
|
4125
|
+
? readiness.recommendations.length
|
|
4126
|
+
: 0;
|
|
4127
|
+
const mandatoryCheckIds = Array.isArray(readiness && readiness.mandatoryChecks)
|
|
4128
|
+
? readiness.mandatoryChecks
|
|
4129
|
+
.map((entry) => {
|
|
4130
|
+
const source = entry && typeof entry === 'object' ? entry : {};
|
|
4131
|
+
return trimString(source.gateId);
|
|
4132
|
+
})
|
|
4133
|
+
.filter(Boolean)
|
|
4134
|
+
: [];
|
|
4135
|
+
const mandatoryChecks = Array.isArray(readiness && readiness.mandatoryChecks)
|
|
4136
|
+
? readiness.mandatoryChecks
|
|
4137
|
+
.map((entry) => {
|
|
4138
|
+
const source = entry && typeof entry === 'object' ? entry : {};
|
|
4139
|
+
return {
|
|
4140
|
+
gateId: trimString(source.gateId),
|
|
4141
|
+
command: trimString(source.command),
|
|
4142
|
+
};
|
|
4143
|
+
})
|
|
4144
|
+
.filter((entry) => entry.gateId)
|
|
4145
|
+
: [];
|
|
4146
|
+
const provenance = readiness && readiness.provenance && typeof readiness.provenance === 'object'
|
|
4147
|
+
? readiness.provenance
|
|
4148
|
+
: {};
|
|
4149
|
+
const promotionBlockers = Array.isArray(readiness && readiness.promotionBlockers)
|
|
4150
|
+
? readiness.promotionBlockers
|
|
4151
|
+
.map((entry) => {
|
|
4152
|
+
const source = entry && typeof entry === 'object' ? entry : {};
|
|
4153
|
+
return {
|
|
4154
|
+
blockerId: trimString(source.blockerId),
|
|
4155
|
+
summary: trimString(source.summary),
|
|
4156
|
+
};
|
|
4157
|
+
})
|
|
4158
|
+
.filter((entry) => entry.blockerId)
|
|
4159
|
+
: [];
|
|
4160
|
+
const promotionCriteria = Array.isArray(readiness && readiness.promotionCriteria)
|
|
4161
|
+
? readiness.promotionCriteria
|
|
4162
|
+
.map((entry) => {
|
|
4163
|
+
const source = entry && typeof entry === 'object' ? entry : {};
|
|
4164
|
+
return {
|
|
4165
|
+
criterionId: trimString(source.criterionId),
|
|
4166
|
+
satisfied: Boolean(source.satisfied),
|
|
4167
|
+
summary: trimString(source.summary),
|
|
4168
|
+
};
|
|
4169
|
+
})
|
|
4170
|
+
.filter((entry) => entry.criterionId)
|
|
4171
|
+
: [];
|
|
4172
|
+
const promotionBlockerIds = promotionBlockers.map((entry) => entry.blockerId);
|
|
4173
|
+
const promotionCriteriaPassed = Number.isFinite(Number(readiness && readiness.promotionCriteriaPassed))
|
|
4174
|
+
? Number(readiness && readiness.promotionCriteriaPassed)
|
|
4175
|
+
: promotionCriteria.filter((entry) => entry.satisfied).length;
|
|
4176
|
+
const promotionCriteriaTotal = Number.isFinite(Number(readiness && readiness.promotionCriteriaTotal))
|
|
4177
|
+
? Number(readiness && readiness.promotionCriteriaTotal)
|
|
4178
|
+
: promotionCriteria.length;
|
|
4179
|
+
const promotionCriteriaSatisfiedIds = Array.isArray(readiness && readiness.promotionCriteriaSatisfiedIds)
|
|
4180
|
+
? readiness.promotionCriteriaSatisfiedIds.map((entry) => trimString(entry)).filter(Boolean)
|
|
4181
|
+
: promotionCriteria.filter((entry) => entry.satisfied).map((entry) => entry.criterionId);
|
|
4182
|
+
const promotionCriteriaUnsatisfiedIds = Array.isArray(readiness && readiness.promotionCriteriaUnsatisfiedIds)
|
|
4183
|
+
? readiness.promotionCriteriaUnsatisfiedIds.map((entry) => trimString(entry)).filter(Boolean)
|
|
4184
|
+
: promotionCriteria.filter((entry) => !entry.satisfied).map((entry) => entry.criterionId);
|
|
4185
|
+
diagnostics.lastFoundationReadiness = {
|
|
4186
|
+
requestedAt,
|
|
4187
|
+
respondedAt: nowIso(),
|
|
4188
|
+
evaluatedAt: trimString(readiness && readiness.evaluatedAt),
|
|
4189
|
+
status: trimString(readiness && readiness.status),
|
|
4190
|
+
decision: trimString(readiness && readiness.decision),
|
|
4191
|
+
storeType: trimString(baseline.storeType),
|
|
4192
|
+
graphBackendStatus: trimString(baseline.graphBackendStatus),
|
|
4193
|
+
graphBackendSignalKind: trimString(baseline.graphBackendSignalKind),
|
|
4194
|
+
graphBackendIndependent: Boolean(baseline.graphBackendIndependent),
|
|
4195
|
+
queryBackendDefaultMode: trimString(baseline.queryBackendDefaultMode),
|
|
4196
|
+
queryBackendScoreSignals: Array.isArray(baseline.queryBackendScoreSignals)
|
|
4197
|
+
? baseline.queryBackendScoreSignals.map((entry) => trimString(entry)).filter(Boolean)
|
|
4198
|
+
: [],
|
|
4199
|
+
vectorAdapterStatus: trimString(baseline.vectorAdapterStatus),
|
|
4200
|
+
vectorAdapterSignalKind: trimString(baseline.vectorAdapterSignalKind),
|
|
4201
|
+
vectorAdapterIndependent: Boolean(baseline.vectorAdapterIndependent),
|
|
4202
|
+
vectorAdapterLinkedIntoQueryBackend: Boolean(baseline.vectorAdapterLinkedIntoQueryBackend),
|
|
4203
|
+
repoRootSource: trimString(provenance.repoRootSource),
|
|
4204
|
+
runtimeProjectRootAligned: Boolean(provenance.runtimeProjectRootAligned),
|
|
4205
|
+
mandatoryCheckIds,
|
|
4206
|
+
mandatoryChecks,
|
|
4207
|
+
promotionCriteriaPassed,
|
|
4208
|
+
promotionCriteriaTotal,
|
|
4209
|
+
mandatoryChecksCount: mandatoryCheckIds.length,
|
|
4210
|
+
promotionCriteriaSatisfiedIds,
|
|
4211
|
+
promotionCriteriaUnsatisfiedIds,
|
|
4212
|
+
promotionCriteria,
|
|
4213
|
+
promotionBlockerIds,
|
|
4214
|
+
promotionBlockers,
|
|
4215
|
+
promotionBlockersCount: promotionBlockerIds.length,
|
|
4216
|
+
recommendations: Array.isArray(readiness && readiness.recommendations)
|
|
4217
|
+
? readiness.recommendations.map((entry) => trimString(entry)).filter(Boolean)
|
|
4218
|
+
: [],
|
|
4219
|
+
recommendationsCount,
|
|
4220
|
+
};
|
|
4221
|
+
const queryBackendScoreSignals = Array.isArray(baseline.queryBackendScoreSignals)
|
|
4222
|
+
? baseline.queryBackendScoreSignals.map((entry) => trimString(entry)).filter(Boolean)
|
|
4223
|
+
: [];
|
|
4224
|
+
appendMessage(
|
|
4225
|
+
'assistant',
|
|
4226
|
+
getI18nText(
|
|
4227
|
+
'agentWorkspace.messages.foundationReadinessLoaded',
|
|
4228
|
+
`Foundation readiness ${trimString(readiness && readiness.status) || 'unknown'} / ${trimString(readiness && readiness.decision) || 'unknown'} (store ${trimString(baseline.storeType) || 'n/a'}, graph ${trimString(baseline.graphBackendStatus) || 'n/a'}/${trimString(baseline.graphBackendSignalKind) || 'n/a'}, graph-independent ${Boolean(baseline.graphBackendIndependent) ? 'yes' : 'no'}, backend ${trimString(baseline.queryBackendDefaultMode) || 'n/a'}, signals ${queryBackendScoreSignals.join(', ') || 'none'}, vector ${trimString(baseline.vectorAdapterStatus) || 'n/a'}, signal-kind ${trimString(baseline.vectorAdapterSignalKind) || 'n/a'}, independent ${Boolean(baseline.vectorAdapterIndependent) ? 'yes' : 'no'}, linked ${Boolean(baseline.vectorAdapterLinkedIntoQueryBackend) ? 'yes' : 'no'}, repo-source ${trimString(provenance.repoRootSource) || 'n/a'}, aligned ${Boolean(provenance.runtimeProjectRootAligned) ? 'yes' : 'no'}, gates ${mandatoryCheckIds.join(', ') || 'none'}, criteria ${promotionCriteriaPassed}/${promotionCriteriaTotal}, criteria-detail ${promotionCriteria.length}, satisfied ${promotionCriteriaSatisfiedIds.join(', ') || 'none'}, unmet ${promotionCriteriaUnsatisfiedIds.join(', ') || 'none'}, blockers ${promotionBlockerIds.join(', ') || 'none'}, recommendations ${recommendationsCount}).`,
|
|
4229
|
+
{
|
|
4230
|
+
status: trimString(readiness && readiness.status) || 'unknown',
|
|
4231
|
+
decision: trimString(readiness && readiness.decision) || 'unknown',
|
|
4232
|
+
storeType: trimString(baseline.storeType) || 'n/a',
|
|
4233
|
+
graphBackendStatus: trimString(baseline.graphBackendStatus) || 'n/a',
|
|
4234
|
+
graphBackendSignalKind: trimString(baseline.graphBackendSignalKind) || 'n/a',
|
|
4235
|
+
graphBackendIndependent: Boolean(baseline.graphBackendIndependent) ? 'yes' : 'no',
|
|
4236
|
+
queryBackendDefaultMode: trimString(baseline.queryBackendDefaultMode) || 'n/a',
|
|
4237
|
+
queryBackendScoreSignals: queryBackendScoreSignals.join(', ') || 'none',
|
|
4238
|
+
vectorAdapterStatus: trimString(baseline.vectorAdapterStatus) || 'n/a',
|
|
4239
|
+
vectorAdapterSignalKind: trimString(baseline.vectorAdapterSignalKind) || 'n/a',
|
|
4240
|
+
vectorAdapterIndependent: Boolean(baseline.vectorAdapterIndependent) ? 'yes' : 'no',
|
|
4241
|
+
vectorAdapterLinkedIntoQueryBackend: Boolean(baseline.vectorAdapterLinkedIntoQueryBackend)
|
|
4242
|
+
? 'yes'
|
|
4243
|
+
: 'no',
|
|
4244
|
+
repoRootSource: trimString(provenance.repoRootSource) || 'n/a',
|
|
4245
|
+
runtimeProjectRootAligned: Boolean(provenance.runtimeProjectRootAligned) ? 'yes' : 'no',
|
|
4246
|
+
mandatoryCheckIds: mandatoryCheckIds.join(', ') || 'none',
|
|
4247
|
+
promotionCriteriaPassed,
|
|
4248
|
+
promotionCriteriaTotal,
|
|
4249
|
+
promotionCriteriaCount: promotionCriteria.length,
|
|
4250
|
+
promotionCriteriaSatisfiedIds: promotionCriteriaSatisfiedIds.join(', ') || 'none',
|
|
4251
|
+
promotionCriteriaUnsatisfiedIds: promotionCriteriaUnsatisfiedIds.join(', ') || 'none',
|
|
4252
|
+
promotionBlockerIds: promotionBlockerIds.join(', ') || 'none',
|
|
4253
|
+
recommendationsCount,
|
|
4254
|
+
}
|
|
4255
|
+
)
|
|
4256
|
+
);
|
|
4257
|
+
} catch (error) {
|
|
4258
|
+
const errorMessage = trimString(error && error.message);
|
|
4259
|
+
diagnostics.lastFoundationReadiness = {
|
|
4260
|
+
requestedAt,
|
|
4261
|
+
respondedAt: nowIso(),
|
|
4262
|
+
status: 'failed',
|
|
4263
|
+
decision: '',
|
|
4264
|
+
storeType: '',
|
|
4265
|
+
graphBackendStatus: '',
|
|
4266
|
+
graphBackendSignalKind: '',
|
|
4267
|
+
graphBackendIndependent: false,
|
|
4268
|
+
queryBackendDefaultMode: '',
|
|
4269
|
+
queryBackendScoreSignals: [],
|
|
4270
|
+
vectorAdapterStatus: '',
|
|
4271
|
+
vectorAdapterSignalKind: '',
|
|
4272
|
+
vectorAdapterIndependent: false,
|
|
4273
|
+
vectorAdapterLinkedIntoQueryBackend: false,
|
|
4274
|
+
repoRootSource: '',
|
|
4275
|
+
runtimeProjectRootAligned: false,
|
|
4276
|
+
mandatoryCheckIds: [],
|
|
4277
|
+
mandatoryChecks: [],
|
|
4278
|
+
promotionCriteriaPassed: 0,
|
|
4279
|
+
promotionCriteriaTotal: 0,
|
|
4280
|
+
mandatoryChecksCount: 0,
|
|
4281
|
+
promotionCriteriaSatisfiedIds: [],
|
|
4282
|
+
promotionCriteriaUnsatisfiedIds: [],
|
|
4283
|
+
promotionCriteria: [],
|
|
4284
|
+
promotionBlockerIds: [],
|
|
4285
|
+
promotionBlockers: [],
|
|
4286
|
+
promotionBlockersCount: 0,
|
|
4287
|
+
recommendations: [],
|
|
4288
|
+
recommendationsCount: 0,
|
|
4289
|
+
};
|
|
4290
|
+
recordFailure('loadFoundationReadiness', errorMessage);
|
|
4291
|
+
appendMessage(
|
|
4292
|
+
'assistant',
|
|
4293
|
+
getI18nText(
|
|
4294
|
+
'agentWorkspace.messages.foundationReadinessFailed',
|
|
4295
|
+
`Foundation readiness request failed: ${errorMessage || 'unknown error'}.`
|
|
4296
|
+
)
|
|
4297
|
+
);
|
|
4298
|
+
console.error('[AgentWorkspace] foundation readiness request failed:', error);
|
|
4299
|
+
} finally {
|
|
4300
|
+
setBusy(false);
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
function bindDom() {
|
|
4305
|
+
dom.panel = document.getElementById('agent-workspace-panel');
|
|
4306
|
+
dom.form = document.getElementById('agent-workspace-form');
|
|
4307
|
+
dom.userIdInput = document.getElementById('agent-workspace-user-id');
|
|
4308
|
+
dom.input = document.getElementById('agent-workspace-input');
|
|
4309
|
+
dom.sendButton = document.getElementById('agent-workspace-send');
|
|
4310
|
+
dom.messages = document.getElementById('agent-workspace-messages');
|
|
4311
|
+
dom.knowledgeList = document.getElementById('agent-workspace-knowledge-list');
|
|
4312
|
+
dom.openPathButton = document.getElementById('agent-workspace-open-learning-path');
|
|
4313
|
+
dom.closePathButton = document.getElementById('agent-workspace-close-learning-path');
|
|
4314
|
+
dom.pathFullscreenButton = document.getElementById('agent-workspace-path-fullscreen');
|
|
4315
|
+
dom.foundationReadinessButton = document.getElementById('agent-workspace-open-foundation-readiness');
|
|
4316
|
+
if (!dom.panel || !dom.form || !dom.input || !dom.sendButton || !dom.messages || !dom.knowledgeList) {
|
|
4317
|
+
return false;
|
|
4318
|
+
}
|
|
4319
|
+
return true;
|
|
4320
|
+
}
|
|
4321
|
+
|
|
4322
|
+
function applyI18nPlaceholders() {
|
|
4323
|
+
if (dom.input) {
|
|
4324
|
+
dom.input.placeholder = getI18nText(
|
|
4325
|
+
'agentWorkspace.placeholders.input',
|
|
4326
|
+
'Ask agent to find local knowledge and run actions...'
|
|
4327
|
+
);
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4330
|
+
|
|
4331
|
+
function init() {
|
|
4332
|
+
if (state.initialized || !globalScope.document) {
|
|
4333
|
+
return;
|
|
4334
|
+
}
|
|
4335
|
+
if (!bindDom()) {
|
|
4336
|
+
return;
|
|
4337
|
+
}
|
|
4338
|
+
state.initialized = true;
|
|
4339
|
+
document.body.classList.add(BODY_CLASS_ENABLED);
|
|
4340
|
+
applyI18nPlaceholders();
|
|
4341
|
+
|
|
4342
|
+
if (dom.userIdInput) {
|
|
4343
|
+
dom.userIdInput.value = trimString(options.defaultUserId) || 'agent_user_default';
|
|
4344
|
+
}
|
|
4345
|
+
dom.form.addEventListener('submit', async (event) => {
|
|
4346
|
+
event.preventDefault();
|
|
4347
|
+
await sendConversation();
|
|
4348
|
+
});
|
|
4349
|
+
if (dom.openPathButton) {
|
|
4350
|
+
dom.openPathButton.addEventListener('click', () => {
|
|
4351
|
+
const activePoint = findKnowledgePoint(resolvePathAtomId(''));
|
|
4352
|
+
if (activePoint) {
|
|
4353
|
+
triggerPointAction('open_learning_path', activePoint);
|
|
4354
|
+
return;
|
|
4355
|
+
}
|
|
4356
|
+
openLearningPathDock('');
|
|
4357
|
+
});
|
|
4358
|
+
}
|
|
4359
|
+
if (dom.closePathButton) {
|
|
4360
|
+
dom.closePathButton.addEventListener('click', () => {
|
|
4361
|
+
hidePathDock();
|
|
4362
|
+
});
|
|
4363
|
+
}
|
|
4364
|
+
if (dom.pathFullscreenButton) {
|
|
4365
|
+
dom.pathFullscreenButton.addEventListener('click', () => {
|
|
4366
|
+
togglePathFullscreen();
|
|
4367
|
+
});
|
|
4368
|
+
}
|
|
4369
|
+
if (dom.foundationReadinessButton) {
|
|
4370
|
+
dom.foundationReadinessButton.addEventListener('click', () => {
|
|
4371
|
+
void loadFoundationReadiness();
|
|
4372
|
+
});
|
|
4373
|
+
}
|
|
4374
|
+
globalScope.addEventListener('nc:pathmode:exited', () => {
|
|
4375
|
+
hidePathDock();
|
|
4376
|
+
});
|
|
4377
|
+
if (globalScope.i18n && typeof globalScope.i18n.onLanguageChange === 'function') {
|
|
4378
|
+
globalScope.i18n.onLanguageChange(() => {
|
|
4379
|
+
applyI18nPlaceholders();
|
|
4380
|
+
refreshToolbarButtons();
|
|
4381
|
+
renderKnowledgePoints(state.latestKnowledgePoints);
|
|
4382
|
+
});
|
|
4383
|
+
}
|
|
4384
|
+
appendMessage(
|
|
4385
|
+
'system',
|
|
4386
|
+
getI18nText(
|
|
4387
|
+
'agentWorkspace.messages.ready',
|
|
4388
|
+
'Agent workspace ready. Ask for a topic to retrieve local knowledge points.'
|
|
4389
|
+
)
|
|
4390
|
+
);
|
|
4391
|
+
refreshToolbarButtons();
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
return {
|
|
4395
|
+
init,
|
|
4396
|
+
sendConversation,
|
|
4397
|
+
loadFoundationReadiness,
|
|
4398
|
+
openLearningPathDock,
|
|
4399
|
+
hidePathDock,
|
|
4400
|
+
togglePathFullscreen,
|
|
4401
|
+
getDiagnosticsSnapshot,
|
|
4402
|
+
getDiagnosticsTrendSnapshot,
|
|
4403
|
+
getDiagnosticsIndexSnapshot,
|
|
4404
|
+
exportDiagnosticsReport,
|
|
4405
|
+
persistDiagnosticsReport,
|
|
4406
|
+
_state: state,
|
|
4407
|
+
};
|
|
4408
|
+
}
|
|
4409
|
+
|
|
4410
|
+
function initAgentWorkspaceRuntime(options = {}) {
|
|
4411
|
+
const runtime = createAgentWorkspaceRuntime(options);
|
|
4412
|
+
runtime.init();
|
|
4413
|
+
if (globalScope && typeof globalScope === 'object') {
|
|
4414
|
+
globalScope.__noteConnectionAgentWorkspaceRuntimeInstance = runtime;
|
|
4415
|
+
}
|
|
4416
|
+
return runtime;
|
|
4417
|
+
}
|
|
4418
|
+
|
|
4419
|
+
if (globalScope && globalScope.document) {
|
|
4420
|
+
if (document.readyState === 'loading') {
|
|
4421
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
4422
|
+
initAgentWorkspaceRuntime();
|
|
4423
|
+
});
|
|
4424
|
+
} else {
|
|
4425
|
+
initAgentWorkspaceRuntime();
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
return {
|
|
4430
|
+
createAgentWorkspaceRuntime,
|
|
4431
|
+
initAgentWorkspaceRuntime,
|
|
4432
|
+
};
|
|
4433
|
+
}
|
|
4434
|
+
);
|