{"_id":"@coralwisdom/coral-extension","_rev":"10-640bf335d01335a3c301fa171df9bd5f","name":"@coralwisdom/coral-extension","dist-tags":{"latest":"0.1.10"},"versions":{"0.1.0":{"name":"@coralwisdom/coral-extension","version":"0.1.0","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.0","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"05f42bb37ed4998970f6571ec1f6c59b57038c2f","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.0.tgz","fileCount":5,"integrity":"sha512-6+CKiEhohvGhjJ904Jv/W5qeRurECWQWUkp0sSm7JOgqY/V9JWU3bLbALX8SDL+ddcOERzmhuzGU1SqubktlIA==","signatures":[{"sig":"MEUCIEkBwy+r+yOZ3gYESq853jl3zYfz7D+a1iLtWpI7A3zBAiEArlikppMhnUPnHKHrWfXDIE0QJ71i5oRmAE7bFUdJZpk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21296},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"7db4b0c0c35edfe0824f132a9212af5c9857737e","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.0_1787056148245_0.07621668138607207","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@coralwisdom/coral-extension","version":"0.1.1","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.1","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"97b25afa5391e79fd107be1415122e8e290d699a","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.1.tgz","fileCount":5,"integrity":"sha512-Xm6/BMoxYTprvMTn7mnbmmqbmzmR27hoOUF+1kDbhrE2Vv9HOw8lFCDCFiUHJlEwk9bngLxPrMkDQK/G0NVFGw==","signatures":[{"sig":"MEUCIA8zthaN+WnlIX0sGpZpC0oxu7cfNHAEA9wJrP6NPv17AiEA/dnKPcGgKX/PpflFm3EVSu5FiQwSYFNwJ1Hue37ok7s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIG/ZNSWThExCrj66jLg1+Uy7eDNFx4COh9gQlJL/VqQiAiBL6mpuuG53hSr7ZGL9q2AKGrmQ8HTICTMwmk96ILTkww==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23635},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"de338d110219c0472a1af57f17a35b053e5cb2f8","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.1_1787924306901_0.011653959918543899","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@coralwisdom/coral-extension","version":"0.1.2","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.2","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"9f48018be1d5c0c210d841a1e5fd6e6ff0c339e5","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.2.tgz","fileCount":5,"integrity":"sha512-XuxN1jEj/yan22BagFSgajaC7U22d35lQcIU1Yl6OXZzAGDcxZyZLlusDnUixQUk4VxLhZ/uWZq5yfEXupApGw==","signatures":[{"sig":"MEQCICqUHKYEZrNJD1evPk8pMiH2F87vfgLjAPtYCPd73dmlAiARmgs2wiEhvNQYfnUUgOj5fIkhjEHwJHwsfNW15bn08g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIFJT/MMpm9DilrJD5GhKjfLd3d9OY5FjiDhYs9b7ezDRAiEAnhCp20mmnZV6HIdzLh8NdXbw3vmUI5kM7UK4hnu9oRQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":24319},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"178ab1dede21fda63971051638b17167ba17c689","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.2_1787992262249_0.2817272824823145","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@coralwisdom/coral-extension","version":"0.1.4","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.4","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"5b02b4c8379ad78a10398d4173d61eab1377b07f","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.4.tgz","fileCount":5,"integrity":"sha512-JKKpgXapfAY3QPH4tqAXT/W7TH1ykH8BxCWSBQLAqXvCl5gpa25u+MgBwZdCe0n7vGzSuw9O20Mm3lXPopi/lA==","signatures":[{"sig":"MEYCIQDooGUM/WL0AIz5zrKiH6xJmKbCL43qk3rW1+YZ6adCugIhAKm7cWDHHcOl06JBq17A4AUWab78c9c98XBoRxPi0AvU","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICJ0k/kJqDEkgJpSEIHnEfeAwZRQNHD/EBw3jZfsZiJkAiEAgUHmotF4IOSEyNMGImNqGlHYuQA0BVhjA7UjvuxNV0g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35754},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a7e8c62f47938583a82bba87642992714a1d817f","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.4_1788177360351_0.4521619252156439","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@coralwisdom/coral-extension","version":"0.1.5","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.5","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"3ad90fd835fb5939137d4a23f509a7bcbd61b635","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.5.tgz","fileCount":5,"integrity":"sha512-SINnh8TwxagiDIQhIE49gNR5TzomZDow8I5wRxOhyCdM+rhKsR9oy/tlnsf+Gb+S9cSUe0Qx28a+z4LOz5uUTg==","signatures":[{"sig":"MEUCIDM0qVZwyQPVvfsD+hLys8FuLX5Fm9905QD1wPDuhkhXAiEA2LI8/A/UwwbL8IZXO9k9ZKdCD7gvSC8CxYqeN2X6xGs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHj4bvVn0zNH0CqRAqRus0QhP7oSEvIaR/BjzeNu3dDiAiEAxvY0CTNAYELwJBRRIKsCx02Ehm6hXWnZWKMbzZ1yfys=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38755},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a7e8c62f47938583a82bba87642992714a1d817f","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.5_1788251140149_0.5549191889146032","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@coralwisdom/coral-extension","version":"0.1.6","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.6","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"dab6f2757ef043f1becfd9c2822cc6537c45ca54","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.6.tgz","fileCount":5,"integrity":"sha512-mWMmsR+zaTGPDb48tUa4TJ++4LwPfJekRVp7WSc8lltpzoE9AMpsBHCDe6CnbWw4ZJrDz6xlBqurCfAmr7sgrA==","signatures":[{"sig":"MEYCIQD3xP6b4P3y8y6rIMQ3i3EJd/vlEsIZge2Pgj8A7c6/QwIhALaEy5fngPSGuNt68csve4zDHytKXt2R78stuus9cvyk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDU3NUHqzuMXpCJxVtQiWySHglnfa6xzMWP97Po1ik4vAIhAL/SuNdOOkSZuOnVa4ViW/T3BU69NZFmoB7sg/LZ2sC2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":39268},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a7e8c62f47938583a82bba87642992714a1d817f","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.6_1788340903153_0.21344228403457577","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@coralwisdom/coral-extension","version":"0.1.7","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.7","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"19f55fecb5cb4c808f3411ca45e9e0c6c7c06ed1","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.7.tgz","fileCount":5,"integrity":"sha512-VKrDI/T2Te1SthROgVms7zsNiLDsdjlZzvMP/UjEEXTqs/rV8NQ0ZjYUaIW7m6JJmveJiQQpmcFUN+q6Wp4tFQ==","signatures":[{"sig":"MEQCIHEQD0f+woyYC9QpAoH6ECOwX6USgDgsOXGEGBfbTfCYAiAYgTyK7+4VbKlQjT8KXyUWoT4w891673UuAuIXqQzqag==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIC6wUidVAn31WS8Rg7xCqlRLQCgLqYknizCzgOoue/XjAiEA3+EcfQJRbJqpLpe0VEHhvzsuNy7gHTM4RmUv1F5S1qg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40794},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"7cca00e38d8606ef0d0fe95ded4dcb70ba0ecc2f","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.7_1788349015473_0.6948211448146322","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@coralwisdom/coral-extension","version":"0.1.8","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.8","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"c2a06c3937039875879aa7800e88b789da9988c4","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.8.tgz","fileCount":5,"integrity":"sha512-qZUhan+xsJKYxb0SfOzBD4jDvLVqouJETKWOYcm+9gccGxC4qRZh6K/EDd6avPKpTTJghc+AwTCNfrfFQTjV7Q==","signatures":[{"sig":"MEQCIDga1K353wNUXnh+957g2M02h64hmBbRqsQkoOGPAz0ZAiAVxgChNd/JDUtdDmwh3Zo3t5453YvYuQFTF3Y+qhhmhg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEcJReYg2wTJ+CPeWWZS6/+/kH1ZJkpMfYja3H+5ccJLAiAthi2wEJ9r/vl0G1iXZyhHJ7VyqFCTrk/VGxy8W52GJA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49571},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"477aae6c0f7c767b7d77e747603ff806fe0a883f","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.8_1788857547356_0.9595561457344526","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@coralwisdom/coral-extension","version":"0.1.9","license":"UNLICENSED","_id":"@coralwisdom/coral-extension@0.1.9","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"fde11065fbbb4b0d4fa439547f90e3c268a3315a","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.9.tgz","fileCount":5,"integrity":"sha512-lzyvhZuKGnjKVq0Z2J2fgfkOqZ+gO56fa2ap5bYzv3dlnkhbSjhyzFvFTopqSgkFH3Tbnfe+qqKgW/NU4ocfCg==","signatures":[{"sig":"MEUCIQCYX8f6SQnf44Z6fpWVrsSRiZ06aDg8c9ARHRRfWWrqggIgHXDvMYdMYguaCE2a6EUPpJDsCm5CsUC8hUNVgEwRGcY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIATTKiu0PGXhqBc1oSlAcLXEDS87JzfY9XTSHWTlEEfEAiEAnN2Ee0vRm4GRrHgFKktXmgZthVc5xma1HEu0rVwQtlM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49571},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"477aae6c0f7c767b7d77e747603ff806fe0a883f","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"tmp":"tmp/coral-extension_0.1.9_1788857738428_0.060801423344991834","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"_id":"@coralwisdom/coral-extension@0.1.10","bin":{"coral-extension":"bin/coral-extension.mjs"},"dist":{"shasum":"573d0dc07df99862515dff013a44f1ae16815fd8","tarball":"https://registry.npmjs.org/@coralwisdom/coral-extension/-/coral-extension-0.1.10.tgz","fileCount":5,"integrity":"sha512-ad/Uw6bc2YCXFKO2or64uLmTMSN7EShqY+oE45RLwOt9FrT++DLwk9S/hSLRjjL3PL3fSYPyvenlXZN1n9hu3w==","signatures":[{"sig":"MEUCIGN7QOB+Z+24vAWASKwtZxojehwrjWHg96kXL+ENDwfsAiEArLwZCR05KfrrDsoPON0KC6jjuf9jdb4eCZ26CTQongo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAlgB6UgscZHTvFSB3NHGs9tb7nH15b3wimmen5RUm5JAiEAjC6W4Q7N1zlOIsMVXRPEsoocQD5tsedwXwMvSdpjeCI="}],"unpackedSize":49598},"main":"./dist/index.js","name":"@coralwisdom/coral-extension","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"fe66dcab02b18f60d548fad50174e82f53e0598f","license":"UNLICENSED","scripts":{"build":"tsc -p tsconfig.json","pack:plugin":"node ./bin/coral-extension.mjs pack"},"version":"0.1.10","_npmUser":{"name":"long_bot","email":"long_bot@sina.com"},"_npmVersion":"10.9.3","description":"职阅桌面插件开发 SDK","directories":{},"maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"_nodeVersion":"22.18.0","dependencies":{"jszip":"3.10.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/coral-extension_0.1.10_1789451446103_0.8019598578017675"}}},"time":{"created":"2026-08-18T12:29:08.088Z","modified":"2026-09-15T05:50:46.349Z","0.1.0":"2026-08-18T12:29:08.392Z","0.1.1":"2026-08-28T13:38:26.986Z","0.1.2":"2026-08-29T08:31:02.347Z","0.1.4":"2026-08-31T11:56:00.411Z","0.1.5":"2026-09-01T08:25:40.320Z","0.1.6":"2026-09-02T09:21:43.238Z","0.1.7":"2026-09-02T11:36:55.553Z","0.1.8":"2026-09-08T08:52:27.451Z","0.1.9":"2026-09-08T08:55:38.552Z","0.1.10":"2026-09-15T05:50:46.198Z"},"license":"UNLICENSED","description":"职阅桌面插件开发 SDK","maintainers":[{"name":"long_bot","email":"long_bot@sina.com"}],"readme":"# Coral 插件开发指南\n\n`@coralwisdom/coral-extension` 是职阅桌面插件 SDK。插件以独立的 Node.js Utility Process 运行，通过依赖注入访问 Coral 服务，并向职阅工作区提供 HTML 视图。\n\n本文描述一个插件从创建、运行、调试、打包到安装的完整流程。仓库中的可运行示例位于 [`plugins/hello-plugin`](../../../plugins/hello-plugin)。工作区视图是标准的 React 前端：宿主提供挂载节点和构建后的浏览器 bundle，插件在 iframe 中使用 `createRoot`、hooks、状态和异步接口。\n\n## 1. 先了解运行模型\n\n一个插件由三部分组成：\n\n1. `manifest.json` 描述插件身份、职阅版本要求、权限和界面扩展点。\n2. `main` 指向构建后的 CommonJS `.cjs` 入口。职阅启动 Utility Process 后加载这个文件并调用 `activate(context)`。\n3. `WorkspaceService` 注册视图 provider。职阅请求视图时调用 `render(context)`，provider 返回 React 挂载节点。宿主随后读取 manifest 中 `workspaceViews[].entry` 指向的浏览器 bundle，在 iframe 中执行它。主题和语言由宿主文档提供，数据和认证能力通过 SDK 请求。\n\n插件不能直接访问职阅渲染进程、Electron 对象或宿主内部模块。所有宿主能力都通过 `context.services.get(...)` 获取。\n\n## 2. 环境要求\n\n- Node.js 20 或更高版本\n- npm 10 或更高版本\n- 已安装职阅桌面客户端\n- 能够执行 `npm install` 的网络环境\n\n入口必须构建为自包含的 CommonJS `.cjs` 文件。职阅不会直接执行 TypeScript、TSX 或未构建的 JavaScript 源文件。\n\n## 3. 创建插件目录\n\n建议从以下结构开始：\n\n```text\nhello-plugin/\n├── assets/\n│   └── hello.svg\n├── dist/\n│   ├── extension.cjs\n│   └── hello.main.js\n├── scripts/\n│   └── start.mjs\n├── src/\n│   ├── extension.tsx\n│   └── views/\n│       ├── HelloPluginView.tsx\n│       └── entry.tsx\n├── manifest.json\n├── package.json\n├── package-lock.json\n└── tsconfig.json\n```\n\n| 路径 | 必需 | 用途 |\n| --- | --- | --- |\n| `manifest.json` | 是 | 运行时元数据、权限和扩展点声明 |\n| `src/` | 是（开发命令要求） | TypeScript/React 源码 |\n| `dist/` | 是（构建后） | `main` 指向的 `.cjs` 文件和 `workspaceViews[].entry` 指向的浏览器 bundle |\n| `assets/` | 按需 | 导航图标等静态资源 |\n| `scripts/start.mjs` | 否 | 启动开发宿主的项目脚本 |\n\n`manifest.json` 必须位于插件根目录，不能放在 `src/` 或 `dist/` 中。\n\n## 4. 配置 package.json\n\n下面是与示例一致的 React + TypeScript 配置。SDK 版本应与实际发布版本一致：\n\n```json\n{\n  \"name\": \"zhiyue-hello-plugin\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"npm run typecheck && esbuild src/extension.tsx --bundle --platform=node --format=cjs --outfile=dist/extension.cjs && esbuild src/views/entry.tsx --bundle --platform=browser --format=iife --outfile=dist/hello.main.js\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"dev\": \"coral-extension dev\",\n    \"start\": \"node scripts/start.mjs\",\n    \"pack\": \"coral-extension pack\"\n  },\n  \"dependencies\": {\n    \"@coralwisdom/coral-extension\": \"^0.1.0\",\n    \"react\": \"19.2.6\",\n    \"react-dom\": \"19.2.6\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"19.2.7\",\n    \"@types/react-dom\": \"19.2.3\",\n    \"esbuild\": \"^0.25.0\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n```\n\n安装依赖并生成 lock 文件：\n\n```bash\nnpm install\n```\n\n`build` 会先执行严格类型检查，再分别生成 Utility Process 入口 `dist/extension.cjs` 和浏览器端 React bundle（例如 `dist/hello.main.js`）。安装包不需要携带 `node_modules`。\n\n## 5. 配置 tsconfig.json\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"jsx\": \"react-jsx\",\n    \"strict\": true,\n    \"noEmit\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src\"]\n}\n```\n\n`noEmit` 保证 TypeScript 只做类型检查；真正的产物由 esbuild 生成。插件代码应保持严格类型，读取存储值后必须先判断类型再使用。\n\n## 6. 编写 manifest.json\n\n当前 schema 只有 `1`，并且 manifest 使用严格字段校验：不能添加未定义字段，也不能遗漏必填字段。\n\n```json\n{\n  \"schemaVersion\": 1,\n  \"id\": \"com.zhiyue.hello\",\n  \"name\": \"职阅示例插件\",\n  \"version\": \"1.0.0\",\n  \"engines\": {\n    \"zhiyue\": \"^3.0.0\"\n  },\n  \"main\": \"dist/extension.cjs\",\n  \"permissions\": [\"http\"],\n  \"contributes\": {\n    \"navigationItems\": [\n      {\n        \"id\": \"hello\",\n        \"title\": \"示例插件\",\n        \"icon\": \"assets/hello.svg\",\n        \"order\": 100,\n        \"workspaceView\": \"hello.main\"\n      }\n    ],\n    \"workspaceViews\": [\n      {\n        \"id\": \"hello.main\",\n        \"title\": \"示例插件\",\n      \"type\": \"webview\",\n      \"entry\": \"dist/hello.main.js\"\n      }\n    ]\n  }\n}\n```\n\n字段规则：\n\n| 字段 | 规则 |\n| --- | --- |\n| `schemaVersion` | 必须是数字 `1` |\n| `id` | 全局唯一；只允许小写字母、数字、`.`、`-`，且必须以小写字母或数字开头 |\n| `name` | 非空显示名称 |\n| `version` | 使用 `x.y.z`，例如 `1.2.0` |\n| `engines.zhiyue` | 使用 `^x.y.z`，例如 `^3.0.0`；职阅主版本必须相同，当前版本不得低于声明的最低版本 |\n| `main` | 插件目录内的相对路径，必须以 `.cjs` 结尾 |\n| `permissions` | 只能填写 `storage`、`commands`、`http`；未使用的权限不要申请 |\n\n`contributes.navigationItems` 中每项必须包含 `id`、`title`、`icon`、整数 `order`、`workspaceView`。`contributes.workspaceViews` 中每项必须包含 `id`、`title`、`type`、`entry`，其中 `type` 只能是 `webview`，`entry` 必须指向插件目录内的浏览器 bundle。导航项的 `workspaceView` 必须引用已声明的视图 ID。\n\n`contributes.commands` 为可选字段。提供时必须是数组，数组中的每项必须包含非空的 `command` 和 `title`。\n\n图标支持 `svg`、`png`、`jpg`、`jpeg`、`webp`。图标和入口路径都必须留在插件目录内，不能使用绝对路径、`..` 或符号链接。\n\n## 7. 编写插件入口\n\n推荐使用 `defineExtension` 导出默认扩展模块：\n\n```tsx\nimport {\n  WorkspaceService,\n  defineExtension,\n} from '@coralwisdom/coral-extension';\n\nexport default defineExtension({\n  activate(context) {\n    const workspace = context.services.get(WorkspaceService);\n\n    context.subscriptions.add(\n      workspace.registerViewProvider('hello.main', {\n        render(_context) {\n          return '<div id=\"root\"></div>';\n        },\n      }),\n    );\n  },\n});\n```\n\n`activate` 可以同步返回，也可以返回 `Promise<void>`。注册的每个 disposable 都必须加入 `context.subscriptions`，宿主结束插件进程时会按逆序释放它们。也可以导出 `deactivate()` 做异步清理；资源释放仍应优先通过 disposable 完成。\n\n## 8. 编写工作区视图\n\n视图 provider 的唯一契约是：\n\n```ts\ntype WorkspaceViewRenderContext = {\n  readonly locale: 'zh' | 'en';\n  readonly action?: { type: string; payload?: Record<string, string | number | boolean | null> };\n};\n\ntype WorkspaceViewProvider = {\n  render(context: WorkspaceViewRenderContext): Promise<string> | string;\n};\n```\n\nprovider 只负责返回前端的挂载节点：\n\n```tsx\nexport function HelloPluginView() {\n  return (\n    <main>\n      <h1>职阅示例插件</h1>\n      <p>插件已经通过依赖注入注册了中间工作区视图。</p>\n    </main>\n  );\n}\n```\n\n浏览器入口（例如 `src/views/entry.tsx`）负责挂载 React：\n\n```tsx\nimport { createRoot } from 'react-dom/client';\nimport { HelloPluginView } from './HelloPluginView';\n\nconst root = document.getElementById('root');\nif (!root) throw new Error('插件视图缺少 root 节点');\ncreateRoot(root).render(<HelloPluginView />);\n```\n\n组件可以正常使用 `useState`、`useEffect`、事件处理器和异步接口。语言和主题由宿主写入文档，也可以在 bundle 中通过 `getPluginLocale()`、`getPluginTheme()` 获取；颜色使用宿主注入的 `var(--...)` 变量。通过 `requestHttp()` 发起的请求必须传入完整的 `http` 或 `https` URL，默认会自动附加当前会话和企业上下文，也可通过 `withCredentials: false` 请求第三方公共接口；使用该能力必须在 manifest 中声明 `http` 权限。`render(context)` 必须返回非空 HTML，否则宿主会将视图标记为渲染失败。\n\n## 9. Coral 服务和权限\n\n### WorkspaceService\n\n注册一个已经在 manifest 中声明的视图。每个视图只能注册一次：\n\n```ts\nconst workspace = context.services.get(WorkspaceService);\nconst disposable = workspace.registerViewProvider('hello.main', {\n    render: ({ locale }) =>\n    locale === 'zh' ? '<main>你好</main>' : '<main>Hello</main>',\n});\ncontext.subscriptions.add(disposable);\n```\n\n### ThemeService\n\n在视图 `render` 期间获取当前已解析的主题：\n\n```ts\nconst theme = context.services.get(ThemeService).getTheme();\n```\n\n浏览器 bundle 使用 `getPluginTheme()` 获取同一个主题；组件不需要接收 `theme` prop。\n\n插件视图文档会自动获得以下壳主题变量：\n\n```css\nvar(--bg-app)\nvar(--bg-sidebar)\nvar(--bg-sidebar-rail)\nvar(--bg-titlebar)\nvar(--bg-panel)\nvar(--bg-modal)\nvar(--bg-modal-nav)\nvar(--bg-card)\nvar(--bg-hover)\nvar(--bg-active)\nvar(--bg-block)\nvar(--bg-input)\nvar(--bg-input-deep)\nvar(--bg-overlay)\nvar(--bg-surface)\nvar(--bg-elevated)\nvar(--bg-selected)\nvar(--bg-disabled)\nvar(--border)\nvar(--border-subtle)\nvar(--border-strong)\nvar(--border-focus)\nvar(--context-menu-bg)\nvar(--scrollbar-thumb)\nvar(--scrollbar-thumb-hover)\nvar(--tab-hover-bg)\nvar(--tab-active-bg)\nvar(--tab-active-border)\nvar(--header-border)\nvar(--section-border)\nvar(--btn-hover-bg)\nvar(--btn-hover-bg-lg)\nvar(--project-row-active-bg)\nvar(--sidebar-header-border)\nvar(--section-header-hover-bg)\nvar(--text-primary)\nvar(--text-secondary)\nvar(--text-tertiary)\nvar(--text-muted)\nvar(--text-disabled)\nvar(--text-inverse)\nvar(--text-link)\nvar(--text-title)\nvar(--text-list)\nvar(--accent)\nvar(--accent-color)\nvar(--accent-hover)\nvar(--accent-bg)\nvar(--accent-text)\nvar(--accent-subtle)\nvar(--accent-active)\nvar(--success)\nvar(--success-hover)\nvar(--success-bg)\nvar(--success-text)\nvar(--warning)\nvar(--warning-hover)\nvar(--warning-bg)\nvar(--warning-text)\nvar(--danger)\nvar(--danger-hover)\nvar(--danger-bg)\nvar(--danger-text)\nvar(--info)\nvar(--info-bg)\nvar(--info-text)\nvar(--error)\nvar(--focus-ring)\nvar(--close-btn-bg)\nvar(--close-btn-bg-hover)\nvar(--action-btn-bg)\nvar(--action-btn-bg-hover)\nvar(--action-btn-border)\nvar(--font-family)\nvar(--font-mono)\nvar(--font-size-xs)\nvar(--font-size-sm)\nvar(--font-size-md)\nvar(--font-size-lg)\nvar(--font-size-xl)\nvar(--font-size-2xl)\nvar(--font-weight-regular)\nvar(--font-weight-medium)\nvar(--font-weight-semibold)\nvar(--font-weight-bold)\nvar(--line-height-tight)\nvar(--line-height-normal)\nvar(--line-height-relaxed)\nvar(--spacing-1)\nvar(--spacing-2)\nvar(--spacing-3)\nvar(--spacing-4)\nvar(--spacing-5)\nvar(--spacing-6)\nvar(--radius-xs)\nvar(--radius-sm)\nvar(--radius-md)\nvar(--radius-lg)\nvar(--radius-pill)\nvar(--shadow-sm)\nvar(--shadow-md)\nvar(--shadow-lg)\nvar(--duration-fast)\nvar(--duration-normal)\nvar(--duration-slow)\nvar(--ease-standard)\nvar(--control-height-sm)\nvar(--control-height-md)\nvar(--control-height-lg)\nvar(--icon-size-sm)\nvar(--icon-size-md)\nvar(--icon-size-lg)\nvar(--opacity-disabled)\nvar(--opacity-muted)\nvar(--z-index-dropdown)\nvar(--z-index-modal)\nvar(--z-index-toast)\n```\n\n变量按颜色、排版、间距、圆角、阴影和动效分组，足以覆盖插件常见的页面、表单、列表、卡片、弹窗、状态提示和交互反馈。颜色值以壳当前 WorkVista、Chat 和终端面板样式中已经使用的值为准，主题契约与壳切换时同步更新。插件不得覆盖这些全局变量，也不得为明暗主题复制一套颜色值；插件只允许增加带有插件前缀的局部变量。\n\n推荐写法：\n\n```css\n.plugin-card {\n  padding: var(--spacing-4);\n  color: var(--text-primary);\n  background: var(--bg-surface);\n  border: 1px solid var(--border-subtle);\n  border-radius: var(--radius-md);\n  box-shadow: var(--shadow-sm);\n  transition: background var(--duration-normal) var(--ease-standard);\n}\n\n.plugin-card:hover {\n  background: var(--bg-hover);\n}\n```\n\n### AuthService\n\n在视图 `render` 期间获取当前登录用户的 token 和企业上下文：\n\n```ts\nconst auth = await context.services.get(AuthService).getContext();\n// auth.accessToken, auth.tenantUuid, auth.organizationUuid\n```\n\n浏览器插件视图可以直接获取当前用户信息：\n\n```ts\nimport { requestUserInfo } from '@coralwisdom/coral-extension';\n\nconst member = await requestUserInfo();\n// 返回 /bff/iam-ui/members/me 的完整成员数据，例如 memberUuid、avatar 等字段\n```\n\n浏览器 bundle 不直接读取令牌，使用 `requestHttp()` 即可让宿主代理完成认证请求。\n\n### StorageService\n\n用于保存插件自己的 JSON 数据：\n\n```ts\nconst storage = context.services.get(StorageService);\nconst raw = storage.get('settings');\nif (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) {\n  // 在这里按业务字段读取 raw\n}\nstorage.set('settings', { theme: 'light' });\n```\n\n必须在 manifest 中写入 `\"permissions\": [\"storage\"]`。数据保存在插件目录下的 `.storage.json`，`get` 的返回类型是 `unknown`，只允许写入 JSON 可序列化值。不要保存密码、令牌或其他敏感信息。\n\n### HttpService 与浏览器请求\n\n浏览器 bundle 使用 SDK 的 `requestHttp()`：\n\n```tsx\nimport { requestHttp } from '@coralwisdom/coral-extension';\n\nconst response = await requestHttp<ProjectPage>({\n  method: 'GET',\n  url: 'https://app.shanhuyun.cn/bff/ab-project',\n  params: { page: 1, limit: 20 },\n});\n```\n\n#### 1. 认证与第三方公共接口 (`withCredentials`)\n- **默认企业认证请求**（`withCredentials: true`）：职阅代理负责自动注入访问令牌（`Authorization: Bearer <token>`）、`tenantUuid` 和 `organizationUuid`，插件无需也不应手动传递这些鉴权信息；\n- **第三方公共接口请求**（`withCredentials: false`）：当需要请求外部开放 API、第三方微服务或自建公共接口时，可指定 `withCredentials: false`。此时职阅代理**不会注入**任何内部 Token、租户或组织头，并设置 `credentials: 'omit'` **禁止携带 Cookie**，同时允许在未登录或无企业上下文的状态下发起请求。\n\n```tsx\n// 请求第三方公共接口（免 Token、Cookie 和租户信息）\nconst zenResponse = await requestHttp<string>({\n  method: 'GET',\n  url: 'https://api.github.com/zen',\n  withCredentials: false,\n});\n```\n\n#### 2. 支持 FormData 与 Blob / 二进制\n`requestHttp` 原生支持上传与接收复杂二进制数据：\n- **上传 FormData**：`body` 可直接传入浏览器原生 `FormData`，SDK 会自动解析为二进制并生成带正确 boundary 的 `multipart/form-data` 头；\n- **上传 Blob / ArrayBuffer**：`body` 支持传入 `Blob`、`ArrayBuffer` 或 `Uint8Array`；\n- **接收 Blob / 二进制**：通过设置 `responseType: 'blob'` 或 `'arraybuffer'`，响应中的 `response.data` 会直接转换为对应的原生对象。\n\n```tsx\n// 上传 FormData 示例\nconst formData = new FormData();\nformData.append('title', '示例附件');\nformData.append('file', new Blob(['Hello Coral'], { type: 'text/plain' }), 'hello.txt');\n\nawait requestHttp({\n  method: 'POST',\n  url: 'https://example.com/api/upload',\n  body: formData,\n  withCredentials: false,\n});\n\n// 下载文件并获取 Blob 示例\nconst imageResponse = await requestHttp<Blob>({\n  method: 'GET',\n  url: 'https://example.com/images/logo.png',\n  responseType: 'blob',\n  withCredentials: false,\n});\nconst previewUrl = URL.createObjectURL(imageResponse.data);\n```\n\n#### 3. 桌面端网络代理\nHTTP 代理走桌面端 Electron 原生 Chromium 网络栈，自动遵从操作系统的系统代理设置（HTTP / HTTPS / SOCKS 代理）、系统 PAC 脚本以及客户端配置的会话代理。\n\n#### 4. 安全防护与限制\n- **SSRF 防护**：通过 DNS 解析拦截所有私有网段（`10.x`、`172.16-31.x`、`192.168.x`、`fc00::/7`）、回环地址（`127.0.0.1`、`::1`、`localhost`）以及云厂商元数据地址（`169.254.169.254`、`fe80::/10`）；\n- **重定向安全控制**：限制最大重定向次数为 5 次，每次跳转的目标地址均会重新执行 SSRF 拦截校验，跨源跳转自动清除认证凭证；\n- **超时与体积防护**：支持 `timeoutMs` 参数（默认 30 秒），超时自动中断；支持 `maxResponseBytes`（默认 50MB），流式读取超限时立即终止以防内存溢出。\n\n### CommandsService\n\n用于在插件进程内注册和调用命令：\n\n```ts\nimport { CommandsService } from '@coralwisdom/coral-extension';\n\nconst commands = context.services.get(CommandsService);\ncontext.subscriptions.add(\n  commands.registerCommand('hello.reset', (reason: unknown) => {\n    if (typeof reason !== 'string') {\n      throw new Error('reason 必须是字符串');\n    }\n    return `reset: ${reason}`;\n  }),\n);\n\nconst result = await commands.executeCommand('hello.reset', 'manual');\nif (typeof result !== 'string') {\n  throw new Error('命令返回值必须是字符串');\n}\n```\n\n必须在 manifest 中声明 `commands` 权限。命令只能由插件进程内的 `executeCommand` 调用，不会自动出现在职阅导航、按钮或全局命令面板中。重复注册命令或调用未注册命令会直接抛错。\n\n## 10. 本地开发和调试\n\n### 使用示例的 start 脚本\n\n在插件目录执行：\n\n```bash\nnpm run start\n```\n\n示例的 `scripts/start.mjs` 会调用 `coral-extension dev --host <职阅可执行文件>`。它会先构建插件、注册开发插件、监听 `src/` 并串行重建，然后启动带 `--coral-extension-dev=<插件 ID>` 参数的职阅。\n\nmacOS 默认使用 `/Applications/职阅.app/Contents/MacOS/职阅`，Windows 默认使用 `%LOCALAPPDATA%/Programs/职阅/职阅.exe`。自定义位置或 Linux 必须设置 `ZHIYUE_HOST`：\n\n```bash\nZHIYUE_HOST=\"/path/to/职阅\" npm run start\n```\n\nPowerShell：\n\n```powershell\n$env:ZHIYUE_HOST = 'C:\\path\\to\\职阅.exe'\nnpm run start\n```\n\n### 仅注册开发插件\n\n职阅已经运行时，可以执行：\n\n```bash\nnpm run dev\n```\n\n也可以直接传入宿主路径：\n\n```bash\nnpx coral-extension dev --host \"/path/to/职阅\"\n```\n\n开发命令会把绝对插件目录写入 `~/.zhiyue/.dev-plugins.json`。按 `Ctrl+C` 停止后会删除当前注册。开发插件 ID 不能与已安装插件重复。监听范围包括 `src/` 的构建输出、`dist/`、`manifest.json` 和 `assets/`；`.storage.json` 变化不会触发重载。\n\n## 11. 构建、打包和安装\n\n先检查类型并构建：\n\n```bash\nnpm run typecheck\nnpm run build\n```\n\n生成 `.cep`：\n\n```bash\nnpm run pack\n```\n\n指定输出文件：\n\n```bash\nnpm run pack -- ./release/hello.cep\n```\n\n打包器只收集 `manifest.json`、`dist/`、`assets/` 三个根路径，并检查入口和导航图标是否存在。安装包约束如下：\n\n- 压缩包文件小于 20 MB\n- 解压后文件总大小小于 50 MB\n- 文件数量不超过 500\n- 不允许符号链接\n\n在职阅左侧插件管理入口选择“安装插件”，选择 `.cep` 文件。正式安装前必须停止同 ID 的开发插件；安装包内不应出现 `node_modules`、`.storage.json`、源码地图或本地配置。\n\n## 12. 发布前检查清单\n\n1. `manifest.json` 位于插件根目录，且没有额外字段。\n2. `id` 全局唯一，`version` 使用 `x.y.z` 并已递增。\n3. `engines.zhiyue` 使用 `^x.y.z`，目标职阅版本满足要求。\n4. `main` 指向真实存在的 `dist/*.cjs`，入口导出 `activate`。\n5. 每个导航图标存在且扩展名受支持。\n6. 使用的每个服务都已声明对应权限。\n7. `npm run typecheck`、`npm run build`、`npm run pack` 全部通过。\n8. 在干净的职阅环境实际安装 `.cep`，打开导航项并渲染每个视图。\n9. 验证启停插件时 disposable 被释放，重复激活不会重复注册视图或命令。\n10. 检查压缩包内容、大小、文件数量和依赖来源。\n\n## 13. 常见错误\n\n### `manifest.json` 校验失败\n\n检查字段名是否完全匹配 schema。`manifest`、`engines`、`contributes`、导航项和工作区视图都不接受额外字段；`id`、路径和版本格式也必须符合上文规则。\n\n### 视图没有显示\n\n确认导航项的 `workspaceView`、`workspaceViews[].id`、`registerViewProvider()` 三处 ID 完全一致，并且 `activate()` 没有抛错。每个视图只能注册一个 provider。\n\n### `插件未声明 ... 权限`\n\n在 `permissions` 中加入实际使用的 `storage`、`commands` 或 `http`，然后重新构建并重启开发宿主。权限变更不会由旧进程自动生效。\n\n### `插件入口必须是 CommonJS .cjs 文件`\n\n确认 `manifest.main` 指向 `dist/extension.cjs`，并先执行 `npm run build`。不要把 `.ts`、`.tsx` 或 ESM 文件直接配置为入口。\n\n### `npm run start` 找不到职阅\n\n检查 `ZHIYUE_HOST` 是否指向可执行文件本身。macOS 应指向 `.app/Contents/MacOS/职阅`，不能指向 `.app` 目录。\n\n### 安装时提示 ID 冲突\n\n停止同 ID 的 `npm run dev`/`npm run start`，或卸载已有正式插件。开发插件和正式插件不能同时使用相同 ID。\n\n## 14. 安全边界\n\n- 插件运行在独立 Utility Process，不要依赖渲染进程对象或宿主私有模块路径。\n- 所有资源路径都使用插件目录内的相对路径。\n- 不要把用户凭据、访问令牌或个人数据写入 `.storage.json`。\n- 发布前固定依赖版本，审查 `dist/extension.cjs` 和 `.cep` 的实际内容。\n","readmeFilename":"README.md"}