total-recall-brain 3.45.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 +4 -2
- 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 +183 -236
- 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 +6 -6
- 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/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/{ui/DESIGN.md → DESIGN.md} +32 -21
- package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +17 -1
- package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +10 -1
- package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +4 -3
- package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +11 -27
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -2
- 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/{card.js → home.js} +32 -27
- 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 +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +6 -6
- 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 +6 -6
- 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 +6 -6
- 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 +25 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/cli.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +17 -27
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +30 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +24 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +33 -7
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +29 -5
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -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 +6 -6
- 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 +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +43 -22
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
- 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 +17 -14
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +6 -6
- 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.mjs +6 -3
- 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 +6 -6
- 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 +2 -0
- package/src/cli/api.mjs +3 -3
- package/src/cli/brief.mjs +3 -0
- package/src/cli/config.mjs +16 -0
- package/src/cli/connect.mjs +2 -7
- package/src/cli/plugin/chunks.mjs +145 -0
- package/src/cli/plugin/create.mjs +24 -52
- package/src/cli/plugin/index.mjs +20 -9
- package/src/cli/setup.mjs +2 -9
- package/src/cli/start.mjs +1 -0
- package/src/cli/startup.mjs +18 -0
- package/src/core/app-deploy/design-tokens.mjs +14 -9
- package/src/core/app-deploy/ui-elements.mjs +1 -1
- package/src/core/brain-registry.mjs +5 -0
- package/src/core/brain-updates.mjs +5 -1
- package/src/core/daemon-control.mjs +5 -1
- package/src/core/dashboard-bundle.mjs +261 -0
- package/src/core/ensure-dependencies.mjs +19 -15
- package/src/core/memory-brain.mjs +30 -8
- package/src/core/plugin-activation.mjs +63 -20
- package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +23 -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 +9 -5
- package/src/core/plugin-runner.mjs +21 -10
- package/src/core/plugin-startup-checks.mjs +44 -0
- package/src/core/plugin-state.mjs +19 -5
- package/src/core/plugin-store.mjs +30 -11
- package/src/core/project-id.mjs +15 -5
- package/src/core/required-plugins.mjs +31 -6
- package/src/core/schema.mjs +2 -0
- package/src/core/ssss-operation-service.mjs +1 -0
- package/src/core/startup-health.mjs +28 -3
- 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/vault-cache.mjs +58 -59
- 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/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 +52 -4
- package/src/server/routes/_shared.mjs +7 -14
- package/src/server/routes/brains.mjs +29 -44
- package/src/server/routes/dashboard.mjs +26 -0
- package/src/server/routes/plugins.mjs +154 -45
- package/src/server/routes/ui-chunks.mjs +192 -0
- package/frontend/dist/assets/index-DACh1dhx.js +0 -5613
- 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/ui/DESIGN.md +0 -100
- package/scaffold/.agent/skills/total-recall/plugins/git/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
|
@@ -16,12 +16,14 @@ export async function listMemory(brainId?: string, category?: string, status?: s
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const ids = brainId.split(',')
|
|
19
|
+
const globalParams = new URLSearchParams(params)
|
|
20
|
+
globalParams.set('brain', 'global')
|
|
19
21
|
const fetchPromises = ids.map(async (id) => {
|
|
20
22
|
const url = id === 'global'
|
|
21
|
-
? `${API_BASE}/api/memory?${
|
|
22
|
-
: `${API_BASE}/api/brains/${id}/nodes?${params}`
|
|
23
|
+
? `${API_BASE}/api/memory?${globalParams}`
|
|
24
|
+
: `${API_BASE}/api/brains/${encodeURIComponent(id)}/nodes?${params}`
|
|
23
25
|
try {
|
|
24
|
-
const res = await apiFetch(url)
|
|
26
|
+
const res = await apiFetch(url, { cache: 'no-store' })
|
|
25
27
|
if (!res.ok) return []
|
|
26
28
|
const data = await res.json()
|
|
27
29
|
return Array.isArray(data) ? data : (data.nodes || [])
|
|
@@ -54,10 +56,11 @@ export async function listMemory(brainId?: string, category?: string, status?: s
|
|
|
54
56
|
return merged
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
export async function searchMemory(query: string, category?: string): Promise<MemoryNode[]> {
|
|
59
|
+
export async function searchMemory(query: string, category?: string, brainId?: string): Promise<MemoryNode[]> {
|
|
58
60
|
const params = new URLSearchParams({ q: query })
|
|
59
61
|
if (category) params.set('category', category)
|
|
60
|
-
|
|
62
|
+
if (brainId) params.set('brain', brainId)
|
|
63
|
+
const res = await apiFetch(`${API_BASE}/api/memory?${params}`, { cache: 'no-store' })
|
|
61
64
|
if (!res.ok) throw new Error(`Memory API error: ${res.status}`)
|
|
62
65
|
const data = await res.json()
|
|
63
66
|
return Array.isArray(data) ? data : (data.nodes || [])
|
|
@@ -167,10 +170,12 @@ export async function fetchOpenWikiNodes(
|
|
|
167
170
|
// Reuse listMemory brain routing (global vs project:name), then keep openwiki-tagged only.
|
|
168
171
|
// Server also filters tag=openwiki when we hit /api/memory?tag=openwiki.
|
|
169
172
|
const params = new URLSearchParams({ tag: 'openwiki', limit: '500' })
|
|
173
|
+
const globalParams = new URLSearchParams(params)
|
|
174
|
+
globalParams.set('brain', 'global')
|
|
170
175
|
const ids = active.split(',').map((s) => s.trim()).filter(Boolean)
|
|
171
176
|
|
|
172
177
|
if (ids.length === 0 || (ids.length === 1 && ids[0] === 'global')) {
|
|
173
|
-
const res = await apiFetch(`${API_BASE}/api/memory?${
|
|
178
|
+
const res = await apiFetch(`${API_BASE}/api/memory?${globalParams}`, { cache: 'no-store' })
|
|
174
179
|
if (!res.ok) throw new Error(`OpenWiki nodes error: ${res.status}`)
|
|
175
180
|
const data = await res.json()
|
|
176
181
|
const nodes = Array.isArray(data) ? data : (data.nodes ?? [])
|
|
@@ -181,7 +186,7 @@ export async function fetchOpenWikiNodes(
|
|
|
181
186
|
const fetchPromises = ids.map(async (id) => {
|
|
182
187
|
try {
|
|
183
188
|
if (id === 'global') {
|
|
184
|
-
const res = await apiFetch(`${API_BASE}/api/memory?${
|
|
189
|
+
const res = await apiFetch(`${API_BASE}/api/memory?${globalParams}`, { cache: 'no-store' })
|
|
185
190
|
if (!res.ok) return []
|
|
186
191
|
const data = await res.json()
|
|
187
192
|
return Array.isArray(data) ? data : (data.nodes ?? [])
|
|
@@ -190,7 +195,7 @@ export async function fetchOpenWikiNodes(
|
|
|
190
195
|
const res = await apiFetch(`${API_BASE}/api/brains/${encodeURIComponent(id)}/nodes`)
|
|
191
196
|
if (!res.ok) {
|
|
192
197
|
// Fallback: memory list with brain header already set by apiFetch
|
|
193
|
-
const res2 = await apiFetch(`${API_BASE}/api/memory?${params}&brain=${encodeURIComponent(id)}
|
|
198
|
+
const res2 = await apiFetch(`${API_BASE}/api/memory?${params}&brain=${encodeURIComponent(id)}`, { cache: 'no-store' })
|
|
194
199
|
if (!res2.ok) return []
|
|
195
200
|
const data2 = await res2.json()
|
|
196
201
|
return Array.isArray(data2) ? data2 : (data2.nodes ?? [])
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { apiFetch, API_BASE } from './_base'
|
|
2
|
+
import type { PluginInfo } from './plugins'
|
|
3
|
+
|
|
4
|
+
export async function readSavedPluginCredentials() {
|
|
5
|
+
const response = await apiFetch(`${API_BASE}/api/plugins/auth/secrets?catalog=0`)
|
|
6
|
+
if (!response.ok) throw new Error('Could not check saved credentials.')
|
|
7
|
+
const payload = await response.json()
|
|
8
|
+
const rows = Array.isArray(payload) ? payload : payload?.keys
|
|
9
|
+
if (!Array.isArray(rows)) throw new Error('Could not check saved credentials.')
|
|
10
|
+
return new Set<string>(rows.filter(row => typeof row?.key === 'string' && row.set !== false).map(row => row.key))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function savePluginCredential(plugin: PluginInfo, key: string, value: string, brainId?: string) {
|
|
14
|
+
const runtime = plugin.manifest?.runtime as { modules?: { credentials?: string } } | undefined
|
|
15
|
+
const route = runtime?.modules?.credentials
|
|
16
|
+
? `/api/plugins/${encodeURIComponent(plugin.id)}/credentials${brainId ? `?brain=${encodeURIComponent(brainId)}` : ''}`
|
|
17
|
+
: '/api/plugins/auth/secrets'
|
|
18
|
+
const response = await apiFetch(API_BASE + route, {
|
|
19
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
body: JSON.stringify({ key, value, tags: [`plugin:${plugin.id}`] }),
|
|
21
|
+
})
|
|
22
|
+
if (!response.ok) throw new Error('Could not verify and save the credential.')
|
|
23
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// plugin came from, its content hash, whether it is shared, and — for peers —
|
|
5
5
|
// whether that peer answered. There are no ratings, reviews or install counts.
|
|
6
6
|
|
|
7
|
-
import { apiFetch, API_BASE
|
|
7
|
+
import { apiFetch, API_BASE } from "./_base"
|
|
8
8
|
|
|
9
9
|
export type PluginSourceKind = "bundled" | "public" | "peer" | "git" | "local" | "link"
|
|
10
10
|
|
|
@@ -21,33 +21,9 @@ export interface PluginTask {
|
|
|
21
21
|
last_run: string | null
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export interface CardFaceAction {
|
|
25
|
-
subcommand: string
|
|
26
|
-
label: string
|
|
27
|
-
icon?: string
|
|
28
|
-
color?: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface CardFaceMetric {
|
|
32
|
-
label: string
|
|
33
|
-
value: string
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface CardFaceConfig {
|
|
37
|
-
skin?: string
|
|
38
|
-
theme?: string
|
|
39
|
-
headline?: string
|
|
40
|
-
primary_color?: string
|
|
41
|
-
secondary_color?: string
|
|
42
|
-
accent_color?: string
|
|
43
|
-
touch_layout?: string
|
|
44
|
-
quick_actions?: CardFaceAction[]
|
|
45
|
-
metrics?: CardFaceMetric[]
|
|
46
|
-
interactive?: boolean
|
|
47
|
-
}
|
|
48
|
-
|
|
49
24
|
export interface PluginInfo {
|
|
50
25
|
id: string
|
|
26
|
+
core?: boolean
|
|
51
27
|
name: string
|
|
52
28
|
version: string
|
|
53
29
|
description: string
|
|
@@ -57,7 +33,7 @@ export interface PluginInfo {
|
|
|
57
33
|
use_cases: string[]
|
|
58
34
|
valid: boolean
|
|
59
35
|
errors: string[]
|
|
60
|
-
scope: "project" | "global"
|
|
36
|
+
scope: "project" | "global" | "scaffold"
|
|
61
37
|
linked: boolean
|
|
62
38
|
dir: string
|
|
63
39
|
shared: boolean
|
|
@@ -73,16 +49,26 @@ export interface PluginInfo {
|
|
|
73
49
|
categories: Array<{ name: string; description?: string; node_type?: string }>
|
|
74
50
|
tasks: PluginTask[]
|
|
75
51
|
openwiki_hubs: Array<{ title?: string; path: string }>
|
|
76
|
-
cli: { command: string | null; subcommands: Array<{ name: string; description?: string }> } | null
|
|
52
|
+
cli: { command: string | null; subcommands: Array<{ name: string; description?: string; sensitive_output?: boolean; terminal_only?: boolean }> } | null
|
|
77
53
|
has_generator: boolean
|
|
78
54
|
branding?: { icon?: string | null; image?: string | null; color?: string | null; badge?: string | null; name?: string; wordmark?: string; accent?: string; background?: string }
|
|
79
|
-
card_face?: CardFaceConfig
|
|
80
55
|
locked?: boolean
|
|
81
56
|
store_deployed?: boolean
|
|
82
57
|
secrets?: Array<{ key: string; description?: string; required?: boolean }>
|
|
83
58
|
manifest?: Record<string, unknown>
|
|
84
|
-
activation?: { state: 'active' | 'inactive'; enabled: boolean }
|
|
85
|
-
|
|
59
|
+
activation?: { state: 'active' | 'inactive' | 'error' | 'mixed'; enabled: boolean; required?: boolean; mode?: 'on-use' }
|
|
60
|
+
activationByBrain?: BrainPluginActivation[]
|
|
61
|
+
servingAvailable?: boolean
|
|
62
|
+
ui?: { home?: string; elements: Array<{ id: string; kind: string; tag: string; module: string; description?: string }> } | null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface BrainPluginActivation {
|
|
66
|
+
brainId: string
|
|
67
|
+
name: string
|
|
68
|
+
state: 'active' | 'inactive' | 'error' | 'unavailable'
|
|
69
|
+
enabled: boolean
|
|
70
|
+
required?: boolean
|
|
71
|
+
mode?: 'on-use'
|
|
86
72
|
}
|
|
87
73
|
|
|
88
74
|
export interface BundledPlugin {
|
|
@@ -154,20 +140,18 @@ async function post(url: string, body: unknown, method = "POST"): Promise<Result
|
|
|
154
140
|
}
|
|
155
141
|
}
|
|
156
142
|
|
|
157
|
-
export async function fetchPlugins(): Promise<PluginInfo[]> {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return []
|
|
165
|
-
}
|
|
143
|
+
export async function fetchPlugins(brain?: string): Promise<PluginInfo[]> {
|
|
144
|
+
const selector = brain === undefined ? '' : `?brain=${encodeURIComponent(brain)}`
|
|
145
|
+
const res = await apiFetch(`${API_BASE}/api/plugins${selector}`, { cache: 'no-store' })
|
|
146
|
+
const data = await readJson(res)
|
|
147
|
+
if (!res.ok) throw new Error(data.error || `Could not load plugins (${res.status})`)
|
|
148
|
+
if (!Array.isArray(data.plugins)) throw new Error("The server did not return a plugin list")
|
|
149
|
+
return data.plugins
|
|
166
150
|
}
|
|
167
151
|
|
|
168
152
|
export async function fetchPlugin(id: string): Promise<PluginInfo | null> {
|
|
169
153
|
try {
|
|
170
|
-
const res = await apiFetch(`${API_BASE}/api/plugins/${encodeURIComponent(id)}
|
|
154
|
+
const res = await apiFetch(`${API_BASE}/api/plugins/${encodeURIComponent(id)}`, { cache: 'no-store' })
|
|
171
155
|
if (!res.ok) return null
|
|
172
156
|
const data = await readJson(res)
|
|
173
157
|
return data.plugin || null
|
|
@@ -178,7 +162,7 @@ export async function fetchPlugin(id: string): Promise<PluginInfo | null> {
|
|
|
178
162
|
|
|
179
163
|
export async function fetchBundledPlugins(): Promise<BundledPlugin[]> {
|
|
180
164
|
try {
|
|
181
|
-
const res = await apiFetch(`${API_BASE}/api/plugins/available
|
|
165
|
+
const res = await apiFetch(`${API_BASE}/api/plugins/available`, { cache: 'no-store' })
|
|
182
166
|
if (!res.ok) return []
|
|
183
167
|
const data = await readJson(res)
|
|
184
168
|
return Array.isArray(data.plugins) ? data.plugins : []
|
|
@@ -190,7 +174,7 @@ export async function fetchBundledPlugins(): Promise<BundledPlugin[]> {
|
|
|
190
174
|
/** Asks every mesh peer live; `null` means this node could not ask at all. */
|
|
191
175
|
export async function fetchPeerPlugins(): Promise<PeersResponse | null> {
|
|
192
176
|
try {
|
|
193
|
-
const res = await apiFetch(`${API_BASE}/api/plugins/peers
|
|
177
|
+
const res = await apiFetch(`${API_BASE}/api/plugins/peers`, { cache: 'no-store' })
|
|
194
178
|
if (!res.ok) return null
|
|
195
179
|
const data = await readJson(res)
|
|
196
180
|
return { mesh: data.mesh || { available: false, configured: false }, peers: Array.isArray(data.peers) ? data.peers : [] }
|
|
@@ -215,21 +199,21 @@ export function updatePluginBranding(id: string, branding: { icon?: string; imag
|
|
|
215
199
|
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/branding`, { branding })
|
|
216
200
|
}
|
|
217
201
|
|
|
218
|
-
export function updatePluginCardFace(
|
|
219
|
-
id: string,
|
|
220
|
-
updates: { card_face?: CardFaceConfig; branding?: Record<string, unknown> }
|
|
221
|
-
): Promise<Result & { card_face?: CardFaceConfig; branding?: Record<string, unknown> }> {
|
|
222
|
-
return patch(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/card-face`, updates)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
202
|
export function setPluginLocked(id: string, locked: boolean): Promise<Result> {
|
|
226
203
|
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/lock`, { locked })
|
|
227
204
|
}
|
|
228
205
|
|
|
229
|
-
export function setPluginActivation(id: string,
|
|
230
|
-
|
|
206
|
+
export function setPluginActivation(id: string, value: boolean | 'on-use' | 'use', brainIds?: string[]): Promise<Result & {
|
|
207
|
+
activation?: { enabled: boolean; state: string }
|
|
208
|
+
cleanup?: PluginCleanup
|
|
209
|
+
results?: Array<Pick<BrainPluginActivation, 'brainId' | 'name'> & Result & { cleanup?: PluginCleanup }>
|
|
210
|
+
}> {
|
|
211
|
+
const policy = typeof value === 'boolean' ? { enabled: value } : { mode: value }
|
|
212
|
+
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/activation`, { ...policy, brainIds }, "PUT")
|
|
231
213
|
}
|
|
232
214
|
|
|
215
|
+
interface PluginCleanup { ok: boolean; state: string; error?: string }
|
|
216
|
+
|
|
233
217
|
export function deployPluginToStore(id: string, autoLock = true): Promise<Result & { storePackage?: any }> {
|
|
234
218
|
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/deploy-store`, { autoLock })
|
|
235
219
|
}
|
|
@@ -238,7 +222,7 @@ export async function runPluginCommand(
|
|
|
238
222
|
id: string,
|
|
239
223
|
subcommand = "",
|
|
240
224
|
args: string[] = [],
|
|
241
|
-
options?: { stdin?: string; execution?: PluginExecution }
|
|
225
|
+
options?: { stdin?: string; execution?: PluginExecution; brainId?: string }
|
|
242
226
|
): Promise<{ success: boolean; output?: string; error?: string; exitCode?: number | null; timedOut?: boolean }> {
|
|
243
227
|
const res = await post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/run`, { subcommand, args, ...(options || {}) })
|
|
244
228
|
if (res.error) return { success: false, error: res.error }
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { apiFetch, getApiBase } from './_base'
|
|
2
|
+
|
|
3
|
+
export type DrawerSide = 'right' | 'bottom'
|
|
4
|
+
export interface PanelRef { plugin: string; element: string }
|
|
5
|
+
export interface DrawerConfig {
|
|
6
|
+
html: string
|
|
7
|
+
chunks: string[]
|
|
8
|
+
panels: PanelRef[]
|
|
9
|
+
shortcuts: { label: string; href: string }[]
|
|
10
|
+
}
|
|
11
|
+
export interface DrawerRevision { config: DrawerConfig; version: string | null }
|
|
12
|
+
export interface PluginDesign { revision: string | null; css: string; components: string[] }
|
|
13
|
+
export interface WorkspaceChunk {
|
|
14
|
+
key: string
|
|
15
|
+
plugin: string
|
|
16
|
+
id: string
|
|
17
|
+
title: string
|
|
18
|
+
description: string
|
|
19
|
+
surfaces: string[]
|
|
20
|
+
panel?: string
|
|
21
|
+
operations?: string[]
|
|
22
|
+
data?: string[]
|
|
23
|
+
sha256: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SavedPageSummary { id: string; title: string; version: string }
|
|
27
|
+
export interface SavedPage extends SavedPageSummary { chunks: WorkspaceChunk[] }
|
|
28
|
+
|
|
29
|
+
export function listSavedPages(brainId: string, signal: AbortSignal) {
|
|
30
|
+
return request<{ pages: SavedPageSummary[] }>(
|
|
31
|
+
`/api/workspace/pages?brain=${encodeURIComponent(brainId)}`, { signal },
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function readSavedPage(id: string, brainId: string, signal: AbortSignal) {
|
|
36
|
+
return request<SavedPage>(
|
|
37
|
+
`/api/workspace/pages/${encodeURIComponent(id)}?brain=${encodeURIComponent(brainId)}`, { signal },
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function readWorkspaceComposition(plugin: string, signal: AbortSignal, brainId?: string) {
|
|
42
|
+
const scope = brainId ? `?brain=${encodeURIComponent(brainId)}` : ''
|
|
43
|
+
return request<{ chunks: WorkspaceChunk[]; version: string | null }>(
|
|
44
|
+
`/api/ui-chunks/${encodeURIComponent(plugin)}/composition/current${scope}`, { signal },
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
|
49
|
+
const response = await apiFetch(getApiBase() + path, { cache: 'no-store', ...options })
|
|
50
|
+
if (!response.headers.get('content-type')?.includes('application/json')) {
|
|
51
|
+
throw new Error('This server does not support saved drawer layouts yet.')
|
|
52
|
+
}
|
|
53
|
+
const data = await response.json()
|
|
54
|
+
if (!response.ok) throw new Error(data.error?.message || data.error || 'Could not load the workspace layout.')
|
|
55
|
+
return data as T
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function readDrawer(side: DrawerSide, signal?: AbortSignal) {
|
|
59
|
+
return request<DrawerRevision>(`/api/dashboard/drawers/${side}`, { signal })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function saveDrawer(side: DrawerSide, revision: DrawerRevision) {
|
|
63
|
+
return request<DrawerRevision>(`/api/dashboard/drawers/${side}`, {
|
|
64
|
+
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(revision),
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function findWorkspaceChunks(
|
|
69
|
+
surface: DrawerSide | 'page', query: string, signal?: AbortSignal, plugin?: string,
|
|
70
|
+
brainId?: string, page?: { limit: number; offset: number },
|
|
71
|
+
) {
|
|
72
|
+
const params = new URLSearchParams({ surface, q: query, limit: String(page?.limit ?? 24) })
|
|
73
|
+
if (page) params.set('offset', String(page.offset))
|
|
74
|
+
if (plugin) params.set('plugin', plugin)
|
|
75
|
+
if (brainId) params.set('brain', brainId)
|
|
76
|
+
return request<{ chunks: WorkspaceChunk[]; total: number }>(`/api/ui-chunks?${params}`, { signal })
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function readPluginDesign(plugin: string, revision: string | null, signal: AbortSignal, brainId?: string) {
|
|
80
|
+
const params = new URLSearchParams()
|
|
81
|
+
if (revision) params.set('revision', revision)
|
|
82
|
+
if (brainId) params.set('brain', brainId)
|
|
83
|
+
const query = params.size ? `?${params}` : ''
|
|
84
|
+
return request<PluginDesign | { unchanged: true }>(
|
|
85
|
+
`/api/ui-chunks/${encodeURIComponent(plugin)}/design/revision${query}`, { signal },
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function readWorkspaceChunk(key: string, surface: DrawerSide | 'page', signal?: AbortSignal, brainId?: string) {
|
|
90
|
+
const [plugin, id] = key.split(':')
|
|
91
|
+
const params = new URLSearchParams({ surface })
|
|
92
|
+
if (brainId) params.set('brain', brainId)
|
|
93
|
+
const data = await request<{ chunk: WorkspaceChunk & { html: string } }>(
|
|
94
|
+
`/api/ui-chunks/${encodeURIComponent(plugin)}/${encodeURIComponent(id)}?${params}`, { signal },
|
|
95
|
+
)
|
|
96
|
+
return data.chunk
|
|
97
|
+
}
|
|
@@ -16,6 +16,7 @@ interface BrainInfo {
|
|
|
16
16
|
interface BrainSelectorProps {
|
|
17
17
|
activeBrainId: string
|
|
18
18
|
onBrainChange: (brainId: string) => void
|
|
19
|
+
onSelectionComplete?: () => void
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
function layerDot(layer: string, multi = false): string {
|
|
@@ -31,7 +32,7 @@ function layerBadge(layer: string): string {
|
|
|
31
32
|
return 'P'
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
export default function BrainSelector({ activeBrainId, onBrainChange }: BrainSelectorProps) {
|
|
35
|
+
export default function BrainSelector({ activeBrainId, onBrainChange, onSelectionComplete }: BrainSelectorProps) {
|
|
35
36
|
const [brains, setBrains] = useState<BrainInfo[]>([])
|
|
36
37
|
const [expanded, setExpanded] = useState(false)
|
|
37
38
|
const [loading, setLoading] = useState(true)
|
|
@@ -42,7 +43,7 @@ export default function BrainSelector({ activeBrainId, onBrainChange }: BrainSel
|
|
|
42
43
|
setLoading(true)
|
|
43
44
|
setError(null)
|
|
44
45
|
try {
|
|
45
|
-
const res = await apiFetch(`${getApiBase()}/api/brains
|
|
46
|
+
const res = await apiFetch(`${getApiBase()}/api/brains`, { cache: 'no-store' })
|
|
46
47
|
if (!res.ok) {
|
|
47
48
|
const body = await res.json().catch(() => ({}))
|
|
48
49
|
throw new Error(body.error || `Brains API ${res.status}`)
|
|
@@ -121,6 +122,7 @@ export default function BrainSelector({ activeBrainId, onBrainChange }: BrainSel
|
|
|
121
122
|
const handleSelectOnly = (id: string) => {
|
|
122
123
|
setSelection([id])
|
|
123
124
|
setExpanded(false)
|
|
125
|
+
onSelectionComplete?.()
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
if (loading) {
|
|
@@ -224,7 +226,7 @@ export default function BrainSelector({ activeBrainId, onBrainChange }: BrainSel
|
|
|
224
226
|
data-testid="brain-selector-menu"
|
|
225
227
|
style={{
|
|
226
228
|
position: 'absolute',
|
|
227
|
-
|
|
229
|
+
top: '100%',
|
|
228
230
|
left: 0,
|
|
229
231
|
right: 0,
|
|
230
232
|
marginBottom: 6,
|
|
@@ -360,6 +362,10 @@ export default function BrainSelector({ activeBrainId, onBrainChange }: BrainSel
|
|
|
360
362
|
</div>
|
|
361
363
|
)
|
|
362
364
|
})}
|
|
365
|
+
{onSelectionComplete && <button type="button" className="btn btn-ghost btn-sm" onClick={() => {
|
|
366
|
+
setExpanded(false)
|
|
367
|
+
onSelectionComplete()
|
|
368
|
+
}}>Done</button>}
|
|
363
369
|
</div>
|
|
364
370
|
)}
|
|
365
371
|
</div>
|
|
@@ -2,8 +2,10 @@ import { useEffect, useRef, useState } from 'react'
|
|
|
2
2
|
import type { PluginInfo } from '../../api/plugins'
|
|
3
3
|
import { runPluginCommand } from '../../api/plugins'
|
|
4
4
|
import { apiFetch, API_BASE } from '../../api/_base'
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
5
|
+
import { readSavedPluginCredentials, savePluginCredential } from '../../api/plugin-credentials'
|
|
6
|
+
import { changeAuthCredential, readAuthInventory } from '../../api/auth-inventory'
|
|
7
|
+
import { usePluginDesign } from '../workspace/usePluginDesign'
|
|
8
|
+
import { pluginFrameDocument, allowedFrameCommand, browserPluginOperations, pluginCommandTimeouts } from './plugin-frame'
|
|
7
9
|
|
|
8
10
|
export interface PluginElement {
|
|
9
11
|
id: string
|
|
@@ -11,10 +13,13 @@ export interface PluginElement {
|
|
|
11
13
|
tag: string
|
|
12
14
|
module: string
|
|
13
15
|
description?: string
|
|
16
|
+
events?: string[]
|
|
17
|
+
props?: { view?: unknown }
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export function pluginElements(plugin: PluginInfo): PluginElement[] {
|
|
17
|
-
|
|
21
|
+
const elements = (plugin.manifest?.ui as { elements?: PluginElement[] } | undefined)?.elements || plugin.ui?.elements || []
|
|
22
|
+
return elements.filter(element => ['panel', 'form', 'list', 'detail', 'settings', 'widget'].includes(element.kind))
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
export function parsePluginOutput(rawOutput: string | undefined): unknown {
|
|
@@ -40,57 +45,93 @@ export function parsePluginOutput(rawOutput: string | undefined): unknown {
|
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
/** Loads owner code
|
|
44
|
-
export function PluginPanel({ plugin, elementId, readOnly = false
|
|
48
|
+
/** Loads owner code in an isolated document. Auth's inventory is a privileged bridge. */
|
|
49
|
+
export function PluginPanel({ plugin, elementId, readOnly = false, designCss, brainId }: {
|
|
50
|
+
plugin: PluginInfo; elementId?: string; readOnly?: boolean; designCss?: string; brainId?: string
|
|
51
|
+
}) {
|
|
45
52
|
const elements = pluginElements(plugin).filter(element => element.kind !== 'settings' && (!elementId || element.id === elementId))
|
|
46
|
-
const
|
|
47
|
-
const [selected, setSelected] = useState(elementId ||
|
|
53
|
+
const home = (plugin.manifest?.ui as { home?: string } | undefined)?.home || plugin.ui?.home
|
|
54
|
+
const [selected, setSelected] = useState(elementId || home || elements[0]?.id || '')
|
|
55
|
+
const currentElement = elements.find(item => item.id === selected) || elements[0]
|
|
56
|
+
const usesOwnerDesign = designCss === undefined && currentElement
|
|
57
|
+
const ownerDesign = usePluginDesign(usesOwnerDesign ? plugin.id : undefined, brainId)
|
|
58
|
+
const css = designCss ?? ownerDesign?.design?.css ?? ''
|
|
48
59
|
const [error, setError] = useState('')
|
|
49
60
|
const frame = useRef<HTMLIFrameElement>(null)
|
|
61
|
+
const activeChannel = useRef('')
|
|
50
62
|
const [document, setDocument] = useState('')
|
|
51
63
|
const [height, setHeight] = useState(240)
|
|
52
64
|
|
|
53
65
|
useEffect(() => {
|
|
54
66
|
let disposed = false
|
|
67
|
+
const controller = new AbortController()
|
|
55
68
|
setError('')
|
|
56
69
|
setDocument('')
|
|
57
70
|
const channel = crypto.randomUUID()
|
|
71
|
+
activeChannel.current = channel
|
|
58
72
|
const commands = plugin.manifest?.cli as { subcommands?: Array<{ name: string; effect?: string; args?: Array<{ secret?: boolean; type?: string; flag?: string }> }> } | undefined
|
|
59
73
|
const readCommands = new Set((commands?.subcommands || []).filter(command => command.effect === 'read').map(command => command.name))
|
|
60
|
-
const allowed = new Set((plugin
|
|
74
|
+
const allowed = new Set(browserPluginOperations(plugin).filter(command => !readOnly || readCommands.has(command.name)).map(command => command.name))
|
|
61
75
|
const secretCommands = new Set((commands?.subcommands || []).filter(command => {
|
|
62
76
|
const secrets = command.args?.filter(arg => arg.secret === true) || []
|
|
63
77
|
return secrets.length === 1 && secrets[0].type === 'string' && secrets[0].flag === undefined
|
|
64
78
|
}).map(command => command.name))
|
|
65
79
|
const element = elements.find(item => item.id === selected) || elements[0]
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
frame.current?.contentWindow?.postMessage({ channel, type: 'show-screen', screen: detail.screen }, '*')
|
|
71
|
-
}
|
|
80
|
+
const credentials = plugin.secrets || []
|
|
81
|
+
const credentialPanel = element?.events?.includes('save-token') === true && !!element.props?.view && credentials.length === 1
|
|
82
|
+
const authInventory = plugin.id === 'auth' && element?.events?.includes('auth-inventory') === true
|
|
83
|
+
const authChanges = authInventory && !readOnly && element?.events?.includes('auth-credential-mutate') === true
|
|
72
84
|
let active = 0
|
|
85
|
+
let changingCredential = false
|
|
73
86
|
const message = async (event: MessageEvent) => {
|
|
74
87
|
if (disposed || event.source !== frame.current?.contentWindow || event.origin !== 'null' || event.data?.channel !== channel) return
|
|
75
88
|
const data = event.data
|
|
76
|
-
if (data.type === '
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
if (data.type === 'height' && Number.isFinite(data.height)) setHeight(Math.max(128, Math.min(1000, data.height)))
|
|
90
|
+
if (data.type === 'error') setError('Could not open the plugin interface')
|
|
91
|
+
const target = event.source as Window
|
|
92
|
+
const reply = (result?: unknown, error?: string) => { if (!disposed) target.postMessage({ channel, type: 'result', requestId: data.requestId, result, error }, '*') }
|
|
93
|
+
if (data.type === 'auth-credential-mutate') {
|
|
94
|
+
if (!authChanges || changingCredential) { reply(undefined, 'Credential changes are unavailable'); return }
|
|
95
|
+
changingCredential = true
|
|
96
|
+
try {
|
|
97
|
+
reply(await changeAuthCredential(data.change, controller.signal))
|
|
98
|
+
} catch (error) {
|
|
99
|
+
reply(undefined, error instanceof Error ? error.message : 'Could not change the credential')
|
|
100
|
+
} finally { changingCredential = false }
|
|
81
101
|
return
|
|
82
102
|
}
|
|
83
|
-
if (data.type === '
|
|
84
|
-
if (
|
|
85
|
-
|
|
103
|
+
if (data.type === 'auth-inventory') {
|
|
104
|
+
if (!authInventory || active >= 12) { reply(undefined, 'Auth inventory is unavailable'); return }
|
|
105
|
+
active++
|
|
106
|
+
try {
|
|
107
|
+
reply(await readAuthInventory(data.resource, controller.signal))
|
|
108
|
+
} catch (error) {
|
|
109
|
+
reply(undefined, error instanceof Error ? error.message : 'Could not load the inventory')
|
|
110
|
+
} finally { active-- }
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
if (data.type === 'credential-status' || data.type === 'credential-save') {
|
|
114
|
+
if (!credentialPanel || active >= 12) { reply(undefined, 'Credential check is unavailable'); return }
|
|
115
|
+
const { key } = credentials[0]
|
|
116
|
+
active++
|
|
117
|
+
try {
|
|
118
|
+
if (data.type === 'credential-save') {
|
|
119
|
+
if (readOnly || data.key !== key || typeof data.value !== 'string' || !data.value.trim() || data.value.length > 16384) {
|
|
120
|
+
reply(undefined, 'Credential update is unavailable')
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
await savePluginCredential(plugin, key, data.value, brainId)
|
|
124
|
+
reply({ present: true, secretKey: key })
|
|
125
|
+
} else {
|
|
126
|
+
const saved = await readSavedPluginCredentials()
|
|
127
|
+
reply({ present: saved.has(key), secretKey: key })
|
|
128
|
+
}
|
|
129
|
+
} catch {
|
|
130
|
+
reply(undefined, data.type === 'credential-save' ? 'Could not verify and save the credential.' : 'Could not check saved credentials.')
|
|
131
|
+
} finally { active-- }
|
|
86
132
|
return
|
|
87
133
|
}
|
|
88
|
-
if (data.type === 'contextmenu') window.dispatchEvent(new CustomEvent('plugin-context-menu', { detail: { pluginId: plugin.id } }))
|
|
89
|
-
if (data.type === 'height' && Number.isFinite(data.height)) setHeight(Math.max(128, Math.min(1000, data.height)))
|
|
90
|
-
if (data.type === 'error') setError('Could not open the plugin interface')
|
|
91
134
|
if (data.type !== 'run') return
|
|
92
|
-
const target = event.source as Window
|
|
93
|
-
const reply = (result?: unknown, error?: string) => { if (!disposed) target.postMessage({ channel, type: 'result', requestId: data.requestId, result, error }, '*') }
|
|
94
135
|
|
|
95
136
|
let subcommand = data.subcommand
|
|
96
137
|
let args = Array.isArray(data.args) ? [...data.args] : []
|
|
@@ -101,11 +142,11 @@ export function PluginPanel({ plugin, elementId, readOnly = false }: { plugin: P
|
|
|
101
142
|
|
|
102
143
|
if (!allowedFrameCommand({ ...data, subcommand, args }, allowed, secretCommands) || active >= 12) { reply(undefined, 'Operation is not available'); return }
|
|
103
144
|
active++
|
|
104
|
-
window.dispatchEvent(new CustomEvent('plugin-command-activity', { detail: { pluginId: plugin.id, requestId: data.requestId, command: subcommand, running: true } }))
|
|
105
145
|
try {
|
|
106
146
|
const finalArgs = args.includes('--json') ? args : [...args, '--json']
|
|
107
|
-
const
|
|
108
|
-
|
|
147
|
+
const options = { ...(brainId ? { brainId } : {}), ...(data.stdin !== undefined ? { stdin: data.stdin } : {}) }
|
|
148
|
+
const result = Object.keys(options).length
|
|
149
|
+
? await runPluginCommand(plugin.id, subcommand, finalArgs, options)
|
|
109
150
|
: await runPluginCommand(plugin.id, subcommand, finalArgs)
|
|
110
151
|
if (!result.success) { reply(undefined, data.stdin !== undefined ? 'Credential operation failed' : result.output || result.error || 'Operation failed'); return }
|
|
111
152
|
if (data.stdin !== undefined) {
|
|
@@ -114,22 +155,18 @@ export function PluginPanel({ plugin, elementId, readOnly = false }: { plugin: P
|
|
|
114
155
|
}
|
|
115
156
|
reply(parsePluginOutput(result.output))
|
|
116
157
|
} catch { reply(undefined, 'Operation failed') }
|
|
117
|
-
finally {
|
|
118
|
-
active--
|
|
119
|
-
window.dispatchEvent(new CustomEvent('plugin-command-activity', { detail: { pluginId: plugin.id, requestId: data.requestId, command: subcommand, running: false } }))
|
|
120
|
-
}
|
|
158
|
+
finally { active-- }
|
|
121
159
|
}
|
|
122
160
|
window.addEventListener('message', message)
|
|
123
|
-
window.addEventListener('plugin-show-screen', showScreen)
|
|
124
161
|
const dispose = () => {
|
|
125
162
|
disposed = true
|
|
163
|
+
controller.abort()
|
|
126
164
|
window.removeEventListener('message', message)
|
|
127
|
-
window.removeEventListener('plugin-show-screen', showScreen)
|
|
128
|
-
if (element?.kind === 'card') window.dispatchEvent(new CustomEvent('plugin-screens', { detail: { pluginId: plugin.id, screens: [] } }))
|
|
129
165
|
}
|
|
130
166
|
if (!element) return dispose
|
|
131
167
|
const load = async () => {
|
|
132
|
-
const
|
|
168
|
+
const scope = brainId ? `?brain=${encodeURIComponent(brainId)}` : ''
|
|
169
|
+
const response = await apiFetch(`${API_BASE}/api/plugins/${encodeURIComponent(plugin.id)}/ui/${encodeURIComponent(element.id)}${scope}`, { cache: 'no-store' })
|
|
133
170
|
if (!response.ok) throw new Error(`Could not open ${plugin.name} (${response.status})`)
|
|
134
171
|
const source = await response.text()
|
|
135
172
|
if (source.length > 1024 * 1024) throw new Error('The plugin interface is too large')
|
|
@@ -137,14 +174,17 @@ export function PluginPanel({ plugin, elementId, readOnly = false }: { plugin: P
|
|
|
137
174
|
const styles = getComputedStyle(window.document.documentElement)
|
|
138
175
|
const theme: Record<string, string> = {}
|
|
139
176
|
for (const name of ['--text-primary', '--text-secondary', '--text-tertiary', '--bg-primary', '--bg-secondary', '--border', '--accent', '--font-sans', '--color-text', '--color-surface', '--color-border', '--spacing-md', '--radius-md']) theme[name] = styles.getPropertyValue(name)
|
|
140
|
-
setDocument(pluginFrameDocument(source, element.tag, channel, theme, plugin.id, pluginCommandTimeouts(plugin.manifest), [...allowed]))
|
|
177
|
+
setDocument(pluginFrameDocument(source, element.tag, channel, theme, plugin.id, pluginCommandTimeouts(plugin.manifest), [...allowed], credentialPanel, authInventory, authChanges))
|
|
141
178
|
}
|
|
142
179
|
load().catch(err => { if (!disposed) setError(err.message) })
|
|
143
180
|
return dispose
|
|
144
|
-
}, [plugin.id, selected, plugin.sha256, elementId, readOnly])
|
|
181
|
+
}, [plugin.id, selected, plugin.sha256, elementId, readOnly, brainId])
|
|
145
182
|
|
|
146
|
-
|
|
147
|
-
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
frame.current?.contentWindow?.postMessage({ channel: activeChannel.current, type: 'design', css }, '*')
|
|
185
|
+
}, [css])
|
|
186
|
+
|
|
187
|
+
const showNav = elements.length > 1
|
|
148
188
|
|
|
149
189
|
return <section>
|
|
150
190
|
{showNav && <nav style={{ display: 'flex', gap: 8 }}>
|
|
@@ -154,6 +194,7 @@ export function PluginPanel({ plugin, elementId, readOnly = false }: { plugin: P
|
|
|
154
194
|
{elements.length === 0 && <p>This plugin has not supplied its interface yet.</p>}
|
|
155
195
|
{document && <iframe ref={frame} title={`${plugin.name} interface`} sandbox="allow-scripts" referrerPolicy="no-referrer"
|
|
156
196
|
allow="camera 'none'; microphone 'none'; geolocation 'none'; clipboard-read 'none'; clipboard-write 'none'"
|
|
197
|
+
onLoad={() => frame.current?.contentWindow?.postMessage({ channel: activeChannel.current, type: 'design', css }, '*')}
|
|
157
198
|
srcDoc={document} style={{ width: '100%', height, border: 0 }} />}
|
|
158
199
|
</section>
|
|
159
200
|
}
|