@ikie-dev/cli 9.8.6 → 9.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ikie/ferments/019f2b5d-426e-741a-a176-6031399e42cd/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4289-71d5-9c92-949495910599/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-42a0-74f5-b804-1dd55616035a/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-42c5-7381-83e5-548f04ddbc55/runtime.json +12 -0
- package/.ikie/ferments/019f2b5d-42fd-702c-baef-81f5354cc24e/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-432e-7322-9af5-5333b4686468/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-434d-7429-b25f-0b58109fa362/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-436e-7389-b2ad-6a02cda4f9bb/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-439d-74dd-9786-13df51571d6b/runtime.json +13 -0
- package/.ikie/ferments/019f2b5d-43ce-71c9-81e0-16aa00ff9e28/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-440e-72cc-8509-b6b3fd2b6c6c/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-444f-73c1-8172-dbad1e42640a/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4469-71c1-97ff-23e2bb7ccc3b/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-448d-714d-b181-338e8a5dc8e1/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-44ad-71fb-b0a9-a1f949f9129a/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-44ca-730d-993c-9a827d415ffd/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-44ec-71c8-8523-031284e26b4b/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-450e-7013-93c5-3dd9b900ebd3/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-452a-714d-aff8-fdaca0988792/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-4550-749d-8807-3e9493ba614b/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-4570-7713-8d0f-5d13e8446bfb/runtime.json +15 -0
- package/.ikie/ferments/019f2b5d-459a-778a-a7f7-3317ecd6837f/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-45c1-718d-9ba5-b55dd0160a78/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-45f9-7381-9394-4647f47a2132/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2b5d-45f9-7381-9394-4647f47a2132/runtime.json +17 -0
- package/.ikie/ferments/019f2b5d-4782-71d4-89de-9c3e734707c8/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2b5d-4782-71d4-89de-9c3e734707c8/runtime.json +17 -0
- package/.ikie/ferments/019f2b5d-4950-728c-bf46-542c8ec21a6c/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4de5-75df-8d7d-a1cd2588a596/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4e07-70d4-9152-0925c5f81057/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4e28-7770-8b24-587c856e4b9b/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4e48-7159-9cb7-6401c6930ed4/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-4e6e-73a9-8bfd-639e394f48a4/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b5d-4e85-73c4-b099-4f6dc69c5268/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b5d-4fd0-7019-a28a-49af2a0266ed/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b5d-5045-70cc-b084-9ccd595944b3/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b5d-5056-759a-ae60-d4e8d2f7554f/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b5d-883b-759c-8453-2a7e8200e481/runtime.json +13 -0
- package/.ikie/ferments/019f2b5d-8873-723e-9b60-75d7ece374f9/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8898-70a3-8c9d-ef7f569c3e72/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-88b4-710c-ba72-ef0fc3dbf0ae/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-88d2-73cf-8983-953907020e62/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-88f3-73df-9ffa-dd262c3d4163/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8912-74db-b14a-95e882507c3e/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-892b-76c2-b9b3-42dbf26fa1c5/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8956-74d1-883d-b974060e341f/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-8979-741b-9ecc-2fe299103e8e/runtime.json +13 -0
- package/.ikie/ferments/019f2b5d-89a1-74ed-83f8-f19dd9f63c9d/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-89c9-71d8-88b2-8ded0c6a473e/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8a28-7309-a773-95dde5282ddf/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8a3c-7088-85cd-9e45836799c8/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-8a58-727b-8607-94e087e8b56f/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-8a6d-7465-bd8e-ab8c1cdbeef8/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8b30-75d0-9526-93a548435f3a/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8b4b-7352-a7a2-899427c50e5d/runtime.json +12 -0
- package/.ikie/ferments/019f2b5d-8b6f-723b-83fa-556273e78c4e/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8b95-74b2-b003-5ecf17ff2936/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8ba6-71f3-90eb-37751e5bab04/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8bbe-7251-b4f0-5d52ca8bbd0f/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-8bd6-779d-b55d-3df6cfd3d4ba/runtime.json +13 -0
- package/.ikie/ferments/019f2b5d-8bee-75b5-acf7-95f68fd37837/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-9b8e-7307-a95c-7e184eed7946/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2b5d-9b8e-7307-a95c-7e184eed7946/runtime.json +11 -0
- package/.ikie/ferments/019f2b5d-9bd7-7418-a977-3d39b5027fcc/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2b5d-9bd7-7418-a977-3d39b5027fcc/runtime.json +13 -0
- package/.ikie/ferments/019f2b5d-9c36-738b-9800-c32b17ab0a08/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b5d-9c36-738b-9800-c32b17ab0a08/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-9c67-76b8-9a49-00bf505ca1b8/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b5d-9c67-76b8-9a49-00bf505ca1b8/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-9c80-73ba-98ca-fa4595c45658/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b5d-9c80-73ba-98ca-fa4595c45658/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-9c9e-71a5-bd87-e317142e21fd/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b5d-9c9e-71a5-bd87-e317142e21fd/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-9cc1-73bf-98ae-cdd3759fdbd4/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b5d-9cc1-73bf-98ae-cdd3759fdbd4/runtime.json +9 -0
- package/.ikie/ferments/019f2b5d-9cd9-7478-aa4d-68ff15ec302e/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2b5d-9cd9-7478-aa4d-68ff15ec302e/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-10f5-71fd-b0ac-906640800f2a/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-111f-75fe-af2b-0a9cf1727058/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-113b-73de-9df2-3dc2058b0037/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-115e-772e-91f2-45da602cc046/runtime.json +12 -0
- package/.ikie/ferments/019f2b6e-1174-70a1-a06e-4c9a676e7a44/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1199-70d9-ae9a-01e965e953f1/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-11d1-74af-ab47-8e94823af880/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-11f3-7087-a610-3673d9a730c8/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-1214-7778-974a-3773b4f88517/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-123b-762d-8600-80a4da430695/runtime.json +13 -0
- package/.ikie/ferments/019f2b6e-1271-76b7-8c79-2c86e0e70e8c/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-129a-731e-93aa-a4f113bfeda8/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-12db-728a-bea2-d97e3310b918/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-12f5-72a8-8ea9-e83e907bb297/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-131a-714e-8d20-eb7a6aaeed29/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-1349-72aa-a518-6fac705a8a5f/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-1374-740e-8b66-ccc849baf168/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-13a6-75fd-a594-0e6dec52929b/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-13d3-775b-a8ad-e8efc6332d52/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-13ff-753a-aac4-207bd4d84720/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-1423-71ba-9cb9-8d5dc4ba44af/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-1449-77b9-95f8-c8b9a5cdbe1b/runtime.json +15 -0
- package/.ikie/ferments/019f2b6e-1475-771f-95b7-41248e78e547/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1498-76c2-a4c3-4a9d6ea8727d/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-14bd-77ad-89ea-7706d62850c0/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2b6e-14bd-77ad-89ea-7706d62850c0/runtime.json +17 -0
- package/.ikie/ferments/019f2b6e-1627-755e-943c-164dc672353c/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2b6e-1627-755e-943c-164dc672353c/runtime.json +17 -0
- package/.ikie/ferments/019f2b6e-17a9-74b2-921b-1d9ec0a01d5f/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1bb3-71ad-8be1-e8e3cd1a78b8/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1bde-778e-9fd2-dc5291b667d4/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1bfd-717c-8ab8-6d6b97e73a76/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1c1e-724b-80f7-e8084123ea42/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-1c3c-70a8-ab5c-8858a41b1111/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b6e-1c52-71af-975e-f514de2d2a9f/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b6e-1d84-726a-9382-0f49ac269f40/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b6e-1dcb-760e-b2cd-c06ba8d57f7c/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b6e-1de3-74a8-8567-7960dca0da46/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b6e-50b5-77dc-a145-de2797f954ba/runtime.json +13 -0
- package/.ikie/ferments/019f2b6e-513b-7019-9404-f46db9a8b3ec/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-5159-7711-9957-3393d05b23a3/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-5175-771d-8391-8f6b9f807ea8/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-519c-730d-bfed-592ef56a2720/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-51cd-709b-b3b5-352e20717ad9/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-51f0-728a-9edf-7e48bd6c69a7/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-521b-763a-9fe9-c7197b8209cd/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-5242-702d-a4aa-feb8569b86ad/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-5269-725a-be96-7135e5857c5f/runtime.json +13 -0
- package/.ikie/ferments/019f2b6e-52a5-74c9-b708-335a2e9bf42b/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-52e4-7506-89cb-182398a88f40/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-5389-736c-b328-dd8fa27082f9/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-53be-774f-9a27-291c66f2747a/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-53f4-73ae-bbca-2124c710812b/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-542e-71ee-87b1-37bbc5f40ccd/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-55b4-7238-89f5-a2a50dcaff05/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-55ec-72ba-a3b7-3b7739efe858/runtime.json +12 -0
- package/.ikie/ferments/019f2b6e-563d-721b-8ba0-f3286b33f62f/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-565b-7453-9046-2a7e60c63c62/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-5684-7125-a1ef-41494eb8be74/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-56a7-7512-b7e5-3c709a24a5e9/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-56ea-702a-9a97-7911f5f2caad/runtime.json +13 -0
- package/.ikie/ferments/019f2b6e-5730-75fb-bad2-18d701837e37/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-645f-7522-a80c-ddcd6935f5dc/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2b6e-645f-7522-a80c-ddcd6935f5dc/runtime.json +11 -0
- package/.ikie/ferments/019f2b6e-64aa-7328-ae9b-04f663f377b8/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2b6e-64aa-7328-ae9b-04f663f377b8/runtime.json +13 -0
- package/.ikie/ferments/019f2b6e-64fe-723a-99a2-0fab54b29f4a/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b6e-64fe-723a-99a2-0fab54b29f4a/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-651b-7018-91c0-baa3cf77c217/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b6e-651b-7018-91c0-baa3cf77c217/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-6533-70ee-a6de-6b3bc5ca17ef/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b6e-6533-70ee-a6de-6b3bc5ca17ef/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-654d-7760-942f-6ea45bebb394/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b6e-654d-7760-942f-6ea45bebb394/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-6563-74c5-bfd2-d8075d4005db/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b6e-6563-74c5-bfd2-d8075d4005db/runtime.json +9 -0
- package/.ikie/ferments/019f2b6e-6586-748a-83ac-05ea7a9e24f3/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2b6e-6586-748a-83ac-05ea7a9e24f3/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-485a-722f-ab3e-0b23bdf37851/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-4876-7247-ba41-e38f1dc709af/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-488d-732e-9b99-75f4ad2f9983/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-48ad-70b7-b262-ecb600a8be1a/runtime.json +12 -0
- package/.ikie/ferments/019f2b8e-48d9-73af-92cb-aa861441eef8/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-4906-7494-9168-5e15c0e984ed/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4929-71db-a7b5-b8686b433b49/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-494a-774c-8e7e-e881204e3b2b/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4972-70ab-8b70-9f8ac3ad9f33/runtime.json +13 -0
- package/.ikie/ferments/019f2b8e-49a7-7058-95e7-ea362f0554ba/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-49d5-750e-a1e0-7e7cf027c6c7/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4a12-7181-a65a-c6bbb6e750f3/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-4a2a-7741-a5d7-8109a9bf4c22/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4a4e-712f-9830-598e984f59b5/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4a72-71da-97bf-f2970d34ae8d/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4a93-76bc-8a04-28cdbb24a987/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4ab9-770e-b160-59b011c69b81/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4ae2-7619-8055-ddefbc9f4698/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4b0c-722e-9afe-6fab90611474/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4b3f-7143-b577-91721e39f89d/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4b72-720d-a104-19ce38a362e2/runtime.json +15 -0
- package/.ikie/ferments/019f2b8e-4bab-70e9-ac26-136c55e9e4c0/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-4bca-714d-80d0-317ca4733687/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-4bf1-7029-a93f-c509e847ec71/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2b8e-4bf1-7029-a93f-c509e847ec71/runtime.json +17 -0
- package/.ikie/ferments/019f2b8e-4d51-75ff-951e-652cf6a5e901/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2b8e-4d51-75ff-951e-652cf6a5e901/runtime.json +17 -0
- package/.ikie/ferments/019f2b8e-4ece-70cf-a9bb-9ba0327f74f1/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-52f5-71dc-86d6-d08c3dba9c10/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-5313-747f-b0b7-9ec09f80674a/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-5333-759e-9a2e-2198d28d8a31/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-535d-7501-86c4-2d120359fda5/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-537e-7528-b236-a550ec6f9b9b/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b8e-5393-74aa-86a6-31db0e99c73c/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b8e-54cd-7573-bb52-14899e431b6a/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b8e-551d-755d-9aa9-52bb0c7ce63e/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b8e-5549-708c-8b89-1a6cc53a4ec5/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2b8e-8874-7469-a3ca-1f19416a5413/runtime.json +13 -0
- package/.ikie/ferments/019f2b8e-88a4-737d-82ba-59fb52017a81/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-88c7-7448-a22d-bc9dcd6e06a2/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-88dc-72a8-813b-c9f1c91a6dd2/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-88ee-7600-a227-18ca80b3d525/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-88ff-7027-9bb9-e583b435e8b0/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8919-737a-9f89-b74eeb851e5c/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8936-71cc-9056-bca6ef3cbb91/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8966-77f5-b367-a9262cc45f25/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-8990-747d-b585-59cd82d765c6/runtime.json +13 -0
- package/.ikie/ferments/019f2b8e-89c9-71ed-a2e6-016626cbe5aa/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-89de-741f-ba71-489cca892cc4/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8a1e-727d-b14a-daf7374500ea/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8a35-7463-803e-de399c8d3158/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-8a51-72ad-b6d1-966e350960b7/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-8a6c-73e1-a3ab-f1e554db6b03/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8b16-7688-a299-84f3acc74338/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8b2f-71bf-8c76-21f5ce28b4fd/runtime.json +12 -0
- package/.ikie/ferments/019f2b8e-8b54-711e-b25c-8e06b22d52a3/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8b66-7039-97d2-00e7b31d85fe/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8b7a-76c8-8456-727db5f07f3f/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8b8e-7451-a3d6-7fbcc67a28c9/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-8ba1-73e8-bff2-bfbc47873b3b/runtime.json +13 -0
- package/.ikie/ferments/019f2b8e-8bb9-721b-aad5-fab25fa9b1d1/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-982a-74b9-b1b2-ad6c1b598e0a/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2b8e-982a-74b9-b1b2-ad6c1b598e0a/runtime.json +11 -0
- package/.ikie/ferments/019f2b8e-986d-7469-949a-be76ce3780d3/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2b8e-986d-7469-949a-be76ce3780d3/runtime.json +13 -0
- package/.ikie/ferments/019f2b8e-98ba-749a-839a-f5b64fbca3bc/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b8e-98ba-749a-839a-f5b64fbca3bc/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-98f7-7482-b89d-ca40d860d72b/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b8e-98f7-7482-b89d-ca40d860d72b/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-991a-729a-83c8-0da93e3f26ff/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b8e-991a-729a-83c8-0da93e3f26ff/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-9931-713f-845d-211cb77d0482/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b8e-9931-713f-845d-211cb77d0482/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-9952-734c-a3b4-8877348a7856/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2b8e-9952-734c-a3b4-8877348a7856/runtime.json +9 -0
- package/.ikie/ferments/019f2b8e-9974-700e-b045-cc2244e4d691/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2b8e-9974-700e-b045-cc2244e4d691/runtime.json +9 -0
- package/benchmark/audit-session/audit-session.sh +0 -0
- package/benchmark/manual/check-session.py +0 -0
- package/benchmark/manual/new-session-claude.sh +0 -0
- package/benchmark/manual/new-session.sh +0 -0
- package/benchmark/manual/run-evaluation.sh +0 -0
- package/benchmark/manual/start-self-improvement.sh +0 -0
- package/benchmark/terminal-bench-2/scripts/analyze-ferment-bench.py +0 -0
- package/benchmark/terminal-bench-2/scripts/run-claude-code-ikie.sh +0 -0
- package/benchmark/terminal-bench-2/scripts/run-gsd-ikie.sh +0 -0
- package/benchmark/terminal-bench-2/scripts/run-local.sh +0 -0
- package/benchmark/terminal-bench-2/scripts/run-opencode-ikie.sh +0 -0
- package/benchmark/terminal-bench-2/scripts/run-release.sh +0 -0
- package/package.json +103 -125
- package/scripts/dev-overlay.sh +0 -0
- package/scripts/dev-startup.sh +0 -0
- package/scripts/install.sh +0 -0
- package/scripts/prepublish-npm.js +25 -9
- package/scripts/verify-acp-load.mjs +0 -0
- package/src/cli-auth/index.test.ts +14 -10
- package/src/core/export-html/ansi-to-html.js +249 -0
- package/src/core/export-html/index.js +226 -0
- package/src/core/export-html/template.css +1066 -0
- package/src/core/export-html/template.html +66 -0
- package/src/core/export-html/template.js +1864 -0
- package/src/core/export-html/tool-renderer.js +108 -0
- package/src/core/export-html/vendor/highlight.min.js +1213 -0
- package/src/core/export-html/vendor/marked.min.js +6 -0
- package/src/extensions/agents/prompt/skill-loader.test.ts +18 -0
- package/src/extensions/agents/prompt/skill-loader.ts +4 -1
- package/src/extensions/prompt-construction/prompt-enrichment.test.ts +41 -0
- package/src/extensions/prompt-construction/prompt-enrichment.ts +4 -1
- package/src/extensions/skills-manager/skill-manager.test.ts +31 -14
- package/src/extensions/skills-manager/skill-manager.ts +14 -5
- package/src/extensions/skills-manager/skill-sanitizer.test.ts +287 -0
- package/src/extensions/skills-manager/skill-sanitizer.ts +269 -0
- package/src/models.test.ts +3 -1
- package/src/modes/interactive/theme/catppuccin-macchiato.json +82 -0
- package/src/modes/interactive/theme/dark.json +87 -0
- package/src/modes/interactive/theme/dracula.json +79 -0
- package/src/modes/interactive/theme/github-dark.json +80 -0
- package/src/modes/interactive/theme/github-light.json +80 -0
- package/src/modes/interactive/theme/ikie-light.json +92 -0
- package/src/modes/interactive/theme/ikie-minimal.json +79 -0
- package/src/modes/interactive/theme/ikie.json +96 -0
- package/src/modes/interactive/theme/light.json +86 -0
- package/src/modes/interactive/theme/lucent-orng.json +79 -0
- package/src/modes/interactive/theme/monokai.json +78 -0
- package/src/modes/interactive/theme/neon.json +87 -0
- package/src/modes/interactive/theme/night-owl.json +87 -0
- package/src/modes/interactive/theme/nord.json +82 -0
- package/src/modes/interactive/theme/one-dark.json +79 -0
- package/src/modes/interactive/theme/solarized-dark.json +81 -0
- package/src/modes/interactive/theme/solarized-light.json +81 -0
- package/src/modes/interactive/theme/theme-schema.json +335 -0
- package/vendor/superpowers/hooks/run-hook.cmd +0 -0
- package/vendor/superpowers/hooks/session-start +0 -0
- package/vendor/superpowers/scripts/bump-version.sh +0 -0
- package/vendor/superpowers/scripts/sync-to-codex-plugin.sh +0 -0
- package/vendor/superpowers/skills/brainstorming/scripts/start-server.sh +0 -0
- package/vendor/superpowers/skills/brainstorming/scripts/stop-server.sh +0 -0
- package/vendor/superpowers/skills/systematic-debugging/find-polluter.sh +0 -0
- package/vendor/superpowers/skills/writing-skills/render-graphs.js +0 -0
- package/vendor/superpowers/tests/brainstorm-server/windows-lifecycle.test.sh +0 -0
- package/vendor/superpowers/tests/claude-code/analyze-token-usage.py +0 -0
- package/vendor/superpowers/tests/claude-code/run-skill-tests.sh +0 -0
- package/vendor/superpowers/tests/claude-code/test-document-review-system.sh +0 -0
- package/vendor/superpowers/tests/claude-code/test-helpers.sh +0 -0
- package/vendor/superpowers/tests/claude-code/test-requesting-code-review.sh +0 -0
- package/vendor/superpowers/tests/claude-code/test-subagent-driven-development-integration.sh +0 -0
- package/vendor/superpowers/tests/claude-code/test-subagent-driven-development.sh +0 -0
- package/vendor/superpowers/tests/claude-code/test-worktree-native-preference.sh +0 -0
- package/vendor/superpowers/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh +0 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-all.sh +0 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-claude-describes-sdd.sh +0 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-extended-multiturn-test.sh +0 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-haiku-test.sh +0 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-multiturn-test.sh +0 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-test.sh +0 -0
- package/vendor/superpowers/tests/opencode/run-tests.sh +0 -0
- package/vendor/superpowers/tests/opencode/setup.sh +0 -0
- package/vendor/superpowers/tests/opencode/test-bootstrap-caching.sh +0 -0
- package/vendor/superpowers/tests/opencode/test-plugin-loading.sh +0 -0
- package/vendor/superpowers/tests/opencode/test-priority.sh +0 -0
- package/vendor/superpowers/tests/opencode/test-tools.sh +0 -0
- package/vendor/superpowers/tests/skill-triggering/run-all.sh +0 -0
- package/vendor/superpowers/tests/skill-triggering/run-test.sh +0 -0
- package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/scaffold.sh +0 -0
- package/vendor/superpowers/tests/subagent-driven-dev/run-test.sh +0 -0
- package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/scaffold.sh +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* marked v15.0.4 - a markdown parser
|
|
3
|
+
* Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed)
|
|
4
|
+
* https://github.com/markedjs/marked
|
|
5
|
+
*/
|
|
6
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}function n(t){e.defaults=t}e.defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};const s={exec:()=>null};function r(e,t=""){let n="string"==typeof e?e:e.source;const s={replace:(e,t)=>{let r="string"==typeof t?t:t.source;return r=r.replace(i.caret,"$1"),n=n.replace(e,r),s},getRegex:()=>new RegExp(n,t)};return s}const i={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>new RegExp(`^( {0,3}${e})((?:[\t ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),hrRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,"i")},l=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,o=/(?:[*+-]|\d{1,9}[.)])/,a=r(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g,o).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).getRegex(),c=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,h=/(?!\s*\])(?:\\.|[^\[\]\\])+/,p=r(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",h).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),u=r(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,o).getRegex(),g="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",k=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,f=r("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$))","i").replace("comment",k).replace("tag",g).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),d=r(c).replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",g).getRegex(),x={blockquote:r(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",d).getRegex(),code:/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,def:p,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:l,html:f,lheading:a,list:u,newline:/^(?:[ \t]*(?:\n|$))+/,paragraph:d,table:s,text:/^[^\n]+/},b=r("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3}\t)[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",g).getRegex(),w={...x,table:b,paragraph:r(c).replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",b).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",g).getRegex()},m={...x,html:r("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:\"[^\"]*\"|'[^']*'|\\s[^'\"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",k).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:s,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:r(c).replace("hr",l).replace("heading"," *#{1,6} *[^\n]").replace("lheading",a).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},y=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,$=/^( {2,}|\\)\n(?!\s*$)/,R=/[\p{P}\p{S}]/u,S=/[\s\p{P}\p{S}]/u,T=/[^\s\p{P}\p{S}]/u,z=r(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,S).getRegex(),A=r(/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,"u").replace(/punct/g,R).getRegex(),_=r("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)","gu").replace(/notPunctSpace/g,T).replace(/punctSpace/g,S).replace(/punct/g,R).getRegex(),P=r("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,T).replace(/punctSpace/g,S).replace(/punct/g,R).getRegex(),I=r(/\\(punct)/,"gu").replace(/punct/g,R).getRegex(),L=r(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),B=r(k).replace("(?:--\x3e|$)","--\x3e").getRegex(),C=r("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",B).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),E=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,q=r(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",E).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Z=r(/^!?\[(label)\]\[(ref)\]/).replace("label",E).replace("ref",h).getRegex(),v=r(/^!?\[(ref)\](?:\[\])?/).replace("ref",h).getRegex(),D={_backpedal:s,anyPunctuation:I,autolink:L,blockSkip:/\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g,br:$,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:s,emStrongLDelim:A,emStrongRDelimAst:_,emStrongRDelimUnd:P,escape:y,link:q,nolink:v,punctuation:z,reflink:Z,reflinkSearch:r("reflink|nolink(?!\\()","g").replace("reflink",Z).replace("nolink",v).getRegex(),tag:C,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,url:s},M={...D,link:r(/^!?\[(label)\]\((.*?)\)/).replace("label",E).getRegex(),reflink:r(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",E).getRegex()},O={...D,escape:r(y).replace("])","~|])").getRegex(),url:r(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/},Q={...O,br:r($).replace("{2,}","*").getRegex(),text:r(O.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},j={normal:x,gfm:w,pedantic:m},N={normal:D,gfm:O,breaks:Q,pedantic:M},G={"&":"&","<":"<",">":">",'"':""","'":"'"},H=e=>G[e];function X(e,t){if(t){if(i.escapeTest.test(e))return e.replace(i.escapeReplace,H)}else if(i.escapeTestNoEncode.test(e))return e.replace(i.escapeReplaceNoEncode,H);return e}function F(e){try{e=encodeURI(e).replace(i.percentDecode,"%")}catch{return null}return e}function U(e,t){const n=e.replace(i.findPipe,((e,t,n)=>{let s=!1,r=t;for(;--r>=0&&"\\"===n[r];)s=!s;return s?"|":" |"})).split(i.splitPipe);let s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length<t;)n.push("");for(;s<n.length;s++)n[s]=n[s].trim().replace(i.slashPipe,"|");return n}function J(e,t,n){const s=e.length;if(0===s)return"";let r=0;for(;r<s;){const i=e.charAt(s-r-1);if(i!==t||n){if(i===t||!n)break;r++}else r++}return e.slice(0,s-r)}function K(e,t,n,s,r){const i=t.href,l=t.title||null,o=e[1].replace(r.other.outputLinkReplace,"$1");if("!"!==e[0].charAt(0)){s.state.inLink=!0;const e={type:"link",raw:n,href:i,title:l,text:o,tokens:s.inlineTokens(o)};return s.state.inLink=!1,e}return{type:"image",raw:n,href:i,title:l,text:o}}class V{options;rules;lexer;constructor(t){this.options=t||e.defaults}space(e){const t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?e:J(e,"\n")}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n=function(e,t,n){const s=e.match(n.other.indentCodeCompensation);if(null===s)return t;const r=s[1];return t.split("\n").map((e=>{const t=e.match(n.other.beginningSpace);if(null===t)return e;const[s]=t;return s.length>=r.length?e.slice(r.length):e})).join("\n")}(e,t[3]||"",this.rules);return{type:"code",raw:e,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:n}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].trim();if(this.rules.other.endingHash.test(e)){const t=J(e,"#");this.options.pedantic?e=t.trim():t&&!this.rules.other.endingSpaceChar.test(t)||(e=t.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:e,tokens:this.lexer.inline(e)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:J(t[0],"\n")}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let e=J(t[0],"\n").split("\n"),n="",s="";const r=[];for(;e.length>0;){let t=!1;const i=[];let l;for(l=0;l<e.length;l++)if(this.rules.other.blockquoteStart.test(e[l]))i.push(e[l]),t=!0;else{if(t)break;i.push(e[l])}e=e.slice(l);const o=i.join("\n"),a=o.replace(this.rules.other.blockquoteSetextReplace,"\n $1").replace(this.rules.other.blockquoteSetextReplace2,"");n=n?`${n}\n${o}`:o,s=s?`${s}\n${a}`:a;const c=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(a,r,!0),this.lexer.state.top=c,0===e.length)break;const h=r.at(-1);if("code"===h?.type)break;if("blockquote"===h?.type){const t=h,i=t.raw+"\n"+e.join("\n"),l=this.blockquote(i);r[r.length-1]=l,n=n.substring(0,n.length-t.raw.length)+l.raw,s=s.substring(0,s.length-t.text.length)+l.text;break}if("list"!==h?.type);else{const t=h,i=t.raw+"\n"+e.join("\n"),l=this.list(i);r[r.length-1]=l,n=n.substring(0,n.length-h.raw.length)+l.raw,s=s.substring(0,s.length-t.raw.length)+l.raw,e=i.substring(r.at(-1).raw.length).split("\n")}}return{type:"blockquote",raw:n,tokens:r,text:s}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim();const s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=this.rules.other.listItemRegex(n);let l=!1;for(;e;){let n=!1,s="",o="";if(!(t=i.exec(e)))break;if(this.rules.block.hr.test(e))break;s=t[0],e=e.substring(s.length);let a=t[2].split("\n",1)[0].replace(this.rules.other.listReplaceTabs,(e=>" ".repeat(3*e.length))),c=e.split("\n",1)[0],h=!a.trim(),p=0;if(this.options.pedantic?(p=2,o=a.trimStart()):h?p=t[1].length+1:(p=t[2].search(this.rules.other.nonSpaceChar),p=p>4?1:p,o=a.slice(p),p+=t[1].length),h&&this.rules.other.blankLine.test(c)&&(s+=c+"\n",e=e.substring(c.length+1),n=!0),!n){const t=this.rules.other.nextBulletRegex(p),n=this.rules.other.hrRegex(p),r=this.rules.other.fencesBeginRegex(p),i=this.rules.other.headingBeginRegex(p),l=this.rules.other.htmlBeginRegex(p);for(;e;){const u=e.split("\n",1)[0];let g;if(c=u,this.options.pedantic?(c=c.replace(this.rules.other.listReplaceNesting," "),g=c):g=c.replace(this.rules.other.tabCharGlobal," "),r.test(c))break;if(i.test(c))break;if(l.test(c))break;if(t.test(c))break;if(n.test(c))break;if(g.search(this.rules.other.nonSpaceChar)>=p||!c.trim())o+="\n"+g.slice(p);else{if(h)break;if(a.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4)break;if(r.test(a))break;if(i.test(a))break;if(n.test(a))break;o+="\n"+c}h||c.trim()||(h=!0),s+=u+"\n",e=e.substring(u.length+1),a=g.slice(p)}}r.loose||(l?r.loose=!0:this.rules.other.doubleBlankLine.test(s)&&(l=!0));let u,g=null;this.options.gfm&&(g=this.rules.other.listIsTask.exec(o),g&&(u="[ ] "!==g[0],o=o.replace(this.rules.other.listReplaceTask,""))),r.items.push({type:"list_item",raw:s,task:!!g,checked:u,loose:!1,text:o,tokens:[]}),r.raw+=s}const o=r.items.at(-1);if(!o)return;o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd(),r.raw=r.raw.trimEnd();for(let e=0;e<r.items.length;e++)if(this.lexer.state.top=!1,r.items[e].tokens=this.lexer.blockTokens(r.items[e].text,[]),!r.loose){const t=r.items[e].tokens.filter((e=>"space"===e.type)),n=t.length>0&&t.some((e=>this.rules.other.anyLine.test(e.raw)));r.loose=n}if(r.loose)for(let e=0;e<r.items.length;e++)r.items[e].loose=!0;return r}}html(e){const t=this.rules.block.html.exec(e);if(t){return{type:"html",block:!0,raw:t[0],pre:"pre"===t[1]||"script"===t[1]||"style"===t[1],text:t[0]}}}def(e){const t=this.rules.block.def.exec(e);if(t){const e=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),n=t[2]?t[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",s=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:e,raw:t[0],href:n,title:s}}}table(e){const t=this.rules.block.table.exec(e);if(!t)return;if(!this.rules.other.tableDelimiter.test(t[2]))return;const n=U(t[1]),s=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split("\n"):[],i={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===s.length){for(const e of s)this.rules.other.tableAlignRight.test(e)?i.align.push("right"):this.rules.other.tableAlignCenter.test(e)?i.align.push("center"):this.rules.other.tableAlignLeft.test(e)?i.align.push("left"):i.align.push(null);for(let e=0;e<n.length;e++)i.header.push({text:n[e],tokens:this.lexer.inline(n[e]),header:!0,align:i.align[e]});for(const e of r)i.rows.push(U(e,i.header.length).map(((e,t)=>({text:e,tokens:this.lexer.inline(e),header:!1,align:i.align[t]}))));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e="\n"===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:e,tokens:this.lexer.inline(e)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(e)){if(!this.rules.other.endAngleBracket.test(e))return;const t=J(e.slice(0,-1),"\\");if((e.length-t.length)%2==0)return}else{const e=function(e,t){if(-1===e.indexOf(t[1]))return-1;let n=0;for(let s=0;s<e.length;s++)if("\\"===e[s])s++;else if(e[s]===t[0])n++;else if(e[s]===t[1]&&(n--,n<0))return s;return-1}(t[2],"()");if(e>-1){const n=(0===t[0].indexOf("!")?5:4)+t[1].length+e;t[2]=t[2].substring(0,e),t[0]=t[0].substring(0,n).trim(),t[3]=""}}let n=t[2],s="";if(this.options.pedantic){const e=this.rules.other.pedanticHrefTitle.exec(n);e&&(n=e[1],s=e[3])}else s=t[3]?t[3].slice(1,-1):"";return n=n.trim(),this.rules.other.startAngleBracket.test(n)&&(n=this.options.pedantic&&!this.rules.other.endAngleBracket.test(e)?n.slice(1):n.slice(1,-1)),K(t,{href:n?n.replace(this.rules.inline.anyPunctuation,"$1"):n,title:s?s.replace(this.rules.inline.anyPunctuation,"$1"):s},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const e=t[(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," ").toLowerCase()];if(!e){const e=n[0].charAt(0);return{type:"text",raw:e,text:e}}return K(n,e,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s)return;if(s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const n=[...s[0]].length-1;let r,i,l=n,o=0;const a="*"===s[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+n);null!=(s=a.exec(t));){if(r=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!r)continue;if(i=[...r].length,s[3]||s[4]){l+=i;continue}if((s[5]||s[6])&&n%3&&!((n+i)%3)){o+=i;continue}if(l-=i,l>0)continue;i=Math.min(i,i+l+o);const t=[...s[0]][0].length,a=e.slice(0,n+s.index+t+i);if(Math.min(n,i)%2){const e=a.slice(1,-1);return{type:"em",raw:a,text:e,tokens:this.lexer.inlineTokens(e)}}const c=a.slice(2,-2);return{type:"strong",raw:a,text:c,tokens:this.lexer.inlineTokens(c)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].replace(this.rules.other.newLineCharGlobal," ");const n=this.rules.other.nonSpaceChar.test(e),s=this.rules.other.startingSpaceChar.test(e)&&this.rules.other.endingSpaceChar.test(e);return n&&s&&(e=e.substring(1,e.length-1)),{type:"codespan",raw:t[0],text:e}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let e,n;return"@"===t[2]?(e=t[1],n="mailto:"+e):(e=t[1],n=e),{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let e,n;if("@"===t[2])e=t[0],n="mailto:"+e;else{let s;do{s=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??""}while(s!==t[0]);e=t[0],n="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){const e=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:e}}}}class W{tokens;options;state;tokenizer;inlineQueue;constructor(t){this.tokens=[],this.tokens.links=Object.create(null),this.options=t||e.defaults,this.options.tokenizer=this.options.tokenizer||new V,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};const n={other:i,block:j.normal,inline:N.normal};this.options.pedantic?(n.block=j.pedantic,n.inline=N.pedantic):this.options.gfm&&(n.block=j.gfm,this.options.breaks?n.inline=N.breaks:n.inline=N.gfm),this.tokenizer.rules=n}static get rules(){return{block:j,inline:N}}static lex(e,t){return new W(t).lex(e)}static lexInline(e,t){return new W(t).inlineTokens(e)}lex(e){e=e.replace(i.carriageReturn,"\n"),this.blockTokens(e,this.tokens);for(let e=0;e<this.inlineQueue.length;e++){const t=this.inlineQueue[e];this.inlineTokens(t.src,t.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],n=!1){for(this.options.pedantic&&(e=e.replace(i.tabCharGlobal," ").replace(i.spaceLine,""));e;){let s;if(this.options.extensions?.block?.some((n=>!!(s=n.call({lexer:this},e,t))&&(e=e.substring(s.raw.length),t.push(s),!0))))continue;if(s=this.tokenizer.space(e)){e=e.substring(s.raw.length);const n=t.at(-1);1===s.raw.length&&void 0!==n?n.raw+="\n":t.push(s);continue}if(s=this.tokenizer.code(e)){e=e.substring(s.raw.length);const n=t.at(-1);"paragraph"===n?.type||"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.text,this.inlineQueue.at(-1).src=n.text):t.push(s);continue}if(s=this.tokenizer.fences(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.heading(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.hr(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.blockquote(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.list(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.html(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.def(e)){e=e.substring(s.raw.length);const n=t.at(-1);"paragraph"===n?.type||"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.raw,this.inlineQueue.at(-1).src=n.text):this.tokens.links[s.tag]||(this.tokens.links[s.tag]={href:s.href,title:s.title});continue}if(s=this.tokenizer.table(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.lheading(e)){e=e.substring(s.raw.length),t.push(s);continue}let r=e;if(this.options.extensions?.startBlock){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startBlock.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(this.state.top&&(s=this.tokenizer.paragraph(r))){const i=t.at(-1);n&&"paragraph"===i?.type?(i.raw+="\n"+s.raw,i.text+="\n"+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=i.text):t.push(s),n=r.length!==e.length,e=e.substring(s.raw.length)}else if(s=this.tokenizer.text(e)){e=e.substring(s.raw.length);const n=t.at(-1);"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=n.text):t.push(s)}else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,s=null;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(s=this.tokenizer.rules.inline.reflinkSearch.exec(n));)e.includes(s[0].slice(s[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(s=this.tokenizer.rules.inline.blockSkip.exec(n));)n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(s=this.tokenizer.rules.inline.anyPunctuation.exec(n));)n=n.slice(0,s.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let r=!1,i="";for(;e;){let s;if(r||(i=""),r=!1,this.options.extensions?.inline?.some((n=>!!(s=n.call({lexer:this},e,t))&&(e=e.substring(s.raw.length),t.push(s),!0))))continue;if(s=this.tokenizer.escape(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.tag(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.link(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(s.raw.length);const n=t.at(-1);"text"===s.type&&"text"===n?.type?(n.raw+=s.raw,n.text+=s.text):t.push(s);continue}if(s=this.tokenizer.emStrong(e,n,i)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.codespan(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.br(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.del(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.autolink(e)){e=e.substring(s.raw.length),t.push(s);continue}if(!this.state.inLink&&(s=this.tokenizer.url(e))){e=e.substring(s.raw.length),t.push(s);continue}let l=e;if(this.options.extensions?.startInline){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startInline.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(l=e.substring(0,t+1))}if(s=this.tokenizer.inlineText(l)){e=e.substring(s.raw.length),"_"!==s.raw.slice(-1)&&(i=s.raw.slice(-1)),r=!0;const n=t.at(-1);"text"===n?.type?(n.raw+=s.raw,n.text+=s.text):t.push(s)}else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return t}}class Y{options;parser;constructor(t){this.options=t||e.defaults}space(e){return""}code({text:e,lang:t,escaped:n}){const s=(t||"").match(i.notSpaceStart)?.[0],r=e.replace(i.endingNewline,"")+"\n";return s?'<pre><code class="language-'+X(s)+'">'+(n?r:X(r,!0))+"</code></pre>\n":"<pre><code>"+(n?r:X(r,!0))+"</code></pre>\n"}blockquote({tokens:e}){return`<blockquote>\n${this.parser.parse(e)}</blockquote>\n`}html({text:e}){return e}heading({tokens:e,depth:t}){return`<h${t}>${this.parser.parseInline(e)}</h${t}>\n`}hr(e){return"<hr>\n"}list(e){const t=e.ordered,n=e.start;let s="";for(let t=0;t<e.items.length;t++){const n=e.items[t];s+=this.listitem(n)}const r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+s+"</"+r+">\n"}listitem(e){let t="";if(e.task){const n=this.checkbox({checked:!!e.checked});e.loose?"paragraph"===e.tokens[0]?.type?(e.tokens[0].text=n+" "+e.tokens[0].text,e.tokens[0].tokens&&e.tokens[0].tokens.length>0&&"text"===e.tokens[0].tokens[0].type&&(e.tokens[0].tokens[0].text=n+" "+X(e.tokens[0].tokens[0].text),e.tokens[0].tokens[0].escaped=!0)):e.tokens.unshift({type:"text",raw:n+" ",text:n+" ",escaped:!0}):t+=n+" "}return t+=this.parser.parse(e.tokens,!!e.loose),`<li>${t}</li>\n`}checkbox({checked:e}){return"<input "+(e?'checked="" ':"")+'disabled="" type="checkbox">'}paragraph({tokens:e}){return`<p>${this.parser.parseInline(e)}</p>\n`}table(e){let t="",n="";for(let t=0;t<e.header.length;t++)n+=this.tablecell(e.header[t]);t+=this.tablerow({text:n});let s="";for(let t=0;t<e.rows.length;t++){const r=e.rows[t];n="";for(let e=0;e<r.length;e++)n+=this.tablecell(r[e]);s+=this.tablerow({text:n})}return s&&(s=`<tbody>${s}</tbody>`),"<table>\n<thead>\n"+t+"</thead>\n"+s+"</table>\n"}tablerow({text:e}){return`<tr>\n${e}</tr>\n`}tablecell(e){const t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>\n`}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${X(e,!0)}</code>`}br(e){return"<br>"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){const s=this.parser.parseInline(n),r=F(e);if(null===r)return s;let i='<a href="'+(e=r)+'"';return t&&(i+=' title="'+X(t)+'"'),i+=">"+s+"</a>",i}image({href:e,title:t,text:n}){const s=F(e);if(null===s)return X(n);let r=`<img src="${e=s}" alt="${n}"`;return t&&(r+=` title="${X(t)}"`),r+=">",r}text(e){return"tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:X(e.text)}}class ee{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return""+e}image({text:e}){return""+e}br(){return""}}class te{options;renderer;textRenderer;constructor(t){this.options=t||e.defaults,this.options.renderer=this.options.renderer||new Y,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new ee}static parse(e,t){return new te(t).parse(e)}static parseInline(e,t){return new te(t).parseInline(e)}parse(e,t=!0){let n="";for(let s=0;s<e.length;s++){const r=e[s];if(this.options.extensions?.renderers?.[r.type]){const e=r,t=this.options.extensions.renderers[e.type].call({parser:this},e);if(!1!==t||!["space","hr","heading","code","table","blockquote","list","html","paragraph","text"].includes(e.type)){n+=t||"";continue}}const i=r;switch(i.type){case"space":n+=this.renderer.space(i);continue;case"hr":n+=this.renderer.hr(i);continue;case"heading":n+=this.renderer.heading(i);continue;case"code":n+=this.renderer.code(i);continue;case"table":n+=this.renderer.table(i);continue;case"blockquote":n+=this.renderer.blockquote(i);continue;case"list":n+=this.renderer.list(i);continue;case"html":n+=this.renderer.html(i);continue;case"paragraph":n+=this.renderer.paragraph(i);continue;case"text":{let r=i,l=this.renderer.text(r);for(;s+1<e.length&&"text"===e[s+1].type;)r=e[++s],l+="\n"+this.renderer.text(r);n+=t?this.renderer.paragraph({type:"paragraph",raw:l,text:l,tokens:[{type:"text",raw:l,text:l,escaped:!0}]}):l;continue}default:{const e='Token with "'+i.type+'" type was not found.';if(this.options.silent)return console.error(e),"";throw new Error(e)}}}return n}parseInline(e,t=this.renderer){let n="";for(let s=0;s<e.length;s++){const r=e[s];if(this.options.extensions?.renderers?.[r.type]){const e=this.options.extensions.renderers[r.type].call({parser:this},r);if(!1!==e||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(r.type)){n+=e||"";continue}}const i=r;switch(i.type){case"escape":case"text":n+=t.text(i);break;case"html":n+=t.html(i);break;case"link":n+=t.link(i);break;case"image":n+=t.image(i);break;case"strong":n+=t.strong(i);break;case"em":n+=t.em(i);break;case"codespan":n+=t.codespan(i);break;case"br":n+=t.br(i);break;case"del":n+=t.del(i);break;default:{const e='Token with "'+i.type+'" type was not found.';if(this.options.silent)return console.error(e),"";throw new Error(e)}}}return n}}class ne{options;block;constructor(t){this.options=t||e.defaults}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}provideLexer(){return this.block?W.lex:W.lexInline}provideParser(){return this.block?te.parse:te.parseInline}}class se{defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=te;Renderer=Y;TextRenderer=ee;Lexer=W;Tokenizer=V;Hooks=ne;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(const s of e)switch(n=n.concat(t.call(this,s)),s.type){case"table":{const e=s;for(const s of e.header)n=n.concat(this.walkTokens(s.tokens,t));for(const s of e.rows)for(const e of s)n=n.concat(this.walkTokens(e.tokens,t));break}case"list":{const e=s;n=n.concat(this.walkTokens(e.items,t));break}default:{const e=s;this.defaults.extensions?.childTokens?.[e.type]?this.defaults.extensions.childTokens[e.type].forEach((s=>{const r=e[s].flat(1/0);n=n.concat(this.walkTokens(r,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let s=e.renderer.apply(this,t);return!1===s&&(s=n.apply(this,t)),s}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new Y(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if(["options","parser"].includes(n))continue;const s=n,r=e.renderer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new V(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const s=n,r=e.tokenizer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new ne;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if(["options","block"].includes(n))continue;const s=n,r=e.hooks[s],i=t[s];ne.passThroughHooks.has(n)?t[s]=e=>{if(this.defaults.async)return Promise.resolve(r.call(t,e)).then((e=>i.call(t,e)));const n=r.call(t,e);return i.call(t,n)}:t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,s=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(s.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return W.lex(e,t??this.defaults)}parser(e,t){return te.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{const s={...n},r={...this.defaults,...s},i=this.onError(!!r.silent,!!r.async);if(!0===this.defaults.async&&!1===s.async)return i(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(null==t)return i(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof t)return i(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(t)+", string expected"));r.hooks&&(r.hooks.options=r,r.hooks.block=e);const l=r.hooks?r.hooks.provideLexer():e?W.lex:W.lexInline,o=r.hooks?r.hooks.provideParser():e?te.parse:te.parseInline;if(r.async)return Promise.resolve(r.hooks?r.hooks.preprocess(t):t).then((e=>l(e,r))).then((e=>r.hooks?r.hooks.processAllTokens(e):e)).then((e=>r.walkTokens?Promise.all(this.walkTokens(e,r.walkTokens)).then((()=>e)):e)).then((e=>o(e,r))).then((e=>r.hooks?r.hooks.postprocess(e):e)).catch(i);try{r.hooks&&(t=r.hooks.preprocess(t));let e=l(t,r);r.hooks&&(e=r.hooks.processAllTokens(e)),r.walkTokens&&this.walkTokens(e,r.walkTokens);let n=o(e,r);return r.hooks&&(n=r.hooks.postprocess(n)),n}catch(e){return i(e)}}}onError(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="<p>An error occurred:</p><pre>"+X(n.message+"",!0)+"</pre>";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}}const re=new se;function ie(e,t){return re.parse(e,t)}ie.options=ie.setOptions=function(e){return re.setOptions(e),ie.defaults=re.defaults,n(ie.defaults),ie},ie.getDefaults=t,ie.defaults=e.defaults,ie.use=function(...e){return re.use(...e),ie.defaults=re.defaults,n(ie.defaults),ie},ie.walkTokens=function(e,t){return re.walkTokens(e,t)},ie.parseInline=re.parseInline,ie.Parser=te,ie.parser=te.parse,ie.Renderer=Y,ie.TextRenderer=ee,ie.Lexer=W,ie.lexer=W.lex,ie.Tokenizer=V,ie.Hooks=ne,ie.parse=ie;const le=ie.options,oe=ie.setOptions,ae=ie.use,ce=ie.walkTokens,he=ie.parseInline,pe=ie,ue=te.parse,ge=W.lex;e.Hooks=ne,e.Lexer=W,e.Marked=se,e.Parser=te,e.Renderer=Y,e.TextRenderer=ee,e.Tokenizer=V,e.getDefaults=t,e.lexer=ge,e.marked=ie,e.options=le,e.parse=pe,e.parseInline=he,e.parser=ue,e.setOptions=oe,e.use=ae,e.walkTokens=ce}));
|
|
@@ -38,4 +38,22 @@ describe("preloadSkills", () => {
|
|
|
38
38
|
expect(results[0].name).toBe("my-skill")
|
|
39
39
|
expect(results[0].content).toContain("This is the skill content.")
|
|
40
40
|
})
|
|
41
|
+
|
|
42
|
+
it("normalizes an invalid skill name before loading", () => {
|
|
43
|
+
const base = join(tmpdir(), `ikie-skill-test-${Date.now()}`)
|
|
44
|
+
const cwd = join(base, "project")
|
|
45
|
+
|
|
46
|
+
// Place skill at <cwd>/.pi/agent/skills (second entry in DEFAULT_SKILL_PATHS)
|
|
47
|
+
const skillDir = join(cwd, ".pi", "agent", "skills", "ckm:slides")
|
|
48
|
+
mkdirSync(skillDir, { recursive: true })
|
|
49
|
+
writeFileSync(
|
|
50
|
+
join(skillDir, "SKILL.md"),
|
|
51
|
+
"---\nname: ckm:slides\ndescription: slides skill\n---\nSlides skill body.",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
const results = preloadSkills(["ckm-slides"], cwd)
|
|
55
|
+
expect(results).toHaveLength(1)
|
|
56
|
+
expect(results[0].name).toBe("ckm-slides")
|
|
57
|
+
expect(results[0].content).toContain("Slides skill body.")
|
|
58
|
+
})
|
|
41
59
|
})
|
|
@@ -10,8 +10,11 @@ import { isAbsolute, join } from "node:path"
|
|
|
10
10
|
import type { Skill } from "@earendil-works/pi-coding-agent"
|
|
11
11
|
import { loadSkillsFromDir } from "@earendil-works/pi-coding-agent"
|
|
12
12
|
import { DEFAULT_SKILL_PATHS } from "../../../config.js"
|
|
13
|
+
import { createSkillSanitizer } from "../../skills-manager/skill-sanitizer.js"
|
|
13
14
|
import { isUnsafeName } from "../memory/memory.js"
|
|
14
15
|
|
|
16
|
+
const skillSanitizer = createSkillSanitizer()
|
|
17
|
+
|
|
15
18
|
export interface PreloadedSkill {
|
|
16
19
|
name: string
|
|
17
20
|
content: string
|
|
@@ -44,7 +47,7 @@ export function preloadSkills(skillNames: string[], cwd: string): PreloadedSkill
|
|
|
44
47
|
const allSkills = new Map<string, Skill>()
|
|
45
48
|
for (const dir of resolvedPaths) {
|
|
46
49
|
try {
|
|
47
|
-
const { skills } = loadSkillsFromDir({ dir, source: dir })
|
|
50
|
+
const { skills } = loadSkillsFromDir({ dir: skillSanitizer.sanitizePath(dir), source: dir })
|
|
48
51
|
for (const skill of skills) {
|
|
49
52
|
// Later paths (higher priority) override earlier ones
|
|
50
53
|
allSkills.set(skill.name, skill)
|
|
@@ -3,6 +3,7 @@ import { arch, version as osVersion, platform, release, tmpdir } from "node:os"
|
|
|
3
3
|
import { join } from "node:path"
|
|
4
4
|
import type { AssistantMessage, ToolResultMessage } from "@earendil-works/pi-ai"
|
|
5
5
|
import type { ExtensionAPI, ToolInfo } from "@earendil-works/pi-coding-agent"
|
|
6
|
+
import { loadSkillsFromDir } from "@earendil-works/pi-coding-agent"
|
|
6
7
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
7
8
|
import * as config from "../../config.js"
|
|
8
9
|
import type { ModelMetadata } from "../../models.js"
|
|
@@ -509,6 +510,46 @@ describe("prompt enrichment Claude Code skills", () => {
|
|
|
509
510
|
|
|
510
511
|
expect(result.systemPrompt).not.toContain("<name>typescript-safety</name>")
|
|
511
512
|
})
|
|
513
|
+
|
|
514
|
+
it("sanitizes project skill names and emits no name-validation diagnostics", async () => {
|
|
515
|
+
const cwd = join(dir, "project")
|
|
516
|
+
const skillDir = join(cwd, ".ikie", "skills", "ckm-slides")
|
|
517
|
+
writeRawSkill(
|
|
518
|
+
join(skillDir, "SKILL.md"),
|
|
519
|
+
`---
|
|
520
|
+
name: ckm:slides
|
|
521
|
+
description: Ikie project slides skill.
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
# Slides
|
|
525
|
+
|
|
526
|
+
Slides skill body.
|
|
527
|
+
`,
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
const { createSkillSanitizer } = await import("../skills-manager/skill-sanitizer.js")
|
|
531
|
+
const sanitizer = createSkillSanitizer()
|
|
532
|
+
const sanitizedDir = sanitizer.sanitizePath(skillDir)
|
|
533
|
+
const directLoad = loadSkillsFromDir({ dir: sanitizedDir, source: "project" })
|
|
534
|
+
const nameDiagnostics = directLoad.diagnostics.filter(
|
|
535
|
+
(d) => d.type === "warning" && typeof d.message === "string" && d.message.toLowerCase().includes("name"),
|
|
536
|
+
)
|
|
537
|
+
expect(nameDiagnostics).toEqual([])
|
|
538
|
+
expect(directLoad.skills.map((s) => s.name)).toContain("ckm-slides")
|
|
539
|
+
sanitizer.cleanup()
|
|
540
|
+
|
|
541
|
+
const { beforeAgentStart } = buildPromptExtensionWithHandlers([])
|
|
542
|
+
if (!beforeAgentStart) throw new Error("before_agent_start handler was not registered")
|
|
543
|
+
|
|
544
|
+
const result = (await beforeAgentStart(
|
|
545
|
+
{},
|
|
546
|
+
{ cwd, model: undefined, hasUI: false, sessionManager: { getSessionId: () => "session-1" } },
|
|
547
|
+
)) as { systemPrompt: string }
|
|
548
|
+
|
|
549
|
+
expect(result.systemPrompt).toContain("<available_skills>")
|
|
550
|
+
expect(result.systemPrompt).toContain("<name>ckm-slides</name>")
|
|
551
|
+
expect(result.systemPrompt).toContain("Ikie project slides skill.")
|
|
552
|
+
})
|
|
512
553
|
})
|
|
513
554
|
|
|
514
555
|
describe("append system prompt", () => {
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
splitModelRef,
|
|
64
64
|
validateModelRoles,
|
|
65
65
|
} from "../orchestration/model-roles.js"
|
|
66
|
+
import { createSkillSanitizer } from "../skills-manager/skill-sanitizer.js"
|
|
66
67
|
import { getCurrentPhase } from "../tags.js"
|
|
67
68
|
import { type ContextFile, loadGlobalContextFiles, loadProjectContextFiles } from "./context-files.js"
|
|
68
69
|
import {
|
|
@@ -476,6 +477,8 @@ export default function (skillPaths: string[]) {
|
|
|
476
477
|
const cachedUsername = safeUsername()
|
|
477
478
|
const cachedHomeDir = homedir()
|
|
478
479
|
|
|
480
|
+
const skillSanitizer = createSkillSanitizer()
|
|
481
|
+
|
|
479
482
|
let cachedContextFiles: ContextFile[] | undefined
|
|
480
483
|
let cachedSkills: Skill[] | undefined
|
|
481
484
|
let cachedGitRemote: string | undefined | null = null
|
|
@@ -505,7 +508,7 @@ export default function (skillPaths: string[]) {
|
|
|
505
508
|
cachedSkills = loadSkills({
|
|
506
509
|
cwd: ctx.cwd,
|
|
507
510
|
agentDir: getAgentDir(),
|
|
508
|
-
skillPaths: allSkillPaths,
|
|
511
|
+
skillPaths: allSkillPaths.map((p) => skillSanitizer.sanitizePath(p)),
|
|
509
512
|
includeDefaults: false,
|
|
510
513
|
}).skills
|
|
511
514
|
}
|
|
@@ -15,36 +15,53 @@ import {
|
|
|
15
15
|
|
|
16
16
|
describe("validateName", () => {
|
|
17
17
|
const valid = (name: string) => expect(validateName(name)).toBeNull()
|
|
18
|
-
const invalid = (name: string
|
|
19
|
-
|
|
20
|
-
expect(result).not.toBeNull()
|
|
21
|
-
expect(result?.toLowerCase()).toContain(contains)
|
|
18
|
+
const invalid = (name: string) => {
|
|
19
|
+
expect(validateName(name)).not.toBeNull()
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
it("accepts valid names", () => {
|
|
23
|
+
valid("ckm-slides")
|
|
24
|
+
valid("ui-ux-pro-max")
|
|
25
25
|
valid("systematic-debugging")
|
|
26
|
-
valid("debug_v2")
|
|
27
|
-
valid("foo.bar")
|
|
28
26
|
valid("abc123")
|
|
29
27
|
})
|
|
30
28
|
|
|
31
|
-
it("rejects names
|
|
32
|
-
invalid("
|
|
33
|
-
|
|
29
|
+
it("rejects names with colons", () => {
|
|
30
|
+
invalid("ckm:slides")
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it("rejects names with underscores", () => {
|
|
34
|
+
invalid("foo_bar")
|
|
35
|
+
invalid("debug_v2")
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it("rejects names with dots", () => {
|
|
39
|
+
invalid("foo.bar")
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it("rejects names with a leading hyphen", () => {
|
|
43
|
+
invalid("-bad")
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it("rejects names with consecutive hyphens", () => {
|
|
47
|
+
invalid("bad--bad")
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it("rejects names starting with an underscore", () => {
|
|
51
|
+
invalid("_bar")
|
|
34
52
|
})
|
|
35
53
|
|
|
36
54
|
it("rejects uppercase letters", () => {
|
|
37
|
-
invalid("Foo"
|
|
38
|
-
invalid("SYSTEM"
|
|
55
|
+
invalid("Foo")
|
|
56
|
+
invalid("SYSTEM")
|
|
39
57
|
})
|
|
40
58
|
|
|
41
59
|
it("rejects names longer than 64 chars", () => {
|
|
42
|
-
invalid("a".repeat(65)
|
|
60
|
+
invalid("a".repeat(65))
|
|
43
61
|
})
|
|
44
62
|
|
|
45
63
|
it("rejects names with spaces", () => {
|
|
46
|
-
|
|
47
|
-
expect(result).not.toBeNull()
|
|
64
|
+
invalid("foo bar")
|
|
48
65
|
})
|
|
49
66
|
})
|
|
50
67
|
|
|
@@ -44,23 +44,32 @@ export interface SkillManageResult {
|
|
|
44
44
|
path?: string
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
// Agent Skills spec: only lowercase a-z, 0-9, hyphens; no leading/trailing
|
|
48
|
+
// hyphens; no consecutive hyphens; max 64 characters.
|
|
49
|
+
const SKILL_NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/
|
|
50
|
+
// Category directory names are filesystem-side only, so they allow a broader
|
|
51
|
+
// set of characters (dots, underscores) but still reject spaces and must
|
|
52
|
+
// start with a lowercase letter or digit.
|
|
53
|
+
const CATEGORY_RE = /^[a-z0-9][a-z0-9._-]*$/
|
|
48
54
|
const MAX_NAME_LEN = 64
|
|
49
55
|
const ALLOWED_SUBDIRS = new Set(["references", "templates", "scripts", "assets"])
|
|
50
56
|
|
|
51
57
|
export function validateName(name: string): string | null {
|
|
52
58
|
if (name.length === 0) return "Name cannot be empty."
|
|
53
59
|
if (name.length > MAX_NAME_LEN) return `Name must be at most ${MAX_NAME_LEN} characters.`
|
|
54
|
-
if (!
|
|
55
|
-
|
|
56
|
-
return "Name must contain only lowercase letters, digits, dots, underscores, or hyphens."
|
|
60
|
+
if (!SKILL_NAME_RE.test(name)) {
|
|
61
|
+
return "Name must contain only lowercase letters, digits, and hyphens, with no leading or trailing hyphens or consecutive hyphens."
|
|
57
62
|
}
|
|
58
63
|
return null
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
export function validateCategory(category?: string): string | null {
|
|
62
67
|
if (!category) return null
|
|
63
|
-
|
|
68
|
+
if (category.length > MAX_NAME_LEN) return `Category must be at most ${MAX_NAME_LEN} characters.`
|
|
69
|
+
if (!CATEGORY_RE.test(category)) {
|
|
70
|
+
return "Category must start with a lowercase letter or digit and contain only lowercase letters, digits, dots, underscores, or hyphens."
|
|
71
|
+
}
|
|
72
|
+
return null
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
/**
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { tmpdir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
import { loadSkillsFromDir } from "@earendil-works/pi-coding-agent"
|
|
5
|
+
import { afterEach, describe, expect, it } from "vitest"
|
|
6
|
+
import { createSkillSanitizer, isValidSkillName, normalizeSkillName, sanitizeSkillMarkdown } from "./skill-sanitizer.js"
|
|
7
|
+
|
|
8
|
+
describe("normalizeSkillName", () => {
|
|
9
|
+
it("lowercases input", () => {
|
|
10
|
+
expect(normalizeSkillName("FooBar")).toBe("foobar")
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it("replaces runs of invalid chars with a single hyphen", () => {
|
|
14
|
+
expect(normalizeSkillName("ckm:slides")).toBe("ckm-slides")
|
|
15
|
+
expect(normalizeSkillName("foo_bar")).toBe("foo-bar")
|
|
16
|
+
expect(normalizeSkillName("a b")).toBe("a-b")
|
|
17
|
+
expect(normalizeSkillName("a___b")).toBe("a-b")
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it("trims leading and trailing hyphens", () => {
|
|
21
|
+
expect(normalizeSkillName("-foo-")).toBe("foo")
|
|
22
|
+
expect(normalizeSkillName("---bar---")).toBe("bar")
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it("truncates to 64 characters", () => {
|
|
26
|
+
const long = "a".repeat(100)
|
|
27
|
+
expect(normalizeSkillName(long)).toHaveLength(64)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it("falls back to 'skill' when empty after normalization", () => {
|
|
31
|
+
expect(normalizeSkillName("")).toBe("skill")
|
|
32
|
+
expect(normalizeSkillName("___")).toBe("skill")
|
|
33
|
+
expect(normalizeSkillName("---")).toBe("skill")
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it("collapses consecutive hyphens", () => {
|
|
37
|
+
expect(normalizeSkillName("foo--bar")).toBe("foo-bar")
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe("isValidSkillName", () => {
|
|
42
|
+
it("accepts valid names", () => {
|
|
43
|
+
expect(isValidSkillName("ckm-slides")).toBe(true)
|
|
44
|
+
expect(isValidSkillName("ui-ux-pro-max")).toBe(true)
|
|
45
|
+
expect(isValidSkillName("abc")).toBe(true)
|
|
46
|
+
expect(isValidSkillName("a1b2")).toBe(true)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it("rejects empty or too long", () => {
|
|
50
|
+
expect(isValidSkillName("")).toBe(false)
|
|
51
|
+
expect(isValidSkillName("a".repeat(65))).toBe(false)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it("rejects invalid characters", () => {
|
|
55
|
+
expect(isValidSkillName("ckm:slides")).toBe(false)
|
|
56
|
+
expect(isValidSkillName("Foo_Bar")).toBe(false)
|
|
57
|
+
expect(isValidSkillName("foo.bar")).toBe(false)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it("rejects leading/trailing hyphens", () => {
|
|
61
|
+
expect(isValidSkillName("-bad")).toBe(false)
|
|
62
|
+
expect(isValidSkillName("bad-")).toBe(false)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it("rejects consecutive hyphens", () => {
|
|
66
|
+
expect(isValidSkillName("bad--bad")).toBe(false)
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe("sanitizeSkillMarkdown", () => {
|
|
71
|
+
it("leaves valid skill content unchanged", () => {
|
|
72
|
+
const input = `---
|
|
73
|
+
name: ckm-slides
|
|
74
|
+
description: My slides skill
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
# Body
|
|
78
|
+
|
|
79
|
+
Some content.`
|
|
80
|
+
expect(sanitizeSkillMarkdown(input)).toBe(input)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it("rewrites name: ckm:slides to quoted normalized form", () => {
|
|
84
|
+
const input = `---
|
|
85
|
+
name: ckm:slides
|
|
86
|
+
description: slides
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
Body content`
|
|
90
|
+
const out = sanitizeSkillMarkdown(input)
|
|
91
|
+
expect(out).toContain('name: "ckm-slides"')
|
|
92
|
+
expect(out).not.toContain("ckm:slides")
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it("rewrites name: Foo_Bar to quoted normalized form", () => {
|
|
96
|
+
const input = `---
|
|
97
|
+
name: Foo_Bar
|
|
98
|
+
description: foo bar
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
Body`
|
|
102
|
+
const out = sanitizeSkillMarkdown(input)
|
|
103
|
+
expect(out).toContain('name: "foo-bar"')
|
|
104
|
+
expect(out).not.toContain("Foo_Bar")
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it("preserves body content", () => {
|
|
108
|
+
const input = `---
|
|
109
|
+
name: ckm:slides
|
|
110
|
+
description: slides
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
# Heading
|
|
114
|
+
|
|
115
|
+
Important body content with code:
|
|
116
|
+
|
|
117
|
+
\`\`\`bash
|
|
118
|
+
echo hi
|
|
119
|
+
\`\`\`
|
|
120
|
+
`
|
|
121
|
+
const out = sanitizeSkillMarkdown(input)
|
|
122
|
+
expect(out).toContain("# Heading")
|
|
123
|
+
expect(out).toContain("Important body content")
|
|
124
|
+
expect(out).toContain("echo hi")
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it("preserves non-name frontmatter keys", () => {
|
|
128
|
+
const input = `---
|
|
129
|
+
name: ckm:slides
|
|
130
|
+
description: slides
|
|
131
|
+
allowed-tools: Read, Write
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
Body`
|
|
135
|
+
const out = sanitizeSkillMarkdown(input)
|
|
136
|
+
expect(out).toContain('name: "ckm-slides"')
|
|
137
|
+
expect(out).toContain("allowed-tools: Read, Write")
|
|
138
|
+
expect(out).toContain("description: slides")
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it("returns content unchanged when name is missing", () => {
|
|
142
|
+
const input = `---
|
|
143
|
+
description: only description
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
Body`
|
|
147
|
+
expect(sanitizeSkillMarkdown(input)).toBe(input)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it("returns content unchanged when there is no frontmatter", () => {
|
|
151
|
+
const input = "Just a body with no frontmatter."
|
|
152
|
+
expect(sanitizeSkillMarkdown(input)).toBe(input)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it("returns content unchanged on frontmatter parse failure", () => {
|
|
156
|
+
const input = `---
|
|
157
|
+
name: ckm:slides
|
|
158
|
+
description: [unterminated
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
Body`
|
|
162
|
+
expect(sanitizeSkillMarkdown(input)).toBe(input)
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
describe("createSkillSanitizer / sanitizeDir", () => {
|
|
167
|
+
let createdTempDirs: string[] = []
|
|
168
|
+
|
|
169
|
+
afterEach(() => {
|
|
170
|
+
for (const d of createdTempDirs) {
|
|
171
|
+
try {
|
|
172
|
+
rmSync(d, { recursive: true, force: true })
|
|
173
|
+
} catch {
|
|
174
|
+
// ignore
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
createdTempDirs = []
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
function makeSourceDir(files: Record<string, string>): string {
|
|
181
|
+
const dir = mkdtempSync(join(tmpdir(), "ikie-sanitizer-test-src-"))
|
|
182
|
+
createdTempDirs.push(dir)
|
|
183
|
+
for (const [relPath, content] of Object.entries(files)) {
|
|
184
|
+
const full = join(dir, relPath)
|
|
185
|
+
mkdirSync(join(full, ".."), { recursive: true })
|
|
186
|
+
writeFileSync(full, content, "utf-8")
|
|
187
|
+
}
|
|
188
|
+
return dir
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
it("produces a directory that loads cleanly via upstream loadSkillsFromDir", () => {
|
|
192
|
+
const source = makeSourceDir({
|
|
193
|
+
"ckm:slides/SKILL.md": `---
|
|
194
|
+
name: ckm:slides
|
|
195
|
+
description: slides skill
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
body`,
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const sanitizer = createSkillSanitizer()
|
|
202
|
+
const sanitizedDir = sanitizer.sanitizeDir(source)
|
|
203
|
+
createdTempDirs.push(sanitizedDir)
|
|
204
|
+
expect(existsSync(join(sanitizedDir, "ckm:slides", "SKILL.md"))).toBe(true)
|
|
205
|
+
|
|
206
|
+
const result = loadSkillsFromDir({ dir: sanitizedDir, source: "user" })
|
|
207
|
+
const nameDiagnostics = result.diagnostics.filter(
|
|
208
|
+
(d) => typeof d.message === "string" && d.message.toLowerCase().includes("name"),
|
|
209
|
+
)
|
|
210
|
+
expect(nameDiagnostics).toEqual([])
|
|
211
|
+
expect(result.skills.length).toBe(1)
|
|
212
|
+
expect(result.skills[0].name).toBe("ckm-slides")
|
|
213
|
+
|
|
214
|
+
const sanitizedContent = readFileSync(join(sanitizedDir, "ckm:slides", "SKILL.md"), "utf-8")
|
|
215
|
+
expect(sanitizedContent).toContain('name: "ckm-slides"')
|
|
216
|
+
|
|
217
|
+
sanitizer.cleanup()
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it("sanitizePath handles a directory via sanitizeDir", () => {
|
|
221
|
+
const source = makeSourceDir({
|
|
222
|
+
"ckm:slides/SKILL.md": `---
|
|
223
|
+
name: ckm:slides
|
|
224
|
+
description: slides skill
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
body`,
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
const sanitizer = createSkillSanitizer()
|
|
231
|
+
const sanitizedDir = sanitizer.sanitizePath(source)
|
|
232
|
+
createdTempDirs.push(sanitizedDir)
|
|
233
|
+
expect(existsSync(join(sanitizedDir, "ckm:slides", "SKILL.md"))).toBe(true)
|
|
234
|
+
|
|
235
|
+
const result = loadSkillsFromDir({ dir: sanitizedDir, source: "user" })
|
|
236
|
+
const nameDiagnostics = result.diagnostics.filter(
|
|
237
|
+
(d) => typeof d.message === "string" && d.message.toLowerCase().includes("name"),
|
|
238
|
+
)
|
|
239
|
+
expect(nameDiagnostics).toEqual([])
|
|
240
|
+
expect(result.skills.length).toBe(1)
|
|
241
|
+
expect(result.skills[0].name).toBe("ckm-slides")
|
|
242
|
+
|
|
243
|
+
sanitizer.cleanup()
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it("sanitizePath handles a single .md file by copying it into a cached skill directory", () => {
|
|
247
|
+
const sourceDir = mkdtempSync(join(tmpdir(), "ikie-sanitizer-test-src-"))
|
|
248
|
+
createdTempDirs.push(sourceDir)
|
|
249
|
+
const sourceFile = join(sourceDir, "ckm:slides.md")
|
|
250
|
+
writeFileSync(
|
|
251
|
+
sourceFile,
|
|
252
|
+
`---
|
|
253
|
+
name: ckm:slides
|
|
254
|
+
description: slides skill
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
body content`,
|
|
258
|
+
"utf-8",
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
const sanitizer = createSkillSanitizer()
|
|
262
|
+
const sanitizedDir = sanitizer.sanitizePath(sourceFile)
|
|
263
|
+
createdTempDirs.push(sanitizedDir)
|
|
264
|
+
expect(existsSync(join(sanitizedDir, "SKILL.md"))).toBe(true)
|
|
265
|
+
|
|
266
|
+
const result = loadSkillsFromDir({ dir: sanitizedDir, source: "user" })
|
|
267
|
+
const nameDiagnostics = result.diagnostics.filter(
|
|
268
|
+
(d) => typeof d.message === "string" && d.message.toLowerCase().includes("name"),
|
|
269
|
+
)
|
|
270
|
+
expect(nameDiagnostics).toEqual([])
|
|
271
|
+
expect(result.skills.length).toBe(1)
|
|
272
|
+
expect(result.skills[0].name).toBe("ckm-slides")
|
|
273
|
+
|
|
274
|
+
const sanitizedContent = readFileSync(join(sanitizedDir, "SKILL.md"), "utf-8")
|
|
275
|
+
expect(sanitizedContent).toContain('name: "ckm-slides"')
|
|
276
|
+
expect(sanitizedContent).toContain("body content")
|
|
277
|
+
|
|
278
|
+
sanitizer.cleanup()
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
it("sanitizePath returns the original path for non-existent paths", () => {
|
|
282
|
+
const sanitizer = createSkillSanitizer()
|
|
283
|
+
const missing = join(tmpdir(), "ikie-sanitizer-missing-", Date.now().toString())
|
|
284
|
+
expect(sanitizer.sanitizePath(missing)).toBe(missing)
|
|
285
|
+
sanitizer.cleanup()
|
|
286
|
+
})
|
|
287
|
+
})
|