@pi-harness/pi-harness 0.1.30 → 0.1.32
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/README.md +1 -1
- package/apps/web/dist/assets/index-BqOM0elx.css +2 -0
- package/apps/web/dist/assets/index-x2UhIAWm.js +25 -0
- package/apps/web/dist/index.html +2 -2
- package/apps/web/package.json +1 -1
- package/apps/web/profile/cordis.yml +0 -221
- package/apps/web/server-dist/bin.js +11 -3
- package/apps/web/server-dist/bin.js.map +1 -1
- package/apps/web/src/server/bin.ts +10 -2
- package/apps/web/src/style.css +30 -1
- package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/index.js +70 -18
- package/node_modules/@pi-harness/api-gateway/dist/index.js.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +1 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-group.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-timer.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +2 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +2 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +2 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +2 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +2 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -9
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -8
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +2 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -7
- package/node_modules/@pi-harness/api-gateway/dist/marketplace.d.ts +18 -2
- package/node_modules/@pi-harness/api-gateway/dist/marketplace.d.ts.map +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace.js +93 -10
- package/node_modules/@pi-harness/api-gateway/dist/marketplace.js.map +1 -1
- package/node_modules/@pi-harness/api-gateway/package.json +1 -27
- package/node_modules/@pi-harness/cli/dist/main.d.ts.map +1 -1
- package/node_modules/@pi-harness/cli/dist/main.js +19 -3
- package/node_modules/@pi-harness/cli/dist/main.js.map +1 -1
- package/node_modules/@pi-harness/cli/package.json +1 -1
- package/node_modules/@pi-harness/cli/profiles/default/cordis.yml +0 -87
- package/node_modules/@pi-harness/host-webserver/package.json +1 -1
- package/node_modules/@pi-harness/web-app/package.json +1 -1
- package/package.json +6 -79
- package/packages/api-gateway/dist/index.d.ts.map +1 -1
- package/packages/api-gateway/dist/index.js +70 -18
- package/packages/api-gateway/dist/index.js.map +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/context.json +1 -7
- package/packages/api-gateway/dist/marketplace-entries/official/cordis-group.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cordis-timer.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +2 -10
- package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -7
- package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +2 -8
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +2 -8
- package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +2 -9
- package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +2 -10
- package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -9
- package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -8
- package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -7
- package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +2 -2
- package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -7
- package/packages/api-gateway/dist/marketplace.d.ts +18 -2
- package/packages/api-gateway/dist/marketplace.d.ts.map +1 -1
- package/packages/api-gateway/dist/marketplace.js +93 -10
- package/packages/api-gateway/dist/marketplace.js.map +1 -1
- package/packages/api-gateway/package.json +1 -27
- package/packages/api-gateway/src/index.ts +85 -23
- package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/at-file.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/context.json +1 -7
- package/packages/api-gateway/src/marketplace-entries/official/cordis-group.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cordis-logger-console.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cordis-timer.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +2 -10
- package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/genui.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +1 -7
- package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +2 -8
- package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/modlens.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/openpets.json +2 -8
- package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +2 -9
- package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +2 -10
- package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +1 -9
- package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +1 -8
- package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +1 -7
- package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +2 -2
- package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +1 -7
- package/packages/api-gateway/src/marketplace.ts +113 -12
- package/packages/api-gateway/test/index.test.ts +297 -5
- package/packages/api-gateway/test/marketplace-schema.test.ts +12 -0
- package/packages/api-gateway/test/marketplace.test.ts +172 -240
- package/packages/api-gateway/test/packed-package.test.ts +18 -6
- package/packages/api-gateway/test/release-contract.test.ts +8 -4
- package/packages/bundle-web-app/package.json +1 -1
- package/packages/cli/dist/main.d.ts.map +1 -1
- package/packages/cli/dist/main.js +19 -3
- package/packages/cli/dist/main.js.map +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/cli/profiles/default/cordis.yml +0 -87
- package/packages/cli/src/main.ts +18 -3
- package/packages/cli/test/cli.test.ts +20 -0
- package/packages/cli/test/profiles/plugins/cordis.yml +122 -0
- package/packages/cli/test/profiles.integration.test.ts +40 -23
- package/packages/host-webserver/package.json +1 -1
- package/apps/web/dist/assets/index-B7pwZ76Z.js +0 -25
- package/apps/web/dist/assets/index-xF647pQJ.css +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
1
|
+
import { describe, expect, test, vi } from "vitest";
|
|
2
2
|
import {
|
|
3
3
|
MARKETPLACE_CAPABILITIES,
|
|
4
4
|
MARKETPLACE_CATEGORIES,
|
|
@@ -40,14 +40,7 @@ describe("plugin marketplace registry", () => {
|
|
|
40
40
|
expect(official.get("plugin-stars")?.description).toMatch(
|
|
41
41
|
/curated.*raw\.githubusercontent\.com.*descriptor-safe.*bounded.*cancellable.*fail-closed.*panel/iu,
|
|
42
42
|
);
|
|
43
|
-
expect(official.get("plugin-stars")?.capabilities).toEqual([
|
|
44
|
-
"curated GitHub ranking search",
|
|
45
|
-
"strict bounded snapshot validation",
|
|
46
|
-
"redirect-free source fetch",
|
|
47
|
-
"cancellable request lifecycle",
|
|
48
|
-
"bounded panel inventory",
|
|
49
|
-
"validated fail-closed panel reporting",
|
|
50
|
-
]);
|
|
43
|
+
expect(official.get("plugin-stars")?.capabilities).toEqual(["network-access"]);
|
|
51
44
|
expect(official.get("plugin-stars")?.hooks).toEqual(["ranking search tool", "raw GitHub snapshot", "plugin UI"]);
|
|
52
45
|
expect(official.get("plugin-stars")?.profile.config).toEqual({
|
|
53
46
|
sourceUrl: "https://raw.githubusercontent.com/ywsldxk/dsh-plugin-stars/main/data/plugins.json",
|
|
@@ -56,135 +49,58 @@ describe("plugin marketplace registry", () => {
|
|
|
56
49
|
});
|
|
57
50
|
expect(official.get("vision-toolkit")?.category.id).toBe("multimodal");
|
|
58
51
|
expect(official.get("vision-toolkit")?.description).toMatch(/signature-verified.*PNG.*JPEG.*GIF.*WebP.*bounded header.*cancellable.*local/iu);
|
|
59
|
-
expect(official.get("vision-toolkit")?.capabilities).toEqual([
|
|
60
|
-
"bounded workspace image catalog",
|
|
61
|
-
"signature-verified image metadata",
|
|
62
|
-
"PNG JPEG GIF and WebP dimensions",
|
|
63
|
-
"cancellable bounded traversal",
|
|
64
|
-
"bounded normalized panel",
|
|
65
|
-
]);
|
|
52
|
+
expect(official.get("vision-toolkit")?.capabilities).toEqual(["read-only", "reads-files"]);
|
|
66
53
|
expect(official.get("vision-toolkit")?.hooks).toEqual(["image metadata tools", "workspace access", "plugin UI"]);
|
|
67
54
|
expect(official.get("vision-toolkit")?.profile.config).toEqual({});
|
|
68
55
|
expect(official.get("session-bridge")?.category.id).toBe("workflow");
|
|
69
56
|
expect(official.get("session-bridge")?.description).toMatch(/preview.*export.*confirmed import.*strictly validated.*bounded.*LLM context.*duplicate/iu);
|
|
70
|
-
expect(official.get("session-bridge")?.capabilities).toEqual([
|
|
71
|
-
"strict bounded handoff format",
|
|
72
|
-
"five-part review preview",
|
|
73
|
-
"confirmed context import",
|
|
74
|
-
"active-session targeting",
|
|
75
|
-
"duplicate import protection",
|
|
76
|
-
"bounded operation status",
|
|
77
|
-
"bounded normalized panel",
|
|
78
|
-
]);
|
|
57
|
+
expect(official.get("session-bridge")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
79
58
|
expect(official.get("session-bridge")?.hooks).toEqual(["session bridge tools", "active session manager", "custom context messages", "plugin UI"]);
|
|
80
59
|
expect(official.get("session-bridge")?.profile.config).toEqual({});
|
|
81
60
|
expect(official.get("skill-guard")?.category.id).toBe("security");
|
|
82
61
|
expect(official.get("skill-guard")?.description).toMatch(/loaded Skill entry.*bounded heuristic.*does not disable/iu);
|
|
83
|
-
expect(official.get("skill-guard")?.capabilities).toEqual([
|
|
84
|
-
"bounded loaded-entry audit",
|
|
85
|
-
"instruction-override heuristics",
|
|
86
|
-
"secret-exfiltration heuristics",
|
|
87
|
-
"destructive-command and obfuscation heuristics",
|
|
88
|
-
"descriptor-safe cancellable scans",
|
|
89
|
-
"bounded normalized panel",
|
|
90
|
-
]);
|
|
62
|
+
expect(official.get("skill-guard")?.capabilities).toEqual(["read-only", "reads-files"]);
|
|
91
63
|
expect(official.get("skill-guard")?.hooks).toEqual(["skill scan tool", "resource loader", "plugin UI"]);
|
|
92
64
|
expect(official.get("skill-guard")?.profile.config).toEqual({});
|
|
93
65
|
expect(official.get("cost-meter")?.category.id).toBe("observability");
|
|
94
66
|
expect(official.get("cost-meter")?.description).toMatch(/runtime-reported.*UTC daily increments.*bounded local ledger/iu);
|
|
95
|
-
expect(official.get("cost-meter")?.capabilities).toEqual([
|
|
96
|
-
"UTC daily cost ledger",
|
|
97
|
-
"session cost snapshots",
|
|
98
|
-
"daily budget monitoring",
|
|
99
|
-
"bounded local persistence",
|
|
100
|
-
]);
|
|
67
|
+
expect(official.get("cost-meter")?.capabilities).toEqual(["session-data", "reads-files", "writes-files"]);
|
|
101
68
|
expect(official.get("cost-meter")?.hooks).toEqual(["agent end", "cost report tool", "plugin UI"]);
|
|
102
69
|
expect(official.get("cost-meter")?.profile.config).toEqual({ dailyBudget: 0, maxEntries: 365 });
|
|
103
70
|
expect(official.get("skill-catalog")?.category.id).toBe("discovery");
|
|
104
71
|
expect(official.get("prompt-guard")?.category.id).toBe("security");
|
|
105
72
|
expect(official.get("browser-fetch")?.category.id).toBe("web");
|
|
106
73
|
expect(official.get("browser-fetch")?.description).toMatch(/bounded.*text.*descriptor-safe.*DNS.*pinn.*redirect.*private.*timeout.*validated.*panel/iu);
|
|
107
|
-
expect(official.get("browser-fetch")?.capabilities).toEqual([
|
|
108
|
-
"bounded textual HTTP fetch",
|
|
109
|
-
"DNS rebinding protection",
|
|
110
|
-
"per-hop SSRF validation",
|
|
111
|
-
"cancellable request lifecycle",
|
|
112
|
-
"bounded browser preview",
|
|
113
|
-
"validated fail-closed panel reporting",
|
|
114
|
-
]);
|
|
74
|
+
expect(official.get("browser-fetch")?.capabilities).toEqual(["network-access"]);
|
|
115
75
|
expect(official.get("browser-fetch")?.profile.config).toEqual({ allowPrivate: false, timeoutMs: 20_000 });
|
|
116
76
|
expect(official.get("web-research")?.category.id).toBe("web");
|
|
117
77
|
expect(official.get("mcp-client")?.category.id).toBe("tools");
|
|
118
78
|
expect(official.get("mcp-client")?.description).toMatch(/MCP stdio.*bounded.*pagination.*tool.*resource.*prompt.*cancellable.*lifecycle/iu);
|
|
119
|
-
expect(official.get("mcp-client")?.capabilities).toEqual([
|
|
120
|
-
"bounded MCP stdio transport",
|
|
121
|
-
"bounded inventory pagination",
|
|
122
|
-
"tool resource and prompt bridging",
|
|
123
|
-
"persistent server lifecycle",
|
|
124
|
-
"cancellable queued requests",
|
|
125
|
-
]);
|
|
79
|
+
expect(official.get("mcp-client")?.capabilities).toEqual(["runs-commands"]);
|
|
126
80
|
expect(official.get("mcp-client")?.hooks).toEqual(["MCP stdio tools", "managed server lifecycle", "plugin UI"]);
|
|
127
81
|
expect(official.get("mcp-client")?.profile.config).toEqual({ servers: [] });
|
|
128
82
|
expect(official.get("at-file")?.category.id).toBe("context");
|
|
129
83
|
expect(official.get("at-file")?.description).toMatch(/bounded 256 KiB.*UTF-8.*canonical.*untrusted.*closing-tag.*cancellable.*sequential/iu);
|
|
130
|
-
expect(official.get("at-file")?.capabilities).toEqual([
|
|
131
|
-
"256 KiB strict UTF-8 text attachments",
|
|
132
|
-
"canonical workspace path confinement",
|
|
133
|
-
"no-follow regular-file reads",
|
|
134
|
-
"untrusted context framing",
|
|
135
|
-
"closing-tag neutralization",
|
|
136
|
-
"cancellable sequential execution",
|
|
137
|
-
"descriptor-safe normalized panel",
|
|
138
|
-
]);
|
|
84
|
+
expect(official.get("at-file")?.capabilities).toEqual(["read-only", "reads-files"]);
|
|
139
85
|
expect(official.get("at-file")?.hooks).toEqual(["file context tool", "workspace file read", "plugin UI"]);
|
|
140
86
|
expect(official.get("at-file")?.profile.config).toEqual({});
|
|
141
87
|
expect(official.get("dependency-checker")?.category.id).toBe("developer");
|
|
142
88
|
expect(official.get("dependency-checker")?.description).toMatch(/bounded.*offline.*read-only.*package\.json.*requirements.*presence.*unresolved/iu);
|
|
143
|
-
expect(official.get("dependency-checker")?.capabilities).toEqual([
|
|
144
|
-
"2000-declaration local presence scan",
|
|
145
|
-
"4096-entry workspace-contained virtualenv scan",
|
|
146
|
-
"npm common-intersection conflict detection",
|
|
147
|
-
"bounded Python numeric constraint analysis",
|
|
148
|
-
"unresolved constraint and directive reporting",
|
|
149
|
-
"optional dependency reporting",
|
|
150
|
-
"descriptor-safe normalized panel",
|
|
151
|
-
]);
|
|
89
|
+
expect(official.get("dependency-checker")?.capabilities).toEqual(["read-only", "reads-files"]);
|
|
152
90
|
expect(official.get("dependency-checker")?.hooks).toEqual(["dependency check tool", "workspace manifest read", "plugin UI"]);
|
|
153
91
|
expect(official.get("token-guard")?.category.id).toBe("observability");
|
|
154
92
|
expect(official.get("token-guard")?.description).toMatch(/descriptor-safe.*one abort.*per run.*context.*billed run-token.*cached.*normalized panel/iu);
|
|
155
|
-
expect(official.get("token-guard")?.capabilities).toEqual([
|
|
156
|
-
"strict context percentage budget",
|
|
157
|
-
"optional billed run-token budget",
|
|
158
|
-
"one abort request per run",
|
|
159
|
-
"resilient descriptor-safe monitoring",
|
|
160
|
-
"bounded streaming inspection cadence",
|
|
161
|
-
"bounded abort error status",
|
|
162
|
-
"cached normalized panel",
|
|
163
|
-
]);
|
|
93
|
+
expect(official.get("token-guard")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
164
94
|
expect(official.get("token-guard")?.hooks).toEqual(["Pi session lifecycle", "active runtime abort", "session usage and statistics", "plugin UI"]);
|
|
165
95
|
expect(official.get("token-guard")?.profile.config).toEqual({ maxPercent: 90, maxRunTokens: 0 });
|
|
166
96
|
expect(official.get("recall-unread")?.category.id).toBe("workflow");
|
|
167
97
|
expect(official.get("recall-unread")?.description).toMatch(/read-only.*bounded.*strict UTF-8.*current workspace.*unanswered.*cached/iu);
|
|
168
|
-
expect(official.get("recall-unread")?.capabilities).toEqual([
|
|
169
|
-
"bounded current-workspace JSONL discovery",
|
|
170
|
-
"strict UTF-8 no-follow session reads",
|
|
171
|
-
"unanswered-tail detection",
|
|
172
|
-
"cached startup and manual rescans",
|
|
173
|
-
"descriptor-safe cancellable queries",
|
|
174
|
-
"bounded normalized panel",
|
|
175
|
-
]);
|
|
98
|
+
expect(official.get("recall-unread")?.capabilities).toEqual(["read-only", "session-data", "reads-files"]);
|
|
176
99
|
expect(official.get("recall-unread")?.hooks).toEqual(["recall unread tool", "native session storage", "active session manager", "plugin UI"]);
|
|
177
100
|
expect(official.get("recall-unread")?.profile.config).toEqual({});
|
|
178
101
|
expect(official.get("turn-rewind")?.category.id).toBe("workflow");
|
|
179
102
|
expect(official.get("turn-rewind")?.description).toMatch(/bounded.*current branch.*queued.*cancellable.*native session tree/iu);
|
|
180
|
-
expect(official.get("turn-rewind")?.capabilities).toEqual([
|
|
181
|
-
"bounded current-branch candidate scan",
|
|
182
|
-
"settled-state queued navigation",
|
|
183
|
-
"preserved native session branches",
|
|
184
|
-
"optional branch summarization",
|
|
185
|
-
"cancellable serialized rewinds",
|
|
186
|
-
"bounded normalized operation panel",
|
|
187
|
-
]);
|
|
103
|
+
expect(official.get("turn-rewind")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
188
104
|
expect(official.get("turn-rewind")?.hooks).toEqual(["session rewind tool", "active session tree", "agent settled lifecycle", "plugin UI"]);
|
|
189
105
|
expect(official.get("turn-rewind")?.profile.config).toEqual({});
|
|
190
106
|
expect(official.get("context-doctor")?.category.id).toBe("observability");
|
|
@@ -198,82 +114,41 @@ describe("plugin marketplace registry", () => {
|
|
|
198
114
|
expect(official.get("image-compressor")?.category.id).toBe("multimodal");
|
|
199
115
|
expect(official.get("code2skill")?.category.id).toBe("tools");
|
|
200
116
|
expect(official.get("code2skill")?.description).toMatch(/selected workspace source files/iu);
|
|
201
|
-
expect(official.get("code2skill")?.capabilities).toEqual(["
|
|
117
|
+
expect(official.get("code2skill")?.capabilities).toEqual(["reads-files", "writes-files"]);
|
|
202
118
|
expect(official.get("workspace-search")?.category.id).toBe("context");
|
|
203
119
|
expect(official.get("plugin-check")?.category.id).toBe("security");
|
|
204
120
|
expect(official.get("test-harness")?.category.id).toBe("testing");
|
|
205
121
|
expect(official.get("test-harness")?.description).toMatch(
|
|
206
122
|
/five fixed npm script.*trusted workspace.*12 KiB.*UTF-8.*untrusted.*timeout.*cancellable process-tree/iu,
|
|
207
123
|
);
|
|
208
|
-
expect(official.get("test-harness")?.capabilities).toEqual([
|
|
209
|
-
"five-script verification allowlist",
|
|
210
|
-
"real npm exit status and signal reporting",
|
|
211
|
-
"12 KiB UTF-8-safe output tail",
|
|
212
|
-
"terminal-control sanitization and untrusted framing",
|
|
213
|
-
"configurable bounded timeout",
|
|
214
|
-
"cancellable process-tree cleanup",
|
|
215
|
-
"descriptor-safe normalized panel",
|
|
216
|
-
]);
|
|
124
|
+
expect(official.get("test-harness")?.capabilities).toEqual(["runs-commands"]);
|
|
217
125
|
expect(official.get("test-harness")?.hooks).toEqual(["project verification tool", "workspace npm scripts", "plugin UI"]);
|
|
218
126
|
expect(official.get("test-harness")?.profile.config).toEqual({ timeoutMs: 120_000 });
|
|
219
127
|
expect(official.get("git-time-capsule")?.category.id).toBe("workflow");
|
|
220
128
|
expect(official.get("git-time-capsule")?.description).toMatch(/unstaged tracked Git diff.*byte.*validated.*reverse/iu);
|
|
221
|
-
expect(official.get("git-time-capsule")?.capabilities).toEqual([
|
|
222
|
-
"byte-exact validated unstaged diff capture",
|
|
223
|
-
"exclusive no-clobber capsule publication",
|
|
224
|
-
"confirmed deterministic reverse apply",
|
|
225
|
-
"bounded 256-capsule inventory",
|
|
226
|
-
"cancellable serialized Git operations",
|
|
227
|
-
"descriptor-safe normalized panel",
|
|
228
|
-
]);
|
|
129
|
+
expect(official.get("git-time-capsule")?.capabilities).toEqual(["reads-files", "writes-files", "runs-commands"]);
|
|
229
130
|
expect(official.get("git-time-capsule")?.hooks).toEqual(["Git snapshot tool", "Git restore tool", "plugin UI"]);
|
|
230
131
|
expect(official.get("git-time-capsule")?.profile.config).toEqual({ timeoutMs: 15_000 });
|
|
231
132
|
expect(official.get("graph-memory")?.description).toMatch(/bounded typed.*directed relations.*atomic.*cross-session/iu);
|
|
232
|
-
expect(official.get("graph-memory")?.capabilities).toEqual([
|
|
233
|
-
"bounded typed nodes",
|
|
234
|
-
"validated directed relations",
|
|
235
|
-
"ranked graph search",
|
|
236
|
-
"atomic locked persistence",
|
|
237
|
-
]);
|
|
133
|
+
expect(official.get("graph-memory")?.capabilities).toEqual(["reads-files", "writes-files"]);
|
|
238
134
|
expect(official.get("graph-memory")?.hooks).toEqual(["graph memory tools", "local graph file", "plugin UI"]);
|
|
239
135
|
expect(official.get("graph-memory")?.profile.config).toEqual({ fileName: "graph-memory.json", maxNodes: 2_000, maxRelations: 5_000 });
|
|
240
136
|
expect(official.get("yaml-validator")?.category.id).toBe("developer");
|
|
241
137
|
expect(official.get("yaml-validator")?.description).toMatch(/workspace-contained.*UTF-8.*multi-document.*bounded.*cancellable/iu);
|
|
242
|
-
expect(official.get("yaml-validator")?.capabilities).toEqual([
|
|
243
|
-
"workspace-contained bounded reads",
|
|
244
|
-
"strict UTF-8 multi-document YAML",
|
|
245
|
-
"line-aware error and warning diagnostics",
|
|
246
|
-
"cancellable validation lifecycle",
|
|
247
|
-
"bounded panel previews",
|
|
248
|
-
]);
|
|
138
|
+
expect(official.get("yaml-validator")?.capabilities).toEqual(["read-only", "reads-files"]);
|
|
249
139
|
expect(official.get("yaml-validator")?.hooks).toEqual(["YAML validation tool", "workspace files", "plugin UI"]);
|
|
250
140
|
expect(official.get("yaml-validator")?.profile.config).toEqual({});
|
|
251
141
|
expect(official.get("browser-session")?.category.id).toBe("web");
|
|
252
142
|
expect(official.get("browser-session")?.category).toEqual(official.get("browser-fetch")?.category);
|
|
253
143
|
expect(official.get("browser-session")?.description).toMatch(/loopback-only.*descriptor-safe.*bounded.*cancellable.*screenshot.*validated.*panel/iu);
|
|
254
|
-
expect(official.get("browser-session")?.capabilities).toEqual([
|
|
255
|
-
"loopback-only CDP endpoint",
|
|
256
|
-
"bounded tab discovery",
|
|
257
|
-
"navigation read click and screenshot tools",
|
|
258
|
-
"cancellable request lifecycle",
|
|
259
|
-
"bounded panel previews",
|
|
260
|
-
"validated fail-closed panel reporting",
|
|
261
|
-
]);
|
|
144
|
+
expect(official.get("browser-session")?.capabilities).toEqual(["network-access"]);
|
|
262
145
|
expect(official.get("browser-session")?.hooks).toEqual(["browser session tools", "Chrome DevTools Protocol", "plugin UI"]);
|
|
263
146
|
expect(official.get("browser-session")?.profile.config).toEqual({ endpoint: "http://127.0.0.1:9222" });
|
|
264
147
|
expect(official.get("docker-sandbox")?.category.id).toBe("security");
|
|
265
148
|
expect(official.get("docker-sandbox")?.description).toMatch(
|
|
266
149
|
/descriptor-safe.*local-only.*no container network.*read-only workspace.*CPU.*memory.*PID.*sanitized output.*strict panel.*cancellation cleanup/iu,
|
|
267
150
|
);
|
|
268
|
-
expect(official.get("docker-sandbox")?.capabilities).toEqual([
|
|
269
|
-
"local-only image execution",
|
|
270
|
-
"no-network containers",
|
|
271
|
-
"read-only workspace by default",
|
|
272
|
-
"CPU memory and PID limits",
|
|
273
|
-
"sanitized bounded output",
|
|
274
|
-
"strict panel reporting",
|
|
275
|
-
"cancellation cleanup",
|
|
276
|
-
]);
|
|
151
|
+
expect(official.get("docker-sandbox")?.capabilities).toEqual(["reads-files", "writes-files", "runs-commands"]);
|
|
277
152
|
expect(official.get("docker-sandbox")?.hooks).toEqual(["sandbox execution tool", "Docker CLI", "plugin UI"]);
|
|
278
153
|
expect(official.get("docker-sandbox")?.profile.config).toEqual({});
|
|
279
154
|
expect(official.get("mock-server")?.category.id).toBe("tools");
|
|
@@ -281,27 +156,14 @@ describe("plugin marketplace registry", () => {
|
|
|
281
156
|
expect(official.get("sql-lens")?.description).toMatch(
|
|
282
157
|
/workspace.*SQLite.*strict.*descriptor-safe.*single.*read-only.*bounded.*symlink.*timed.*cancellation.*fail-closed.*panel/iu,
|
|
283
158
|
);
|
|
284
|
-
expect(official.get("sql-lens")?.capabilities).toEqual([
|
|
285
|
-
"single-statement SQLite inspection",
|
|
286
|
-
"isolated read-only query worker",
|
|
287
|
-
"bounded rows cells and result bytes",
|
|
288
|
-
"workspace and symlink safety checks",
|
|
289
|
-
"timeout and cancellation termination",
|
|
290
|
-
"validated fail-closed panel reporting",
|
|
291
|
-
]);
|
|
159
|
+
expect(official.get("sql-lens")?.capabilities).toEqual(["reads-files", "runs-commands"]);
|
|
292
160
|
expect(official.get("sql-lens")?.hooks).toEqual(["SQL read-only tool", "workspace SQLite files", "plugin UI"]);
|
|
293
161
|
expect(official.get("sql-lens")?.profile.config).toEqual({ timeoutMs: 5_000 });
|
|
294
162
|
expect(official.get("i18n-pair")?.category.id).toBe("workflow");
|
|
295
163
|
expect(official.get("i18n-pair")?.description).toMatch(
|
|
296
164
|
/strict read-only.*bounded JSON locale.*no-follow workspace.*collision-safe missing.*extra.*stable failures.*cancellation.*validated panel/iu,
|
|
297
165
|
);
|
|
298
|
-
expect(official.get("i18n-pair")?.capabilities).toEqual([
|
|
299
|
-
"collision-safe locale key parity",
|
|
300
|
-
"strict bounded workspace-only JSON reads",
|
|
301
|
-
"no-follow symbolic-link safety",
|
|
302
|
-
"stable sequential cancellable inspection",
|
|
303
|
-
"validated bounded panel reporting",
|
|
304
|
-
]);
|
|
166
|
+
expect(official.get("i18n-pair")?.capabilities).toEqual(["read-only", "reads-files"]);
|
|
305
167
|
expect(official.get("i18n-pair")?.hooks).toEqual(["i18n check tool", "workspace locale files", "plugin UI"]);
|
|
306
168
|
expect(official.get("i18n-pair")?.profile.config).toEqual({});
|
|
307
169
|
expect(official.get("plugin-finder")?.category.id).toBe("discovery");
|
|
@@ -309,15 +171,7 @@ describe("plugin marketplace registry", () => {
|
|
|
309
171
|
expect(official.get("readme-gen")?.description).toMatch(
|
|
310
172
|
/strictly bounded manifest.*descriptor-safe loader.*Markdown-safe.*confirmed.*no-clobber atomic.*explicit overwrite.*cancellable/iu,
|
|
311
173
|
);
|
|
312
|
-
expect(official.get("readme-gen")?.capabilities).toEqual([
|
|
313
|
-
"bounded manifest metadata",
|
|
314
|
-
"descriptor-safe loader inventory",
|
|
315
|
-
"Markdown-safe rendering",
|
|
316
|
-
"confirmed no-clobber atomic writes",
|
|
317
|
-
"explicit overwrite confirmation",
|
|
318
|
-
"cancellable sequential tools",
|
|
319
|
-
"bounded normalized operation panel",
|
|
320
|
-
]);
|
|
174
|
+
expect(official.get("readme-gen")?.capabilities).toEqual(["reads-files", "writes-files"]);
|
|
321
175
|
expect(official.get("readme-gen")?.hooks).toEqual([
|
|
322
176
|
"README report and write tools",
|
|
323
177
|
"workspace manifest and files",
|
|
@@ -332,28 +186,14 @@ describe("plugin marketplace registry", () => {
|
|
|
332
186
|
expect(official.get("openpets")?.description).toMatch(
|
|
333
187
|
/bounded.*companion state.*validated.*session entr.*without retaining message contents.*persistence/iu,
|
|
334
188
|
);
|
|
335
|
-
expect(official.get("openpets")?.capabilities).toEqual([
|
|
336
|
-
"bounded durable companion state",
|
|
337
|
-
"validated session recovery",
|
|
338
|
-
"descriptor-safe pet actions",
|
|
339
|
-
"session event reactions",
|
|
340
|
-
"persistence health panel",
|
|
341
|
-
]);
|
|
189
|
+
expect(official.get("openpets")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
342
190
|
expect(official.get("openpets")?.hooks).toEqual(["session events", "pet reaction tool", "session storage", "plugin UI"]);
|
|
343
191
|
expect(official.get("openpets")?.profile.config).toEqual({});
|
|
344
192
|
expect(official.get("session-insights")?.category.id).toBe("observability");
|
|
345
193
|
expect(official.get("session-insights")?.description).toMatch(
|
|
346
194
|
/descriptor-safe.*validated.*cached.*session.*statistics.*confirmed.*settled.*compaction.*model.*usage.*cost.*cancellable/iu,
|
|
347
195
|
);
|
|
348
|
-
expect(official.get("session-insights")?.capabilities).toEqual([
|
|
349
|
-
"validated detached session statistics",
|
|
350
|
-
"message token cache cost and context accounting",
|
|
351
|
-
"cached active-session panel",
|
|
352
|
-
"confirmed settled-session compaction",
|
|
353
|
-
"dedicated compaction cancellation",
|
|
354
|
-
"single-flight bounded operation status",
|
|
355
|
-
"normalized fail-closed browser view",
|
|
356
|
-
]);
|
|
196
|
+
expect(official.get("session-insights")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
357
197
|
expect(official.get("session-insights")?.hooks).toEqual(["session report tool", "active runtime session", "Pi session lifecycle", "plugin UI"]);
|
|
358
198
|
expect(official.get("session-insights")?.profile.config).toEqual({});
|
|
359
199
|
expect(official.get("mcp-panel")?.category.id).toBe("tools");
|
|
@@ -361,31 +201,14 @@ describe("plugin marketplace registry", () => {
|
|
|
361
201
|
expect(official.get("fail-logger")?.description).toMatch(
|
|
362
202
|
/bounded.*extension.*Agent.*non-aborted compaction.*descriptor-safe event inspection.*safe diagnostic.*occurrence counts/iu,
|
|
363
203
|
);
|
|
364
|
-
expect(official.get("fail-logger")?.capabilities).toEqual([
|
|
365
|
-
"bounded failure aggregation",
|
|
366
|
-
"descriptor-safe event inspection",
|
|
367
|
-
"abort-aware compaction diagnostics",
|
|
368
|
-
"occurrence counting",
|
|
369
|
-
"safe diagnostic summaries",
|
|
370
|
-
"capacity visibility",
|
|
371
|
-
]);
|
|
204
|
+
expect(official.get("fail-logger")?.capabilities).toEqual(["read-only"]);
|
|
372
205
|
expect(official.get("fail-logger")?.hooks).toEqual(["extension error", "agent end", "compaction end", "plugin UI"]);
|
|
373
206
|
expect(official.get("genui")?.description).toMatch(/bounded.*text, badge, and decimal progress.*plain text/iu);
|
|
374
|
-
expect(official.get("genui")?.capabilities).toEqual([
|
|
375
|
-
"bounded structured cards",
|
|
376
|
-
"typed text badge and progress blocks",
|
|
377
|
-
"decimal progress validation",
|
|
378
|
-
"plain-text HTML handling",
|
|
379
|
-
]);
|
|
207
|
+
expect(official.get("genui")?.capabilities).toEqual(["read-only"]);
|
|
380
208
|
expect(official.get("genui")?.hooks).toEqual(["GenUI render tool", "plugin UI"]);
|
|
381
209
|
expect(official.get("plugin-dev")?.category.id).toBe("developer");
|
|
382
210
|
expect(official.get("plugin-dev")?.description).toMatch(/defer.*session resource.*agent.*settled.*single.*reload.*bounded.*trusted.*development/iu);
|
|
383
|
-
expect(official.get("plugin-dev")?.capabilities).toEqual([
|
|
384
|
-
"settled-session resource reload",
|
|
385
|
-
"single-flight reload guard",
|
|
386
|
-
"bounded reload status",
|
|
387
|
-
"cancellable caller wait",
|
|
388
|
-
]);
|
|
211
|
+
expect(official.get("plugin-dev")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
389
212
|
expect(official.get("plugin-dev")?.hooks).toEqual(["session resource reload tool", "Pi session lifecycle", "plugin UI"]);
|
|
390
213
|
expect(official.get("plugin-dev")?.profile.config).toEqual({});
|
|
391
214
|
expect(official.get("session-export")?.category.id).toBe("workflow");
|
|
@@ -403,25 +226,12 @@ describe("plugin marketplace registry", () => {
|
|
|
403
226
|
expect(official.get("context-insights")?.description).toMatch(
|
|
404
227
|
/descriptor-safe.*bounded message composition.*cached.*active-session.*lifecycle.*normalized browser/iu,
|
|
405
228
|
);
|
|
406
|
-
expect(official.get("context-insights")?.capabilities).toEqual([
|
|
407
|
-
"descriptor-safe bounded message composition",
|
|
408
|
-
"resilient context usage inspection",
|
|
409
|
-
"active-session lifecycle counters",
|
|
410
|
-
"cached session-aware panel",
|
|
411
|
-
"bounded normalized browser view",
|
|
412
|
-
]);
|
|
229
|
+
expect(official.get("context-insights")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
413
230
|
expect(official.get("context-insights")?.hooks).toEqual(["context inspection tool", "active runtime session", "Pi session lifecycle", "plugin UI"]);
|
|
414
231
|
expect(official.get("context-insights")?.profile.config).toEqual({});
|
|
415
232
|
expect(official.get("context-doctor")?.category.id).toBe("observability");
|
|
416
233
|
expect(official.get("context-doctor")?.description).toMatch(/descriptor-safe.*bounded.*queued.*agent.*settled.*confirmed.*model.*cost.*cancellable/iu);
|
|
417
|
-
expect(official.get("context-doctor")?.capabilities).toEqual([
|
|
418
|
-
"descriptor-safe bounded context audit",
|
|
419
|
-
"pressure oversized uninspectable and tool-error diagnostics",
|
|
420
|
-
"confirmed settled-session compaction",
|
|
421
|
-
"dedicated compaction cancellation",
|
|
422
|
-
"single-flight bounded operation status",
|
|
423
|
-
"cached normalized panel",
|
|
424
|
-
]);
|
|
234
|
+
expect(official.get("context-doctor")?.capabilities).toEqual(["read-only", "session-data"]);
|
|
425
235
|
expect(official.get("context-doctor")?.hooks).toEqual([
|
|
426
236
|
"context doctor tool",
|
|
427
237
|
"session messages and usage",
|
|
@@ -431,40 +241,27 @@ describe("plugin marketplace registry", () => {
|
|
|
431
241
|
]);
|
|
432
242
|
expect(official.get("context-doctor")?.profile.config).toEqual({});
|
|
433
243
|
expect(official.get("cordis-group")?.category.id).toBe("composition");
|
|
434
|
-
expect(official.get("cordis-group")?.capabilities).toEqual(["
|
|
244
|
+
expect(official.get("cordis-group")?.capabilities).toEqual(["read-only"]);
|
|
435
245
|
expect(official.get("cordis-group")?.hooks).toEqual(["loader entry tree"]);
|
|
436
246
|
expect(official.get("cordis-logger-console")?.category.id).toBe("observability");
|
|
437
|
-
expect(official.get("cordis-logger-console")?.capabilities).toEqual(["
|
|
247
|
+
expect(official.get("cordis-logger-console")?.capabilities).toEqual(["read-only"]);
|
|
438
248
|
expect(official.get("cordis-logger-console")?.hooks).toEqual(["Cordis logger exporter", "plugin UI"]);
|
|
439
249
|
expect(official.get("cordis-logger-console")?.profile.config).toEqual({ levels: { default: 2 }, maxLength: 8_192 });
|
|
440
250
|
expect(official.get("cordis-timer")?.category.id).toBe("runtime");
|
|
441
|
-
expect(official.get("cordis-timer")?.capabilities).toEqual([
|
|
442
|
-
"scheduling",
|
|
443
|
-
"lifecycle-owned cancellation",
|
|
444
|
-
"async interval iteration",
|
|
445
|
-
"throttle and debounce",
|
|
446
|
-
]);
|
|
251
|
+
expect(official.get("cordis-timer")?.capabilities).toEqual(["read-only"]);
|
|
447
252
|
expect(official.get("cordis-timer")?.hooks).toEqual(["Cordis timer service", "plugin UI"]);
|
|
448
253
|
expect(official.get("prompt-library")?.category.id).toBe("workflow");
|
|
449
254
|
expect(official.get("cleaner")?.category.id).toBe("developer");
|
|
450
255
|
expect(official.get("cleaner")?.description).toMatch(
|
|
451
256
|
/strict.*descriptor-safe.*display-safe.*bounded.*Git capsule.*explicit confirmation.*retention.*symlink.*replacement.*cancellable.*fail-closed/iu,
|
|
452
257
|
);
|
|
453
|
-
expect(official.get("cleaner")?.capabilities).toEqual([
|
|
454
|
-
"strict configuration and parameters",
|
|
455
|
-
"bounded capsule inventory",
|
|
456
|
-
"display-safe capsule filtering",
|
|
457
|
-
"confirmed retention cleanup",
|
|
458
|
-
"symlink and replacement defenses",
|
|
459
|
-
"cancellable serialized cleanup",
|
|
460
|
-
"fail-closed normalized panel",
|
|
461
|
-
]);
|
|
258
|
+
expect(official.get("cleaner")?.capabilities).toEqual(["reads-files", "writes-files"]);
|
|
462
259
|
expect(official.get("cleaner")?.hooks).toEqual(["capsule cleanup tool", "agent capsule directory", "plugin UI"]);
|
|
463
260
|
expect(official.get("cleaner")?.profile.config).toEqual({});
|
|
464
261
|
expect(official.get("cli-notifier")?.category.id).toBe("workflow");
|
|
465
262
|
expect(official.get("cli-notifier")?.description).toMatch(/local desktop notifications/iu);
|
|
466
263
|
expect(official.get("cli-notifier")?.description).not.toMatch(/webhook/iu);
|
|
467
|
-
expect(official.get("cli-notifier")?.capabilities).toEqual(["
|
|
264
|
+
expect(official.get("cli-notifier")?.capabilities).toEqual(["runs-commands"]);
|
|
468
265
|
expect(official.get("cli-notifier")?.hooks).toEqual(["agent end", "compaction error", "plugin UI"]);
|
|
469
266
|
expect(official.get("obsidian-sync")?.category.id).toBe("workflow");
|
|
470
267
|
expect(official.get("tab-manager")?.category.id).toBe("workflow");
|
|
@@ -481,7 +278,7 @@ describe("plugin marketplace registry", () => {
|
|
|
481
278
|
});
|
|
482
279
|
|
|
483
280
|
test("filters by query and capability without mutating the registry", () => {
|
|
484
|
-
const result = searchMarketplace("timer", "
|
|
281
|
+
const result = searchMarketplace("timer", "read-only");
|
|
485
282
|
expect(result.map((plugin) => plugin.packageName)).toEqual(["@deepseek-ai/cordis-plugin-timer"]);
|
|
486
283
|
expect(searchMarketplace("does-not-exist")).toEqual([]);
|
|
487
284
|
expect(MARKETPLACE_PLUGINS.length).toBeGreaterThan(3);
|
|
@@ -503,7 +300,44 @@ describe("plugin marketplace registry", () => {
|
|
|
503
300
|
pageSize: 2,
|
|
504
301
|
hasNext: MARKETPLACE_PLUGINS.length > 4,
|
|
505
302
|
});
|
|
506
|
-
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// The filter is the first thing a reader touches before installing anything, so what it offers has to be a fixed set that says what a plugin does to the machine, and every entry has to answer it.
|
|
306
|
+
test("describes every entry with the same closed capability vocabulary", () => {
|
|
307
|
+
const vocabulary = MARKETPLACE_CAPABILITIES.map((capability) => capability.id);
|
|
308
|
+
expect(vocabulary).toEqual(["read-only", "session-data", "reads-files", "writes-files", "runs-commands", "local-server", "network-access", "model-calls"]);
|
|
309
|
+
expect(MARKETPLACE_CAPABILITIES.every((capability) => capability.label !== "" && capability.count > 0)).toBe(true);
|
|
310
|
+
expect(MARKETPLACE_CAPABILITIES.reduce((sum, capability) => sum + capability.count, 0)).toBe(
|
|
311
|
+
MARKETPLACE_PLUGINS.reduce((sum, plugin) => sum + plugin.capabilities.length, 0),
|
|
312
|
+
);
|
|
313
|
+
for (const plugin of MARKETPLACE_PLUGINS) {
|
|
314
|
+
expect(plugin.capabilities.length).toBeGreaterThan(0);
|
|
315
|
+
expect(plugin.capabilities.filter((capability) => vocabulary.includes(capability))).toEqual(plugin.capabilities);
|
|
316
|
+
expect(new Set(plugin.capabilities).size).toBe(plugin.capabilities.length);
|
|
317
|
+
// A plugin that says it changes nothing cannot also say it writes, executes, listens, dials out, or spends money.
|
|
318
|
+
if (plugin.capabilities.includes("read-only"))
|
|
319
|
+
expect(
|
|
320
|
+
plugin.capabilities.some((capability) => ["writes-files", "runs-commands", "local-server", "network-access", "model-calls"].includes(capability)),
|
|
321
|
+
).toBe(false);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// The tabs take their label from whichever entry happens to be read first, so two spellings of one category would make the console's own vocabulary depend on file order.
|
|
326
|
+
test("spells each category the same way in every entry", () => {
|
|
327
|
+
const labels = new Map<string, string>();
|
|
328
|
+
for (const plugin of MARKETPLACE_PLUGINS) {
|
|
329
|
+
expect(labels.get(plugin.category.id) ?? plugin.category.label).toBe(plugin.category.label);
|
|
330
|
+
labels.set(plugin.category.id, plugin.category.label);
|
|
331
|
+
}
|
|
332
|
+
expect(labels.size).toBe(MARKETPLACE_CATEGORIES.length);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// The ids are what the filter and the URL carry, and the labels are what the reader sees, so a search for either has to find the same plugin.
|
|
336
|
+
test("finds a plugin by a capability id and by its label", () => {
|
|
337
|
+
const byId = searchMarketplace("local-server");
|
|
338
|
+
expect(byId.map((plugin) => plugin.id)).toEqual(["mock-server"]);
|
|
339
|
+
expect(searchMarketplace("监听本地端口").map((plugin) => plugin.id)).toEqual(["mock-server"]);
|
|
340
|
+
expect(searchMarketplace("", "local-server").map((plugin) => plugin.id)).toEqual(["mock-server"]);
|
|
507
341
|
});
|
|
508
342
|
|
|
509
343
|
test("maps plugin entry points to their published npm package", () => {
|
|
@@ -658,6 +492,104 @@ describe("plugin marketplace registry", () => {
|
|
|
658
492
|
expect(requests).toBe(3);
|
|
659
493
|
});
|
|
660
494
|
|
|
495
|
+
test("serves the statistics already cached and warms the missing ones in the background", async () => {
|
|
496
|
+
const requests: string[] = [];
|
|
497
|
+
const fetcher = (url: string): Promise<Response> => {
|
|
498
|
+
requests.push(url);
|
|
499
|
+
if (url.startsWith("https://registry.npmjs.org/-/v1/search"))
|
|
500
|
+
return Promise.resolve(
|
|
501
|
+
Response.json({
|
|
502
|
+
objects: [
|
|
503
|
+
{
|
|
504
|
+
package: { name: new URL(url).searchParams.get("text"), date: "2026-08-30T13:14:00.557Z" },
|
|
505
|
+
score: { detail: { quality: 0.9 } },
|
|
506
|
+
},
|
|
507
|
+
],
|
|
508
|
+
}),
|
|
509
|
+
);
|
|
510
|
+
return Promise.resolve(Response.json({ downloads: 4_200 }));
|
|
511
|
+
};
|
|
512
|
+
const load = createMarketplaceStatisticsLoader({ fetcher, ttlMs: 60_000 });
|
|
513
|
+
const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === "cordis-timer")!;
|
|
514
|
+
|
|
515
|
+
expect(load.readCached([plugin])).toEqual({ ready: false, statistics: new Map() });
|
|
516
|
+
await vi.waitFor(() => expect(requests).toHaveLength(2));
|
|
517
|
+
|
|
518
|
+
expect(load.readCached([plugin])).toEqual({
|
|
519
|
+
ready: true,
|
|
520
|
+
statistics: new Map([["@deepseek-ai/cordis-plugin-timer", { downloads30d: 4_200, quality: 0.9, updatedAt: "2026-08-30T13:14:00.557Z" }]]),
|
|
521
|
+
});
|
|
522
|
+
expect(requests).toHaveLength(2);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
test("stays ready once a lookup has expired so the catalogue is not reordered back to its unsorted form mid-session", async () => {
|
|
526
|
+
let timestamp = 1_000;
|
|
527
|
+
const fetcher = (url: string): Promise<Response> => {
|
|
528
|
+
if (url.startsWith("https://registry.npmjs.org/-/v1/search"))
|
|
529
|
+
return Promise.resolve(Response.json({ objects: [{ package: { name: "@deepseek-ai/cordis-plugin-timer" }, score: { detail: { quality: 0.5 } } }] }));
|
|
530
|
+
return Promise.resolve(Response.json({ downloads: 10 }));
|
|
531
|
+
};
|
|
532
|
+
const load = createMarketplaceStatisticsLoader({ fetcher, now: () => timestamp, ttlMs: 100 });
|
|
533
|
+
const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === "cordis-timer")!;
|
|
534
|
+
|
|
535
|
+
await load([plugin]);
|
|
536
|
+
timestamp += 101;
|
|
537
|
+
|
|
538
|
+
// The entry is stale and is refreshed in the background, but it has been looked up, so the caller keeps sorting on statistics instead of dropping the whole grid back to catalogue order for one poll.
|
|
539
|
+
const cached = load.readCached([plugin]);
|
|
540
|
+
expect(cached.ready).toBe(true);
|
|
541
|
+
expect(cached.statistics.size).toBe(0);
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
test("keeps the npm fan-out below the configured concurrency instead of asking for every package at once", async () => {
|
|
545
|
+
let active = 0;
|
|
546
|
+
let peak = 0;
|
|
547
|
+
const fetcher = async (): Promise<Response> => {
|
|
548
|
+
active += 1;
|
|
549
|
+
peak = Math.max(peak, active);
|
|
550
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
551
|
+
active -= 1;
|
|
552
|
+
return Response.json({ objects: [] });
|
|
553
|
+
};
|
|
554
|
+
const base = MARKETPLACE_PLUGINS.find((plugin) => plugin.id === "cordis-timer")!;
|
|
555
|
+
const plugins = Array.from({ length: 12 }, (_, index) => ({ ...base, id: `bulk-${index}`, packageName: `bulk-package-${index}` }));
|
|
556
|
+
const load = createMarketplaceStatisticsLoader({ concurrency: 3, fetcher });
|
|
557
|
+
|
|
558
|
+
await load(plugins);
|
|
559
|
+
|
|
560
|
+
expect(peak).toBe(3);
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
test("backs off further on every consecutive npm failure so an open console stops re-issuing the same lookups", async () => {
|
|
564
|
+
let timestamp = 1_000;
|
|
565
|
+
let requests = 0;
|
|
566
|
+
const fetcher = (): Promise<Response> => {
|
|
567
|
+
requests += 1;
|
|
568
|
+
throw new Error("npm unavailable");
|
|
569
|
+
};
|
|
570
|
+
const load = createMarketplaceStatisticsLoader({ failureMaxTtlMs: 400, failureTtlMs: 100, fetcher, now: () => timestamp });
|
|
571
|
+
const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === "cordis-timer")!;
|
|
572
|
+
|
|
573
|
+
await load([plugin]);
|
|
574
|
+
timestamp += 101;
|
|
575
|
+
await load([plugin]);
|
|
576
|
+
expect(requests).toBe(2);
|
|
577
|
+
|
|
578
|
+
// The second failure doubles the retry window, so the poll that would have retried under a flat window finds the cache still valid.
|
|
579
|
+
timestamp += 101;
|
|
580
|
+
await load([plugin]);
|
|
581
|
+
expect(requests).toBe(2);
|
|
582
|
+
|
|
583
|
+
timestamp += 100;
|
|
584
|
+
await load([plugin]);
|
|
585
|
+
expect(requests).toBe(3);
|
|
586
|
+
|
|
587
|
+
// The window is capped rather than doubling forever, so the package is retried again once the ceiling elapses.
|
|
588
|
+
timestamp += 401;
|
|
589
|
+
await load([plugin]);
|
|
590
|
+
expect(requests).toBe(4);
|
|
591
|
+
});
|
|
592
|
+
|
|
661
593
|
test("sorts recommendations before pagination using verification, npm quality, downloads and recency", () => {
|
|
662
594
|
const base = MARKETPLACE_PLUGINS.find((plugin) => plugin.id === "cordis-timer")!;
|
|
663
595
|
const plugins = [
|