total-recall-brain 3.44.0 → 3.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/total-recall.mjs +10 -6
- package/docs/ARCHITECTURE.md +10 -7
- package/docs/reference/cli-reference.md +13 -8
- package/frontend/dist/assets/index-BRYE1jmv.css +1 -0
- package/frontend/dist/assets/index-D1goIPjC.js +5598 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/sw.js +5 -4
- package/frontend/src/App.tsx +185 -238
- package/frontend/src/api/auth-inventory.ts +62 -0
- package/frontend/src/api/memory.ts +13 -8
- package/frontend/src/api/plugin-credentials.ts +23 -0
- package/frontend/src/api/plugins.ts +37 -53
- package/frontend/src/api/workspace-drawers.ts +97 -0
- package/frontend/src/components/BrainSelector.tsx +9 -3
- package/frontend/src/components/plugins/PluginPanel.tsx +83 -42
- package/frontend/src/components/plugins/PluginSettings.tsx +10 -20
- package/frontend/src/components/plugins/PluginWorkspace.tsx +367 -0
- package/frontend/src/components/plugins/ScopedPluginCommands.tsx +142 -0
- package/frontend/src/components/plugins/plugin-frame.ts +44 -33
- package/frontend/src/components/plugins/scoped-plugin-operations.ts +28 -0
- package/frontend/src/components/workspace/DrawerChat.tsx +110 -0
- package/frontend/src/components/workspace/DrawerLayout.tsx +196 -0
- package/frontend/src/components/workspace/DrawerMarkup.tsx +49 -0
- package/frontend/src/components/workspace/PluginChunkLibrary.tsx +92 -0
- package/frontend/src/components/workspace/PluginHome.tsx +76 -0
- package/frontend/src/components/workspace/WorkspaceDrawers.tsx +96 -0
- package/frontend/src/components/workspace/WorkspacePage.tsx +95 -0
- package/frontend/src/components/workspace/usePluginDesign.ts +38 -0
- package/frontend/src/index.css +409 -136
- package/frontend/src/pages/HelpPage.tsx +15 -46
- package/frontend/src/pages/MemoryPage.tsx +19 -36
- package/frontend/src/pages/SettingsPage.tsx +1 -1
- package/metadata.plugin.schema.json +53 -227
- package/package.json +1 -1
- package/scaffold/.agent/skills/plugin/SKILL.md +13 -11
- package/scaffold/.agent/skills/plugin/evals/README.md +14 -21
- package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +15 -18
- package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +19 -24
- package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +12 -20
- package/scaffold/.agent/skills/plugin/evals/cases/04-home-collects-credential.mjs +35 -0
- package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +8 -28
- package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +85 -47
- package/scaffold/.agent/skills/plugin/evals/run.mjs +17 -18
- package/scaffold/.agent/skills/plugin/prompts/05-credentials.md +4 -4
- package/scaffold/.agent/skills/plugin/prompts/07-scaffold.md +2 -2
- package/scaffold/.agent/skills/plugin/prompts/08-verify.md +4 -4
- package/scaffold/.agent/skills/plugin/references/anti-patterns.md +2 -2
- package/scaffold/.agent/skills/plugin/references/generative-home.md +38 -0
- package/scaffold/.agent/skills/plugin/references/scaffold.md +5 -5
- package/scaffold/.agent/skills/plugin/references/surfaces.md +13 -4
- package/scaffold/.agent/skills/plugin/scripts/record.mjs +75 -153
- package/scaffold/.agent/skills/plugin/subagents/plugin-reviewer.md +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/DESIGN.md +76 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +3 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +20 -15
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +13 -51
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +20 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/access-overview.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/agent-login.md +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/baseline-audit.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-repository-binding.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-store-maintenance.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-password.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-sessions.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/endpoint-probe.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/google-sign-in.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/mesh-machines.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/passkey-enrollment.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/registered-brains.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/scoped-access-keys.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/secret-inventory.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/signing-key-rotation.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/home.js +375 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/BRICK.md +7 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/DESIGN.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/README.md +66 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +247 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +130 -0
- package/{src/core/plugin-cron.mjs → scaffold/.agent/skills/total-recall/plugins/automations/cron.mjs} +1 -3
- package/scaffold/.agent/skills/total-recall/plugins/automations/inventory.mjs +88 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +7661 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +36 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +151 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/control-ledger.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/local-inventory-triage.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/pending-control.md +39 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/run-evidence.md +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/schedule-vs-run-evidence.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/source-coverage.md +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/home.js +278 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/DESIGN.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +61 -7
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +40 -14
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +15 -40
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +40 -40
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/config.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/detect.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/gate.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/init.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/report.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/run.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/snapshot.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +55 -23
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/home.mjs +214 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/DESIGN.md +146 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +51 -34
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/create.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/history.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/library.md +49 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/list.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/promote.md +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/read.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/remove.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/rollback.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/show.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/status.md +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test-path.md +38 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test.md +46 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/update.md +32 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/home.js +533 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/DESIGN.md +110 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +13 -10
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/benchmark.md +49 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/coverage.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/models.md +43 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/pull.md +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/status.md +59 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/home.js +353 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/DESIGN.md +31 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/README.md +136 -0
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +140 -24
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +9 -9
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +151 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/context.mjs +94 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/phase3-spec-support.mjs +50 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/runtime.mjs +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/spec-support.mjs +51 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/_support.mjs +195 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/auth.mjs +201 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/bisect.mjs +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/cli-meta.mjs +159 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +54 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit.mjs +46 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +174 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/force-push.mjs +58 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/group.mjs +119 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/handoff.mjs +59 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/message.mjs +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/resolve.mjs +60 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/rules.mjs +81 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +92 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +156 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/change-comparison.md +27 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/commit-identity.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/create-worktree.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/registered-worktrees.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/remove-worktree.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/repository-ledger.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/unmerged-work.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/upstream-divergence.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-conflict-triage.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-terminal.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/home.js +273 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/DESIGN.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +4 -5
- package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +37 -39
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/active-device-dispatch.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-probe.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-server.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/credential-readiness.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/elected-leader.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/enrollment-key.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/file-receipt.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-execution.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-presence.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/interactive-ssh.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/local-enrollment.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/mesh-policy.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/network-atlas.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-roster.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-selection-proof.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/owner-observations.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/peer-path.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/pinned-leader.md +24 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/reachability-evidence-ladder.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/recorded-login.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/remote-execution.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/secret-grants.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/{card.js → home.js} +93 -22
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/DESIGN.md +86 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +44 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +18 -6
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +128 -24
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +188 -34
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +17 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +92 -18
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/control.mjs +145 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +42 -21
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +33 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +55 -11
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +26 -4
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/hermes.mjs +29 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/index.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/included-usage.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/jobs.mjs +84 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +3 -12
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/maintenance.mjs +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/mcp-server.mjs +228 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +25 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/review.mjs +34 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reviews.mjs +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/claude.mjs +319 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/codex.mjs +387 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/result.mjs +67 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/resume.mjs +373 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/run.mjs +223 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session-jobs.mjs +72 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +6 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/termination.mjs +16 -12
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/threads.mjs +32 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/usage-queue.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/verify-ssss.mjs +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +285 -40
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/adapter-docs-freshness.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/chat-handoff.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/fleet-maintenance.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/harness-inventory.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-access.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-usage-verification.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/independent-review.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/managed-execution.md +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/official-documentation.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/quota-recovery.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/review-routing-decision.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/route-work.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/routing-evidence.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/run-ledger.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/home.js +198 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/DESIGN.md +75 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +2 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +64 -32
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +10 -44
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +5 -4
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +3 -4
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +23 -18
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +8 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh-diagnostics.mjs +44 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +123 -113
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +3 -5
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/token.mjs +21 -47
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/upstream-watcher.mjs +17 -6
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/auto-refresh.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/bootstrap-pages.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generate-wiki.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generator-settings.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/host-probe.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/ingest-preview.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-hygiene.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-topology.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/passage-search.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/propagation-plan.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/provider-credentials.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/refresh-report.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/task-evidence.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/upstream-record.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/watch-upstream.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/wiki-atlas.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +261 -513
- package/scaffold/.agent/skills/total-recall/plugins/security/DESIGN.md +84 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/README.md +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +7 -19
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +2 -3
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +19 -52
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/device-evidence.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/evidence-desk.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/guided-device-review.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/host-and-network.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/https-headers.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/mesh-coverage.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/private-security-tools.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/single-origin-header-check.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/source-review.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/ssh-permission-plan.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/home.js +283 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/DESIGN.md +93 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/conformance.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/registry.md +37 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/repair.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/scaffold.md +33 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/status.md +43 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validate.md +34 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validation-diagnostics.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/workspace-registry-preflight.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/home.js +348 -0
- package/scaffold/.agent/skills/total-recall/references/operations.md +3 -1
- package/src/cli/agent.mjs +1 -1
- package/src/cli/api.mjs +3 -3
- package/src/cli/brief.mjs +3 -0
- package/src/cli/command.mjs +41 -2
- package/src/cli/config.mjs +16 -0
- package/src/cli/connect.mjs +2 -7
- package/src/cli/dream.mjs +93 -69
- package/src/cli/harness.mjs +4 -4
- package/src/cli/help.mjs +1 -1
- package/src/cli/init.mjs +0 -25
- package/src/cli/lessons.mjs +51 -0
- package/src/cli/memory-plugin.mjs +1 -1
- package/src/cli/plugin/chunks.mjs +145 -0
- package/src/cli/plugin/copies.mjs +64 -14
- package/src/cli/plugin/create.mjs +30 -59
- package/src/cli/plugin/index.mjs +31 -16
- package/src/cli/plugin/install.mjs +10 -15
- package/src/cli/plugin/remove.mjs +1 -1
- package/src/cli/plugin/search.mjs +2 -2
- package/src/cli/preflight.mjs +19 -6
- package/src/cli/proposals.mjs +1 -1
- package/src/cli/recall.mjs +66 -23
- package/src/cli/remember.mjs +3 -14
- package/src/cli/server.mjs +18 -0
- package/src/cli/setup.mjs +2 -9
- package/src/cli/start.mjs +1 -0
- package/src/cli/startup.mjs +19 -0
- package/src/cli/task.mjs +9 -2
- package/src/cli/update.mjs +6 -2
- package/src/core/access-ledger.mjs +78 -0
- package/src/core/agent-manager.mjs +2 -2
- package/src/core/app-deploy/design-tokens.mjs +14 -9
- package/src/core/app-deploy/ui-elements.mjs +1 -1
- package/src/core/brain-locate.mjs +15 -0
- package/src/core/brain-registry.mjs +5 -0
- package/src/core/brain-updates.mjs +35 -11
- package/src/core/claude-hooks.mjs +3 -1
- package/src/core/cleanup-task.mjs +15 -0
- package/src/core/cli-commands.mjs +2 -0
- package/src/core/cli-maintenance.mjs +4 -1
- package/src/core/cli-semantic-index.mjs +23 -3
- package/src/core/context-compiler.mjs +20 -0
- package/src/core/daemon-control.mjs +5 -1
- package/src/core/daemon-loop.mjs +39 -62
- package/src/core/dashboard-bundle.mjs +261 -0
- package/src/core/default-plugins.mjs +1 -1
- package/src/core/dream.mjs +33 -105
- package/src/core/ensure-dependencies.mjs +152 -0
- package/src/core/fast-recall.mjs +2 -2
- package/src/core/field-evaluation.mjs +23 -0
- package/src/core/gate-mode.mjs +1 -1
- package/src/core/harness-hooks.mjs +14 -2
- package/src/core/lesson-hooks.mjs +74 -0
- package/src/core/lesson-memory.mjs +24 -0
- package/src/core/lesson-sessions.mjs +52 -0
- package/src/core/lessons.mjs +96 -0
- package/src/core/memory-brain.mjs +30 -8
- package/src/core/meta-harness.mjs +2 -2
- package/src/core/optimizer.mjs +66 -165
- package/src/core/plugin-activation.mjs +63 -20
- package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +26 -57
- package/src/core/plugin-contracts/startup-check.mjs +49 -0
- package/src/core/plugin-contracts/ui.mjs +9 -3
- package/src/core/plugin-distribution.mjs +6 -6
- package/src/core/plugin-lifecycle.mjs +58 -0
- package/src/core/plugin-loader.mjs +21 -8
- package/src/core/plugin-runner.mjs +21 -10
- package/src/core/plugin-runtime.mjs +40 -1
- package/src/core/plugin-startup-checks.mjs +44 -0
- package/src/core/plugin-state.mjs +19 -5
- package/src/core/plugin-store.mjs +64 -33
- package/src/core/post-mortem.mjs +52 -36
- package/src/core/preflight-gate.mjs +23 -2
- package/src/core/project-id.mjs +15 -5
- package/src/core/proposal-applier.mjs +31 -2
- package/src/core/repo-sync.mjs +4 -6
- package/src/core/required-plugins.mjs +57 -10
- package/src/core/rule-length.mjs +23 -0
- package/src/core/runtime.mjs +1 -1
- package/src/core/scheduler.mjs +35 -43
- package/src/core/schema.mjs +3 -2
- package/src/core/search.mjs +4 -3
- package/src/core/server-service.mjs +148 -0
- package/src/core/session-watcher.mjs +19 -1
- package/src/core/skill-gap.mjs +16 -0
- package/src/core/ssss-kernel-bridge.mjs +32 -4
- package/src/core/ssss-operation-service.mjs +1 -0
- package/src/core/startup-health.mjs +34 -4
- package/src/core/surface.mjs +65 -54
- package/src/core/task-executors.mjs +54 -106
- package/src/core/testing/plugin-fixture.mjs +22 -21
- package/src/core/throttled-fetch.mjs +25 -18
- package/src/core/ui-chunk-choice.mjs +77 -0
- package/src/core/ui-chunk.registry.json +23 -0
- package/src/core/ui-chunks.mjs +434 -0
- package/src/core/validated-write.mjs +1 -0
- package/src/core/vault-cache.mjs +58 -59
- package/src/core/vector-field.mjs +134 -192
- package/src/core/workspace-compositions.mjs +151 -0
- package/src/core/workspace-drawers.mjs +79 -0
- package/src/server/api.mjs +4 -27
- package/src/server/index.mjs +28 -21
- package/src/server/invoke-core-child.mjs +24 -0
- package/src/server/invoke-core-operations.mjs +102 -0
- package/src/server/memory-events.mjs +31 -0
- package/src/server/plugin-brain-targets.mjs +89 -0
- package/src/server/rest.mjs +2 -0
- package/src/server/route-inventory.mjs +3 -2
- package/src/server/route-manifest.json +47 -55
- package/src/server/routes/_shared.mjs +7 -14
- package/src/server/routes/brains.mjs +29 -62
- package/src/server/routes/context.mjs +0 -41
- package/src/server/routes/dashboard.mjs +26 -0
- package/src/server/routes/invoke.mjs +26 -1
- package/src/server/routes/plugins.mjs +154 -45
- package/src/server/routes/ssss.mjs +0 -169
- package/src/server/routes/system.mjs +0 -15
- package/src/server/routes/tasks.mjs +0 -26
- package/src/server/routes/ui-chunks.mjs +192 -0
- package/src/server/routes/vault.mjs +2 -23
- package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
- package/frontend/dist/assets/index-DtwsDyFM.css +0 -1
- package/frontend/src/components/plugins/card/CardEngine.tsx +0 -108
- package/frontend/src/components/plugins/card/CardScenes.tsx +0 -103
- package/frontend/src/components/plugins/card/ExecutionPicker.tsx +0 -64
- package/frontend/src/components/plugins/card/args.ts +0 -28
- package/frontend/src/components/plugins/card/card.css +0 -32
- package/frontend/src/components/plugins/card/cli-line.ts +0 -13
- package/frontend/src/components/plugins/card/contract.ts +0 -91
- package/frontend/src/components/plugins/card/format.ts +0 -49
- package/frontend/src/components/plugins/card/runner-context.ts +0 -11
- package/frontend/src/components/plugins/card/runner.tsx +0 -43
- package/frontend/src/components/plugins/card/theme.ts +0 -35
- package/frontend/src/components/plugins/card/use-source.ts +0 -22
- package/frontend/src/components/plugins/card/widgets.tsx +0 -94
- package/frontend/src/components/plugins/workspace/WorkspaceHost.tsx +0 -23
- package/frontend/src/pages/PluginsPage.tsx +0 -1719
- package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +0 -47
- package/scaffold/.agent/skills/plugin/prompts/06-card.md +0 -46
- package/scaffold/.agent/skills/plugin/references/card.md +0 -90
- package/scaffold/.agent/skills/plugin/subagents/card-designer.md +0 -60
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +0 -67
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +0 -1179
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +0 -32
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +0 -588
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +0 -575
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +0 -32
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +0 -482
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +0 -53
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +0 -129
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +0 -100
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +0 -637
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +0 -217
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +0 -32
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +0 -1276
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +0 -45
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +0 -1401
- package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +0 -4
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +0 -41
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +0 -396
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +0 -98
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/DESIGN.md +0 -15
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/card.js +0 -182
- package/src/core/append-log.mjs +0 -131
- package/src/core/plugin-tasks.mjs +0 -173
- package/templates/onboarding-interview.md +0 -82
- /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/LICENSE +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Private dashboard chrome settings, shared by the HTTP and CLI adapters. */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { executePluginState, PluginStateStore } from './plugin-state-store.mjs';
|
|
4
|
+
|
|
5
|
+
const OWNER = 'workspace-ui';
|
|
6
|
+
const ID = /^[a-z][a-z0-9-]{0,63}$/;
|
|
7
|
+
const EMPTY = { html: '', chunks: [], panels: [], shortcuts: [] };
|
|
8
|
+
export const MAX_DRAWER_HTML_BYTES = 64 * 1024;
|
|
9
|
+
|
|
10
|
+
export class DrawerInputError extends Error {}
|
|
11
|
+
|
|
12
|
+
function stateFile(brainDir, edge) {
|
|
13
|
+
if (edge !== 'right' && edge !== 'bottom') throw new DrawerInputError('Choose the right or bottom drawer.');
|
|
14
|
+
return path.join(brainDir, 'config', `workspace-drawer-${edge}.json`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function list(value, name, limit) {
|
|
18
|
+
if (!Array.isArray(value) || value.length > limit) throw new DrawerInputError(`${name} must contain at most ${limit} items.`);
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function shortcutHref(value) {
|
|
23
|
+
if (typeof value !== 'string' || value.length > 1024 || /[\u0000-\u0020\u007f\\]/.test(value)) {
|
|
24
|
+
throw new DrawerInputError('Use a dashboard path or an HTTPS address for each shortcut.');
|
|
25
|
+
}
|
|
26
|
+
const base = 'https://workspace.invalid';
|
|
27
|
+
let url;
|
|
28
|
+
try { url = new URL(value, base); } catch { throw new DrawerInputError('Invalid shortcut address.'); }
|
|
29
|
+
if (value.startsWith('/') && !value.startsWith('//') && url.origin === base && !url.pathname.startsWith('//') &&
|
|
30
|
+
!/%(?:2f|5c)/i.test(url.pathname)) {
|
|
31
|
+
return url.pathname + url.search + url.hash;
|
|
32
|
+
}
|
|
33
|
+
if (value.startsWith('https://') && !url.username && !url.password) return url.href;
|
|
34
|
+
throw new DrawerInputError('Use a dashboard path or an HTTPS address for each shortcut.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function validateDrawerConfig(value) {
|
|
38
|
+
if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).some(key => !Object.hasOwn(EMPTY, key))) {
|
|
39
|
+
throw new DrawerInputError('Invalid drawer configuration.');
|
|
40
|
+
}
|
|
41
|
+
const { html = '', chunks = [], panels = [], shortcuts = [] } = value;
|
|
42
|
+
if (typeof html !== 'string' || Buffer.byteLength(html, 'utf8') > MAX_DRAWER_HTML_BYTES) {
|
|
43
|
+
throw new DrawerInputError('Drawer HTML must be at most 64 KiB.');
|
|
44
|
+
}
|
|
45
|
+
const chunkIds = list(chunks, 'Chunks', 8).map(key => {
|
|
46
|
+
if (typeof key !== 'string' || key.split(':').length !== 2 || key.split(':').some(id => !ID.test(id))) {
|
|
47
|
+
throw new DrawerInputError('Each chunk needs a plugin ID and a chunk ID.');
|
|
48
|
+
}
|
|
49
|
+
return key;
|
|
50
|
+
});
|
|
51
|
+
const references = list(panels, 'Panels', 6).map(panel => {
|
|
52
|
+
if (typeof panel?.plugin !== 'string' || typeof panel?.element !== 'string' ||
|
|
53
|
+
!ID.test(panel.plugin) || !ID.test(panel.element)) throw new DrawerInputError('Invalid plugin panel reference.');
|
|
54
|
+
return { plugin: panel.plugin, element: panel.element };
|
|
55
|
+
});
|
|
56
|
+
const links = list(shortcuts, 'Shortcuts', 16).map(shortcut => {
|
|
57
|
+
const label = typeof shortcut?.label === 'string' ? shortcut.label.trim() : '';
|
|
58
|
+
if (!label || label.length > 80 || /[\u0000-\u001f\u007f]/.test(label)) throw new DrawerInputError('Give each shortcut a name of 1–80 characters.');
|
|
59
|
+
return { label, href: shortcutHref(shortcut.href) };
|
|
60
|
+
});
|
|
61
|
+
return { html, chunks: [...new Set(chunkIds)], panels: references, shortcuts: links };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function readDrawerConfig(brainDir, edge) {
|
|
65
|
+
const store = new PluginStateStore(stateFile(brainDir, edge), OWNER);
|
|
66
|
+
const config = validateDrawerConfig(store.read(EMPTY));
|
|
67
|
+
return { config, version: store.version };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function writeDrawerConfig(brainDir, edge, config, version) {
|
|
71
|
+
if (version !== null && (typeof version !== 'string' || !/^[0-9a-f]{64}$/.test(version))) {
|
|
72
|
+
throw new DrawerInputError('Reload the drawer before saving.');
|
|
73
|
+
}
|
|
74
|
+
const value = validateDrawerConfig(config);
|
|
75
|
+
const result = await executePluginState({
|
|
76
|
+
file: stateFile(brainDir, edge), plugin: OWNER, action: 'write', value, expectedVersion: version,
|
|
77
|
+
});
|
|
78
|
+
return { config: value, version: result.version };
|
|
79
|
+
}
|
package/src/server/api.mjs
CHANGED
|
@@ -15,10 +15,10 @@ import { runInSandbox } from '../core/sandbox.mjs';
|
|
|
15
15
|
import { resolveAgentDir } from '../cli/agent-dir.mjs';
|
|
16
16
|
import { removeSessionEmbeddingFromIndex } from '../core/embeddings.mjs';
|
|
17
17
|
import path from 'path';
|
|
18
|
-
import os from 'os';
|
|
19
18
|
import fs from 'fs';
|
|
20
19
|
import matter from '../core/frontmatter.mjs';
|
|
21
20
|
import { agentDir, brainDir, surfaceDir, instructionsFilePath } from '../core/config.mjs';
|
|
21
|
+
import { resolveVaultFromQuery } from './routes/_shared.mjs';
|
|
22
22
|
|
|
23
23
|
const AGENT_DIR = process.env.AGENT_DIR || agentDir;
|
|
24
24
|
const BRAIN_DIR = process.env.TR_BRAIN || path.join(AGENT_DIR, 'skills', 'total-recall');
|
|
@@ -43,32 +43,9 @@ const MODEL_CATALOG_DIR = path.join(ROOT, 'models', 'catalog', 'total-recall');
|
|
|
43
43
|
* @returns {string} Absolute path to the memory-vault directory
|
|
44
44
|
*/
|
|
45
45
|
function resolveVaultDir(brainId) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (brainId.startsWith('project:')) {
|
|
51
|
-
const projectName = brainId.slice('project:'.length);
|
|
52
|
-
const globalBrainDir = path.join(os.homedir(), '.agent', 'skills', 'total-recall');
|
|
53
|
-
const registryPath = path.join(globalBrainDir, 'config', 'project-registry.json');
|
|
54
|
-
|
|
55
|
-
if (fs.existsSync(registryPath)) {
|
|
56
|
-
try {
|
|
57
|
-
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
58
|
-
const project = registry.find(p => p.name === projectName);
|
|
59
|
-
if (project) {
|
|
60
|
-
const projectVaultDir = path.join(project.brainDir, 'memory-vault');
|
|
61
|
-
if (fs.existsSync(projectVaultDir)) {
|
|
62
|
-
return projectVaultDir;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
} catch {
|
|
66
|
-
// Registry parse error — fall through to default
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return VAULT_DIR;
|
|
46
|
+
return typeof brainId === 'string' && (brainId === 'global' || brainId.startsWith('project:'))
|
|
47
|
+
? resolveVaultFromQuery({ query: { brain: brainId } })
|
|
48
|
+
: VAULT_DIR;
|
|
72
49
|
}
|
|
73
50
|
|
|
74
51
|
function sha256(content) {
|
package/src/server/index.mjs
CHANGED
|
@@ -352,6 +352,8 @@ app.get('/health', requireAuthOrLocal, async (req, res) => {
|
|
|
352
352
|
cloudflare: cloudflareStatus,
|
|
353
353
|
emergency_alerts: emergencyAlerts || null,
|
|
354
354
|
fetch_gate,
|
|
355
|
+
// Whether the served dashboard is as new as this checkout's frontend sources.
|
|
356
|
+
dashboard: dashboardBundle.state(),
|
|
355
357
|
vfs: {
|
|
356
358
|
exists: vaultExists,
|
|
357
359
|
skill_exists: skillExists,
|
|
@@ -444,24 +446,30 @@ try {
|
|
|
444
446
|
|
|
445
447
|
const frontendDist = path.join(ROOT, 'frontend', 'dist');
|
|
446
448
|
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
449
|
+
// Live refresh for the memory page on this port (the /stream monitor listens on 127.0.0.1 only).
|
|
450
|
+
const { memoryEventsHandler } = await import('./memory-events.mjs');
|
|
451
|
+
app.get('/api/memory-events', requireAuth, memoryEventsHandler(logEvents));
|
|
452
|
+
|
|
453
|
+
// Keep the served dashboard as new as its sources. A missing or stale bundle is
|
|
454
|
+
// rebuilt in the background while the current one keeps serving; express.static
|
|
455
|
+
// resolves files per request, so the swapped-in build serves without a restart.
|
|
456
|
+
// Building only when index.html was missing left every later frontend commit unserved.
|
|
457
|
+
const { watchDashboardBundle } = await import('../core/dashboard-bundle.mjs');
|
|
458
|
+
const dashboardBundle = watchDashboardBundle({
|
|
459
|
+
root: ROOT,
|
|
460
|
+
report: (state) => {
|
|
461
|
+
if (state.status === 'current' && state.rebuilt) {
|
|
462
|
+
logger.info('server', `Dashboard bundle rebuilt from newer sources (${Math.round(state.durationMs / 1000)} s); serving it now.`);
|
|
463
|
+
} else if (state.status === 'current') {
|
|
464
|
+
logger.info('server', 'Dashboard bundle is current.');
|
|
465
|
+
} else if (state.retryInMs) {
|
|
466
|
+
logger.info('server', `Dashboard bundle is ${state.status}; rebuilding once the sources stop changing.`);
|
|
467
|
+
} else {
|
|
468
|
+
logger.error('server', `Dashboard bundle is ${state.status} and was not rebuilt: ${state.reason}.${state.build?.output ? ` Build output: ${state.build.output.slice(-1500)}` : ''}`);
|
|
462
469
|
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
dashboardBundle.check();
|
|
465
473
|
|
|
466
474
|
app.use(express.static(frontendDist));
|
|
467
475
|
|
|
@@ -803,8 +811,7 @@ app.get('/chat', (req, res) => {
|
|
|
803
811
|
|
|
804
812
|
// SPA fallback — serve index.html for all unmatched routes
|
|
805
813
|
app.get(/^(.*)$/, (req, res) => {
|
|
806
|
-
|
|
807
|
-
res.sendFile(indexPath, (err) => {
|
|
814
|
+
res.sendFile('index.html', { root: frontendDist }, (err) => {
|
|
808
815
|
if (err) {
|
|
809
816
|
// Frontend not built yet — return a helpful message
|
|
810
817
|
res.status(200).json({
|
|
@@ -814,7 +821,7 @@ app.get(/^(.*)$/, (req, res) => {
|
|
|
814
821
|
memory: 'GET /api/memory',
|
|
815
822
|
sandbox: 'POST /api/sandbox',
|
|
816
823
|
health: 'GET /health',
|
|
817
|
-
dashboard:
|
|
824
|
+
dashboard: `Dashboard bundle is ${dashboardBundle.state().status}${dashboardBundle.state().reason ? `: ${dashboardBundle.state().reason}` : ''}. The server rebuilds it from frontend/ in the background.`
|
|
818
825
|
}
|
|
819
826
|
});
|
|
820
827
|
}
|
|
@@ -874,7 +881,7 @@ const server = app.listen(PORT, HOST, () => {
|
|
|
874
881
|
|
|
875
882
|
// Only meaningful once the socket is up: asking before the callback fires
|
|
876
883
|
// reads an empty set, which is "unknown", so the watch never armed.
|
|
877
|
-
if (isReachableFromOtherDevices() === false) {
|
|
884
|
+
if (bindResolution.usedLoopbackFallback && isReachableFromOtherDevices() === false) {
|
|
878
885
|
logger.warn(
|
|
879
886
|
'server',
|
|
880
887
|
`Bound to loopback only — no other device can reach this brain at :${PORT}. `
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Full-mode owner work shares invoke's process-group and output limits. */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
console.log = console.info = console.debug = (...args) => console.error(...args);
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
let input = '';
|
|
7
|
+
for await (const chunk of process.stdin) {
|
|
8
|
+
input += chunk;
|
|
9
|
+
if (Buffer.byteLength(input) > 32768) throw new Error('Input limit');
|
|
10
|
+
}
|
|
11
|
+
const { operation, params, brain, registryBrain } = JSON.parse(input);
|
|
12
|
+
// Config and Auth must use the serving brain, not a brain inferred from cwd.
|
|
13
|
+
process.env.AGENT_DIR = path.dirname(path.dirname(brain));
|
|
14
|
+
process.env.TR_SECRETS_BRAIN = brain;
|
|
15
|
+
const { executeCoreOperation } = await import('./invoke-core-operations.mjs');
|
|
16
|
+
const result = await executeCoreOperation(operation, params, { brain, registryBrain });
|
|
17
|
+
process.stdout.write(JSON.stringify({ ok: true, result }));
|
|
18
|
+
} catch (err) {
|
|
19
|
+
// Return curated policy codes only. Never return owner exception text.
|
|
20
|
+
const { InvokeError } = await import('./invoke-execution.mjs');
|
|
21
|
+
process.stdout.write(JSON.stringify({ ok: false, error: err instanceof InvokeError ? err.code : 'operation-failed',
|
|
22
|
+
status: err instanceof InvokeError ? err.status : 502 }));
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/** Owner adapters for the retired one-off remote routes. */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import matter from '../core/frontmatter.mjs';
|
|
5
|
+
import { readRegisteredProjects } from '../core/brain-registry.mjs';
|
|
6
|
+
import { InvokeError } from './invoke-execution.mjs';
|
|
7
|
+
|
|
8
|
+
export const CORE_OPERATIONS = Object.freeze({
|
|
9
|
+
'context.preview': { scope: 'memory:read', family: 'context' },
|
|
10
|
+
'context.stream': { scope: 'memory:read', family: 'context' },
|
|
11
|
+
'context.flash.health': { scope: 'memory:read', family: 'context' },
|
|
12
|
+
'brains.sync': { scope: 'memory:write', family: 'brains' },
|
|
13
|
+
'tasks.cleanup': { scope: 'tasks:write', family: 'tasks' },
|
|
14
|
+
'tasks.failed': { scope: 'tasks:read', family: 'tasks' },
|
|
15
|
+
'vault.hash': { scope: 'memory:read', family: 'vault' },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export function validateCoreParams(operation, params) {
|
|
19
|
+
if (params.timeoutMs !== undefined && (!Number.isFinite(Number(params.timeoutMs)) || Number(params.timeoutMs) <= 0)) {
|
|
20
|
+
throw new InvokeError(400, 'invalid-timeout', 'timeoutMs must be positive and finite.');
|
|
21
|
+
}
|
|
22
|
+
const allowed = new Set(['target', 'timeoutMs']);
|
|
23
|
+
if (!['brains.sync', 'context.flash.health'].includes(operation)) allowed.add('brainId');
|
|
24
|
+
if (operation === 'context.stream') for (const key of ['query', 'budget_tokens', 'concurrency', 'min_score']) allowed.add(key);
|
|
25
|
+
if (Object.keys(params).some(key => !allowed.has(key))) throw new InvokeError(400, 'unknown-parameter', 'Unsupported operation parameter.');
|
|
26
|
+
if (params.brainId !== undefined && (typeof params.brainId !== 'string' || !params.brainId || params.brainId.includes(','))) {
|
|
27
|
+
throw new InvokeError(400, 'invalid-brain', 'brainId must select one brain.');
|
|
28
|
+
}
|
|
29
|
+
if (params.brainId !== undefined && !['server', 'global'].includes(params.brainId) &&
|
|
30
|
+
!/^project:[^/\\\0,]+$/.test(params.brainId)) {
|
|
31
|
+
throw new InvokeError(400, 'invalid-brain', 'brainId must select the server or a registered project.');
|
|
32
|
+
}
|
|
33
|
+
if (operation === 'context.stream') {
|
|
34
|
+
if (typeof params.query !== 'string' || !params.query.trim()) throw new InvokeError(400, 'invalid-query', 'query is required.');
|
|
35
|
+
for (const [key, min, max] of [['budget_tokens', 1, 65536], ['concurrency', 1, 4], ['min_score', 0, 100]]) {
|
|
36
|
+
if (params[key] !== undefined && (!Number.isInteger(params[key]) || params[key] < min || params[key] > max)) {
|
|
37
|
+
throw new InvokeError(400, 'invalid-parameter', `Invalid ${key}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function selectedBrain(brainId, brain, registryBrain) {
|
|
44
|
+
if (brainId === undefined || brainId === 'server' || brainId === 'global') return brain;
|
|
45
|
+
if (brainId.startsWith('project:')) {
|
|
46
|
+
const name = brainId.slice('project:'.length);
|
|
47
|
+
const project = readRegisteredProjects(registryBrain).find(row => row.name === name || row.project_id === name);
|
|
48
|
+
if (project?.brainDir && fs.existsSync(path.join(project.brainDir, 'memory-vault'))) return project.brainDir;
|
|
49
|
+
}
|
|
50
|
+
throw new InvokeError(404, 'brain-unavailable', 'Selected brain is unavailable.');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function executeCoreOperation(operation, params, { brain, registryBrain }) {
|
|
54
|
+
if (!Object.hasOwn(CORE_OPERATIONS, operation)) throw new InvokeError(404, 'unknown-operation', 'Unknown operation.');
|
|
55
|
+
validateCoreParams(operation, params);
|
|
56
|
+
const selected = selectedBrain(params.brainId, brain, registryBrain);
|
|
57
|
+
const vaultDir = path.join(selected, 'memory-vault');
|
|
58
|
+
switch (operation) {
|
|
59
|
+
case 'context.preview': {
|
|
60
|
+
const { previewContext } = await import('../core/context-compiler.mjs');
|
|
61
|
+
return previewContext({ vaultDir });
|
|
62
|
+
}
|
|
63
|
+
case 'context.stream': {
|
|
64
|
+
const { streamParallelContext } = await import('../core/parallel-context.mjs');
|
|
65
|
+
const result = await streamParallelContext({ query: params.query, vaultDir,
|
|
66
|
+
budgetTokens: params.budget_tokens, concurrency: params.concurrency, minScore: params.min_score });
|
|
67
|
+
// Provider diagnostics can contain a credential-bearing URL.
|
|
68
|
+
return { ...result, scored: result.scored.map(({ error, ...row }) => error ? { ...row, error: 'provider-failed' } : row) };
|
|
69
|
+
}
|
|
70
|
+
case 'context.flash.health': {
|
|
71
|
+
const { checkFlashHealth } = await import('../core/parallel-context.mjs');
|
|
72
|
+
const { error, ...result } = await checkFlashHealth();
|
|
73
|
+
return error ? { ...result, error: 'provider-unavailable' } : result;
|
|
74
|
+
}
|
|
75
|
+
case 'brains.sync': {
|
|
76
|
+
const { syncAllRepos } = await import('../core/repo-sync.mjs');
|
|
77
|
+
const result = await syncAllRepos({ registryBrain });
|
|
78
|
+
if (result.repos.some(row => row.errors)) throw new InvokeError(502, 'sync-failed', 'Some repositories failed to sync.');
|
|
79
|
+
return { ok: true, ...result };
|
|
80
|
+
}
|
|
81
|
+
case 'tasks.cleanup': {
|
|
82
|
+
const queue = path.join(selected, 'scheduler/queue');
|
|
83
|
+
let deleted = 0;
|
|
84
|
+
if (fs.existsSync(queue)) for (const entry of fs.readdirSync(queue, { withFileTypes: true })) {
|
|
85
|
+
if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
|
|
86
|
+
const file = path.join(queue, entry.name);
|
|
87
|
+
const { data } = matter(fs.readFileSync(file, 'utf8'));
|
|
88
|
+
if (data.status === 'completed') { fs.unlinkSync(file); deleted++; }
|
|
89
|
+
}
|
|
90
|
+
return { deleted };
|
|
91
|
+
}
|
|
92
|
+
case 'tasks.failed': {
|
|
93
|
+
const { listTasks } = await import('../core/task-envelope.mjs');
|
|
94
|
+
const tasks = listTasks(path.join(selected, 'scheduler/queue'), { status: 'failed' });
|
|
95
|
+
return { total: tasks.length, tasks };
|
|
96
|
+
}
|
|
97
|
+
case 'vault.hash': {
|
|
98
|
+
const file = path.join(selected, 'memory-derived/vault-hash.txt');
|
|
99
|
+
return { vault_hash: fs.existsSync(file) ? fs.readFileSync(file, 'utf8').trim() : null, vault_dir: vaultDir };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live refresh for the memory page, on the dashboard's own port.
|
|
3
|
+
*
|
|
4
|
+
* The page listened to `/stream` on the dashboard origin, but the server
|
|
5
|
+
* serves `/stream` only on the 127.0.0.1 monitor port, so the dashboard got
|
|
6
|
+
* its HTML fallback and the live refresh never connected. This stream is
|
|
7
|
+
* authenticated like the rest of the dashboard API and carries only the
|
|
8
|
+
* subsystem name of the events that change what the page shows, never log
|
|
9
|
+
* contents.
|
|
10
|
+
*/
|
|
11
|
+
export const MEMORY_EVENT_SUBSYSTEMS = new Set(['conflict-detector', 'rebuild', 'session-watcher']);
|
|
12
|
+
const HEARTBEAT_MS = 25000;
|
|
13
|
+
|
|
14
|
+
/** @param {import('node:events').EventEmitter} events Emits 'log' entries ({ subsystem, ... }). */
|
|
15
|
+
export function memoryEventsHandler(events, { heartbeatMs = HEARTBEAT_MS } = {}) {
|
|
16
|
+
return (req, res) => {
|
|
17
|
+
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });
|
|
18
|
+
res.write(': connected\n\n');
|
|
19
|
+
const onLog = (entry) => {
|
|
20
|
+
if (MEMORY_EVENT_SUBSYSTEMS.has(entry?.subsystem)) res.write(`data: ${JSON.stringify({ subsystem: entry.subsystem })}\n\n`);
|
|
21
|
+
};
|
|
22
|
+
events.on('log', onLog);
|
|
23
|
+
// Comment lines keep proxies from closing an idle stream.
|
|
24
|
+
const heartbeat = setInterval(() => res.write(': ping\n\n'), heartbeatMs);
|
|
25
|
+
heartbeat.unref?.();
|
|
26
|
+
req.on('close', () => {
|
|
27
|
+
events.off('log', onLog);
|
|
28
|
+
clearInterval(heartbeat);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { dashboardBrainDir, globalBrainDirFor, readBrainToggles, readRegisteredProjects } from '../core/brain-registry.mjs';
|
|
4
|
+
import { projectPluginsDir } from '../core/plugin-loader.mjs';
|
|
5
|
+
import { readProjectId } from '../core/project-id.mjs';
|
|
6
|
+
import { keyHasScope } from './keys.mjs';
|
|
7
|
+
|
|
8
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
9
|
+
const PROJECT_SELECTOR = /^project:[^/\\:,\x00-\x1f\x7f]{1,160}$/u;
|
|
10
|
+
|
|
11
|
+
const targetError = (status, message) => Object.assign(new Error(message), { status });
|
|
12
|
+
|
|
13
|
+
function optionalDirectoriesAreLocal(brainDir) {
|
|
14
|
+
for (const name of ['plugins', 'memory-vault', 'memory-derived']) {
|
|
15
|
+
try {
|
|
16
|
+
if (!fs.lstatSync(path.join(brainDir, name)).isDirectory()) return false;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error.code !== 'ENOENT') return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function resolveProject(row, sharedBrain, toggles) {
|
|
25
|
+
try {
|
|
26
|
+
if (typeof row.path !== 'string' || !path.isAbsolute(row.path) ||
|
|
27
|
+
typeof row.brainDir !== 'string' || !path.isAbsolute(row.brainDir)) return null;
|
|
28
|
+
const projectRoot = fs.realpathSync(row.path);
|
|
29
|
+
const brainDir = path.dirname(projectPluginsDir(projectRoot));
|
|
30
|
+
const identity = path.join(brainDir, 'config', 'brain.json');
|
|
31
|
+
if (brainDir === sharedBrain || fs.realpathSync(row.brainDir) !== brainDir ||
|
|
32
|
+
fs.realpathSync(brainDir) !== brainDir || fs.realpathSync(identity) !== identity ||
|
|
33
|
+
!fs.lstatSync(identity).isFile() || readProjectId(brainDir) !== row.project_id ||
|
|
34
|
+
toggles[path.resolve(row.brainDir)] === false || toggles[brainDir] === false ||
|
|
35
|
+
!optionalDirectoriesAreLocal(brainDir)) return null;
|
|
36
|
+
return { brainDir, projectRoot };
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function authorize(auth, scope) {
|
|
43
|
+
if (auth?.type === 'dashboard_session') return;
|
|
44
|
+
if (auth?.type !== 'pat' || !keyHasScope(auth, scope)) {
|
|
45
|
+
throw targetError(403, 'The token does not grant access to a selected brain.');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Resolve selected IDs against server-owned registrations before plugin I/O. */
|
|
50
|
+
export function resolvePluginBrainTargets(ids, auth, { registryBrain = globalBrainDirFor() } = {}) {
|
|
51
|
+
if (!Array.isArray(ids) || !ids.length || ids.length > 64 ||
|
|
52
|
+
ids.some(id => typeof id !== 'string' || (id !== 'global' && !PROJECT_SELECTOR.test(id)))) {
|
|
53
|
+
throw targetError(400, 'Select up to 64 global or registered project brain IDs.');
|
|
54
|
+
}
|
|
55
|
+
let sharedBrain, rows, toggles, globalToggles;
|
|
56
|
+
try {
|
|
57
|
+
const projectRegistryBrain = dashboardBrainDir(process.env, registryBrain);
|
|
58
|
+
sharedBrain = fs.realpathSync(registryBrain);
|
|
59
|
+
globalToggles = ids.includes('global') ? readBrainToggles(registryBrain, { strict: true }) : {};
|
|
60
|
+
const needsProjects = ids.some(id => id !== 'global');
|
|
61
|
+
toggles = needsProjects ? readBrainToggles(projectRegistryBrain, { strict: true }) : {};
|
|
62
|
+
rows = needsProjects ? readRegisteredProjects(projectRegistryBrain) : [];
|
|
63
|
+
} catch {
|
|
64
|
+
throw targetError(503, 'Brain registry metadata is unavailable.');
|
|
65
|
+
}
|
|
66
|
+
const resolved = new Set();
|
|
67
|
+
return [...new Set(ids)].map(brainId => {
|
|
68
|
+
if (brainId === 'global') {
|
|
69
|
+
authorize(auth, 'brain:global');
|
|
70
|
+
if (globalToggles[path.resolve(registryBrain)] === false || globalToggles[sharedBrain] === false) {
|
|
71
|
+
throw targetError(404, 'The selected global brain is unavailable.');
|
|
72
|
+
}
|
|
73
|
+
return { brainId, name: 'Global Brain', brainDir: sharedBrain, projectRoot: null };
|
|
74
|
+
}
|
|
75
|
+
const selector = brainId.slice('project:'.length);
|
|
76
|
+
const matches = rows.filter(row => row.name === selector || row.project_id === selector);
|
|
77
|
+
if (matches.length > 1) throw targetError(409, 'A selected project brain ID is ambiguous.');
|
|
78
|
+
const row = matches[0];
|
|
79
|
+
if (typeof row?.project_id !== 'string' || !UUID.test(row.project_id) || rows.filter(candidate => candidate.project_id === row.project_id).length !== 1) {
|
|
80
|
+
throw targetError(404, 'A selected project brain is unavailable.');
|
|
81
|
+
}
|
|
82
|
+
authorize(auth, 'brain:project-' + row.project_id);
|
|
83
|
+
const target = resolveProject(row, sharedBrain, toggles);
|
|
84
|
+
if (!target) throw targetError(404, 'A selected project brain is unavailable.');
|
|
85
|
+
if (resolved.has(target.brainDir)) throw targetError(400, 'Select each project brain once.');
|
|
86
|
+
resolved.add(target.brainDir);
|
|
87
|
+
return { brainId, name: row.name || selector, ...target };
|
|
88
|
+
});
|
|
89
|
+
}
|
package/src/server/rest.mjs
CHANGED
|
@@ -121,6 +121,7 @@ import updateRouter from './routes/update.mjs';
|
|
|
121
121
|
import { rulesRouter } from './routes/rules.mjs';
|
|
122
122
|
import notificationsRouter from './routes/notifications.mjs';
|
|
123
123
|
import pluginsRouter from './routes/plugins.mjs';
|
|
124
|
+
import uiChunksRouter from './routes/ui-chunks.mjs';
|
|
124
125
|
// ollamaUrl removed — CLI agents replace Ollama
|
|
125
126
|
import {
|
|
126
127
|
AGENT_DIR,
|
|
@@ -235,6 +236,7 @@ router.use(ssssRouter);
|
|
|
235
236
|
router.use(rulesRouter);
|
|
236
237
|
router.use(notificationsRouter);
|
|
237
238
|
router.use(pluginsRouter);
|
|
239
|
+
router.use(uiChunksRouter);
|
|
238
240
|
for (const pluginRouter of await (await import('../core/plugin-runtime.mjs')).loadPluginRouters()) router.use(pluginRouter);
|
|
239
241
|
|
|
240
242
|
export { router as restRouter };
|
|
@@ -29,13 +29,14 @@ export function extractRoutes(router) {
|
|
|
29
29
|
|
|
30
30
|
for (const layer of stack) {
|
|
31
31
|
if (layer.route) {
|
|
32
|
-
|
|
32
|
+
// Express keeps aliases and regular expressions in Route.path.
|
|
33
|
+
const paths = [layer.route.path].flat(Infinity).map(String);
|
|
33
34
|
const methods = Object.keys(layer.route.methods)
|
|
34
35
|
.filter((method) => layer.route.methods[method])
|
|
35
36
|
.map((method) => method.toUpperCase());
|
|
36
37
|
|
|
37
38
|
for (const method of methods) {
|
|
38
|
-
routes.push({ method, path
|
|
39
|
+
for (const path of paths) routes.push({ method, path });
|
|
39
40
|
}
|
|
40
41
|
} else if (layer.name === 'router' && layer.handle && layer.handle.stack) {
|
|
41
42
|
// Sub-router mounted via router.use()
|