@monoes/monomindcli 1.6.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/.claude/agents/academic/academic-anthropologist.md +126 -0
- package/.claude/agents/academic/academic-geographer.md +128 -0
- package/.claude/agents/academic/academic-historian.md +124 -0
- package/.claude/agents/academic/academic-narratologist.md +119 -0
- package/.claude/agents/academic/academic-psychologist.md +119 -0
- package/.claude/agents/analysis/analyze-code-quality.md +58 -0
- package/.claude/agents/analysis/code-analyzer.md +189 -0
- package/.claude/agents/analysis/code-review/analyze-code-quality.md +58 -0
- package/.claude/agents/architecture/system-design/arch-system-design.md +54 -0
- package/.claude/agents/consensus/crdt-synchronizer.md +977 -0
- package/.claude/agents/consensus/performance-benchmarker.md +831 -0
- package/.claude/agents/consensus/quorum-manager.md +803 -0
- package/.claude/agents/consensus/security-manager.md +602 -0
- package/.claude/agents/core/coder.md +262 -0
- package/.claude/agents/core/planner.md +170 -0
- package/.claude/agents/core/researcher.md +192 -0
- package/.claude/agents/core/reviewer.md +327 -0
- package/.claude/agents/core/tester.md +318 -0
- package/.claude/agents/data/ml/data-ml-model.md +76 -0
- package/.claude/agents/design/design-brand-guardian.md +323 -0
- package/.claude/agents/design/design-image-prompt-engineer.md +237 -0
- package/.claude/agents/design/design-inclusive-visuals-specialist.md +72 -0
- package/.claude/agents/design/design-ui-designer.md +384 -0
- package/.claude/agents/design/design-ux-architect.md +470 -0
- package/.claude/agents/design/design-ux-researcher.md +330 -0
- package/.claude/agents/design/design-visual-storyteller.md +150 -0
- package/.claude/agents/design/design-whimsy-injector.md +439 -0
- package/.claude/agents/development/dev-backend-api.md +178 -0
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +52 -0
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +63 -0
- package/.claude/agents/engineering/engineering-ai-data-remediation-engineer.md +212 -0
- package/.claude/agents/engineering/engineering-ai-engineer.md +165 -0
- package/.claude/agents/engineering/engineering-autonomous-optimization-architect.md +108 -0
- package/.claude/agents/engineering/engineering-backend-architect.md +254 -0
- package/.claude/agents/engineering/engineering-code-reviewer.md +95 -0
- package/.claude/agents/engineering/engineering-data-engineer.md +307 -0
- package/.claude/agents/engineering/engineering-database-optimizer.md +200 -0
- package/.claude/agents/engineering/engineering-devops-automator.md +430 -0
- package/.claude/agents/engineering/engineering-embedded-firmware-engineer.md +174 -0
- package/.claude/agents/engineering/engineering-feishu-integration-developer.md +607 -0
- package/.claude/agents/engineering/engineering-frontend-developer.md +249 -0
- package/.claude/agents/engineering/engineering-git-workflow-master.md +108 -0
- package/.claude/agents/engineering/engineering-incident-response-commander.md +482 -0
- package/.claude/agents/engineering/engineering-mobile-app-builder.md +499 -0
- package/.claude/agents/engineering/engineering-rapid-prototyper.md +463 -0
- package/.claude/agents/engineering/engineering-security-engineer.md +303 -0
- package/.claude/agents/engineering/engineering-senior-developer.md +195 -0
- package/.claude/agents/engineering/engineering-software-architect.md +100 -0
- package/.claude/agents/engineering/engineering-solidity-smart-contract-engineer.md +528 -0
- package/.claude/agents/engineering/engineering-sre.md +114 -0
- package/.claude/agents/engineering/engineering-technical-writer.md +412 -0
- package/.claude/agents/engineering/engineering-threat-detection-engineer.md +540 -0
- package/.claude/agents/engineering/engineering-wechat-mini-program-developer.md +351 -0
- package/.claude/agents/game-development/blender/blender-addon-engineer.md +235 -0
- package/.claude/agents/game-development/game-audio-engineer.md +265 -0
- package/.claude/agents/game-development/game-designer.md +168 -0
- package/.claude/agents/game-development/godot/godot-gameplay-scripter.md +335 -0
- package/.claude/agents/game-development/godot/godot-multiplayer-engineer.md +298 -0
- package/.claude/agents/game-development/godot/godot-shader-developer.md +267 -0
- package/.claude/agents/game-development/level-designer.md +209 -0
- package/.claude/agents/game-development/narrative-designer.md +244 -0
- package/.claude/agents/game-development/roblox-studio/roblox-avatar-creator.md +298 -0
- package/.claude/agents/game-development/roblox-studio/roblox-experience-designer.md +306 -0
- package/.claude/agents/game-development/roblox-studio/roblox-systems-scripter.md +326 -0
- package/.claude/agents/game-development/technical-artist.md +230 -0
- package/.claude/agents/game-development/unity/unity-architect.md +272 -0
- package/.claude/agents/game-development/unity/unity-editor-tool-developer.md +311 -0
- package/.claude/agents/game-development/unity/unity-multiplayer-engineer.md +322 -0
- package/.claude/agents/game-development/unity/unity-shader-graph-artist.md +270 -0
- package/.claude/agents/game-development/unreal-engine/unreal-multiplayer-architect.md +314 -0
- package/.claude/agents/game-development/unreal-engine/unreal-systems-engineer.md +311 -0
- package/.claude/agents/game-development/unreal-engine/unreal-technical-artist.md +257 -0
- package/.claude/agents/game-development/unreal-engine/unreal-world-builder.md +274 -0
- package/.claude/agents/github/code-review-swarm.md +557 -0
- package/.claude/agents/github/github-modes.md +154 -0
- package/.claude/agents/github/issue-tracker.md +299 -0
- package/.claude/agents/github/multi-repo-swarm.md +525 -0
- package/.claude/agents/github/pr-manager.md +163 -0
- package/.claude/agents/github/project-board-sync.md +478 -0
- package/.claude/agents/github/release-manager.md +352 -0
- package/.claude/agents/github/release-swarm.md +597 -0
- package/.claude/agents/github/repo-architect.md +378 -0
- package/.claude/agents/github/swarm-issue.md +548 -0
- package/.claude/agents/github/swarm-pr.md +427 -0
- package/.claude/agents/github/sync-coordinator.md +423 -0
- package/.claude/agents/github/workflow-automation.md +640 -0
- package/.claude/agents/goal/agent.md +804 -0
- package/.claude/agents/goal/code-goal-planner.md +445 -0
- package/.claude/agents/goal/goal-planner.md +168 -0
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -0
- package/.claude/agents/hive-mind/queen-coordinator.md +202 -0
- package/.claude/agents/hive-mind/scout-explorer.md +241 -0
- package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -0
- package/.claude/agents/hive-mind/worker-specialist.md +216 -0
- package/.claude/agents/marketing/marketing-ai-citation-strategist.md +171 -0
- package/.claude/agents/marketing/marketing-app-store-optimizer.md +322 -0
- package/.claude/agents/marketing/marketing-baidu-seo-specialist.md +227 -0
- package/.claude/agents/marketing/marketing-bilibili-content-strategist.md +200 -0
- package/.claude/agents/marketing/marketing-book-co-author.md +111 -0
- package/.claude/agents/marketing/marketing-carousel-growth-engine.md +200 -0
- package/.claude/agents/marketing/marketing-china-ecommerce-operator.md +284 -0
- package/.claude/agents/marketing/marketing-content-creator.md +54 -0
- package/.claude/agents/marketing/marketing-cross-border-ecommerce.md +260 -0
- package/.claude/agents/marketing/marketing-douyin-strategist.md +150 -0
- package/.claude/agents/marketing/marketing-growth-hacker.md +54 -0
- package/.claude/agents/marketing/marketing-instagram-curator.md +114 -0
- package/.claude/agents/marketing/marketing-kuaishou-strategist.md +224 -0
- package/.claude/agents/marketing/marketing-linkedin-content-creator.md +215 -0
- package/.claude/agents/marketing/marketing-livestream-commerce-coach.md +306 -0
- package/.claude/agents/marketing/marketing-podcast-strategist.md +278 -0
- package/.claude/agents/marketing/marketing-private-domain-operator.md +309 -0
- package/.claude/agents/marketing/marketing-reddit-community-builder.md +124 -0
- package/.claude/agents/marketing/marketing-seo-specialist.md +279 -0
- package/.claude/agents/marketing/marketing-short-video-editing-coach.md +413 -0
- package/.claude/agents/marketing/marketing-social-media-strategist.md +125 -0
- package/.claude/agents/marketing/marketing-tiktok-strategist.md +126 -0
- package/.claude/agents/marketing/marketing-twitter-engager.md +127 -0
- package/.claude/agents/marketing/marketing-wechat-official-account.md +146 -0
- package/.claude/agents/marketing/marketing-weibo-strategist.md +241 -0
- package/.claude/agents/marketing/marketing-xiaohongshu-specialist.md +139 -0
- package/.claude/agents/marketing/marketing-zhihu-strategist.md +163 -0
- package/.claude/agents/neural/safla-neural.md +74 -0
- package/.claude/agents/optimization/benchmark-suite.md +663 -0
- package/.claude/agents/optimization/load-balancer.md +429 -0
- package/.claude/agents/optimization/performance-monitor.md +670 -0
- package/.claude/agents/optimization/resource-allocator.md +672 -0
- package/.claude/agents/optimization/topology-optimizer.md +806 -0
- package/.claude/agents/paid-media/paid-media-auditor.md +71 -0
- package/.claude/agents/paid-media/paid-media-creative-strategist.md +71 -0
- package/.claude/agents/paid-media/paid-media-paid-social-strategist.md +71 -0
- package/.claude/agents/paid-media/paid-media-ppc-strategist.md +71 -0
- package/.claude/agents/paid-media/paid-media-programmatic-buyer.md +71 -0
- package/.claude/agents/paid-media/paid-media-search-query-analyst.md +71 -0
- package/.claude/agents/paid-media/paid-media-tracking-specialist.md +71 -0
- package/.claude/agents/payments/agentic-payments.md +126 -0
- package/.claude/agents/product/product-behavioral-nudge-engine.md +81 -0
- package/.claude/agents/product/product-feedback-synthesizer.md +119 -0
- package/.claude/agents/product/product-manager.md +469 -0
- package/.claude/agents/product/product-sprint-prioritizer.md +154 -0
- package/.claude/agents/product/product-trend-researcher.md +159 -0
- package/.claude/agents/project-management/project-management-experiment-tracker.md +199 -0
- package/.claude/agents/project-management/project-management-jira-workflow-steward.md +231 -0
- package/.claude/agents/project-management/project-management-project-shepherd.md +195 -0
- package/.claude/agents/project-management/project-management-studio-operations.md +201 -0
- package/.claude/agents/project-management/project-management-studio-producer.md +204 -0
- package/.claude/agents/project-management/project-manager-senior.md +136 -0
- package/.claude/agents/reasoning/agent.md +804 -0
- package/.claude/agents/reasoning/goal-planner.md +73 -0
- package/.claude/agents/sales/sales-account-strategist.md +228 -0
- package/.claude/agents/sales/sales-coach.md +272 -0
- package/.claude/agents/sales/sales-deal-strategist.md +181 -0
- package/.claude/agents/sales/sales-discovery-coach.md +226 -0
- package/.claude/agents/sales/sales-engineer.md +183 -0
- package/.claude/agents/sales/sales-outbound-strategist.md +202 -0
- package/.claude/agents/sales/sales-pipeline-analyst.md +268 -0
- package/.claude/agents/sales/sales-proposal-strategist.md +218 -0
- package/.claude/agents/schemas/architecture-output.json +43 -0
- package/.claude/agents/schemas/code-review-output.json +28 -0
- package/.claude/agents/schemas/generic-task-input.json +12 -0
- package/.claude/agents/schemas/implementation-output.json +18 -0
- package/.claude/agents/schemas/research-output.json +31 -0
- package/.claude/agents/schemas/security-audit-output.json +29 -0
- package/.claude/agents/schemas/test-report-output.json +29 -0
- package/.claude/agents/sona/sona-learning-optimizer.md +65 -0
- package/.claude/agents/sparc/architecture.md +453 -0
- package/.claude/agents/sparc/pseudocode.md +299 -0
- package/.claude/agents/sparc/refinement.md +504 -0
- package/.claude/agents/sparc/specification.md +258 -0
- package/.claude/agents/spatial-computing/macos-spatial-metal-engineer.md +338 -0
- package/.claude/agents/spatial-computing/terminal-integration-specialist.md +71 -0
- package/.claude/agents/spatial-computing/visionos-spatial-engineer.md +55 -0
- package/.claude/agents/specialized/accounts-payable-agent.md +186 -0
- package/.claude/agents/specialized/agentic-identity-trust.md +388 -0
- package/.claude/agents/specialized/agents-orchestrator.md +368 -0
- package/.claude/agents/specialized/automation-governance-architect.md +217 -0
- package/.claude/agents/specialized/blockchain-security-auditor.md +497 -0
- package/.claude/agents/specialized/compliance-auditor.md +159 -0
- package/.claude/agents/specialized/corporate-training-designer.md +193 -0
- package/.claude/agents/specialized/data-consolidation-agent.md +61 -0
- package/.claude/agents/specialized/government-digital-presales-consultant.md +364 -0
- package/.claude/agents/specialized/healthcare-marketing-compliance.md +396 -0
- package/.claude/agents/specialized/identity-graph-operator.md +261 -0
- package/.claude/agents/specialized/lsp-index-engineer.md +315 -0
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +89 -0
- package/.claude/agents/specialized/recruitment-specialist.md +510 -0
- package/.claude/agents/specialized/report-distribution-agent.md +66 -0
- package/.claude/agents/specialized/sales-data-extraction-agent.md +68 -0
- package/.claude/agents/specialized/specialized-cultural-intelligence-strategist.md +89 -0
- package/.claude/agents/specialized/specialized-developer-advocate.md +318 -0
- package/.claude/agents/specialized/specialized-document-generator.md +56 -0
- package/.claude/agents/specialized/specialized-french-consulting-market.md +193 -0
- package/.claude/agents/specialized/specialized-korean-business-navigator.md +217 -0
- package/.claude/agents/specialized/specialized-mcp-builder.md +64 -0
- package/.claude/agents/specialized/specialized-model-qa.md +489 -0
- package/.claude/agents/specialized/specialized-salesforce-architect.md +181 -0
- package/.claude/agents/specialized/specialized-workflow-architect.md +598 -0
- package/.claude/agents/specialized/study-abroad-advisor.md +283 -0
- package/.claude/agents/specialized/supply-chain-strategist.md +583 -0
- package/.claude/agents/specialized/zk-steward.md +212 -0
- package/.claude/agents/sublinear/consensus-coordinator.md +333 -0
- package/.claude/agents/sublinear/matrix-optimizer.md +180 -0
- package/.claude/agents/sublinear/pagerank-analyzer.md +295 -0
- package/.claude/agents/sublinear/performance-optimizer.md +363 -0
- package/.claude/agents/sublinear/trading-predictor.md +242 -0
- package/.claude/agents/support/support-analytics-reporter.md +366 -0
- package/.claude/agents/support/support-executive-summary-generator.md +213 -0
- package/.claude/agents/support/support-finance-tracker.md +443 -0
- package/.claude/agents/support/support-infrastructure-maintainer.md +619 -0
- package/.claude/agents/support/support-legal-compliance-checker.md +589 -0
- package/.claude/agents/support/support-support-responder.md +586 -0
- package/.claude/agents/swarm/adaptive-coordinator.md +364 -0
- package/.claude/agents/swarm/hierarchical-coordinator.md +318 -0
- package/.claude/agents/swarm/mesh-coordinator.md +363 -0
- package/.claude/agents/templates/automation-smart-agent.md +185 -0
- package/.claude/agents/templates/coordinator-swarm-init.md +83 -0
- package/.claude/agents/templates/github-pr-manager.md +155 -0
- package/.claude/agents/templates/implementer-sparc-coder.md +231 -0
- package/.claude/agents/templates/memory-coordinator.md +163 -0
- package/.claude/agents/templates/migration-plan.md +724 -0
- package/.claude/agents/templates/orchestrator-task.md +120 -0
- package/.claude/agents/templates/performance-analyzer.md +179 -0
- package/.claude/agents/templates/sparc-coordinator.md +163 -0
- package/.claude/agents/testing/production-validator.md +374 -0
- package/.claude/agents/testing/tdd-london-swarm.md +241 -0
- package/.claude/agents/testing/testing-accessibility-auditor.md +322 -0
- package/.claude/agents/testing/testing-api-tester.md +307 -0
- package/.claude/agents/testing/testing-evidence-collector.md +211 -0
- package/.claude/agents/testing/testing-performance-benchmarker.md +269 -0
- package/.claude/agents/testing/testing-reality-checker.md +237 -0
- package/.claude/agents/testing/testing-test-results-analyzer.md +306 -0
- package/.claude/agents/testing/testing-tool-evaluator.md +395 -0
- package/.claude/agents/testing/testing-workflow-optimizer.md +451 -0
- package/.claude/agents/v3/integration-architect.md +338 -0
- package/.claude/agents/v3/memory-specialist.md +298 -0
- package/.claude/agents/v3/performance-engineer.md +387 -0
- package/.claude/agents/v3/queen-coordinator.md +67 -0
- package/.claude/agents/v3/security-architect.md +154 -0
- package/.claude/commands/agents/README.md +10 -0
- package/.claude/commands/agents/agent-capabilities.md +21 -0
- package/.claude/commands/agents/agent-coordination.md +28 -0
- package/.claude/commands/agents/agent-spawning.md +28 -0
- package/.claude/commands/agents/agent-types.md +26 -0
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
- package/.claude/commands/analysis/README.md +9 -0
- package/.claude/commands/analysis/bottleneck-detect.md +162 -0
- package/.claude/commands/analysis/performance-bottlenecks.md +59 -0
- package/.claude/commands/analysis/performance-report.md +25 -0
- package/.claude/commands/analysis/token-efficiency.md +45 -0
- package/.claude/commands/analysis/token-usage.md +25 -0
- package/.claude/commands/automation/README.md +9 -0
- package/.claude/commands/automation/auto-agent.md +122 -0
- package/.claude/commands/automation/self-healing.md +106 -0
- package/.claude/commands/automation/session-memory.md +90 -0
- package/.claude/commands/automation/smart-agents.md +73 -0
- package/.claude/commands/automation/smart-spawn.md +25 -0
- package/.claude/commands/automation/workflow-select.md +25 -0
- package/.claude/commands/browse.md +27 -0
- package/.claude/commands/coordination/README.md +9 -0
- package/.claude/commands/coordination/agent-spawn.md +25 -0
- package/.claude/commands/coordination/init.md +44 -0
- package/.claude/commands/coordination/orchestrate.md +43 -0
- package/.claude/commands/coordination/spawn.md +45 -0
- package/.claude/commands/coordination/swarm-init.md +85 -0
- package/.claude/commands/coordination/task-orchestrate.md +25 -0
- package/.claude/commands/github/README.md +11 -0
- package/.claude/commands/github/code-review-swarm.md +550 -0
- package/.claude/commands/github/code-review.md +25 -0
- package/.claude/commands/github/github-modes.md +147 -0
- package/.claude/commands/github/github-swarm.md +121 -0
- package/.claude/commands/github/issue-tracker.md +292 -0
- package/.claude/commands/github/issue-triage.md +25 -0
- package/.claude/commands/github/multi-repo-swarm.md +519 -0
- package/.claude/commands/github/pr-enhance.md +26 -0
- package/.claude/commands/github/pr-manager.md +170 -0
- package/.claude/commands/github/project-board-sync.md +471 -0
- package/.claude/commands/github/release-manager.md +355 -0
- package/.claude/commands/github/release-swarm.md +590 -0
- package/.claude/commands/github/repo-analyze.md +25 -0
- package/.claude/commands/github/repo-architect.md +381 -0
- package/.claude/commands/github/swarm-issue.md +482 -0
- package/.claude/commands/github/swarm-pr.md +310 -0
- package/.claude/commands/github/sync-coordinator.md +301 -0
- package/.claude/commands/github/workflow-automation.md +468 -0
- package/.claude/commands/hive-mind/README.md +17 -0
- package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-init.md +18 -0
- package/.claude/commands/hive-mind/hive-mind-memory.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-resume.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -0
- package/.claude/commands/hive-mind/hive-mind-status.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-stop.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -0
- package/.claude/commands/hive-mind/hive-mind.md +27 -0
- package/.claude/commands/hooks/README.md +11 -0
- package/.claude/commands/hooks/overview.md +58 -0
- package/.claude/commands/hooks/post-edit.md +117 -0
- package/.claude/commands/hooks/post-task.md +112 -0
- package/.claude/commands/hooks/pre-edit.md +113 -0
- package/.claude/commands/hooks/pre-task.md +111 -0
- package/.claude/commands/hooks/session-end.md +118 -0
- package/.claude/commands/hooks/setup.md +103 -0
- package/.claude/commands/list-agents.md +17 -0
- package/.claude/commands/mastermind.md +121 -0
- package/.claude/commands/memory/README.md +9 -0
- package/.claude/commands/memory/memory-persist.md +25 -0
- package/.claude/commands/memory/memory-search.md +25 -0
- package/.claude/commands/memory/memory-usage.md +25 -0
- package/.claude/commands/memory/neural.md +47 -0
- package/.claude/commands/metrics.md +11 -0
- package/.claude/commands/monitoring/README.md +9 -0
- package/.claude/commands/monitoring/agent-metrics.md +25 -0
- package/.claude/commands/monitoring/agents.md +44 -0
- package/.claude/commands/monitoring/real-time-view.md +25 -0
- package/.claude/commands/monitoring/status.md +46 -0
- package/.claude/commands/monitoring/swarm-monitor.md +25 -0
- package/.claude/commands/monobrain-help.md +103 -0
- package/.claude/commands/monobrain-memory.md +107 -0
- package/.claude/commands/monobrain-swarm.md +205 -0
- package/.claude/commands/monomind-do.md +276 -0
- package/.claude/commands/monomind-idea.md +269 -0
- package/.claude/commands/monomind-repeat.md +95 -0
- package/.claude/commands/optimization/README.md +9 -0
- package/.claude/commands/optimization/auto-topology.md +62 -0
- package/.claude/commands/optimization/cache-manage.md +25 -0
- package/.claude/commands/optimization/parallel-execution.md +50 -0
- package/.claude/commands/optimization/topology-optimize.md +25 -0
- package/.claude/commands/pair/README.md +261 -0
- package/.claude/commands/pair/commands.md +546 -0
- package/.claude/commands/pair/config.md +510 -0
- package/.claude/commands/pair/examples.md +512 -0
- package/.claude/commands/pair/modes.md +348 -0
- package/.claude/commands/pair/session.md +407 -0
- package/.claude/commands/pair/start.md +209 -0
- package/.claude/commands/sparc/analyzer.md +52 -0
- package/.claude/commands/sparc/architect.md +53 -0
- package/.claude/commands/sparc/ask.md +97 -0
- package/.claude/commands/sparc/batch-executor.md +54 -0
- package/.claude/commands/sparc/code.md +89 -0
- package/.claude/commands/sparc/coder.md +54 -0
- package/.claude/commands/sparc/debug.md +83 -0
- package/.claude/commands/sparc/debugger.md +54 -0
- package/.claude/commands/sparc/designer.md +53 -0
- package/.claude/commands/sparc/devops.md +109 -0
- package/.claude/commands/sparc/docs-writer.md +80 -0
- package/.claude/commands/sparc/documenter.md +54 -0
- package/.claude/commands/sparc/innovator.md +54 -0
- package/.claude/commands/sparc/integration.md +83 -0
- package/.claude/commands/sparc/mcp.md +117 -0
- package/.claude/commands/sparc/memory-manager.md +54 -0
- package/.claude/commands/sparc/optimizer.md +54 -0
- package/.claude/commands/sparc/orchestrator.md +132 -0
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -0
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -0
- package/.claude/commands/sparc/researcher.md +54 -0
- package/.claude/commands/sparc/reviewer.md +54 -0
- package/.claude/commands/sparc/security-review.md +80 -0
- package/.claude/commands/sparc/sparc-modes.md +174 -0
- package/.claude/commands/sparc/sparc.md +111 -0
- package/.claude/commands/sparc/spec-pseudocode.md +80 -0
- package/.claude/commands/sparc/supabase-admin.md +348 -0
- package/.claude/commands/sparc/swarm-coordinator.md +54 -0
- package/.claude/commands/sparc/tdd.md +54 -0
- package/.claude/commands/sparc/tester.md +54 -0
- package/.claude/commands/sparc/tutorial.md +79 -0
- package/.claude/commands/sparc/workflow-manager.md +54 -0
- package/.claude/commands/sparc.md +166 -0
- package/.claude/commands/stream-chain/pipeline.md +121 -0
- package/.claude/commands/stream-chain/run.md +70 -0
- package/.claude/commands/swarm/README.md +15 -0
- package/.claude/commands/swarm/analysis.md +95 -0
- package/.claude/commands/swarm/development.md +96 -0
- package/.claude/commands/swarm/examples.md +168 -0
- package/.claude/commands/swarm/maintenance.md +102 -0
- package/.claude/commands/swarm/optimization.md +117 -0
- package/.claude/commands/swarm/research.md +136 -0
- package/.claude/commands/swarm/swarm-analysis.md +8 -0
- package/.claude/commands/swarm/swarm-background.md +8 -0
- package/.claude/commands/swarm/swarm-modes.md +8 -0
- package/.claude/commands/swarm/swarm-monitor.md +8 -0
- package/.claude/commands/swarm/swarm-status.md +8 -0
- package/.claude/commands/swarm/swarm-strategies.md +8 -0
- package/.claude/commands/swarm/swarm.md +27 -0
- package/.claude/commands/swarm/testing.md +131 -0
- package/.claude/commands/tokens.md +13 -0
- package/.claude/commands/training/README.md +9 -0
- package/.claude/commands/training/model-update.md +25 -0
- package/.claude/commands/training/neural-patterns.md +74 -0
- package/.claude/commands/training/neural-train.md +25 -0
- package/.claude/commands/training/pattern-learn.md +25 -0
- package/.claude/commands/training/specialization.md +63 -0
- package/.claude/commands/truth/start.md +143 -0
- package/.claude/commands/ts.md +9 -0
- package/.claude/commands/use-agent.md +67 -0
- package/.claude/commands/verify/check.md +50 -0
- package/.claude/commands/verify/start.md +128 -0
- package/.claude/commands/workflows/README.md +9 -0
- package/.claude/commands/workflows/development.md +78 -0
- package/.claude/commands/workflows/research.md +63 -0
- package/.claude/commands/workflows/workflow-create.md +25 -0
- package/.claude/commands/workflows/workflow-execute.md +25 -0
- package/.claude/commands/workflows/workflow-export.md +25 -0
- package/.claude/helpers/README.md +105 -0
- package/.claude/helpers/auto-memory-hook.mjs +369 -0
- package/.claude/helpers/context-persistence-hook.mjs +1988 -0
- package/.claude/helpers/extras-registry.json +3028 -0
- package/.claude/helpers/graphify-freshen.cjs +109 -0
- package/.claude/helpers/hook-handler.cjs +1446 -0
- package/.claude/helpers/intelligence.cjs +227 -0
- package/.claude/helpers/learning-service.mjs +1144 -0
- package/.claude/helpers/memory-palace.cjs +401 -0
- package/.claude/helpers/memory.cjs +84 -0
- package/.claude/helpers/metrics-db.mjs +488 -0
- package/.claude/helpers/router.cjs +306 -0
- package/.claude/helpers/session.cjs +125 -0
- package/.claude/helpers/skill-registry.json +961 -0
- package/.claude/helpers/statusline.cjs +1276 -0
- package/.claude/helpers/swarm-hooks.sh +761 -0
- package/.claude/helpers/toggle-statusline.cjs +58 -0
- package/.claude/helpers/token-tracker.cjs +934 -0
- package/.claude/skills/agent-browser-testing/SKILL.md +312 -0
- package/.claude/skills/agentdb-advanced/SKILL.md +550 -0
- package/.claude/skills/agentdb-learning/SKILL.md +545 -0
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -0
- package/.claude/skills/agentdb-optimization/SKILL.md +509 -0
- package/.claude/skills/agentdb-vector-search/SKILL.md +339 -0
- package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
- package/.claude/skills/github-code-review/SKILL.md +1148 -0
- package/.claude/skills/github-multi-repo/SKILL.md +916 -0
- package/.claude/skills/github-project-management/SKILL.md +1250 -0
- package/.claude/skills/github-release-management/SKILL.md +1124 -0
- package/.claude/skills/github-workflow-automation/SKILL.md +1111 -0
- package/.claude/skills/hive-mind-advanced/SKILL.md +709 -0
- package/.claude/skills/hooks-automation/SKILL.md +1200 -0
- package/.claude/skills/pair-programming/SKILL.md +1202 -0
- package/.claude/skills/performance-analysis/SKILL.md +560 -0
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -0
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/.claude/skills/sparc-methodology/SKILL.md +1106 -0
- package/.claude/skills/specialagent/SKILL.md +208 -0
- package/.claude/skills/stream-chain/SKILL.md +560 -0
- package/.claude/skills/swarm-advanced/SKILL.md +970 -0
- package/.claude/skills/swarm-orchestration/SKILL.md +179 -0
- package/.claude/skills/v3-cli-modernization/SKILL.md +941 -0
- package/.claude/skills/v3-core-implementation/SKILL.md +867 -0
- package/.claude/skills/v3-ddd-architecture/SKILL.md +451 -0
- package/.claude/skills/v3-integration-deep/SKILL.md +258 -0
- package/.claude/skills/v3-mcp-optimization/SKILL.md +816 -0
- package/.claude/skills/v3-memory-unification/SKILL.md +180 -0
- package/.claude/skills/v3-performance-optimization/SKILL.md +408 -0
- package/.claude/skills/v3-security-overhaul/SKILL.md +91 -0
- package/.claude/skills/v3-swarm-coordination/SKILL.md +433 -0
- package/.claude/skills/verification-quality/SKILL.md +674 -0
- package/README.md +687 -0
- package/bin/cli.js +156 -0
- package/bin/mcp-server.js +189 -0
- package/bin/preinstall.cjs +2 -0
- package/dist/src/agents/halt-signal.d.ts +25 -0
- package/dist/src/agents/halt-signal.d.ts.map +1 -0
- package/dist/src/agents/halt-signal.js +50 -0
- package/dist/src/agents/halt-signal.js.map +1 -0
- package/dist/src/agents/index.d.ts +18 -0
- package/dist/src/agents/index.d.ts.map +1 -0
- package/dist/src/agents/index.js +13 -0
- package/dist/src/agents/index.js.map +1 -0
- package/dist/src/agents/managed-agent.d.ts +41 -0
- package/dist/src/agents/managed-agent.d.ts.map +1 -0
- package/dist/src/agents/managed-agent.js +66 -0
- package/dist/src/agents/managed-agent.js.map +1 -0
- package/dist/src/agents/prompt-experiment.d.ts +22 -0
- package/dist/src/agents/prompt-experiment.d.ts.map +1 -0
- package/dist/src/agents/prompt-experiment.js +49 -0
- package/dist/src/agents/prompt-experiment.js.map +1 -0
- package/dist/src/agents/prompt-version-manager.d.ts +19 -0
- package/dist/src/agents/prompt-version-manager.d.ts.map +1 -0
- package/dist/src/agents/prompt-version-manager.js +58 -0
- package/dist/src/agents/prompt-version-manager.js.map +1 -0
- package/dist/src/agents/registry-builder.d.ts +36 -0
- package/dist/src/agents/registry-builder.d.ts.map +1 -0
- package/dist/src/agents/registry-builder.js +200 -0
- package/dist/src/agents/registry-builder.js.map +1 -0
- package/dist/src/agents/registry-query.d.ts +71 -0
- package/dist/src/agents/registry-query.d.ts.map +1 -0
- package/dist/src/agents/registry-query.js +125 -0
- package/dist/src/agents/registry-query.js.map +1 -0
- package/dist/src/agents/score-decay.d.ts +19 -0
- package/dist/src/agents/score-decay.d.ts.map +1 -0
- package/dist/src/agents/score-decay.js +22 -0
- package/dist/src/agents/score-decay.js.map +1 -0
- package/dist/src/agents/shared-instructions-loader.d.ts +13 -0
- package/dist/src/agents/shared-instructions-loader.d.ts.map +1 -0
- package/dist/src/agents/shared-instructions-loader.js +40 -0
- package/dist/src/agents/shared-instructions-loader.js.map +1 -0
- package/dist/src/agents/specialization-scorer.d.ts +54 -0
- package/dist/src/agents/specialization-scorer.d.ts.map +1 -0
- package/dist/src/agents/specialization-scorer.js +204 -0
- package/dist/src/agents/specialization-scorer.js.map +1 -0
- package/dist/src/agents/termination-watcher.d.ts +30 -0
- package/dist/src/agents/termination-watcher.d.ts.map +1 -0
- package/dist/src/agents/termination-watcher.js +84 -0
- package/dist/src/agents/termination-watcher.js.map +1 -0
- package/dist/src/agents/trigger-index.d.ts +20 -0
- package/dist/src/agents/trigger-index.d.ts.map +1 -0
- package/dist/src/agents/trigger-index.js +38 -0
- package/dist/src/agents/trigger-index.js.map +1 -0
- package/dist/src/agents/trigger-scanner.d.ts +62 -0
- package/dist/src/agents/trigger-scanner.d.ts.map +1 -0
- package/dist/src/agents/trigger-scanner.js +260 -0
- package/dist/src/agents/trigger-scanner.js.map +1 -0
- package/dist/src/agents/version-diff.d.ts +18 -0
- package/dist/src/agents/version-diff.d.ts.map +1 -0
- package/dist/src/agents/version-diff.js +64 -0
- package/dist/src/agents/version-diff.js.map +1 -0
- package/dist/src/agents/version-store.d.ts +61 -0
- package/dist/src/agents/version-store.d.ts.map +1 -0
- package/dist/src/agents/version-store.js +212 -0
- package/dist/src/agents/version-store.js.map +1 -0
- package/dist/src/autopilot-state.d.ts +77 -0
- package/dist/src/autopilot-state.d.ts.map +1 -0
- package/dist/src/autopilot-state.js +279 -0
- package/dist/src/autopilot-state.js.map +1 -0
- package/dist/src/benchmarks/benchmark-runner.d.ts +82 -0
- package/dist/src/benchmarks/benchmark-runner.d.ts.map +1 -0
- package/dist/src/benchmarks/benchmark-runner.js +261 -0
- package/dist/src/benchmarks/benchmark-runner.js.map +1 -0
- package/dist/src/benchmarks/metric-evaluators.d.ts +35 -0
- package/dist/src/benchmarks/metric-evaluators.d.ts.map +1 -0
- package/dist/src/benchmarks/metric-evaluators.js +91 -0
- package/dist/src/benchmarks/metric-evaluators.js.map +1 -0
- package/dist/src/benchmarks/pretrain/index.d.ts +58 -0
- package/dist/src/benchmarks/pretrain/index.d.ts.map +1 -0
- package/dist/src/benchmarks/pretrain/index.js +404 -0
- package/dist/src/benchmarks/pretrain/index.js.map +1 -0
- package/dist/src/commands/agent-wasm.d.ts +14 -0
- package/dist/src/commands/agent-wasm.d.ts.map +1 -0
- package/dist/src/commands/agent-wasm.js +333 -0
- package/dist/src/commands/agent-wasm.js.map +1 -0
- package/dist/src/commands/agent.d.ts +8 -0
- package/dist/src/commands/agent.d.ts.map +1 -0
- package/dist/src/commands/agent.js +941 -0
- package/dist/src/commands/agent.js.map +1 -0
- package/dist/src/commands/analyze.d.ts +19 -0
- package/dist/src/commands/analyze.d.ts.map +1 -0
- package/dist/src/commands/analyze.js +2048 -0
- package/dist/src/commands/analyze.js.map +1 -0
- package/dist/src/commands/appliance-advanced.d.ts +9 -0
- package/dist/src/commands/appliance-advanced.d.ts.map +1 -0
- package/dist/src/commands/appliance-advanced.js +215 -0
- package/dist/src/commands/appliance-advanced.js.map +1 -0
- package/dist/src/commands/appliance.d.ts +8 -0
- package/dist/src/commands/appliance.d.ts.map +1 -0
- package/dist/src/commands/appliance.js +406 -0
- package/dist/src/commands/appliance.js.map +1 -0
- package/dist/src/commands/autopilot.d.ts +15 -0
- package/dist/src/commands/autopilot.d.ts.map +1 -0
- package/dist/src/commands/autopilot.js +362 -0
- package/dist/src/commands/autopilot.js.map +1 -0
- package/dist/src/commands/benchmark.d.ts +10 -0
- package/dist/src/commands/benchmark.d.ts.map +1 -0
- package/dist/src/commands/benchmark.js +460 -0
- package/dist/src/commands/benchmark.js.map +1 -0
- package/dist/src/commands/claims.d.ts +10 -0
- package/dist/src/commands/claims.d.ts.map +1 -0
- package/dist/src/commands/claims.js +624 -0
- package/dist/src/commands/claims.js.map +1 -0
- package/dist/src/commands/cleanup.d.ts +13 -0
- package/dist/src/commands/cleanup.d.ts.map +1 -0
- package/dist/src/commands/cleanup.js +218 -0
- package/dist/src/commands/cleanup.js.map +1 -0
- package/dist/src/commands/completions.d.ts +10 -0
- package/dist/src/commands/completions.d.ts.map +1 -0
- package/dist/src/commands/completions.js +539 -0
- package/dist/src/commands/completions.js.map +1 -0
- package/dist/src/commands/config.d.ts +8 -0
- package/dist/src/commands/config.d.ts.map +1 -0
- package/dist/src/commands/config.js +428 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/daemon.d.ts +8 -0
- package/dist/src/commands/daemon.d.ts.map +1 -0
- package/dist/src/commands/daemon.js +669 -0
- package/dist/src/commands/daemon.js.map +1 -0
- package/dist/src/commands/deployment.d.ts +10 -0
- package/dist/src/commands/deployment.d.ts.map +1 -0
- package/dist/src/commands/deployment.js +672 -0
- package/dist/src/commands/deployment.js.map +1 -0
- package/dist/src/commands/doctor.d.ts +10 -0
- package/dist/src/commands/doctor.d.ts.map +1 -0
- package/dist/src/commands/doctor.js +619 -0
- package/dist/src/commands/doctor.js.map +1 -0
- package/dist/src/commands/embeddings.d.ts +18 -0
- package/dist/src/commands/embeddings.d.ts.map +1 -0
- package/dist/src/commands/embeddings.js +1576 -0
- package/dist/src/commands/embeddings.js.map +1 -0
- package/dist/src/commands/guidance.d.ts +8 -0
- package/dist/src/commands/guidance.d.ts.map +1 -0
- package/dist/src/commands/guidance.js +560 -0
- package/dist/src/commands/guidance.js.map +1 -0
- package/dist/src/commands/hive-mind.d.ts +11 -0
- package/dist/src/commands/hive-mind.d.ts.map +1 -0
- package/dist/src/commands/hive-mind.js +1237 -0
- package/dist/src/commands/hive-mind.js.map +1 -0
- package/dist/src/commands/hooks.d.ts +8 -0
- package/dist/src/commands/hooks.d.ts.map +1 -0
- package/dist/src/commands/hooks.js +4442 -0
- package/dist/src/commands/hooks.js.map +1 -0
- package/dist/src/commands/index.d.ts +117 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +391 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/commands/init.d.ts +8 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +817 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/issues.d.ts +21 -0
- package/dist/src/commands/issues.d.ts.map +1 -0
- package/dist/src/commands/issues.js +567 -0
- package/dist/src/commands/issues.js.map +1 -0
- package/dist/src/commands/mcp.d.ts +11 -0
- package/dist/src/commands/mcp.d.ts.map +1 -0
- package/dist/src/commands/mcp.js +718 -0
- package/dist/src/commands/mcp.js.map +1 -0
- package/dist/src/commands/memory.d.ts +8 -0
- package/dist/src/commands/memory.d.ts.map +1 -0
- package/dist/src/commands/memory.js +1565 -0
- package/dist/src/commands/memory.js.map +1 -0
- package/dist/src/commands/migrate.d.ts +8 -0
- package/dist/src/commands/migrate.d.ts.map +1 -0
- package/dist/src/commands/migrate.js +742 -0
- package/dist/src/commands/migrate.js.map +1 -0
- package/dist/src/commands/neural.d.ts +10 -0
- package/dist/src/commands/neural.d.ts.map +1 -0
- package/dist/src/commands/neural.js +1454 -0
- package/dist/src/commands/neural.js.map +1 -0
- package/dist/src/commands/performance.d.ts +10 -0
- package/dist/src/commands/performance.d.ts.map +1 -0
- package/dist/src/commands/performance.js +579 -0
- package/dist/src/commands/performance.js.map +1 -0
- package/dist/src/commands/plugins.d.ts +11 -0
- package/dist/src/commands/plugins.d.ts.map +1 -0
- package/dist/src/commands/plugins.js +820 -0
- package/dist/src/commands/plugins.js.map +1 -0
- package/dist/src/commands/process.d.ts +10 -0
- package/dist/src/commands/process.d.ts.map +1 -0
- package/dist/src/commands/process.js +695 -0
- package/dist/src/commands/process.js.map +1 -0
- package/dist/src/commands/progress.d.ts +11 -0
- package/dist/src/commands/progress.d.ts.map +1 -0
- package/dist/src/commands/progress.js +259 -0
- package/dist/src/commands/progress.js.map +1 -0
- package/dist/src/commands/providers.d.ts +10 -0
- package/dist/src/commands/providers.d.ts.map +1 -0
- package/dist/src/commands/providers.js +359 -0
- package/dist/src/commands/providers.js.map +1 -0
- package/dist/src/commands/replay.d.ts +8 -0
- package/dist/src/commands/replay.d.ts.map +1 -0
- package/dist/src/commands/replay.js +60 -0
- package/dist/src/commands/replay.js.map +1 -0
- package/dist/src/commands/route.d.ts +16 -0
- package/dist/src/commands/route.d.ts.map +1 -0
- package/dist/src/commands/route.js +907 -0
- package/dist/src/commands/route.js.map +1 -0
- package/dist/src/commands/ruvector/backup.d.ts +11 -0
- package/dist/src/commands/ruvector/backup.d.ts.map +1 -0
- package/dist/src/commands/ruvector/backup.js +746 -0
- package/dist/src/commands/ruvector/backup.js.map +1 -0
- package/dist/src/commands/ruvector/benchmark.d.ts +11 -0
- package/dist/src/commands/ruvector/benchmark.d.ts.map +1 -0
- package/dist/src/commands/ruvector/benchmark.js +489 -0
- package/dist/src/commands/ruvector/benchmark.js.map +1 -0
- package/dist/src/commands/ruvector/import.d.ts +18 -0
- package/dist/src/commands/ruvector/import.d.ts.map +1 -0
- package/dist/src/commands/ruvector/import.js +349 -0
- package/dist/src/commands/ruvector/import.js.map +1 -0
- package/dist/src/commands/ruvector/index.d.ts +29 -0
- package/dist/src/commands/ruvector/index.d.ts.map +1 -0
- package/dist/src/commands/ruvector/index.js +129 -0
- package/dist/src/commands/ruvector/index.js.map +1 -0
- package/dist/src/commands/ruvector/init.d.ts +11 -0
- package/dist/src/commands/ruvector/init.d.ts.map +1 -0
- package/dist/src/commands/ruvector/init.js +466 -0
- package/dist/src/commands/ruvector/init.js.map +1 -0
- package/dist/src/commands/ruvector/migrate.d.ts +11 -0
- package/dist/src/commands/ruvector/migrate.d.ts.map +1 -0
- package/dist/src/commands/ruvector/migrate.js +497 -0
- package/dist/src/commands/ruvector/migrate.js.map +1 -0
- package/dist/src/commands/ruvector/optimize.d.ts +11 -0
- package/dist/src/commands/ruvector/optimize.d.ts.map +1 -0
- package/dist/src/commands/ruvector/optimize.js +504 -0
- package/dist/src/commands/ruvector/optimize.js.map +1 -0
- package/dist/src/commands/ruvector/setup.d.ts +18 -0
- package/dist/src/commands/ruvector/setup.d.ts.map +1 -0
- package/dist/src/commands/ruvector/setup.js +765 -0
- package/dist/src/commands/ruvector/setup.js.map +1 -0
- package/dist/src/commands/ruvector/status.d.ts +11 -0
- package/dist/src/commands/ruvector/status.d.ts.map +1 -0
- package/dist/src/commands/ruvector/status.js +478 -0
- package/dist/src/commands/ruvector/status.js.map +1 -0
- package/dist/src/commands/security.d.ts +10 -0
- package/dist/src/commands/security.d.ts.map +1 -0
- package/dist/src/commands/security.js +794 -0
- package/dist/src/commands/security.js.map +1 -0
- package/dist/src/commands/session.d.ts +8 -0
- package/dist/src/commands/session.d.ts.map +1 -0
- package/dist/src/commands/session.js +750 -0
- package/dist/src/commands/session.js.map +1 -0
- package/dist/src/commands/start.d.ts +8 -0
- package/dist/src/commands/start.d.ts.map +1 -0
- package/dist/src/commands/start.js +418 -0
- package/dist/src/commands/start.js.map +1 -0
- package/dist/src/commands/status.d.ts +8 -0
- package/dist/src/commands/status.d.ts.map +1 -0
- package/dist/src/commands/status.js +591 -0
- package/dist/src/commands/status.js.map +1 -0
- package/dist/src/commands/swarm.d.ts +8 -0
- package/dist/src/commands/swarm.d.ts.map +1 -0
- package/dist/src/commands/swarm.js +801 -0
- package/dist/src/commands/swarm.js.map +1 -0
- package/dist/src/commands/task.d.ts +8 -0
- package/dist/src/commands/task.d.ts.map +1 -0
- package/dist/src/commands/task.js +671 -0
- package/dist/src/commands/task.js.map +1 -0
- package/dist/src/commands/tokens.d.ts +8 -0
- package/dist/src/commands/tokens.d.ts.map +1 -0
- package/dist/src/commands/tokens.js +107 -0
- package/dist/src/commands/tokens.js.map +1 -0
- package/dist/src/commands/transfer-store.d.ts +13 -0
- package/dist/src/commands/transfer-store.d.ts.map +1 -0
- package/dist/src/commands/transfer-store.js +428 -0
- package/dist/src/commands/transfer-store.js.map +1 -0
- package/dist/src/commands/ui.js +68 -0
- package/dist/src/commands/update.d.ts +8 -0
- package/dist/src/commands/update.d.ts.map +1 -0
- package/dist/src/commands/update.js +276 -0
- package/dist/src/commands/update.js.map +1 -0
- package/dist/src/commands/workflow.d.ts +8 -0
- package/dist/src/commands/workflow.d.ts.map +1 -0
- package/dist/src/commands/workflow.js +617 -0
- package/dist/src/commands/workflow.js.map +1 -0
- package/dist/src/config-adapter.d.ts +15 -0
- package/dist/src/config-adapter.d.ts.map +1 -0
- package/dist/src/config-adapter.js +186 -0
- package/dist/src/config-adapter.js.map +1 -0
- package/dist/src/consensus/audit-writer.d.ts +50 -0
- package/dist/src/consensus/audit-writer.d.ts.map +1 -0
- package/dist/src/consensus/audit-writer.js +109 -0
- package/dist/src/consensus/audit-writer.js.map +1 -0
- package/dist/src/consensus/index.d.ts +7 -0
- package/dist/src/consensus/index.d.ts.map +1 -0
- package/dist/src/consensus/index.js +6 -0
- package/dist/src/consensus/index.js.map +1 -0
- package/dist/src/consensus/vote-signer.d.ts +39 -0
- package/dist/src/consensus/vote-signer.d.ts.map +1 -0
- package/dist/src/consensus/vote-signer.js +63 -0
- package/dist/src/consensus/vote-signer.js.map +1 -0
- package/dist/src/context/context-provider.d.ts +44 -0
- package/dist/src/context/context-provider.d.ts.map +1 -0
- package/dist/src/context/context-provider.js +25 -0
- package/dist/src/context/context-provider.js.map +1 -0
- package/dist/src/context/git-state-provider.d.ts +12 -0
- package/dist/src/context/git-state-provider.d.ts.map +1 -0
- package/dist/src/context/git-state-provider.js +34 -0
- package/dist/src/context/git-state-provider.js.map +1 -0
- package/dist/src/context/index.d.ts +12 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +12 -0
- package/dist/src/context/index.js.map +1 -0
- package/dist/src/context/project-conventions-provider.d.ts +15 -0
- package/dist/src/context/project-conventions-provider.d.ts.map +1 -0
- package/dist/src/context/project-conventions-provider.js +19 -0
- package/dist/src/context/project-conventions-provider.js.map +1 -0
- package/dist/src/context/prompt-assembler.d.ts +26 -0
- package/dist/src/context/prompt-assembler.d.ts.map +1 -0
- package/dist/src/context/prompt-assembler.js +93 -0
- package/dist/src/context/prompt-assembler.js.map +1 -0
- package/dist/src/context/task-history-provider.d.ts +24 -0
- package/dist/src/context/task-history-provider.d.ts.map +1 -0
- package/dist/src/context/task-history-provider.js +32 -0
- package/dist/src/context/task-history-provider.js.map +1 -0
- package/dist/src/context/user-preferences-provider.d.ts +14 -0
- package/dist/src/context/user-preferences-provider.d.ts.map +1 -0
- package/dist/src/context/user-preferences-provider.js +27 -0
- package/dist/src/context/user-preferences-provider.js.map +1 -0
- package/dist/src/dlq/dlq-reader.d.ts +29 -0
- package/dist/src/dlq/dlq-reader.d.ts.map +1 -0
- package/dist/src/dlq/dlq-reader.js +64 -0
- package/dist/src/dlq/dlq-reader.js.map +1 -0
- package/dist/src/dlq/dlq-replayer.d.ts +20 -0
- package/dist/src/dlq/dlq-replayer.d.ts.map +1 -0
- package/dist/src/dlq/dlq-replayer.js +56 -0
- package/dist/src/dlq/dlq-replayer.js.map +1 -0
- package/dist/src/dlq/dlq-writer.d.ts +24 -0
- package/dist/src/dlq/dlq-writer.d.ts.map +1 -0
- package/dist/src/dlq/dlq-writer.js +43 -0
- package/dist/src/dlq/dlq-writer.js.map +1 -0
- package/dist/src/dlq/index.d.ts +10 -0
- package/dist/src/dlq/index.d.ts.map +1 -0
- package/dist/src/dlq/index.js +7 -0
- package/dist/src/dlq/index.js.map +1 -0
- package/dist/src/eval/dataset-manager.d.ts +33 -0
- package/dist/src/eval/dataset-manager.d.ts.map +1 -0
- package/dist/src/eval/dataset-manager.js +97 -0
- package/dist/src/eval/dataset-manager.js.map +1 -0
- package/dist/src/eval/dataset-runner.d.ts +23 -0
- package/dist/src/eval/dataset-runner.d.ts.map +1 -0
- package/dist/src/eval/dataset-runner.js +59 -0
- package/dist/src/eval/dataset-runner.js.map +1 -0
- package/dist/src/eval/index.d.ts +10 -0
- package/dist/src/eval/index.d.ts.map +1 -0
- package/dist/src/eval/index.js +7 -0
- package/dist/src/eval/index.js.map +1 -0
- package/dist/src/eval/trace-collector.d.ts +40 -0
- package/dist/src/eval/trace-collector.d.ts.map +1 -0
- package/dist/src/eval/trace-collector.js +82 -0
- package/dist/src/eval/trace-collector.js.map +1 -0
- package/dist/src/graph/enrich.mjs +362 -0
- package/dist/src/index.d.ts +82 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +578 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
- package/dist/src/infrastructure/in-memory-repositories.d.ts.map +1 -0
- package/dist/src/infrastructure/in-memory-repositories.js +264 -0
- package/dist/src/infrastructure/in-memory-repositories.js.map +1 -0
- package/dist/src/init/claudemd-generator.d.ts +25 -0
- package/dist/src/init/claudemd-generator.d.ts.map +1 -0
- package/dist/src/init/claudemd-generator.js +522 -0
- package/dist/src/init/claudemd-generator.js.map +1 -0
- package/dist/src/init/executor.d.ts +38 -0
- package/dist/src/init/executor.d.ts.map +1 -0
- package/dist/src/init/executor.js +1919 -0
- package/dist/src/init/executor.js.map +1 -0
- package/dist/src/init/helpers-generator.d.ts +60 -0
- package/dist/src/init/helpers-generator.d.ts.map +1 -0
- package/dist/src/init/helpers-generator.js +1222 -0
- package/dist/src/init/helpers-generator.js.map +1 -0
- package/dist/src/init/index.d.ts +13 -0
- package/dist/src/init/index.d.ts.map +1 -0
- package/dist/src/init/index.js +15 -0
- package/dist/src/init/index.js.map +1 -0
- package/dist/src/init/mcp-generator.d.ts +26 -0
- package/dist/src/init/mcp-generator.d.ts.map +1 -0
- package/dist/src/init/mcp-generator.js +99 -0
- package/dist/src/init/mcp-generator.js.map +1 -0
- package/dist/src/init/settings-generator.d.ts +14 -0
- package/dist/src/init/settings-generator.d.ts.map +1 -0
- package/dist/src/init/settings-generator.js +392 -0
- package/dist/src/init/settings-generator.js.map +1 -0
- package/dist/src/init/statusline-generator.d.ts +25 -0
- package/dist/src/init/statusline-generator.d.ts.map +1 -0
- package/dist/src/init/statusline-generator.js +1157 -0
- package/dist/src/init/statusline-generator.js.map +1 -0
- package/dist/src/init/types.d.ts +291 -0
- package/dist/src/init/types.d.ts.map +1 -0
- package/dist/src/init/types.js +258 -0
- package/dist/src/init/types.js.map +1 -0
- package/dist/src/interactive/interrupt.d.ts +22 -0
- package/dist/src/interactive/interrupt.d.ts.map +1 -0
- package/dist/src/interactive/interrupt.js +66 -0
- package/dist/src/interactive/interrupt.js.map +1 -0
- package/dist/src/mcp/deprecation-injector.d.ts +25 -0
- package/dist/src/mcp/deprecation-injector.d.ts.map +1 -0
- package/dist/src/mcp/deprecation-injector.js +48 -0
- package/dist/src/mcp/deprecation-injector.js.map +1 -0
- package/dist/src/mcp/tool-registry.d.ts +61 -0
- package/dist/src/mcp/tool-registry.d.ts.map +1 -0
- package/dist/src/mcp/tool-registry.js +212 -0
- package/dist/src/mcp/tool-registry.js.map +1 -0
- package/dist/src/mcp-client.d.ts +92 -0
- package/dist/src/mcp-client.d.ts.map +1 -0
- package/dist/src/mcp-client.js +261 -0
- package/dist/src/mcp-client.js.map +1 -0
- package/dist/src/mcp-server.d.ts +163 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/dist/src/mcp-server.js +682 -0
- package/dist/src/mcp-server.js.map +1 -0
- package/dist/src/mcp-tools/a2a-tools.d.ts +14 -0
- package/dist/src/mcp-tools/a2a-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/a2a-tools.js +244 -0
- package/dist/src/mcp-tools/a2a-tools.js.map +1 -0
- package/dist/src/mcp-tools/agent-tools.d.ts +9 -0
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/agent-tools.js +564 -0
- package/dist/src/mcp-tools/agent-tools.js.map +1 -0
- package/dist/src/mcp-tools/agentdb-tools.d.ts +30 -0
- package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/agentdb-tools.js +569 -0
- package/dist/src/mcp-tools/agentdb-tools.js.map +1 -0
- package/dist/src/mcp-tools/analyze-tools.d.ts +38 -0
- package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/analyze-tools.js +317 -0
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -0
- package/dist/src/mcp-tools/auto-install.d.ts +83 -0
- package/dist/src/mcp-tools/auto-install.d.ts.map +1 -0
- package/dist/src/mcp-tools/auto-install.js +131 -0
- package/dist/src/mcp-tools/auto-install.js.map +1 -0
- package/dist/src/mcp-tools/autopilot-tools.d.ts +12 -0
- package/dist/src/mcp-tools/autopilot-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/autopilot-tools.js +227 -0
- package/dist/src/mcp-tools/autopilot-tools.js.map +1 -0
- package/dist/src/mcp-tools/browser-tools.d.ts +13 -0
- package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/browser-tools.js +550 -0
- package/dist/src/mcp-tools/browser-tools.js.map +1 -0
- package/dist/src/mcp-tools/claims-tools.d.ts +12 -0
- package/dist/src/mcp-tools/claims-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/claims-tools.js +747 -0
- package/dist/src/mcp-tools/claims-tools.js.map +1 -0
- package/dist/src/mcp-tools/config-tools.d.ts +8 -0
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/config-tools.js +353 -0
- package/dist/src/mcp-tools/config-tools.js.map +1 -0
- package/dist/src/mcp-tools/coordination-tools.d.ts +13 -0
- package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/coordination-tools.js +673 -0
- package/dist/src/mcp-tools/coordination-tools.js.map +1 -0
- package/dist/src/mcp-tools/daa-tools.d.ts +13 -0
- package/dist/src/mcp-tools/daa-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/daa-tools.js +473 -0
- package/dist/src/mcp-tools/daa-tools.js.map +1 -0
- package/dist/src/mcp-tools/embeddings-tools.d.ts +9 -0
- package/dist/src/mcp-tools/embeddings-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/embeddings-tools.js +782 -0
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -0
- package/dist/src/mcp-tools/github-tools.d.ts +9 -0
- package/dist/src/mcp-tools/github-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/github-tools.js +472 -0
- package/dist/src/mcp-tools/github-tools.js.map +1 -0
- package/dist/src/mcp-tools/graphify-tools.d.ts +73 -0
- package/dist/src/mcp-tools/graphify-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/graphify-tools.js +1235 -0
- package/dist/src/mcp-tools/graphify-tools.js.map +1 -0
- package/dist/src/mcp-tools/guidance-tools.d.ts +15 -0
- package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/guidance-tools.js +618 -0
- package/dist/src/mcp-tools/guidance-tools.js.map +1 -0
- package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/hive-mind-tools.js +877 -0
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts +44 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.js +3397 -0
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -0
- package/dist/src/mcp-tools/index.d.ts +38 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -0
- package/dist/src/mcp-tools/index.js +40 -0
- package/dist/src/mcp-tools/index.js.map +1 -0
- package/dist/src/mcp-tools/memory-tools.d.ts +14 -0
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/memory-tools.js +514 -0
- package/dist/src/mcp-tools/memory-tools.js.map +1 -0
- package/dist/src/mcp-tools/neural-tools.d.ts +16 -0
- package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/neural-tools.js +634 -0
- package/dist/src/mcp-tools/neural-tools.js.map +1 -0
- package/dist/src/mcp-tools/performance-tools.d.ts +16 -0
- package/dist/src/mcp-tools/performance-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/performance-tools.js +643 -0
- package/dist/src/mcp-tools/performance-tools.js.map +1 -0
- package/dist/src/mcp-tools/progress-tools.d.ts +14 -0
- package/dist/src/mcp-tools/progress-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/progress-tools.js +348 -0
- package/dist/src/mcp-tools/progress-tools.js.map +1 -0
- package/dist/src/mcp-tools/request-tracker.d.ts +17 -0
- package/dist/src/mcp-tools/request-tracker.d.ts.map +1 -0
- package/dist/src/mcp-tools/request-tracker.js +27 -0
- package/dist/src/mcp-tools/request-tracker.js.map +1 -0
- package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
- package/dist/src/mcp-tools/ruvllm-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/ruvllm-tools.js +284 -0
- package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -0
- package/dist/src/mcp-tools/security-tools.d.ts +18 -0
- package/dist/src/mcp-tools/security-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/security-tools.js +434 -0
- package/dist/src/mcp-tools/security-tools.js.map +1 -0
- package/dist/src/mcp-tools/session-tools.d.ts +8 -0
- package/dist/src/mcp-tools/session-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/session-tools.js +338 -0
- package/dist/src/mcp-tools/session-tools.js.map +1 -0
- package/dist/src/mcp-tools/swarm-tools.d.ts +9 -0
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/swarm-tools.js +289 -0
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -0
- package/dist/src/mcp-tools/system-tools.d.ts +13 -0
- package/dist/src/mcp-tools/system-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/system-tools.js +551 -0
- package/dist/src/mcp-tools/system-tools.js.map +1 -0
- package/dist/src/mcp-tools/task-tools.d.ts +8 -0
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/task-tools.js +406 -0
- package/dist/src/mcp-tools/task-tools.js.map +1 -0
- package/dist/src/mcp-tools/terminal-tools.d.ts +8 -0
- package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/terminal-tools.js +260 -0
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -0
- package/dist/src/mcp-tools/transfer-tools.d.ts +14 -0
- package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/transfer-tools.js +396 -0
- package/dist/src/mcp-tools/transfer-tools.js.map +1 -0
- package/dist/src/mcp-tools/types.d.ts +37 -0
- package/dist/src/mcp-tools/types.d.ts.map +1 -0
- package/dist/src/mcp-tools/types.js +14 -0
- package/dist/src/mcp-tools/types.js.map +1 -0
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js +230 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.js +562 -0
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -0
- package/dist/src/memory/ewc-consolidation.d.ts +295 -0
- package/dist/src/memory/ewc-consolidation.d.ts.map +1 -0
- package/dist/src/memory/ewc-consolidation.js +601 -0
- package/dist/src/memory/ewc-consolidation.js.map +1 -0
- package/dist/src/memory/intelligence.d.ts +338 -0
- package/dist/src/memory/intelligence.d.ts.map +1 -0
- package/dist/src/memory/intelligence.js +1023 -0
- package/dist/src/memory/intelligence.js.map +1 -0
- package/dist/src/memory/memory-bridge.d.ts +409 -0
- package/dist/src/memory/memory-bridge.d.ts.map +1 -0
- package/dist/src/memory/memory-bridge.js +1561 -0
- package/dist/src/memory/memory-bridge.js.map +1 -0
- package/dist/src/memory/memory-initializer.d.ts +414 -0
- package/dist/src/memory/memory-initializer.d.ts.map +1 -0
- package/dist/src/memory/memory-initializer.js +2222 -0
- package/dist/src/memory/memory-initializer.js.map +1 -0
- package/dist/src/memory/sona-optimizer.d.ts +227 -0
- package/dist/src/memory/sona-optimizer.d.ts.map +1 -0
- package/dist/src/memory/sona-optimizer.js +633 -0
- package/dist/src/memory/sona-optimizer.js.map +1 -0
- package/dist/src/model/complexity-scorer.d.ts +21 -0
- package/dist/src/model/complexity-scorer.d.ts.map +1 -0
- package/dist/src/model/complexity-scorer.js +106 -0
- package/dist/src/model/complexity-scorer.js.map +1 -0
- package/dist/src/model/index.d.ts +4 -0
- package/dist/src/model/index.d.ts.map +1 -0
- package/dist/src/model/index.js +4 -0
- package/dist/src/model/index.js.map +1 -0
- package/dist/src/model/model-settings.d.ts +22 -0
- package/dist/src/model/model-settings.d.ts.map +1 -0
- package/dist/src/model/model-settings.js +33 -0
- package/dist/src/model/model-settings.js.map +1 -0
- package/dist/src/model/model-tier-resolver.d.ts +24 -0
- package/dist/src/model/model-tier-resolver.d.ts.map +1 -0
- package/dist/src/model/model-tier-resolver.js +65 -0
- package/dist/src/model/model-tier-resolver.js.map +1 -0
- package/dist/src/orchestration/index.d.ts +7 -0
- package/dist/src/orchestration/index.d.ts.map +1 -0
- package/dist/src/orchestration/index.js +6 -0
- package/dist/src/orchestration/index.js.map +1 -0
- package/dist/src/orchestration/mode-dispatcher.d.ts +11 -0
- package/dist/src/orchestration/mode-dispatcher.d.ts.map +1 -0
- package/dist/src/orchestration/mode-dispatcher.js +31 -0
- package/dist/src/orchestration/mode-dispatcher.js.map +1 -0
- package/dist/src/orchestration/routing-modes.d.ts +68 -0
- package/dist/src/orchestration/routing-modes.d.ts.map +1 -0
- package/dist/src/orchestration/routing-modes.js +150 -0
- package/dist/src/orchestration/routing-modes.js.map +1 -0
- package/dist/src/output.d.ts +133 -0
- package/dist/src/output.d.ts.map +1 -0
- package/dist/src/output.js +514 -0
- package/dist/src/output.js.map +1 -0
- package/dist/src/parser.d.ts +51 -0
- package/dist/src/parser.d.ts.map +1 -0
- package/dist/src/parser.js +425 -0
- package/dist/src/parser.js.map +1 -0
- package/dist/src/plugins/manager.d.ts +133 -0
- package/dist/src/plugins/manager.d.ts.map +1 -0
- package/dist/src/plugins/manager.js +400 -0
- package/dist/src/plugins/manager.js.map +1 -0
- package/dist/src/plugins/store/discovery.d.ts +88 -0
- package/dist/src/plugins/store/discovery.d.ts.map +1 -0
- package/dist/src/plugins/store/discovery.js +841 -0
- package/dist/src/plugins/store/discovery.js.map +1 -0
- package/dist/src/plugins/store/index.d.ts +76 -0
- package/dist/src/plugins/store/index.d.ts.map +1 -0
- package/dist/src/plugins/store/index.js +141 -0
- package/dist/src/plugins/store/index.js.map +1 -0
- package/dist/src/plugins/store/search.d.ts +46 -0
- package/dist/src/plugins/store/search.d.ts.map +1 -0
- package/dist/src/plugins/store/search.js +230 -0
- package/dist/src/plugins/store/search.js.map +1 -0
- package/dist/src/plugins/store/types.d.ts +274 -0
- package/dist/src/plugins/store/types.d.ts.map +1 -0
- package/dist/src/plugins/store/types.js +7 -0
- package/dist/src/plugins/store/types.js.map +1 -0
- package/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
- package/dist/src/plugins/tests/demo-plugin-store.d.ts.map +1 -0
- package/dist/src/plugins/tests/demo-plugin-store.js +126 -0
- package/dist/src/plugins/tests/demo-plugin-store.js.map +1 -0
- package/dist/src/plugins/tests/standalone-test.d.ts +12 -0
- package/dist/src/plugins/tests/standalone-test.d.ts.map +1 -0
- package/dist/src/plugins/tests/standalone-test.js +188 -0
- package/dist/src/plugins/tests/standalone-test.js.map +1 -0
- package/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
- package/dist/src/plugins/tests/test-plugin-store.d.ts.map +1 -0
- package/dist/src/plugins/tests/test-plugin-store.js +206 -0
- package/dist/src/plugins/tests/test-plugin-store.js.map +1 -0
- package/dist/src/production/circuit-breaker.d.ts +101 -0
- package/dist/src/production/circuit-breaker.d.ts.map +1 -0
- package/dist/src/production/circuit-breaker.js +241 -0
- package/dist/src/production/circuit-breaker.js.map +1 -0
- package/dist/src/production/error-handler.d.ts +92 -0
- package/dist/src/production/error-handler.d.ts.map +1 -0
- package/dist/src/production/error-handler.js +299 -0
- package/dist/src/production/error-handler.js.map +1 -0
- package/dist/src/production/index.d.ts +23 -0
- package/dist/src/production/index.d.ts.map +1 -0
- package/dist/src/production/index.js +18 -0
- package/dist/src/production/index.js.map +1 -0
- package/dist/src/production/monitoring.d.ts +161 -0
- package/dist/src/production/monitoring.d.ts.map +1 -0
- package/dist/src/production/monitoring.js +356 -0
- package/dist/src/production/monitoring.js.map +1 -0
- package/dist/src/production/rate-limiter.d.ts +80 -0
- package/dist/src/production/rate-limiter.d.ts.map +1 -0
- package/dist/src/production/rate-limiter.js +201 -0
- package/dist/src/production/rate-limiter.js.map +1 -0
- package/dist/src/production/retry.d.ts +48 -0
- package/dist/src/production/retry.d.ts.map +1 -0
- package/dist/src/production/retry.js +179 -0
- package/dist/src/production/retry.js.map +1 -0
- package/dist/src/prompt.d.ts +44 -0
- package/dist/src/prompt.d.ts.map +1 -0
- package/dist/src/prompt.js +501 -0
- package/dist/src/prompt.js.map +1 -0
- package/dist/src/runtime/headless.d.ts +60 -0
- package/dist/src/runtime/headless.d.ts.map +1 -0
- package/dist/src/runtime/headless.js +284 -0
- package/dist/src/runtime/headless.js.map +1 -0
- package/dist/src/ruvector/agent-wasm.d.ts +182 -0
- package/dist/src/ruvector/agent-wasm.d.ts.map +1 -0
- package/dist/src/ruvector/agent-wasm.js +316 -0
- package/dist/src/ruvector/agent-wasm.js.map +1 -0
- package/dist/src/ruvector/ast-analyzer.d.ts +67 -0
- package/dist/src/ruvector/ast-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/ast-analyzer.js +277 -0
- package/dist/src/ruvector/ast-analyzer.js.map +1 -0
- package/dist/src/ruvector/coverage-router.d.ts +160 -0
- package/dist/src/ruvector/coverage-router.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-router.js +529 -0
- package/dist/src/ruvector/coverage-router.js.map +1 -0
- package/dist/src/ruvector/coverage-tools.d.ts +33 -0
- package/dist/src/ruvector/coverage-tools.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-tools.js +157 -0
- package/dist/src/ruvector/coverage-tools.js.map +1 -0
- package/dist/src/ruvector/diff-classifier.d.ts +175 -0
- package/dist/src/ruvector/diff-classifier.d.ts.map +1 -0
- package/dist/src/ruvector/diff-classifier.js +698 -0
- package/dist/src/ruvector/diff-classifier.js.map +1 -0
- package/dist/src/ruvector/enhanced-model-router.d.ts +146 -0
- package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -0
- package/dist/src/ruvector/enhanced-model-router.js +529 -0
- package/dist/src/ruvector/enhanced-model-router.js.map +1 -0
- package/dist/src/ruvector/flash-attention.d.ts +195 -0
- package/dist/src/ruvector/flash-attention.d.ts.map +1 -0
- package/dist/src/ruvector/flash-attention.js +643 -0
- package/dist/src/ruvector/flash-attention.js.map +1 -0
- package/dist/src/ruvector/graph-analyzer.d.ts +187 -0
- package/dist/src/ruvector/graph-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/graph-analyzer.js +929 -0
- package/dist/src/ruvector/graph-analyzer.js.map +1 -0
- package/dist/src/ruvector/index.d.ts +40 -0
- package/dist/src/ruvector/index.d.ts.map +1 -0
- package/dist/src/ruvector/index.js +76 -0
- package/dist/src/ruvector/index.js.map +1 -0
- package/dist/src/ruvector/lora-adapter.d.ts +218 -0
- package/dist/src/ruvector/lora-adapter.d.ts.map +1 -0
- package/dist/src/ruvector/lora-adapter.js +455 -0
- package/dist/src/ruvector/lora-adapter.js.map +1 -0
- package/dist/src/ruvector/model-router.d.ts +220 -0
- package/dist/src/ruvector/model-router.d.ts.map +1 -0
- package/dist/src/ruvector/model-router.js +488 -0
- package/dist/src/ruvector/model-router.js.map +1 -0
- package/dist/src/ruvector/moe-router.d.ts +206 -0
- package/dist/src/ruvector/moe-router.d.ts.map +1 -0
- package/dist/src/ruvector/moe-router.js +626 -0
- package/dist/src/ruvector/moe-router.js.map +1 -0
- package/dist/src/ruvector/q-learning-router.d.ts +211 -0
- package/dist/src/ruvector/q-learning-router.d.ts.map +1 -0
- package/dist/src/ruvector/q-learning-router.js +681 -0
- package/dist/src/ruvector/q-learning-router.js.map +1 -0
- package/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
- package/dist/src/ruvector/ruvllm-wasm.d.ts.map +1 -0
- package/dist/src/ruvector/ruvllm-wasm.js +363 -0
- package/dist/src/ruvector/ruvllm-wasm.js.map +1 -0
- package/dist/src/ruvector/semantic-router.d.ts +77 -0
- package/dist/src/ruvector/semantic-router.d.ts.map +1 -0
- package/dist/src/ruvector/semantic-router.js +178 -0
- package/dist/src/ruvector/semantic-router.js.map +1 -0
- package/dist/src/ruvector/vector-db.d.ts +69 -0
- package/dist/src/ruvector/vector-db.d.ts.map +1 -0
- package/dist/src/ruvector/vector-db.js +243 -0
- package/dist/src/ruvector/vector-db.js.map +1 -0
- package/dist/src/services/agentic-flow-bridge.d.ts +50 -0
- package/dist/src/services/agentic-flow-bridge.d.ts.map +1 -0
- package/dist/src/services/agentic-flow-bridge.js +95 -0
- package/dist/src/services/agentic-flow-bridge.js.map +1 -0
- package/dist/src/services/claim-service.d.ts +204 -0
- package/dist/src/services/claim-service.d.ts.map +1 -0
- package/dist/src/services/claim-service.js +818 -0
- package/dist/src/services/claim-service.js.map +1 -0
- package/dist/src/services/config-file-manager.d.ts +37 -0
- package/dist/src/services/config-file-manager.d.ts.map +1 -0
- package/dist/src/services/config-file-manager.js +224 -0
- package/dist/src/services/config-file-manager.js.map +1 -0
- package/dist/src/services/container-worker-pool.d.ts +197 -0
- package/dist/src/services/container-worker-pool.d.ts.map +1 -0
- package/dist/src/services/container-worker-pool.js +583 -0
- package/dist/src/services/container-worker-pool.js.map +1 -0
- package/dist/src/services/headless-worker-executor.d.ts +304 -0
- package/dist/src/services/headless-worker-executor.d.ts.map +1 -0
- package/dist/src/services/headless-worker-executor.js +1024 -0
- package/dist/src/services/headless-worker-executor.js.map +1 -0
- package/dist/src/services/index.d.ts +13 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +11 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/registry-api.d.ts +58 -0
- package/dist/src/services/registry-api.d.ts.map +1 -0
- package/dist/src/services/registry-api.js +146 -0
- package/dist/src/services/registry-api.js.map +1 -0
- package/dist/src/services/ruvector-training.d.ts +222 -0
- package/dist/src/services/ruvector-training.d.ts.map +1 -0
- package/dist/src/services/ruvector-training.js +688 -0
- package/dist/src/services/ruvector-training.js.map +1 -0
- package/dist/src/services/worker-daemon.d.ts +245 -0
- package/dist/src/services/worker-daemon.d.ts.map +1 -0
- package/dist/src/services/worker-daemon.js +999 -0
- package/dist/src/services/worker-daemon.js.map +1 -0
- package/dist/src/services/worker-queue.d.ts +194 -0
- package/dist/src/services/worker-queue.d.ts.map +1 -0
- package/dist/src/services/worker-queue.js +513 -0
- package/dist/src/services/worker-queue.js.map +1 -0
- package/dist/src/suggest.d.ts +53 -0
- package/dist/src/suggest.d.ts.map +1 -0
- package/dist/src/suggest.js +200 -0
- package/dist/src/suggest.js.map +1 -0
- package/dist/src/swarm/communication-graph.d.ts +25 -0
- package/dist/src/swarm/communication-graph.d.ts.map +1 -0
- package/dist/src/swarm/communication-graph.js +77 -0
- package/dist/src/swarm/communication-graph.js.map +1 -0
- package/dist/src/swarm/flow-enforcer.d.ts +29 -0
- package/dist/src/swarm/flow-enforcer.d.ts.map +1 -0
- package/dist/src/swarm/flow-enforcer.js +49 -0
- package/dist/src/swarm/flow-enforcer.js.map +1 -0
- package/dist/src/swarm/flow-visualizer.d.ts +16 -0
- package/dist/src/swarm/flow-visualizer.d.ts.map +1 -0
- package/dist/src/swarm/flow-visualizer.js +44 -0
- package/dist/src/swarm/flow-visualizer.js.map +1 -0
- package/dist/src/transfer/anonymization/index.d.ts +25 -0
- package/dist/src/transfer/anonymization/index.d.ts.map +1 -0
- package/dist/src/transfer/anonymization/index.js +175 -0
- package/dist/src/transfer/anonymization/index.js.map +1 -0
- package/dist/src/transfer/deploy-seraphine.d.ts +13 -0
- package/dist/src/transfer/deploy-seraphine.d.ts.map +1 -0
- package/dist/src/transfer/deploy-seraphine.js +205 -0
- package/dist/src/transfer/deploy-seraphine.js.map +1 -0
- package/dist/src/transfer/export.d.ts +25 -0
- package/dist/src/transfer/export.d.ts.map +1 -0
- package/dist/src/transfer/export.js +113 -0
- package/dist/src/transfer/export.js.map +1 -0
- package/dist/src/transfer/index.d.ts +12 -0
- package/dist/src/transfer/index.d.ts.map +1 -0
- package/dist/src/transfer/index.js +31 -0
- package/dist/src/transfer/index.js.map +1 -0
- package/dist/src/transfer/ipfs/client.d.ts +109 -0
- package/dist/src/transfer/ipfs/client.d.ts.map +1 -0
- package/dist/src/transfer/ipfs/client.js +307 -0
- package/dist/src/transfer/ipfs/client.js.map +1 -0
- package/dist/src/transfer/ipfs/upload.d.ts +95 -0
- package/dist/src/transfer/ipfs/upload.d.ts.map +1 -0
- package/dist/src/transfer/ipfs/upload.js +411 -0
- package/dist/src/transfer/ipfs/upload.js.map +1 -0
- package/dist/src/transfer/models/seraphine.d.ts +72 -0
- package/dist/src/transfer/models/seraphine.d.ts.map +1 -0
- package/dist/src/transfer/models/seraphine.js +373 -0
- package/dist/src/transfer/models/seraphine.js.map +1 -0
- package/dist/src/transfer/serialization/cfp.d.ts +49 -0
- package/dist/src/transfer/serialization/cfp.d.ts.map +1 -0
- package/dist/src/transfer/serialization/cfp.js +183 -0
- package/dist/src/transfer/serialization/cfp.js.map +1 -0
- package/dist/src/transfer/storage/gcs.d.ts +82 -0
- package/dist/src/transfer/storage/gcs.d.ts.map +1 -0
- package/dist/src/transfer/storage/gcs.js +272 -0
- package/dist/src/transfer/storage/gcs.js.map +1 -0
- package/dist/src/transfer/storage/index.d.ts +6 -0
- package/dist/src/transfer/storage/index.d.ts.map +1 -0
- package/dist/src/transfer/storage/index.js +6 -0
- package/dist/src/transfer/storage/index.js.map +1 -0
- package/dist/src/transfer/store/discovery.d.ts +84 -0
- package/dist/src/transfer/store/discovery.d.ts.map +1 -0
- package/dist/src/transfer/store/discovery.js +382 -0
- package/dist/src/transfer/store/discovery.js.map +1 -0
- package/dist/src/transfer/store/download.d.ts +70 -0
- package/dist/src/transfer/store/download.d.ts.map +1 -0
- package/dist/src/transfer/store/download.js +334 -0
- package/dist/src/transfer/store/download.js.map +1 -0
- package/dist/src/transfer/store/index.d.ts +84 -0
- package/dist/src/transfer/store/index.d.ts.map +1 -0
- package/dist/src/transfer/store/index.js +153 -0
- package/dist/src/transfer/store/index.js.map +1 -0
- package/dist/src/transfer/store/publish.d.ts +76 -0
- package/dist/src/transfer/store/publish.d.ts.map +1 -0
- package/dist/src/transfer/store/publish.js +294 -0
- package/dist/src/transfer/store/publish.js.map +1 -0
- package/dist/src/transfer/store/registry.d.ts +58 -0
- package/dist/src/transfer/store/registry.d.ts.map +1 -0
- package/dist/src/transfer/store/registry.js +285 -0
- package/dist/src/transfer/store/registry.js.map +1 -0
- package/dist/src/transfer/store/search.d.ts +54 -0
- package/dist/src/transfer/store/search.d.ts.map +1 -0
- package/dist/src/transfer/store/search.js +232 -0
- package/dist/src/transfer/store/search.js.map +1 -0
- package/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
- package/dist/src/transfer/store/tests/standalone-test.d.ts.map +1 -0
- package/dist/src/transfer/store/tests/standalone-test.js +190 -0
- package/dist/src/transfer/store/tests/standalone-test.js.map +1 -0
- package/dist/src/transfer/store/types.d.ts +193 -0
- package/dist/src/transfer/store/types.d.ts.map +1 -0
- package/dist/src/transfer/store/types.js +6 -0
- package/dist/src/transfer/store/types.js.map +1 -0
- package/dist/src/transfer/test-seraphine.d.ts +6 -0
- package/dist/src/transfer/test-seraphine.d.ts.map +1 -0
- package/dist/src/transfer/test-seraphine.js +105 -0
- package/dist/src/transfer/test-seraphine.js.map +1 -0
- package/dist/src/transfer/tests/test-store.d.ts +7 -0
- package/dist/src/transfer/tests/test-store.d.ts.map +1 -0
- package/dist/src/transfer/tests/test-store.js +214 -0
- package/dist/src/transfer/tests/test-store.js.map +1 -0
- package/dist/src/transfer/types.d.ts +245 -0
- package/dist/src/transfer/types.d.ts.map +1 -0
- package/dist/src/transfer/types.js +6 -0
- package/dist/src/transfer/types.js.map +1 -0
- package/dist/src/types.d.ts +198 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +38 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/ui/.monomind/data/pending-insights.jsonl +0 -0
- package/dist/src/ui/.monomind/data/ranked-context.json +5 -0
- package/dist/src/ui/.monomind/sessions/current.json +13 -0
- package/dist/src/ui/collector.mjs +517 -0
- package/dist/src/ui/dashboard.html +4409 -0
- package/dist/src/ui/server.mjs +909 -0
- package/dist/src/update/checker.d.ts +34 -0
- package/dist/src/update/checker.d.ts.map +1 -0
- package/dist/src/update/checker.js +185 -0
- package/dist/src/update/checker.js.map +1 -0
- package/dist/src/update/executor.d.ts +32 -0
- package/dist/src/update/executor.d.ts.map +1 -0
- package/dist/src/update/executor.js +181 -0
- package/dist/src/update/executor.js.map +1 -0
- package/dist/src/update/index.d.ts +33 -0
- package/dist/src/update/index.d.ts.map +1 -0
- package/dist/src/update/index.js +64 -0
- package/dist/src/update/index.js.map +1 -0
- package/dist/src/update/rate-limiter.d.ts +20 -0
- package/dist/src/update/rate-limiter.d.ts.map +1 -0
- package/dist/src/update/rate-limiter.js +96 -0
- package/dist/src/update/rate-limiter.js.map +1 -0
- package/dist/src/update/validator.d.ts +17 -0
- package/dist/src/update/validator.d.ts.map +1 -0
- package/dist/src/update/validator.js +118 -0
- package/dist/src/update/validator.js.map +1 -0
- package/dist/src/workflow/condition-evaluator.d.ts +10 -0
- package/dist/src/workflow/condition-evaluator.d.ts.map +1 -0
- package/dist/src/workflow/condition-evaluator.js +48 -0
- package/dist/src/workflow/condition-evaluator.js.map +1 -0
- package/dist/src/workflow/context-resolver.d.ts +12 -0
- package/dist/src/workflow/context-resolver.d.ts.map +1 -0
- package/dist/src/workflow/context-resolver.js +23 -0
- package/dist/src/workflow/context-resolver.js.map +1 -0
- package/dist/src/workflow/dag-builder.d.ts +17 -0
- package/dist/src/workflow/dag-builder.d.ts.map +1 -0
- package/dist/src/workflow/dag-builder.js +113 -0
- package/dist/src/workflow/dag-builder.js.map +1 -0
- package/dist/src/workflow/dag-executor.d.ts +9 -0
- package/dist/src/workflow/dag-executor.d.ts.map +1 -0
- package/dist/src/workflow/dag-executor.js +78 -0
- package/dist/src/workflow/dag-executor.js.map +1 -0
- package/dist/src/workflow/dag-types.d.ts +41 -0
- package/dist/src/workflow/dag-types.d.ts.map +1 -0
- package/dist/src/workflow/dag-types.js +8 -0
- package/dist/src/workflow/dag-types.js.map +1 -0
- package/dist/src/workflow/dsl-parser.d.ts +12 -0
- package/dist/src/workflow/dsl-parser.d.ts.map +1 -0
- package/dist/src/workflow/dsl-parser.js +20 -0
- package/dist/src/workflow/dsl-parser.js.map +1 -0
- package/dist/src/workflow/dsl-schema.d.ts +162 -0
- package/dist/src/workflow/dsl-schema.d.ts.map +1 -0
- package/dist/src/workflow/dsl-schema.js +78 -0
- package/dist/src/workflow/dsl-schema.js.map +1 -0
- package/dist/src/workflow/index.d.ts +13 -0
- package/dist/src/workflow/index.d.ts.map +1 -0
- package/dist/src/workflow/index.js +11 -0
- package/dist/src/workflow/index.js.map +1 -0
- package/dist/src/workflow/template-engine.d.ts +11 -0
- package/dist/src/workflow/template-engine.d.ts.map +1 -0
- package/dist/src/workflow/template-engine.js +33 -0
- package/dist/src/workflow/template-engine.js.map +1 -0
- package/dist/src/workflow/workflow-executor.d.ts +29 -0
- package/dist/src/workflow/workflow-executor.d.ts.map +1 -0
- package/dist/src/workflow/workflow-executor.js +146 -0
- package/dist/src/workflow/workflow-executor.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +105 -0
|
@@ -0,0 +1,4409 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>MONOMIND CONTROL</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Azeret+Mono:wght@400;500&family=Syne:wght@600;800&display=swap" rel="stylesheet">
|
|
10
|
+
<style>
|
|
11
|
+
:root {
|
|
12
|
+
--teal: #00E5C8;
|
|
13
|
+
--amber: #FFB700;
|
|
14
|
+
--red: #FF5577;
|
|
15
|
+
--green: #00E587;
|
|
16
|
+
--text: #D4D4E8;
|
|
17
|
+
--muted: #7880A8;
|
|
18
|
+
--dim: #4A5070;
|
|
19
|
+
--bg: #07080F;
|
|
20
|
+
--panel-bg: rgba(10, 11, 24, 0.92);
|
|
21
|
+
--border: rgba(0, 229, 200, 0.14);
|
|
22
|
+
--border-live: rgba(0, 229, 200, 0.5);
|
|
23
|
+
--glow: rgba(0, 229, 200, 0.07);
|
|
24
|
+
--glow-hover: rgba(0, 229, 200, 0.12);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
28
|
+
|
|
29
|
+
html, body {
|
|
30
|
+
height: 100%;
|
|
31
|
+
background: var(--bg);
|
|
32
|
+
color: var(--text);
|
|
33
|
+
font-family: 'Azeret Mono', monospace;
|
|
34
|
+
font-size: 12px;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
body {
|
|
39
|
+
background-color: var(--bg);
|
|
40
|
+
background-image:
|
|
41
|
+
repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(0,229,200,0.04) 39px, rgba(0,229,200,0.04) 40px),
|
|
42
|
+
repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(0,229,200,0.04) 39px, rgba(0,229,200,0.04) 40px);
|
|
43
|
+
background-size: 40px 40px;
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
height: 100vh;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
min-width: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* ─── HEADER ───────────────────────────────────────────────────── */
|
|
52
|
+
#header {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: space-between;
|
|
56
|
+
padding: 10px 18px;
|
|
57
|
+
border-bottom: 1px solid var(--border);
|
|
58
|
+
background: rgba(7, 8, 15, 0.97);
|
|
59
|
+
backdrop-filter: blur(16px);
|
|
60
|
+
flex-shrink: 0;
|
|
61
|
+
z-index: 10;
|
|
62
|
+
box-shadow: 0 1px 20px rgba(0,0,0,0.4);
|
|
63
|
+
min-width: 0;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
#header-left {
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: 14px;
|
|
71
|
+
flex-shrink: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#header h1 {
|
|
75
|
+
font-family: 'Syne', sans-serif;
|
|
76
|
+
font-weight: 800;
|
|
77
|
+
font-size: 15px;
|
|
78
|
+
letter-spacing: 0.22em;
|
|
79
|
+
color: var(--teal);
|
|
80
|
+
text-transform: uppercase;
|
|
81
|
+
text-shadow: 0 0 20px rgba(0,229,200,0.35);
|
|
82
|
+
white-space: nowrap;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#header-meta {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 18px;
|
|
89
|
+
font-size: 11px;
|
|
90
|
+
color: var(--muted);
|
|
91
|
+
letter-spacing: 0.05em;
|
|
92
|
+
min-width: 0;
|
|
93
|
+
overflow: hidden;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#header-meta span { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
|
|
97
|
+
|
|
98
|
+
#conn-dot {
|
|
99
|
+
width: 7px;
|
|
100
|
+
height: 7px;
|
|
101
|
+
border-radius: 50%;
|
|
102
|
+
background: var(--muted);
|
|
103
|
+
transition: background 0.3s;
|
|
104
|
+
flex-shrink: 0;
|
|
105
|
+
}
|
|
106
|
+
#conn-dot.connected { background: var(--green); animation: pulse-dot 2s infinite; }
|
|
107
|
+
#conn-dot.error { background: var(--red); }
|
|
108
|
+
|
|
109
|
+
#header-right {
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
gap: 16px;
|
|
113
|
+
font-size: 11px;
|
|
114
|
+
color: var(--dim);
|
|
115
|
+
letter-spacing: 0.06em;
|
|
116
|
+
flex-shrink: 0;
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#uptime-val, #session-val, #project-val {
|
|
121
|
+
color: var(--text);
|
|
122
|
+
font-weight: 500;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* ─── GRID LAYOUT ───────────────────────────────────────────────── */
|
|
126
|
+
#grid {
|
|
127
|
+
display: grid;
|
|
128
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
129
|
+
grid-template-rows: auto auto auto auto auto;
|
|
130
|
+
gap: 8px;
|
|
131
|
+
padding: 8px 8px 16px;
|
|
132
|
+
flex: 1;
|
|
133
|
+
min-height: 0;
|
|
134
|
+
overflow-y: auto;
|
|
135
|
+
overflow-x: hidden;
|
|
136
|
+
align-content: start;
|
|
137
|
+
scrollbar-width: thin;
|
|
138
|
+
scrollbar-color: var(--border) transparent;
|
|
139
|
+
}
|
|
140
|
+
#grid::-webkit-scrollbar { width: 6px; }
|
|
141
|
+
#grid::-webkit-scrollbar-track { background: transparent; }
|
|
142
|
+
#grid::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
|
|
143
|
+
#grid::-webkit-scrollbar-thumb:hover { background: var(--muted); }
|
|
144
|
+
|
|
145
|
+
/* Row 0: all projects (full width) */
|
|
146
|
+
#panel-projects { grid-column: 1 / 5; grid-row: 1; min-height: 200px; }
|
|
147
|
+
|
|
148
|
+
/* Row 1: agents | agents | tokens | tokens */
|
|
149
|
+
#panel-agents { grid-column: 1 / 3; grid-row: 2; }
|
|
150
|
+
#panel-tokens { grid-column: 3 / 5; grid-row: 2; }
|
|
151
|
+
|
|
152
|
+
/* Row 2: memory (2 cols) | hooks (2 cols) */
|
|
153
|
+
#panel-memory { grid-column: 1 / 3; grid-row: 3; }
|
|
154
|
+
#panel-hooks { grid-column: 3 / 5; grid-row: 3; }
|
|
155
|
+
|
|
156
|
+
/* Row 3: metrics (2 cols) | activity | system */
|
|
157
|
+
#panel-metrics { grid-column: 1 / 3; grid-row: 4; }
|
|
158
|
+
#panel-activity { grid-column: 3; grid-row: 4; }
|
|
159
|
+
#panel-system { grid-column: 4; grid-row: 4; }
|
|
160
|
+
|
|
161
|
+
/* All grid children must not overflow their columns */
|
|
162
|
+
#grid > * { min-width: 0; }
|
|
163
|
+
|
|
164
|
+
/* ─── PROJECTS TABLE ──────────────────────────────────────────── */
|
|
165
|
+
#projects-table {
|
|
166
|
+
display: grid;
|
|
167
|
+
grid-template-columns: 2fr 1fr 56px 56px 66px 80px;
|
|
168
|
+
gap: 0;
|
|
169
|
+
overflow-y: auto;
|
|
170
|
+
max-height: 160px;
|
|
171
|
+
font-size: 11px;
|
|
172
|
+
}
|
|
173
|
+
.proj-header {
|
|
174
|
+
color: var(--dim);
|
|
175
|
+
font-size: 9px;
|
|
176
|
+
letter-spacing: 0.14em;
|
|
177
|
+
text-transform: uppercase;
|
|
178
|
+
padding: 5px 8px;
|
|
179
|
+
border-bottom: 1px solid rgba(0,229,200,0.10);
|
|
180
|
+
position: sticky;
|
|
181
|
+
top: 0;
|
|
182
|
+
background: rgba(9, 10, 20, 0.98);
|
|
183
|
+
z-index: 1;
|
|
184
|
+
}
|
|
185
|
+
.proj-cell {
|
|
186
|
+
padding: 5px 8px;
|
|
187
|
+
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
188
|
+
white-space: nowrap;
|
|
189
|
+
overflow: hidden;
|
|
190
|
+
text-overflow: ellipsis;
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
gap: 5px;
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
transition: background 0.15s;
|
|
196
|
+
}
|
|
197
|
+
.proj-cell:hover { background: rgba(0,229,200,0.05); }
|
|
198
|
+
.proj-name { color: var(--text); font-weight: 500; }
|
|
199
|
+
.proj-path { color: var(--muted); font-size: 10px; }
|
|
200
|
+
.proj-count { color: var(--teal); text-align: right; font-weight: 600; }
|
|
201
|
+
.proj-size { color: var(--muted); text-align: right; }
|
|
202
|
+
.proj-age { color: var(--muted); font-size: 10px; }
|
|
203
|
+
.proj-dots { color: var(--amber); font-size: 10px; font-weight: 600; }
|
|
204
|
+
.proj-exists-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
|
|
205
|
+
.proj-exists-dot.on { background: var(--teal); box-shadow: 0 0 4px var(--teal); }
|
|
206
|
+
.proj-exists-dot.off { background: var(--muted); }
|
|
207
|
+
|
|
208
|
+
/* ─── PROJECT STATS STRIP ─────────────────────────────────── */
|
|
209
|
+
#project-stats-strip {
|
|
210
|
+
display: flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
gap: 5px;
|
|
213
|
+
padding: 6px 10px;
|
|
214
|
+
border-top: 1px solid var(--border);
|
|
215
|
+
flex-wrap: wrap;
|
|
216
|
+
background: rgba(0, 0, 0, 0.2);
|
|
217
|
+
flex-shrink: 0;
|
|
218
|
+
}
|
|
219
|
+
.stat-pill {
|
|
220
|
+
display: flex;
|
|
221
|
+
align-items: center;
|
|
222
|
+
gap: 4px;
|
|
223
|
+
padding: 2px 7px;
|
|
224
|
+
background: rgba(0, 229, 200, 0.05);
|
|
225
|
+
border: 1px solid rgba(0, 229, 200, 0.10);
|
|
226
|
+
border-radius: 3px;
|
|
227
|
+
white-space: nowrap;
|
|
228
|
+
}
|
|
229
|
+
.stat-pill-key {
|
|
230
|
+
font-size: 9px;
|
|
231
|
+
color: var(--muted);
|
|
232
|
+
letter-spacing: 0.06em;
|
|
233
|
+
text-transform: uppercase;
|
|
234
|
+
}
|
|
235
|
+
.stat-pill-val {
|
|
236
|
+
font-size: 10px;
|
|
237
|
+
font-weight: 600;
|
|
238
|
+
color: var(--teal);
|
|
239
|
+
}
|
|
240
|
+
.stat-pill-val.amber { color: var(--amber); }
|
|
241
|
+
.stat-pill-val.green { color: var(--green); }
|
|
242
|
+
.stat-pill-val.dim { color: var(--muted); }
|
|
243
|
+
|
|
244
|
+
/* ─── PANELS ────────────────────────────────────────────────────── */
|
|
245
|
+
.panel {
|
|
246
|
+
background: var(--panel-bg);
|
|
247
|
+
border: 1px solid var(--border);
|
|
248
|
+
border-radius: 6px;
|
|
249
|
+
backdrop-filter: blur(14px);
|
|
250
|
+
display: flex;
|
|
251
|
+
flex-direction: column;
|
|
252
|
+
overflow: hidden;
|
|
253
|
+
transition: border-color 0.4s, box-shadow 0.4s;
|
|
254
|
+
position: relative;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.panel:hover {
|
|
258
|
+
border-color: rgba(0, 229, 200, 0.28);
|
|
259
|
+
box-shadow: 0 0 18px rgba(0, 229, 200, 0.06), inset 0 0 14px rgba(0, 229, 200, 0.02);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.panel.live {
|
|
263
|
+
border-color: var(--border-live);
|
|
264
|
+
box-shadow: 0 0 12px rgba(0, 229, 200, 0.08);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* ─── COLLAPSIBLE PANELS ────────────────────────────────────────── */
|
|
268
|
+
.panel-header {
|
|
269
|
+
display: flex;
|
|
270
|
+
align-items: center;
|
|
271
|
+
justify-content: space-between;
|
|
272
|
+
padding: 7px 10px 6px;
|
|
273
|
+
border-bottom: 1px solid var(--border);
|
|
274
|
+
flex-shrink: 0;
|
|
275
|
+
cursor: pointer;
|
|
276
|
+
user-select: none;
|
|
277
|
+
transition: background 0.15s;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* Projects panel header is not collapsible */
|
|
281
|
+
#panel-projects .panel-header { cursor: default; }
|
|
282
|
+
|
|
283
|
+
.panel-header:not(#panel-projects .panel-header):hover {
|
|
284
|
+
background: rgba(0, 229, 200, 0.03);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.panel-chevron {
|
|
288
|
+
font-size: 11px;
|
|
289
|
+
color: var(--muted);
|
|
290
|
+
transition: transform 0.2s ease;
|
|
291
|
+
flex-shrink: 0;
|
|
292
|
+
margin-left: 6px;
|
|
293
|
+
line-height: 1;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Body hidden by default (collapsed) — projects panel always visible */
|
|
297
|
+
.panel-body { display: none; }
|
|
298
|
+
#panel-projects .panel-body { display: block; }
|
|
299
|
+
#panel-activity .panel-body { display: flex; flex-direction: column; }
|
|
300
|
+
|
|
301
|
+
/* Panel is open */
|
|
302
|
+
.panel.open .panel-body {
|
|
303
|
+
display: flex;
|
|
304
|
+
flex-direction: column;
|
|
305
|
+
min-height: 140px;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* Override display for specific panels that need block */
|
|
309
|
+
#panel-memory.open .panel-body,
|
|
310
|
+
#panel-hooks.open .panel-body { display: block; }
|
|
311
|
+
#panel-knowledge.open .panel-body,
|
|
312
|
+
#panel-metrics.open .panel-body,
|
|
313
|
+
#panel-system.open .panel-body { display: block; }
|
|
314
|
+
|
|
315
|
+
/* Graphify panel inner layout */
|
|
316
|
+
.graphify-layout { display: grid; grid-template-columns: 220px 1fr; gap: 12px; }
|
|
317
|
+
.graphify-stats { display: flex; flex-direction: column; gap: 6px; }
|
|
318
|
+
.graphify-stat-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
|
|
319
|
+
.graphify-stat-key { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
320
|
+
.graphify-stat-val { font-size: 11px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
|
|
321
|
+
.graphify-report { overflow-y: auto; max-height: 320px; }
|
|
322
|
+
.graphify-section { margin-bottom: 10px; }
|
|
323
|
+
.graphify-section-title { font-size: 9px; font-weight: 700; letter-spacing: 0.08em; color: var(--muted); text-transform: uppercase; margin-bottom: 4px; padding-bottom: 3px; border-bottom: 1px solid var(--border); }
|
|
324
|
+
.graphify-section-body { font-size: 10px; color: var(--dim); line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
|
|
325
|
+
.graphify-section-body code { font-family: inherit; color: var(--teal); }
|
|
326
|
+
.graphify-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 24px; color: var(--muted); font-size: 11px; text-align: center; }
|
|
327
|
+
.graphify-build-cmd { font-family: monospace; font-size: 10px; background: var(--panel-bg); border: 1px solid var(--border); border-radius: 4px; padding: 6px 10px; color: var(--teal); margin-top: 4px; }
|
|
328
|
+
|
|
329
|
+
/* Fixed heights for canvas-based panels */
|
|
330
|
+
|
|
331
|
+
/* Chevron rotates when open */
|
|
332
|
+
.panel.open .panel-chevron { transform: rotate(90deg); }
|
|
333
|
+
|
|
334
|
+
.panel-title {
|
|
335
|
+
font-family: 'Syne', sans-serif;
|
|
336
|
+
font-weight: 600;
|
|
337
|
+
font-size: 10px;
|
|
338
|
+
letter-spacing: 0.16em;
|
|
339
|
+
text-transform: uppercase;
|
|
340
|
+
color: var(--teal);
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
gap: 6px;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.panel-badge {
|
|
347
|
+
font-family: 'Azeret Mono', monospace;
|
|
348
|
+
font-size: 10px;
|
|
349
|
+
background: rgba(0, 229, 200, 0.12);
|
|
350
|
+
color: var(--teal);
|
|
351
|
+
border: 1px solid rgba(0, 229, 200, 0.25);
|
|
352
|
+
border-radius: 3px;
|
|
353
|
+
padding: 1px 6px;
|
|
354
|
+
font-weight: 600;
|
|
355
|
+
letter-spacing: 0.04em;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.panel-body {
|
|
359
|
+
flex: 1;
|
|
360
|
+
overflow-y: auto;
|
|
361
|
+
overflow-x: hidden;
|
|
362
|
+
padding: 8px 10px;
|
|
363
|
+
min-height: 0;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.panel-body::-webkit-scrollbar { width: 3px; }
|
|
367
|
+
.panel-body::-webkit-scrollbar-track { background: transparent; }
|
|
368
|
+
.panel-body::-webkit-scrollbar-thumb { background: var(--muted); border-radius: 2px; }
|
|
369
|
+
|
|
370
|
+
/* ─── ANIMATIONS ────────────────────────────────────────────────── */
|
|
371
|
+
@keyframes pulse-dot {
|
|
372
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
373
|
+
50% { opacity: 0.5; transform: scale(0.85); }
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
@keyframes flash-teal {
|
|
377
|
+
0% { color: var(--teal); }
|
|
378
|
+
100% { color: inherit; }
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.flash {
|
|
382
|
+
animation: flash-teal 0.7s ease-out;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@keyframes fadeIn {
|
|
386
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
387
|
+
to { opacity: 1; transform: translateY(0); }
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.fade-in { animation: fadeIn 0.25s ease-out; }
|
|
391
|
+
|
|
392
|
+
/* ─── LIVE DOT ──────────────────────────────────────────────────── */
|
|
393
|
+
.live-dot {
|
|
394
|
+
display: inline-block;
|
|
395
|
+
width: 6px;
|
|
396
|
+
height: 6px;
|
|
397
|
+
border-radius: 50%;
|
|
398
|
+
background: var(--teal);
|
|
399
|
+
animation: pulse-dot 1.8s infinite;
|
|
400
|
+
flex-shrink: 0;
|
|
401
|
+
}
|
|
402
|
+
.live-dot.amber { background: var(--amber); }
|
|
403
|
+
.live-dot.muted { background: var(--muted); animation: none; }
|
|
404
|
+
.live-dot.green { background: var(--green); }
|
|
405
|
+
.live-dot.red { background: var(--red); animation: none; }
|
|
406
|
+
|
|
407
|
+
/* ─── PLACEHOLDER ──────────────────────────────────────────────── */
|
|
408
|
+
.placeholder {
|
|
409
|
+
color: var(--dim);
|
|
410
|
+
font-size: 11px;
|
|
411
|
+
display: flex;
|
|
412
|
+
align-items: center;
|
|
413
|
+
justify-content: center;
|
|
414
|
+
height: 100%;
|
|
415
|
+
letter-spacing: 0.08em;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* ─── SESSIONS PANEL ────────────────────────────────────────────── */
|
|
419
|
+
.session-item {
|
|
420
|
+
display: flex;
|
|
421
|
+
align-items: center;
|
|
422
|
+
gap: 6px;
|
|
423
|
+
padding: 5px 6px;
|
|
424
|
+
border-radius: 4px;
|
|
425
|
+
cursor: pointer;
|
|
426
|
+
border: 1px solid transparent;
|
|
427
|
+
transition: background 0.15s, border-color 0.15s;
|
|
428
|
+
margin-bottom: 3px;
|
|
429
|
+
}
|
|
430
|
+
.session-item:hover {
|
|
431
|
+
background: rgba(0, 229, 200, 0.04);
|
|
432
|
+
border-color: var(--border);
|
|
433
|
+
}
|
|
434
|
+
.session-item.expanded {
|
|
435
|
+
background: rgba(0, 229, 200, 0.06);
|
|
436
|
+
border-color: rgba(0, 229, 200, 0.2);
|
|
437
|
+
}
|
|
438
|
+
.session-id {
|
|
439
|
+
flex: 1;
|
|
440
|
+
font-size: 10px;
|
|
441
|
+
color: var(--text);
|
|
442
|
+
white-space: nowrap;
|
|
443
|
+
overflow: hidden;
|
|
444
|
+
text-overflow: ellipsis;
|
|
445
|
+
font-weight: 500;
|
|
446
|
+
}
|
|
447
|
+
.session-meta {
|
|
448
|
+
font-size: 10px;
|
|
449
|
+
color: var(--muted);
|
|
450
|
+
white-space: nowrap;
|
|
451
|
+
}
|
|
452
|
+
.session-drawer {
|
|
453
|
+
display: none;
|
|
454
|
+
background: rgba(0, 0, 0, 0.3);
|
|
455
|
+
border-radius: 4px;
|
|
456
|
+
padding: 6px 8px;
|
|
457
|
+
margin: -1px 0 4px 12px;
|
|
458
|
+
font-size: 10px;
|
|
459
|
+
color: var(--muted);
|
|
460
|
+
border-left: 2px solid rgba(0, 229, 200, 0.2);
|
|
461
|
+
}
|
|
462
|
+
.session-drawer.open { display: block; animation: fadeIn 0.2s ease-out; }
|
|
463
|
+
|
|
464
|
+
.palace-row {
|
|
465
|
+
display: flex;
|
|
466
|
+
align-items: center;
|
|
467
|
+
justify-content: space-between;
|
|
468
|
+
padding: 5px 6px;
|
|
469
|
+
border-radius: 4px;
|
|
470
|
+
background: rgba(0, 229, 200, 0.04);
|
|
471
|
+
border: 1px solid var(--border);
|
|
472
|
+
margin-top: 6px;
|
|
473
|
+
font-size: 10px;
|
|
474
|
+
}
|
|
475
|
+
.palace-label {
|
|
476
|
+
font-family: 'Syne', sans-serif;
|
|
477
|
+
font-size: 9px;
|
|
478
|
+
letter-spacing: 0.12em;
|
|
479
|
+
text-transform: uppercase;
|
|
480
|
+
color: var(--muted);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/* ─── AGENTS PANEL ──────────────────────────────────────────────── */
|
|
484
|
+
.agent-grid {
|
|
485
|
+
display: grid;
|
|
486
|
+
grid-template-columns: 1fr 1fr;
|
|
487
|
+
gap: 5px;
|
|
488
|
+
}
|
|
489
|
+
.agent-card {
|
|
490
|
+
background: rgba(0, 0, 0, 0.3);
|
|
491
|
+
border: 1px solid var(--border);
|
|
492
|
+
border-radius: 4px;
|
|
493
|
+
padding: 6px 7px;
|
|
494
|
+
display: flex;
|
|
495
|
+
flex-direction: column;
|
|
496
|
+
gap: 3px;
|
|
497
|
+
transition: border-color 0.2s;
|
|
498
|
+
}
|
|
499
|
+
.agent-card:hover { border-color: rgba(0, 229, 200, 0.25); }
|
|
500
|
+
.agent-card-top {
|
|
501
|
+
display: flex;
|
|
502
|
+
align-items: center;
|
|
503
|
+
gap: 5px;
|
|
504
|
+
}
|
|
505
|
+
.agent-name {
|
|
506
|
+
font-size: 10px;
|
|
507
|
+
font-weight: 500;
|
|
508
|
+
color: var(--text);
|
|
509
|
+
flex: 1;
|
|
510
|
+
white-space: nowrap;
|
|
511
|
+
overflow: hidden;
|
|
512
|
+
text-overflow: ellipsis;
|
|
513
|
+
}
|
|
514
|
+
.agent-type {
|
|
515
|
+
font-size: 9px;
|
|
516
|
+
color: var(--muted);
|
|
517
|
+
letter-spacing: 0.05em;
|
|
518
|
+
}
|
|
519
|
+
.agent-activity {
|
|
520
|
+
font-size: 9px;
|
|
521
|
+
color: var(--muted);
|
|
522
|
+
white-space: nowrap;
|
|
523
|
+
overflow: hidden;
|
|
524
|
+
text-overflow: ellipsis;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/* ─── TOKENS PANEL ──────────────────────────────────────────────── */
|
|
528
|
+
.token-summary {
|
|
529
|
+
display: grid;
|
|
530
|
+
grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
531
|
+
gap: 5px;
|
|
532
|
+
}
|
|
533
|
+
.token-stat {
|
|
534
|
+
background: rgba(0, 0, 0, 0.3);
|
|
535
|
+
border: 1px solid var(--border);
|
|
536
|
+
border-radius: 4px;
|
|
537
|
+
padding: 5px 6px;
|
|
538
|
+
text-align: center;
|
|
539
|
+
}
|
|
540
|
+
.token-stat-label {
|
|
541
|
+
font-size: 9px;
|
|
542
|
+
color: var(--muted);
|
|
543
|
+
letter-spacing: 0.08em;
|
|
544
|
+
text-transform: uppercase;
|
|
545
|
+
margin-bottom: 3px;
|
|
546
|
+
}
|
|
547
|
+
.token-stat-val {
|
|
548
|
+
font-size: 12px;
|
|
549
|
+
font-weight: 500;
|
|
550
|
+
color: var(--teal);
|
|
551
|
+
}
|
|
552
|
+
#tokens-canvas { display: none; }
|
|
553
|
+
|
|
554
|
+
/* ─── SWARM PANEL ───────────────────────────────────────────────── */
|
|
555
|
+
.swarm-meta {
|
|
556
|
+
display: flex;
|
|
557
|
+
flex-direction: column;
|
|
558
|
+
gap: 4px;
|
|
559
|
+
margin-bottom: 6px;
|
|
560
|
+
flex-shrink: 0;
|
|
561
|
+
}
|
|
562
|
+
.swarm-row {
|
|
563
|
+
display: flex;
|
|
564
|
+
align-items: center;
|
|
565
|
+
justify-content: space-between;
|
|
566
|
+
font-size: 10px;
|
|
567
|
+
}
|
|
568
|
+
.swarm-key { color: var(--muted); letter-spacing: 0.06em; font-size: 9px; text-transform: uppercase; }
|
|
569
|
+
.swarm-val { color: var(--text); font-weight: 600; }
|
|
570
|
+
#swarm-canvas {
|
|
571
|
+
width: 100%;
|
|
572
|
+
flex: 1;
|
|
573
|
+
display: block;
|
|
574
|
+
border-radius: 4px;
|
|
575
|
+
min-height: 0;
|
|
576
|
+
}
|
|
577
|
+
.no-swarm {
|
|
578
|
+
flex: 1;
|
|
579
|
+
display: flex;
|
|
580
|
+
align-items: center;
|
|
581
|
+
justify-content: center;
|
|
582
|
+
flex-direction: column;
|
|
583
|
+
gap: 8px;
|
|
584
|
+
color: var(--muted);
|
|
585
|
+
}
|
|
586
|
+
.no-swarm-label {
|
|
587
|
+
font-family: 'Syne', sans-serif;
|
|
588
|
+
font-size: 10px;
|
|
589
|
+
letter-spacing: 0.2em;
|
|
590
|
+
text-transform: uppercase;
|
|
591
|
+
}
|
|
592
|
+
.grid-placeholder {
|
|
593
|
+
width: 64px;
|
|
594
|
+
height: 64px;
|
|
595
|
+
background-image:
|
|
596
|
+
repeating-linear-gradient(0deg, transparent, transparent 7px, rgba(58,58,90,0.4) 7px, rgba(58,58,90,0.4) 8px),
|
|
597
|
+
repeating-linear-gradient(90deg, transparent, transparent 7px, rgba(58,58,90,0.4) 7px, rgba(58,58,90,0.4) 8px);
|
|
598
|
+
border-radius: 4px;
|
|
599
|
+
opacity: 0.5;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/* ─── MEMORY PANEL ──────────────────────────────────────────────── */
|
|
603
|
+
.memory-layout {
|
|
604
|
+
display: grid;
|
|
605
|
+
grid-template-columns: 1fr 1fr;
|
|
606
|
+
gap: 8px;
|
|
607
|
+
height: 100%;
|
|
608
|
+
}
|
|
609
|
+
.memory-left, .memory-right { display: flex; flex-direction: column; gap: 5px; overflow-y: auto; }
|
|
610
|
+
.drawer-item {
|
|
611
|
+
display: flex;
|
|
612
|
+
flex-direction: column;
|
|
613
|
+
gap: 2px;
|
|
614
|
+
padding: 4px 6px;
|
|
615
|
+
border-radius: 4px;
|
|
616
|
+
background: rgba(0, 0, 0, 0.2);
|
|
617
|
+
border: 1px solid var(--border);
|
|
618
|
+
margin-bottom: 3px;
|
|
619
|
+
cursor: default;
|
|
620
|
+
}
|
|
621
|
+
.drawer-item:hover { border-color: rgba(0,229,200,0.22); }
|
|
622
|
+
.drawer-top {
|
|
623
|
+
display: flex;
|
|
624
|
+
align-items: center;
|
|
625
|
+
justify-content: space-between;
|
|
626
|
+
gap: 5px;
|
|
627
|
+
}
|
|
628
|
+
.drawer-wing {
|
|
629
|
+
font-size: 10px;
|
|
630
|
+
font-weight: 500;
|
|
631
|
+
color: var(--text);
|
|
632
|
+
white-space: nowrap;
|
|
633
|
+
overflow: hidden;
|
|
634
|
+
text-overflow: ellipsis;
|
|
635
|
+
flex: 1;
|
|
636
|
+
}
|
|
637
|
+
.drawer-room { font-size: 9px; color: var(--muted); white-space: nowrap; }
|
|
638
|
+
.drawer-content {
|
|
639
|
+
font-size: 9px;
|
|
640
|
+
color: var(--muted);
|
|
641
|
+
white-space: nowrap;
|
|
642
|
+
overflow: hidden;
|
|
643
|
+
text-overflow: ellipsis;
|
|
644
|
+
}
|
|
645
|
+
.hnsw-badge {
|
|
646
|
+
display: inline-flex;
|
|
647
|
+
align-items: center;
|
|
648
|
+
gap: 4px;
|
|
649
|
+
font-size: 9px;
|
|
650
|
+
background: rgba(255, 183, 0, 0.1);
|
|
651
|
+
border: 1px solid rgba(255, 183, 0, 0.2);
|
|
652
|
+
color: var(--amber);
|
|
653
|
+
border-radius: 3px;
|
|
654
|
+
padding: 2px 5px;
|
|
655
|
+
letter-spacing: 0.08em;
|
|
656
|
+
}
|
|
657
|
+
.mem-stat-row {
|
|
658
|
+
display: flex;
|
|
659
|
+
align-items: center;
|
|
660
|
+
justify-content: space-between;
|
|
661
|
+
font-size: 10px;
|
|
662
|
+
padding: 4px 6px;
|
|
663
|
+
border-radius: 3px;
|
|
664
|
+
background: rgba(0,0,0,0.2);
|
|
665
|
+
border: 1px solid var(--border);
|
|
666
|
+
}
|
|
667
|
+
.mem-stat-key { color: var(--muted); font-size: 10px; }
|
|
668
|
+
.mem-stat-val { color: var(--text); font-weight: 600; }
|
|
669
|
+
|
|
670
|
+
/* ─── HOOKS PANEL ───────────────────────────────────────────────── */
|
|
671
|
+
.hooks-layout {
|
|
672
|
+
display: grid;
|
|
673
|
+
grid-template-columns: 1fr 1fr;
|
|
674
|
+
gap: 8px;
|
|
675
|
+
height: 100%;
|
|
676
|
+
}
|
|
677
|
+
.hooks-col { display: flex; flex-direction: column; gap: 5px; overflow: hidden; }
|
|
678
|
+
.route-block {
|
|
679
|
+
background: rgba(0, 0, 0, 0.3);
|
|
680
|
+
border: 1px solid var(--border);
|
|
681
|
+
border-radius: 4px;
|
|
682
|
+
padding: 7px 8px;
|
|
683
|
+
}
|
|
684
|
+
.route-task-text {
|
|
685
|
+
font-size: 10px;
|
|
686
|
+
color: var(--text);
|
|
687
|
+
line-height: 1.5;
|
|
688
|
+
margin-bottom: 5px;
|
|
689
|
+
display: -webkit-box;
|
|
690
|
+
-webkit-line-clamp: 2;
|
|
691
|
+
-webkit-box-orient: vertical;
|
|
692
|
+
overflow: hidden;
|
|
693
|
+
}
|
|
694
|
+
.route-agents {
|
|
695
|
+
display: flex;
|
|
696
|
+
flex-wrap: wrap;
|
|
697
|
+
gap: 3px;
|
|
698
|
+
}
|
|
699
|
+
.route-agent-tag {
|
|
700
|
+
font-size: 9px;
|
|
701
|
+
background: rgba(0, 229, 200, 0.1);
|
|
702
|
+
color: var(--teal);
|
|
703
|
+
border: 1px solid rgba(0, 229, 200, 0.2);
|
|
704
|
+
border-radius: 3px;
|
|
705
|
+
padding: 1px 5px;
|
|
706
|
+
letter-spacing: 0.05em;
|
|
707
|
+
}
|
|
708
|
+
.feedback-item {
|
|
709
|
+
display: flex;
|
|
710
|
+
align-items: center;
|
|
711
|
+
gap: 5px;
|
|
712
|
+
padding: 3px 5px;
|
|
713
|
+
border-radius: 3px;
|
|
714
|
+
border: 1px solid var(--border);
|
|
715
|
+
background: rgba(0,0,0,0.2);
|
|
716
|
+
margin-bottom: 3px;
|
|
717
|
+
font-size: 10px;
|
|
718
|
+
}
|
|
719
|
+
.feedback-text {
|
|
720
|
+
flex: 1;
|
|
721
|
+
white-space: nowrap;
|
|
722
|
+
overflow: hidden;
|
|
723
|
+
text-overflow: ellipsis;
|
|
724
|
+
color: var(--muted);
|
|
725
|
+
}
|
|
726
|
+
.feedback-ok { color: var(--green); font-size: 9px; }
|
|
727
|
+
.worker-tag {
|
|
728
|
+
display: inline-flex;
|
|
729
|
+
align-items: center;
|
|
730
|
+
gap: 3px;
|
|
731
|
+
font-size: 9px;
|
|
732
|
+
background: rgba(255, 183, 0, 0.07);
|
|
733
|
+
color: var(--amber);
|
|
734
|
+
border: 1px solid rgba(255, 183, 0, 0.18);
|
|
735
|
+
border-radius: 3px;
|
|
736
|
+
padding: 2px 5px;
|
|
737
|
+
margin: 2px;
|
|
738
|
+
letter-spacing: 0.05em;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* ─── KNOWLEDGE PANEL ───────────────────────────────────────────── */
|
|
742
|
+
.knowledge-counts {
|
|
743
|
+
display: grid;
|
|
744
|
+
grid-template-columns: 1fr 1fr;
|
|
745
|
+
gap: 5px;
|
|
746
|
+
margin-bottom: 7px;
|
|
747
|
+
}
|
|
748
|
+
.know-stat {
|
|
749
|
+
background: rgba(0,0,0,0.3);
|
|
750
|
+
border: 1px solid var(--border);
|
|
751
|
+
border-radius: 4px;
|
|
752
|
+
padding: 5px 7px;
|
|
753
|
+
text-align: center;
|
|
754
|
+
}
|
|
755
|
+
.know-stat-label { font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 2px; }
|
|
756
|
+
.know-stat-val { font-size: 14px; font-weight: 500; color: var(--text); }
|
|
757
|
+
.chunk-preview {
|
|
758
|
+
font-size: 10px;
|
|
759
|
+
color: var(--muted);
|
|
760
|
+
padding: 4px 6px;
|
|
761
|
+
border-radius: 3px;
|
|
762
|
+
border-left: 2px solid var(--border);
|
|
763
|
+
margin-bottom: 3px;
|
|
764
|
+
white-space: nowrap;
|
|
765
|
+
overflow: hidden;
|
|
766
|
+
text-overflow: ellipsis;
|
|
767
|
+
background: rgba(0,0,0,0.15);
|
|
768
|
+
line-height: 1.5;
|
|
769
|
+
}
|
|
770
|
+
.chunk-preview:hover { border-left-color: var(--teal); color: var(--text); }
|
|
771
|
+
/* Chunk cards in palace KNOWLEDGE tab */
|
|
772
|
+
.chunk-card {
|
|
773
|
+
background: rgba(0,0,0,0.25); border: 1px solid var(--border); border-radius: 4px;
|
|
774
|
+
padding: 10px 12px; display: flex; flex-direction: column; gap: 5px;
|
|
775
|
+
transition: border-color 0.12s;
|
|
776
|
+
}
|
|
777
|
+
.chunk-card:hover { border-color: rgba(0,229,200,0.3); }
|
|
778
|
+
.chunk-card-src { font-size: 8px; color: var(--teal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: 0.04em; }
|
|
779
|
+
.chunk-card-text { font-size: 10px; color: var(--text); line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
|
|
780
|
+
.chunk-card-ns { font-size: 8px; color: var(--muted); }
|
|
781
|
+
.chunk-card-actions { display: flex; gap: 6px; margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--border); }
|
|
782
|
+
/* Chunk edit modal */
|
|
783
|
+
#po-chunk-edit-modal { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.65); z-index: 22; align-items: center; justify-content: center; }
|
|
784
|
+
#po-chunk-edit-modal.open { display: flex; }
|
|
785
|
+
|
|
786
|
+
/* ─── METRICS PANEL ─────────────────────────────────────────────── */
|
|
787
|
+
.metric-block {
|
|
788
|
+
background: rgba(0,0,0,0.25);
|
|
789
|
+
border: 1px solid var(--border);
|
|
790
|
+
border-radius: 4px;
|
|
791
|
+
padding: 6px 8px;
|
|
792
|
+
margin-bottom: 5px;
|
|
793
|
+
}
|
|
794
|
+
.metric-block-title {
|
|
795
|
+
font-family: 'Syne', sans-serif;
|
|
796
|
+
font-size: 9px;
|
|
797
|
+
letter-spacing: 0.12em;
|
|
798
|
+
text-transform: uppercase;
|
|
799
|
+
color: var(--muted);
|
|
800
|
+
margin-bottom: 5px;
|
|
801
|
+
}
|
|
802
|
+
.metric-row {
|
|
803
|
+
display: flex;
|
|
804
|
+
align-items: center;
|
|
805
|
+
justify-content: space-between;
|
|
806
|
+
font-size: 10px;
|
|
807
|
+
margin-bottom: 3px;
|
|
808
|
+
}
|
|
809
|
+
.metric-key { color: var(--muted); font-size: 10px; }
|
|
810
|
+
.metric-val { color: var(--text); font-weight: 600; }
|
|
811
|
+
.security-ok { color: var(--green); }
|
|
812
|
+
.security-warn { color: var(--amber); }
|
|
813
|
+
.security-fail { color: var(--red); }
|
|
814
|
+
|
|
815
|
+
/* ─── ACTIVITY PANEL ────────────────────────────────────────────── */
|
|
816
|
+
#activity-log {
|
|
817
|
+
display: flex;
|
|
818
|
+
flex-direction: column;
|
|
819
|
+
gap: 3px;
|
|
820
|
+
}
|
|
821
|
+
.activity-entry {
|
|
822
|
+
display: flex;
|
|
823
|
+
align-items: flex-start;
|
|
824
|
+
gap: 6px;
|
|
825
|
+
font-size: 10px;
|
|
826
|
+
line-height: 1.4;
|
|
827
|
+
padding: 3px 5px;
|
|
828
|
+
border-radius: 3px;
|
|
829
|
+
border-left: 2px solid transparent;
|
|
830
|
+
animation: fadeIn 0.2s ease-out;
|
|
831
|
+
}
|
|
832
|
+
.activity-entry.type-session { border-left-color: var(--teal); background: rgba(0,229,200,0.03); }
|
|
833
|
+
.activity-entry.type-swarm { border-left-color: var(--amber); background: rgba(255,183,0,0.03); }
|
|
834
|
+
.activity-entry.type-agent { border-left-color: var(--green); background: rgba(0,229,135,0.03); }
|
|
835
|
+
.activity-entry.type-error { border-left-color: var(--red); background: rgba(255,68,102,0.03); }
|
|
836
|
+
.activity-entry.type-default { border-left-color: var(--muted); }
|
|
837
|
+
.activity-time { color: var(--dim); white-space: nowrap; font-size: 9px; flex-shrink: 0; letter-spacing: 0.03em; }
|
|
838
|
+
.activity-msg { color: var(--text); flex: 1; font-size: 10px; }
|
|
839
|
+
|
|
840
|
+
/* ─── SYSTEM PANEL ──────────────────────────────────────────────── */
|
|
841
|
+
.sys-row {
|
|
842
|
+
display: flex;
|
|
843
|
+
align-items: center;
|
|
844
|
+
justify-content: space-between;
|
|
845
|
+
font-size: 10px;
|
|
846
|
+
padding: 4px 6px;
|
|
847
|
+
border-radius: 3px;
|
|
848
|
+
border: 1px solid var(--border);
|
|
849
|
+
background: rgba(0,0,0,0.2);
|
|
850
|
+
margin-bottom: 4px;
|
|
851
|
+
}
|
|
852
|
+
.sys-key { color: var(--muted); letter-spacing: 0.06em; font-size: 10px; }
|
|
853
|
+
.sys-val { color: var(--text); font-weight: 600; }
|
|
854
|
+
|
|
855
|
+
/* ─── SECTION LABELS ────────────────────────────────────────────── */
|
|
856
|
+
.section-label {
|
|
857
|
+
font-family: 'Syne', sans-serif;
|
|
858
|
+
font-size: 9px;
|
|
859
|
+
letter-spacing: 0.14em;
|
|
860
|
+
text-transform: uppercase;
|
|
861
|
+
color: var(--muted);
|
|
862
|
+
margin-bottom: 5px;
|
|
863
|
+
margin-top: 4px;
|
|
864
|
+
opacity: 0.85;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/* ─── SCROLLBAR GLOBAL ──────────────────────────────────────────── */
|
|
868
|
+
* {
|
|
869
|
+
scrollbar-width: thin;
|
|
870
|
+
scrollbar-color: var(--muted) transparent;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/* ─── SESSION DETAIL OVERLAY ──────────────────────────────────── */
|
|
874
|
+
#session-overlay {
|
|
875
|
+
position: fixed; inset: 0; z-index: 1000;
|
|
876
|
+
background: var(--bg);
|
|
877
|
+
display: none; flex-direction: column;
|
|
878
|
+
overflow: hidden;
|
|
879
|
+
}
|
|
880
|
+
#session-overlay.open { display: flex; }
|
|
881
|
+
#sd-header {
|
|
882
|
+
display: flex; align-items: center; gap: 12px;
|
|
883
|
+
padding: 10px 16px; border-bottom: 1px solid var(--border);
|
|
884
|
+
flex-shrink: 0;
|
|
885
|
+
}
|
|
886
|
+
#sd-back {
|
|
887
|
+
background: none; border: 1px solid var(--border); color: var(--teal);
|
|
888
|
+
font-family: var(--font); font-size: 11px; letter-spacing: 0.08em;
|
|
889
|
+
padding: 4px 10px; cursor: pointer; border-radius: 3px;
|
|
890
|
+
transition: background 0.15s;
|
|
891
|
+
}
|
|
892
|
+
#sd-back:hover { background: rgba(0,229,200,0.08); }
|
|
893
|
+
#sd-title { font-size: 12px; color: var(--text); font-weight: 600; letter-spacing: 0.08em; }
|
|
894
|
+
#sd-subtitle { font-size: 10px; color: var(--muted); flex: 1; }
|
|
895
|
+
#sd-stats-bar {
|
|
896
|
+
display: flex; gap: 12px; font-size: 10px; color: var(--muted);
|
|
897
|
+
}
|
|
898
|
+
#sd-stats-bar span { display: flex; align-items: center; gap: 4px; }
|
|
899
|
+
#sd-body {
|
|
900
|
+
display: grid; grid-template-columns: 1fr 280px;
|
|
901
|
+
flex: 1; overflow: hidden;
|
|
902
|
+
gap: 0;
|
|
903
|
+
}
|
|
904
|
+
#sd-timeline {
|
|
905
|
+
overflow-y: auto; padding: 12px 16px; display: flex; flex-direction: column; gap: 6px;
|
|
906
|
+
border-right: 1px solid var(--border);
|
|
907
|
+
}
|
|
908
|
+
#sd-sidebar {
|
|
909
|
+
overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 12px;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/* events */
|
|
913
|
+
.ev { border-radius: 4px; padding: 6px 10px; font-size: 11px; line-height: 1.45; }
|
|
914
|
+
.ev-user {
|
|
915
|
+
background: rgba(74,158,255,0.08); border-left: 3px solid #4A9EFF;
|
|
916
|
+
color: var(--text);
|
|
917
|
+
}
|
|
918
|
+
.ev-user::before { content: '⬤ USER '; font-size: 9px; color: #4A9EFF; letter-spacing: 0.1em; display: block; margin-bottom: 3px; }
|
|
919
|
+
.ev-text {
|
|
920
|
+
background: rgba(0,229,200,0.05); border-left: 3px solid var(--teal);
|
|
921
|
+
color: var(--text);
|
|
922
|
+
}
|
|
923
|
+
.ev-text::before { content: '⬤ ASSISTANT '; font-size: 9px; color: var(--teal); letter-spacing: 0.1em; display: block; margin-bottom: 3px; }
|
|
924
|
+
.ev-thinking {
|
|
925
|
+
background: rgba(255,255,255,0.02); border-left: 3px solid #444;
|
|
926
|
+
color: var(--muted); font-style: italic; font-size: 10px;
|
|
927
|
+
}
|
|
928
|
+
.ev-thinking::before { content: '◌ THINKING '; font-size: 9px; color: #555; letter-spacing: 0.1em; display: block; margin-bottom: 3px; }
|
|
929
|
+
.ev-tool {
|
|
930
|
+
display: flex; align-items: center; gap: 8px;
|
|
931
|
+
padding: 4px 8px; border-radius: 3px;
|
|
932
|
+
background: rgba(255,255,255,0.03); border: 1px solid var(--border);
|
|
933
|
+
font-size: 10px;
|
|
934
|
+
}
|
|
935
|
+
.ev-tool-badge {
|
|
936
|
+
font-size: 9px; font-weight: 700; letter-spacing: 0.06em;
|
|
937
|
+
padding: 2px 5px; border-radius: 2px; flex-shrink: 0;
|
|
938
|
+
text-transform: uppercase;
|
|
939
|
+
}
|
|
940
|
+
.ev-tool-label { color: var(--text); flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
941
|
+
.ev-tool-ts { color: var(--muted); font-size: 9px; flex-shrink: 0; }
|
|
942
|
+
.ev-tool-result {
|
|
943
|
+
margin-left: 16px; padding: 3px 8px;
|
|
944
|
+
background: rgba(0,0,0,0.3); border-left: 2px solid #333;
|
|
945
|
+
font-size: 10px; color: var(--muted);
|
|
946
|
+
white-space: pre-wrap; word-break: break-all; max-height: 80px; overflow-y: auto;
|
|
947
|
+
border-radius: 0 3px 3px 0;
|
|
948
|
+
}
|
|
949
|
+
.ev-tool-result.error { border-left-color: #EF5350; color: #EF5350; }
|
|
950
|
+
.ev-agent-spawn {
|
|
951
|
+
background: rgba(176,120,255,0.08); border: 1px solid rgba(176,120,255,0.3);
|
|
952
|
+
border-radius: 4px; padding: 6px 10px;
|
|
953
|
+
}
|
|
954
|
+
.ev-agent-spawn-header {
|
|
955
|
+
display: flex; align-items: center; gap: 8px; font-size: 10px;
|
|
956
|
+
}
|
|
957
|
+
.ev-agent-type {
|
|
958
|
+
background: rgba(176,120,255,0.2); color: #B078FF;
|
|
959
|
+
padding: 2px 6px; border-radius: 2px; font-size: 9px; font-weight: 700; letter-spacing: 0.08em;
|
|
960
|
+
}
|
|
961
|
+
.ev-agent-label { color: var(--text); font-size: 10px; flex: 1; }
|
|
962
|
+
.ev-agent-bg { font-size: 9px; color: #888; }
|
|
963
|
+
|
|
964
|
+
/* tool badge colors */
|
|
965
|
+
.cat-file { background: rgba(74,158,255,0.15); color: #4A9EFF; }
|
|
966
|
+
.cat-bash { background: rgba(255,140,66,0.15); color: #FF8C42; }
|
|
967
|
+
.cat-agent { background: rgba(176,120,255,0.15); color: #B078FF; }
|
|
968
|
+
.cat-memory { background: rgba(255,215,0,0.15); color: #FFD700; }
|
|
969
|
+
.cat-web { background: rgba(0,229,200,0.15); color: var(--teal); }
|
|
970
|
+
.cat-task { background: rgba(102,187,106,0.15); color: #66BB6A; }
|
|
971
|
+
.cat-skill { background: rgba(255,128,171,0.15); color: #FF80AB; }
|
|
972
|
+
.cat-search { background: rgba(239,83,80,0.15); color: #EF5350; }
|
|
973
|
+
.cat-mcp { background: rgba(38,198,218,0.15); color: #26C6DA; }
|
|
974
|
+
.cat-other { background: rgba(144,164,174,0.1); color: #90A4AE; }
|
|
975
|
+
|
|
976
|
+
/* sidebar */
|
|
977
|
+
.sd-section-title {
|
|
978
|
+
font-size: 9px; letter-spacing: 0.1em; color: var(--muted);
|
|
979
|
+
border-bottom: 1px solid var(--border); padding-bottom: 4px; margin-bottom: 6px;
|
|
980
|
+
}
|
|
981
|
+
.tool-breakdown { display: flex; flex-wrap: wrap; gap: 5px; }
|
|
982
|
+
.tool-chip {
|
|
983
|
+
display: flex; align-items: center; gap: 4px;
|
|
984
|
+
padding: 3px 7px; border-radius: 10px; font-size: 10px;
|
|
985
|
+
}
|
|
986
|
+
.tool-chip-count { font-weight: 700; }
|
|
987
|
+
.agent-node {
|
|
988
|
+
display: flex; align-items: center; gap: 6px; padding: 4px 6px;
|
|
989
|
+
border-radius: 3px; font-size: 10px; color: var(--text);
|
|
990
|
+
background: rgba(176,120,255,0.06); margin-bottom: 3px;
|
|
991
|
+
}
|
|
992
|
+
.agent-node-dot { width: 6px; height: 6px; border-radius: 50%; background: #B078FF; flex-shrink: 0; }
|
|
993
|
+
.memory-op {
|
|
994
|
+
display: flex; align-items: center; gap: 6px;
|
|
995
|
+
padding: 3px 6px; font-size: 10px; color: var(--muted);
|
|
996
|
+
border-left: 2px solid #FFD700; padding-left: 6px; margin-bottom: 3px;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
/* ─── PALACE OVERLAY ────────────────────────────────────────────── */
|
|
1000
|
+
#palace-overlay {
|
|
1001
|
+
position: fixed; inset: 0; z-index: 1000;
|
|
1002
|
+
background: var(--bg);
|
|
1003
|
+
display: none; flex-direction: column;
|
|
1004
|
+
overflow: hidden;
|
|
1005
|
+
}
|
|
1006
|
+
#palace-overlay.open { display: flex; }
|
|
1007
|
+
#po-header {
|
|
1008
|
+
display: flex; align-items: center; gap: 14px;
|
|
1009
|
+
padding: 10px 16px; border-bottom: 1px solid var(--border);
|
|
1010
|
+
flex-shrink: 0; background: rgba(7,8,15,0.97);
|
|
1011
|
+
backdrop-filter: blur(16px);
|
|
1012
|
+
}
|
|
1013
|
+
#po-back {
|
|
1014
|
+
background: none; border: 1px solid var(--border); color: var(--teal);
|
|
1015
|
+
font-family: 'Azeret Mono', monospace; font-size: 11px; letter-spacing: 0.08em;
|
|
1016
|
+
padding: 4px 10px; cursor: pointer; border-radius: 3px; transition: background 0.15s;
|
|
1017
|
+
}
|
|
1018
|
+
#po-back:hover { background: rgba(0,229,200,0.08); }
|
|
1019
|
+
#po-title {
|
|
1020
|
+
font-family: 'Syne', sans-serif; font-weight: 700; font-size: 13px;
|
|
1021
|
+
color: var(--teal); letter-spacing: 0.14em; text-transform: uppercase;
|
|
1022
|
+
}
|
|
1023
|
+
#po-tabs { display: flex; gap: 2px; margin-left: 4px; }
|
|
1024
|
+
.po-tab {
|
|
1025
|
+
background: none; border: 1px solid transparent; color: var(--muted);
|
|
1026
|
+
font-family: 'Azeret Mono', monospace; font-size: 10px; letter-spacing: 0.1em;
|
|
1027
|
+
padding: 4px 12px; cursor: pointer; border-radius: 3px; transition: all 0.15s;
|
|
1028
|
+
text-transform: uppercase;
|
|
1029
|
+
}
|
|
1030
|
+
.po-tab:hover { color: var(--text); border-color: var(--border); }
|
|
1031
|
+
.po-tab.active { color: var(--teal); border-color: rgba(0,229,200,0.35); background: rgba(0,229,200,0.06); }
|
|
1032
|
+
#po-stats { margin-left: auto; font-size: 10px; color: var(--muted); display: flex; gap: 16px; }
|
|
1033
|
+
#po-body { flex: 1; overflow: hidden; position: relative; }
|
|
1034
|
+
.po-tab-pane { display: none; position: absolute; inset: 0; }
|
|
1035
|
+
.po-tab-pane.active { display: flex; }
|
|
1036
|
+
|
|
1037
|
+
/* Drawers pane */
|
|
1038
|
+
#po-drawers-tab { flex-direction: row; }
|
|
1039
|
+
#po-drawers-sidebar {
|
|
1040
|
+
width: 280px; flex-shrink: 0; border-right: 1px solid var(--border);
|
|
1041
|
+
display: flex; flex-direction: column; overflow: hidden;
|
|
1042
|
+
}
|
|
1043
|
+
#po-search {
|
|
1044
|
+
background: rgba(0,0,0,0.4); border: none; border-bottom: 1px solid var(--border);
|
|
1045
|
+
color: var(--text); font-family: 'Azeret Mono', monospace; font-size: 11px;
|
|
1046
|
+
padding: 8px 12px; outline: none;
|
|
1047
|
+
}
|
|
1048
|
+
#po-search::placeholder { color: var(--dim); }
|
|
1049
|
+
#po-search:focus { border-bottom-color: rgba(0,229,200,0.4); }
|
|
1050
|
+
#po-drawer-list { flex: 1; overflow-y: auto; padding: 6px; }
|
|
1051
|
+
.po-drawer-item {
|
|
1052
|
+
padding: 7px 10px; border-radius: 4px; cursor: pointer; margin-bottom: 3px;
|
|
1053
|
+
border: 1px solid transparent; transition: all 0.12s;
|
|
1054
|
+
display: flex; flex-direction: column; gap: 2px;
|
|
1055
|
+
}
|
|
1056
|
+
.po-drawer-item:hover { background: rgba(0,229,200,0.04); border-color: var(--border); }
|
|
1057
|
+
.po-drawer-item.selected { background: rgba(0,229,200,0.08); border-color: rgba(0,229,200,0.3); }
|
|
1058
|
+
.po-drawer-wing { font-size: 10px; font-weight: 600; color: var(--text); }
|
|
1059
|
+
.po-drawer-room { font-size: 9px; color: var(--teal); letter-spacing: 0.06em; }
|
|
1060
|
+
.po-drawer-preview { font-size: 10px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1061
|
+
.po-wing-header {
|
|
1062
|
+
font-family: 'Syne', sans-serif; font-size: 9px; color: var(--dim);
|
|
1063
|
+
letter-spacing: 0.14em; text-transform: uppercase; padding: 8px 8px 4px;
|
|
1064
|
+
border-bottom: 1px solid rgba(0,229,200,0.08); margin-bottom: 3px;
|
|
1065
|
+
}
|
|
1066
|
+
#po-drawer-detail {
|
|
1067
|
+
flex: 1; overflow-y: auto; padding: 20px 24px;
|
|
1068
|
+
display: flex; flex-direction: column; gap: 12px;
|
|
1069
|
+
}
|
|
1070
|
+
.po-select-hint {
|
|
1071
|
+
height: 100%; display: flex; align-items: center; justify-content: center;
|
|
1072
|
+
font-size: 11px; color: var(--dim); letter-spacing: 0.1em;
|
|
1073
|
+
}
|
|
1074
|
+
.po-detail-field { display: flex; flex-direction: column; gap: 4px; }
|
|
1075
|
+
.po-detail-label {
|
|
1076
|
+
font-size: 9px; color: var(--dim); letter-spacing: 0.14em;
|
|
1077
|
+
text-transform: uppercase; font-family: 'Syne', sans-serif;
|
|
1078
|
+
}
|
|
1079
|
+
.po-detail-value {
|
|
1080
|
+
font-size: 11px; color: var(--text); background: rgba(0,0,0,0.3);
|
|
1081
|
+
border: 1px solid var(--border); border-radius: 4px; padding: 8px 10px;
|
|
1082
|
+
line-height: 1.6; white-space: pre-wrap; word-break: break-word;
|
|
1083
|
+
}
|
|
1084
|
+
.po-detail-value.mono { font-family: 'Azeret Mono', monospace; font-size: 10px; }
|
|
1085
|
+
|
|
1086
|
+
/* Memory action buttons */
|
|
1087
|
+
.po-action-bar { display: flex; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
|
|
1088
|
+
.po-btn { font-family: 'Azeret Mono', monospace; font-size: 9px; letter-spacing: 0.08em; padding: 4px 12px; border-radius: 3px; cursor: pointer; transition: background 0.15s; }
|
|
1089
|
+
.po-btn-edit { background: none; border: 1px solid rgba(0,229,200,0.35); color: var(--teal); }
|
|
1090
|
+
.po-btn-edit:hover { background: rgba(0,229,200,0.1); }
|
|
1091
|
+
.po-btn-delete { background: none; border: 1px solid rgba(255,80,80,0.35); color: #ff6b6b; }
|
|
1092
|
+
.po-btn-delete:hover { background: rgba(255,80,80,0.1); }
|
|
1093
|
+
.po-btn-save { background: rgba(0,229,200,0.15); border: 1px solid rgba(0,229,200,0.45); color: var(--teal); }
|
|
1094
|
+
.po-btn-save:hover { background: rgba(0,229,200,0.25); }
|
|
1095
|
+
.po-btn-cancel { background: none; border: 1px solid var(--border); color: var(--muted); }
|
|
1096
|
+
.po-btn-cancel:hover { background: rgba(255,255,255,0.04); }
|
|
1097
|
+
/* New memory button */
|
|
1098
|
+
#po-search-row { display: flex; gap: 4px; padding: 6px 8px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
|
|
1099
|
+
#po-search-row #po-search { flex: 1; border-bottom: none; padding: 4px 8px; }
|
|
1100
|
+
#po-new-btn { font-family: 'Azeret Mono', monospace; font-size: 13px; background: none; border: 1px solid rgba(0,229,200,0.3); color: var(--teal); width: 26px; height: 26px; cursor: pointer; border-radius: 3px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background 0.15s; }
|
|
1101
|
+
#po-new-btn:hover { background: rgba(0,229,200,0.1); }
|
|
1102
|
+
/* Edit modal */
|
|
1103
|
+
#po-edit-modal { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.65); z-index: 20; align-items: center; justify-content: center; }
|
|
1104
|
+
#po-edit-modal.open { display: flex; }
|
|
1105
|
+
#po-edit-box { background: #1a1a2e; border: 1px solid rgba(0,229,200,0.25); border-radius: 6px; width: min(640px, 90%); max-height: 80vh; display: flex; flex-direction: column; box-shadow: 0 16px 48px rgba(0,0,0,0.6); }
|
|
1106
|
+
#po-edit-hdr { display: flex; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--border); gap: 10px; }
|
|
1107
|
+
#po-edit-title { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; color: var(--text); flex: 1; }
|
|
1108
|
+
#po-edit-close { background: none; border: none; color: var(--muted); font-size: 14px; cursor: pointer; padding: 0 2px; }
|
|
1109
|
+
#po-edit-close:hover { color: var(--text); }
|
|
1110
|
+
#po-edit-textarea { flex: 1; background: rgba(0,0,0,0.4); border: none; border-bottom: 1px solid var(--border); color: var(--text); font-family: 'Azeret Mono', monospace; font-size: 11px; line-height: 1.6; padding: 14px 16px; resize: none; outline: none; min-height: 300px; white-space: pre; overflow-x: auto; }
|
|
1111
|
+
#po-edit-footer { display: flex; align-items: center; gap: 8px; padding: 10px 16px; }
|
|
1112
|
+
#po-edit-status { font-size: 10px; color: var(--muted); margin-left: auto; }
|
|
1113
|
+
/* Template picker */
|
|
1114
|
+
#po-tpl-picker { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.65); z-index: 21; align-items: center; justify-content: center; }
|
|
1115
|
+
#po-tpl-picker.open { display: flex; }
|
|
1116
|
+
#po-tpl-box { background: #1a1a2e; border: 1px solid rgba(0,229,200,0.25); border-radius: 6px; width: min(400px, 90%); display: flex; flex-direction: column; box-shadow: 0 16px 48px rgba(0,0,0,0.6); padding: 20px; gap: 12px; }
|
|
1117
|
+
.po-tpl-option { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 4px; cursor: pointer; transition: border-color 0.15s, background 0.15s; }
|
|
1118
|
+
.po-tpl-option:hover { border-color: rgba(0,229,200,0.35); background: rgba(0,229,200,0.04); }
|
|
1119
|
+
.po-tpl-name { font-size: 10px; font-weight: 600; letter-spacing: 0.08em; }
|
|
1120
|
+
.po-tpl-desc { font-size: 9px; color: var(--muted); }
|
|
1121
|
+
|
|
1122
|
+
/* Sessions pane */
|
|
1123
|
+
#po-sessions-tab { flex-direction: row; }
|
|
1124
|
+
#po-sessions-list {
|
|
1125
|
+
width: 300px; flex-shrink: 0; border-right: 1px solid var(--border);
|
|
1126
|
+
overflow-y: auto; padding: 6px;
|
|
1127
|
+
}
|
|
1128
|
+
.po-session-item {
|
|
1129
|
+
display: flex; align-items: center; gap: 8px;
|
|
1130
|
+
padding: 7px 10px; border-radius: 4px; cursor: pointer; margin-bottom: 3px;
|
|
1131
|
+
border: 1px solid transparent; transition: all 0.12s;
|
|
1132
|
+
}
|
|
1133
|
+
.po-session-item:hover { background: rgba(0,229,200,0.04); border-color: var(--border); }
|
|
1134
|
+
.po-session-item.selected { background: rgba(0,229,200,0.08); border-color: rgba(0,229,200,0.3); }
|
|
1135
|
+
.po-session-id { font-size: 10px; font-weight: 600; color: var(--text); flex: 1; font-family: 'Azeret Mono', monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1136
|
+
.po-session-meta { font-size: 9px; color: var(--muted); white-space: nowrap; }
|
|
1137
|
+
#po-sessions-detail {
|
|
1138
|
+
flex: 1; overflow: hidden; display: flex; flex-direction: column;
|
|
1139
|
+
}
|
|
1140
|
+
#po-sd-hint { padding: 24px; color: var(--muted); font-size: 10px; text-align: center; }
|
|
1141
|
+
#po-sd-header {
|
|
1142
|
+
padding: 10px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0;
|
|
1143
|
+
display: flex; flex-direction: column; gap: 3px;
|
|
1144
|
+
}
|
|
1145
|
+
#po-sd-stats-bar {
|
|
1146
|
+
display: flex; gap: 12px; font-size: 10px; color: var(--muted); padding: 6px 16px;
|
|
1147
|
+
border-bottom: 1px solid var(--border); flex-shrink: 0;
|
|
1148
|
+
}
|
|
1149
|
+
#po-sd-stats-bar span { display: flex; align-items: center; gap: 4px; }
|
|
1150
|
+
#po-sd-body {
|
|
1151
|
+
display: grid; grid-template-columns: 1fr 220px; flex: 1; overflow: hidden;
|
|
1152
|
+
}
|
|
1153
|
+
#po-sd-timeline {
|
|
1154
|
+
overflow-y: auto; padding: 10px 14px; display: flex; flex-direction: column; gap: 6px;
|
|
1155
|
+
border-right: 1px solid var(--border);
|
|
1156
|
+
}
|
|
1157
|
+
#po-sd-sidebar {
|
|
1158
|
+
overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 12px;
|
|
1159
|
+
}
|
|
1160
|
+
.po-sd-sidebar-section { display: flex; flex-direction: column; gap: 4px; }
|
|
1161
|
+
.po-sd-sidebar-label { font-size: 9px; color: var(--muted); letter-spacing: 0.1em; margin-bottom: 2px; }
|
|
1162
|
+
|
|
1163
|
+
/* Graph pane */
|
|
1164
|
+
#po-graph-tab { flex-direction: column; }
|
|
1165
|
+
#po-graph-controls {
|
|
1166
|
+
padding: 6px 12px; border-bottom: 1px solid var(--border);
|
|
1167
|
+
display: flex; align-items: center; gap: 16px; flex-shrink: 0;
|
|
1168
|
+
font-size: 10px; color: var(--muted); letter-spacing: 0.08em;
|
|
1169
|
+
}
|
|
1170
|
+
#po-graph-controls label { display: flex; align-items: center; gap: 5px; cursor: pointer; }
|
|
1171
|
+
#po-kg-canvas { flex: 1; width: 100%; display: block; }
|
|
1172
|
+
|
|
1173
|
+
/* Knowledge graph pane */
|
|
1174
|
+
#po-knowledge-tab { flex-direction: row; }
|
|
1175
|
+
#po-knowledge-sidebar {
|
|
1176
|
+
width: 200px; flex-shrink: 0; border-right: 1px solid var(--border);
|
|
1177
|
+
padding: 16px 14px; overflow-y: auto; background: rgba(0,0,0,0.12);
|
|
1178
|
+
}
|
|
1179
|
+
#po-knowledge-canvas-wrap {
|
|
1180
|
+
flex: 1; min-width: 0; border-right: 1px solid var(--border);
|
|
1181
|
+
display: flex; flex-direction: column; position: relative;
|
|
1182
|
+
}
|
|
1183
|
+
#po-knowledge-canvas-controls {
|
|
1184
|
+
padding: 5px 12px; border-bottom: 1px solid var(--border);
|
|
1185
|
+
display: flex; align-items: center; gap: 14px; flex-shrink: 0;
|
|
1186
|
+
font-size: 9px; color: var(--muted); letter-spacing: 0.07em;
|
|
1187
|
+
}
|
|
1188
|
+
#po-knowledge-canvas-controls label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
|
|
1189
|
+
#po-kg2-canvas { flex: 1; width: 100%; display: block; }
|
|
1190
|
+
#po-knowledge-main { flex: 1; min-width: 240px; overflow-y: auto; padding: 16px 20px; }
|
|
1191
|
+
|
|
1192
|
+
/* Sidebar stat blocks */
|
|
1193
|
+
.kg-stat-group { margin-bottom: 18px; }
|
|
1194
|
+
.kg-stat-group-label { font-size: 8px; font-weight: 700; letter-spacing: 0.12em; color: var(--muted); text-transform: uppercase; margin-bottom: 10px; padding-bottom: 4px; border-bottom: 1px solid rgba(255,255,255,0.05); }
|
|
1195
|
+
.kg-stat-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 7px; }
|
|
1196
|
+
.kg-stat-key { font-size: 9px; color: var(--muted); letter-spacing: 0.03em; }
|
|
1197
|
+
.kg-stat-val { font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
|
|
1198
|
+
.kg-bar-wrap { margin: 4px 0 10px; height: 3px; background: rgba(255,255,255,0.06); border-radius: 2px; overflow: hidden; }
|
|
1199
|
+
.kg-bar-fill { height: 100%; border-radius: 2px; transition: width 0.6s ease; }
|
|
1200
|
+
.kg-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 8px; letter-spacing: 0.08em; padding: 2px 6px; border-radius: 2px; font-weight: 600; margin-bottom: 5px; }
|
|
1201
|
+
.kg-badge-ok { background: rgba(0,229,200,0.12); color: var(--teal); border: 1px solid rgba(0,229,200,0.2); }
|
|
1202
|
+
.kg-badge-warn { background: rgba(255,183,77,0.1); color: var(--amber); border: 1px solid rgba(255,183,77,0.2); }
|
|
1203
|
+
.kg-action-btn { display: block; width: 100%; margin-top: 6px; background: rgba(0,229,200,0.07); border: 1px solid rgba(0,229,200,0.2); color: var(--teal); font-family: var(--font); font-size: 8px; letter-spacing: 0.1em; padding: 5px 0; cursor: pointer; border-radius: 2px; text-align: center; transition: background 0.15s, border-color 0.15s; }
|
|
1204
|
+
.kg-action-btn:hover { background: rgba(0,229,200,0.14); border-color: rgba(0,229,200,0.35); }
|
|
1205
|
+
|
|
1206
|
+
/* Main report cards */
|
|
1207
|
+
.kg-report-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
|
1208
|
+
.kg-card { background: rgba(255,255,255,0.025); border: 1px solid var(--border); border-radius: 4px; padding: 14px 16px; }
|
|
1209
|
+
.kg-card-wide { grid-column: 1 / -1; }
|
|
1210
|
+
.kg-card-title { font-size: 8px; font-weight: 700; letter-spacing: 0.12em; color: var(--muted); text-transform: uppercase; margin-bottom: 10px; display: flex; align-items: center; gap: 6px; }
|
|
1211
|
+
.kg-card-title-icon { font-size: 12px; line-height: 1; }
|
|
1212
|
+
.kg-card-body { font-size: 10px; color: var(--dim); line-height: 1.75; white-space: pre-wrap; word-break: break-word; }
|
|
1213
|
+
.kg-card-body code { color: var(--teal); font-family: inherit; }
|
|
1214
|
+
.kg-card:hover { border-color: rgba(255,255,255,0.1); background: rgba(255,255,255,0.035); transition: all 0.15s; }
|
|
1215
|
+
|
|
1216
|
+
/* Node list inside cards (god nodes etc.) */
|
|
1217
|
+
.kg-node-list { list-style: none; margin: 0; padding: 0; }
|
|
1218
|
+
.kg-node-item { display: flex; align-items: center; gap: 8px; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.04); }
|
|
1219
|
+
.kg-node-item:last-child { border-bottom: none; }
|
|
1220
|
+
.kg-node-rank { font-size: 8px; color: var(--muted); width: 16px; text-align: right; flex-shrink: 0; }
|
|
1221
|
+
.kg-node-name { font-size: 10px; color: var(--teal); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1222
|
+
.kg-node-meta { font-size: 8px; color: var(--muted); flex-shrink: 0; }
|
|
1223
|
+
|
|
1224
|
+
</style>
|
|
1225
|
+
</head>
|
|
1226
|
+
<body>
|
|
1227
|
+
|
|
1228
|
+
<!-- ═══════════════════ SESSION DETAIL OVERLAY ═══════════════════ -->
|
|
1229
|
+
<div id="session-overlay">
|
|
1230
|
+
<div id="sd-header">
|
|
1231
|
+
<button id="sd-back" onclick="closeSessionDetail()">← BACK</button>
|
|
1232
|
+
<span id="sd-title">SESSION</span>
|
|
1233
|
+
<span id="sd-subtitle"></span>
|
|
1234
|
+
<div id="sd-stats-bar">
|
|
1235
|
+
<span id="sd-stat-turns"></span>
|
|
1236
|
+
<span id="sd-stat-tools"></span>
|
|
1237
|
+
<span id="sd-stat-agents"></span>
|
|
1238
|
+
<span id="sd-stat-mem"></span>
|
|
1239
|
+
</div>
|
|
1240
|
+
</div>
|
|
1241
|
+
<div id="sd-body">
|
|
1242
|
+
<div id="sd-timeline"><div class="placeholder">LOADING…</div></div>
|
|
1243
|
+
<div id="sd-sidebar">
|
|
1244
|
+
<div>
|
|
1245
|
+
<div class="sd-section-title">TOOL BREAKDOWN</div>
|
|
1246
|
+
<div id="sd-tool-breakdown" class="tool-breakdown"></div>
|
|
1247
|
+
</div>
|
|
1248
|
+
<div>
|
|
1249
|
+
<div class="sd-section-title">AGENT SPAWNS</div>
|
|
1250
|
+
<div id="sd-agent-tree"></div>
|
|
1251
|
+
</div>
|
|
1252
|
+
<div>
|
|
1253
|
+
<div class="sd-section-title">MEMORY OPS</div>
|
|
1254
|
+
<div id="sd-memory-ops"></div>
|
|
1255
|
+
</div>
|
|
1256
|
+
</div>
|
|
1257
|
+
</div>
|
|
1258
|
+
</div>
|
|
1259
|
+
|
|
1260
|
+
<!-- ═══════════════════════════ PALACE OVERLAY ═══════════════════ -->
|
|
1261
|
+
<div id="palace-overlay">
|
|
1262
|
+
<div id="po-header">
|
|
1263
|
+
<button id="po-back" onclick="closePalaceOverlay()">← BACK</button>
|
|
1264
|
+
<span id="po-title">MEMORY PALACE</span>
|
|
1265
|
+
<div id="po-tabs">
|
|
1266
|
+
<button class="po-tab active" onclick="switchPalaceTab('drawers')">MEMORIES</button>
|
|
1267
|
+
<button class="po-tab" onclick="switchPalaceTab('sessions')">SESSIONS</button>
|
|
1268
|
+
<button class="po-tab" onclick="switchPalaceTab('chunks')">KNOWLEDGE</button>
|
|
1269
|
+
<button class="po-tab" onclick="switchPalaceTab('swarm')">SWARM</button>
|
|
1270
|
+
<button class="po-tab" onclick="switchPalaceTab('graph')">AGENT GRAPH</button>
|
|
1271
|
+
<button class="po-tab" onclick="switchPalaceTab('knowledge')">CODE GRAPH</button>
|
|
1272
|
+
</div>
|
|
1273
|
+
<div id="po-stats"></div>
|
|
1274
|
+
</div>
|
|
1275
|
+
<div id="po-body">
|
|
1276
|
+
<div id="po-drawers-tab" class="po-tab-pane active">
|
|
1277
|
+
<div id="po-drawers-sidebar">
|
|
1278
|
+
<div id="po-search-row">
|
|
1279
|
+
<input id="po-search" type="text" placeholder="Filter memories…" oninput="filterDrawers(this.value)">
|
|
1280
|
+
<button id="po-new-btn" onclick="openNewMemory()" title="New memory entry">+</button>
|
|
1281
|
+
</div>
|
|
1282
|
+
<div id="po-drawer-list"></div>
|
|
1283
|
+
</div>
|
|
1284
|
+
<div id="po-drawer-detail">
|
|
1285
|
+
<div class="po-select-hint">SELECT A MEMORY</div>
|
|
1286
|
+
</div>
|
|
1287
|
+
</div>
|
|
1288
|
+
<div id="po-sessions-tab" class="po-tab-pane">
|
|
1289
|
+
<div id="po-sessions-list"></div>
|
|
1290
|
+
<div id="po-sessions-detail">
|
|
1291
|
+
<div id="po-sd-hint" class="po-select-hint">SELECT A SESSION</div>
|
|
1292
|
+
<div id="po-sd-header" style="display:none;">
|
|
1293
|
+
<div style="font-size:11px;font-weight:700;color:var(--text);font-family:'Azeret Mono',monospace;" id="po-sd-title"></div>
|
|
1294
|
+
<div style="font-size:9px;color:var(--muted);" id="po-sd-subtitle"></div>
|
|
1295
|
+
</div>
|
|
1296
|
+
<div id="po-sd-stats-bar" style="display:none;">
|
|
1297
|
+
<span id="po-sd-stat-turns"></span>
|
|
1298
|
+
<span id="po-sd-stat-tools"></span>
|
|
1299
|
+
<span id="po-sd-stat-agents"></span>
|
|
1300
|
+
<span id="po-sd-stat-mem"></span>
|
|
1301
|
+
</div>
|
|
1302
|
+
<div id="po-sd-body" style="display:none;">
|
|
1303
|
+
<div id="po-sd-timeline"><div class="placeholder">LOADING…</div></div>
|
|
1304
|
+
<div id="po-sd-sidebar">
|
|
1305
|
+
<div class="po-sd-sidebar-section">
|
|
1306
|
+
<div class="po-sd-sidebar-label">TOOL BREAKDOWN</div>
|
|
1307
|
+
<div id="po-sd-tool-breakdown"></div>
|
|
1308
|
+
</div>
|
|
1309
|
+
<div class="po-sd-sidebar-section">
|
|
1310
|
+
<div class="po-sd-sidebar-label">AGENTS SPAWNED</div>
|
|
1311
|
+
<div id="po-sd-agent-tree"></div>
|
|
1312
|
+
</div>
|
|
1313
|
+
<div class="po-sd-sidebar-section">
|
|
1314
|
+
<div class="po-sd-sidebar-label">MEMORY OPS</div>
|
|
1315
|
+
<div id="po-sd-memory-ops"></div>
|
|
1316
|
+
</div>
|
|
1317
|
+
</div>
|
|
1318
|
+
</div>
|
|
1319
|
+
</div>
|
|
1320
|
+
</div>
|
|
1321
|
+
<div id="po-graph-tab" class="po-tab-pane">
|
|
1322
|
+
<div id="po-graph-controls">
|
|
1323
|
+
<span id="po-graph-info"></span>
|
|
1324
|
+
<label><input type="checkbox" id="po-graph-labels" checked onchange="kgGraph.toggleLabels(this.checked)"> LABELS</label>
|
|
1325
|
+
</div>
|
|
1326
|
+
<canvas id="po-kg-canvas"></canvas>
|
|
1327
|
+
</div>
|
|
1328
|
+
<div id="po-swarm-tab" class="po-tab-pane" style="flex-direction:row;overflow:hidden;">
|
|
1329
|
+
<div id="po-swarm-sidebar" style="width:200px;flex-shrink:0;border-right:1px solid var(--border);padding:20px 16px;display:flex;flex-direction:column;gap:12px;">
|
|
1330
|
+
<div class="section-label">TOPOLOGY</div>
|
|
1331
|
+
<div id="po-swarm-meta" style="display:flex;flex-direction:column;gap:8px;">
|
|
1332
|
+
<div style="color:var(--muted);font-size:10px;">Loading…</div>
|
|
1333
|
+
</div>
|
|
1334
|
+
</div>
|
|
1335
|
+
<div style="flex:1;position:relative;display:flex;flex-direction:column;">
|
|
1336
|
+
<div id="po-swarm-label" style="position:absolute;top:12px;left:20px;font-size:10px;color:var(--muted);letter-spacing:0.1em;z-index:2;"></div>
|
|
1337
|
+
<canvas id="po-swarm-canvas" style="flex:1;width:100%;height:100%;display:block;"></canvas>
|
|
1338
|
+
</div>
|
|
1339
|
+
</div>
|
|
1340
|
+
<div id="po-chunks-tab" class="po-tab-pane" style="flex-direction:column;overflow:hidden;">
|
|
1341
|
+
<div id="po-chunks-header" style="display:flex;align-items:center;gap:16px;padding:12px 20px;border-bottom:1px solid var(--border);flex-shrink:0;">
|
|
1342
|
+
<div style="display:flex;gap:20px;">
|
|
1343
|
+
<div class="know-stat"><div class="know-stat-label">CHUNKS</div><div class="know-stat-val" id="po-chunks-count">—</div></div>
|
|
1344
|
+
<div class="know-stat"><div class="know-stat-label">SKILLS</div><div class="know-stat-val" id="po-skills-count">—</div></div>
|
|
1345
|
+
</div>
|
|
1346
|
+
<input id="po-chunks-search" type="text" placeholder="Filter chunks…" oninput="filterChunks(this.value)"
|
|
1347
|
+
style="flex:1;max-width:320px;background:rgba(0,0,0,0.3);border:1px solid var(--border);color:var(--text);font-family:'Azeret Mono',monospace;font-size:10px;padding:4px 8px;border-radius:3px;outline:none;">
|
|
1348
|
+
</div>
|
|
1349
|
+
<div id="po-chunks-body" style="flex:1;overflow-y:auto;padding:16px 20px;display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:8px;align-content:start;">
|
|
1350
|
+
<div style="color:var(--muted);font-size:10px;">Loading…</div>
|
|
1351
|
+
</div>
|
|
1352
|
+
</div>
|
|
1353
|
+
<div id="po-knowledge-tab" class="po-tab-pane">
|
|
1354
|
+
<div id="po-knowledge-sidebar">
|
|
1355
|
+
<div id="po-knowledge-stats"><div style="color:var(--muted);font-size:10px;">Loading…</div></div>
|
|
1356
|
+
</div>
|
|
1357
|
+
<div id="po-knowledge-canvas-wrap">
|
|
1358
|
+
<div id="po-knowledge-canvas-controls">
|
|
1359
|
+
<span id="po-kg2-info">—</span>
|
|
1360
|
+
<label><input type="checkbox" id="po-kg2-labels" checked onchange="kgCodeGraph.toggleLabels(this.checked)"> LABELS</label>
|
|
1361
|
+
</div>
|
|
1362
|
+
<canvas id="po-kg2-canvas"></canvas>
|
|
1363
|
+
</div>
|
|
1364
|
+
<div id="po-knowledge-main">
|
|
1365
|
+
<div id="po-knowledge-body"><div style="color:var(--muted);font-size:10px;padding:16px;">Loading…</div></div>
|
|
1366
|
+
</div>
|
|
1367
|
+
</div>
|
|
1368
|
+
</div>
|
|
1369
|
+
<!-- Edit memory modal -->
|
|
1370
|
+
<div id="po-edit-modal">
|
|
1371
|
+
<div id="po-edit-box">
|
|
1372
|
+
<div id="po-edit-hdr">
|
|
1373
|
+
<span id="po-edit-title">EDIT MEMORY</span>
|
|
1374
|
+
<button id="po-edit-close" onclick="closeEditModal()">✕</button>
|
|
1375
|
+
</div>
|
|
1376
|
+
<textarea id="po-edit-textarea" spellcheck="false"></textarea>
|
|
1377
|
+
<div id="po-edit-footer">
|
|
1378
|
+
<button class="po-btn po-btn-save" onclick="saveEditedMemory()">SAVE</button>
|
|
1379
|
+
<button class="po-btn po-btn-cancel" onclick="closeEditModal()">CANCEL</button>
|
|
1380
|
+
<span id="po-edit-status"></span>
|
|
1381
|
+
</div>
|
|
1382
|
+
</div>
|
|
1383
|
+
</div>
|
|
1384
|
+
<!-- Template picker modal -->
|
|
1385
|
+
<div id="po-tpl-picker">
|
|
1386
|
+
<div id="po-tpl-box">
|
|
1387
|
+
<div style="display:flex;align-items:center;margin-bottom:4px;">
|
|
1388
|
+
<span style="font-size:11px;font-weight:700;letter-spacing:0.1em;color:var(--text);flex:1;">NEW MEMORY</span>
|
|
1389
|
+
<button onclick="closeTplPicker()" style="background:none;border:none;color:var(--muted);font-size:14px;cursor:pointer;">✕</button>
|
|
1390
|
+
</div>
|
|
1391
|
+
<div style="font-size:10px;color:var(--muted);margin-bottom:8px;">Choose a template type</div>
|
|
1392
|
+
<div id="po-tpl-list"></div>
|
|
1393
|
+
</div>
|
|
1394
|
+
</div>
|
|
1395
|
+
<!-- Chunk edit modal -->
|
|
1396
|
+
<div id="po-chunk-edit-modal">
|
|
1397
|
+
<div id="po-edit-box">
|
|
1398
|
+
<div id="po-edit-hdr">
|
|
1399
|
+
<span id="po-chunk-edit-title">EDIT CHUNK</span>
|
|
1400
|
+
<button id="po-edit-close" onclick="closeChunkEditModal()">✕</button>
|
|
1401
|
+
</div>
|
|
1402
|
+
<textarea id="po-chunk-edit-textarea" spellcheck="false"></textarea>
|
|
1403
|
+
<div id="po-edit-footer">
|
|
1404
|
+
<button class="po-btn po-btn-save" onclick="saveEditedChunk()">SAVE</button>
|
|
1405
|
+
<button class="po-btn po-btn-cancel" onclick="closeChunkEditModal()">CANCEL</button>
|
|
1406
|
+
<span id="po-chunk-edit-status"></span>
|
|
1407
|
+
</div>
|
|
1408
|
+
</div>
|
|
1409
|
+
</div>
|
|
1410
|
+
</div>
|
|
1411
|
+
|
|
1412
|
+
<!-- ═══════════════════════════ HEADER ═══════════════════════════ -->
|
|
1413
|
+
<div id="header">
|
|
1414
|
+
<div id="header-left">
|
|
1415
|
+
<h1>MONOMIND CONTROL</h1>
|
|
1416
|
+
<div id="header-meta">
|
|
1417
|
+
<span><span id="conn-dot"></span><span id="conn-label">CONNECTING</span></span>
|
|
1418
|
+
</div>
|
|
1419
|
+
</div>
|
|
1420
|
+
<div id="header-right">
|
|
1421
|
+
<span>PROJECT <span id="project-val">—</span></span>
|
|
1422
|
+
<span>SESSION <span id="session-val">—</span></span>
|
|
1423
|
+
<span>UPTIME <span id="uptime-val">—</span></span>
|
|
1424
|
+
<span id="last-update-label" style="color:var(--muted);font-size:10px;">—</span>
|
|
1425
|
+
</div>
|
|
1426
|
+
</div>
|
|
1427
|
+
|
|
1428
|
+
<!-- ═══════════════════════════ GRID ═════════════════════════════ -->
|
|
1429
|
+
<div id="grid">
|
|
1430
|
+
|
|
1431
|
+
<!-- ─── ALL PROJECTS ────────────────────────────────────────── -->
|
|
1432
|
+
<div class="panel" id="panel-projects">
|
|
1433
|
+
<div class="panel-header">
|
|
1434
|
+
<div class="panel-title"><span class="live-dot"></span>ALL PROJECTS</div>
|
|
1435
|
+
<span class="panel-badge" id="projects-badge">0</span>
|
|
1436
|
+
</div>
|
|
1437
|
+
<div class="panel-body" style="padding:0;">
|
|
1438
|
+
<div id="projects-table">
|
|
1439
|
+
<div class="proj-header">Project</div>
|
|
1440
|
+
<div class="proj-header">Path</div>
|
|
1441
|
+
<div class="proj-header" style="text-align:right">Sessions</div>
|
|
1442
|
+
<div class="proj-header" style="text-align:right">Drawers</div>
|
|
1443
|
+
<div class="proj-header" style="text-align:right">Size</div>
|
|
1444
|
+
<div class="proj-header">Last Active</div>
|
|
1445
|
+
<div class="proj-cell" style="grid-column:1/7;color:var(--muted)">Loading projects…</div>
|
|
1446
|
+
</div>
|
|
1447
|
+
<div id="project-stats-strip"></div>
|
|
1448
|
+
</div>
|
|
1449
|
+
</div>
|
|
1450
|
+
|
|
1451
|
+
<!-- ─── AGENTS ──────────────────────────────────────────────── -->
|
|
1452
|
+
<div class="panel open" id="panel-agents">
|
|
1453
|
+
<div class="panel-header" onclick="togglePanel('panel-agents')">
|
|
1454
|
+
<div class="panel-title"><span class="live-dot green"></span>AGENTS</div>
|
|
1455
|
+
<span class="panel-badge" id="agents-badge">0</span>
|
|
1456
|
+
<span class="panel-chevron">›</span>
|
|
1457
|
+
</div>
|
|
1458
|
+
<div class="panel-body" id="agents-body">
|
|
1459
|
+
<div class="placeholder">NO AGENTS</div>
|
|
1460
|
+
</div>
|
|
1461
|
+
</div>
|
|
1462
|
+
|
|
1463
|
+
<!-- ─── TOKENS ──────────────────────────────────────────────── -->
|
|
1464
|
+
<div class="panel open" id="panel-tokens">
|
|
1465
|
+
<div class="panel-header" onclick="togglePanel('panel-tokens')">
|
|
1466
|
+
<div class="panel-title"><span class="live-dot amber"></span>TOKENS</div>
|
|
1467
|
+
<span class="panel-badge" id="tokens-badge">0</span>
|
|
1468
|
+
<span class="panel-chevron">›</span>
|
|
1469
|
+
</div>
|
|
1470
|
+
<div class="panel-body" id="tokens-body">
|
|
1471
|
+
<div class="token-summary" id="token-summary"></div>
|
|
1472
|
+
<canvas id="tokens-canvas"></canvas>
|
|
1473
|
+
</div>
|
|
1474
|
+
</div>
|
|
1475
|
+
|
|
1476
|
+
<!-- ─── MEMORY PALACE ───────────────────────────────────────── -->
|
|
1477
|
+
<div class="panel open" id="panel-memory">
|
|
1478
|
+
<div class="panel-header" onclick="togglePanel('panel-memory')">
|
|
1479
|
+
<div class="panel-title"><span class="live-dot"></span>MEMORY PALACE</div>
|
|
1480
|
+
<div style="display:flex;gap:6px;align-items:center;">
|
|
1481
|
+
<span id="hnsw-indicator"></span>
|
|
1482
|
+
<button onclick="event.stopPropagation();openPalaceOverlay()" style="background:none;border:1px solid rgba(0,229,200,0.3);color:var(--teal);font-family:'Azeret Mono',monospace;font-size:9px;letter-spacing:0.08em;padding:2px 7px;cursor:pointer;border-radius:3px;transition:background 0.15s;" onmouseover="this.style.background='rgba(0,229,200,0.08)'" onmouseout="this.style.background='none'">EXPLORE</button>
|
|
1483
|
+
<span class="panel-badge" id="memory-badge">0</span>
|
|
1484
|
+
<span class="panel-chevron">›</span>
|
|
1485
|
+
</div>
|
|
1486
|
+
</div>
|
|
1487
|
+
<div class="panel-body" id="memory-body">
|
|
1488
|
+
<div class="memory-layout">
|
|
1489
|
+
<div class="memory-left" id="memory-left"></div>
|
|
1490
|
+
<div class="memory-right" id="memory-right"></div>
|
|
1491
|
+
</div>
|
|
1492
|
+
</div>
|
|
1493
|
+
</div>
|
|
1494
|
+
|
|
1495
|
+
<!-- ─── HOOKS & ROUTING ─────────────────────────────────────── -->
|
|
1496
|
+
<div class="panel open" id="panel-hooks">
|
|
1497
|
+
<div class="panel-header" onclick="togglePanel('panel-hooks')">
|
|
1498
|
+
<div class="panel-title"><span class="live-dot amber"></span>HOOKS & ROUTING</div>
|
|
1499
|
+
<div style="display:flex;align-items:center;gap:6px;">
|
|
1500
|
+
<span class="panel-badge" id="hooks-badge">—</span>
|
|
1501
|
+
<span class="panel-chevron">›</span>
|
|
1502
|
+
</div>
|
|
1503
|
+
</div>
|
|
1504
|
+
<div class="panel-body" id="hooks-body">
|
|
1505
|
+
<div class="hooks-layout">
|
|
1506
|
+
<div class="hooks-col" id="hooks-left"></div>
|
|
1507
|
+
<div class="hooks-col" id="hooks-right"></div>
|
|
1508
|
+
</div>
|
|
1509
|
+
</div>
|
|
1510
|
+
</div>
|
|
1511
|
+
|
|
1512
|
+
<!-- ─── METRICS ─────────────────────────────────────────────── -->
|
|
1513
|
+
<div class="panel open" id="panel-metrics">
|
|
1514
|
+
<div class="panel-header" onclick="togglePanel('panel-metrics')">
|
|
1515
|
+
<div class="panel-title"><span class="live-dot muted"></span>METRICS</div>
|
|
1516
|
+
<span class="panel-chevron">›</span>
|
|
1517
|
+
</div>
|
|
1518
|
+
<div class="panel-body" id="metrics-body">
|
|
1519
|
+
<div class="placeholder">—</div>
|
|
1520
|
+
</div>
|
|
1521
|
+
</div>
|
|
1522
|
+
|
|
1523
|
+
<!-- ─── ACTIVITY ────────────────────────────────────────────── -->
|
|
1524
|
+
<div class="panel open" id="panel-activity">
|
|
1525
|
+
<div class="panel-header" onclick="togglePanel('panel-activity')">
|
|
1526
|
+
<div class="panel-title"><span class="live-dot"></span>ACTIVITY</div>
|
|
1527
|
+
<div style="display:flex;align-items:center;gap:6px;">
|
|
1528
|
+
<span class="panel-badge" id="activity-badge">0</span>
|
|
1529
|
+
<span class="panel-chevron">›</span>
|
|
1530
|
+
</div>
|
|
1531
|
+
</div>
|
|
1532
|
+
<div class="panel-body" id="activity-body">
|
|
1533
|
+
<div id="activity-log"></div>
|
|
1534
|
+
</div>
|
|
1535
|
+
</div>
|
|
1536
|
+
|
|
1537
|
+
<div class="panel" id="panel-system">
|
|
1538
|
+
<div class="panel-header" onclick="togglePanel('panel-system')">
|
|
1539
|
+
<div class="panel-title"><span class="live-dot muted"></span>SYSTEM</div>
|
|
1540
|
+
<span class="panel-chevron">›</span>
|
|
1541
|
+
</div>
|
|
1542
|
+
<div class="panel-body" id="system-body">
|
|
1543
|
+
<div class="placeholder">—</div>
|
|
1544
|
+
</div>
|
|
1545
|
+
</div>
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
</div><!-- end #grid -->
|
|
1549
|
+
|
|
1550
|
+
<script>
|
|
1551
|
+
'use strict';
|
|
1552
|
+
|
|
1553
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1554
|
+
// STATE
|
|
1555
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1556
|
+
let appData = null;
|
|
1557
|
+
let lastUpdateTime = 0;
|
|
1558
|
+
let activityCount = 0;
|
|
1559
|
+
const MAX_ACTIVITY = 80;
|
|
1560
|
+
|
|
1561
|
+
// Track which panels are currently open (match initial HTML .open classes)
|
|
1562
|
+
const expandedPanels = new Set([
|
|
1563
|
+
'panel-projects',
|
|
1564
|
+
'panel-agents', 'panel-tokens', 'panel-activity', 'panel-hooks', 'panel-metrics', 'panel-memory'
|
|
1565
|
+
]);
|
|
1566
|
+
|
|
1567
|
+
// Section name → panel id mapping
|
|
1568
|
+
const SECTION_PANEL = {
|
|
1569
|
+
agents: 'panel-agents',
|
|
1570
|
+
tokens: 'panel-tokens', memory: 'panel-memory', hooks: 'panel-hooks',
|
|
1571
|
+
knowledge: 'panel-memory', metrics: 'panel-metrics', system: 'panel-system',
|
|
1572
|
+
};
|
|
1573
|
+
|
|
1574
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1575
|
+
// COLLAPSIBLE PANELS
|
|
1576
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1577
|
+
window.togglePanel = function(panelId) {
|
|
1578
|
+
const panel = document.getElementById(panelId);
|
|
1579
|
+
if (!panel) return;
|
|
1580
|
+
|
|
1581
|
+
if (expandedPanels.has(panelId)) {
|
|
1582
|
+
// Collapse
|
|
1583
|
+
expandedPanels.delete(panelId);
|
|
1584
|
+
panel.classList.remove('open');
|
|
1585
|
+
} else {
|
|
1586
|
+
// Expand
|
|
1587
|
+
expandedPanels.add(panelId);
|
|
1588
|
+
panel.classList.add('open');
|
|
1589
|
+
// Render from cached data immediately
|
|
1590
|
+
if (appData) {
|
|
1591
|
+
renderPanelById(panelId);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
};
|
|
1595
|
+
|
|
1596
|
+
function renderPanelById(panelId) {
|
|
1597
|
+
if (!appData) return;
|
|
1598
|
+
switch (panelId) {
|
|
1599
|
+
case 'panel-agents': renderAgents(appData); break;
|
|
1600
|
+
case 'panel-tokens': renderTokens(appData); break;
|
|
1601
|
+
case 'panel-memory': renderMemory(appData); break;
|
|
1602
|
+
case 'panel-hooks': renderHooks(appData); break;
|
|
1603
|
+
case 'panel-knowledge': renderMemory(appData); break;
|
|
1604
|
+
case 'panel-metrics': renderMetrics(appData); break;
|
|
1605
|
+
case 'panel-system': renderSystem(appData); break;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
// Fetch one or more sections from /api/section and re-render them if open
|
|
1610
|
+
async function fetchAndRenderSections(sections) {
|
|
1611
|
+
const dir = selectedProjectDir || '';
|
|
1612
|
+
let metricsStale = false;
|
|
1613
|
+
for (const name of sections) {
|
|
1614
|
+
const panelId = SECTION_PANEL[name];
|
|
1615
|
+
// If a data source used by metrics changed, mark metrics for re-render
|
|
1616
|
+
if (['hooks', 'swarm', 'tokens'].includes(name)) metricsStale = true;
|
|
1617
|
+
if (!panelId || !expandedPanels.has(panelId)) continue;
|
|
1618
|
+
try {
|
|
1619
|
+
const url = `/api/section?name=${name}${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
|
|
1620
|
+
const res = await fetch(url);
|
|
1621
|
+
if (!res.ok) continue;
|
|
1622
|
+
const partial = await res.json();
|
|
1623
|
+
if (appData) Object.assign(appData, partial);
|
|
1624
|
+
else appData = partial;
|
|
1625
|
+
renderPanelById(panelId);
|
|
1626
|
+
} catch (e) { /* ignore transient fetch errors */ }
|
|
1627
|
+
}
|
|
1628
|
+
// Re-render metrics panel when its source data changed
|
|
1629
|
+
if (metricsStale && expandedPanels.has('panel-metrics') && appData) {
|
|
1630
|
+
renderMetrics(appData);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1635
|
+
// UTILITIES
|
|
1636
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1637
|
+
function fmt(v, fallback) {
|
|
1638
|
+
if (v === null || v === undefined || v === '') return fallback || '—';
|
|
1639
|
+
return String(v);
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
function fmtBytes(b) {
|
|
1643
|
+
if (!b) return '—';
|
|
1644
|
+
if (b < 1024) return b + ' B';
|
|
1645
|
+
if (b < 1024 * 1024) return (b / 1024).toFixed(1) + ' KB';
|
|
1646
|
+
return (b / 1024 / 1024).toFixed(1) + ' MB';
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
function fmtUptime(seconds) {
|
|
1650
|
+
if (!seconds && seconds !== 0) return '—';
|
|
1651
|
+
const h = Math.floor(seconds / 3600);
|
|
1652
|
+
const m = Math.floor((seconds % 3600) / 60);
|
|
1653
|
+
const s = Math.floor(seconds % 60);
|
|
1654
|
+
if (h > 0) return h + 'h ' + m + 'm';
|
|
1655
|
+
if (m > 0) return m + 'm ' + s + 's';
|
|
1656
|
+
return s + 's';
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
function fmtAge(mtimeMs) {
|
|
1660
|
+
if (!mtimeMs) return '—';
|
|
1661
|
+
const diff = Date.now() - mtimeMs;
|
|
1662
|
+
const s = Math.floor(diff / 1000);
|
|
1663
|
+
if (s < 60) return s + 's ago';
|
|
1664
|
+
const m = Math.floor(s / 60);
|
|
1665
|
+
if (m < 60) return m + 'm ago';
|
|
1666
|
+
const h = Math.floor(m / 60);
|
|
1667
|
+
if (h < 24) return h + 'h ago';
|
|
1668
|
+
return Math.floor(h / 24) + 'd ago';
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
function fmtCost(dollars) {
|
|
1672
|
+
if (dollars === null || dollars === undefined) return '—';
|
|
1673
|
+
if (dollars === 0) return '$0.00';
|
|
1674
|
+
if (dollars < 0.001) return '<$0.001';
|
|
1675
|
+
return '$' + dollars.toFixed(3);
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
function fmtNum(n) {
|
|
1679
|
+
if (n === null || n === undefined) return '—';
|
|
1680
|
+
if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
|
|
1681
|
+
if (n >= 1000) return (n / 1000).toFixed(1) + 'K';
|
|
1682
|
+
return String(n);
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
function now() {
|
|
1686
|
+
const d = new Date();
|
|
1687
|
+
return d.getHours().toString().padStart(2,'0') + ':' +
|
|
1688
|
+
d.getMinutes().toString().padStart(2,'0') + ':' +
|
|
1689
|
+
d.getSeconds().toString().padStart(2,'0');
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
function flashEl(el) {
|
|
1693
|
+
if (!el) return;
|
|
1694
|
+
el.classList.remove('flash');
|
|
1695
|
+
void el.offsetWidth;
|
|
1696
|
+
el.classList.add('flash');
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
function setText(id, value, doFlash) {
|
|
1700
|
+
const el = document.getElementById(id);
|
|
1701
|
+
if (!el) return;
|
|
1702
|
+
const str = fmt(value);
|
|
1703
|
+
if (el.textContent !== str) {
|
|
1704
|
+
el.textContent = str;
|
|
1705
|
+
if (doFlash) flashEl(el);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1710
|
+
// PANEL LIVE STATE
|
|
1711
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1712
|
+
function markLive(panelId) {
|
|
1713
|
+
const el = document.getElementById(panelId);
|
|
1714
|
+
if (el) el.classList.add('live');
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
function updateLiveBorders() {
|
|
1718
|
+
const panelIds = [
|
|
1719
|
+
'panel-agents','panel-tokens',
|
|
1720
|
+
'panel-memory','panel-hooks','panel-metrics',
|
|
1721
|
+
'panel-activity','panel-system'
|
|
1722
|
+
];
|
|
1723
|
+
const isLive = lastUpdateTime > 0 && (Date.now() - lastUpdateTime) < 5000;
|
|
1724
|
+
panelIds.forEach(id => {
|
|
1725
|
+
const el = document.getElementById(id);
|
|
1726
|
+
if (el) el.classList.toggle('live', isLive);
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1731
|
+
// HEADER
|
|
1732
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1733
|
+
function updateHeader(data) {
|
|
1734
|
+
const proj = data.project;
|
|
1735
|
+
setText('project-val', proj && proj.name ? proj.name : '—');
|
|
1736
|
+
|
|
1737
|
+
const sys = data.system || {};
|
|
1738
|
+
setText('uptime-val', fmtUptime(sys.uptime));
|
|
1739
|
+
|
|
1740
|
+
// session val = count from sessions
|
|
1741
|
+
const sCount = data.sessions && data.sessions.count != null ? data.sessions.count : 0;
|
|
1742
|
+
setText('session-val', sCount + ' sessions');
|
|
1743
|
+
|
|
1744
|
+
// last update
|
|
1745
|
+
const el = document.getElementById('last-update-label');
|
|
1746
|
+
if (el) el.textContent = 'UPDATED ' + now();
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1750
|
+
// ALL PROJECTS PANEL
|
|
1751
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1752
|
+
function formatBytes(b) {
|
|
1753
|
+
if (!b) return '—';
|
|
1754
|
+
if (b < 1024) return b + ' B';
|
|
1755
|
+
if (b < 1024 * 1024) return (b / 1024).toFixed(0) + ' KB';
|
|
1756
|
+
return (b / (1024 * 1024)).toFixed(1) + ' MB';
|
|
1757
|
+
}
|
|
1758
|
+
function timeAgo(ms) {
|
|
1759
|
+
if (!ms) return '—';
|
|
1760
|
+
const diff = Date.now() - ms;
|
|
1761
|
+
const m = Math.floor(diff / 60000);
|
|
1762
|
+
if (m < 1) return 'just now';
|
|
1763
|
+
if (m < 60) return m + 'm ago';
|
|
1764
|
+
const h = Math.floor(m / 60);
|
|
1765
|
+
if (h < 24) return h + 'h ago';
|
|
1766
|
+
const d = Math.floor(h / 24);
|
|
1767
|
+
return d + 'd ago';
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
// Track which project dir is currently selected (null = default/server project)
|
|
1771
|
+
let selectedProjectDir = null;
|
|
1772
|
+
|
|
1773
|
+
async function selectProject(dir) {
|
|
1774
|
+
if (selectedProjectDir === dir) return;
|
|
1775
|
+
selectedProjectDir = dir;
|
|
1776
|
+
_codeGraphLoaded = false; kgCodeGraph.reset();
|
|
1777
|
+
try {
|
|
1778
|
+
const res = await fetch(`/api/data?dir=${encodeURIComponent(dir)}`);
|
|
1779
|
+
const data = await res.json();
|
|
1780
|
+
updateAllPanels(data);
|
|
1781
|
+
} catch (e) {
|
|
1782
|
+
appendActivity(`Failed to load project: ${e.message}`, 'error');
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
function renderProjects(data) {
|
|
1787
|
+
const projects = data.allProjects || [];
|
|
1788
|
+
const badge = document.getElementById('projects-badge');
|
|
1789
|
+
if (badge) badge.textContent = projects.length;
|
|
1790
|
+
|
|
1791
|
+
const table = document.getElementById('projects-table');
|
|
1792
|
+
if (!table) return;
|
|
1793
|
+
|
|
1794
|
+
if (!projects.length) {
|
|
1795
|
+
table.innerHTML = '<div class="proj-cell" style="grid-column:1/7;color:var(--muted)">No projects found in ~/.claude/projects/</div>';
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
const activeDir = selectedProjectDir || (data.project && data.project.dir);
|
|
1800
|
+
const isCurrent = (p) => p.path === activeDir;
|
|
1801
|
+
|
|
1802
|
+
let html = `
|
|
1803
|
+
<div class="proj-header">Project</div>
|
|
1804
|
+
<div class="proj-header">Path</div>
|
|
1805
|
+
<div class="proj-header" style="text-align:right">Sessions</div>
|
|
1806
|
+
<div class="proj-header" style="text-align:right">Drawers</div>
|
|
1807
|
+
<div class="proj-header" style="text-align:right">Size</div>
|
|
1808
|
+
<div class="proj-header">Last Active</div>
|
|
1809
|
+
`;
|
|
1810
|
+
|
|
1811
|
+
for (const p of projects) {
|
|
1812
|
+
const current = isCurrent(p);
|
|
1813
|
+
const highlight = current ? 'background:rgba(0,229,200,0.08);' : '';
|
|
1814
|
+
const cursor = p.exists ? 'cursor:pointer;' : 'cursor:pointer;opacity:0.6;';
|
|
1815
|
+
const rowClick = `onclick="selectProject('${p.path.replace(/'/g, "\\'")}')"`;
|
|
1816
|
+
|
|
1817
|
+
html += `
|
|
1818
|
+
<div class="proj-cell proj-name" style="${highlight}${cursor}" ${rowClick} title="${p.path}">
|
|
1819
|
+
<span class="proj-exists-dot ${p.exists ? 'on' : 'off'}"></span>
|
|
1820
|
+
${current ? '<span style="color:var(--teal);margin-right:3px;">▶</span>' : ''}
|
|
1821
|
+
${p.name}
|
|
1822
|
+
</div>
|
|
1823
|
+
<div class="proj-cell proj-path" style="${highlight}${cursor}" ${rowClick}>${p.path.replace(/\/Users\/[^/]+/, '~')}</div>
|
|
1824
|
+
<div class="proj-cell proj-count" style="${highlight}${cursor};justify-content:flex-end" ${rowClick}>${p.sessionCount}</div>
|
|
1825
|
+
<div class="proj-cell proj-dots" style="${highlight}${cursor};justify-content:flex-end" ${rowClick}>${p.drawerCount || '—'}</div>
|
|
1826
|
+
<div class="proj-cell proj-size" style="${highlight}${cursor};justify-content:flex-end" ${rowClick}>${formatBytes(p.totalSize)}</div>
|
|
1827
|
+
<div class="proj-cell proj-age" style="${highlight}${cursor}" ${rowClick}>${timeAgo(p.lastActivity)}</div>
|
|
1828
|
+
`;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
table.innerHTML = html;
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// SESSIONS PANEL
|
|
1835
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1836
|
+
const expandedSessions = new Set();
|
|
1837
|
+
|
|
1838
|
+
function renderSessions(data) {
|
|
1839
|
+
const s = data.sessions || {};
|
|
1840
|
+
const list = s.list || [];
|
|
1841
|
+
const palace = s.palace || {};
|
|
1842
|
+
|
|
1843
|
+
const badge = document.getElementById('sessions-badge');
|
|
1844
|
+
if (badge) badge.textContent = list.length;
|
|
1845
|
+
|
|
1846
|
+
const body = document.getElementById('sessions-body');
|
|
1847
|
+
if (!body) return;
|
|
1848
|
+
|
|
1849
|
+
if (!list.length && !palace.count) {
|
|
1850
|
+
body.innerHTML = '<div class="placeholder">NO SESSION DATA</div>';
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
let html = '';
|
|
1855
|
+
list.slice(0, 12).forEach(sess => {
|
|
1856
|
+
const safeFile = (sess.file || '').replace(/'/g, "\\'");
|
|
1857
|
+
html += `<div class="session-item" onclick="openSessionDetail('${safeFile}', '${sess.id}')">
|
|
1858
|
+
<span class="live-dot" style="flex-shrink:0;"></span>
|
|
1859
|
+
<span class="session-id" title="${sess.id}">${sess.id.slice(0, 20)}</span>
|
|
1860
|
+
<span class="session-meta">${fmtAge(sess.mtime)}</span>
|
|
1861
|
+
<span class="session-meta">${fmtBytes(sess.size)}</span>
|
|
1862
|
+
<span style="font-size:9px;color:var(--teal);margin-left:2px;">›</span>
|
|
1863
|
+
</div>`;
|
|
1864
|
+
});
|
|
1865
|
+
|
|
1866
|
+
// Palace info
|
|
1867
|
+
html += `<div class="palace-row" style="cursor:pointer;" onclick="openPalaceOverlay()">
|
|
1868
|
+
<span class="palace-label">MEMORY PALACE</span>
|
|
1869
|
+
<span style="display:flex;align-items:center;gap:6px;">
|
|
1870
|
+
<span style="font-size:11px;color:var(--text);font-weight:500;" id="palace-count-anim">${palace.count || 0}</span>
|
|
1871
|
+
<span style="font-size:9px;color:var(--muted);">MEMORIES</span>
|
|
1872
|
+
<span style="font-size:9px;color:var(--teal);letter-spacing:0.06em;">EXPLORE →</span>
|
|
1873
|
+
</span>
|
|
1874
|
+
</div>`;
|
|
1875
|
+
|
|
1876
|
+
body.innerHTML = html;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
window.toggleSession = function(id) {
|
|
1880
|
+
if (expandedSessions.has(id)) {
|
|
1881
|
+
expandedSessions.delete(id);
|
|
1882
|
+
} else {
|
|
1883
|
+
expandedSessions.add(id);
|
|
1884
|
+
}
|
|
1885
|
+
if (appData) renderSessions(appData);
|
|
1886
|
+
};
|
|
1887
|
+
|
|
1888
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1889
|
+
// SESSION DETAIL OVERLAY
|
|
1890
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
1891
|
+
const CAT_LABELS = { file:'FILE', bash:'BASH', agent:'AGENT', memory:'MEM', web:'WEB', task:'TASK', skill:'SKILL', search:'SEARCH', mcp:'MCP', other:'TOOL' };
|
|
1892
|
+
|
|
1893
|
+
window.openSessionDetail = async function(file, id) {
|
|
1894
|
+
const overlay = document.getElementById('session-overlay');
|
|
1895
|
+
overlay.classList.add('open');
|
|
1896
|
+
document.getElementById('sd-title').textContent = 'SESSION ' + id.slice(0, 8) + '…';
|
|
1897
|
+
document.getElementById('sd-subtitle').textContent = file;
|
|
1898
|
+
document.getElementById('sd-timeline').innerHTML = '<div class="placeholder">LOADING…</div>';
|
|
1899
|
+
document.getElementById('sd-tool-breakdown').innerHTML = '';
|
|
1900
|
+
document.getElementById('sd-agent-tree').innerHTML = '';
|
|
1901
|
+
document.getElementById('sd-memory-ops').innerHTML = '';
|
|
1902
|
+
|
|
1903
|
+
try {
|
|
1904
|
+
const res = await fetch(`/api/session?file=${encodeURIComponent(file)}&limit=600`);
|
|
1905
|
+
const { events, total, shown } = await res.json();
|
|
1906
|
+
document.getElementById('sd-subtitle').textContent = `${id} · ${total} entries · showing last ${shown}`;
|
|
1907
|
+
renderSessionDetail(events);
|
|
1908
|
+
} catch (e) {
|
|
1909
|
+
document.getElementById('sd-timeline').innerHTML = `<div class="placeholder" style="color:#EF5350">ERROR: ${e.message}</div>`;
|
|
1910
|
+
}
|
|
1911
|
+
};
|
|
1912
|
+
|
|
1913
|
+
window.closeSessionDetail = function() {
|
|
1914
|
+
document.getElementById('session-overlay').classList.remove('open');
|
|
1915
|
+
};
|
|
1916
|
+
|
|
1917
|
+
function renderSessionDetail(events) {
|
|
1918
|
+
// ── Stats ──────────────────────────────────────────────────────
|
|
1919
|
+
const userTurns = events.filter(e => e.kind === 'user').length;
|
|
1920
|
+
const toolEvents = events.filter(e => e.kind === 'tool');
|
|
1921
|
+
const agentEvents = events.filter(e => e.kind === 'tool' && e.cat === 'agent');
|
|
1922
|
+
const memEvents = events.filter(e => e.kind === 'tool' && e.cat === 'memory');
|
|
1923
|
+
setText('sd-stat-turns', `💬 ${userTurns} turns`);
|
|
1924
|
+
setText('sd-stat-tools', `🔧 ${toolEvents.length} tools`);
|
|
1925
|
+
setText('sd-stat-agents', `🤖 ${agentEvents.length} agents`);
|
|
1926
|
+
setText('sd-stat-mem', `🧠 ${memEvents.length} memory`);
|
|
1927
|
+
|
|
1928
|
+
// ── Tool breakdown sidebar ─────────────────────────────────────
|
|
1929
|
+
const catCounts = {};
|
|
1930
|
+
for (const e of toolEvents) catCounts[e.cat] = (catCounts[e.cat] || 0) + 1;
|
|
1931
|
+
const breakdown = document.getElementById('sd-tool-breakdown');
|
|
1932
|
+
breakdown.innerHTML = Object.entries(catCounts).sort((a,b)=>b[1]-a[1]).map(([cat, count]) =>
|
|
1933
|
+
`<span class="tool-chip cat-${cat}"><span class="tool-chip-count">${count}</span><span>${CAT_LABELS[cat]||cat}</span></span>`
|
|
1934
|
+
).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
|
|
1935
|
+
|
|
1936
|
+
// ── Agent tree sidebar ─────────────────────────────────────────
|
|
1937
|
+
const agentTree = document.getElementById('sd-agent-tree');
|
|
1938
|
+
agentTree.innerHTML = agentEvents.map(e =>
|
|
1939
|
+
`<div class="agent-node"><div class="agent-node-dot"></div><span style="color:#B078FF;font-size:9px;font-weight:700;margin-right:4px">${e.subagent || '?'}</span><span style="color:var(--muted)">${e.label.replace(/^→\s*/,'').slice(0,40)}</span>${e.background ? '<span style="font-size:9px;color:#555;margin-left:auto">bg</span>' : ''}</div>`
|
|
1940
|
+
).join('') || '<span style="font-size:10px;color:var(--muted)">No agents spawned</span>';
|
|
1941
|
+
|
|
1942
|
+
// ── Memory ops sidebar ─────────────────────────────────────────
|
|
1943
|
+
const memOpEl = document.getElementById('sd-memory-ops');
|
|
1944
|
+
memOpEl.innerHTML = memEvents.slice(0, 20).map(e =>
|
|
1945
|
+
`<div class="memory-op"><span style="color:#FFD700;font-size:9px">${e.name.replace('mcp__monobrain__','').slice(0,20)}</span><span>${e.label.replace(/^mem:/,'').slice(0,30)}</span></div>`
|
|
1946
|
+
).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
|
|
1947
|
+
|
|
1948
|
+
// ── Timeline ───────────────────────────────────────────────────
|
|
1949
|
+
const timeline = document.getElementById('sd-timeline');
|
|
1950
|
+
const frags = [];
|
|
1951
|
+
// group tool + its result together
|
|
1952
|
+
const usedResultIdx = new Set();
|
|
1953
|
+
|
|
1954
|
+
for (let i = 0; i < events.length; i++) {
|
|
1955
|
+
const e = events[i];
|
|
1956
|
+
|
|
1957
|
+
if (e.kind === 'user') {
|
|
1958
|
+
frags.push(`<div class="ev ev-user">${esc(e.text)}</div>`);
|
|
1959
|
+
} else if (e.kind === 'thinking') {
|
|
1960
|
+
frags.push(`<div class="ev ev-thinking">${esc(e.text.slice(0,120))}${e.text.length>120?'…':''}</div>`);
|
|
1961
|
+
} else if (e.kind === 'text') {
|
|
1962
|
+
frags.push(`<div class="ev ev-text">${esc(e.text)}</div>`);
|
|
1963
|
+
} else if (e.kind === 'tool') {
|
|
1964
|
+
if (e.cat === 'agent') {
|
|
1965
|
+
frags.push(`<div class="ev-agent-spawn">
|
|
1966
|
+
<div class="ev-agent-spawn-header">
|
|
1967
|
+
<span class="ev-agent-type">${e.subagent || 'AGENT'}</span>
|
|
1968
|
+
<span class="ev-agent-label">${esc(e.label.replace(/^→\s*/,''))}</span>
|
|
1969
|
+
${e.background ? '<span class="ev-agent-bg">⬡ background</span>' : ''}
|
|
1970
|
+
${e.ts ? `<span class="ev-tool-ts">${fmtTime(e.ts)}</span>` : ''}
|
|
1971
|
+
</div>
|
|
1972
|
+
</div>`);
|
|
1973
|
+
} else {
|
|
1974
|
+
// find matching result
|
|
1975
|
+
let resultHtml = '';
|
|
1976
|
+
for (let j = i+1; j < Math.min(i+8, events.length); j++) {
|
|
1977
|
+
const r = events[j];
|
|
1978
|
+
if (r.kind === 'tool_result' && r.tool_use_id === e.id && !usedResultIdx.has(j)) {
|
|
1979
|
+
usedResultIdx.add(j);
|
|
1980
|
+
const cls = r.isError ? ' error' : '';
|
|
1981
|
+
resultHtml = `<div class="ev-tool-result${cls}">${esc(r.text.slice(0,300))}</div>`;
|
|
1982
|
+
break;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
frags.push(`<div class="ev-tool">
|
|
1986
|
+
<span class="ev-tool-badge cat-${e.cat}">${CAT_LABELS[e.cat]||e.cat}</span>
|
|
1987
|
+
<span class="ev-tool-label" title="${esc(e.label)}">${esc(e.label)}</span>
|
|
1988
|
+
${e.ts ? `<span class="ev-tool-ts">${fmtTime(e.ts)}</span>` : ''}
|
|
1989
|
+
</div>${resultHtml}`);
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
// standalone tool results already embedded above are skipped via usedResultIdx
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
timeline.innerHTML = frags.join('');
|
|
1996
|
+
timeline.scrollTop = timeline.scrollHeight;
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
function fmtTime(ts) {
|
|
2000
|
+
if (!ts) return '';
|
|
2001
|
+
try { return new Date(ts).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit',second:'2-digit'}); } catch { return ''; }
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
function esc(str) {
|
|
2005
|
+
return String(str||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2009
|
+
// AGENTS PANEL
|
|
2010
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2011
|
+
function renderAgents(data) {
|
|
2012
|
+
const a = data.agents || {};
|
|
2013
|
+
const regs = a.registrations || [];
|
|
2014
|
+
// Prefer registry agents (rich data: slug, name, category) over minimal registrations
|
|
2015
|
+
const registryAgents = (a.registry && a.registry.agents) ? a.registry.agents : [];
|
|
2016
|
+
const displayAgents = registryAgents.length ? registryAgents : regs;
|
|
2017
|
+
const totalCount = (a.registry && a.registry.totalAgents) || regs.length || 0;
|
|
2018
|
+
|
|
2019
|
+
const badge = document.getElementById('agents-badge');
|
|
2020
|
+
if (badge) badge.textContent = totalCount;
|
|
2021
|
+
|
|
2022
|
+
const body = document.getElementById('agents-body');
|
|
2023
|
+
if (!body) return;
|
|
2024
|
+
|
|
2025
|
+
if (!displayAgents.length) {
|
|
2026
|
+
body.innerHTML = '<div class="placeholder">NO REGISTERED AGENTS</div>';
|
|
2027
|
+
return;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
let html = '<div class="agent-grid">';
|
|
2031
|
+
displayAgents.slice(0, 16).forEach(agent => {
|
|
2032
|
+
if (!agent) return;
|
|
2033
|
+
const status = agent.status || 'idle';
|
|
2034
|
+
const isActive = status === 'active' || status === 'running';
|
|
2035
|
+
const isIdle = status === 'idle' || status === 'waiting';
|
|
2036
|
+
const dotClass = isActive ? '' : isIdle ? 'amber' : 'muted';
|
|
2037
|
+
const name = agent.slug || agent.name || agent.id || '?';
|
|
2038
|
+
const type = agent.category || agent.agentType || agent.type || '';
|
|
2039
|
+
const activity = agent.capabilities && agent.capabilities[0] ? agent.capabilities[0] : (agent.lastActivity || status);
|
|
2040
|
+
|
|
2041
|
+
html += `<div class="agent-card">
|
|
2042
|
+
<div class="agent-card-top">
|
|
2043
|
+
<span class="live-dot ${dotClass}"></span>
|
|
2044
|
+
<span class="agent-name" title="${name}">${name.slice(0,18)}</span>
|
|
2045
|
+
</div>
|
|
2046
|
+
<div class="agent-type">${type.slice(0,20)}</div>
|
|
2047
|
+
<div class="agent-activity" title="${activity}">${activity ? activity.slice(0,30) : status}</div>
|
|
2048
|
+
</div>`;
|
|
2049
|
+
});
|
|
2050
|
+
html += '</div>';
|
|
2051
|
+
body.innerHTML = html;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2055
|
+
// TOKENS PANEL + CANVAS BAR CHART
|
|
2056
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2057
|
+
let tokensBarData = [];
|
|
2058
|
+
let tokensBarAnimPct = 0;
|
|
2059
|
+
let tokensBarRAF = null;
|
|
2060
|
+
|
|
2061
|
+
function renderTokens(data) {
|
|
2062
|
+
const t = data.tokens || {};
|
|
2063
|
+
const summary = t.summary || {};
|
|
2064
|
+
const sessions = t.sessions || [];
|
|
2065
|
+
|
|
2066
|
+
const todayCost = summary.todayCost ?? (summary.today?.cost ?? null);
|
|
2067
|
+
const todayCalls = summary.todayCalls ?? null;
|
|
2068
|
+
const monthlyCost = summary.monthlyCost ?? summary.monthCost ?? (summary.monthly?.cost ?? null);
|
|
2069
|
+
const monthlyCalls = summary.monthCalls ?? summary.monthlyCalls ?? null;
|
|
2070
|
+
|
|
2071
|
+
// All-time: sum sessions if available, else fall back to monthly
|
|
2072
|
+
let allTimeCost = summary.allTimeCost ?? summary.totalCost ?? null;
|
|
2073
|
+
let allTimeCalls = summary.allTimeCalls ?? summary.totalCalls ?? null;
|
|
2074
|
+
if (allTimeCost == null && sessions.length > 0) {
|
|
2075
|
+
allTimeCost = sessions.reduce((s, x) => s + (x.cost || x.totalCost || 0), 0);
|
|
2076
|
+
allTimeCalls = sessions.reduce((s, x) => s + (x.calls || x.callCount || 0), 0);
|
|
2077
|
+
}
|
|
2078
|
+
// Last resort: use monthly as best available approximation
|
|
2079
|
+
if (allTimeCost == null) allTimeCost = monthlyCost;
|
|
2080
|
+
if (allTimeCalls == null) allTimeCalls = monthlyCalls;
|
|
2081
|
+
|
|
2082
|
+
const summaryEl = document.getElementById('token-summary');
|
|
2083
|
+
if (summaryEl) {
|
|
2084
|
+
summaryEl.innerHTML = `
|
|
2085
|
+
<div class="token-stat">
|
|
2086
|
+
<div class="token-stat-label">DAILY</div>
|
|
2087
|
+
<div class="token-stat-val">${fmtCost(todayCost)}</div>
|
|
2088
|
+
${todayCalls != null ? `<div style="font-size:9px;color:var(--muted);margin-top:2px;">${fmtNum(todayCalls)} calls</div>` : ''}
|
|
2089
|
+
</div>
|
|
2090
|
+
<div class="token-stat">
|
|
2091
|
+
<div class="token-stat-label">MONTHLY</div>
|
|
2092
|
+
<div class="token-stat-val">${fmtCost(monthlyCost)}</div>
|
|
2093
|
+
${monthlyCalls != null ? `<div style="font-size:9px;color:var(--muted);margin-top:2px;">${fmtNum(monthlyCalls)} calls</div>` : ''}
|
|
2094
|
+
</div>
|
|
2095
|
+
<div class="token-stat">
|
|
2096
|
+
<div class="token-stat-label">ALL TIME $</div>
|
|
2097
|
+
<div class="token-stat-val">${fmtCost(allTimeCost)}</div>
|
|
2098
|
+
</div>
|
|
2099
|
+
<div class="token-stat">
|
|
2100
|
+
<div class="token-stat-label">ALL TIME CALLS</div>
|
|
2101
|
+
<div class="token-stat-val">${fmtNum(allTimeCalls) || '—'}</div>
|
|
2102
|
+
</div>
|
|
2103
|
+
`;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
const badge = document.getElementById('tokens-badge');
|
|
2107
|
+
if (badge) badge.textContent = todayCost != null ? fmtCost(todayCost) : '—';
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
function animateTokenBars() {
|
|
2111
|
+
tokensBarAnimPct = Math.min(1, tokensBarAnimPct + 0.06);
|
|
2112
|
+
drawTokenBars(tokensBarAnimPct);
|
|
2113
|
+
if (tokensBarAnimPct < 1) {
|
|
2114
|
+
tokensBarRAF = requestAnimationFrame(animateTokenBars);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
function drawTokenBars(pct) {
|
|
2119
|
+
const canvas = document.getElementById('tokens-canvas');
|
|
2120
|
+
if (!canvas) return;
|
|
2121
|
+
const body = document.getElementById('tokens-body');
|
|
2122
|
+
const availH = body ? body.clientHeight - 64 : 80;
|
|
2123
|
+
canvas.width = canvas.offsetWidth * window.devicePixelRatio;
|
|
2124
|
+
canvas.height = Math.max(50, availH) * window.devicePixelRatio;
|
|
2125
|
+
canvas.style.height = Math.max(50, availH) + 'px';
|
|
2126
|
+
const dpr = window.devicePixelRatio;
|
|
2127
|
+
const ctx = canvas.getContext('2d');
|
|
2128
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2129
|
+
|
|
2130
|
+
const W = canvas.width;
|
|
2131
|
+
const H = canvas.height;
|
|
2132
|
+
const d = tokensBarData;
|
|
2133
|
+
if (!d || !d.length) {
|
|
2134
|
+
ctx.fillStyle = 'rgba(58,58,90,0.4)';
|
|
2135
|
+
ctx.font = `${10 * dpr}px "Azeret Mono", monospace`;
|
|
2136
|
+
ctx.textAlign = 'center';
|
|
2137
|
+
ctx.fillText('NO TOKEN DATA', W / 2, H / 2);
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
const padL = 6 * dpr, padR = 6 * dpr, padT = 6 * dpr, padB = 22 * dpr;
|
|
2142
|
+
const chartW = W - padL - padR;
|
|
2143
|
+
const chartH = H - padT - padB;
|
|
2144
|
+
const maxVal = Math.max(...d.map(b => b.value), 0.0001);
|
|
2145
|
+
const barW = chartW / d.length;
|
|
2146
|
+
const gap = barW * 0.2;
|
|
2147
|
+
|
|
2148
|
+
// Grid lines
|
|
2149
|
+
ctx.strokeStyle = 'rgba(58,58,90,0.35)';
|
|
2150
|
+
ctx.lineWidth = dpr;
|
|
2151
|
+
for (let i = 0; i <= 3; i++) {
|
|
2152
|
+
const y = padT + chartH - (i / 3) * chartH;
|
|
2153
|
+
ctx.beginPath();
|
|
2154
|
+
ctx.moveTo(padL, y);
|
|
2155
|
+
ctx.lineTo(W - padR, y);
|
|
2156
|
+
ctx.stroke();
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
// Bars
|
|
2160
|
+
d.forEach((bar, i) => {
|
|
2161
|
+
const x = padL + i * barW + gap / 2;
|
|
2162
|
+
const w = barW - gap;
|
|
2163
|
+
const frac = maxVal > 0 ? (bar.value / maxVal) * pct : 0;
|
|
2164
|
+
const barH = Math.max(2 * dpr, frac * chartH);
|
|
2165
|
+
const y = padT + chartH - barH;
|
|
2166
|
+
|
|
2167
|
+
// Bar fill
|
|
2168
|
+
const grad = ctx.createLinearGradient(0, y, 0, padT + chartH);
|
|
2169
|
+
grad.addColorStop(0, 'rgba(0,229,200,0.85)');
|
|
2170
|
+
grad.addColorStop(1, 'rgba(0,229,200,0.2)');
|
|
2171
|
+
ctx.fillStyle = grad;
|
|
2172
|
+
ctx.beginPath();
|
|
2173
|
+
ctx.roundRect(x, y, w, barH, [2 * dpr, 2 * dpr, 0, 0]);
|
|
2174
|
+
ctx.fill();
|
|
2175
|
+
|
|
2176
|
+
// Top cap glow
|
|
2177
|
+
ctx.fillStyle = 'rgba(0,229,200,0.5)';
|
|
2178
|
+
ctx.fillRect(x, y, w, 2 * dpr);
|
|
2179
|
+
|
|
2180
|
+
// Label
|
|
2181
|
+
ctx.fillStyle = 'rgba(58,58,90,0.9)';
|
|
2182
|
+
ctx.font = `${9 * dpr}px "Azeret Mono", monospace`;
|
|
2183
|
+
ctx.textAlign = 'center';
|
|
2184
|
+
ctx.fillText(bar.label, x + w / 2, H - 4 * dpr);
|
|
2185
|
+
|
|
2186
|
+
// Value above bar
|
|
2187
|
+
if (pct > 0.7 && bar.value > 0) {
|
|
2188
|
+
ctx.fillStyle = 'rgba(192,192,212,0.7)';
|
|
2189
|
+
ctx.font = `${8 * dpr}px "Azeret Mono", monospace`;
|
|
2190
|
+
ctx.textAlign = 'center';
|
|
2191
|
+
const valStr = bar.value < 0.001 ? '<0.001' : bar.value.toFixed(3);
|
|
2192
|
+
ctx.fillText('$' + valStr, x + w / 2, y - 3 * dpr);
|
|
2193
|
+
}
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2198
|
+
// SWARM TOPOLOGY CANVAS — force-directed graph
|
|
2199
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2200
|
+
const swarm = {
|
|
2201
|
+
nodes: [],
|
|
2202
|
+
edges: [],
|
|
2203
|
+
animRAF: null,
|
|
2204
|
+
lastNodes: 0
|
|
2205
|
+
};
|
|
2206
|
+
|
|
2207
|
+
function buildSwarmGraph(data) {
|
|
2208
|
+
const sw = data.swarm || {};
|
|
2209
|
+
const state = sw.state || {};
|
|
2210
|
+
const activity = sw.activity || {};
|
|
2211
|
+
const config = sw.config || {};
|
|
2212
|
+
const suggestion = sw.suggestion || {};
|
|
2213
|
+
const agents = data.agents || {};
|
|
2214
|
+
const regs = agents.registrations || [];
|
|
2215
|
+
|
|
2216
|
+
// A "live" swarm requires real topology state, not just bare agent registrations
|
|
2217
|
+
const hasLiveSwarm = !!(state.id || state.swarmId || state.active);
|
|
2218
|
+
const activitySwarm = activity.swarm || {};
|
|
2219
|
+
const hasActivity = !!(activitySwarm.agent_count);
|
|
2220
|
+
|
|
2221
|
+
// Update swarm meta — prefer live state, fall back to suggestion/activity
|
|
2222
|
+
const meta = document.getElementById('swarm-meta');
|
|
2223
|
+
if (meta) {
|
|
2224
|
+
const topology = config.topology || state.topology || suggestion.topology || '—';
|
|
2225
|
+
const consensus = config.consensus || state.consensus || suggestion.consensus || '—';
|
|
2226
|
+
const score = suggestion.score != null ? suggestion.score + '/7' : null;
|
|
2227
|
+
const lastRun = activity.timestamp ? fmtAge(new Date(activity.timestamp).getTime()) : null;
|
|
2228
|
+
meta.innerHTML = `
|
|
2229
|
+
<div class="swarm-row">
|
|
2230
|
+
<span class="swarm-key">TOPOLOGY</span>
|
|
2231
|
+
<span class="swarm-val">${fmt(topology).toUpperCase()}</span>
|
|
2232
|
+
</div>
|
|
2233
|
+
<div class="swarm-row">
|
|
2234
|
+
<span class="swarm-key">CONSENSUS</span>
|
|
2235
|
+
<span class="swarm-val">${fmt(consensus).toUpperCase()}</span>
|
|
2236
|
+
</div>
|
|
2237
|
+
<div class="swarm-row">
|
|
2238
|
+
<span class="swarm-key">STATUS</span>
|
|
2239
|
+
<span class="swarm-val" style="color:${hasLiveSwarm ? 'var(--green)' : 'var(--muted)'}">${hasLiveSwarm ? 'ACTIVE' : 'IDLE'}</span>
|
|
2240
|
+
</div>
|
|
2241
|
+
${score ? `<div class="swarm-row"><span class="swarm-key">COMPLEXITY</span><span class="swarm-val">${escHtml(score)}</span></div>` : ''}
|
|
2242
|
+
${lastRun ? `<div class="swarm-row"><span class="swarm-key">LAST RUN</span><span class="swarm-val" style="color:var(--muted)">${escHtml(lastRun)}</span></div>` : ''}
|
|
2243
|
+
`;
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
const badge = document.getElementById('swarm-agents-badge');
|
|
2247
|
+
|
|
2248
|
+
const canvas = document.getElementById('swarm-canvas');
|
|
2249
|
+
if (!canvas) return;
|
|
2250
|
+
|
|
2251
|
+
if (!hasLiveSwarm) {
|
|
2252
|
+
if (badge) badge.textContent = activitySwarm.agent_count || regs.length || '0';
|
|
2253
|
+
if (swarm.animRAF) { cancelAnimationFrame(swarm.animRAF); swarm.animRAF = null; }
|
|
2254
|
+
// Draw static summary canvas
|
|
2255
|
+
const ctx = canvas.getContext('2d');
|
|
2256
|
+
canvas.width = canvas.offsetWidth * window.devicePixelRatio;
|
|
2257
|
+
canvas.height = canvas.offsetHeight * window.devicePixelRatio;
|
|
2258
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2259
|
+
const dpr = window.devicePixelRatio;
|
|
2260
|
+
const CW = canvas.width, CH = canvas.height;
|
|
2261
|
+
// Grid
|
|
2262
|
+
const step = 20 * dpr;
|
|
2263
|
+
ctx.strokeStyle = 'rgba(58,58,90,0.20)';
|
|
2264
|
+
ctx.lineWidth = dpr * 0.5;
|
|
2265
|
+
for (let gx = 0; gx <= CW; gx += step) { ctx.beginPath(); ctx.moveTo(gx,0); ctx.lineTo(gx,CH); ctx.stroke(); }
|
|
2266
|
+
for (let gy = 0; gy <= CH; gy += step) { ctx.beginPath(); ctx.moveTo(0,gy); ctx.lineTo(CW,gy); ctx.stroke(); }
|
|
2267
|
+
// Draw a representative static mini-topology based on suggestion
|
|
2268
|
+
const consensus = (suggestion.consensus || 'hierarchical').toLowerCase();
|
|
2269
|
+
const totalAgents = activitySwarm.agent_count || regs.length || 0;
|
|
2270
|
+
const nodeCount = Math.min(8, Math.max(3, totalAgents > 0 ? 7 : 3));
|
|
2271
|
+
const cx = CW / 2, cy = CH / 2;
|
|
2272
|
+
const r = Math.min(CW, CH) * 0.32;
|
|
2273
|
+
// Draw edges first
|
|
2274
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.12)';
|
|
2275
|
+
ctx.lineWidth = dpr;
|
|
2276
|
+
const positions = [];
|
|
2277
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
2278
|
+
const angle = (i / nodeCount) * Math.PI * 2 - Math.PI / 2;
|
|
2279
|
+
positions.push([cx + r * Math.cos(angle), cy + r * Math.sin(angle)]);
|
|
2280
|
+
}
|
|
2281
|
+
if (consensus === 'byzantine' || consensus === 'mesh') {
|
|
2282
|
+
// Mesh: connect each to next 2
|
|
2283
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
2284
|
+
for (let j = i+1; j <= i+2 && j < nodeCount; j++) {
|
|
2285
|
+
ctx.beginPath(); ctx.moveTo(positions[i][0], positions[i][1]); ctx.lineTo(positions[j][0], positions[j][1]); ctx.stroke();
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
} else {
|
|
2289
|
+
// Hierarchical: center node connects to all
|
|
2290
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
2291
|
+
ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(positions[i][0], positions[i][1]); ctx.stroke();
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
// Draw outer nodes
|
|
2295
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
2296
|
+
const [nx, ny] = positions[i];
|
|
2297
|
+
ctx.beginPath();
|
|
2298
|
+
ctx.arc(nx, ny, 5 * dpr, 0, Math.PI * 2);
|
|
2299
|
+
ctx.fillStyle = 'rgba(0,229,200,0.35)';
|
|
2300
|
+
ctx.fill();
|
|
2301
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.6)';
|
|
2302
|
+
ctx.lineWidth = dpr;
|
|
2303
|
+
ctx.stroke();
|
|
2304
|
+
}
|
|
2305
|
+
// Center node (coordinator)
|
|
2306
|
+
if (consensus !== 'mesh') {
|
|
2307
|
+
ctx.beginPath();
|
|
2308
|
+
ctx.arc(cx, cy, 7 * dpr, 0, Math.PI * 2);
|
|
2309
|
+
ctx.fillStyle = 'rgba(0,229,200,0.6)';
|
|
2310
|
+
ctx.fill();
|
|
2311
|
+
ctx.strokeStyle = 'rgba(0,229,200,1)';
|
|
2312
|
+
ctx.lineWidth = dpr * 1.5;
|
|
2313
|
+
ctx.stroke();
|
|
2314
|
+
}
|
|
2315
|
+
// Label
|
|
2316
|
+
ctx.fillStyle = 'rgba(100,100,140,0.8)';
|
|
2317
|
+
ctx.font = `500 ${9 * dpr}px "Syne Mono", monospace`;
|
|
2318
|
+
ctx.textAlign = 'center';
|
|
2319
|
+
const label = totalAgents > 0
|
|
2320
|
+
? `LAST SWARM · ${totalAgents} AGENTS`
|
|
2321
|
+
: 'NO SWARM HISTORY';
|
|
2322
|
+
ctx.fillText(label, CW / 2, CH - 10 * dpr);
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
// Live swarm: build nodes from state.agents
|
|
2327
|
+
const agentList = (state.agents || []).slice(0, 40);
|
|
2328
|
+
if (badge) badge.textContent = agentList.length;
|
|
2329
|
+
|
|
2330
|
+
// Only rebuild physics nodes if count changed
|
|
2331
|
+
if (agentList.length !== swarm.lastNodes) {
|
|
2332
|
+
swarm.lastNodes = agentList.length;
|
|
2333
|
+
const cx = 0.5, cy = 0.5;
|
|
2334
|
+
swarm.nodes = agentList.map((a, i) => {
|
|
2335
|
+
const angle = (i / Math.max(agentList.length, 1)) * Math.PI * 2;
|
|
2336
|
+
const r = 0.3;
|
|
2337
|
+
return {
|
|
2338
|
+
id: a ? (a.id || a.name || String(i)) : String(i),
|
|
2339
|
+
label: a ? (a.name || a.type || a.id || '?').slice(0,8) : '?',
|
|
2340
|
+
type: a ? (a.type || a.agentType || '') : '',
|
|
2341
|
+
status: a ? (a.status || 'unknown') : 'unknown',
|
|
2342
|
+
x: cx + r * Math.cos(angle) + (Math.random() - 0.5) * 0.05,
|
|
2343
|
+
y: cy + r * Math.sin(angle) + (Math.random() - 0.5) * 0.05,
|
|
2344
|
+
vx: 0, vy: 0
|
|
2345
|
+
};
|
|
2346
|
+
});
|
|
2347
|
+
|
|
2348
|
+
// Add coordinator node if swarm active
|
|
2349
|
+
if (state.id || state.active) {
|
|
2350
|
+
swarm.nodes.unshift({
|
|
2351
|
+
id: '__coord__',
|
|
2352
|
+
label: 'COORD',
|
|
2353
|
+
type: 'coordinator',
|
|
2354
|
+
status: 'active',
|
|
2355
|
+
x: cx, y: cy, vx: 0, vy: 0, isCoord: true
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
// Edges: connect all agents to coordinator
|
|
2360
|
+
swarm.edges = [];
|
|
2361
|
+
if (swarm.nodes.length > 1) {
|
|
2362
|
+
const coordIdx = swarm.nodes.findIndex(n => n.isCoord);
|
|
2363
|
+
if (coordIdx >= 0) {
|
|
2364
|
+
swarm.nodes.forEach((n, i) => {
|
|
2365
|
+
if (i !== coordIdx) swarm.edges.push([coordIdx, i]);
|
|
2366
|
+
});
|
|
2367
|
+
} else {
|
|
2368
|
+
// mesh-style
|
|
2369
|
+
for (let i = 0; i < Math.min(swarm.nodes.length, 6); i++) {
|
|
2370
|
+
swarm.edges.push([i, (i + 1) % swarm.nodes.length]);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
// Start animation loop
|
|
2377
|
+
if (!swarm.animRAF) {
|
|
2378
|
+
swarmAnimate();
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
function swarmPhysics() {
|
|
2383
|
+
const nodes = swarm.nodes;
|
|
2384
|
+
if (!nodes || nodes.length < 2) return;
|
|
2385
|
+
|
|
2386
|
+
const repulse = 0.0008;
|
|
2387
|
+
const attract = 0.0015;
|
|
2388
|
+
const damp = 0.88;
|
|
2389
|
+
const restLen = 0.22;
|
|
2390
|
+
|
|
2391
|
+
// Repulsion
|
|
2392
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2393
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
2394
|
+
const dx = nodes[j].x - nodes[i].x;
|
|
2395
|
+
const dy = nodes[j].y - nodes[i].y;
|
|
2396
|
+
const dist = Math.sqrt(dx * dx + dy * dy) || 0.01;
|
|
2397
|
+
const force = repulse / (dist * dist);
|
|
2398
|
+
const fx = (dx / dist) * force;
|
|
2399
|
+
const fy = (dy / dist) * force;
|
|
2400
|
+
nodes[i].vx -= fx;
|
|
2401
|
+
nodes[i].vy -= fy;
|
|
2402
|
+
nodes[j].vx += fx;
|
|
2403
|
+
nodes[j].vy += fy;
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
// Spring attraction along edges
|
|
2408
|
+
swarm.edges.forEach(([a, b]) => {
|
|
2409
|
+
if (!nodes[a] || !nodes[b]) return;
|
|
2410
|
+
const dx = nodes[b].x - nodes[a].x;
|
|
2411
|
+
const dy = nodes[b].y - nodes[a].y;
|
|
2412
|
+
const dist = Math.sqrt(dx * dx + dy * dy) || 0.01;
|
|
2413
|
+
const stretch = dist - restLen;
|
|
2414
|
+
const force = attract * stretch;
|
|
2415
|
+
const fx = (dx / dist) * force;
|
|
2416
|
+
const fy = (dy / dist) * force;
|
|
2417
|
+
nodes[a].vx += fx;
|
|
2418
|
+
nodes[a].vy += fy;
|
|
2419
|
+
nodes[b].vx -= fx;
|
|
2420
|
+
nodes[b].vy -= fy;
|
|
2421
|
+
});
|
|
2422
|
+
|
|
2423
|
+
// Center gravity
|
|
2424
|
+
nodes.forEach(n => {
|
|
2425
|
+
n.vx += (0.5 - n.x) * 0.001;
|
|
2426
|
+
n.vy += (0.5 - n.y) * 0.001;
|
|
2427
|
+
});
|
|
2428
|
+
|
|
2429
|
+
// Integrate + damp + clamp
|
|
2430
|
+
nodes.forEach(n => {
|
|
2431
|
+
n.vx *= damp;
|
|
2432
|
+
n.vy *= damp;
|
|
2433
|
+
n.x += n.vx;
|
|
2434
|
+
n.y += n.vy;
|
|
2435
|
+
n.x = Math.max(0.05, Math.min(0.95, n.x));
|
|
2436
|
+
n.y = Math.max(0.05, Math.min(0.95, n.y));
|
|
2437
|
+
});
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
function swarmAnimate() {
|
|
2441
|
+
swarm.animRAF = null; // main swarm panel removed; animation disabled
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
function swarmDraw() {
|
|
2445
|
+
const canvas = document.getElementById('swarm-canvas');
|
|
2446
|
+
if (!canvas) return;
|
|
2447
|
+
const dpr = window.devicePixelRatio;
|
|
2448
|
+
const W = canvas.offsetWidth * dpr;
|
|
2449
|
+
const H = canvas.offsetHeight * dpr;
|
|
2450
|
+
if (W <= 0 || H <= 0) return;
|
|
2451
|
+
if (canvas.width !== W || canvas.height !== H) {
|
|
2452
|
+
canvas.width = W;
|
|
2453
|
+
canvas.height = H;
|
|
2454
|
+
}
|
|
2455
|
+
const ctx = canvas.getContext('2d');
|
|
2456
|
+
ctx.clearRect(0, 0, W, H);
|
|
2457
|
+
|
|
2458
|
+
const nodes = swarm.nodes;
|
|
2459
|
+
if (!nodes || !nodes.length) return;
|
|
2460
|
+
|
|
2461
|
+
const tw = W / dpr, th = H / dpr;
|
|
2462
|
+
|
|
2463
|
+
// Draw edges
|
|
2464
|
+
swarm.edges.forEach(([a, b]) => {
|
|
2465
|
+
if (!nodes[a] || !nodes[b]) return;
|
|
2466
|
+
const x1 = nodes[a].x * W;
|
|
2467
|
+
const y1 = nodes[a].y * H;
|
|
2468
|
+
const x2 = nodes[b].x * W;
|
|
2469
|
+
const y2 = nodes[b].y * H;
|
|
2470
|
+
ctx.beginPath();
|
|
2471
|
+
ctx.moveTo(x1, y1);
|
|
2472
|
+
ctx.lineTo(x2, y2);
|
|
2473
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.15)';
|
|
2474
|
+
ctx.lineWidth = dpr;
|
|
2475
|
+
ctx.stroke();
|
|
2476
|
+
});
|
|
2477
|
+
|
|
2478
|
+
// Draw nodes
|
|
2479
|
+
nodes.forEach(n => {
|
|
2480
|
+
const x = n.x * W;
|
|
2481
|
+
const y = n.y * H;
|
|
2482
|
+
const r = n.isCoord ? 7 * dpr : 5 * dpr;
|
|
2483
|
+
const isActive = n.status === 'active' || n.status === 'running';
|
|
2484
|
+
const isIdle = n.status === 'idle';
|
|
2485
|
+
const color = n.isCoord ? '#00E5C8' : isActive ? '#00E5C8' : isIdle ? '#FFB700' : '#3A3A5A';
|
|
2486
|
+
|
|
2487
|
+
// Glow
|
|
2488
|
+
if (isActive || n.isCoord) {
|
|
2489
|
+
const grd = ctx.createRadialGradient(x, y, 0, x, y, r * 3);
|
|
2490
|
+
grd.addColorStop(0, 'rgba(0,229,200,0.25)');
|
|
2491
|
+
grd.addColorStop(1, 'rgba(0,229,200,0)');
|
|
2492
|
+
ctx.beginPath();
|
|
2493
|
+
ctx.arc(x, y, r * 3, 0, Math.PI * 2);
|
|
2494
|
+
ctx.fillStyle = grd;
|
|
2495
|
+
ctx.fill();
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// Circle
|
|
2499
|
+
ctx.beginPath();
|
|
2500
|
+
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
2501
|
+
ctx.fillStyle = color;
|
|
2502
|
+
ctx.fill();
|
|
2503
|
+
if (n.isCoord) {
|
|
2504
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.8)';
|
|
2505
|
+
ctx.lineWidth = dpr;
|
|
2506
|
+
ctx.stroke();
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
// Label
|
|
2510
|
+
ctx.fillStyle = 'rgba(192,192,212,0.75)';
|
|
2511
|
+
ctx.font = `${7 * dpr}px "Azeret Mono", monospace`;
|
|
2512
|
+
ctx.textAlign = 'center';
|
|
2513
|
+
ctx.fillText(n.label, x, y + r + 8 * dpr);
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2518
|
+
// MEMORY PALACE PANEL
|
|
2519
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2520
|
+
const MEM_COLORS = { user: '#7B8EFF', feedback: '#FFB347', project: '#00E5C8', reference: '#B47BFF', handoff: '#FF6B9D' };
|
|
2521
|
+
const MEM_TYPE_ORDER = ['handoff', 'user', 'feedback', 'project', 'reference'];
|
|
2522
|
+
|
|
2523
|
+
function renderMemoryFiles(files) {
|
|
2524
|
+
const left = document.getElementById('memory-left');
|
|
2525
|
+
if (!left) return;
|
|
2526
|
+
const byType = {};
|
|
2527
|
+
(files || []).forEach(f => {
|
|
2528
|
+
const t = f.type || 'project';
|
|
2529
|
+
if (!byType[t]) byType[t] = [];
|
|
2530
|
+
byType[t].push(f);
|
|
2531
|
+
});
|
|
2532
|
+
const typesSorted = [...MEM_TYPE_ORDER.filter(t => byType[t]), ...Object.keys(byType).filter(t => !MEM_TYPE_ORDER.includes(t))];
|
|
2533
|
+
let leftHtml = '<div class="section-label">MEMORIES</div>';
|
|
2534
|
+
if (!files || !files.length) {
|
|
2535
|
+
leftHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">No memory files found</div>';
|
|
2536
|
+
} else {
|
|
2537
|
+
typesSorted.forEach(type => {
|
|
2538
|
+
const color = MEM_COLORS[type] || 'var(--muted)';
|
|
2539
|
+
byType[type].forEach(m => {
|
|
2540
|
+
leftHtml += `<div class="drawer-item" style="cursor:pointer;" onclick="openPalaceOverlay()">
|
|
2541
|
+
<div class="drawer-top">
|
|
2542
|
+
<span style="font-size:8px;font-family:monospace;color:${color};background:${color}22;padding:1px 5px;border-radius:2px;letter-spacing:0.06em;white-space:nowrap">${escHtml(type.toUpperCase())}</span>
|
|
2543
|
+
<span class="drawer-wing" style="flex:1;padding-left:6px">${escHtml(m.name)}</span>
|
|
2544
|
+
</div>
|
|
2545
|
+
${m.description ? `<div class="drawer-content">${escHtml(m.description)}</div>` : ''}
|
|
2546
|
+
</div>`;
|
|
2547
|
+
});
|
|
2548
|
+
});
|
|
2549
|
+
}
|
|
2550
|
+
left.innerHTML = leftHtml;
|
|
2551
|
+
|
|
2552
|
+
const badge = document.getElementById('memory-badge');
|
|
2553
|
+
if (badge) { badge.textContent = (files || []).length; flashEl(badge); }
|
|
2554
|
+
|
|
2555
|
+
// Update BY TYPE in right panel if already rendered
|
|
2556
|
+
const right = document.getElementById('memory-right');
|
|
2557
|
+
if (right) {
|
|
2558
|
+
const byTypeEl = right.querySelector('[data-by-type]');
|
|
2559
|
+
if (byTypeEl) {
|
|
2560
|
+
let html = '';
|
|
2561
|
+
if (!files || !files.length) {
|
|
2562
|
+
html = '<div style="color:var(--muted);font-size:10px;padding:4px 0;">—</div>';
|
|
2563
|
+
} else {
|
|
2564
|
+
typesSorted.forEach(type => {
|
|
2565
|
+
const color = MEM_COLORS[type] || 'var(--muted)';
|
|
2566
|
+
html += `<div class="mem-stat-row"><span class="mem-stat-key" style="color:${color}">${escHtml(type.toUpperCase())}</span><span class="mem-stat-val">${(byType[type]||[]).length}</span></div>`;
|
|
2567
|
+
});
|
|
2568
|
+
}
|
|
2569
|
+
byTypeEl.innerHTML = html;
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
function renderMemory(data) {
|
|
2575
|
+
const mem = data.memory || {};
|
|
2576
|
+
|
|
2577
|
+
const hnswEl = document.getElementById('hnsw-indicator');
|
|
2578
|
+
if (hnswEl) {
|
|
2579
|
+
hnswEl.innerHTML = mem.hnsw ? '<span class="hnsw-badge"><span class="live-dot amber" style="width:5px;height:5px;"></span>HNSW</span>' : '';
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
const left = document.getElementById('memory-left');
|
|
2583
|
+
const right = document.getElementById('memory-right');
|
|
2584
|
+
if (!left || !right) return;
|
|
2585
|
+
|
|
2586
|
+
// Left: fetch memory files directly from endpoint (works regardless of server version)
|
|
2587
|
+
left.innerHTML = '<div class="section-label">MEMORIES</div><div style="color:var(--dim);font-size:10px;padding:4px 0;">Loading…</div>';
|
|
2588
|
+
const dir = selectedProjectDir || '';
|
|
2589
|
+
fetch(`/api/memory-files${dir ? '?dir=' + encodeURIComponent(dir) : ''}`)
|
|
2590
|
+
.then(r => r.ok ? r.json() : { memories: [] })
|
|
2591
|
+
.then(d => renderMemoryFiles(d.memories || []))
|
|
2592
|
+
.catch(() => renderMemoryFiles([]));
|
|
2593
|
+
|
|
2594
|
+
// Right: storage stats + type counts placeholder
|
|
2595
|
+
let rightHtml = '<div class="section-label">STORAGE</div>';
|
|
2596
|
+
const dbTitle = mem.dbPath ? `title="${escHtml(mem.dbPath)}"` : '';
|
|
2597
|
+
rightHtml += `<div class="mem-stat-row" ${dbTitle}><span class="mem-stat-key">DB SIZE</span><span class="mem-stat-val" style="color:${mem.dbSize ? 'var(--text)' : 'var(--muted)'}">${mem.dbSize ? fmtBytes(mem.dbSize) : '—'}</span></div>`;
|
|
2598
|
+
rightHtml += `<div class="mem-stat-row" style="margin-top:4px;"><span class="mem-stat-key">HNSW INDEX</span><span class="mem-stat-val" style="color:${mem.hnsw ? 'var(--green)' : 'var(--muted)'}">${mem.hnsw ? 'PRESENT' : 'ABSENT'}</span></div>`;
|
|
2599
|
+
rightHtml += '<div class="section-label" style="margin-top:10px;">RUVECTOR</div>';
|
|
2600
|
+
rightHtml += `<div class="mem-stat-row"><span class="mem-stat-key">DB SIZE</span><span class="mem-stat-val" style="color:${mem.ruvectorExists ? 'var(--text)' : 'var(--muted)'}">${mem.ruvectorExists ? fmtBytes(mem.ruvectorSize) : '—'}</span></div>`;
|
|
2601
|
+
rightHtml += `<div class="mem-stat-row" style="margin-top:4px;"><span class="mem-stat-key">PATTERNS</span><span class="mem-stat-val" style="color:${mem.ruvectorPatterns ? 'var(--teal)' : 'var(--muted)'}">${mem.ruvectorPatterns || '—'}</span></div>`;
|
|
2602
|
+
rightHtml += '<div class="section-label" style="margin-top:10px;">BY TYPE</div><div data-by-type>—</div>';
|
|
2603
|
+
|
|
2604
|
+
// Knowledge section integrated into Memory Palace
|
|
2605
|
+
const k = data.knowledge || {};
|
|
2606
|
+
const kChunks = k.chunks || 0;
|
|
2607
|
+
const kSkills = k.skills || 0;
|
|
2608
|
+
const kRecent = k.recent || [];
|
|
2609
|
+
rightHtml += '<div class="section-label" style="margin-top:10px;">KNOWLEDGE</div>';
|
|
2610
|
+
rightHtml += `<div class="mem-stat-row"><span class="mem-stat-key">CHUNKS</span><span class="mem-stat-val" style="color:${kChunks ? 'var(--teal)' : 'var(--muted)'}">${kChunks || '—'}</span></div>`;
|
|
2611
|
+
rightHtml += `<div class="mem-stat-row" style="margin-top:3px;"><span class="mem-stat-key">SKILLS</span><span class="mem-stat-val" style="color:${kSkills ? 'var(--text)' : 'var(--muted)'}">${kSkills || '—'}</span></div>`;
|
|
2612
|
+
if (kRecent.length) {
|
|
2613
|
+
rightHtml += '<div style="margin-top:6px;">';
|
|
2614
|
+
kRecent.slice(0,3).forEach(c => {
|
|
2615
|
+
if (!c) return;
|
|
2616
|
+
const text = c.content || c.text || c.chunk || c.value || '';
|
|
2617
|
+
if (!text) return;
|
|
2618
|
+
rightHtml += `<div class="chunk-preview" title="${escHtml(String(text))}">${escHtml(String(text).slice(0,55))}</div>`;
|
|
2619
|
+
});
|
|
2620
|
+
rightHtml += '</div>';
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
right.innerHTML = rightHtml;
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2627
|
+
// HOOKS & ROUTING PANEL
|
|
2628
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2629
|
+
function renderHooks(data) {
|
|
2630
|
+
const h = data.hooks || {};
|
|
2631
|
+
const lastRoute = h.lastRoute || {};
|
|
2632
|
+
const feedback = h.feedback || [];
|
|
2633
|
+
const workers = h.workerDispatch || [];
|
|
2634
|
+
|
|
2635
|
+
const badge = document.getElementById('hooks-badge');
|
|
2636
|
+
if (badge) badge.textContent = feedback.length || '—';
|
|
2637
|
+
|
|
2638
|
+
const left = document.getElementById('hooks-left');
|
|
2639
|
+
const right = document.getElementById('hooks-right');
|
|
2640
|
+
if (!left || !right) return;
|
|
2641
|
+
|
|
2642
|
+
// Left: last route — actual fields: agent, confidence, reason, semanticRouting, updatedAt
|
|
2643
|
+
let leftHtml = '<div class="section-label">LAST ROUTE</div>';
|
|
2644
|
+
const routeAgent = lastRoute.agent || lastRoute.suggestedAgent || null;
|
|
2645
|
+
if (routeAgent) {
|
|
2646
|
+
const conf = lastRoute.confidence != null ? Math.round(lastRoute.confidence * 100) + '%' : null;
|
|
2647
|
+
const reason = lastRoute.reason || null;
|
|
2648
|
+
const mode = lastRoute.semanticRouting ? 'semantic' : 'pattern';
|
|
2649
|
+
const age = lastRoute.updatedAt ? fmtAge(new Date(lastRoute.updatedAt).getTime()) : null;
|
|
2650
|
+
leftHtml += `<div class="route-block">
|
|
2651
|
+
<div style="display:flex;align-items:center;gap:6px;margin-bottom:5px;">
|
|
2652
|
+
<span class="route-agent-tag" style="font-size:10px;padding:2px 8px;">${escHtml(routeAgent)}</span>
|
|
2653
|
+
${conf ? `<span style="font-size:11px;color:var(--teal);font-weight:600;">${conf}</span>` : ''}
|
|
2654
|
+
<span style="font-size:9px;color:var(--dim);margin-left:auto;">${escHtml(mode)}</span>
|
|
2655
|
+
</div>
|
|
2656
|
+
${reason ? `<div class="route-task-text" style="color:var(--muted);font-size:9px;">${escHtml(reason.slice(0,100))}</div>` : ''}
|
|
2657
|
+
${age ? `<div style="font-size:9px;color:var(--dim);margin-top:4px;">${escHtml(age)}</div>` : ''}
|
|
2658
|
+
</div>`;
|
|
2659
|
+
} else {
|
|
2660
|
+
leftHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">Run a task to see routing</div>';
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
leftHtml += '<div class="section-label" style="margin-top:7px;">WORKERS DISPATCHED</div>';
|
|
2664
|
+
if (!workers.length) {
|
|
2665
|
+
leftHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">None dispatched yet</div>';
|
|
2666
|
+
} else {
|
|
2667
|
+
leftHtml += '<div style="display:flex;flex-wrap:wrap;">';
|
|
2668
|
+
workers.slice(0,12).forEach(w => {
|
|
2669
|
+
leftHtml += `<span class="worker-tag">${escHtml(String(w).slice(0,18))}</span>`;
|
|
2670
|
+
});
|
|
2671
|
+
leftHtml += '</div>';
|
|
2672
|
+
}
|
|
2673
|
+
left.innerHTML = leftHtml;
|
|
2674
|
+
|
|
2675
|
+
// Right: routing history — actual fields: suggestedAgent, confidence, sessionId, timestamp
|
|
2676
|
+
let rightHtml = '<div class="section-label">ROUTING HISTORY</div>';
|
|
2677
|
+
if (!feedback.length) {
|
|
2678
|
+
rightHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">No history yet</div>';
|
|
2679
|
+
} else {
|
|
2680
|
+
[...feedback].reverse().forEach(fb => {
|
|
2681
|
+
if (!fb) return;
|
|
2682
|
+
const agent = fb.suggestedAgent || fb.agent || '?';
|
|
2683
|
+
const conf = fb.confidence != null ? Math.round(fb.confidence * 100) + '%' : '';
|
|
2684
|
+
const ts = fb.timestamp ? fmtAge(new Date(fb.timestamp).getTime()) : '';
|
|
2685
|
+
rightHtml += `<div class="feedback-item">
|
|
2686
|
+
<span class="route-agent-tag" style="font-size:9px;">${escHtml(agent.slice(0,16))}</span>
|
|
2687
|
+
${conf ? `<span style="font-size:9px;color:var(--teal);font-weight:600;">${conf}</span>` : ''}
|
|
2688
|
+
<span style="font-size:9px;color:var(--dim);margin-left:auto;">${escHtml(ts)}</span>
|
|
2689
|
+
</div>`;
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
right.innerHTML = rightHtml;
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2696
|
+
// KNOWLEDGE PANEL
|
|
2697
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2698
|
+
function renderKnowledge(data) {
|
|
2699
|
+
const k = data.knowledge || {};
|
|
2700
|
+
const chunks = k.chunks || 0;
|
|
2701
|
+
const skills = k.skills || 0;
|
|
2702
|
+
const recent = k.recent || [];
|
|
2703
|
+
|
|
2704
|
+
const badge = document.getElementById('knowledge-badge');
|
|
2705
|
+
if (badge) badge.textContent = chunks;
|
|
2706
|
+
|
|
2707
|
+
const body = document.getElementById('knowledge-body');
|
|
2708
|
+
if (!body) return;
|
|
2709
|
+
|
|
2710
|
+
let html = '<div class="knowledge-counts">';
|
|
2711
|
+
html += `<div class="know-stat"><div class="know-stat-label">CHUNKS</div><div class="know-stat-val">${fmtNum(chunks)}</div></div>`;
|
|
2712
|
+
html += `<div class="know-stat"><div class="know-stat-label">SKILLS</div><div class="know-stat-val">${fmtNum(skills)}</div></div>`;
|
|
2713
|
+
html += '</div>';
|
|
2714
|
+
|
|
2715
|
+
if (recent.length) {
|
|
2716
|
+
html += '<div class="section-label">RECENT CHUNKS</div>';
|
|
2717
|
+
recent.forEach(c => {
|
|
2718
|
+
if (!c) return;
|
|
2719
|
+
const text = c.content || c.text || c.chunk || c.value || JSON.stringify(c).slice(0, 60);
|
|
2720
|
+
html += `<div class="chunk-preview" title="${escHtml(String(text))}">${escHtml(String(text).slice(0,70))}</div>`;
|
|
2721
|
+
});
|
|
2722
|
+
} else {
|
|
2723
|
+
html += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">No chunks found</div>';
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
body.innerHTML = html;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2730
|
+
// METRICS PANEL
|
|
2731
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2732
|
+
function renderMetrics(data) {
|
|
2733
|
+
const m = data.metrics || {};
|
|
2734
|
+
|
|
2735
|
+
// Fall back to top-level appData sections when metrics sub-keys are missing
|
|
2736
|
+
// (happens when server was started before collectMetrics was updated)
|
|
2737
|
+
let routing = m.routing || {};
|
|
2738
|
+
if (!routing.total && data.hooks && data.hooks.feedback) {
|
|
2739
|
+
const fb = data.hooks.feedback || [];
|
|
2740
|
+
let confSum = 0, confCnt = 0;
|
|
2741
|
+
const counts = {};
|
|
2742
|
+
for (const f of fb) {
|
|
2743
|
+
if (f.confidence != null) { confSum += f.confidence; confCnt++; }
|
|
2744
|
+
const a = f.suggestedAgent || f.agent;
|
|
2745
|
+
if (a) counts[a] = (counts[a] || 0) + 1;
|
|
2746
|
+
}
|
|
2747
|
+
const top = Object.entries(counts).sort((a, b) => b[1] - a[1])[0];
|
|
2748
|
+
routing = {
|
|
2749
|
+
total: fb.length,
|
|
2750
|
+
avgConfidence: confCnt > 0 ? Math.round((confSum / confCnt) * 100) : null,
|
|
2751
|
+
topAgent: top ? top[0] : null,
|
|
2752
|
+
topAgentCount: top ? top[1] : null,
|
|
2753
|
+
};
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
let swarmM = m.swarm || {};
|
|
2757
|
+
if (!swarmM.lastActive && data.swarm) {
|
|
2758
|
+
const sw = data.swarm || {};
|
|
2759
|
+
const act = sw.activity || {};
|
|
2760
|
+
const actSw = act.swarm || {};
|
|
2761
|
+
swarmM = {
|
|
2762
|
+
active: !!(sw.state && (sw.state.id || sw.state.active)) || actSw.active,
|
|
2763
|
+
agentCount: actSw.agent_count || (sw.state && sw.state.agents && sw.state.agents.length) || null,
|
|
2764
|
+
lastActive: act.timestamp || null,
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
let tokens = m.tokens || {};
|
|
2769
|
+
if (tokens.todayCost == null && data.tokens) {
|
|
2770
|
+
const sum = data.tokens.summary || {};
|
|
2771
|
+
tokens = {
|
|
2772
|
+
todayCost: sum.todayCost ?? null,
|
|
2773
|
+
todayCalls: sum.todayCalls ?? null,
|
|
2774
|
+
monthCost: sum.monthCost ?? sum.monthlyCost ?? null,
|
|
2775
|
+
monthCalls: sum.monthCalls ?? sum.monthlyCalls ?? null,
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
const security = m.security || {};
|
|
2780
|
+
|
|
2781
|
+
const body = document.getElementById('metrics-body');
|
|
2782
|
+
if (!body) return;
|
|
2783
|
+
|
|
2784
|
+
let html = '';
|
|
2785
|
+
|
|
2786
|
+
// Routing Intelligence
|
|
2787
|
+
html += '<div class="metric-block">';
|
|
2788
|
+
html += '<div class="metric-block-title">ROUTING INTELLIGENCE</div>';
|
|
2789
|
+
if (routing.total > 0) {
|
|
2790
|
+
html += `<div class="metric-row"><span class="metric-key">DECISIONS</span><span class="metric-val">${routing.total}</span></div>`;
|
|
2791
|
+
if (routing.avgConfidence != null) html += `<div class="metric-row"><span class="metric-key">AVG CONF</span><span class="metric-val">${routing.avgConfidence}%</span></div>`;
|
|
2792
|
+
if (routing.topAgent) html += `<div class="metric-row"><span class="metric-key">TOP AGENT</span><span class="metric-val" style="color:var(--teal)">${escHtml(routing.topAgent)} <span style="color:var(--muted)">(${routing.topAgentCount}×)</span></span></div>`;
|
|
2793
|
+
} else {
|
|
2794
|
+
html += '<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val" style="color:var(--muted)">NO HISTORY YET</span></div>';
|
|
2795
|
+
}
|
|
2796
|
+
html += '</div>';
|
|
2797
|
+
|
|
2798
|
+
// Swarm Activity
|
|
2799
|
+
html += '<div class="metric-block">';
|
|
2800
|
+
html += '<div class="metric-block-title">SWARM ACTIVITY</div>';
|
|
2801
|
+
if (swarmM.lastActive) {
|
|
2802
|
+
const swarmStatusClass = swarmM.active ? 'security-ok' : '';
|
|
2803
|
+
html += `<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val ${swarmStatusClass}">${swarmM.active ? 'ACTIVE' : 'IDLE'}</span></div>`;
|
|
2804
|
+
if (swarmM.agentCount != null) html += `<div class="metric-row"><span class="metric-key">AGENTS</span><span class="metric-val">${swarmM.agentCount}</span></div>`;
|
|
2805
|
+
html += `<div class="metric-row"><span class="metric-key">LAST RUN</span><span class="metric-val" style="color:var(--muted)">${escHtml(fmtAge(new Date(swarmM.lastActive).getTime()))}</span></div>`;
|
|
2806
|
+
} else {
|
|
2807
|
+
html += '<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val" style="color:var(--muted)">NO SWARM YET</span></div>';
|
|
2808
|
+
}
|
|
2809
|
+
html += '</div>';
|
|
2810
|
+
|
|
2811
|
+
// Token Usage (summary)
|
|
2812
|
+
html += '<div class="metric-block">';
|
|
2813
|
+
html += '<div class="metric-block-title">TOKEN USAGE</div>';
|
|
2814
|
+
if (tokens.todayCost != null) {
|
|
2815
|
+
html += `<div class="metric-row"><span class="metric-key">TODAY</span><span class="metric-val">${fmtCost(tokens.todayCost)} <span style="color:var(--muted)">(${fmt(tokens.todayCalls)} calls)</span></span></div>`;
|
|
2816
|
+
html += `<div class="metric-row"><span class="metric-key">MONTH</span><span class="metric-val">${fmtCost(tokens.monthCost)} <span style="color:var(--muted)">(${fmt(tokens.monthCalls)} calls)</span></span></div>`;
|
|
2817
|
+
} else {
|
|
2818
|
+
html += '<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val" style="color:var(--muted)">NO DATA</span></div>';
|
|
2819
|
+
}
|
|
2820
|
+
html += '</div>';
|
|
2821
|
+
|
|
2822
|
+
body.innerHTML = html;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2826
|
+
// ACTIVITY PANEL
|
|
2827
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2828
|
+
function appendActivity(msg, type) {
|
|
2829
|
+
const log = document.getElementById('activity-log');
|
|
2830
|
+
if (!log) return;
|
|
2831
|
+
activityCount++;
|
|
2832
|
+
|
|
2833
|
+
const entry = document.createElement('div');
|
|
2834
|
+
entry.className = 'activity-entry type-' + (type || 'default');
|
|
2835
|
+
entry.innerHTML = `<span class="activity-time">${now()}</span><span class="activity-msg">${escHtml(String(msg).slice(0,100))}</span>`;
|
|
2836
|
+
log.insertBefore(entry, log.firstChild);
|
|
2837
|
+
|
|
2838
|
+
// Trim old entries
|
|
2839
|
+
while (log.children.length > MAX_ACTIVITY) {
|
|
2840
|
+
log.removeChild(log.lastChild);
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
const badge = document.getElementById('activity-badge');
|
|
2844
|
+
if (badge) badge.textContent = Math.min(activityCount, MAX_ACTIVITY);
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
function inferActivityType(data, prevData) {
|
|
2848
|
+
if (!prevData) return 'default';
|
|
2849
|
+
// Detect what changed
|
|
2850
|
+
const sessNew = (data.sessions && data.sessions.count) || 0;
|
|
2851
|
+
const sessPrev = (prevData.sessions && prevData.sessions.count) || 0;
|
|
2852
|
+
if (sessNew !== sessPrev) return 'session';
|
|
2853
|
+
|
|
2854
|
+
const swNew = JSON.stringify(data.swarm || {});
|
|
2855
|
+
const swPrev = JSON.stringify(prevData.swarm || {});
|
|
2856
|
+
if (swNew !== swPrev) return 'swarm';
|
|
2857
|
+
|
|
2858
|
+
const agNew = (data.agents && data.agents.count) || 0;
|
|
2859
|
+
const agPrev = (prevData.agents && prevData.agents.count) || 0;
|
|
2860
|
+
if (agNew !== agPrev) return 'agent';
|
|
2861
|
+
|
|
2862
|
+
return 'default';
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2866
|
+
// SYSTEM PANEL
|
|
2867
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2868
|
+
function renderSystem(data) {
|
|
2869
|
+
const sys = data.system || {};
|
|
2870
|
+
const body = document.getElementById('system-body');
|
|
2871
|
+
if (!body) return;
|
|
2872
|
+
|
|
2873
|
+
const rows = [
|
|
2874
|
+
{ key: 'NODE', val: fmt(sys.nodeVersion) },
|
|
2875
|
+
{ key: 'PLATFORM', val: fmt(sys.platform) },
|
|
2876
|
+
{ key: 'UPTIME', val: fmtUptime(sys.uptime) },
|
|
2877
|
+
{ key: 'HEAP', val: sys.memoryMB != null ? sys.memoryMB + ' MB' : '—' }
|
|
2878
|
+
];
|
|
2879
|
+
|
|
2880
|
+
let html = rows.map(r =>
|
|
2881
|
+
`<div class="sys-row"><span class="sys-key">${r.key}</span><span class="sys-val">${escHtml(r.val)}</span></div>`
|
|
2882
|
+
).join('');
|
|
2883
|
+
|
|
2884
|
+
body.innerHTML = html;
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2888
|
+
// PROJECT STATS STRIP
|
|
2889
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2890
|
+
function renderProjectStats(data) {
|
|
2891
|
+
const strip = document.getElementById('project-stats-strip');
|
|
2892
|
+
if (!strip) return;
|
|
2893
|
+
|
|
2894
|
+
const tok = (data.tokens && data.tokens.summary) || {};
|
|
2895
|
+
const mem = data.memory || {};
|
|
2896
|
+
const sw = data.swarm || {};
|
|
2897
|
+
const know = data.knowledge || {};
|
|
2898
|
+
const hooks = data.hooks || {};
|
|
2899
|
+
const swState = sw.state || {};
|
|
2900
|
+
const swConfig = sw.config || {};
|
|
2901
|
+
|
|
2902
|
+
const todayCost = tok.todayCost != null ? tok.todayCost : (tok.today && tok.today.cost != null ? tok.today.cost : null);
|
|
2903
|
+
const monthlyCost = tok.monthlyCost != null ? tok.monthlyCost : (tok.monthly && tok.monthly.cost != null ? tok.monthly.cost : null);
|
|
2904
|
+
const memDb = mem.dbSize ? fmtBytes(mem.dbSize) : null;
|
|
2905
|
+
const hnswOn = !!mem.hnsw;
|
|
2906
|
+
const chunks = know.chunks || 0;
|
|
2907
|
+
const topology = swConfig.topology || swState.topology || null;
|
|
2908
|
+
const swarmActive = !!(swState.id || swState.swarmId || swState.active);
|
|
2909
|
+
const lastAgent = hooks.lastRoute && hooks.lastRoute.agent ? hooks.lastRoute.agent : null;
|
|
2910
|
+
const sessionCount = data.sessions && data.sessions.count != null ? data.sessions.count : 0;
|
|
2911
|
+
const ruvectorPatterns = mem.ruvectorPatterns || 0;
|
|
2912
|
+
|
|
2913
|
+
const pills = [];
|
|
2914
|
+
pills.push({ key: 'SESSIONS', val: String(sessionCount), cls: '' });
|
|
2915
|
+
if (todayCost != null) pills.push({ key: 'TODAY', val: fmtCost(todayCost), cls: 'amber' });
|
|
2916
|
+
if (monthlyCost != null) pills.push({ key: 'MONTH', val: fmtCost(monthlyCost), cls: 'amber' });
|
|
2917
|
+
pills.push({ key: 'MEM DB', val: memDb || '—', cls: memDb ? '' : 'dim' });
|
|
2918
|
+
pills.push({ key: 'HNSW', val: hnswOn ? 'ON' : 'OFF', cls: hnswOn ? 'green' : 'dim' });
|
|
2919
|
+
if (chunks) pills.push({ key: 'CHUNKS', val: fmtNum(chunks), cls: '' });
|
|
2920
|
+
if (ruvectorPatterns) pills.push({ key: 'PATTERNS', val: fmtNum(ruvectorPatterns), cls: '' });
|
|
2921
|
+
pills.push({ key: 'SWARM', val: swarmActive ? (topology || 'ACTIVE').toUpperCase() : (topology ? topology.toUpperCase() : 'IDLE'), cls: swarmActive ? 'green' : (topology ? '' : 'dim') });
|
|
2922
|
+
if (lastAgent) pills.push({ key: 'LAST ROUTE', val: lastAgent.slice(0, 14), cls: '' });
|
|
2923
|
+
|
|
2924
|
+
strip.innerHTML = pills.map(p =>
|
|
2925
|
+
`<div class="stat-pill"><span class="stat-pill-key">${p.key}</span><span class="stat-pill-val ${p.cls}">${escHtml(String(p.val))}</span></div>`
|
|
2926
|
+
).join('');
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2930
|
+
// MASTER UPDATE
|
|
2931
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2932
|
+
function updateAllPanels(data) {
|
|
2933
|
+
if (!data) return;
|
|
2934
|
+
const prev = appData;
|
|
2935
|
+
appData = data;
|
|
2936
|
+
lastUpdateTime = Date.now();
|
|
2937
|
+
|
|
2938
|
+
updateHeader(data);
|
|
2939
|
+
renderProjects(data); // always render (navigation panel)
|
|
2940
|
+
renderProjectStats(data);
|
|
2941
|
+
// Only render panels that are currently expanded
|
|
2942
|
+
if (expandedPanels.has('panel-agents')) renderAgents(data);
|
|
2943
|
+
if (expandedPanels.has('panel-tokens')) renderTokens(data);
|
|
2944
|
+
if (expandedPanels.has('panel-memory')) renderMemory(data);
|
|
2945
|
+
// Always update hooks badge even when panel is collapsed
|
|
2946
|
+
{ const h = data.hooks || {}; const lr = h.lastRoute || {}; const badge = document.getElementById('hooks-badge'); if (badge) badge.textContent = lr.agent || lr.suggestedAgent || (h.feedback && h.feedback.length) || '—'; }
|
|
2947
|
+
if (expandedPanels.has('panel-hooks')) renderHooks(data);
|
|
2948
|
+
if (expandedPanels.has('panel-metrics')) renderMetrics(data);
|
|
2949
|
+
if (expandedPanels.has('panel-system')) renderSystem(data);
|
|
2950
|
+
// Activity log entry
|
|
2951
|
+
if (prev) {
|
|
2952
|
+
const type = inferActivityType(data, prev);
|
|
2953
|
+
const msg = buildActivityMsg(data, prev);
|
|
2954
|
+
if (msg) appendActivity(msg, type);
|
|
2955
|
+
} else {
|
|
2956
|
+
appendActivity('Initial data loaded', 'default');
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
updateLiveBorders();
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
function buildActivityMsg(data, prev) {
|
|
2963
|
+
const sessNew = (data.sessions && data.sessions.count) || 0;
|
|
2964
|
+
const sessPrev = (prev.sessions && prev.sessions.count) || 0;
|
|
2965
|
+
if (sessNew !== sessPrev) {
|
|
2966
|
+
return `Sessions changed: ${sessPrev} → ${sessNew}`;
|
|
2967
|
+
}
|
|
2968
|
+
const agNew = (data.agents && data.agents.count) || 0;
|
|
2969
|
+
const agPrev = (prev.agents && prev.agents.count) || 0;
|
|
2970
|
+
if (agNew !== agPrev) {
|
|
2971
|
+
return `Agents changed: ${agPrev} → ${agNew}`;
|
|
2972
|
+
}
|
|
2973
|
+
const swStateNew = JSON.stringify((data.swarm && data.swarm.state) || {});
|
|
2974
|
+
const swStatePrev = JSON.stringify((prev.swarm && prev.swarm.state) || {});
|
|
2975
|
+
if (swStateNew !== swStatePrev) return 'Swarm state updated';
|
|
2976
|
+
|
|
2977
|
+
const tokNew = JSON.stringify((data.tokens && data.tokens.summary) || {});
|
|
2978
|
+
const tokPrev = JSON.stringify((prev.tokens && prev.tokens.summary) || {});
|
|
2979
|
+
if (tokNew !== tokPrev) return 'Token metrics updated';
|
|
2980
|
+
|
|
2981
|
+
return null; // no visible change
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2985
|
+
// SSE CONNECTION
|
|
2986
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
2987
|
+
let sse = null;
|
|
2988
|
+
|
|
2989
|
+
function connectSSE() {
|
|
2990
|
+
if (sse) { try { sse.close(); } catch(e) {} }
|
|
2991
|
+
|
|
2992
|
+
const dot = document.getElementById('conn-dot');
|
|
2993
|
+
const label = document.getElementById('conn-label');
|
|
2994
|
+
|
|
2995
|
+
sse = new EventSource('/api/stream');
|
|
2996
|
+
|
|
2997
|
+
sse.onopen = function() {
|
|
2998
|
+
if (dot) dot.className = 'connected';
|
|
2999
|
+
if (label) label.textContent = 'LIVE';
|
|
3000
|
+
appendActivity('SSE stream connected', 'session');
|
|
3001
|
+
};
|
|
3002
|
+
|
|
3003
|
+
sse.onmessage = function(e) {
|
|
3004
|
+
try {
|
|
3005
|
+
const msg = JSON.parse(e.data);
|
|
3006
|
+
if (msg.kind === 'changed' && Array.isArray(msg.sections)) {
|
|
3007
|
+
// Incremental update: fetch only expanded panels that changed
|
|
3008
|
+
fetchAndRenderSections(msg.sections);
|
|
3009
|
+
appendActivity('Changed: ' + msg.sections.join(', '), 'default');
|
|
3010
|
+
lastUpdateTime = Date.now();
|
|
3011
|
+
updateLiveBorders();
|
|
3012
|
+
} else if (!msg.kind) {
|
|
3013
|
+
// Full snapshot (initial SSE message or legacy server)
|
|
3014
|
+
updateAllPanels(msg);
|
|
3015
|
+
}
|
|
3016
|
+
} catch(err) {
|
|
3017
|
+
appendActivity('Parse error: ' + err.message, 'error');
|
|
3018
|
+
}
|
|
3019
|
+
};
|
|
3020
|
+
|
|
3021
|
+
sse.onerror = function() {
|
|
3022
|
+
if (dot) dot.className = 'error';
|
|
3023
|
+
if (label) label.textContent = 'DISCONNECTED';
|
|
3024
|
+
appendActivity('SSE stream disconnected — reconnecting…', 'error');
|
|
3025
|
+
// EventSource auto-reconnects; update UI after a moment
|
|
3026
|
+
setTimeout(() => {
|
|
3027
|
+
if (sse && sse.readyState === EventSource.CONNECTING) {
|
|
3028
|
+
if (label) label.textContent = 'RECONNECTING';
|
|
3029
|
+
}
|
|
3030
|
+
}, 2000);
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3035
|
+
// INITIAL FETCH
|
|
3036
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3037
|
+
async function fetchInitial() {
|
|
3038
|
+
try {
|
|
3039
|
+
const resp = await fetch('/api/data');
|
|
3040
|
+
if (!resp.ok) throw new Error('HTTP ' + resp.status);
|
|
3041
|
+
const data = await resp.json();
|
|
3042
|
+
updateAllPanels(data);
|
|
3043
|
+
appendActivity('Initial state loaded from /api/data', 'session');
|
|
3044
|
+
} catch(err) {
|
|
3045
|
+
appendActivity('Failed to load /api/data: ' + err.message, 'error');
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3050
|
+
// LIVE BORDER REFRESH TIMER
|
|
3051
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3052
|
+
setInterval(updateLiveBorders, 2000);
|
|
3053
|
+
|
|
3054
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3055
|
+
// CANVAS RESIZE HANDLER
|
|
3056
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3057
|
+
let resizeTimer = null;
|
|
3058
|
+
window.addEventListener('resize', () => {
|
|
3059
|
+
clearTimeout(resizeTimer);
|
|
3060
|
+
resizeTimer = setTimeout(() => {
|
|
3061
|
+
if (appData) renderTokens(appData);
|
|
3062
|
+
}, 150);
|
|
3063
|
+
});
|
|
3064
|
+
|
|
3065
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3066
|
+
// HTML ESCAPE
|
|
3067
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3068
|
+
function escHtml(str) {
|
|
3069
|
+
return String(str)
|
|
3070
|
+
.replace(/&/g,'&')
|
|
3071
|
+
.replace(/</g,'<')
|
|
3072
|
+
.replace(/>/g,'>')
|
|
3073
|
+
.replace(/"/g,'"')
|
|
3074
|
+
.replace(/'/g,''');
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3078
|
+
// UPTIME TICKER
|
|
3079
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3080
|
+
setInterval(() => {
|
|
3081
|
+
if (appData && appData.system) {
|
|
3082
|
+
const el = document.getElementById('uptime-val');
|
|
3083
|
+
if (el) {
|
|
3084
|
+
appData.system.uptime = (appData.system.uptime || 0) + 2;
|
|
3085
|
+
el.textContent = fmtUptime(appData.system.uptime);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
}, 2000);
|
|
3089
|
+
|
|
3090
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3091
|
+
// PALACE OVERLAY
|
|
3092
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3093
|
+
let palaceData = null;
|
|
3094
|
+
let palaceCurrentTab = 'drawers';
|
|
3095
|
+
let palaceSelectedDrawer = null;
|
|
3096
|
+
|
|
3097
|
+
window.openPalaceOverlay = async function() {
|
|
3098
|
+
const overlay = document.getElementById('palace-overlay');
|
|
3099
|
+
overlay.classList.add('open');
|
|
3100
|
+
// Load data if not yet loaded
|
|
3101
|
+
if (!palaceData) await loadPalaceData();
|
|
3102
|
+
renderPalaceTab(palaceCurrentTab);
|
|
3103
|
+
};
|
|
3104
|
+
|
|
3105
|
+
window.closePalaceOverlay = function() {
|
|
3106
|
+
document.getElementById('palace-overlay').classList.remove('open');
|
|
3107
|
+
};
|
|
3108
|
+
|
|
3109
|
+
window.switchPalaceTab = function(tab) {
|
|
3110
|
+
palaceCurrentTab = tab;
|
|
3111
|
+
// Drive active state from the onclick argument, not DOM index
|
|
3112
|
+
document.querySelectorAll('#po-tabs .po-tab').forEach(b => {
|
|
3113
|
+
const btnTab = (b.getAttribute('onclick') || '').match(/'(\w+)'/);
|
|
3114
|
+
b.classList.toggle('active', !!(btnTab && btnTab[1] === tab));
|
|
3115
|
+
});
|
|
3116
|
+
document.querySelectorAll('.po-tab-pane').forEach(p => p.classList.remove('active'));
|
|
3117
|
+
const paneIds = { drawers: 'po-drawers-tab', sessions: 'po-sessions-tab', chunks: 'po-chunks-tab', swarm: 'po-swarm-tab', graph: 'po-graph-tab', knowledge: 'po-knowledge-tab' };
|
|
3118
|
+
const pane = document.getElementById(paneIds[tab]);
|
|
3119
|
+
if (pane) pane.classList.add('active');
|
|
3120
|
+
if (tab !== 'graph') kgGraph.stop();
|
|
3121
|
+
if (tab !== 'knowledge') kgCodeGraph.stop();
|
|
3122
|
+
if (palaceData) renderPalaceTab(tab);
|
|
3123
|
+
};
|
|
3124
|
+
|
|
3125
|
+
async function loadPalaceData() {
|
|
3126
|
+
const dir = selectedProjectDir || '';
|
|
3127
|
+
const safeJson = async (res, fallback) => { try { return res.ok ? await res.json() : fallback; } catch { return fallback; } };
|
|
3128
|
+
|
|
3129
|
+
const palaceUrl = `/api/palace${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
|
|
3130
|
+
const graphUrl = `/api/graph${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
|
|
3131
|
+
const memUrl = `/api/memory-files${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
|
|
3132
|
+
const sectionUrl = `/api/section?name=sessions${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
|
|
3133
|
+
|
|
3134
|
+
const knowUrl = `/api/section?name=knowledge${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
|
|
3135
|
+
const swarmUrl = `/api/section?name=swarm${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
|
|
3136
|
+
const [palaceRes, graphRes, memRes, sessRes, knowRes, swarmRes] = await Promise.all([
|
|
3137
|
+
fetch(palaceUrl).catch(() => ({ ok: false })),
|
|
3138
|
+
fetch(graphUrl).catch(() => ({ ok: false })),
|
|
3139
|
+
fetch(memUrl).catch(() => ({ ok: false })),
|
|
3140
|
+
fetch(sectionUrl).catch(() => ({ ok: false })),
|
|
3141
|
+
fetch(knowUrl).catch(() => ({ ok: false })),
|
|
3142
|
+
fetch(swarmUrl).catch(() => ({ ok: false }))
|
|
3143
|
+
]);
|
|
3144
|
+
|
|
3145
|
+
palaceData = await safeJson(palaceRes, { drawers: [], identity: null, kg: [] });
|
|
3146
|
+
palaceData.graph = await safeJson(graphRes, { nodes: [], edges: [] });
|
|
3147
|
+
const memData = await safeJson(memRes, { memories: [], memDir: '' });
|
|
3148
|
+
palaceData.memories = memData.memories || [];
|
|
3149
|
+
palaceData.memDir = memData.memDir || '';
|
|
3150
|
+
const sessData = await safeJson(sessRes, { sessions: {} });
|
|
3151
|
+
palaceData.sessions = (sessData.sessions && sessData.sessions.list) || [];
|
|
3152
|
+
const knowData = await safeJson(knowRes, { knowledge: {} });
|
|
3153
|
+
palaceData.knowledge = knowData.knowledge || {};
|
|
3154
|
+
const swarmSectionData = await safeJson(swarmRes, {});
|
|
3155
|
+
palaceData.swarmSection = swarmSectionData.swarm || swarmSectionData || {};
|
|
3156
|
+
// Update stats bar
|
|
3157
|
+
const stats = document.getElementById('po-stats');
|
|
3158
|
+
if (stats && palaceData) {
|
|
3159
|
+
const mems = (palaceData.memories || []).length;
|
|
3160
|
+
const sess = (palaceData.sessions || []).length;
|
|
3161
|
+
const chunks = palaceData.knowledge.chunks || 0;
|
|
3162
|
+
stats.innerHTML = `<span>${mems} memories</span><span>${sess} sessions</span>${chunks ? `<span>${fmtNum(chunks)} chunks</span>` : ''}`;
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3166
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3167
|
+
// GRAPHIFY REPORT PARSER (used by Memory Palace knowledge tab)
|
|
3168
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3169
|
+
function parseGraphifyReport(md) {
|
|
3170
|
+
const SECTION_ICONS = {
|
|
3171
|
+
'corpus check': '📂', 'summary': '📊', 'god nodes': '⭐',
|
|
3172
|
+
'surprising connections': '🔗', 'communities': '🏘', 'community': '🏘',
|
|
3173
|
+
'ambiguous edges': '⚠', 'knowledge gaps': '🕳', 'suggested questions': '💡',
|
|
3174
|
+
'hyperedges': '🔀',
|
|
3175
|
+
};
|
|
3176
|
+
const WIDE_SECTIONS = ['summary', 'corpus check', 'suggested questions'];
|
|
3177
|
+
const lines = md.split('\n');
|
|
3178
|
+
const sections = [];
|
|
3179
|
+
let currentTitle = null;
|
|
3180
|
+
let currentBody = [];
|
|
3181
|
+
|
|
3182
|
+
const flush = () => {
|
|
3183
|
+
if (currentTitle === null) return;
|
|
3184
|
+
const body = currentBody.join('\n').trim();
|
|
3185
|
+
sections.push({ title: currentTitle, body: body.length > 1200 ? body.slice(0, 1200) + '\n…' : body });
|
|
3186
|
+
};
|
|
3187
|
+
|
|
3188
|
+
for (const line of lines) {
|
|
3189
|
+
const h = line.match(/^#{2,3}\s+(.+)/);
|
|
3190
|
+
if (h) { flush(); currentTitle = h[1].replace(/\*\*/g, '').trim(); currentBody = []; }
|
|
3191
|
+
else if (currentTitle !== null) currentBody.push(line);
|
|
3192
|
+
}
|
|
3193
|
+
flush();
|
|
3194
|
+
|
|
3195
|
+
if (!sections.length) {
|
|
3196
|
+
return `<div class="kg-report-grid"><div class="kg-card kg-card-wide"><div class="kg-card-body">${escHtml(md.slice(0, 2000))}</div></div></div>`;
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3199
|
+
const cards = sections.map(sec => {
|
|
3200
|
+
const k = Object.keys(SECTION_ICONS).find(key => sec.title.toLowerCase().includes(key));
|
|
3201
|
+
const icon = k ? SECTION_ICONS[k] : '';
|
|
3202
|
+
const wide = WIDE_SECTIONS.some(w => sec.title.toLowerCase().includes(w)) ? ' kg-card-wide' : '';
|
|
3203
|
+
return `<div class="kg-card${wide}">
|
|
3204
|
+
<div class="kg-card-title">${icon ? `<span class="kg-card-title-icon">${icon}</span>` : ''}${escHtml(sec.title.toUpperCase())}</div>
|
|
3205
|
+
${sec.body ? `<div class="kg-card-body">${escHtml(sec.body)}</div>` : ''}
|
|
3206
|
+
</div>`;
|
|
3207
|
+
}).join('');
|
|
3208
|
+
return `<div class="kg-report-grid">${cards}</div>`;
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
function renderPalaceTab(tab) {
|
|
3212
|
+
if (!palaceData) return;
|
|
3213
|
+
if (tab === 'drawers') renderMemories();
|
|
3214
|
+
else if (tab === 'sessions') renderPalaceSessions();
|
|
3215
|
+
else if (tab === 'chunks') renderPalaceChunks();
|
|
3216
|
+
else if (tab === 'swarm') renderPalaceSwarm();
|
|
3217
|
+
else if (tab === 'graph') { kgGraph.init(); kgGraph.render(palaceData.graph || { nodes: [], edges: [] }); }
|
|
3218
|
+
else if (tab === 'knowledge') { renderPalaceKnowledge(); renderPalaceCodeGraph(); }
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
let _allChunks = [];
|
|
3222
|
+
function renderPalaceChunks(filter) {
|
|
3223
|
+
const kd = (palaceData && palaceData.knowledge) || {};
|
|
3224
|
+
const countEl = document.getElementById('po-chunks-count');
|
|
3225
|
+
const skillsEl = document.getElementById('po-skills-count');
|
|
3226
|
+
const body = document.getElementById('po-chunks-body');
|
|
3227
|
+
if (!body) return;
|
|
3228
|
+
|
|
3229
|
+
if (countEl) countEl.textContent = fmtNum(kd.chunks || 0);
|
|
3230
|
+
if (skillsEl) skillsEl.textContent = fmtNum(kd.skills || 0);
|
|
3231
|
+
|
|
3232
|
+
// Fetch all chunks from the server if not loaded yet
|
|
3233
|
+
if (!_allChunks.length && kd.chunks > 0) {
|
|
3234
|
+
body.innerHTML = '<div style="color:var(--muted);font-size:10px;">Loading chunks…</div>';
|
|
3235
|
+
const dir = selectedProjectDir || '';
|
|
3236
|
+
fetch(`/api/section?name=knowledge&full=1${dir ? '&dir=' + encodeURIComponent(dir) : ''}`)
|
|
3237
|
+
.then(r => r.ok ? r.json() : { knowledge: {} })
|
|
3238
|
+
.then(d => {
|
|
3239
|
+
const k = d.knowledge || {};
|
|
3240
|
+
_allChunks = k.allChunks || k.recent || [];
|
|
3241
|
+
renderPalaceChunks();
|
|
3242
|
+
})
|
|
3243
|
+
.catch(() => { body.innerHTML = '<div style="color:var(--muted);font-size:10px;">Failed to load chunks</div>'; });
|
|
3244
|
+
return;
|
|
3245
|
+
}
|
|
3246
|
+
|
|
3247
|
+
const chunks = filter
|
|
3248
|
+
? _allChunks.filter(c => { const t = (c && (c.content || c.text || c.chunk || c.value || '')).toLowerCase(); return t.includes(filter.toLowerCase()); })
|
|
3249
|
+
: _allChunks;
|
|
3250
|
+
|
|
3251
|
+
if (!chunks.length && !kd.chunks) {
|
|
3252
|
+
body.innerHTML = '<div style="color:var(--muted);font-size:10px;padding:8px 0;">No knowledge chunks indexed yet.<br><br>Run: <code style="color:var(--teal)">npx monomind graphify build</code></div>';
|
|
3253
|
+
return;
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3256
|
+
if (!chunks.length) {
|
|
3257
|
+
body.innerHTML = `<div style="color:var(--muted);font-size:10px;padding:8px 0;">${filter ? 'No matches' : 'Chunks not available for preview'}</div>`;
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
|
|
3261
|
+
body.innerHTML = chunks.map(c => {
|
|
3262
|
+
if (!c) return '';
|
|
3263
|
+
const text = c.text || c.content || c.chunk || c.value || '';
|
|
3264
|
+
const src = (c.metadata && c.metadata.filePath) || c.source || c.file || c.sourceFile || '';
|
|
3265
|
+
const ns = c.namespace || c.type || c.chunkType || '';
|
|
3266
|
+
const shortSrc = src ? src.split('/').slice(-2).join('/') : '';
|
|
3267
|
+
const cid = escHtml(c.chunkId || '');
|
|
3268
|
+
return `<div class="chunk-card" data-chunk-id="${cid}" title="${escHtml(src)}">
|
|
3269
|
+
<div class="chunk-card-src">${shortSrc ? escHtml(shortSrc) : '—'}</div>
|
|
3270
|
+
<div class="chunk-card-text">${escHtml(String(text).slice(0, 220))}${text.length > 220 ? '<span style="color:var(--dim)">…</span>' : ''}</div>
|
|
3271
|
+
${ns ? `<div class="chunk-card-ns">${escHtml(ns)}</div>` : ''}
|
|
3272
|
+
${cid ? `<div class="chunk-card-actions">
|
|
3273
|
+
<button class="po-btn po-btn-edit" onclick="editKnowledgeChunk('${cid}')">EDIT</button>
|
|
3274
|
+
<button class="po-btn po-btn-delete" onclick="deleteKnowledgeChunk('${cid}')">DELETE</button>
|
|
3275
|
+
</div>` : ''}
|
|
3276
|
+
</div>`;
|
|
3277
|
+
}).join('');
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
window.filterChunks = function(val) {
|
|
3281
|
+
renderPalaceChunks(val);
|
|
3282
|
+
};
|
|
3283
|
+
|
|
3284
|
+
let _editingChunkId = null;
|
|
3285
|
+
window.editKnowledgeChunk = function(chunkId) {
|
|
3286
|
+
const chunk = _allChunks.find(c => c && c.chunkId === chunkId);
|
|
3287
|
+
if (!chunk) return;
|
|
3288
|
+
_editingChunkId = chunkId;
|
|
3289
|
+
const src = (chunk.metadata && chunk.metadata.filePath) || chunk.source || '';
|
|
3290
|
+
const shortSrc = src ? src.split('/').slice(-2).join('/') : chunkId;
|
|
3291
|
+
const titleEl = document.getElementById('po-chunk-edit-title');
|
|
3292
|
+
if (titleEl) titleEl.textContent = 'EDIT CHUNK — ' + shortSrc;
|
|
3293
|
+
const ta = document.getElementById('po-chunk-edit-textarea');
|
|
3294
|
+
if (ta) { ta.value = chunk.text || chunk.content || chunk.chunk || chunk.value || ''; ta.style.height = ''; }
|
|
3295
|
+
const modal = document.getElementById('po-chunk-edit-modal');
|
|
3296
|
+
if (modal) modal.classList.add('open');
|
|
3297
|
+
const status = document.getElementById('po-chunk-edit-status');
|
|
3298
|
+
if (status) status.textContent = '';
|
|
3299
|
+
if (ta) ta.focus();
|
|
3300
|
+
};
|
|
3301
|
+
|
|
3302
|
+
window.closeChunkEditModal = function() {
|
|
3303
|
+
const modal = document.getElementById('po-chunk-edit-modal');
|
|
3304
|
+
if (modal) modal.classList.remove('open');
|
|
3305
|
+
_editingChunkId = null;
|
|
3306
|
+
};
|
|
3307
|
+
|
|
3308
|
+
window.saveEditedChunk = async function() {
|
|
3309
|
+
if (!_editingChunkId) return;
|
|
3310
|
+
const ta = document.getElementById('po-chunk-edit-textarea');
|
|
3311
|
+
const status = document.getElementById('po-chunk-edit-status');
|
|
3312
|
+
const newText = ta ? ta.value : '';
|
|
3313
|
+
if (!newText.trim()) { if (status) status.textContent = 'Text cannot be empty'; return; }
|
|
3314
|
+
const dir = selectedProjectDir || '';
|
|
3315
|
+
try {
|
|
3316
|
+
const r = await fetch(`/api/knowledge-chunk${dir ? '?dir=' + encodeURIComponent(dir) : ''}`, {
|
|
3317
|
+
method: 'PUT',
|
|
3318
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3319
|
+
body: JSON.stringify({ chunkId: _editingChunkId, text: newText })
|
|
3320
|
+
});
|
|
3321
|
+
const d = await r.json();
|
|
3322
|
+
if (!r.ok) throw new Error(d.error || 'Save failed');
|
|
3323
|
+
// Update in-memory cache
|
|
3324
|
+
const idx = _allChunks.findIndex(c => c && c.chunkId === _editingChunkId);
|
|
3325
|
+
if (idx !== -1) _allChunks[idx] = { ..._allChunks[idx], text: newText };
|
|
3326
|
+
closeChunkEditModal();
|
|
3327
|
+
renderPalaceChunks();
|
|
3328
|
+
} catch (e) {
|
|
3329
|
+
if (status) status.textContent = e.message;
|
|
3330
|
+
}
|
|
3331
|
+
};
|
|
3332
|
+
|
|
3333
|
+
window.deleteKnowledgeChunk = async function(chunkId) {
|
|
3334
|
+
const chunk = _allChunks.find(c => c && c.chunkId === chunkId);
|
|
3335
|
+
const preview = chunk ? (chunk.text || '').slice(0, 60) : chunkId;
|
|
3336
|
+
if (!confirm(`Delete chunk?\n"${preview}"`)) return;
|
|
3337
|
+
const dir = selectedProjectDir || '';
|
|
3338
|
+
try {
|
|
3339
|
+
const r = await fetch(`/api/knowledge-chunk${dir ? '?dir=' + encodeURIComponent(dir) : ''}`, {
|
|
3340
|
+
method: 'DELETE',
|
|
3341
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3342
|
+
body: JSON.stringify({ chunkId })
|
|
3343
|
+
});
|
|
3344
|
+
const d = await r.json();
|
|
3345
|
+
if (!r.ok) throw new Error(d.error || 'Delete failed');
|
|
3346
|
+
_allChunks = _allChunks.filter(c => !c || c.chunkId !== chunkId);
|
|
3347
|
+
if (palaceData && palaceData.knowledge) {
|
|
3348
|
+
palaceData.knowledge.chunks = Math.max(0, (palaceData.knowledge.chunks || 1) - 1);
|
|
3349
|
+
}
|
|
3350
|
+
renderPalaceChunks();
|
|
3351
|
+
const countEl = document.getElementById('po-chunks-count');
|
|
3352
|
+
if (countEl) countEl.textContent = String(_allChunks.length);
|
|
3353
|
+
} catch (e) {
|
|
3354
|
+
alert('Delete failed: ' + e.message);
|
|
3355
|
+
}
|
|
3356
|
+
};
|
|
3357
|
+
|
|
3358
|
+
function renderPalaceSwarm() {
|
|
3359
|
+
if (!palaceData) return;
|
|
3360
|
+
// Pull swarm data — prefer appData (live SSE feed) over the palace section fetch
|
|
3361
|
+
const src = (appData && appData.swarm) ? appData : { swarm: palaceData.swarmSection || {} };
|
|
3362
|
+
const sw = src.swarm || {};
|
|
3363
|
+
const state = sw.state || {};
|
|
3364
|
+
const activity = sw.activity || {};
|
|
3365
|
+
const config = sw.config || {};
|
|
3366
|
+
const suggestion = sw.suggestion || {};
|
|
3367
|
+
const agentRegs = (src.agents && src.agents.registrations) ? src.agents.registrations : [];
|
|
3368
|
+
|
|
3369
|
+
const hasLiveSwarm = !!(state.id || state.swarmId || state.active);
|
|
3370
|
+
const activitySwarm = activity.swarm || {};
|
|
3371
|
+
const topology = config.topology || state.topology || suggestion.topology || '—';
|
|
3372
|
+
const consensus = config.consensus || state.consensus || suggestion.consensus || '—';
|
|
3373
|
+
const agentCount = hasLiveSwarm
|
|
3374
|
+
? (state.agents || []).length
|
|
3375
|
+
: (activitySwarm.agent_count || agentRegs.length || 0);
|
|
3376
|
+
const score = suggestion.score != null ? suggestion.score + '/7' : null;
|
|
3377
|
+
const lastRun = activity.timestamp ? fmtAge(new Date(activity.timestamp).getTime()) : null;
|
|
3378
|
+
const recommended = suggestion.recommended || null;
|
|
3379
|
+
|
|
3380
|
+
// Render sidebar meta
|
|
3381
|
+
const meta = document.getElementById('po-swarm-meta');
|
|
3382
|
+
if (meta) {
|
|
3383
|
+
const rows = [
|
|
3384
|
+
['TOPOLOGY', fmt(topology).toUpperCase()],
|
|
3385
|
+
['CONSENSUS', fmt(consensus).toUpperCase()],
|
|
3386
|
+
['STATUS', hasLiveSwarm ? '<span style="color:var(--green)">ACTIVE</span>' : '<span style="color:var(--muted)">IDLE</span>'],
|
|
3387
|
+
['AGENTS', agentCount || '—'],
|
|
3388
|
+
];
|
|
3389
|
+
if (score) rows.push(['COMPLEXITY', score]);
|
|
3390
|
+
if (recommended) rows.push(['RECOMMENDED', recommended]);
|
|
3391
|
+
if (lastRun) rows.push(['LAST RUN', `<span style="color:var(--muted)">${escHtml(lastRun)}</span>`]);
|
|
3392
|
+
meta.innerHTML = rows.map(([k, v]) =>
|
|
3393
|
+
`<div class="swarm-row"><span class="swarm-key">${k}</span><span class="swarm-val">${v}</span></div>`
|
|
3394
|
+
).join('');
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
// Update label
|
|
3398
|
+
const labelEl = document.getElementById('po-swarm-label');
|
|
3399
|
+
if (labelEl) labelEl.textContent = hasLiveSwarm ? 'LIVE TOPOLOGY' : 'LAST KNOWN TOPOLOGY';
|
|
3400
|
+
|
|
3401
|
+
// Draw on canvas — defer one frame so layout is flushed and offsetWidth/Height are non-zero
|
|
3402
|
+
const canvas = document.getElementById('po-swarm-canvas');
|
|
3403
|
+
if (!canvas) return;
|
|
3404
|
+
if (!canvas.offsetWidth) { requestAnimationFrame(renderPalaceSwarm); return; }
|
|
3405
|
+
const dpr = window.devicePixelRatio || 1;
|
|
3406
|
+
canvas.width = canvas.offsetWidth * dpr;
|
|
3407
|
+
canvas.height = canvas.offsetHeight * dpr;
|
|
3408
|
+
const ctx = canvas.getContext('2d');
|
|
3409
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
3410
|
+
const CW = canvas.width, CH = canvas.height;
|
|
3411
|
+
|
|
3412
|
+
// Grid background
|
|
3413
|
+
const step = 30 * dpr;
|
|
3414
|
+
ctx.strokeStyle = 'rgba(58,58,90,0.15)';
|
|
3415
|
+
ctx.lineWidth = dpr * 0.5;
|
|
3416
|
+
for (let gx = 0; gx <= CW; gx += step) { ctx.beginPath(); ctx.moveTo(gx,0); ctx.lineTo(gx,CH); ctx.stroke(); }
|
|
3417
|
+
for (let gy = 0; gy <= CH; gy += step) { ctx.beginPath(); ctx.moveTo(0,gy); ctx.lineTo(CW,gy); ctx.stroke(); }
|
|
3418
|
+
|
|
3419
|
+
const consensusLow = consensus.toLowerCase();
|
|
3420
|
+
const cx = CW / 2, cy = CH / 2;
|
|
3421
|
+
|
|
3422
|
+
if (hasLiveSwarm) {
|
|
3423
|
+
// Live: draw actual agent nodes
|
|
3424
|
+
const agentList = (state.agents || []).slice(0, 50);
|
|
3425
|
+
const n = agentList.length || 1;
|
|
3426
|
+
const r = Math.min(CW, CH) * 0.36;
|
|
3427
|
+
const positions = agentList.map((_, i) => {
|
|
3428
|
+
const angle = (i / n) * Math.PI * 2 - Math.PI / 2;
|
|
3429
|
+
return [cx + r * Math.cos(angle), cy + r * Math.sin(angle)];
|
|
3430
|
+
});
|
|
3431
|
+
// Edges
|
|
3432
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.15)';
|
|
3433
|
+
ctx.lineWidth = dpr;
|
|
3434
|
+
if (consensusLow === 'byzantine' || consensusLow === 'mesh') {
|
|
3435
|
+
for (let i = 0; i < n; i++) {
|
|
3436
|
+
for (let j = i+1; j <= i+2 && j < n; j++) {
|
|
3437
|
+
ctx.beginPath(); ctx.moveTo(positions[i][0], positions[i][1]); ctx.lineTo(positions[j][0], positions[j][1]); ctx.stroke();
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
} else {
|
|
3441
|
+
positions.forEach(([nx, ny]) => { ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(nx, ny); ctx.stroke(); });
|
|
3442
|
+
}
|
|
3443
|
+
// Nodes
|
|
3444
|
+
positions.forEach(([nx, ny], i) => {
|
|
3445
|
+
ctx.beginPath(); ctx.arc(nx, ny, 5 * dpr, 0, Math.PI * 2);
|
|
3446
|
+
ctx.fillStyle = 'rgba(0,229,200,0.4)'; ctx.fill();
|
|
3447
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.7)'; ctx.lineWidth = dpr; ctx.stroke();
|
|
3448
|
+
// Agent label
|
|
3449
|
+
const a = agentList[i];
|
|
3450
|
+
const lbl = (a.type || a.role || '?').slice(0, 6).toUpperCase();
|
|
3451
|
+
ctx.fillStyle = 'rgba(180,180,220,0.6)';
|
|
3452
|
+
ctx.font = `${7 * dpr}px "Azeret Mono", monospace`;
|
|
3453
|
+
ctx.textAlign = 'center';
|
|
3454
|
+
ctx.fillText(lbl, nx, ny + 10 * dpr);
|
|
3455
|
+
});
|
|
3456
|
+
// Coordinator
|
|
3457
|
+
ctx.beginPath(); ctx.arc(cx, cy, 9 * dpr, 0, Math.PI * 2);
|
|
3458
|
+
ctx.fillStyle = 'rgba(0,229,200,0.7)'; ctx.fill();
|
|
3459
|
+
ctx.strokeStyle = 'rgba(0,229,200,1)'; ctx.lineWidth = dpr * 2; ctx.stroke();
|
|
3460
|
+
ctx.fillStyle = '#fff';
|
|
3461
|
+
ctx.font = `bold ${8 * dpr}px "Azeret Mono", monospace`;
|
|
3462
|
+
ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
|
|
3463
|
+
ctx.fillText('Q', cx, cy);
|
|
3464
|
+
ctx.textBaseline = 'alphabetic';
|
|
3465
|
+
} else {
|
|
3466
|
+
// Idle: representative static diagram
|
|
3467
|
+
const nodeCount = Math.min(10, Math.max(4, agentCount > 0 ? 7 : 4));
|
|
3468
|
+
const r = Math.min(CW, CH) * 0.36;
|
|
3469
|
+
const positions = [];
|
|
3470
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
3471
|
+
const angle = (i / nodeCount) * Math.PI * 2 - Math.PI / 2;
|
|
3472
|
+
positions.push([cx + r * Math.cos(angle), cy + r * Math.sin(angle)]);
|
|
3473
|
+
}
|
|
3474
|
+
// Edges
|
|
3475
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.10)';
|
|
3476
|
+
ctx.lineWidth = dpr;
|
|
3477
|
+
if (consensusLow === 'byzantine' || consensusLow === 'mesh') {
|
|
3478
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
3479
|
+
for (let j = i+1; j <= i+3 && j < nodeCount; j++) {
|
|
3480
|
+
ctx.beginPath(); ctx.moveTo(positions[i][0], positions[i][1]); ctx.lineTo(positions[j][0], positions[j][1]); ctx.stroke();
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
} else {
|
|
3484
|
+
positions.forEach(([nx, ny]) => { ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(nx, ny); ctx.stroke(); });
|
|
3485
|
+
}
|
|
3486
|
+
// Outer nodes
|
|
3487
|
+
positions.forEach(([nx, ny]) => {
|
|
3488
|
+
ctx.beginPath(); ctx.arc(nx, ny, 6 * dpr, 0, Math.PI * 2);
|
|
3489
|
+
ctx.fillStyle = 'rgba(0,229,200,0.2)'; ctx.fill();
|
|
3490
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.45)'; ctx.lineWidth = dpr; ctx.stroke();
|
|
3491
|
+
});
|
|
3492
|
+
// Center coordinator (if not pure mesh)
|
|
3493
|
+
if (consensusLow !== 'mesh') {
|
|
3494
|
+
ctx.beginPath(); ctx.arc(cx, cy, 9 * dpr, 0, Math.PI * 2);
|
|
3495
|
+
ctx.fillStyle = 'rgba(0,229,200,0.35)'; ctx.fill();
|
|
3496
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.7)'; ctx.lineWidth = dpr * 1.5; ctx.stroke();
|
|
3497
|
+
}
|
|
3498
|
+
// Footer label
|
|
3499
|
+
ctx.fillStyle = 'rgba(100,100,140,0.6)';
|
|
3500
|
+
ctx.font = `500 ${9 * dpr}px "Azeret Mono", monospace`;
|
|
3501
|
+
ctx.textAlign = 'center';
|
|
3502
|
+
const footerLabel = agentCount > 0
|
|
3503
|
+
? `LAST SWARM · ${agentCount} AGENTS`
|
|
3504
|
+
: 'NO SWARM HISTORY';
|
|
3505
|
+
ctx.fillText(footerLabel, CW / 2, CH - 14 * dpr);
|
|
3506
|
+
// Topology label in center for mesh
|
|
3507
|
+
if (consensusLow === 'mesh' || consensusLow === 'byzantine') {
|
|
3508
|
+
ctx.fillStyle = 'rgba(0,229,200,0.25)';
|
|
3509
|
+
ctx.font = `bold ${10 * dpr}px "Syne", sans-serif`;
|
|
3510
|
+
ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
|
|
3511
|
+
ctx.fillText(consensusLow.toUpperCase(), cx, cy);
|
|
3512
|
+
ctx.textBaseline = 'alphabetic';
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3517
|
+
async function renderPalaceKnowledge() {
|
|
3518
|
+
const statsEl = document.getElementById('po-knowledge-stats');
|
|
3519
|
+
const bodyEl = document.getElementById('po-knowledge-body');
|
|
3520
|
+
if (!statsEl || !bodyEl) return;
|
|
3521
|
+
|
|
3522
|
+
const dir = selectedProjectDir || '';
|
|
3523
|
+
let d;
|
|
3524
|
+
try {
|
|
3525
|
+
const r = await fetch(`/api/graphify-report${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
|
|
3526
|
+
d = r.ok ? await r.json() : { exists: false, stats: null, content: null };
|
|
3527
|
+
} catch { d = { exists: false, stats: null, content: null }; }
|
|
3528
|
+
|
|
3529
|
+
// Append monomind knowledge (chunks/skills) to sidebar regardless of graph state
|
|
3530
|
+
const kd = (palaceData && palaceData.knowledge) || {};
|
|
3531
|
+
const kChunks = kd.chunks || 0;
|
|
3532
|
+
const kSkills = kd.skills || 0;
|
|
3533
|
+
const kRecent = kd.recent || [];
|
|
3534
|
+
const knowledgeSuffix = `
|
|
3535
|
+
<div class="kg-stat-group" style="margin-top:16px;border-top:1px solid var(--border);padding-top:12px;">
|
|
3536
|
+
<div class="kg-stat-group-label">MONOMIND KNOWLEDGE</div>
|
|
3537
|
+
<div class="kg-stat-row"><span class="kg-stat-key">Chunks</span><span class="kg-stat-val" style="color:${kChunks ? 'var(--teal)' : 'var(--muted)'}">${kChunks || '—'}</span></div>
|
|
3538
|
+
${kSkills ? `<div class="kg-stat-row"><span class="kg-stat-key">Skills</span><span class="kg-stat-val">${kSkills}</span></div>` : ''}
|
|
3539
|
+
${kRecent.slice(0,3).map(c => {
|
|
3540
|
+
if (!c) return '';
|
|
3541
|
+
const t = c.content || c.text || c.chunk || c.value || '';
|
|
3542
|
+
return t ? `<div class="chunk-preview" title="${escHtml(String(t))}" style="margin-top:4px;">${escHtml(String(t).slice(0,55))}</div>` : '';
|
|
3543
|
+
}).join('')}
|
|
3544
|
+
</div>`;
|
|
3545
|
+
|
|
3546
|
+
if (!d.stats) {
|
|
3547
|
+
statsEl.innerHTML = `<div class="kg-badge kg-badge-warn">NO GRAPH</div>
|
|
3548
|
+
<div style="font-size:9px;color:var(--muted);margin:10px 0 14px;line-height:1.6;">No graph built yet.</div>
|
|
3549
|
+
<button class="kg-action-btn" onclick="triggerPalaceGraphBuild()">BUILD GRAPH</button>
|
|
3550
|
+
<div style="margin-top:10px;font-size:8px;color:var(--dim);line-height:1.7;">or run:<br><code style="color:var(--teal)">npx monomind graphify build</code></div>
|
|
3551
|
+
${knowledgeSuffix}`;
|
|
3552
|
+
} else {
|
|
3553
|
+
const s = d.stats;
|
|
3554
|
+
const e = s.enriched ?? d.enriched;
|
|
3555
|
+
statsEl.innerHTML = `
|
|
3556
|
+
<div class="kg-badge kg-badge-ok">INDEXED</div>
|
|
3557
|
+
<div class="kg-stat-group" style="margin-top:14px;">
|
|
3558
|
+
<div class="kg-stat-group-label">RAW GRAPH</div>
|
|
3559
|
+
${s.nodes !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Nodes</span><span class="kg-stat-val" style="color:var(--teal)">${fmtNum(s.nodes)}</span></div><div class="kg-bar-wrap"><div class="kg-bar-fill" style="background:var(--teal);width:60%"></div></div>` : ''}
|
|
3560
|
+
${s.edges !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Edges</span><span class="kg-stat-val" style="color:var(--sky)">${fmtNum(s.edges)}</span></div><div class="kg-bar-wrap"><div class="kg-bar-fill" style="background:var(--sky);width:78%"></div></div>` : ''}
|
|
3561
|
+
${s.size ? `<div class="kg-stat-row"><span class="kg-stat-key">Size</span><span class="kg-stat-val" style="color:var(--dim)">${fmtBytes(s.size)}</span></div>` : ''}
|
|
3562
|
+
${s.mtime ? `<div class="kg-stat-row"><span class="kg-stat-key">Built</span><span id="po-knowledge-age" data-mtime="${s.mtime}" class="kg-stat-val" style="color:var(--dim)">${fmtAge(s.mtime)}</span></div>` : ''}
|
|
3563
|
+
</div>
|
|
3564
|
+
${e && !e.tooLarge ? `<div class="kg-stat-group">
|
|
3565
|
+
<div class="kg-stat-group-label">ENRICHED</div>
|
|
3566
|
+
${e.pageRankComputed ? '<div class="kg-badge kg-badge-ok" style="margin-bottom:10px;">PAGERANK</div>' : ''}
|
|
3567
|
+
${e.enrichedNodes !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Enriched</span><span class="kg-stat-val" style="color:var(--teal)">${fmtNum(e.enrichedNodes)}</span></div>` : ''}
|
|
3568
|
+
${e.resolvedCallEdges !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Call edges</span><span class="kg-stat-val" style="color:var(--sky)">${fmtNum(e.resolvedCallEdges)}</span></div>` : ''}
|
|
3569
|
+
</div>` : ''}
|
|
3570
|
+
<button class="kg-action-btn" onclick="triggerPalaceGraphBuild()">REBUILD</button>
|
|
3571
|
+
${knowledgeSuffix}`;
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3574
|
+
if (!d.exists || !d.content) {
|
|
3575
|
+
bodyEl.innerHTML = `<div class="kg-report-grid"><div class="kg-card kg-card-wide" style="text-align:center;padding:40px 20px;">
|
|
3576
|
+
<div class="kg-card-title" style="justify-content:center;margin-bottom:12px;"><span class="kg-card-title-icon">🗂</span>NO REPORT GENERATED</div>
|
|
3577
|
+
<div class="kg-card-body" style="text-align:center;">Run <code>npx monomind graphify report</code><br>or click REBUILD to generate a full analysis.</div>
|
|
3578
|
+
</div></div>`;
|
|
3579
|
+
} else {
|
|
3580
|
+
bodyEl.innerHTML = parseGraphifyReport(d.content);
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
let _codeGraphPending = false;
|
|
3585
|
+
let _codeGraphLoaded = false;
|
|
3586
|
+
async function renderPalaceCodeGraph(force = false) {
|
|
3587
|
+
if (_codeGraphPending) return;
|
|
3588
|
+
if (_codeGraphLoaded && !force) return;
|
|
3589
|
+
_codeGraphPending = true;
|
|
3590
|
+
const dir = selectedProjectDir || '';
|
|
3591
|
+
let gd;
|
|
3592
|
+
try {
|
|
3593
|
+
const r = await fetch(`/api/graphify-graph${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
|
|
3594
|
+
gd = r.ok ? await r.json() : null;
|
|
3595
|
+
} catch { gd = null; }
|
|
3596
|
+
_codeGraphPending = false;
|
|
3597
|
+
if ((selectedProjectDir || '') !== dir) return;
|
|
3598
|
+
if (palaceCurrentTab !== 'knowledge') return;
|
|
3599
|
+
const info = document.getElementById('po-kg2-info');
|
|
3600
|
+
if (!gd || !gd.nodes || !gd.nodes.length) {
|
|
3601
|
+
if (info) info.textContent = gd && gd.tooLarge ? 'Graph too large to display' : 'No graph data';
|
|
3602
|
+
return;
|
|
3603
|
+
}
|
|
3604
|
+
kgCodeGraph.init();
|
|
3605
|
+
kgCodeGraph.render(gd, () => { _codeGraphLoaded = true; });
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
window.triggerPalaceGraphBuild = async function() {
|
|
3609
|
+
const statsEl = document.getElementById('po-knowledge-stats');
|
|
3610
|
+
const bodyEl = document.getElementById('po-knowledge-body');
|
|
3611
|
+
if (statsEl) statsEl.innerHTML = '<div style="color:var(--teal);font-size:10px;letter-spacing:0.06em;">BUILDING…</div>';
|
|
3612
|
+
if (bodyEl) bodyEl.innerHTML = '<div style="color:var(--dim);font-size:10px;padding:16px;">Background build started — panel updates when complete.</div>';
|
|
3613
|
+
const dir = selectedProjectDir || '';
|
|
3614
|
+
try {
|
|
3615
|
+
await fetch(`/api/graphify-build${dir ? '?dir=' + encodeURIComponent(dir) : ''}`, { method: 'POST' });
|
|
3616
|
+
let attempts = 0;
|
|
3617
|
+
const poll = setInterval(async () => {
|
|
3618
|
+
attempts++;
|
|
3619
|
+
try {
|
|
3620
|
+
const r = await fetch(`/api/graphify-report${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
|
|
3621
|
+
const d = await r.json();
|
|
3622
|
+
if (d.stats || d.exists) { clearInterval(poll); renderPalaceKnowledge(); _codeGraphLoaded = false; kgCodeGraph.reset(); renderPalaceCodeGraph(); }
|
|
3623
|
+
else if (attempts >= 36) { clearInterval(poll); if (bodyEl) bodyEl.innerHTML = '<div style="color:var(--amber);font-size:10px;">Build timed out — check server logs.</div>'; }
|
|
3624
|
+
} catch {}
|
|
3625
|
+
}, 5000);
|
|
3626
|
+
} catch (e) {
|
|
3627
|
+
if (statsEl) statsEl.innerHTML = '<div style="color:#EF5350;font-size:10px;">Build failed.</div>';
|
|
3628
|
+
if (bodyEl) bodyEl.innerHTML = `<div style="color:#EF5350;font-size:10px;">${escHtml(e.message)}</div>`;
|
|
3629
|
+
}
|
|
3630
|
+
};
|
|
3631
|
+
|
|
3632
|
+
let _palaceSelectedSession = null;
|
|
3633
|
+
|
|
3634
|
+
function renderPalaceSessions() {
|
|
3635
|
+
const sessions = palaceData ? palaceData.sessions || [] : [];
|
|
3636
|
+
const list = document.getElementById('po-sessions-list');
|
|
3637
|
+
if (!list) return;
|
|
3638
|
+
|
|
3639
|
+
if (!sessions.length) {
|
|
3640
|
+
list.innerHTML = '<div style="padding:16px;color:var(--muted);font-size:10px;text-align:center;">NO SESSIONS FOUND</div>';
|
|
3641
|
+
return;
|
|
3642
|
+
}
|
|
3643
|
+
|
|
3644
|
+
let html = `<div class="po-wing-header" style="color:var(--teal)">SESSIONS <span style="color:var(--teal)">${sessions.length}</span></div>`;
|
|
3645
|
+
sessions.forEach((sess, i) => {
|
|
3646
|
+
const isSelected = _palaceSelectedSession && _palaceSelectedSession.file === sess.file;
|
|
3647
|
+
html += `<div class="po-session-item${isSelected ? ' selected' : ''}" onclick="selectPalaceSession(${i})">
|
|
3648
|
+
<span class="live-dot" style="flex-shrink:0;"></span>
|
|
3649
|
+
<span class="po-session-id" title="${escHtml(sess.id || '')}">${escHtml((sess.id || 'unknown').slice(0, 22))}</span>
|
|
3650
|
+
<span class="po-session-meta">${fmtAge(sess.mtime)}</span>
|
|
3651
|
+
<span class="po-session-meta">${fmtBytes(sess.size)}</span>
|
|
3652
|
+
</div>`;
|
|
3653
|
+
});
|
|
3654
|
+
list.innerHTML = html;
|
|
3655
|
+
}
|
|
3656
|
+
|
|
3657
|
+
window.selectPalaceSession = async function(idx) {
|
|
3658
|
+
if (!palaceData) return;
|
|
3659
|
+
const sess = (palaceData.sessions || [])[idx];
|
|
3660
|
+
if (!sess) return;
|
|
3661
|
+
_palaceSelectedSession = sess;
|
|
3662
|
+
renderPalaceSessions();
|
|
3663
|
+
|
|
3664
|
+
const hint = document.getElementById('po-sd-hint');
|
|
3665
|
+
const header = document.getElementById('po-sd-header');
|
|
3666
|
+
const statsBar= document.getElementById('po-sd-stats-bar');
|
|
3667
|
+
const body = document.getElementById('po-sd-body');
|
|
3668
|
+
const timeline= document.getElementById('po-sd-timeline');
|
|
3669
|
+
|
|
3670
|
+
hint.style.display = 'none';
|
|
3671
|
+
header.style.display = 'flex';
|
|
3672
|
+
statsBar.style.display= 'flex';
|
|
3673
|
+
body.style.display = 'grid';
|
|
3674
|
+
timeline.innerHTML = '<div class="placeholder">LOADING…</div>';
|
|
3675
|
+
|
|
3676
|
+
document.getElementById('po-sd-title').textContent = (sess.id || 'unknown').slice(0, 40);
|
|
3677
|
+
document.getElementById('po-sd-subtitle').textContent = sess.file || '';
|
|
3678
|
+
|
|
3679
|
+
try {
|
|
3680
|
+
const res = await fetch(`/api/session?file=${encodeURIComponent(sess.file)}&limit=600`);
|
|
3681
|
+
const { events = [], total = 0, shown = 0, error: apiErr } = await res.json();
|
|
3682
|
+
if (apiErr) throw new Error(apiErr);
|
|
3683
|
+
|
|
3684
|
+
document.getElementById('po-sd-subtitle').textContent = `${sess.id || ''} · ${total} entries · showing last ${shown}`;
|
|
3685
|
+
|
|
3686
|
+
// Stats
|
|
3687
|
+
const userTurns = events.filter(e => e.kind === 'user').length;
|
|
3688
|
+
const toolEvents = events.filter(e => e.kind === 'tool');
|
|
3689
|
+
const agentEvts = toolEvents.filter(e => e.cat === 'agent');
|
|
3690
|
+
const memEvts = toolEvents.filter(e => e.cat === 'memory');
|
|
3691
|
+
document.getElementById('po-sd-stat-turns').textContent = `💬 ${userTurns} turns`;
|
|
3692
|
+
document.getElementById('po-sd-stat-tools').textContent = `🔧 ${toolEvents.length} tools`;
|
|
3693
|
+
document.getElementById('po-sd-stat-agents').textContent = `🤖 ${agentEvts.length} agents`;
|
|
3694
|
+
document.getElementById('po-sd-stat-mem').textContent = `🧠 ${memEvts.length} memory`;
|
|
3695
|
+
|
|
3696
|
+
// Tool breakdown
|
|
3697
|
+
const catCounts = {};
|
|
3698
|
+
for (const e of toolEvents) catCounts[e.cat] = (catCounts[e.cat] || 0) + 1;
|
|
3699
|
+
document.getElementById('po-sd-tool-breakdown').innerHTML =
|
|
3700
|
+
Object.entries(catCounts).sort((a,b)=>b[1]-a[1]).map(([cat, count]) =>
|
|
3701
|
+
`<span class="tool-chip cat-${cat}"><span class="tool-chip-count">${count}</span><span>${CAT_LABELS[cat]||cat}</span></span>`
|
|
3702
|
+
).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
|
|
3703
|
+
|
|
3704
|
+
// Agent tree
|
|
3705
|
+
document.getElementById('po-sd-agent-tree').innerHTML =
|
|
3706
|
+
agentEvts.map(e =>
|
|
3707
|
+
`<div class="agent-node"><div class="agent-node-dot"></div><span style="color:#B078FF;font-size:9px;font-weight:700;margin-right:4px">${e.subagent||'?'}</span><span style="color:var(--muted)">${esc(e.label.replace(/^→\s*/,'').slice(0,40))}</span>${e.background?'<span style="font-size:9px;color:#555;margin-left:auto">bg</span>':''}</div>`
|
|
3708
|
+
).join('') || '<span style="font-size:10px;color:var(--muted)">No agents spawned</span>';
|
|
3709
|
+
|
|
3710
|
+
// Memory ops
|
|
3711
|
+
document.getElementById('po-sd-memory-ops').innerHTML =
|
|
3712
|
+
memEvts.slice(0,20).map(e =>
|
|
3713
|
+
`<div class="memory-op"><span style="color:#FFD700;font-size:9px">${esc(e.name.replace('mcp__monobrain__','').slice(0,20))}</span><span>${esc(e.label.replace(/^mem:/,'').slice(0,30))}</span></div>`
|
|
3714
|
+
).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
|
|
3715
|
+
|
|
3716
|
+
// Timeline — identical logic to renderSessionDetail
|
|
3717
|
+
const frags = [];
|
|
3718
|
+
const usedResultIdx = new Set();
|
|
3719
|
+
for (let i = 0; i < events.length; i++) {
|
|
3720
|
+
const e = events[i];
|
|
3721
|
+
if (e.kind === 'user') {
|
|
3722
|
+
frags.push(`<div class="ev ev-user">${esc(e.text)}</div>`);
|
|
3723
|
+
} else if (e.kind === 'thinking') {
|
|
3724
|
+
frags.push(`<div class="ev ev-thinking">${esc(e.text.slice(0,120))}${e.text.length>120?'…':''}</div>`);
|
|
3725
|
+
} else if (e.kind === 'text') {
|
|
3726
|
+
frags.push(`<div class="ev ev-text">${esc(e.text)}</div>`);
|
|
3727
|
+
} else if (e.kind === 'tool') {
|
|
3728
|
+
if (e.cat === 'agent') {
|
|
3729
|
+
frags.push(`<div class="ev-agent-spawn">
|
|
3730
|
+
<div class="ev-agent-spawn-header">
|
|
3731
|
+
<span class="ev-agent-type">${e.subagent||'AGENT'}</span>
|
|
3732
|
+
<span class="ev-agent-label">${esc(e.label.replace(/^→\s*/,''))}</span>
|
|
3733
|
+
${e.background?'<span class="ev-agent-bg">⬡ background</span>':''}
|
|
3734
|
+
${e.ts?`<span class="ev-tool-ts">${fmtTime(e.ts)}</span>`:''}
|
|
3735
|
+
</div>
|
|
3736
|
+
</div>`);
|
|
3737
|
+
} else {
|
|
3738
|
+
let resultHtml = '';
|
|
3739
|
+
for (let j = i+1; j < Math.min(i+8, events.length); j++) {
|
|
3740
|
+
const r = events[j];
|
|
3741
|
+
if (r.kind === 'tool_result' && r.tool_use_id === e.id && !usedResultIdx.has(j)) {
|
|
3742
|
+
usedResultIdx.add(j);
|
|
3743
|
+
resultHtml = `<div class="ev-tool-result${r.isError?' error':''}">${esc(r.text.slice(0,300))}</div>`;
|
|
3744
|
+
break;
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
frags.push(`<div class="ev-tool">
|
|
3748
|
+
<span class="ev-tool-badge cat-${e.cat}">${CAT_LABELS[e.cat]||e.cat}</span>
|
|
3749
|
+
<span class="ev-tool-label" title="${esc(e.label)}">${esc(e.label)}</span>
|
|
3750
|
+
${e.ts?`<span class="ev-tool-ts">${fmtTime(e.ts)}</span>`:''}
|
|
3751
|
+
</div>${resultHtml}`);
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
timeline.innerHTML = frags.join('');
|
|
3756
|
+
timeline.scrollTop = timeline.scrollHeight;
|
|
3757
|
+
} catch (err) {
|
|
3758
|
+
timeline.innerHTML = `<div class="placeholder" style="color:#EF5350">ERROR: ${esc(err.message)}</div>`;
|
|
3759
|
+
}
|
|
3760
|
+
};
|
|
3761
|
+
|
|
3762
|
+
window.filterDrawers = function(query) {
|
|
3763
|
+
if (!palaceData) return;
|
|
3764
|
+
renderMemories(query.toLowerCase());
|
|
3765
|
+
};
|
|
3766
|
+
|
|
3767
|
+
// Store filtered memories so onclick can reference by index
|
|
3768
|
+
let _palaceFilteredDrawers = [];
|
|
3769
|
+
|
|
3770
|
+
const MEMORY_TYPE_COLORS = { user: '#7B8EFF', feedback: '#FFB347', project: '#00E5C8', reference: '#B47BFF', handoff: '#FF6B9D' };
|
|
3771
|
+
|
|
3772
|
+
function renderMemories(filter) {
|
|
3773
|
+
const memories = palaceData ? palaceData.memories || [] : [];
|
|
3774
|
+
const list = document.getElementById('po-drawer-list');
|
|
3775
|
+
if (!list) return;
|
|
3776
|
+
|
|
3777
|
+
_palaceFilteredDrawers = filter ? memories.filter(m =>
|
|
3778
|
+
(m.name||'').toLowerCase().includes(filter) ||
|
|
3779
|
+
(m.description||'').toLowerCase().includes(filter) ||
|
|
3780
|
+
(m.type||'').toLowerCase().includes(filter) ||
|
|
3781
|
+
(m.body||'').toLowerCase().includes(filter)
|
|
3782
|
+
) : memories;
|
|
3783
|
+
|
|
3784
|
+
// Group by type
|
|
3785
|
+
const byType = {};
|
|
3786
|
+
_palaceFilteredDrawers.forEach((m, idx) => {
|
|
3787
|
+
const t = m.type || 'project';
|
|
3788
|
+
if (!byType[t]) byType[t] = [];
|
|
3789
|
+
byType[t].push({ m, idx });
|
|
3790
|
+
});
|
|
3791
|
+
|
|
3792
|
+
const typeOrder = ['handoff', 'user', 'feedback', 'project', 'reference'];
|
|
3793
|
+
const sorted = [...typeOrder.filter(t => byType[t]), ...Object.keys(byType).filter(t => !typeOrder.includes(t))];
|
|
3794
|
+
|
|
3795
|
+
let html = '';
|
|
3796
|
+
for (const type of sorted) {
|
|
3797
|
+
const items = byType[type] || [];
|
|
3798
|
+
const color = MEMORY_TYPE_COLORS[type] || 'var(--muted)';
|
|
3799
|
+
html += `<div class="po-wing-header" style="color:${color}">${type.toUpperCase()} <span style="color:var(--teal)">${items.length}</span></div>`;
|
|
3800
|
+
for (const { m, idx } of items) {
|
|
3801
|
+
const isSelected = palaceSelectedDrawer && palaceSelectedDrawer.filename === m.filename;
|
|
3802
|
+
html += `<div class="po-drawer-item${isSelected ? ' selected' : ''}" onclick="selectDrawer(${idx})">
|
|
3803
|
+
<div class="po-drawer-wing">${escHtml(m.name)}</div>
|
|
3804
|
+
${m.description ? `<div class="po-drawer-room">${escHtml(m.description)}</div>` : ''}
|
|
3805
|
+
</div>`;
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
if (!_palaceFilteredDrawers.length) html = '<div style="padding:16px;font-size:10px;color:var(--dim);text-align:center;">NO MEMORIES</div>';
|
|
3809
|
+
list.innerHTML = html;
|
|
3810
|
+
}
|
|
3811
|
+
|
|
3812
|
+
window.selectDrawer = function(idx) {
|
|
3813
|
+
const m = _palaceFilteredDrawers[idx];
|
|
3814
|
+
if (!m) return;
|
|
3815
|
+
palaceSelectedDrawer = m;
|
|
3816
|
+
renderMemories(document.getElementById('po-search')?.value?.toLowerCase() || '');
|
|
3817
|
+
renderMemoryDetail(m);
|
|
3818
|
+
};
|
|
3819
|
+
|
|
3820
|
+
function renderMemoryDetail(m) {
|
|
3821
|
+
const el = document.getElementById('po-drawer-detail');
|
|
3822
|
+
if (!el) return;
|
|
3823
|
+
const ts = m.mtime ? new Date(m.mtime).toLocaleString() : '—';
|
|
3824
|
+
const color = MEMORY_TYPE_COLORS[m.type] || 'var(--muted)';
|
|
3825
|
+
// Simple markdown-lite: bold **text**, headers ##, bullet points
|
|
3826
|
+
const renderBody = text => text.split('\n').map(line => {
|
|
3827
|
+
line = escHtml(line);
|
|
3828
|
+
line = line.replace(/\*\*(.+?)\*\*/g, '<strong style="color:var(--text)">$1</strong>');
|
|
3829
|
+
if (line.startsWith('## ')) return `<div style="color:var(--teal);font-size:10px;margin:10px 0 4px;letter-spacing:0.08em">${line.slice(3)}</div>`;
|
|
3830
|
+
if (line.startsWith('# ')) return `<div style="color:var(--teal);font-size:11px;margin:10px 0 4px;letter-spacing:0.08em">${line.slice(2)}</div>`;
|
|
3831
|
+
if (line.startsWith('- ')) return `<div style="padding-left:12px;margin:2px 0">· ${line.slice(2)}</div>`;
|
|
3832
|
+
if (line.trim() === '') return '<div style="height:6px"></div>';
|
|
3833
|
+
return `<div style="margin:2px 0">${line}</div>`;
|
|
3834
|
+
}).join('');
|
|
3835
|
+
el.innerHTML = `
|
|
3836
|
+
<div style="display:flex;align-items:center;gap:10px;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--border)">
|
|
3837
|
+
<span style="color:${color};font-size:9px;font-family:monospace;background:${color}22;padding:2px 8px;border-radius:3px;letter-spacing:0.08em">${escHtml(m.type||'project').toUpperCase()}</span>
|
|
3838
|
+
<span style="color:var(--text);font-size:12px;font-family:monospace">${escHtml(m.name)}</span>
|
|
3839
|
+
</div>
|
|
3840
|
+
${m.description ? `<div class="po-detail-field"><div class="po-detail-label">DESCRIPTION</div><div class="po-detail-value" style="color:var(--muted)">${escHtml(m.description)}</div></div>` : ''}
|
|
3841
|
+
<div class="po-detail-field"><div class="po-detail-label">CONTENT</div>
|
|
3842
|
+
<div class="po-detail-value" style="font-size:10px;line-height:1.6;max-height:none">${renderBody(m.body||'')}</div>
|
|
3843
|
+
</div>
|
|
3844
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px">
|
|
3845
|
+
<div class="po-detail-field"><div class="po-detail-label">FILE</div><div class="po-detail-value mono" style="font-size:9px;color:var(--dim)">${escHtml(m.filename||'—')}</div></div>
|
|
3846
|
+
<div class="po-detail-field"><div class="po-detail-label">MODIFIED</div><div class="po-detail-value mono" style="font-size:9px">${escHtml(ts)}</div></div>
|
|
3847
|
+
</div>
|
|
3848
|
+
<div class="po-action-bar">
|
|
3849
|
+
<button class="po-btn po-btn-edit" onclick="editMemory(palaceSelectedDrawer)">EDIT</button>
|
|
3850
|
+
<button class="po-btn po-btn-delete" onclick="deleteMemory(palaceSelectedDrawer)">DELETE</button>
|
|
3851
|
+
</div>
|
|
3852
|
+
`;
|
|
3853
|
+
}
|
|
3854
|
+
|
|
3855
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3856
|
+
// MEMORY EDIT / DELETE / NEW
|
|
3857
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
3858
|
+
|
|
3859
|
+
const MEMORY_TEMPLATES = {
|
|
3860
|
+
user: {
|
|
3861
|
+
label: 'User',
|
|
3862
|
+
color: '#7B8EFF',
|
|
3863
|
+
description: 'Role, goals, knowledge level',
|
|
3864
|
+
scaffold: `---
|
|
3865
|
+
name: user_role
|
|
3866
|
+
description: <one-line summary of user role and context>
|
|
3867
|
+
type: user
|
|
3868
|
+
---
|
|
3869
|
+
|
|
3870
|
+
<Role and experience description. What does the user know well? What are they new to?>
|
|
3871
|
+
Frame explanations accordingly.`
|
|
3872
|
+
},
|
|
3873
|
+
feedback: {
|
|
3874
|
+
label: 'Feedback',
|
|
3875
|
+
color: '#FFB347',
|
|
3876
|
+
description: 'How to approach work — corrections and validations',
|
|
3877
|
+
scaffold: `---
|
|
3878
|
+
name: feedback_<topic>
|
|
3879
|
+
description: <one-line rule that triggers on lookup>
|
|
3880
|
+
type: feedback
|
|
3881
|
+
---
|
|
3882
|
+
|
|
3883
|
+
<The rule itself — what to do or avoid.>
|
|
3884
|
+
|
|
3885
|
+
**Why:** <Reason the user gave — past incident, strong preference, etc.>
|
|
3886
|
+
|
|
3887
|
+
**How to apply:** <When does this kick in? What edge cases does it cover?>`
|
|
3888
|
+
},
|
|
3889
|
+
project: {
|
|
3890
|
+
label: 'Project',
|
|
3891
|
+
color: '#00E5C8',
|
|
3892
|
+
description: 'Ongoing work context, decisions, deadlines',
|
|
3893
|
+
scaffold: `---
|
|
3894
|
+
name: project_<initiative>
|
|
3895
|
+
description: <one-line fact about the project decision or constraint>
|
|
3896
|
+
type: project
|
|
3897
|
+
---
|
|
3898
|
+
|
|
3899
|
+
<The fact or decision — what is happening and what was decided.>
|
|
3900
|
+
|
|
3901
|
+
**Why:** <Motivation — constraint, deadline, stakeholder ask, compliance issue.>
|
|
3902
|
+
|
|
3903
|
+
**How to apply:** <How should this shape future suggestions and decisions?>`
|
|
3904
|
+
},
|
|
3905
|
+
reference: {
|
|
3906
|
+
label: 'Reference',
|
|
3907
|
+
color: '#B47BFF',
|
|
3908
|
+
description: 'Pointers to external resources',
|
|
3909
|
+
scaffold: `---
|
|
3910
|
+
name: reference_<resource>
|
|
3911
|
+
description: <what this resource contains and when to use it>
|
|
3912
|
+
type: reference
|
|
3913
|
+
---
|
|
3914
|
+
|
|
3915
|
+
<Resource name and location (URL, project name, channel, etc.)>
|
|
3916
|
+
|
|
3917
|
+
Use this when: <specific scenarios where this reference is relevant>.`
|
|
3918
|
+
}
|
|
3919
|
+
};
|
|
3920
|
+
|
|
3921
|
+
let _editingFilename = null;
|
|
3922
|
+
let _editingIsNew = false;
|
|
3923
|
+
|
|
3924
|
+
window.editMemory = function(m) {
|
|
3925
|
+
if (!m) return;
|
|
3926
|
+
_editingFilename = m.filename;
|
|
3927
|
+
_editingIsNew = false;
|
|
3928
|
+
// Reconstruct full file content from parsed fields
|
|
3929
|
+
const body = `---\nname: ${m.name || ''}\ndescription: ${m.description || ''}\ntype: ${m.type || 'project'}\n---\n\n${m.body || ''}`;
|
|
3930
|
+
document.getElementById('po-edit-title').textContent = 'EDIT — ' + (m.name || m.filename);
|
|
3931
|
+
document.getElementById('po-edit-textarea').value = body;
|
|
3932
|
+
document.getElementById('po-edit-status').textContent = '';
|
|
3933
|
+
document.getElementById('po-edit-modal').classList.add('open');
|
|
3934
|
+
setTimeout(() => document.getElementById('po-edit-textarea').focus(), 50);
|
|
3935
|
+
};
|
|
3936
|
+
|
|
3937
|
+
window.closeEditModal = function() {
|
|
3938
|
+
document.getElementById('po-edit-modal').classList.remove('open');
|
|
3939
|
+
_editingFilename = null;
|
|
3940
|
+
_editingIsNew = false;
|
|
3941
|
+
};
|
|
3942
|
+
|
|
3943
|
+
window.saveEditedMemory = async function() {
|
|
3944
|
+
const content = document.getElementById('po-edit-textarea').value;
|
|
3945
|
+
const statusEl = document.getElementById('po-edit-status');
|
|
3946
|
+
|
|
3947
|
+
if (_editingIsNew) {
|
|
3948
|
+
// Derive filename from name field in frontmatter
|
|
3949
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
3950
|
+
const rawName = nameMatch ? nameMatch[1].trim() : 'memory_' + Date.now();
|
|
3951
|
+
_editingFilename = rawName.replace(/[^a-z0-9_-]/gi, '_').toLowerCase() + '.md';
|
|
3952
|
+
}
|
|
3953
|
+
|
|
3954
|
+
if (!_editingFilename) { statusEl.textContent = 'No filename'; return; }
|
|
3955
|
+
|
|
3956
|
+
statusEl.textContent = 'Saving…';
|
|
3957
|
+
try {
|
|
3958
|
+
const qs = dir ? `?dir=${encodeURIComponent(dir)}` : '';
|
|
3959
|
+
const resp = await fetch(`/api/memory-file${qs}`, {
|
|
3960
|
+
method: 'PUT',
|
|
3961
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3962
|
+
body: JSON.stringify({ filename: _editingFilename, content })
|
|
3963
|
+
});
|
|
3964
|
+
const data = await resp.json();
|
|
3965
|
+
if (!resp.ok || !data.ok) throw new Error(data.error || 'Failed');
|
|
3966
|
+
statusEl.textContent = 'Saved ✓';
|
|
3967
|
+
setTimeout(() => {
|
|
3968
|
+
closeEditModal();
|
|
3969
|
+
loadPalaceData().then(() => renderMemories());
|
|
3970
|
+
}, 600);
|
|
3971
|
+
} catch (err) {
|
|
3972
|
+
statusEl.textContent = 'Error: ' + err.message;
|
|
3973
|
+
}
|
|
3974
|
+
};
|
|
3975
|
+
|
|
3976
|
+
window.deleteMemory = async function(m) {
|
|
3977
|
+
if (!m || !m.filename) return;
|
|
3978
|
+
if (!confirm(`Delete memory "${m.name || m.filename}"?\n\nThis cannot be undone.`)) return;
|
|
3979
|
+
try {
|
|
3980
|
+
const qs = dir ? `?dir=${encodeURIComponent(dir)}` : '';
|
|
3981
|
+
const resp = await fetch(`/api/memory-file${qs}`, {
|
|
3982
|
+
method: 'DELETE',
|
|
3983
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3984
|
+
body: JSON.stringify({ filename: m.filename })
|
|
3985
|
+
});
|
|
3986
|
+
const data = await resp.json();
|
|
3987
|
+
if (!resp.ok || !data.ok) throw new Error(data.error || 'Failed');
|
|
3988
|
+
palaceSelectedDrawer = null;
|
|
3989
|
+
document.getElementById('po-drawer-detail').innerHTML = '<div class="po-select-hint">SELECT A MEMORY</div>';
|
|
3990
|
+
loadPalaceData().then(() => renderMemories());
|
|
3991
|
+
} catch (err) {
|
|
3992
|
+
alert('Delete failed: ' + err.message);
|
|
3993
|
+
}
|
|
3994
|
+
};
|
|
3995
|
+
|
|
3996
|
+
window.openNewMemory = function() {
|
|
3997
|
+
const list = document.getElementById('po-tpl-list');
|
|
3998
|
+
list.innerHTML = Object.entries(MEMORY_TEMPLATES).map(([key, t]) => `
|
|
3999
|
+
<div class="po-tpl-option" onclick="selectTemplate('${key}')">
|
|
4000
|
+
<div class="po-tpl-name" style="color:${t.color}">${t.label.toUpperCase()}</div>
|
|
4001
|
+
<div class="po-tpl-desc">${t.description}</div>
|
|
4002
|
+
</div>`).join('');
|
|
4003
|
+
document.getElementById('po-tpl-picker').classList.add('open');
|
|
4004
|
+
};
|
|
4005
|
+
|
|
4006
|
+
window.closeTplPicker = function() {
|
|
4007
|
+
document.getElementById('po-tpl-picker').classList.remove('open');
|
|
4008
|
+
};
|
|
4009
|
+
|
|
4010
|
+
window.selectTemplate = function(type) {
|
|
4011
|
+
closeTplPicker();
|
|
4012
|
+
const t = MEMORY_TEMPLATES[type];
|
|
4013
|
+
if (!t) return;
|
|
4014
|
+
_editingFilename = null;
|
|
4015
|
+
_editingIsNew = true;
|
|
4016
|
+
document.getElementById('po-edit-title').textContent = 'NEW ' + t.label.toUpperCase() + ' MEMORY';
|
|
4017
|
+
document.getElementById('po-edit-textarea').value = t.scaffold;
|
|
4018
|
+
document.getElementById('po-edit-status').textContent = '';
|
|
4019
|
+
document.getElementById('po-edit-modal').classList.add('open');
|
|
4020
|
+
setTimeout(() => document.getElementById('po-edit-textarea').focus(), 50);
|
|
4021
|
+
};
|
|
4022
|
+
|
|
4023
|
+
// Agent Graph renderer — sessions (inner ring, teal) + agent types (outer ring, amber)
|
|
4024
|
+
const kgGraph = (function() {
|
|
4025
|
+
let canvas, ctx, nodes = [], edges = [], animRAF = null, showLabels = true;
|
|
4026
|
+
let mouseX = -999, mouseY = -999, hoveredNode = null;
|
|
4027
|
+
|
|
4028
|
+
function init() {
|
|
4029
|
+
canvas = document.getElementById('po-kg-canvas');
|
|
4030
|
+
if (!canvas) return;
|
|
4031
|
+
ctx = canvas.getContext('2d');
|
|
4032
|
+
canvas.onmousemove = e => {
|
|
4033
|
+
const r = canvas.getBoundingClientRect();
|
|
4034
|
+
mouseX = e.clientX - r.left;
|
|
4035
|
+
mouseY = e.clientY - r.top;
|
|
4036
|
+
};
|
|
4037
|
+
canvas.onmouseleave = () => { mouseX = -999; mouseY = -999; hoveredNode = null; };
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
function render(graphData) {
|
|
4041
|
+
if (!canvas) init();
|
|
4042
|
+
if (!canvas) return;
|
|
4043
|
+
if (!graphData || !graphData.nodes) return;
|
|
4044
|
+
|
|
4045
|
+
const sessionNodes = graphData.nodes.filter(n => n.type === 'session')
|
|
4046
|
+
.sort((a, b) => (b.mtime || 0) - (a.mtime || 0));
|
|
4047
|
+
const agentNodes = graphData.nodes.filter(n => n.type === 'agenttype')
|
|
4048
|
+
.sort((a, b) => (b.totalSpawns || 0) - (a.totalSpawns || 0));
|
|
4049
|
+
|
|
4050
|
+
canvas.width = canvas.offsetWidth;
|
|
4051
|
+
canvas.height = canvas.offsetHeight;
|
|
4052
|
+
const W = canvas.width, H = canvas.height;
|
|
4053
|
+
const cx = W / 2, cy = H / 2;
|
|
4054
|
+
const innerR = Math.min(W, H) * 0.22;
|
|
4055
|
+
const outerR = Math.min(W, H) * 0.40;
|
|
4056
|
+
|
|
4057
|
+
const maxTools = Math.max(...sessionNodes.map(n => n.totalTools || 0), 1);
|
|
4058
|
+
const maxSpawns = Math.max(...agentNodes.map(n => n.totalSpawns || 0), 1);
|
|
4059
|
+
|
|
4060
|
+
// Session nodes on inner ring, sized by tool count
|
|
4061
|
+
sessionNodes.forEach((n, i) => {
|
|
4062
|
+
const angle = (i / Math.max(sessionNodes.length, 1)) * Math.PI * 2 - Math.PI / 2;
|
|
4063
|
+
n._x = cx + Math.cos(angle) * innerR;
|
|
4064
|
+
n._y = cy + Math.sin(angle) * innerR;
|
|
4065
|
+
n._size = 4 + (n.totalTools / maxTools) * 9;
|
|
4066
|
+
});
|
|
4067
|
+
|
|
4068
|
+
// Agent type nodes on outer ring, sized by spawn count
|
|
4069
|
+
agentNodes.forEach((n, i) => {
|
|
4070
|
+
const angle = (i / Math.max(agentNodes.length, 1)) * Math.PI * 2 - Math.PI / 2;
|
|
4071
|
+
n._x = cx + Math.cos(angle) * outerR;
|
|
4072
|
+
n._y = cy + Math.sin(angle) * outerR;
|
|
4073
|
+
n._size = 3 + (n.totalSpawns / maxSpawns) * 7;
|
|
4074
|
+
});
|
|
4075
|
+
|
|
4076
|
+
nodes = [...sessionNodes, ...agentNodes];
|
|
4077
|
+
const nodeIds = new Set(nodes.map(n => n.id));
|
|
4078
|
+
edges = graphData.edges.filter(e => nodeIds.has(e.source) && nodeIds.has(e.target));
|
|
4079
|
+
|
|
4080
|
+
const totalSpawns = agentNodes.reduce((s, n) => s + (n.totalSpawns || 0), 0);
|
|
4081
|
+
const info = document.getElementById('po-graph-info');
|
|
4082
|
+
if (info) info.textContent = `${sessionNodes.length} sessions · ${agentNodes.length} agent types · ${totalSpawns} total spawns`;
|
|
4083
|
+
|
|
4084
|
+
if (animRAF) cancelAnimationFrame(animRAF);
|
|
4085
|
+
draw();
|
|
4086
|
+
animRAF = requestAnimationFrame(function loop() {
|
|
4087
|
+
if (palaceCurrentTab !== 'graph') { animRAF = null; return; }
|
|
4088
|
+
const prev = hoveredNode;
|
|
4089
|
+
hoveredNode = null;
|
|
4090
|
+
for (const n of nodes) {
|
|
4091
|
+
const dx = n._x - mouseX, dy = n._y - mouseY;
|
|
4092
|
+
const r = (n._size || 5) + 4;
|
|
4093
|
+
if (dx*dx + dy*dy < r*r) { hoveredNode = n; break; }
|
|
4094
|
+
}
|
|
4095
|
+
if (hoveredNode !== prev) draw();
|
|
4096
|
+
animRAF = requestAnimationFrame(loop);
|
|
4097
|
+
});
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
function draw() {
|
|
4101
|
+
if (!canvas || !ctx) return;
|
|
4102
|
+
const W = canvas.width, H = canvas.height;
|
|
4103
|
+
if (!W || !H) return;
|
|
4104
|
+
ctx.clearRect(0, 0, W, H);
|
|
4105
|
+
const cx = W/2, cy = H/2;
|
|
4106
|
+
const innerR = Math.min(W,H)*0.22, outerR = Math.min(W,H)*0.40;
|
|
4107
|
+
|
|
4108
|
+
// Guide rings
|
|
4109
|
+
ctx.beginPath(); ctx.arc(cx, cy, innerR, 0, Math.PI*2);
|
|
4110
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.06)'; ctx.lineWidth = 1; ctx.stroke();
|
|
4111
|
+
ctx.beginPath(); ctx.arc(cx, cy, outerR, 0, Math.PI*2);
|
|
4112
|
+
ctx.strokeStyle = 'rgba(255,179,71,0.06)'; ctx.lineWidth = 1; ctx.stroke();
|
|
4113
|
+
|
|
4114
|
+
// Ring labels at top
|
|
4115
|
+
ctx.font = '8px monospace'; ctx.textAlign = 'center';
|
|
4116
|
+
ctx.fillStyle = 'rgba(0,229,200,0.3)';
|
|
4117
|
+
ctx.fillText('SESSIONS', cx, cy - innerR - 6);
|
|
4118
|
+
ctx.fillStyle = 'rgba(255,179,71,0.3)';
|
|
4119
|
+
ctx.fillText('AGENT TYPES', cx, cy - outerR - 6);
|
|
4120
|
+
|
|
4121
|
+
// Edges
|
|
4122
|
+
const maxW = Math.max(...edges.map(e => e.weight || 1), 1);
|
|
4123
|
+
const idToNode = {};
|
|
4124
|
+
for (const n of nodes) idToNode[n.id] = n;
|
|
4125
|
+
for (const e of edges) {
|
|
4126
|
+
const a = idToNode[e.source], b = idToNode[e.target];
|
|
4127
|
+
if (!a || !b) continue;
|
|
4128
|
+
const hl = hoveredNode && (hoveredNode.id === e.source || hoveredNode.id === e.target);
|
|
4129
|
+
const alpha = 0.05 + (e.weight / maxW) * 0.22;
|
|
4130
|
+
ctx.beginPath(); ctx.moveTo(a._x, a._y); ctx.lineTo(b._x, b._y);
|
|
4131
|
+
ctx.strokeStyle = hl ? 'rgba(0,229,200,0.65)' : `rgba(120,128,168,${alpha.toFixed(2)})`;
|
|
4132
|
+
ctx.lineWidth = hl ? Math.max(1, (e.weight / maxW) * 3) : Math.max(0.4, (e.weight / maxW) * 1.5);
|
|
4133
|
+
ctx.stroke();
|
|
4134
|
+
if (showLabels && hl) {
|
|
4135
|
+
ctx.font = '8px monospace'; ctx.fillStyle = 'rgba(0,229,200,0.9)'; ctx.textAlign = 'center';
|
|
4136
|
+
ctx.fillText('×' + e.label, (a._x+b._x)/2, (a._y+b._y)/2 - 4);
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
// Nodes
|
|
4141
|
+
for (const n of nodes) {
|
|
4142
|
+
const isHov = hoveredNode && hoveredNode.id === n.id;
|
|
4143
|
+
const isSession = n.type === 'session';
|
|
4144
|
+
const r = (n._size || 5) + (isHov ? 2 : 0);
|
|
4145
|
+
if (isHov) { ctx.shadowBlur = 18; ctx.shadowColor = isSession ? '#00E5C8' : '#FFB347'; }
|
|
4146
|
+
ctx.beginPath(); ctx.arc(n._x, n._y, r, 0, Math.PI*2);
|
|
4147
|
+
ctx.fillStyle = isSession
|
|
4148
|
+
? (isHov ? '#00E5C8' : 'rgba(0,229,200,0.82)')
|
|
4149
|
+
: (isHov ? '#FFB347' : 'rgba(255,179,71,0.78)');
|
|
4150
|
+
ctx.fill(); ctx.shadowBlur = 0;
|
|
4151
|
+
if (showLabels) {
|
|
4152
|
+
const label = (n.label || n.id).length > 18 ? (n.label || n.id).slice(0, 16) + '…' : (n.label || n.id);
|
|
4153
|
+
ctx.font = isHov ? '10px monospace' : '8px monospace';
|
|
4154
|
+
ctx.fillStyle = isHov ? 'rgba(255,255,255,0.95)'
|
|
4155
|
+
: (isSession ? 'rgba(0,229,200,0.65)' : 'rgba(255,179,71,0.6)');
|
|
4156
|
+
ctx.textAlign = 'center';
|
|
4157
|
+
ctx.fillText(label, n._x, n._y + r + 11);
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
|
|
4161
|
+
// Tooltip
|
|
4162
|
+
if (hoveredNode) {
|
|
4163
|
+
const n = hoveredNode;
|
|
4164
|
+
const isSession = n.type === 'session';
|
|
4165
|
+
const lines = [isSession ? n.label + ' (session)' : n.label + ' (agent type)'];
|
|
4166
|
+
if (isSession) {
|
|
4167
|
+
lines.push(`${n.turns || 0} turns · ${n.totalTools || 0} tools · $${(n.cost || 0).toFixed(3)}`);
|
|
4168
|
+
const ts = n.mtime ? new Date(n.mtime).toLocaleDateString() : '';
|
|
4169
|
+
if (ts) lines.push(ts);
|
|
4170
|
+
const spawned = Object.entries(n.agentSpawns || {}).sort((a,b) => b[1]-a[1]).slice(0, 5);
|
|
4171
|
+
spawned.forEach(([k,v]) => lines.push(`→ ${k.slice(0,22)} ×${v}`));
|
|
4172
|
+
} else {
|
|
4173
|
+
lines.push(`${n.totalSpawns} total spawns`);
|
|
4174
|
+
const ne = edges.filter(e => e.source === n.id || e.target === n.id).slice(0, 5);
|
|
4175
|
+
ne.forEach(e => {
|
|
4176
|
+
const other = e.source === n.id ? e.target : e.source;
|
|
4177
|
+
lines.push(`${other.slice(0, 8)}… ×${e.weight}`);
|
|
4178
|
+
});
|
|
4179
|
+
}
|
|
4180
|
+
const tw = 290, th = lines.length * 14 + 16;
|
|
4181
|
+
let tx = n._x + 14, ty = n._y - th / 2;
|
|
4182
|
+
if (tx + tw > W - 4) tx = n._x - tw - 14;
|
|
4183
|
+
if (ty < 4) ty = 4;
|
|
4184
|
+
if (ty + th > H - 4) ty = H - th - 4;
|
|
4185
|
+
ctx.fillStyle = 'rgba(7,8,15,0.95)'; ctx.strokeStyle = 'rgba(0,229,200,0.28)'; ctx.lineWidth = 1;
|
|
4186
|
+
roundRect(ctx, tx, ty, tw, th, 4); ctx.fill(); ctx.stroke();
|
|
4187
|
+
ctx.font = '9px monospace'; ctx.textAlign = 'left';
|
|
4188
|
+
lines.forEach((l, i) => {
|
|
4189
|
+
ctx.fillStyle = i === 0 ? 'rgba(255,255,255,0.92)'
|
|
4190
|
+
: i === 1 ? (isSession ? 'rgba(0,229,200,0.65)' : 'rgba(255,179,71,0.65)')
|
|
4191
|
+
: 'rgba(212,212,232,0.8)';
|
|
4192
|
+
ctx.fillText(l, tx + 8, ty + 13 + i * 14);
|
|
4193
|
+
});
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
|
|
4197
|
+
function roundRect(c, x, y, w, h, r) {
|
|
4198
|
+
c.beginPath();
|
|
4199
|
+
c.moveTo(x+r,y); c.lineTo(x+w-r,y); c.quadraticCurveTo(x+w,y,x+w,y+r);
|
|
4200
|
+
c.lineTo(x+w,y+h-r); c.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
|
|
4201
|
+
c.lineTo(x+r,y+h); c.quadraticCurveTo(x,y+h,x,y+h-r);
|
|
4202
|
+
c.lineTo(x,y+r); c.quadraticCurveTo(x,y,x+r,y);
|
|
4203
|
+
c.closePath();
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
function stop() { if (animRAF) { cancelAnimationFrame(animRAF); animRAF = null; } }
|
|
4207
|
+
function toggleLabels(v) { showLabels = v; draw(); }
|
|
4208
|
+
|
|
4209
|
+
return { init, render, stop, toggleLabels };
|
|
4210
|
+
})();
|
|
4211
|
+
|
|
4212
|
+
// ══════════════════ CODE KNOWLEDGE GRAPH — force-directed ══════════════════
|
|
4213
|
+
const kgCodeGraph = (function() {
|
|
4214
|
+
let canvas, ctx, simNodes = [], edges = [], animRAF = null, showLabels = true;
|
|
4215
|
+
let mouseX = -999, mouseY = -999, hoveredNode = null;
|
|
4216
|
+
let W = 0, H = 0, simIdMap = {};
|
|
4217
|
+
|
|
4218
|
+
const TYPE_COLOR = {
|
|
4219
|
+
file: '#6BA3FF', function: '#00E5C8', class: '#FFB347',
|
|
4220
|
+
interface: '#87CEEB', type: '#C39BD3', method: '#7EC8A4',
|
|
4221
|
+
};
|
|
4222
|
+
const DEFAULT_COLOR = '#8890A8';
|
|
4223
|
+
|
|
4224
|
+
function nodeColor(n) { return TYPE_COLOR[n.type] || DEFAULT_COLOR; }
|
|
4225
|
+
|
|
4226
|
+
function init() {
|
|
4227
|
+
canvas = document.getElementById('po-kg2-canvas');
|
|
4228
|
+
if (!canvas) return;
|
|
4229
|
+
ctx = canvas.getContext('2d');
|
|
4230
|
+
canvas.onmousemove = e => {
|
|
4231
|
+
const r = canvas.getBoundingClientRect();
|
|
4232
|
+
mouseX = e.clientX - r.left; mouseY = e.clientY - r.top;
|
|
4233
|
+
};
|
|
4234
|
+
canvas.onmouseleave = () => { mouseX = -999; mouseY = -999; hoveredNode = null; };
|
|
4235
|
+
}
|
|
4236
|
+
|
|
4237
|
+
function render(graphData, onFirstDraw) {
|
|
4238
|
+
if (!canvas) init();
|
|
4239
|
+
if (!canvas || !graphData || !graphData.nodes || !graphData.nodes.length) return;
|
|
4240
|
+
W = canvas.offsetWidth; H = canvas.offsetHeight;
|
|
4241
|
+
if (!W || !H) {
|
|
4242
|
+
if (palaceCurrentTab === 'knowledge') {
|
|
4243
|
+
if (animRAF) cancelAnimationFrame(animRAF);
|
|
4244
|
+
animRAF = requestAnimationFrame(() => render(graphData, onFirstDraw));
|
|
4245
|
+
}
|
|
4246
|
+
return;
|
|
4247
|
+
}
|
|
4248
|
+
canvas.width = W; canvas.height = H;
|
|
4249
|
+
const maxDeg = Math.max(...graphData.nodes.map(n => n.degree || 0), 1);
|
|
4250
|
+
simNodes = graphData.nodes.map(n => ({
|
|
4251
|
+
...n, _size: 3 + ((n.degree || 0) / maxDeg) * 11,
|
|
4252
|
+
_x: W / 2 + (Math.random() - 0.5) * W * 0.6,
|
|
4253
|
+
_y: H / 2 + (Math.random() - 0.5) * H * 0.6,
|
|
4254
|
+
_vx: 0, _vy: 0,
|
|
4255
|
+
}));
|
|
4256
|
+
edges = graphData.edges || [];
|
|
4257
|
+
simIdMap = {}; for (const n of simNodes) simIdMap[n.id] = n;
|
|
4258
|
+
for (let i = 0; i < 100; i++) tick();
|
|
4259
|
+
const info = document.getElementById('po-kg2-info');
|
|
4260
|
+
if (info) info.textContent = `${simNodes.length} nodes · ${edges.length} edges`;
|
|
4261
|
+
if (animRAF) cancelAnimationFrame(animRAF);
|
|
4262
|
+
let frame = 0;
|
|
4263
|
+
animRAF = requestAnimationFrame(function loop() {
|
|
4264
|
+
if (palaceCurrentTab !== 'knowledge') { animRAF = null; return; }
|
|
4265
|
+
if (frame < 250) { tick(); frame++; }
|
|
4266
|
+
const prev = hoveredNode;
|
|
4267
|
+
hoveredNode = null;
|
|
4268
|
+
for (const n of simNodes) {
|
|
4269
|
+
const dx = n._x - mouseX, dy = n._y - mouseY;
|
|
4270
|
+
if (dx*dx + dy*dy < (n._size + 4) * (n._size + 4)) { hoveredNode = n; break; }
|
|
4271
|
+
}
|
|
4272
|
+
if (frame < 250 || hoveredNode !== prev) draw();
|
|
4273
|
+
animRAF = requestAnimationFrame(loop);
|
|
4274
|
+
});
|
|
4275
|
+
draw();
|
|
4276
|
+
if (onFirstDraw) onFirstDraw();
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
function tick() {
|
|
4280
|
+
if (!simNodes.length) return;
|
|
4281
|
+
const REP = 140, SPRING_K = 0.035, REST = 75, GRAV = 0.012, DAMP = 0.87;
|
|
4282
|
+
const cx = W / 2, cy = H / 2;
|
|
4283
|
+
for (const n of simNodes) { n._fx = 0; n._fy = 0; }
|
|
4284
|
+
// Repulsion
|
|
4285
|
+
for (let i = 0; i < simNodes.length; i++) {
|
|
4286
|
+
const a = simNodes[i];
|
|
4287
|
+
for (let j = i + 1; j < simNodes.length; j++) {
|
|
4288
|
+
const b = simNodes[j];
|
|
4289
|
+
const dx = a._x - b._x, dy = a._y - b._y;
|
|
4290
|
+
const d2 = Math.max(dx*dx + dy*dy, 1), d = Math.sqrt(d2);
|
|
4291
|
+
const f = REP / d2;
|
|
4292
|
+
a._fx += (dx/d)*f; a._fy += (dy/d)*f;
|
|
4293
|
+
b._fx -= (dx/d)*f; b._fy -= (dy/d)*f;
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
// Spring
|
|
4297
|
+
for (const e of edges) {
|
|
4298
|
+
const a = simIdMap[e.source], b = simIdMap[e.target];
|
|
4299
|
+
if (!a || !b) continue;
|
|
4300
|
+
const dx = b._x - a._x, dy = b._y - a._y;
|
|
4301
|
+
const d = Math.max(Math.sqrt(dx*dx + dy*dy), 1);
|
|
4302
|
+
const f = SPRING_K * (d - REST);
|
|
4303
|
+
a._fx += (dx/d)*f; a._fy += (dy/d)*f;
|
|
4304
|
+
b._fx -= (dx/d)*f; b._fy -= (dy/d)*f;
|
|
4305
|
+
}
|
|
4306
|
+
// Gravity + integrate
|
|
4307
|
+
for (const n of simNodes) {
|
|
4308
|
+
n._fx += (cx - n._x) * GRAV; n._fy += (cy - n._y) * GRAV;
|
|
4309
|
+
n._vx = (n._vx + n._fx * 0.1) * DAMP; n._vy = (n._vy + n._fy * 0.1) * DAMP;
|
|
4310
|
+
n._x = Math.max(n._size + 2, Math.min(W - n._size - 2, n._x + n._vx));
|
|
4311
|
+
n._y = Math.max(n._size + 2, Math.min(H - n._size - 2, n._y + n._vy));
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
|
|
4315
|
+
function draw() {
|
|
4316
|
+
if (!canvas || !ctx || !W || !H) return;
|
|
4317
|
+
ctx.clearRect(0, 0, W, H);
|
|
4318
|
+
// Edges
|
|
4319
|
+
for (const e of edges) {
|
|
4320
|
+
const a = simIdMap[e.source], b = simIdMap[e.target];
|
|
4321
|
+
if (!a || !b) continue;
|
|
4322
|
+
const hl = hoveredNode && (hoveredNode.id === e.source || hoveredNode.id === e.target);
|
|
4323
|
+
ctx.beginPath(); ctx.moveTo(a._x, a._y); ctx.lineTo(b._x, b._y);
|
|
4324
|
+
ctx.strokeStyle = hl ? 'rgba(0,229,200,0.5)' : 'rgba(120,128,168,0.07)';
|
|
4325
|
+
ctx.lineWidth = hl ? 1.4 : 0.5; ctx.stroke();
|
|
4326
|
+
}
|
|
4327
|
+
// Nodes
|
|
4328
|
+
for (const n of simNodes) {
|
|
4329
|
+
const hov = hoveredNode && hoveredNode.id === n.id;
|
|
4330
|
+
const c = nodeColor(n);
|
|
4331
|
+
const r = n._size + (hov ? 2.5 : 0);
|
|
4332
|
+
if (hov) { ctx.shadowBlur = 16; ctx.shadowColor = c; }
|
|
4333
|
+
ctx.beginPath(); ctx.arc(n._x, n._y, r, 0, Math.PI * 2);
|
|
4334
|
+
ctx.globalAlpha = hov ? 1 : 0.75;
|
|
4335
|
+
ctx.fillStyle = c; ctx.fill();
|
|
4336
|
+
ctx.globalAlpha = 1; ctx.shadowBlur = 0;
|
|
4337
|
+
if (showLabels && (hov || n._size > 7)) {
|
|
4338
|
+
const lbl = (n.label || n.id).length > 20 ? (n.label || n.id).slice(0, 18) + '…' : (n.label || n.id);
|
|
4339
|
+
ctx.font = hov ? '9px monospace' : '8px monospace';
|
|
4340
|
+
ctx.fillStyle = hov ? 'rgba(255,255,255,0.95)' : 'rgba(180,188,210,0.55)';
|
|
4341
|
+
ctx.textAlign = 'center';
|
|
4342
|
+
ctx.fillText(lbl, n._x, n._y + r + 10);
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4345
|
+
// Tooltip
|
|
4346
|
+
if (hoveredNode) {
|
|
4347
|
+
const n = hoveredNode;
|
|
4348
|
+
const lines = [n.label || n.id, `${n.type || 'node'} · degree ${n.degree || 0}`];
|
|
4349
|
+
const tw = 250, th = lines.length * 14 + 16;
|
|
4350
|
+
let tx = n._x + 14, ty = n._y - th / 2;
|
|
4351
|
+
if (tx + tw > W - 4) tx = n._x - tw - 14;
|
|
4352
|
+
if (tx < 4) tx = 4;
|
|
4353
|
+
if (ty < 4) ty = 4;
|
|
4354
|
+
if (ty + th > H - 4) ty = H - th - 4;
|
|
4355
|
+
ctx.fillStyle = 'rgba(7,8,15,0.95)';
|
|
4356
|
+
ctx.strokeStyle = 'rgba(0,229,200,0.28)'; ctx.lineWidth = 1;
|
|
4357
|
+
roundRectCG(ctx, tx, ty, tw, th, 4); ctx.fill(); ctx.stroke();
|
|
4358
|
+
ctx.font = '9px monospace'; ctx.textAlign = 'left';
|
|
4359
|
+
ctx.fillStyle = 'rgba(255,255,255,0.92)'; ctx.fillText(lines[0], tx+8, ty+13);
|
|
4360
|
+
ctx.fillStyle = 'rgba(180,188,210,0.72)'; ctx.fillText(lines[1], tx+8, ty+27);
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4364
|
+
function roundRectCG(c, x, y, w, h, r) {
|
|
4365
|
+
c.beginPath();
|
|
4366
|
+
c.moveTo(x+r,y); c.lineTo(x+w-r,y); c.quadraticCurveTo(x+w,y,x+w,y+r);
|
|
4367
|
+
c.lineTo(x+w,y+h-r); c.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
|
|
4368
|
+
c.lineTo(x+r,y+h); c.quadraticCurveTo(x,y+h,x,y+h-r);
|
|
4369
|
+
c.lineTo(x,y+r); c.quadraticCurveTo(x,y,x+r,y); c.closePath();
|
|
4370
|
+
}
|
|
4371
|
+
|
|
4372
|
+
function stop() { if (animRAF) { cancelAnimationFrame(animRAF); animRAF = null; } }
|
|
4373
|
+
function reset() { stop(); simNodes = []; edges = []; simIdMap = {}; if (canvas && ctx) ctx.clearRect(0, 0, canvas.width, canvas.height); }
|
|
4374
|
+
function toggleLabels(v) { showLabels = v; draw(); }
|
|
4375
|
+
|
|
4376
|
+
return { init, render, stop, reset, toggleLabels };
|
|
4377
|
+
})();
|
|
4378
|
+
|
|
4379
|
+
// Wire up the MEMORY PALACE panel "open" button in sessions panel
|
|
4380
|
+
// Also refresh palace data when project changes
|
|
4381
|
+
const _origOpenPalace = window.openPalaceOverlay;
|
|
4382
|
+
window.openPalaceOverlay = async function() {
|
|
4383
|
+
palaceData = null;
|
|
4384
|
+
_palaceSelectedSession = null;
|
|
4385
|
+
await _origOpenPalace();
|
|
4386
|
+
};
|
|
4387
|
+
|
|
4388
|
+
// Stop KG graph animations when overlay closes
|
|
4389
|
+
const _origClose = window.closePalaceOverlay;
|
|
4390
|
+
window.closePalaceOverlay = function() {
|
|
4391
|
+
kgGraph.stop();
|
|
4392
|
+
kgCodeGraph.stop();
|
|
4393
|
+
_origClose();
|
|
4394
|
+
};
|
|
4395
|
+
|
|
4396
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
4397
|
+
// BOOT
|
|
4398
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
4399
|
+
(function boot() {
|
|
4400
|
+
// Set conn dot initial state
|
|
4401
|
+
const dot = document.getElementById('conn-dot');
|
|
4402
|
+
if (dot) dot.className = '';
|
|
4403
|
+
|
|
4404
|
+
fetchInitial();
|
|
4405
|
+
connectSSE();
|
|
4406
|
+
})();
|
|
4407
|
+
</script>
|
|
4408
|
+
</body>
|
|
4409
|
+
</html>
|