fix(plugin-sdk): detect private type changes in API baseline (#120975)

* fix(plugin-sdk): hash private declaration dependencies

* chore(plugin-sdk): refresh API baseline
This commit is contained in:
Peter Steinberger
2026-08-09 00:52:34 -07:00
committed by GitHub
parent cc4cc83e36
commit e09b0ebfba
5 changed files with 671 additions and 225 deletions
+149 -149
View File
@@ -1,151 +1,151 @@
cada1ccdba113c813b6c012d4e119e2a67e23cf7015ebfd62403ed8e74d83cbd module/account-core
4c7a44c538a6856a0861300f05a5df16cb7805fbf1b22c5b772c0a6ad71c45ef module/account-helpers
cbf4e2c3088f8886a7c9ea91325a66e0f0846cea21f0b2891f36399b4811306c module/account-id
8e985f345f21a1c9a2b0e94304aaaad6a326bec1c1ce3b26027d2862804a366e module/account-resolution
e5e67ddf3cab38fcbf9220bc3160715897e2709d9a9ff6ff36f1ecc9453c2367 module/agent-config-primitives
74daa746deb548379d3f0d6eac3c4d082df1034c4360cc03bf51fee0f10a2e4d module/agent-harness
a43840ff36833daef61050fd801e825ec3ba806348b4fbe6c613f20a8807a5e7 module/agent-harness-runtime
5168648cd946abad8a92822889f13ceacc87ed502314a66190d0b1eb8ebe76ea module/agent-media-payload
e82bf122ca0787ec0bcdd12b669cfe24f07da16be1f4090e84c7d645b07ac79f module/agent-runtime
6d12eed0833b9f63b5cea9a763c470487c85c5a722a3a35ec1f5ce07dc8715a9 module/agent-scope-runtime
56b6d5fb6af3d95af1200065aca2e7d4f59e5fa59740505fe6ff433077ef6646 module/allow-from
55cea5390d68839ca7768b4a0cc570b17b65fa0fa3bc4d76130ef0f16cb79ede module/allowlist-config-edit
7ddd81bd5f55de9adf64bf4d92d012f24b37b6da0a72805a3a220d8feff24ca3 module/approval-auth-runtime
a973b03d88f2aa71d3b6c39241527c18d9b1b75f5639bf39cc9b080efbe7b6c6 module/approval-client-runtime
59af6c9bfddc98a0ad2cdc733c6f439f5aa2b14ee14267be81e68715f835bf29 module/approval-delivery-runtime
e26d5faba8bae937a29cb7a8864a1f6ad7e999dd55b47245973ba5fa2dbecae4 module/approval-gateway-runtime
aceab327f18983cfa074384b4510648be2156dfdd30415a2d7a48fd1f38da1c6 module/approval-handler-adapter-runtime
a453261fc6c0d45ad652992bfa3139a1295b6e6296878ee5fde2cf12b995516e module/approval-handler-runtime
dad0906b607cfc044805279c25f656b65579b92b458c8a7c248b7cc8e297d99b module/approval-native-runtime
22db78ca5d8bb308d4ea35fdf0027d6bb6b7ceff8b5737e5bbd651b252d87b5f module/approval-reply-runtime
f5017f6d734f068fd069e5a0611f5728a827bfe05a054389b169e64820b30e72 module/approval-runtime
d3add5597be9e422974496ed388dc0abf5d99941ff60b874d008beab1a1b8a0b module/account-core
1b9d38050a1de968515048d4ada89d5b9d686bd51be0f0c0cb8987a124bb59a7 module/account-helpers
71522995185b956a0cc4927a472cc8d1153e5e998874bfd9a750513175174713 module/account-id
1fe4f05f95e7b29cd81daf65c76fce5db229158c4ffcb8341b390c8ea2e63696 module/account-resolution
87714a883fa2d8c39db921b25992546ab07e23bb5c6bfe739c340d65a989db47 module/agent-config-primitives
a1062730b6e11a0af669590968c839ee5315c2bd2df829fad46a6237569cc0d3 module/agent-harness
2f26ff0e35f6255982f12cdd0facbd0cdb73c9c176fb0e2597b1e40581e55829 module/agent-harness-runtime
b39e78226063156e97da6189b34f1bf92dc07f4bc49a7f67e8dcc521dd878dac module/agent-media-payload
734d51410340183df3a1465d887786ffda6f3f73bcefe905a3ae9c92b85f4e67 module/agent-runtime
68040b4e24969a5d209097b982e1382c7d8bed48d1d1fd5ef5f20754064421e0 module/agent-scope-runtime
8fecb210e22bce4532b6ab649b09465f0bd2c857a44abf40db7d683d6491e6da module/allow-from
74f099da550f5c949541a529d716a7c39a0af7f183d51e433a8b433c98be59f1 module/allowlist-config-edit
8b7e61f1a86d511fd20a28822af13fafcc850d7e68a95d217d42605c13a572e4 module/approval-auth-runtime
e79039b7fae653bbb75c95a20571d0ac3cb508113cf2cb79f5d30ca566fa68ec module/approval-client-runtime
d69e1eaf278e2c913a3317c3fe3f591bfb9b0d331d07fbd3bfab2972e21e18cd module/approval-delivery-runtime
f02f81c3cf3fcaa3bc215b5a1e3ffc3c3c959f4ef8e53423344e3850329f9601 module/approval-gateway-runtime
c5a5a0736d0a999e1b7c8fa967f2d220b03c0c5d8ac30ec43cd0e5bb9b1e2962 module/approval-handler-adapter-runtime
1201987b2a51de1783ee03983f45c14aa5f8c350c427b4aaa6ae6c3287bedc90 module/approval-handler-runtime
796430a3a811d711a6f596984b95fda6a218813128096b3c1eac001944d4aaf7 module/approval-native-runtime
fe40c01e9b168c9b00426eb4febdc557d69d38082e092ca994589acfbb1ae99e module/approval-reply-runtime
06ca5134208844f05a7fb30f334dd4c6d329b9aaecd4baa6f366d4624e9b987f module/approval-runtime
01ca912836b8dec672f705e294f72d346e778557e4c591317d67558ea7669c0b module/archive
ad60ccc4fe9084d47f0477e02d9296bacad32f26d7456e2a84be8d25a53a25c2 module/boolean-param
6e3b8ccee738f8eddde5d813b6e204d6f7c8541fda4cb279a3be3ead27f47e7d module/channel-actions
00d326fdff396dfcc657d1fd16a4015b81d60ae8bf7dad09ac1010b376814de6 module/channel-config-helpers
16dc9d32e8ca3ef78fc63e0fc4b20e6b943633e9572de1a49d24a880b6ffc66c module/channel-config-primitives
c0f910ebfa3dbf283145fb1e3b9c016d03e853ef13e70402b09f3b9d9c2f4ab0 module/channel-config-schema
2dd98659d9600e755f09ef00dd91c36692b8562ed3700461937e94f6cd1e640a module/channel-contract
16d2565753d9b5023549480321c3a8d359b672f4203f1c103523489ce5ff121e module/channel-core
9a5aaf650f9242523bb57bdc2556c323ab64e55aa11e25e2685b73b23ee12534 module/channel-dm-policy
ba41c40956d6b4565605fa38c2d12f4b8471a0f8afe842798716b9032ee4d74a module/channel-entry-contract
982f29a18e07228e3da82cae67d06ff38249592a29c2fd28f01f0d2016ff80d9 module/channel-feedback
1d13edd07a8ae8e21ece6c542cb0cde22e5b6e11d3bb9b2bfaa5ebd2a5239bf8 module/channel-inbound
76bb7f531f3702c801e8fe7479e9e499f601fb361a4303afdcb45fc0da440e4b module/channel-inbound-debounce
df567ce2f4a4ba8a0937f825c46e83763412a724e36b72ce727dc4203c7dd134 module/channel-ingress-runtime
0e6efb79730fae59bb549ad00d9af2848c139b4bb1762e83b66886284e1c1421 module/channel-lifecycle
159d034b431d113f3a6dc41ec0bcadba2d6664051f158330b0e3dd3da8b5d42f module/channel-logging
3aaa573834c68f71490a0b0a8687cd942122cdca03d3b08781cf52220ab71544 module/channel-message
9182ed800c19f6324654dc62f0c78fc11e6a5ef18f4387284066e5b2104da848 module/channel-outbound
930beff13ed42a138f65164013c82f4f4c96422292c5fc634a5edee1dce71367 module/channel-pairing
ee4292b069d4d48cce4fc2dc26df5b5c87eb1fa4769f1f6be9a10c3e1221e1a9 module/channel-plugin-common
94ef57c8f6087fcaa56e59e493c391a04377ed03f23c681edd8d8f6e2d64e0da module/channel-policy
cc0a77137b304b27a313791aa30e43efb4acc254da7590bd47493d81e7104fba module/channel-reply-pipeline
bba5540be7cf9613a163663decdb2affe2af9bbd3ad7914989ab186f9c2abec1 module/channel-runtime-context
f3cee48527f5cddde81912a588e72947d40443322b716871a8d9e5dc0c37c542 module/channel-secret-basic-runtime
0ceb4378709eb2d92a62a275f87fa04e18f77df8f942a9a0acef81019ebc1e24 module/channel-secret-runtime
7c90157a95bc0523fc66b1f78ce140f7ec7dbf809dfa3a480244efc01f972754 module/channel-send-result
fb123c1b557ed2527e335f13c3d6de41ab0c3305151001cf2b1075d1da8034c5 module/channel-setup
aeac9bb8127faf636dde79772a577d9cb003660ef3d1df03ddf606101020c402 module/channel-status
d70ef71f48f9fe5dc01bf13ba3a2ba515322f81dc8f32d08528a113fbc78e30e module/channel-streaming
7f4714752b40f014605e2e7d46006b519972f81b528a286e1a40758493fdef5d module/channel-streaming-config
14f0103adb14627b662fbe9fdd5ed08596ed702a250853e8beb8bb8dd1361588 module/cli-argv
c89ec1b194b76f67a6f4dd108dccf460da6065646cba31374c8aa748f23a39e4 module/collection-runtime
391e6f0c77da2e17a058fc5aea87fd193830b2a14e12fae77c7f63b0226f0bb5 module/command-auth
7dede491d22f7226d955210befca09b32e955c59436c27500f0c7d1971ba07d5 module/command-auth-native
fa2df02bede6ed8843e5c2bd605c6ea5cd20313c305593fbd371dba6f1b931c3 module/command-detection
28a0cae8dee664aef14b1a64c86a46d0fb5637cf9f671790d4fc9ba205e42820 module/command-primitives-runtime
eb4c757fe0086c1dbfa4c3f3caf3dcff0d3cab3924c608237f08f740a6ee5f59 module/command-status
0ef109bca0630cab8578b6d1ad1eb0f92e76dc3995f4a180e34f03212d42f1e0 module/config-contracts
20f3f8042de53e4eee61b64de9102c8c202b9299e6a29235647a4729f70145f2 module/config-mutation
189fa5a240cad0404cd281ad0a14a105a8f3231278d87b71cfbc4f96fb8e48ef module/config-runtime
c1ea9510dfda047609a99d5d2cd1f1560f5d469a36e6b695766213d695c25b0f module/conversation-runtime
c85a82e8f37313cf2111ef6839a48cce6084efef8fd0c199c634fa400032765c module/core
4af19d59c2f18674e7d7f7dc1b358b644dc707e6bd601dc47168bd9e4a669940 module/dedupe-runtime
f70c93d28053ca2e8353e45e6515ce7acef188097c6117d1545965d0699c8004 module/device-bootstrap
68c726280f6585af96c071758ba383e55480b4fc913eae7c26aea1af331dedf3 module/diagnostic-runtime
ea81ef06956c1bc0853fa00afbbc2b5a4019116aaf8a436e1b27d06f7a2c9e88 module/directory-runtime
086bb46f97cb1f4a040b602444daf2c47ac2c24aca150a0d238933956a8100fc module/discord
f65408d85477bb362ebe6ed9148c1bb6b9eb7839733e5e3119f4ff8f1cfd0567 module/error-runtime
b013053a61e7d9be3d0c683c02baf57fa7e4393ec54e0df6a46ab0f2fe2348fd module/extension-shared
ceacad83db01c66e7be6aa21a291597020f13f737b697690eae7d47098e6499a module/gateway-method-runtime
8fa198fde6cb5f651caaa7349bc37992642ea827da6a4c52c94017a0e5dafd6a module/gateway-runtime
6062869202e3d7fdaa1f6801d6c1df7bf7406b8118cc4c7167ed409f5257b05c module/group-access
d117ebba8cc490501725778676a9d75855872b6e5fe2b2f64b1270d4808a2277 module/health
182dc685f2103ff66c1a4839a48f4f40d2eeb0070cd74e449b47aacc4e6f1c22 module/hook-runtime
f6e3c44e7d1090a97aca554a3c247219b8de78b3cb4399cac5efde8a0a6c1156 module/inbound-envelope
1d5ca69fcf2a8476a2309dcd830fc3bbae04b7029fa30eea1081b6590a789f10 module/inbound-event-delivery
36721c58f479fe9ca32737f67850f4607bf8753ef6b193ff129e7a9e5fdbc6bd module/inbound-reply-dispatch
03f7e1190d4101c486908383da099d545e59a6a90f5699b397c976ce6624c029 module/infra-runtime
2e717cccb3db127aed0287d4ea14c41a8e64e46d60c728638153e31e2fb0d296 module/ingress-effect-once
9389d91a090259f06e5ec2aae14c9857e45988d4edc4f91170cb8bc573b966a2 module/interactive-runtime
9dd66baf2def46386ad4706380e57f9068fa9bb3878be2d9ba961ec2f46d3d87 module/json-store
d8ca27a737f235e09f1a9f8cd4b82ac0cde96f10c662347b6ac82e27b70b4a40 module/lazy-runtime
fd00374a91ab5b393152bbbaf90010f9140cf15827bde360d0c6c8724ed34e2e module/logging-core
7670808d8c6227a52b2cddb72121aed9767313dd674f294a1f426dc185c13046 module/matrix
7c2c3ff80fce4cbd02e8976c7418d2da1be190832dd624e59bb30bbc12047755 module/media-local-roots
a5f59c9acbcaa3f82247bf806eb5ba08032373fb853719f0ec9457690f16fc70 module/media-mime
14e6c4c8471207a204710322e88ae2cda12b9e37c726f508f0da45e136262470 module/media-runtime
7a5a1de743fff9d5a86515b501ffd88e7fa49970c9f46a5153816e2ebaef7bb0 module/media-store
c5e3eb1a584f4b8126d9d6c177a840ec9103671e8d1242634ee67db9b5b9e573 module/media-understanding
2288d50521f3323c070a0b74b17e0e647f7ee0e422ccc12989a9ffb8eefacdd4 module/media-understanding-runtime
bebd2931dc51d67c063ff19fa1c278f8dcfe00ab23cfbd480d47329ea8e5088e module/meeting-runtime
ea56ea0455c62f292e1c7b3e56cac6eb3fea00e548f9ab2f4a69e0b41b0a2d96 module/memory-core-host-engine-foundation
00d6f8bc78256558972d431b7983d7b774e0a98d802a1eec533d2cae1e1f1986 module/memory-host-core
87b7a3206346c0d4b294fb3a2395cbaabc3e73ff8b1b9ea925bc3aade3e52687 module/messaging-targets
50e4001a5917b629b51e4d47857db57f01cf4a499f3b6be78ee99568ce7fd46e module/model-session-runtime
44655a08ce111a036c837b8d2e796cf0036941379ab317e5764c6c01e73b39f3 module/models-provider-runtime
55a7e1e57345726b2b54a4c71c66744d5559dd40a164ca552808b689306f53f8 module/native-command-config-runtime
1892da4151de02907448430a4661b8578295bb91638fa6c8d940d858d902876f module/native-command-registry
9470d8e08f7e1d2fe144a81da1b4a331b31a0c74d0c9a5f7cfaa15814e953ea2 module/param-readers
8d8c0c4ebfc6e0c6125df3ae64ec66c10cd797a325de5ea7869fcd84068ab290 module/persistent-dedupe
987648ebe317cc4d6c0505a52d344b12ce9c3a8261a5bd969cee3423c0c53529 module/plugin-config-runtime
f83dbe9460f793f5b57f6df1c208bdf99f272aff7fd9f5cda8e6b25b15bbff20 module/plugin-entry
c0894007b842d68f1dcf0ba6e9a61486d06ef820e78e194939b70a5a4b28e9cb module/plugin-runtime
de508df6d9cfa9d21c4524989dd8bd142fb60cb4ae980193e0907767d76e6022 module/provider-auth
71bebeac51e701cd7c8e63d22754b9bcbd82b024aced303aa055d229781129d7 module/provider-catalog-runtime
56151035047a69e6163d5578023d00f51a2413b777f3784af88e06261c039345 module/proxy-capture
cc3f586640ca1f1988de64ab2b6c9a119024a911a27289fdacfa0901d093c8fe module/question-gateway-runtime
2e09c3181e79e157ed5366b144d116ef8cc06023256ace3fa59b35c43cab513a module/reply-chunking
7994045066b29af1fc6b36ae32068f2a6f277195971af84701cb739cc23d0579 module/reply-dispatch-runtime
ac2b199e95c5c8b1e2a65e62bd41d1b6322e531bca294ef4979a297a12640bce module/reply-history
ad69a4a6970cfac86f9379efb927beac898217946d025c3aea55e6f399da08bb module/reply-payload
1f899eb54013f268d6698ce8e6943289ea0e872747e8e868259106829518db86 module/reply-runtime
b4043b356372f6af64ee3c26e4d6a6d623b817e4d95346358dc0e64a3b61d1e0 module/root-walk
011840eb45317373eefc8505a021c19ef47e7e7f4134c6e411a32ce120ca739f module/routing
ff6cca86f54f94f238205f5b122af36666314e0a380f3ec7f0ccb9ed9208df31 module/run-command
53b0295cec105696a1664c5c7f5576a7b55d197eb95dcd9185486f010bd53750 module/runtime
fcf103d18c1d64ffa9719f1d5a1ca349df3a6125d00c9d54a1b76c195ba8691b module/runtime-config-snapshot
b6b8edc50ecab8386c9acd8f374a207212b5a99c8f518538bbcf0c458dda3881 module/runtime-env
1b223b31f6f78d9eca4a07b92802e59684f24d7a1d040b83856ad165d0dd70fd module/runtime-group-policy
0d8f2c5f3a3325d7d190d2c395835f58ac57f1bea9b6fa516c6942b96d9bf605 module/runtime-store
aa8a411ad37c1d1143b67376bf2d20255b9eedff61d80815f42e4f8ed7bd8e58 module/secret-file
44adc2205f926172fcd3762ca8a96c1485beabcb1bef8b9acfd2233cefea2a6a module/secret-input
57dcb1462d4c4f9a98d934c4ca975b163d704758af9821a64001ff3ac05637c3 module/secret-input-runtime
dc0ee07d392a85c218939000b28c0138f139215da00f5592b34a68ba8e29a25d module/secret-ref-runtime
f97549081955e412d8eb64070c64bb5921bb1324744d824db05767d3adcce403 module/security-runtime
b18d65a8abbed79bcb77e34679b7aeb03f2e9101271f48298b47eb839c33a379 module/session-catalog
046b8f75735b5abeea15dde510f409e429b90f5220ee5c89275861f71fe19f55 module/session-discussion
f112bdabc51ba8659b37d0a6f6a32a2b1d471e5b49b56e108bf750ec55a7ea71 module/session-store-runtime
36affbe151431a6141664b6838e20f2d121ff210d57a3c1b4b41a8818b5c81d8 module/setup
21071e8c2ef020685aba09b5661e37e7415938ff6602053fa831ac9d58673248 module/setup-runtime
df263e722a36ffa168522fa739924bec6b4b122ac3f1e25497a30962bec30607 module/setup-tools
18e384ec43d9eaee52c8e286e127bda2048370e2337964a754d94b236724ca9e module/skill-commands-runtime
ae469f32799380e6b045abaefefee6eb3f00d714ffbf36b6eeef5025dc529472 module/speech-settings
92f8e3fe8b29fa5050f30bcc7a19f1085a590064d9e8b6ac54991e60a691a61e module/ssrf-policy
19c2ac7f81de3203ab91fc88793cf7e0b5bf4eaa2d5d61f4ee9e9f34e3f56be8 module/ssrf-runtime
ff35f9f74d35d37a2eb6126b57f3dc5a4d580b6222fe3a34c9368779ad32eab7 module/state-paths
44cc071d9ba2baa26d6f33ba9407867fb07c33384f49d3e3d5210232022c1b5f module/status-helpers
537047854c21ad20ea0572f8019503cbda3bbafece8194a28c30b0639bde2fde module/string-coerce-runtime
1b5b9a4532db991fce807ba736b550de27aa5f9de2e1f508a8f4f09cae76ea29 module/telegram-account
110944726884fca94f38c9c329b5950629438b9a719f4782c4beeade8bd67746 module/temp-path
0e230313a7a27a915a7aa399c0afd94c4c3e10d485c7b513e757f41bfc362dbe module/text-chunking
2a9971449c5e31c61a715e8ae2d99ac7453690f595c84f4daf85b640bb711689 module/text-runtime
a94c9ff59cc361b04f8731a47d722c4bc88cfabf942221369a8cb67bdcda7249 module/tool-plugin
89846974257b7551d46a514902998d0592fc67b1d8ce036c6514d7b9cd1bc159 module/tool-results
9d6ab352913a573b226e054e1dc8c6d088493aea9954950c65585923b5b6895a module/tool-send
541df9dea799f25e83ea483d481ecebc5b91c016effab593c54d3efe3ee6517b module/web-media
7c43c2cd0f09d72cf5f7cd7df582767e436acb697a81722dde47dbe171c66d2e module/webhook-ingress
af8c5e1c84ec9d365a7aa0d15eb63f0dd9e7b50526023e6212bba020c229f224 module/webhook-request-guards
1cc469eacda2818a116ab7b63847b9ddf86225e8d02e62fac48e618ba41a9852 module/widget-html
d7e53de63b0ac11a266e4abdc18ba6e9401b80309f5c8f5f6a72a00f65dfe3bd module/boolean-param
b234c18152ce7c204483f12b56432eaf628487a58985b45fad5a748efbe7102b module/channel-actions
5b1c747a84962082207d88d629dc8e32a1c71e5579fc50899dc9d0af25347415 module/channel-config-helpers
c2cc71d5070b6071c51248b0648d1ad1a9468d3737df890adc77ec02025e8853 module/channel-config-primitives
45af2c37b55888cd81115aa6837c3cc2ae5a73dd0173e982fff608bed8c3d607 module/channel-config-schema
a38cb34f477cdd6a1a0a664ddcfa8f0f2e1d5f1c30f7fb8bcff0aa3b5fb81a1c module/channel-contract
5167018e99f87bb5d921bdc7709bf05fb433470467f76f698954a366c0a30a8d module/channel-core
b0441683ed12ad0d1e3bd81124f9bfc492bfc8e3307bf1dc85068674e49419a6 module/channel-dm-policy
e3bc795de2eff64754072b7a062cba6b8cf3882b4e12cfc3f3de2cd694fdb18a module/channel-entry-contract
e348cf7e5d26ee4dc7f8de827834f7db5379a08aedc498b5ca899b3fdff497dc module/channel-feedback
90c98588542ed1875f0c26b579930ecb76ea2e8ecfc7815eae64f337d11c19c3 module/channel-inbound
3cd9fdf44a03bd23098a5106ada7b41dd0b4e69039051cbee5fc05965060f8e6 module/channel-inbound-debounce
cc0c189a754c91267948a74096f9617f7f53945f09751243070917961c71ab46 module/channel-ingress-runtime
4ef3dd0ac32f99659e17df55ce4dc1aeda9711ddca0df5508d1907fcb4d43f16 module/channel-lifecycle
0e47457e38d1df0bd572e1408cde2ca6a788b65205f43c585316b5ad3a8f2f16 module/channel-logging
ff897c034772de4c093392fce06671814349cbc1f7d39ded6c90412407998e2f module/channel-message
392c3e8757eb568877e00235a9a6b67044f102f9fd18dc169254071af657b8b4 module/channel-outbound
7441ea71c470e82beffeca577d69beedeb7efcf4439085e35c9813b12e96cdb9 module/channel-pairing
46bbdfff44d2a1e72c8c68d0801fda463361d70a79c50448505f487ff2363f90 module/channel-plugin-common
43a4a56defd68e433dc5a30e25eefccf598513d1bd721b6861574c6fe9783bd5 module/channel-policy
3a342f575458bf45e7c3b9618f7fb196089b7e91fcee16b23bc0b7faedcdb6c4 module/channel-reply-pipeline
482370e60135db9bfaf07f24bab549e5fde09ab265a6061a1f587c5d93929e91 module/channel-runtime-context
e5bab77cf56d4a549b4ba1ba16c15f86394266ecd07b31f96abd5adbfa9bd94b module/channel-secret-basic-runtime
53677d02f5cc8744bd9d335bcb4172a7eda083872f90ffc65c3e474ee149ec0e module/channel-secret-runtime
6c7a1dfd020f3611568c84b8687ce6d06795c953f8f5de71f490fa1d9cc6eead module/channel-send-result
844e8476d0c2967820ff612ca4c11841c149fbfcf541378b9c980013baf30f05 module/channel-setup
528ab5be35a3ad564e74699c6c4aec289a2c424e19f14b7e74fcaf41b0acbe7f module/channel-status
91b43898e843e9497ff1c3aad3d5de5357f0f44e3987d28e5ea70d980b7d418a module/channel-streaming
67df67da5ae72e9eaeb19d41b6bd2432ec4fd8b7b63b2b616fb98f3b4e0ec41d module/channel-streaming-config
1303df5cc58539c6941e2cd159c93259804c925795219f1630f4d740896a77c1 module/cli-argv
ad12670dbfe538f8d0ebf4fb2b68080e93a760278278e6b1ce9bb129d4b2d533 module/collection-runtime
3c625ff1528eb4586f7f287d21afe75905873c0463bc701a9dd7c70d233c1dda module/command-auth
e3bc0ceda7d12196d06bc476e70f980c08a61ba0357fdeaeaf0c6778ac969671 module/command-auth-native
1c725b558e450d7961fc6fe7c0843838860946cb78c1ec82f68305489d534524 module/command-detection
ebaccf95249d1037448f58c543b448ccccff493c4b2086f10093faff87668a61 module/command-primitives-runtime
e85a6cc9ac9972d142cde8ff6e5b8a84b643868b7b1c402b0eede321262f2cd4 module/command-status
3bd594bf7f101450275b8e3593e6420ce25e90093489f2ebe1375ea0f3bb7c23 module/config-contracts
1ac59199900b7ee5ea1d73adcb513d282b62dfe011ce807ddf0df125a30f8008 module/config-mutation
5ec2e13d88466ab2c0c7f25d9cadb6d3a62cb4c7959be11d6e72ad4cf4c5dd6a module/config-runtime
834069efe69c5cda2747b2415baad705767276d5d3ddbe99c2ce83d2b11527eb module/conversation-runtime
dcf04fc00b0d158b118fc9020deb5b032868308cb6f82f49b70ed9d05979fd94 module/core
70f0ceffe7df659416c2114a00cb915b0f2ea45e99862b2dc7f5c21e6fdaa94f module/dedupe-runtime
ebef0e650ab45e44c9335e2b3e15588c968cea6dadd125364a076f9c50ad1e8c module/device-bootstrap
c944f438e9108f3e023149c3d22d152e1c59867151668b9e61bba4da0c09c2cb module/diagnostic-runtime
3519f2584015d6817eefd7803cca7089d66d8569c297367a10aa2114cf6d24d2 module/directory-runtime
10c0932e21a5a8eeca9b515a8f80c420f9d767ddc7cd9926b3ff8f3936ad7f26 module/discord
12f4ff032680218e63370698e2ec8b0c46a5a4dc86ce05462dd1284a06ed2eef module/error-runtime
cdf0108ad6ac4fcd8f1b2f50b0a6f10f28f1dd1a36a60b8345a4f5f0862c8eac module/extension-shared
dd9f6e0fd33cc88b22543c1ee30cc09cf4de4d8f30dff7b7f9cebef885c21543 module/gateway-method-runtime
1f594cdd836aa9bdd0698d1927b164190710e9baf0f66917a45d2f62aa2fc84d module/gateway-runtime
575656e5e0195c8d1813a4e2e3a271e800bb97d44f2dd78c242e3b6714ffa097 module/group-access
e86e937127cf17772834e1c06dc5407d7504b97cac9fe32ef3bf730ad9ea3e58 module/health
54301207a429f30f78aeadb99d6b61591c81b6ea4f467daf3d49efe9106bde81 module/hook-runtime
73c55fa5541efc308d1c99e012f651e45ca84d9049bb8125b6dea687f435862b module/inbound-envelope
4928af5d2509f696b896f53ac790303a0742202dbcdae3e44fe6d1b434a9c1ba module/inbound-event-delivery
8d4232e1b5b24522383888c2f5b14ecae3c615d007b8e73a0cda22b505f42308 module/inbound-reply-dispatch
5069264ca7327b8c5637cf3a854501ec8263148744c3e62af8c0d9f48689b48f module/infra-runtime
ce73721421f1b903dd04ead4df173582e59ea3e9990248102c448b419cc6d272 module/ingress-effect-once
6d0ef8e970d63f711298747344f3c6757fbad6d920b270be06e7611130d846cf module/interactive-runtime
408d257ab5cc4b88a22b7e7595039cb8fc524b261c44141b294fbd0100ba62ee module/json-store
e907fd3a98185f2c261f2aafcaa5a19ee1d7b459d519a498397d629f84c68312 module/lazy-runtime
259373ff0a62fe30ddc4e36260bdba6bf206f98b71a953948bf4dad17c137fff module/logging-core
f1ca4ced4305d0769c2d8cc1291137ac7002fe0e6eaec2c1a71edad2204c8311 module/matrix
3955a8dd748418fa830a9b9a28cd3fdea844212db164b75828aa61ff3848eb5e module/media-local-roots
f74d7295fe716aa140aa0bc9300d6259d71dab826de0808fca6bb02592bf5d6e module/media-mime
2223ff355bea9bf5f903237e1e7dfc2b1c92df27a4141f448b1a20dc0d403a4e module/media-runtime
6a52f93107335f88751704352cc01e62add06f854a5b7d765e2a5ee87c0313b6 module/media-store
bb9f787cd2362268894393f5cf8d16ea582609cb1bb27fbdfc8ea97a76cea214 module/media-understanding
7fc60001aee2f0f95caa7eebe4e8dc74d3a4dcac71f16ce63447d73226f9c683 module/media-understanding-runtime
11aceef9da8abc590d2b5b2cd6a11caaed3c9e54f39cb7e24038bfb01e355b4d module/meeting-runtime
327414d8448f9bbac5d6770f67be92bc7e343415779476611b61acf6e842b0ad module/memory-core-host-engine-foundation
1cad1ac074f2c701e3a48a5b116169292330bd919d5eeedaaf2c36376d449007 module/memory-host-core
1efa0aadc4261d1c6073058cbf3dcc9fa681424819bdd14333e19b249bbc4b18 module/messaging-targets
c374d5020754909d1997b228a2cef74529a11d2deb1f0f65078e9ceb2ed8b7ae module/model-session-runtime
95d7e048fe4e784f149a272a764685081e97fd852c95bbe859519daf36d2d63a module/models-provider-runtime
bba9f68844a60e9bd9b03c694684f62bd7cc11542d6f600bf65b561cadbca8ea module/native-command-config-runtime
62b6329334d16090db4af2a45f4ab5d43842b62db92f458df73af3d9323e681a module/native-command-registry
e1230968f3a3587679a4fa57b67ab36af9bcc81b2bce730c9e724eb66c4418e9 module/param-readers
ca7a56bb1a6169b4cf9befbf5aa21da280a8086fdc49fca4eec520a7a7c98549 module/persistent-dedupe
e3984a76820581c5281412b2449b2bb431110547c2cd833e63d29991e18f7176 module/plugin-config-runtime
7b4fa841f2e5f24a6fb8b7348acb2840d3ed29555d67202cb33d07cb968bdf19 module/plugin-entry
f3df17caa3a3c1904abf7b2ac51cde116135117b545b5fd0f5f3b9eb548075a9 module/plugin-runtime
cff4cdfe96da2a5caa53a5b77addf7f2f9ce94d668be5c9d7e6a11f9b64e7ce0 module/provider-auth
4ddfeb578b91f3bfe82883a97b5378d8baaae4e071dad6b5f9c5a8e331d284ff module/provider-catalog-runtime
8131147d699394bd06503e2ea2f5f1a50b1594a87dded6d118b74a8d0328c8f6 module/proxy-capture
61a976f321591ab6980fff5e780ee8019b57658e94b39370ba6e5923ce28f818 module/question-gateway-runtime
deebc97abbbae14b005ca599d9708fc4ca71964406f6cbb38af7339cf2cdd0df module/reply-chunking
55e675b4c22019fd41d6a6c8cee4f61f8d4e983be517d27519cb8b5fad6b9cf7 module/reply-dispatch-runtime
73f861fa3179d5af1159853c5acab0eec7a6c8f9398dcb75ea770e784fca6727 module/reply-history
0e32d365a83854a04b27522abf9a331a5170ebd345157e11bace539af6a70d88 module/reply-payload
9c510890a98eb0f03c370e58f16c22427720388894e777667c4a874f6ac878ae module/reply-runtime
aa07d85d99fdd2b1e0cbe9975fb6dcae66b8bdce2607c6bd5402ae68bb15118c module/root-walk
3941a8508e73944bf0d920a7334e525c617fc24105ca984fcdc69930ae5cbb7b module/routing
7877a7e58fa32a64107154e5b714c6d165e96989d4aa5f43e0afac085a187af0 module/run-command
9a119658075d586a41dcbd2b4e431c5da1ec2c3d6d21317a18aeeef06359c8ac module/runtime
6df4f6a901ddfafd4f441ef6a2d9a41fca48dd953dc377def2b8ed39db95934f module/runtime-config-snapshot
45bede83ee89886eeda9155f9d4356ce7fa7611c4be744443c1c439173d666ce module/runtime-env
7e871b7319745678bb83fcfc1b54c8751b0ab1af92ff06c01d0659ac92863c11 module/runtime-group-policy
434002543659a8235bf484d88f10d02439b3dbc056bd67c6117bae2da9279048 module/runtime-store
d17862c40825af1ddf0257b44f1e1cbb9c375e8e5ed668fae75d530d1a465cf9 module/secret-file
8e2ac4d3973d8d8ce4478e3440d66ee5c0d9213b0fe9e927c421d14fd31e5e86 module/secret-input
ccd790bc28ce44ca8a2df9a643103555dc650e9778a969c2f6fdeb1f0e1fba1b module/secret-input-runtime
f473090754cb12a5c4a2d39d693315700b25cb053c825c30b3a889a555f10f16 module/secret-ref-runtime
3ac69236c14ac1861aff09f267c523b8f34a63b9bbca085d326c21056604ede0 module/security-runtime
34b3c3904acb961959616b9cefa5b2bc7bc3f543c3e961a94bc6b0d53c148c79 module/session-catalog
c6cf92d099719c629cfddd24243b1deb8febc3122816822e5f4314f9b190e0af module/session-discussion
db9dfcfcdecceae09f163aaad12387e53081a54b6fc7b3ac76427c654662a96c module/session-store-runtime
5af106014a62ef2802236dbc5484d55bfffc2cf7105fd184a4d3b80ac0ab7727 module/setup
b64a0abce77e276b739f8b3979ba60b9b6407955aaedd7803c7d7b9936250574 module/setup-runtime
44d37e0d9131ad2859f41068f2604090c784e65f1bd6ebda8e051b6f2e5e1660 module/setup-tools
fbf92bec93e5cf2afb8be92f9eaefe44dcd8b9c5ba524910d786bca6b48e2530 module/skill-commands-runtime
65438b2c377f9dd3c2a24bfa92e9bca7d568ee6da9d15d8737975bd85a01e188 module/speech-settings
3650198b8d9b0ec76560ebc30bd09fb9f99b22366749cd870918160dd87a2f33 module/ssrf-policy
e6ec1baaa72323bfd0e6e0f2bb1550896d8c95ae4a5d588bd1faeeacd651ed16 module/ssrf-runtime
c1f4358865191005afa6885abf8ed891e0d6fbdc82a04bb7473a5108a0e21516 module/state-paths
80eca61f8d0fc88798a7fb62bc09fee8ffeec7b2329abaaecf3c41c16fa1ba83 module/status-helpers
f097d0096b21c8a052f0f649b7512ecf2aba4744ae6956f001950e053828b309 module/string-coerce-runtime
799a08a3be07df057bb62c01f51b1a35bdfa360ebc3f4c5f9fcccedd19d3aea5 module/telegram-account
aef35bee2502cd6ed8765409b758e452aff8ac9469fd773e6a2a44c9a1bc3f66 module/temp-path
87fa81b9e58d8fc04a4b4202d2d37fca339615f5225687d9db905151439e0f4d module/text-chunking
87f5a0d7948934e403f4e15cb4d2fb54dd97a16a35dffec3cf5ee66ddbd46169 module/text-runtime
b6fa8e1d2c99997aa734a699610c2d06d32fe93d009298d7511c101bd0798a24 module/tool-plugin
dc1a073c59ab61e2789533b777b3f0cb9af689d64a97796b10e8aa82552510db module/tool-results
9a2f1691d747799e833f19ce8b31b844421a660354221d42299ade9cfefcbeda module/tool-send
cda105b721d498df23a554c6b68be150b8fe66b8b9172185c31a0b3b0646b1dc module/web-media
acd86723117251ac58a46347ccae7893c35539d72b97a904372dbafb34f50e22 module/webhook-ingress
3d7a4d6c0e769a78a47d6a67393c72b3a5df9c272058f1f072a28ac9d6b2cfb8 module/webhook-request-guards
de59e86e126b75d13251cba7ebbe27b44d9b5588785d98df5ff4d6722374c81f module/widget-html
9161b36ec0ab062ea41b363c894fcd672a7727f21cb726739f99f9c184fce69d module/zod
@@ -0,0 +1,305 @@
// Declaration closure rendering keeps compiler-owned dependencies in API baselines.
import { createHash } from "node:crypto";
import path from "node:path";
import ts from "typescript";
import {
normalizePluginSdkApiDeclarationText,
normalizePluginSdkApiSourcePath,
} from "./api-baseline-normalization.js";
export type PluginSdkDeclarationClosure = {
hash: string;
};
type ClosureExport<T> = {
closure: PluginSdkDeclarationClosure;
surface: T;
};
type DeclarationReference = {
mode: ts.ResolutionMode;
specifier: string;
};
type EmittedDeclaration = {
declarationFile: ts.SourceFile;
text: string;
};
function compareText(left: string, right: string): number {
return left < right ? -1 : left > right ? 1 : 0;
}
export function formatPluginSdkDiagnostics(
diagnostics: readonly ts.Diagnostic[],
currentDirectory: string,
): string {
return ts.formatDiagnostics(diagnostics, {
getCanonicalFileName: (fileName) => fileName,
getCurrentDirectory: () => currentDirectory,
getNewLine: () => "\n",
});
}
export function attachPluginSdkDeclarationClosures<T extends { declaration: string | null }>(
exports: readonly ClosureExport<T>[],
): T[] {
return exports.map(({ closure, surface }) => {
if (surface.declaration && closure.hash) {
surface.declaration = `// declaration closure: ${closure.hash}\n${surface.declaration}`;
}
return surface;
});
}
function collectDeclarationReferences(
sourceFile: ts.SourceFile,
options: ts.CompilerOptions,
): DeclarationReference[] {
const references = new Map<string, DeclarationReference>();
const add = (literal: ts.StringLiteralLike) => {
const mode = ts.getModeForUsageLocation(sourceFile, literal, options);
references.set(`${mode ?? "default"}\0${literal.text}`, {
mode,
specifier: literal.text,
});
};
const visit = (node: ts.Node) => {
if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier)) {
add(node.moduleSpecifier);
} else if (
ts.isExportDeclaration(node) &&
node.moduleSpecifier &&
ts.isStringLiteralLike(node.moduleSpecifier)
) {
add(node.moduleSpecifier);
} else if (
ts.isImportEqualsDeclaration(node) &&
ts.isExternalModuleReference(node.moduleReference) &&
node.moduleReference.expression &&
ts.isStringLiteralLike(node.moduleReference.expression)
) {
add(node.moduleReference.expression);
} else if (
ts.isImportTypeNode(node) &&
ts.isLiteralTypeNode(node.argument) &&
ts.isStringLiteralLike(node.argument.literal)
) {
add(node.argument.literal);
}
ts.forEachChild(node, visit);
};
visit(sourceFile);
return [...references.values()].toSorted(
(left, right) =>
compareText(left.specifier, right.specifier) ||
compareText(String(left.mode), String(right.mode)),
);
}
export function createDeclarationClosureRenderer(params: {
printer: ts.Printer;
program: ts.Program;
repoRoot: string;
}): (sourceFile: ts.SourceFile) => PluginSdkDeclarationClosure {
const { printer, program, repoRoot } = params;
const options = program.getCompilerOptions();
const canonical = (fileName: string) => {
const resolved = path.resolve(fileName);
return ts.sys.useCaseSensitiveFileNames ? resolved : resolved.toLowerCase();
};
const sourceFiles = new Map<string, ts.SourceFile>();
for (const sourceFile of program.getSourceFiles()) {
sourceFiles.set(canonical(sourceFile.fileName), sourceFile);
const realPath = ts.sys.realpath?.(sourceFile.fileName);
if (realPath) {
sourceFiles.set(canonical(realPath), sourceFile);
}
}
const resolutionCache = ts.createModuleResolutionCache(repoRoot, canonical, options);
const moduleHost = ts.createCompilerHost(options, true);
const emitted = new Map<string, EmittedDeclaration>();
const renderedClosures = new Map<string, PluginSdkDeclarationClosure>();
const baseDiagnostics = [...program.getOptionsDiagnostics(), ...program.getGlobalDiagnostics()];
if (baseDiagnostics.length > 0) {
throw new Error(
`Unable to emit Plugin SDK declarations:\n${formatPluginSdkDiagnostics(baseDiagnostics, program.getCurrentDirectory())}`,
);
}
const isRepoOwned = (sourceFile: ts.SourceFile) => {
if (
program.isSourceFileDefaultLibrary(sourceFile) ||
program.isSourceFileFromExternalLibrary(sourceFile)
) {
return false;
}
const relative = path.relative(repoRoot, path.resolve(sourceFile.fileName));
return (
relative !== "" &&
relative !== ".." &&
!relative.startsWith(`..${path.sep}`) &&
!path.isAbsolute(relative) &&
!relative.split(path.sep).includes("node_modules")
);
};
const getDeclaration = (sourceFile: ts.SourceFile): EmittedDeclaration => {
const key = canonical(sourceFile.fileName);
const cached = emitted.get(key);
if (cached) {
return cached;
}
const diagnostics = [
...program.getSyntacticDiagnostics(sourceFile),
...(sourceFile.isDeclarationFile ? [] : program.getDeclarationDiagnostics(sourceFile)),
];
if (diagnostics.length > 0) {
throw new Error(
`Unable to emit ${normalizePluginSdkApiSourcePath(repoRoot, sourceFile.fileName)}:\n${formatPluginSdkDiagnostics(diagnostics, program.getCurrentDirectory())}`,
);
}
let declarationFile = sourceFile;
if (!sourceFile.isDeclarationFile) {
let output: { content: string; fileName: string } | undefined;
const result = program.emit(
sourceFile,
(fileName, content, _writeByteOrderMark, _onError, outputSources) => {
if (!/\.d\.[cm]?ts$/u.test(fileName)) {
return;
}
const outputSource = outputSources?.[0];
if (
outputSources?.length !== 1 ||
!outputSource ||
canonical(outputSource.fileName) !== canonical(sourceFile.fileName)
) {
throw new Error(`Declaration output ${fileName} has no unique source owner`);
}
if (output) {
throw new Error(`Duplicate declaration output for ${sourceFile.fileName}`);
}
output = { content, fileName };
},
undefined,
true,
);
if (result.emitSkipped || result.diagnostics.length > 0) {
const detail = result.diagnostics.length
? `\n${formatPluginSdkDiagnostics(result.diagnostics, program.getCurrentDirectory())}`
: "";
throw new Error(
`Unable to emit ${normalizePluginSdkApiSourcePath(repoRoot, sourceFile.fileName)}${detail}`,
);
}
if (!output) {
throw new Error(
`Missing emitted declaration for ${normalizePluginSdkApiSourcePath(repoRoot, sourceFile.fileName)}`,
);
}
declarationFile = ts.createSourceFile(
output.fileName,
output.content,
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TS,
);
declarationFile.impliedNodeFormat = sourceFile.impliedNodeFormat;
}
const declaration = {
declarationFile,
text: normalizePluginSdkApiDeclarationText(
repoRoot,
printer.printFile(declarationFile).trim(),
),
};
emitted.set(key, declaration);
return declaration;
};
const resolveDependency = (
sourceFile: ts.SourceFile,
reference: DeclarationReference,
): ts.SourceFile | undefined => {
const resolved = ts.resolveModuleName(
reference.specifier,
sourceFile.fileName,
options,
moduleHost,
resolutionCache,
undefined,
reference.mode,
).resolvedModule;
if (!resolved) {
if (ts.isExternalModuleNameRelative(reference.specifier)) {
throw new Error(
`Unable to resolve declaration dependency ${reference.specifier} from ${normalizePluginSdkApiSourcePath(repoRoot, sourceFile.fileName)}`,
);
}
return undefined;
}
if (resolved.isExternalLibraryImport) {
return undefined;
}
const dependency = sourceFiles.get(canonical(resolved.resolvedFileName));
if (!dependency) {
const relative = path.relative(repoRoot, path.resolve(resolved.resolvedFileName));
if (
relative !== ".." &&
!relative.startsWith(`..${path.sep}`) &&
!path.isAbsolute(relative)
) {
throw new Error(
`Missing program source for declaration dependency ${resolved.resolvedFileName}`,
);
}
return undefined;
}
return isRepoOwned(dependency) ? dependency : undefined;
};
return (owner) => {
const ownerKey = canonical(owner.fileName);
const cached = renderedClosures.get(ownerKey);
if (cached) {
return cached;
}
if (!isRepoOwned(owner)) {
return { hash: "" };
}
const visited = new Set<string>();
const sections = new Map<string, string>();
const visit = (sourceFile: ts.SourceFile) => {
const key = canonical(sourceFile.fileName);
if (visited.has(key)) {
return;
}
visited.add(key);
const declaration = getDeclaration(sourceFile);
sections.set(
normalizePluginSdkApiSourcePath(repoRoot, sourceFile.fileName),
declaration.text,
);
for (const reference of collectDeclarationReferences(declaration.declarationFile, options)) {
const dependency = resolveDependency(sourceFile, reference);
if (dependency) {
visit(dependency);
}
}
};
visit(owner);
const renderedSections = [...sections.entries()]
.toSorted(([left], [right]) => compareText(left, right))
.map(([sourcePath, text]) => ({ sourcePath, text }));
const hash = createHash("sha256")
.update(JSON.stringify(renderedSections), "utf8")
.digest("hex");
const closure = { hash };
renderedClosures.set(ownerKey, closure);
return closure;
};
}
@@ -0,0 +1,48 @@
// API baseline normalization removes machine-local path differences from compiler output.
import path from "node:path";
/** Normalize compiler source paths into stable repo-relative or node_modules-relative paths. */
export function normalizePluginSdkApiSourcePath(repoRoot: string, filePath: string): string {
const resolvedPath = path.resolve(filePath);
const relative = path.relative(repoRoot, resolvedPath);
const relativePosix = relative.split(path.sep).join(path.posix.sep);
if (
!relative.startsWith("..") &&
!path.isAbsolute(relative) &&
!relativePosix.startsWith("node_modules/")
) {
return relativePosix;
}
const pathParts = resolvedPath.split(/[\\/]+/);
const nodeModulesIndex = pathParts.lastIndexOf("node_modules");
if (nodeModulesIndex >= 0 && nodeModulesIndex < pathParts.length - 1) {
return ["node_modules", ...pathParts.slice(nodeModulesIndex + 1)].join(path.posix.sep);
}
return relativePosix;
}
function normalizeDeclarationImportSpecifier(repoRoot: string, value: string): string {
if (!path.isAbsolute(value) && !/^[A-Za-z]:[\\/]/.test(value)) {
return value;
}
const resolvedPath = path.resolve(value);
const relative = path.relative(repoRoot, resolvedPath);
if (relative.startsWith("..") || path.isAbsolute(relative)) {
return value;
}
return relative.split(path.sep).join(path.posix.sep);
}
/** Strip machine-local absolute paths from declaration text before hashing baseline output. */
export function normalizePluginSdkApiDeclarationText(repoRoot: string, value: string): string {
return value.replaceAll(
/import\("([^"]+)"((?:\s*,[^)]*)?)\)/g,
(match, specifier: string, suffix: string) => {
const normalized = normalizeDeclarationImportSpecifier(repoRoot, specifier);
return normalized === specifier ? match : `import("${normalized}"${suffix})`;
},
);
}
+106 -1
View File
@@ -1,10 +1,12 @@
/**
* Tests the plugin SDK public API baseline.
*/
import fs from "node:fs";
import path from "node:path";
import ts from "typescript";
import { beforeAll, describe, expect, it } from "vitest";
import { afterEach, beforeAll, describe, expect, it } from "vitest";
import { publicPluginSdkEntrypoints } from "../../scripts/lib/plugin-sdk-entries.mjs";
import { useAutoCleanupTempDirTracker } from "../../test/helpers/temp-dir.js";
import {
computePluginSdkApiBaselineHashFileContent,
formatPluginSdkApiTypeAlias,
@@ -22,6 +24,7 @@ const TEST_ENTRYPOINTS = [
"channel-policy",
"core",
"infra-runtime",
"plugin-entry",
"provider-auth",
"provider-catalog-live-runtime",
"provider-oauth-runtime",
@@ -32,6 +35,67 @@ const TEST_ENTRYPOINTS = [
"sqlite-runtime-testing",
] as const;
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
async function renderPrivateDeclarationFixture(params?: {
optionalOption?: boolean;
optionalResult?: boolean;
}) {
const repoRoot = tempDirs.make("openclaw-plugin-sdk-api-");
const sourceDir = path.join(repoRoot, "src", "plugin-sdk");
const externalDir = path.join(repoRoot, "node_modules", "fixture-external");
fs.mkdirSync(sourceDir, { recursive: true });
fs.mkdirSync(externalDir, { recursive: true });
fs.writeFileSync(
path.join(repoRoot, "tsconfig.json"),
`${JSON.stringify({
compilerOptions: {
module: "NodeNext",
moduleResolution: "NodeNext",
target: "ESNext",
},
})}\n`,
);
fs.writeFileSync(
path.join(sourceDir, "fixture.ts"),
[
'import type { FixtureOptionLeaf } from "./fixture-option.js";',
'import type { FixtureResultLeaf } from "./fixture-result.js";',
"type FixtureOptions = { nested: FixtureOptionLeaf };",
"type FixtureResult = { nested: FixtureResultLeaf };",
"export declare function createFixture(options: FixtureOptions): FixtureResult;",
].join("\n"),
);
fs.writeFileSync(
path.join(sourceDir, "fixture-option.ts"),
[
'import type { FixtureResultLeaf } from "./fixture-result.js";',
'import type { FixtureExternal } from "fixture-external";',
`export type FixtureOptionLeaf = { required${params?.optionalOption ? "?" : ""}: string; result?: FixtureResultLeaf; external?: FixtureExternal };`,
].join("\n"),
);
fs.writeFileSync(
path.join(sourceDir, "fixture-result.ts"),
'export type { FixtureResultLeaf } from "./fixture-result-shape.js";\n',
);
fs.writeFileSync(
path.join(sourceDir, "fixture-result-shape.ts"),
[
'import type { FixtureOptionLeaf } from "./fixture-option.js";',
`export type FixtureResultLeaf = { value${params?.optionalResult ? "?" : ""}: string; option?: FixtureOptionLeaf };`,
].join("\n"),
);
fs.writeFileSync(
path.join(externalDir, "package.json"),
`${JSON.stringify({ name: "fixture-external", types: "index.d.ts" })}\n`,
);
fs.writeFileSync(
path.join(externalDir, "index.d.ts"),
"export type FixtureExternal = { externalOnly: string };\n",
);
return renderPluginSdkApiBaseline({ repoRoot, entrypoints: ["fixture"] });
}
function createTupleAliasFixture(tuple: string, warmup: string, prewarm: boolean) {
const fileName = "/plugin-sdk-tuple-fixture.ts";
const source = [
@@ -192,6 +256,11 @@ describe("Plugin SDK API baseline", () => {
expect(findDeclaration("SqliteTrajectoryRuntimeEventForTest")).toContain(
"export type SqliteTrajectoryRuntimeEventForTest =",
);
expect(findDeclaration("definePluginEntry")).toMatch(
/^\/\/ declaration closure: [a-f0-9]{64}/u,
);
expect(findDeclaration("definePluginEntry")).toContain("DefinePluginEntryOptions");
expect(findDeclaration("definePluginEntry")).toContain("DefinedPluginEntry");
expect(findDeclaration("ProviderSelection")).toContain(
"export type ProviderSelection<TProvider> =",
);
@@ -233,4 +302,40 @@ describe("Plugin SDK API baseline", () => {
expect(after[0]).not.toBe(before[0]);
expect(after.slice(1)).toEqual(before.slice(1));
});
it("captures transitive private declaration changes deterministically", async () => {
const baseline = await renderPrivateDeclarationFixture();
const unchanged = await renderPrivateDeclarationFixture();
const optionChanged = await renderPrivateDeclarationFixture({ optionalOption: true });
const resultChanged = await renderPrivateDeclarationFixture({ optionalResult: true });
const declaration = baseline.baseline.modules[0]?.exports[0];
expect(declaration).toEqual(
expect.objectContaining({
exportName: "createFixture",
kind: "function",
source: { path: "src/plugin-sdk/fixture.ts" },
}),
);
expect(declaration?.declaration).toMatch(/^\/\/ declaration closure: [a-f0-9]{64}/u);
expect(declaration?.declaration).toContain("FixtureOptions");
expect(declaration?.declaration).toContain("FixtureResult");
expect(declaration?.declaration).not.toContain("required: string;");
expect(declaration?.declaration).not.toContain("value: string;");
expect(declaration?.declaration).not.toContain("externalOnly: string;");
expect(unchanged.json).toBe(baseline.json);
expect(unchanged.jsonl).toBe(baseline.jsonl);
expect(computePluginSdkApiBaselineHashFileContent(unchanged)).toBe(
computePluginSdkApiBaselineHashFileContent(baseline),
);
for (const changed of [optionChanged, resultChanged]) {
expect(changed.baseline.modules[0]?.exports[0]?.declaration).not.toBe(
declaration?.declaration,
);
expect(computePluginSdkApiBaselineHashFileContent(changed)).not.toBe(
computePluginSdkApiBaselineHashFileContent(baseline),
);
}
});
});
+63 -75
View File
@@ -10,6 +10,21 @@ import {
type PluginSdkDocEntrypoint,
} from "../../scripts/lib/plugin-sdk-doc-metadata.ts";
import { publicPluginSdkEntrypoints } from "../../scripts/lib/plugin-sdk-entries.mjs";
import {
attachPluginSdkDeclarationClosures,
createDeclarationClosureRenderer,
formatPluginSdkDiagnostics,
type PluginSdkDeclarationClosure,
} from "./api-baseline-declaration-closure.js";
import {
normalizePluginSdkApiDeclarationText,
normalizePluginSdkApiSourcePath as relativePath,
} from "./api-baseline-normalization.js";
export {
normalizePluginSdkApiDeclarationText,
normalizePluginSdkApiSourcePath,
} from "./api-baseline-normalization.js";
/** Declaration kind recorded for each public SDK export in the API baseline. */
export type PluginSdkApiExportKind =
@@ -102,60 +117,6 @@ function resolveRepoRoot(): string {
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
}
/** Normalize compiler source paths into stable repo-relative or node_modules-relative paths. */
export function normalizePluginSdkApiSourcePath(repoRoot: string, filePath: string): string {
const resolvedPath = path.resolve(filePath);
const relative = path.relative(repoRoot, resolvedPath);
const relativePosix = relative.split(path.sep).join(path.posix.sep);
if (
!relative.startsWith("..") &&
!path.isAbsolute(relative) &&
!relativePosix.startsWith("node_modules/")
) {
return relativePosix;
}
const pathParts = resolvedPath.split(/[\\/]+/);
const nodeModulesIndex = pathParts.lastIndexOf("node_modules");
if (nodeModulesIndex >= 0 && nodeModulesIndex < pathParts.length - 1) {
return ["node_modules", ...pathParts.slice(nodeModulesIndex + 1)].join(path.posix.sep);
}
return relativePosix;
}
function relativePath(repoRoot: string, filePath: string): string {
return normalizePluginSdkApiSourcePath(repoRoot, filePath);
}
function isAbsoluteImportPath(value: string): boolean {
return path.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value);
}
function normalizeDeclarationImportSpecifier(repoRoot: string, value: string): string {
if (!isAbsoluteImportPath(value)) {
return value;
}
const resolvedPath = path.resolve(value);
const relative = path.relative(repoRoot, resolvedPath);
if (relative.startsWith("..") || path.isAbsolute(relative)) {
return value;
}
return relative.split(path.sep).join(path.posix.sep);
}
/** Strip machine-local absolute paths from declaration text before hashing baseline output. */
export function normalizePluginSdkApiDeclarationText(repoRoot: string, value: string): string {
return value.replaceAll(
/import\("([^"]+)"((?:\s*,[^)]*)?)\)/g,
(match, specifier: string, suffix: string) => {
const normalized = normalizeDeclarationImportSpecifier(repoRoot, specifier);
return normalized === specifier ? match : `import("${normalized}"${suffix})`;
},
);
}
function createCompilerContext(repoRoot: string, entrypoints: readonly string[]) {
const configPath = ts.findConfigFile(
repoRoot,
@@ -168,6 +129,9 @@ function createCompilerContext(repoRoot: string, entrypoints: readonly string[])
throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n"));
}
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, repoRoot);
if (parsedConfig.errors.length > 0) {
throw new Error(formatPluginSdkDiagnostics(parsedConfig.errors, repoRoot));
}
const fileNames = entrypoints
.map((entrypoint) => path.join(repoRoot, "src", "plugin-sdk", `${entrypoint}.ts`))
.toSorted((left, right) =>
@@ -176,10 +140,26 @@ function createCompilerContext(repoRoot: string, entrypoints: readonly string[])
relativePath(repoRoot, path.resolve(right)),
),
);
const program = ts.createProgram(fileNames, parsedConfig.options);
const program = ts.createProgram(fileNames, {
...parsedConfig.options,
declaration: true,
declarationMap: false,
emitDeclarationOnly: true,
noEmit: false,
// Declaration diagnostics are checked explicitly; unrelated untyped external JS stays valid.
noEmitOnError: false,
removeComments: true,
sourceMap: false,
});
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: true });
return {
checker: program.getTypeChecker(),
printer: ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: true }),
declarationClosure: createDeclarationClosureRenderer({
printer,
program,
repoRoot,
}),
printer,
program,
};
}
@@ -189,12 +169,6 @@ export function listPluginSdkApiBaselineEntrypoints(): string[] {
return [...publicPluginSdkEntrypoints];
}
function buildSourceLink(repoRoot: string, filePath: string): PluginSdkApiSourceLink {
return {
path: relativePath(repoRoot, filePath),
};
}
function inferExportKind(
symbol: ts.Symbol,
declaration: ts.Declaration | undefined,
@@ -571,20 +545,27 @@ function compareDeclarations(
function buildExportSurface(params: {
checker: ts.TypeChecker;
declarationClosure: (sourceFile: ts.SourceFile) => PluginSdkDeclarationClosure;
printer: ts.Printer;
repoRoot: string;
symbol: ts.Symbol;
}): PluginSdkApiExport {
const { checker, printer, repoRoot, symbol } = params;
}): { closure: PluginSdkDeclarationClosure; surface: PluginSdkApiExport } {
const { checker, declarationClosure, printer, repoRoot, symbol } = params;
const { declaration, resolvedSymbol } = resolveSymbolAndDeclaration(checker, repoRoot, symbol);
const exportName = symbol.getName();
const declarationText = declaration
? printNode(repoRoot, checker, printer, declaration, exportName)
: null;
return {
declaration: declaration
? printNode(repoRoot, checker, printer, declaration, exportName)
: null,
exportName,
kind: inferExportKind(resolvedSymbol, declaration),
source: declaration ? buildSourceLink(repoRoot, declaration.getSourceFile().fileName) : null,
closure: declaration ? declarationClosure(declaration.getSourceFile()) : { hash: "" },
surface: {
declaration: declarationText,
exportName,
kind: inferExportKind(resolvedSymbol, declaration),
source: declaration
? { path: relativePath(repoRoot, declaration.getSourceFile().fileName) }
: null,
},
};
}
@@ -608,12 +589,13 @@ function sortExports(left: PluginSdkApiExport, right: PluginSdkApiExport): numbe
function buildModuleSurface(params: {
checker: ts.TypeChecker;
declarationClosure: (sourceFile: ts.SourceFile) => PluginSdkDeclarationClosure;
printer: ts.Printer;
program: ts.Program;
repoRoot: string;
entrypoint: string;
}): PluginSdkApiModule {
const { checker, printer, program, repoRoot, entrypoint } = params;
const { checker, declarationClosure, printer, program, repoRoot, entrypoint } = params;
const metadata = Object.hasOwn(pluginSdkDocMetadata, entrypoint)
? pluginSdkDocMetadata[entrypoint as PluginSdkDocEntrypoint]
: undefined;
@@ -625,25 +607,27 @@ function buildModuleSurface(params: {
const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
assert(moduleSymbol, `Unable to resolve module symbol for ${importSpecifier}`);
const exports = checker
const builtExports = checker
.getExportsOfModule(moduleSymbol)
.filter((symbol) => symbol.getName() !== "__esModule")
.map((symbol) =>
buildExportSurface({
checker,
declarationClosure,
printer,
repoRoot,
symbol,
}),
)
.toSorted(sortExports);
.toSorted((left, right) => sortExports(left.surface, right.surface));
const exports = attachPluginSdkDeclarationClosures(builtExports);
return {
category: metadata?.category ?? null,
entrypoint,
exports,
importSpecifier,
source: buildSourceLink(repoRoot, moduleSourcePath),
source: { path: relativePath(repoRoot, moduleSourcePath) },
};
}
@@ -687,10 +671,14 @@ export async function renderPluginSdkApiBaseline(params?: {
const repoRoot = params?.repoRoot ?? resolveRepoRoot();
const entrypoints = params?.entrypoints ?? listPluginSdkApiBaselineEntrypoints();
validateMetadata();
const { checker, printer, program } = createCompilerContext(repoRoot, entrypoints);
const { checker, declarationClosure, printer, program } = createCompilerContext(
repoRoot,
entrypoints,
);
const modules = entrypoints.map((entrypoint) =>
buildModuleSurface({
checker,
declarationClosure,
printer,
program,
repoRoot,