@inharness-ai/claude4spec 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/c4s-brief-implementer/SKILL.md +120 -53
- package/CHANGELOG.md +20 -0
- package/dist/bin/c4s/commands/agent.d.ts +18 -0
- package/dist/bin/c4s/commands/agent.js +102 -0
- package/dist/bin/c4s/commands/agent.js.map +1 -0
- package/dist/bin/c4s/commands/ask.d.ts +9 -8
- package/dist/bin/c4s/commands/ask.js +23 -31
- package/dist/bin/c4s/commands/ask.js.map +1 -1
- package/dist/bin/c4s/commands/catalog.d.ts +1 -1
- package/dist/bin/c4s/commands/catalog.js +2 -2
- package/dist/bin/c4s/commands/catalog.js.map +1 -1
- package/dist/bin/c4s/commands/describe.d.ts +1 -1
- package/dist/bin/c4s/commands/describe.js +2 -2
- package/dist/bin/c4s/commands/describe.js.map +1 -1
- package/dist/bin/c4s/commands/detail.d.ts +1 -1
- package/dist/bin/c4s/commands/detail.js +2 -2
- package/dist/bin/c4s/commands/detail.js.map +1 -1
- package/dist/bin/c4s/commands/element-list.d.ts +1 -1
- package/dist/bin/c4s/commands/element-list.js +2 -2
- package/dist/bin/c4s/commands/element-list.js.map +1 -1
- package/dist/bin/c4s/commands/find-references.js +1 -1
- package/dist/bin/c4s/commands/find-references.js.map +1 -1
- package/dist/bin/c4s/commands/inline-mention.d.ts +1 -1
- package/dist/bin/c4s/commands/inline-mention.js +2 -2
- package/dist/bin/c4s/commands/inline-mention.js.map +1 -1
- package/dist/bin/c4s/commands/list-slugs.d.ts +1 -1
- package/dist/bin/c4s/commands/list-slugs.js +2 -2
- package/dist/bin/c4s/commands/list-slugs.js.map +1 -1
- package/dist/bin/c4s/commands/list-tags.d.ts +1 -1
- package/dist/bin/c4s/commands/list-tags.js +2 -2
- package/dist/bin/c4s/commands/list-tags.js.map +1 -1
- package/dist/bin/c4s/commands/plugins.d.ts +9 -0
- package/dist/bin/c4s/commands/plugins.js +81 -0
- package/dist/bin/c4s/commands/plugins.js.map +1 -0
- package/dist/bin/c4s/commands/resolve.d.ts +1 -1
- package/dist/bin/c4s/commands/resolve.js +2 -2
- package/dist/bin/c4s/commands/resolve.js.map +1 -1
- package/dist/bin/c4s/commands/single-element.d.ts +1 -1
- package/dist/bin/c4s/commands/single-element.js +2 -2
- package/dist/bin/c4s/commands/single-element.js.map +1 -1
- package/dist/bin/c4s/commands/tagged-list-mixed.d.ts +1 -1
- package/dist/bin/c4s/commands/tagged-list-mixed.js +2 -2
- package/dist/bin/c4s/commands/tagged-list-mixed.js.map +1 -1
- package/dist/bin/c4s/commands/tagged-list.d.ts +1 -1
- package/dist/bin/c4s/commands/tagged-list.js +2 -2
- package/dist/bin/c4s/commands/tagged-list.js.map +1 -1
- package/dist/bin/c4s/context.d.ts +3 -3
- package/dist/bin/c4s/context.js +7 -4
- package/dist/bin/c4s/context.js.map +1 -1
- package/dist/bin/c4s/errors.d.ts +1 -1
- package/dist/bin/c4s/errors.js.map +1 -1
- package/dist/bin/c4s-mcp.js +6 -2
- package/dist/bin/c4s-mcp.js.map +1 -1
- package/dist/bin/c4s.js +19 -4
- package/dist/bin/c4s.js.map +1 -1
- package/dist/bin/gitignore.js +7 -11
- package/dist/bin/gitignore.js.map +1 -1
- package/dist/client/assets/{arc-Coa9fbDO.js → arc-C9oTB3b1.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-VJZcRMEN.js → architectureDiagram-3BPJPVTR-Bno5ViqK.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-C7dU2lW1.js → blockDiagram-GPEHLZMM-CJYBoeWQ.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CG_BBm_5.js → c4Diagram-AAUBKEIU-DaaqWE6s.js} +1 -1
- package/dist/client/assets/channel-Cei_E79M.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BnS95YpK.js → chunk-2J33WTMH-P_I0OPMy.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-COr8w3X3.js → chunk-4BX2VUAB-CCySMlh5.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CxrIbZhB.js → chunk-55IACEB6-CEUyqKGF.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DRchPPRe.js → chunk-727SXJPM-CoTSYOVz.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-_SfN7mED.js → chunk-AQP2D5EJ-DB0nMxPr.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-p2tIiP1D.js → chunk-FMBD7UC4-PG3m6-_a.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-B1mbl2hP.js → chunk-ND2GUHAM-CBNk6IaV.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-DBUpeqvS.js → chunk-QZHKN3VN-CLFa0WvN.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DUe_fAto.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DUe_fAto.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BBsY5aKD.js → cose-bilkent-S5V4N54A-BDwDDxHN.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-b-vu4RC9.js → dagre-BM42HDAG-DR-1e8N5.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-j-DW9qSf.js → diagram-2AECGRRQ-C-tHgBWt.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DHX_WYWQ.js → diagram-5GNKFQAL-uLmoKaJL.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DxdQok_M.js → diagram-KO2AKTUF-8Fd-xuOy.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-BbTIX5c1.js → diagram-LMA3HP47-C1gniWsn.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BQ9ODAlH.js → diagram-OG6HWLK6-BMWjZbeC.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-6lwAL1y9.js → erDiagram-TEJ5UH35-CIUO8hrR.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-ioSHb5-t.js → flowDiagram-I6XJVG4X-Ccw5YEf3.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CXFQp9Nj.js → ganttDiagram-6RSMTGT7-BAvlf8cY.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-C1pVD_NQ.js → gitGraphDiagram-PVQCEYII-ChCkdYar.js} +1 -1
- package/dist/client/assets/{index-JaAxQJXh.js → index-BotCWOKC.js} +1 -1
- package/dist/client/assets/index-CtdzGyqj.js +805 -0
- package/dist/client/assets/{index-hz5T_W2e.js → index-DtpKHGD1.js} +1 -1
- package/dist/client/assets/{infoDiagram-5YYISTIA-C2Guev-g.js → infoDiagram-5YYISTIA-CZMGwNyB.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-D3v8VBb2.js → ishikawaDiagram-YF4QCWOH-CubjZGk6.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DX1AW_Ap.js → journeyDiagram-JHISSGLW-DzwOyVzB.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CzXThvq2.js → kanban-definition-UN3LZRKU-CXznoTY9.js} +1 -1
- package/dist/client/assets/{linear-CVw4gl5i.js → linear-EDwTFRrU.js} +1 -1
- package/dist/client/assets/{mermaid.core-C29eoXRj.js → mermaid.core-Lae2097R.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DEEGVQVA.js → mindmap-definition-RKZ34NQL-DFjIW41g.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-Dme-VM6m.js → pieDiagram-4H26LBE5-CZDLR1jd.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CURFNo24.js → quadrantDiagram-W4KKPZXB-CTGDzbqp.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DxMZWXME.js → requirementDiagram-4Y6WPE33-CeH0NbMv.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BW64D4_P.js → sankeyDiagram-5OEKKPKP-B6ZTjurV.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BATRPm8Q.js → sequenceDiagram-3UESZ5HK-DcTRztVx.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-pgHVMnO3.js → stateDiagram-AJRCARHV-nUgRVZSA.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-D9pJuQbI.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-qBxJZPWd.js → timeline-definition-PNZ67QCA-CXm5n4rV.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BZJK9hqJ.js → vennDiagram-CIIHVFJN-EmNJBYNd.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BobtgEXg.js → wardley-L42UT6IY-MLrlp8H-.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DuWfX_-P.js → wardleyDiagram-YWT4CUSO-5QoES25n.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DCw1iURo.js → xychartDiagram-2RQKCTM6-CbDEQbY0.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/core/agent/run-agent.d.ts +61 -0
- package/dist/core/agent/run-agent.js +212 -0
- package/dist/core/agent/run-agent.js.map +1 -0
- package/dist/core/ask/run-ask.d.ts +1 -1
- package/dist/core/ask/run-ask.js +14 -5
- package/dist/core/ask/run-ask.js.map +1 -1
- package/dist/core/workspace/resolve.d.ts +2 -0
- package/dist/core/workspace/resolve.js +2 -1
- package/dist/core/workspace/resolve.js.map +1 -1
- package/dist/plugin-types/ambient.d.ts +30 -0
- package/dist/plugin-types/plugin-runtime.d.ts +172 -0
- package/dist/plugin-types/ui.d.ts +154 -0
- package/dist/server/config.d.ts +12 -0
- package/dist/server/config.js +26 -0
- package/dist/server/config.js.map +1 -1
- package/dist/server/core/plugin-host/__fixtures__/plugins.d.ts +14 -0
- package/dist/server/core/plugin-host/__fixtures__/plugins.js +56 -0
- package/dist/server/core/plugin-host/__fixtures__/plugins.js.map +1 -0
- package/dist/server/core/plugin-host/base-packages.d.ts +14 -0
- package/dist/server/core/plugin-host/base-packages.js +26 -0
- package/dist/server/core/plugin-host/base-packages.js.map +1 -0
- package/dist/server/core/plugin-host/cache-bust.d.ts +10 -0
- package/dist/server/core/plugin-host/cache-bust.js +21 -0
- package/dist/server/core/plugin-host/cache-bust.js.map +1 -0
- package/dist/server/core/plugin-host/cli-engine.d.ts +7 -2
- package/dist/server/core/plugin-host/cli-engine.js +11 -3
- package/dist/server/core/plugin-host/cli-engine.js.map +1 -1
- package/dist/server/core/plugin-host/cli-plugins.d.ts +23 -0
- package/dist/server/core/plugin-host/cli-plugins.js +49 -0
- package/dist/server/core/plugin-host/cli-plugins.js.map +1 -0
- package/dist/server/core/plugin-host/cross-cutting.d.ts +41 -4
- package/dist/server/core/plugin-host/cross-cutting.js +52 -4
- package/dist/server/core/plugin-host/cross-cutting.js.map +1 -1
- package/dist/server/core/plugin-host/frontend-assets.d.ts +100 -0
- package/dist/server/core/plugin-host/frontend-assets.js +262 -0
- package/dist/server/core/plugin-host/frontend-assets.js.map +1 -0
- package/dist/server/core/plugin-host/frontend-manifest.d.ts +33 -0
- package/dist/server/core/plugin-host/frontend-manifest.js +60 -0
- package/dist/server/core/plugin-host/frontend-manifest.js.map +1 -0
- package/dist/server/core/plugin-host/loader.d.ts +107 -0
- package/dist/server/core/plugin-host/loader.js +196 -0
- package/dist/server/core/plugin-host/loader.js.map +1 -0
- package/dist/server/core/plugin-host/manifest-adapter.d.ts +30 -0
- package/dist/server/core/plugin-host/manifest-adapter.js +119 -0
- package/dist/server/core/plugin-host/manifest-adapter.js.map +1 -0
- package/dist/server/core/plugin-host/overlay-loader.d.ts +60 -0
- package/dist/server/core/plugin-host/overlay-loader.js +243 -0
- package/dist/server/core/plugin-host/overlay-loader.js.map +1 -0
- package/dist/server/core/plugin-host/plugin-watcher.d.ts +41 -0
- package/dist/server/core/plugin-host/plugin-watcher.js +95 -0
- package/dist/server/core/plugin-host/plugin-watcher.js.map +1 -0
- package/dist/server/core/plugin-host/project-host.d.ts +8 -2
- package/dist/server/core/plugin-host/project-host.js +56 -6
- package/dist/server/core/plugin-host/project-host.js.map +1 -1
- package/dist/server/core/plugin-host/registry.d.ts +26 -2
- package/dist/server/core/plugin-host/registry.js +107 -2
- package/dist/server/core/plugin-host/registry.js.map +1 -1
- package/dist/server/core/plugin-host/runtime-shims.d.ts +26 -0
- package/dist/server/core/plugin-host/runtime-shims.js +96 -0
- package/dist/server/core/plugin-host/runtime-shims.js.map +1 -0
- package/dist/server/core/plugin-host/types.d.ts +105 -3
- package/dist/server/db/migrations/042_chat_thread_drop_context_type_check.sql +61 -0
- package/dist/server/external-skills/brief-implementer-template.d.ts +1 -1
- package/dist/server/external-skills/brief-implementer-template.js +5 -2
- package/dist/server/external-skills/brief-implementer-template.js.map +1 -1
- package/dist/server/external-skills/spec-reader-template.d.ts +1 -1
- package/dist/server/external-skills/spec-reader-template.js +14 -0
- package/dist/server/external-skills/spec-reader-template.js.map +1 -1
- package/dist/server/index.js +82 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/c4s-tools.d.ts +6 -1
- package/dist/server/mcp/c4s-tools.js +18 -13
- package/dist/server/mcp/c4s-tools.js.map +1 -1
- package/dist/server/plugin-runtime/index.d.ts +17 -0
- package/dist/server/plugin-runtime/index.js +16 -0
- package/dist/server/plugin-runtime/index.js.map +1 -0
- package/dist/server/plugin-runtime/ui.d.ts +15 -0
- package/dist/server/plugin-runtime/ui.js +15 -0
- package/dist/server/plugin-runtime/ui.js.map +1 -0
- package/dist/server/routes/agent-turn.d.ts +8 -1
- package/dist/server/routes/agent-turn.js +67 -39
- package/dist/server/routes/agent-turn.js.map +1 -1
- package/dist/server/routes/config.d.ts +8 -0
- package/dist/server/routes/config.js +41 -3
- package/dist/server/routes/config.js.map +1 -1
- package/dist/server/routes/plugins.d.ts +43 -0
- package/dist/server/routes/plugins.js +93 -0
- package/dist/server/routes/plugins.js.map +1 -0
- package/dist/server/routes/threads.js +21 -3
- package/dist/server/routes/threads.js.map +1 -1
- package/dist/server/serialization/registerAll.d.ts +4 -0
- package/dist/server/serialization/registerAll.js +4 -2
- package/dist/server/serialization/registerAll.js.map +1 -1
- package/dist/server/services/chat-context.d.ts +34 -0
- package/dist/server/services/chat-context.js +58 -15
- package/dist/server/services/chat-context.js.map +1 -1
- package/dist/server/services/chat.d.ts +6 -0
- package/dist/server/services/chat.js +18 -2
- package/dist/server/services/chat.js.map +1 -1
- package/dist/server/services/entity-writer.d.ts +2 -3
- package/dist/server/services/entity-writer.js.map +1 -1
- package/dist/server/services/skill-registry.d.ts +31 -2
- package/dist/server/services/skill-registry.js +73 -1
- package/dist/server/services/skill-registry.js.map +1 -1
- package/dist/server/workspace/context-cache.d.ts +9 -0
- package/dist/server/workspace/context-cache.js +14 -0
- package/dist/server/workspace/context-cache.js.map +1 -1
- package/dist/server/workspace/project-context.d.ts +3 -0
- package/dist/server/workspace/project-context.js +106 -4
- package/dist/server/workspace/project-context.js.map +1 -1
- package/dist/server/workspace/registry.d.ts +28 -1
- package/dist/server/workspace/registry.js +57 -1
- package/dist/server/workspace/registry.js.map +1 -1
- package/dist/server/workspace/types.d.ts +15 -0
- package/dist/shared/entities.d.ts +4 -1
- package/dist/shared/entities.js.map +1 -1
- package/dist/shared/plugin-host/frontend-manifest.d.ts +56 -0
- package/dist/shared/plugin-host/frontend-manifest.js +89 -0
- package/dist/shared/plugin-host/frontend-manifest.js.map +1 -0
- package/dist/shared/plugin-host/host-api.d.ts +60 -0
- package/dist/shared/plugin-host/host-api.js +67 -0
- package/dist/shared/plugin-host/host-api.js.map +1 -0
- package/dist/shared/plugin-host/manifest.d.ts +194 -0
- package/dist/shared/plugin-host/manifest.js +52 -0
- package/dist/shared/plugin-host/manifest.js.map +1 -0
- package/dist/shared/plugin-host/ui-kit-surface.d.ts +22 -0
- package/dist/shared/plugin-host/ui-kit-surface.js +25 -0
- package/dist/shared/plugin-host/ui-kit-surface.js.map +1 -0
- package/dist/shared/types.d.ts +5 -0
- package/package.json +18 -3
- package/dist/client/assets/channel-D5gzBvo7.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CT-amIxa.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CT-amIxa.js +0 -1
- package/dist/client/assets/index-DyAnw7YN.js +0 -798
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-szm_LIuD.js +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M33 plugin loader — the single mechanism that turns workspace-declared npm
|
|
3
|
+
* packages into registered host capabilities, run identically from every entry
|
|
4
|
+
* point (server, `c4s`, `c4s-mcp`, `c4s-reader`).
|
|
5
|
+
*
|
|
6
|
+
* Four steps, per package, each isolated in its own try/catch so a single bad
|
|
7
|
+
* plugin is skipped — never crashing the process:
|
|
8
|
+
* 1. Dynamic import — `await import(pkg)` (native ESM).
|
|
9
|
+
* 2. Manifest extraction — `mod.manifest` or `mod.default`.
|
|
10
|
+
* 3. Validation gate — hostApiVersion range + engines.node.
|
|
11
|
+
* 4. Registration — `registry.registerPlugin(manifest)`.
|
|
12
|
+
*/
|
|
13
|
+
import type { PluginManifest } from '../../../shared/plugin-host/manifest.js';
|
|
14
|
+
import { type PluginMigrationInfo } from '../../../shared/plugin-host/host-api.js';
|
|
15
|
+
import type { PluginRegistry } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* `incompatible` (M33) is distinct from `skipped`: it means the package
|
|
18
|
+
* was built against an incompatible MAJOR Host API and carries a `migration`
|
|
19
|
+
* descriptor (a repair path), whereas `skipped` is an environment problem (an
|
|
20
|
+
* `engines` miss) with no migration path.
|
|
21
|
+
*/
|
|
22
|
+
export type PluginLoadStatus = 'loaded' | 'skipped' | 'incompatible' | 'failed';
|
|
23
|
+
export type PluginLoadCode = 'PLUGIN_HOST_API_MISMATCH' | 'PLUGIN_ENGINE_UNSATISFIED' | 'PLUGIN_IMPORT_FAILED' | 'PLUGIN_INVALID_MANIFEST' | 'PLUGIN_TYPE_CONFLICT' | 'PLUGIN_PROJECT_UNTRUSTED';
|
|
24
|
+
/** Which layer a record belongs to — base (workspace/npm) vs overlay (project-local). */
|
|
25
|
+
export type PluginLayer = 'base' | 'overlay';
|
|
26
|
+
/**
|
|
27
|
+
* Per-package outcome. Adds `layer` (base/overlay), `trust`, `origin`
|
|
28
|
+
* (project-local source path), and `shadows`/`shadowedTypes` — all optional so
|
|
29
|
+
* base records keep their shape.
|
|
30
|
+
*/
|
|
31
|
+
export interface PluginLoadRecord {
|
|
32
|
+
/** Source identifier: the npm package name, or a synthetic id for built-ins. */
|
|
33
|
+
package: string;
|
|
34
|
+
status: PluginLoadStatus;
|
|
35
|
+
/** Machine code for skipped/failed packages. */
|
|
36
|
+
code?: PluginLoadCode;
|
|
37
|
+
/** Human-readable explanation for skipped/failed packages. */
|
|
38
|
+
reason?: string;
|
|
39
|
+
manifestName?: string;
|
|
40
|
+
manifestVersion?: string;
|
|
41
|
+
/** Entity types this package contributed (only when `loaded`). */
|
|
42
|
+
contributedTypes?: string[];
|
|
43
|
+
/** Which layer this record came from (base/overlay). */
|
|
44
|
+
layer?: PluginLayer;
|
|
45
|
+
/** Trust state of the project-local layer (overlay only). */
|
|
46
|
+
trust?: 'trusted' | 'untrusted';
|
|
47
|
+
/** Source path under `<cwd>/.claude4spec/plugins/` (overlay only). */
|
|
48
|
+
origin?: string;
|
|
49
|
+
/**
|
|
50
|
+
* M33: present on `incompatible` records — the repair path (target
|
|
51
|
+
* Host API version, applicable migration descriptors, shim availability).
|
|
52
|
+
*/
|
|
53
|
+
migration?: PluginMigrationInfo;
|
|
54
|
+
}
|
|
55
|
+
export interface PluginLoadResult {
|
|
56
|
+
records: PluginLoadRecord[];
|
|
57
|
+
}
|
|
58
|
+
/** Module importer — overridable in tests; defaults to native dynamic import. */
|
|
59
|
+
export type PluginImporter = (specifier: string) => Promise<unknown>;
|
|
60
|
+
/** Pull the `PluginManifest` off a freshly-imported module namespace. Shared by
|
|
61
|
+
* the workspace loader and the project-local overlay loader. */
|
|
62
|
+
export declare function extractManifest(mod: unknown): PluginManifest | null;
|
|
63
|
+
/** A structurally-valid manifest carries at least string `name` + `hostApiVersion`. */
|
|
64
|
+
export declare function isValidManifestShape(manifest: PluginManifest | null): manifest is PluginManifest;
|
|
65
|
+
/**
|
|
66
|
+
* Outcome of the compatibility gate. `status` lets the caller record an
|
|
67
|
+
* `incompatible` (major Host API mismatch — carries a `migration` repair path)
|
|
68
|
+
* distinctly from a `skipped` (host-api same-major miss, or an `engines` miss —
|
|
69
|
+
* environment problems with no migration path).
|
|
70
|
+
*/
|
|
71
|
+
export interface GateResult {
|
|
72
|
+
status: 'skipped' | 'incompatible';
|
|
73
|
+
code: PluginLoadCode;
|
|
74
|
+
reason: string;
|
|
75
|
+
migration?: PluginMigrationInfo;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Compatibility gate shared by all layers: hostApiVersion range + engines.node.
|
|
79
|
+
* Returns `null` when the manifest may register; otherwise the gate result.
|
|
80
|
+
* A MAJOR Host API mismatch → `incompatible` + a migration descriptor; an
|
|
81
|
+
* `engines` miss (or a same-major host-api miss) → `skipped`.
|
|
82
|
+
*/
|
|
83
|
+
export declare function gateManifest(manifest: PluginManifest): GateResult | null;
|
|
84
|
+
/**
|
|
85
|
+
* Load and register the given workspace plugin packages onto `registry`.
|
|
86
|
+
* Returns one record per package for the diagnostics route. Never throws.
|
|
87
|
+
*/
|
|
88
|
+
export declare function loadWorkspacePlugins(registry: PluginRegistry, packageNames: string[], importer?: PluginImporter): Promise<PluginLoadResult>;
|
|
89
|
+
/** Seams for `reloadPlugin` — overridable in tests. */
|
|
90
|
+
export interface ReloadPluginOptions {
|
|
91
|
+
importer?: PluginImporter;
|
|
92
|
+
resolveEntry?: (pkg: string) => string | null;
|
|
93
|
+
cacheBust?: (entry: string) => string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* M33 — hot-reload pipeline for ONE base (workspace/npm) package.
|
|
97
|
+
*
|
|
98
|
+
* Atomicity: the failure modes the brief names "old stays" — import failure,
|
|
99
|
+
* missing manifest export, incompatible major — are all checked BEFORE any
|
|
100
|
+
* teardown, so the previously-registered version remains registered and the
|
|
101
|
+
* caller surfaces a warning. Only once a fresh, compatible manifest is in hand
|
|
102
|
+
* do we tear the old version down (`unregisterPlugin` → its `onUnregister`) and
|
|
103
|
+
* register the new one — the brief's "onUnregister old, then register new".
|
|
104
|
+
*
|
|
105
|
+
* Returns the per-package record (`loaded` / `skipped` / `failed`). Never throws.
|
|
106
|
+
*/
|
|
107
|
+
export declare function reloadPlugin(registry: PluginRegistry, pkg: string, opts?: ReloadPluginOptions): Promise<PluginLoadRecord>;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M33 plugin loader — the single mechanism that turns workspace-declared npm
|
|
3
|
+
* packages into registered host capabilities, run identically from every entry
|
|
4
|
+
* point (server, `c4s`, `c4s-mcp`, `c4s-reader`).
|
|
5
|
+
*
|
|
6
|
+
* Four steps, per package, each isolated in its own try/catch so a single bad
|
|
7
|
+
* plugin is skipped — never crashing the process:
|
|
8
|
+
* 1. Dynamic import — `await import(pkg)` (native ESM).
|
|
9
|
+
* 2. Manifest extraction — `mod.manifest` or `mod.default`.
|
|
10
|
+
* 3. Validation gate — hostApiVersion range + engines.node.
|
|
11
|
+
* 4. Registration — `registry.registerPlugin(manifest)`.
|
|
12
|
+
*/
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import { pathToFileURL } from 'node:url';
|
|
15
|
+
import semver from 'semver';
|
|
16
|
+
import { HOST_API_VERSION } from '../../../shared/plugin-host/manifest.js';
|
|
17
|
+
import { buildMigrationInfo } from '../../../shared/plugin-host/host-api.js';
|
|
18
|
+
import { entryCacheBust } from './cache-bust.js';
|
|
19
|
+
const defaultImporter = (specifier) => import(specifier);
|
|
20
|
+
/** Pull the `PluginManifest` off a freshly-imported module namespace. Shared by
|
|
21
|
+
* the workspace loader and the project-local overlay loader. */
|
|
22
|
+
export function extractManifest(mod) {
|
|
23
|
+
if (mod == null || typeof mod !== 'object')
|
|
24
|
+
return null;
|
|
25
|
+
const ns = mod;
|
|
26
|
+
const candidate = (ns.manifest ?? ns.default);
|
|
27
|
+
if (candidate == null || typeof candidate !== 'object')
|
|
28
|
+
return null;
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
31
|
+
/** A structurally-valid manifest carries at least string `name` + `hostApiVersion`. */
|
|
32
|
+
export function isValidManifestShape(manifest) {
|
|
33
|
+
return (manifest != null &&
|
|
34
|
+
typeof manifest.name === 'string' &&
|
|
35
|
+
typeof manifest.hostApiVersion === 'string');
|
|
36
|
+
}
|
|
37
|
+
/** engines.node satisfied by the running node? Missing constraint = satisfied. */
|
|
38
|
+
function enginesSatisfied(manifest) {
|
|
39
|
+
const node = manifest.engines?.node;
|
|
40
|
+
if (!node)
|
|
41
|
+
return true;
|
|
42
|
+
return semver.satisfies(process.versions.node, node);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Compatibility gate shared by all layers: hostApiVersion range + engines.node.
|
|
46
|
+
* Returns `null` when the manifest may register; otherwise the gate result.
|
|
47
|
+
* A MAJOR Host API mismatch → `incompatible` + a migration descriptor; an
|
|
48
|
+
* `engines` miss (or a same-major host-api miss) → `skipped`.
|
|
49
|
+
*/
|
|
50
|
+
export function gateManifest(manifest) {
|
|
51
|
+
if (!semver.satisfies(HOST_API_VERSION, manifest.hostApiVersion)) {
|
|
52
|
+
const migration = buildMigrationInfo(manifest.hostApiVersion);
|
|
53
|
+
return {
|
|
54
|
+
status: migration ? 'incompatible' : 'skipped',
|
|
55
|
+
code: 'PLUGIN_HOST_API_MISMATCH',
|
|
56
|
+
reason: `host API ${HOST_API_VERSION} does not satisfy plugin requirement "${manifest.hostApiVersion}"`,
|
|
57
|
+
migration: migration ?? undefined,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (!enginesSatisfied(manifest)) {
|
|
61
|
+
return {
|
|
62
|
+
status: 'skipped',
|
|
63
|
+
code: 'PLUGIN_ENGINE_UNSATISFIED',
|
|
64
|
+
reason: `node ${process.versions.node} does not satisfy engines.node "${manifest.engines?.node}"`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Load and register the given workspace plugin packages onto `registry`.
|
|
71
|
+
* Returns one record per package for the diagnostics route. Never throws.
|
|
72
|
+
*/
|
|
73
|
+
export async function loadWorkspacePlugins(registry, packageNames, importer = defaultImporter) {
|
|
74
|
+
const records = [];
|
|
75
|
+
for (const pkg of packageNames) {
|
|
76
|
+
let mod;
|
|
77
|
+
try {
|
|
78
|
+
mod = await importer(pkg);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const reason = err.message;
|
|
82
|
+
console.warn(`[plugin-loader] PLUGIN_IMPORT_FAILED ${pkg}: ${reason}`);
|
|
83
|
+
records.push({ package: pkg, status: 'failed', code: 'PLUGIN_IMPORT_FAILED', reason });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const manifest = extractManifest(mod);
|
|
87
|
+
if (!isValidManifestShape(manifest)) {
|
|
88
|
+
const reason = 'package does not export a valid PluginManifest (manifest/default)';
|
|
89
|
+
console.warn(`[plugin-loader] PLUGIN_INVALID_MANIFEST ${pkg}: ${reason}`);
|
|
90
|
+
records.push({ package: pkg, status: 'failed', code: 'PLUGIN_INVALID_MANIFEST', reason });
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const base = {
|
|
94
|
+
package: pkg,
|
|
95
|
+
status: 'loaded',
|
|
96
|
+
layer: 'base',
|
|
97
|
+
manifestName: manifest.name,
|
|
98
|
+
manifestVersion: manifest.version,
|
|
99
|
+
};
|
|
100
|
+
const gate = gateManifest(manifest);
|
|
101
|
+
if (gate) {
|
|
102
|
+
console.warn(`[plugin-loader] ${gate.code} ${pkg}: ${gate.reason}`);
|
|
103
|
+
records.push({
|
|
104
|
+
...base,
|
|
105
|
+
status: gate.status,
|
|
106
|
+
code: gate.code,
|
|
107
|
+
reason: gate.reason,
|
|
108
|
+
migration: gate.migration,
|
|
109
|
+
});
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
registry.registerPlugin(manifest);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
const reason = err.message;
|
|
117
|
+
console.warn(`[plugin-loader] PLUGIN_INVALID_MANIFEST ${pkg}: ${reason}`);
|
|
118
|
+
records.push({ ...base, status: 'failed', code: 'PLUGIN_INVALID_MANIFEST', reason });
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
records.push({
|
|
122
|
+
...base,
|
|
123
|
+
contributedTypes: (manifest.contributes.entities ?? []).map((e) => e.type),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return { records };
|
|
127
|
+
}
|
|
128
|
+
/** Resolve a base package's main entry to an absolute path (cache-bust + watch). */
|
|
129
|
+
function resolveBaseEntry(pkg) {
|
|
130
|
+
try {
|
|
131
|
+
return createRequire(import.meta.url).resolve(pkg);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* M33 — hot-reload pipeline for ONE base (workspace/npm) package.
|
|
139
|
+
*
|
|
140
|
+
* Atomicity: the failure modes the brief names "old stays" — import failure,
|
|
141
|
+
* missing manifest export, incompatible major — are all checked BEFORE any
|
|
142
|
+
* teardown, so the previously-registered version remains registered and the
|
|
143
|
+
* caller surfaces a warning. Only once a fresh, compatible manifest is in hand
|
|
144
|
+
* do we tear the old version down (`unregisterPlugin` → its `onUnregister`) and
|
|
145
|
+
* register the new one — the brief's "onUnregister old, then register new".
|
|
146
|
+
*
|
|
147
|
+
* Returns the per-package record (`loaded` / `skipped` / `failed`). Never throws.
|
|
148
|
+
*/
|
|
149
|
+
export async function reloadPlugin(registry, pkg, opts = {}) {
|
|
150
|
+
const importer = opts.importer ?? defaultImporter;
|
|
151
|
+
const resolveEntry = opts.resolveEntry ?? resolveBaseEntry;
|
|
152
|
+
const cacheBust = opts.cacheBust ?? entryCacheBust;
|
|
153
|
+
const base = { package: pkg, status: 'loaded', layer: 'base' };
|
|
154
|
+
const entry = resolveEntry(pkg);
|
|
155
|
+
const specifier = entry ? pathToFileURL(entry).href + cacheBust(entry) : pkg;
|
|
156
|
+
let mod;
|
|
157
|
+
try {
|
|
158
|
+
mod = await importer(specifier);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
const reason = err.message;
|
|
162
|
+
console.warn(`[plugin-loader] reload PLUGIN_IMPORT_FAILED ${pkg}: ${reason} (old version retained)`);
|
|
163
|
+
return { ...base, status: 'failed', code: 'PLUGIN_IMPORT_FAILED', reason };
|
|
164
|
+
}
|
|
165
|
+
const manifest = extractManifest(mod);
|
|
166
|
+
if (!isValidManifestShape(manifest)) {
|
|
167
|
+
const reason = 'package does not export a valid PluginManifest (manifest/default)';
|
|
168
|
+
console.warn(`[plugin-loader] reload PLUGIN_INVALID_MANIFEST ${pkg}: ${reason} (old version retained)`);
|
|
169
|
+
return { ...base, status: 'failed', code: 'PLUGIN_INVALID_MANIFEST', reason };
|
|
170
|
+
}
|
|
171
|
+
const named = { ...base, manifestName: manifest.name, manifestVersion: manifest.version };
|
|
172
|
+
const gate = gateManifest(manifest);
|
|
173
|
+
if (gate) {
|
|
174
|
+
console.warn(`[plugin-loader] reload ${gate.code} ${pkg}: ${gate.reason} (old version retained)`);
|
|
175
|
+
return { ...named, status: gate.status, code: gate.code, reason: gate.reason, migration: gate.migration };
|
|
176
|
+
}
|
|
177
|
+
// Atomicity: validate + lower the NEW manifest BEFORE tearing the old one
|
|
178
|
+
// down, so a structurally-broken new version leaves the old one in place
|
|
179
|
+
// (parity with the import/gate failures above — "old stays").
|
|
180
|
+
try {
|
|
181
|
+
registry.validatePlugin(manifest);
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
const reason = err.message;
|
|
185
|
+
console.warn(`[plugin-loader] reload PLUGIN_INVALID_MANIFEST ${pkg}: ${reason} (old version retained)`);
|
|
186
|
+
return { ...named, status: 'failed', code: 'PLUGIN_INVALID_MANIFEST', reason };
|
|
187
|
+
}
|
|
188
|
+
// Fresh, compatible, valid: tear the old version down, then register the new.
|
|
189
|
+
registry.unregisterPlugin(manifest.name);
|
|
190
|
+
registry.registerPlugin(manifest);
|
|
191
|
+
return {
|
|
192
|
+
...named,
|
|
193
|
+
contributedTypes: (manifest.contributes.entities ?? []).map((e) => e.type),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../../src/server/core/plugin-host/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M33: lower a runtime plugin's authoring shape (`EntityContribution`) into the
|
|
3
|
+
* internal `BackendModule` the host already understands. This keeps
|
|
4
|
+
* `mountBackend` / `MountContext` / `ProjectPluginHost` 100% unchanged — the
|
|
5
|
+
* manifest is purely an authoring envelope, reconciled here.
|
|
6
|
+
*
|
|
7
|
+
* Two backend shapes are supported:
|
|
8
|
+
* - `backend.mount` (full power) — passes through as the `BackendModule` mount.
|
|
9
|
+
* - `backend.routes` (sugar) — a pre-built express Router; synthesized into
|
|
10
|
+
* `mount = (ctx) => ctx.app.use(pathPrefix, routes)`. No MCP server, no entity
|
|
11
|
+
* service, no migrations beyond what is declared.
|
|
12
|
+
*/
|
|
13
|
+
import type { EntityContribution, WritingStyleContribution } from '../../../shared/plugin-host/manifest.js';
|
|
14
|
+
import type { BackendModule } from './types.js';
|
|
15
|
+
/** Thrown when a contribution is structurally invalid. Caught per-package by the loader. */
|
|
16
|
+
export declare class PluginManifestError extends Error {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validate one writing-style contribution (M15). Mirrors the SKILL.md
|
|
21
|
+
* frontmatter checks in skill-registry so a plugin style is held to the same
|
|
22
|
+
* shape as a file-authored one. Throws `PluginManifestError` (caught per-package
|
|
23
|
+
* by the loader) on any structural problem.
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateWritingStyle(c: WritingStyleContribution): WritingStyleContribution;
|
|
26
|
+
/**
|
|
27
|
+
* Convert one `EntityContribution` (shared authoring shape with `unknown`
|
|
28
|
+
* server payloads) into a fully-typed `BackendModule`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function lowerEntityContribution(c: EntityContribution): BackendModule;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M33: lower a runtime plugin's authoring shape (`EntityContribution`) into the
|
|
3
|
+
* internal `BackendModule` the host already understands. This keeps
|
|
4
|
+
* `mountBackend` / `MountContext` / `ProjectPluginHost` 100% unchanged — the
|
|
5
|
+
* manifest is purely an authoring envelope, reconciled here.
|
|
6
|
+
*
|
|
7
|
+
* Two backend shapes are supported:
|
|
8
|
+
* - `backend.mount` (full power) — passes through as the `BackendModule` mount.
|
|
9
|
+
* - `backend.routes` (sugar) — a pre-built express Router; synthesized into
|
|
10
|
+
* `mount = (ctx) => ctx.app.use(pathPrefix, routes)`. No MCP server, no entity
|
|
11
|
+
* service, no migrations beyond what is declared.
|
|
12
|
+
*/
|
|
13
|
+
/** Thrown when a contribution is structurally invalid. Caught per-package by the loader. */
|
|
14
|
+
export class PluginManifestError extends Error {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'PluginManifestError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate one writing-style contribution (M15). Mirrors the SKILL.md
|
|
22
|
+
* frontmatter checks in skill-registry so a plugin style is held to the same
|
|
23
|
+
* shape as a file-authored one. Throws `PluginManifestError` (caught per-package
|
|
24
|
+
* by the loader) on any structural problem.
|
|
25
|
+
*/
|
|
26
|
+
export function validateWritingStyle(c) {
|
|
27
|
+
if (!c || typeof c !== 'object') {
|
|
28
|
+
throw new PluginManifestError('writingStyle contribution must be an object');
|
|
29
|
+
}
|
|
30
|
+
if (typeof c.slug !== 'string' || c.slug.length === 0) {
|
|
31
|
+
throw new PluginManifestError('writingStyle — slug must be a non-empty string');
|
|
32
|
+
}
|
|
33
|
+
if (typeof c.title !== 'string' || c.title.length === 0) {
|
|
34
|
+
throw new PluginManifestError(`writingStyle "${c.slug}" — title must be a non-empty string`);
|
|
35
|
+
}
|
|
36
|
+
if (typeof c.description !== 'string' || c.description.length === 0) {
|
|
37
|
+
throw new PluginManifestError(`writingStyle "${c.slug}" — description must be a non-empty string`);
|
|
38
|
+
}
|
|
39
|
+
if (typeof c.version !== 'number' || !Number.isInteger(c.version) || c.version < 1) {
|
|
40
|
+
throw new PluginManifestError(`writingStyle "${c.slug}" — version must be a positive integer`);
|
|
41
|
+
}
|
|
42
|
+
if (c.language !== 'en' && c.language !== 'pl') {
|
|
43
|
+
throw new PluginManifestError(`writingStyle "${c.slug}" — language must be 'en' or 'pl'`);
|
|
44
|
+
}
|
|
45
|
+
if (typeof c.content !== 'string') {
|
|
46
|
+
throw new PluginManifestError(`writingStyle "${c.slug}" — content must be a string`);
|
|
47
|
+
}
|
|
48
|
+
return c;
|
|
49
|
+
}
|
|
50
|
+
const MANIFEST_FIELDS = [
|
|
51
|
+
'type',
|
|
52
|
+
'table',
|
|
53
|
+
'label',
|
|
54
|
+
'labelPlural',
|
|
55
|
+
'displayOrder',
|
|
56
|
+
'slugFrom',
|
|
57
|
+
'pathPrefix',
|
|
58
|
+
];
|
|
59
|
+
function assertContribution(c) {
|
|
60
|
+
if (!c || typeof c !== 'object') {
|
|
61
|
+
throw new PluginManifestError('entity contribution must be an object');
|
|
62
|
+
}
|
|
63
|
+
const record = c;
|
|
64
|
+
for (const f of MANIFEST_FIELDS) {
|
|
65
|
+
if (record[f] == null) {
|
|
66
|
+
throw new PluginManifestError(`entity "${c.type ?? '?'}" missing required field "${f}"`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (typeof c.slugFrom !== 'function') {
|
|
70
|
+
throw new PluginManifestError(`entity "${c.type}" — slugFrom must be a function`);
|
|
71
|
+
}
|
|
72
|
+
if (c.serializer == null) {
|
|
73
|
+
throw new PluginManifestError(`entity "${c.type}" — serializer is required`);
|
|
74
|
+
}
|
|
75
|
+
if (c.systemPrompt == null) {
|
|
76
|
+
throw new PluginManifestError(`entity "${c.type}" — systemPrompt is required`);
|
|
77
|
+
}
|
|
78
|
+
const backend = c.backend;
|
|
79
|
+
if (backend != null && typeof backend !== 'object') {
|
|
80
|
+
throw new PluginManifestError(`entity "${c.type}" — backend must be an object`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Convert one `EntityContribution` (shared authoring shape with `unknown`
|
|
85
|
+
* server payloads) into a fully-typed `BackendModule`.
|
|
86
|
+
*/
|
|
87
|
+
export function lowerEntityContribution(c) {
|
|
88
|
+
assertContribution(c);
|
|
89
|
+
const backend = c.backend;
|
|
90
|
+
let backendSlot;
|
|
91
|
+
if (backend) {
|
|
92
|
+
const migrations = backend.migrations;
|
|
93
|
+
let mount = backend.mount;
|
|
94
|
+
if (!mount && backend.routes != null) {
|
|
95
|
+
const routes = backend.routes;
|
|
96
|
+
const pathPrefix = c.pathPrefix;
|
|
97
|
+
mount = (ctx) => {
|
|
98
|
+
ctx.app.use(pathPrefix, routes);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (mount && typeof mount !== 'function') {
|
|
102
|
+
throw new PluginManifestError(`entity "${c.type}" — backend.mount must be a function`);
|
|
103
|
+
}
|
|
104
|
+
backendSlot = { migrations, mount };
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
type: c.type,
|
|
108
|
+
table: c.table,
|
|
109
|
+
label: c.label,
|
|
110
|
+
labelPlural: c.labelPlural,
|
|
111
|
+
displayOrder: c.displayOrder,
|
|
112
|
+
slugFrom: c.slugFrom,
|
|
113
|
+
pathPrefix: c.pathPrefix,
|
|
114
|
+
serializer: c.serializer,
|
|
115
|
+
systemPrompt: c.systemPrompt,
|
|
116
|
+
backend: backendSlot,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=manifest-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-adapter.js","sourceRoot":"","sources":["../../../../src/server/core/plugin-host/manifest-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,4FAA4F;AAC5F,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAA2B;IAC9D,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,mBAAmB,CAAC,6CAA6C,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,mBAAmB,CAAC,gDAAgD,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,IAAI,sCAAsC,CAAC,CAAC;IAC/F,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,IAAI,4CAA4C,CAAC,CAAC;IACrG,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,IAAI,wCAAwC,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC/C,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,IAAI,mCAAmC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,IAAI,8BAA8B,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,eAAe,GAAG;IACtB,MAAM;IACN,OAAO;IACP,OAAO;IACP,aAAa;IACb,cAAc;IACd,UAAU;IACV,YAAY;CACJ,CAAC;AAEX,SAAS,kBAAkB,CAAC,CAAqB;IAC/C,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,mBAAmB,CAAC,uCAAuC,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,MAAM,GAAG,CAAuC,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QAChC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YACtB,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,GAAG,6BAA6B,CAAC,GAAG,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,iCAAiC,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,4BAA4B,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,8BAA8B,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;IAC1B,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACnD,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,+BAA+B,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAqB;IAC3D,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAEtB,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;IAC1B,IAAI,WAAqC,CAAC;IAE1C,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,OAAO,CAAC,UAAwC,CAAC;QACpE,IAAI,KAAK,GAAG,OAAO,CAAC,KAAkC,CAAC;QAEvD,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAgB,CAAC;YACxC,MAAM,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;YAChC,KAAK,GAAG,CAAC,GAAiB,EAAQ,EAAE;gBAClC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAClC,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YACzC,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,sCAAsC,CAAC,CAAC;QACzF,CAAC;QAED,WAAW,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACtC,CAAC;IAED,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,UAAU,EAAE,CAAC,CAAC,UAAuC;QACrD,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,OAAO,EAAE,WAAW;KACrB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M33 — project-local plugin overlay loader.
|
|
3
|
+
*
|
|
4
|
+
* The second of the two M33 tracks (the first being the process-global
|
|
5
|
+
* `loadWorkspacePlugins`). This one loads plugins committed into a repo at
|
|
6
|
+
* `<cwd>/.claude4spec/plugins/<pkg>/` and builds a per-`ProjectContext`
|
|
7
|
+
* `ProjectPluginOverlay`. Because a `git clone` brings this code with it,
|
|
8
|
+
* loading is gated by `trustProjectPlugins` — the CALLER decides trust and only
|
|
9
|
+
* invokes `loadProjectOverlay` when trusted; `enumerateOverlayPackages` is the
|
|
10
|
+
* code-free probe used to drive the trust prompt.
|
|
11
|
+
*
|
|
12
|
+
* Per package, each step is isolated in its own try/catch so one bad plugin is
|
|
13
|
+
* skipped — never failing the project build:
|
|
14
|
+
* 1. Resolve entry — package.json main/module/exports, else index.{js,mjs}.
|
|
15
|
+
* 2. Dynamic import — `import(pathToFileURL(entry))` (native ESM).
|
|
16
|
+
* 3. Validate+gate — shared with the workspace loader (hostApiVersion+engines).
|
|
17
|
+
* 4. Lower entities — `lowerEntityContribution`, enforcing within-overlay
|
|
18
|
+
* type uniqueness (second duplicate → PLUGIN_TYPE_CONFLICT, rejected).
|
|
19
|
+
*/
|
|
20
|
+
import { type PluginLoadRecord } from './loader.js';
|
|
21
|
+
import type { ProjectPluginOverlay } from './types.js';
|
|
22
|
+
import type { WritingStyleContribution } from '../../../shared/plugin-host/manifest.js';
|
|
23
|
+
/** Importer seam — overridable in tests; defaults to native dynamic import. */
|
|
24
|
+
export type PluginImporter = (specifier: string) => Promise<unknown>;
|
|
25
|
+
export interface ProjectOverlayResult {
|
|
26
|
+
/** The overlay, or `undefined` when no loadable project-local module exists. */
|
|
27
|
+
overlay: ProjectPluginOverlay | undefined;
|
|
28
|
+
/** Per-package diagnostics for the per-project `/_meta/plugins` route. */
|
|
29
|
+
records: PluginLoadRecord[];
|
|
30
|
+
/** M15: trusted project-local writing styles, pushed into SkillRegistry. */
|
|
31
|
+
writingStyles: WritingStyleContribution[];
|
|
32
|
+
/** Best-effort detach of imported project-local modules (see dispose note). */
|
|
33
|
+
dispose: () => void;
|
|
34
|
+
}
|
|
35
|
+
/** Absolute path to a project's local plugins directory. */
|
|
36
|
+
export declare function projectPluginsDir(cwd: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Package directory names under `<cwd>/.claude4spec/plugins/`. Pure FS read — no
|
|
39
|
+
* code runs — so it is safe to call before the trust decision (drives the prompt
|
|
40
|
+
* and the untrusted-layer diagnostics).
|
|
41
|
+
*/
|
|
42
|
+
export declare function enumerateOverlayPackages(cwd: string): string[];
|
|
43
|
+
/** True when the project ships at least one local plugin package. */
|
|
44
|
+
export declare function hasProjectPlugins(cwd: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a package.json `exports` field to a relative entry path. Handles the
|
|
47
|
+
* common shapes: a bare string, the `"."` subpath, and a conditions object
|
|
48
|
+
* (`{ import, default, require, node }`) at either the top level or under `"."`.
|
|
49
|
+
* Returns the first string match (preferring ESM `import`/`default`), or
|
|
50
|
+
* undefined if no string entry is reachable (caller falls back to module/main).
|
|
51
|
+
* Exported so the workspace-tier frontend resolver reuses the same condition
|
|
52
|
+
* handling for a plugin's `exports['./frontend']` (see `frontend-assets.ts`).
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveExportsEntry(exp: unknown): string | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Load and validate the trusted project-local overlay for `cwd`. The caller must
|
|
57
|
+
* have already confirmed `trustProjectPlugins === true`; this function executes
|
|
58
|
+
* project-committed code.
|
|
59
|
+
*/
|
|
60
|
+
export declare function loadProjectOverlay(cwd: string, importer?: PluginImporter): Promise<ProjectOverlayResult>;
|