@ikie-dev/cli 9.8.1
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/.envrc +3 -0
- package/.github/CODEOWNERS +16 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +85 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- package/.github/ISSUE_TEMPLATE/question.yml +16 -0
- package/.github/actions/setup/action.yml +49 -0
- package/.github/pull_request_template.md +18 -0
- package/.github/release.yml +17 -0
- package/.github/workflows/acp-e2e.yml +52 -0
- package/.github/workflows/arc-terminal-bench-poc.yml +157 -0
- package/.github/workflows/auto-label-pr.yml +90 -0
- package/.github/workflows/canary.yml +302 -0
- package/.github/workflows/ci.yml +114 -0
- package/.github/workflows/close-stale.yml +21 -0
- package/.github/workflows/release.yml +288 -0
- package/.github/workflows/require-linked-issue.yml +21 -0
- package/.github/workflows/stale.yml +32 -0
- package/.github/workflows/tui-e2e.yml +52 -0
- package/.github/workflows/welcome.yml +21 -0
- package/.gitmodules +3 -0
- package/.husky/pre-commit +1 -0
- package/.ikie/ferments/019f2735-088f-75e4-9a8f-7d7b037c2a59/runtime.json +11 -0
- package/.ikie/ferments/019f2735-08b3-70fe-88df-8dd1494f6a8e/runtime.json +11 -0
- package/.ikie/ferments/019f2735-08d3-7041-8d5e-a153e2937274/runtime.json +11 -0
- package/.ikie/ferments/019f2735-08f8-7591-bf1a-6c1324842331/runtime.json +12 -0
- package/.ikie/ferments/019f2735-0913-73d5-82b4-37012a5c1148/runtime.json +11 -0
- package/.ikie/ferments/019f2735-0940-76dc-b667-964b9cd9294d/runtime.json +11 -0
- package/.ikie/ferments/019f2735-0971-7094-92e3-b8ea4cdb9390/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0999-72aa-9727-f6e8c3427ed6/runtime.json +15 -0
- package/.ikie/ferments/019f2735-09bf-76dd-88a2-c7e574b45636/runtime.json +15 -0
- package/.ikie/ferments/019f2735-09f1-77af-8820-89c0b3b5a182/runtime.json +13 -0
- package/.ikie/ferments/019f2735-0a49-77d9-b4c7-5a80bbbbafd9/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0a79-73c3-977b-0c9164267b94/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0abd-70ba-a794-fbb63fbf23de/runtime.json +11 -0
- package/.ikie/ferments/019f2735-0ad6-7079-8576-8fb651b4b698/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0b03-70db-b5e5-59b1869aa2dc/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0b34-7675-a4ed-39a15333e3b8/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0b6c-716e-9f92-c391d6acb6f0/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0b90-72be-a60d-3dd4c514d1c3/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0baf-72e7-b5c5-99d8533b8343/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0bd8-70f8-9d83-1a2b9152a013/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0bfa-70de-ad20-7fe8c41b968e/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0c26-7246-a2ab-f24f5a76fc5f/runtime.json +15 -0
- package/.ikie/ferments/019f2735-0c49-771b-934f-4afdb5664666/runtime.json +11 -0
- package/.ikie/ferments/019f2735-0c63-73f8-944e-14d19e69ba41/runtime.json +11 -0
- package/.ikie/ferments/019f2735-0c80-772b-8530-2df4d15b9d7a/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2735-0c80-772b-8530-2df4d15b9d7a/runtime.json +17 -0
- package/.ikie/ferments/019f2735-0dfc-7551-b147-aa46815027f5/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2735-0dfc-7551-b147-aa46815027f5/runtime.json +17 -0
- package/.ikie/ferments/019f2735-0f74-70f6-804c-e4d2145b32e1/runtime.json +11 -0
- package/.ikie/ferments/019f2735-1354-7041-854e-e6a577467dd0/runtime.json +11 -0
- package/.ikie/ferments/019f2735-1371-749f-8ea9-01f7f8734568/runtime.json +11 -0
- package/.ikie/ferments/019f2735-138f-72f2-ba7b-7912ad4cd7b9/runtime.json +11 -0
- package/.ikie/ferments/019f2735-13ad-710a-9c4d-38a30a0f4b37/runtime.json +11 -0
- package/.ikie/ferments/019f2735-13cb-7698-88c1-890fba497dc0/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2735-13da-77dd-a916-8d82348671d2/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2735-14d3-727a-81db-347c03cb2919/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2735-1521-736e-8b75-22e94a8775f7/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2735-1542-777c-a3a7-bc7f1edf1922/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2735-3528-75bc-b100-8deb63dfde55/runtime.json +13 -0
- package/.ikie/ferments/019f2735-3553-72d8-a60d-9357420e110a/runtime.json +11 -0
- package/.ikie/ferments/019f2735-3569-756b-bc90-01c9ab00e413/runtime.json +11 -0
- package/.ikie/ferments/019f2735-3583-71d0-83f9-fc40b292190b/runtime.json +11 -0
- package/.ikie/ferments/019f2735-3597-7571-8332-47b3443395a6/runtime.json +11 -0
- package/.ikie/ferments/019f2735-35b3-74fe-a5db-82651a97cf0d/runtime.json +11 -0
- package/.ikie/ferments/019f2735-35de-741a-94e7-7b89c4eaaa43/runtime.json +11 -0
- package/.ikie/ferments/019f2735-35f5-713c-9892-f6179e783d02/runtime.json +11 -0
- package/.ikie/ferments/019f2735-360d-7056-a5e0-43fb3eb0f98e/runtime.json +9 -0
- package/.ikie/ferments/019f2735-362e-756c-b848-34f3c3c4602b/runtime.json +13 -0
- package/.ikie/ferments/019f2735-364a-76f9-bfba-ba52ca3852fd/runtime.json +11 -0
- package/.ikie/ferments/019f2735-3662-754c-8a88-807a68e0790e/runtime.json +11 -0
- package/.ikie/ferments/019f2735-36c2-71f9-a003-2921a1792be1/runtime.json +11 -0
- package/.ikie/ferments/019f2735-36d6-751d-9776-1e1def988d2d/runtime.json +9 -0
- package/.ikie/ferments/019f2735-36ef-70bf-a6b2-f2a0944f1b7e/runtime.json +9 -0
- package/.ikie/ferments/019f2735-3712-77e3-a46e-c69470e4e850/runtime.json +11 -0
- package/.ikie/ferments/019f2735-37cf-712f-bfaa-8fc9e29da513/runtime.json +11 -0
- package/.ikie/ferments/019f2735-37ed-727a-8a74-fe716d22571d/runtime.json +12 -0
- package/.ikie/ferments/019f2735-3810-7370-b587-eef0bb9d4d81/runtime.json +11 -0
- package/.ikie/ferments/019f2735-3828-71ad-9ee9-62fa0f46cad7/runtime.json +11 -0
- package/.ikie/ferments/019f2735-383f-722b-8d96-5038b9c9aa5a/runtime.json +11 -0
- package/.ikie/ferments/019f2735-385a-72c8-b269-a87a416c5a10/runtime.json +11 -0
- package/.ikie/ferments/019f2735-386d-73fe-be0a-1bc89a0264c4/runtime.json +13 -0
- package/.ikie/ferments/019f2735-388a-7276-9bee-81dcd177953f/runtime.json +11 -0
- package/.ikie/ferments/019f2735-82ed-74e8-870d-d8678feaf7bb/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2735-82ed-74e8-870d-d8678feaf7bb/runtime.json +11 -0
- package/.ikie/ferments/019f2735-831e-70aa-b9d6-1214165775d0/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2735-831e-70aa-b9d6-1214165775d0/runtime.json +13 -0
- package/.ikie/ferments/019f2735-835e-73b3-bb48-2d0080526fc3/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2735-835e-73b3-bb48-2d0080526fc3/runtime.json +9 -0
- package/.ikie/ferments/019f2735-8379-74b6-b62f-816bb5276a85/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2735-8379-74b6-b62f-816bb5276a85/runtime.json +9 -0
- package/.ikie/ferments/019f2735-8391-7385-bab6-03362866622a/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2735-8391-7385-bab6-03362866622a/runtime.json +9 -0
- package/.ikie/ferments/019f2735-83ad-7251-8280-aa6f7f3bfc5e/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2735-83ad-7251-8280-aa6f7f3bfc5e/runtime.json +9 -0
- package/.ikie/ferments/019f2735-83d2-77be-984e-fb65263a3a5b/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2735-83d2-77be-984e-fb65263a3a5b/runtime.json +9 -0
- package/.ikie/ferments/019f2735-83ec-7743-acc5-b2bf14c3cc54/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2735-83ec-7743-acc5-b2bf14c3cc54/runtime.json +9 -0
- package/.ikie/ferments/019f2740-c8c5-720f-b641-214bb99d8a83/runtime.json +11 -0
- package/.ikie/ferments/019f2740-c8fb-763f-8310-88c7e558e410/runtime.json +11 -0
- package/.ikie/ferments/019f2740-c917-70d2-8be6-15f376c60a70/runtime.json +11 -0
- package/.ikie/ferments/019f2740-c984-711f-a903-4b2251918413/runtime.json +12 -0
- package/.ikie/ferments/019f2740-ca09-71cf-93a5-86efc136ecd5/runtime.json +11 -0
- package/.ikie/ferments/019f2740-ca46-77f4-ae02-88e42f2153fb/runtime.json +15 -0
- package/.ikie/ferments/019f2740-ca74-72dd-8855-3feedfa071db/runtime.json +15 -0
- package/.ikie/ferments/019f2740-ca9a-710b-9bb7-feffa42cdb36/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cac9-7518-ae93-973e4cf364ce/runtime.json +13 -0
- package/.ikie/ferments/019f2740-cb04-71c1-83a7-a448fefc6764/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cb35-743b-bc18-434c7c233a08/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cb6e-742c-970b-1893b4bf4e87/runtime.json +11 -0
- package/.ikie/ferments/019f2740-cb92-76a7-bd20-fd4f3f17664f/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cbc1-7509-8542-302d2d1d3084/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cbfa-719d-94c0-9d03a864e7e1/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cc31-75f8-82a0-7d8078979000/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cc58-765b-9f0c-c3aa2e09f27b/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cc7c-7375-99b4-e90496e819e3/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cca3-704a-bc20-e8c35cff6cec/runtime.json +15 -0
- package/.ikie/ferments/019f2740-ccd1-71cf-b8e8-be3527117f9a/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cd0c-771f-ba4a-9188c31f3ee4/runtime.json +15 -0
- package/.ikie/ferments/019f2740-cd39-778e-a052-cc7f522f022d/runtime.json +11 -0
- package/.ikie/ferments/019f2740-cd5f-725e-8ec7-48a624398d2f/runtime.json +11 -0
- package/.ikie/ferments/019f2740-cd7f-713e-b20f-2321c13a86a8/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2740-cd7f-713e-b20f-2321c13a86a8/runtime.json +17 -0
- package/.ikie/ferments/019f2740-cf49-72fc-94b1-a262676c1136/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2740-cf49-72fc-94b1-a262676c1136/runtime.json +17 -0
- package/.ikie/ferments/019f2740-d16a-763d-b668-7c7cebc74c16/runtime.json +11 -0
- package/.ikie/ferments/019f2740-d675-747d-aa4c-b60d1616d218/runtime.json +11 -0
- package/.ikie/ferments/019f2740-d6ad-72de-bab7-e6344d568636/runtime.json +11 -0
- package/.ikie/ferments/019f2740-d6db-751a-bf3b-09d1c7ba989b/runtime.json +11 -0
- package/.ikie/ferments/019f2740-d712-75c8-b209-efc11bb1a22a/runtime.json +11 -0
- package/.ikie/ferments/019f2740-d745-764f-b758-99b0df2d6c01/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2740-d76b-74a8-94c1-3d0cabd8cacf/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2740-d88d-722b-8265-c8b89e1e59db/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2740-d8f6-756a-b704-8a64a28290e8/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2740-d90b-730f-87b9-85bee8e00a55/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2740-f11f-76ff-9bd0-1e449804cc12/runtime.json +13 -0
- package/.ikie/ferments/019f2740-f155-767e-96db-6cf60c8b8dc1/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f172-755f-a741-8e55858f5362/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f18f-7328-b679-49f91b3c558c/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f1b4-7289-b2f3-46f2bedf0e8f/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f1dc-769b-bfe1-abcbcfd8ff2f/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f1ed-760b-91dc-3bf7950fc112/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f1fd-72dd-9c40-e6ab17b819ef/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f23d-7588-95af-66be8cae9529/runtime.json +9 -0
- package/.ikie/ferments/019f2740-f269-7334-9c82-6554d9fc595a/runtime.json +13 -0
- package/.ikie/ferments/019f2740-f2bf-7147-9e68-cd8cb74d1604/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f2f3-73db-9542-23a91c3632e5/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f387-77e6-99f2-7cabb6f1ef37/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f3af-722d-92a8-b49ab2e974fd/runtime.json +9 -0
- package/.ikie/ferments/019f2740-f3e6-7142-870c-ec1ee626cef4/runtime.json +9 -0
- package/.ikie/ferments/019f2740-f408-74f3-b1a2-3187af4e7bf8/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f535-7419-8dc5-3c00bfeb566e/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f546-7749-b0bd-cc0ec724f9c4/runtime.json +12 -0
- package/.ikie/ferments/019f2740-f576-7649-a468-cc473a719123/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f599-7239-aa50-4bde87b6fe17/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f5b8-7236-9b88-a0abe214d6b6/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f5d1-73fc-9eea-06cf527069f2/runtime.json +11 -0
- package/.ikie/ferments/019f2740-f5fb-757e-b89e-52aeb00d53a0/runtime.json +13 -0
- package/.ikie/ferments/019f2740-f616-7770-96df-c4d02e293b96/runtime.json +11 -0
- package/.ikie/ferments/019f2741-09b2-777a-960c-544786151af2/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2741-09b2-777a-960c-544786151af2/runtime.json +11 -0
- package/.ikie/ferments/019f2741-0a0a-735a-b158-6a1f99b53082/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2741-0a0a-735a-b158-6a1f99b53082/runtime.json +13 -0
- package/.ikie/ferments/019f2741-0a87-74ec-bcb1-e88127e8739b/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2741-0a87-74ec-bcb1-e88127e8739b/runtime.json +9 -0
- package/.ikie/ferments/019f2741-0aaa-7399-905b-0c8f62000e15/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2741-0aaa-7399-905b-0c8f62000e15/runtime.json +9 -0
- package/.ikie/ferments/019f2741-0acc-7062-86e9-0d2d365446d9/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2741-0acc-7062-86e9-0d2d365446d9/runtime.json +9 -0
- package/.ikie/ferments/019f2741-0b14-709e-a5aa-80efb5a3c7d7/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2741-0b14-709e-a5aa-80efb5a3c7d7/runtime.json +9 -0
- package/.ikie/ferments/019f2741-0b3d-77ed-bdd9-322103b094e2/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2741-0b3d-77ed-bdd9-322103b094e2/runtime.json +9 -0
- package/.ikie/ferments/019f2741-0b7b-70ab-b3d6-ada61a3e0a92/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2741-0b7b-70ab-b3d6-ada61a3e0a92/runtime.json +9 -0
- package/.ikie/ferments/019f2742-b177-74a8-90f2-c1130a6ddae7/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b193-72cf-9826-86ede671e061/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b1af-76d9-972c-b67a2f5854d1/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b1de-763e-8e31-a14505f9b64d/runtime.json +12 -0
- package/.ikie/ferments/019f2742-b25b-71fe-81de-89fc3b431b39/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b291-7078-ba58-d4b50df3dd81/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b2db-71a8-9d5d-da4bccc3e572/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b305-7323-86c6-39adaa181f18/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b330-77ad-9315-8ca801c973e8/runtime.json +13 -0
- package/.ikie/ferments/019f2742-b377-703f-9781-394729f9fe89/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b3af-75aa-9bb7-750cb6af56e4/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b3fb-7159-a969-be0073f90b6d/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b41a-730e-ae6e-89421276e69d/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b44e-75ec-824c-f6b77f643438/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b47d-70c6-af2f-04922c1aef02/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b4ad-748b-86db-3c8ae8907dbc/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b4d5-72ff-a1b0-0da356ab94e6/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b508-71fd-8181-7bb013178e5e/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b536-7129-8b5c-2e132b38a98e/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b55d-738b-8663-88a05c1e44b5/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b587-714c-b043-f0a553a22404/runtime.json +15 -0
- package/.ikie/ferments/019f2742-b5b5-74ff-a850-a24ff317c1df/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b5f5-72ba-b6b8-a4d62df39a2c/runtime.json +11 -0
- package/.ikie/ferments/019f2742-b621-7530-8e63-d252ae47ffd6/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2742-b621-7530-8e63-d252ae47ffd6/runtime.json +17 -0
- package/.ikie/ferments/019f2742-b7c0-756d-8014-e96fec9713ee/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2742-b7c0-756d-8014-e96fec9713ee/runtime.json +17 -0
- package/.ikie/ferments/019f2742-b95b-76bb-a4a6-e5cc31788fe3/runtime.json +11 -0
- package/.ikie/ferments/019f2742-be6b-759b-ba34-29d0245dc929/runtime.json +11 -0
- package/.ikie/ferments/019f2742-be98-73ba-aac5-07ad4f7d887d/runtime.json +11 -0
- package/.ikie/ferments/019f2742-beba-703c-aadb-32c590404bfa/runtime.json +11 -0
- package/.ikie/ferments/019f2742-bee0-76ad-9e47-81cff634877f/runtime.json +11 -0
- package/.ikie/ferments/019f2742-bf10-742f-a792-7aa3836d81ad/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2742-bf36-779c-b126-2ccb8ec97138/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2742-c098-74ee-9a07-575f50989d9f/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2742-c135-74fe-aefa-d1a5db536132/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2742-c19a-779c-a175-27330932470d/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2742-db2a-745f-b7c8-8fb383e044e7/runtime.json +13 -0
- package/.ikie/ferments/019f2742-db83-77ac-b1d2-a422571fbcf6/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dba7-779e-9560-7df90ddab3c4/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dbd2-740c-9f94-9f313c07ee52/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dbfb-77b3-8e3f-b0d20bd29689/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dc10-769d-b9a2-bab4851f5cf5/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dc23-7235-a215-8b86d261566a/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dc37-762d-a5da-87ff3f2206b0/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dc65-73c8-aa07-f803b1066c8b/runtime.json +9 -0
- package/.ikie/ferments/019f2742-dc91-7165-bbfe-4659f754c4a6/runtime.json +13 -0
- package/.ikie/ferments/019f2742-dcd1-7252-ad9b-12c0dab633e6/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dceb-75ba-b8cb-557e60aa4a9b/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dd2f-77a6-b71c-a9543ac1145f/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dd6a-70ab-aff3-ae678e8be52f/runtime.json +9 -0
- package/.ikie/ferments/019f2742-dd85-7529-90c0-2cb497df7711/runtime.json +9 -0
- package/.ikie/ferments/019f2742-dda0-715e-ae24-693bfa79f191/runtime.json +11 -0
- package/.ikie/ferments/019f2742-deb9-7319-9599-d96743413a8c/runtime.json +11 -0
- package/.ikie/ferments/019f2742-dee3-705e-9550-b7701bc8dfbf/runtime.json +12 -0
- package/.ikie/ferments/019f2742-df10-71bf-8ac0-8e4a8c40cfa8/runtime.json +11 -0
- package/.ikie/ferments/019f2742-df29-735f-817c-2819becd5092/runtime.json +11 -0
- package/.ikie/ferments/019f2742-df46-7592-b070-7bdf50095ce2/runtime.json +11 -0
- package/.ikie/ferments/019f2742-df66-75e4-9926-4d5dacd457f4/runtime.json +11 -0
- package/.ikie/ferments/019f2742-df96-71c4-973e-045dc4f272e0/runtime.json +13 -0
- package/.ikie/ferments/019f2742-dfca-7353-bfd3-f010ec0726e8/runtime.json +11 -0
- package/.ikie/ferments/019f2742-f0fb-77cb-9a95-25a7231702b7/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2742-f0fb-77cb-9a95-25a7231702b7/runtime.json +11 -0
- package/.ikie/ferments/019f2742-f145-77ec-a4c7-fafd1605d492/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2742-f145-77ec-a4c7-fafd1605d492/runtime.json +13 -0
- package/.ikie/ferments/019f2742-f1dc-74bd-8452-067d9c1b909d/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2742-f1dc-74bd-8452-067d9c1b909d/runtime.json +9 -0
- package/.ikie/ferments/019f2742-f1fd-745d-b989-9a2d3ec7594d/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2742-f1fd-745d-b989-9a2d3ec7594d/runtime.json +9 -0
- package/.ikie/ferments/019f2742-f21a-7398-9190-8bba01c6248e/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2742-f21a-7398-9190-8bba01c6248e/runtime.json +9 -0
- package/.ikie/ferments/019f2742-f23a-73b1-89d2-1272093e6d2d/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2742-f23a-73b1-89d2-1272093e6d2d/runtime.json +9 -0
- package/.ikie/ferments/019f2742-f25c-74d1-80b3-129a992edd3f/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2742-f25c-74d1-80b3-129a992edd3f/runtime.json +9 -0
- package/.ikie/ferments/019f2742-f285-708d-bdd2-c2875cc16158/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2742-f285-708d-bdd2-c2875cc16158/runtime.json +9 -0
- package/.ikie/ferments/019f2745-3a6e-7769-8da0-1994b591349d/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3a8c-74db-bd6b-b4a1164b381a/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3aad-7249-b742-f1e6722d5c97/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3ae9-76fb-861c-49f13c1db883/runtime.json +12 -0
- package/.ikie/ferments/019f2745-3b16-721b-b523-469846e0c9e5/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3b53-7119-ae88-20cf3d567e91/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3ba2-71b6-9fab-faaf750f8535/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3bed-764b-9b4b-79b4d7daa35d/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3c3e-7792-8df7-d88bab7aa48d/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3c81-770d-bcf9-6d163ffeb285/runtime.json +13 -0
- package/.ikie/ferments/019f2745-3cca-748d-9740-8c55644c9afa/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3d12-71cc-923f-520142ddf544/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3d79-7083-8865-8f54989080e0/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3da9-74f9-a640-86b4685f40a0/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3ddf-721b-8a40-3a2318b6bc0a/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3e2a-76a8-8c61-ef15db41aef2/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3e5d-75bb-ab71-b4aa83c491b7/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3e7e-7437-848a-100463c72f90/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3ea7-7729-9000-7874145f4bb5/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3ecf-760c-931c-3dc5996b06b1/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3f05-72d8-ad71-d1df02c5939a/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3f37-74ad-9e02-6e0d3854b664/runtime.json +15 -0
- package/.ikie/ferments/019f2745-3f65-740d-8094-58f60c9cdcec/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3f91-7219-8eec-f5f7873a434a/runtime.json +11 -0
- package/.ikie/ferments/019f2745-3fc5-706a-8188-5a3b4e13a796/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2745-3fc5-706a-8188-5a3b4e13a796/runtime.json +17 -0
- package/.ikie/ferments/019f2745-417c-77ad-bdaf-380b81846577/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2745-417c-77ad-bdaf-380b81846577/runtime.json +17 -0
- package/.ikie/ferments/019f2745-4372-72ff-a50c-3eaad36a726b/runtime.json +11 -0
- package/.ikie/ferments/019f2745-4859-714b-a8b7-0a82d35b87c7/runtime.json +11 -0
- package/.ikie/ferments/019f2745-488a-724f-91a9-d621e9f2b3f7/runtime.json +11 -0
- package/.ikie/ferments/019f2745-48ae-7741-8598-03ede47b4594/runtime.json +11 -0
- package/.ikie/ferments/019f2745-48e9-710f-889b-e88aa5d7e60e/runtime.json +11 -0
- package/.ikie/ferments/019f2745-4917-7268-9b76-f8bb1215ea19/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2745-493c-775d-a10d-4a2cf8305a4e/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2745-4abd-7319-9e11-4b348ab24547/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2745-4b10-726d-ad1f-c086e7d4dfc0/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2745-4b21-75a6-b151-472f4eb9b95d/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2745-5dd5-741b-85e2-1d67ce09a138/runtime.json +13 -0
- package/.ikie/ferments/019f2745-5e14-73dd-bd03-3b5765f70fac/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5e2e-70b5-9348-35ebbdb8ec8e/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5e4f-7626-b075-6b6d30099847/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5e71-7768-b436-e739555f1038/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5e8a-77c5-ba98-cb2802c55266/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5ea8-707f-b034-9c98e6ca720b/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5ebd-73aa-a919-150c9bb014f9/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5ed6-71e9-9a20-360fa807f598/runtime.json +9 -0
- package/.ikie/ferments/019f2745-5ef8-7199-bd13-69b5c883541b/runtime.json +13 -0
- package/.ikie/ferments/019f2745-5f30-73f9-a647-9e7518599c32/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5f53-7358-897a-37717d64d996/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5fb6-736b-b42d-bbc3c1916321/runtime.json +11 -0
- package/.ikie/ferments/019f2745-5fea-730e-b57b-d7f1965d5934/runtime.json +9 -0
- package/.ikie/ferments/019f2745-6014-77cb-b01f-d93baf8af409/runtime.json +9 -0
- package/.ikie/ferments/019f2745-602f-74b9-8eed-bb29fa4a76d4/runtime.json +11 -0
- package/.ikie/ferments/019f2745-60e2-7562-8e7c-2ded6cf75426/runtime.json +11 -0
- package/.ikie/ferments/019f2745-6114-703e-ac05-5ba11b255b62/runtime.json +12 -0
- package/.ikie/ferments/019f2745-6160-733e-93f5-df586c6afc0a/runtime.json +11 -0
- package/.ikie/ferments/019f2745-6179-702b-84fb-09bc60f8c04c/runtime.json +11 -0
- package/.ikie/ferments/019f2745-618d-74dc-a174-28a134d353fa/runtime.json +11 -0
- package/.ikie/ferments/019f2745-619e-72a8-8377-34127bfc774f/runtime.json +11 -0
- package/.ikie/ferments/019f2745-61ae-767e-8a2e-a5ca6bc84a88/runtime.json +13 -0
- package/.ikie/ferments/019f2745-61c7-760c-9914-a9bf3c96acd8/runtime.json +11 -0
- package/.ikie/ferments/019f2745-79a2-70b8-bcd0-fbaee13849db/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2745-79a2-70b8-bcd0-fbaee13849db/runtime.json +11 -0
- package/.ikie/ferments/019f2745-79e7-74d5-b867-e23b027a8512/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2745-79e7-74d5-b867-e23b027a8512/runtime.json +13 -0
- package/.ikie/ferments/019f2745-7a5b-703e-999e-dd5cb98133eb/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2745-7a5b-703e-999e-dd5cb98133eb/runtime.json +9 -0
- package/.ikie/ferments/019f2745-7a90-732a-b09a-9aa29e2390cd/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2745-7a90-732a-b09a-9aa29e2390cd/runtime.json +9 -0
- package/.ikie/ferments/019f2745-7aad-731c-ac2a-cf71d20fb709/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2745-7aad-731c-ac2a-cf71d20fb709/runtime.json +9 -0
- package/.ikie/ferments/019f2745-7ad2-70ff-986b-83679208066a/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2745-7ad2-70ff-986b-83679208066a/runtime.json +9 -0
- package/.ikie/ferments/019f2745-7af8-735c-8200-f49b201f5b7f/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2745-7af8-735c-8200-f49b201f5b7f/runtime.json +9 -0
- package/.ikie/ferments/019f2745-7b17-7489-b4d5-b83e4feeb641/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2745-7b17-7489-b4d5-b83e4feeb641/runtime.json +9 -0
- package/.ikie/ferments/019f2747-700f-77dd-8fec-eec70eb204bf/runtime.json +11 -0
- package/.ikie/ferments/019f2747-702b-748d-83a8-a44d909b5d84/runtime.json +11 -0
- package/.ikie/ferments/019f2747-704a-77c6-a068-5eff8527f149/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7075-7628-9088-9c79d85087be/runtime.json +12 -0
- package/.ikie/ferments/019f2747-70e4-7157-aa37-d8201f07134a/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7139-74da-8f85-02b76ecfc932/runtime.json +15 -0
- package/.ikie/ferments/019f2747-7156-762f-8c31-84ae357e2edd/runtime.json +15 -0
- package/.ikie/ferments/019f2747-7175-76e7-9d21-15608a6463ca/runtime.json +15 -0
- package/.ikie/ferments/019f2747-71c8-777c-8106-df11073ad85f/runtime.json +13 -0
- package/.ikie/ferments/019f2747-7209-71f5-8f4e-ccfd46653321/runtime.json +15 -0
- package/.ikie/ferments/019f2747-723d-728f-baa8-dd3b4b239037/runtime.json +15 -0
- package/.ikie/ferments/019f2747-728d-749b-9e9a-962ea824d13d/runtime.json +11 -0
- package/.ikie/ferments/019f2747-72b0-756e-b648-c5491d46dc37/runtime.json +15 -0
- package/.ikie/ferments/019f2747-72e8-747e-9e5b-93005dd51d36/runtime.json +15 -0
- package/.ikie/ferments/019f2747-7319-702b-84bd-aed70c3f60c3/runtime.json +15 -0
- package/.ikie/ferments/019f2747-734a-732c-89d8-47fa74a13f6b/runtime.json +15 -0
- package/.ikie/ferments/019f2747-7372-72ce-99d0-ddeeb20c73e5/runtime.json +15 -0
- package/.ikie/ferments/019f2747-73a1-723d-b064-2240965b5460/runtime.json +15 -0
- package/.ikie/ferments/019f2747-73cd-71b5-9b21-481224573278/runtime.json +15 -0
- package/.ikie/ferments/019f2747-73f7-779f-a227-64ba479c2615/runtime.json +15 -0
- package/.ikie/ferments/019f2747-743e-759e-856b-283e346eec66/runtime.json +15 -0
- package/.ikie/ferments/019f2747-74ac-702b-877f-1b4447f77938/runtime.json +11 -0
- package/.ikie/ferments/019f2747-74cc-773a-ad3a-febf5e9e5a57/runtime.json +11 -0
- package/.ikie/ferments/019f2747-750b-77dc-aa24-230eef901e40/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2747-750b-77dc-aa24-230eef901e40/runtime.json +17 -0
- package/.ikie/ferments/019f2747-76f2-72c9-8764-82fdd0429215/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2747-76f2-72c9-8764-82fdd0429215/runtime.json +17 -0
- package/.ikie/ferments/019f2747-795d-7452-9810-a64e86f3d5c5/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7ee1-770e-ace1-bc0f5571f69a/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7f01-738d-a2a2-c7aa33365582/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7f40-712b-bea9-8a20399c9dfd/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7fb4-70c9-aaf6-af4ac5fbebef/runtime.json +11 -0
- package/.ikie/ferments/019f2747-7fe2-77e7-90d5-dcee3cbe73ea/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2747-7ff9-7028-ac25-77ab9c513710/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2747-81c3-7320-8a96-88880d06cc14/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2747-8236-76c0-b17c-1f13a22af974/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2747-824b-77ba-90bd-67bcb4e9d5d6/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2747-a18a-77f4-802d-18ab07f51261/runtime.json +13 -0
- package/.ikie/ferments/019f2747-a1b6-76cf-9688-94e8f41b179f/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a1e2-730b-a56d-cb622d190c49/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a20b-739e-a524-b5b2cdabdf49/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a228-7026-9fe2-79fc90d7c622/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a244-71b5-8ceb-d6094c7a5d28/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a25d-723e-9962-ed1f266a9709/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a275-734d-9ede-ae9644a179b6/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a2a4-7280-b8c4-d8233d9e322a/runtime.json +9 -0
- package/.ikie/ferments/019f2747-a2ca-767d-8a35-9043b18e5ec7/runtime.json +13 -0
- package/.ikie/ferments/019f2747-a2f5-745d-929e-9fb2ef5d333f/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a317-76b9-8954-2b7a4487a352/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a380-7746-be44-cb9e1920561f/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a3a2-77ac-9fe5-2a844b64872d/runtime.json +9 -0
- package/.ikie/ferments/019f2747-a3b7-70ee-ba83-b3c43d3122c8/runtime.json +9 -0
- package/.ikie/ferments/019f2747-a3e7-76e9-96f0-143c82d8005b/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a4d3-737b-8d80-2dc63a0fbe1a/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a506-7442-919f-50ae2b602e7a/runtime.json +12 -0
- package/.ikie/ferments/019f2747-a53e-76cb-9876-a81dd08e3fe7/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a56a-7208-ad93-0fdcbc41c1ed/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a581-73fc-aac5-a44f696ccbe8/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a595-71d2-9c2d-d846e9803665/runtime.json +11 -0
- package/.ikie/ferments/019f2747-a5a7-73c6-b881-f9c0a08f3af3/runtime.json +13 -0
- package/.ikie/ferments/019f2747-a5be-7777-94c0-0849e693ffcb/runtime.json +11 -0
- package/.ikie/ferments/019f2747-b3e6-706a-912c-71d57080c7c1/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2747-b3e6-706a-912c-71d57080c7c1/runtime.json +11 -0
- package/.ikie/ferments/019f2747-b464-75bd-9c0b-c6b5e5de789e/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2747-b464-75bd-9c0b-c6b5e5de789e/runtime.json +13 -0
- package/.ikie/ferments/019f2747-b4f2-719c-86a6-763c494a680c/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2747-b4f2-719c-86a6-763c494a680c/runtime.json +9 -0
- package/.ikie/ferments/019f2747-b52b-75cd-b664-8c2aedd87893/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2747-b52b-75cd-b664-8c2aedd87893/runtime.json +9 -0
- package/.ikie/ferments/019f2747-b551-7188-81a3-7b7e8371aea4/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2747-b551-7188-81a3-7b7e8371aea4/runtime.json +9 -0
- package/.ikie/ferments/019f2747-b5a5-703f-98e6-5eac131044ed/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2747-b5a5-703f-98e6-5eac131044ed/runtime.json +9 -0
- package/.ikie/ferments/019f2747-b5cc-7560-80d8-509578bdae44/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2747-b5cc-7560-80d8-509578bdae44/runtime.json +9 -0
- package/.ikie/ferments/019f2747-b5f7-7079-ba17-833018701a06/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2747-b5f7-7079-ba17-833018701a06/runtime.json +9 -0
- package/.ikie/ferments/019f274a-bb4e-77b1-9f03-633b22b8e54c/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bb6e-7715-92a0-c73da2ff97da/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bb89-75b5-9daa-c57ef85c64c1/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bbb7-72ad-9695-3227786b16ef/runtime.json +12 -0
- package/.ikie/ferments/019f274a-bbfb-70da-95f3-54a3e507888d/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bc37-771a-8e77-b8d5476a8a1e/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bc61-7024-9311-148a94a6713e/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bca0-76a9-b966-59bbe3fb5bdd/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bcc9-774d-adc2-aa99e82abb79/runtime.json +13 -0
- package/.ikie/ferments/019f274a-bcfb-737e-9c7d-b9db4762b624/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bd3f-725b-9d39-b672191556ac/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bd82-75a8-b936-350a55a7a1da/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bda4-71b2-aa8b-7ba6f6103814/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bddc-70ff-90f8-f1648dede718/runtime.json +15 -0
- package/.ikie/ferments/019f274a-be12-70bd-b935-0173946e60c2/runtime.json +15 -0
- package/.ikie/ferments/019f274a-be51-7719-b04b-d720a1d215f7/runtime.json +15 -0
- package/.ikie/ferments/019f274a-be8c-7084-aa78-4d139084333b/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bebc-70b7-8c8d-fc7b50eda266/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bee6-732f-b9ee-9fb3f1966e3d/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bf19-76bc-8ab4-fe8c3fb28875/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bf40-755b-bd4f-eec6d8e7a4de/runtime.json +15 -0
- package/.ikie/ferments/019f274a-bf74-7013-beb9-08aab0dc8866/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bfa3-718d-ab5d-ededc4cf9e63/runtime.json +11 -0
- package/.ikie/ferments/019f274a-bfd6-7689-b29b-2c3ebfe1afd3/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274a-bfd6-7689-b29b-2c3ebfe1afd3/runtime.json +17 -0
- package/.ikie/ferments/019f274a-c186-77ea-a92c-78fa52657710/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274a-c186-77ea-a92c-78fa52657710/runtime.json +17 -0
- package/.ikie/ferments/019f274a-c3cf-77e8-9917-76d94992456a/runtime.json +11 -0
- package/.ikie/ferments/019f274a-c8eb-7071-9900-1668ccf13dad/runtime.json +11 -0
- package/.ikie/ferments/019f274a-c928-7276-9fd8-c8fdfbd215ff/runtime.json +11 -0
- package/.ikie/ferments/019f274a-c957-7698-8a97-54584a38f472/runtime.json +11 -0
- package/.ikie/ferments/019f274a-c97f-71b5-8fd9-727b49c9b72c/runtime.json +11 -0
- package/.ikie/ferments/019f274a-c9ad-76bb-99f8-b8f7840ad3ab/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274a-c9cf-73ad-8229-d03bd5389697/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274a-cb01-720a-b512-e49f820b9be5/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274a-cbba-764d-a8e7-da6a060d9cd1/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274a-cbdd-744f-84e9-af64527ff116/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274a-efc1-75b6-ad54-83a9fcb061af/runtime.json +13 -0
- package/.ikie/ferments/019f274a-effe-713a-9672-ca8c839b0936/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f03c-7194-b9e6-a24620ef1b89/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f058-758c-9ecf-f6af131a0798/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f06e-712d-b720-09a6188a152a/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f085-715e-8b5b-07587107bc86/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f0a8-755b-b747-adaa0f997d8a/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f0cd-765c-90ce-48685c67299c/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f0e1-71a8-bafc-cc3eeff4f275/runtime.json +9 -0
- package/.ikie/ferments/019f274a-f104-73c0-be62-16f724e0d4c6/runtime.json +13 -0
- package/.ikie/ferments/019f274a-f129-70ea-aa16-254d0fc662bf/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f14b-7742-8e88-7a3fe9d16f08/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f18b-7148-afb1-b9ff1ab54bbc/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f1a2-734d-bf87-6f80955a3b64/runtime.json +9 -0
- package/.ikie/ferments/019f274a-f1c0-75a7-8675-f4fcf15df9bd/runtime.json +9 -0
- package/.ikie/ferments/019f274a-f1e2-7346-b97f-9340f86e6397/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f2a1-7758-a891-413d15c9c29c/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f2bc-76fd-b2dc-e14feea4fb86/runtime.json +12 -0
- package/.ikie/ferments/019f274a-f2e0-7474-97b8-79e01d130940/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f2fa-70fb-a2da-0fb3e9a729ef/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f30f-71bc-bf7f-198ef4b68568/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f326-768b-b55e-e340dd3bf7fc/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f339-75a5-9d45-d9393ccf3436/runtime.json +13 -0
- package/.ikie/ferments/019f274a-f35b-7386-9eb0-8f1e45618131/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f96b-7633-9b6d-6722ea8232a2/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f274a-f96b-7633-9b6d-6722ea8232a2/runtime.json +11 -0
- package/.ikie/ferments/019f274a-f9b7-769e-94ac-8f5c7e23ee88/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f274a-f9b7-769e-94ac-8f5c7e23ee88/runtime.json +13 -0
- package/.ikie/ferments/019f274a-fa07-70b1-bc68-1a9d3378deff/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274a-fa07-70b1-bc68-1a9d3378deff/runtime.json +9 -0
- package/.ikie/ferments/019f274a-fa2f-7658-86ad-cc69215f1c94/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274a-fa2f-7658-86ad-cc69215f1c94/runtime.json +9 -0
- package/.ikie/ferments/019f274a-fa46-72ca-a252-65a5b2995bc4/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274a-fa46-72ca-a252-65a5b2995bc4/runtime.json +9 -0
- package/.ikie/ferments/019f274a-fa70-705f-9112-d48e1042f1d4/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274a-fa70-705f-9112-d48e1042f1d4/runtime.json +9 -0
- package/.ikie/ferments/019f274a-fa94-73e5-9fc3-ea21ee5cfc59/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274a-fa94-73e5-9fc3-ea21ee5cfc59/runtime.json +9 -0
- package/.ikie/ferments/019f274a-fab9-720d-9ce3-0041a27f83e0/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f274a-fab9-720d-9ce3-0041a27f83e0/runtime.json +9 -0
- package/.ikie/ferments/019f274c-7608-76f8-89c7-6e3b7d9095b2/runtime.json +11 -0
- package/.ikie/ferments/019f274c-762a-717c-9ec2-530d37897051/runtime.json +11 -0
- package/.ikie/ferments/019f274c-7644-76fc-a27d-c699d368a511/runtime.json +11 -0
- package/.ikie/ferments/019f274c-7667-7260-87b3-f2ad6ff10c04/runtime.json +12 -0
- package/.ikie/ferments/019f274c-7696-753f-8634-5cb24d2aabaa/runtime.json +11 -0
- package/.ikie/ferments/019f274c-76c8-76e8-b4d8-0cabd7f32047/runtime.json +15 -0
- package/.ikie/ferments/019f274c-76f5-732e-88f3-0461f79b7733/runtime.json +15 -0
- package/.ikie/ferments/019f274c-771b-762e-abb6-1bfe6838545b/runtime.json +15 -0
- package/.ikie/ferments/019f274c-774a-769f-b15f-d36a990c8aa2/runtime.json +13 -0
- package/.ikie/ferments/019f274c-7791-7040-9c73-fe5922824edc/runtime.json +15 -0
- package/.ikie/ferments/019f274c-77c3-76f9-a5c6-e0f5030f615c/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7805-70eb-ac17-888c2a0ab5cb/runtime.json +11 -0
- package/.ikie/ferments/019f274c-7820-71da-9baf-d7953b547620/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7855-708f-bbe8-a9e13258cc98/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7886-70fc-9572-b96090b16cf9/runtime.json +15 -0
- package/.ikie/ferments/019f274c-78b7-756e-82ef-8a8e953000bf/runtime.json +15 -0
- package/.ikie/ferments/019f274c-78df-7198-b1dd-58c3ea1e0d6e/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7902-77d4-b443-b105d0a3acd5/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7926-7628-82dc-e71e8f5d58f0/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7948-7755-bc18-c8d9975c762f/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7972-72a5-bc5e-e47579f25c32/runtime.json +15 -0
- package/.ikie/ferments/019f274c-7998-71bf-960e-caba2791ece7/runtime.json +11 -0
- package/.ikie/ferments/019f274c-79c4-71c6-97ef-0dac30d26152/runtime.json +11 -0
- package/.ikie/ferments/019f274c-79e3-7249-8bac-82b74fbd9d1d/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274c-79e3-7249-8bac-82b74fbd9d1d/runtime.json +17 -0
- package/.ikie/ferments/019f274c-7b11-769e-b05b-354105048fb2/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274c-7b11-769e-b05b-354105048fb2/runtime.json +17 -0
- package/.ikie/ferments/019f274c-7c7b-73ad-98d3-739e5f0187ec/runtime.json +11 -0
- package/.ikie/ferments/019f274c-8054-728f-96c1-6cae4b96c94e/runtime.json +11 -0
- package/.ikie/ferments/019f274c-8072-7209-82b0-84facff2e61a/runtime.json +11 -0
- package/.ikie/ferments/019f274c-8094-77ec-81dd-e50e61dc11db/runtime.json +11 -0
- package/.ikie/ferments/019f274c-80bc-75c9-89e8-540dba77996e/runtime.json +11 -0
- package/.ikie/ferments/019f274c-80dd-7439-a5b0-b36fcf77c8f1/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-80f1-71ac-bd32-fd151f38519c/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-81dc-70e6-a5c9-249b196c75c3/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-8238-772c-9da3-f27e467100a7/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-824a-76d9-aac3-c51171e256b4/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-a854-7349-b76a-4a0bc2ecc2f7/runtime.json +11 -0
- package/.ikie/ferments/019f274c-a872-701b-a311-51267fc54aa5/runtime.json +11 -0
- package/.ikie/ferments/019f274c-a8a2-756e-9051-15fcd0be1584/runtime.json +11 -0
- package/.ikie/ferments/019f274c-a8d8-767c-8190-d30a2e78815f/runtime.json +12 -0
- package/.ikie/ferments/019f274c-a914-701e-95ab-9eeca15f5ccd/runtime.json +11 -0
- package/.ikie/ferments/019f274c-a951-720f-bc99-2ea22021a624/runtime.json +15 -0
- package/.ikie/ferments/019f274c-a978-750b-aecb-a5a2aa684cdf/runtime.json +15 -0
- package/.ikie/ferments/019f274c-a9a6-71e9-82ac-66c74cf51964/runtime.json +15 -0
- package/.ikie/ferments/019f274c-a9e0-77ae-96eb-dad523b6a843/runtime.json +13 -0
- package/.ikie/ferments/019f274c-aa2c-7658-a652-ca1a27093c42/runtime.json +15 -0
- package/.ikie/ferments/019f274c-aa77-72b4-a8de-56a2217c759f/runtime.json +15 -0
- package/.ikie/ferments/019f274c-aacf-74fa-943c-26412ddd8b5d/runtime.json +11 -0
- package/.ikie/ferments/019f274c-ab08-709f-aaff-09f10230738f/runtime.json +15 -0
- package/.ikie/ferments/019f274c-ab66-730b-86a5-7571dac8802c/runtime.json +15 -0
- package/.ikie/ferments/019f274c-abb2-77d2-91b6-ea175f561d8a/runtime.json +15 -0
- package/.ikie/ferments/019f274c-ac01-74ff-a2c6-28dbadc051e7/runtime.json +15 -0
- package/.ikie/ferments/019f274c-ac4b-75ad-93a6-aa6af74ca708/runtime.json +15 -0
- package/.ikie/ferments/019f274c-ac80-77b4-bfcf-f7a7187a42f6/runtime.json +15 -0
- package/.ikie/ferments/019f274c-acd9-7239-ad37-73d57031d1bc/runtime.json +15 -0
- package/.ikie/ferments/019f274c-ad22-74bb-9cf2-ed681dd73504/runtime.json +15 -0
- package/.ikie/ferments/019f274c-ad7d-720c-89bf-5a79ceec8173/runtime.json +15 -0
- package/.ikie/ferments/019f274c-adca-762a-b177-4d76b886003b/runtime.json +11 -0
- package/.ikie/ferments/019f274c-ae26-7109-bfaa-39d692fdc1ac/runtime.json +11 -0
- package/.ikie/ferments/019f274c-ae59-76bb-80ae-f556e764f2ca/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274c-ae59-76bb-80ae-f556e764f2ca/runtime.json +17 -0
- package/.ikie/ferments/019f274c-b059-76e5-9b73-bedc0d4b5aaa/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274c-b059-76e5-9b73-bedc0d4b5aaa/runtime.json +17 -0
- package/.ikie/ferments/019f274c-b21f-700a-adda-4bfd9d27a0ac/runtime.json +11 -0
- package/.ikie/ferments/019f274c-b91a-7306-8825-3581ef16ab34/runtime.json +11 -0
- package/.ikie/ferments/019f274c-b966-737f-a1c7-e8e7d3af929c/runtime.json +11 -0
- package/.ikie/ferments/019f274c-b99d-74dd-b8e8-1ddc50293a9a/runtime.json +11 -0
- package/.ikie/ferments/019f274c-ba0e-72ae-ad14-983edb8d90ac/runtime.json +11 -0
- package/.ikie/ferments/019f274c-ba4f-7101-b851-12564620c50f/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-ba63-712c-858f-96cee1384cec/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-bbe3-7343-a8b0-e6f91c3ab922/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-bc4a-740e-a12a-9c04181702d9/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-bc7b-707c-90b9-d30cf92b5fb9/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274c-e044-750a-a9e1-623de3afa666/runtime.json +13 -0
- package/.ikie/ferments/019f274c-e07a-77cb-9f17-726e4afb3ee1/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e0a2-754a-ac70-aac9cd3d3dc2/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e0ba-72de-bf83-25a8319eddc5/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e0cf-77c1-9c23-65745da294b4/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e0e7-77f7-9436-0537e2095c6b/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e103-70d7-abd9-01305b905259/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e121-7328-9eab-3babb40f26b3/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e135-76d4-9176-2033e41fa5a8/runtime.json +9 -0
- package/.ikie/ferments/019f274c-e157-7043-9b54-fd7c40cb0793/runtime.json +13 -0
- package/.ikie/ferments/019f274c-e181-718e-804d-d0edfaabd5cd/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e19b-72ab-bf87-b7a53037becb/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e20a-716e-8cab-f0cd93259148/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e228-73a3-a655-48bc44db0325/runtime.json +9 -0
- package/.ikie/ferments/019f274c-e243-7609-bec4-905caa78d674/runtime.json +9 -0
- package/.ikie/ferments/019f274c-e258-76ba-912c-bab41dfeaac2/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e35a-776b-a644-52ee82afec4d/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e378-73e8-943d-f2fc2ee875ef/runtime.json +12 -0
- package/.ikie/ferments/019f274c-e3a6-757d-b33c-c6fbdd9cf8c7/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e3c9-77a7-be2b-43891355a506/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e3db-776b-8de6-fb1aeab60a7b/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e3f4-700e-8780-2dee3c117eb8/runtime.json +11 -0
- package/.ikie/ferments/019f274c-e409-71af-a0f9-ff159811e472/runtime.json +13 -0
- package/.ikie/ferments/019f274c-e432-73cd-bd34-39f0e34a568d/runtime.json +11 -0
- package/.ikie/ferments/019f274c-eb55-73fe-bb2a-34b4a2df3f4e/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f274c-eb55-73fe-bb2a-34b4a2df3f4e/runtime.json +11 -0
- package/.ikie/ferments/019f274c-eb9b-728e-93e2-80afb71ae50e/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f274c-eb9b-728e-93e2-80afb71ae50e/runtime.json +13 -0
- package/.ikie/ferments/019f274c-ebf3-77bb-8f8a-6081787fbcb3/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274c-ebf3-77bb-8f8a-6081787fbcb3/runtime.json +9 -0
- package/.ikie/ferments/019f274c-ec22-7123-8c8f-0c129c2e0719/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274c-ec22-7123-8c8f-0c129c2e0719/runtime.json +9 -0
- package/.ikie/ferments/019f274c-ec85-757c-9600-8be68ceccb55/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274c-ec85-757c-9600-8be68ceccb55/runtime.json +9 -0
- package/.ikie/ferments/019f274c-ecd9-704e-8c99-65c64be0a8e1/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274c-ecd9-704e-8c99-65c64be0a8e1/runtime.json +9 -0
- package/.ikie/ferments/019f274c-ecee-70bb-9087-da3b4c57d281/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274c-ecee-70bb-9087-da3b4c57d281/runtime.json +9 -0
- package/.ikie/ferments/019f274c-ed18-77bf-8cde-812d1e273bda/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f274c-ed18-77bf-8cde-812d1e273bda/runtime.json +9 -0
- package/.ikie/ferments/019f274f-0303-7543-9aa9-fa7f54d5f6c6/runtime.json +11 -0
- package/.ikie/ferments/019f274f-032c-70aa-b5b5-d695429a50bc/runtime.json +11 -0
- package/.ikie/ferments/019f274f-036d-763c-8cf9-cb62245aff49/runtime.json +11 -0
- package/.ikie/ferments/019f274f-03bd-709c-85ee-698745beac66/runtime.json +12 -0
- package/.ikie/ferments/019f274f-0404-75cf-8731-f0182bd84d87/runtime.json +11 -0
- package/.ikie/ferments/019f274f-0442-75fe-8cc3-44bfe5dd84bf/runtime.json +15 -0
- package/.ikie/ferments/019f274f-048f-759f-ae18-5fe9975647bf/runtime.json +15 -0
- package/.ikie/ferments/019f274f-04f1-72fa-a2ba-0b9e066ae6eb/runtime.json +15 -0
- package/.ikie/ferments/019f274f-0541-728d-8893-0b0b45547a56/runtime.json +13 -0
- package/.ikie/ferments/019f274f-058e-7508-b67a-ebe736113e1e/runtime.json +15 -0
- package/.ikie/ferments/019f274f-0625-77d9-bf99-bcdf0ca2d5b2/runtime.json +15 -0
- package/.ikie/ferments/019f274f-0694-715c-b008-29a3cf0d6c9c/runtime.json +11 -0
- package/.ikie/ferments/019f274f-06b1-71fb-a812-3fd3cefda2ea/runtime.json +15 -0
- package/.ikie/ferments/019f274f-06e9-701b-9396-dca2be2330e5/runtime.json +15 -0
- package/.ikie/ferments/019f274f-072b-76b2-8d77-32d0ad5abb81/runtime.json +15 -0
- package/.ikie/ferments/019f274f-0770-75ce-886f-c1c12d6682eb/runtime.json +15 -0
- package/.ikie/ferments/019f274f-07ab-75fc-a71b-ca3b4b4acca5/runtime.json +15 -0
- package/.ikie/ferments/019f274f-07f0-72cd-a577-316526b45983/runtime.json +15 -0
- package/.ikie/ferments/019f274f-0837-72ed-94f2-dd68e9273549/runtime.json +15 -0
- package/.ikie/ferments/019f274f-0866-765d-a2fc-8cce9d53e417/runtime.json +15 -0
- package/.ikie/ferments/019f274f-08bb-737e-8f23-4b2e069bc7e5/runtime.json +15 -0
- package/.ikie/ferments/019f274f-08f6-73aa-968a-85f55d5e047c/runtime.json +11 -0
- package/.ikie/ferments/019f274f-0949-77b7-8d2c-46fbeb423e3a/runtime.json +11 -0
- package/.ikie/ferments/019f274f-0979-71ad-91b5-d2e52366b74d/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274f-0979-71ad-91b5-d2e52366b74d/runtime.json +17 -0
- package/.ikie/ferments/019f274f-0b57-7329-884a-43e712cd093c/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f274f-0b57-7329-884a-43e712cd093c/runtime.json +17 -0
- package/.ikie/ferments/019f274f-0d87-772d-a6f3-b71179eec14f/runtime.json +11 -0
- package/.ikie/ferments/019f274f-12f0-73be-b630-54a329974d0b/runtime.json +11 -0
- package/.ikie/ferments/019f274f-1332-7202-90be-f7e94dd16e66/runtime.json +11 -0
- package/.ikie/ferments/019f274f-1368-778a-b044-0306086fe9cf/runtime.json +11 -0
- package/.ikie/ferments/019f274f-13a9-7287-974d-8db5c1b7dda6/runtime.json +11 -0
- package/.ikie/ferments/019f274f-13d1-7069-91d8-2e4efe8d8982/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274f-13f8-717c-92c9-9bc9b37ee2cc/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274f-1566-753b-b053-f14ccb779e36/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274f-15d3-76f8-8467-e368f0c40baf/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274f-15f0-716f-92e7-d966f4476b09/pending-proposal.json +45 -0
- package/.ikie/ferments/019f274f-2a19-762d-be24-59afdd71b303/runtime.json +13 -0
- package/.ikie/ferments/019f274f-2a74-74cb-ab51-dd779739478e/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2a92-71e1-9e68-15f750efc6ec/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2ab1-73eb-8930-b9d161230fcc/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2ad9-70ea-83a9-f8ae1af1edcf/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2b02-77ea-b187-43489c9a88f8/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2b2d-728c-9b69-7a6e4956a88c/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2b42-7358-b1fa-9754d2ca530d/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2b74-77ee-b062-8b111368fc58/runtime.json +9 -0
- package/.ikie/ferments/019f274f-2b9b-703b-8abd-5b4ff212ce66/runtime.json +13 -0
- package/.ikie/ferments/019f274f-2bd6-7109-93ec-12f609270c84/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2bea-75cf-b3d2-aedca4b0c8a4/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2c1c-7085-b221-ecf2a371e6cf/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2c2f-71fb-9b03-41d6f8a5d2d6/runtime.json +9 -0
- package/.ikie/ferments/019f274f-2c5d-719d-a913-5255a7b3e376/runtime.json +9 -0
- package/.ikie/ferments/019f274f-2c92-75bb-b691-4efd9b706418/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2d9e-7186-b8f9-0d5863265329/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2dbb-73f9-8231-b52b6e1eb863/runtime.json +12 -0
- package/.ikie/ferments/019f274f-2ddf-7477-a5a2-a20be1921fbf/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2e01-710b-8175-18eeb0e792e2/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2e26-7217-a41e-3bd106e0a9cf/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2e3a-72bc-9945-37a576bb7ef1/runtime.json +11 -0
- package/.ikie/ferments/019f274f-2e61-77e5-85ab-dda905bded90/runtime.json +13 -0
- package/.ikie/ferments/019f274f-2e7e-73ea-a7c9-14ab5125c3d3/runtime.json +11 -0
- package/.ikie/ferments/019f274f-4262-76b9-884a-9ff2121f2c3a/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f274f-4262-76b9-884a-9ff2121f2c3a/runtime.json +11 -0
- package/.ikie/ferments/019f274f-42ce-753f-ba6d-c1c2be5b7c71/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f274f-42ce-753f-ba6d-c1c2be5b7c71/runtime.json +13 -0
- package/.ikie/ferments/019f274f-4353-75ed-bad2-0f74d61ceff5/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274f-4353-75ed-bad2-0f74d61ceff5/runtime.json +9 -0
- package/.ikie/ferments/019f274f-4379-7716-af61-2381f422540e/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274f-4379-7716-af61-2381f422540e/runtime.json +9 -0
- package/.ikie/ferments/019f274f-43a1-716c-ba31-4b705e8afb1a/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274f-43a1-716c-ba31-4b705e8afb1a/runtime.json +9 -0
- package/.ikie/ferments/019f274f-43de-761a-b793-fca5ca243eea/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274f-43de-761a-b793-fca5ca243eea/runtime.json +9 -0
- package/.ikie/ferments/019f274f-4401-73e9-b9d8-99631bab030b/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f274f-4401-73e9-b9d8-99631bab030b/runtime.json +9 -0
- package/.ikie/ferments/019f274f-442b-770b-b411-feeb46ae7a8d/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f274f-442b-770b-b411-feeb46ae7a8d/runtime.json +9 -0
- package/.ikie/ferments/019f275c-3e9e-7557-b50e-0e56cc6b07f5/runtime.json +11 -0
- package/.ikie/ferments/019f275c-3ec3-73ea-b557-77cc517095f2/runtime.json +11 -0
- package/.ikie/ferments/019f275c-3ee5-774f-876e-3caacb9b1d95/runtime.json +11 -0
- package/.ikie/ferments/019f275c-3f28-73ee-8eae-568fec8011b6/runtime.json +12 -0
- package/.ikie/ferments/019f275c-3f57-70a8-ba4d-d179cceaabbf/runtime.json +11 -0
- package/.ikie/ferments/019f275c-3f88-72cb-abb5-8e0e176e1dd2/runtime.json +15 -0
- package/.ikie/ferments/019f275c-3fb4-7248-9c23-874baa6e2a9d/runtime.json +15 -0
- package/.ikie/ferments/019f275c-3fe1-759b-afd9-f5e47564de48/runtime.json +15 -0
- package/.ikie/ferments/019f275c-401f-74e8-b968-d325ae2faf56/runtime.json +13 -0
- package/.ikie/ferments/019f275c-4067-752e-a0d8-d85f670f9473/runtime.json +15 -0
- package/.ikie/ferments/019f275c-40a2-74de-b858-ef4ad52484ea/runtime.json +15 -0
- package/.ikie/ferments/019f275c-4105-738f-95d0-6e9f7f9568fb/runtime.json +11 -0
- package/.ikie/ferments/019f275c-411b-76e9-b030-df118a1b23b4/runtime.json +15 -0
- package/.ikie/ferments/019f275c-4153-74ec-8b93-e2e0e82c27b0/runtime.json +15 -0
- package/.ikie/ferments/019f275c-4199-739b-9af9-b1cfc26623c3/runtime.json +15 -0
- package/.ikie/ferments/019f275c-41cb-746b-8481-7ca9d82a8b64/runtime.json +15 -0
- package/.ikie/ferments/019f275c-4209-756f-b335-8e6dfe51bac1/runtime.json +15 -0
- package/.ikie/ferments/019f275c-424c-7512-ac17-b8c04dcf82ac/runtime.json +15 -0
- package/.ikie/ferments/019f275c-4269-74eb-a213-e221479a26e5/runtime.json +15 -0
- package/.ikie/ferments/019f275c-428b-71ea-acda-027b98d191d1/runtime.json +15 -0
- package/.ikie/ferments/019f275c-42bb-75da-b330-e9f101c36d5c/runtime.json +15 -0
- package/.ikie/ferments/019f275c-42e3-777a-8e8c-80772f6d6bcb/runtime.json +11 -0
- package/.ikie/ferments/019f275c-430b-7779-bcc7-95a0b6fc693d/runtime.json +11 -0
- package/.ikie/ferments/019f275c-432e-71f9-b65d-88d26f3b185f/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f275c-432e-71f9-b65d-88d26f3b185f/runtime.json +17 -0
- package/.ikie/ferments/019f275c-447e-756d-8ec0-091e54bcc7b4/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f275c-447e-756d-8ec0-091e54bcc7b4/runtime.json +17 -0
- package/.ikie/ferments/019f275c-4602-757e-9283-3606516f4d15/runtime.json +11 -0
- package/.ikie/ferments/019f275c-4a3b-75f0-8355-8524d1589242/runtime.json +11 -0
- package/.ikie/ferments/019f275c-4a5c-744e-9792-deb33fe1e244/runtime.json +11 -0
- package/.ikie/ferments/019f275c-4a79-73d2-beae-4e85f8906581/runtime.json +11 -0
- package/.ikie/ferments/019f275c-4a97-70b9-98d1-53d9326b4c95/runtime.json +11 -0
- package/.ikie/ferments/019f275c-4ac1-7452-ab7a-485bde641591/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275c-4ad7-77ba-8a63-d8586db466e7/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275c-4bee-77b9-8470-98c4aafeae43/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275c-4c3d-712b-95f6-a671b7884658/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275c-4c4e-73a0-accb-e76c29bc1f6d/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275c-7598-775d-beed-cde3b6cb74e6/runtime.json +13 -0
- package/.ikie/ferments/019f275c-75c0-773d-9c0c-dd4943fc6092/runtime.json +11 -0
- package/.ikie/ferments/019f275c-75dc-7629-8a52-1eba66275779/runtime.json +11 -0
- package/.ikie/ferments/019f275c-75f3-742b-8494-e8a1facb02bb/runtime.json +11 -0
- package/.ikie/ferments/019f275c-760c-705e-8d98-7963d8830086/runtime.json +11 -0
- package/.ikie/ferments/019f275c-7627-763c-ae8e-20dde59c64b9/runtime.json +11 -0
- package/.ikie/ferments/019f275c-763c-74ae-b835-b52b57c52e9b/runtime.json +11 -0
- package/.ikie/ferments/019f275c-7650-7499-b744-7f38cfa776f4/runtime.json +11 -0
- package/.ikie/ferments/019f275c-766d-75b8-ba35-69e472baf630/runtime.json +9 -0
- package/.ikie/ferments/019f275c-7687-72cc-beac-339a11625f14/runtime.json +13 -0
- package/.ikie/ferments/019f275c-76a6-773d-a4c1-19a5ec313596/runtime.json +11 -0
- package/.ikie/ferments/019f275c-76c1-71b9-a49e-4b520fcef543/runtime.json +11 -0
- package/.ikie/ferments/019f275c-7706-761f-a9cf-7e412e88015d/runtime.json +11 -0
- package/.ikie/ferments/019f275c-772b-745f-a74d-de30f52a3316/runtime.json +9 -0
- package/.ikie/ferments/019f275c-7746-759c-a116-c2cd08e2f29b/runtime.json +9 -0
- package/.ikie/ferments/019f275c-7760-709d-83bc-4d6fff7ac768/runtime.json +11 -0
- package/.ikie/ferments/019f275c-780e-74db-9d7d-bcc430c1a964/runtime.json +11 -0
- package/.ikie/ferments/019f275c-7826-734e-8113-90111e82d96a/runtime.json +12 -0
- package/.ikie/ferments/019f275c-7849-72ed-8fb0-d1815d2f66d3/runtime.json +11 -0
- package/.ikie/ferments/019f275c-785f-716e-b077-eee453653ee0/runtime.json +11 -0
- package/.ikie/ferments/019f275c-7871-70fe-b543-bcdaaa10d320/runtime.json +11 -0
- package/.ikie/ferments/019f275c-7888-777d-8edf-1a5a906679d7/runtime.json +11 -0
- package/.ikie/ferments/019f275c-78b3-722e-9d1a-f354b0d0fa96/runtime.json +13 -0
- package/.ikie/ferments/019f275c-78cb-7568-ad11-191bc98cabe5/runtime.json +11 -0
- package/.ikie/ferments/019f275c-8905-76ae-beb3-2ec9138b799b/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f275c-8905-76ae-beb3-2ec9138b799b/runtime.json +11 -0
- package/.ikie/ferments/019f275c-8970-713f-a498-af24ac57355a/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f275c-8970-713f-a498-af24ac57355a/runtime.json +13 -0
- package/.ikie/ferments/019f275c-89c6-712f-b3c9-d9459bdaba76/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275c-89c6-712f-b3c9-d9459bdaba76/runtime.json +9 -0
- package/.ikie/ferments/019f275c-89e8-7105-9ba9-eda02056339a/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275c-89e8-7105-9ba9-eda02056339a/runtime.json +9 -0
- package/.ikie/ferments/019f275c-8a0d-71cb-bbb3-aa061c305aab/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275c-8a0d-71cb-bbb3-aa061c305aab/runtime.json +9 -0
- package/.ikie/ferments/019f275c-8a31-758b-87c7-1b2ec8b0bd7a/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275c-8a31-758b-87c7-1b2ec8b0bd7a/runtime.json +9 -0
- package/.ikie/ferments/019f275c-8a4f-7649-a250-4074bed6f208/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275c-8a4f-7649-a250-4074bed6f208/runtime.json +9 -0
- package/.ikie/ferments/019f275c-8a6e-706d-af6d-f6636f3b229e/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f275c-8a6e-706d-af6d-f6636f3b229e/runtime.json +9 -0
- package/.ikie/ferments/019f275e-8903-721d-98f8-0135ab6b4698/runtime.json +11 -0
- package/.ikie/ferments/019f275e-8920-7644-a529-664b63f9bab1/runtime.json +11 -0
- package/.ikie/ferments/019f275e-8938-75c2-85ab-f5a50138a4eb/runtime.json +11 -0
- package/.ikie/ferments/019f275e-895e-74a1-b263-2f73d989898e/runtime.json +12 -0
- package/.ikie/ferments/019f275e-8977-75ee-9e9a-cc069fff1cfa/runtime.json +11 -0
- package/.ikie/ferments/019f275e-899d-773b-abe3-e93c56f57cf1/runtime.json +11 -0
- package/.ikie/ferments/019f275e-89d1-72ea-9362-d4ce4079e846/runtime.json +15 -0
- package/.ikie/ferments/019f275e-89f9-7007-b382-a55e983d9520/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8a1d-7687-a56e-94ead3cafbf8/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8a49-760f-9639-3ce1494f37e9/runtime.json +13 -0
- package/.ikie/ferments/019f275e-8a7d-7461-b978-c3478b99b386/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8aac-736d-bd96-6b442359993b/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8ae6-7298-a523-d2fb7287bed3/runtime.json +11 -0
- package/.ikie/ferments/019f275e-8b01-7059-85a1-a665334ced3e/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8b29-7295-be5b-0468763ab101/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8b51-7204-9d30-0a67dae9c341/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8b78-71eb-a8a3-1448d3373912/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8b9d-76bf-9caa-0fed193b85bf/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8bc0-71df-9356-19d3075c9568/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8be2-75bd-be4a-ba2ede0e95f3/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8c0b-714a-a389-20ffe6d0e66d/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8c30-7371-86af-78e5f5ac8b23/runtime.json +15 -0
- package/.ikie/ferments/019f275e-8c5a-7383-bd79-c7fec3a71946/runtime.json +11 -0
- package/.ikie/ferments/019f275e-8c75-76b1-bcaa-81e67fc35aa8/runtime.json +11 -0
- package/.ikie/ferments/019f275e-8caa-71e9-9e66-0d30c4a03123/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f275e-8caa-71e9-9e66-0d30c4a03123/runtime.json +17 -0
- package/.ikie/ferments/019f275e-8e59-7787-84f8-fcf93ec75949/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f275e-8e59-7787-84f8-fcf93ec75949/runtime.json +17 -0
- package/.ikie/ferments/019f275e-8ffb-70c2-844e-e1f4fa4c2cc4/runtime.json +11 -0
- package/.ikie/ferments/019f275e-949b-7158-a426-07bcca442439/runtime.json +11 -0
- package/.ikie/ferments/019f275e-94c6-7479-abcb-c22fc19445a0/runtime.json +11 -0
- package/.ikie/ferments/019f275e-94eb-76e9-a148-fb5001492823/runtime.json +11 -0
- package/.ikie/ferments/019f275e-9516-765a-b8ee-e88e5ab2530f/runtime.json +11 -0
- package/.ikie/ferments/019f275e-9539-740f-bbdb-09b82f71fc81/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275e-954f-73e0-9286-fdf09cb1cbc6/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275e-967d-73dc-bfaf-18e44335cff8/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275e-96f0-702d-b0d2-f2aeb1c7ee15/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275e-9708-770c-bae2-2652e32be3cf/pending-proposal.json +45 -0
- package/.ikie/ferments/019f275e-c992-77a4-960a-d6d51983c9d6/runtime.json +13 -0
- package/.ikie/ferments/019f275e-c9cf-724a-a59f-8e34f026db5e/runtime.json +11 -0
- package/.ikie/ferments/019f275e-c9e6-7647-9517-b2b25cd1f495/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ca11-716b-832b-11fc14ce1ded/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ca2f-74df-90fa-2eed00b55ecf/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ca49-77ed-bb62-cd9c3c1176a5/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ca62-77ca-aed0-74728cab4be4/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ca7a-76aa-a860-42152a699337/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ca9b-766c-9ad4-2f86ff5c9dbe/runtime.json +9 -0
- package/.ikie/ferments/019f275e-cabc-77cf-a94a-9f8988667998/runtime.json +13 -0
- package/.ikie/ferments/019f275e-cae6-76d9-8682-d138cbd0e3cf/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cb0a-7361-8e72-84e44afa7847/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cb67-71dd-a7b7-35d98fca2379/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cb8c-75c8-9a02-812c50dbcc28/runtime.json +9 -0
- package/.ikie/ferments/019f275e-cba7-74c5-8a0e-facff616ecf0/runtime.json +9 -0
- package/.ikie/ferments/019f275e-cbc6-719a-a1e9-86fad18fb0de/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cc83-7608-878d-3b107b55db48/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cc96-72f9-9e5d-a350ea59c5b7/runtime.json +12 -0
- package/.ikie/ferments/019f275e-ccb5-72bf-8ad6-8ea4f87f86c0/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ccd9-77de-89ff-25fa626c05b4/runtime.json +11 -0
- package/.ikie/ferments/019f275e-ccfb-777a-8a40-1ccaf4c139c4/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cd15-7785-be69-1f9ef80faa52/runtime.json +11 -0
- package/.ikie/ferments/019f275e-cd31-7629-9034-57bcde8cf8e1/runtime.json +13 -0
- package/.ikie/ferments/019f275e-cd56-74be-8cdd-94af39b5593b/runtime.json +11 -0
- package/.ikie/ferments/019f275e-db71-73fb-9992-6d52de708265/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f275e-db71-73fb-9992-6d52de708265/runtime.json +11 -0
- package/.ikie/ferments/019f275e-dbc0-725b-bb55-3eca5072215b/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f275e-dbc0-725b-bb55-3eca5072215b/runtime.json +13 -0
- package/.ikie/ferments/019f275e-dc11-7320-bc60-fbca50c8e709/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275e-dc11-7320-bc60-fbca50c8e709/runtime.json +9 -0
- package/.ikie/ferments/019f275e-dc39-73ee-9d63-d8fbb906d877/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275e-dc39-73ee-9d63-d8fbb906d877/runtime.json +9 -0
- package/.ikie/ferments/019f275e-dc60-7649-9918-b236d9a16cef/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275e-dc60-7649-9918-b236d9a16cef/runtime.json +9 -0
- package/.ikie/ferments/019f275e-dc83-7030-aa35-3a78b18fadb4/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275e-dc83-7030-aa35-3a78b18fadb4/runtime.json +9 -0
- package/.ikie/ferments/019f275e-dcb3-706f-b3b0-b44556b7d3cb/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f275e-dcb3-706f-b3b0-b44556b7d3cb/runtime.json +9 -0
- package/.ikie/ferments/019f275e-dcd6-717c-afe6-82a959a0fcbd/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f275e-dcd6-717c-afe6-82a959a0fcbd/runtime.json +9 -0
- package/.ikie/ferments/019f2764-6cde-7610-b409-ee715ca796e8/runtime.json +11 -0
- package/.ikie/ferments/019f2764-6cfa-733d-8231-937535e2e6b8/runtime.json +11 -0
- package/.ikie/ferments/019f2764-6d11-7611-b216-dcdaa468d686/runtime.json +11 -0
- package/.ikie/ferments/019f2764-6d33-728f-901c-4fef8141050d/runtime.json +12 -0
- package/.ikie/ferments/019f2764-6d5d-7314-9e98-3851effc803f/runtime.json +11 -0
- package/.ikie/ferments/019f2764-6d87-722e-bf53-0dd6182ea7c6/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6daa-7052-b766-8aef8e542b88/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6dc9-73fc-8665-a3f8b51f7450/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6df3-7368-94a2-5369f3276848/runtime.json +13 -0
- package/.ikie/ferments/019f2764-6e25-762c-a0e0-0ef60c6e2653/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6e58-733d-ab0e-8fad4b2c665e/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6ead-742a-afc5-e10a044333ec/runtime.json +11 -0
- package/.ikie/ferments/019f2764-6ec9-7566-a4f0-e0d14f80e103/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6efe-727d-a81b-36fbde2904b3/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6f3d-7292-bbf4-88e9ee6b077e/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6f6c-758f-9427-652571b7494f/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6faa-700b-8d2d-cbed35957db8/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6fcb-71d8-9daf-225746805ba4/runtime.json +15 -0
- package/.ikie/ferments/019f2764-6ff0-7573-9208-e236e2969c5a/runtime.json +15 -0
- package/.ikie/ferments/019f2764-7012-77ce-97c9-6e99dd0367b3/runtime.json +15 -0
- package/.ikie/ferments/019f2764-703d-7554-8008-5104879d081d/runtime.json +15 -0
- package/.ikie/ferments/019f2764-7082-7399-80d5-659015dc6129/runtime.json +11 -0
- package/.ikie/ferments/019f2764-70b4-7581-b83e-9945010b008b/runtime.json +11 -0
- package/.ikie/ferments/019f2764-70d2-71a1-8b2f-1db7c0de5d5b/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2764-70d2-71a1-8b2f-1db7c0de5d5b/runtime.json +17 -0
- package/.ikie/ferments/019f2764-7256-714b-9804-17a6ad3c7996/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2764-7256-714b-9804-17a6ad3c7996/runtime.json +17 -0
- package/.ikie/ferments/019f2764-742b-711f-9997-ae6ce141d7d9/runtime.json +11 -0
- package/.ikie/ferments/019f2764-78e4-765c-bcf6-ae76955d98c0/runtime.json +11 -0
- package/.ikie/ferments/019f2764-7900-7573-afaf-c32d1b6a7be0/runtime.json +11 -0
- package/.ikie/ferments/019f2764-7920-7463-b2c3-132980285998/runtime.json +11 -0
- package/.ikie/ferments/019f2764-7947-721f-9c5e-6fc087b2e912/runtime.json +11 -0
- package/.ikie/ferments/019f2764-7967-735b-9066-12a93c490f17/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2764-798b-749d-b86b-90c55c838b29/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2764-7a9f-747c-81ce-f27825e1cefb/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2764-7afc-745a-8d70-a2ebf234977d/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2764-7b0f-715d-a410-e707593c0f1b/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2764-a49c-750d-8022-8d5ef7b34341/runtime.json +13 -0
- package/.ikie/ferments/019f2764-a4c0-7779-a268-1589e2c4d025/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a4e2-706f-8cc3-f71f13a5334c/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a4fc-765c-b248-0fd90d273737/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a511-7719-b577-47d9389dc68c/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a524-731c-91d5-99c2242128e7/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a53c-7308-a4a2-2c4ebd0af1f2/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a555-762a-b6ec-c7a1ea59914b/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a56e-776a-8421-d52ce16332e6/runtime.json +9 -0
- package/.ikie/ferments/019f2764-a584-75ad-8cf4-02ad739aeac6/runtime.json +13 -0
- package/.ikie/ferments/019f2764-a5a6-716c-8803-03dfe8638639/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a5cb-75a8-9184-8bc493e04858/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a613-726d-9770-828b95668f3d/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a62b-703f-ad34-e560da58091f/runtime.json +9 -0
- package/.ikie/ferments/019f2764-a646-75a7-a048-e1c6a57c17db/runtime.json +9 -0
- package/.ikie/ferments/019f2764-a65d-7369-8043-22e8aa877564/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a714-7737-9aca-229d1f730df1/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a725-71af-91db-6146483607ce/runtime.json +12 -0
- package/.ikie/ferments/019f2764-a748-721c-a9bb-9a5cd1a6390b/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a761-7632-84ba-5d4da92e371d/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a776-76dd-a48e-148e4d5e6dcd/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a78f-77d0-9647-ffb2ed828229/runtime.json +11 -0
- package/.ikie/ferments/019f2764-a7ab-716e-958d-c3f3c4d33a34/runtime.json +13 -0
- package/.ikie/ferments/019f2764-a7cb-775b-8844-8faa27f1ac1c/runtime.json +11 -0
- package/.ikie/ferments/019f2764-bd5e-773d-9b24-9da824db3174/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2764-bd5e-773d-9b24-9da824db3174/runtime.json +11 -0
- package/.ikie/ferments/019f2764-bda9-7207-b421-beff2d49cd2a/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2764-bda9-7207-b421-beff2d49cd2a/runtime.json +13 -0
- package/.ikie/ferments/019f2764-be1e-775f-b937-81b9fd368168/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2764-be1e-775f-b937-81b9fd368168/runtime.json +9 -0
- package/.ikie/ferments/019f2764-be38-7792-b549-8583fd6c5e70/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2764-be38-7792-b549-8583fd6c5e70/runtime.json +9 -0
- package/.ikie/ferments/019f2764-be5e-73da-85c5-508167795c94/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2764-be5e-73da-85c5-508167795c94/runtime.json +9 -0
- package/.ikie/ferments/019f2764-be82-721a-aa06-3b54c6236827/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2764-be82-721a-aa06-3b54c6236827/runtime.json +9 -0
- package/.ikie/ferments/019f2764-be97-703d-8e0a-6496ed0a83ca/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2764-be97-703d-8e0a-6496ed0a83ca/runtime.json +9 -0
- package/.ikie/ferments/019f2764-bebc-756a-a6ca-0f40b9705a0f/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2764-bebc-756a-a6ca-0f40b9705a0f/runtime.json +9 -0
- package/.ikie/ferments/019f2766-a81a-73aa-ba58-4a0192a7b079/runtime.json +11 -0
- package/.ikie/ferments/019f2766-a839-708c-b3bf-4c3f2279558e/runtime.json +11 -0
- package/.ikie/ferments/019f2766-a852-7641-a85f-69ea0ce5d73b/runtime.json +11 -0
- package/.ikie/ferments/019f2766-a877-74b8-b1de-3ffbbcb6f14b/runtime.json +12 -0
- package/.ikie/ferments/019f2766-a892-767d-b447-2e7a666f42f0/runtime.json +11 -0
- package/.ikie/ferments/019f2766-a8c2-7178-b06c-00d7646d1966/runtime.json +11 -0
- package/.ikie/ferments/019f2766-a8f5-713b-92d4-c4c70e48c5db/runtime.json +15 -0
- package/.ikie/ferments/019f2766-a91c-76a8-9d47-7e07b7843506/runtime.json +15 -0
- package/.ikie/ferments/019f2766-a944-7458-bae5-e3c38b3eec06/runtime.json +15 -0
- package/.ikie/ferments/019f2766-a973-77da-b2c0-d4f59f145d19/runtime.json +13 -0
- package/.ikie/ferments/019f2766-a9ae-701f-b8af-2d02369bc2f1/runtime.json +15 -0
- package/.ikie/ferments/019f2766-a9e5-7319-882f-58450ee132ea/runtime.json +15 -0
- package/.ikie/ferments/019f2766-aa3a-722b-9ed0-f38465896d02/runtime.json +11 -0
- package/.ikie/ferments/019f2766-aa58-7389-b25e-688385ff4a7f/runtime.json +15 -0
- package/.ikie/ferments/019f2766-aa8c-72f1-8b4e-a5260ac64189/runtime.json +15 -0
- package/.ikie/ferments/019f2766-aab7-7310-a9ec-b3027823b960/runtime.json +15 -0
- package/.ikie/ferments/019f2766-aae0-714c-b796-491d0c0d0e5b/runtime.json +15 -0
- package/.ikie/ferments/019f2766-ab05-740a-9fe0-2882dcad789b/runtime.json +15 -0
- package/.ikie/ferments/019f2766-ab2d-7188-9d25-545da08208e3/runtime.json +15 -0
- package/.ikie/ferments/019f2766-ab55-71d1-aafa-b6c62c6d7c7c/runtime.json +15 -0
- package/.ikie/ferments/019f2766-ab7f-76a1-9cde-c84ebb38a76c/runtime.json +15 -0
- package/.ikie/ferments/019f2766-abad-71db-9b6c-c341a91e609c/runtime.json +15 -0
- package/.ikie/ferments/019f2766-abd1-7392-a14e-a62f58887e86/runtime.json +11 -0
- package/.ikie/ferments/019f2766-abee-7229-9251-77f5474df062/runtime.json +11 -0
- package/.ikie/ferments/019f2766-ac13-77ab-ad1f-179bbf19f285/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2766-ac13-77ab-ad1f-179bbf19f285/runtime.json +17 -0
- package/.ikie/ferments/019f2766-ad4e-771a-8809-da61d5e9187d/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2766-ad4e-771a-8809-da61d5e9187d/runtime.json +17 -0
- package/.ikie/ferments/019f2766-aec7-72c7-8400-65d8774d93fe/runtime.json +11 -0
- package/.ikie/ferments/019f2766-b2e5-775e-a211-97476c9184fa/runtime.json +11 -0
- package/.ikie/ferments/019f2766-b303-70c5-a66a-e39ce29d0a4a/runtime.json +11 -0
- package/.ikie/ferments/019f2766-b32e-7618-860c-3cf1a98c2562/runtime.json +11 -0
- package/.ikie/ferments/019f2766-b353-719b-9299-207b9a3b41b3/runtime.json +11 -0
- package/.ikie/ferments/019f2766-b374-72e3-a804-8f3c82dc2059/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-b38b-75ca-83c3-d4e5625f814b/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-b495-73d6-a0d3-b26c033d4769/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-b4e1-70f8-a38e-c478ab72c091/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-b4f5-7671-b2c4-76d6f9f68cd3/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-d341-7410-8d94-056f70b5d884/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d35f-71a3-bdd3-c749aa870ff8/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d382-70be-9a79-094070335d58/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d3ae-75c7-b83e-4636e859cf7d/runtime.json +12 -0
- package/.ikie/ferments/019f2766-d3c7-778d-b399-f3e13fa34204/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d3f0-7730-9e47-9bbc5483d5c9/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d422-74ab-8e0b-6b5f139658b8/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d448-7428-94ec-084521c6f60a/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d46e-730e-89a6-dd0907baa5aa/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d49b-71df-91f7-b4fb8e050c88/runtime.json +13 -0
- package/.ikie/ferments/019f2766-d4d6-72fd-b5ab-8aa8554c3ac8/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d50b-7146-a0e2-bcc33cbf8168/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d54e-7614-a157-8c6225b09552/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d571-72f9-ac5f-9a58f8913af1/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d5aa-7756-b523-29a10b1f0f93/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d5ce-77b9-9746-ca5281e76d1e/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d5f2-76ee-92f0-88e85515bb8c/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d617-7669-8175-57038e3790b0/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d63b-72aa-a6ca-f355b068db00/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d664-754e-b827-42f9c6fc161b/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d68c-710d-8769-befe67aad042/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d6af-767c-9547-eee7f9c08dcf/runtime.json +15 -0
- package/.ikie/ferments/019f2766-d6d5-751e-8752-dcdc451712e2/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d6f7-77b8-807d-75d914ff0302/runtime.json +11 -0
- package/.ikie/ferments/019f2766-d720-7159-97a9-820f305b3805/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2766-d720-7159-97a9-820f305b3805/runtime.json +17 -0
- package/.ikie/ferments/019f2766-d87f-729d-be05-90c4adb20ade/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2766-d87f-729d-be05-90c4adb20ade/runtime.json +17 -0
- package/.ikie/ferments/019f2766-da17-724b-ab3c-7154c7845381/runtime.json +11 -0
- package/.ikie/ferments/019f2766-ddf5-7470-a884-297c8936753a/runtime.json +11 -0
- package/.ikie/ferments/019f2766-de1a-7283-89b6-a249b9c8bdc1/runtime.json +11 -0
- package/.ikie/ferments/019f2766-de39-7771-a717-14beb4313f79/runtime.json +11 -0
- package/.ikie/ferments/019f2766-de5b-7418-bbcc-2ed38543137c/runtime.json +11 -0
- package/.ikie/ferments/019f2766-de7d-76cc-a74f-def9d1d99ac3/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-de92-75a2-bcae-86efd5efe066/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-dfb5-771c-adc0-9e948e0b8f18/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-dff6-71cd-a14e-ab9e88792ca4/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2766-e006-727b-83d9-af9c71158bef/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2767-0345-74ba-a163-0c909ee37df1/runtime.json +11 -0
- package/.ikie/ferments/019f2767-036c-713d-9ef9-58a1191bd341/runtime.json +11 -0
- package/.ikie/ferments/019f2767-0387-72e6-b8b6-314fedade6e0/runtime.json +11 -0
- package/.ikie/ferments/019f2767-03af-738b-acde-360fa30a55f8/runtime.json +12 -0
- package/.ikie/ferments/019f2767-03cc-76e8-ae01-5b33c85fb46b/runtime.json +11 -0
- package/.ikie/ferments/019f2767-0409-7745-8f9d-a41ce8b7b11e/runtime.json +11 -0
- package/.ikie/ferments/019f2767-0467-70a9-8a75-2688109ab9c3/runtime.json +15 -0
- package/.ikie/ferments/019f2767-0493-7047-b2c9-a7ed6f70c89f/runtime.json +15 -0
- package/.ikie/ferments/019f2767-04b7-7486-a7cf-5ad7a09060a7/runtime.json +15 -0
- package/.ikie/ferments/019f2767-050f-713f-ba94-c01b549b3dfa/runtime.json +13 -0
- package/.ikie/ferments/019f2767-0561-7481-90da-2febe6cffddd/runtime.json +15 -0
- package/.ikie/ferments/019f2767-059c-74bb-b3fb-5e762939b3f6/runtime.json +15 -0
- package/.ikie/ferments/019f2767-05f6-7778-87d7-bd17f16cbfb5/runtime.json +11 -0
- package/.ikie/ferments/019f2767-0621-765e-9af4-4fd53e8fa0ec/runtime.json +15 -0
- package/.ikie/ferments/019f2767-0652-77a4-86f8-fd32c3d03927/runtime.json +15 -0
- package/.ikie/ferments/019f2767-067b-734b-85e5-cd7fc79c73cb/runtime.json +15 -0
- package/.ikie/ferments/019f2767-06aa-71fa-a287-db9463cdae51/runtime.json +15 -0
- package/.ikie/ferments/019f2767-06d5-771d-8f7b-cb18b2f9f122/runtime.json +15 -0
- package/.ikie/ferments/019f2767-070a-7043-87fe-09012eaea4d6/runtime.json +15 -0
- package/.ikie/ferments/019f2767-0733-707e-b141-7af7e0e43e30/runtime.json +15 -0
- package/.ikie/ferments/019f2767-0751-7478-ae88-39af753f8f08/runtime.json +15 -0
- package/.ikie/ferments/019f2767-0791-73af-be60-fe5a809f66bc/runtime.json +15 -0
- package/.ikie/ferments/019f2767-07c5-720a-b9b7-1f96816c4122/runtime.json +11 -0
- package/.ikie/ferments/019f2767-07e4-74fc-bf92-5f4c9c1cefab/runtime.json +11 -0
- package/.ikie/ferments/019f2767-080c-77c8-a174-e8b97bd69510/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2767-080c-77c8-a174-e8b97bd69510/runtime.json +17 -0
- package/.ikie/ferments/019f2767-0986-7509-b1d0-7650aae65deb/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2767-0986-7509-b1d0-7650aae65deb/runtime.json +17 -0
- package/.ikie/ferments/019f2767-0b6e-7011-aec4-f728f98727ed/runtime.json +11 -0
- package/.ikie/ferments/019f2767-10a6-75cc-850a-34d704f7eac9/runtime.json +11 -0
- package/.ikie/ferments/019f2767-10cf-70aa-a00c-086ec4813201/runtime.json +11 -0
- package/.ikie/ferments/019f2767-1101-74f7-8518-da795dd7aef7/runtime.json +11 -0
- package/.ikie/ferments/019f2767-1140-738e-b9ce-35b94e415549/runtime.json +11 -0
- package/.ikie/ferments/019f2767-1172-75a9-8f24-74316bfc7d53/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2767-118b-7048-a5d7-cffbef0e44e2/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2767-12be-730b-92b2-0bba958b78a1/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2767-131f-720b-b45a-382835a523ef/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2767-1335-74eb-b84c-9af1e9e52ff0/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2767-4563-715a-8c3c-cadf61ab94cf/runtime.json +13 -0
- package/.ikie/ferments/019f2767-45b2-701b-990c-a8a30ff2c5f2/runtime.json +11 -0
- package/.ikie/ferments/019f2767-45d7-705e-a8fc-202c2c894d5f/runtime.json +11 -0
- package/.ikie/ferments/019f2767-45ee-773f-a4e7-6022c91b113c/runtime.json +11 -0
- package/.ikie/ferments/019f2767-4613-7769-b4fa-6abde054e49d/runtime.json +11 -0
- package/.ikie/ferments/019f2767-4626-704a-9d3e-6d51ff2c45c6/runtime.json +11 -0
- package/.ikie/ferments/019f2767-4637-7346-b00e-35216ec55688/runtime.json +11 -0
- package/.ikie/ferments/019f2767-4649-709c-9269-7d92ac49807a/runtime.json +11 -0
- package/.ikie/ferments/019f2767-465e-76ec-a7c0-c63d79f0807f/runtime.json +9 -0
- package/.ikie/ferments/019f2767-4679-76c1-8e62-1c105c4c6b0b/runtime.json +13 -0
- package/.ikie/ferments/019f2767-4692-762a-963b-a53456d259fc/runtime.json +11 -0
- package/.ikie/ferments/019f2767-46a7-7236-9510-fd0d5ecf273f/runtime.json +11 -0
- package/.ikie/ferments/019f2767-46ee-705c-ad1a-e028ca79062a/runtime.json +11 -0
- package/.ikie/ferments/019f2767-4702-741b-bb09-b4fd8cd9f15a/runtime.json +9 -0
- package/.ikie/ferments/019f2767-4720-7192-9e90-89cc2710255a/runtime.json +9 -0
- package/.ikie/ferments/019f2767-475f-70dc-9883-271aaa69c2b4/runtime.json +11 -0
- package/.ikie/ferments/019f2767-4852-749f-9c8b-920b2c2b25d3/runtime.json +11 -0
- package/.ikie/ferments/019f2767-486c-7309-a9ff-92579b04dc8c/runtime.json +12 -0
- package/.ikie/ferments/019f2767-4899-771f-9f50-89e448dff488/runtime.json +11 -0
- package/.ikie/ferments/019f2767-48ae-7328-a163-a959e2087743/runtime.json +11 -0
- package/.ikie/ferments/019f2767-48ce-717a-828c-6b765da0a306/runtime.json +11 -0
- package/.ikie/ferments/019f2767-48ef-707c-a17e-9db9da0eee1f/runtime.json +11 -0
- package/.ikie/ferments/019f2767-490b-704b-9369-05fcbb050e2b/runtime.json +13 -0
- package/.ikie/ferments/019f2767-4938-752e-a022-f76dadf8fcaf/runtime.json +11 -0
- package/.ikie/ferments/019f2767-5cc6-73b9-b8e4-cb3719bbdc8d/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f2767-5cc6-73b9-b8e4-cb3719bbdc8d/runtime.json +11 -0
- package/.ikie/ferments/019f2767-5d22-7419-840b-e18d2fe5a41d/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f2767-5d22-7419-840b-e18d2fe5a41d/runtime.json +13 -0
- package/.ikie/ferments/019f2767-5d8c-75b0-bf28-5a0781cd0686/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2767-5d8c-75b0-bf28-5a0781cd0686/runtime.json +9 -0
- package/.ikie/ferments/019f2767-5dae-76e9-b23a-366527e3a529/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2767-5dae-76e9-b23a-366527e3a529/runtime.json +9 -0
- package/.ikie/ferments/019f2767-5dd4-73bf-821e-d74e53b266e1/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2767-5dd4-73bf-821e-d74e53b266e1/runtime.json +9 -0
- package/.ikie/ferments/019f2767-5de9-7518-a677-02b4926a0196/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2767-5de9-7518-a677-02b4926a0196/runtime.json +9 -0
- package/.ikie/ferments/019f2767-5dff-772a-b855-57afbb5e9c7e/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f2767-5dff-772a-b855-57afbb5e9c7e/runtime.json +9 -0
- package/.ikie/ferments/019f2767-5e39-76a5-8dcc-6f9004f4a58e/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f2767-5e39-76a5-8dcc-6f9004f4a58e/runtime.json +9 -0
- package/.ikie/ferments/019f2769-b766-74eb-844e-9903bf64f06d/runtime.json +11 -0
- package/.ikie/ferments/019f2769-b784-72fa-a138-7bdc2fc6e070/runtime.json +11 -0
- package/.ikie/ferments/019f2769-b79d-745b-b577-2ee15d5649b0/runtime.json +11 -0
- package/.ikie/ferments/019f2769-b7c3-75be-9db0-360b0deea44b/runtime.json +12 -0
- package/.ikie/ferments/019f2769-b7e0-758f-bd6a-734520ad3afa/runtime.json +11 -0
- package/.ikie/ferments/019f2769-b807-721e-8827-30e490c8823c/runtime.json +11 -0
- package/.ikie/ferments/019f2769-b836-727d-9c7f-b5a5f03dcc56/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b858-76ae-9fe0-b56d97afdf9b/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b87a-716c-9c81-14f1fa52f217/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b8a2-73dc-9d6d-ac781b700816/runtime.json +13 -0
- package/.ikie/ferments/019f2769-b8d1-7689-9405-e97b063ec3a1/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b904-7154-8946-12e041f89921/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b941-713f-8e2b-1a608dec7ca6/runtime.json +11 -0
- package/.ikie/ferments/019f2769-b95b-7122-bb5d-0bb3a2ad220a/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b97d-728d-b8fb-b1f302b1d819/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b99d-747b-853b-e415c006bfd2/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b9c0-76d6-a254-fba31ac6b662/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b9dd-7349-b246-95853d5d3af0/runtime.json +15 -0
- package/.ikie/ferments/019f2769-b9fe-774f-80cd-06bfedd8a956/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ba1e-70d2-af18-3ea245abc903/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ba45-7730-aae9-9ca14bc6a81b/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ba72-7273-903c-d33bcd036a6b/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ba93-70f3-8884-7b067dd711a4/runtime.json +11 -0
- package/.ikie/ferments/019f2769-baad-714f-8207-a7d630f37e84/runtime.json +11 -0
- package/.ikie/ferments/019f2769-bac7-75ae-95cb-dda85f7fd6a8/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2769-bac7-75ae-95cb-dda85f7fd6a8/runtime.json +17 -0
- package/.ikie/ferments/019f2769-bbf3-745d-87d3-d594593afbf0/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2769-bbf3-745d-87d3-d594593afbf0/runtime.json +17 -0
- package/.ikie/ferments/019f2769-bd4e-735d-b931-2077f62d385a/runtime.json +11 -0
- package/.ikie/ferments/019f2769-c103-723f-aebe-ab3ae76aedd9/runtime.json +11 -0
- package/.ikie/ferments/019f2769-c11e-771a-b365-96bf54691b95/runtime.json +11 -0
- package/.ikie/ferments/019f2769-c13b-749e-840d-5136528371f3/runtime.json +11 -0
- package/.ikie/ferments/019f2769-c15a-7065-83b5-2064b699a6d9/runtime.json +11 -0
- package/.ikie/ferments/019f2769-c175-77b2-80df-918134508175/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-c189-7508-8a46-3ff461bf759f/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-c27c-71eb-910f-36daf69588f8/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-c2c5-71bd-b6a6-dd0f8365cc7c/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-c2d6-7260-bab6-3e46b6e9100c/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-e6d9-700b-a486-64cad0909610/runtime.json +11 -0
- package/.ikie/ferments/019f2769-e6f5-7524-955a-dd4d91813ee5/runtime.json +11 -0
- package/.ikie/ferments/019f2769-e713-715e-9450-42b5250709c8/runtime.json +11 -0
- package/.ikie/ferments/019f2769-e738-7537-b5d5-5209200233da/runtime.json +12 -0
- package/.ikie/ferments/019f2769-e769-752f-b806-14f369200356/runtime.json +11 -0
- package/.ikie/ferments/019f2769-e795-77e8-bc69-fa7496923f00/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e7bb-72a8-ba2a-6d90fe6003cc/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e7e1-719b-becd-d456fe580bf8/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e80b-7539-ac23-4ccf01499e01/runtime.json +13 -0
- package/.ikie/ferments/019f2769-e83e-77c7-8415-7b3e76c827b1/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e86c-7008-8cdb-4d2ae411fc57/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e8ac-7480-b1cc-6913e20e012f/runtime.json +11 -0
- package/.ikie/ferments/019f2769-e8ca-76bd-b0be-bee2f2a97d7d/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e904-7759-b2aa-dbb47427c11b/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e92a-7285-bbd7-ed4220ac3f44/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e95e-77eb-9e17-6b2ad4532f0c/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e992-75ea-adf9-53f548b600a0/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e9b9-75bc-ab7a-a4ba5e8f1124/runtime.json +15 -0
- package/.ikie/ferments/019f2769-e9ec-700b-990f-320c347ee271/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ea15-72cb-96af-a45603082ee1/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ea42-735c-b71e-259c75688841/runtime.json +15 -0
- package/.ikie/ferments/019f2769-ea6f-7074-acde-65385abd199a/runtime.json +11 -0
- package/.ikie/ferments/019f2769-ea98-759c-aeda-90b28cab640c/runtime.json +11 -0
- package/.ikie/ferments/019f2769-eac3-70a7-993e-435d9a1dfd91/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2769-eac3-70a7-993e-435d9a1dfd91/runtime.json +17 -0
- package/.ikie/ferments/019f2769-ec3c-7674-829a-fba66a9bc62e/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f2769-ec3c-7674-829a-fba66a9bc62e/runtime.json +17 -0
- package/.ikie/ferments/019f2769-edcb-748c-be28-51e21c608c6f/runtime.json +11 -0
- package/.ikie/ferments/019f2769-f2df-7759-811f-ef76a54375e8/runtime.json +11 -0
- package/.ikie/ferments/019f2769-f311-7641-88b0-81c54945642f/runtime.json +11 -0
- package/.ikie/ferments/019f2769-f363-723b-80f1-b52334dc6a15/runtime.json +11 -0
- package/.ikie/ferments/019f2769-f38e-72cc-a4ac-81cefc3a95f4/runtime.json +11 -0
- package/.ikie/ferments/019f2769-f3b6-763a-bf65-011ce164f5d4/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-f3c7-745e-9da1-37e14b1cfddf/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-f4e4-71b1-83f1-b16014904ec3/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-f556-761d-b331-acc7cc02317d/pending-proposal.json +45 -0
- package/.ikie/ferments/019f2769-f56d-77af-82f3-b9915ca80a61/pending-proposal.json +45 -0
- package/.ikie/ferments/019f276a-23f9-7653-8be0-dca748ac5e0f/runtime.json +13 -0
- package/.ikie/ferments/019f276a-2428-731f-959b-8d346551f0c4/runtime.json +11 -0
- package/.ikie/ferments/019f276a-2446-7250-be5c-bdb0ac1ef2fa/runtime.json +11 -0
- package/.ikie/ferments/019f276a-2462-764e-a7f4-d9ab3876fbd2/runtime.json +11 -0
- package/.ikie/ferments/019f276a-2482-768b-919e-d81a0709abd5/runtime.json +11 -0
- package/.ikie/ferments/019f276a-2494-77ee-8b28-72b9b0d19d56/runtime.json +11 -0
- package/.ikie/ferments/019f276a-24aa-76fd-8fba-2a1d73960010/runtime.json +11 -0
- package/.ikie/ferments/019f276a-24c3-7799-bd35-0a3374f3e469/runtime.json +11 -0
- package/.ikie/ferments/019f276a-24f1-7498-a372-975f72302a0d/runtime.json +9 -0
- package/.ikie/ferments/019f276a-251e-71ac-ba90-af2a49c22b6b/runtime.json +13 -0
- package/.ikie/ferments/019f276a-2545-746f-bdf3-ca3c11ab9968/runtime.json +11 -0
- package/.ikie/ferments/019f276a-256d-765b-9f94-90047d4ca21e/runtime.json +11 -0
- package/.ikie/ferments/019f276a-25cb-753b-9905-7250e4eea970/runtime.json +11 -0
- package/.ikie/ferments/019f276a-25f8-73a2-aede-f2c017fa80c9/runtime.json +9 -0
- package/.ikie/ferments/019f276a-2613-774b-80c0-3b206ac95435/runtime.json +9 -0
- package/.ikie/ferments/019f276a-264e-73a3-90ad-017ef8ea05b6/runtime.json +11 -0
- package/.ikie/ferments/019f276a-2760-758f-b0a6-cd04a8b0ee76/runtime.json +11 -0
- package/.ikie/ferments/019f276a-277b-73a9-8655-6bf7018262dc/runtime.json +12 -0
- package/.ikie/ferments/019f276a-27a6-709d-a90f-f1784e248fca/runtime.json +11 -0
- package/.ikie/ferments/019f276a-27b7-75bf-b0b5-013581917821/runtime.json +11 -0
- package/.ikie/ferments/019f276a-27ce-759a-93de-474988efc050/runtime.json +11 -0
- package/.ikie/ferments/019f276a-27e9-7564-999a-73beef96d35c/runtime.json +11 -0
- package/.ikie/ferments/019f276a-27fc-714b-9ddb-117b439b664e/runtime.json +13 -0
- package/.ikie/ferments/019f276a-2824-762e-8def-3c17aa4041f9/runtime.json +11 -0
- package/.ikie/ferments/019f276a-38fe-725b-9c16-f1b5174302d0/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f276a-38fe-725b-9c16-f1b5174302d0/runtime.json +11 -0
- package/.ikie/ferments/019f276a-393c-75e2-b29f-092b82105a74/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f276a-393c-75e2-b29f-092b82105a74/runtime.json +13 -0
- package/.ikie/ferments/019f276a-3990-75f9-9b6f-ab6d45bf8e32/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276a-3990-75f9-9b6f-ab6d45bf8e32/runtime.json +9 -0
- package/.ikie/ferments/019f276a-39ab-76bb-be69-8658a1b6a76f/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276a-39ab-76bb-be69-8658a1b6a76f/runtime.json +9 -0
- package/.ikie/ferments/019f276a-39c9-76ac-95a8-2d5575d26573/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276a-39c9-76ac-95a8-2d5575d26573/runtime.json +9 -0
- package/.ikie/ferments/019f276a-39f6-76cc-9011-3f6b08068155/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276a-39f6-76cc-9011-3f6b08068155/runtime.json +9 -0
- package/.ikie/ferments/019f276a-3a0c-76a9-80b2-2bb7952fe9d7/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276a-3a0c-76a9-80b2-2bb7952fe9d7/runtime.json +9 -0
- package/.ikie/ferments/019f276a-3a22-7140-8a4d-0d17ada653b3/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f276a-3a22-7140-8a4d-0d17ada653b3/runtime.json +9 -0
- package/.ikie/ferments/019f276c-2f88-74ae-8bc2-5cec42d56757/runtime.json +11 -0
- package/.ikie/ferments/019f276c-2fb8-7599-b61c-e73c85399ee0/runtime.json +11 -0
- package/.ikie/ferments/019f276c-2fd9-75db-8e13-8e9137cecedd/runtime.json +11 -0
- package/.ikie/ferments/019f276c-302f-760f-97e7-2f10f283dfe1/runtime.json +12 -0
- package/.ikie/ferments/019f276c-3060-77ca-a0e3-d49781feca6d/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3091-744e-9394-a59b9f37db9e/runtime.json +11 -0
- package/.ikie/ferments/019f276c-30da-76ba-bd76-a72e053f218d/runtime.json +15 -0
- package/.ikie/ferments/019f276c-3110-7277-ab9a-820992db76da/runtime.json +15 -0
- package/.ikie/ferments/019f276c-314a-740f-b533-a31c4e9ebd52/runtime.json +15 -0
- package/.ikie/ferments/019f276c-3189-732c-a4ec-09e4f1e3a8da/runtime.json +13 -0
- package/.ikie/ferments/019f276c-31ce-75c8-a4e9-507d408920b6/runtime.json +15 -0
- package/.ikie/ferments/019f276c-320e-710b-b32a-4577244dcc6a/runtime.json +15 -0
- package/.ikie/ferments/019f276c-3262-7611-af21-ad12693acdd5/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3288-7559-b7c3-299dd548decb/runtime.json +15 -0
- package/.ikie/ferments/019f276c-32c4-70a0-899d-ad17469a015c/runtime.json +15 -0
- package/.ikie/ferments/019f276c-32f0-7036-86ae-19c9f703cd9a/runtime.json +15 -0
- package/.ikie/ferments/019f276c-3324-7021-8f89-d46fbfa45e00/runtime.json +15 -0
- package/.ikie/ferments/019f276c-334b-71df-b20d-d9a7bcccdc0a/runtime.json +15 -0
- package/.ikie/ferments/019f276c-3379-7593-957a-ee9631368280/runtime.json +15 -0
- package/.ikie/ferments/019f276c-33a9-705d-a590-eff1c46bcd67/runtime.json +15 -0
- package/.ikie/ferments/019f276c-33d5-7784-b35a-01d3c06b16c0/runtime.json +15 -0
- package/.ikie/ferments/019f276c-341c-76ce-b950-7a7e7472eeb8/runtime.json +15 -0
- package/.ikie/ferments/019f276c-3462-744d-b42a-9756a33b7223/runtime.json +11 -0
- package/.ikie/ferments/019f276c-348e-706a-9791-5213dfd00593/runtime.json +11 -0
- package/.ikie/ferments/019f276c-34b6-70f9-b678-d3a7d876758c/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f276c-34b6-70f9-b678-d3a7d876758c/runtime.json +17 -0
- package/.ikie/ferments/019f276c-3640-75da-915e-b0dba80bfcda/reviews/phase-phase-1-1.json +63 -0
- package/.ikie/ferments/019f276c-3640-75da-915e-b0dba80bfcda/runtime.json +17 -0
- package/.ikie/ferments/019f276c-37df-76f9-b7a8-1285ee0ac11d/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3caa-748a-a0aa-9e068f18f2ac/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3cc8-7347-9764-dd4ab7f87646/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3cef-75dd-be90-593fd20a850d/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3d14-72af-ae89-6c0605227a05/runtime.json +11 -0
- package/.ikie/ferments/019f276c-3d36-716c-ac4e-59444fdec814/pending-proposal.json +45 -0
- package/.ikie/ferments/019f276c-3d4c-7208-9130-7f168aeba08e/pending-proposal.json +45 -0
- package/.ikie/ferments/019f276c-3e7f-7552-a37f-61442d720fb9/pending-proposal.json +45 -0
- package/.ikie/ferments/019f276c-3ed9-74f2-9332-d5a492d39130/pending-proposal.json +45 -0
- package/.ikie/ferments/019f276c-3ef4-757e-b0c6-9d7c6f0326e7/pending-proposal.json +45 -0
- package/.ikie/ferments/019f276c-651d-70ac-bfb4-5d033388e28c/runtime.json +13 -0
- package/.ikie/ferments/019f276c-6546-7569-b609-74b2258985a8/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6566-71e2-b937-390aea78900a/runtime.json +11 -0
- package/.ikie/ferments/019f276c-657c-75ee-864b-5b5601e3b9d1/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6590-7729-a6e7-466ace311e0d/runtime.json +11 -0
- package/.ikie/ferments/019f276c-65a5-779f-a3da-36bc91cf31f3/runtime.json +11 -0
- package/.ikie/ferments/019f276c-65b9-77f0-97fc-fcf70d7125b8/runtime.json +11 -0
- package/.ikie/ferments/019f276c-65cd-74ef-9094-db3c5a98348b/runtime.json +11 -0
- package/.ikie/ferments/019f276c-65e3-7632-9df9-58cfa083a065/runtime.json +9 -0
- package/.ikie/ferments/019f276c-65fb-763a-aec7-54ece64d7342/runtime.json +13 -0
- package/.ikie/ferments/019f276c-661a-74e9-81b1-d1ba625c04b0/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6630-7748-ab90-869f75ed2de5/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6670-758f-b0da-673d81bd319e/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6687-71fa-8286-2d25de36c9b4/runtime.json +9 -0
- package/.ikie/ferments/019f276c-669d-7679-91d5-4df6315d3823/runtime.json +9 -0
- package/.ikie/ferments/019f276c-66b3-72a6-974d-1bc3477eb6f2/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6769-776c-9868-0c929ee31f5f/runtime.json +11 -0
- package/.ikie/ferments/019f276c-678e-7588-a059-c1efd9e9c9a6/runtime.json +12 -0
- package/.ikie/ferments/019f276c-67af-729c-a5f8-79e8e78bbe9b/runtime.json +11 -0
- package/.ikie/ferments/019f276c-67c3-70b8-8606-aad72ab0cd6f/runtime.json +11 -0
- package/.ikie/ferments/019f276c-67d7-734c-83fd-132c54564004/runtime.json +11 -0
- package/.ikie/ferments/019f276c-67ec-710d-8497-eba65301d741/runtime.json +11 -0
- package/.ikie/ferments/019f276c-6805-742c-8a1c-f370733226ae/runtime.json +13 -0
- package/.ikie/ferments/019f276c-6825-7768-8ca1-f5dac5c1d374/runtime.json +11 -0
- package/.ikie/ferments/019f276c-7f49-751d-bbb8-f828debd3cb9/reviews/phase-phase-1-1.json +41 -0
- package/.ikie/ferments/019f276c-7f49-751d-bbb8-f828debd3cb9/runtime.json +11 -0
- package/.ikie/ferments/019f276c-7f7b-74d0-b46e-e8efa73fb5b5/reviews/phase-phase-1-1.json +47 -0
- package/.ikie/ferments/019f276c-7f7b-74d0-b46e-e8efa73fb5b5/runtime.json +13 -0
- package/.ikie/ferments/019f276c-8004-74fe-b37f-f9fc659f7f0c/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276c-8004-74fe-b37f-f9fc659f7f0c/runtime.json +9 -0
- package/.ikie/ferments/019f276c-8025-7328-afef-6703215c208c/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276c-8025-7328-afef-6703215c208c/runtime.json +9 -0
- package/.ikie/ferments/019f276c-8043-749c-8cbb-47d0df9819df/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276c-8043-749c-8cbb-47d0df9819df/runtime.json +9 -0
- package/.ikie/ferments/019f276c-8062-7436-99eb-80e09bc6b067/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276c-8062-7436-99eb-80e09bc6b067/runtime.json +9 -0
- package/.ikie/ferments/019f276c-8081-727c-aa11-d606a64b88ed/reviews/phase-phase-1-1.json +40 -0
- package/.ikie/ferments/019f276c-8081-727c-aa11-d606a64b88ed/runtime.json +9 -0
- package/.ikie/ferments/019f276c-80b6-7528-8687-e11cc4691930/reviews/phase-phase-1-1.json +62 -0
- package/.ikie/ferments/019f276c-80b6-7528-8687-e11cc4691930/runtime.json +9 -0
- package/AGENTS.md +120 -0
- package/CLA.md +39 -0
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +57 -0
- package/LICENSE +203 -0
- package/NOTICE +28 -0
- package/README.md +568 -0
- package/SECURITY.md +36 -0
- package/TODO.md +33 -0
- package/benchmark/audit-session/README.md +217 -0
- package/benchmark/audit-session/audit-session-prompt.md +557 -0
- package/benchmark/audit-session/audit-session.sh +323 -0
- package/benchmark/manual/README.md +166 -0
- package/benchmark/manual/__pycache__/check-session.cpython-313.pyc +0 -0
- package/benchmark/manual/analyze-session.py +290 -0
- package/benchmark/manual/benchmark.json +4 -0
- package/benchmark/manual/check-session.py +268 -0
- package/benchmark/manual/compare-sessions.py +118 -0
- package/benchmark/manual/lib.sh +284 -0
- package/benchmark/manual/new-session-claude.sh +86 -0
- package/benchmark/manual/new-session.sh +191 -0
- package/benchmark/manual/run-evaluation.sh +201 -0
- package/benchmark/manual/seeds/explore-refactor/cmd/server/main.go +37 -0
- package/benchmark/manual/seeds/explore-refactor/go.mod +3 -0
- package/benchmark/manual/seeds/explore-refactor/internal/handler/audit.go +39 -0
- package/benchmark/manual/seeds/explore-refactor/internal/handler/invitation.go +56 -0
- package/benchmark/manual/seeds/explore-refactor/internal/handler/team.go +86 -0
- package/benchmark/manual/seeds/explore-refactor/internal/handler/user.go +126 -0
- package/benchmark/manual/seeds/explore-refactor/internal/model/model.go +37 -0
- package/benchmark/manual/seeds/explore-refactor/internal/repository/audit.go +57 -0
- package/benchmark/manual/seeds/explore-refactor/internal/repository/invitation.go +58 -0
- package/benchmark/manual/seeds/explore-refactor/internal/repository/team.go +66 -0
- package/benchmark/manual/seeds/explore-refactor/internal/repository/user.go +91 -0
- package/benchmark/manual/seeds/explore-refactor/internal/service/invitation.go +45 -0
- package/benchmark/manual/seeds/explore-refactor/internal/service/team.go +62 -0
- package/benchmark/manual/seeds/explore-refactor/internal/service/user.go +94 -0
- package/benchmark/manual/self-improvement.md +203 -0
- package/benchmark/manual/session-summary.py +95 -0
- package/benchmark/manual/start-self-improvement.sh +27 -0
- package/benchmark/manual/tasks.md +154 -0
- package/benchmark/terminal-bench-2/README.md +261 -0
- package/benchmark/terminal-bench-2/config/retry.yaml +48 -0
- package/benchmark/terminal-bench-2/docs/ferment-terminal-bench-analysis.md +233 -0
- package/benchmark/terminal-bench-2/pyproject.toml +32 -0
- package/benchmark/terminal-bench-2/scripts/analyze-ferment-bench.py +1193 -0
- package/benchmark/terminal-bench-2/scripts/run-claude-code-ikie.sh +41 -0
- package/benchmark/terminal-bench-2/scripts/run-gsd-ikie.sh +29 -0
- package/benchmark/terminal-bench-2/scripts/run-local.sh +32 -0
- package/benchmark/terminal-bench-2/scripts/run-opencode-ikie.sh +30 -0
- package/benchmark/terminal-bench-2/scripts/run-release.sh +28 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/__init__.py +6 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/agent.py +445 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/agent_test.py +233 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/claude_code_ikie.py +356 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/claude_code_ikie_test.py +506 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/config.py +56 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/gateway.py +163 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/gsd_ikie.py +340 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/gsd_ikie_test.py +304 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/messages.py +27 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/opencode_ikie.py +146 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/opencode_ikie_test.py +308 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/release.py +174 -0
- package/benchmark/terminal-bench-2/src/ikie_agent/retry_config_test.py +55 -0
- package/benchmark/terminal-bench-2/uv.lock +1948 -0
- package/biome.json +54 -0
- package/docs/agents.md +295 -0
- package/docs/bash-tool-guard.md +206 -0
- package/docs/expected-execution-scenarios.md +348 -0
- package/docs/ferment-storage-schema.md +199 -0
- package/docs/ferment.md +633 -0
- package/docs/hooks.md +263 -0
- package/docs/subagents/README.md +22 -0
- package/docs/subagents/code-reviewer.md +39 -0
- package/docs/subagents/research-assistant.md +81 -0
- package/docs/subagents/test-writer.md +49 -0
- package/docs/teleport.md +424 -0
- package/docs/windows/README.md +226 -0
- package/extensions/active-tools.ts +74 -0
- package/ikie.png +0 -0
- package/package.json +125 -0
- package/patches/@earendil-works__pi-ai@0.78.1.patch +68 -0
- package/patches/@earendil-works__pi-coding-agent@0.78.1.patch +535 -0
- package/patches/@earendil-works__pi-tui.patch +171 -0
- package/patches/playwright-core@1.59.1.patch +24 -0
- package/resources/oauth/error.html +185 -0
- package/resources/oauth/success.html +185 -0
- package/scripts/build-binary.js +113 -0
- package/scripts/build-proxy-helper.js +66 -0
- package/scripts/copy-resources.js +104 -0
- package/scripts/dev-overlay.sh +52 -0
- package/scripts/dev-startup.sh +82 -0
- package/scripts/install-local.js +34 -0
- package/scripts/install.ps1 +258 -0
- package/scripts/install.sh +160 -0
- package/scripts/package-release-asset.js +82 -0
- package/scripts/patch-pi-ai-oauth.js +109 -0
- package/scripts/run-tui-e2e.js +153 -0
- package/scripts/set-version.js +31 -0
- package/scripts/verify-acp-load.mjs +358 -0
- package/scripts/verify-acp.mjs +217 -0
- package/src/__mocks__/earendil-clipboard-image.js +6 -0
- package/src/agent-discovery/agents/claude-code.test.ts +156 -0
- package/src/agent-discovery/agents/claude-code.ts +85 -0
- package/src/agent-discovery/agents/cursor.test.ts +178 -0
- package/src/agent-discovery/agents/cursor.ts +74 -0
- package/src/agent-discovery/agents/opencode.test.ts +461 -0
- package/src/agent-discovery/agents/opencode.ts +156 -0
- package/src/agent-discovery/agents/skills-only.test.ts +77 -0
- package/src/agent-discovery/agents/skills-only.ts +47 -0
- package/src/agent-discovery/engine.test.ts +408 -0
- package/src/agent-discovery/engine.ts +117 -0
- package/src/agent-discovery/index.ts +75 -0
- package/src/agent-discovery/jsonc.ts +52 -0
- package/src/ansi.ts +51 -0
- package/src/api/me.test.ts +86 -0
- package/src/api/me.ts +59 -0
- package/src/auth/validator.test.ts +106 -0
- package/src/auth/validator.ts +103 -0
- package/src/auxiliary-files/resolver.test.ts +85 -0
- package/src/auxiliary-files/resolver.ts +27 -0
- package/src/auxiliary-files/validator.test.ts +68 -0
- package/src/auxiliary-files/validator.ts +31 -0
- package/src/cli-args.test.ts +232 -0
- package/src/cli-args.ts +94 -0
- package/src/cli-auth/callback-server.test.ts +169 -0
- package/src/cli-auth/callback-server.ts +165 -0
- package/src/cli-auth/index.test.ts +103 -0
- package/src/cli-auth/index.ts +117 -0
- package/src/cli-auth/oauth-page.ts +94 -0
- package/src/cli.ts +564 -0
- package/src/commands/_helpers.ts +87 -0
- package/src/commands/banner.test.ts +39 -0
- package/src/commands/banner.ts +74 -0
- package/src/commands/claude.ts +28 -0
- package/src/commands/config.test.ts +149 -0
- package/src/commands/config.ts +98 -0
- package/src/commands/cursor.ts +23 -0
- package/src/commands/dispatch.test.ts +102 -0
- package/src/commands/dispatch.ts +40 -0
- package/src/commands/gsd2.ts +23 -0
- package/src/commands/help.ts +104 -0
- package/src/commands/login.ts +46 -0
- package/src/commands/openclaw.ts +23 -0
- package/src/commands/opencode.ts +31 -0
- package/src/commands/registry.ts +44 -0
- package/src/commands/resources.ts +77 -0
- package/src/commands/setup-tools.test.ts +231 -0
- package/src/commands/setup-tools.ts +164 -0
- package/src/commands/setup.ts +28 -0
- package/src/commands/update.test.ts +312 -0
- package/src/commands/update.ts +291 -0
- package/src/commands/version.ts +9 -0
- package/src/components/editor.test.ts +182 -0
- package/src/components/editor.ts +186 -0
- package/src/components/footer.test.ts +790 -0
- package/src/components/footer.ts +640 -0
- package/src/components/logo-art.test.ts +30 -0
- package/src/components/logo-art.ts +66 -0
- package/src/components/logo.test.ts +316 -0
- package/src/components/logo.ts +127 -0
- package/src/components/tool-block.test.ts +75 -0
- package/src/components/tool-block.ts +166 -0
- package/src/config/footer-config.test.ts +191 -0
- package/src/config/footer-config.ts +130 -0
- package/src/config/json.test.ts +78 -0
- package/src/config/json.ts +112 -0
- package/src/config/scope.test.ts +49 -0
- package/src/config/scope.ts +38 -0
- package/src/config/shell-profile.test.ts +130 -0
- package/src/config/shell-profile.ts +131 -0
- package/src/config.test.ts +723 -0
- package/src/config.ts +697 -0
- package/src/entry.ts +62 -0
- package/src/env.ts +4 -0
- package/src/expand-state.ts +41 -0
- package/src/extensions/activity.test.ts +160 -0
- package/src/extensions/activity.ts +192 -0
- package/src/extensions/agent-worker-context.test.ts +31 -0
- package/src/extensions/agent-worker-context.ts +11 -0
- package/src/extensions/agents/default-agents.test.ts +24 -0
- package/src/extensions/agents/discovery-priority.test.ts +65 -0
- package/src/extensions/agents/env.ts +33 -0
- package/src/extensions/agents/index.test.ts +32 -0
- package/src/extensions/agents/index.ts +2226 -0
- package/src/extensions/agents/manager/agent-manager.test.ts +896 -0
- package/src/extensions/agents/manager/agent-manager.ts +714 -0
- package/src/extensions/agents/manager/agent-runner.test.ts +1846 -0
- package/src/extensions/agents/manager/agent-runner.ts +964 -0
- package/src/extensions/agents/manager/budget-retry-guard.test.ts +95 -0
- package/src/extensions/agents/manager/budget-retry-guard.ts +57 -0
- package/src/extensions/agents/manager/constants.ts +1 -0
- package/src/extensions/agents/manager/group-join.ts +136 -0
- package/src/extensions/agents/manager/output-file.test.ts +31 -0
- package/src/extensions/agents/manager/output-file.ts +92 -0
- package/src/extensions/agents/manager/session-file.test.ts +59 -0
- package/src/extensions/agents/manager/session-file.ts +37 -0
- package/src/extensions/agents/manager/usage.ts +52 -0
- package/src/extensions/agents/memory/memory.test.ts +54 -0
- package/src/extensions/agents/memory/memory.ts +166 -0
- package/src/extensions/agents/memory.test.ts +54 -0
- package/src/extensions/agents/package-resources.test.ts +147 -0
- package/src/extensions/agents/package-resources.ts +37 -0
- package/src/extensions/agents/personas/__snapshots__/default-agents.test.ts.snap +75 -0
- package/src/extensions/agents/personas/agent-types.test.ts +33 -0
- package/src/extensions/agents/personas/agent-types.ts +150 -0
- package/src/extensions/agents/personas/custom-agents.test.ts +171 -0
- package/src/extensions/agents/personas/custom-agents.ts +147 -0
- package/src/extensions/agents/personas/default-agents.test.ts +101 -0
- package/src/extensions/agents/personas/default-agents.ts +335 -0
- package/src/extensions/agents/personas/discovery-priority.test.ts +65 -0
- package/src/extensions/agents/personas/types.ts +229 -0
- package/src/extensions/agents/prompt/context.ts +54 -0
- package/src/extensions/agents/prompt/prompts.test.ts +314 -0
- package/src/extensions/agents/prompt/prompts.ts +164 -0
- package/src/extensions/agents/prompt/skill-loader.test.ts +41 -0
- package/src/extensions/agents/prompt/skill-loader.ts +80 -0
- package/src/extensions/agents/resolution/invocation-config.test.ts +81 -0
- package/src/extensions/agents/resolution/invocation-config.ts +68 -0
- package/src/extensions/agents/resolution/model-resolver.ts +85 -0
- package/src/extensions/agents/resume-tool.test.ts +146 -0
- package/src/extensions/agents/resume-tool.ts +90 -0
- package/src/extensions/agents/settings.ts +163 -0
- package/src/extensions/agents/skill-loader.test.ts +41 -0
- package/src/extensions/agents/tool-result.ts +4 -0
- package/src/extensions/agents/ui/agent-widget.ts +458 -0
- package/src/extensions/agents/ui/conversation-viewer.ts +261 -0
- package/src/extensions/agents/worker-budget-policy.ts +48 -0
- package/src/extensions/agents/worker-report.test.ts +69 -0
- package/src/extensions/agents/worker-report.ts +72 -0
- package/src/extensions/assistant-prefix.ts +80 -0
- package/src/extensions/bash-collapse.test.ts +21 -0
- package/src/extensions/bash-collapse.ts +3 -0
- package/src/extensions/bash-default-timeout.test.ts +189 -0
- package/src/extensions/bash-default-timeout.ts +73 -0
- package/src/extensions/bash-tool-guard-events.ts +39 -0
- package/src/extensions/bash-tool-guard.integration.test.ts +771 -0
- package/src/extensions/bash-tool-guard.test.ts +890 -0
- package/src/extensions/bash-tool-guard.ts +640 -0
- package/src/extensions/behaviours/bash-tokenize.test.ts +125 -0
- package/src/extensions/behaviours/bash-tokenize.ts +272 -0
- package/src/extensions/behaviours/bodies/bound-tool-output.md +11 -0
- package/src/extensions/behaviours/bodies/gh-cli.md +80 -0
- package/src/extensions/behaviours/bodies/git-hygiene.md +13 -0
- package/src/extensions/behaviours/bodies/glab-cli.md +95 -0
- package/src/extensions/behaviours/bodies/python-edit.md +10 -0
- package/src/extensions/behaviours/bodies/re-read-before-edit.md +10 -0
- package/src/extensions/behaviours/bodies.d.ts +7 -0
- package/src/extensions/behaviours/build.test.ts +89 -0
- package/src/extensions/behaviours/build.ts +63 -0
- package/src/extensions/behaviours/engine.test.ts +300 -0
- package/src/extensions/behaviours/engine.ts +131 -0
- package/src/extensions/behaviours/eval-engine.test.ts +165 -0
- package/src/extensions/behaviours/eval-engine.ts +104 -0
- package/src/extensions/behaviours/frontmatter.ts +22 -0
- package/src/extensions/behaviours/index.ts +35 -0
- package/src/extensions/behaviours/matchers.test.ts +153 -0
- package/src/extensions/behaviours/matchers.ts +69 -0
- package/src/extensions/behaviours/registry.ts +73 -0
- package/src/extensions/behaviours/session-context.test.ts +192 -0
- package/src/extensions/behaviours/session-context.ts +170 -0
- package/src/extensions/behaviours/stats.ts +47 -0
- package/src/extensions/behaviours/tool-args.smoke.test.ts +34 -0
- package/src/extensions/behaviours/tool-args.ts +65 -0
- package/src/extensions/behaviours/triggers.ts +164 -0
- package/src/extensions/behaviours/types.ts +49 -0
- package/src/extensions/behaviours/wiring.smoke.test.ts +488 -0
- package/src/extensions/behaviours/wiring.ts +196 -0
- package/src/extensions/branch-command.test.ts +208 -0
- package/src/extensions/branch-command.ts +89 -0
- package/src/extensions/claude-code-hook-adapter/definition.test.ts +51 -0
- package/src/extensions/claude-code-hook-adapter/definition.ts +36 -0
- package/src/extensions/claude-code-hook-adapter/index.ts +6 -0
- package/src/extensions/claude-code-skills/definition.test.ts +228 -0
- package/src/extensions/claude-code-skills/definition.ts +475 -0
- package/src/extensions/claude-code-skills/index.test.ts +227 -0
- package/src/extensions/claude-code-skills/index.ts +101 -0
- package/src/extensions/clipboard-image.test.ts +383 -0
- package/src/extensions/clipboard-image.ts +266 -0
- package/src/extensions/compaction-thresholds.test.ts +8 -0
- package/src/extensions/compaction-thresholds.ts +13 -0
- package/src/extensions/curator/index.test.ts +33 -0
- package/src/extensions/curator/index.ts +296 -0
- package/src/extensions/curator/review.test.ts +82 -0
- package/src/extensions/curator/review.ts +438 -0
- package/src/extensions/curator/state.test.ts +79 -0
- package/src/extensions/curator/state.ts +61 -0
- package/src/extensions/curator/transitions.test.ts +96 -0
- package/src/extensions/curator/transitions.ts +56 -0
- package/src/extensions/customize-footer-command.test.ts +258 -0
- package/src/extensions/customize-footer-command.ts +158 -0
- package/src/extensions/deferred-action.ts +38 -0
- package/src/extensions/disabled/tool-result-pruning.test.ts +397 -0
- package/src/extensions/disabled/tool-result-pruning.ts +181 -0
- package/src/extensions/exit-utils.ts +8 -0
- package/src/extensions/exploration-guard.test.ts +646 -0
- package/src/extensions/exploration-guard.ts +293 -0
- package/src/extensions/ferment/action-tool-names.ts +25 -0
- package/src/extensions/ferment/agent-spawn-guard.test.ts +339 -0
- package/src/extensions/ferment/agent-spawn-guard.ts +188 -0
- package/src/extensions/ferment/ask-user.test.ts +838 -0
- package/src/extensions/ferment/ask-user.ts +569 -0
- package/src/extensions/ferment/auto-compaction.test.ts +933 -0
- package/src/extensions/ferment/auto-compaction.ts +525 -0
- package/src/extensions/ferment/breadcrumb-renderer.ts +46 -0
- package/src/extensions/ferment/colors.ts +95 -0
- package/src/extensions/ferment/command-parser.test.ts +82 -0
- package/src/extensions/ferment/command-parser.ts +52 -0
- package/src/extensions/ferment/commands.test.ts +1659 -0
- package/src/extensions/ferment/commands.ts +1025 -0
- package/src/extensions/ferment/constants.ts +37 -0
- package/src/extensions/ferment/contextual-options.test.ts +70 -0
- package/src/extensions/ferment/contextual-options.ts +107 -0
- package/src/extensions/ferment/continuation.test.ts +141 -0
- package/src/extensions/ferment/continuation.ts +59 -0
- package/src/extensions/ferment/derive-state.test.ts +222 -0
- package/src/extensions/ferment/derive-state.ts +158 -0
- package/src/extensions/ferment/domain-events-emitter.ts +255 -0
- package/src/extensions/ferment/domain-events.ts +146 -0
- package/src/extensions/ferment/events.test.ts +616 -0
- package/src/extensions/ferment/events.ts +561 -0
- package/src/extensions/ferment/footer-status.test.ts +62 -0
- package/src/extensions/ferment/footer-status.ts +61 -0
- package/src/extensions/ferment/format.test.ts +55 -0
- package/src/extensions/ferment/format.ts +111 -0
- package/src/extensions/ferment/fsm-adapter.test.ts +43 -0
- package/src/extensions/ferment/fsm-adapter.ts +112 -0
- package/src/extensions/ferment/gate-registry.test.ts +176 -0
- package/src/extensions/ferment/gate-registry.ts +352 -0
- package/src/extensions/ferment/gate-validation.test.ts +319 -0
- package/src/extensions/ferment/gate-validation.ts +160 -0
- package/src/extensions/ferment/git-init.test.ts +146 -0
- package/src/extensions/ferment/git-init.ts +66 -0
- package/src/extensions/ferment/index.test.ts +1439 -0
- package/src/extensions/ferment/index.ts +337 -0
- package/src/extensions/ferment/judge.test.ts +172 -0
- package/src/extensions/ferment/judge.ts +342 -0
- package/src/extensions/ferment/nudge.test.ts +700 -0
- package/src/extensions/ferment/nudge.ts +332 -0
- package/src/extensions/ferment/oneshot.test.ts +115 -0
- package/src/extensions/ferment/oneshot.ts +52 -0
- package/src/extensions/ferment/pending-proposal-store.test.ts +272 -0
- package/src/extensions/ferment/pending-proposal-store.ts +142 -0
- package/src/extensions/ferment/phase-editor.test.ts +174 -0
- package/src/extensions/ferment/phase-editor.ts +148 -0
- package/src/extensions/ferment/phase-evidence.test.ts +154 -0
- package/src/extensions/ferment/phase-evidence.ts +179 -0
- package/src/extensions/ferment/plan-review-trigger.ts +34 -0
- package/src/extensions/ferment/plan-review.test.ts +182 -0
- package/src/extensions/ferment/plan-review.ts +205 -0
- package/src/extensions/ferment/progress-overlay.test.ts +197 -0
- package/src/extensions/ferment/progress-overlay.ts +326 -0
- package/src/extensions/ferment/project-tests.test.ts +160 -0
- package/src/extensions/ferment/project-tests.ts +246 -0
- package/src/extensions/ferment/prompt-block.test.ts +501 -0
- package/src/extensions/ferment/prompt-block.ts +203 -0
- package/src/extensions/ferment/prompt-ui.test.ts +311 -0
- package/src/extensions/ferment/prompt-ui.ts +302 -0
- package/src/extensions/ferment/resume.test.ts +218 -0
- package/src/extensions/ferment/resume.ts +180 -0
- package/src/extensions/ferment/review-evidence.ts +269 -0
- package/src/extensions/ferment/runtime-state-store.test.ts +148 -0
- package/src/extensions/ferment/runtime-state-store.ts +132 -0
- package/src/extensions/ferment/runtime.test.ts +38 -0
- package/src/extensions/ferment/runtime.ts +208 -0
- package/src/extensions/ferment/scheduler.ts +226 -0
- package/src/extensions/ferment/scoping-benchmark.test.ts +137 -0
- package/src/extensions/ferment/scoping-confirmation.test.ts +209 -0
- package/src/extensions/ferment/scoping-confirmation.ts +87 -0
- package/src/extensions/ferment/scoping-flow.integration.test.ts +203 -0
- package/src/extensions/ferment/scoping.test.ts +235 -0
- package/src/extensions/ferment/scoping.ts +208 -0
- package/src/extensions/ferment/state.test.ts +300 -0
- package/src/extensions/ferment/state.ts +696 -0
- package/src/extensions/ferment/tips.test.ts +171 -0
- package/src/extensions/ferment/tips.ts +61 -0
- package/src/extensions/ferment/todo-headless-wiring.test.ts +641 -0
- package/src/extensions/ferment/todo-sync.test.ts +805 -0
- package/src/extensions/ferment/todo-sync.ts +520 -0
- package/src/extensions/ferment/tool-helpers.test.ts +121 -0
- package/src/extensions/ferment/tool-helpers.ts +217 -0
- package/src/extensions/ferment/tool-names.test.ts +55 -0
- package/src/extensions/ferment/tool-names.ts +78 -0
- package/src/extensions/ferment/tool-schemas.test.ts +587 -0
- package/src/extensions/ferment/tool-schemas.ts +428 -0
- package/src/extensions/ferment/tool-scope.test.ts +373 -0
- package/src/extensions/ferment/tool-scope.ts +176 -0
- package/src/extensions/ferment/tools/knowledge.ts +60 -0
- package/src/extensions/ferment/tools/lifecycle.test.ts +1196 -0
- package/src/extensions/ferment/tools/lifecycle.ts +1296 -0
- package/src/extensions/ferment/tools/phases.test.ts +379 -0
- package/src/extensions/ferment/tools/phases.ts +757 -0
- package/src/extensions/ferment/tools/steps.test.ts +998 -0
- package/src/extensions/ferment/tools/steps.ts +765 -0
- package/src/extensions/ferment/tools.integration.test.ts +1975 -0
- package/src/extensions/ferment/ui.ts +10 -0
- package/src/extensions/ferment/worker-prompt.test.ts +285 -0
- package/src/extensions/ferment/worker-prompt.ts +85 -0
- package/src/extensions/ferment/worktree.ts +44 -0
- package/src/extensions/format.ts +12 -0
- package/src/extensions/help.ts +172 -0
- package/src/extensions/hide-thinking.test.ts +407 -0
- package/src/extensions/hide-thinking.ts +375 -0
- package/src/extensions/hook-adapters/adapter.integration.test.ts +134 -0
- package/src/extensions/hook-adapters/adapter.test.ts +1062 -0
- package/src/extensions/hook-adapters/adapter.ts +784 -0
- package/src/extensions/hook-adapters/discovery.test.ts +105 -0
- package/src/extensions/hook-adapters/discovery.ts +213 -0
- package/src/extensions/ide-adapter/ARCHITECTURE.md +77 -0
- package/src/extensions/ide-adapter/CONTRACT.md +129 -0
- package/src/extensions/ide-adapter/README.md +24 -0
- package/src/extensions/ide-adapter/at-mentions.test.ts +40 -0
- package/src/extensions/ide-adapter/at-mentions.ts +44 -0
- package/src/extensions/ide-adapter/index.test.ts +434 -0
- package/src/extensions/ide-adapter/index.ts +250 -0
- package/src/extensions/ide-adapter/lockfile.test.ts +137 -0
- package/src/extensions/ide-adapter/lockfile.ts +82 -0
- package/src/extensions/ide-adapter/mcp-client.test.ts +285 -0
- package/src/extensions/ide-adapter/mcp-client.ts +208 -0
- package/src/extensions/ide-adapter/types.ts +47 -0
- package/src/extensions/ikie-minimal-tints.ts +124 -0
- package/src/extensions/ikie-process.ts +49 -0
- package/src/extensions/improve/SKILL.md +51 -0
- package/src/extensions/improve/index.ts +72 -0
- package/src/extensions/input-history.test.ts +475 -0
- package/src/extensions/input-history.ts +111 -0
- package/src/extensions/llm-response-log.test.ts +200 -0
- package/src/extensions/llm-response-log.ts +87 -0
- package/src/extensions/login/flow.test.ts +47 -0
- package/src/extensions/login/flow.ts +638 -0
- package/src/extensions/login/index.ts +57 -0
- package/src/extensions/login/startup-auth.test.ts +510 -0
- package/src/extensions/login/startup-auth.ts +205 -0
- package/src/extensions/loop-guard.test.ts +993 -0
- package/src/extensions/loop-guard.ts +710 -0
- package/src/extensions/lsp/client.ts +501 -0
- package/src/extensions/lsp/edits.test.ts +69 -0
- package/src/extensions/lsp/edits.ts +78 -0
- package/src/extensions/lsp/lsp-entry.test.ts +24 -0
- package/src/extensions/lsp/servers.ts +76 -0
- package/src/extensions/lsp/types.ts +166 -0
- package/src/extensions/lsp/utils.test.ts +81 -0
- package/src/extensions/lsp/utils.ts +80 -0
- package/src/extensions/lsp.test.ts +1049 -0
- package/src/extensions/lsp.ts +470 -0
- package/src/extensions/mcp-adapter/CHANGELOG.md +264 -0
- package/src/extensions/mcp-adapter/LICENSE +21 -0
- package/src/extensions/mcp-adapter/README.md +316 -0
- package/src/extensions/mcp-adapter/app-bridge.bundle.js +10430 -0
- package/src/extensions/mcp-adapter/bm25.ts +187 -0
- package/src/extensions/mcp-adapter/cache-resolver.integration.test.ts +282 -0
- package/src/extensions/mcp-adapter/commands.ts +235 -0
- package/src/extensions/mcp-adapter/config.test.ts +189 -0
- package/src/extensions/mcp-adapter/config.ts +233 -0
- package/src/extensions/mcp-adapter/consent-manager.ts +64 -0
- package/src/extensions/mcp-adapter/context-providers.test.ts +123 -0
- package/src/extensions/mcp-adapter/context-providers.ts +55 -0
- package/src/extensions/mcp-adapter/direct-tool-visibility.test.ts +61 -0
- package/src/extensions/mcp-adapter/direct-tool-visibility.ts +47 -0
- package/src/extensions/mcp-adapter/direct-tools.ts +413 -0
- package/src/extensions/mcp-adapter/errors.ts +198 -0
- package/src/extensions/mcp-adapter/glimpse-ui.ts +78 -0
- package/src/extensions/mcp-adapter/host-html-template.ts +423 -0
- package/src/extensions/mcp-adapter/index.test.ts +323 -0
- package/src/extensions/mcp-adapter/index.ts +604 -0
- package/src/extensions/mcp-adapter/init.ts +402 -0
- package/src/extensions/mcp-adapter/lifecycle.ts +93 -0
- package/src/extensions/mcp-adapter/logger.ts +169 -0
- package/src/extensions/mcp-adapter/mcp-auth-flow.ts +394 -0
- package/src/extensions/mcp-adapter/mcp-auth.ts +267 -0
- package/src/extensions/mcp-adapter/mcp-callback-server.ts +284 -0
- package/src/extensions/mcp-adapter/mcp-oauth-provider.ts +288 -0
- package/src/extensions/mcp-adapter/mcp-panel.test.ts +321 -0
- package/src/extensions/mcp-adapter/mcp-panel.ts +835 -0
- package/src/extensions/mcp-adapter/metadata-cache.test.ts +83 -0
- package/src/extensions/mcp-adapter/metadata-cache.ts +332 -0
- package/src/extensions/mcp-adapter/npx-resolver.ts +429 -0
- package/src/extensions/mcp-adapter/oauth-handler.ts +57 -0
- package/src/extensions/mcp-adapter/proxy-modes.test.ts +147 -0
- package/src/extensions/mcp-adapter/proxy-modes.ts +1035 -0
- package/src/extensions/mcp-adapter/resource-tools.ts +17 -0
- package/src/extensions/mcp-adapter/server-manager.ts +355 -0
- package/src/extensions/mcp-adapter/state.ts +45 -0
- package/src/extensions/mcp-adapter/tool-metadata.test.ts +115 -0
- package/src/extensions/mcp-adapter/tool-metadata.ts +185 -0
- package/src/extensions/mcp-adapter/tool-registrar.ts +46 -0
- package/src/extensions/mcp-adapter/types.ts +423 -0
- package/src/extensions/mcp-adapter/ui-resource-handler.ts +143 -0
- package/src/extensions/mcp-adapter/ui-server.ts +619 -0
- package/src/extensions/mcp-adapter/ui-session.ts +378 -0
- package/src/extensions/mcp-adapter/ui-stream-types.ts +93 -0
- package/src/extensions/mcp-adapter/utils.ts +76 -0
- package/src/extensions/model-catalog/builtin-models.ts +180 -0
- package/src/extensions/model-catalog/guidelines/claude-family.ts +49 -0
- package/src/extensions/model-catalog/guidelines/default-orchestration-guidelines.ts +11 -0
- package/src/extensions/model-catalog/guidelines/default-phase-guidelines.ts +59 -0
- package/src/extensions/model-catalog/guidelines/guidelines-resolver.test.ts +191 -0
- package/src/extensions/model-catalog/guidelines/guidelines-resolver.ts +39 -0
- package/src/extensions/model-catalog/guidelines/kimi-family.ts +82 -0
- package/src/extensions/model-catalog/guidelines/minimax-family.ts +62 -0
- package/src/extensions/model-catalog/guidelines/nemotron-family.ts +53 -0
- package/src/extensions/model-catalog/index.ts +10 -0
- package/src/extensions/model-catalog/model-metadata.test.ts +688 -0
- package/src/extensions/model-catalog/model-metadata.ts +250 -0
- package/src/extensions/model-catalog/model-registry.test.ts +228 -0
- package/src/extensions/model-catalog/model-registry.ts +116 -0
- package/src/extensions/model-catalog/ref-utils.ts +22 -0
- package/src/extensions/model-catalog/types.ts +41 -0
- package/src/extensions/model-guard.test.ts +756 -0
- package/src/extensions/model-guard.ts +402 -0
- package/src/extensions/model-switch.test.ts +1105 -0
- package/src/extensions/model-switch.ts +261 -0
- package/src/extensions/onboarding/picker-editor.ts +22 -0
- package/src/extensions/onboarding/session-mode-picker.test.ts +135 -0
- package/src/extensions/onboarding/session-mode-picker.ts +136 -0
- package/src/extensions/onboarding/session-mode-startup.test.ts +237 -0
- package/src/extensions/onboarding/session-mode-startup.ts +36 -0
- package/src/extensions/onboarding/session-mode.test.ts +501 -0
- package/src/extensions/onboarding/session-mode.ts +363 -0
- package/src/extensions/orchestration/continuation-nudge.test.ts +595 -0
- package/src/extensions/orchestration/continuation-nudge.ts +270 -0
- package/src/extensions/orchestration/model-metadata.test.ts +671 -0
- package/src/extensions/orchestration/model-metadata.ts +246 -0
- package/src/extensions/orchestration/model-ref-utils.ts +5 -0
- package/src/extensions/orchestration/model-registry/builtin-models.ts +223 -0
- package/src/extensions/orchestration/model-registry/guidelines/claude-family.ts +49 -0
- package/src/extensions/orchestration/model-registry/guidelines/default-orchestration-guidelines.ts +11 -0
- package/src/extensions/orchestration/model-registry/guidelines/default-phase-guidelines.ts +67 -0
- package/src/extensions/orchestration/model-registry/guidelines/guidelines-resolver.test.ts +273 -0
- package/src/extensions/orchestration/model-registry/guidelines/guidelines-resolver.ts +39 -0
- package/src/extensions/orchestration/model-registry/guidelines/kimi-family.ts +89 -0
- package/src/extensions/orchestration/model-registry/guidelines/minimax-family.ts +68 -0
- package/src/extensions/orchestration/model-registry/guidelines/nemotron-family.ts +60 -0
- package/src/extensions/orchestration/model-registry/index.ts +4 -0
- package/src/extensions/orchestration/model-registry/model-registry.test.ts +228 -0
- package/src/extensions/orchestration/model-registry/model-registry.ts +116 -0
- package/src/extensions/orchestration/model-registry/types.ts +41 -0
- package/src/extensions/orchestration/model-roles-command.test.ts +367 -0
- package/src/extensions/orchestration/model-roles-command.ts +531 -0
- package/src/extensions/orchestration/model-roles.test.ts +448 -0
- package/src/extensions/orchestration/model-roles.ts +302 -0
- package/src/extensions/orchestration/orchestration-instructions.test.ts +459 -0
- package/src/extensions/orchestration/orchestration-instructions.ts +614 -0
- package/src/extensions/orphan-tool-result-sanitizer.test.ts +198 -0
- package/src/extensions/orphan-tool-result-sanitizer.ts +128 -0
- package/src/extensions/permissions/classifier-model.test.ts +127 -0
- package/src/extensions/permissions/classifier-model.ts +65 -0
- package/src/extensions/permissions/classifier.test.ts +334 -0
- package/src/extensions/permissions/classifier.ts +228 -0
- package/src/extensions/permissions/commands.ts +244 -0
- package/src/extensions/permissions/config.test.ts +101 -0
- package/src/extensions/permissions/config.ts +143 -0
- package/src/extensions/permissions/constants.ts +1 -0
- package/src/extensions/permissions/index.test.ts +1822 -0
- package/src/extensions/permissions/index.ts +1193 -0
- package/src/extensions/permissions/keybindings.test.ts +130 -0
- package/src/extensions/permissions/keybindings.ts +91 -0
- package/src/extensions/permissions/mode-controller-registry.ts +50 -0
- package/src/extensions/permissions/mode-controller.ts +91 -0
- package/src/extensions/permissions/mode.test.ts +51 -0
- package/src/extensions/permissions/mode.ts +29 -0
- package/src/extensions/permissions/plan-persistence.test.ts +56 -0
- package/src/extensions/permissions/plan-persistence.ts +12 -0
- package/src/extensions/permissions/plan-persona.test.ts +42 -0
- package/src/extensions/permissions/prompter.ts +21 -0
- package/src/extensions/permissions/prompts/classifier-system-prompt.ts +33 -0
- package/src/extensions/permissions/prompts/plan-mode-supplement.test.ts +59 -0
- package/src/extensions/permissions/prompts/plan-mode-supplement.ts +38 -0
- package/src/extensions/permissions/prompts.test.ts +67 -0
- package/src/extensions/permissions/prompts.ts +212 -0
- package/src/extensions/permissions/rules.test.ts +327 -0
- package/src/extensions/permissions/rules.ts +210 -0
- package/src/extensions/permissions/select-utils.ts +2 -0
- package/src/extensions/permissions/session-memory.test.ts +75 -0
- package/src/extensions/permissions/session-memory.ts +94 -0
- package/src/extensions/permissions/taxonomy.test.ts +684 -0
- package/src/extensions/permissions/taxonomy.ts +616 -0
- package/src/extensions/permissions/types.ts +70 -0
- package/src/extensions/pi-compat.test.ts +201 -0
- package/src/extensions/pi-package-lookup/index.test.ts +177 -0
- package/src/extensions/pi-package-lookup/index.ts +263 -0
- package/src/extensions/pi-package-lookup/native-compat.test.ts +230 -0
- package/src/extensions/pi-package-lookup/native-compat.ts +279 -0
- package/src/extensions/plugin-package-hook-adapter/definition.test.ts +220 -0
- package/src/extensions/plugin-package-hook-adapter/definition.ts +60 -0
- package/src/extensions/plugin-package-hook-adapter/index.ts +4 -0
- package/src/extensions/prompt-construction/context-files.test.ts +167 -0
- package/src/extensions/prompt-construction/context-files.ts +111 -0
- package/src/extensions/prompt-construction/index.ts +8 -0
- package/src/extensions/prompt-construction/prompt-enrichment.test.ts +1103 -0
- package/src/extensions/prompt-construction/prompt-enrichment.ts +588 -0
- package/src/extensions/prompt-construction/system-prompt-blocks.test.ts +323 -0
- package/src/extensions/prompt-construction/system-prompt-blocks.ts +122 -0
- package/src/extensions/prompt-construction/system-prompt.test.ts +528 -0
- package/src/extensions/prompt-construction/system-prompt.ts +316 -0
- package/src/extensions/prompt-construction/tool-visibility.test.ts +170 -0
- package/src/extensions/prompt-construction/tool-visibility.ts +121 -0
- package/src/extensions/prompt-summary.test.ts +56 -0
- package/src/extensions/prompt-summary.ts +258 -0
- package/src/extensions/questionnaire/constants.ts +6 -0
- package/src/extensions/questionnaire/index.ts +8 -0
- package/src/extensions/questionnaire/questionnaire-fallback.test.ts +948 -0
- package/src/extensions/questionnaire/questionnaire-fallback.ts +230 -0
- package/src/extensions/questionnaire/questionnaire-form.ts +314 -0
- package/src/extensions/questionnaire/questionnaire-reducer.test.ts +508 -0
- package/src/extensions/questionnaire/questionnaire-reducer.ts +510 -0
- package/src/extensions/questionnaire/questionnaire.test.ts +425 -0
- package/src/extensions/questionnaire/questionnaire.ts +280 -0
- package/src/extensions/report-bug.test.ts +301 -0
- package/src/extensions/report-bug.ts +93 -0
- package/src/extensions/review-write-guard.integration.test.ts +167 -0
- package/src/extensions/review-write-guard.test.ts +150 -0
- package/src/extensions/review-write-guard.ts +143 -0
- package/src/extensions/rtk-rewrite.test.ts +325 -0
- package/src/extensions/rtk-rewrite.ts +201 -0
- package/src/extensions/session-metadata/index.test.ts +158 -0
- package/src/extensions/session-metadata/index.ts +66 -0
- package/src/extensions/session-name.test.ts +248 -0
- package/src/extensions/session-name.ts +192 -0
- package/src/extensions/session-repair/orphan-tool-result-repair.test.ts +227 -0
- package/src/extensions/session-repair/orphan-tool-result-repair.ts +183 -0
- package/src/extensions/shared-footer.ts +24 -0
- package/src/extensions/shared-input.test.ts +27 -0
- package/src/extensions/shared-input.ts +24 -0
- package/src/extensions/shutdown-marker.test.ts +195 -0
- package/src/extensions/shutdown-marker.ts +61 -0
- package/src/extensions/skills-manager/index.test.ts +17 -0
- package/src/extensions/skills-manager/index.ts +18 -0
- package/src/extensions/skills-manager/skill-manager.test.ts +350 -0
- package/src/extensions/skills-manager/skill-manager.ts +508 -0
- package/src/extensions/skills-manager/tool.test.ts +234 -0
- package/src/extensions/skills-manager/tool.ts +241 -0
- package/src/extensions/skills-manager/usage.test.ts +119 -0
- package/src/extensions/skills-manager/usage.ts +249 -0
- package/src/extensions/slash-commands.ts +22 -0
- package/src/extensions/spinner.ts +117 -0
- package/src/extensions/stale-ctx.ts +15 -0
- package/src/extensions/startup-update.test.ts +130 -0
- package/src/extensions/startup-update.ts +33 -0
- package/src/extensions/stats/api.ts +168 -0
- package/src/extensions/stats/display.ts +210 -0
- package/src/extensions/stats/index.ts +130 -0
- package/src/extensions/stats/stats.test.ts +547 -0
- package/src/extensions/stats/types.ts +263 -0
- package/src/extensions/stats/visual.ts +439 -0
- package/src/extensions/strip-images.test.ts +118 -0
- package/src/extensions/strip-images.ts +162 -0
- package/src/extensions/superpowers/config.ts +10 -0
- package/src/extensions/superpowers.test.ts +17 -0
- package/src/extensions/superpowers.ts +5 -0
- package/src/extensions/surveys/index.test.ts +200 -0
- package/src/extensions/surveys/index.ts +107 -0
- package/src/extensions/surveys/survey.test.ts +157 -0
- package/src/extensions/surveys/survey.ts +204 -0
- package/src/extensions/tags.test.ts +275 -0
- package/src/extensions/tags.ts +662 -0
- package/src/extensions/telemetry/README.md +113 -0
- package/src/extensions/telemetry/accumulator.test.ts +260 -0
- package/src/extensions/telemetry/accumulator.ts +146 -0
- package/src/extensions/telemetry/config-snapshot.test.ts +259 -0
- package/src/extensions/telemetry/config-snapshot.ts +177 -0
- package/src/extensions/telemetry/handlers/messages.test.ts +422 -0
- package/src/extensions/telemetry/handlers/messages.ts +113 -0
- package/src/extensions/telemetry/handlers/session.test.ts +198 -0
- package/src/extensions/telemetry/handlers/session.ts +24 -0
- package/src/extensions/telemetry/handlers/tools.test.ts +416 -0
- package/src/extensions/telemetry/handlers/tools.ts +171 -0
- package/src/extensions/telemetry/handlers/transport-errors.test.ts +178 -0
- package/src/extensions/telemetry/handlers/transport-errors.ts +42 -0
- package/src/extensions/telemetry/helpers.test.ts +266 -0
- package/src/extensions/telemetry/helpers.ts +146 -0
- package/src/extensions/telemetry/index.test.ts +1170 -0
- package/src/extensions/telemetry/index.ts +609 -0
- package/src/extensions/telemetry/pre-session.test.ts +390 -0
- package/src/extensions/telemetry/pre-session.ts +135 -0
- package/src/extensions/telemetry/session-context.test.ts +487 -0
- package/src/extensions/telemetry/session-context.ts +281 -0
- package/src/extensions/telemetry/session-type.ts +5 -0
- package/src/extensions/telemetry/settings-change-emitter.test.ts +197 -0
- package/src/extensions/telemetry/settings-change-emitter.ts +127 -0
- package/src/extensions/telemetry/survey.test.ts +140 -0
- package/src/extensions/telemetry/survey.ts +70 -0
- package/src/extensions/telemetry/transport.test.ts +301 -0
- package/src/extensions/telemetry/transport.ts +217 -0
- package/src/extensions/teleport/commands/args.test.ts +166 -0
- package/src/extensions/teleport/commands/args.ts +226 -0
- package/src/extensions/teleport/commands/attach.test.ts +209 -0
- package/src/extensions/teleport/commands/attach.ts +91 -0
- package/src/extensions/teleport/commands/errors.ts +26 -0
- package/src/extensions/teleport/commands/remote-sessions.test.ts +350 -0
- package/src/extensions/teleport/commands/remote-sessions.ts +193 -0
- package/src/extensions/teleport/commands/ssh-config.ts +25 -0
- package/src/extensions/teleport/commands/sync.test.ts +104 -0
- package/src/extensions/teleport/commands/sync.ts +205 -0
- package/src/extensions/teleport/commands/teleport.test.ts +593 -0
- package/src/extensions/teleport/commands/teleport.ts +359 -0
- package/src/extensions/teleport/commands/terminal.test.ts +228 -0
- package/src/extensions/teleport/commands/terminal.ts +97 -0
- package/src/extensions/teleport/commands/workspace-ref.test.ts +269 -0
- package/src/extensions/teleport/commands/workspace-ref.ts +105 -0
- package/src/extensions/teleport/index.test.ts +72 -0
- package/src/extensions/teleport/index.ts +66 -0
- package/src/extensions/teleport/overlay/keybindings.test.ts +101 -0
- package/src/extensions/teleport/overlay/keybindings.ts +65 -0
- package/src/extensions/teleport/overlay/overlay-component.test.ts +102 -0
- package/src/extensions/teleport/overlay/overlay-component.ts +284 -0
- package/src/extensions/teleport/overlay/reconnect-banner.test.ts +63 -0
- package/src/extensions/teleport/overlay/reconnect-banner.ts +69 -0
- package/src/extensions/teleport/overlay/tab-bar.test.ts +72 -0
- package/src/extensions/teleport/overlay/tab-bar.ts +146 -0
- package/src/extensions/teleport/overlay/tab-manager.test.ts +484 -0
- package/src/extensions/teleport/overlay/tab-manager.ts +293 -0
- package/src/extensions/teleport/preflight/git.test.ts +94 -0
- package/src/extensions/teleport/preflight/git.ts +40 -0
- package/src/extensions/teleport/preflight/index.test.ts +97 -0
- package/src/extensions/teleport/preflight/index.ts +43 -0
- package/src/extensions/teleport/preflight/rsync.test.ts +39 -0
- package/src/extensions/teleport/preflight/rsync.ts +23 -0
- package/src/extensions/teleport/preflight/workspace-size.ts +2 -0
- package/src/extensions/teleport/provisioning/concurrency.ts +40 -0
- package/src/extensions/teleport/provisioning/constants.ts +3 -0
- package/src/extensions/teleport/provisioning/estimate-bytes.test.ts +107 -0
- package/src/extensions/teleport/provisioning/estimate-bytes.ts +123 -0
- package/src/extensions/teleport/provisioning/git-provision.test.ts +76 -0
- package/src/extensions/teleport/provisioning/git-provision.ts +54 -0
- package/src/extensions/teleport/provisioning/include-list.test.ts +222 -0
- package/src/extensions/teleport/provisioning/include-list.ts +203 -0
- package/src/extensions/teleport/provisioning/paths.ts +54 -0
- package/src/extensions/teleport/provisioning/proxy-command.ts +30 -0
- package/src/extensions/teleport/provisioning/rsync-runner.test.ts +544 -0
- package/src/extensions/teleport/provisioning/rsync-runner.ts +675 -0
- package/src/extensions/teleport/pty/mouse-capture.ts +7 -0
- package/src/extensions/teleport/pty/reconnect-supervisor.ts +117 -0
- package/src/extensions/teleport/pty/terminal-component.test.ts +282 -0
- package/src/extensions/teleport/pty/terminal-component.ts +331 -0
- package/src/extensions/teleport/pty/websocket-transport.test.ts +440 -0
- package/src/extensions/teleport/pty/websocket-transport.ts +228 -0
- package/src/extensions/teleport/pty/xterm-core.test.ts +79 -0
- package/src/extensions/teleport/pty/xterm-core.ts +159 -0
- package/src/extensions/teleport/session-filter.ts +10 -0
- package/src/extensions/teleport/ssh-config/paths.ts +27 -0
- package/src/extensions/teleport/ssh-config/render.test.ts +111 -0
- package/src/extensions/teleport/ssh-config/render.ts +97 -0
- package/src/extensions/teleport/ssh-config/sync.test.ts +170 -0
- package/src/extensions/teleport/ssh-config/sync.ts +92 -0
- package/src/extensions/teleport/types.ts +14 -0
- package/src/extensions/teleport/ui/format-bytes.ts +13 -0
- package/src/extensions/teleport/ui/git-token-prompt.ts +164 -0
- package/src/extensions/teleport/ui/help-modal.ts +100 -0
- package/src/extensions/teleport/ui/progress.test.ts +236 -0
- package/src/extensions/teleport/ui/progress.ts +345 -0
- package/src/extensions/teleport/ui/remote-sessions-panel.test.ts +221 -0
- package/src/extensions/teleport/ui/remote-sessions-panel.ts +309 -0
- package/src/extensions/teleport/ui/sessions-table.ts +24 -0
- package/src/extensions/teleport/ui/sync-progress-row.ts +30 -0
- package/src/extensions/teleport/ui/tty-handoff.ts +131 -0
- package/src/extensions/teleport/ui/workspaces-panel.test.ts +307 -0
- package/src/extensions/teleport/ui/workspaces-panel.ts +364 -0
- package/src/extensions/teleport/ui/workspaces-table.ts +12 -0
- package/src/extensions/terminal-colors.ts +256 -0
- package/src/extensions/terminal-compat/keyboard-capability.test.ts +69 -0
- package/src/extensions/terminal-compat/keyboard-capability.ts +103 -0
- package/src/extensions/terminal-compat/startup-warning.test.ts +273 -0
- package/src/extensions/terminal-compat/startup-warning.ts +77 -0
- package/src/extensions/theme-selector.test.ts +297 -0
- package/src/extensions/theme-selector.ts +156 -0
- package/src/extensions/thinking-steps/index.ts +429 -0
- package/src/extensions/thinking-steps/internal-patch.ts +483 -0
- package/src/extensions/thinking-steps/parse.ts +1376 -0
- package/src/extensions/thinking-steps/persistence.ts +95 -0
- package/src/extensions/thinking-steps/render.ts +496 -0
- package/src/extensions/thinking-steps/state.ts +482 -0
- package/src/extensions/thinking-steps/types.ts +55 -0
- package/src/extensions/tips/general-tips.test.ts +33 -0
- package/src/extensions/tips/general-tips.ts +81 -0
- package/src/extensions/tips/index.test.ts +198 -0
- package/src/extensions/tips/index.ts +231 -0
- package/src/extensions/tips/presenter.test.ts +160 -0
- package/src/extensions/tips/presenter.ts +170 -0
- package/src/extensions/tips/registry.test.ts +59 -0
- package/src/extensions/tips/registry.ts +66 -0
- package/src/extensions/tips/tip-row.test.ts +97 -0
- package/src/extensions/tips/tip-row.ts +48 -0
- package/src/extensions/tips/tips-panel.test.ts +222 -0
- package/src/extensions/tips/tips-panel.ts +310 -0
- package/src/extensions/tips/types.ts +21 -0
- package/src/extensions/todos/command.test.ts +103 -0
- package/src/extensions/todos/command.ts +266 -0
- package/src/extensions/todos/constants.ts +1 -0
- package/src/extensions/todos/index.test.ts +405 -0
- package/src/extensions/todos/index.ts +238 -0
- package/src/extensions/todos/prompt-block.test.ts +219 -0
- package/src/extensions/todos/prompt-block.ts +176 -0
- package/src/extensions/todos/reducer.test.ts +141 -0
- package/src/extensions/todos/reducer.ts +155 -0
- package/src/extensions/todos/scope.test.ts +42 -0
- package/src/extensions/todos/scope.ts +109 -0
- package/src/extensions/todos/store.test.ts +78 -0
- package/src/extensions/todos/store.ts +92 -0
- package/src/extensions/todos/tool.test.ts +84 -0
- package/src/extensions/todos/tool.ts +240 -0
- package/src/extensions/todos/types.ts +79 -0
- package/src/extensions/todos/widget.test.ts +348 -0
- package/src/extensions/todos/widget.ts +332 -0
- package/src/extensions/tool-grouping.test.ts +387 -0
- package/src/extensions/tool-grouping.ts +346 -0
- package/src/extensions/tool-rendering.test.ts +401 -0
- package/src/extensions/tool-rendering.ts +4511 -0
- package/src/extensions/trace-id.test.ts +230 -0
- package/src/extensions/trace-id.ts +46 -0
- package/src/extensions/ui-branch-poll.test.ts +164 -0
- package/src/extensions/ui-branch-poll.ts +57 -0
- package/src/extensions/ui.test.ts +185 -0
- package/src/extensions/ui.ts +649 -0
- package/src/extensions/web-fetch/browser-pool.test.ts +237 -0
- package/src/extensions/web-fetch/browser-pool.ts +145 -0
- package/src/extensions/web-fetch/cache.test.ts +196 -0
- package/src/extensions/web-fetch/cache.ts +114 -0
- package/src/extensions/web-fetch/content-converter.test.ts +341 -0
- package/src/extensions/web-fetch/content-converter.ts +188 -0
- package/src/extensions/web-fetch/execute-handler.test.ts +384 -0
- package/src/extensions/web-fetch/execute-handler.ts +131 -0
- package/src/extensions/web-fetch/index.ts +113 -0
- package/src/extensions/web-fetch/integration.test.ts +618 -0
- package/src/extensions/web-fetch/page-fetcher.test.ts +532 -0
- package/src/extensions/web-fetch/page-fetcher.ts +358 -0
- package/src/extensions/web-fetch/url-validator.test.ts +230 -0
- package/src/extensions/web-fetch/url-validator.ts +153 -0
- package/src/extensions/web-search/execute-handler.test.ts +216 -0
- package/src/extensions/web-search/execute-handler.ts +151 -0
- package/src/extensions/web-search/index.ts +107 -0
- package/src/ferment/engine.test.ts +279 -0
- package/src/ferment/engine.ts +320 -0
- package/src/ferment/event-mapper.ts +313 -0
- package/src/ferment/event-store.property.test.ts +240 -0
- package/src/ferment/event-store.test.ts +780 -0
- package/src/ferment/event-store.ts +1332 -0
- package/src/ferment/fsm.test.ts +630 -0
- package/src/ferment/fsm.ts +466 -0
- package/src/ferment/lifecycle.ts +35 -0
- package/src/ferment/state-machine.test.ts +1215 -0
- package/src/ferment/state-machine.ts +994 -0
- package/src/ferment/stats.test.ts +31 -0
- package/src/ferment/stats.ts +334 -0
- package/src/ferment/store.test.ts +543 -0
- package/src/ferment/store.ts +906 -0
- package/src/ferment/success-criteria.ts +51 -0
- package/src/ferment/text.ts +11 -0
- package/src/ferment/title.test.ts +35 -0
- package/src/ferment/title.ts +28 -0
- package/src/ferment/types.ts +277 -0
- package/src/fs-paths.test.ts +104 -0
- package/src/fs-paths.ts +112 -0
- package/src/integrations/__fixtures__/models.ts +72 -0
- package/src/integrations/bun-sqlite.d.ts +22 -0
- package/src/integrations/claude-code.test.ts +488 -0
- package/src/integrations/claude-code.ts +221 -0
- package/src/integrations/constants.ts +9 -0
- package/src/integrations/cursor.test.ts +91 -0
- package/src/integrations/cursor.ts +188 -0
- package/src/integrations/detect.ts +92 -0
- package/src/integrations/gsd2.test.ts +146 -0
- package/src/integrations/gsd2.ts +162 -0
- package/src/integrations/models.ts +212 -0
- package/src/integrations/openclaw.test.ts +314 -0
- package/src/integrations/openclaw.ts +276 -0
- package/src/integrations/opencode.test.ts +216 -0
- package/src/integrations/opencode.ts +226 -0
- package/src/integrations/provider/opencode.ts +37 -0
- package/src/integrations/registry.test.ts +43 -0
- package/src/integrations/registry.ts +33 -0
- package/src/integrations/spawn.ts +88 -0
- package/src/integrations/types.ts +35 -0
- package/src/login-command-patch.test.ts +609 -0
- package/src/login-command-patch.ts +299 -0
- package/src/models.test.ts +827 -0
- package/src/models.ts +379 -0
- package/src/modes/acp/acp-prompter.ts +64 -0
- package/src/modes/acp/acp-ui-context.test.ts +1001 -0
- package/src/modes/acp/acp-ui-context.ts +435 -0
- package/src/modes/acp/capabilities.ts +36 -0
- package/src/modes/acp/commands.test.ts +29 -0
- package/src/modes/acp/commands.ts +19 -0
- package/src/modes/acp/permission-prompter-registry.ts +17 -0
- package/src/modes/acp/server.test.ts +4392 -0
- package/src/modes/acp/server.ts +1569 -0
- package/src/modes/acp/utils.ts +10 -0
- package/src/oauth-page-patch.test.ts +84 -0
- package/src/ollama.test.ts +1469 -0
- package/src/ollama.ts +491 -0
- package/src/paste-interceptor.test.ts +179 -0
- package/src/paste-interceptor.ts +61 -0
- package/src/paste-to-editor-patch.test.ts +24 -0
- package/src/paste-to-editor-patch.ts +27 -0
- package/src/posthog-device.ts +31 -0
- package/src/proxy.test.ts +36 -0
- package/src/proxy.ts +36 -0
- package/src/resources/bash-hook-discovery.ts +69 -0
- package/src/resources/bash-hooks.test.ts +93 -0
- package/src/resources/bash-hooks.ts +109 -0
- package/src/resources/claude-code-hook-resources.ts +35 -0
- package/src/resources/definitions.test.ts +92 -0
- package/src/resources/definitions.ts +149 -0
- package/src/resources/extension.test.ts +168 -0
- package/src/resources/extension.ts +114 -0
- package/src/resources/filter.ts +11 -0
- package/src/resources/package-resources.test.ts +234 -0
- package/src/resources/package-resources.ts +152 -0
- package/src/resources/rtk-install.test.ts +37 -0
- package/src/resources/rtk-install.ts +289 -0
- package/src/resources/store.test.ts +118 -0
- package/src/resources/store.ts +76 -0
- package/src/resources/tool-blocker.ts +14 -0
- package/src/resources/types.ts +23 -0
- package/src/resources/ui.test.ts +74 -0
- package/src/resources/ui.ts +221 -0
- package/src/sandbox/cloud/auth.test.ts +219 -0
- package/src/sandbox/cloud/auth.ts +127 -0
- package/src/sandbox/cloud/http.test.ts +88 -0
- package/src/sandbox/cloud/http.ts +46 -0
- package/src/sandbox/cloud/index.ts +18 -0
- package/src/sandbox/cloud/keys.test.ts +44 -0
- package/src/sandbox/cloud/keys.ts +34 -0
- package/src/sandbox/cloud/readiness.test.ts +115 -0
- package/src/sandbox/cloud/readiness.ts +122 -0
- package/src/sandbox/cloud/types.ts +70 -0
- package/src/sandbox/cloud/uri.test.ts +51 -0
- package/src/sandbox/cloud/uri.ts +30 -0
- package/src/sandbox/cloud/workspaces.test.ts +249 -0
- package/src/sandbox/cloud/workspaces.ts +161 -0
- package/src/sandbox/constants.ts +2 -0
- package/src/sandbox/git-credentials.test.ts +89 -0
- package/src/sandbox/git-credentials.ts +72 -0
- package/src/sandbox/worker/client.test.ts +156 -0
- package/src/sandbox/worker/client.ts +201 -0
- package/src/sandbox/worker/git-identity.test.ts +99 -0
- package/src/sandbox/worker/git-identity.ts +69 -0
- package/src/sandbox/worker/index.ts +36 -0
- package/src/sandbox/worker/secrets.test.ts +61 -0
- package/src/sandbox/worker/secrets.ts +28 -0
- package/src/sandbox/worker/sessions.test.ts +197 -0
- package/src/sandbox/worker/sessions.ts +32 -0
- package/src/sandbox/worker/status.test.ts +57 -0
- package/src/sandbox/worker/status.ts +6 -0
- package/src/sandbox/worker/types.ts +119 -0
- package/src/set-package-dir.ts +5 -0
- package/src/settings-watcher.test.ts +116 -0
- package/src/settings-watcher.ts +79 -0
- package/src/setup-wizard/apply-tools.test.ts +131 -0
- package/src/setup-wizard/apply-tools.ts +70 -0
- package/src/setup-wizard/index.ts +107 -0
- package/src/setup-wizard/prompt.ts +126 -0
- package/src/setup-wizard/shell-profile.test.ts +154 -0
- package/src/setup-wizard/shell-profile.ts +169 -0
- package/src/setup-wizard/state.ts +45 -0
- package/src/setup-wizard/steps/auth.test.ts +145 -0
- package/src/setup-wizard/steps/auth.ts +130 -0
- package/src/setup-wizard/steps/done.test.ts +267 -0
- package/src/setup-wizard/steps/done.ts +121 -0
- package/src/setup-wizard/steps/rtk.ts +6 -0
- package/src/setup-wizard/steps/telemetry.test.ts +46 -0
- package/src/setup-wizard/steps/telemetry.ts +41 -0
- package/src/setup-wizard/steps/tools.ts +45 -0
- package/src/setup-wizard/steps/welcome.ts +42 -0
- package/src/setup-wizard.test.ts +384 -0
- package/src/setup-wizard.ts +405 -0
- package/src/shared/planning/entry-trigger-registry.test.ts +427 -0
- package/src/shared/planning/entry-trigger-registry.ts +216 -0
- package/src/shared/planning/plan-artifact-store.test.ts +338 -0
- package/src/shared/planning/plan-artifact-store.ts +244 -0
- package/src/shared/planning/plan-decomposition.test.ts +183 -0
- package/src/shared/planning/plan-decomposition.ts +338 -0
- package/src/shared/planning/planning-stop-nudge.test.ts +217 -0
- package/src/shared/planning/planning-stop-nudge.ts +133 -0
- package/src/shared/planning/prompt-supplement-registry.test.ts +264 -0
- package/src/shared/planning/prompt-supplement-registry.ts +250 -0
- package/src/shared/planning/read-only-tool-registry.test.ts +96 -0
- package/src/shared/planning/read-only-tool-registry.ts +98 -0
- package/src/shared/planning/shared-planning-process.test.ts +224 -0
- package/src/shared/planning/shared-planning-process.ts +128 -0
- package/src/shared/planning/tool-catalog.test.ts +344 -0
- package/src/shared/planning/tool-catalog.ts +258 -0
- package/src/shared/planning/tool-profile-manager.test.ts +409 -0
- package/src/shared/planning/tool-profile-manager.ts +281 -0
- package/src/skill-paths.test.ts +33 -0
- package/src/skill-paths.ts +18 -0
- package/src/skills-wizard.ts +44 -0
- package/src/ssh-proxy.test.ts +102 -0
- package/src/ssh-proxy.ts +79 -0
- package/src/startup-context.ts +23 -0
- package/src/startup-settings.test.ts +37 -0
- package/src/startup-settings.ts +26 -0
- package/src/terminal-bg-probe.test.ts +131 -0
- package/src/terminal-bg-probe.ts +238 -0
- package/src/theme-file-watcher.ts +95 -0
- package/src/types/before-provider-headers.ts +48 -0
- package/src/types/pi-coding-agent-utils.d.ts +34 -0
- package/src/update/extract.ts +75 -0
- package/src/update/github.test.ts +133 -0
- package/src/update/github.ts +190 -0
- package/src/update/install.test.ts +210 -0
- package/src/update/install.ts +205 -0
- package/src/update/paths.test.ts +97 -0
- package/src/update/paths.ts +109 -0
- package/src/update/state.test.ts +215 -0
- package/src/update/state.ts +94 -0
- package/src/update/workflow.test.ts +397 -0
- package/src/update/workflow.ts +217 -0
- package/src/upstream-retry-patch.test.ts +77 -0
- package/src/upstream-retry-patch.ts +41 -0
- package/src/utils/clipboard-image.test.ts +117 -0
- package/src/utils/clipboard-image.ts +316 -0
- package/src/utils/clipboard-linux-routing.test.ts +100 -0
- package/src/utils/clipboard-linux-subprocess.test.ts +176 -0
- package/src/utils/clipboard-linux-subprocess.ts +58 -0
- package/src/utils/clipboard-native-harness-wsl.test.ts +109 -0
- package/src/utils/clipboard-native-harness.test.ts +54 -0
- package/src/utils/clipboard-native-harness.ts +146 -0
- package/src/utils/clipboard-read.test.ts +88 -0
- package/src/utils/clipboard-read.ts +69 -0
- package/src/utils/export-post-process.test.ts +539 -0
- package/src/utils/export-post-process.ts +213 -0
- package/src/utils/http.test.ts +302 -0
- package/src/utils/http.ts +106 -0
- package/src/utils/image-registry.test.ts +88 -0
- package/src/utils/image-registry.ts +132 -0
- package/src/utils/image-utils.test.ts +58 -0
- package/src/utils/image-utils.ts +38 -0
- package/src/utils/os-metadata.ts +65 -0
- package/src/utils/sandbox.test.ts +98 -0
- package/src/utils/sandbox.ts +24 -0
- package/src/utils/session-metadata-store.test.ts +228 -0
- package/src/utils/session-metadata-store.ts +96 -0
- package/src/utils/spawn-ikie-subprocess.ts +57 -0
- package/src/utils/trace-id-export.test.ts +343 -0
- package/src/utils/trace-id-export.ts +84 -0
- package/src/utils.test.ts +38 -0
- package/src/utils.ts +65 -0
- package/test-cases/README.md +54 -0
- package/test-cases/bitcoin-price.md +52 -0
- package/test-cases/golang-question.md +29 -0
- package/test-cases/offender.md +32 -0
- package/test-cases/pi-mono-design.md +27 -0
- package/test-cases/pi-mono-tool-card-loop.txt +1381 -0
- package/test-cases/pi-mono-tool-card.md +60 -0
- package/test-cases/pokemon.md +27 -0
- package/test-cases/problem-740.md +20 -0
- package/test-cases/python-project.md +24 -0
- package/test-cases/remove-home-directory.md +53 -0
- package/test-cases/use-gh.md +25 -0
- package/tests/e2e/acp/all-capabilities.test.ts +102 -0
- package/tests/e2e/acp/elicitation-dialogs.test.ts +139 -0
- package/tests/e2e/acp/elicitation-only.test.ts +76 -0
- package/tests/e2e/acp/message-id.test.ts +139 -0
- package/tests/e2e/acp/no-capabilities.test.ts +71 -0
- package/tests/e2e/acp/permission-flow.test.ts +237 -0
- package/tests/e2e/acp/support/acp-fixture.ts +413 -0
- package/tests/e2e/acp/support/scenarios.ts +55 -0
- package/tests/e2e/acp/support/test-dialog-extension.js +22 -0
- package/tests/e2e/acp/support/test-ui-extension.js +14 -0
- package/tests/e2e/acp/vitest.config.ts +12 -0
- package/tests/e2e/tui/ask-user-form.test.ts +310 -0
- package/tests/e2e/tui/basic-session-lifecycle.test.ts +20 -0
- package/tests/e2e/tui/branch-resume.test.ts +71 -0
- package/tests/e2e/tui/cooking-animation.test.ts +213 -0
- package/tests/e2e/tui/editor-narrow-layout.test.ts +47 -0
- package/tests/e2e/tui/extension-custom-headers.test.ts +75 -0
- package/tests/e2e/tui/ferment-draft-proposal-persistence.test.ts +125 -0
- package/tests/e2e/tui/ferment-new-runs-planning.test.ts +211 -0
- package/tests/e2e/tui/ferment-phase-review.test.ts +78 -0
- package/tests/e2e/tui/ferment-plan-review-suppression.test.ts +404 -0
- package/tests/e2e/tui/multi-model-command.test.ts +624 -0
- package/tests/e2e/tui/nudge-wiring.test.ts +129 -0
- package/tests/e2e/tui/ollama-models.test.ts +143 -0
- package/tests/e2e/tui/oneshot-bypasses-dropdown.test.ts +97 -0
- package/tests/e2e/tui/plan-mode-tool-switch.test.ts +73 -0
- package/tests/e2e/tui/plan-review-dismissal.test.ts +291 -0
- package/tests/e2e/tui/plan-to-ferment-promo.test.ts +204 -0
- package/tests/e2e/tui/skip-list.js +9 -0
- package/tests/e2e/tui/support/assertions.ts +41 -0
- package/tests/e2e/tui/support/fake-ollama-server.ts +356 -0
- package/tests/e2e/tui/support/fake-openai-server.ts +361 -0
- package/tests/e2e/tui/support/ikie-fixture.ts +374 -0
- package/tests/e2e/tui/theme-selector.test.ts +99 -0
- package/tests/e2e/tui/todo-overlay.test.ts +163 -0
- package/tests/e2e/tui/todo-widget-ferment.test.ts +346 -0
- package/tests/e2e/tui/tui-test.config.ts +6 -0
- package/tests/smoke/agent-session-tracking.test.ts +203 -0
- package/tests/smoke/binary.test.ts +186 -0
- package/tests/smoke/ferment-oneshot-exit.test.ts +514 -0
- package/tests/smoke/harness.ts +236 -0
- package/tests/smoke/interactive-paste.test.ts +167 -0
- package/tests/smoke/vitest.config.ts +12 -0
- package/tests/smoke/web-fetch.test.ts +41 -0
- package/tests/smoke/web-search.test.ts +47 -0
- package/themes/catppuccin-macchiato.json +82 -0
- package/themes/dark.json +87 -0
- package/themes/dracula.json +79 -0
- package/themes/github-dark.json +80 -0
- package/themes/github-light.json +80 -0
- package/themes/ikie-light.json +92 -0
- package/themes/ikie-minimal.json +79 -0
- package/themes/ikie.json +96 -0
- package/themes/light.json +86 -0
- package/themes/lucent-orng.json +79 -0
- package/themes/monokai.json +78 -0
- package/themes/neon.json +87 -0
- package/themes/night-owl.json +87 -0
- package/themes/nord.json +82 -0
- package/themes/one-dark.json +79 -0
- package/themes/solarized-dark.json +81 -0
- package/themes/solarized-light.json +81 -0
- package/tools/proxy-helper/Makefile +11 -0
- package/tools/proxy-helper/cmd/proxy/proxy.go +211 -0
- package/tools/proxy-helper/cmd/proxy/proxy_test.go +309 -0
- package/tools/proxy-helper/go.mod +13 -0
- package/tools/proxy-helper/go.sum +12 -0
- package/tools/proxy-helper/main.go +29 -0
- package/tools/proxy-helper/pkg/cast/cast.go +287 -0
- package/tsconfig.json +17 -0
- package/vendor/superpowers/.claude-plugin/marketplace.json +20 -0
- package/vendor/superpowers/.claude-plugin/plugin.json +20 -0
- package/vendor/superpowers/.codex-plugin/plugin.json +47 -0
- package/vendor/superpowers/.cursor-plugin/plugin.json +25 -0
- package/vendor/superpowers/.gitattributes +18 -0
- package/vendor/superpowers/.github/FUNDING.yml +3 -0
- package/vendor/superpowers/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
- package/vendor/superpowers/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/vendor/superpowers/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
- package/vendor/superpowers/.github/ISSUE_TEMPLATE/platform_support.md +23 -0
- package/vendor/superpowers/.github/PULL_REQUEST_TEMPLATE.md +126 -0
- package/vendor/superpowers/.opencode/INSTALL.md +110 -0
- package/vendor/superpowers/.opencode/plugins/superpowers.js +135 -0
- package/vendor/superpowers/.version-bump.json +20 -0
- package/vendor/superpowers/CLAUDE.md +106 -0
- package/vendor/superpowers/CODE_OF_CONDUCT.md +128 -0
- package/vendor/superpowers/GEMINI.md +2 -0
- package/vendor/superpowers/LICENSE +21 -0
- package/vendor/superpowers/README.md +233 -0
- package/vendor/superpowers/RELEASE-NOTES.md +1180 -0
- package/vendor/superpowers/assets/app-icon.png +0 -0
- package/vendor/superpowers/assets/superpowers-small.svg +1 -0
- package/vendor/superpowers/docs/README.opencode.md +157 -0
- package/vendor/superpowers/docs/plans/2025-11-22-opencode-support-design.md +294 -0
- package/vendor/superpowers/docs/plans/2025-11-22-opencode-support-implementation.md +1095 -0
- package/vendor/superpowers/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +711 -0
- package/vendor/superpowers/docs/plans/2026-01-17-visual-brainstorming.md +571 -0
- package/vendor/superpowers/docs/superpowers/plans/2026-01-22-document-review-system.md +301 -0
- package/vendor/superpowers/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md +523 -0
- package/vendor/superpowers/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md +479 -0
- package/vendor/superpowers/docs/superpowers/plans/2026-03-23-codex-app-compatibility.md +564 -0
- package/vendor/superpowers/docs/superpowers/plans/2026-04-06-worktree-rototill.md +879 -0
- package/vendor/superpowers/docs/superpowers/specs/2026-01-22-document-review-system-design.md +136 -0
- package/vendor/superpowers/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md +162 -0
- package/vendor/superpowers/docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md +118 -0
- package/vendor/superpowers/docs/superpowers/specs/2026-03-23-codex-app-compatibility-design.md +244 -0
- package/vendor/superpowers/docs/superpowers/specs/2026-04-06-worktree-rototill-design.md +342 -0
- package/vendor/superpowers/docs/testing.md +303 -0
- package/vendor/superpowers/docs/windows/polyglot-hooks.md +212 -0
- package/vendor/superpowers/gemini-extension.json +6 -0
- package/vendor/superpowers/hooks/hooks-cursor.json +10 -0
- package/vendor/superpowers/hooks/hooks.json +16 -0
- package/vendor/superpowers/hooks/run-hook.cmd +46 -0
- package/vendor/superpowers/hooks/session-start +57 -0
- package/vendor/superpowers/package.json +6 -0
- package/vendor/superpowers/scripts/bump-version.sh +220 -0
- package/vendor/superpowers/scripts/sync-to-codex-plugin.sh +462 -0
- package/vendor/superpowers/skills/brainstorming/SKILL.md +164 -0
- package/vendor/superpowers/skills/brainstorming/scripts/frame-template.html +214 -0
- package/vendor/superpowers/skills/brainstorming/scripts/helper.js +88 -0
- package/vendor/superpowers/skills/brainstorming/scripts/server.cjs +354 -0
- package/vendor/superpowers/skills/brainstorming/scripts/start-server.sh +148 -0
- package/vendor/superpowers/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/vendor/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/vendor/superpowers/skills/brainstorming/visual-companion.md +287 -0
- package/vendor/superpowers/skills/dispatching-parallel-agents/SKILL.md +182 -0
- package/vendor/superpowers/skills/executing-plans/SKILL.md +70 -0
- package/vendor/superpowers/skills/finishing-a-development-branch/SKILL.md +251 -0
- package/vendor/superpowers/skills/receiving-code-review/SKILL.md +213 -0
- package/vendor/superpowers/skills/requesting-code-review/SKILL.md +103 -0
- package/vendor/superpowers/skills/requesting-code-review/code-reviewer.md +168 -0
- package/vendor/superpowers/skills/subagent-driven-development/SKILL.md +279 -0
- package/vendor/superpowers/skills/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
- package/vendor/superpowers/skills/subagent-driven-development/implementer-prompt.md +113 -0
- package/vendor/superpowers/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/vendor/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/vendor/superpowers/skills/systematic-debugging/SKILL.md +296 -0
- package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/vendor/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/vendor/superpowers/skills/systematic-debugging/find-polluter.sh +63 -0
- package/vendor/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/vendor/superpowers/skills/systematic-debugging/test-academic.md +14 -0
- package/vendor/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/vendor/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/vendor/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/vendor/superpowers/skills/test-driven-development/SKILL.md +371 -0
- package/vendor/superpowers/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/vendor/superpowers/skills/using-git-worktrees/SKILL.md +215 -0
- package/vendor/superpowers/skills/using-superpowers/SKILL.md +117 -0
- package/vendor/superpowers/skills/using-superpowers/references/codex-tools.md +59 -0
- package/vendor/superpowers/skills/using-superpowers/references/copilot-tools.md +42 -0
- package/vendor/superpowers/skills/using-superpowers/references/gemini-tools.md +51 -0
- package/vendor/superpowers/skills/verification-before-completion/SKILL.md +139 -0
- package/vendor/superpowers/skills/writing-plans/SKILL.md +152 -0
- package/vendor/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/vendor/superpowers/skills/writing-skills/SKILL.md +655 -0
- package/vendor/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/vendor/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/vendor/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/vendor/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
- package/vendor/superpowers/skills/writing-skills/render-graphs.js +168 -0
- package/vendor/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/vendor/superpowers/tests/brainstorm-server/package-lock.json +36 -0
- package/vendor/superpowers/tests/brainstorm-server/package.json +10 -0
- package/vendor/superpowers/tests/brainstorm-server/server.test.js +427 -0
- package/vendor/superpowers/tests/brainstorm-server/windows-lifecycle.test.sh +351 -0
- package/vendor/superpowers/tests/brainstorm-server/ws-protocol.test.js +392 -0
- package/vendor/superpowers/tests/claude-code/README.md +170 -0
- package/vendor/superpowers/tests/claude-code/analyze-token-usage.py +168 -0
- package/vendor/superpowers/tests/claude-code/run-skill-tests.sh +188 -0
- package/vendor/superpowers/tests/claude-code/test-document-review-system.sh +177 -0
- package/vendor/superpowers/tests/claude-code/test-helpers.sh +202 -0
- package/vendor/superpowers/tests/claude-code/test-requesting-code-review.sh +214 -0
- package/vendor/superpowers/tests/claude-code/test-subagent-driven-development-integration.sh +322 -0
- package/vendor/superpowers/tests/claude-code/test-subagent-driven-development.sh +165 -0
- package/vendor/superpowers/tests/claude-code/test-worktree-native-preference.sh +176 -0
- package/vendor/superpowers/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh +615 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/action-oriented.txt +3 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/after-planning-flow.txt +17 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/claude-suggested-it.txt +11 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/i-know-what-sdd-means.txt +8 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/mid-conversation-execute-plan.txt +3 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/please-use-brainstorming.txt +1 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/skip-formalities.txt +3 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/subagent-driven-development-please.txt +1 -0
- package/vendor/superpowers/tests/explicit-skill-requests/prompts/use-systematic-debugging.txt +1 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-all.sh +70 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-claude-describes-sdd.sh +100 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-extended-multiturn-test.sh +113 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-haiku-test.sh +144 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-multiturn-test.sh +143 -0
- package/vendor/superpowers/tests/explicit-skill-requests/run-test.sh +136 -0
- package/vendor/superpowers/tests/opencode/run-tests.sh +165 -0
- package/vendor/superpowers/tests/opencode/setup.sh +88 -0
- package/vendor/superpowers/tests/opencode/test-bootstrap-caching.mjs +124 -0
- package/vendor/superpowers/tests/opencode/test-bootstrap-caching.sh +32 -0
- package/vendor/superpowers/tests/opencode/test-plugin-loading.sh +82 -0
- package/vendor/superpowers/tests/opencode/test-priority.sh +217 -0
- package/vendor/superpowers/tests/opencode/test-tools.sh +95 -0
- package/vendor/superpowers/tests/skill-triggering/prompts/dispatching-parallel-agents.txt +8 -0
- package/vendor/superpowers/tests/skill-triggering/prompts/executing-plans.txt +1 -0
- package/vendor/superpowers/tests/skill-triggering/prompts/requesting-code-review.txt +3 -0
- package/vendor/superpowers/tests/skill-triggering/prompts/systematic-debugging.txt +11 -0
- package/vendor/superpowers/tests/skill-triggering/prompts/test-driven-development.txt +7 -0
- package/vendor/superpowers/tests/skill-triggering/prompts/writing-plans.txt +10 -0
- package/vendor/superpowers/tests/skill-triggering/run-all.sh +60 -0
- package/vendor/superpowers/tests/skill-triggering/run-test.sh +88 -0
- package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/design.md +81 -0
- package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/plan.md +172 -0
- package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/scaffold.sh +45 -0
- package/vendor/superpowers/tests/subagent-driven-dev/run-test.sh +106 -0
- package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/design.md +70 -0
- package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/plan.md +222 -0
- package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/scaffold.sh +46 -0
- package/vitest.config.ts +22 -0
|
@@ -0,0 +1,4511 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { readFile as readFileAsync } from "node:fs/promises"
|
|
3
|
+
import { extname, relative, resolve } from "node:path"
|
|
4
|
+
import { formatDuration } from "../extensions/format.js"
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
BashToolDetails,
|
|
8
|
+
ExtensionAPI,
|
|
9
|
+
GrepToolDetails,
|
|
10
|
+
ReadToolDetails,
|
|
11
|
+
Theme,
|
|
12
|
+
} from "@earendil-works/pi-coding-agent"
|
|
13
|
+
import {
|
|
14
|
+
AssistantMessageComponent,
|
|
15
|
+
ToolExecutionComponent,
|
|
16
|
+
UserMessageComponent,
|
|
17
|
+
createBashTool,
|
|
18
|
+
createEditTool,
|
|
19
|
+
createFindTool,
|
|
20
|
+
createGrepTool,
|
|
21
|
+
createLsTool,
|
|
22
|
+
createReadTool,
|
|
23
|
+
createWriteTool,
|
|
24
|
+
} from "@earendil-works/pi-coding-agent"
|
|
25
|
+
import {
|
|
26
|
+
Container,
|
|
27
|
+
Text,
|
|
28
|
+
deleteAllKittyImages,
|
|
29
|
+
getCapabilities,
|
|
30
|
+
getImageDimensions,
|
|
31
|
+
imageFallback,
|
|
32
|
+
truncateToWidth,
|
|
33
|
+
visibleWidth,
|
|
34
|
+
wrapTextWithAnsi,
|
|
35
|
+
} from "@earendil-works/pi-tui"
|
|
36
|
+
|
|
37
|
+
import * as Diff from "diff"
|
|
38
|
+
import { getBashCommandForDisplay } from "./rtk-rewrite.js"
|
|
39
|
+
import { TODO_TOOL_NAMES } from "./todos/tool.js"
|
|
40
|
+
import type { BundledLanguage, BundledTheme } from "shiki"
|
|
41
|
+
|
|
42
|
+
const RESET = "\x1b[0m"
|
|
43
|
+
const TRANSPARENT_BG = "\x1b[49m"
|
|
44
|
+
const TRANSPARENT_RESET = `${RESET}${TRANSPARENT_BG}`
|
|
45
|
+
|
|
46
|
+
// Border / branch rule colors. Defaults match the previous hardcoded values
|
|
47
|
+
// so behavior is identical when the theme is unavailable or themeAdaptive=false.
|
|
48
|
+
// `applyThemePaletteIfNeeded(theme)` re-derives these from `theme.fg("borderMuted"|"muted")`.
|
|
49
|
+
let BORDER_COLOR = "\x1b[38;5;238m"
|
|
50
|
+
const ANSI_RE = /\x1b\[[0-9;]*m/g
|
|
51
|
+
const ANSI_PRESENT_RE = /\x1b\[[0-9;]*m/
|
|
52
|
+
const PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-container-render")
|
|
53
|
+
const TOOL_RENDER_CACHE = Symbol.for("pi-claude-style-tools:tool-render-cache")
|
|
54
|
+
const TOOL_CACHE_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-tool-cache-invalidation")
|
|
55
|
+
const TOOL_IMAGE_EXPAND_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-read-image-expansion")
|
|
56
|
+
const USER_MESSAGE_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-user-message-render")
|
|
57
|
+
const HIDDEN_TOOL_BLOCK_NAMES = new Set(["write_todos", ...TODO_TOOL_NAMES])
|
|
58
|
+
const WRAP_MARK = "\uE000"
|
|
59
|
+
const KITTY_IMAGE_PREFIX = "\x1b_G"
|
|
60
|
+
const ITERM2_IMAGE_PREFIX = "\x1b]1337;File="
|
|
61
|
+
|
|
62
|
+
let toolBackgroundMode: "default" | "transparent" | "outlines" = "outlines"
|
|
63
|
+
|
|
64
|
+
interface SettingsFile {
|
|
65
|
+
toolBackground?: "default" | "transparent" | "outlines" | "border"
|
|
66
|
+
readOutputMode?: "hidden" | "summary" | "preview"
|
|
67
|
+
searchOutputMode?: "hidden" | "count" | "preview"
|
|
68
|
+
mcpOutputMode?: "hidden" | "summary" | "preview"
|
|
69
|
+
previewLines?: number
|
|
70
|
+
expandedPreviewMaxLines?: number
|
|
71
|
+
bashOutputMode?: "opencode" | "summary" | "preview"
|
|
72
|
+
bashCollapsedLines?: number
|
|
73
|
+
showTruncationHints?: boolean
|
|
74
|
+
diffCollapsedLines?: number
|
|
75
|
+
diffTheme?: string
|
|
76
|
+
diffColors?: Record<string, string>
|
|
77
|
+
/**
|
|
78
|
+
* When true (default), derive borders, dim text, branch rules, and diff
|
|
79
|
+
* accents from the active pi theme via `theme.getFgAnsi`/`getBgAnsi`.
|
|
80
|
+
* Explicit `diffTheme` / `diffColors` always win over theme-derived
|
|
81
|
+
* defaults so users keep full control.
|
|
82
|
+
*/
|
|
83
|
+
themeAdaptive?: boolean
|
|
84
|
+
/**
|
|
85
|
+
* Theme color key used for the spinner verb (e.g. "Cooking…"). Defaults
|
|
86
|
+
* to "accent". Useful when the active theme's accent is overloaded for
|
|
87
|
+
* borders, headings, or bash mode and the verb should pop differently.
|
|
88
|
+
* Valid keys are any of the pi theme `ThemeColor` names (e.g. accent,
|
|
89
|
+
* borderAccent, success, warning, mdHeading, thinkingMedium, bashMode).
|
|
90
|
+
*/
|
|
91
|
+
spinnerVerbColor?: string
|
|
92
|
+
/**
|
|
93
|
+
* Theme color key used for the spinner status suffix (the parenthesized
|
|
94
|
+
* "(thinking · ↓ 10 tokens · 2s)" trailer). Defaults to "muted".
|
|
95
|
+
*/
|
|
96
|
+
spinnerStatusColor?: string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let _settingsCache: { value: SettingsFile; timestamp: number } | null = null
|
|
100
|
+
const SETTINGS_CACHE_TTL_MS = 5_000
|
|
101
|
+
|
|
102
|
+
function readSettings(): SettingsFile {
|
|
103
|
+
const now = Date.now()
|
|
104
|
+
if (_settingsCache && now - _settingsCache.timestamp < SETTINGS_CACHE_TTL_MS) {
|
|
105
|
+
return _settingsCache.value
|
|
106
|
+
}
|
|
107
|
+
const paths = [`${process.cwd()}/.pi/settings.json`, `${process.env.HOME ?? ""}/.pi/settings.json`]
|
|
108
|
+
for (const path of paths) {
|
|
109
|
+
try {
|
|
110
|
+
if (!path || !existsSync(path)) continue
|
|
111
|
+
const raw = JSON.parse(readFileSync(path, "utf8"))
|
|
112
|
+
if (raw && typeof raw === "object") {
|
|
113
|
+
const result = raw as SettingsFile
|
|
114
|
+
_settingsCache = { value: result, timestamp: now }
|
|
115
|
+
return result
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// ignore invalid settings files
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const empty: SettingsFile = {}
|
|
122
|
+
_settingsCache = { value: empty, timestamp: now }
|
|
123
|
+
return empty
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Cross-extension bust signal for spinner.ts — it watches this counter on
|
|
127
|
+
// globalThis and invalidates its settings cache when it changes. Lets
|
|
128
|
+
// /cc-spinner edits take effect on the next 250ms spinner tick instead of
|
|
129
|
+
// waiting for the file-stat TTL.
|
|
130
|
+
const SPINNER_BUST_KEY = Symbol.for("pi-claude-style-tools:spinner-settings-bust")
|
|
131
|
+
function bustSpinnerSettingsCache(): void {
|
|
132
|
+
const current = ((globalThis as any)[SPINNER_BUST_KEY] as number | undefined) ?? 0
|
|
133
|
+
;(globalThis as any)[SPINNER_BUST_KEY] = current + 1
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function writeSettingsKey(key: string, value: unknown): void {
|
|
137
|
+
_settingsCache = null // invalidate cache on write
|
|
138
|
+
const home = process.env.HOME ?? ""
|
|
139
|
+
if (!home) return
|
|
140
|
+
const dir = `${home}/.pi`
|
|
141
|
+
const path = `${dir}/settings.json`
|
|
142
|
+
let settings: Record<string, unknown> = {}
|
|
143
|
+
try {
|
|
144
|
+
if (existsSync(path)) settings = JSON.parse(readFileSync(path, "utf8")) ?? {}
|
|
145
|
+
} catch {
|
|
146
|
+
/* start fresh */
|
|
147
|
+
}
|
|
148
|
+
if (value === undefined) {
|
|
149
|
+
delete settings[key]
|
|
150
|
+
} else {
|
|
151
|
+
settings[key] = value
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
mkdirSync(dir, { recursive: true })
|
|
155
|
+
writeFileSync(path, JSON.stringify(settings, null, 2) + "\n")
|
|
156
|
+
} catch {
|
|
157
|
+
/* best effort */
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let toolBackgroundOverride: "default" | "transparent" | "outlines" | null = null
|
|
162
|
+
|
|
163
|
+
function syncToolBackgroundMode(): void {
|
|
164
|
+
if (toolBackgroundOverride) {
|
|
165
|
+
toolBackgroundMode = toolBackgroundOverride
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
const settings = readSettings()
|
|
169
|
+
// Backward compat: "border" was renamed to "outlines"
|
|
170
|
+
const raw = settings.toolBackground === "border" ? "outlines" : settings.toolBackground
|
|
171
|
+
toolBackgroundMode = raw ?? "outlines"
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function setThemeBg(theme: unknown, key: string, value: string): void {
|
|
175
|
+
const themeAny = theme as any
|
|
176
|
+
if (themeAny.bgColors instanceof Map) {
|
|
177
|
+
themeAny.bgColors.set(key, value)
|
|
178
|
+
} else if (themeAny.bgColors && typeof themeAny.bgColors === "object") {
|
|
179
|
+
themeAny.bgColors[key] = value
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function applyToolBackgroundMode(theme: unknown): void {
|
|
184
|
+
syncToolBackgroundMode()
|
|
185
|
+
if (toolBackgroundMode === "default") return
|
|
186
|
+
|
|
187
|
+
setThemeBg(theme, "toolPendingBg", TRANSPARENT_BG)
|
|
188
|
+
setThemeBg(theme, "toolSuccessBg", TRANSPARENT_BG)
|
|
189
|
+
setThemeBg(theme, "toolErrorBg", TRANSPARENT_BG)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function stripAnsi(text: string): string {
|
|
193
|
+
return text.replace(ANSI_RE, "")
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function isBlankLine(text: string): boolean {
|
|
197
|
+
// Strip ANSI escapes and the ▍ stroke prefix (with its trailing space) before checking.
|
|
198
|
+
return stripAnsi(text).replace(/▍ ?/g, "").trim().length === 0
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function borderLine(width: number): string {
|
|
202
|
+
return `${BORDER_COLOR}${"─".repeat(Math.max(1, width))}${TRANSPARENT_RESET}`
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function clampLineWidth(line: string, width: number): string {
|
|
206
|
+
if (width <= 0) return ""
|
|
207
|
+
return visibleWidth(line) > width ? truncateToWidth(line, width) : line
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function isToolExecutionLike(value: unknown): value is { toolName: string; toolCallId: string } {
|
|
211
|
+
if (!value || typeof value !== "object") return false
|
|
212
|
+
const candidate = value as Record<string, unknown>
|
|
213
|
+
return typeof candidate.toolName === "string" && typeof candidate.toolCallId === "string"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function isTerminalImageLine(line: string): boolean {
|
|
217
|
+
return line.includes(KITTY_IMAGE_PREFIX) || line.includes(ITERM2_IMAGE_PREFIX)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function normalizeLeadingCheckGlyph(line: string): string {
|
|
221
|
+
return line.replace(/^((?:\x1b\[[0-9;]*m|[ \t])*)[✓✔](?=\s)/, "$1●")
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function firstImageBlockStart(lines: string[]): number {
|
|
225
|
+
const imageLineIndex = lines.findIndex(isTerminalImageLine)
|
|
226
|
+
if (imageLineIndex === -1) return -1
|
|
227
|
+
let start = imageLineIndex
|
|
228
|
+
while (start > 0 && isBlankLine(lines[start - 1])) start--
|
|
229
|
+
return start
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function splitRenderedImageBlock(lines: string[]): { textLines: string[]; imageLines: string[] } {
|
|
233
|
+
const imageStart = firstImageBlockStart(lines)
|
|
234
|
+
if (imageStart === -1) return { textLines: lines, imageLines: [] }
|
|
235
|
+
const textLines = lines.slice(0, imageStart)
|
|
236
|
+
while (textLines.length > 0 && isBlankLine(textLines[textLines.length - 1])) textLines.pop()
|
|
237
|
+
return { textLines, imageLines: lines.slice(imageStart) }
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function patchGlobalToolBorders(): void {
|
|
241
|
+
const proto = Container.prototype as any
|
|
242
|
+
if (proto[PATCH_FLAG]) return
|
|
243
|
+
|
|
244
|
+
const originalRender = proto.render
|
|
245
|
+
proto.render = function patchedContainerRender(width: number): string[] {
|
|
246
|
+
if (isToolExecutionLike(this) && HIDDEN_TOOL_BLOCK_NAMES.has(this.toolName.toLowerCase())) return []
|
|
247
|
+
if (isToolExecutionLike(this)) {
|
|
248
|
+
const cached = (this as any)[TOOL_RENDER_CACHE]
|
|
249
|
+
if (cached?.width === width && cached?.mode === toolBackgroundMode) {
|
|
250
|
+
return cached.lines
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const rendered = originalRender.call(this, width)
|
|
255
|
+
if (!Array.isArray(rendered) || rendered.length === 0) return rendered
|
|
256
|
+
if (!isToolExecutionLike(this)) return rendered
|
|
257
|
+
if (toolBackgroundMode === "default") {
|
|
258
|
+
;(this as any)[TOOL_RENDER_CACHE] = { width, mode: toolBackgroundMode, lines: rendered }
|
|
259
|
+
return rendered
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let start = 0
|
|
263
|
+
while (start < rendered.length && isBlankLine(rendered[start])) start++
|
|
264
|
+
let end = rendered.length - 1
|
|
265
|
+
while (end >= start && isBlankLine(rendered[end])) end--
|
|
266
|
+
if (start > end) return rendered
|
|
267
|
+
|
|
268
|
+
const { textLines, imageLines } = splitRenderedImageBlock(rendered.slice(start, end + 1))
|
|
269
|
+
if (imageLines.length > 0) {
|
|
270
|
+
;(this as any)[TOOL_RENDER_CACHE] = { width, mode: toolBackgroundMode, lines: rendered }
|
|
271
|
+
return rendered
|
|
272
|
+
}
|
|
273
|
+
const core = textLines.map((line) => clampLineWidth(normalizeLeadingCheckGlyph(line), width))
|
|
274
|
+
const spacerLine = " ".repeat(width)
|
|
275
|
+
let result: string[]
|
|
276
|
+
|
|
277
|
+
if (toolBackgroundMode === "outlines") {
|
|
278
|
+
const ruleWidth = Math.max(1, width)
|
|
279
|
+
const framed = core.length > 0 ? [borderLine(ruleWidth), ...core, borderLine(ruleWidth)] : []
|
|
280
|
+
result = [spacerLine, ...framed, ...imageLines]
|
|
281
|
+
} else {
|
|
282
|
+
result = [spacerLine, ...core, ...imageLines]
|
|
283
|
+
}
|
|
284
|
+
;(this as any)[TOOL_RENDER_CACHE] = { width, mode: toolBackgroundMode, lines: result }
|
|
285
|
+
return result
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
proto[PATCH_FLAG] = true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function summarizeText(text: string, max = 60): string {
|
|
292
|
+
const oneLine = text.replace(/\n/g, " ").trim()
|
|
293
|
+
if (oneLine.length <= max) return oneLine
|
|
294
|
+
return `${oneLine.slice(0, Math.max(0, max - 3))}...`
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function hashText(text: string): string {
|
|
298
|
+
let hash = 2166136261
|
|
299
|
+
for (let i = 0; i < text.length; i++) {
|
|
300
|
+
hash ^= text.charCodeAt(i)
|
|
301
|
+
hash = Math.imul(hash, 16777619)
|
|
302
|
+
}
|
|
303
|
+
return (hash >>> 0).toString(36)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function clearToolRenderCache(value: unknown): void {
|
|
307
|
+
if (!value || typeof value !== "object") return
|
|
308
|
+
delete (value as any)[TOOL_RENDER_CACHE]
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function unrefTimer(timer: ReturnType<typeof setTimeout> | null | undefined): void {
|
|
312
|
+
;(timer as any)?.unref?.()
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const TOOL_EXECUTION_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-tool-execution")
|
|
316
|
+
const WORKED_DURATION_KEY = "_piClaudeStyleWorkedDurationMs"
|
|
317
|
+
const WORKED_START_KEY = "_piClaudeStyleWorkedStartMs"
|
|
318
|
+
const ASSISTANT_MESSAGE_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-assistant-message-render")
|
|
319
|
+
// OSC 133 zone markers applied by AssistantMessageComponent.render() — must be
|
|
320
|
+
// reattached to the last line after we append the duration widget.
|
|
321
|
+
const OSC133_ZONE_END = "\x1b]133;B\x07"
|
|
322
|
+
const OSC133_ZONE_FINAL = "\x1b]133;C\x07"
|
|
323
|
+
const OSC133_ZONE_SUFFIX = OSC133_ZONE_END + OSC133_ZONE_FINAL
|
|
324
|
+
// WORKED_LINE_FG is theme-derived (from "muted") when themeAdaptive is on.
|
|
325
|
+
let WORKED_LINE_FG = "\x1b[38;2;140;140;140m"
|
|
326
|
+
let currentAgentWorkStartMs: number | undefined
|
|
327
|
+
let currentAssistantMessageStartMs: number | undefined
|
|
328
|
+
|
|
329
|
+
function formatWorkedDuration(ms: number): string {
|
|
330
|
+
const safeMs = Math.max(0, Number.isFinite(ms) ? ms : 0)
|
|
331
|
+
if (safeMs < 60_000) {
|
|
332
|
+
return `${Math.max(0, Math.floor(safeMs / 1000))}s`
|
|
333
|
+
}
|
|
334
|
+
let days = Math.floor(safeMs / 86_400_000)
|
|
335
|
+
let hours = Math.floor((safeMs % 86_400_000) / 3_600_000)
|
|
336
|
+
let minutes = Math.floor((safeMs % 3_600_000) / 60_000)
|
|
337
|
+
let seconds = Math.round((safeMs % 60_000) / 1000)
|
|
338
|
+
if (seconds === 60) {
|
|
339
|
+
seconds = 0
|
|
340
|
+
minutes++
|
|
341
|
+
}
|
|
342
|
+
if (minutes === 60) {
|
|
343
|
+
minutes = 0
|
|
344
|
+
hours++
|
|
345
|
+
}
|
|
346
|
+
if (hours === 24) {
|
|
347
|
+
hours = 0
|
|
348
|
+
days++
|
|
349
|
+
}
|
|
350
|
+
if (days > 0) return `${days}d ${hours}h ${minutes}m`
|
|
351
|
+
if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`
|
|
352
|
+
return `${minutes}m ${seconds}s`
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Returns elapsed milliseconds for a tool call.
|
|
357
|
+
*
|
|
358
|
+
* Note: `ctx.state` is the component's `rendererState` — the upstream
|
|
359
|
+
* framework's `getRenderContext` method aliases them via
|
|
360
|
+
* `state: this.rendererState`.
|
|
361
|
+
*/
|
|
362
|
+
export function getToolElapsedMs(ctx: any): number {
|
|
363
|
+
const startedAt = ctx?.state?._executionStartedAt
|
|
364
|
+
if (!startedAt) return 0
|
|
365
|
+
const endedAt = ctx?.state?._executionEndedAt
|
|
366
|
+
return (endedAt ?? Date.now()) - startedAt
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export function formatToolTimer(elapsedMs: number): string | undefined {
|
|
370
|
+
if (elapsedMs <= 0) return undefined
|
|
371
|
+
return formatDuration(elapsedMs)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// One space of indent — aligns the ✻ glyph with the assistant message body.
|
|
375
|
+
const WORKED_DURATION_INDENT = " "
|
|
376
|
+
|
|
377
|
+
function inlineWorkedDurationText(ms: number): string {
|
|
378
|
+
return `${WORKED_DURATION_INDENT}${WORKED_LINE_FG}✻ Worked for ${formatWorkedDuration(ms)}${RESET}`
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function patchAssistantMessageRender(): void {
|
|
382
|
+
const proto = AssistantMessageComponent.prototype as any
|
|
383
|
+
if (proto[ASSISTANT_MESSAGE_PATCH_FLAG]) return
|
|
384
|
+
const originalRender = proto.render
|
|
385
|
+
if (typeof originalRender !== "function") return
|
|
386
|
+
proto.render = function patchedAssistantMessageRender(width: number) {
|
|
387
|
+
const lines: string[] = originalRender.call(this, width)
|
|
388
|
+
if (!Array.isArray(lines) || lines.length === 0) return lines
|
|
389
|
+
const message = (this as any).lastMessage
|
|
390
|
+
const durationMs = message?.[WORKED_DURATION_KEY]
|
|
391
|
+
if (typeof durationMs !== "number" || durationMs <= 0) return lines
|
|
392
|
+
// The original render() appends OSC 133 zone markers to the last line
|
|
393
|
+
// (B = command end, C = command output). Strip them off, push the widget
|
|
394
|
+
// line, then reattach so the zone still brackets the full message.
|
|
395
|
+
const lastIdx = lines.length - 1
|
|
396
|
+
const widgetLine = inlineWorkedDurationText(durationMs)
|
|
397
|
+
if (lines[lastIdx].includes(OSC133_ZONE_END)) {
|
|
398
|
+
lines[lastIdx] = lines[lastIdx].replace(OSC133_ZONE_SUFFIX, "")
|
|
399
|
+
lines.push("", widgetLine)
|
|
400
|
+
lines[lines.length - 1] += OSC133_ZONE_SUFFIX
|
|
401
|
+
} else {
|
|
402
|
+
lines.push("", widgetLine)
|
|
403
|
+
}
|
|
404
|
+
return lines
|
|
405
|
+
}
|
|
406
|
+
proto[ASSISTANT_MESSAGE_PATCH_FLAG] = true
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// OSC 133 zone markers that UserMessageComponent prepends/appends for shell integration.
|
|
410
|
+
// A one-line message can start with multiple markers because the first and last
|
|
411
|
+
// rendered lines are the same physical line.
|
|
412
|
+
const OSC133_MARKER_RE = /^(?:\x1b\]133;[ABC]\x07)+/
|
|
413
|
+
|
|
414
|
+
export function splitLeadingOsc133Markers(line: string): { markers: string; rest: string } {
|
|
415
|
+
const match = line.match(OSC133_MARKER_RE)
|
|
416
|
+
if (!match) return { markers: "", rest: line }
|
|
417
|
+
const markers = match[0]
|
|
418
|
+
return { markers, rest: line.slice(markers.length) }
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export function patchUserMessageRender(): void {
|
|
422
|
+
const proto = UserMessageComponent.prototype as any
|
|
423
|
+
if (proto[USER_MESSAGE_PATCH_FLAG]) return
|
|
424
|
+
const originalRender = proto.render
|
|
425
|
+
if (typeof originalRender !== "function") return
|
|
426
|
+
proto.render = function patchedUserMessageRender(width: number) {
|
|
427
|
+
const box = (this as any).contentBox
|
|
428
|
+
if (box) {
|
|
429
|
+
// Remove the ▍ stroke and blank padding lines. paddingX=0 lets content
|
|
430
|
+
// render at full width; we prepend the prefix and truncate explicitly.
|
|
431
|
+
box.bgFn = null
|
|
432
|
+
box.paddingY = 0
|
|
433
|
+
box.paddingX = 0
|
|
434
|
+
box.invalidateCache?.()
|
|
435
|
+
}
|
|
436
|
+
const theme = _themePaletteCacheTheme as any
|
|
437
|
+
const glyph = typeof theme?.fg === "function" ? theme.fg("accent", "❯") : "❯"
|
|
438
|
+
const prefix = ` ${glyph} `
|
|
439
|
+
const prefixW = visibleWidth(prefix)
|
|
440
|
+
// Render content narrower so all lines fit when we prepend the indent.
|
|
441
|
+
const innerWidth = Math.max(1, width - prefixW)
|
|
442
|
+
const lines: string[] = originalRender.call(this, innerWidth)
|
|
443
|
+
if (!Array.isArray(lines) || lines.length === 0) return lines
|
|
444
|
+
const indent = " ".repeat(prefixW)
|
|
445
|
+
const hasBg = typeof theme?.bg === "function"
|
|
446
|
+
for (let i = 0; i < lines.length; i++) {
|
|
447
|
+
const linePrefix = i === 0 ? prefix : indent
|
|
448
|
+
const { markers, rest } = i === 0 ? splitLeadingOsc133Markers(lines[0]) : { markers: "", rest: lines[i] }
|
|
449
|
+
const composed = linePrefix + rest
|
|
450
|
+
const pad = Math.max(0, width - visibleWidth(composed))
|
|
451
|
+
const styled = hasBg ? theme.bg("userMessageBg", composed + " ".repeat(pad)) : composed
|
|
452
|
+
lines[i] = markers + styled
|
|
453
|
+
}
|
|
454
|
+
return lines
|
|
455
|
+
}
|
|
456
|
+
proto[USER_MESSAGE_PATCH_FLAG] = true
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export function patchToolRenderCacheInvalidation(): void {
|
|
460
|
+
const proto = ToolExecutionComponent.prototype as any
|
|
461
|
+
if (proto[TOOL_CACHE_PATCH_FLAG]) return
|
|
462
|
+
|
|
463
|
+
const methods = [
|
|
464
|
+
"updateDisplay",
|
|
465
|
+
"updateArgs",
|
|
466
|
+
"markExecutionStarted",
|
|
467
|
+
"setArgsComplete",
|
|
468
|
+
"updateResult",
|
|
469
|
+
"setExpanded",
|
|
470
|
+
"setShowImages",
|
|
471
|
+
"setImageWidthCells",
|
|
472
|
+
"invalidate",
|
|
473
|
+
]
|
|
474
|
+
|
|
475
|
+
for (const method of methods) {
|
|
476
|
+
const original = proto[method]
|
|
477
|
+
if (typeof original !== "function") continue
|
|
478
|
+
proto[method] = function patchedToolMutation(...args: any[]) {
|
|
479
|
+
clearToolRenderCache(this)
|
|
480
|
+
if (method === "markExecutionStarted" && !this.rendererState._executionStartedAt) {
|
|
481
|
+
this.rendererState._executionStartedAt = Date.now()
|
|
482
|
+
}
|
|
483
|
+
if (
|
|
484
|
+
method === "updateResult" &&
|
|
485
|
+
!this.rendererState._executionEndedAt &&
|
|
486
|
+
args[1] !== true
|
|
487
|
+
) {
|
|
488
|
+
this.rendererState._executionEndedAt = Date.now()
|
|
489
|
+
}
|
|
490
|
+
const result = original.apply(this, args)
|
|
491
|
+
clearToolRenderCache(this)
|
|
492
|
+
return result
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
proto[TOOL_CACHE_PATCH_FLAG] = true
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function deleteRenderedKittyImages(component: any): void {
|
|
500
|
+
if (
|
|
501
|
+
!process.stdout.isTTY ||
|
|
502
|
+
getCapabilities().images !== "kitty" ||
|
|
503
|
+
!Array.isArray(component.imageComponents) ||
|
|
504
|
+
component.imageComponents.length === 0
|
|
505
|
+
)
|
|
506
|
+
return
|
|
507
|
+
try {
|
|
508
|
+
process.stdout.write(deleteAllKittyImages())
|
|
509
|
+
} catch {
|
|
510
|
+
/* noop */
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function removeImageChildren(component: any): void {
|
|
515
|
+
deleteRenderedKittyImages(component)
|
|
516
|
+
const children = [
|
|
517
|
+
...(Array.isArray(component.imageComponents) ? component.imageComponents : []),
|
|
518
|
+
...(Array.isArray(component.imageSpacers) ? component.imageSpacers : []),
|
|
519
|
+
]
|
|
520
|
+
for (const child of children) {
|
|
521
|
+
try {
|
|
522
|
+
component.removeChild?.(child)
|
|
523
|
+
} catch {
|
|
524
|
+
/* noop */
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
component.imageComponents = []
|
|
528
|
+
component.imageSpacers = []
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function patchReadImageExpansion(): void {
|
|
532
|
+
const proto = ToolExecutionComponent.prototype as any
|
|
533
|
+
if (proto[TOOL_IMAGE_EXPAND_PATCH_FLAG]) return
|
|
534
|
+
const originalUpdateDisplay = proto.updateDisplay
|
|
535
|
+
if (typeof originalUpdateDisplay !== "function") return
|
|
536
|
+
proto.updateDisplay = function patchedReadImageUpdateDisplay(...args: any[]) {
|
|
537
|
+
const result = originalUpdateDisplay.apply(this, args)
|
|
538
|
+
const hasImage =
|
|
539
|
+
Array.isArray(this.result?.content) && this.result.content.some((block: any) => block?.type === "image")
|
|
540
|
+
if (this.toolName === "read" && hasImage && this.expanded !== true) {
|
|
541
|
+
removeImageChildren(this)
|
|
542
|
+
clearToolRenderCache(this)
|
|
543
|
+
}
|
|
544
|
+
return result
|
|
545
|
+
}
|
|
546
|
+
proto[TOOL_IMAGE_EXPAND_PATCH_FLAG] = true
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function patchToolExecutionRenderers(): void {
|
|
550
|
+
const proto = ToolExecutionComponent.prototype as any
|
|
551
|
+
if (proto[TOOL_EXECUTION_PATCH_FLAG]) return
|
|
552
|
+
|
|
553
|
+
const originalHasRendererDefinition = proto.hasRendererDefinition
|
|
554
|
+
const originalGetCallRenderer = proto.getCallRenderer
|
|
555
|
+
const originalGetResultRenderer = proto.getResultRenderer
|
|
556
|
+
|
|
557
|
+
if (typeof originalHasRendererDefinition === "function") {
|
|
558
|
+
proto.hasRendererDefinition = function patchedHasRendererDefinition() {
|
|
559
|
+
return originalHasRendererDefinition.call(this) || shouldUseGenericToolRenderer(this?.toolName)
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
proto.getCallRenderer = function patchedGetCallRenderer() {
|
|
564
|
+
const toolName = typeof this?.toolName === "string" ? this.toolName : ""
|
|
565
|
+
if (toolName === "apply_patch") {
|
|
566
|
+
return (args: any, theme: Theme, ctx: any) =>
|
|
567
|
+
renderApplyPatchCall(args, theme, ctx, (path: string) => shortPath(ctx.cwd ?? process.cwd(), path))
|
|
568
|
+
}
|
|
569
|
+
if (shouldUseGenericToolRenderer(toolName)) {
|
|
570
|
+
return (args: any, theme: Theme, ctx: any) => renderGenericToolCall(toolName, args, theme, ctx)
|
|
571
|
+
}
|
|
572
|
+
return typeof originalGetCallRenderer === "function" ? originalGetCallRenderer.call(this) : undefined
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
proto.getResultRenderer = function patchedGetResultRenderer() {
|
|
576
|
+
const toolName = typeof this?.toolName === "string" ? this.toolName : ""
|
|
577
|
+
if (toolName === "apply_patch") {
|
|
578
|
+
return (result: any, options: any, theme: Theme, ctx: any) =>
|
|
579
|
+
renderApplyPatchResult({ content: result.content, details: result.details }, options.isPartial, theme, ctx)
|
|
580
|
+
}
|
|
581
|
+
if (shouldUseGenericToolRenderer(toolName)) {
|
|
582
|
+
return (result: any, options: any, theme: Theme, ctx: any) =>
|
|
583
|
+
renderGenericToolResult(toolName, result, options, theme, ctx)
|
|
584
|
+
}
|
|
585
|
+
return typeof originalGetResultRenderer === "function" ? originalGetResultRenderer.call(this) : undefined
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
proto[TOOL_EXECUTION_PATCH_FLAG] = true
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
function shortPath(cwd: string, filePath: string): string {
|
|
592
|
+
if (!filePath) return ""
|
|
593
|
+
const rel = relative(cwd, filePath)
|
|
594
|
+
if (!rel.startsWith("..") && !rel.startsWith("/")) return rel || "."
|
|
595
|
+
const home = process.env.HOME ?? ""
|
|
596
|
+
return home ? filePath.replace(home, "~") : filePath
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// ---------------------------------------------------------------------------
|
|
600
|
+
// Status dot — flickers green/gray while pending
|
|
601
|
+
// ---------------------------------------------------------------------------
|
|
602
|
+
|
|
603
|
+
export function toolHeader(tool: string, summary: string, theme: Theme, prefix = "", timer?: string): string {
|
|
604
|
+
applyThemePaletteIfNeeded(theme)
|
|
605
|
+
const label = theme.fg("toolTitle", theme.bold(tool))
|
|
606
|
+
let result = `${prefix}${label}`
|
|
607
|
+
if (summary) result += ` ${WRAP_MARK}${theme.fg("accent", summary)}`
|
|
608
|
+
if (timer) result += ` ${theme.fg("dim", timer)}`
|
|
609
|
+
return result
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
function shouldRevealCallArgs(ctx: any): boolean {
|
|
614
|
+
if (ctx?.argsComplete === true || ctx?.executionStarted === true) return true
|
|
615
|
+
const args = ctx?.args
|
|
616
|
+
if (!args || typeof args !== "object") return false
|
|
617
|
+
return Object.keys(args).some((key) => args[key] !== undefined && args[key] !== null && args[key] !== "")
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function stableCallSummary(ctx: any, key: string, build: () => string, reveal = shouldRevealCallArgs(ctx)): string {
|
|
621
|
+
const state = ctx?.state
|
|
622
|
+
const cached = state?.[key]
|
|
623
|
+
const completeKey = `${key}Complete`
|
|
624
|
+
if (!reveal) return typeof cached === "string" ? cached : ""
|
|
625
|
+
if (ctx?.argsComplete === true && state?.[completeKey] === true && typeof cached === "string") return cached
|
|
626
|
+
if (!shouldRevealCallArgs(ctx) && typeof cached === "string" && cached) return cached
|
|
627
|
+
const summary = build()
|
|
628
|
+
if (state) {
|
|
629
|
+
state[key] = summary
|
|
630
|
+
if (ctx?.argsComplete === true) state[completeKey] = true
|
|
631
|
+
else delete state[completeKey]
|
|
632
|
+
}
|
|
633
|
+
return summary
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function hasOwnArg(args: any, key: string): boolean {
|
|
637
|
+
return !!args && Object.prototype.hasOwnProperty.call(args, key)
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function fileExistsForTool(cwd: string, filePath: string): boolean {
|
|
641
|
+
if (!filePath) return false
|
|
642
|
+
try {
|
|
643
|
+
return existsSync(resolve(cwd, filePath))
|
|
644
|
+
} catch {
|
|
645
|
+
return false
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const WRITE_EXISTED_BEFORE = new Map<string, boolean>()
|
|
650
|
+
|
|
651
|
+
function getWriteWasNewFile(
|
|
652
|
+
ctx: any,
|
|
653
|
+
cwd: string,
|
|
654
|
+
filePath: string,
|
|
655
|
+
reveal = shouldRevealCallArgs(ctx),
|
|
656
|
+
): boolean | undefined {
|
|
657
|
+
if (typeof ctx?.state?._writeWasNewFile === "boolean") return ctx.state._writeWasNewFile
|
|
658
|
+
if (!filePath || !reveal) return undefined
|
|
659
|
+
const existedBefore = typeof ctx?.toolCallId === "string" ? WRITE_EXISTED_BEFORE.get(ctx.toolCallId) : undefined
|
|
660
|
+
const wasNew = existedBefore === undefined ? !fileExistsForTool(cwd, filePath) : !existedBefore
|
|
661
|
+
if (ctx?.state) ctx.state._writeWasNewFile = wasNew
|
|
662
|
+
return wasNew
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function toolStatusDot(ctx: any, theme: Theme): string {
|
|
666
|
+
if (!ctx.isPartial && !ctx.isError) return `${theme.fg("success", "●")} `
|
|
667
|
+
if (!ctx.isPartial && ctx.isError) return `${theme.fg("error", "●")} `
|
|
668
|
+
return `${blinkDot(ctx, theme)} `
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// ---------------------------------------------------------------------------
|
|
672
|
+
// Branch connector — visual tree from header to output
|
|
673
|
+
// ---------------------------------------------------------------------------
|
|
674
|
+
|
|
675
|
+
function branchIndent(text: string, continued = false): string {
|
|
676
|
+
const prefix = continued ? `${TOOL_RULE}│${TRANSPARENT_RESET} ` : " "
|
|
677
|
+
return `${prefix}${WRAP_MARK}${text}`
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function branchLead(text: string, continued = false): string {
|
|
681
|
+
return `${TOOL_RULE}${continued ? "├─" : "└─"}${TRANSPARENT_RESET} ${WRAP_MARK}${text}`
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function withBranch(content: string, _theme: Theme, _isError = false, continued = false): string {
|
|
685
|
+
if (!content || !content.trim()) return ""
|
|
686
|
+
const lines = content.split("\n")
|
|
687
|
+
const first = lines[0] ?? ""
|
|
688
|
+
if (lines.length === 1) return branchLead(first, continued)
|
|
689
|
+
const rest = lines.slice(1).map((line) => branchIndent(line, continued))
|
|
690
|
+
return `${branchLead(first, continued)}\n${rest.join("\n")}`
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function withFinalBranchBlock(content: string): string {
|
|
694
|
+
if (!content || !content.trim()) return ""
|
|
695
|
+
const lines = content.split("\n")
|
|
696
|
+
const first = lines[0] ?? ""
|
|
697
|
+
if (lines.length === 1) return branchLead(first, false)
|
|
698
|
+
const middle = lines.slice(1, -1).map((line) => branchIndent(line, true))
|
|
699
|
+
const last = lines[lines.length - 1] ?? ""
|
|
700
|
+
return [branchLead(first, true), ...middle, branchLead(last, false)].join("\n")
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function indentBranchBlock(block: string): string {
|
|
704
|
+
return block
|
|
705
|
+
.split("\n")
|
|
706
|
+
.map((line) => (line ? ` ${line}` : line))
|
|
707
|
+
.join("\n")
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ---------------------------------------------------------------------------
|
|
711
|
+
// Blink timer for partial (running) states
|
|
712
|
+
// ---------------------------------------------------------------------------
|
|
713
|
+
|
|
714
|
+
// ---------------------------------------------------------------------------
|
|
715
|
+
// Global blink timer — single timer invalidates all active contexts
|
|
716
|
+
// ---------------------------------------------------------------------------
|
|
717
|
+
|
|
718
|
+
const MAX_BLINKING_TOOLS = 5
|
|
719
|
+
const BLINK_INTERVAL_MS = 500
|
|
720
|
+
|
|
721
|
+
type BlinkEntry = { key: any; order: number; invalidate: () => void }
|
|
722
|
+
|
|
723
|
+
const _blinkContexts = new Map<any, BlinkEntry>()
|
|
724
|
+
let _globalBlinkTimer: ReturnType<typeof setTimeout> | null = null
|
|
725
|
+
let _blinkOrder = 0
|
|
726
|
+
let _globalBlinkPhase = true
|
|
727
|
+
|
|
728
|
+
function getBlinkIntervalMs(): number {
|
|
729
|
+
return BLINK_INTERVAL_MS
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
function getBlinkKey(ctx: any): any {
|
|
733
|
+
return ctx?.state ?? ctx
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function getBlinkingEntries(): BlinkEntry[] {
|
|
737
|
+
return [..._blinkContexts.values()].sort((a, b) => b.order - a.order).slice(0, MAX_BLINKING_TOOLS)
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function updateBlinkActiveStates(): void {
|
|
741
|
+
const activeSet = new Set(getBlinkingEntries().map((entry) => entry.key))
|
|
742
|
+
for (const entry of _blinkContexts.values()) {
|
|
743
|
+
const active = activeSet.has(entry.key)
|
|
744
|
+
if (entry.key?._blinkActive !== active) {
|
|
745
|
+
entry.key._blinkActive = active
|
|
746
|
+
try {
|
|
747
|
+
entry.invalidate()
|
|
748
|
+
} catch {
|
|
749
|
+
/* noop */
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
function _scheduleGlobalBlinkTimer(): void {
|
|
756
|
+
if (_globalBlinkTimer) return
|
|
757
|
+
const intervalMs = getBlinkIntervalMs()
|
|
758
|
+
if (_blinkContexts.size === 0) return
|
|
759
|
+
_globalBlinkTimer = setTimeout(() => {
|
|
760
|
+
_globalBlinkTimer = null
|
|
761
|
+
if (_blinkContexts.size === 0) {
|
|
762
|
+
updateBlinkActiveStates()
|
|
763
|
+
return
|
|
764
|
+
}
|
|
765
|
+
_globalBlinkPhase = !_globalBlinkPhase
|
|
766
|
+
for (const entry of getBlinkingEntries()) {
|
|
767
|
+
try {
|
|
768
|
+
entry.invalidate()
|
|
769
|
+
} catch {
|
|
770
|
+
/* noop */
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
_scheduleGlobalBlinkTimer()
|
|
774
|
+
}, intervalMs)
|
|
775
|
+
unrefTimer(_globalBlinkTimer)
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function _stopGlobalBlinkTimerIfEmpty(): void {
|
|
779
|
+
if (_globalBlinkTimer && _blinkContexts.size === 0) {
|
|
780
|
+
clearTimeout(_globalBlinkTimer)
|
|
781
|
+
_globalBlinkTimer = null
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function setupBlinkTimer(ctx: any): void {
|
|
786
|
+
const key = getBlinkKey(ctx)
|
|
787
|
+
if (!key) return
|
|
788
|
+
const invalidate = typeof ctx?.invalidate === "function" ? () => ctx.invalidate() : () => {}
|
|
789
|
+
const existing = _blinkContexts.get(key)
|
|
790
|
+
if (existing) {
|
|
791
|
+
// Already tracked — just refresh the invalidate fn, skip expensive recalc
|
|
792
|
+
existing.invalidate = invalidate
|
|
793
|
+
return
|
|
794
|
+
}
|
|
795
|
+
_blinkContexts.set(key, { key, order: ++_blinkOrder, invalidate })
|
|
796
|
+
key._blinkActive = false
|
|
797
|
+
updateBlinkActiveStates()
|
|
798
|
+
_stopGlobalBlinkTimerIfEmpty()
|
|
799
|
+
_scheduleGlobalBlinkTimer()
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function clearBlinkTimer(ctx: any): void {
|
|
803
|
+
const key = getBlinkKey(ctx)
|
|
804
|
+
if (!key) return
|
|
805
|
+
_blinkContexts.delete(key)
|
|
806
|
+
key._blinkActive = false
|
|
807
|
+
updateBlinkActiveStates()
|
|
808
|
+
_stopGlobalBlinkTimerIfEmpty()
|
|
809
|
+
_scheduleGlobalBlinkTimer()
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
function blinkDot(ctx: any, theme: Theme): string {
|
|
813
|
+
setupBlinkTimer(ctx)
|
|
814
|
+
const key = getBlinkKey(ctx)
|
|
815
|
+
if (key?._blinkActive !== true) return theme.fg("muted", "○")
|
|
816
|
+
return _globalBlinkPhase ? theme.fg("success", "●") : theme.fg("muted", "○")
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// ---------------------------------------------------------------------------
|
|
820
|
+
// File icons — Nerd Font glyphs (requires Nerd Font terminal)
|
|
821
|
+
// ---------------------------------------------------------------------------
|
|
822
|
+
|
|
823
|
+
const NF_DIR = `\x1b[38;2;100;140;220m\ue5ff\x1b[0m`
|
|
824
|
+
const NF_DEFAULT = `\x1b[38;2;80;80;80m\uf15b\x1b[0m`
|
|
825
|
+
|
|
826
|
+
const EXT_ICON: Record<string, string> = {
|
|
827
|
+
ts: `\x1b[38;2;49;120;198m\ue628\x1b[0m`,
|
|
828
|
+
tsx: `\x1b[38;2;49;120;198m\ue7ba\x1b[0m`,
|
|
829
|
+
js: `\x1b[38;2;241;224;90m\ue74e\x1b[0m`,
|
|
830
|
+
jsx: `\x1b[38;2;97;218;251m\ue7ba\x1b[0m`,
|
|
831
|
+
py: `\x1b[38;2;55;118;171m\ue73c\x1b[0m`,
|
|
832
|
+
rs: `\x1b[38;2;222;165;132m\ue7a8\x1b[0m`,
|
|
833
|
+
go: `\x1b[38;2;0;173;216m\ue724\x1b[0m`,
|
|
834
|
+
java: `\x1b[38;2;204;62;68m\ue738\x1b[0m`,
|
|
835
|
+
rb: `\x1b[38;2;204;52;45m\ue739\x1b[0m`,
|
|
836
|
+
swift: `\x1b[38;2;255;172;77m\ue755\x1b[0m`,
|
|
837
|
+
c: `\x1b[38;2;85;154;211m\ue61e\x1b[0m`,
|
|
838
|
+
cpp: `\x1b[38;2;85;154;211m\ue61d\x1b[0m`,
|
|
839
|
+
html: `\x1b[38;2;228;77;38m\ue736\x1b[0m`,
|
|
840
|
+
css: `\x1b[38;2;66;165;245m\ue749\x1b[0m`,
|
|
841
|
+
scss: `\x1b[38;2;207;100;154m\ue749\x1b[0m`,
|
|
842
|
+
vue: `\x1b[38;2;65;184;131m\ue6a0\x1b[0m`,
|
|
843
|
+
svelte: `\x1b[38;2;255;62;0m\ue697\x1b[0m`,
|
|
844
|
+
json: `\x1b[38;2;241;224;90m\ue60b\x1b[0m`,
|
|
845
|
+
yaml: `\x1b[38;2;160;116;196m\ue6a8\x1b[0m`,
|
|
846
|
+
yml: `\x1b[38;2;160;116;196m\ue6a8\x1b[0m`,
|
|
847
|
+
toml: `\x1b[38;2;160;116;196m\ue6b2\x1b[0m`,
|
|
848
|
+
md: `\x1b[38;2;66;165;245m\ue73e\x1b[0m`,
|
|
849
|
+
sh: `\x1b[38;2;137;180;130m\ue795\x1b[0m`,
|
|
850
|
+
bash: `\x1b[38;2;137;180;130m\ue795\x1b[0m`,
|
|
851
|
+
zsh: `\x1b[38;2;137;180;130m\ue795\x1b[0m`,
|
|
852
|
+
lua: `\x1b[38;2;81;160;207m\ue620\x1b[0m`,
|
|
853
|
+
php: `\x1b[38;2;137;147;186m\ue73d\x1b[0m`,
|
|
854
|
+
sql: `\x1b[38;2;218;218;218m\ue706\x1b[0m`,
|
|
855
|
+
xml: `\x1b[38;2;228;77;38m\ue619\x1b[0m`,
|
|
856
|
+
graphql: `\x1b[38;2;224;51;144m\ue662\x1b[0m`,
|
|
857
|
+
dockerfile: `\x1b[38;2;56;152;236m\ue7b0\x1b[0m`,
|
|
858
|
+
lock: `\x1b[38;2;130;130;130m\uf023\x1b[0m`,
|
|
859
|
+
png: `\x1b[38;2;160;116;196m\uf1c5\x1b[0m`,
|
|
860
|
+
jpg: `\x1b[38;2;160;116;196m\uf1c5\x1b[0m`,
|
|
861
|
+
svg: `\x1b[38;2;255;180;50m\uf1c5\x1b[0m`,
|
|
862
|
+
gif: `\x1b[38;2;160;116;196m\uf1c5\x1b[0m`,
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const NAME_ICON: Record<string, string> = {
|
|
866
|
+
"package.json": `\x1b[38;2;137;180;130m\ue71e\x1b[0m`,
|
|
867
|
+
"tsconfig.json": `\x1b[38;2;49;120;198m\ue628\x1b[0m`,
|
|
868
|
+
".gitignore": `\x1b[38;2;222;165;132m\ue702\x1b[0m`,
|
|
869
|
+
dockerfile: `\x1b[38;2;56;152;236m\ue7b0\x1b[0m`,
|
|
870
|
+
makefile: `\x1b[38;2;130;130;130m\ue615\x1b[0m`,
|
|
871
|
+
"readme.md": `\x1b[38;2;66;165;245m\ue73e\x1b[0m`,
|
|
872
|
+
license: `\x1b[38;2;218;218;218m\ue60a\x1b[0m`,
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
function fileIcon(fp: string): string {
|
|
876
|
+
const base = fp.split("/").pop()?.toLowerCase() ?? ""
|
|
877
|
+
if (NAME_ICON[base]) return `${NAME_ICON[base]} `
|
|
878
|
+
const ext = base.includes(".") ? (base.split(".").pop() ?? "") : ""
|
|
879
|
+
return EXT_ICON[ext] ? `${EXT_ICON[ext]} ` : `${NF_DEFAULT} `
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
function dirIcon(): string {
|
|
883
|
+
return `${NF_DIR} `
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
function lineCount(text: string): number {
|
|
887
|
+
if (!text) return 0
|
|
888
|
+
return text.split("\n").length
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
function padToWidth(line: string, width: number): string {
|
|
892
|
+
const padding = Math.max(0, width - visibleWidth(line))
|
|
893
|
+
return `${line}${" ".repeat(padding)}`
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
function markedContinuationPrefix(prefix: string): string {
|
|
897
|
+
const plain = stripAnsi(prefix)
|
|
898
|
+
const branchMatch = /^(\s*)(│ {2}|├─ |└─ )/.exec(plain)
|
|
899
|
+
if (branchMatch) {
|
|
900
|
+
const connector = branchMatch[2]
|
|
901
|
+
if (connector === "└─ ") return `${branchMatch[1]} `
|
|
902
|
+
return `${branchMatch[1]}${TOOL_RULE}│${TRANSPARENT_RESET} `
|
|
903
|
+
}
|
|
904
|
+
return " ".repeat(visibleWidth(prefix))
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function wrapMarkedLine(line: string, width: number): string[] {
|
|
908
|
+
const markerIndex = line.indexOf(WRAP_MARK)
|
|
909
|
+
if (markerIndex === -1) return wrapTextWithAnsi(line, width)
|
|
910
|
+
const prefix = line.slice(0, markerIndex)
|
|
911
|
+
const body = line.slice(markerIndex + WRAP_MARK.length)
|
|
912
|
+
const prefixWidth = visibleWidth(prefix)
|
|
913
|
+
const bodyWidth = Math.max(1, width - prefixWidth)
|
|
914
|
+
const wrapped = wrapTextWithAnsi(body, bodyWidth)
|
|
915
|
+
const continuation = markedContinuationPrefix(prefix)
|
|
916
|
+
return wrapped.map((part, index) => (index === 0 ? `${prefix}${part}` : `${continuation}${part}`))
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
class ToolText extends Text {
|
|
920
|
+
private value = ""
|
|
921
|
+
private toolCachedValue?: string
|
|
922
|
+
private toolCachedWidth?: number
|
|
923
|
+
private toolCachedLines?: string[]
|
|
924
|
+
|
|
925
|
+
constructor(text = "") {
|
|
926
|
+
super("", 0, 0)
|
|
927
|
+
this.value = text
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
setText(text: string): void {
|
|
931
|
+
if (this.value === text) return
|
|
932
|
+
this.value = text
|
|
933
|
+
this.invalidate()
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
invalidate(): void {
|
|
937
|
+
this.toolCachedValue = undefined
|
|
938
|
+
this.toolCachedWidth = undefined
|
|
939
|
+
this.toolCachedLines = undefined
|
|
940
|
+
super.invalidate()
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
render(width: number): string[] {
|
|
944
|
+
if (this.toolCachedLines && this.toolCachedValue === this.value && this.toolCachedWidth === width)
|
|
945
|
+
return this.toolCachedLines
|
|
946
|
+
if (!this.value || this.value.trim() === "") {
|
|
947
|
+
this.toolCachedValue = this.value
|
|
948
|
+
this.toolCachedWidth = width
|
|
949
|
+
this.toolCachedLines = []
|
|
950
|
+
return this.toolCachedLines
|
|
951
|
+
}
|
|
952
|
+
const contentWidth = Math.max(1, width)
|
|
953
|
+
const lines = this.value.replace(/\t/g, " ").split("\n")
|
|
954
|
+
const rendered = lines.flatMap((line) => wrapMarkedLine(line, contentWidth)).map((line) => padToWidth(line, width))
|
|
955
|
+
this.toolCachedValue = this.value
|
|
956
|
+
this.toolCachedWidth = width
|
|
957
|
+
this.toolCachedLines = rendered
|
|
958
|
+
return rendered
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
function makeText(last: unknown, text: string): Text {
|
|
963
|
+
const component = last instanceof ToolText ? last : new ToolText()
|
|
964
|
+
component.setText(text)
|
|
965
|
+
return component
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
function previewLimit(): number {
|
|
969
|
+
const value = readSettings().previewLines
|
|
970
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 8
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function expandedPreviewLimit(): number {
|
|
974
|
+
const value = readSettings().expandedPreviewMaxLines
|
|
975
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 4000
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
function bashCollapsedLimit(): number {
|
|
979
|
+
const value = readSettings().bashCollapsedLines
|
|
980
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : 10
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function diffCollapsedLimit(): number {
|
|
984
|
+
const value = readSettings().diffCollapsedLines
|
|
985
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 24
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function collapsedPreviewCount(expanded: boolean, fallback: number): number {
|
|
989
|
+
return expanded ? expandedPreviewLimit() : fallback
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function buildPreviewText(lines: string[], expanded: boolean, theme: Theme, fallbackCollapsed = 8): string {
|
|
993
|
+
if (lines.length === 0) return theme.fg("muted", "(no output)")
|
|
994
|
+
const maxLines = collapsedPreviewCount(expanded, fallbackCollapsed)
|
|
995
|
+
const shown = lines.slice(0, maxLines)
|
|
996
|
+
let text = shown.join("\n")
|
|
997
|
+
const remaining = lines.length - shown.length
|
|
998
|
+
if (remaining > 0) {
|
|
999
|
+
text += `\n${theme.fg("muted", `... (${remaining} more lines${expanded ? "" : " • ctrl+o to expand"})`)}`
|
|
1000
|
+
}
|
|
1001
|
+
if (expanded && lines.length > maxLines) {
|
|
1002
|
+
text += `\n${theme.fg("warning", `(display capped at ${maxLines} lines)`)}`
|
|
1003
|
+
}
|
|
1004
|
+
return text
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// ===========================================================================
|
|
1008
|
+
// Diff rendering — adapted from /tmp/pi-diff
|
|
1009
|
+
// ===========================================================================
|
|
1010
|
+
|
|
1011
|
+
interface DiffPreset {
|
|
1012
|
+
name: string
|
|
1013
|
+
description: string
|
|
1014
|
+
shikiTheme?: string
|
|
1015
|
+
bgAdd?: string
|
|
1016
|
+
bgDel?: string
|
|
1017
|
+
bgAddHighlight?: string
|
|
1018
|
+
bgDelHighlight?: string
|
|
1019
|
+
bgGutterAdd?: string
|
|
1020
|
+
bgGutterDel?: string
|
|
1021
|
+
bgEmpty?: string
|
|
1022
|
+
fgAdd?: string
|
|
1023
|
+
fgDel?: string
|
|
1024
|
+
fgDim?: string
|
|
1025
|
+
fgLnum?: string
|
|
1026
|
+
fgRule?: string
|
|
1027
|
+
fgStripe?: string
|
|
1028
|
+
fgSafeMuted?: string
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
interface DiffUserConfig {
|
|
1032
|
+
diffTheme?: string
|
|
1033
|
+
diffColors?: Record<string, string>
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
const DIFF_PRESETS: Record<string, DiffPreset> = {
|
|
1037
|
+
default: {
|
|
1038
|
+
name: "default",
|
|
1039
|
+
description: "Original pi-diff colors",
|
|
1040
|
+
bgAdd: "#162620",
|
|
1041
|
+
bgDel: "#2d1919",
|
|
1042
|
+
bgAddHighlight: "#234b32",
|
|
1043
|
+
bgDelHighlight: "#502323",
|
|
1044
|
+
bgGutterAdd: "#12201a",
|
|
1045
|
+
bgGutterDel: "#261616",
|
|
1046
|
+
bgEmpty: "#121212",
|
|
1047
|
+
fgDim: "#505050",
|
|
1048
|
+
fgLnum: "#646464",
|
|
1049
|
+
fgRule: "#323232",
|
|
1050
|
+
fgStripe: "#282828",
|
|
1051
|
+
fgSafeMuted: "#8b949e",
|
|
1052
|
+
},
|
|
1053
|
+
midnight: {
|
|
1054
|
+
name: "midnight",
|
|
1055
|
+
description: "Subtle tints for black backgrounds",
|
|
1056
|
+
bgAdd: "#0d1a12",
|
|
1057
|
+
bgDel: "#1a0d0d",
|
|
1058
|
+
bgAddHighlight: "#1a3825",
|
|
1059
|
+
bgDelHighlight: "#381a1a",
|
|
1060
|
+
bgGutterAdd: "#091208",
|
|
1061
|
+
bgGutterDel: "#120908",
|
|
1062
|
+
bgEmpty: "#080808",
|
|
1063
|
+
fgDim: "#404040",
|
|
1064
|
+
fgLnum: "#505050",
|
|
1065
|
+
fgRule: "#282828",
|
|
1066
|
+
fgStripe: "#1e1e1e",
|
|
1067
|
+
fgSafeMuted: "#8b949e",
|
|
1068
|
+
},
|
|
1069
|
+
neon: {
|
|
1070
|
+
name: "neon",
|
|
1071
|
+
description: "Higher contrast backgrounds",
|
|
1072
|
+
bgAdd: "#1a3320",
|
|
1073
|
+
bgDel: "#331a16",
|
|
1074
|
+
bgAddHighlight: "#2d5c3a",
|
|
1075
|
+
bgDelHighlight: "#5c2d2d",
|
|
1076
|
+
bgGutterAdd: "#142818",
|
|
1077
|
+
bgGutterDel: "#28120e",
|
|
1078
|
+
bgEmpty: "#141414",
|
|
1079
|
+
fgDim: "#606060",
|
|
1080
|
+
fgLnum: "#787878",
|
|
1081
|
+
fgRule: "#404040",
|
|
1082
|
+
fgStripe: "#303030",
|
|
1083
|
+
fgSafeMuted: "#9da5ae",
|
|
1084
|
+
},
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
function loadDiffConfig(): DiffUserConfig {
|
|
1088
|
+
const settings = readSettings()
|
|
1089
|
+
return { diffTheme: settings.diffTheme, diffColors: settings.diffColors }
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// 6x6x6 color cube channel values used by pi's 256color fallback.
|
|
1093
|
+
const CUBE_VALUES = [0, 95, 135, 175, 215, 255]
|
|
1094
|
+
|
|
1095
|
+
function xterm256ToRgb(index: number): { r: number; g: number; b: number } | null {
|
|
1096
|
+
if (!Number.isInteger(index) || index < 0 || index > 255) return null
|
|
1097
|
+
if (index < 16) {
|
|
1098
|
+
// Standard 16 ANSI colors — terminal-defined, approximate with VS Code defaults.
|
|
1099
|
+
const basic: Array<[number, number, number]> = [
|
|
1100
|
+
[0, 0, 0],
|
|
1101
|
+
[128, 0, 0],
|
|
1102
|
+
[0, 128, 0],
|
|
1103
|
+
[128, 128, 0],
|
|
1104
|
+
[0, 0, 128],
|
|
1105
|
+
[128, 0, 128],
|
|
1106
|
+
[0, 128, 128],
|
|
1107
|
+
[192, 192, 192],
|
|
1108
|
+
[128, 128, 128],
|
|
1109
|
+
[255, 0, 0],
|
|
1110
|
+
[0, 255, 0],
|
|
1111
|
+
[255, 255, 0],
|
|
1112
|
+
[0, 0, 255],
|
|
1113
|
+
[255, 0, 255],
|
|
1114
|
+
[0, 255, 255],
|
|
1115
|
+
[255, 255, 255],
|
|
1116
|
+
]
|
|
1117
|
+
const [r, g, b] = basic[index]
|
|
1118
|
+
return { r, g, b }
|
|
1119
|
+
}
|
|
1120
|
+
if (index < 232) {
|
|
1121
|
+
const i = index - 16
|
|
1122
|
+
return {
|
|
1123
|
+
r: CUBE_VALUES[Math.floor(i / 36) % 6],
|
|
1124
|
+
g: CUBE_VALUES[Math.floor(i / 6) % 6],
|
|
1125
|
+
b: CUBE_VALUES[i % 6],
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
const level = 8 + (index - 232) * 10
|
|
1129
|
+
return { r: level, g: level, b: level }
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
function parseAnsiRgb(ansi: string): { r: number; g: number; b: number } | null {
|
|
1133
|
+
if (!ansi) return null
|
|
1134
|
+
const esc = "\u001b"
|
|
1135
|
+
// Truecolor: \e[38;2;R;G;Bm or \e[48;2;R;G;Bm
|
|
1136
|
+
const tc = ansi.match(new RegExp(`${esc}\\[(?:38|48);2;(\\d+);(\\d+);(\\d+)m`))
|
|
1137
|
+
if (tc) return { r: +tc[1], g: +tc[2], b: +tc[3] }
|
|
1138
|
+
// 256-color: \e[38;5;Nm or \e[48;5;Nm — happens on Apple Terminal, screen, etc.
|
|
1139
|
+
const idx = ansi.match(new RegExp(`${esc}\\[(?:38|48);5;(\\d+)m`))
|
|
1140
|
+
if (idx) return xterm256ToRgb(+idx[1])
|
|
1141
|
+
return null
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
function hexToBgAnsi(hex: string): string {
|
|
1145
|
+
if (!hex || !/^#[0-9a-fA-F]{6}$/.test(hex)) return ""
|
|
1146
|
+
const r = Number.parseInt(hex.slice(1, 3), 16)
|
|
1147
|
+
const g = Number.parseInt(hex.slice(3, 5), 16)
|
|
1148
|
+
const b = Number.parseInt(hex.slice(5, 7), 16)
|
|
1149
|
+
return `\x1b[48;2;${r};${g};${b}m`
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
function hexToFgAnsi(hex: string): string {
|
|
1153
|
+
if (!hex || !/^#[0-9a-fA-F]{6}$/.test(hex)) return ""
|
|
1154
|
+
const r = Number.parseInt(hex.slice(1, 3), 16)
|
|
1155
|
+
const g = Number.parseInt(hex.slice(3, 5), 16)
|
|
1156
|
+
const b = Number.parseInt(hex.slice(5, 7), 16)
|
|
1157
|
+
return `\x1b[38;2;${r};${g};${b}m`
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// ---------------------------------------------------------------------------
|
|
1161
|
+
// Theme palette extraction — pull RGB from the active pi theme so our
|
|
1162
|
+
// hardcoded greys and accent colors track the user's selected theme.
|
|
1163
|
+
//
|
|
1164
|
+
// `theme.getFgAnsi(name)` / `theme.getBgAnsi(name)` return raw ANSI escapes
|
|
1165
|
+
// (either truecolor or 256color depending on the terminal). We parse those
|
|
1166
|
+
// back into RGB so we can mix tints for diff backgrounds.
|
|
1167
|
+
// ---------------------------------------------------------------------------
|
|
1168
|
+
|
|
1169
|
+
type Rgb = { r: number; g: number; b: number }
|
|
1170
|
+
|
|
1171
|
+
function safeFgAnsi(theme: any, key: string): string | null {
|
|
1172
|
+
try {
|
|
1173
|
+
const ansi = theme?.getFgAnsi?.(key)
|
|
1174
|
+
return typeof ansi === "string" && ansi.length > 0 ? ansi : null
|
|
1175
|
+
} catch {
|
|
1176
|
+
return null
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
function safeBgAnsi(theme: any, key: string): string | null {
|
|
1181
|
+
try {
|
|
1182
|
+
const ansi = theme?.getBgAnsi?.(key)
|
|
1183
|
+
return typeof ansi === "string" && ansi.length > 0 ? ansi : null
|
|
1184
|
+
} catch {
|
|
1185
|
+
return null
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
function themeFgRgb(theme: any, key: string): Rgb | null {
|
|
1190
|
+
const ansi = safeFgAnsi(theme, key)
|
|
1191
|
+
return ansi ? parseAnsiRgb(ansi) : null
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function themeBgRgb(theme: any, key: string): Rgb | null {
|
|
1195
|
+
const ansi = safeBgAnsi(theme, key)
|
|
1196
|
+
return ansi ? parseAnsiRgb(ansi) : null
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// Cache theme identity so we only recompute on theme change. The Theme
|
|
1200
|
+
// object is reused across renders within a single session unless the user
|
|
1201
|
+
// switches themes via the picker.
|
|
1202
|
+
let _themePaletteCacheTheme: unknown = null
|
|
1203
|
+
|
|
1204
|
+
function themeAdaptiveEnabled(): boolean {
|
|
1205
|
+
const settings = readSettings()
|
|
1206
|
+
return settings.themeAdaptive !== false
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
let DIFF_THEME: BundledTheme = (process.env.DIFF_THEME as BundledTheme | undefined) ?? "github-dark"
|
|
1210
|
+
let codeToAnsiLoader: Promise<any> | null = null
|
|
1211
|
+
|
|
1212
|
+
const SPLIT_MIN_WIDTH = 150
|
|
1213
|
+
const SPLIT_MIN_CODE_WIDTH = 60
|
|
1214
|
+
const SPLIT_MAX_WRAP_RATIO = 0.2
|
|
1215
|
+
const SPLIT_MAX_WRAP_LINES = 8
|
|
1216
|
+
const MAX_TERM_WIDTH = 210
|
|
1217
|
+
const DEFAULT_TERM_WIDTH = 200
|
|
1218
|
+
const MAX_PREVIEW_LINES = 60
|
|
1219
|
+
const MAX_RENDER_LINES = 150
|
|
1220
|
+
const MAX_HL_CHARS = 32_000
|
|
1221
|
+
const CACHE_LIMIT = 48
|
|
1222
|
+
const WORD_DIFF_MIN_SIM = 0.15
|
|
1223
|
+
const MAX_WRAP_ROWS_WIDE = 3
|
|
1224
|
+
const MAX_WRAP_ROWS_MED = 2
|
|
1225
|
+
const MAX_WRAP_ROWS_NARROW = 1
|
|
1226
|
+
|
|
1227
|
+
let D_RST = "\x1b[0m"
|
|
1228
|
+
const D_BOLD = "\x1b[1m"
|
|
1229
|
+
const D_DIM = "\x1b[2m"
|
|
1230
|
+
|
|
1231
|
+
// Diff backgrounds — defaults are transparent; autoDeriveBgFromTheme fills them
|
|
1232
|
+
// using pi-tool-display's mix ratios against the theme's toolSuccessBg.
|
|
1233
|
+
let BG_ADD = "\x1b[49m"
|
|
1234
|
+
let BG_DEL = "\x1b[49m"
|
|
1235
|
+
let BG_ADD_W = "\x1b[49m"
|
|
1236
|
+
let BG_DEL_W = "\x1b[49m"
|
|
1237
|
+
let BG_GUTTER_ADD = "\x1b[49m"
|
|
1238
|
+
let BG_GUTTER_DEL = "\x1b[49m"
|
|
1239
|
+
let BG_EMPTY = "\x1b[49m"
|
|
1240
|
+
let BG_BASE = "\x1b[49m"
|
|
1241
|
+
|
|
1242
|
+
let FG_ADD = "\x1b[38;2;100;180;120m"
|
|
1243
|
+
let FG_DEL = "\x1b[38;2;200;100;100m"
|
|
1244
|
+
let FG_DIM = "\x1b[38;2;80;80;80m"
|
|
1245
|
+
let FG_LNUM = "\x1b[38;2;100;100;100m"
|
|
1246
|
+
let FG_RULE = "\x1b[38;2;50;50;50m"
|
|
1247
|
+
let TOOL_RULE = "\x1b[38;2;153;153;153m"
|
|
1248
|
+
let FG_SAFE_MUTED = "\x1b[38;2;139;148;158m"
|
|
1249
|
+
let FG_STRIPE = "\x1b[38;2;40;40;40m"
|
|
1250
|
+
|
|
1251
|
+
let DIVIDER = `${FG_RULE}│${D_RST}`
|
|
1252
|
+
|
|
1253
|
+
interface DiffColors {
|
|
1254
|
+
fgAdd: string
|
|
1255
|
+
fgDel: string
|
|
1256
|
+
fgCtx: string
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
let DEFAULT_DIFF_COLORS: DiffColors = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
|
|
1260
|
+
let autoDerivePending = true
|
|
1261
|
+
let hasExplicitBgConfig = false
|
|
1262
|
+
|
|
1263
|
+
// pi-tool-display tint targets for diff palette derivation
|
|
1264
|
+
const ADDITION_TINT_TARGET = { r: 84, g: 190, b: 118 }
|
|
1265
|
+
const DELETION_TINT_TARGET = { r: 232, g: 95, b: 122 }
|
|
1266
|
+
// Fallback base that matches most dark themes (NOT black)
|
|
1267
|
+
const FALLBACK_BASE_BG = { r: 32, g: 35, b: 42 }
|
|
1268
|
+
const UNIVERSAL_DIFF_ADD_FG = { r: 110, g: 210, b: 130 }
|
|
1269
|
+
const UNIVERSAL_DIFF_DEL_FG = { r: 225, g: 110, b: 110 }
|
|
1270
|
+
|
|
1271
|
+
function mixRgb(
|
|
1272
|
+
a: { r: number; g: number; b: number },
|
|
1273
|
+
b: { r: number; g: number; b: number },
|
|
1274
|
+
ratio: number,
|
|
1275
|
+
): { r: number; g: number; b: number } {
|
|
1276
|
+
return {
|
|
1277
|
+
r: a.r + (b.r - a.r) * ratio,
|
|
1278
|
+
g: a.g + (b.g - a.g) * ratio,
|
|
1279
|
+
b: a.b + (b.b - a.b) * ratio,
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
function rgbToBgAnsi(c: { r: number; g: number; b: number }): string {
|
|
1284
|
+
return `\x1b[48;2;${Math.round(c.r)};${Math.round(c.g)};${Math.round(c.b)}m`
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
function autoDeriveBgFromTheme(theme: any): void {
|
|
1288
|
+
// Diff palette derivation.
|
|
1289
|
+
//
|
|
1290
|
+
// `toolDiffAdded` / `toolDiffRemoved` from the active pi theme give us the
|
|
1291
|
+
// fg accents. The base background is taken from `toolSuccessBg` (close to
|
|
1292
|
+
// the panel color the row will sit on) so the tinted backgrounds blend in
|
|
1293
|
+
// instead of forcing a hardcoded dark hue. Falls back to the universal
|
|
1294
|
+
// dark palette when the theme is unavailable or themeAdaptive=false.
|
|
1295
|
+
const useTheme = themeAdaptiveEnabled() && theme
|
|
1296
|
+
const addFgRgb = (useTheme && themeFgRgb(theme, "toolDiffAdded")) || UNIVERSAL_DIFF_ADD_FG
|
|
1297
|
+
const delFgRgb = (useTheme && themeFgRgb(theme, "toolDiffRemoved")) || UNIVERSAL_DIFF_DEL_FG
|
|
1298
|
+
const base = (useTheme && themeBgRgb(theme, "toolSuccessBg")) || FALLBACK_BASE_BG
|
|
1299
|
+
|
|
1300
|
+
const addTint = mixRgb(addFgRgb, ADDITION_TINT_TARGET, 0.35)
|
|
1301
|
+
const delTint = mixRgb(delFgRgb, DELETION_TINT_TARGET, 0.65)
|
|
1302
|
+
|
|
1303
|
+
FG_ADD = `\x1b[38;2;${Math.round(addFgRgb.r)};${Math.round(addFgRgb.g)};${Math.round(addFgRgb.b)}m`
|
|
1304
|
+
FG_DEL = `\x1b[38;2;${Math.round(delFgRgb.r)};${Math.round(delFgRgb.g)};${Math.round(delFgRgb.b)}m`
|
|
1305
|
+
BG_ADD = rgbToBgAnsi(mixRgb(base, addTint, 0.24))
|
|
1306
|
+
BG_DEL = rgbToBgAnsi(mixRgb(base, delTint, 0.12))
|
|
1307
|
+
BG_ADD_W = rgbToBgAnsi(mixRgb(base, addTint, 0.44))
|
|
1308
|
+
BG_DEL_W = rgbToBgAnsi(mixRgb(base, delTint, 0.26))
|
|
1309
|
+
BG_GUTTER_ADD = rgbToBgAnsi(mixRgb(base, addTint, 0.14))
|
|
1310
|
+
BG_GUTTER_DEL = rgbToBgAnsi(mixRgb(base, delTint, 0.08))
|
|
1311
|
+
BG_EMPTY = TRANSPARENT_BG
|
|
1312
|
+
BG_BASE = TRANSPARENT_BG
|
|
1313
|
+
D_RST = TRANSPARENT_RESET
|
|
1314
|
+
DIVIDER = `${FG_RULE}│${D_RST}`
|
|
1315
|
+
DEFAULT_DIFF_COLORS = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
// Track which palette fields the user explicitly set so theme-derived
|
|
1319
|
+
// updates don't clobber their config.
|
|
1320
|
+
const _explicitFgFields = new Set<"fgAdd" | "fgDel" | "fgDim" | "fgLnum" | "fgRule" | "fgStripe" | "fgSafeMuted">()
|
|
1321
|
+
|
|
1322
|
+
// Original Claude-Code-style palette captured at module-load so we can
|
|
1323
|
+
// restore it when the user toggles themeAdaptive off at runtime.
|
|
1324
|
+
const _claudeStyleDefaults = {
|
|
1325
|
+
BORDER_COLOR: "\x1b[38;5;238m",
|
|
1326
|
+
WORKED_LINE_FG: "\x1b[38;2;140;140;140m",
|
|
1327
|
+
TOOL_RULE: "\x1b[38;2;153;153;153m",
|
|
1328
|
+
FG_DIM: "\x1b[38;2;80;80;80m",
|
|
1329
|
+
FG_LNUM: "\x1b[38;2;100;100;100m",
|
|
1330
|
+
FG_RULE: "\x1b[38;2;50;50;50m",
|
|
1331
|
+
FG_STRIPE: "\x1b[38;2;40;40;40m",
|
|
1332
|
+
FG_SAFE_MUTED: "\x1b[38;2;139;148;158m",
|
|
1333
|
+
FG_ADD: "\x1b[38;2;100;180;120m",
|
|
1334
|
+
FG_DEL: "\x1b[38;2;200;100;100m",
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
function resetThemePalette(): void {
|
|
1338
|
+
BORDER_COLOR = _claudeStyleDefaults.BORDER_COLOR
|
|
1339
|
+
WORKED_LINE_FG = _claudeStyleDefaults.WORKED_LINE_FG
|
|
1340
|
+
TOOL_RULE = _claudeStyleDefaults.TOOL_RULE
|
|
1341
|
+
if (!_explicitFgFields.has("fgDim")) FG_DIM = _claudeStyleDefaults.FG_DIM
|
|
1342
|
+
if (!_explicitFgFields.has("fgLnum")) FG_LNUM = _claudeStyleDefaults.FG_LNUM
|
|
1343
|
+
if (!_explicitFgFields.has("fgRule")) FG_RULE = _claudeStyleDefaults.FG_RULE
|
|
1344
|
+
if (!_explicitFgFields.has("fgStripe")) FG_STRIPE = _claudeStyleDefaults.FG_STRIPE
|
|
1345
|
+
if (!_explicitFgFields.has("fgSafeMuted")) FG_SAFE_MUTED = _claudeStyleDefaults.FG_SAFE_MUTED
|
|
1346
|
+
if (!_explicitFgFields.has("fgAdd")) FG_ADD = _claudeStyleDefaults.FG_ADD
|
|
1347
|
+
if (!_explicitFgFields.has("fgDel")) FG_DEL = _claudeStyleDefaults.FG_DEL
|
|
1348
|
+
DIVIDER = `${FG_RULE}│${D_RST}`
|
|
1349
|
+
DEFAULT_DIFF_COLORS = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
function applyThemePaletteIfNeeded(theme: any): void {
|
|
1353
|
+
if (!theme) return
|
|
1354
|
+
if (!themeAdaptiveEnabled()) return
|
|
1355
|
+
if (_themePaletteCacheTheme === theme) return // already applied for this theme instance
|
|
1356
|
+
_themePaletteCacheTheme = theme
|
|
1357
|
+
|
|
1358
|
+
// Borders (top/bottom outlines, user-message frame, branch rule).
|
|
1359
|
+
const borderMuted = safeFgAnsi(theme, "borderMuted")
|
|
1360
|
+
if (borderMuted) BORDER_COLOR = borderMuted
|
|
1361
|
+
|
|
1362
|
+
// "Worked for Ns" line + thinking-block italics share pi's `muted` color.
|
|
1363
|
+
const muted = safeFgAnsi(theme, "muted")
|
|
1364
|
+
if (muted) WORKED_LINE_FG = muted
|
|
1365
|
+
|
|
1366
|
+
// Tool branch rule (├─ / └─ connectors). Use `dim` if present, else `muted`.
|
|
1367
|
+
const dim = safeFgAnsi(theme, "dim") ?? muted
|
|
1368
|
+
if (dim) TOOL_RULE = dim
|
|
1369
|
+
|
|
1370
|
+
// Diff support text colors. These are user-overridable via diffColors.* so
|
|
1371
|
+
// we only touch the ones not explicitly set.
|
|
1372
|
+
if (!_explicitFgFields.has("fgDim") && muted) FG_DIM = muted
|
|
1373
|
+
if (!_explicitFgFields.has("fgLnum") && muted) FG_LNUM = muted
|
|
1374
|
+
if (!_explicitFgFields.has("fgRule") && borderMuted) FG_RULE = borderMuted
|
|
1375
|
+
if (!_explicitFgFields.has("fgStripe") && borderMuted) FG_STRIPE = borderMuted
|
|
1376
|
+
if (!_explicitFgFields.has("fgSafeMuted") && muted) FG_SAFE_MUTED = muted
|
|
1377
|
+
|
|
1378
|
+
DIVIDER = `${FG_RULE}│${D_RST}`
|
|
1379
|
+
|
|
1380
|
+
// Re-trigger background derivation against the new theme unless the user
|
|
1381
|
+
// set explicit bg overrides via diffTheme/diffColors.
|
|
1382
|
+
if (!hasExplicitBgConfig) {
|
|
1383
|
+
autoDeriveBgFromTheme(theme)
|
|
1384
|
+
autoDerivePending = false
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
function applyDiffPalette(): void {
|
|
1389
|
+
const config = loadDiffConfig()
|
|
1390
|
+
const preset = config.diffTheme ? DIFF_PRESETS[config.diffTheme] : null
|
|
1391
|
+
if (preset) hasExplicitBgConfig = true
|
|
1392
|
+
const overrides = config.diffColors ?? {}
|
|
1393
|
+
if (Object.keys(overrides).length > 0) hasExplicitBgConfig = true
|
|
1394
|
+
_explicitFgFields.clear()
|
|
1395
|
+
|
|
1396
|
+
const applyBg = (key: string, presetValue: string | undefined, set: (value: string) => void) => {
|
|
1397
|
+
const hex = overrides[key] ?? presetValue
|
|
1398
|
+
if (!hex) return
|
|
1399
|
+
const ansi = hexToBgAnsi(hex)
|
|
1400
|
+
if (ansi) set(ansi)
|
|
1401
|
+
}
|
|
1402
|
+
const applyFg = (
|
|
1403
|
+
key: "fgAdd" | "fgDel" | "fgDim" | "fgLnum" | "fgRule" | "fgStripe" | "fgSafeMuted",
|
|
1404
|
+
presetValue: string | undefined,
|
|
1405
|
+
set: (value: string) => void,
|
|
1406
|
+
) => {
|
|
1407
|
+
const hex = overrides[key] ?? presetValue
|
|
1408
|
+
if (!hex) return
|
|
1409
|
+
const ansi = hexToFgAnsi(hex)
|
|
1410
|
+
if (!ansi) return
|
|
1411
|
+
set(ansi)
|
|
1412
|
+
_explicitFgFields.add(key)
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
applyBg("bgAdd", preset?.bgAdd, (v) => {
|
|
1416
|
+
BG_ADD = v
|
|
1417
|
+
})
|
|
1418
|
+
applyBg("bgDel", preset?.bgDel, (v) => {
|
|
1419
|
+
BG_DEL = v
|
|
1420
|
+
})
|
|
1421
|
+
applyBg("bgAddHighlight", preset?.bgAddHighlight, (v) => {
|
|
1422
|
+
BG_ADD_W = v
|
|
1423
|
+
})
|
|
1424
|
+
applyBg("bgDelHighlight", preset?.bgDelHighlight, (v) => {
|
|
1425
|
+
BG_DEL_W = v
|
|
1426
|
+
})
|
|
1427
|
+
applyBg("bgGutterAdd", preset?.bgGutterAdd, (v) => {
|
|
1428
|
+
BG_GUTTER_ADD = v
|
|
1429
|
+
})
|
|
1430
|
+
applyBg("bgGutterDel", preset?.bgGutterDel, (v) => {
|
|
1431
|
+
BG_GUTTER_DEL = v
|
|
1432
|
+
})
|
|
1433
|
+
applyBg("bgEmpty", preset?.bgEmpty, (v) => {
|
|
1434
|
+
BG_EMPTY = v
|
|
1435
|
+
})
|
|
1436
|
+
|
|
1437
|
+
applyFg("fgAdd", preset?.fgAdd, (v) => {
|
|
1438
|
+
FG_ADD = v
|
|
1439
|
+
})
|
|
1440
|
+
applyFg("fgDel", preset?.fgDel, (v) => {
|
|
1441
|
+
FG_DEL = v
|
|
1442
|
+
})
|
|
1443
|
+
applyFg("fgDim", preset?.fgDim, (v) => {
|
|
1444
|
+
FG_DIM = v
|
|
1445
|
+
})
|
|
1446
|
+
applyFg("fgLnum", preset?.fgLnum, (v) => {
|
|
1447
|
+
FG_LNUM = v
|
|
1448
|
+
})
|
|
1449
|
+
applyFg("fgRule", preset?.fgRule, (v) => {
|
|
1450
|
+
FG_RULE = v
|
|
1451
|
+
})
|
|
1452
|
+
applyFg("fgStripe", preset?.fgStripe, (v) => {
|
|
1453
|
+
FG_STRIPE = v
|
|
1454
|
+
})
|
|
1455
|
+
applyFg("fgSafeMuted", preset?.fgSafeMuted, (v) => {
|
|
1456
|
+
FG_SAFE_MUTED = v
|
|
1457
|
+
})
|
|
1458
|
+
|
|
1459
|
+
const shiki = overrides.shikiTheme ?? preset?.shikiTheme
|
|
1460
|
+
if (shiki) DIFF_THEME = shiki as BundledTheme
|
|
1461
|
+
|
|
1462
|
+
DIVIDER = `${FG_RULE}│${D_RST}`
|
|
1463
|
+
DEFAULT_DIFF_COLORS = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
|
|
1464
|
+
// Only trigger auto-derive when the user did NOT supply an explicit
|
|
1465
|
+
// preset or per-color override; otherwise we would overwrite their config
|
|
1466
|
+
// with the hardcoded dark palette on first render.
|
|
1467
|
+
autoDerivePending = !hasExplicitBgConfig
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
function resolveDiffColors(theme?: any): DiffColors {
|
|
1471
|
+
applyThemePaletteIfNeeded(theme)
|
|
1472
|
+
if (autoDerivePending && theme?.getFgAnsi) {
|
|
1473
|
+
autoDeriveBgFromTheme(theme)
|
|
1474
|
+
autoDerivePending = false
|
|
1475
|
+
}
|
|
1476
|
+
return DEFAULT_DIFF_COLORS
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
interface DiffLine {
|
|
1480
|
+
type: "add" | "del" | "ctx" | "sep"
|
|
1481
|
+
oldNum: number | null
|
|
1482
|
+
newNum: number | null
|
|
1483
|
+
content: string
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
interface ParsedDiff {
|
|
1487
|
+
lines: DiffLine[]
|
|
1488
|
+
added: number
|
|
1489
|
+
removed: number
|
|
1490
|
+
chars: number
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
function diffStrip(value: string): string {
|
|
1494
|
+
return value.replace(ANSI_RE, "")
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
function tabs(text: string): string {
|
|
1498
|
+
return text.replace(/\t/g, " ")
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
function termW(): number {
|
|
1502
|
+
const raw =
|
|
1503
|
+
process.stdout.columns ||
|
|
1504
|
+
(process.stderr as any).columns ||
|
|
1505
|
+
Number.parseInt(process.env.COLUMNS ?? "", 10) ||
|
|
1506
|
+
DEFAULT_TERM_WIDTH
|
|
1507
|
+
return Math.max(40, Math.min(raw - 4, MAX_TERM_WIDTH))
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
function branchDiffWidth(): number {
|
|
1511
|
+
return Math.max(40, termW() - 8)
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
function adaptiveWrapRows(tw?: number): number {
|
|
1515
|
+
const width = tw ?? termW()
|
|
1516
|
+
if (width >= 180) return MAX_WRAP_ROWS_WIDE
|
|
1517
|
+
if (width >= 120) return MAX_WRAP_ROWS_MED
|
|
1518
|
+
return MAX_WRAP_ROWS_NARROW
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
function fit(value: string, width: number): string {
|
|
1522
|
+
if (width <= 0) return ""
|
|
1523
|
+
const plain = diffStrip(value)
|
|
1524
|
+
if (plain.length <= width) return value + " ".repeat(width - plain.length)
|
|
1525
|
+
const showWidth = width > 2 ? width - 1 : width
|
|
1526
|
+
let vis = 0
|
|
1527
|
+
let i = 0
|
|
1528
|
+
while (i < value.length && vis < showWidth) {
|
|
1529
|
+
if (value[i] === "\x1b") {
|
|
1530
|
+
const end = value.indexOf("m", i)
|
|
1531
|
+
if (end !== -1) {
|
|
1532
|
+
i = end + 1
|
|
1533
|
+
continue
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
vis++
|
|
1537
|
+
i++
|
|
1538
|
+
}
|
|
1539
|
+
return width > 2 ? `${value.slice(0, i)}${D_RST}${FG_DIM}›${D_RST}` : `${value.slice(0, i)}${D_RST}`
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
function ansiState(text: string): string {
|
|
1543
|
+
const matches = text.match(/\x1b\[[0-9;]*m/g) ?? []
|
|
1544
|
+
let fg = ""
|
|
1545
|
+
let bg = ""
|
|
1546
|
+
for (const seq of matches) {
|
|
1547
|
+
const params = seq.slice(2, -1)
|
|
1548
|
+
if (params === "0") {
|
|
1549
|
+
fg = ""
|
|
1550
|
+
bg = ""
|
|
1551
|
+
} else if (params === "39") {
|
|
1552
|
+
fg = ""
|
|
1553
|
+
} else if (params.startsWith("38;")) {
|
|
1554
|
+
fg = seq
|
|
1555
|
+
} else if (params.startsWith("48;")) {
|
|
1556
|
+
bg = seq
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
return bg + fg
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
function normalizeShikiContrast(ansi: string): string {
|
|
1563
|
+
return ansi.replace(/\x1b\[([0-9;]*)m/g, (seq, params: string) => {
|
|
1564
|
+
if (params === "30" || params === "90" || params === "38;5;0" || params === "38;5;8") return FG_SAFE_MUTED
|
|
1565
|
+
if (!params.startsWith("38;2;")) return seq
|
|
1566
|
+
const parts = params.split(";").map(Number)
|
|
1567
|
+
if (parts.length !== 5 || parts.some((n) => !Number.isFinite(n))) return seq
|
|
1568
|
+
const [, , r, g, b] = parts
|
|
1569
|
+
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
1570
|
+
return luminance < 72 ? FG_SAFE_MUTED : seq
|
|
1571
|
+
})
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
function wrapAnsi(text: string, width: number, maxRows = adaptiveWrapRows(), fillBg = ""): string[] {
|
|
1575
|
+
if (width <= 0) return [""]
|
|
1576
|
+
const plain = diffStrip(text)
|
|
1577
|
+
if (plain.length <= width) {
|
|
1578
|
+
const pad = width - plain.length
|
|
1579
|
+
return pad > 0 ? [text + fillBg + " ".repeat(pad) + (fillBg ? D_RST : "")] : [text]
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
const rows: string[] = []
|
|
1583
|
+
let row = ""
|
|
1584
|
+
let vis = 0
|
|
1585
|
+
let i = 0
|
|
1586
|
+
let onLastRow = false
|
|
1587
|
+
let effectiveWidth = width
|
|
1588
|
+
|
|
1589
|
+
while (i < text.length) {
|
|
1590
|
+
if (!onLastRow && rows.length >= maxRows - 1) {
|
|
1591
|
+
onLastRow = true
|
|
1592
|
+
effectiveWidth = width > 2 ? width - 1 : width
|
|
1593
|
+
}
|
|
1594
|
+
if (text[i] === "\x1b") {
|
|
1595
|
+
const end = text.indexOf("m", i)
|
|
1596
|
+
if (end !== -1) {
|
|
1597
|
+
row += text.slice(i, end + 1)
|
|
1598
|
+
i = end + 1
|
|
1599
|
+
continue
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
if (vis >= effectiveWidth) {
|
|
1603
|
+
if (onLastRow) {
|
|
1604
|
+
let hasMore = false
|
|
1605
|
+
for (let j = i; j < text.length; j++) {
|
|
1606
|
+
if (text[j] === "\x1b") {
|
|
1607
|
+
const e2 = text.indexOf("m", j)
|
|
1608
|
+
if (e2 !== -1) {
|
|
1609
|
+
j = e2
|
|
1610
|
+
continue
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
hasMore = true
|
|
1614
|
+
break
|
|
1615
|
+
}
|
|
1616
|
+
if (hasMore && width > 2) row += `${D_RST}${FG_DIM}›${D_RST}`
|
|
1617
|
+
else row += fillBg + " ".repeat(Math.max(0, width - vis)) + D_RST
|
|
1618
|
+
rows.push(row)
|
|
1619
|
+
return rows
|
|
1620
|
+
}
|
|
1621
|
+
const state = ansiState(row)
|
|
1622
|
+
rows.push(row + D_RST)
|
|
1623
|
+
row = state + fillBg
|
|
1624
|
+
vis = 0
|
|
1625
|
+
if (rows.length >= maxRows - 1) {
|
|
1626
|
+
onLastRow = true
|
|
1627
|
+
effectiveWidth = width > 2 ? width - 1 : width
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
row += text[i]
|
|
1631
|
+
vis++
|
|
1632
|
+
i++
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
if (row.length > 0 || rows.length === 0) {
|
|
1636
|
+
rows.push(row + fillBg + " ".repeat(Math.max(0, width - vis)) + D_RST)
|
|
1637
|
+
}
|
|
1638
|
+
return rows
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
function lnum(n: number | null, width: number, fg = FG_LNUM): string {
|
|
1642
|
+
if (n === null) return " ".repeat(width)
|
|
1643
|
+
const value = String(n)
|
|
1644
|
+
return `${fg}${" ".repeat(Math.max(0, width - value.length))}${value}${D_RST}`
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
function stripes(width: number): string {
|
|
1648
|
+
return BG_BASE + FG_STRIPE + "╱".repeat(width) + D_RST
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
function renderDiffStatBar(added: number, removed: number, width = termW()): string {
|
|
1652
|
+
const total = added + removed
|
|
1653
|
+
if (total === 0 || width < 20) return ""
|
|
1654
|
+
const slots = Math.max(8, Math.min(20, Math.floor(width / 14)))
|
|
1655
|
+
let addSlots = Math.max(0, Math.min(slots, Math.round((added / total) * slots)))
|
|
1656
|
+
if (added > 0 && addSlots === 0) addSlots = 1
|
|
1657
|
+
if (removed > 0 && addSlots >= slots) addSlots = slots - 1
|
|
1658
|
+
const removeSlots = Math.max(0, slots - addSlots)
|
|
1659
|
+
const addBar = addSlots > 0 ? `${FG_ADD}${"━".repeat(addSlots)}${D_RST}` : ""
|
|
1660
|
+
const removeBar = removeSlots > 0 ? `${FG_DEL}${"━".repeat(removeSlots)}${D_RST}` : ""
|
|
1661
|
+
return `${FG_DIM}[${D_RST}${addBar}${removeBar}${FG_DIM}]${D_RST}`
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
function summarizeDiff(added: number, removed: number): string {
|
|
1665
|
+
const parts: string[] = []
|
|
1666
|
+
if (added > 0) parts.push(`${FG_ADD}+${added}${D_RST}`)
|
|
1667
|
+
if (removed > 0) parts.push(`${FG_DEL}-${removed}${D_RST}`)
|
|
1668
|
+
if (!parts.length) return `${FG_DIM}no changes${D_RST}`
|
|
1669
|
+
const bar = renderDiffStatBar(added, removed)
|
|
1670
|
+
return bar ? `${parts.join(" ")} ${bar}` : parts.join(" ")
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
function diffSummaryWithMeta(added: number, removed: number, hunks: number, mode: string): string {
|
|
1674
|
+
const base = summarizeDiff(added, removed)
|
|
1675
|
+
const extras: string[] = []
|
|
1676
|
+
if (hunks > 0) extras.push(`${FG_DIM}${hunks} hunk${hunks === 1 ? "" : "s"}${D_RST}`)
|
|
1677
|
+
if (mode) extras.push(`${FG_DIM}${mode}${D_RST}`)
|
|
1678
|
+
return extras.length ? `${base} ${FG_DIM}•${D_RST} ${extras.join(` ${FG_DIM}•${D_RST} `)}` : base
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
function collapsedDiffHint(remainingLines: number, hiddenHunks: number): string {
|
|
1682
|
+
const width = termW()
|
|
1683
|
+
const candidates = [
|
|
1684
|
+
`… (${remainingLines} more diff lines${hiddenHunks > 0 ? ` • ${hiddenHunks} more hunks` : ""} • ctrl+o to expand)`,
|
|
1685
|
+
`… (${remainingLines} more lines${hiddenHunks > 0 ? ` • ${hiddenHunks} hunks` : ""})`,
|
|
1686
|
+
`… (+${remainingLines}${hiddenHunks > 0 ? ` • +${hiddenHunks}h` : ""})`,
|
|
1687
|
+
"…",
|
|
1688
|
+
]
|
|
1689
|
+
for (const candidate of candidates) {
|
|
1690
|
+
if (visibleWidth(candidate) <= width) return candidate
|
|
1691
|
+
}
|
|
1692
|
+
return truncateToWidth("…", width, "")
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
function diffRule(width: number): string {
|
|
1696
|
+
return `${BG_BASE}${FG_RULE}${"─".repeat(width)}${D_RST}`
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
function shouldUseSplit(diff: ParsedDiff, tw: number, maxRows = MAX_PREVIEW_LINES): boolean {
|
|
1700
|
+
if (!diff.lines.length) return false
|
|
1701
|
+
if (tw < SPLIT_MIN_WIDTH) return false
|
|
1702
|
+
const nw = Math.max(2, String(Math.max(...diff.lines.map((l) => l.oldNum ?? l.newNum ?? 0), 0)).length)
|
|
1703
|
+
const half = Math.floor((tw - 1) / 2)
|
|
1704
|
+
const gw = nw + 5
|
|
1705
|
+
const cw = Math.max(12, half - gw)
|
|
1706
|
+
if (cw < SPLIT_MIN_CODE_WIDTH) return false
|
|
1707
|
+
const vis = diff.lines.slice(0, maxRows)
|
|
1708
|
+
let contentLines = 0
|
|
1709
|
+
let wrapCandidates = 0
|
|
1710
|
+
for (const line of vis) {
|
|
1711
|
+
if (line.type === "sep") continue
|
|
1712
|
+
contentLines++
|
|
1713
|
+
if (tabs(line.content).length > cw) wrapCandidates++
|
|
1714
|
+
}
|
|
1715
|
+
if (contentLines === 0) return true
|
|
1716
|
+
const wrapRatio = wrapCandidates / contentLines
|
|
1717
|
+
if (wrapCandidates >= SPLIT_MAX_WRAP_LINES) return false
|
|
1718
|
+
if (wrapRatio >= SPLIT_MAX_WRAP_RATIO) return false
|
|
1719
|
+
return true
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
const EXT_LANG: Record<string, BundledLanguage> = {
|
|
1723
|
+
ts: "typescript",
|
|
1724
|
+
tsx: "tsx",
|
|
1725
|
+
js: "javascript",
|
|
1726
|
+
jsx: "jsx",
|
|
1727
|
+
mjs: "javascript",
|
|
1728
|
+
cjs: "javascript",
|
|
1729
|
+
py: "python",
|
|
1730
|
+
rb: "ruby",
|
|
1731
|
+
rs: "rust",
|
|
1732
|
+
go: "go",
|
|
1733
|
+
java: "java",
|
|
1734
|
+
c: "c",
|
|
1735
|
+
cpp: "cpp",
|
|
1736
|
+
h: "c",
|
|
1737
|
+
hpp: "cpp",
|
|
1738
|
+
cs: "csharp",
|
|
1739
|
+
swift: "swift",
|
|
1740
|
+
kt: "kotlin",
|
|
1741
|
+
html: "html",
|
|
1742
|
+
css: "css",
|
|
1743
|
+
scss: "scss",
|
|
1744
|
+
json: "json",
|
|
1745
|
+
yaml: "yaml",
|
|
1746
|
+
yml: "yaml",
|
|
1747
|
+
toml: "toml",
|
|
1748
|
+
md: "markdown",
|
|
1749
|
+
sql: "sql",
|
|
1750
|
+
sh: "bash",
|
|
1751
|
+
bash: "bash",
|
|
1752
|
+
zsh: "bash",
|
|
1753
|
+
lua: "lua",
|
|
1754
|
+
php: "php",
|
|
1755
|
+
dart: "dart",
|
|
1756
|
+
xml: "xml",
|
|
1757
|
+
graphql: "graphql",
|
|
1758
|
+
svelte: "svelte",
|
|
1759
|
+
vue: "vue",
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
function lang(filePath: string): BundledLanguage | undefined {
|
|
1763
|
+
return EXT_LANG[extname(filePath).slice(1).toLowerCase()]
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
async function codeToAnsiLazy(code: string, language: BundledLanguage, theme: BundledTheme): Promise<string> {
|
|
1767
|
+
if (!codeToAnsiLoader) {
|
|
1768
|
+
codeToAnsiLoader = import("@shikijs/cli").then((mod) => mod.codeToANSI)
|
|
1769
|
+
}
|
|
1770
|
+
const codeToAnsi = await codeToAnsiLoader
|
|
1771
|
+
return codeToAnsi(code, language, theme)
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
const hlCache = new Map<string, string[]>()
|
|
1775
|
+
|
|
1776
|
+
function clearHighlightCache(): void {
|
|
1777
|
+
hlCache.clear()
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
function touchCache(key: string, value: string[]): string[] {
|
|
1781
|
+
hlCache.delete(key)
|
|
1782
|
+
hlCache.set(key, value)
|
|
1783
|
+
while (hlCache.size > CACHE_LIMIT) {
|
|
1784
|
+
const first = hlCache.keys().next().value
|
|
1785
|
+
if (first === undefined) break
|
|
1786
|
+
hlCache.delete(first)
|
|
1787
|
+
}
|
|
1788
|
+
return value
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
async function hlBlock(code: string, language: BundledLanguage | undefined): Promise<string[]> {
|
|
1792
|
+
if (!code) return [""]
|
|
1793
|
+
if (!language || code.length > MAX_HL_CHARS) return code.split("\n")
|
|
1794
|
+
const key = `${DIFF_THEME}\0${language}\0${code}`
|
|
1795
|
+
const hit = hlCache.get(key)
|
|
1796
|
+
if (hit) return touchCache(key, hit)
|
|
1797
|
+
try {
|
|
1798
|
+
const ansi = normalizeShikiContrast(await codeToAnsiLazy(code, language, DIFF_THEME))
|
|
1799
|
+
const out = (ansi.endsWith("\n") ? ansi.slice(0, -1) : ansi).split("\n")
|
|
1800
|
+
return touchCache(key, out)
|
|
1801
|
+
} catch {
|
|
1802
|
+
return code.split("\n")
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
function parseDiff(oldContent: string, newContent: string, ctxLines = 3): ParsedDiff {
|
|
1807
|
+
const patch = Diff.structuredPatch("", "", oldContent, newContent, "", "", { context: ctxLines })
|
|
1808
|
+
const lines: DiffLine[] = []
|
|
1809
|
+
let added = 0
|
|
1810
|
+
let removed = 0
|
|
1811
|
+
for (let hi = 0; hi < patch.hunks.length; hi++) {
|
|
1812
|
+
if (hi > 0) {
|
|
1813
|
+
const prev = patch.hunks[hi - 1]
|
|
1814
|
+
const gap = patch.hunks[hi].oldStart - (prev.oldStart + prev.oldLines)
|
|
1815
|
+
lines.push({ type: "sep", oldNum: null, newNum: gap > 0 ? gap : null, content: "" })
|
|
1816
|
+
}
|
|
1817
|
+
const hunk = patch.hunks[hi]
|
|
1818
|
+
let oldLine = hunk.oldStart
|
|
1819
|
+
let newLine = hunk.newStart
|
|
1820
|
+
for (const raw of hunk.lines) {
|
|
1821
|
+
if (raw === "\") continue
|
|
1822
|
+
const ch = raw[0]
|
|
1823
|
+
const text = raw.slice(1)
|
|
1824
|
+
if (ch === "+") {
|
|
1825
|
+
lines.push({ type: "add", oldNum: null, newNum: newLine++, content: text })
|
|
1826
|
+
added++
|
|
1827
|
+
} else if (ch === "-") {
|
|
1828
|
+
lines.push({ type: "del", oldNum: oldLine++, newNum: null, content: text })
|
|
1829
|
+
removed++
|
|
1830
|
+
} else {
|
|
1831
|
+
lines.push({ type: "ctx", oldNum: oldLine++, newNum: newLine++, content: text })
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
return { lines, added, removed, chars: oldContent.length + newContent.length }
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
function getCachedParsedDiff(ctx: any, key: string, oldContent: string, newContent: string): ParsedDiff {
|
|
1839
|
+
if (ctx.state?._parsedDiffKey === key && ctx.state._parsedDiff) {
|
|
1840
|
+
return ctx.state._parsedDiff as ParsedDiff
|
|
1841
|
+
}
|
|
1842
|
+
const diff = parseDiff(oldContent, newContent)
|
|
1843
|
+
if (ctx.state) {
|
|
1844
|
+
ctx.state._parsedDiffKey = key
|
|
1845
|
+
ctx.state._parsedDiff = diff
|
|
1846
|
+
}
|
|
1847
|
+
return diff
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
function wordDiffAnalysis(
|
|
1851
|
+
oldText: string,
|
|
1852
|
+
newText: string,
|
|
1853
|
+
): { similarity: number; oldRanges: Array<[number, number]>; newRanges: Array<[number, number]> } {
|
|
1854
|
+
if (!oldText && !newText) return { similarity: 1, oldRanges: [], newRanges: [] }
|
|
1855
|
+
const parts = Diff.diffWords(oldText, newText)
|
|
1856
|
+
const oldRanges: Array<[number, number]> = []
|
|
1857
|
+
const newRanges: Array<[number, number]> = []
|
|
1858
|
+
let oldPos = 0
|
|
1859
|
+
let newPos = 0
|
|
1860
|
+
let same = 0
|
|
1861
|
+
for (const part of parts) {
|
|
1862
|
+
if (part.removed) {
|
|
1863
|
+
oldRanges.push([oldPos, oldPos + part.value.length])
|
|
1864
|
+
oldPos += part.value.length
|
|
1865
|
+
} else if (part.added) {
|
|
1866
|
+
newRanges.push([newPos, newPos + part.value.length])
|
|
1867
|
+
newPos += part.value.length
|
|
1868
|
+
} else {
|
|
1869
|
+
const len = part.value.length
|
|
1870
|
+
same += len
|
|
1871
|
+
oldPos += len
|
|
1872
|
+
newPos += len
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
const maxLen = Math.max(oldText.length, newText.length)
|
|
1876
|
+
return { similarity: maxLen > 0 ? same / maxLen : 1, oldRanges, newRanges }
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
function injectBg(ansiLine: string, ranges: Array<[number, number]>, baseBg: string, hlBg: string): string {
|
|
1880
|
+
if (!ranges.length) return baseBg + ansiLine + D_RST
|
|
1881
|
+
let out = baseBg
|
|
1882
|
+
let vis = 0
|
|
1883
|
+
let inHL = false
|
|
1884
|
+
let rangeIndex = 0
|
|
1885
|
+
let i = 0
|
|
1886
|
+
while (i < ansiLine.length) {
|
|
1887
|
+
if (ansiLine[i] === "\x1b") {
|
|
1888
|
+
const end = ansiLine.indexOf("m", i)
|
|
1889
|
+
if (end !== -1) {
|
|
1890
|
+
const seq = ansiLine.slice(i, end + 1)
|
|
1891
|
+
out += seq
|
|
1892
|
+
if (seq === "\x1b[0m") out += inHL ? hlBg : baseBg
|
|
1893
|
+
i = end + 1
|
|
1894
|
+
continue
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
while (rangeIndex < ranges.length && vis >= ranges[rangeIndex][1]) rangeIndex++
|
|
1898
|
+
const want = rangeIndex < ranges.length && vis >= ranges[rangeIndex][0] && vis < ranges[rangeIndex][1]
|
|
1899
|
+
if (want !== inHL) {
|
|
1900
|
+
inHL = want
|
|
1901
|
+
out += inHL ? hlBg : baseBg
|
|
1902
|
+
}
|
|
1903
|
+
out += ansiLine[i]
|
|
1904
|
+
vis++
|
|
1905
|
+
i++
|
|
1906
|
+
}
|
|
1907
|
+
return out + D_RST
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
function plainWordDiff(oldText: string, newText: string): { old: string; new: string } {
|
|
1911
|
+
const parts = Diff.diffWords(oldText, newText)
|
|
1912
|
+
let oldOut = ""
|
|
1913
|
+
let newOut = ""
|
|
1914
|
+
for (const part of parts) {
|
|
1915
|
+
if (part.removed) oldOut += `${BG_DEL_W}${part.value}${D_RST}${BG_DEL}`
|
|
1916
|
+
else if (part.added) newOut += `${BG_ADD_W}${part.value}${D_RST}${BG_ADD}`
|
|
1917
|
+
else {
|
|
1918
|
+
oldOut += part.value
|
|
1919
|
+
newOut += part.value
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
return { old: oldOut, new: newOut }
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
async function renderUnified(
|
|
1926
|
+
diff: ParsedDiff,
|
|
1927
|
+
language: BundledLanguage | undefined,
|
|
1928
|
+
max = MAX_RENDER_LINES,
|
|
1929
|
+
dc: DiffColors = DEFAULT_DIFF_COLORS,
|
|
1930
|
+
width = termW(),
|
|
1931
|
+
): Promise<string> {
|
|
1932
|
+
if (!diff.lines.length) return ""
|
|
1933
|
+
const vis = diff.lines.slice(0, max)
|
|
1934
|
+
const tw = width
|
|
1935
|
+
const nw = Math.max(2, String(Math.max(...vis.map((l) => l.oldNum ?? l.newNum ?? 0), 0)).length)
|
|
1936
|
+
const gw = nw + 5
|
|
1937
|
+
const cw = Math.max(20, tw - gw)
|
|
1938
|
+
const canHL = diff.chars <= MAX_HL_CHARS && vis.length <= MAX_RENDER_LINES
|
|
1939
|
+
|
|
1940
|
+
const oldSrc: string[] = []
|
|
1941
|
+
const newSrc: string[] = []
|
|
1942
|
+
for (const line of vis) {
|
|
1943
|
+
if (line.type === "ctx" || line.type === "del") oldSrc.push(line.content)
|
|
1944
|
+
if (line.type === "ctx" || line.type === "add") newSrc.push(line.content)
|
|
1945
|
+
}
|
|
1946
|
+
const [oldHL, newHL] = canHL
|
|
1947
|
+
? await Promise.all([hlBlock(oldSrc.join("\n"), language), hlBlock(newSrc.join("\n"), language)])
|
|
1948
|
+
: [oldSrc, newSrc]
|
|
1949
|
+
|
|
1950
|
+
let oldIndex = 0
|
|
1951
|
+
let newIndex = 0
|
|
1952
|
+
let index = 0
|
|
1953
|
+
const out: string[] = [diffRule(tw)]
|
|
1954
|
+
|
|
1955
|
+
function emitRow(
|
|
1956
|
+
num: number | null,
|
|
1957
|
+
sign: string,
|
|
1958
|
+
gutterBg: string,
|
|
1959
|
+
signFg: string,
|
|
1960
|
+
body: string,
|
|
1961
|
+
bodyBg = "",
|
|
1962
|
+
): void {
|
|
1963
|
+
const borderFg = sign === "-" ? dc.fgDel : sign === "+" ? dc.fgAdd : ""
|
|
1964
|
+
const border = borderFg ? `${borderFg}▌${D_RST}` : `${BG_BASE} `
|
|
1965
|
+
const numFg = borderFg || FG_LNUM
|
|
1966
|
+
const gutter = `${border}${gutterBg}${lnum(num, nw, numFg)}${signFg}${sign}${D_RST} ${DIVIDER} `
|
|
1967
|
+
const cont = `${border}${gutterBg}${" ".repeat(nw + 1)}${D_RST} ${DIVIDER} `
|
|
1968
|
+
const rows = wrapAnsi(tabs(body), cw, adaptiveWrapRows(), bodyBg)
|
|
1969
|
+
out.push(`${gutter}${rows[0]}${D_RST}`)
|
|
1970
|
+
for (let r = 1; r < rows.length; r++) out.push(`${cont}${rows[r]}${D_RST}`)
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
while (index < vis.length) {
|
|
1974
|
+
const line = vis[index]
|
|
1975
|
+
if (line.type === "sep") {
|
|
1976
|
+
const gap = line.newNum
|
|
1977
|
+
const label = gap && gap > 0 ? ` ${gap} unmodified lines ` : "···"
|
|
1978
|
+
const totalW = Math.min(tw, 72)
|
|
1979
|
+
const pad = Math.max(0, totalW - label.length - 2)
|
|
1980
|
+
const half1 = Math.floor(pad / 2)
|
|
1981
|
+
const half2 = pad - half1
|
|
1982
|
+
out.push(`${BG_BASE}${FG_DIM}${"─".repeat(half1)}${label}${"─".repeat(half2)}${D_RST}`)
|
|
1983
|
+
index++
|
|
1984
|
+
continue
|
|
1985
|
+
}
|
|
1986
|
+
if (line.type === "ctx") {
|
|
1987
|
+
const hl = oldHL[oldIndex] ?? line.content
|
|
1988
|
+
emitRow(line.newNum, " ", BG_BASE, dc.fgCtx, `${BG_BASE}${D_DIM}${hl}`, BG_BASE)
|
|
1989
|
+
oldIndex++
|
|
1990
|
+
newIndex++
|
|
1991
|
+
index++
|
|
1992
|
+
continue
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
const dels: Array<{ l: DiffLine; hl: string }> = []
|
|
1996
|
+
while (index < vis.length && vis[index].type === "del") {
|
|
1997
|
+
dels.push({ l: vis[index], hl: oldHL[oldIndex] ?? vis[index].content })
|
|
1998
|
+
oldIndex++
|
|
1999
|
+
index++
|
|
2000
|
+
}
|
|
2001
|
+
const adds: Array<{ l: DiffLine; hl: string }> = []
|
|
2002
|
+
while (index < vis.length && vis[index].type === "add") {
|
|
2003
|
+
adds.push({ l: vis[index], hl: newHL[newIndex] ?? vis[index].content })
|
|
2004
|
+
newIndex++
|
|
2005
|
+
index++
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
const isPaired = dels.length === 1 && adds.length === 1
|
|
2009
|
+
const wd = isPaired ? wordDiffAnalysis(dels[0].l.content, adds[0].l.content) : null
|
|
2010
|
+
if (isPaired && wd && wd.similarity >= WORD_DIFF_MIN_SIM && canHL) {
|
|
2011
|
+
emitRow(
|
|
2012
|
+
dels[0].l.oldNum,
|
|
2013
|
+
"-",
|
|
2014
|
+
BG_GUTTER_DEL,
|
|
2015
|
+
`${dc.fgDel}${D_BOLD}`,
|
|
2016
|
+
injectBg(dels[0].hl, wd.oldRanges, BG_DEL, BG_DEL_W),
|
|
2017
|
+
BG_DEL,
|
|
2018
|
+
)
|
|
2019
|
+
emitRow(
|
|
2020
|
+
adds[0].l.newNum,
|
|
2021
|
+
"+",
|
|
2022
|
+
BG_GUTTER_ADD,
|
|
2023
|
+
`${dc.fgAdd}${D_BOLD}`,
|
|
2024
|
+
injectBg(adds[0].hl, wd.newRanges, BG_ADD, BG_ADD_W),
|
|
2025
|
+
BG_ADD,
|
|
2026
|
+
)
|
|
2027
|
+
continue
|
|
2028
|
+
}
|
|
2029
|
+
if (isPaired && wd && wd.similarity >= WORD_DIFF_MIN_SIM && !canHL) {
|
|
2030
|
+
const pwd = plainWordDiff(dels[0].l.content, adds[0].l.content)
|
|
2031
|
+
emitRow(dels[0].l.oldNum, "-", BG_GUTTER_DEL, `${dc.fgDel}${D_BOLD}`, `${BG_DEL}${pwd.old}`, BG_DEL)
|
|
2032
|
+
emitRow(adds[0].l.newNum, "+", BG_GUTTER_ADD, `${dc.fgAdd}${D_BOLD}`, `${BG_ADD}${pwd.new}`, BG_ADD)
|
|
2033
|
+
continue
|
|
2034
|
+
}
|
|
2035
|
+
for (const d of dels)
|
|
2036
|
+
emitRow(d.l.oldNum, "-", BG_GUTTER_DEL, `${dc.fgDel}${D_BOLD}`, `${BG_DEL}${canHL ? d.hl : d.l.content}`, BG_DEL)
|
|
2037
|
+
for (const a of adds)
|
|
2038
|
+
emitRow(a.l.newNum, "+", BG_GUTTER_ADD, `${dc.fgAdd}${D_BOLD}`, `${BG_ADD}${canHL ? a.hl : a.l.content}`, BG_ADD)
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
out.push(diffRule(tw))
|
|
2042
|
+
if (diff.lines.length > vis.length)
|
|
2043
|
+
out.push(`${BG_BASE}${FG_DIM} ${collapsedDiffHint(diff.lines.length - vis.length, 0)}${D_RST}`)
|
|
2044
|
+
return out.join("\n")
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
async function renderSplit(
|
|
2048
|
+
diff: ParsedDiff,
|
|
2049
|
+
language: BundledLanguage | undefined,
|
|
2050
|
+
max = MAX_PREVIEW_LINES,
|
|
2051
|
+
dc: DiffColors = DEFAULT_DIFF_COLORS,
|
|
2052
|
+
width = termW(),
|
|
2053
|
+
): Promise<string> {
|
|
2054
|
+
const tw = width
|
|
2055
|
+
if (!shouldUseSplit(diff, tw, max)) return renderUnified(diff, language, max, dc, width)
|
|
2056
|
+
if (!diff.lines.length) return ""
|
|
2057
|
+
|
|
2058
|
+
type Row = { left: DiffLine | null; right: DiffLine | null }
|
|
2059
|
+
const rows: Row[] = []
|
|
2060
|
+
let i = 0
|
|
2061
|
+
while (i < diff.lines.length) {
|
|
2062
|
+
const line = diff.lines[i]
|
|
2063
|
+
if (line.type === "sep" || line.type === "ctx") {
|
|
2064
|
+
rows.push({ left: line, right: line })
|
|
2065
|
+
i++
|
|
2066
|
+
continue
|
|
2067
|
+
}
|
|
2068
|
+
const dels: DiffLine[] = []
|
|
2069
|
+
const adds: DiffLine[] = []
|
|
2070
|
+
while (i < diff.lines.length && diff.lines[i].type === "del") dels.push(diff.lines[i++])
|
|
2071
|
+
while (i < diff.lines.length && diff.lines[i].type === "add") adds.push(diff.lines[i++])
|
|
2072
|
+
const n = Math.max(dels.length, adds.length)
|
|
2073
|
+
for (let j = 0; j < n; j++) rows.push({ left: dels[j] ?? null, right: adds[j] ?? null })
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
const vis = rows.slice(0, max)
|
|
2077
|
+
const half = Math.floor((tw - 1) / 2)
|
|
2078
|
+
const nw = Math.max(2, String(Math.max(...diff.lines.map((l) => l.oldNum ?? l.newNum ?? 0), 0)).length)
|
|
2079
|
+
const gw = nw + 5
|
|
2080
|
+
const cw = Math.max(12, half - gw)
|
|
2081
|
+
const canHL = diff.chars <= MAX_HL_CHARS && vis.length * 2 <= MAX_RENDER_LINES * 2
|
|
2082
|
+
|
|
2083
|
+
const leftSrc: string[] = []
|
|
2084
|
+
const rightSrc: string[] = []
|
|
2085
|
+
for (const row of vis) {
|
|
2086
|
+
if (row.left && row.left.type !== "sep") leftSrc.push(row.left.content)
|
|
2087
|
+
if (row.right && row.right.type !== "sep") rightSrc.push(row.right.content)
|
|
2088
|
+
}
|
|
2089
|
+
const [leftHL, rightHL] = canHL
|
|
2090
|
+
? await Promise.all([hlBlock(leftSrc.join("\n"), language), hlBlock(rightSrc.join("\n"), language)])
|
|
2091
|
+
: [leftSrc, rightSrc]
|
|
2092
|
+
|
|
2093
|
+
let leftIndex = 0
|
|
2094
|
+
let rightIndex = 0
|
|
2095
|
+
|
|
2096
|
+
type HalfResult = { gutter: string; contGutter: string; bodyRows: string[] }
|
|
2097
|
+
function halfBuild(
|
|
2098
|
+
line: DiffLine | null,
|
|
2099
|
+
hl: string,
|
|
2100
|
+
ranges: Array<[number, number]> | null,
|
|
2101
|
+
side: "left" | "right",
|
|
2102
|
+
): HalfResult {
|
|
2103
|
+
if (!line) {
|
|
2104
|
+
const gPat = FG_STRIPE + "╱".repeat(nw + 2) + D_RST
|
|
2105
|
+
const gutter = ` ${gPat}${FG_RULE}│${D_RST} `
|
|
2106
|
+
return { gutter, contGutter: gutter, bodyRows: [stripes(cw)] }
|
|
2107
|
+
}
|
|
2108
|
+
if (line.type === "sep") {
|
|
2109
|
+
const gap = line.newNum
|
|
2110
|
+
const label = gap && gap > 0 ? `··· ${gap} lines ···` : "···"
|
|
2111
|
+
const gutter = `${BG_BASE} ${FG_DIM}${fit("", nw + 2)}${D_RST}${FG_RULE}│${D_RST} `
|
|
2112
|
+
return { gutter, contGutter: gutter, bodyRows: [`${BG_BASE}${FG_DIM}${fit(label, cw)}${D_RST}`] }
|
|
2113
|
+
}
|
|
2114
|
+
const isDel = line.type === "del"
|
|
2115
|
+
const isAdd = line.type === "add"
|
|
2116
|
+
const gBg = isDel ? BG_GUTTER_DEL : isAdd ? BG_GUTTER_ADD : BG_BASE
|
|
2117
|
+
const cBg = isDel ? BG_DEL : isAdd ? BG_ADD : BG_BASE
|
|
2118
|
+
const sFg = isDel ? dc.fgDel : isAdd ? dc.fgAdd : dc.fgCtx
|
|
2119
|
+
const sign = isDel ? "-" : isAdd ? "+" : " "
|
|
2120
|
+
const num = isDel ? line.oldNum : isAdd ? line.newNum : side === "left" ? line.oldNum : line.newNum
|
|
2121
|
+
const borderFg = isDel ? dc.fgDel : isAdd ? dc.fgAdd : ""
|
|
2122
|
+
const border = borderFg ? `${borderFg}▌${D_RST}` : ` ${BG_BASE}`
|
|
2123
|
+
const numFg = borderFg || FG_LNUM
|
|
2124
|
+
let body: string
|
|
2125
|
+
if (ranges && ranges.length > 0) body = injectBg(hl, ranges, cBg, isDel ? BG_DEL_W : BG_ADD_W)
|
|
2126
|
+
else if (isDel || isAdd) body = `${cBg}${hl}`
|
|
2127
|
+
else body = `${BG_BASE}${D_DIM}${hl}`
|
|
2128
|
+
const gutter = `${border}${gBg}${lnum(num, nw, numFg)}${sFg}${D_BOLD}${sign}${D_RST} ${FG_RULE}│${D_RST} `
|
|
2129
|
+
const contGutter = `${border}${gBg}${" ".repeat(nw + 1)}${D_RST} ${FG_RULE}│${D_RST} `
|
|
2130
|
+
return { gutter, contGutter, bodyRows: wrapAnsi(tabs(body), cw, adaptiveWrapRows(), cBg) }
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
const out: string[] = []
|
|
2134
|
+
const hdrOld = `${BG_BASE}${" ".repeat(Math.max(0, nw - 2))}${dc.fgDel}${D_DIM}old${D_RST}`
|
|
2135
|
+
const hdrNew = `${BG_BASE}${" ".repeat(Math.max(0, nw - 2))}${dc.fgAdd}${D_DIM}new${D_RST}`
|
|
2136
|
+
out.push(`${BG_BASE}${hdrOld}${" ".repeat(Math.max(0, half - nw - 1))}${FG_RULE}┊${D_RST}${hdrNew}`)
|
|
2137
|
+
out.push(`${diffRule(half)}${FG_RULE}┊${D_RST}${diffRule(half)}`)
|
|
2138
|
+
|
|
2139
|
+
for (const row of vis) {
|
|
2140
|
+
const leftLine = row.left
|
|
2141
|
+
const rightLine = row.right
|
|
2142
|
+
const paired = Boolean(leftLine && rightLine && leftLine.type === "del" && rightLine.type === "add")
|
|
2143
|
+
const wd = paired && leftLine && rightLine ? wordDiffAnalysis(leftLine.content, rightLine.content) : null
|
|
2144
|
+
let leftResult: HalfResult
|
|
2145
|
+
let rightResult: HalfResult
|
|
2146
|
+
if (paired && wd && leftLine && rightLine && wd.similarity >= WORD_DIFF_MIN_SIM && canHL) {
|
|
2147
|
+
leftResult = halfBuild(leftLine, leftHL[leftIndex++] ?? leftLine.content, wd.oldRanges, "left")
|
|
2148
|
+
rightResult = halfBuild(rightLine, rightHL[rightIndex++] ?? rightLine.content, wd.newRanges, "right")
|
|
2149
|
+
} else if (paired && wd && leftLine && rightLine && wd.similarity >= WORD_DIFF_MIN_SIM && !canHL) {
|
|
2150
|
+
const pwd = plainWordDiff(leftLine.content, rightLine.content)
|
|
2151
|
+
leftIndex++
|
|
2152
|
+
rightIndex++
|
|
2153
|
+
leftResult = halfBuild(leftLine, pwd.old, null, "left")
|
|
2154
|
+
rightResult = halfBuild(rightLine, pwd.new, null, "right")
|
|
2155
|
+
} else {
|
|
2156
|
+
leftResult = halfBuild(
|
|
2157
|
+
row.left,
|
|
2158
|
+
row.left && row.left.type !== "sep" ? (leftHL[leftIndex++] ?? row.left.content) : "",
|
|
2159
|
+
null,
|
|
2160
|
+
"left",
|
|
2161
|
+
)
|
|
2162
|
+
rightResult = halfBuild(
|
|
2163
|
+
row.right,
|
|
2164
|
+
row.right && row.right.type !== "sep" ? (rightHL[rightIndex++] ?? row.right.content) : "",
|
|
2165
|
+
null,
|
|
2166
|
+
"right",
|
|
2167
|
+
)
|
|
2168
|
+
}
|
|
2169
|
+
const maxRows = Math.max(leftResult.bodyRows.length, rightResult.bodyRows.length)
|
|
2170
|
+
for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
|
|
2171
|
+
const lg = rowIndex === 0 ? leftResult.gutter : leftResult.contGutter
|
|
2172
|
+
const rg = rowIndex === 0 ? rightResult.gutter : rightResult.contGutter
|
|
2173
|
+
const lb = leftResult.bodyRows[rowIndex] ?? (!row.left ? stripes(cw) : `${BG_EMPTY}${" ".repeat(cw)}${D_RST}`)
|
|
2174
|
+
const rb = rightResult.bodyRows[rowIndex] ?? (!row.right ? stripes(cw) : `${BG_EMPTY}${" ".repeat(cw)}${D_RST}`)
|
|
2175
|
+
out.push(`${lg}${lb}${DIVIDER}${rg}${rb}`)
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
out.push(`${diffRule(half)}${FG_RULE}┊${D_RST}${diffRule(half)}`)
|
|
2180
|
+
if (rows.length > vis.length)
|
|
2181
|
+
out.push(`${BG_BASE}${FG_DIM} ${collapsedDiffHint(rows.length - vis.length, 0)}${D_RST}`)
|
|
2182
|
+
return out.join("\n")
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
function getEditOperations(input: any): Array<{ oldText: string; newText: string }> {
|
|
2186
|
+
if (Array.isArray(input?.edits)) {
|
|
2187
|
+
return input.edits
|
|
2188
|
+
.map((edit: any) => ({
|
|
2189
|
+
oldText:
|
|
2190
|
+
typeof edit?.oldText === "string" ? edit.oldText : typeof edit?.old_text === "string" ? edit.old_text : "",
|
|
2191
|
+
newText:
|
|
2192
|
+
typeof edit?.newText === "string" ? edit.newText : typeof edit?.new_text === "string" ? edit.new_text : "",
|
|
2193
|
+
}))
|
|
2194
|
+
.filter((edit: { oldText: string; newText: string }) => edit.oldText && edit.oldText !== edit.newText)
|
|
2195
|
+
}
|
|
2196
|
+
const oldText =
|
|
2197
|
+
typeof input?.oldText === "string" ? input.oldText : typeof input?.old_text === "string" ? input.old_text : ""
|
|
2198
|
+
const newText =
|
|
2199
|
+
typeof input?.newText === "string" ? input.newText : typeof input?.new_text === "string" ? input.new_text : ""
|
|
2200
|
+
return oldText && oldText !== newText ? [{ oldText, newText }] : []
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
function summarizeEditOperations(operations: Array<{ oldText: string; newText: string }>) {
|
|
2204
|
+
const diffs = operations.map((edit) => parseDiff(edit.oldText, edit.newText))
|
|
2205
|
+
const totalAdded = diffs.reduce((sum, diff) => sum + diff.added, 0)
|
|
2206
|
+
const totalRemoved = diffs.reduce((sum, diff) => sum + diff.removed, 0)
|
|
2207
|
+
const totalLines = diffs.reduce((sum, diff) => sum + diff.lines.length, 0)
|
|
2208
|
+
const totalHunks = diffs.reduce(
|
|
2209
|
+
(sum, diff) => sum + diff.lines.filter((l) => l.type === "sep").length + (diff.lines.length ? 1 : 0),
|
|
2210
|
+
0,
|
|
2211
|
+
)
|
|
2212
|
+
return { diffs, totalAdded, totalRemoved, totalLines, totalHunks, summary: summarizeDiff(totalAdded, totalRemoved) }
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
type EditOperationSummary = ReturnType<typeof summarizeEditOperations>
|
|
2216
|
+
|
|
2217
|
+
function getCachedEditOperationSummary(
|
|
2218
|
+
ctx: any,
|
|
2219
|
+
key: string,
|
|
2220
|
+
operations: Array<{ oldText: string; newText: string }>,
|
|
2221
|
+
): EditOperationSummary {
|
|
2222
|
+
if (ctx.state?._editSummaryKey === key && ctx.state._editSummary) {
|
|
2223
|
+
return ctx.state._editSummary as EditOperationSummary
|
|
2224
|
+
}
|
|
2225
|
+
const summary = summarizeEditOperations(operations)
|
|
2226
|
+
if (ctx.state) {
|
|
2227
|
+
ctx.state._editSummaryKey = key
|
|
2228
|
+
ctx.state._editSummary = summary
|
|
2229
|
+
}
|
|
2230
|
+
return summary
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
function normalizeToLf(text: string): string {
|
|
2234
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n")
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
function stripBomText(text: string): string {
|
|
2238
|
+
return text.startsWith("\uFEFF") ? text.slice(1) : text
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
function normalizeTextForFuzzyMatch(text: string): string {
|
|
2242
|
+
return text
|
|
2243
|
+
.normalize("NFKC")
|
|
2244
|
+
.split("\n")
|
|
2245
|
+
.map((line) => line.trimEnd())
|
|
2246
|
+
.join("\n")
|
|
2247
|
+
.replace(/[\u2018\u2019\u201A\u201B]/g, "'")
|
|
2248
|
+
.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
|
|
2249
|
+
.replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-")
|
|
2250
|
+
.replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ")
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
function findEditMatch(
|
|
2254
|
+
content: string,
|
|
2255
|
+
oldText: string,
|
|
2256
|
+
): { found: boolean; index: number; matchLength: number; usedFuzzyMatch: boolean } {
|
|
2257
|
+
const exactIndex = content.indexOf(oldText)
|
|
2258
|
+
if (exactIndex !== -1) return { found: true, index: exactIndex, matchLength: oldText.length, usedFuzzyMatch: false }
|
|
2259
|
+
const fuzzyContent = normalizeTextForFuzzyMatch(content)
|
|
2260
|
+
const fuzzyOldText = normalizeTextForFuzzyMatch(oldText)
|
|
2261
|
+
const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText)
|
|
2262
|
+
return fuzzyIndex === -1
|
|
2263
|
+
? { found: false, index: -1, matchLength: 0, usedFuzzyMatch: false }
|
|
2264
|
+
: { found: true, index: fuzzyIndex, matchLength: fuzzyOldText.length, usedFuzzyMatch: true }
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
function countFuzzyOccurrences(content: string, oldText: string): number {
|
|
2268
|
+
const fuzzyContent = normalizeTextForFuzzyMatch(content)
|
|
2269
|
+
const fuzzyOldText = normalizeTextForFuzzyMatch(oldText)
|
|
2270
|
+
return fuzzyContent.split(fuzzyOldText).length - 1
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
function lineNumberAtIndex(text: string, index: number): number {
|
|
2274
|
+
return text.slice(0, Math.max(0, index)).split("\n").length
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
function countLineBreaks(text: string): number {
|
|
2278
|
+
return (text.match(/\n/g) ?? []).length
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
function offsetParsedDiff(diff: ParsedDiff, oldOffset: number, newOffset = oldOffset): ParsedDiff {
|
|
2282
|
+
return {
|
|
2283
|
+
...diff,
|
|
2284
|
+
lines: diff.lines.map((line) =>
|
|
2285
|
+
line.type === "sep"
|
|
2286
|
+
? line
|
|
2287
|
+
: {
|
|
2288
|
+
...line,
|
|
2289
|
+
oldNum: line.oldNum === null ? null : line.oldNum + oldOffset,
|
|
2290
|
+
newNum: line.newNum === null ? null : line.newNum + newOffset,
|
|
2291
|
+
},
|
|
2292
|
+
),
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
function getFirstChangedNewLine(diff: ParsedDiff): number {
|
|
2297
|
+
let currentNewLine = 0
|
|
2298
|
+
for (let i = 0; i < diff.lines.length; i++) {
|
|
2299
|
+
const line = diff.lines[i]
|
|
2300
|
+
if (line.type === "sep") {
|
|
2301
|
+
currentNewLine = 0
|
|
2302
|
+
continue
|
|
2303
|
+
}
|
|
2304
|
+
if (line.type === "ctx") {
|
|
2305
|
+
currentNewLine = (line.newNum ?? currentNewLine) + 1
|
|
2306
|
+
continue
|
|
2307
|
+
}
|
|
2308
|
+
if (line.type === "add") return line.newNum ?? currentNewLine
|
|
2309
|
+
if (currentNewLine > 0) return currentNewLine
|
|
2310
|
+
const next = diff.lines.slice(i + 1).find((entry) => entry.type !== "sep" && entry.newNum !== null)
|
|
2311
|
+
if (next && next.newNum !== null) return next.newNum
|
|
2312
|
+
return line.oldNum ?? 0
|
|
2313
|
+
}
|
|
2314
|
+
return 0
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
interface LocalizedEditDiff {
|
|
2318
|
+
diff: ParsedDiff
|
|
2319
|
+
line: number
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
async function computeLocalizedEditDiffs(
|
|
2323
|
+
filePath: string,
|
|
2324
|
+
operations: Array<{ oldText: string; newText: string }>,
|
|
2325
|
+
cwd: string,
|
|
2326
|
+
): Promise<LocalizedEditDiff[] | null> {
|
|
2327
|
+
if (!filePath || operations.length === 0) return null
|
|
2328
|
+
try {
|
|
2329
|
+
const rawContent = await readFileAsync(resolve(cwd, filePath), "utf8")
|
|
2330
|
+
const normalizedContent = normalizeToLf(stripBomText(rawContent))
|
|
2331
|
+
const normalizedOps = operations.map((edit) => ({
|
|
2332
|
+
oldText: normalizeToLf(edit.oldText),
|
|
2333
|
+
newText: normalizeToLf(edit.newText),
|
|
2334
|
+
}))
|
|
2335
|
+
const baseContent = normalizedOps.some((edit) => findEditMatch(normalizedContent, edit.oldText).usedFuzzyMatch)
|
|
2336
|
+
? normalizeTextForFuzzyMatch(normalizedContent)
|
|
2337
|
+
: normalizedContent
|
|
2338
|
+
const matches = normalizedOps.map((edit, editIndex) => {
|
|
2339
|
+
const match = findEditMatch(baseContent, edit.oldText)
|
|
2340
|
+
if (!match.found || countFuzzyOccurrences(baseContent, edit.oldText) !== 1) return null
|
|
2341
|
+
return { editIndex, matchIndex: match.index, matchLength: match.matchLength, newText: edit.newText }
|
|
2342
|
+
})
|
|
2343
|
+
if (matches.some((match) => match === null)) return null
|
|
2344
|
+
const ordered = [
|
|
2345
|
+
...(matches as Array<{ editIndex: number; matchIndex: number; matchLength: number; newText: string }>),
|
|
2346
|
+
].sort((a, b) => a.matchIndex - b.matchIndex)
|
|
2347
|
+
for (let i = 1; i < ordered.length; i++) {
|
|
2348
|
+
const prev = ordered[i - 1]
|
|
2349
|
+
const current = ordered[i]
|
|
2350
|
+
if (prev.matchIndex + prev.matchLength > current.matchIndex) return null
|
|
2351
|
+
}
|
|
2352
|
+
const localized: Array<LocalizedEditDiff | null> = Array(operations.length).fill(null)
|
|
2353
|
+
let lineDelta = 0
|
|
2354
|
+
for (const match of ordered) {
|
|
2355
|
+
const oldChunk = baseContent.slice(match.matchIndex, match.matchIndex + match.matchLength)
|
|
2356
|
+
const oldStartLine = lineNumberAtIndex(baseContent, match.matchIndex)
|
|
2357
|
+
const newStartLine = oldStartLine + lineDelta
|
|
2358
|
+
const diff = offsetParsedDiff(parseDiff(oldChunk, match.newText), oldStartLine - 1, newStartLine - 1)
|
|
2359
|
+
localized[match.editIndex] = { diff, line: getFirstChangedNewLine(diff) }
|
|
2360
|
+
lineDelta += countLineBreaks(match.newText) - countLineBreaks(oldChunk)
|
|
2361
|
+
}
|
|
2362
|
+
return localized.every(Boolean) ? (localized as LocalizedEditDiff[]) : null
|
|
2363
|
+
} catch {
|
|
2364
|
+
return null
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
function renderEditPreviewBody(
|
|
2369
|
+
ctx: any,
|
|
2370
|
+
key: string,
|
|
2371
|
+
theme: Theme,
|
|
2372
|
+
language: BundledLanguage | undefined,
|
|
2373
|
+
operations: Array<{ oldText: string; newText: string }>,
|
|
2374
|
+
diffs: ParsedDiff[],
|
|
2375
|
+
lines: number[],
|
|
2376
|
+
summary: string,
|
|
2377
|
+
): void {
|
|
2378
|
+
const dc = resolveDiffColors(theme)
|
|
2379
|
+
const branchWidth = branchDiffWidth()
|
|
2380
|
+
if (operations.length === 1) {
|
|
2381
|
+
const [diff] = diffs
|
|
2382
|
+
const line = lines[0] ?? getFirstChangedNewLine(diff)
|
|
2383
|
+
renderSplit(diff, language, ctx.expanded ? MAX_PREVIEW_LINES : 32, dc, branchWidth)
|
|
2384
|
+
.then((rendered) => {
|
|
2385
|
+
if (ctx.state._pk !== key) return
|
|
2386
|
+
ctx.state._ptBody = `${summarizeDiff(diff.added, diff.removed)}${formatLineMeta(line, theme)}\n${rendered}`
|
|
2387
|
+
ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
|
|
2388
|
+
ctx.invalidate()
|
|
2389
|
+
})
|
|
2390
|
+
.catch(() => {
|
|
2391
|
+
if (ctx.state._pk !== key) return
|
|
2392
|
+
ctx.state._ptBody = `${summarizeDiff(diff.added, diff.removed)}${formatLineMeta(line, theme)}`
|
|
2393
|
+
ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
|
|
2394
|
+
ctx.invalidate()
|
|
2395
|
+
})
|
|
2396
|
+
return
|
|
2397
|
+
}
|
|
2398
|
+
const maxShown = ctx.expanded ? operations.length : Math.min(operations.length, 3)
|
|
2399
|
+
const previewLines = ctx.expanded
|
|
2400
|
+
? Math.max(6, Math.floor(MAX_RENDER_LINES / Math.max(1, maxShown)))
|
|
2401
|
+
: Math.max(8, Math.floor(MAX_PREVIEW_LINES / Math.max(1, maxShown)))
|
|
2402
|
+
void Promise.all(
|
|
2403
|
+
diffs.slice(0, maxShown).map((diff, index) => {
|
|
2404
|
+
const line = lines[index] ?? getFirstChangedNewLine(diff)
|
|
2405
|
+
return renderSplit(diff, language, previewLines, dc, branchWidth)
|
|
2406
|
+
.then((rendered) => `Edit ${index + 1}/${operations.length}${formatLineMeta(line, theme)}\n${rendered}`)
|
|
2407
|
+
.catch(
|
|
2408
|
+
() =>
|
|
2409
|
+
`Edit ${index + 1}/${operations.length}${formatLineMeta(line, theme)} ${summarizeDiff(diff.added, diff.removed)}`,
|
|
2410
|
+
)
|
|
2411
|
+
}),
|
|
2412
|
+
)
|
|
2413
|
+
.then((sections) => {
|
|
2414
|
+
if (ctx.state._pk !== key) return
|
|
2415
|
+
const remainder = operations.length - maxShown
|
|
2416
|
+
const suffix =
|
|
2417
|
+
remainder > 0
|
|
2418
|
+
? `\n${theme.fg("muted", `… ${remainder} more edit blocks${ctx.expanded ? "" : " • ctrl+o to expand"}`)}`
|
|
2419
|
+
: ""
|
|
2420
|
+
ctx.state._ptBody = `${operations.length} edits ${summary}\n\n${sections.join("\n\n")}${suffix}`
|
|
2421
|
+
ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
|
|
2422
|
+
ctx.invalidate()
|
|
2423
|
+
})
|
|
2424
|
+
.catch(() => {
|
|
2425
|
+
if (ctx.state._pk !== key) return
|
|
2426
|
+
ctx.state._ptBody = `${operations.length} edits ${summary}`
|
|
2427
|
+
ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
|
|
2428
|
+
ctx.invalidate()
|
|
2429
|
+
})
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
function stripThinkingPresentationArtifacts(text: string): string {
|
|
2433
|
+
if (!ANSI_PRESENT_RE.test(text) && !/^\s*thinking:\s*/i.test(text)) return text
|
|
2434
|
+
let current = ANSI_PRESENT_RE.test(text) ? text.replace(ANSI_RE, "") : text
|
|
2435
|
+
while (true) {
|
|
2436
|
+
const next = current.replace(/^(?:thinking:\s*)+/i, "").trimStart()
|
|
2437
|
+
if (next === current) return current
|
|
2438
|
+
current = next
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
function prefixThinkingLine(text: string, _theme: Theme | undefined): string {
|
|
2443
|
+
if (!ANSI_PRESENT_RE.test(text) && text.startsWith("Thinking: ") && !/^Thinking:\s*thinking:\s*/i.test(text)) {
|
|
2444
|
+
return text
|
|
2445
|
+
}
|
|
2446
|
+
const normalized = stripThinkingPresentationArtifacts(text).trim()
|
|
2447
|
+
if (!normalized) return text
|
|
2448
|
+
// Plain text — no ANSI colors, no theme. The ThinkingParagraph handles styling.
|
|
2449
|
+
return `Thinking: ${normalized}`
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
function registerThinkingLabels(pi: ExtensionAPI): void {
|
|
2453
|
+
const patchMessage = (event: any, theme?: Theme) => {
|
|
2454
|
+
// Keep theme-derived border / dim text colors in sync with the
|
|
2455
|
+
// active pi theme. Cheap when the theme hasn't changed (identity check).
|
|
2456
|
+
if (theme) applyThemePaletteIfNeeded(theme)
|
|
2457
|
+
const message = event?.message
|
|
2458
|
+
if (!message || message.role !== "assistant" || !Array.isArray(message.content)) return
|
|
2459
|
+
for (const block of message.content) {
|
|
2460
|
+
if (block && block.type === "thinking" && typeof block.thinking === "string") {
|
|
2461
|
+
block.thinking = prefixThinkingLine(block.thinking, theme)
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
pi.on("before_agent_start", async () => {
|
|
2466
|
+
// Start once per top-level request. Steering/follow-up messages can be
|
|
2467
|
+
// injected while the agent is already active; those must not reset the
|
|
2468
|
+
// request timer.
|
|
2469
|
+
if (currentAgentWorkStartMs === undefined) {
|
|
2470
|
+
currentAgentWorkStartMs = Date.now()
|
|
2471
|
+
}
|
|
2472
|
+
currentAssistantMessageStartMs = undefined
|
|
2473
|
+
})
|
|
2474
|
+
pi.on("agent_start", async () => {
|
|
2475
|
+
if (currentAgentWorkStartMs === undefined) {
|
|
2476
|
+
currentAgentWorkStartMs = Date.now()
|
|
2477
|
+
}
|
|
2478
|
+
currentAssistantMessageStartMs = undefined
|
|
2479
|
+
})
|
|
2480
|
+
pi.on("message_start", async (event: any) => {
|
|
2481
|
+
const message = event?.message
|
|
2482
|
+
if (message?.role === "user" && currentAgentWorkStartMs === undefined) {
|
|
2483
|
+
currentAgentWorkStartMs = Date.now()
|
|
2484
|
+
}
|
|
2485
|
+
if (message?.role === "assistant") {
|
|
2486
|
+
currentAssistantMessageStartMs = Date.now()
|
|
2487
|
+
;(message as any)[WORKED_START_KEY] = currentAssistantMessageStartMs
|
|
2488
|
+
}
|
|
2489
|
+
})
|
|
2490
|
+
pi.on("message_update", async (event, ctx) => patchMessage(event, ctx.ui?.theme))
|
|
2491
|
+
pi.on("message_end", async (event, ctx) => {
|
|
2492
|
+
const message = (event as any)?.message
|
|
2493
|
+
if (message?.role === "assistant") {
|
|
2494
|
+
const started =
|
|
2495
|
+
typeof currentAgentWorkStartMs === "number"
|
|
2496
|
+
? currentAgentWorkStartMs
|
|
2497
|
+
: typeof (message as any)[WORKED_START_KEY] === "number"
|
|
2498
|
+
? (message as any)[WORKED_START_KEY]
|
|
2499
|
+
: currentAssistantMessageStartMs
|
|
2500
|
+
const isFinalAssistantMessage = message.stopReason !== "toolUse"
|
|
2501
|
+
if (started !== undefined && isFinalAssistantMessage) {
|
|
2502
|
+
const durationMs = Date.now() - started
|
|
2503
|
+
// Store duration as metadata on the message object. The patched
|
|
2504
|
+
// AssistantMessageComponent.render() reads it and appends the widget
|
|
2505
|
+
// line outside of the message content blocks — never injected into
|
|
2506
|
+
// the text that gets sent to the model.
|
|
2507
|
+
;(message as any)[WORKED_DURATION_KEY] = durationMs
|
|
2508
|
+
// Persist the duration as a sidecar entry in the JSONL session file
|
|
2509
|
+
// (type: "custom", does not participate in LLM context).
|
|
2510
|
+
pi.appendEntry("turn_duration", { durationMs })
|
|
2511
|
+
}
|
|
2512
|
+
currentAssistantMessageStartMs = undefined
|
|
2513
|
+
}
|
|
2514
|
+
patchMessage(event, ctx.ui?.theme)
|
|
2515
|
+
})
|
|
2516
|
+
pi.on("agent_end", async () => {
|
|
2517
|
+
currentAgentWorkStartMs = undefined
|
|
2518
|
+
currentAssistantMessageStartMs = undefined
|
|
2519
|
+
})
|
|
2520
|
+
pi.on("context", async (event) => {
|
|
2521
|
+
if (!Array.isArray((event as any).messages)) return
|
|
2522
|
+
for (const msg of (event as any).messages) {
|
|
2523
|
+
if (!msg || msg.role !== "assistant" || !Array.isArray(msg.content)) continue
|
|
2524
|
+
for (const block of msg.content) {
|
|
2525
|
+
if (block && block.type === "thinking" && typeof block.thinking === "string") {
|
|
2526
|
+
block.thinking = stripThinkingPresentationArtifacts(block.thinking)
|
|
2527
|
+
}
|
|
2528
|
+
// Legacy sessions written before this change may have the duration
|
|
2529
|
+
// text injected directly into content blocks. Strip it so it doesn't
|
|
2530
|
+
// appear twice alongside the widget.
|
|
2531
|
+
if (block && block.type === "text" && typeof block.text === "string") {
|
|
2532
|
+
const marker = "Worked for"
|
|
2533
|
+
if (block.text.includes(marker)) {
|
|
2534
|
+
block.text = block.text
|
|
2535
|
+
.split(/\r?\n/)
|
|
2536
|
+
.filter((l: string) => !(l.includes(marker) && /^✻ Worked for [^\r\n]+$/.test(l.replace(/\x1b\[[0-9;]*m/g, "").trim())))
|
|
2537
|
+
.join("\n")
|
|
2538
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
})
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
function getMode<T extends string>(value: unknown, allowed: readonly T[], fallback: T): T {
|
|
2547
|
+
return typeof value === "string" && (allowed as readonly string[]).includes(value) ? (value as T) : fallback
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
const CORE_TOOL_OVERRIDES = new Set(["read", "bash", "grep", "find", "ls", "write", "edit", "set_phase"])
|
|
2551
|
+
|
|
2552
|
+
const OPENAI_STYLE_TOOL_NAMES = new Set([
|
|
2553
|
+
"apply_patch",
|
|
2554
|
+
"webfetch",
|
|
2555
|
+
"question",
|
|
2556
|
+
"questionnaire",
|
|
2557
|
+
"context_tag",
|
|
2558
|
+
"context_log",
|
|
2559
|
+
"context_checkout",
|
|
2560
|
+
"annotate",
|
|
2561
|
+
"web_search",
|
|
2562
|
+
"code_search",
|
|
2563
|
+
"fetch_content",
|
|
2564
|
+
"get_search_content",
|
|
2565
|
+
"alpha_search",
|
|
2566
|
+
"alpha_get_paper",
|
|
2567
|
+
"alpha_ask_paper",
|
|
2568
|
+
"alpha_annotate_paper",
|
|
2569
|
+
"alpha_list_annotations",
|
|
2570
|
+
"alpha_read_code",
|
|
2571
|
+
"Skill",
|
|
2572
|
+
"EnterPlanMode",
|
|
2573
|
+
"ExitPlanMode",
|
|
2574
|
+
"Agent",
|
|
2575
|
+
"get_subagent_result",
|
|
2576
|
+
"steer_subagent",
|
|
2577
|
+
"TaskCreate",
|
|
2578
|
+
"TaskList",
|
|
2579
|
+
"TaskGet",
|
|
2580
|
+
"TaskUpdate",
|
|
2581
|
+
"TaskOutput",
|
|
2582
|
+
"TaskStop",
|
|
2583
|
+
"TaskExecute",
|
|
2584
|
+
])
|
|
2585
|
+
|
|
2586
|
+
function isMcpToolCandidate(tool: unknown): boolean {
|
|
2587
|
+
const rec = tool as Record<string, unknown> | undefined
|
|
2588
|
+
const name = typeof rec?.name === "string" ? rec.name : ""
|
|
2589
|
+
const description = typeof rec?.description === "string" ? rec.description : ""
|
|
2590
|
+
return name === "mcp" || /\bmcp\b/i.test(description)
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
function isOpenAiToolCandidate(tool: unknown): boolean {
|
|
2594
|
+
const rec = tool as Record<string, unknown> | undefined
|
|
2595
|
+
const name = typeof rec?.name === "string" ? rec.name : ""
|
|
2596
|
+
if (!name || CORE_TOOL_OVERRIDES.has(name) || isMcpToolCandidate(tool)) return false
|
|
2597
|
+
return OPENAI_STYLE_TOOL_NAMES.has(name)
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
function humanizeToolName(name: string): string {
|
|
2601
|
+
return name
|
|
2602
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
2603
|
+
.replace(/[_-]+/g, " ")
|
|
2604
|
+
.replace(/\b\w/g, (char) => char.toUpperCase())
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
export function isMcpToolName(name: string): boolean {
|
|
2608
|
+
return name === "mcp" || /^mcp[_:-]/i.test(name) || /[_:-]mcp[_:-]/i.test(name)
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
function shouldUseGenericToolRenderer(name: unknown): boolean {
|
|
2612
|
+
return typeof name === "string" && name.length > 0 && !CORE_TOOL_OVERRIDES.has(name)
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
function genericToolLabel(name: string): string {
|
|
2616
|
+
return isMcpToolName(name) ? "MCP" : humanizeToolName(name)
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
function renderGenericToolCall(name: string, args: any, theme: Theme, ctx: any): Text {
|
|
2620
|
+
ctx.state._openAiPatchFiles = []
|
|
2621
|
+
const sp = (path: string) => shortPath(ctx.cwd ?? process.cwd(), path)
|
|
2622
|
+
if (isMcpToolName(name)) {
|
|
2623
|
+
// For MCP calls the summary may already contain ANSI color codes (muted
|
|
2624
|
+
// for the args suffix) so we build the header line directly instead of
|
|
2625
|
+
// passing it through toolHeader() which would re-wrap everything in accent.
|
|
2626
|
+
// The cache key includes expanded state so ctrl+o triggers a full re-render.
|
|
2627
|
+
const expanded = !!ctx.expanded
|
|
2628
|
+
const cacheKey = `_mcpLabelSummary:${expanded ? 1 : 0}`
|
|
2629
|
+
const packed = stableCallSummary(ctx, cacheKey, () => {
|
|
2630
|
+
const ls = mcpCallLabelAndSummary(args, theme, expanded)
|
|
2631
|
+
return `${ls.label}\x00${ls.summary}`
|
|
2632
|
+
})
|
|
2633
|
+
const sepIdx = packed.indexOf("\x00")
|
|
2634
|
+
const mcpLabel = sepIdx >= 0 ? packed.slice(0, sepIdx) : "MCP"
|
|
2635
|
+
const mcpSummary = sepIdx >= 0 ? packed.slice(sepIdx + 1) : ""
|
|
2636
|
+
const dot = toolStatusDot(ctx, theme)
|
|
2637
|
+
const labelPart = theme.fg("toolTitle", theme.bold(mcpLabel))
|
|
2638
|
+
const header = mcpSummary ? `${dot}${labelPart} ${WRAP_MARK}${mcpSummary}` : `${dot}${labelPart}`
|
|
2639
|
+
return makeText(ctx.lastComponent, header)
|
|
2640
|
+
}
|
|
2641
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => summarizeGenericToolCall(name, args, theme, sp))
|
|
2642
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
2643
|
+
return makeText(ctx.lastComponent, toolHeader(genericToolLabel(name), summary, theme, toolStatusDot(ctx, theme), timer))
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
function renderGenericToolResult(name: string, result: any, options: any, theme: Theme, ctx: any): Text {
|
|
2647
|
+
if (isMcpToolName(name)) {
|
|
2648
|
+
return renderMcpToolResult(result, !!options?.expanded, !!options?.isPartial, theme, ctx)
|
|
2649
|
+
}
|
|
2650
|
+
return renderOpenAiToolResult(
|
|
2651
|
+
name,
|
|
2652
|
+
{ content: result.content, details: result.details },
|
|
2653
|
+
!!options?.expanded,
|
|
2654
|
+
!!options?.isPartial,
|
|
2655
|
+
theme,
|
|
2656
|
+
ctx,
|
|
2657
|
+
)
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
function getTextContent(result: any): string {
|
|
2661
|
+
if (!Array.isArray(result?.content)) return ""
|
|
2662
|
+
return result.content
|
|
2663
|
+
.filter((block: any) => block?.type === "text" && typeof block.text === "string")
|
|
2664
|
+
.map((block: any) => block.text)
|
|
2665
|
+
.join("\n")
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
function getStringArg(args: any, ...keys: string[]): string {
|
|
2669
|
+
for (const key of keys) {
|
|
2670
|
+
const value = args?.[key]
|
|
2671
|
+
if (typeof value === "string" && value.trim()) return value.trim()
|
|
2672
|
+
}
|
|
2673
|
+
return ""
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
function getStringArrayArg(args: any, ...keys: string[]): string[] {
|
|
2677
|
+
for (const key of keys) {
|
|
2678
|
+
const value = args?.[key]
|
|
2679
|
+
if (!Array.isArray(value)) continue
|
|
2680
|
+
const items = value.filter((item): item is string => typeof item === "string" && item.trim().length > 0)
|
|
2681
|
+
if (items.length > 0) return items
|
|
2682
|
+
}
|
|
2683
|
+
return []
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
function extractApplyPatchFiles(patchText: string): string[] {
|
|
2687
|
+
if (!patchText) return []
|
|
2688
|
+
const files = new Set<string>()
|
|
2689
|
+
for (const match of patchText.matchAll(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/gm)) {
|
|
2690
|
+
const filePath = match[1]?.trim()
|
|
2691
|
+
if (filePath) files.add(filePath)
|
|
2692
|
+
}
|
|
2693
|
+
return [...files]
|
|
2694
|
+
}
|
|
2695
|
+
|
|
2696
|
+
interface ApplyPatchChangePreview {
|
|
2697
|
+
kind: "add" | "update" | "delete"
|
|
2698
|
+
path: string
|
|
2699
|
+
displayPath: string
|
|
2700
|
+
moveTo?: string
|
|
2701
|
+
diff: ParsedDiff
|
|
2702
|
+
language: BundledLanguage | undefined
|
|
2703
|
+
hunks: number
|
|
2704
|
+
summary: string
|
|
2705
|
+
line: number
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
interface ApplyPatchPreview {
|
|
2709
|
+
changes: ApplyPatchChangePreview[]
|
|
2710
|
+
totalAdded: number
|
|
2711
|
+
totalRemoved: number
|
|
2712
|
+
totalHunks: number
|
|
2713
|
+
totalLines: number
|
|
2714
|
+
summary: string
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
interface ApplyPatchResultMeta {
|
|
2718
|
+
changeCount: number
|
|
2719
|
+
totalAdded: number
|
|
2720
|
+
totalRemoved: number
|
|
2721
|
+
totalHunks: number
|
|
2722
|
+
totalLines: number
|
|
2723
|
+
firstChange?: {
|
|
2724
|
+
displayPath: string
|
|
2725
|
+
kind: ApplyPatchChangePreview["kind"]
|
|
2726
|
+
hunks: number
|
|
2727
|
+
line: number
|
|
2728
|
+
added: number
|
|
2729
|
+
removed: number
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
function buildApplyPatchResultMeta(preview: ApplyPatchPreview): ApplyPatchResultMeta {
|
|
2734
|
+
const firstChange = preview.changes[0]
|
|
2735
|
+
return {
|
|
2736
|
+
changeCount: preview.changes.length,
|
|
2737
|
+
totalAdded: preview.totalAdded,
|
|
2738
|
+
totalRemoved: preview.totalRemoved,
|
|
2739
|
+
totalHunks: preview.totalHunks,
|
|
2740
|
+
totalLines: preview.totalLines,
|
|
2741
|
+
firstChange: firstChange
|
|
2742
|
+
? {
|
|
2743
|
+
displayPath: firstChange.displayPath,
|
|
2744
|
+
kind: firstChange.kind,
|
|
2745
|
+
hunks: firstChange.hunks,
|
|
2746
|
+
line: firstChange.line,
|
|
2747
|
+
added: firstChange.diff.added,
|
|
2748
|
+
removed: firstChange.diff.removed,
|
|
2749
|
+
}
|
|
2750
|
+
: undefined,
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
function countDiffHunks(diff: ParsedDiff): number {
|
|
2755
|
+
return diff.lines.length === 0 ? 0 : diff.lines.filter((line) => line.type === "sep").length + 1
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
function getApplyPatchLine(diff: ParsedDiff, kind: ApplyPatchChangePreview["kind"]): number {
|
|
2759
|
+
if (kind === "add") {
|
|
2760
|
+
return diff.lines.find((line) => line.type === "add" && line.newNum !== null)?.newNum ?? 1
|
|
2761
|
+
}
|
|
2762
|
+
if (kind === "delete") {
|
|
2763
|
+
return diff.lines.find((line) => line.type === "del" && line.oldNum !== null)?.oldNum ?? 1
|
|
2764
|
+
}
|
|
2765
|
+
for (const line of diff.lines) {
|
|
2766
|
+
if (line.type === "add" && line.newNum !== null) return line.newNum
|
|
2767
|
+
if (line.type === "del" && line.oldNum !== null) return line.oldNum
|
|
2768
|
+
}
|
|
2769
|
+
return 0
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
function parsePatchBodyLine(rawLine: string): { marker: "+" | "-" | " "; content: string } {
|
|
2773
|
+
const marker = rawLine[0]
|
|
2774
|
+
if (marker === "+" || marker === "-" || marker === " ") return { marker, content: rawLine.slice(1) }
|
|
2775
|
+
return { marker: " ", content: rawLine }
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
function findLineSequence(haystack: string[], needle: string[], fromIndex = 0): number {
|
|
2779
|
+
if (needle.length === 0) return Math.max(0, fromIndex)
|
|
2780
|
+
outer: for (let i = Math.max(0, fromIndex); i <= haystack.length - needle.length; i++) {
|
|
2781
|
+
for (let j = 0; j < needle.length; j++) {
|
|
2782
|
+
if (haystack[i + j] !== needle[j]) continue outer
|
|
2783
|
+
}
|
|
2784
|
+
return i
|
|
2785
|
+
}
|
|
2786
|
+
return -1
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
function inferApplyPatchHunkStarts(
|
|
2790
|
+
lines: string[],
|
|
2791
|
+
sourceContent: string,
|
|
2792
|
+
): Array<{ oldStart: number | null; newStart: number | null }> {
|
|
2793
|
+
const sourceLines = normalizeToLf(sourceContent).split("\n")
|
|
2794
|
+
const hunks: string[][] = []
|
|
2795
|
+
let currentHunk: string[] | null = null
|
|
2796
|
+
for (const rawLine of lines) {
|
|
2797
|
+
if (rawLine.startsWith("*** Move to: ")) continue
|
|
2798
|
+
if (rawLine.startsWith("@@")) {
|
|
2799
|
+
if (currentHunk) hunks.push(currentHunk)
|
|
2800
|
+
currentHunk = []
|
|
2801
|
+
continue
|
|
2802
|
+
}
|
|
2803
|
+
if (!currentHunk) currentHunk = []
|
|
2804
|
+
currentHunk.push(rawLine)
|
|
2805
|
+
}
|
|
2806
|
+
if (currentHunk) hunks.push(currentHunk)
|
|
2807
|
+
|
|
2808
|
+
const starts: Array<{ oldStart: number | null; newStart: number | null }> = []
|
|
2809
|
+
let searchFrom = 0
|
|
2810
|
+
let lineDelta = 0
|
|
2811
|
+
for (const hunk of hunks) {
|
|
2812
|
+
const oldLines = hunk
|
|
2813
|
+
.map((rawLine) => parsePatchBodyLine(rawLine))
|
|
2814
|
+
.filter((line) => line.marker !== "+")
|
|
2815
|
+
.map((line) => line.content)
|
|
2816
|
+
let matchIndex = findLineSequence(sourceLines, oldLines, searchFrom)
|
|
2817
|
+
if (matchIndex === -1) matchIndex = findLineSequence(sourceLines, oldLines, 0)
|
|
2818
|
+
const oldStart = matchIndex === -1 ? null : matchIndex + 1
|
|
2819
|
+
const newStart = oldStart === null ? null : oldStart + lineDelta
|
|
2820
|
+
starts.push({ oldStart, newStart })
|
|
2821
|
+
if (matchIndex === -1) continue
|
|
2822
|
+
searchFrom = matchIndex + oldLines.length
|
|
2823
|
+
const added = hunk.filter((rawLine) => parsePatchBodyLine(rawLine).marker === "+").length
|
|
2824
|
+
const removed = hunk.filter((rawLine) => parsePatchBodyLine(rawLine).marker === "-").length
|
|
2825
|
+
lineDelta += added - removed
|
|
2826
|
+
}
|
|
2827
|
+
return starts
|
|
2828
|
+
}
|
|
2829
|
+
|
|
2830
|
+
function stripPatchLinePrefix(line: string, prefix: "+" | "-"): string {
|
|
2831
|
+
return line.startsWith(prefix) ? line.slice(1) : line
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
function trimDiffSeparators(lines: DiffLine[]): DiffLine[] {
|
|
2835
|
+
const trimmed = [...lines]
|
|
2836
|
+
while (trimmed[0]?.type === "sep") trimmed.shift()
|
|
2837
|
+
while (trimmed[trimmed.length - 1]?.type === "sep") trimmed.pop()
|
|
2838
|
+
return trimmed
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
function parseApplyPatchUpdateDiff(lines: string[], sourceContent?: string): ParsedDiff {
|
|
2842
|
+
const diffLines: DiffLine[] = []
|
|
2843
|
+
let added = 0
|
|
2844
|
+
let removed = 0
|
|
2845
|
+
let chars = 0
|
|
2846
|
+
let oldLine: number | null = null
|
|
2847
|
+
let newLine: number | null = null
|
|
2848
|
+
let inHunk = false
|
|
2849
|
+
const inferredStarts = sourceContent ? inferApplyPatchHunkStarts(lines, sourceContent) : []
|
|
2850
|
+
let hunkIndex = 0
|
|
2851
|
+
|
|
2852
|
+
for (const rawLine of lines) {
|
|
2853
|
+
if (rawLine.startsWith("*** Move to: ")) continue
|
|
2854
|
+
if (rawLine.startsWith("@@")) {
|
|
2855
|
+
if (diffLines.length > 0 && diffLines[diffLines.length - 1]?.type !== "sep") {
|
|
2856
|
+
diffLines.push({ type: "sep", oldNum: null, newNum: null, content: "" })
|
|
2857
|
+
}
|
|
2858
|
+
const match = rawLine.match(/^@@\s*-(\d+)(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s*@@/)
|
|
2859
|
+
const inferred = inferredStarts[hunkIndex] ?? { oldStart: null, newStart: null }
|
|
2860
|
+
oldLine = match ? Number.parseInt(match[1], 10) : inferred.oldStart
|
|
2861
|
+
newLine = match ? Number.parseInt(match[2], 10) : inferred.newStart
|
|
2862
|
+
hunkIndex++
|
|
2863
|
+
inHunk = true
|
|
2864
|
+
continue
|
|
2865
|
+
}
|
|
2866
|
+
if (rawLine === "\") continue
|
|
2867
|
+
if (!inHunk) {
|
|
2868
|
+
const inferred = inferredStarts[hunkIndex] ?? { oldStart: null, newStart: null }
|
|
2869
|
+
oldLine = inferred.oldStart
|
|
2870
|
+
newLine = inferred.newStart
|
|
2871
|
+
hunkIndex++
|
|
2872
|
+
inHunk = true
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
const { marker, content } = parsePatchBodyLine(rawLine)
|
|
2876
|
+
|
|
2877
|
+
chars += content.length
|
|
2878
|
+
if (marker === "+") {
|
|
2879
|
+
diffLines.push({ type: "add", oldNum: null, newNum: newLine, content })
|
|
2880
|
+
added++
|
|
2881
|
+
if (newLine !== null) newLine++
|
|
2882
|
+
continue
|
|
2883
|
+
}
|
|
2884
|
+
if (marker === "-") {
|
|
2885
|
+
diffLines.push({ type: "del", oldNum: oldLine, newNum: null, content })
|
|
2886
|
+
removed++
|
|
2887
|
+
if (oldLine !== null) oldLine++
|
|
2888
|
+
continue
|
|
2889
|
+
}
|
|
2890
|
+
diffLines.push({ type: "ctx", oldNum: oldLine, newNum: newLine, content })
|
|
2891
|
+
if (oldLine !== null) oldLine++
|
|
2892
|
+
if (newLine !== null) newLine++
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2895
|
+
return {
|
|
2896
|
+
lines: trimDiffSeparators(diffLines),
|
|
2897
|
+
added,
|
|
2898
|
+
removed,
|
|
2899
|
+
chars,
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
|
|
2903
|
+
function parseApplyPatchPreview(
|
|
2904
|
+
patchText: string,
|
|
2905
|
+
sp: (path: string) => string,
|
|
2906
|
+
cwd = process.cwd(),
|
|
2907
|
+
): ApplyPatchPreview {
|
|
2908
|
+
const normalized = patchText.replace(/\r\n/g, "\n")
|
|
2909
|
+
const lines = normalized.split("\n")
|
|
2910
|
+
const changes: ApplyPatchChangePreview[] = []
|
|
2911
|
+
let index = 0
|
|
2912
|
+
|
|
2913
|
+
const fileHeader = /^\*\*\* (Add|Update|Delete) File: (.+)$/
|
|
2914
|
+
const endHeader = /^\*\*\* End Patch$/
|
|
2915
|
+
|
|
2916
|
+
while (index < lines.length) {
|
|
2917
|
+
const line = lines[index]
|
|
2918
|
+
if (!line || line === "*** Begin Patch") {
|
|
2919
|
+
index++
|
|
2920
|
+
continue
|
|
2921
|
+
}
|
|
2922
|
+
if (endHeader.test(line)) break
|
|
2923
|
+
const header = line.match(fileHeader)
|
|
2924
|
+
if (!header) {
|
|
2925
|
+
index++
|
|
2926
|
+
continue
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
const kind = header[1].toLowerCase() as ApplyPatchChangePreview["kind"]
|
|
2930
|
+
const path = header[2].trim()
|
|
2931
|
+
index++
|
|
2932
|
+
|
|
2933
|
+
let moveTo: string | undefined
|
|
2934
|
+
const body: string[] = []
|
|
2935
|
+
while (index < lines.length && !fileHeader.test(lines[index]) && !endHeader.test(lines[index])) {
|
|
2936
|
+
if (lines[index].startsWith("*** Move to: ")) {
|
|
2937
|
+
moveTo = lines[index].slice("*** Move to: ".length).trim()
|
|
2938
|
+
index++
|
|
2939
|
+
continue
|
|
2940
|
+
}
|
|
2941
|
+
body.push(lines[index])
|
|
2942
|
+
index++
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
const displayPath = moveTo ? `${sp(path)} ${BORDER_COLOR}→${TRANSPARENT_RESET} ${sp(moveTo)}` : sp(path)
|
|
2946
|
+
let sourceContent: string | undefined
|
|
2947
|
+
if (kind === "update") {
|
|
2948
|
+
try {
|
|
2949
|
+
sourceContent = readFileSync(resolve(cwd, path), "utf8")
|
|
2950
|
+
} catch {
|
|
2951
|
+
sourceContent = undefined
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
const diff =
|
|
2955
|
+
kind === "add"
|
|
2956
|
+
? parseDiff("", body.map((entry) => stripPatchLinePrefix(entry, "+")).join("\n"))
|
|
2957
|
+
: kind === "delete"
|
|
2958
|
+
? parseDiff(body.map((entry) => stripPatchLinePrefix(entry, "-")).join("\n"), "")
|
|
2959
|
+
: parseApplyPatchUpdateDiff(body, sourceContent)
|
|
2960
|
+
changes.push({
|
|
2961
|
+
kind,
|
|
2962
|
+
path,
|
|
2963
|
+
displayPath,
|
|
2964
|
+
moveTo,
|
|
2965
|
+
diff,
|
|
2966
|
+
language: lang(moveTo || path),
|
|
2967
|
+
hunks: countDiffHunks(diff),
|
|
2968
|
+
summary: summarizeDiff(diff.added, diff.removed),
|
|
2969
|
+
line: getApplyPatchLine(diff, kind),
|
|
2970
|
+
})
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
const totalAdded = changes.reduce((sum, change) => sum + change.diff.added, 0)
|
|
2974
|
+
const totalRemoved = changes.reduce((sum, change) => sum + change.diff.removed, 0)
|
|
2975
|
+
const totalHunks = changes.reduce((sum, change) => sum + change.hunks, 0)
|
|
2976
|
+
const totalLines = changes.reduce((sum, change) => sum + change.diff.lines.length, 0)
|
|
2977
|
+
return {
|
|
2978
|
+
changes,
|
|
2979
|
+
totalAdded,
|
|
2980
|
+
totalRemoved,
|
|
2981
|
+
totalHunks,
|
|
2982
|
+
totalLines,
|
|
2983
|
+
summary: summarizeDiff(totalAdded, totalRemoved),
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
function describeApplyPatchChange(change: ApplyPatchChangePreview): string {
|
|
2988
|
+
if (change.moveTo) return `Rename ${change.displayPath}`
|
|
2989
|
+
if (change.kind === "add") return `Create ${change.displayPath}`
|
|
2990
|
+
if (change.kind === "delete") return `Delete ${change.displayPath}`
|
|
2991
|
+
return `Update ${change.displayPath}`
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
function formatLineMeta(line: number, theme: Theme): string {
|
|
2995
|
+
return line > 0 ? ` ${theme.fg("muted", `at line ${line}`)}` : ""
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
function formatApplyPatchLine(change: ApplyPatchChangePreview, theme: Theme): string {
|
|
2999
|
+
return formatLineMeta(change.line, theme)
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
function getCachedApplyPatchPreview(
|
|
3003
|
+
patchText: string,
|
|
3004
|
+
sp: (path: string) => string,
|
|
3005
|
+
ctx: any,
|
|
3006
|
+
): ApplyPatchPreview | null {
|
|
3007
|
+
if (!patchText) return null
|
|
3008
|
+
const key = `apply-meta:${ctx.cwd ?? process.cwd()}:${hashText(patchText)}`
|
|
3009
|
+
if (ctx.state?._applyPatchMetaKey === key && ctx.state._applyPatchPreview) {
|
|
3010
|
+
return ctx.state._applyPatchPreview as ApplyPatchPreview
|
|
3011
|
+
}
|
|
3012
|
+
try {
|
|
3013
|
+
const preview = parseApplyPatchPreview(patchText, sp, ctx.cwd ?? process.cwd())
|
|
3014
|
+
if (ctx.state) {
|
|
3015
|
+
ctx.state._applyPatchMetaKey = key
|
|
3016
|
+
ctx.state._applyPatchPreview = preview
|
|
3017
|
+
ctx.state._applyPatchMeta = buildApplyPatchResultMeta(preview)
|
|
3018
|
+
}
|
|
3019
|
+
return preview
|
|
3020
|
+
} catch {
|
|
3021
|
+
return null
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
function getApplyPatchResultMeta(args: any, ctx: any, sp: (path: string) => string): ApplyPatchResultMeta | null {
|
|
3026
|
+
const patchText = getStringArg(args ?? ctx?.args, "patchText", "patch_text")
|
|
3027
|
+
if (!patchText) return null
|
|
3028
|
+
const preview = getCachedApplyPatchPreview(patchText, sp, ctx)
|
|
3029
|
+
return preview && ctx.state?._applyPatchMeta ? (ctx.state._applyPatchMeta as ApplyPatchResultMeta) : null
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
function renderApplyPatchCall(args: any, theme: Theme, ctx: any, sp: (path: string) => string): Text {
|
|
3033
|
+
const patchText = getStringArg(args, "patchText", "patch_text")
|
|
3034
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => summarizeOpenAiToolCall("apply_patch", args, theme, sp))
|
|
3035
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
3036
|
+
const hdr = toolHeader("Apply Patch", summary, theme, toolStatusDot(ctx, theme), timer)
|
|
3037
|
+
|
|
3038
|
+
if (!ctx.argsComplete) return makeText(ctx.lastComponent, hdr)
|
|
3039
|
+
const preview = getCachedApplyPatchPreview(patchText, sp, ctx)
|
|
3040
|
+
if (!preview || preview.changes.length === 0) {
|
|
3041
|
+
ctx.state._openAiPatchFiles = []
|
|
3042
|
+
return makeText(ctx.lastComponent, hdr)
|
|
3043
|
+
}
|
|
3044
|
+
ctx.state._openAiPatchFiles = preview.changes.map((change) => change.displayPath)
|
|
3045
|
+
|
|
3046
|
+
const diffWidth = branchDiffWidth()
|
|
3047
|
+
const key = `apply-preview:${ctx.state._applyPatchMetaKey ?? hashText(patchText)}:${diffWidth}:${ctx.expanded ? 1 : 0}`
|
|
3048
|
+
if (ctx.state._applyPatchPreviewKey !== key) {
|
|
3049
|
+
ctx.state._applyPatchPreviewKey = key
|
|
3050
|
+
ctx.state._applyPatchPreviewBody = theme.fg("muted", "(rendering…)")
|
|
3051
|
+
ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
|
|
3052
|
+
const dc = resolveDiffColors(theme)
|
|
3053
|
+
if (preview.changes.length === 1) {
|
|
3054
|
+
const [change] = preview.changes
|
|
3055
|
+
renderSplit(change.diff, change.language, ctx.expanded ? MAX_PREVIEW_LINES : 32, dc, diffWidth)
|
|
3056
|
+
.then((rendered) => {
|
|
3057
|
+
if (ctx.state._applyPatchPreviewKey !== key) return
|
|
3058
|
+
ctx.state._applyPatchPreviewBody = `${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}\n${rendered}`
|
|
3059
|
+
ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
|
|
3060
|
+
ctx.invalidate()
|
|
3061
|
+
})
|
|
3062
|
+
.catch(() => {
|
|
3063
|
+
if (ctx.state._applyPatchPreviewKey !== key) return
|
|
3064
|
+
ctx.state._applyPatchPreviewBody = `${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}`
|
|
3065
|
+
ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
|
|
3066
|
+
ctx.invalidate()
|
|
3067
|
+
})
|
|
3068
|
+
} else {
|
|
3069
|
+
const maxShown = ctx.expanded ? preview.changes.length : Math.min(preview.changes.length, 3)
|
|
3070
|
+
const previewLines = ctx.expanded
|
|
3071
|
+
? Math.max(6, Math.floor(MAX_RENDER_LINES / Math.max(1, maxShown)))
|
|
3072
|
+
: Math.max(8, Math.floor(MAX_PREVIEW_LINES / Math.max(1, maxShown)))
|
|
3073
|
+
Promise.all(
|
|
3074
|
+
preview.changes.slice(0, maxShown).map((change, index) =>
|
|
3075
|
+
renderSplit(change.diff, change.language, previewLines, dc, diffWidth)
|
|
3076
|
+
.then(
|
|
3077
|
+
(rendered) =>
|
|
3078
|
+
`${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}\n${rendered}`,
|
|
3079
|
+
)
|
|
3080
|
+
.catch(
|
|
3081
|
+
() =>
|
|
3082
|
+
`${index + 1}. ${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}`,
|
|
3083
|
+
),
|
|
3084
|
+
),
|
|
3085
|
+
)
|
|
3086
|
+
.then((sections) => {
|
|
3087
|
+
if (ctx.state._applyPatchPreviewKey !== key) return
|
|
3088
|
+
const remainder = preview.changes.length - maxShown
|
|
3089
|
+
const suffix =
|
|
3090
|
+
remainder > 0
|
|
3091
|
+
? `\n${theme.fg("muted", `… ${remainder} more file patches${ctx.expanded ? "" : " • ctrl+o to expand"}`)}`
|
|
3092
|
+
: ""
|
|
3093
|
+
const summary = `${preview.changes.length} files ${preview.summary}`
|
|
3094
|
+
ctx.state._applyPatchPreviewBody = `${summary}\n\n${sections.join("\n\n")}${suffix}`
|
|
3095
|
+
ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
|
|
3096
|
+
ctx.invalidate()
|
|
3097
|
+
})
|
|
3098
|
+
.catch(() => {
|
|
3099
|
+
if (ctx.state._applyPatchPreviewKey !== key) return
|
|
3100
|
+
ctx.state._applyPatchPreviewBody = `${preview.changes.length} files ${preview.summary}`
|
|
3101
|
+
ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
|
|
3102
|
+
ctx.invalidate()
|
|
3103
|
+
})
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
const body = ctx.state._applyPatchPreviewDisplay as string | undefined
|
|
3108
|
+
return makeText(ctx.lastComponent, body ? `${hdr}\n${body}` : hdr)
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
function renderApplyPatchResult(result: any, isPartial: boolean, theme: Theme, ctx: any): Text {
|
|
3112
|
+
if (isPartial) {
|
|
3113
|
+
setupBlinkTimer(ctx)
|
|
3114
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Applying Patch..."), theme))
|
|
3115
|
+
}
|
|
3116
|
+
clearBlinkTimer(ctx)
|
|
3117
|
+
|
|
3118
|
+
if (ctx.isError) {
|
|
3119
|
+
const raw = getTextContent(result).trim()
|
|
3120
|
+
const firstLine = raw ? raw.split("\n")[0] : "Apply patch failed"
|
|
3121
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("error", firstLine), theme))
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
const meta = getApplyPatchResultMeta(ctx.args, ctx, (path: string) => shortPath(ctx.cwd ?? process.cwd(), path))
|
|
3125
|
+
if (!meta || meta.changeCount === 0) {
|
|
3126
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("success", "Applied"), theme))
|
|
3127
|
+
}
|
|
3128
|
+
|
|
3129
|
+
if (meta.changeCount === 1 && meta.firstChange) {
|
|
3130
|
+
const change = meta.firstChange
|
|
3131
|
+
const summary = diffSummaryWithMeta(
|
|
3132
|
+
change.added,
|
|
3133
|
+
change.removed,
|
|
3134
|
+
change.hunks,
|
|
3135
|
+
change.kind === "add" ? "new file" : change.kind === "delete" ? "delete" : "",
|
|
3136
|
+
)
|
|
3137
|
+
return makeText(
|
|
3138
|
+
ctx.lastComponent,
|
|
3139
|
+
withBranch(
|
|
3140
|
+
`${theme.fg("success", "Applied")} ${theme.fg("muted", change.displayPath)} ${summary}${formatLineMeta(change.line, theme)}`,
|
|
3141
|
+
theme,
|
|
3142
|
+
),
|
|
3143
|
+
)
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
const summary = diffSummaryWithMeta(meta.totalAdded, meta.totalRemoved, meta.totalHunks, "")
|
|
3147
|
+
return makeText(
|
|
3148
|
+
ctx.lastComponent,
|
|
3149
|
+
withBranch(
|
|
3150
|
+
`${theme.fg("success", "Applied")} ${meta.changeCount} files ${summary}${meta.totalLines ? ` ${theme.fg("muted", `(${meta.totalLines} diff lines)`)}` : ""}`,
|
|
3151
|
+
theme,
|
|
3152
|
+
),
|
|
3153
|
+
)
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
/** Max chars shown for a single arg value before truncation. */
|
|
3157
|
+
const MCP_ARG_VALUE_MAX = 60
|
|
3158
|
+
/** Max total chars for the entire (key=val, …) suffix. */
|
|
3159
|
+
const MCP_ARGS_SUFFIX_MAX = 120
|
|
3160
|
+
|
|
3161
|
+
/**
|
|
3162
|
+
* Keys whose values are typically long blobs (file paths list, prompt text,
|
|
3163
|
+
* raw content). These get truncated more aggressively or skipped when many
|
|
3164
|
+
* other keys are present.
|
|
3165
|
+
*/
|
|
3166
|
+
|
|
3167
|
+
/**
|
|
3168
|
+
* For an MCP gateway call whose args contain `tool`, parse the nested args
|
|
3169
|
+
* JSON and return a compact `(key=val, key=val)` style plain string (no ANSI),
|
|
3170
|
+
* matching the style used by the `read` tool for offset/limit.
|
|
3171
|
+
*
|
|
3172
|
+
* When `expanded` is false (collapsed view) long values are truncated and the
|
|
3173
|
+
* whole suffix is capped at MCP_ARGS_SUFFIX_MAX chars so the header stays on
|
|
3174
|
+
* one line. When `expanded` is true all values are shown in full.
|
|
3175
|
+
*/
|
|
3176
|
+
export function summarizeMcpToolInvocationArgs(args: any, expanded = false): string {
|
|
3177
|
+
const rawArgs = getStringArg(args, "args")
|
|
3178
|
+
if (!rawArgs) return ""
|
|
3179
|
+
try {
|
|
3180
|
+
const parsed = JSON.parse(rawArgs)
|
|
3181
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return ""
|
|
3182
|
+
|
|
3183
|
+
const parts: string[] = []
|
|
3184
|
+
// Always use original key order — collapsed mode just stops at the cap.
|
|
3185
|
+
const ordered = Object.entries(parsed as Record<string, unknown>)
|
|
3186
|
+
for (const [key, val] of ordered) {
|
|
3187
|
+
if (val === undefined || val === null) continue
|
|
3188
|
+
let display: string
|
|
3189
|
+
if (Array.isArray(val)) {
|
|
3190
|
+
if (val.length === 0) continue
|
|
3191
|
+
if (expanded) {
|
|
3192
|
+
display = val.map((v) => String(v)).join(", ")
|
|
3193
|
+
} else {
|
|
3194
|
+
const first = String(val[0])
|
|
3195
|
+
display =
|
|
3196
|
+
val.length === 1
|
|
3197
|
+
? summarizeText(first, MCP_ARG_VALUE_MAX)
|
|
3198
|
+
: `${summarizeText(first, 30)} +${val.length - 1}`
|
|
3199
|
+
}
|
|
3200
|
+
} else if (typeof val === "object") {
|
|
3201
|
+
continue // skip nested objects
|
|
3202
|
+
} else {
|
|
3203
|
+
display = expanded ? String(val) : summarizeText(String(val), MCP_ARG_VALUE_MAX)
|
|
3204
|
+
}
|
|
3205
|
+
const part = `${key}=${display}`
|
|
3206
|
+
// In collapsed mode stop adding parts if we'd exceed the suffix cap.
|
|
3207
|
+
if (!expanded) {
|
|
3208
|
+
const currentLen = parts.reduce((n, p) => n + p.length + 2, 0)
|
|
3209
|
+
if (currentLen + part.length > MCP_ARGS_SUFFIX_MAX) break
|
|
3210
|
+
}
|
|
3211
|
+
parts.push(part)
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
if (parts.length === 0) return ""
|
|
3215
|
+
return `(${parts.join(", ")})`
|
|
3216
|
+
} catch {
|
|
3217
|
+
// not valid JSON — ignore
|
|
3218
|
+
}
|
|
3219
|
+
return ""
|
|
3220
|
+
}
|
|
3221
|
+
|
|
3222
|
+
function summarizeMcpToolCall(args: any, theme: Theme, expanded = false): string {
|
|
3223
|
+
const tool = getStringArg(args, "tool")
|
|
3224
|
+
if (tool) {
|
|
3225
|
+
const argsSummary = summarizeMcpToolInvocationArgs(args, expanded)
|
|
3226
|
+
return argsSummary ? theme.fg("muted", argsSummary) : ""
|
|
3227
|
+
}
|
|
3228
|
+
const connect = getStringArg(args, "connect")
|
|
3229
|
+
if (connect) return connect
|
|
3230
|
+
const search = getStringArg(args, "search", "describe", "server", "action")
|
|
3231
|
+
if (search) return summarizeText(search, 72)
|
|
3232
|
+
return theme.fg("muted", "status")
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
/**
|
|
3236
|
+
* Returns the display label and summary for an MCP gateway call.
|
|
3237
|
+
* - Tool invocation (`args.tool` present): label = humanized tool name, summary = args preview
|
|
3238
|
+
* - Discovery (`args.search` / `args.describe` / …): label = "Tool search" / "Tool describe" / …
|
|
3239
|
+
* - Connect: label = "Tool connect"
|
|
3240
|
+
*/
|
|
3241
|
+
export function mcpCallLabelAndSummary(
|
|
3242
|
+
args: any,
|
|
3243
|
+
theme: Theme,
|
|
3244
|
+
expanded = false,
|
|
3245
|
+
): { label: string; summary: string } {
|
|
3246
|
+
const tool = getStringArg(args, "tool")
|
|
3247
|
+
if (tool) {
|
|
3248
|
+
const server = getStringArg(args, "server")
|
|
3249
|
+
const toolDisplay = tool.replace(/_/g, " ")
|
|
3250
|
+
const label = server ? `${server} - ${toolDisplay}` : toolDisplay
|
|
3251
|
+
const rawSuffix = summarizeMcpToolInvocationArgs(args, expanded)
|
|
3252
|
+
const summary = rawSuffix ? theme.fg("muted", rawSuffix) : ""
|
|
3253
|
+
return { label, summary }
|
|
3254
|
+
}
|
|
3255
|
+
if (getStringArg(args, "connect")) {
|
|
3256
|
+
return { label: "Tool connect", summary: theme.fg("muted", `(server=${getStringArg(args, "connect")})`) }
|
|
3257
|
+
}
|
|
3258
|
+
if (getStringArg(args, "describe")) {
|
|
3259
|
+
return { label: "Tool describe", summary: theme.fg("muted", `(tool=${summarizeText(getStringArg(args, "describe"), 60)})`) }
|
|
3260
|
+
}
|
|
3261
|
+
if (getStringArg(args, "search")) {
|
|
3262
|
+
return { label: "Tool search", summary: theme.fg("muted", `(query=${summarizeText(getStringArg(args, "search"), 60)})`) }
|
|
3263
|
+
}
|
|
3264
|
+
if (getStringArg(args, "server")) {
|
|
3265
|
+
return { label: "Tool search", summary: theme.fg("muted", `(server=${summarizeText(getStringArg(args, "server"), 60)})`) }
|
|
3266
|
+
}
|
|
3267
|
+
if (getStringArg(args, "action")) {
|
|
3268
|
+
return { label: "Tool action", summary: theme.fg("muted", `(action=${summarizeText(getStringArg(args, "action"), 60)})`) }
|
|
3269
|
+
}
|
|
3270
|
+
return { label: "MCP", summary: theme.fg("muted", "(status)") }
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
function summarizeGenericToolCall(name: string, args: any, theme: Theme, sp: (path: string) => string): string {
|
|
3274
|
+
if (isMcpToolName(name)) return summarizeMcpToolCall(args, theme)
|
|
3275
|
+
return summarizeOpenAiToolCall(name, args, theme, sp)
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
function renderMcpToolResult(result: any, expanded: boolean, isPartial: boolean, theme: Theme, ctx: any): Text {
|
|
3279
|
+
if (isPartial) {
|
|
3280
|
+
setupBlinkTimer(ctx)
|
|
3281
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "MCP running..."), theme))
|
|
3282
|
+
}
|
|
3283
|
+
clearBlinkTimer(ctx)
|
|
3284
|
+
|
|
3285
|
+
const mode = getMode(readSettings().mcpOutputMode, ["hidden", "summary", "preview"] as const, "preview")
|
|
3286
|
+
if (mode === "hidden") return makeText(ctx.lastComponent, "")
|
|
3287
|
+
|
|
3288
|
+
const raw = getTextContent(result).trim()
|
|
3289
|
+
const lines = raw ? raw.split("\n") : []
|
|
3290
|
+
if (lines.length === 0) {
|
|
3291
|
+
return makeText(
|
|
3292
|
+
ctx.lastComponent,
|
|
3293
|
+
withBranch(theme.fg(ctx.isError ? "error" : "success", ctx.isError ? "Failed" : "Done"), theme),
|
|
3294
|
+
)
|
|
3295
|
+
}
|
|
3296
|
+
|
|
3297
|
+
const statusText = ctx.isError
|
|
3298
|
+
? theme.fg("error", lines[0])
|
|
3299
|
+
: theme.fg("muted", `${lines.length} line${lines.length === 1 ? "" : "s"} returned`)
|
|
3300
|
+
if (mode === "summary") return makeText(ctx.lastComponent, withBranch(statusText, theme))
|
|
3301
|
+
if (!expanded && !ctx.isError)
|
|
3302
|
+
return makeText(ctx.lastComponent, withBranch(`${statusText}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
3303
|
+
const preview = buildPreviewText(
|
|
3304
|
+
lines.map((line) => theme.fg(ctx.isError ? "error" : "toolOutput", line || " ")),
|
|
3305
|
+
true,
|
|
3306
|
+
theme,
|
|
3307
|
+
previewLimit(),
|
|
3308
|
+
)
|
|
3309
|
+
return makeText(ctx.lastComponent, withBranch(`${statusText}\n${preview}`, theme))
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
export function summarizeOpenAiToolCall(name: string, args: any, theme: Theme, sp: (path: string) => string): string {
|
|
3313
|
+
switch (name) {
|
|
3314
|
+
case "apply_patch": {
|
|
3315
|
+
const patchText = getStringArg(args, "patchText", "patch_text")
|
|
3316
|
+
const files = extractApplyPatchFiles(patchText)
|
|
3317
|
+
if (files.length === 0) return theme.fg("muted", "patch")
|
|
3318
|
+
if (files.length === 1) return sp(files[0])
|
|
3319
|
+
return `${sp(files[0])} ${theme.fg("muted", `(+${files.length - 1} files)`)}`
|
|
3320
|
+
}
|
|
3321
|
+
case "webfetch":
|
|
3322
|
+
return getStringArg(args, "url") || theme.fg("muted", "fetch page")
|
|
3323
|
+
case "fetch_content": {
|
|
3324
|
+
const url = getStringArg(args, "url")
|
|
3325
|
+
if (url) return url
|
|
3326
|
+
const urls = getStringArrayArg(args, "urls")
|
|
3327
|
+
if (urls.length === 0) return theme.fg("muted", "fetch content")
|
|
3328
|
+
if (urls.length === 1) return urls[0]
|
|
3329
|
+
return `${urls[0]} ${theme.fg("muted", `(+${urls.length - 1} urls)`)}`
|
|
3330
|
+
}
|
|
3331
|
+
case "get_search_content":
|
|
3332
|
+
return getStringArg(args, "responseId", "response_id") || theme.fg("muted", "load cached content")
|
|
3333
|
+
case "web_search": {
|
|
3334
|
+
const query = getStringArg(args, "query")
|
|
3335
|
+
if (query) return summarizeText(query, 72)
|
|
3336
|
+
const queries = getStringArrayArg(args, "queries")
|
|
3337
|
+
if (queries.length === 0) return theme.fg("muted", "search web")
|
|
3338
|
+
if (queries.length === 1) return summarizeText(queries[0], 72)
|
|
3339
|
+
return `${summarizeText(queries[0], 48)} ${theme.fg("muted", `(+${queries.length - 1} queries)`)}`
|
|
3340
|
+
}
|
|
3341
|
+
case "code_search":
|
|
3342
|
+
return summarizeText(getStringArg(args, "query") || "search code", 72)
|
|
3343
|
+
case "question":
|
|
3344
|
+
return summarizeText(getStringArg(args, "question") || "ask user", 72)
|
|
3345
|
+
case "questionnaire": {
|
|
3346
|
+
const qs = Array.isArray(args?.questions) ? (args.questions as Array<Record<string, unknown>>) : []
|
|
3347
|
+
if (qs.length === 0) return theme.fg("muted", "questionnaire")
|
|
3348
|
+
let firstText = ""
|
|
3349
|
+
for (const key of ["question", "prompt", "text"]) {
|
|
3350
|
+
const value = qs[0]?.[key]
|
|
3351
|
+
if (typeof value === "string") {
|
|
3352
|
+
firstText = value
|
|
3353
|
+
break
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
if (!firstText) return `${qs.length} question${qs.length === 1 ? "" : "s"}`
|
|
3357
|
+
if (qs.length === 1) return summarizeText(firstText, 72)
|
|
3358
|
+
return `${summarizeText(firstText, 48)} ${theme.fg("muted", `(+${qs.length - 1} more)`)}`
|
|
3359
|
+
}
|
|
3360
|
+
case "context_tag":
|
|
3361
|
+
return getStringArg(args, "name") || theme.fg("muted", "save point")
|
|
3362
|
+
case "context_log":
|
|
3363
|
+
return theme.fg("muted", "history")
|
|
3364
|
+
case "context_checkout":
|
|
3365
|
+
return getStringArg(args, "target") || theme.fg("muted", "checkout context")
|
|
3366
|
+
case "annotate":
|
|
3367
|
+
return getStringArg(args, "url") || theme.fg("muted", "current tab")
|
|
3368
|
+
case "alpha_search":
|
|
3369
|
+
return summarizeText(getStringArg(args, "query") || "search papers", 72)
|
|
3370
|
+
case "alpha_get_paper":
|
|
3371
|
+
case "alpha_ask_paper":
|
|
3372
|
+
case "alpha_annotate_paper":
|
|
3373
|
+
return getStringArg(args, "paper") || theme.fg("muted", "paper")
|
|
3374
|
+
case "alpha_read_code":
|
|
3375
|
+
return getStringArg(args, "githubUrl", "github_url") || theme.fg("muted", "repository")
|
|
3376
|
+
case "Skill":
|
|
3377
|
+
// SkillToolSchema accepts both 'skill' (primary) and 'name' (alias for Claude Code compat).
|
|
3378
|
+
// The adapter passes 'skill'; direct tool calls may pass either. Check both before falling back.
|
|
3379
|
+
return getStringArg(args, "skill") || getStringArg(args, "name") || theme.fg("muted", "run skill")
|
|
3380
|
+
case "EnterPlanMode":
|
|
3381
|
+
return theme.fg("muted", "enable read-only planning")
|
|
3382
|
+
case "ExitPlanMode":
|
|
3383
|
+
return theme.fg("muted", "present plan")
|
|
3384
|
+
case "set_phase":
|
|
3385
|
+
return getStringArg(args, "phase") || theme.fg("muted", "set phase")
|
|
3386
|
+
case "Agent":
|
|
3387
|
+
return summarizeText(getStringArg(args, "description", "prompt") || "launch agent", 72)
|
|
3388
|
+
case "get_subagent_result":
|
|
3389
|
+
return getStringArg(args, "agent_id") || theme.fg("muted", "agent result")
|
|
3390
|
+
case "steer_subagent":
|
|
3391
|
+
return getStringArg(args, "agent_id") || theme.fg("muted", "steer agent")
|
|
3392
|
+
case "TaskCreate":
|
|
3393
|
+
return summarizeText(getStringArg(args, "subject") || "create task", 72)
|
|
3394
|
+
case "TaskList":
|
|
3395
|
+
return theme.fg("muted", "task list")
|
|
3396
|
+
case "TaskGet":
|
|
3397
|
+
case "TaskUpdate":
|
|
3398
|
+
return getStringArg(args, "taskId", "task_id") || theme.fg("muted", "task")
|
|
3399
|
+
case "TaskOutput":
|
|
3400
|
+
case "TaskStop":
|
|
3401
|
+
return getStringArg(args, "task_id", "taskId") || theme.fg("muted", "background task")
|
|
3402
|
+
case "TaskExecute": {
|
|
3403
|
+
const taskIds = getStringArrayArg(args, "task_ids", "taskIds")
|
|
3404
|
+
if (taskIds.length === 0) return theme.fg("muted", "start tasks")
|
|
3405
|
+
return taskIds.length === 1 ? taskIds[0] : `${taskIds[0]} ${theme.fg("muted", `(+${taskIds.length - 1} tasks)`)}`
|
|
3406
|
+
}
|
|
3407
|
+
default:
|
|
3408
|
+
return summarizeText(
|
|
3409
|
+
getStringArg(args, "path", "file_path", "url", "query", "name", "subject", "tool", "description", "prompt") ||
|
|
3410
|
+
humanizeToolName(name),
|
|
3411
|
+
72,
|
|
3412
|
+
)
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
|
|
3416
|
+
interface ParsedTaskListLine {
|
|
3417
|
+
id: string
|
|
3418
|
+
status: string
|
|
3419
|
+
subject: string
|
|
3420
|
+
}
|
|
3421
|
+
|
|
3422
|
+
function parseTaskListLine(line: string): ParsedTaskListLine | null {
|
|
3423
|
+
const match = line.match(/^#(\d+) \[([^\]]+)\] (.+)$/)
|
|
3424
|
+
if (!match) return null
|
|
3425
|
+
return {
|
|
3426
|
+
id: match[1],
|
|
3427
|
+
status: match[2],
|
|
3428
|
+
subject: match[3],
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
|
|
3432
|
+
function formatTaskStatus(status: string, theme: Theme): string {
|
|
3433
|
+
if (status === "completed") return theme.fg("success", status)
|
|
3434
|
+
if (status === "in_progress") return theme.fg("warning", status)
|
|
3435
|
+
return theme.fg("muted", status)
|
|
3436
|
+
}
|
|
3437
|
+
|
|
3438
|
+
function formatOpenAiSuccessLine(name: string, line: string, theme: Theme): string {
|
|
3439
|
+
const trimmed = line.trim()
|
|
3440
|
+
if (!trimmed) return theme.fg("success", "Done")
|
|
3441
|
+
|
|
3442
|
+
if (name === "TaskCreate") {
|
|
3443
|
+
const match = trimmed.match(/^Task #(\d+) created successfully: (.+)$/)
|
|
3444
|
+
if (match) {
|
|
3445
|
+
return `${theme.fg("success", "Created task")} ${theme.fg("accent", `#${match[1]}`)} ${theme.fg("muted", match[2])}`
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
|
|
3449
|
+
if (name === "TaskUpdate") {
|
|
3450
|
+
const match = trimmed.match(/^Updated task #(\d+) (.+)$/)
|
|
3451
|
+
if (match) {
|
|
3452
|
+
return `${theme.fg("success", "Updated task")} ${theme.fg("accent", `#${match[1]}`)} ${theme.fg("muted", match[2])}`
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3456
|
+
if (name === "TaskExecute") {
|
|
3457
|
+
return `${theme.fg("success", "Started")} ${theme.fg("muted", trimmed)}`
|
|
3458
|
+
}
|
|
3459
|
+
|
|
3460
|
+
if (name === "context_tag") {
|
|
3461
|
+
const match = trimmed.match(/^Created tag '([^']+)' at (.+)$/)
|
|
3462
|
+
if (match) {
|
|
3463
|
+
return `${theme.fg("success", "Created tag")} ${theme.fg("accent", match[1])} ${theme.fg("muted", match[2])}`
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3467
|
+
if (name === "context_checkout") {
|
|
3468
|
+
return `${theme.fg("success", "Checked out")} ${theme.fg("muted", trimmed.replace(/^Checked out\s*/i, ""))}`
|
|
3469
|
+
}
|
|
3470
|
+
|
|
3471
|
+
if (name === "TaskStop") {
|
|
3472
|
+
return `${theme.fg("success", "Stopped")} ${theme.fg("muted", trimmed)}`
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3475
|
+
return theme.fg("muted", trimmed)
|
|
3476
|
+
}
|
|
3477
|
+
|
|
3478
|
+
function renderTaskListResult(lines: string[], expanded: boolean, theme: Theme, ctx: any): Text {
|
|
3479
|
+
const tasks = lines.map(parseTaskListLine).filter((task): task is ParsedTaskListLine => task !== null)
|
|
3480
|
+
if (tasks.length === 0) {
|
|
3481
|
+
const text =
|
|
3482
|
+
lines.length === 0
|
|
3483
|
+
? theme.fg("muted", "no tasks")
|
|
3484
|
+
: buildPreviewText(
|
|
3485
|
+
lines.map((line) => theme.fg("dim", line)),
|
|
3486
|
+
expanded,
|
|
3487
|
+
theme,
|
|
3488
|
+
previewLimit(),
|
|
3489
|
+
)
|
|
3490
|
+
return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
3491
|
+
}
|
|
3492
|
+
|
|
3493
|
+
const pending = tasks.filter((task) => task.status === "pending").length
|
|
3494
|
+
const inProgress = tasks.filter((task) => task.status === "in_progress").length
|
|
3495
|
+
const completed = tasks.filter((task) => task.status === "completed").length
|
|
3496
|
+
let summary = theme.fg("muted", `${tasks.length} tasks`)
|
|
3497
|
+
const parts: string[] = []
|
|
3498
|
+
if (inProgress > 0) parts.push(`${theme.fg("warning", String(inProgress))} in progress`)
|
|
3499
|
+
if (pending > 0) parts.push(`${theme.fg("muted", String(pending))} pending`)
|
|
3500
|
+
if (completed > 0) parts.push(`${theme.fg("success", String(completed))} completed`)
|
|
3501
|
+
if (parts.length > 0) summary += ` ${theme.fg("muted", "•")} ${parts.join(` ${theme.fg("muted", "•")} `)}`
|
|
3502
|
+
|
|
3503
|
+
if (!expanded) {
|
|
3504
|
+
return makeText(ctx.lastComponent, withBranch(`${summary}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
const shown = tasks.slice(0, previewLimit())
|
|
3508
|
+
const preview = shown.map(
|
|
3509
|
+
(task) =>
|
|
3510
|
+
`${theme.fg("accent", `#${task.id}`)} ${formatTaskStatus(task.status, theme)} ${theme.fg("dim", task.subject)}`,
|
|
3511
|
+
)
|
|
3512
|
+
const remaining = tasks.length - shown.length
|
|
3513
|
+
if (remaining > 0) preview.push(theme.fg("muted", `… ${remaining} more tasks`))
|
|
3514
|
+
return makeText(ctx.lastComponent, withBranch(`${summary}\n${preview.join("\n")}`, theme))
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3517
|
+
function getFirstImageBlock(result: any): { data: string; mimeType: string } | undefined {
|
|
3518
|
+
if (!Array.isArray(result?.content)) return undefined
|
|
3519
|
+
return result.content.find(
|
|
3520
|
+
(block: any) => block?.type === "image" && typeof block.data === "string" && typeof block.mimeType === "string",
|
|
3521
|
+
)
|
|
3522
|
+
}
|
|
3523
|
+
|
|
3524
|
+
function getReadImageFallback(result: any, ctx: any): string {
|
|
3525
|
+
const image = getFirstImageBlock(result)
|
|
3526
|
+
if (!image) return ""
|
|
3527
|
+
let dimensions
|
|
3528
|
+
try {
|
|
3529
|
+
dimensions = getImageDimensions(image.data, image.mimeType) ?? undefined
|
|
3530
|
+
} catch {
|
|
3531
|
+
dimensions = undefined
|
|
3532
|
+
}
|
|
3533
|
+
const path = getStringArg(ctx.args, "path", "file_path")
|
|
3534
|
+
const filename = path ? shortPath(ctx.cwd ?? process.cwd(), path) : undefined
|
|
3535
|
+
return imageFallback(image.mimeType, dimensions, filename)
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
function renderReadImageResult(result: any, expanded: boolean, theme: Theme, ctx: any): Text {
|
|
3539
|
+
const image = getFirstImageBlock(result)
|
|
3540
|
+
const mimeType = image?.mimeType ?? "image"
|
|
3541
|
+
const summary = `${theme.fg("success", "Image loaded")} ${theme.fg("muted", `[${mimeType}]`)}`
|
|
3542
|
+
if (!expanded) {
|
|
3543
|
+
return makeText(ctx.lastComponent, withBranch(`${summary}${theme.fg("muted", " • ctrl+o to show")}`, theme))
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
const noteLines = getTextContent(result)
|
|
3547
|
+
.split("\n")
|
|
3548
|
+
.map((line) => line.trim())
|
|
3549
|
+
.filter((line) => line && !/^Read image file\b/i.test(line))
|
|
3550
|
+
const lines = [summary, ...noteLines.map((line) => theme.fg("dim", line))]
|
|
3551
|
+
if (!getCapabilities().images || !ctx.showImages) {
|
|
3552
|
+
const fallback = getReadImageFallback(result, ctx)
|
|
3553
|
+
if (fallback) lines.push(theme.fg("toolOutput", fallback))
|
|
3554
|
+
}
|
|
3555
|
+
return makeText(ctx.lastComponent, withBranch(lines.join("\n"), theme))
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
function renderOpenAiToolResult(
|
|
3559
|
+
name: string,
|
|
3560
|
+
result: any,
|
|
3561
|
+
expanded: boolean,
|
|
3562
|
+
isPartial: boolean,
|
|
3563
|
+
theme: Theme,
|
|
3564
|
+
ctx: any,
|
|
3565
|
+
): Text {
|
|
3566
|
+
if (isPartial) {
|
|
3567
|
+
setupBlinkTimer(ctx)
|
|
3568
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", `${humanizeToolName(name)}...`), theme))
|
|
3569
|
+
}
|
|
3570
|
+
clearBlinkTimer(ctx)
|
|
3571
|
+
|
|
3572
|
+
const raw = getTextContent(result).trim()
|
|
3573
|
+
const lines = raw ? raw.split("\n") : []
|
|
3574
|
+
const patchFiles = Array.isArray(ctx.state?._openAiPatchFiles) ? ctx.state._openAiPatchFiles : []
|
|
3575
|
+
|
|
3576
|
+
if (lines.length === 0) {
|
|
3577
|
+
if (patchFiles.length > 0) {
|
|
3578
|
+
const suffix = patchFiles.length === 1 ? patchFiles[0] : `${patchFiles.length} files`
|
|
3579
|
+
return makeText(
|
|
3580
|
+
ctx.lastComponent,
|
|
3581
|
+
withBranch(
|
|
3582
|
+
`${theme.fg(ctx.isError ? "error" : "success", ctx.isError ? "Failed" : "Applied")} ${theme.fg("muted", suffix)}`,
|
|
3583
|
+
theme,
|
|
3584
|
+
),
|
|
3585
|
+
)
|
|
3586
|
+
}
|
|
3587
|
+
return makeText(
|
|
3588
|
+
ctx.lastComponent,
|
|
3589
|
+
withBranch(theme.fg(ctx.isError ? "error" : "success", ctx.isError ? "Failed" : "Done"), theme),
|
|
3590
|
+
)
|
|
3591
|
+
}
|
|
3592
|
+
|
|
3593
|
+
if (!ctx.isError && name === "TaskList") {
|
|
3594
|
+
return renderTaskListResult(lines, expanded, theme, ctx)
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
const statusText = ctx.isError
|
|
3598
|
+
? theme.fg("error", lines[0])
|
|
3599
|
+
: theme.fg("muted", `${lines.length} line${lines.length === 1 ? "" : "s"} returned`)
|
|
3600
|
+
if (!expanded && !ctx.isError) {
|
|
3601
|
+
return makeText(ctx.lastComponent, withBranch(`${statusText}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3604
|
+
if (!ctx.isError && lines.length === 1) {
|
|
3605
|
+
return makeText(ctx.lastComponent, withBranch(formatOpenAiSuccessLine(name, lines[0], theme), theme))
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
const preview =
|
|
3609
|
+
lines.length === 1
|
|
3610
|
+
? theme.fg(ctx.isError ? "error" : "dim", lines[0])
|
|
3611
|
+
: buildPreviewText(
|
|
3612
|
+
lines.map((line) => theme.fg(ctx.isError ? "error" : "dim", line || " ")),
|
|
3613
|
+
true,
|
|
3614
|
+
theme,
|
|
3615
|
+
previewLimit(),
|
|
3616
|
+
)
|
|
3617
|
+
return makeText(ctx.lastComponent, withBranch(`${statusText}\n${preview}`, theme))
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
// ===========================================================================
|
|
3621
|
+
// Extension
|
|
3622
|
+
// ===========================================================================
|
|
3623
|
+
|
|
3624
|
+
export default function (pi: ExtensionAPI) {
|
|
3625
|
+
patchToolRenderCacheInvalidation()
|
|
3626
|
+
patchReadImageExpansion()
|
|
3627
|
+
patchGlobalToolBorders()
|
|
3628
|
+
patchToolExecutionRenderers()
|
|
3629
|
+
patchUserMessageRender()
|
|
3630
|
+
patchAssistantMessageRender()
|
|
3631
|
+
applyDiffPalette()
|
|
3632
|
+
registerThinkingLabels(pi)
|
|
3633
|
+
|
|
3634
|
+
// /cc-tools command — toggle tool border style at runtime
|
|
3635
|
+
const TOOL_MODES = ["outlines", "transparent", "default"] as const
|
|
3636
|
+
pi.registerCommand("cc-tools", {
|
|
3637
|
+
description:
|
|
3638
|
+
"Switch tool display style: outlines (lines around tools), transparent (no chrome), default (pi built-in backgrounds)",
|
|
3639
|
+
getArgumentCompletions(prefix) {
|
|
3640
|
+
return TOOL_MODES.filter((m) => m.startsWith(prefix)).map((m) => ({
|
|
3641
|
+
value: m,
|
|
3642
|
+
label: m,
|
|
3643
|
+
description:
|
|
3644
|
+
m === "outlines"
|
|
3645
|
+
? "Horizontal rules around each tool (default)"
|
|
3646
|
+
: m === "transparent"
|
|
3647
|
+
? "No borders or backgrounds"
|
|
3648
|
+
: "Pi built-in tool backgrounds",
|
|
3649
|
+
}))
|
|
3650
|
+
},
|
|
3651
|
+
async handler(args, ctx) {
|
|
3652
|
+
const mode = args.trim().toLowerCase()
|
|
3653
|
+
if (!mode) {
|
|
3654
|
+
if (ctx.hasUI) ctx.ui.notify(`Tool style: ${toolBackgroundMode}`, "info")
|
|
3655
|
+
return
|
|
3656
|
+
}
|
|
3657
|
+
if (!(TOOL_MODES as readonly string[]).includes(mode)) {
|
|
3658
|
+
if (ctx.hasUI) ctx.ui.notify(`Unknown mode "${mode}". Options: ${TOOL_MODES.join(", ")}`, "error")
|
|
3659
|
+
return
|
|
3660
|
+
}
|
|
3661
|
+
toolBackgroundOverride = mode as typeof toolBackgroundMode
|
|
3662
|
+
toolBackgroundMode = toolBackgroundOverride
|
|
3663
|
+
writeSettingsKey("toolBackground", mode)
|
|
3664
|
+
if (ctx.hasUI) {
|
|
3665
|
+
applyToolBackgroundMode(ctx.ui.theme)
|
|
3666
|
+
ctx.ui.notify(`Tool style → ${mode}`, "info")
|
|
3667
|
+
}
|
|
3668
|
+
},
|
|
3669
|
+
})
|
|
3670
|
+
|
|
3671
|
+
// /cc-theme command — toggle pi-theme-adaptive coloring at runtime.
|
|
3672
|
+
const THEME_MODES = ["on", "off", "toggle", "status"] as const
|
|
3673
|
+
pi.registerCommand("cc-theme", {
|
|
3674
|
+
description: "Toggle whether tool borders / branch rules / diff colors follow the active pi theme",
|
|
3675
|
+
getArgumentCompletions(prefix) {
|
|
3676
|
+
return THEME_MODES.filter((m) => m.startsWith(prefix)).map((m) => ({
|
|
3677
|
+
value: m,
|
|
3678
|
+
label: m,
|
|
3679
|
+
description:
|
|
3680
|
+
m === "on"
|
|
3681
|
+
? "Derive borders, branch rules, dim text and diff tints from the active pi theme (default)"
|
|
3682
|
+
: m === "off"
|
|
3683
|
+
? "Keep the fixed Claude-style palette regardless of theme"
|
|
3684
|
+
: m === "toggle"
|
|
3685
|
+
? "Flip between on and off"
|
|
3686
|
+
: "Show the current setting and a preview of the derived colors",
|
|
3687
|
+
}))
|
|
3688
|
+
},
|
|
3689
|
+
async handler(args, ctx) {
|
|
3690
|
+
const raw = args.trim().toLowerCase()
|
|
3691
|
+
const current = themeAdaptiveEnabled()
|
|
3692
|
+
|
|
3693
|
+
if (!raw || raw === "status") {
|
|
3694
|
+
if (!ctx.hasUI) return
|
|
3695
|
+
const theme = ctx.ui.theme as any
|
|
3696
|
+
const themeName = theme?.name ?? "unknown"
|
|
3697
|
+
const state = current ? "on" : "off"
|
|
3698
|
+
if (raw === "status" && current) {
|
|
3699
|
+
const settings = readSettings()
|
|
3700
|
+
const verbKey = settings.spinnerVerbColor || "borderAccent"
|
|
3701
|
+
const statusKey = settings.spinnerStatusColor || "muted"
|
|
3702
|
+
const verbAnsi = safeFgAnsi(theme, verbKey) ?? safeFgAnsi(theme, "accent")
|
|
3703
|
+
const statusAnsi = safeFgAnsi(theme, statusKey) ?? safeFgAnsi(theme, "muted")
|
|
3704
|
+
// Print a short preview of what we derived.
|
|
3705
|
+
const preview = [
|
|
3706
|
+
`borders : ${safeFgAnsi(theme, "borderMuted") ? `${safeFgAnsi(theme, "borderMuted")}────\x1b[39m` : "(unchanged)"}`,
|
|
3707
|
+
`branches : ${(safeFgAnsi(theme, "dim") ?? safeFgAnsi(theme, "muted")) ? `${safeFgAnsi(theme, "dim") ?? safeFgAnsi(theme, "muted")}├─ └─\x1b[39m` : "(unchanged)"}`,
|
|
3708
|
+
`muted text : ${safeFgAnsi(theme, "muted") ? `${safeFgAnsi(theme, "muted")}example dim text\x1b[39m` : "(unchanged)"}`,
|
|
3709
|
+
`diff add : ${safeFgAnsi(theme, "toolDiffAdded") ? `${safeFgAnsi(theme, "toolDiffAdded")}+ added line\x1b[39m` : "(unchanged)"}`,
|
|
3710
|
+
`diff del : ${safeFgAnsi(theme, "toolDiffRemoved") ? `${safeFgAnsi(theme, "toolDiffRemoved")}- removed line\x1b[39m` : "(unchanged)"}`,
|
|
3711
|
+
`spinner verb: ${verbAnsi ? `${verbAnsi}Cooking…\x1b[39m` : "(unchanged)"} (key: ${verbKey})`,
|
|
3712
|
+
`spinner stat: ${statusAnsi ? `${statusAnsi}(thinking · ↓ 10 tokens · 2s)\x1b[39m` : "(unchanged)"} (key: ${statusKey})`,
|
|
3713
|
+
].join("\n ")
|
|
3714
|
+
ctx.ui.notify(`Theme adaptive: ${state} (theme "${themeName}")\n ${preview}`, "info")
|
|
3715
|
+
} else {
|
|
3716
|
+
ctx.ui.notify(`Theme adaptive: ${state} (theme "${themeName}")`, "info")
|
|
3717
|
+
}
|
|
3718
|
+
return
|
|
3719
|
+
}
|
|
3720
|
+
|
|
3721
|
+
let next: boolean
|
|
3722
|
+
if (raw === "on") next = true
|
|
3723
|
+
else if (raw === "off") next = false
|
|
3724
|
+
else if (raw === "toggle") next = !current
|
|
3725
|
+
else {
|
|
3726
|
+
if (ctx.hasUI) ctx.ui.notify(`Unknown option "${raw}". Options: ${THEME_MODES.join(", ")}`, "error")
|
|
3727
|
+
return
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3730
|
+
writeSettingsKey("themeAdaptive", next)
|
|
3731
|
+
bustSpinnerSettingsCache()
|
|
3732
|
+
// Invalidate caches so the next render re-derives from the active
|
|
3733
|
+
// theme (or falls back to the fixed Claude palette).
|
|
3734
|
+
_themePaletteCacheTheme = null
|
|
3735
|
+
autoDerivePending = true
|
|
3736
|
+
if (next) {
|
|
3737
|
+
if (ctx.hasUI) applyThemePaletteIfNeeded(ctx.ui.theme)
|
|
3738
|
+
} else {
|
|
3739
|
+
resetThemePalette()
|
|
3740
|
+
}
|
|
3741
|
+
if (ctx.hasUI) {
|
|
3742
|
+
const label = next ? "on — colors follow pi theme" : "off — fixed Claude palette"
|
|
3743
|
+
ctx.ui.notify(`Theme adaptive: ${label}`, "info")
|
|
3744
|
+
}
|
|
3745
|
+
},
|
|
3746
|
+
})
|
|
3747
|
+
|
|
3748
|
+
// /cc-spinner command — pick which theme color keys drive the spinner verb
|
|
3749
|
+
// and status suffix.
|
|
3750
|
+
const COMMON_COLOR_KEYS: readonly string[] = [
|
|
3751
|
+
"accent",
|
|
3752
|
+
"borderAccent",
|
|
3753
|
+
"success",
|
|
3754
|
+
"error",
|
|
3755
|
+
"warning",
|
|
3756
|
+
"muted",
|
|
3757
|
+
"dim",
|
|
3758
|
+
"text",
|
|
3759
|
+
"thinkingText",
|
|
3760
|
+
"toolTitle",
|
|
3761
|
+
"mdHeading",
|
|
3762
|
+
"mdCode",
|
|
3763
|
+
"mdLink",
|
|
3764
|
+
"mdListBullet",
|
|
3765
|
+
"bashMode",
|
|
3766
|
+
"thinkingLow",
|
|
3767
|
+
"thinkingMedium",
|
|
3768
|
+
"thinkingHigh",
|
|
3769
|
+
"thinkingXhigh",
|
|
3770
|
+
"syntaxKeyword",
|
|
3771
|
+
"syntaxFunction",
|
|
3772
|
+
"syntaxString",
|
|
3773
|
+
"syntaxType",
|
|
3774
|
+
]
|
|
3775
|
+
pi.registerCommand("cc-spinner", {
|
|
3776
|
+
description: "Set the spinner verb or status theme color, or preview current values",
|
|
3777
|
+
getArgumentCompletions(prefix) {
|
|
3778
|
+
const subCommands = ["verb", "status", "reset", "preview"]
|
|
3779
|
+
const parts = prefix.split(/\s+/)
|
|
3780
|
+
if (parts.length <= 1) {
|
|
3781
|
+
return subCommands
|
|
3782
|
+
.filter((c) => c.startsWith(parts[0] ?? ""))
|
|
3783
|
+
.map((c) => ({
|
|
3784
|
+
value: c,
|
|
3785
|
+
label: c,
|
|
3786
|
+
description:
|
|
3787
|
+
c === "verb"
|
|
3788
|
+
? "Set the color key used for the spinner verb (e.g. 'Cooking…')"
|
|
3789
|
+
: c === "status"
|
|
3790
|
+
? "Set the color key used for the spinner status suffix"
|
|
3791
|
+
: c === "reset"
|
|
3792
|
+
? "Reset both verb and status to defaults (borderAccent, muted)"
|
|
3793
|
+
: "Preview every theme color key with its current sample",
|
|
3794
|
+
}))
|
|
3795
|
+
}
|
|
3796
|
+
// Second arg: color key completions for verb/status.
|
|
3797
|
+
if (parts[0] === "verb" || parts[0] === "status") {
|
|
3798
|
+
const keyPrefix = (parts[1] ?? "").toLowerCase()
|
|
3799
|
+
return COMMON_COLOR_KEYS.filter((k) => k.toLowerCase().startsWith(keyPrefix)).map((k) => ({
|
|
3800
|
+
value: k,
|
|
3801
|
+
label: k,
|
|
3802
|
+
description: `theme.fg("${k}", …)`,
|
|
3803
|
+
}))
|
|
3804
|
+
}
|
|
3805
|
+
return []
|
|
3806
|
+
},
|
|
3807
|
+
async handler(args, ctx) {
|
|
3808
|
+
const parts = args
|
|
3809
|
+
.trim()
|
|
3810
|
+
.split(/\s+/)
|
|
3811
|
+
.filter((p) => p.length > 0)
|
|
3812
|
+
const sub = (parts[0] ?? "").toLowerCase()
|
|
3813
|
+
const theme = ctx.hasUI ? ctx.ui.theme : null
|
|
3814
|
+
const settings = readSettings()
|
|
3815
|
+
const currentVerb = settings.spinnerVerbColor || "borderAccent"
|
|
3816
|
+
const currentStatus = settings.spinnerStatusColor || "muted"
|
|
3817
|
+
|
|
3818
|
+
if (!sub || sub === "preview") {
|
|
3819
|
+
if (!ctx.hasUI) return
|
|
3820
|
+
if (!theme) {
|
|
3821
|
+
ctx.ui.notify(`Spinner verb: ${currentVerb}, status: ${currentStatus} (no theme)`, "info")
|
|
3822
|
+
return
|
|
3823
|
+
}
|
|
3824
|
+
const lines: string[] = [
|
|
3825
|
+
`Current: verb=${currentVerb}, status=${currentStatus}`,
|
|
3826
|
+
"",
|
|
3827
|
+
"Preview of common theme keys (pick one for verb or status):",
|
|
3828
|
+
]
|
|
3829
|
+
for (const key of COMMON_COLOR_KEYS) {
|
|
3830
|
+
const ansi = safeFgAnsi(theme, key)
|
|
3831
|
+
const marker = key === currentVerb ? "(verb)" : key === currentStatus ? "(status)" : ""
|
|
3832
|
+
const sample = ansi ? `${ansi}Cooking…\x1b[39m` : "(unmapped)"
|
|
3833
|
+
lines.push(` ${key.padEnd(16)} ${sample} ${marker}`)
|
|
3834
|
+
}
|
|
3835
|
+
ctx.ui.notify(lines.join("\n"), "info")
|
|
3836
|
+
return
|
|
3837
|
+
}
|
|
3838
|
+
|
|
3839
|
+
if (sub === "reset") {
|
|
3840
|
+
writeSettingsKey("spinnerVerbColor", undefined)
|
|
3841
|
+
writeSettingsKey("spinnerStatusColor", undefined)
|
|
3842
|
+
bustSpinnerSettingsCache()
|
|
3843
|
+
if (ctx.hasUI) ctx.ui.notify("Spinner colors reset to defaults (verb=borderAccent, status=muted)", "info")
|
|
3844
|
+
return
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
if (sub !== "verb" && sub !== "status") {
|
|
3848
|
+
if (ctx.hasUI) ctx.ui.notify(`Usage: /cc-spinner verb <key> | status <key> | reset | preview`, "error")
|
|
3849
|
+
return
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
const key = parts[1]
|
|
3853
|
+
if (!key) {
|
|
3854
|
+
if (ctx.hasUI) ctx.ui.notify(`Missing color key. Try /cc-spinner preview to see available keys.`, "error")
|
|
3855
|
+
return
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3858
|
+
// Validate the key resolves to *some* color in the active theme;
|
|
3859
|
+
// accept anyway if the user insists so themes with custom keys work.
|
|
3860
|
+
const ansi = theme ? safeFgAnsi(theme, key) : null
|
|
3861
|
+
const settingKey = sub === "verb" ? "spinnerVerbColor" : "spinnerStatusColor"
|
|
3862
|
+
writeSettingsKey(settingKey, key)
|
|
3863
|
+
bustSpinnerSettingsCache()
|
|
3864
|
+
if (ctx.hasUI) {
|
|
3865
|
+
const sample = ansi ? `${ansi}sample\x1b[39m` : "(key unmapped in current theme)"
|
|
3866
|
+
ctx.ui.notify(`Spinner ${sub} → ${key} ${sample}`, "info")
|
|
3867
|
+
}
|
|
3868
|
+
},
|
|
3869
|
+
})
|
|
3870
|
+
|
|
3871
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
3872
|
+
if (!ctx.hasUI) return
|
|
3873
|
+
applyToolBackgroundMode(ctx.ui.theme)
|
|
3874
|
+
applyThemePaletteIfNeeded(ctx.ui.theme)
|
|
3875
|
+
})
|
|
3876
|
+
|
|
3877
|
+
pi.on("turn_start", async (_event, ctx) => {
|
|
3878
|
+
if (!ctx.hasUI) return
|
|
3879
|
+
applyToolBackgroundMode(ctx.ui.theme)
|
|
3880
|
+
applyThemePaletteIfNeeded(ctx.ui.theme)
|
|
3881
|
+
})
|
|
3882
|
+
|
|
3883
|
+
const cwd = process.cwd()
|
|
3884
|
+
const sp = (path: string) => shortPath(cwd, path)
|
|
3885
|
+
|
|
3886
|
+
const readTool = createReadTool(cwd)
|
|
3887
|
+
pi.registerTool({
|
|
3888
|
+
name: "read",
|
|
3889
|
+
label: "read",
|
|
3890
|
+
description: readTool.description,
|
|
3891
|
+
parameters: readTool.parameters,
|
|
3892
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
3893
|
+
return readTool.execute(toolCallId, params, signal, onUpdate)
|
|
3894
|
+
},
|
|
3895
|
+
renderCall(args, theme, ctx) {
|
|
3896
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => {
|
|
3897
|
+
let value = sp(args.path ?? "")
|
|
3898
|
+
if (args.offset || args.limit) {
|
|
3899
|
+
const parts: string[] = []
|
|
3900
|
+
if (args.offset) parts.push(`offset=${args.offset}`)
|
|
3901
|
+
if (args.limit) parts.push(`limit=${args.limit}`)
|
|
3902
|
+
value += ` ${theme.fg("muted", `(${parts.join(", ")})`)}`
|
|
3903
|
+
}
|
|
3904
|
+
return value
|
|
3905
|
+
})
|
|
3906
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
3907
|
+
return makeText(ctx.lastComponent, toolHeader("Read", summary, theme, toolStatusDot(ctx, theme), timer))
|
|
3908
|
+
},
|
|
3909
|
+
renderResult(result, { expanded, isPartial }, theme, ctx) {
|
|
3910
|
+
if (isPartial) {
|
|
3911
|
+
setupBlinkTimer(ctx)
|
|
3912
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Reading..."), theme))
|
|
3913
|
+
}
|
|
3914
|
+
clearBlinkTimer(ctx)
|
|
3915
|
+
if (getFirstImageBlock(result)) return renderReadImageResult(result, expanded, theme, ctx)
|
|
3916
|
+
const details = result.details as ReadToolDetails | undefined
|
|
3917
|
+
const content = result.content.find((block: any) => block?.type === "text")
|
|
3918
|
+
if (content?.type !== "text")
|
|
3919
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("error", "No text content"), theme))
|
|
3920
|
+
const lines = content.text.split("\n")
|
|
3921
|
+
if (ctx.isError) {
|
|
3922
|
+
const header = theme.fg("muted", `${lines.length} lines loaded`)
|
|
3923
|
+
const body = lines.map((line) => theme.fg("error", line || " ")).join("\n")
|
|
3924
|
+
return makeText(ctx.lastComponent, withBranch(`${header}\n${body}`, theme))
|
|
3925
|
+
}
|
|
3926
|
+
let text = theme.fg("muted", `${lines.length} lines loaded`)
|
|
3927
|
+
if (details?.truncation?.truncated) text += theme.fg("warning", " (truncated)")
|
|
3928
|
+
if (!expanded)
|
|
3929
|
+
return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
3930
|
+
const shown = lines.slice(0, previewLimit())
|
|
3931
|
+
text += `\n${buildPreviewText(
|
|
3932
|
+
shown.map((line) => theme.fg("dim", line || " ")),
|
|
3933
|
+
false,
|
|
3934
|
+
theme,
|
|
3935
|
+
previewLimit(),
|
|
3936
|
+
)}`
|
|
3937
|
+
return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
3938
|
+
},
|
|
3939
|
+
})
|
|
3940
|
+
|
|
3941
|
+
const bashTool = createBashTool(cwd)
|
|
3942
|
+
pi.registerTool({
|
|
3943
|
+
name: "bash",
|
|
3944
|
+
label: "bash",
|
|
3945
|
+
description: bashTool.description,
|
|
3946
|
+
parameters: bashTool.parameters,
|
|
3947
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
3948
|
+
return bashTool.execute(toolCallId, params, signal, onUpdate)
|
|
3949
|
+
},
|
|
3950
|
+
renderCall(args, theme, ctx) {
|
|
3951
|
+
const command = getBashCommandForDisplay(args.command) ?? args.command
|
|
3952
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
3953
|
+
if (ctx.expanded && command) {
|
|
3954
|
+
// Expanded: show the tool name + timer on line 1, then the full
|
|
3955
|
+
// command (with real newlines) as a continued branch block below.
|
|
3956
|
+
const hdr = toolHeader("Bash", "", theme, toolStatusDot(ctx, theme), timer)
|
|
3957
|
+
const cmdBlock = withBranch(command.split("\n").map((l) => theme.fg("accent", l)).join("\n"), theme, false, true)
|
|
3958
|
+
return makeText(ctx.lastComponent, `${hdr}\n${cmdBlock}`)
|
|
3959
|
+
}
|
|
3960
|
+
const summary = summarizeText(command, 72)
|
|
3961
|
+
return makeText(ctx.lastComponent, toolHeader("Bash", summary, theme, toolStatusDot(ctx, theme), timer))
|
|
3962
|
+
},
|
|
3963
|
+
renderResult(result, { expanded, isPartial }, theme, ctx) {
|
|
3964
|
+
const details = result.details as BashToolDetails | undefined
|
|
3965
|
+
const output = result.content[0]?.type === "text" ? result.content[0].text : ""
|
|
3966
|
+
const nonEmpty = output.split("\n").filter((line) => line.trim().length > 0)
|
|
3967
|
+
if (isPartial) {
|
|
3968
|
+
setupBlinkTimer(ctx)
|
|
3969
|
+
return makeText(
|
|
3970
|
+
ctx.lastComponent,
|
|
3971
|
+
withBranch(theme.fg("warning", `Running... (${nonEmpty.length} lines)`), theme),
|
|
3972
|
+
)
|
|
3973
|
+
}
|
|
3974
|
+
clearBlinkTimer(ctx)
|
|
3975
|
+
const exitMatch = output.match(/exit code: (\d+)/)
|
|
3976
|
+
const exitCode = exitMatch ? Number.parseInt(exitMatch[1], 10) : null
|
|
3977
|
+
const isExitError = exitCode !== null && exitCode !== 0
|
|
3978
|
+
const isError = ctx.isError || isExitError
|
|
3979
|
+
let text = isError
|
|
3980
|
+
? theme.fg("error", exitCode != null ? `Exit ${exitCode}` : "Failed")
|
|
3981
|
+
: theme.fg("success", "Done")
|
|
3982
|
+
text += theme.fg("muted", ` (${nonEmpty.length} lines)`)
|
|
3983
|
+
if (details?.truncation?.truncated) text += theme.fg("warning", " [truncated]")
|
|
3984
|
+
if (!expanded && !isError && nonEmpty.length > 0)
|
|
3985
|
+
return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
3986
|
+
if (!expanded && !isError) return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
3987
|
+
const collapsed = bashCollapsedLimit()
|
|
3988
|
+
text += `\n${buildPreviewText(
|
|
3989
|
+
nonEmpty.map((line) => theme.fg("dim", line)),
|
|
3990
|
+
expanded,
|
|
3991
|
+
theme,
|
|
3992
|
+
collapsed,
|
|
3993
|
+
)}`
|
|
3994
|
+
return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
3995
|
+
},
|
|
3996
|
+
})
|
|
3997
|
+
|
|
3998
|
+
const grepTool = createGrepTool(cwd)
|
|
3999
|
+
pi.registerTool({
|
|
4000
|
+
name: "grep",
|
|
4001
|
+
label: "grep",
|
|
4002
|
+
description: grepTool.description,
|
|
4003
|
+
parameters: grepTool.parameters,
|
|
4004
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
4005
|
+
return grepTool.execute(toolCallId, params, signal, onUpdate)
|
|
4006
|
+
},
|
|
4007
|
+
renderCall(args, theme, ctx) {
|
|
4008
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => {
|
|
4009
|
+
let value = `\"${summarizeText(args.pattern, 40)}\"`
|
|
4010
|
+
if (args.path) value += ` in ${args.path}`
|
|
4011
|
+
return value
|
|
4012
|
+
})
|
|
4013
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
4014
|
+
return makeText(ctx.lastComponent, toolHeader("Grep", summary, theme, toolStatusDot(ctx, theme), timer))
|
|
4015
|
+
},
|
|
4016
|
+
renderResult(result, { expanded, isPartial }, theme, ctx) {
|
|
4017
|
+
if (isPartial) {
|
|
4018
|
+
setupBlinkTimer(ctx)
|
|
4019
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Searching..."), theme))
|
|
4020
|
+
}
|
|
4021
|
+
clearBlinkTimer(ctx)
|
|
4022
|
+
const details = result.details as GrepToolDetails | undefined
|
|
4023
|
+
const matches = (result.content[0]?.type === "text" ? result.content[0].text : "")
|
|
4024
|
+
.split("\n")
|
|
4025
|
+
.filter((line) => line.trim().length > 0)
|
|
4026
|
+
if (matches.length === 0) return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "no matches"), theme))
|
|
4027
|
+
let text = theme.fg("muted", `${matches.length} matches`)
|
|
4028
|
+
if (details?.truncation?.truncated) text += theme.fg("warning", " (truncated)")
|
|
4029
|
+
if (!expanded)
|
|
4030
|
+
return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
4031
|
+
text += `\n${buildPreviewText(
|
|
4032
|
+
matches.map((line) => theme.fg("dim", line)),
|
|
4033
|
+
false,
|
|
4034
|
+
theme,
|
|
4035
|
+
previewLimit(),
|
|
4036
|
+
)}`
|
|
4037
|
+
return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
4038
|
+
},
|
|
4039
|
+
})
|
|
4040
|
+
|
|
4041
|
+
const findTool = createFindTool(cwd)
|
|
4042
|
+
pi.registerTool({
|
|
4043
|
+
name: "find",
|
|
4044
|
+
label: "find",
|
|
4045
|
+
description: findTool.description,
|
|
4046
|
+
parameters: findTool.parameters,
|
|
4047
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
4048
|
+
return findTool.execute(toolCallId, params, signal, onUpdate)
|
|
4049
|
+
},
|
|
4050
|
+
renderCall(args, theme, ctx) {
|
|
4051
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => {
|
|
4052
|
+
let value = `\"${summarizeText(args.pattern, 40)}\"`
|
|
4053
|
+
if (args.path) value += ` in ${args.path}`
|
|
4054
|
+
return value
|
|
4055
|
+
})
|
|
4056
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
4057
|
+
return makeText(ctx.lastComponent, toolHeader("Find", summary, theme, toolStatusDot(ctx, theme), timer))
|
|
4058
|
+
},
|
|
4059
|
+
renderResult(result, { expanded, isPartial }, theme, ctx) {
|
|
4060
|
+
if (isPartial) {
|
|
4061
|
+
setupBlinkTimer(ctx)
|
|
4062
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Finding..."), theme))
|
|
4063
|
+
}
|
|
4064
|
+
clearBlinkTimer(ctx)
|
|
4065
|
+
const items = (result.content[0]?.type === "text" ? result.content[0].text : "")
|
|
4066
|
+
.split("\n")
|
|
4067
|
+
.filter((line) => line.trim().length > 0)
|
|
4068
|
+
if (items.length === 0) return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "no files found"), theme))
|
|
4069
|
+
let text = theme.fg("muted", `${items.length} files`)
|
|
4070
|
+
if (!expanded)
|
|
4071
|
+
return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
4072
|
+
// Expanded: grouped find results with icons
|
|
4073
|
+
const maxShow = previewLimit()
|
|
4074
|
+
const shown = items.slice(0, maxShow)
|
|
4075
|
+
const findLines: string[] = []
|
|
4076
|
+
for (let i = 0; i < shown.length; i++) {
|
|
4077
|
+
const item = shown[i].trim()
|
|
4078
|
+
const icon = fileIcon(item)
|
|
4079
|
+
findLines.push(` ${icon}${theme.fg("dim", item)}`)
|
|
4080
|
+
}
|
|
4081
|
+
const remaining = items.length - shown.length
|
|
4082
|
+
if (remaining > 0) {
|
|
4083
|
+
findLines.push(` ${theme.fg("muted", `… ${remaining} more files`)}`)
|
|
4084
|
+
}
|
|
4085
|
+
text += `\n${findLines.join("\n")}`
|
|
4086
|
+
return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
4087
|
+
},
|
|
4088
|
+
})
|
|
4089
|
+
|
|
4090
|
+
const lsTool = createLsTool(cwd)
|
|
4091
|
+
pi.registerTool({
|
|
4092
|
+
name: "ls",
|
|
4093
|
+
label: "ls",
|
|
4094
|
+
description: lsTool.description,
|
|
4095
|
+
parameters: lsTool.parameters,
|
|
4096
|
+
async execute(toolCallId, params, signal, onUpdate) {
|
|
4097
|
+
return lsTool.execute(toolCallId, params, signal, onUpdate)
|
|
4098
|
+
},
|
|
4099
|
+
renderCall(args, theme, ctx) {
|
|
4100
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => sp(args.path ?? "."))
|
|
4101
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
4102
|
+
return makeText(ctx.lastComponent, toolHeader("List", summary, theme, toolStatusDot(ctx, theme), timer))
|
|
4103
|
+
},
|
|
4104
|
+
renderResult(result, { expanded, isPartial }, theme, ctx) {
|
|
4105
|
+
if (isPartial) {
|
|
4106
|
+
setupBlinkTimer(ctx)
|
|
4107
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Listing..."), theme))
|
|
4108
|
+
}
|
|
4109
|
+
clearBlinkTimer(ctx)
|
|
4110
|
+
const items = (result.content[0]?.type === "text" ? result.content[0].text : "")
|
|
4111
|
+
.split("\n")
|
|
4112
|
+
.filter((line) => line.trim().length > 0)
|
|
4113
|
+
if (items.length === 0)
|
|
4114
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "empty directory"), theme))
|
|
4115
|
+
let text = theme.fg("muted", `${items.length} entries`)
|
|
4116
|
+
if (!expanded)
|
|
4117
|
+
return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
|
|
4118
|
+
// Expanded: tree-view with icons
|
|
4119
|
+
const maxShow = previewLimit()
|
|
4120
|
+
const shown = items.slice(0, maxShow)
|
|
4121
|
+
const treeLines: string[] = []
|
|
4122
|
+
for (let i = 0; i < shown.length; i++) {
|
|
4123
|
+
const item = shown[i]
|
|
4124
|
+
const isDir = item.endsWith("/")
|
|
4125
|
+
const isLast = i === shown.length - 1 && items.length <= maxShow
|
|
4126
|
+
const prefix = isLast ? `${FG_RULE}\u2514\u2500\u2500${D_RST} ` : `${FG_RULE}\u251c\u2500\u2500${D_RST} `
|
|
4127
|
+
const icon = isDir ? dirIcon() : fileIcon(item)
|
|
4128
|
+
const name = isDir ? theme.fg("accent", theme.bold(item)) : theme.fg("dim", item)
|
|
4129
|
+
treeLines.push(`${prefix}${icon}${name}`)
|
|
4130
|
+
}
|
|
4131
|
+
const remaining = items.length - shown.length
|
|
4132
|
+
if (remaining > 0) {
|
|
4133
|
+
treeLines.push(`${FG_RULE}\u2514\u2500\u2500${D_RST} ${theme.fg("muted", `\u2026 ${remaining} more entries`)}`)
|
|
4134
|
+
}
|
|
4135
|
+
text += `\n${treeLines.join("\n")}`
|
|
4136
|
+
return makeText(ctx.lastComponent, withBranch(text, theme))
|
|
4137
|
+
},
|
|
4138
|
+
})
|
|
4139
|
+
|
|
4140
|
+
const writeTool = createWriteTool(cwd)
|
|
4141
|
+
pi.registerTool({
|
|
4142
|
+
name: "write",
|
|
4143
|
+
label: "write",
|
|
4144
|
+
description: writeTool.description,
|
|
4145
|
+
parameters: writeTool.parameters,
|
|
4146
|
+
async execute(toolCallId, params, signal, onUpdate, _ctx) {
|
|
4147
|
+
const fp = params.path ?? (params as any).file_path ?? ""
|
|
4148
|
+
const fullPath = fp ? resolve(cwd, fp) : ""
|
|
4149
|
+
const existedBefore = !!fullPath && fileExistsForTool(cwd, fp)
|
|
4150
|
+
WRITE_EXISTED_BEFORE.set(toolCallId, existedBefore)
|
|
4151
|
+
let old: string | null = null
|
|
4152
|
+
try {
|
|
4153
|
+
if (fullPath && existedBefore) old = readFileSync(fullPath, "utf-8")
|
|
4154
|
+
} catch {
|
|
4155
|
+
old = null
|
|
4156
|
+
}
|
|
4157
|
+
const result = await writeTool.execute(toolCallId, params, signal, onUpdate)
|
|
4158
|
+
const content = params.content ?? ""
|
|
4159
|
+
if (old !== null && old !== content) {
|
|
4160
|
+
const diff = parseDiff(old, content)
|
|
4161
|
+
;(result as any).details = {
|
|
4162
|
+
_type: "diff",
|
|
4163
|
+
summary: summarizeDiff(diff.added, diff.removed),
|
|
4164
|
+
diff,
|
|
4165
|
+
language: lang(fp),
|
|
4166
|
+
}
|
|
4167
|
+
} else if (old === null) {
|
|
4168
|
+
;(result as any).details = { _type: "new", lines: lineCount(content), filePath: fp }
|
|
4169
|
+
} else if (old === content) {
|
|
4170
|
+
;(result as any).details = { _type: "noChange" }
|
|
4171
|
+
}
|
|
4172
|
+
return result
|
|
4173
|
+
},
|
|
4174
|
+
renderCall(args, theme, ctx) {
|
|
4175
|
+
const fp = args?.path ?? (args as any)?.file_path ?? ""
|
|
4176
|
+
const revealSummary = shouldRevealCallArgs(ctx) || (!!fp && hasOwnArg(args, "content"))
|
|
4177
|
+
const wasNew = getWriteWasNewFile(ctx, cwd, fp, revealSummary)
|
|
4178
|
+
const label = wasNew === true ? "Create" : "Write"
|
|
4179
|
+
const summary = stableCallSummary(
|
|
4180
|
+
ctx,
|
|
4181
|
+
"_callSummary",
|
|
4182
|
+
() => {
|
|
4183
|
+
const base = sp(fp)
|
|
4184
|
+
return shouldRevealCallArgs(ctx)
|
|
4185
|
+
? `${base} ${theme.fg("muted", `(${lineCount(args.content ?? "")} lines)`)}`
|
|
4186
|
+
: base
|
|
4187
|
+
},
|
|
4188
|
+
revealSummary,
|
|
4189
|
+
)
|
|
4190
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
4191
|
+
const hdr = toolHeader(label, summary, theme, toolStatusDot(ctx, theme), timer)
|
|
4192
|
+
return makeText(ctx.lastComponent, hdr)
|
|
4193
|
+
},
|
|
4194
|
+
renderResult(result, { isPartial }, theme, ctx) {
|
|
4195
|
+
if (isPartial) {
|
|
4196
|
+
setupBlinkTimer(ctx)
|
|
4197
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Writing..."), theme))
|
|
4198
|
+
}
|
|
4199
|
+
clearBlinkTimer(ctx)
|
|
4200
|
+
if (typeof ctx?.toolCallId === "string") WRITE_EXISTED_BEFORE.delete(ctx.toolCallId)
|
|
4201
|
+
if (ctx.isError) {
|
|
4202
|
+
const e =
|
|
4203
|
+
result.content
|
|
4204
|
+
?.filter((c: any) => c.type === "text")
|
|
4205
|
+
.map((c: any) => c.text || "")
|
|
4206
|
+
.join("\n") ?? "Error"
|
|
4207
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("error", e), theme))
|
|
4208
|
+
}
|
|
4209
|
+
const d = (result as any).details
|
|
4210
|
+
if (d?._type === "diff") {
|
|
4211
|
+
const previewLines = ctx.expanded ? MAX_RENDER_LINES : diffCollapsedLimit()
|
|
4212
|
+
const hunks = d.diff?.lines?.filter((l: any) => l.type === "sep").length + (d.diff?.lines?.length ? 1 : 0)
|
|
4213
|
+
const diffWidth = branchDiffWidth()
|
|
4214
|
+
const mode = shouldUseSplit(d.diff, diffWidth, previewLines) ? "split" : "unified"
|
|
4215
|
+
const richSummary = diffSummaryWithMeta(d.diff.added, d.diff.removed, hunks, mode)
|
|
4216
|
+
const key = `wd:${diffWidth}:${d.summary}:${d.diff?.lines?.length ?? 0}:${d.language ?? ""}:${ctx.expanded ? 1 : 0}`
|
|
4217
|
+
if (ctx.state._wdk !== key) {
|
|
4218
|
+
ctx.state._wdk = key
|
|
4219
|
+
ctx.state._wdt = withFinalBranchBlock(`${richSummary}\n${theme.fg("muted", "rendering diff…")}`)
|
|
4220
|
+
const dc = resolveDiffColors(theme)
|
|
4221
|
+
renderSplit(d.diff, d.language, previewLines, dc, diffWidth)
|
|
4222
|
+
.then((rendered) => {
|
|
4223
|
+
if (ctx.state._wdk !== key) return
|
|
4224
|
+
ctx.state._wdt = withFinalBranchBlock(`${richSummary}\n${rendered}`)
|
|
4225
|
+
ctx.invalidate()
|
|
4226
|
+
})
|
|
4227
|
+
.catch(() => {
|
|
4228
|
+
if (ctx.state._wdk !== key) return
|
|
4229
|
+
ctx.state._wdt = withBranch(richSummary, theme)
|
|
4230
|
+
ctx.invalidate()
|
|
4231
|
+
})
|
|
4232
|
+
}
|
|
4233
|
+
return makeText(ctx.lastComponent, ctx.state._wdt ?? withBranch(richSummary, theme))
|
|
4234
|
+
}
|
|
4235
|
+
if (d?._type === "noChange")
|
|
4236
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "✓ no changes"), theme))
|
|
4237
|
+
if (d?._type === "new") {
|
|
4238
|
+
const content = typeof ctx.args?.content === "string" ? ctx.args.content : ""
|
|
4239
|
+
const lineTotal = typeof d.lines === "number" ? d.lines : lineCount(content)
|
|
4240
|
+
const contentHash = hashText(content)
|
|
4241
|
+
const syntheticDiff = getCachedParsedDiff(ctx, `nf-diff:${d.filePath}:${contentHash}`, "", content)
|
|
4242
|
+
const richSummary = diffSummaryWithMeta(syntheticDiff.added, 0, 1, "new file")
|
|
4243
|
+
const previewLines = ctx.expanded ? MAX_RENDER_LINES : diffCollapsedLimit()
|
|
4244
|
+
const diffWidth = branchDiffWidth()
|
|
4245
|
+
const pk = `nf:${d.filePath}:${contentHash}:${diffWidth}:${ctx.expanded ? 1 : 0}`
|
|
4246
|
+
if (ctx.state._nfk !== pk) {
|
|
4247
|
+
ctx.state._nfk = pk
|
|
4248
|
+
ctx.state._nft = withFinalBranchBlock(`${richSummary}\n${theme.fg("muted", "rendering diff…")}`)
|
|
4249
|
+
const dc = resolveDiffColors(theme)
|
|
4250
|
+
renderUnified(syntheticDiff, lang(d.filePath), previewLines, dc, diffWidth)
|
|
4251
|
+
.then((rendered) => {
|
|
4252
|
+
if (ctx.state._nfk !== pk) return
|
|
4253
|
+
ctx.state._nft = withFinalBranchBlock(`${richSummary}\n${rendered}`)
|
|
4254
|
+
ctx.invalidate()
|
|
4255
|
+
})
|
|
4256
|
+
.catch(() => {
|
|
4257
|
+
if (ctx.state._nfk !== pk) return
|
|
4258
|
+
ctx.state._nft = withBranch(`${richSummary} ${theme.fg("muted", `(${lineTotal} lines)`)}`, theme)
|
|
4259
|
+
ctx.invalidate()
|
|
4260
|
+
})
|
|
4261
|
+
}
|
|
4262
|
+
return makeText(
|
|
4263
|
+
ctx.lastComponent,
|
|
4264
|
+
ctx.state._nft ?? withBranch(`${richSummary} ${theme.fg("muted", `(${lineTotal} lines)`)}`, theme),
|
|
4265
|
+
)
|
|
4266
|
+
}
|
|
4267
|
+
return makeText(ctx.lastComponent, withBranch(theme.fg("success", "Written"), theme))
|
|
4268
|
+
},
|
|
4269
|
+
})
|
|
4270
|
+
|
|
4271
|
+
const editTool = createEditTool(cwd)
|
|
4272
|
+
pi.registerTool({
|
|
4273
|
+
name: "edit",
|
|
4274
|
+
label: "edit",
|
|
4275
|
+
description: editTool.description,
|
|
4276
|
+
parameters: editTool.parameters,
|
|
4277
|
+
async execute(toolCallId, params, signal, onUpdate, _ctx) {
|
|
4278
|
+
const fp = params.path ?? (params as any).file_path ?? ""
|
|
4279
|
+
const operations = getEditOperations(params)
|
|
4280
|
+
const localizedDiffs = operations.length === 1 ? await computeLocalizedEditDiffs(fp, operations, cwd) : null
|
|
4281
|
+
const result = await editTool.execute(toolCallId, params, signal, onUpdate)
|
|
4282
|
+
if (operations.length === 0) return result
|
|
4283
|
+
const { diffs, summary, totalLines, totalHunks } = summarizeEditOperations(operations)
|
|
4284
|
+
const baseDetails = ((result as any).details ?? {}) as Record<string, unknown>
|
|
4285
|
+
if (operations.length === 1) {
|
|
4286
|
+
const localized = localizedDiffs?.[0]
|
|
4287
|
+
const editLine =
|
|
4288
|
+
localized?.line ?? (typeof baseDetails.firstChangedLine === "number" ? baseDetails.firstChangedLine : 0)
|
|
4289
|
+
const diff = localized?.diff ?? diffs[0]
|
|
4290
|
+
;(result as any).details = {
|
|
4291
|
+
...baseDetails,
|
|
4292
|
+
_type: "editInfo",
|
|
4293
|
+
summary,
|
|
4294
|
+
editLine,
|
|
4295
|
+
hunks: countDiffHunks(diff),
|
|
4296
|
+
added: diff?.added ?? 0,
|
|
4297
|
+
removed: diff?.removed ?? 0,
|
|
4298
|
+
}
|
|
4299
|
+
return result
|
|
4300
|
+
}
|
|
4301
|
+
;(result as any).details = {
|
|
4302
|
+
...baseDetails,
|
|
4303
|
+
_type: "multiEditInfo",
|
|
4304
|
+
summary,
|
|
4305
|
+
editCount: operations.length,
|
|
4306
|
+
diffLineCount: totalLines,
|
|
4307
|
+
hunks: totalHunks,
|
|
4308
|
+
totalAdded: diffs.reduce((sum, diff) => sum + diff.added, 0),
|
|
4309
|
+
totalRemoved: diffs.reduce((sum, diff) => sum + diff.removed, 0),
|
|
4310
|
+
}
|
|
4311
|
+
return result
|
|
4312
|
+
},
|
|
4313
|
+
renderCall(args, theme, ctx) {
|
|
4314
|
+
const fp = args?.path ?? (args as any)?.file_path ?? ""
|
|
4315
|
+
const operations = getEditOperations(args)
|
|
4316
|
+
const revealSummary = shouldRevealCallArgs(ctx) || (!!fp && hasOwnArg(args, "edits"))
|
|
4317
|
+
const summary = stableCallSummary(
|
|
4318
|
+
ctx,
|
|
4319
|
+
"_callSummary",
|
|
4320
|
+
() =>
|
|
4321
|
+
shouldRevealCallArgs(ctx) && operations.length > 1
|
|
4322
|
+
? `${sp(fp)} ${theme.fg("muted", `(${operations.length} edits)`)}`
|
|
4323
|
+
: sp(fp),
|
|
4324
|
+
revealSummary,
|
|
4325
|
+
)
|
|
4326
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
4327
|
+
const hdr = toolHeader("Edit", summary, theme, ` ${toolStatusDot(ctx, theme)}`, timer)
|
|
4328
|
+
if (!(ctx.argsComplete && operations.length > 0)) return makeText(ctx.lastComponent, hdr)
|
|
4329
|
+
const diffWidth = branchDiffWidth()
|
|
4330
|
+
const key = `edit:${fp}:${hashText(operations.map((edit) => `${edit.oldText}\u0000${edit.newText}`).join("\u0001"))}:${diffWidth}:${ctx.expanded ? 1 : 0}`
|
|
4331
|
+
const { diffs: fallbackDiffs, summary: editSummary } = getCachedEditOperationSummary(ctx, key, operations)
|
|
4332
|
+
if (ctx.state._pk !== key) {
|
|
4333
|
+
ctx.state._pk = key
|
|
4334
|
+
ctx.state._ptBody = theme.fg("muted", "(rendering…)")
|
|
4335
|
+
ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
|
|
4336
|
+
const lg = lang(fp)
|
|
4337
|
+
void computeLocalizedEditDiffs(fp, operations, cwd)
|
|
4338
|
+
.then((localizedDiffs) => {
|
|
4339
|
+
if (ctx.state._pk !== key) return
|
|
4340
|
+
const diffs = localizedDiffs?.map((entry) => entry.diff) ?? fallbackDiffs
|
|
4341
|
+
const lines =
|
|
4342
|
+
localizedDiffs?.map((entry) => entry.line) ?? diffs.map((diff) => getFirstChangedNewLine(diff))
|
|
4343
|
+
renderEditPreviewBody(ctx, key, theme, lg, operations, diffs, lines, editSummary)
|
|
4344
|
+
})
|
|
4345
|
+
.catch(() => {
|
|
4346
|
+
if (ctx.state._pk !== key) return
|
|
4347
|
+
renderEditPreviewBody(
|
|
4348
|
+
ctx,
|
|
4349
|
+
key,
|
|
4350
|
+
theme,
|
|
4351
|
+
lg,
|
|
4352
|
+
operations,
|
|
4353
|
+
fallbackDiffs,
|
|
4354
|
+
fallbackDiffs.map((diff) => getFirstChangedNewLine(diff)),
|
|
4355
|
+
editSummary,
|
|
4356
|
+
)
|
|
4357
|
+
})
|
|
4358
|
+
}
|
|
4359
|
+
const body = ctx.state._ptDisplay as string | undefined
|
|
4360
|
+
return makeText(ctx.lastComponent, body ? `${hdr}\n${body}` : hdr)
|
|
4361
|
+
},
|
|
4362
|
+
renderResult(result, { isPartial }, theme, ctx) {
|
|
4363
|
+
if (isPartial) {
|
|
4364
|
+
setupBlinkTimer(ctx)
|
|
4365
|
+
return makeText(ctx.lastComponent, indentBranchBlock(withBranch(theme.fg("dim", "Editing..."), theme)))
|
|
4366
|
+
}
|
|
4367
|
+
clearBlinkTimer(ctx)
|
|
4368
|
+
if (ctx.isError) {
|
|
4369
|
+
const e =
|
|
4370
|
+
result.content
|
|
4371
|
+
?.filter((c: any) => c.type === "text")
|
|
4372
|
+
.map((c: any) => c.text || "")
|
|
4373
|
+
.join("\n") ?? "Error"
|
|
4374
|
+
return makeText(ctx.lastComponent, indentBranchBlock(withBranch(theme.fg("error", e), theme)))
|
|
4375
|
+
}
|
|
4376
|
+
if ((result as any).details?._type === "editInfo") {
|
|
4377
|
+
const { editLine, hunks, added, removed } = (result as any).details
|
|
4378
|
+
const loc = formatLineMeta(editLine ?? 0, theme)
|
|
4379
|
+
const summary = diffSummaryWithMeta(added ?? 0, removed ?? 0, hunks ?? 0, "")
|
|
4380
|
+
return makeText(ctx.lastComponent, indentBranchBlock(withBranch(`${summary}${loc}`, theme)))
|
|
4381
|
+
}
|
|
4382
|
+
if ((result as any).details?._type === "multiEditInfo") {
|
|
4383
|
+
const { editCount, diffLineCount, hunks, totalAdded, totalRemoved } = (result as any).details
|
|
4384
|
+
const summary = diffSummaryWithMeta(totalAdded ?? 0, totalRemoved ?? 0, hunks ?? 0, "")
|
|
4385
|
+
return makeText(
|
|
4386
|
+
ctx.lastComponent,
|
|
4387
|
+
indentBranchBlock(
|
|
4388
|
+
withBranch(
|
|
4389
|
+
`${editCount} edits ${summary}${typeof diffLineCount === "number" ? ` ${theme.fg("muted", `(${diffLineCount} diff lines)`)}` : ""}`,
|
|
4390
|
+
theme,
|
|
4391
|
+
),
|
|
4392
|
+
),
|
|
4393
|
+
)
|
|
4394
|
+
}
|
|
4395
|
+
return makeText(ctx.lastComponent, indentBranchBlock(withBranch(theme.fg("success", "Applied"), theme)))
|
|
4396
|
+
},
|
|
4397
|
+
})
|
|
4398
|
+
|
|
4399
|
+
const wrappedOpenAiTools = new Set<string>()
|
|
4400
|
+
const registerOpenAiToolOverrides = (): void => {
|
|
4401
|
+
let allTools: unknown[] = []
|
|
4402
|
+
try {
|
|
4403
|
+
allTools = typeof (pi as any).getAllTools === "function" ? (pi as any).getAllTools() : []
|
|
4404
|
+
} catch {
|
|
4405
|
+
allTools = []
|
|
4406
|
+
}
|
|
4407
|
+
for (const tool of allTools) {
|
|
4408
|
+
if (!isOpenAiToolCandidate(tool)) continue
|
|
4409
|
+
const record = tool as Record<string, unknown>
|
|
4410
|
+
const name = typeof record.name === "string" ? record.name : ""
|
|
4411
|
+
if (!name || wrappedOpenAiTools.has(name)) continue
|
|
4412
|
+
const execute = typeof record.execute === "function" ? (record.execute as any) : null
|
|
4413
|
+
if (!execute) continue
|
|
4414
|
+
const rawLabel = typeof record.label === "string" ? record.label.trim() : ""
|
|
4415
|
+
const label = rawLabel && rawLabel !== name && !rawLabel.includes("_") ? rawLabel : humanizeToolName(name)
|
|
4416
|
+
const description = typeof record.description === "string" ? record.description : label
|
|
4417
|
+
;(pi as any).registerTool({
|
|
4418
|
+
name,
|
|
4419
|
+
label,
|
|
4420
|
+
description,
|
|
4421
|
+
parameters: record.parameters,
|
|
4422
|
+
prepareArguments: typeof record.prepareArguments === "function" ? record.prepareArguments : undefined,
|
|
4423
|
+
async execute(toolCallId: string, params: any, signal: AbortSignal | undefined, onUpdate: any, ctx: any) {
|
|
4424
|
+
return await Promise.resolve(execute(toolCallId, params, signal, onUpdate, ctx))
|
|
4425
|
+
},
|
|
4426
|
+
renderCall(args: any, theme: Theme, ctx: any) {
|
|
4427
|
+
if (name === "apply_patch") return renderApplyPatchCall(args, theme, ctx, sp)
|
|
4428
|
+
ctx.state._openAiPatchFiles = []
|
|
4429
|
+
const summary = stableCallSummary(ctx, "_callSummary", () => summarizeOpenAiToolCall(name, args, theme, sp))
|
|
4430
|
+
const timer = formatToolTimer(getToolElapsedMs(ctx))
|
|
4431
|
+
return makeText(ctx.lastComponent, toolHeader(label, summary, theme, toolStatusDot(ctx, theme), timer))
|
|
4432
|
+
},
|
|
4433
|
+
renderResult(result: any, { expanded, isPartial }: any, theme: Theme, ctx: any) {
|
|
4434
|
+
if (name === "apply_patch") return renderApplyPatchResult(result, isPartial, theme, ctx)
|
|
4435
|
+
return renderOpenAiToolResult(name, result, expanded, isPartial, theme, ctx)
|
|
4436
|
+
},
|
|
4437
|
+
})
|
|
4438
|
+
wrappedOpenAiTools.add(name)
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
const wrappedMcpTools = new Set<string>()
|
|
4443
|
+
const registerMcpToolOverrides = (): void => {
|
|
4444
|
+
let allTools: unknown[] = []
|
|
4445
|
+
try {
|
|
4446
|
+
allTools = typeof (pi as any).getAllTools === "function" ? (pi as any).getAllTools() : []
|
|
4447
|
+
} catch {
|
|
4448
|
+
allTools = []
|
|
4449
|
+
}
|
|
4450
|
+
for (const tool of allTools) {
|
|
4451
|
+
if (!isMcpToolCandidate(tool)) continue
|
|
4452
|
+
const record = tool as Record<string, unknown>
|
|
4453
|
+
const name = typeof record.name === "string" ? record.name : ""
|
|
4454
|
+
if (!name || wrappedMcpTools.has(name)) continue
|
|
4455
|
+
const execute = typeof record.execute === "function" ? (record.execute as any) : null
|
|
4456
|
+
if (!execute) continue
|
|
4457
|
+
const label = typeof record.label === "string" ? record.label : name === "mcp" ? "MCP" : `MCP ${name}`
|
|
4458
|
+
const description = typeof record.description === "string" ? record.description : "MCP tool"
|
|
4459
|
+
;(pi as any).registerTool({
|
|
4460
|
+
name,
|
|
4461
|
+
label,
|
|
4462
|
+
description,
|
|
4463
|
+
parameters: record.parameters,
|
|
4464
|
+
prepareArguments: typeof record.prepareArguments === "function" ? record.prepareArguments : undefined,
|
|
4465
|
+
async execute(toolCallId: string, params: any, signal: AbortSignal | undefined, onUpdate: any, ctx: any) {
|
|
4466
|
+
return await Promise.resolve(execute(toolCallId, params, signal, onUpdate, ctx))
|
|
4467
|
+
},
|
|
4468
|
+
renderCall(args: any, theme: Theme, ctx: any) {
|
|
4469
|
+
return renderGenericToolCall(name, args, theme, ctx)
|
|
4470
|
+
},
|
|
4471
|
+
renderResult(result: any, { expanded, isPartial }: any, theme: Theme, ctx: any) {
|
|
4472
|
+
return renderMcpToolResult(result, expanded, isPartial, theme, ctx)
|
|
4473
|
+
},
|
|
4474
|
+
})
|
|
4475
|
+
wrappedMcpTools.add(name)
|
|
4476
|
+
}
|
|
4477
|
+
}
|
|
4478
|
+
|
|
4479
|
+
pi.on("session_start", async () => {
|
|
4480
|
+
registerOpenAiToolOverrides()
|
|
4481
|
+
registerMcpToolOverrides()
|
|
4482
|
+
})
|
|
4483
|
+
pi.on("before_agent_start", async () => {
|
|
4484
|
+
registerOpenAiToolOverrides()
|
|
4485
|
+
registerMcpToolOverrides()
|
|
4486
|
+
})
|
|
4487
|
+
|
|
4488
|
+
// Safety net: clear all blink timers on turn/session boundaries
|
|
4489
|
+
pi.on("turn_end", async () => {
|
|
4490
|
+
for (const entry of _blinkContexts.values()) {
|
|
4491
|
+
entry.key._blinkActive = false
|
|
4492
|
+
}
|
|
4493
|
+
_blinkContexts.clear()
|
|
4494
|
+
clearHighlightCache()
|
|
4495
|
+
if (_globalBlinkTimer) {
|
|
4496
|
+
clearTimeout(_globalBlinkTimer)
|
|
4497
|
+
_globalBlinkTimer = null
|
|
4498
|
+
}
|
|
4499
|
+
})
|
|
4500
|
+
pi.on("session_shutdown", async () => {
|
|
4501
|
+
for (const entry of _blinkContexts.values()) {
|
|
4502
|
+
entry.key._blinkActive = false
|
|
4503
|
+
}
|
|
4504
|
+
_blinkContexts.clear()
|
|
4505
|
+
clearHighlightCache()
|
|
4506
|
+
if (_globalBlinkTimer) {
|
|
4507
|
+
clearTimeout(_globalBlinkTimer)
|
|
4508
|
+
_globalBlinkTimer = null
|
|
4509
|
+
}
|
|
4510
|
+
})
|
|
4511
|
+
}
|