clementine-agent 1.18.21 → 1.18.23
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/dist/agent/action-enforcer.d.ts.map +1 -0
- package/dist/agent/action-enforcer.js.map +1 -0
- package/dist/agent/advisor-rules/context.d.ts.map +1 -0
- package/dist/agent/advisor-rules/context.js.map +1 -0
- package/dist/agent/advisor-rules/engine.d.ts.map +1 -0
- package/dist/agent/advisor-rules/engine.js.map +1 -0
- package/dist/agent/advisor-rules/loader.d.ts.map +1 -0
- package/dist/agent/advisor-rules/loader.js.map +1 -0
- package/dist/agent/advisor-rules/types.d.ts.map +1 -0
- package/dist/agent/advisor-rules/types.js.map +1 -0
- package/dist/agent/agent-manager.d.ts.map +1 -0
- package/dist/agent/agent-manager.js.map +1 -0
- package/dist/agent/assistant.d.ts.map +1 -0
- package/dist/agent/assistant.js +52 -15
- package/dist/agent/assistant.js.map +1 -0
- package/dist/agent/auto-skills.d.ts.map +1 -0
- package/dist/agent/auto-skills.js.map +1 -0
- package/dist/agent/auto-update.d.ts.map +1 -0
- package/dist/agent/auto-update.js.map +1 -0
- package/dist/agent/background-tasks.d.ts.map +1 -0
- package/dist/agent/background-tasks.js.map +1 -0
- package/dist/agent/brain-digest.d.ts.map +1 -0
- package/dist/agent/brain-digest.js.map +1 -0
- package/dist/agent/budget-enforcement.d.ts.map +1 -0
- package/dist/agent/budget-enforcement.js.map +1 -0
- package/dist/agent/complexity-classifier.d.ts.map +1 -0
- package/dist/agent/complexity-classifier.js.map +1 -0
- package/dist/agent/contradiction-validator.d.ts.map +1 -0
- package/dist/agent/contradiction-validator.js.map +1 -0
- package/dist/agent/crash-forensics.d.ts.map +1 -0
- package/dist/agent/crash-forensics.js.map +1 -0
- package/dist/agent/daily-planner.d.ts.map +1 -0
- package/dist/agent/daily-planner.js.map +1 -0
- package/dist/agent/decision-reflection.d.ts.map +1 -0
- package/dist/agent/decision-reflection.js.map +1 -0
- package/dist/agent/execution-advisor.d.ts.map +1 -0
- package/dist/agent/execution-advisor.js.map +1 -0
- package/dist/agent/hooks.d.ts.map +1 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/insight-engine.d.ts.map +1 -0
- package/dist/agent/insight-engine.js.map +1 -0
- package/dist/agent/intent-classifier.d.ts.map +1 -0
- package/dist/agent/intent-classifier.js.map +1 -0
- package/dist/agent/link-extractor.d.ts.map +1 -0
- package/dist/agent/link-extractor.js.map +1 -0
- package/dist/agent/local-turn.d.ts.map +1 -0
- package/dist/agent/local-turn.js.map +1 -0
- package/dist/agent/mcp-bridge.d.ts.map +1 -0
- package/dist/agent/mcp-bridge.js.map +1 -0
- package/dist/agent/mcp-circuit-breaker.d.ts.map +1 -0
- package/dist/agent/mcp-circuit-breaker.js.map +1 -0
- package/dist/agent/mcp-schemas.d.ts.map +1 -0
- package/dist/agent/mcp-schemas.js.map +1 -0
- package/dist/agent/metacognition.d.ts.map +1 -0
- package/dist/agent/metacognition.js.map +1 -0
- package/dist/agent/orchestrator.d.ts.map +1 -0
- package/dist/agent/orchestrator.js.map +1 -0
- package/dist/agent/proactive-engine.d.ts.map +1 -0
- package/dist/agent/proactive-engine.js.map +1 -0
- package/dist/agent/proactive-ledger.d.ts.map +1 -0
- package/dist/agent/proactive-ledger.js.map +1 -0
- package/dist/agent/prompt-cache.d.ts.map +1 -0
- package/dist/agent/prompt-cache.js.map +1 -0
- package/dist/agent/prompt-evolver.d.ts.map +1 -0
- package/dist/agent/prompt-evolver.js.map +1 -0
- package/dist/agent/prompt-overrides/loader.d.ts.map +1 -0
- package/dist/agent/prompt-overrides/loader.js +4 -1
- package/dist/agent/prompt-overrides/loader.js.map +1 -0
- package/dist/agent/prompt-overrides/types.d.ts.map +1 -0
- package/dist/agent/prompt-overrides/types.js.map +1 -0
- package/dist/agent/role-scaffolds.d.ts.map +1 -0
- package/dist/agent/role-scaffolds.js.map +1 -0
- package/dist/agent/route-classifier.d.ts.map +1 -0
- package/dist/agent/route-classifier.js.map +1 -0
- package/dist/agent/safe-restart.d.ts.map +1 -0
- package/dist/agent/safe-restart.js.map +1 -0
- package/dist/agent/self-improve-loop.d.ts.map +1 -0
- package/dist/agent/self-improve-loop.js.map +1 -0
- package/dist/agent/self-improve.d.ts.map +1 -0
- package/dist/agent/self-improve.js.map +1 -0
- package/dist/agent/session-event-log.d.ts.map +1 -0
- package/dist/agent/session-event-log.js.map +1 -0
- package/dist/agent/session-store-adapter.d.ts.map +1 -0
- package/dist/agent/session-store-adapter.js.map +1 -0
- package/dist/agent/skill-extractor.d.ts.map +1 -0
- package/dist/agent/skill-extractor.js.map +1 -0
- package/dist/agent/source-mods.d.ts.map +1 -0
- package/dist/agent/source-mods.js.map +1 -0
- package/dist/agent/source-preflight.d.ts.map +1 -0
- package/dist/agent/source-preflight.js.map +1 -0
- package/dist/agent/stall-guard.d.ts.map +1 -0
- package/dist/agent/stall-guard.js.map +1 -0
- package/dist/agent/strategic-planner.d.ts.map +1 -0
- package/dist/agent/strategic-planner.js.map +1 -0
- package/dist/agent/team-bus.d.ts.map +1 -0
- package/dist/agent/team-bus.js.map +1 -0
- package/dist/agent/team-router.d.ts.map +1 -0
- package/dist/agent/team-router.js.map +1 -0
- package/dist/agent/tool-loop-detector.d.ts.map +1 -0
- package/dist/agent/tool-loop-detector.js.map +1 -0
- package/dist/agent/tool-router.d.ts.map +1 -0
- package/dist/agent/tool-router.js.map +1 -0
- package/dist/agent/toolsets.d.ts.map +1 -0
- package/dist/agent/toolsets.js.map +1 -0
- package/dist/agent/turn-policy.d.ts.map +1 -0
- package/dist/agent/turn-policy.js.map +1 -0
- package/dist/agent/webhook-actions.d.ts.map +1 -0
- package/dist/agent/webhook-actions.js.map +1 -0
- package/dist/agent/workflow-runner.d.ts.map +1 -0
- package/dist/agent/workflow-runner.js.map +1 -0
- package/dist/agent/workflow-variables.d.ts.map +1 -0
- package/dist/agent/workflow-variables.js.map +1 -0
- package/dist/analytics/tool-usage.d.ts.map +1 -0
- package/dist/analytics/tool-usage.js.map +1 -0
- package/dist/brain/adapters/common.d.ts.map +1 -0
- package/dist/brain/adapters/common.js.map +1 -0
- package/dist/brain/adapters/csv.d.ts.map +1 -0
- package/dist/brain/adapters/csv.js.map +1 -0
- package/dist/brain/adapters/docx.d.ts.map +1 -0
- package/dist/brain/adapters/docx.js.map +1 -0
- package/dist/brain/adapters/email.d.ts.map +1 -0
- package/dist/brain/adapters/email.js.map +1 -0
- package/dist/brain/adapters/index.d.ts.map +1 -0
- package/dist/brain/adapters/index.js.map +1 -0
- package/dist/brain/adapters/json.d.ts.map +1 -0
- package/dist/brain/adapters/json.js.map +1 -0
- package/dist/brain/adapters/markdown.d.ts.map +1 -0
- package/dist/brain/adapters/markdown.js.map +1 -0
- package/dist/brain/adapters/pdf.d.ts.map +1 -0
- package/dist/brain/adapters/pdf.js.map +1 -0
- package/dist/brain/adapters/rest.d.ts.map +1 -0
- package/dist/brain/adapters/rest.js.map +1 -0
- package/dist/brain/batch-summary.d.ts.map +1 -0
- package/dist/brain/batch-summary.js.map +1 -0
- package/dist/brain/connector-recipes.d.ts.map +1 -0
- package/dist/brain/connector-recipes.js.map +1 -0
- package/dist/brain/format-detector.d.ts.map +1 -0
- package/dist/brain/format-detector.js.map +1 -0
- package/dist/brain/graph-extractor.d.ts.map +1 -0
- package/dist/brain/graph-extractor.js.map +1 -0
- package/dist/brain/ingest-scheduler.d.ts.map +1 -0
- package/dist/brain/ingest-scheduler.js.map +1 -0
- package/dist/brain/ingestion-pipeline.d.ts.map +1 -0
- package/dist/brain/ingestion-pipeline.js.map +1 -0
- package/dist/brain/intelligence.d.ts.map +1 -0
- package/dist/brain/intelligence.js.map +1 -0
- package/dist/brain/llm-client.d.ts.map +1 -0
- package/dist/brain/llm-client.js.map +1 -0
- package/dist/brain/source-registry.d.ts.map +1 -0
- package/dist/brain/source-registry.js.map +1 -0
- package/dist/channels/discord-agent-bot.d.ts.map +1 -0
- package/dist/channels/discord-agent-bot.js.map +1 -0
- package/dist/channels/discord-bot-manager.d.ts.map +1 -0
- package/dist/channels/discord-bot-manager.js.map +1 -0
- package/dist/channels/discord-utils.d.ts.map +1 -0
- package/dist/channels/discord-utils.js.map +1 -0
- package/dist/channels/discord.d.ts.map +1 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/slack-agent-bot.d.ts.map +1 -0
- package/dist/channels/slack-agent-bot.js.map +1 -0
- package/dist/channels/slack-bot-manager.d.ts.map +1 -0
- package/dist/channels/slack-bot-manager.js.map +1 -0
- package/dist/channels/slack-utils.d.ts.map +1 -0
- package/dist/channels/slack-utils.js.map +1 -0
- package/dist/channels/slack.d.ts.map +1 -0
- package/dist/channels/slack.js.map +1 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/webhook.d.ts.map +1 -0
- package/dist/channels/webhook.js.map +1 -0
- package/dist/channels/whatsapp.d.ts.map +1 -0
- package/dist/channels/whatsapp.js.map +1 -0
- package/dist/cli/browser.d.ts.map +1 -0
- package/dist/cli/browser.js.map +1 -0
- package/dist/cli/chat.d.ts.map +1 -0
- package/dist/cli/chat.js.map +1 -0
- package/dist/cli/cron.d.ts.map +1 -0
- package/dist/cli/cron.js.map +1 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +1135 -113
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ingest.d.ts.map +1 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/routes/delegations.d.ts.map +1 -0
- package/dist/cli/routes/delegations.js.map +1 -0
- package/dist/cli/routes/digest.d.ts.map +1 -0
- package/dist/cli/routes/digest.js.map +1 -0
- package/dist/cli/routes/goals.d.ts.map +1 -0
- package/dist/cli/routes/goals.js.map +1 -0
- package/dist/cli/routes/workflows.d.ts.map +1 -0
- package/dist/cli/routes/workflows.js.map +1 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/tunnel.d.ts.map +1 -0
- package/dist/cli/tunnel.js.map +1 -0
- package/dist/cli/version-check.d.ts.map +1 -0
- package/dist/cli/version-check.js.map +1 -0
- package/dist/config/clementine-json.d.ts.map +1 -0
- package/dist/config/clementine-json.js.map +1 -0
- package/dist/config/config-doctor.d.ts.map +1 -0
- package/dist/config/config-doctor.js.map +1 -0
- package/dist/config/effective-config.d.ts.map +1 -0
- package/dist/config/effective-config.js.map +1 -0
- package/dist/config/env-parser.d.ts.map +1 -0
- package/dist/config/env-parser.js.map +1 -0
- package/dist/config/harden-permissions.d.ts.map +1 -0
- package/dist/config/harden-permissions.js.map +1 -0
- package/dist/config/integrations-registry.d.ts.map +1 -0
- package/dist/config/integrations-registry.js.map +1 -0
- package/dist/config/keychain-first-run-wizard.d.ts.map +1 -0
- package/dist/config/keychain-first-run-wizard.js.map +1 -0
- package/dist/config/keychain-fix-acl.d.ts.map +1 -0
- package/dist/config/keychain-fix-acl.js.map +1 -0
- package/dist/config/migrate-from-keychain.d.ts.map +1 -0
- package/dist/config/migrate-from-keychain.js.map +1 -0
- package/dist/config/migrate-keychain.d.ts.map +1 -0
- package/dist/config/migrate-keychain.js.map +1 -0
- package/dist/config.d.ts +7 -3
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -12
- package/dist/config.js.map +1 -0
- package/dist/dashboard/builder/dry-run.d.ts.map +1 -0
- package/dist/dashboard/builder/dry-run.js.map +1 -0
- package/dist/dashboard/builder/events.d.ts.map +1 -0
- package/dist/dashboard/builder/events.js.map +1 -0
- package/dist/dashboard/builder/mcp-invoke.d.ts.map +1 -0
- package/dist/dashboard/builder/mcp-invoke.js.map +1 -0
- package/dist/dashboard/builder/runner.d.ts.map +1 -0
- package/dist/dashboard/builder/runner.js.map +1 -0
- package/dist/dashboard/builder/serializer.d.ts.map +1 -0
- package/dist/dashboard/builder/serializer.js.map +1 -0
- package/dist/dashboard/builder/snapshots.d.ts.map +1 -0
- package/dist/dashboard/builder/snapshots.js.map +1 -0
- package/dist/dashboard/builder/validation.d.ts.map +1 -0
- package/dist/dashboard/builder/validation.js.map +1 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js.map +1 -0
- package/dist/gateway/agent-heartbeat-manager.d.ts.map +1 -0
- package/dist/gateway/agent-heartbeat-manager.js.map +1 -0
- package/dist/gateway/agent-heartbeat-scheduler.d.ts.map +1 -0
- package/dist/gateway/agent-heartbeat-scheduler.js.map +1 -0
- package/dist/gateway/claim-tracker.d.ts.map +1 -0
- package/dist/gateway/claim-tracker.js.map +1 -0
- package/dist/gateway/context-hygiene.d.ts.map +1 -0
- package/dist/gateway/context-hygiene.js.map +1 -0
- package/dist/gateway/credit-guard.d.ts.map +1 -0
- package/dist/gateway/credit-guard.js.map +1 -0
- package/dist/gateway/cron-diagnostic-turn.d.ts.map +1 -0
- package/dist/gateway/cron-diagnostic-turn.js.map +1 -0
- package/dist/gateway/cron-scheduler.d.ts.map +1 -0
- package/dist/gateway/cron-scheduler.js +134 -12
- package/dist/gateway/cron-scheduler.js.map +1 -0
- package/dist/gateway/delivery-queue.d.ts.map +1 -0
- package/dist/gateway/delivery-queue.js.map +1 -0
- package/dist/gateway/failure-diagnostics.d.ts +3 -1
- package/dist/gateway/failure-diagnostics.d.ts.map +1 -0
- package/dist/gateway/failure-diagnostics.js +31 -3
- package/dist/gateway/failure-diagnostics.js.map +1 -0
- package/dist/gateway/failure-monitor.d.ts.map +1 -0
- package/dist/gateway/failure-monitor.js +1 -1
- package/dist/gateway/failure-monitor.js.map +1 -0
- package/dist/gateway/fix-applier.d.ts.map +1 -0
- package/dist/gateway/fix-applier.js.map +1 -0
- package/dist/gateway/fix-verification.d.ts.map +1 -0
- package/dist/gateway/fix-verification.js +13 -3
- package/dist/gateway/fix-verification.js.map +1 -0
- package/dist/gateway/heartbeat-scheduler.d.ts.map +1 -0
- package/dist/gateway/heartbeat-scheduler.js.map +1 -0
- package/dist/gateway/heartbeat.d.ts.map +1 -0
- package/dist/gateway/heartbeat.js.map +1 -0
- package/dist/gateway/job-health.d.ts.map +1 -0
- package/dist/gateway/job-health.js +9 -0
- package/dist/gateway/job-health.js.map +1 -0
- package/dist/gateway/lanes.d.ts.map +1 -0
- package/dist/gateway/lanes.js.map +1 -0
- package/dist/gateway/long-task-preflight.d.ts +21 -0
- package/dist/gateway/long-task-preflight.d.ts.map +1 -0
- package/dist/gateway/long-task-preflight.js +203 -0
- package/dist/gateway/long-task-preflight.js.map +1 -0
- package/dist/gateway/notification-context.d.ts.map +1 -0
- package/dist/gateway/notification-context.js.map +1 -0
- package/dist/gateway/notifications.d.ts.map +1 -0
- package/dist/gateway/notifications.js.map +1 -0
- package/dist/gateway/outcome-grader.d.ts.map +1 -0
- package/dist/gateway/outcome-grader.js.map +1 -0
- package/dist/gateway/router.d.ts.map +1 -0
- package/dist/gateway/router.js.map +1 -0
- package/dist/gateway/turn-ledger.d.ts.map +1 -0
- package/dist/gateway/turn-ledger.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/composio/client.d.ts.map +1 -0
- package/dist/integrations/composio/client.js.map +1 -0
- package/dist/integrations/composio/mcp-bridge.d.ts.map +1 -0
- package/dist/integrations/composio/mcp-bridge.js.map +1 -0
- package/dist/integrations/tool-preferences.d.ts.map +1 -0
- package/dist/integrations/tool-preferences.js.map +1 -0
- package/dist/memory/chunker.d.ts.map +1 -0
- package/dist/memory/chunker.js.map +1 -0
- package/dist/memory/consolidation.d.ts.map +1 -0
- package/dist/memory/consolidation.js.map +1 -0
- package/dist/memory/context-assembler.d.ts.map +1 -0
- package/dist/memory/context-assembler.js.map +1 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/graph-store.d.ts.map +1 -0
- package/dist/memory/graph-store.js.map +1 -0
- package/dist/memory/hot-cache.d.ts.map +1 -0
- package/dist/memory/hot-cache.js.map +1 -0
- package/dist/memory/integrity.d.ts.map +1 -0
- package/dist/memory/integrity.js.map +1 -0
- package/dist/memory/maintenance.d.ts.map +1 -0
- package/dist/memory/maintenance.js.map +1 -0
- package/dist/memory/mmr.d.ts.map +1 -0
- package/dist/memory/mmr.js.map +1 -0
- package/dist/memory/search.d.ts.map +1 -0
- package/dist/memory/search.js.map +1 -0
- package/dist/memory/seed-user-model.d.ts.map +1 -0
- package/dist/memory/seed-user-model.js.map +1 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/write-queue.d.ts.map +1 -0
- package/dist/memory/write-queue.js.map +1 -0
- package/dist/secrets/auth-profiles.d.ts.map +1 -0
- package/dist/secrets/auth-profiles.js.map +1 -0
- package/dist/secrets/keychain.d.ts.map +1 -0
- package/dist/secrets/keychain.js.map +1 -0
- package/dist/secrets/resolver.d.ts.map +1 -0
- package/dist/secrets/resolver.js.map +1 -0
- package/dist/secrets/sensitivity.d.ts.map +1 -0
- package/dist/secrets/sensitivity.js.map +1 -0
- package/dist/security/integrity.d.ts.map +1 -0
- package/dist/security/integrity.js.map +1 -0
- package/dist/security/patterns.d.ts.map +1 -0
- package/dist/security/patterns.js.map +1 -0
- package/dist/security/redact.d.ts.map +1 -0
- package/dist/security/redact.js.map +1 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/tools/admin-tools.d.ts.map +1 -0
- package/dist/tools/admin-tools.js.map +1 -0
- package/dist/tools/agent-heartbeat-tools.d.ts.map +1 -0
- package/dist/tools/agent-heartbeat-tools.js.map +1 -0
- package/dist/tools/artifact-tools.d.ts.map +1 -0
- package/dist/tools/artifact-tools.js.map +1 -0
- package/dist/tools/background-task-tools.d.ts.map +1 -0
- package/dist/tools/background-task-tools.js.map +1 -0
- package/dist/tools/brain-tools.d.ts.map +1 -0
- package/dist/tools/brain-tools.js.map +1 -0
- package/dist/tools/builder-tools.d.ts.map +1 -0
- package/dist/tools/builder-tools.js.map +1 -0
- package/dist/tools/decision-reflection-tools.d.ts.map +1 -0
- package/dist/tools/decision-reflection-tools.js.map +1 -0
- package/dist/tools/external-tools.d.ts.map +1 -0
- package/dist/tools/external-tools.js.map +1 -0
- package/dist/tools/goal-tools.d.ts.map +1 -0
- package/dist/tools/goal-tools.js.map +1 -0
- package/dist/tools/mcp-server.d.ts.map +1 -0
- package/dist/tools/mcp-server.js.map +1 -0
- package/dist/tools/memory-tools.d.ts.map +1 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/session-tools.d.ts.map +1 -0
- package/dist/tools/session-tools.js.map +1 -0
- package/dist/tools/shared.d.ts.map +1 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/team-tools.d.ts.map +1 -0
- package/dist/tools/team-tools.js.map +1 -0
- package/dist/tools/tool-meta.d.ts.map +1 -0
- package/dist/tools/tool-meta.js.map +1 -0
- package/dist/tools/vault-tools.d.ts.map +1 -0
- package/dist/tools/vault-tools.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js.map +1 -0
- package/dist/vault-migrations/0001-add-execution-framework.d.ts.map +1 -0
- package/dist/vault-migrations/0001-add-execution-framework.js.map +1 -0
- package/dist/vault-migrations/0002-add-agentic-communication.d.ts.map +1 -0
- package/dist/vault-migrations/0002-add-agentic-communication.js.map +1 -0
- package/dist/vault-migrations/0003-update-execution-pipeline-narration.d.ts.map +1 -0
- package/dist/vault-migrations/0003-update-execution-pipeline-narration.js.map +1 -0
- package/dist/vault-migrations/0004-backfill-schema-versions.d.ts.map +1 -0
- package/dist/vault-migrations/0004-backfill-schema-versions.js.map +1 -0
- package/dist/vault-migrations/0005-create-clementine-json.d.ts.map +1 -0
- package/dist/vault-migrations/0005-create-clementine-json.js.map +1 -0
- package/dist/vault-migrations/helpers.d.ts.map +1 -0
- package/dist/vault-migrations/helpers.js.map +1 -0
- package/dist/vault-migrations/runner.d.ts.map +1 -0
- package/dist/vault-migrations/runner.js.map +1 -0
- package/dist/vault-migrations/types.d.ts.map +1 -0
- package/dist/vault-migrations/types.js.map +1 -0
- package/package.json +1 -1
package/dist/cli/dashboard.js
CHANGED
|
@@ -288,6 +288,255 @@ async function searchMemory(query, limit = 20, filters = {}) {
|
|
|
288
288
|
db.close();
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
|
+
function quotedFtsQuery(query) {
|
|
292
|
+
return query
|
|
293
|
+
.split(/\s+/)
|
|
294
|
+
.map((w) => w.replace(/"/g, '').trim())
|
|
295
|
+
.filter((w) => w.length > 0)
|
|
296
|
+
.map((w) => `"${w}"`)
|
|
297
|
+
.join(' OR ');
|
|
298
|
+
}
|
|
299
|
+
function textPreview(raw, query = '', max = 520) {
|
|
300
|
+
const compact = String(raw ?? '').replace(/\s+/g, ' ').trim();
|
|
301
|
+
if (!compact)
|
|
302
|
+
return '';
|
|
303
|
+
const q = query.trim().toLowerCase();
|
|
304
|
+
if (!q)
|
|
305
|
+
return compact.slice(0, max);
|
|
306
|
+
const idx = compact.toLowerCase().indexOf(q);
|
|
307
|
+
if (idx < 0)
|
|
308
|
+
return compact.slice(0, max);
|
|
309
|
+
const start = Math.max(0, idx - 120);
|
|
310
|
+
const end = Math.min(compact.length, start + max);
|
|
311
|
+
return (start > 0 ? '…' : '') + compact.slice(start, end) + (end < compact.length ? '…' : '');
|
|
312
|
+
}
|
|
313
|
+
function classifyVaultOrigin(relPath) {
|
|
314
|
+
if (relPath.startsWith('04-Ingest/'))
|
|
315
|
+
return 'Seeded';
|
|
316
|
+
if (relPath.startsWith('00-System/skills/') || relPath.startsWith('00-System/workflows/') || relPath.startsWith('00-System/agents/')) {
|
|
317
|
+
return 'Agent-created';
|
|
318
|
+
}
|
|
319
|
+
if (relPath.startsWith('01-Daily/'))
|
|
320
|
+
return 'Conversation';
|
|
321
|
+
return 'Vault';
|
|
322
|
+
}
|
|
323
|
+
async function searchBrainLibrary(query, limit = 30, scope = 'all') {
|
|
324
|
+
const trimmed = query.trim();
|
|
325
|
+
const lowered = trimmed.toLowerCase();
|
|
326
|
+
const qWords = lowered.split(/\s+/).filter(Boolean);
|
|
327
|
+
const perTypeLimit = Math.max(8, Math.ceil(limit / 2));
|
|
328
|
+
const results = [];
|
|
329
|
+
const totalByType = { memory: 0, files: 0, artifacts: 0 };
|
|
330
|
+
const include = (kind) => scope === 'all' || scope === kind;
|
|
331
|
+
const dbExists = existsSync(MEMORY_DB_PATH);
|
|
332
|
+
if (include('memory') && dbExists) {
|
|
333
|
+
const Database = (await import('better-sqlite3')).default;
|
|
334
|
+
const db = new Database(MEMORY_DB_PATH, { readonly: true });
|
|
335
|
+
try {
|
|
336
|
+
let rows = [];
|
|
337
|
+
if (trimmed) {
|
|
338
|
+
const ftsQuery = quotedFtsQuery(trimmed);
|
|
339
|
+
if (ftsQuery) {
|
|
340
|
+
rows = db.prepare(`SELECT c.id, c.source_file, c.section, c.content, c.chunk_type,
|
|
341
|
+
c.updated_at, c.source_slug, c.source_type, c.agent_slug, c.pinned,
|
|
342
|
+
bm25(chunks_fts) AS score
|
|
343
|
+
FROM chunks_fts f
|
|
344
|
+
JOIN chunks c ON c.id = f.rowid
|
|
345
|
+
LEFT JOIN chunk_soft_deletes sd ON sd.chunk_id = c.id
|
|
346
|
+
WHERE chunks_fts MATCH ? AND sd.chunk_id IS NULL
|
|
347
|
+
ORDER BY bm25(chunks_fts)
|
|
348
|
+
LIMIT ?`).all(ftsQuery, perTypeLimit);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
rows = db.prepare(`SELECT c.id, c.source_file, c.section, c.content, c.chunk_type,
|
|
353
|
+
c.updated_at, c.source_slug, c.source_type, c.agent_slug, c.pinned,
|
|
354
|
+
0 AS score
|
|
355
|
+
FROM chunks c
|
|
356
|
+
LEFT JOIN chunk_soft_deletes sd ON sd.chunk_id = c.id
|
|
357
|
+
WHERE sd.chunk_id IS NULL
|
|
358
|
+
ORDER BY c.updated_at DESC, c.id DESC
|
|
359
|
+
LIMIT ?`).all(perTypeLimit);
|
|
360
|
+
}
|
|
361
|
+
totalByType.memory = rows.length;
|
|
362
|
+
for (const row of rows) {
|
|
363
|
+
const sourceFile = String(row.source_file ?? '');
|
|
364
|
+
const sourceSlug = row.source_slug ? String(row.source_slug) : '';
|
|
365
|
+
const section = String(row.section ?? '');
|
|
366
|
+
const score = Number(row.score ?? 0);
|
|
367
|
+
const badges = [
|
|
368
|
+
row.chunk_type ? String(row.chunk_type) : 'chunk',
|
|
369
|
+
sourceSlug ? `source:${sourceSlug}` : classifyVaultOrigin(sourceFile),
|
|
370
|
+
row.pinned ? 'pinned' : '',
|
|
371
|
+
].filter(Boolean);
|
|
372
|
+
results.push({
|
|
373
|
+
id: `memory:${row.id}`,
|
|
374
|
+
kind: 'memory',
|
|
375
|
+
title: section || path.basename(sourceFile) || `Chunk #${row.id}`,
|
|
376
|
+
subtitle: sourceFile,
|
|
377
|
+
preview: textPreview(String(row.content ?? ''), trimmed),
|
|
378
|
+
timestamp: row.updated_at ? String(row.updated_at) : null,
|
|
379
|
+
score: trimmed ? 100 - Math.abs(score) : 0,
|
|
380
|
+
badges,
|
|
381
|
+
chunkId: Number(row.id),
|
|
382
|
+
source: sourceSlug || sourceFile,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
// Missing legacy tables should not break dashboard search.
|
|
388
|
+
}
|
|
389
|
+
finally {
|
|
390
|
+
db.close();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (include('artifacts') && dbExists) {
|
|
394
|
+
const Database = (await import('better-sqlite3')).default;
|
|
395
|
+
const db = new Database(MEMORY_DB_PATH, { readonly: true });
|
|
396
|
+
try {
|
|
397
|
+
let rows = [];
|
|
398
|
+
if (trimmed) {
|
|
399
|
+
const ftsQuery = quotedFtsQuery(trimmed);
|
|
400
|
+
if (ftsQuery) {
|
|
401
|
+
rows = db.prepare(`SELECT a.id, a.tool_name, a.summary, substr(a.content, 1, 900) AS preview,
|
|
402
|
+
a.tags, a.stored_at, a.session_key, a.agent_slug, bm25(tool_artifacts_fts) AS score
|
|
403
|
+
FROM tool_artifacts_fts f
|
|
404
|
+
JOIN tool_artifacts a ON a.id = f.rowid
|
|
405
|
+
WHERE tool_artifacts_fts MATCH ?
|
|
406
|
+
ORDER BY bm25(tool_artifacts_fts)
|
|
407
|
+
LIMIT ?`).all(ftsQuery, perTypeLimit);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
rows = db.prepare(`SELECT id, tool_name, summary, substr(content, 1, 900) AS preview,
|
|
412
|
+
tags, stored_at, session_key, agent_slug, 0 AS score
|
|
413
|
+
FROM tool_artifacts
|
|
414
|
+
ORDER BY stored_at DESC, id DESC
|
|
415
|
+
LIMIT ?`).all(perTypeLimit);
|
|
416
|
+
}
|
|
417
|
+
totalByType.artifacts = rows.length;
|
|
418
|
+
for (const row of rows) {
|
|
419
|
+
const tags = String(row.tags ?? '').split(',').map((t) => t.trim()).filter(Boolean).slice(0, 4);
|
|
420
|
+
results.push({
|
|
421
|
+
id: `artifact:${row.id}`,
|
|
422
|
+
kind: 'artifact',
|
|
423
|
+
title: String(row.summary ?? '').trim() || String(row.tool_name ?? 'Tool artifact'),
|
|
424
|
+
subtitle: `Tool output · ${String(row.tool_name ?? 'unknown')}`,
|
|
425
|
+
preview: textPreview(`${row.summary ?? ''}\n${row.preview ?? ''}`, trimmed),
|
|
426
|
+
timestamp: row.stored_at ? String(row.stored_at) : null,
|
|
427
|
+
score: trimmed ? 100 - Math.abs(Number(row.score ?? 0)) : 0,
|
|
428
|
+
badges: ['artifact', ...tags],
|
|
429
|
+
artifactId: Number(row.id),
|
|
430
|
+
source: row.session_key ? String(row.session_key) : undefined,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
catch {
|
|
435
|
+
// Artifact memory may not exist on older DBs.
|
|
436
|
+
}
|
|
437
|
+
finally {
|
|
438
|
+
db.close();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (include('files')) {
|
|
442
|
+
const vaultRoot = VAULT_DIR;
|
|
443
|
+
const files = [];
|
|
444
|
+
const maxScan = trimmed ? 5000 : 500;
|
|
445
|
+
let scanned = 0;
|
|
446
|
+
function walk(dir) {
|
|
447
|
+
if (scanned >= maxScan)
|
|
448
|
+
return;
|
|
449
|
+
let entries = [];
|
|
450
|
+
try {
|
|
451
|
+
entries = readdirSync(dir);
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
for (const entry of entries) {
|
|
457
|
+
if (scanned >= maxScan)
|
|
458
|
+
break;
|
|
459
|
+
if (entry.startsWith('.'))
|
|
460
|
+
continue;
|
|
461
|
+
const full = path.join(dir, entry);
|
|
462
|
+
let stat;
|
|
463
|
+
try {
|
|
464
|
+
stat = statSync(full);
|
|
465
|
+
}
|
|
466
|
+
catch {
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
if (stat.isDirectory()) {
|
|
470
|
+
if (entry === 'node_modules' || entry === '.git')
|
|
471
|
+
continue;
|
|
472
|
+
walk(full);
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
if (!entry.endsWith('.md') || entry.endsWith('.md.bak'))
|
|
476
|
+
continue;
|
|
477
|
+
scanned += 1;
|
|
478
|
+
const relPath = path.relative(vaultRoot, full);
|
|
479
|
+
let raw = '';
|
|
480
|
+
try {
|
|
481
|
+
raw = readFileSync(full, 'utf-8');
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
let title = path.basename(entry, '.md');
|
|
487
|
+
let typeTag = '';
|
|
488
|
+
let content = raw;
|
|
489
|
+
try {
|
|
490
|
+
const parsed = matter(raw.slice(0, 80_000));
|
|
491
|
+
content = parsed.content || raw;
|
|
492
|
+
const data = parsed.data;
|
|
493
|
+
if (typeof data.title === 'string')
|
|
494
|
+
title = data.title;
|
|
495
|
+
else if (typeof data.name === 'string')
|
|
496
|
+
title = data.name;
|
|
497
|
+
else {
|
|
498
|
+
const h1 = content.match(/^#\s+(.+)$/m);
|
|
499
|
+
if (h1)
|
|
500
|
+
title = h1[1].trim();
|
|
501
|
+
}
|
|
502
|
+
if (typeof data.type === 'string')
|
|
503
|
+
typeTag = data.type;
|
|
504
|
+
}
|
|
505
|
+
catch { /* keep filename */ }
|
|
506
|
+
const hay = `${title}\n${relPath}\n${content.slice(0, 80_000)}`.toLowerCase();
|
|
507
|
+
const match = !trimmed || qWords.every((word) => hay.includes(word)) || hay.includes(lowered);
|
|
508
|
+
if (!match)
|
|
509
|
+
continue;
|
|
510
|
+
const titleHit = lowered && title.toLowerCase().includes(lowered) ? 30 : 0;
|
|
511
|
+
const pathHit = lowered && relPath.toLowerCase().includes(lowered) ? 18 : 0;
|
|
512
|
+
const contentHit = lowered && content.toLowerCase().includes(lowered) ? 10 : 0;
|
|
513
|
+
files.push({
|
|
514
|
+
id: `file:${relPath}`,
|
|
515
|
+
kind: 'file',
|
|
516
|
+
title,
|
|
517
|
+
subtitle: relPath,
|
|
518
|
+
preview: textPreview(content, trimmed),
|
|
519
|
+
timestamp: stat.mtime.toISOString(),
|
|
520
|
+
score: trimmed ? titleHit + pathHit + contentHit : stat.mtimeMs / 1_000_000_000,
|
|
521
|
+
badges: [typeTag || 'note', classifyVaultOrigin(relPath)].filter(Boolean),
|
|
522
|
+
relPath,
|
|
523
|
+
source: relPath,
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (existsSync(vaultRoot))
|
|
528
|
+
walk(vaultRoot);
|
|
529
|
+
files.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
530
|
+
totalByType.files = files.length;
|
|
531
|
+
results.push(...files.slice(0, perTypeLimit));
|
|
532
|
+
}
|
|
533
|
+
results.sort((a, b) => {
|
|
534
|
+
if (trimmed)
|
|
535
|
+
return (b.score ?? 0) - (a.score ?? 0);
|
|
536
|
+
return String(b.timestamp ?? '').localeCompare(String(a.timestamp ?? ''));
|
|
537
|
+
});
|
|
538
|
+
return { results: results.slice(0, limit), totalByType, dbExists };
|
|
539
|
+
}
|
|
291
540
|
// ── Remote access config ────────────────────────────────────────────
|
|
292
541
|
const REMOTE_CONFIG_PATH = path.join(BASE_DIR, 'remote-access.json');
|
|
293
542
|
function generateAccessToken() {
|
|
@@ -4335,7 +4584,8 @@ If the tool returns nothing or errors, return an empty array \`[]\`.`,
|
|
|
4335
4584
|
const { getStore } = await import('../tools/shared.js');
|
|
4336
4585
|
const store = await getStore();
|
|
4337
4586
|
const slug = typeof req.query.slug === 'string' ? req.query.slug : undefined;
|
|
4338
|
-
const
|
|
4587
|
+
const limit = Math.min(Math.max(Number(req.query.limit) || 50, 1), 200);
|
|
4588
|
+
const runs = store.listIngestionRuns(slug, limit);
|
|
4339
4589
|
res.json({ runs });
|
|
4340
4590
|
}
|
|
4341
4591
|
catch (err) {
|
|
@@ -6754,6 +7004,30 @@ If the tool returns nothing or errors, return an empty array \`[]\`.`,
|
|
|
6754
7004
|
res.status(500).json({ error: String(err) });
|
|
6755
7005
|
}
|
|
6756
7006
|
});
|
|
7007
|
+
app.get('/api/brain/artifacts/:id', async (req, res) => {
|
|
7008
|
+
try {
|
|
7009
|
+
const id = Number(req.params.id);
|
|
7010
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
7011
|
+
res.status(400).json({ error: 'invalid artifact id' });
|
|
7012
|
+
return;
|
|
7013
|
+
}
|
|
7014
|
+
const { getStore } = await import('../tools/shared.js');
|
|
7015
|
+
const store = await getStore();
|
|
7016
|
+
if (!store?.getArtifact) {
|
|
7017
|
+
res.status(503).json({ error: 'Artifact memory not available' });
|
|
7018
|
+
return;
|
|
7019
|
+
}
|
|
7020
|
+
const artifact = store.getArtifact(id);
|
|
7021
|
+
if (!artifact) {
|
|
7022
|
+
res.status(404).json({ error: 'artifact not found' });
|
|
7023
|
+
return;
|
|
7024
|
+
}
|
|
7025
|
+
res.json({ ok: true, artifact });
|
|
7026
|
+
}
|
|
7027
|
+
catch (err) {
|
|
7028
|
+
res.status(500).json({ error: String(err) });
|
|
7029
|
+
}
|
|
7030
|
+
});
|
|
6757
7031
|
// ── Cron training chat endpoint ─────────────────────────────────────
|
|
6758
7032
|
app.post('/api/cron/train', async (req, res) => {
|
|
6759
7033
|
const { message, jobName, prompt, context, agentSlug } = req.body;
|
|
@@ -7120,6 +7394,19 @@ If the tool returns nothing or errors, return an empty array \`[]\`.`,
|
|
|
7120
7394
|
res.status(500).json({ results: [], error: String(err) });
|
|
7121
7395
|
}
|
|
7122
7396
|
});
|
|
7397
|
+
app.get('/api/brain/library/search', async (req, res) => {
|
|
7398
|
+
try {
|
|
7399
|
+
const q = String(req.query.q ?? '');
|
|
7400
|
+
const rawScope = String(req.query.scope ?? 'all');
|
|
7401
|
+
const scope = ['all', 'memory', 'files', 'artifacts'].includes(rawScope) ? rawScope : 'all';
|
|
7402
|
+
const limit = Math.min(Math.max(Number(req.query.limit) || 30, 1), 80);
|
|
7403
|
+
const data = await searchBrainLibrary(q, limit, scope);
|
|
7404
|
+
res.json({ ok: true, query: q, scope, ...data });
|
|
7405
|
+
}
|
|
7406
|
+
catch (err) {
|
|
7407
|
+
res.status(500).json({ ok: false, error: String(err), results: [] });
|
|
7408
|
+
}
|
|
7409
|
+
});
|
|
7123
7410
|
// ── Metrics route ─────────────────────────────────────────────────
|
|
7124
7411
|
app.get('/api/metrics', (_req, res) => {
|
|
7125
7412
|
res.json(computeMetrics());
|
|
@@ -11312,6 +11599,201 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
11312
11599
|
overflow-y: auto;
|
|
11313
11600
|
}
|
|
11314
11601
|
|
|
11602
|
+
/* ── Brain command center ──────────────── */
|
|
11603
|
+
.brain-command-shell {
|
|
11604
|
+
display: flex;
|
|
11605
|
+
flex-direction: column;
|
|
11606
|
+
gap: 16px;
|
|
11607
|
+
}
|
|
11608
|
+
.brain-hero-panel {
|
|
11609
|
+
border: 1px solid var(--border);
|
|
11610
|
+
border-radius: var(--radius);
|
|
11611
|
+
background: var(--bg-card);
|
|
11612
|
+
padding: 18px;
|
|
11613
|
+
}
|
|
11614
|
+
.brain-pillar-grid {
|
|
11615
|
+
display: grid;
|
|
11616
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
11617
|
+
gap: 12px;
|
|
11618
|
+
}
|
|
11619
|
+
.brain-pillar-card {
|
|
11620
|
+
border: 1px solid var(--border);
|
|
11621
|
+
border-radius: var(--radius);
|
|
11622
|
+
background: var(--bg-card);
|
|
11623
|
+
padding: 16px;
|
|
11624
|
+
display: flex;
|
|
11625
|
+
flex-direction: column;
|
|
11626
|
+
gap: 10px;
|
|
11627
|
+
min-height: 178px;
|
|
11628
|
+
}
|
|
11629
|
+
.brain-pillar-card strong {
|
|
11630
|
+
font-size: 14px;
|
|
11631
|
+
color: var(--text-primary);
|
|
11632
|
+
}
|
|
11633
|
+
.brain-pillar-card p {
|
|
11634
|
+
margin: 0;
|
|
11635
|
+
color: var(--text-secondary);
|
|
11636
|
+
font-size: 12px;
|
|
11637
|
+
line-height: 1.5;
|
|
11638
|
+
}
|
|
11639
|
+
.brain-pillar-actions {
|
|
11640
|
+
display: flex;
|
|
11641
|
+
gap: 8px;
|
|
11642
|
+
flex-wrap: wrap;
|
|
11643
|
+
margin-top: auto;
|
|
11644
|
+
}
|
|
11645
|
+
.brain-kpi-row {
|
|
11646
|
+
display: grid;
|
|
11647
|
+
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
11648
|
+
gap: 10px;
|
|
11649
|
+
}
|
|
11650
|
+
.brain-kpi {
|
|
11651
|
+
border: 1px solid var(--border);
|
|
11652
|
+
border-radius: var(--radius-sm);
|
|
11653
|
+
background: var(--bg-secondary);
|
|
11654
|
+
padding: 12px;
|
|
11655
|
+
}
|
|
11656
|
+
.brain-kpi .value {
|
|
11657
|
+
font-size: 22px;
|
|
11658
|
+
font-weight: 700;
|
|
11659
|
+
color: var(--text-primary);
|
|
11660
|
+
line-height: 1.1;
|
|
11661
|
+
}
|
|
11662
|
+
.brain-kpi .label {
|
|
11663
|
+
font-size: 11px;
|
|
11664
|
+
color: var(--text-muted);
|
|
11665
|
+
text-transform: uppercase;
|
|
11666
|
+
letter-spacing: 0.04em;
|
|
11667
|
+
margin-top: 4px;
|
|
11668
|
+
}
|
|
11669
|
+
.brain-library-toolbar {
|
|
11670
|
+
display: flex;
|
|
11671
|
+
align-items: center;
|
|
11672
|
+
gap: 8px;
|
|
11673
|
+
flex-wrap: wrap;
|
|
11674
|
+
}
|
|
11675
|
+
.brain-library-toolbar input {
|
|
11676
|
+
flex: 1;
|
|
11677
|
+
min-width: 220px;
|
|
11678
|
+
}
|
|
11679
|
+
.brain-result-row {
|
|
11680
|
+
border: 1px solid var(--border);
|
|
11681
|
+
border-radius: var(--radius);
|
|
11682
|
+
background: var(--bg-card);
|
|
11683
|
+
padding: 13px 15px;
|
|
11684
|
+
margin-bottom: 10px;
|
|
11685
|
+
}
|
|
11686
|
+
.brain-result-row:hover { border-color: var(--accent); }
|
|
11687
|
+
.brain-result-top {
|
|
11688
|
+
display: flex;
|
|
11689
|
+
justify-content: space-between;
|
|
11690
|
+
align-items: flex-start;
|
|
11691
|
+
gap: 12px;
|
|
11692
|
+
}
|
|
11693
|
+
.brain-result-title {
|
|
11694
|
+
font-weight: 600;
|
|
11695
|
+
font-size: 13px;
|
|
11696
|
+
color: var(--text-primary);
|
|
11697
|
+
overflow-wrap: anywhere;
|
|
11698
|
+
}
|
|
11699
|
+
.brain-result-subtitle {
|
|
11700
|
+
font-family: 'JetBrains Mono', monospace;
|
|
11701
|
+
font-size: 11px;
|
|
11702
|
+
color: var(--text-muted);
|
|
11703
|
+
margin-top: 3px;
|
|
11704
|
+
overflow-wrap: anywhere;
|
|
11705
|
+
}
|
|
11706
|
+
.brain-result-preview {
|
|
11707
|
+
font-size: 12px;
|
|
11708
|
+
color: var(--text-secondary);
|
|
11709
|
+
line-height: 1.55;
|
|
11710
|
+
margin-top: 8px;
|
|
11711
|
+
white-space: pre-wrap;
|
|
11712
|
+
max-height: 112px;
|
|
11713
|
+
overflow: hidden;
|
|
11714
|
+
}
|
|
11715
|
+
.brain-badge {
|
|
11716
|
+
display: inline-flex;
|
|
11717
|
+
align-items: center;
|
|
11718
|
+
border: 1px solid var(--border);
|
|
11719
|
+
border-radius: 999px;
|
|
11720
|
+
padding: 2px 7px;
|
|
11721
|
+
font-size: 10px;
|
|
11722
|
+
color: var(--text-secondary);
|
|
11723
|
+
background: var(--bg-secondary);
|
|
11724
|
+
white-space: nowrap;
|
|
11725
|
+
}
|
|
11726
|
+
.brain-flow-list {
|
|
11727
|
+
border: 1px solid var(--border);
|
|
11728
|
+
border-radius: var(--radius);
|
|
11729
|
+
background: var(--bg-card);
|
|
11730
|
+
overflow: hidden;
|
|
11731
|
+
}
|
|
11732
|
+
.brain-flow-row {
|
|
11733
|
+
display: grid;
|
|
11734
|
+
grid-template-columns: minmax(140px, 1.2fr) 100px repeat(4, 72px) minmax(120px, 1fr);
|
|
11735
|
+
gap: 8px;
|
|
11736
|
+
align-items: center;
|
|
11737
|
+
padding: 10px 12px;
|
|
11738
|
+
border-bottom: 1px solid var(--border-light);
|
|
11739
|
+
font-size: 12px;
|
|
11740
|
+
}
|
|
11741
|
+
.brain-flow-row:last-child { border-bottom: none; }
|
|
11742
|
+
.brain-source-card {
|
|
11743
|
+
border: 1px solid var(--border);
|
|
11744
|
+
border-radius: var(--radius);
|
|
11745
|
+
background: var(--bg-card);
|
|
11746
|
+
padding: 12px;
|
|
11747
|
+
display: flex;
|
|
11748
|
+
align-items: flex-start;
|
|
11749
|
+
justify-content: space-between;
|
|
11750
|
+
gap: 12px;
|
|
11751
|
+
margin-bottom: 10px;
|
|
11752
|
+
}
|
|
11753
|
+
.brain-drop-zone {
|
|
11754
|
+
border: 1px dashed var(--border-light);
|
|
11755
|
+
border-radius: var(--radius);
|
|
11756
|
+
background: var(--bg-secondary);
|
|
11757
|
+
padding: 18px;
|
|
11758
|
+
display: flex;
|
|
11759
|
+
align-items: center;
|
|
11760
|
+
justify-content: space-between;
|
|
11761
|
+
gap: 14px;
|
|
11762
|
+
flex-wrap: wrap;
|
|
11763
|
+
}
|
|
11764
|
+
.brain-drop-zone.dragover {
|
|
11765
|
+
border-color: var(--accent);
|
|
11766
|
+
background: var(--accent-glow);
|
|
11767
|
+
}
|
|
11768
|
+
.brain-kv-builder {
|
|
11769
|
+
display: flex;
|
|
11770
|
+
flex-direction: column;
|
|
11771
|
+
gap: 6px;
|
|
11772
|
+
min-width: 0;
|
|
11773
|
+
}
|
|
11774
|
+
.brain-kv-row {
|
|
11775
|
+
display: grid;
|
|
11776
|
+
grid-template-columns: minmax(120px, 1fr) minmax(160px, 1.5fr) 30px;
|
|
11777
|
+
gap: 6px;
|
|
11778
|
+
align-items: center;
|
|
11779
|
+
}
|
|
11780
|
+
.brain-kv-row input {
|
|
11781
|
+
padding: 7px 9px;
|
|
11782
|
+
font-size: 12px;
|
|
11783
|
+
}
|
|
11784
|
+
@media (max-width: 760px) {
|
|
11785
|
+
.brain-flow-row {
|
|
11786
|
+
grid-template-columns: 1fr;
|
|
11787
|
+
gap: 3px;
|
|
11788
|
+
}
|
|
11789
|
+
.brain-result-top {
|
|
11790
|
+
flex-direction: column;
|
|
11791
|
+
}
|
|
11792
|
+
.brain-kv-row {
|
|
11793
|
+
grid-template-columns: 1fr;
|
|
11794
|
+
}
|
|
11795
|
+
}
|
|
11796
|
+
|
|
11315
11797
|
/* ── Toast ──────────────────────────────── */
|
|
11316
11798
|
.toast-container {
|
|
11317
11799
|
position: fixed;
|
|
@@ -13519,7 +14001,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13519
14001
|
<div class="page" id="page-build">
|
|
13520
14002
|
<div class="tab-bar" id="build-tabs" style="margin:0;padding:0 18px;background:var(--bg-secondary);border-bottom:1px solid var(--border)">
|
|
13521
14003
|
<button class="active" data-build-tab="workflows" data-icon="workflow" onclick="switchBuildTab('workflows')"><span class="icon-slot"></span> Workflows</button>
|
|
13522
|
-
<button data-build-tab="crons" data-icon="clock" onclick="switchBuildTab('crons')"><span class="icon-slot"></span>
|
|
14004
|
+
<button data-build-tab="crons" data-icon="clock" onclick="switchBuildTab('crons')"><span class="icon-slot"></span> Scheduled Tasks <span class="tab-badge" id="build-tab-cron-count" style="display:none">0</span></button>
|
|
13523
14005
|
<button data-build-tab="skills" data-icon="shield" onclick="switchBuildTab('skills')"><span class="icon-slot"></span> Skills <span class="tab-badge" id="build-tab-skill-count" style="display:none">0</span></button>
|
|
13524
14006
|
<button data-build-tab="templates" data-icon="fileText" onclick="switchBuildTab('templates')"><span class="icon-slot"></span> Templates</button>
|
|
13525
14007
|
</div>
|
|
@@ -13550,10 +14032,10 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13550
14032
|
<div class="empty-state" id="builder-empty-state" style="margin-top:40px">
|
|
13551
14033
|
<p style="color:var(--text-muted);margin-bottom:12px">Describe what you want to build.</p>
|
|
13552
14034
|
<div style="display:flex;flex-wrap:wrap;gap:8px;justify-content:center">
|
|
13553
|
-
<button class="btn btn-sm quick-pill" onclick="builderQuick('Create a cron job that checks my email every morning and sends me a summary')">Email summary cron</button>
|
|
13554
|
-
<button class="btn btn-sm quick-pill" onclick="builderQuick('Create an SDR agent that researches leads and drafts outreach emails')">SDR agent</button>
|
|
13555
|
-
<button class="btn btn-sm quick-pill" onclick="builderQuick('Build a weekly analytics report that checks SEO rankings')">Weekly SEO report</button>
|
|
13556
14035
|
<button class="btn btn-sm quick-pill" onclick="builderQuick('Create a workflow that researches a topic, writes a draft, and sends it for review')">Research workflow</button>
|
|
14036
|
+
<button class="btn btn-sm quick-pill" onclick="builderQuick('Create a workflow that reviews open PRs, summarizes risk, and sends a digest')">PR review digest</button>
|
|
14037
|
+
<button class="btn btn-sm quick-pill" onclick="builderQuick('Create a workflow that collects leads, scores them against my ICP, and prepares outreach drafts')">Lead research flow</button>
|
|
14038
|
+
<button class="btn btn-sm quick-pill" onclick="builderQuick('Create a workflow that reviews recent notes, extracts open items, and drafts next priorities')">Weekly review workflow</button>
|
|
13557
14039
|
</div>
|
|
13558
14040
|
</div>
|
|
13559
14041
|
</div>
|
|
@@ -13603,8 +14085,6 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13603
14085
|
<div onclick="_builderAddNodeOfKind('mcp')" class="builder-palette-item" data-kind="mcp">mcp tool</div>
|
|
13604
14086
|
<div onclick="_builderAddNodeOfKind('channel')" class="builder-palette-item" data-kind="channel">channel</div>
|
|
13605
14087
|
<div onclick="_builderAddNodeOfKind('transform')" class="builder-palette-item" data-kind="transform">transform</div>
|
|
13606
|
-
<div onclick="_builderAddNodeOfKind('conditional')" class="builder-palette-item" data-kind="conditional">conditional</div>
|
|
13607
|
-
<div onclick="_builderAddNodeOfKind('loop')" class="builder-palette-item" data-kind="loop">loop</div>
|
|
13608
14088
|
</div>
|
|
13609
14089
|
<!-- Slide-out config panel -->
|
|
13610
14090
|
<div id="builder-config-panel" style="display:none;position:absolute;right:0;top:0;bottom:0;width:340px;background:var(--bg-secondary);border-left:1px solid var(--border);box-shadow:-4px 0 16px rgba(0,0,0,0.15);z-index:12;flex-direction:column"></div>
|
|
@@ -13634,6 +14114,18 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13634
14114
|
</div>
|
|
13635
14115
|
</div>
|
|
13636
14116
|
|
|
14117
|
+
<!-- Scheduled Tasks tab — simple recurring-task management. The visual canvas is for workflows. -->
|
|
14118
|
+
<div id="build-tab-crons" data-build-tabpane="crons" style="display:none;flex:1;min-height:0;overflow-y:auto;padding:18px;background:var(--bg-primary)">
|
|
14119
|
+
<div style="display:flex;align-items:flex-start;gap:14px;margin-bottom:16px;flex-wrap:wrap">
|
|
14120
|
+
<div style="flex:1;min-width:260px">
|
|
14121
|
+
<h2 style="font-size:18px;font-weight:600;margin:0 0 4px;color:var(--text-primary)">Scheduled Tasks</h2>
|
|
14122
|
+
<p style="font-size:13px;color:var(--text-muted);margin:0;line-height:1.45">Create and tune recurring agent jobs. Use workflows only when the job needs an explicit multi-step canvas.</p>
|
|
14123
|
+
</div>
|
|
14124
|
+
<button class="btn-sm btn-primary" onclick="newFromBuildHeader()" style="padding:7px 14px;border-radius:6px;cursor:pointer;font-size:12px">New Scheduled Task</button>
|
|
14125
|
+
</div>
|
|
14126
|
+
<div id="panel-cron"></div>
|
|
14127
|
+
</div>
|
|
14128
|
+
|
|
13637
14129
|
<!-- Templates tab — starter patterns -->
|
|
13638
14130
|
<div id="build-tab-templates" data-build-tabpane="templates" style="display:none;padding:24px;overflow-y:auto">
|
|
13639
14131
|
<div style="max-width:920px;margin:0 auto">
|
|
@@ -13643,8 +14135,8 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13643
14135
|
<div class="card clickable-row" onclick="forkBuildTemplate('daily-news-digest')" style="padding:18px">
|
|
13644
14136
|
<div style="font-size:24px;margin-bottom:8px">📰</div>
|
|
13645
14137
|
<div style="font-weight:600;font-size:14px;margin-bottom:4px">Daily news digest</div>
|
|
13646
|
-
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">
|
|
13647
|
-
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">
|
|
14138
|
+
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">Scheduled 7am: pull RSS sources, summarize, send to Slack/email.</div>
|
|
14139
|
+
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">scheduled workflow · 4 steps</div>
|
|
13648
14140
|
</div>
|
|
13649
14141
|
<div class="card clickable-row" onclick="forkBuildTemplate('lead-picker')" style="padding:18px">
|
|
13650
14142
|
<div style="font-size:24px;margin-bottom:8px">📊</div>
|
|
@@ -13655,20 +14147,20 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13655
14147
|
<div class="card clickable-row" onclick="forkBuildTemplate('pr-review-queue')" style="padding:18px">
|
|
13656
14148
|
<div style="font-size:24px;margin-bottom:8px">📝</div>
|
|
13657
14149
|
<div style="font-weight:600;font-size:14px;margin-bottom:4px">PR review queue</div>
|
|
13658
|
-
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">
|
|
13659
|
-
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">
|
|
14150
|
+
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">Scheduled 9am M-F: list open PRs, summarize risk, message to Slack.</div>
|
|
14151
|
+
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">scheduled workflow · 3 steps</div>
|
|
13660
14152
|
</div>
|
|
13661
14153
|
<div class="card clickable-row" onclick="forkBuildTemplate('email-triage')" style="padding:18px">
|
|
13662
14154
|
<div style="font-size:24px;margin-bottom:8px">📧</div>
|
|
13663
14155
|
<div style="font-weight:600;font-size:14px;margin-bottom:4px">Email triage</div>
|
|
13664
|
-
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">
|
|
13665
|
-
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">
|
|
14156
|
+
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">Scheduled 8am: list unread emails, classify by intent, draft replies for review.</div>
|
|
14157
|
+
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">scheduled workflow · 4 steps</div>
|
|
13666
14158
|
</div>
|
|
13667
14159
|
<div class="card clickable-row" onclick="forkBuildTemplate('weekly-review')" style="padding:18px">
|
|
13668
14160
|
<div style="font-size:24px;margin-bottom:8px">📅</div>
|
|
13669
14161
|
<div style="font-weight:600;font-size:14px;margin-bottom:4px">Weekly review</div>
|
|
13670
|
-
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">
|
|
13671
|
-
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">
|
|
14162
|
+
<div style="font-size:12px;color:var(--text-muted);line-height:1.4">Scheduled Fri 6pm: review the week's daily notes, generate review note.</div>
|
|
14163
|
+
<div style="margin-top:10px;font-size:11px;color:var(--clementine);font-weight:500">scheduled workflow · 3 steps</div>
|
|
13672
14164
|
</div>
|
|
13673
14165
|
<div class="card clickable-row" onclick="forkBuildTemplate('blank-workflow')" style="padding:18px;border-style:dashed">
|
|
13674
14166
|
<div style="font-size:24px;margin-bottom:8px">➕</div>
|
|
@@ -13689,7 +14181,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13689
14181
|
si-* status cards/proposals/history, teach-skill-form, panel-skills,
|
|
13690
14182
|
pending-skills-card, panel-workflows, advisor-analytics-content.) -->
|
|
13691
14183
|
<!-- (Session 5) page-automations parking removed. Self-Improve now lives in
|
|
13692
|
-
Brain → Learning; Build (Workflows/
|
|
14184
|
+
Brain → Learning; Build (Workflows/Scheduled Tasks/Skills/Templates) is the home for
|
|
13693
14185
|
everything else that was here. -->
|
|
13694
14186
|
|
|
13695
14187
|
<!-- page-team-status merged into Team → Activity tab.
|
|
@@ -13744,9 +14236,10 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13744
14236
|
<h1>Brain</h1>
|
|
13745
14237
|
<p class="desc">Query what you know, feed new knowledge in, and watch the system learn.</p>
|
|
13746
14238
|
</div>
|
|
13747
|
-
<div class="actions" style="flex:1;max-width:
|
|
13748
|
-
<input type="text" id="memory-search-input" placeholder="
|
|
13749
|
-
<button class="btn-primary btn-sm" onclick="
|
|
14239
|
+
<div class="actions" style="flex:1;max-width:640px;display:flex;gap:8px">
|
|
14240
|
+
<input type="text" id="memory-search-input" placeholder="Find seeded files, memories, notes, and artifacts..." style="flex:1;padding:6px 10px;border:1px solid var(--border);border-radius:6px;background:var(--bg-input);color:var(--text-primary);font-size:13px" onkeydown="if(event.key==='Enter')brainUnifiedSearchFromHeader()">
|
|
14241
|
+
<button class="btn-primary btn-sm" onclick="brainUnifiedSearchFromHeader()" title="Search the whole brain"><span class="icon-slot" data-icon="search"></span> Find</button>
|
|
14242
|
+
<button class="btn-sm" onclick="switchTab('intelligence','seed')" title="Upload a local file or folder"><span class="icon-slot" data-icon="upload"></span> Seed</button>
|
|
13750
14243
|
<button class="btn-sm" onclick="openQuickAddMemory()" title="Append a quick note to today's daily log">+ Add memory</button>
|
|
13751
14244
|
</div>
|
|
13752
14245
|
</div>
|
|
@@ -13779,18 +14272,109 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13779
14272
|
</div>
|
|
13780
14273
|
</div>
|
|
13781
14274
|
<div class="tab-bar" id="intelligence-tabs" style="margin:0 0 0 18px">
|
|
13782
|
-
<button class="active" data-icon="
|
|
14275
|
+
<button class="active" data-icon="layoutDashboard" onclick="switchTab('intelligence','overview')"><span class="icon-slot"></span> Overview</button>
|
|
14276
|
+
<button data-icon="database" onclick="switchTab('intelligence','search')"><span class="icon-slot"></span> Memory</button>
|
|
14277
|
+
<button data-icon="upload" onclick="switchTab('intelligence','seed')"><span class="icon-slot"></span> Seed</button>
|
|
14278
|
+
<button data-icon="repeat" onclick="switchTab('intelligence','sources')"><span class="icon-slot"></span> Automate</button>
|
|
14279
|
+
<button data-icon="listChecks" onclick="switchTab('intelligence','runs')"><span class="icon-slot"></span> Runs</button>
|
|
13783
14280
|
<button data-icon="sparkles" onclick="switchTab('intelligence','graph')"><span class="icon-slot"></span> Knowledge</button>
|
|
13784
14281
|
<button data-icon="fileText" onclick="switchTab('intelligence','files')"><span class="icon-slot"></span> Files</button>
|
|
13785
|
-
<button data-icon="folder" onclick="switchTab('intelligence','sources')"><span class="icon-slot"></span> Ingestion</button>
|
|
13786
14282
|
<button data-icon="zap" onclick="switchTab('intelligence','health')"><span class="icon-slot"></span> Health <span class="tab-badge" id="brain-health-badge" style="display:none;background:#ef4444;color:#fff">0</span></button>
|
|
13787
14283
|
<button data-icon="users" onclick="switchTab('intelligence','user-model')"><span class="icon-slot"></span> User Model</button>
|
|
13788
14284
|
<button data-icon="brain" onclick="switchTab('intelligence','learning')"><span class="icon-slot"></span> Learning <span class="tab-badge" id="brain-learning-badge" style="display:none;background:#f59e0b;color:#000">0</span></button>
|
|
13789
|
-
<button onclick="switchTab('intelligence','seed')">Seed</button>
|
|
13790
|
-
<button onclick="switchTab('intelligence','runs')">Runs</button>
|
|
13791
14285
|
</div>
|
|
13792
14286
|
<div id="intelligence-tab-content">
|
|
13793
|
-
<div class="tab-pane active" id="tab-intelligence-
|
|
14287
|
+
<div class="tab-pane active" id="tab-intelligence-overview">
|
|
14288
|
+
<div class="brain-command-shell">
|
|
14289
|
+
<div class="brain-hero-panel">
|
|
14290
|
+
<div style="display:flex;justify-content:space-between;gap:16px;align-items:flex-start;flex-wrap:wrap;margin-bottom:14px">
|
|
14291
|
+
<div style="max-width:720px">
|
|
14292
|
+
<div style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Brain command center</div>
|
|
14293
|
+
<div style="font-size:18px;font-weight:700;margin-bottom:5px">Find anything Clementine knows, then prove how it got there.</div>
|
|
14294
|
+
<div style="font-size:13px;color:var(--text-secondary);line-height:1.5">Use this page to seed local data, keep connected sources refreshed on a schedule, search agent-created artifacts, and verify retrieval coverage.</div>
|
|
14295
|
+
</div>
|
|
14296
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
14297
|
+
<button class="btn-primary btn-sm" onclick="switchTab('intelligence','seed')"><span class="icon-slot" data-icon="upload"></span> Seed local data</button>
|
|
14298
|
+
<button class="btn-sm" onclick="switchTab('intelligence','sources')"><span class="icon-slot" data-icon="repeat"></span> Add scheduled feed</button>
|
|
14299
|
+
<button class="btn-sm" onclick="switchTab('intelligence','health')"><span class="icon-slot" data-icon="activity"></span> Verify health</button>
|
|
14300
|
+
</div>
|
|
14301
|
+
</div>
|
|
14302
|
+
<div id="brain-command-kpis" class="brain-kpi-row">
|
|
14303
|
+
<div class="skel-block"><div class="skel-row med"></div><div class="skel-row short"></div></div>
|
|
14304
|
+
<div class="skel-block"><div class="skel-row med"></div><div class="skel-row short"></div></div>
|
|
14305
|
+
<div class="skel-block"><div class="skel-row med"></div><div class="skel-row short"></div></div>
|
|
14306
|
+
</div>
|
|
14307
|
+
</div>
|
|
14308
|
+
|
|
14309
|
+
<div class="brain-pillar-grid">
|
|
14310
|
+
<div class="brain-pillar-card">
|
|
14311
|
+
<strong>Find</strong>
|
|
14312
|
+
<p>Search memories, seeded records, vault files, and saved tool artifacts in one place.</p>
|
|
14313
|
+
<div class="brain-pillar-actions">
|
|
14314
|
+
<button class="btn-sm btn-primary" onclick="focusBrainLibrarySearch()">Search library</button>
|
|
14315
|
+
<button class="btn-sm" onclick="switchTab('intelligence','files')">Browse files</button>
|
|
14316
|
+
</div>
|
|
14317
|
+
</div>
|
|
14318
|
+
<div class="brain-pillar-card">
|
|
14319
|
+
<strong>Seed</strong>
|
|
14320
|
+
<p>Choose files or folders from the local machine, preview what will be written, then commit to memory.</p>
|
|
14321
|
+
<div class="brain-pillar-actions">
|
|
14322
|
+
<button class="btn-sm btn-primary" onclick="switchTab('intelligence','seed')">Upload data</button>
|
|
14323
|
+
<button class="btn-sm" onclick="document.getElementById('brain-file-input')?.click()">Choose files</button>
|
|
14324
|
+
</div>
|
|
14325
|
+
</div>
|
|
14326
|
+
<div class="brain-pillar-card">
|
|
14327
|
+
<strong>Automate</strong>
|
|
14328
|
+
<p>Create scheduled feeds for REST endpoints or connected apps so the brain keeps learning without manual uploads.</p>
|
|
14329
|
+
<div class="brain-pillar-actions">
|
|
14330
|
+
<button class="btn-sm btn-primary" onclick="switchTab('intelligence','sources');setTimeout(brainShowPollForm,80)">REST feed</button>
|
|
14331
|
+
<button class="btn-sm" onclick="switchTab('intelligence','sources');setTimeout(brainOpenFeedWizard,80)">Connected app</button>
|
|
14332
|
+
</div>
|
|
14333
|
+
</div>
|
|
14334
|
+
<div class="brain-pillar-card">
|
|
14335
|
+
<strong>Verify</strong>
|
|
14336
|
+
<p>Check dense model readiness, retrieval coverage, ingestion runs, and whether new data is actually searchable.</p>
|
|
14337
|
+
<div class="brain-pillar-actions">
|
|
14338
|
+
<button class="btn-sm btn-primary" onclick="switchTab('intelligence','health')">Open health</button>
|
|
14339
|
+
<button class="btn-sm" onclick="switchTab('intelligence','runs')">View runs</button>
|
|
14340
|
+
</div>
|
|
14341
|
+
</div>
|
|
14342
|
+
</div>
|
|
14343
|
+
|
|
14344
|
+
<div class="brain-hero-panel">
|
|
14345
|
+
<div class="brain-library-toolbar" style="margin-bottom:12px">
|
|
14346
|
+
<input id="brain-library-search-input" type="text" placeholder="Search the whole brain..." onkeydown="if(event.key==='Enter')runBrainLibrarySearch()">
|
|
14347
|
+
<select id="brain-library-scope" onchange="runBrainLibrarySearch()" style="width:150px">
|
|
14348
|
+
<option value="all">Everything</option>
|
|
14349
|
+
<option value="memory">Memory</option>
|
|
14350
|
+
<option value="files">Files</option>
|
|
14351
|
+
<option value="artifacts">Artifacts</option>
|
|
14352
|
+
</select>
|
|
14353
|
+
<button class="btn-primary btn-sm" onclick="runBrainLibrarySearch()">Search</button>
|
|
14354
|
+
<button class="btn-sm" onclick="runBrainLibrarySearch('')">Recent</button>
|
|
14355
|
+
</div>
|
|
14356
|
+
<div id="brain-library-summary" style="font-size:12px;color:var(--text-muted);margin-bottom:10px"></div>
|
|
14357
|
+
<div id="brain-library-results">
|
|
14358
|
+
<div class="empty-state" style="padding:20px">Search the whole brain, or click Recent to inspect the latest remembered items.</div>
|
|
14359
|
+
</div>
|
|
14360
|
+
</div>
|
|
14361
|
+
|
|
14362
|
+
<div>
|
|
14363
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px">
|
|
14364
|
+
<div style="font-weight:600">Recent knowledge flow</div>
|
|
14365
|
+
<button class="btn-sm" onclick="refreshBrainOverview()">Refresh</button>
|
|
14366
|
+
</div>
|
|
14367
|
+
<div id="brain-overview-flow"><div class="skel-block"><div class="skel-row med"></div><div class="skel-row"></div></div></div>
|
|
14368
|
+
</div>
|
|
14369
|
+
</div>
|
|
14370
|
+
</div>
|
|
14371
|
+
<div class="tab-pane" id="tab-intelligence-search">
|
|
14372
|
+
<div style="display:flex;gap:8px;align-items:center;margin-bottom:12px;flex-wrap:wrap">
|
|
14373
|
+
<input type="text" id="memory-detail-search-input" placeholder="Search editable memory chunks..." style="flex:1;min-width:220px" onkeydown="if(event.key==='Enter')runMemoryDetailSearch()">
|
|
14374
|
+
<button class="btn-primary btn-sm" onclick="runMemoryDetailSearch()">Search chunks</button>
|
|
14375
|
+
<button class="btn-sm" onclick="document.getElementById('memory-detail-search-input').value='pinned:true';runMemoryDetailSearch()">Pinned</button>
|
|
14376
|
+
<button class="btn-sm" onclick="document.getElementById('memory-detail-search-input').value='since:7d';runMemoryDetailSearch()">Last 7d</button>
|
|
14377
|
+
</div>
|
|
13794
14378
|
<div id="memory-coverage-strip" style="margin-bottom:14px"></div>
|
|
13795
14379
|
<div id="memory-search-results"></div>
|
|
13796
14380
|
<div id="memory-overview" style="margin-top:18px">
|
|
@@ -13861,18 +14445,24 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13861
14445
|
<div class="card" style="padding:20px;margin-bottom:16px">
|
|
13862
14446
|
<div style="font-weight:600;margin-bottom:8px">Drop a file or folder into the brain</div>
|
|
13863
14447
|
<div style="color:var(--muted);margin-bottom:12px;font-size:13px">
|
|
13864
|
-
Supports CSV, JSON, JSONL, Markdown, PDF, email (.eml / .mbox), DOCX. Preview runs the first 10 records through the full pipeline without writing anything;
|
|
14448
|
+
Supports CSV, JSON, JSONL, Markdown, PDF, email (.eml / .mbox), DOCX. Preview runs the first 10 records through the full pipeline without writing anything; Save to brain writes the full source.
|
|
13865
14449
|
</div>
|
|
13866
14450
|
|
|
13867
14451
|
<!-- Primary: native file/folder pickers -->
|
|
13868
|
-
<div
|
|
13869
|
-
<
|
|
13870
|
-
|
|
13871
|
-
|
|
14452
|
+
<div id="brain-drop-zone" class="brain-drop-zone" ondragover="brainHandleDrag(event, true)" ondragleave="brainHandleDrag(event, false)" ondrop="brainHandleDrop(event)">
|
|
14453
|
+
<div style="min-width:220px;flex:1">
|
|
14454
|
+
<div style="font-weight:600;margin-bottom:4px">Upload local knowledge</div>
|
|
14455
|
+
<div style="font-size:12px;color:var(--text-muted);line-height:1.5">Drop files here, choose a folder, or use the advanced path option for data already on this machine. Clementine previews records before writing anything.</div>
|
|
14456
|
+
</div>
|
|
14457
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
|
14458
|
+
<button class="btn-primary" onclick="document.getElementById('brain-file-input').click()" type="button"><span class="icon-slot" data-icon="fileText"></span> Choose files</button>
|
|
14459
|
+
<button class="btn-primary" onclick="document.getElementById('brain-folder-input').click()" type="button"><span class="icon-slot" data-icon="folder"></span> Choose folder</button>
|
|
14460
|
+
<input type="text" id="brain-seed-slug" placeholder="source name (optional)" style="width:220px">
|
|
14461
|
+
</div>
|
|
13872
14462
|
</div>
|
|
13873
14463
|
<input type="file" id="brain-file-input" multiple style="display:none" onchange="brainHandleFilesChosen(this.files, false)">
|
|
13874
14464
|
<input type="file" id="brain-folder-input" webkitdirectory directory multiple style="display:none" onchange="brainHandleFilesChosen(this.files, true)">
|
|
13875
|
-
<div id="brain-upload-status" style="margin
|
|
14465
|
+
<div id="brain-upload-status" style="margin:8px 0;color:var(--muted);font-size:13px"></div>
|
|
13876
14466
|
|
|
13877
14467
|
<!-- Secondary: for power users who want to point at an existing on-disk path -->
|
|
13878
14468
|
<details style="margin-bottom:8px">
|
|
@@ -13883,8 +14473,8 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13883
14473
|
</details>
|
|
13884
14474
|
|
|
13885
14475
|
<div style="display:flex;gap:8px;margin-top:8px">
|
|
13886
|
-
<button class="btn-primary" onclick="brainPreviewSeed()">Preview</button>
|
|
13887
|
-
<button class="btn-primary" id="brain-commit-btn" onclick="brainCommitSeed()" style="display:none">
|
|
14476
|
+
<button class="btn-primary" onclick="brainPreviewSeed()">Preview records</button>
|
|
14477
|
+
<button class="btn-primary" id="brain-commit-btn" onclick="brainCommitSeed()" style="display:none">Save to brain</button>
|
|
13888
14478
|
</div>
|
|
13889
14479
|
|
|
13890
14480
|
<div id="brain-seed-manifest" style="margin-top:16px"></div>
|
|
@@ -13962,14 +14552,25 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
13962
14552
|
<input type="text" id="brain-poll-url" placeholder="https://api.example.com/v1/items">
|
|
13963
14553
|
<label>Method</label>
|
|
13964
14554
|
<select id="brain-poll-method"><option>GET</option><option>POST</option></select>
|
|
13965
|
-
<label>Headers
|
|
13966
|
-
<
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
14555
|
+
<label>Headers</label>
|
|
14556
|
+
<div class="brain-kv-builder">
|
|
14557
|
+
<div id="brain-poll-headers-rows"></div>
|
|
14558
|
+
<button class="btn-sm" type="button" onclick="brainAddKvRow('headers')">Add header</button>
|
|
14559
|
+
<input type="hidden" id="brain-poll-headers">
|
|
14560
|
+
</div>
|
|
14561
|
+
<label>Query params</label>
|
|
14562
|
+
<div class="brain-kv-builder">
|
|
14563
|
+
<div id="brain-poll-params-rows"></div>
|
|
14564
|
+
<button class="btn-sm" type="button" onclick="brainAddKvRow('params')">Add param</button>
|
|
14565
|
+
<input type="hidden" id="brain-poll-params">
|
|
14566
|
+
</div>
|
|
14567
|
+
<label>Record list field</label>
|
|
14568
|
+
<input type="text" id="brain-poll-recordspath" placeholder="data, items, results">
|
|
13971
14569
|
<label>Cron schedule</label>
|
|
13972
|
-
<
|
|
14570
|
+
<div>
|
|
14571
|
+
<input type="text" id="brain-poll-cron" placeholder="0 * * * * (hourly)">
|
|
14572
|
+
<div id="brain-poll-schedule-chips" style="display:flex;gap:6px;flex-wrap:wrap;margin-top:6px"></div>
|
|
14573
|
+
</div>
|
|
13973
14574
|
<label>Target folder</label>
|
|
13974
14575
|
<input type="text" id="brain-poll-folder" placeholder="04-Ingest/stripe">
|
|
13975
14576
|
<label>Project (optional)</label>
|
|
@@ -14181,6 +14782,269 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
14181
14782
|
error: 'Error',
|
|
14182
14783
|
};
|
|
14183
14784
|
|
|
14785
|
+
function brainTypeLabel(kind) {
|
|
14786
|
+
if (kind === 'memory') return 'Memory';
|
|
14787
|
+
if (kind === 'file') return 'File';
|
|
14788
|
+
if (kind === 'artifact') return 'Artifact';
|
|
14789
|
+
return kind || 'Item';
|
|
14790
|
+
}
|
|
14791
|
+
|
|
14792
|
+
function brainStatusBadge(status) {
|
|
14793
|
+
var s = String(status || 'unknown');
|
|
14794
|
+
var color = s === 'ok' ? 'var(--green)' : (s === 'partial' ? 'var(--yellow)' : (s === 'error' ? 'var(--red)' : 'var(--text-muted)'));
|
|
14795
|
+
return '<span class="brain-badge" style="color:' + color + ';border-color:' + color + '33">' + escapeHtml(s) + '</span>';
|
|
14796
|
+
}
|
|
14797
|
+
|
|
14798
|
+
function brainUnifiedSearchFromHeader() {
|
|
14799
|
+
var header = document.getElementById('memory-search-input');
|
|
14800
|
+
var q = header ? header.value.trim() : '';
|
|
14801
|
+
switchTab('intelligence', 'overview');
|
|
14802
|
+
setTimeout(function() {
|
|
14803
|
+
var input = document.getElementById('brain-library-search-input');
|
|
14804
|
+
if (input) input.value = q;
|
|
14805
|
+
runBrainLibrarySearch(q);
|
|
14806
|
+
}, 60);
|
|
14807
|
+
}
|
|
14808
|
+
|
|
14809
|
+
function focusBrainLibrarySearch() {
|
|
14810
|
+
switchTab('intelligence', 'overview');
|
|
14811
|
+
setTimeout(function() {
|
|
14812
|
+
var input = document.getElementById('brain-library-search-input');
|
|
14813
|
+
if (input) input.focus();
|
|
14814
|
+
}, 80);
|
|
14815
|
+
}
|
|
14816
|
+
|
|
14817
|
+
async function runBrainLibrarySearch(forceQuery) {
|
|
14818
|
+
var input = document.getElementById('brain-library-search-input');
|
|
14819
|
+
var header = document.getElementById('memory-search-input');
|
|
14820
|
+
var scopeEl = document.getElementById('brain-library-scope');
|
|
14821
|
+
var q = forceQuery !== undefined ? String(forceQuery || '') : (input ? input.value.trim() : '');
|
|
14822
|
+
if (input && forceQuery !== undefined) input.value = q;
|
|
14823
|
+
if (header && q) header.value = q;
|
|
14824
|
+
var scope = scopeEl ? scopeEl.value : 'all';
|
|
14825
|
+
var resultsEl = document.getElementById('brain-library-results');
|
|
14826
|
+
var summaryEl = document.getElementById('brain-library-summary');
|
|
14827
|
+
if (!resultsEl) return;
|
|
14828
|
+
resultsEl.innerHTML = '<div class="empty-state" style="padding:20px">Searching…</div>';
|
|
14829
|
+
if (summaryEl) summaryEl.textContent = '';
|
|
14830
|
+
try {
|
|
14831
|
+
var r = await apiFetch('/api/brain/library/search?q=' + encodeURIComponent(q) + '&scope=' + encodeURIComponent(scope) + '&limit=36');
|
|
14832
|
+
var d = await r.json();
|
|
14833
|
+
if (!r.ok || !d.ok) {
|
|
14834
|
+
resultsEl.innerHTML = '<div class="empty-state" style="color:var(--red)">Search failed: ' + escapeHtml(d.error || r.status) + '</div>';
|
|
14835
|
+
return;
|
|
14836
|
+
}
|
|
14837
|
+
var counts = d.totalByType || {};
|
|
14838
|
+
if (summaryEl) {
|
|
14839
|
+
var label = q ? ('Results for "' + q + '"') : 'Recent brain items';
|
|
14840
|
+
summaryEl.innerHTML = escapeHtml(label) + ' · '
|
|
14841
|
+
+ (counts.memory || 0) + ' memory · '
|
|
14842
|
+
+ (counts.files || 0) + ' files · '
|
|
14843
|
+
+ (counts.artifacts || 0) + ' artifacts';
|
|
14844
|
+
}
|
|
14845
|
+
if (!d.results || d.results.length === 0) {
|
|
14846
|
+
resultsEl.innerHTML = '<div class="empty-state" style="padding:20px">No matches. Try fewer words or switch the scope to Everything.</div>';
|
|
14847
|
+
return;
|
|
14848
|
+
}
|
|
14849
|
+
var html = '';
|
|
14850
|
+
for (var i = 0; i < d.results.length; i++) {
|
|
14851
|
+
var item = d.results[i];
|
|
14852
|
+
var badges = ['<span class="brain-badge">' + escapeHtml(brainTypeLabel(item.kind)) + '</span>'];
|
|
14853
|
+
(item.badges || []).slice(0, 4).forEach(function(b) {
|
|
14854
|
+
badges.push('<span class="brain-badge">' + escapeHtml(b) + '</span>');
|
|
14855
|
+
});
|
|
14856
|
+
var actions = '';
|
|
14857
|
+
if (item.kind === 'file' && item.relPath) {
|
|
14858
|
+
actions = '<button class="btn-sm" onclick="openVaultFile(\\'' + escapeHtml(item.relPath) + '\\')">Open</button>';
|
|
14859
|
+
} else if (item.kind === 'memory' && item.chunkId) {
|
|
14860
|
+
actions = '<button class="btn-sm" onclick="editChunk(' + item.chunkId + ')">Edit</button>'
|
|
14861
|
+
+ '<button class="btn-sm" onclick="openBrainChunkTrace(' + item.chunkId + ')">Trace</button>';
|
|
14862
|
+
} else if (item.kind === 'artifact' && item.artifactId) {
|
|
14863
|
+
actions = '<button class="btn-sm" onclick="openBrainArtifact(' + item.artifactId + ')">Open</button>';
|
|
14864
|
+
}
|
|
14865
|
+
html += '<div class="brain-result-row">'
|
|
14866
|
+
+ '<div class="brain-result-top">'
|
|
14867
|
+
+ '<div style="min-width:0;flex:1">'
|
|
14868
|
+
+ '<div class="brain-result-title">' + escapeHtml(item.title || '(untitled)') + '</div>'
|
|
14869
|
+
+ '<div class="brain-result-subtitle">' + escapeHtml(item.subtitle || item.source || '') + '</div>'
|
|
14870
|
+
+ '</div>'
|
|
14871
|
+
+ '<div style="display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end;align-items:center">' + badges.join('') + actions + '</div>'
|
|
14872
|
+
+ '</div>'
|
|
14873
|
+
+ (item.preview ? '<div class="brain-result-preview">' + escapeHtml(item.preview) + '</div>' : '')
|
|
14874
|
+
+ (item.timestamp ? '<div style="font-size:11px;color:var(--text-muted);margin-top:8px">' + escapeHtml(timeAgo(item.timestamp)) + '</div>' : '')
|
|
14875
|
+
+ '</div>';
|
|
14876
|
+
}
|
|
14877
|
+
resultsEl.innerHTML = html;
|
|
14878
|
+
} catch (err) {
|
|
14879
|
+
resultsEl.innerHTML = '<div class="empty-state" style="color:var(--red)">Search error: ' + escapeHtml(String(err)) + '</div>';
|
|
14880
|
+
}
|
|
14881
|
+
}
|
|
14882
|
+
|
|
14883
|
+
async function openBrainChunkTrace(id) {
|
|
14884
|
+
var drawer = document.getElementById('brain-chunk-trace-drawer');
|
|
14885
|
+
if (!drawer) {
|
|
14886
|
+
drawer = document.createElement('div');
|
|
14887
|
+
drawer.id = 'brain-chunk-trace-drawer';
|
|
14888
|
+
drawer.style.cssText = 'position:fixed;right:0;top:0;bottom:0;width:620px;max-width:94vw;background:var(--bg-secondary);border-left:1px solid var(--border);box-shadow:-8px 0 32px rgba(0,0,0,0.18);z-index:221;display:flex;flex-direction:column;transform:translateX(100%);transition:transform 200ms ease';
|
|
14889
|
+
drawer.innerHTML =
|
|
14890
|
+
'<div style="display:flex;align-items:center;gap:10px;padding:14px 18px;border-bottom:1px solid var(--border);flex-shrink:0">'
|
|
14891
|
+
+ '<div style="flex:1;min-width:0">'
|
|
14892
|
+
+ '<div id="brain-chunk-title" style="font-weight:600;font-size:15px"></div>'
|
|
14893
|
+
+ '<div id="brain-chunk-subtitle" style="font-size:11px;color:var(--text-muted);font-family:\\x27JetBrains Mono\\x27,monospace;margin-top:2px"></div>'
|
|
14894
|
+
+ '</div>'
|
|
14895
|
+
+ '<button class="btn-icon btn-sm" onclick="closeBrainChunkTrace()" title="Close">' + lucide('x', 'icn-sm') + '</button>'
|
|
14896
|
+
+ '</div>'
|
|
14897
|
+
+ '<div id="brain-chunk-body" style="flex:1;overflow:auto;padding:18px 22px;font-size:12px;line-height:1.55"></div>';
|
|
14898
|
+
document.body.appendChild(drawer);
|
|
14899
|
+
}
|
|
14900
|
+
drawer.style.transform = 'translateX(0)';
|
|
14901
|
+
document.getElementById('brain-chunk-title').textContent = 'Memory chunk #' + id;
|
|
14902
|
+
document.getElementById('brain-chunk-subtitle').textContent = 'Loading…';
|
|
14903
|
+
document.getElementById('brain-chunk-body').innerHTML = '<div class="skel-block"><div class="skel-row med"></div><div class="skel-row"></div></div>';
|
|
14904
|
+
try {
|
|
14905
|
+
var chunkResp = await apiFetch('/api/memory/chunks/' + id);
|
|
14906
|
+
var chunkData = await chunkResp.json();
|
|
14907
|
+
var historyResp = await apiFetch('/api/memory/chunks/' + id + '/history');
|
|
14908
|
+
var historyData = await historyResp.json();
|
|
14909
|
+
if (!chunkResp.ok || !chunkData.ok || !chunkData.chunk) throw new Error(chunkData.error || 'chunk not found');
|
|
14910
|
+
var c = chunkData.chunk;
|
|
14911
|
+
document.getElementById('brain-chunk-title').textContent = c.section || ('Memory chunk #' + id);
|
|
14912
|
+
document.getElementById('brain-chunk-subtitle').textContent = c.sourceFile || c.source_file || '';
|
|
14913
|
+
var metaRows = [
|
|
14914
|
+
['ID', c.id || id],
|
|
14915
|
+
['Type', c.chunkType || c.chunk_type || '—'],
|
|
14916
|
+
['Source', c.sourceFile || c.source_file || '—'],
|
|
14917
|
+
['Agent', c.agentSlug || c.agent_slug || 'global'],
|
|
14918
|
+
['Salience', c.salience != null ? Number(c.salience).toFixed(2) : '—'],
|
|
14919
|
+
['Confidence', c.confidence != null ? Number(c.confidence).toFixed(2) : '—'],
|
|
14920
|
+
['Updated', c.lastUpdated || c.updated_at || '—'],
|
|
14921
|
+
];
|
|
14922
|
+
var html = '<div style="display:grid;grid-template-columns:110px 1fr;gap:6px 12px;margin-bottom:14px">';
|
|
14923
|
+
metaRows.forEach(function(row) {
|
|
14924
|
+
html += '<div style="color:var(--text-muted)">' + escapeHtml(row[0]) + '</div><div style="overflow-wrap:anywhere">' + escapeHtml(row[1]) + '</div>';
|
|
14925
|
+
});
|
|
14926
|
+
html += '</div>';
|
|
14927
|
+
html += '<div style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;margin-bottom:6px">Stored content</div>';
|
|
14928
|
+
html += '<div style="white-space:pre-wrap;background:var(--bg-input);border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;margin-bottom:14px">' + escapeHtml(c.content || '') + '</div>';
|
|
14929
|
+
var history = historyData.ok && Array.isArray(historyData.history) ? historyData.history : [];
|
|
14930
|
+
html += '<div style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;margin-bottom:6px">Change history</div>';
|
|
14931
|
+
if (!history.length) {
|
|
14932
|
+
html += '<div class="empty-state" style="padding:16px;text-align:left">No edits or supersedes recorded.</div>';
|
|
14933
|
+
} else {
|
|
14934
|
+
html += '<div style="border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden">';
|
|
14935
|
+
history.forEach(function(h) {
|
|
14936
|
+
html += '<div style="padding:8px 10px;border-bottom:1px solid var(--border-light);font-size:12px">'
|
|
14937
|
+
+ '<div style="color:var(--text-muted);font-size:11px">' + escapeHtml(h.timestamp || h.at || '') + '</div>'
|
|
14938
|
+
+ '<div>' + escapeHtml(h.kind || h.action || 'edit') + (h.reason ? ' · ' + escapeHtml(h.reason) : '') + '</div>'
|
|
14939
|
+
+ '</div>';
|
|
14940
|
+
});
|
|
14941
|
+
html += '</div>';
|
|
14942
|
+
}
|
|
14943
|
+
document.getElementById('brain-chunk-body').innerHTML = html;
|
|
14944
|
+
} catch (err) {
|
|
14945
|
+
document.getElementById('brain-chunk-subtitle').textContent = 'Failed';
|
|
14946
|
+
document.getElementById('brain-chunk-body').innerHTML = '<div style="color:var(--red)">' + escapeHtml(String(err)) + '</div>';
|
|
14947
|
+
}
|
|
14948
|
+
}
|
|
14949
|
+
|
|
14950
|
+
function closeBrainChunkTrace() {
|
|
14951
|
+
var drawer = document.getElementById('brain-chunk-trace-drawer');
|
|
14952
|
+
if (drawer) drawer.style.transform = 'translateX(100%)';
|
|
14953
|
+
}
|
|
14954
|
+
|
|
14955
|
+
async function openBrainArtifact(id) {
|
|
14956
|
+
var drawer = document.getElementById('brain-artifact-drawer');
|
|
14957
|
+
if (!drawer) {
|
|
14958
|
+
drawer = document.createElement('div');
|
|
14959
|
+
drawer.id = 'brain-artifact-drawer';
|
|
14960
|
+
drawer.style.cssText = 'position:fixed;right:0;top:0;bottom:0;width:620px;max-width:94vw;background:var(--bg-secondary);border-left:1px solid var(--border);box-shadow:-8px 0 32px rgba(0,0,0,0.18);z-index:220;display:flex;flex-direction:column;transform:translateX(100%);transition:transform 200ms ease';
|
|
14961
|
+
drawer.innerHTML =
|
|
14962
|
+
'<div style="display:flex;align-items:center;gap:10px;padding:14px 18px;border-bottom:1px solid var(--border);flex-shrink:0">'
|
|
14963
|
+
+ '<div style="flex:1;min-width:0">'
|
|
14964
|
+
+ '<div id="brain-artifact-title" style="font-weight:600;font-size:15px"></div>'
|
|
14965
|
+
+ '<div id="brain-artifact-subtitle" style="font-size:11px;color:var(--text-muted);font-family:\\x27JetBrains Mono\\x27,monospace;margin-top:2px"></div>'
|
|
14966
|
+
+ '</div>'
|
|
14967
|
+
+ '<button class="btn-icon btn-sm" onclick="closeBrainArtifact()" title="Close">' + lucide('x', 'icn-sm') + '</button>'
|
|
14968
|
+
+ '</div>'
|
|
14969
|
+
+ '<div id="brain-artifact-body" style="flex:1;overflow:auto;padding:18px 22px;font-size:12px;line-height:1.55;white-space:pre-wrap;font-family:\\x27JetBrains Mono\\x27,monospace"></div>';
|
|
14970
|
+
document.body.appendChild(drawer);
|
|
14971
|
+
}
|
|
14972
|
+
drawer.style.transform = 'translateX(0)';
|
|
14973
|
+
document.getElementById('brain-artifact-title').textContent = 'Artifact #' + id;
|
|
14974
|
+
document.getElementById('brain-artifact-subtitle').textContent = 'Loading…';
|
|
14975
|
+
document.getElementById('brain-artifact-body').textContent = '';
|
|
14976
|
+
try {
|
|
14977
|
+
var r = await apiFetch('/api/brain/artifacts/' + encodeURIComponent(id));
|
|
14978
|
+
var d = await r.json();
|
|
14979
|
+
if (!r.ok || !d.ok || !d.artifact) throw new Error(d.error || 'not found');
|
|
14980
|
+
var a = d.artifact;
|
|
14981
|
+
document.getElementById('brain-artifact-title').textContent = a.summary || ('Artifact #' + id);
|
|
14982
|
+
document.getElementById('brain-artifact-subtitle').textContent = (a.toolName || 'tool') + ' · ' + (a.storedAt || '');
|
|
14983
|
+
document.getElementById('brain-artifact-body').textContent = a.content || a.summary || '';
|
|
14984
|
+
} catch (err) {
|
|
14985
|
+
document.getElementById('brain-artifact-subtitle').textContent = 'Failed';
|
|
14986
|
+
document.getElementById('brain-artifact-body').textContent = String(err);
|
|
14987
|
+
}
|
|
14988
|
+
}
|
|
14989
|
+
|
|
14990
|
+
function closeBrainArtifact() {
|
|
14991
|
+
var drawer = document.getElementById('brain-artifact-drawer');
|
|
14992
|
+
if (drawer) drawer.style.transform = 'translateX(100%)';
|
|
14993
|
+
}
|
|
14994
|
+
|
|
14995
|
+
async function refreshBrainOverview() {
|
|
14996
|
+
var kpis = document.getElementById('brain-command-kpis');
|
|
14997
|
+
var flow = document.getElementById('brain-overview-flow');
|
|
14998
|
+
try {
|
|
14999
|
+
var all = await Promise.all([
|
|
15000
|
+
apiFetch('/api/memory/health').then(function(r) { return r.json(); }).catch(function() { return {}; }),
|
|
15001
|
+
apiFetch('/api/brain/sources').then(function(r) { return r.json(); }).catch(function() { return {}; }),
|
|
15002
|
+
apiFetch('/api/brain/runs?limit=8').then(function(r) { return r.json(); }).catch(function() { return {}; }),
|
|
15003
|
+
]);
|
|
15004
|
+
var h = (all[0] && all[0].health) || {};
|
|
15005
|
+
var sources = (all[1] && all[1].sources) || [];
|
|
15006
|
+
var runs = (all[2] && all[2].runs) || [];
|
|
15007
|
+
var dense = h.denseEmbeddings || {};
|
|
15008
|
+
var densePct = dense.total > 0 ? Math.round((dense.withDense / Math.max(1, dense.total)) * 100) + '%' : '0%';
|
|
15009
|
+
var activeSources = sources.filter(function(s) { return s.enabled; }).length;
|
|
15010
|
+
var scheduledSources = sources.filter(function(s) { return s.enabled && s.scheduleCron; }).length;
|
|
15011
|
+
var lastRun = runs.length ? runs[0] : null;
|
|
15012
|
+
if (kpis) {
|
|
15013
|
+
kpis.innerHTML =
|
|
15014
|
+
'<div class="brain-kpi"><div class="value">' + ((h.chunks && h.chunks.total) || 0).toLocaleString() + '</div><div class="label">Searchable chunks</div></div>'
|
|
15015
|
+
+ '<div class="brain-kpi"><div class="value">' + densePct + '</div><div class="label">Semantic coverage</div></div>'
|
|
15016
|
+
+ '<div class="brain-kpi"><div class="value">' + activeSources + '</div><div class="label">Active sources</div></div>'
|
|
15017
|
+
+ '<div class="brain-kpi"><div class="value">' + scheduledSources + '</div><div class="label">Scheduled feeds</div></div>'
|
|
15018
|
+
+ '<div class="brain-kpi"><div class="value">' + (lastRun ? escapeHtml(lastRun.status) : 'none') + '</div><div class="label">Latest ingestion</div></div>';
|
|
15019
|
+
}
|
|
15020
|
+
if (flow) {
|
|
15021
|
+
if (!runs.length) {
|
|
15022
|
+
flow.innerHTML = '<div class="empty-cta"><div class="label">No ingestion runs yet</div><div class="hint">Seed local data or add a scheduled feed to start the knowledge flow.</div></div>';
|
|
15023
|
+
} else {
|
|
15024
|
+
var html = '<div class="brain-flow-list">';
|
|
15025
|
+
html += '<div class="brain-flow-row" style="color:var(--text-muted);font-size:11px;text-transform:uppercase;letter-spacing:0.04em"><div>Source</div><div>Status</div><div>In</div><div>Written</div><div>Same</div><div>Failed</div><div>When</div></div>';
|
|
15026
|
+
for (var i = 0; i < runs.length; i++) {
|
|
15027
|
+
var run = runs[i];
|
|
15028
|
+
html += '<div class="brain-flow-row">'
|
|
15029
|
+
+ '<div style="font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis">' + escapeHtml(run.sourceSlug || '—') + '</div>'
|
|
15030
|
+
+ '<div>' + brainStatusBadge(run.status) + '</div>'
|
|
15031
|
+
+ '<div>' + (run.recordsIn || 0) + '</div>'
|
|
15032
|
+
+ '<div>' + (run.recordsWritten || 0) + '</div>'
|
|
15033
|
+
+ '<div>' + (run.recordsUnchanged || 0) + '</div>'
|
|
15034
|
+
+ '<div>' + (run.recordsFailed || 0) + '</div>'
|
|
15035
|
+
+ '<div style="color:var(--text-muted)">' + escapeHtml(timeAgo(run.finishedAt || run.startedAt)) + '</div>'
|
|
15036
|
+
+ '</div>';
|
|
15037
|
+
}
|
|
15038
|
+
html += '</div>';
|
|
15039
|
+
flow.innerHTML = html;
|
|
15040
|
+
}
|
|
15041
|
+
}
|
|
15042
|
+
if (document.getElementById('brain-library-results')) runBrainLibrarySearch('');
|
|
15043
|
+
} catch (err) {
|
|
15044
|
+
if (kpis) kpis.innerHTML = '<div class="empty-state" style="color:var(--red)">Failed to load overview: ' + escapeHtml(String(err)) + '</div>';
|
|
15045
|
+
}
|
|
15046
|
+
}
|
|
15047
|
+
|
|
14184
15048
|
function brainRenderProgress(el, opts) {
|
|
14185
15049
|
const label = BRAIN_STAGE_LABELS[opts.stage] || opts.stage || 'Working';
|
|
14186
15050
|
const elapsed = Math.floor((Date.now() - opts.startedAt) / 1000);
|
|
@@ -14368,6 +15232,55 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
14368
15232
|
];
|
|
14369
15233
|
}
|
|
14370
15234
|
|
|
15235
|
+
function brainSetPollCron(expr) {
|
|
15236
|
+
var input = document.getElementById('brain-poll-cron');
|
|
15237
|
+
if (input) input.value = expr;
|
|
15238
|
+
}
|
|
15239
|
+
|
|
15240
|
+
function brainRenderPollScheduleChips() {
|
|
15241
|
+
var el = document.getElementById('brain-poll-schedule-chips');
|
|
15242
|
+
if (!el) return;
|
|
15243
|
+
el.innerHTML = brainScheduleChips().map(function(c) {
|
|
15244
|
+
return '<button class="btn-sm" type="button" onclick="brainSetPollCron(\\'' + escapeHtml(c.cron) + '\\')">' + escapeHtml(c.label) + '</button>';
|
|
15245
|
+
}).join('');
|
|
15246
|
+
}
|
|
15247
|
+
|
|
15248
|
+
function brainAddKvRow(kind, key, value) {
|
|
15249
|
+
var el = document.getElementById(kind === 'params' ? 'brain-poll-params-rows' : 'brain-poll-headers-rows');
|
|
15250
|
+
if (!el) return;
|
|
15251
|
+
var row = document.createElement('div');
|
|
15252
|
+
row.className = 'brain-kv-row';
|
|
15253
|
+
row.innerHTML =
|
|
15254
|
+
'<input type="text" class="brain-kv-key" placeholder="' + (kind === 'params' ? 'limit' : 'Authorization') + '">'
|
|
15255
|
+
+ '<input type="text" class="brain-kv-value" placeholder="' + (kind === 'params' ? '100' : 'Bearer ${"${"}ref}') + '">'
|
|
15256
|
+
+ '<button class="btn-icon btn-sm" type="button" onclick="this.closest(\\'.brain-kv-row\\').remove()" title="Remove">' + lucide('x', 'icn-sm') + '</button>';
|
|
15257
|
+
el.appendChild(row);
|
|
15258
|
+
row.querySelector('.brain-kv-key').value = key || '';
|
|
15259
|
+
row.querySelector('.brain-kv-value').value = value || '';
|
|
15260
|
+
}
|
|
15261
|
+
|
|
15262
|
+
function brainEnsureKvRows() {
|
|
15263
|
+
var h = document.getElementById('brain-poll-headers-rows');
|
|
15264
|
+
var p = document.getElementById('brain-poll-params-rows');
|
|
15265
|
+
if (h && h.children.length === 0) brainAddKvRow('headers', 'Authorization', 'Bearer ${"${"}api_key}');
|
|
15266
|
+
if (p && p.children.length === 0) brainAddKvRow('params', 'limit', '100');
|
|
15267
|
+
brainRenderPollScheduleChips();
|
|
15268
|
+
}
|
|
15269
|
+
|
|
15270
|
+
function brainCollectKv(kind) {
|
|
15271
|
+
var el = document.getElementById(kind === 'params' ? 'brain-poll-params-rows' : 'brain-poll-headers-rows');
|
|
15272
|
+
var out = {};
|
|
15273
|
+
if (!el) return out;
|
|
15274
|
+
el.querySelectorAll('.brain-kv-row').forEach(function(row) {
|
|
15275
|
+
var keyEl = row.querySelector('.brain-kv-key');
|
|
15276
|
+
var valEl = row.querySelector('.brain-kv-value');
|
|
15277
|
+
var key = keyEl ? keyEl.value.trim() : '';
|
|
15278
|
+
var val = valEl ? valEl.value.trim() : '';
|
|
15279
|
+
if (key) out[key] = val;
|
|
15280
|
+
});
|
|
15281
|
+
return out;
|
|
15282
|
+
}
|
|
15283
|
+
|
|
14371
15284
|
async function brainLoadFeedConnectors() {
|
|
14372
15285
|
try {
|
|
14373
15286
|
const resp = await apiFetch('/api/brain/connectors');
|
|
@@ -14417,7 +15330,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
14417
15330
|
'<div style="font-size:12px;margin-top:4px">' + fieldsLine + '</div>' +
|
|
14418
15331
|
'</div>' +
|
|
14419
15332
|
'<button class="btn-primary" onclick="brainRunFeed(\\'' + f.name.replace(/"/g, '') + '\\')">Run now</button> ' +
|
|
14420
|
-
'<button class="btn" onclick="brainDeleteFeed(\\'' + f.name.replace(/"/g, '') + '\\')"
|
|
15333
|
+
'<button class="btn" onclick="brainDeleteFeed(\\'' + f.name.replace(/"/g, '') + '\\')">Delete</button>' +
|
|
14421
15334
|
'</div>';
|
|
14422
15335
|
}).join('');
|
|
14423
15336
|
} catch (err) {
|
|
@@ -14846,25 +15759,44 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
14846
15759
|
const data = await resp.json();
|
|
14847
15760
|
const el = document.getElementById('brain-sources-list');
|
|
14848
15761
|
if (!data.sources || !data.sources.length) {
|
|
14849
|
-
el.innerHTML = '<div
|
|
15762
|
+
el.innerHTML = '<div class="empty-cta"><div class="label">No ingestion sources yet</div><div class="hint">Seed a local file/folder or create a scheduled feed. Ingested data remains searchable even if a source is later disabled.</div></div>';
|
|
14850
15763
|
return;
|
|
14851
15764
|
}
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
14856
|
-
|
|
14857
|
-
|
|
14858
|
-
|
|
14859
|
-
|
|
14860
|
-
|
|
14861
|
-
|
|
14862
|
-
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
15765
|
+
var html = '<div style="display:flex;flex-direction:column;gap:10px">';
|
|
15766
|
+
data.sources.forEach(function(s) {
|
|
15767
|
+
const projTag = s.project
|
|
15768
|
+
? '<span class="brain-badge">' + escapeHtml(s.project.split('/').filter(Boolean).pop() || s.project) + '</span>'
|
|
15769
|
+
: '';
|
|
15770
|
+
const schedule = s.scheduleCron ? '<span class="brain-badge">' + escapeHtml(s.scheduleCron) + '</span>' : '<span class="brain-badge">manual</span>';
|
|
15771
|
+
const enabled = s.enabled ? '<span class="brain-badge" style="color:var(--green);border-color:var(--green)33">enabled</span>' : '<span class="brain-badge">disabled</span>';
|
|
15772
|
+
html += '<div class="brain-source-card">'
|
|
15773
|
+
+ '<div style="min-width:0;flex:1">'
|
|
15774
|
+
+ '<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:5px">'
|
|
15775
|
+
+ '<strong style="font-size:14px">' + escapeHtml(s.slug) + '</strong>'
|
|
15776
|
+
+ '<span class="brain-badge">' + escapeHtml(s.kind) + '</span>'
|
|
15777
|
+
+ '<span class="brain-badge">' + escapeHtml(s.adapter) + '</span>'
|
|
15778
|
+
+ schedule + enabled + projTag
|
|
15779
|
+
+ '</div>'
|
|
15780
|
+
+ '<div style="font-size:12px;color:var(--text-secondary);line-height:1.5">'
|
|
15781
|
+
+ 'Target: <code>' + escapeHtml(s.targetFolder || 'default') + '</code>'
|
|
15782
|
+
+ ' · Last run: ' + escapeHtml(s.lastRunAt ? timeAgo(s.lastRunAt) : 'never')
|
|
15783
|
+
+ ' · Status: ' + escapeHtml(s.lastStatus || 'none')
|
|
15784
|
+
+ '</div>'
|
|
15785
|
+
+ '</div>'
|
|
15786
|
+
+ '<div style="display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end">'
|
|
15787
|
+
+ '<button class="btn-sm brain-run-source" data-slug="' + escapeHtml(s.slug) + '">Run now</button>'
|
|
15788
|
+
+ '<button class="btn-sm brain-delete-source" data-slug="' + escapeHtml(s.slug) + '" title="Delete source">Delete</button>'
|
|
15789
|
+
+ '</div>'
|
|
15790
|
+
+ '</div>';
|
|
15791
|
+
});
|
|
15792
|
+
html += '</div>';
|
|
15793
|
+
el.innerHTML = html;
|
|
15794
|
+
el.querySelectorAll('.brain-run-source').forEach(function(btn) {
|
|
15795
|
+
btn.onclick = function() { brainRunSource(btn.getAttribute('data-slug') || ''); };
|
|
15796
|
+
});
|
|
15797
|
+
el.querySelectorAll('.brain-delete-source').forEach(function(btn) {
|
|
15798
|
+
btn.onclick = function() { brainDeleteSource(btn.getAttribute('data-slug') || ''); };
|
|
15799
|
+
});
|
|
14868
15800
|
}
|
|
14869
15801
|
|
|
14870
15802
|
async function brainRunSource(slug) {
|
|
@@ -14902,6 +15834,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
14902
15834
|
document.getElementById('brain-creds-form').style.display = 'none';
|
|
14903
15835
|
const wf = document.getElementById('brain-webhook-form'); if (wf) wf.style.display = 'none';
|
|
14904
15836
|
brainLoadProjects(['brain-poll-project']);
|
|
15837
|
+
brainEnsureKvRows();
|
|
14905
15838
|
}
|
|
14906
15839
|
|
|
14907
15840
|
function brainShowWebhookForm() {
|
|
@@ -14972,17 +15905,14 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
14972
15905
|
const slug = document.getElementById('brain-poll-slug').value.trim();
|
|
14973
15906
|
const url = document.getElementById('brain-poll-url').value.trim();
|
|
14974
15907
|
const method = document.getElementById('brain-poll-method').value;
|
|
14975
|
-
const headersText = document.getElementById('brain-poll-headers').value.trim();
|
|
14976
|
-
const paramsText = document.getElementById('brain-poll-params').value.trim();
|
|
14977
15908
|
const recordsPath = document.getElementById('brain-poll-recordspath').value.trim();
|
|
14978
15909
|
const cronExpr = document.getElementById('brain-poll-cron').value.trim();
|
|
14979
15910
|
const folder = document.getElementById('brain-poll-folder').value.trim();
|
|
14980
15911
|
const statusEl = document.getElementById('brain-poll-status');
|
|
14981
15912
|
if (!slug || !url) { statusEl.innerHTML = '<span style="color:#e66">slug and URL required</span>'; return; }
|
|
14982
15913
|
|
|
14983
|
-
|
|
14984
|
-
|
|
14985
|
-
try { if (paramsText) params = JSON.parse(paramsText); } catch (e) { statusEl.innerHTML = '<span style="color:#e66">Invalid params JSON</span>'; return; }
|
|
15914
|
+
const headers = brainCollectKv('headers');
|
|
15915
|
+
const params = brainCollectKv('params');
|
|
14986
15916
|
|
|
14987
15917
|
const cfg = { url, method, headers, params };
|
|
14988
15918
|
if (recordsPath) cfg.recordsJsonPath = recordsPath;
|
|
@@ -15018,6 +15948,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
15018
15948
|
async function brainShowCredsForm() {
|
|
15019
15949
|
document.getElementById('brain-creds-form').style.display = '';
|
|
15020
15950
|
document.getElementById('brain-poll-form').style.display = 'none';
|
|
15951
|
+
const wf = document.getElementById('brain-webhook-form'); if (wf) wf.style.display = 'none';
|
|
15021
15952
|
const resp = await apiFetch('/api/brain/credentials');
|
|
15022
15953
|
const data = await resp.json();
|
|
15023
15954
|
const refs = data.refs || [];
|
|
@@ -15045,20 +15976,21 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
15045
15976
|
}
|
|
15046
15977
|
|
|
15047
15978
|
async function brainLoadRuns() {
|
|
15048
|
-
const resp = await apiFetch('/api/brain/runs');
|
|
15979
|
+
const resp = await apiFetch('/api/brain/runs?limit=80');
|
|
15049
15980
|
const data = await resp.json();
|
|
15050
15981
|
const el = document.getElementById('brain-runs-list');
|
|
15051
15982
|
if (!data.runs || !data.runs.length) {
|
|
15052
|
-
el.innerHTML = '<div
|
|
15983
|
+
el.innerHTML = '<div class="empty-cta"><div class="label">No ingestion runs yet</div><div class="hint">Preview and commit a seed, or run a scheduled source.</div></div>';
|
|
15053
15984
|
return;
|
|
15054
15985
|
}
|
|
15055
|
-
el.innerHTML = '<table class="data-table"><thead><tr><th>#</th><th>Source</th><th>Started</th><th>Status</th><th>In</th><th>Written</th><th>Skipped</th><th>Failed</th><th>Overview</th></tr></thead><tbody>' +
|
|
15986
|
+
el.innerHTML = '<table class="data-table"><thead><tr><th>#</th><th>Source</th><th>Started</th><th>Status</th><th>In</th><th>Written</th><th>Same</th><th>Skipped</th><th>Failed</th><th>Recall check</th><th>Overview</th></tr></thead><tbody>' +
|
|
15056
15987
|
data.runs.map((r) =>
|
|
15057
15988
|
'<tr><td>' + r.id + '</td><td>' + escapeHtml(r.sourceSlug) + '</td>' +
|
|
15058
15989
|
'<td>' + escapeHtml(r.startedAt) + '</td>' +
|
|
15059
|
-
'<td>' +
|
|
15990
|
+
'<td>' + brainStatusBadge(r.status) + '</td>' +
|
|
15060
15991
|
'<td>' + r.recordsIn + '</td><td>' + r.recordsWritten + '</td>' +
|
|
15061
|
-
'<td>' + r.recordsSkipped + '</td><td>' + r.recordsFailed + '</td>' +
|
|
15992
|
+
'<td>' + (r.recordsUnchanged || 0) + '</td><td>' + r.recordsSkipped + '</td><td>' + r.recordsFailed + '</td>' +
|
|
15993
|
+
'<td>' + escapeHtml(r.recallCheckStatus || '—') + '</td>' +
|
|
15062
15994
|
'<td>' + (r.overviewNotePath ? '<code style="font-size:12px">' + escapeHtml(r.overviewNotePath) + '</code>' : '—') + '</td></tr>').join('') +
|
|
15063
15995
|
'</tbody></table>';
|
|
15064
15996
|
}
|
|
@@ -15078,6 +16010,23 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
15078
16010
|
// the on-disk path, which we feed into the existing preview/
|
|
15079
16011
|
// commit pipeline.
|
|
15080
16012
|
|
|
16013
|
+
function brainHandleDrag(event, over) {
|
|
16014
|
+
event.preventDefault();
|
|
16015
|
+
var zone = document.getElementById('brain-drop-zone');
|
|
16016
|
+
if (!zone) return;
|
|
16017
|
+
if (over) zone.classList.add('dragover');
|
|
16018
|
+
else zone.classList.remove('dragover');
|
|
16019
|
+
}
|
|
16020
|
+
|
|
16021
|
+
async function brainHandleDrop(event) {
|
|
16022
|
+
event.preventDefault();
|
|
16023
|
+
var zone = document.getElementById('brain-drop-zone');
|
|
16024
|
+
if (zone) zone.classList.remove('dragover');
|
|
16025
|
+
var files = event.dataTransfer && event.dataTransfer.files ? event.dataTransfer.files : null;
|
|
16026
|
+
if (!files || files.length === 0) return;
|
|
16027
|
+
await brainHandleFilesChosen(files, false);
|
|
16028
|
+
}
|
|
16029
|
+
|
|
15081
16030
|
async function brainHandleFilesChosen(fileList, isFolder) {
|
|
15082
16031
|
const statusEl = document.getElementById('brain-upload-status');
|
|
15083
16032
|
if (!fileList || fileList.length === 0) return;
|
|
@@ -15126,15 +16075,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
15126
16075
|
}
|
|
15127
16076
|
}
|
|
15128
16077
|
|
|
15129
|
-
//
|
|
15130
|
-
(function() {
|
|
15131
|
-
const origSwitch = window.switchTab;
|
|
15132
|
-
window.switchTab = function(page, tab) {
|
|
15133
|
-
origSwitch(page, tab);
|
|
15134
|
-
if (page === 'intelligence' && tab === 'sources') { brainLoadSources(); brainLoadFeedConnectors(); brainLoadFeeds(); }
|
|
15135
|
-
if (page === 'intelligence' && tab === 'runs') brainLoadRuns();
|
|
15136
|
-
};
|
|
15137
|
-
})();
|
|
16078
|
+
// Brain tab refresh is handled by the global switchTab dispatcher.
|
|
15138
16079
|
</script>
|
|
15139
16080
|
</div>
|
|
15140
16081
|
|
|
@@ -16343,6 +17284,11 @@ var LUCIDE = {
|
|
|
16343
17284
|
send: '<path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/>',
|
|
16344
17285
|
arrowRight: '<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>',
|
|
16345
17286
|
tool: '<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>',
|
|
17287
|
+
upload: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/>',
|
|
17288
|
+
repeat: '<path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/>',
|
|
17289
|
+
listChecks: '<path d="m3 17 2 2 4-4"/><path d="m3 7 2 2 4-4"/><path d="M13 6h8"/><path d="M13 12h8"/><path d="M13 18h8"/>',
|
|
17290
|
+
activity: '<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>',
|
|
17291
|
+
layoutDashboard:'<rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/>',
|
|
16346
17292
|
database: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14a9 3 0 0 0 18 0V5"/><path d="M3 12a9 3 0 0 0 18 0"/>',
|
|
16347
17293
|
};
|
|
16348
17294
|
function lucide(name, cls) {
|
|
@@ -16366,7 +17312,7 @@ var ROUTE_REDIRECTS = {
|
|
|
16366
17312
|
'heartbeats': { page: 'heartbeat' },
|
|
16367
17313
|
'team-status': { page: 'team', tab: 'activity' },
|
|
16368
17314
|
'agent-detail': { page: 'team', tab: 'roster' },
|
|
16369
|
-
'intelligence': { page: 'brain', tab: '
|
|
17315
|
+
'intelligence': { page: 'brain', tab: 'overview' },
|
|
16370
17316
|
'memory-health': { page: 'brain', tab: 'health' },
|
|
16371
17317
|
'claims': { page: 'brain', tab: 'health' },
|
|
16372
17318
|
'metrics': { page: 'team', tab: 'activity' },
|
|
@@ -16439,9 +17385,10 @@ function navigateTo(page, opts) {
|
|
|
16439
17385
|
}
|
|
16440
17386
|
break;
|
|
16441
17387
|
case 'brain':
|
|
16442
|
-
var bt = opts.tab || '
|
|
17388
|
+
var bt = opts.tab || 'overview';
|
|
16443
17389
|
// Spec tab names → internal intelligence-tab ids
|
|
16444
|
-
var intelTab = bt === '
|
|
17390
|
+
var intelTab = bt === 'overview' ? 'overview'
|
|
17391
|
+
: bt === 'memory' ? 'search'
|
|
16445
17392
|
: bt === 'knowledge' ? 'graph'
|
|
16446
17393
|
: bt === 'ingestion' ? 'sources'
|
|
16447
17394
|
: bt === 'health' ? 'health'
|
|
@@ -16488,7 +17435,7 @@ function switchDestTab(page, tab) {
|
|
|
16488
17435
|
|
|
16489
17436
|
// (Session 5) openAutomationsTab compat shim removed — all callers route via navigateTo + ROUTE_REDIRECTS.
|
|
16490
17437
|
|
|
16491
|
-
// ── Build (Workflows /
|
|
17438
|
+
// ── Build (Workflows / Scheduled Tasks / Skills / Templates) tabs ─────────────
|
|
16492
17439
|
function switchBuildTab(tab) {
|
|
16493
17440
|
if (!tab) tab = 'workflows';
|
|
16494
17441
|
// Update tab-bar active state
|
|
@@ -16497,6 +17444,7 @@ function switchBuildTab(tab) {
|
|
|
16497
17444
|
});
|
|
16498
17445
|
// Show/hide tab panes
|
|
16499
17446
|
var workPane = document.getElementById('build-tab-workflows');
|
|
17447
|
+
var cronPane = document.getElementById('build-tab-crons');
|
|
16500
17448
|
var tplPane = document.getElementById('build-tab-templates');
|
|
16501
17449
|
var headerStrip = document.getElementById('build-header-strip');
|
|
16502
17450
|
// Always close any open workflow when changing tabs — switching context
|
|
@@ -16504,10 +17452,29 @@ function switchBuildTab(tab) {
|
|
|
16504
17452
|
if (typeof closeBuilderCanvas === 'function') closeBuilderCanvas();
|
|
16505
17453
|
if (tab === 'templates') {
|
|
16506
17454
|
if (workPane) workPane.style.display = 'none';
|
|
17455
|
+
if (cronPane) cronPane.style.display = 'none';
|
|
16507
17456
|
if (tplPane) tplPane.style.display = '';
|
|
16508
17457
|
if (headerStrip) headerStrip.style.display = 'none';
|
|
17458
|
+
} else if (tab === 'crons') {
|
|
17459
|
+
if (workPane) workPane.style.display = 'none';
|
|
17460
|
+
if (cronPane) cronPane.style.display = 'block';
|
|
17461
|
+
if (tplPane) tplPane.style.display = 'none';
|
|
17462
|
+
if (headerStrip) headerStrip.style.display = 'flex';
|
|
17463
|
+
var typeSelCron = document.getElementById('builder-type');
|
|
17464
|
+
if (typeSelCron) typeSelCron.value = 'cron';
|
|
17465
|
+
var saveBtnCron = document.getElementById('builder-save-btn');
|
|
17466
|
+
var testBtnCron = document.getElementById('builder-test-btn');
|
|
17467
|
+
var statusCron = document.getElementById('builder-preview-status');
|
|
17468
|
+
if (saveBtnCron) saveBtnCron.style.display = 'none';
|
|
17469
|
+
if (testBtnCron) testBtnCron.style.display = 'none';
|
|
17470
|
+
if (statusCron) statusCron.textContent = '';
|
|
17471
|
+
if (typeof populateBuilderOwnerPicker === 'function') {
|
|
17472
|
+
populateBuilderOwnerPicker().catch(function() { /* */ });
|
|
17473
|
+
}
|
|
17474
|
+
if (typeof refreshCron === 'function') refreshCron();
|
|
16509
17475
|
} else {
|
|
16510
17476
|
if (workPane) workPane.style.display = 'flex';
|
|
17477
|
+
if (cronPane) cronPane.style.display = 'none';
|
|
16511
17478
|
if (tplPane) tplPane.style.display = 'none';
|
|
16512
17479
|
if (headerStrip) headerStrip.style.display = 'flex';
|
|
16513
17480
|
// Map build-tab → builder-type so the canvas + chat reflect the tab.
|
|
@@ -16541,8 +17508,8 @@ function switchBuildTab(tab) {
|
|
|
16541
17508
|
}
|
|
16542
17509
|
}
|
|
16543
17510
|
|
|
16544
|
-
// "New" button in the Build header strip — context-aware.
|
|
16545
|
-
// dedicated cron modal so the entry lands in CRON.md (not as a one-step
|
|
17511
|
+
// "New" button in the Build header strip — context-aware. Scheduled Tasks
|
|
17512
|
+
// open the dedicated cron modal so the entry lands in CRON.md (not as a one-step
|
|
16546
17513
|
// workflow file). Workflows route through /api/builder/workflows. Owner is
|
|
16547
17514
|
// read from the header's Owner picker — empty string means global.
|
|
16548
17515
|
async function newFromBuildHeader() {
|
|
@@ -16618,6 +17585,11 @@ async function onBuilderOwnerChange() {
|
|
|
16618
17585
|
var label = document.getElementById('builder-agent-label');
|
|
16619
17586
|
if (hidden) hidden.value = owner || '';
|
|
16620
17587
|
if (label) label.textContent = owner ? 'Owner: ' + owner : '';
|
|
17588
|
+
var activeTab = document.querySelector('#build-tabs button.active')?.getAttribute('data-build-tab') || 'workflows';
|
|
17589
|
+
if (activeTab === 'crons') {
|
|
17590
|
+
if (typeof refreshCron === 'function') refreshCron();
|
|
17591
|
+
return;
|
|
17592
|
+
}
|
|
16621
17593
|
var typeSel = document.getElementById('builder-type');
|
|
16622
17594
|
var type = typeSel && typeSel.value === 'cron' ? 'cron' : 'workflow';
|
|
16623
17595
|
await refreshBuilderCanvasPicker(type);
|
|
@@ -16676,8 +17648,8 @@ async function forkBuildTemplate(templateId) {
|
|
|
16676
17648
|
});
|
|
16677
17649
|
if (r && r.error) { toast('Create failed: ' + r.error, 'error'); return; }
|
|
16678
17650
|
if (r && r.id) {
|
|
16679
|
-
switchBuildTab(
|
|
16680
|
-
refreshBuilderCanvasPicker(
|
|
17651
|
+
switchBuildTab('workflows');
|
|
17652
|
+
refreshBuilderCanvasPicker('workflow');
|
|
16681
17653
|
setTimeout(function() { openBuilderWorkflow(r.id); }, 200);
|
|
16682
17654
|
toast('Forked template: ' + name, 'success');
|
|
16683
17655
|
}
|
|
@@ -16708,7 +17680,7 @@ function openCommandK() {
|
|
|
16708
17680
|
{ kw: 'home today plan', page: 'home', tab: 'today', label: 'Home · Today' },
|
|
16709
17681
|
{ kw: 'home activity', page: 'home', tab: 'activity', label: 'Home · Activity' },
|
|
16710
17682
|
{ kw: 'build workflows', page: 'build', tab: 'workflows', label: 'Build · Workflows' },
|
|
16711
|
-
{ kw: 'build crons',
|
|
17683
|
+
{ kw: 'build crons scheduled tasks', page: 'build', tab: 'crons', label: 'Build · Scheduled Tasks' },
|
|
16712
17684
|
{ kw: 'build skills', page: 'build', tab: 'skills', label: 'Build · Skills' },
|
|
16713
17685
|
{ kw: 'build templates', page: 'build', tab: 'templates', label: 'Build · Templates' },
|
|
16714
17686
|
{ kw: 'team roster', page: 'team', tab: 'roster', label: 'Team · Roster' },
|
|
@@ -16846,6 +17818,7 @@ function switchTab(group, tab) {
|
|
|
16846
17818
|
}
|
|
16847
17819
|
// Tab-specific refresh
|
|
16848
17820
|
if (group === 'intelligence') {
|
|
17821
|
+
if (tab === 'overview' && typeof refreshBrainOverview === 'function') refreshBrainOverview();
|
|
16849
17822
|
if (tab === 'graph') refreshGraph();
|
|
16850
17823
|
if (tab === 'search') {
|
|
16851
17824
|
// Consolidated Memory tab: search results + stats + MEMORY.md + recent writes + supersedes + coverage strip.
|
|
@@ -16855,6 +17828,12 @@ function switchTab(group, tab) {
|
|
|
16855
17828
|
if (typeof refreshCoverageStrip === 'function') refreshCoverageStrip();
|
|
16856
17829
|
}
|
|
16857
17830
|
if (tab === 'files' && typeof refreshVaultFiles === 'function') refreshVaultFiles();
|
|
17831
|
+
if (tab === 'sources') {
|
|
17832
|
+
if (typeof brainLoadSources === 'function') brainLoadSources();
|
|
17833
|
+
if (typeof brainLoadFeedConnectors === 'function') brainLoadFeedConnectors();
|
|
17834
|
+
if (typeof brainLoadFeeds === 'function') brainLoadFeeds();
|
|
17835
|
+
}
|
|
17836
|
+
if (tab === 'runs' && typeof brainLoadRuns === 'function') brainLoadRuns();
|
|
16858
17837
|
if (tab === 'health') {
|
|
16859
17838
|
if (typeof refreshMemoryHealth === 'function') refreshMemoryHealth();
|
|
16860
17839
|
if (typeof refreshGraphStats === 'function') refreshGraphStats();
|
|
@@ -18180,16 +19159,35 @@ async function refreshCron() {
|
|
|
18180
19159
|
const r = await apiFetch('/api/cron');
|
|
18181
19160
|
const d = await r.json();
|
|
18182
19161
|
cronJobsData = d.jobs || [];
|
|
18183
|
-
document.getElementById('nav-cron-count')
|
|
19162
|
+
var navCount = document.getElementById('nav-cron-count');
|
|
19163
|
+
if (navCount) navCount.textContent = cronJobsData.length;
|
|
19164
|
+
var tabCount = document.getElementById('build-tab-cron-count');
|
|
19165
|
+
if (tabCount) {
|
|
19166
|
+
tabCount.textContent = cronJobsData.length;
|
|
19167
|
+
tabCount.style.display = cronJobsData.length > 0 ? '' : 'none';
|
|
19168
|
+
}
|
|
19169
|
+
|
|
19170
|
+
var panel = document.getElementById('panel-cron');
|
|
19171
|
+
if (!panel) return;
|
|
18184
19172
|
|
|
18185
|
-
|
|
18186
|
-
|
|
19173
|
+
var activeBuildTab = document.querySelector('#build-tabs button.active')?.getAttribute('data-build-tab') || '';
|
|
19174
|
+
var ownerFilter = currentPage === 'build' && activeBuildTab === 'crons'
|
|
19175
|
+
? ((document.getElementById('builder-owner') || {}).value || '')
|
|
19176
|
+
: '';
|
|
19177
|
+
var visibleJobs = currentPage === 'build' && activeBuildTab === 'crons'
|
|
19178
|
+
? cronJobsData.filter(function(j) { return ownerFilter ? j.agent === ownerFilter : !j.agent; })
|
|
19179
|
+
: cronJobsData;
|
|
19180
|
+
|
|
19181
|
+
if (visibleJobs.length === 0) {
|
|
19182
|
+
var emptyLabel = ownerFilter ? 'No scheduled tasks for ' + ownerFilter : 'No global scheduled tasks';
|
|
19183
|
+
panel.innerHTML = '<div class="task-grid"><div class="task-card-add" onclick="openCreateCronModal((document.getElementById(\\x27builder-owner\\x27)||{}).value||\\x27\\x27)">+ New Task</div></div>'
|
|
19184
|
+
+ '<div class="empty-state" style="padding:18px;color:var(--text-muted);font-size:13px">' + esc(emptyLabel) + '</div>';
|
|
18187
19185
|
return;
|
|
18188
19186
|
}
|
|
18189
19187
|
|
|
18190
19188
|
// Group jobs: main (no agent) first, then by agent slug
|
|
18191
19189
|
var groups = {};
|
|
18192
|
-
for (const job of
|
|
19190
|
+
for (const job of visibleJobs) {
|
|
18193
19191
|
var g = job.agent || '_main';
|
|
18194
19192
|
if (!groups[g]) groups[g] = [];
|
|
18195
19193
|
groups[g].push(job);
|
|
@@ -18264,7 +19262,7 @@ async function refreshCron() {
|
|
|
18264
19262
|
}
|
|
18265
19263
|
// Add "new task" card only to the main group
|
|
18266
19264
|
if (groupKey === '_main') {
|
|
18267
|
-
html += '<div class="task-card-add" onclick="openCreateCronModal()">+ New Task</div>';
|
|
19265
|
+
html += '<div class="task-card-add" onclick="openCreateCronModal((document.getElementById(\\x27builder-owner\\x27)||{}).value||\\x27\\x27)">+ New Task</div>';
|
|
18268
19266
|
}
|
|
18269
19267
|
html += '</div>';
|
|
18270
19268
|
}
|
|
@@ -18307,10 +19305,10 @@ async function refreshCron() {
|
|
|
18307
19305
|
}
|
|
18308
19306
|
} catch(ue) { /* unleashed status is optional */ }
|
|
18309
19307
|
|
|
18310
|
-
|
|
19308
|
+
panel.innerHTML = html;
|
|
18311
19309
|
|
|
18312
19310
|
// Attach trace button handlers via delegation
|
|
18313
|
-
|
|
19311
|
+
panel.onclick = function(ev) {
|
|
18314
19312
|
var target = ev.target;
|
|
18315
19313
|
while (target && target.id !== 'panel-cron') {
|
|
18316
19314
|
if (target.dataset && target.dataset.traceJob) {
|
|
@@ -21224,7 +22222,7 @@ function openSkillStudio() {
|
|
|
21224
22222
|
// Pre-set type to skill before navigating
|
|
21225
22223
|
var typeSelect = document.getElementById('builder-type');
|
|
21226
22224
|
if (typeSelect) typeSelect.value = 'skill';
|
|
21227
|
-
navigateTo('
|
|
22225
|
+
navigateTo('build', { tab: 'skills' });
|
|
21228
22226
|
// Update the UI for skill mode
|
|
21229
22227
|
updateBuilderMode();
|
|
21230
22228
|
// Show skill-specific empty state
|
|
@@ -21272,7 +22270,7 @@ function updateBuilderMode() {
|
|
|
21272
22270
|
if (validateBtn) validateBtn.style.display = '';
|
|
21273
22271
|
if (dryrunBtn) dryrunBtn.style.display = '';
|
|
21274
22272
|
if (testBtn) testBtn.style.display = '';
|
|
21275
|
-
if (paneTitle) paneTitle.textContent = (type === 'cron' ? '
|
|
22273
|
+
if (paneTitle) paneTitle.textContent = (type === 'cron' ? 'Scheduled Tasks' : 'Workflows');
|
|
21276
22274
|
refreshBuilderCanvasPicker(type);
|
|
21277
22275
|
} else {
|
|
21278
22276
|
if (preview) preview.style.display = '';
|
|
@@ -21560,7 +22558,7 @@ async function validateBuilderCanvas() {
|
|
|
21560
22558
|
async function deleteCurrentBuilderWorkflow() {
|
|
21561
22559
|
if (!_builderCanvasOpenId) return;
|
|
21562
22560
|
if (!_builderCanvasOpenId.startsWith('workflow:')) {
|
|
21563
|
-
toast('
|
|
22561
|
+
toast('Scheduled tasks can\\x27t be deleted from here — disable instead.', 'info');
|
|
21564
22562
|
return;
|
|
21565
22563
|
}
|
|
21566
22564
|
var name = _builderCanvasOpenId.replace(/^workflow:/, '');
|
|
@@ -22034,7 +23032,7 @@ async function editSkillInBuilder(name, agentSlug) {
|
|
|
22034
23032
|
if (d.error) { toast(d.error, 'error'); return; }
|
|
22035
23033
|
|
|
22036
23034
|
// Switch to builder page
|
|
22037
|
-
navigateTo('
|
|
23035
|
+
navigateTo('build', { tab: 'skills' });
|
|
22038
23036
|
|
|
22039
23037
|
// Set type to skill
|
|
22040
23038
|
var typeSelect = document.getElementById('builder-type');
|
|
@@ -22087,12 +23085,35 @@ async function editSkillInBuilder(name, agentSlug) {
|
|
|
22087
23085
|
}
|
|
22088
23086
|
}
|
|
22089
23087
|
|
|
23088
|
+
function builderEmptyStateHtml(type) {
|
|
23089
|
+
if (type === 'skill') {
|
|
23090
|
+
return '<div class="empty-state" style="margin-top:40px">'
|
|
23091
|
+
+ '<p style="color:var(--text-muted);margin-bottom:8px;font-size:15px;font-weight:600">Skill Studio</p>'
|
|
23092
|
+
+ '<p style="color:var(--text-muted);margin-bottom:16px;font-size:13px">Teach a new skill by describing it, attach reference files, link tools, test it, then save.</p>'
|
|
23093
|
+
+ '<div style="display:flex;flex-wrap:wrap;gap:8px;justify-content:center">'
|
|
23094
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Teach a skill for deploying to production — run tests, build, push, verify\\x27)">Deploy to prod</button>'
|
|
23095
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Teach a skill for writing a weekly status report from git commits and calendar\\x27)">Weekly status report</button>'
|
|
23096
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Teach a skill for onboarding a new team member — set up accounts, send welcome email\\x27)">Onboard team member</button>'
|
|
23097
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Teach a skill for researching a company before a sales call\\x27)">Company research</button>'
|
|
23098
|
+
+ '</div></div>';
|
|
23099
|
+
}
|
|
23100
|
+
return '<div class="empty-state" style="margin-top:40px">'
|
|
23101
|
+
+ '<p style="color:var(--text-muted);margin-bottom:12px">Describe the workflow you want to build.</p>'
|
|
23102
|
+
+ '<div style="display:flex;flex-wrap:wrap;gap:8px;justify-content:center">'
|
|
23103
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Create a workflow that researches a topic, writes a draft, and sends it for review\\x27)">Research workflow</button>'
|
|
23104
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Create a workflow that reviews open PRs, summarizes risk, and sends a digest\\x27)">PR review digest</button>'
|
|
23105
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Create a workflow that collects leads, scores them against my ICP, and prepares outreach drafts\\x27)">Lead research flow</button>'
|
|
23106
|
+
+ '<button class="btn btn-sm quick-pill" onclick="builderQuick(\\x27Create a workflow that reviews recent notes, extracts open items, and drafts next priorities\\x27)">Weekly review workflow</button>'
|
|
23107
|
+
+ '</div></div>';
|
|
23108
|
+
}
|
|
23109
|
+
|
|
22090
23110
|
function resetBuilder() {
|
|
22091
23111
|
builderArtifact = null;
|
|
22092
23112
|
builderSending = false;
|
|
22093
23113
|
_builderLinkedTools = [];
|
|
23114
|
+
var type = (document.getElementById('builder-type') || {}).value || 'workflow';
|
|
22094
23115
|
var msgs = document.getElementById('builder-messages');
|
|
22095
|
-
if (msgs) msgs.innerHTML =
|
|
23116
|
+
if (msgs) msgs.innerHTML = builderEmptyStateHtml(type);
|
|
22096
23117
|
var preview = document.getElementById('builder-preview');
|
|
22097
23118
|
if (preview) preview.innerHTML = '<div class="empty-state" style="font-size:13px;color:var(--text-muted)">The artifact will appear here as you build it</div>';
|
|
22098
23119
|
var saveBtn = document.getElementById('builder-save-btn');
|
|
@@ -22106,24 +23127,19 @@ function resetBuilder() {
|
|
|
22106
23127
|
_builderAttachments = [];
|
|
22107
23128
|
renderBuilderAttachments();
|
|
22108
23129
|
// Tell server to reset session so next message gets the full prefix
|
|
22109
|
-
var type = (document.getElementById('builder-type') || {}).value;
|
|
22110
23130
|
var agent = (document.getElementById('builder-agent') || {}).value;
|
|
22111
23131
|
apiJson('POST', '/api/builder/reset', { artifactType: type, agentSlug: agent || undefined }).catch(function(){});
|
|
22112
23132
|
}
|
|
22113
23133
|
|
|
22114
23134
|
function builderQuick(text) {
|
|
22115
23135
|
var sel = document.getElementById('builder-type');
|
|
22116
|
-
var
|
|
22117
|
-
if (
|
|
22118
|
-
sel.value = '
|
|
22119
|
-
} else if (lower.includes('workflow') || lower.includes('pipeline') || lower.includes('multi-step')) {
|
|
22120
|
-
sel.value = 'workflow';
|
|
22121
|
-
} else if (lower.includes('cron') || lower.includes('scheduled') || lower.includes('every')) {
|
|
22122
|
-
sel.value = 'cron';
|
|
22123
|
-
} else {
|
|
22124
|
-
sel.value = 'skill';
|
|
23136
|
+
var activeTab = document.querySelector('#build-tabs button.active')?.getAttribute('data-build-tab') || 'workflows';
|
|
23137
|
+
if (sel) {
|
|
23138
|
+
sel.value = activeTab === 'skills' ? 'skill' : activeTab === 'crons' ? 'cron' : 'workflow';
|
|
22125
23139
|
}
|
|
22126
|
-
|
|
23140
|
+
if (typeof updateBuilderMode === 'function') updateBuilderMode();
|
|
23141
|
+
var input = document.getElementById('builder-input');
|
|
23142
|
+
if (input) input.value = text;
|
|
22127
23143
|
sendBuilderChat();
|
|
22128
23144
|
}
|
|
22129
23145
|
|
|
@@ -22513,6 +23529,13 @@ function parseSearchFilters(raw) {
|
|
|
22513
23529
|
return { q: cleaned, filters: filters };
|
|
22514
23530
|
}
|
|
22515
23531
|
|
|
23532
|
+
function runMemoryDetailSearch() {
|
|
23533
|
+
var detail = document.getElementById('memory-detail-search-input');
|
|
23534
|
+
var header = document.getElementById('memory-search-input');
|
|
23535
|
+
if (header && detail) header.value = detail.value;
|
|
23536
|
+
runMemorySearch();
|
|
23537
|
+
}
|
|
23538
|
+
|
|
22516
23539
|
async function runMemorySearch() {
|
|
22517
23540
|
const input = document.getElementById('memory-search-input');
|
|
22518
23541
|
const raw = input.value.trim();
|
|
@@ -23163,7 +24186,7 @@ async function submitNewGoal() {
|
|
|
23163
24186
|
|
|
23164
24187
|
// ── Workflows: open Builder for a brand-new workflow ─────────────
|
|
23165
24188
|
function openBuilderForNewWorkflow() {
|
|
23166
|
-
navigateTo('
|
|
24189
|
+
navigateTo('build', { tab: 'workflows' });
|
|
23167
24190
|
setTimeout(function() {
|
|
23168
24191
|
var typeSel = document.getElementById('builder-type');
|
|
23169
24192
|
if (typeSel) { typeSel.value = 'workflow'; updateBuilderMode(); }
|
|
@@ -23183,9 +24206,8 @@ function openBuilderForNewWorkflow() {
|
|
|
23183
24206
|
// ── Unleashed: open the start-task picker ────────────────────────
|
|
23184
24207
|
function openStartUnleashedTask() {
|
|
23185
24208
|
// Reuse the existing cron list — pick a cron job, run it in unleashed mode.
|
|
23186
|
-
|
|
23187
|
-
|
|
23188
|
-
toast('Pick a cron job and click "Run unleashed" — kicks off long-running mode.', 'info');
|
|
24209
|
+
navigateTo('build', { tab: 'crons' });
|
|
24210
|
+
toast('Open a scheduled task, set Mode to Unleashed, then run it.', 'info');
|
|
23189
24211
|
}
|
|
23190
24212
|
|
|
23191
24213
|
async function refreshMemoryHealth() {
|
|
@@ -24023,7 +25045,7 @@ async function refreshHomeDigest() {
|
|
|
24023
25045
|
if (runsBody) {
|
|
24024
25046
|
var runs = d.todayRuns || [];
|
|
24025
25047
|
if (!runs.length) {
|
|
24026
|
-
runsBody.innerHTML = '<div style="padding:14px 18px;color:var(--text-muted);font-size:var(--text-sm)">No scheduled runs configured. <a href="#" onclick="navigateTo(\\x27build\\x27,{tab:\\x27crons\\x27});return false" style="color:var(--clementine)">Add one in Build →
|
|
25048
|
+
runsBody.innerHTML = '<div style="padding:14px 18px;color:var(--text-muted);font-size:var(--text-sm)">No scheduled runs configured. <a href="#" onclick="navigateTo(\\x27build\\x27,{tab:\\x27crons\\x27});return false" style="color:var(--clementine)">Add one in Build → Scheduled Tasks</a>.</div>';
|
|
24027
25049
|
} else {
|
|
24028
25050
|
var html2 = '';
|
|
24029
25051
|
for (var n = 0; n < runs.length; n++) {
|