agim-cli 1.2.150 → 1.2.152
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/CHANGELOG.md +122 -0
- package/dist/core/skills/loader.d.ts +54 -0
- package/dist/core/skills/loader.d.ts.map +1 -1
- package/dist/core/skills/loader.js +221 -96
- package/dist/core/skills/loader.js.map +1 -1
- package/dist/web/agim-skills-api.d.ts.map +1 -1
- package/dist/web/agim-skills-api.js +80 -1
- package/dist/web/agim-skills-api.js.map +1 -1
- package/dist/web/public/assets/{a2a-Cll3P4QN.js → a2a-DZL1sgVk.js} +2 -2
- package/dist/web/public/assets/{a2a-Cll3P4QN.js.map → a2a-DZL1sgVk.js.map} +1 -1
- package/dist/web/public/assets/{activity-B7T7YFlD.js → activity-BsCuSHQd.js} +2 -2
- package/dist/web/public/assets/{activity-B7T7YFlD.js.map → activity-BsCuSHQd.js.map} +1 -1
- package/dist/web/public/assets/{admins-CN7P018S.js → admins-CyG_mVaa.js} +2 -2
- package/dist/web/public/assets/{admins-CN7P018S.js.map → admins-CyG_mVaa.js.map} +1 -1
- package/dist/web/public/assets/{agents-Bqgq7GBF.js → agents-D2wSzcVZ.js} +2 -2
- package/dist/web/public/assets/{agents-Bqgq7GBF.js.map → agents-D2wSzcVZ.js.map} +1 -1
- package/dist/web/public/assets/{approvals-C8IUJQ_A.js → approvals-C3uNQTdL.js} +2 -2
- package/dist/web/public/assets/{approvals-C8IUJQ_A.js.map → approvals-C3uNQTdL.js.map} +1 -1
- package/dist/web/public/assets/{arrow-down-SLWKqtDc.js → arrow-down-CppegASc.js} +2 -2
- package/dist/web/public/assets/{arrow-down-SLWKqtDc.js.map → arrow-down-CppegASc.js.map} +1 -1
- package/dist/web/public/assets/{arrow-up-BOADc9ce.js → arrow-up-8NH41ZQX.js} +2 -2
- package/dist/web/public/assets/{arrow-up-BOADc9ce.js.map → arrow-up-8NH41ZQX.js.map} +1 -1
- package/dist/web/public/assets/{asks-C-j-DypC.js → asks-DiT_eq2x.js} +2 -2
- package/dist/web/public/assets/{asks-C-j-DypC.js.map → asks-DiT_eq2x.js.map} +1 -1
- package/dist/web/public/assets/{audit-DQb-RuXh.js → audit-0T4jT2G0.js} +2 -2
- package/dist/web/public/assets/{audit-DQb-RuXh.js.map → audit-0T4jT2G0.js.map} +1 -1
- package/dist/web/public/assets/{bell-CV88-ul6.js → bell-BoZsoN58.js} +2 -2
- package/dist/web/public/assets/{bell-CV88-ul6.js.map → bell-BoZsoN58.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-CDrK0d-W.js → bgjobs-DbHdPyhE.js} +2 -2
- package/dist/web/public/assets/{bgjobs-CDrK0d-W.js.map → bgjobs-DbHdPyhE.js.map} +1 -1
- package/dist/web/public/assets/{brain-B7HtSOQU.js → brain-D-zbPJ7o.js} +2 -2
- package/dist/web/public/assets/{brain-B7HtSOQU.js.map → brain-D-zbPJ7o.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-mdzuIa__.js → briefcase-D3jWpfeB.js} +2 -2
- package/dist/web/public/assets/{briefcase-mdzuIa__.js.map → briefcase-D3jWpfeB.js.map} +1 -1
- package/dist/web/public/assets/{chat-CSjtY2rN.js → chat-DrYeCiFH.js} +2 -2
- package/dist/web/public/assets/{chat-CSjtY2rN.js.map → chat-DrYeCiFH.js.map} +1 -1
- package/dist/web/public/assets/{chevron-left-uSfPn636.js → chevron-left-D6-MKmUs.js} +2 -2
- package/dist/web/public/assets/{chevron-left-uSfPn636.js.map → chevron-left-D6-MKmUs.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-CtelqacW.js → chevron-right-CHtA6f0-.js} +2 -2
- package/dist/web/public/assets/{chevron-right-CtelqacW.js.map → chevron-right-CHtA6f0-.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-8dbL-u7O.js → circle-check-B9adx56J.js} +2 -2
- package/dist/web/public/assets/{circle-check-8dbL-u7O.js.map → circle-check-B9adx56J.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-D8-svk9a.js → circle-check-big-E1qhYcsu.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-D8-svk9a.js.map → circle-check-big-E1qhYcsu.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-rUxzIz5P.js → circle-x-xB2tQMGw.js} +2 -2
- package/dist/web/public/assets/{circle-x-rUxzIz5P.js.map → circle-x-xB2tQMGw.js.map} +1 -1
- package/dist/web/public/assets/{clock-CG5dlBGB.js → clock-DFU9E0F0.js} +2 -2
- package/dist/web/public/assets/{clock-CG5dlBGB.js.map → clock-DFU9E0F0.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-DlUsSur3.js → confirm-dialog-C1w1040N.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-DlUsSur3.js.map → confirm-dialog-C1w1040N.js.map} +1 -1
- package/dist/web/public/assets/{copy-DnC76wFT.js → copy-UOTkO-2l.js} +2 -2
- package/dist/web/public/assets/{copy-DnC76wFT.js.map → copy-UOTkO-2l.js.map} +1 -1
- package/dist/web/public/assets/{data-table-DswkWUfG.js → data-table-CBTDQyFx.js} +2 -2
- package/dist/web/public/assets/{data-table-DswkWUfG.js.map → data-table-CBTDQyFx.js.map} +1 -1
- package/dist/web/public/assets/{dialog-Ceo4YuXy.js → dialog-CqBNfrYQ.js} +2 -2
- package/dist/web/public/assets/{dialog-Ceo4YuXy.js.map → dialog-CqBNfrYQ.js.map} +1 -1
- package/dist/web/public/assets/{download-DF-46tS4.js → download-BzDp4OCu.js} +2 -2
- package/dist/web/public/assets/{download-DF-46tS4.js.map → download-BzDp4OCu.js.map} +1 -1
- package/dist/web/public/assets/{email-CZee26-_.js → email-BDd0tUm1.js} +2 -2
- package/dist/web/public/assets/{email-CZee26-_.js.map → email-BDd0tUm1.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-D9Hi0Atm.js → empty-state-CKPzKsI5.js} +2 -2
- package/dist/web/public/assets/{empty-state-D9Hi0Atm.js.map → empty-state-CKPzKsI5.js.map} +1 -1
- package/dist/web/public/assets/{external-link-D64iZa9P.js → external-link-Cx0ulEkb.js} +2 -2
- package/dist/web/public/assets/{external-link-D64iZa9P.js.map → external-link-Cx0ulEkb.js.map} +1 -1
- package/dist/web/public/assets/{eye-sY6WZb7D.js → eye-D9PD2xVj.js} +2 -2
- package/dist/web/public/assets/{eye-sY6WZb7D.js.map → eye-D9PD2xVj.js.map} +1 -1
- package/dist/web/public/assets/{facts-B7bGGwvi.js → facts-CRpGEODt.js} +2 -2
- package/dist/web/public/assets/{facts-B7bGGwvi.js.map → facts-CRpGEODt.js.map} +1 -1
- package/dist/web/public/assets/{goals-BfQbsvZv.js → goals-pyF71sFT.js} +2 -2
- package/dist/web/public/assets/{goals-BfQbsvZv.js.map → goals-pyF71sFT.js.map} +1 -1
- package/dist/web/public/assets/{health-Ba_mY0Ts.js → health-_YLm7LIW.js} +2 -2
- package/dist/web/public/assets/{health-Ba_mY0Ts.js.map → health-_YLm7LIW.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-BjikOVwU.js → heart-pulse-DyxG9jqH.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-BjikOVwU.js.map → heart-pulse-DyxG9jqH.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-BM8LlPes.js → heartbeat-bZfXp6Vm.js} +2 -2
- package/dist/web/public/assets/{heartbeat-BM8LlPes.js.map → heartbeat-bZfXp6Vm.js.map} +1 -1
- package/dist/web/public/assets/{hot-BtuLL6n8.js → hot-CSwCgYXw.js} +2 -2
- package/dist/web/public/assets/{hot-BtuLL6n8.js.map → hot-CSwCgYXw.js.map} +1 -1
- package/dist/web/public/assets/{index-DEWFfW_Z.js → index-D5DvetP5.js} +11 -11
- package/dist/web/public/assets/index-D5DvetP5.js.map +1 -0
- package/dist/web/public/assets/{index-f1K5Q2Yz.css → index-uKzGZ_Df.css} +1 -1
- package/dist/web/public/assets/injection-CYjttllI.js +2 -0
- package/dist/web/public/assets/injection-CYjttllI.js.map +1 -0
- package/dist/web/public/assets/installed-C6eNPXLl.js +31 -0
- package/dist/web/public/assets/installed-C6eNPXLl.js.map +1 -0
- package/dist/web/public/assets/{jobs-Ddy81Udm.js → jobs-CKQvijeH.js} +2 -2
- package/dist/web/public/assets/{jobs-Ddy81Udm.js.map → jobs-CKQvijeH.js.map} +1 -1
- package/dist/web/public/assets/{layout-Bp4SAA8_.js → layout-2S0YMTH_.js} +2 -2
- package/dist/web/public/assets/{layout-Bp4SAA8_.js.map → layout-2S0YMTH_.js.map} +1 -1
- package/dist/web/public/assets/{layout-Bn2qUxcK.js → layout-BQGP-bci.js} +2 -2
- package/dist/web/public/assets/{layout-Bn2qUxcK.js.map → layout-BQGP-bci.js.map} +1 -1
- package/dist/web/public/assets/{layout-CZ9pGnW8.js → layout-C4RTH7Mc.js} +2 -2
- package/dist/web/public/assets/{layout-CZ9pGnW8.js.map → layout-C4RTH7Mc.js.map} +1 -1
- package/dist/web/public/assets/{layout-BL74fT-L.js → layout-C9vch6up.js} +2 -2
- package/dist/web/public/assets/{layout-BL74fT-L.js.map → layout-C9vch6up.js.map} +1 -1
- package/dist/web/public/assets/layout-Y4GA9SyV.js +2 -0
- package/dist/web/public/assets/layout-Y4GA9SyV.js.map +1 -0
- package/dist/web/public/assets/{llm-yp7b5xxL.js → llm-CJvopUnt.js} +2 -2
- package/dist/web/public/assets/{llm-yp7b5xxL.js.map → llm-CJvopUnt.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-Bbw4pEyE.js → loader-circle-CgLbYd3g.js} +2 -2
- package/dist/web/public/assets/{loader-circle-Bbw4pEyE.js.map → loader-circle-CgLbYd3g.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-DIXHUQgM.js → map-pin-CdHDC52F.js} +2 -2
- package/dist/web/public/assets/{map-pin-DIXHUQgM.js.map → map-pin-CdHDC52F.js.map} +1 -1
- package/dist/web/public/assets/{mcp-DyaljIM_.js → mcp-SI73JwZR.js} +2 -2
- package/dist/web/public/assets/{mcp-DyaljIM_.js.map → mcp-SI73JwZR.js.map} +1 -1
- package/dist/web/public/assets/{memos-Dkoc157i.js → memos-B-5cdUp2.js} +2 -2
- package/dist/web/public/assets/{memos-Dkoc157i.js.map → memos-B-5cdUp2.js.map} +1 -1
- package/dist/web/public/assets/{messengers-CcyGDeUI.js → messengers-CUz9DXB5.js} +2 -2
- package/dist/web/public/assets/{messengers-CcyGDeUI.js.map → messengers-CUz9DXB5.js.map} +1 -1
- package/dist/web/public/assets/{mobile-DqzIv4Xb.js → mobile-CrdzyGXr.js} +2 -2
- package/dist/web/public/assets/{mobile-DqzIv4Xb.js.map → mobile-CrdzyGXr.js.map} +1 -1
- package/dist/web/public/assets/{native-agent-BQ7WaRGK.js → native-agent-g8BpqzAo.js} +2 -2
- package/dist/web/public/assets/{native-agent-BQ7WaRGK.js.map → native-agent-g8BpqzAo.js.map} +1 -1
- package/dist/web/public/assets/{network-B_yUFAqC.js → network-DcpeRx8a.js} +2 -2
- package/dist/web/public/assets/{network-B_yUFAqC.js.map → network-DcpeRx8a.js.map} +1 -1
- package/dist/web/public/assets/{outbox-l8aVOZqO.js → outbox-uR6crgVJ.js} +2 -2
- package/dist/web/public/assets/{outbox-l8aVOZqO.js.map → outbox-uR6crgVJ.js.map} +1 -1
- package/dist/web/public/assets/{pagination-BAKRGKa9.js → pagination-CxK3lTYb.js} +2 -2
- package/dist/web/public/assets/{pagination-BAKRGKa9.js.map → pagination-CxK3lTYb.js.map} +1 -1
- package/dist/web/public/assets/{persona-D3VL9Rg1.js → persona-B1k5tc4U.js} +2 -2
- package/dist/web/public/assets/{persona-D3VL9Rg1.js.map → persona-B1k5tc4U.js.map} +1 -1
- package/dist/web/public/assets/{plans-BBB5e9my.js → plans-BWQSahSt.js} +2 -2
- package/dist/web/public/assets/{plans-BBB5e9my.js.map → plans-BWQSahSt.js.map} +1 -1
- package/dist/web/public/assets/{play-7-Wd369f.js → play-D2VxB3QN.js} +2 -2
- package/dist/web/public/assets/{play-7-Wd369f.js.map → play-D2VxB3QN.js.map} +1 -1
- package/dist/web/public/assets/{plus-B0sfZy-j.js → plus-_XZVk5F_.js} +2 -2
- package/dist/web/public/assets/{plus-B0sfZy-j.js.map → plus-_XZVk5F_.js.map} +1 -1
- package/dist/web/public/assets/{policy-BM1WRXH0.js → policy-D77IdVzS.js} +2 -2
- package/dist/web/public/assets/{policy-BM1WRXH0.js.map → policy-D77IdVzS.js.map} +1 -1
- package/dist/web/public/assets/{qr-code-DcKs5fi3.js → qr-code-glvcd_3g.js} +2 -2
- package/dist/web/public/assets/{qr-code-DcKs5fi3.js.map → qr-code-glvcd_3g.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-uNKeBeRl.js → refresh-ccw-MfejQvU6.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-uNKeBeRl.js.map → refresh-ccw-MfejQvU6.js.map} +1 -1
- package/dist/web/public/assets/{reminders-DHM8K0_O.js → reminders-CtKa3ECr.js} +2 -2
- package/dist/web/public/assets/{reminders-DHM8K0_O.js.map → reminders-CtKa3ECr.js.map} +1 -1
- package/dist/web/public/assets/{save-qwJa5_SA.js → save-Cha8EnUJ.js} +2 -2
- package/dist/web/public/assets/{save-qwJa5_SA.js.map → save-Cha8EnUJ.js.map} +1 -1
- package/dist/web/public/assets/{schedules-Bcd0wbT4.js → schedules-CuQgG6hz.js} +2 -2
- package/dist/web/public/assets/{schedules-Bcd0wbT4.js.map → schedules-CuQgG6hz.js.map} +1 -1
- package/dist/web/public/assets/{search-i1tP2maJ.js → search-BJqFnKP5.js} +2 -2
- package/dist/web/public/assets/{search-i1tP2maJ.js.map → search-BJqFnKP5.js.map} +1 -1
- package/dist/web/public/assets/{search-BUlzNWrj.js → search-BpyL8Spy.js} +2 -2
- package/dist/web/public/assets/{search-BUlzNWrj.js.map → search-BpyL8Spy.js.map} +1 -1
- package/dist/web/public/assets/{security-DgJyTT4g.js → security-Cw_yJiDX.js} +2 -2
- package/dist/web/public/assets/{security-DgJyTT4g.js.map → security-Cw_yJiDX.js.map} +1 -1
- package/dist/web/public/assets/{service-A0Hzear0.js → service-CgSHzzZ2.js} +2 -2
- package/dist/web/public/assets/{service-A0Hzear0.js.map → service-CgSHzzZ2.js.map} +1 -1
- package/dist/web/public/assets/{shield-alert-DrnN6fz_.js → shield-alert-C_TX7BBD.js} +2 -2
- package/dist/web/public/assets/{shield-alert-DrnN6fz_.js.map → shield-alert-C_TX7BBD.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-Ryzf96Pl.js → status-badge-CLMCkv6R.js} +2 -2
- package/dist/web/public/assets/{status-badge-Ryzf96Pl.js.map → status-badge-CLMCkv6R.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-Bzh3o3EF.js → subtasks-BpXUesU9.js} +2 -2
- package/dist/web/public/assets/{subtasks-Bzh3o3EF.js.map → subtasks-BpXUesU9.js.map} +1 -1
- package/dist/web/public/assets/{table-BbAOSyc8.js → table-B-dheE8t.js} +2 -2
- package/dist/web/public/assets/{table-BbAOSyc8.js.map → table-B-dheE8t.js.map} +1 -1
- package/dist/web/public/assets/{topn-DkhYw-Gp.js → topn-CIXROr87.js} +2 -2
- package/dist/web/public/assets/{topn-DkhYw-Gp.js.map → topn-CIXROr87.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-CA0cLpnU.js → trash-2-CiJPCsGG.js} +2 -2
- package/dist/web/public/assets/{trash-2-CA0cLpnU.js.map → trash-2-CiJPCsGG.js.map} +1 -1
- package/dist/web/public/assets/use-agim-skills-DDOG9Vno.js +2 -0
- package/dist/web/public/assets/use-agim-skills-DDOG9Vno.js.map +1 -0
- package/dist/web/public/assets/{use-background-tasks-B64YjlA8.js → use-background-tasks-BT6BkFMM.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-B64YjlA8.js.map → use-background-tasks-BT6BkFMM.js.map} +1 -1
- package/dist/web/public/assets/{use-llm-admin-DY2axI4D.js → use-llm-admin-C5QwblGu.js} +2 -2
- package/dist/web/public/assets/{use-llm-admin-DY2axI4D.js.map → use-llm-admin-C5QwblGu.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-BYEjVWbU.js → use-memory-BaQLelYY.js} +2 -2
- package/dist/web/public/assets/{use-memory-BYEjVWbU.js.map → use-memory-BaQLelYY.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-Coj02yDo.js → use-observability-DiJjq_81.js} +2 -2
- package/dist/web/public/assets/{use-observability-Coj02yDo.js.map → use-observability-DiJjq_81.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-i1MhlkyC.js → use-settings-CTuwZEdY.js} +2 -2
- package/dist/web/public/assets/{use-settings-i1MhlkyC.js.map → use-settings-CTuwZEdY.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-DgEM35PY.js → use-workspace-42B5n8Aa.js} +2 -2
- package/dist/web/public/assets/{use-workspace-DgEM35PY.js.map → use-workspace-42B5n8Aa.js.map} +1 -1
- package/dist/web/public/assets/{useQuery-CY2iazjN.js → useQuery-BLyYPRRA.js} +2 -2
- package/dist/web/public/assets/{useQuery-CY2iazjN.js.map → useQuery-BLyYPRRA.js.map} +1 -1
- package/dist/web/public/assets/{vector-Ic76u2hY.js → vector-BlyEjpL_.js} +2 -2
- package/dist/web/public/assets/{vector-Ic76u2hY.js.map → vector-BlyEjpL_.js.map} +1 -1
- package/dist/web/public/assets/{viewer-BXbUN1Rl.js → viewer-nKB1rvkV.js} +2 -2
- package/dist/web/public/assets/{viewer-BXbUN1Rl.js.map → viewer-nKB1rvkV.js.map} +1 -1
- package/dist/web/public/assets/{workspace-CUg0JPn6.js → workspace-C5xO2uoT.js} +2 -2
- package/dist/web/public/assets/{workspace-CUg0JPn6.js.map → workspace-C5xO2uoT.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-C-wb5FQj.js → workspaces-BncBOneY.js} +2 -2
- package/dist/web/public/assets/{workspaces-C-wb5FQj.js.map → workspaces-BncBOneY.js.map} +1 -1
- package/dist/web/public/assets/{x-D1iSuoqg.js → x-De6HR8Q5.js} +2 -2
- package/dist/web/public/assets/{x-D1iSuoqg.js.map → x-De6HR8Q5.js.map} +1 -1
- package/dist/web/public/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/public/assets/index-DEWFfW_Z.js.map +0 -1
- package/dist/web/public/assets/installed-Xr8p31ij.js +0 -31
- package/dist/web/public/assets/installed-Xr8p31ij.js.map +0 -1
- package/dist/web/public/assets/layout-pasFRkKV.js +0 -2
- package/dist/web/public/assets/layout-pasFRkKV.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,128 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.2.152] - 2026-06-15
|
|
8
|
+
|
|
9
|
+
### Changed (后台 skills 管理体验)
|
|
10
|
+
|
|
11
|
+
针对 v1.2.151 后两个反馈做体验优化:
|
|
12
|
+
|
|
13
|
+
#### Q1 — installed 页按 5 bucket 分组 + 默认折叠 + 顶部搜索
|
|
14
|
+
|
|
15
|
+
364 个 skill 一根长 list 渲染太重;改成 loader 已有的 5 bucket 分组,
|
|
16
|
+
大组默认折叠:
|
|
17
|
+
|
|
18
|
+
- **Framework**(agim-* 4 条,默认展开)
|
|
19
|
+
- **Agim builtin**(github / weather / 等 8 条,默认展开)
|
|
20
|
+
- **Workspace**(运营者亲装 ~122 条,默认折叠)
|
|
21
|
+
- **ECC 推荐池**(20 条,默认展开)
|
|
22
|
+
- **ECC 余下**(~210 条,默认折叠)
|
|
23
|
+
|
|
24
|
+
顶部加搜索框(按 name + description 模糊匹配)。搜索激活时所有匹配桶
|
|
25
|
+
强制展开,并在每个桶头显示命中数 badge。
|
|
26
|
+
|
|
27
|
+
#### Q2 — injection 页 Refresh 升级为"重建默认注入词"
|
|
28
|
+
|
|
29
|
+
v1.2.151 的 Refresh 按钮只 refetch React Query,没真正失效 loader 5min cache
|
|
30
|
+
——运营者刚新增 skill 后看到的 auto 还是旧的。改成两步:
|
|
31
|
+
1. POST `/api/agim-skills/refresh`(loader 重扫磁盘 + invalidate cache)
|
|
32
|
+
2. refetch `/api/agim-skills/injection`(拿到 fresh auto block)
|
|
33
|
+
|
|
34
|
+
不影响 override(覆盖文件不动)。
|
|
35
|
+
|
|
36
|
+
按钮文案:中文"重建默认注入词" / 英文"Rebuild auto block"。
|
|
37
|
+
|
|
38
|
+
### Files
|
|
39
|
+
|
|
40
|
+
- `src/web/agim-skills-api.ts` — `handleList` 返回多加 `bucket: 0..4`(复用 `rankSkillBucket`)
|
|
41
|
+
- `src/web-app/src/hooks/use-agim-skills.ts` — `AgimSkillMeta.bucket?: 0|1|2|3|4`
|
|
42
|
+
- `src/web-app/src/routes/settings/agim-skills/installed.tsx` — `SkillsList` 重构为 bucket 分组 + 折叠 + 顶部搜索;导入 ChevronDown / ChevronRight / Search 图标
|
|
43
|
+
- `src/web-app/src/routes/settings/agim-skills/injection.tsx` — 新增 `useAgimSkillsRefresh` 依赖;`onRefresh` 改两步语义;按钮文案改成"重建"
|
|
44
|
+
- `src/web-app/src/i18n/locales/{zh,en}/settings.json` — 新增 `agimSkills.group.*` / `searchPlaceholder` / `searchEmpty` + `skillInjection.rebuild*` / `rebuiltToast`
|
|
45
|
+
|
|
46
|
+
### Tests
|
|
47
|
+
|
|
48
|
+
- API list 测试 (`agim-skills-api.test.ts` 13/13 旧 + 6 v1.2.151) + loader (42/42) → 61/61 全过
|
|
49
|
+
- backend typecheck 干净;SPA typecheck 仅遗留 search.tsx 错误(不在本 PR)
|
|
50
|
+
- SPA build 干净
|
|
51
|
+
|
|
52
|
+
## [1.2.151] - 2026-06-13
|
|
53
|
+
|
|
54
|
+
### Changed (skills injection — workspace 完整注入铁律 + 编辑入口)
|
|
55
|
+
|
|
56
|
+
v1.2.150 的 cluster 压缩对 workspace 太狠:35 个 `fin-data-*` 折成一行
|
|
57
|
+
`fin-data-* (35): name1 · name2 · …` 后 LLM 路由质量下降——只剩名字猜,没了
|
|
58
|
+
description 关键词。运营者亲装的 workspace skill 是最强 "我要用" 信号,
|
|
59
|
+
不应该为省 token 牺牲精度。
|
|
60
|
+
|
|
61
|
+
#### 铁律:workspace 完整注入,不折叠
|
|
62
|
+
|
|
63
|
+
`buildSkillsSummary` 拆出 `buildAutoInjectionBlock(all)`,bucket 3(workspace)
|
|
64
|
+
重新走 `renderSkillRow`(完整描述行):
|
|
65
|
+
|
|
66
|
+
- bucket 0/1/3 全部 full row(agim 框架 / agim builtin / **workspace**)
|
|
67
|
+
- bucket 2 ECC picks 仍 full row(20 个 curated 推荐)
|
|
68
|
+
- 只有 bucket 4(ECC remainder 210 个)才 cluster
|
|
69
|
+
|
|
70
|
+
#### 渲染顺序调整:0 → 1 → 3 → 2 → 4
|
|
71
|
+
|
|
72
|
+
workspace 排在 ECC picks 之前。运营者亲装 > 框架预选 > ECC remainder。
|
|
73
|
+
|
|
74
|
+
#### cluster refine bug fix
|
|
75
|
+
|
|
76
|
+
旧实现遇到"所有成员都在单个 sub-key 下"(例如全部 `fin-data-*` skill 都共享
|
|
77
|
+
2 段前缀)时 bottom out 不再递归,导致 fin-data 全部折成一行 cluster。
|
|
78
|
+
现在加分支:单 sub-key 占全部成员时自动 `segDepth+1` 继续细分,
|
|
79
|
+
所以 `fin-data-aspd-*` / `fin-data-stock-*` / `fin-data-fund-*` 会拆成
|
|
80
|
+
独立 cluster 而非合并。
|
|
81
|
+
|
|
82
|
+
#### 编辑入口:~/.agim/skill-injection-override.md
|
|
83
|
+
|
|
84
|
+
运营者可以覆盖自动生成的 skill 块。文件存在且非空时,**全文替换** auto block
|
|
85
|
+
(路由头 + always-on body 保留)。三个 helper:
|
|
86
|
+
`readInjectionOverride / writeInjectionOverride / deleteInjectionOverride`。
|
|
87
|
+
环境变量 `IMHUB_SKILLS_INJECTION_OVERRIDE_PATH` 可改路径(测试用)。
|
|
88
|
+
|
|
89
|
+
#### Admin API + SPA 页
|
|
90
|
+
|
|
91
|
+
- `GET /api/agim-skills/injection` → 返回 `{ auto, override, overrideActive, overridePath, maxOverrideChars }`
|
|
92
|
+
- `PUT /api/agim-skills/injection` body `{ body: string }` → 写 override(空 body=删除;>40k 字符 413)
|
|
93
|
+
- `DELETE /api/agim-skills/injection` → 清除 override
|
|
94
|
+
- 受现有 `/api/agim-skills/*` admin allowlist 守卫
|
|
95
|
+
- 新页面 `/settings/agim-skills/injection`:auto 只读 textarea + override 可编辑 textarea +
|
|
96
|
+
Save / Clear / Copy-auto / Refresh 按钮 + 字符计数 + ≥10k 警告
|
|
97
|
+
- 中英 i18n 全套
|
|
98
|
+
|
|
99
|
+
#### 新增 env knob
|
|
100
|
+
|
|
101
|
+
- `IMHUB_SKILLS_ECC_PICKS=name1,name2,...` 覆盖默认 20 picks(推荐池)
|
|
102
|
+
- `IMHUB_SKILLS_INJECT_ECC_REMAINDER=on|off|name-list`:
|
|
103
|
+
- `on`(默认):cluster 模式
|
|
104
|
+
- `off`:完全抑制 ECC remainder 块(省 token)
|
|
105
|
+
- 逗号分隔白名单:只保留指定 skill
|
|
106
|
+
|
|
107
|
+
### Files
|
|
108
|
+
|
|
109
|
+
- `src/core/skills/loader.ts` — workspace 完整注入 + 顺序调整 + refine bug fix +
|
|
110
|
+
env knob 解析(`resolveEccTopPicks` / `resolveEccRemainderMode`)+
|
|
111
|
+
override 文件 helper(read / write / delete / `injectionOverridePath`)+
|
|
112
|
+
`buildAutoInjectionBlock` 导出供 API 预览
|
|
113
|
+
- `src/web/agim-skills-api.ts` — 新 GET/PUT/DELETE `/api/agim-skills/injection`
|
|
114
|
+
- `src/web/agim-skills-api.test.ts` — +5 case(GET 元数据 / PUT 保存 / DELETE / 空 body=删 / 413 超限)
|
|
115
|
+
- `src/web-app/src/hooks/use-agim-skills.ts` — `useSkillInjection / Save / Delete`
|
|
116
|
+
- `src/web-app/src/routes/settings/agim-skills/injection.tsx` — 新页面
|
|
117
|
+
- `src/web-app/src/routes/settings/agim-skills/layout.tsx` — tab 新增"系统提示注入"
|
|
118
|
+
- `src/web-app/src/router.tsx` — 注册新 route
|
|
119
|
+
- `src/web-app/src/i18n/locales/{zh,en}/settings.json` — `skillInjection.*` 文案
|
|
120
|
+
- `src/core/skills/loader.test.ts` — +5 case(refine 单 sub-key 递归 / picks env / remainder off / remainder allowlist / override 全文替换);2 case 旧断言更新(workspace 不聚类 / workspace 排在 ECC picks 前)
|
|
121
|
+
|
|
122
|
+
### Tests
|
|
123
|
+
|
|
124
|
+
- `loader.test.ts`:42/42 全过
|
|
125
|
+
- `agim-skills-api.test.ts`:19/19 全过
|
|
126
|
+
- typecheck 干净(search.tsx 是历史遗留,不归本 PR)
|
|
127
|
+
- SPA build 干净(`injection-*.js` chunk 已生成)
|
|
128
|
+
|
|
7
129
|
## [1.2.150] - 2026-06-12
|
|
8
130
|
|
|
9
131
|
### Changed (skills system-prompt injection — cluster-aware compression)
|
|
@@ -104,6 +104,40 @@ export declare function getSkillByName(name: string): SkillMeta | null;
|
|
|
104
104
|
* unknown name OR read failure. Honors the MAX_SKILL_BODY_CHARS cap;
|
|
105
105
|
* oversize files come back truncated with a `[truncated …]` footer. */
|
|
106
106
|
export declare function readSkillBody(name: string): string | null;
|
|
107
|
+
/**
|
|
108
|
+
* v1.2.151 — Resolve the active ECC top-pick set. Operators can override
|
|
109
|
+
* via `IMHUB_SKILLS_ECC_PICKS=name1,name2,...`. An empty or unset value
|
|
110
|
+
* falls back to the default 20-name list. Validation is intentionally
|
|
111
|
+
* forgiving: unknown names pass through (they just become no-ops when
|
|
112
|
+
* the named skill isn't installed).
|
|
113
|
+
*/
|
|
114
|
+
export declare function resolveEccTopPicks(): ReadonlySet<string>;
|
|
115
|
+
/**
|
|
116
|
+
* v1.2.151 — ECC remainder injection policy. Default `on` emits the
|
|
117
|
+
* cluster block. `off` suppresses it entirely (token-saving for ops
|
|
118
|
+
* who only want the recommended picks). A comma-list value flips to
|
|
119
|
+
* "allowlist" mode: only remainder skills in the list are emitted.
|
|
120
|
+
*/
|
|
121
|
+
type EccRemainderMode = {
|
|
122
|
+
mode: 'on';
|
|
123
|
+
} | {
|
|
124
|
+
mode: 'off';
|
|
125
|
+
} | {
|
|
126
|
+
mode: 'allowlist';
|
|
127
|
+
names: Set<string>;
|
|
128
|
+
};
|
|
129
|
+
export declare function resolveEccRemainderMode(): EccRemainderMode;
|
|
130
|
+
export declare function injectionOverridePath(): string;
|
|
131
|
+
/** Read the override file. Returns the trimmed body, or null when the
|
|
132
|
+
* file is missing / empty / unreadable. Never throws. */
|
|
133
|
+
export declare function readInjectionOverride(): string | null;
|
|
134
|
+
/** Write (or replace) the override file. The caller is responsible for
|
|
135
|
+
* authorization — this is a thin filesystem helper. Returns true on
|
|
136
|
+
* success, false on any disk error. */
|
|
137
|
+
export declare function writeInjectionOverride(body: string): boolean;
|
|
138
|
+
/** Delete the override file. Returns true when a file was actually
|
|
139
|
+
* removed (or already gone), false on filesystem error. */
|
|
140
|
+
export declare function deleteInjectionOverride(): boolean;
|
|
107
141
|
/**
|
|
108
142
|
* v1.2.149 — Rank a skill into one of four buckets for system-prompt
|
|
109
143
|
* injection. Lower rank wins (fills the visible 32 first). Within a
|
|
@@ -165,5 +199,25 @@ export declare function clusterSkills(skills: ReadonlyArray<SkillMeta>, minSize?
|
|
|
165
199
|
clusters: SkillCluster[];
|
|
166
200
|
singletons: SkillMeta[];
|
|
167
201
|
};
|
|
202
|
+
/**
|
|
203
|
+
* v1.2.151 — Build the auto-generated tier-1 block (no header, no
|
|
204
|
+
* always-on bodies — caller wraps). Separated so the SPA editor can
|
|
205
|
+
* preview "what would auto produce right now" via the admin API.
|
|
206
|
+
*
|
|
207
|
+
* Bucket render order:
|
|
208
|
+
* 0 framework → 1 builtin → **3 workspace** → 2 ECC picks → 4 ECC remainder
|
|
209
|
+
*
|
|
210
|
+
* Operator-installed workspace skills out-rank ECC pinned picks because
|
|
211
|
+
* they are the strongest "I want this" signal. ECC picks (curated
|
|
212
|
+
* harness vocabulary) come right after so the LLM still has them
|
|
213
|
+
* within reach. ECC remainder lives at the bottom as the on-demand
|
|
214
|
+
* pool.
|
|
215
|
+
*
|
|
216
|
+
* Buckets 0/1/2/3 all emit full rows (renderSkillRow). Only bucket 4
|
|
217
|
+
* (ECC remainder) clusters — and even then, the cluster path can be
|
|
218
|
+
* disabled or scoped via `IMHUB_SKILLS_INJECT_ECC_REMAINDER`.
|
|
219
|
+
*/
|
|
220
|
+
export declare function buildAutoInjectionBlock(all: ReadonlyArray<SkillMeta>): string;
|
|
168
221
|
export declare function buildSkillsSummary(): string;
|
|
222
|
+
export {};
|
|
169
223
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/skills/loader.ts"],"names":[],"mappings":"AAiDA;;sEAEsE;AACtE,eAAO,MAAM,oBAAoB,QAAS,CAAA;AAE1C;;gDAEgD;AAChD,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC;;oDAEoD;AACpD,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,4EAA4E;IAC5E,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAA;IACX;;2DAEuD;IACvD,MAAM,EAAE,OAAO,CAAA;IACf;qCACiC;IACjC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB;0DACsD;IACtD,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB;;0EAEsE;IACtE,SAAS,EAAE,OAAO,CAAA;IAClB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;mEAE+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAmCD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;AA4BxD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAiB7C;AAED;sEACsE;AACtE,wBAAgB,oBAAoB,IAAI;IACtC,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB,CAOA;AAuBD,wEAAwE;AACxE,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAmB3E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAajD;AAYD;;oDAEoD;AACpD,wBAAgB,UAAU,IAAI,SAAS,EAAE,CAExC;AAED;;6BAE6B;AAC7B,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE7D;AAED;;wEAEwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzD;AAkDD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAsBpD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf;gEAC4D;IAC5D,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,EAChC,OAAO,SAAI,GACV;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,EAAE,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/skills/loader.ts"],"names":[],"mappings":"AAiDA;;sEAEsE;AACtE,eAAO,MAAM,oBAAoB,QAAS,CAAA;AAE1C;;gDAEgD;AAChD,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC;;oDAEoD;AACpD,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,4EAA4E;IAC5E,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAA;IACX;;2DAEuD;IACvD,MAAM,EAAE,OAAO,CAAA;IACf;qCACiC;IACjC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB;0DACsD;IACtD,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB;;0EAEsE;IACtE,SAAS,EAAE,OAAO,CAAA;IAClB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;mEAE+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAmCD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;AA4BxD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAiB7C;AAED;sEACsE;AACtE,wBAAgB,oBAAoB,IAAI;IACtC,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB,CAOA;AAuBD,wEAAwE;AACxE,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAmB3E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAajD;AAYD;;oDAEoD;AACpD,wBAAgB,UAAU,IAAI,SAAS,EAAE,CAExC;AAED;;6BAE6B;AAC7B,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE7D;AAED;;wEAEwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzD;AAkDD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CAAC,MAAM,CAAC,CAMxD;AAED;;;;;GAKG;AACH,KAAK,gBAAgB,GACjB;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAE7C,wBAAgB,uBAAuB,IAAI,gBAAgB,CAQ1D;AAwBD,wBAAgB,qBAAqB,IAAI,MAAM,CAI9C;AAED;0DAC0D;AAC1D,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAUrD;AAED;;wCAEwC;AACxC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAU5D;AAED;4DAC4D;AAC5D,wBAAgB,uBAAuB,IAAI,OAAO,CAUjD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAsBpD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf;gEAC4D;IAC5D,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,EAChC,OAAO,SAAI,GACV;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,EAAE,CAAA;CAAE,CA6FvD;AAkFD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,aAAa,CAAC,SAAS,CAAC,GAAG,MAAM,CA0C7E;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAmB3C"}
|
|
@@ -315,7 +315,7 @@ export function readSkillBody(name) {
|
|
|
315
315
|
*
|
|
316
316
|
* Add / remove freely — this is a curated list, not a registry.
|
|
317
317
|
*/
|
|
318
|
-
const
|
|
318
|
+
const ECC_TOP_PICKS_DEFAULT = new Set([
|
|
319
319
|
// Agent harness engineering (11)
|
|
320
320
|
'agentic-engineering', 'agent-eval', 'agent-introspection-debugging',
|
|
321
321
|
'agent-harness-construction', 'autonomous-agent-harness', 'autonomous-loops',
|
|
@@ -326,6 +326,105 @@ const ECC_TOP_PICKS = new Set([
|
|
|
326
326
|
'code-tour', 'tdd-workflow', 'security-review', 'benchmark',
|
|
327
327
|
'article-writing', 'content-engine',
|
|
328
328
|
]);
|
|
329
|
+
/**
|
|
330
|
+
* v1.2.151 — Resolve the active ECC top-pick set. Operators can override
|
|
331
|
+
* via `IMHUB_SKILLS_ECC_PICKS=name1,name2,...`. An empty or unset value
|
|
332
|
+
* falls back to the default 20-name list. Validation is intentionally
|
|
333
|
+
* forgiving: unknown names pass through (they just become no-ops when
|
|
334
|
+
* the named skill isn't installed).
|
|
335
|
+
*/
|
|
336
|
+
export function resolveEccTopPicks() {
|
|
337
|
+
const raw = (process.env.IMHUB_SKILLS_ECC_PICKS || '').trim();
|
|
338
|
+
if (!raw)
|
|
339
|
+
return ECC_TOP_PICKS_DEFAULT;
|
|
340
|
+
const names = raw.split(/[,;\s]+/).map((s) => s.trim()).filter(Boolean);
|
|
341
|
+
if (names.length === 0)
|
|
342
|
+
return ECC_TOP_PICKS_DEFAULT;
|
|
343
|
+
return new Set(names);
|
|
344
|
+
}
|
|
345
|
+
export function resolveEccRemainderMode() {
|
|
346
|
+
const raw = (process.env.IMHUB_SKILLS_INJECT_ECC_REMAINDER || '').trim().toLowerCase();
|
|
347
|
+
if (!raw || raw === 'on' || raw === '1' || raw === 'true')
|
|
348
|
+
return { mode: 'on' };
|
|
349
|
+
if (raw === 'off' || raw === '0' || raw === 'false')
|
|
350
|
+
return { mode: 'off' };
|
|
351
|
+
// Anything else is treated as a comma/whitespace-separated allowlist.
|
|
352
|
+
const names = raw.split(/[,;\s]+/).map((s) => s.trim()).filter(Boolean);
|
|
353
|
+
if (names.length === 0)
|
|
354
|
+
return { mode: 'on' };
|
|
355
|
+
return { mode: 'allowlist', names: new Set(names) };
|
|
356
|
+
}
|
|
357
|
+
// ─── v1.2.151 — operator-tunable injection override ────────────────────
|
|
358
|
+
//
|
|
359
|
+
// Operators frequently want to nudge the auto-generated skills block —
|
|
360
|
+
// pin a specific skill higher, hide one that's noisy, add a routing
|
|
361
|
+
// hint about a custom env, etc. Rather than expanding the env-knob
|
|
362
|
+
// surface for every dimension, agim accepts a verbatim text file at
|
|
363
|
+
// `~/.agim/skill-injection-override.md` that REPLACES the auto block.
|
|
364
|
+
//
|
|
365
|
+
// When the file exists and is non-empty, buildSkillsSummary returns:
|
|
366
|
+
// - the standard "[agim tool routing — skills first]" header
|
|
367
|
+
// - the override file contents (verbatim, trimmed)
|
|
368
|
+
// - the always-on skill bodies (unchanged)
|
|
369
|
+
//
|
|
370
|
+
// The auto-generated block (priority buckets + clusters) is suppressed.
|
|
371
|
+
// Tests and CI override the path via IMHUB_SKILLS_INJECTION_OVERRIDE_PATH
|
|
372
|
+
// to avoid polluting the operator's real ~/.agim/.
|
|
373
|
+
//
|
|
374
|
+
// Editor entrypoint: the SPA page `/settings/skill-injection` calls
|
|
375
|
+
// admin endpoints to read auto + read/write/delete the override.
|
|
376
|
+
const INJECTION_OVERRIDE_FILENAME = 'skill-injection-override.md';
|
|
377
|
+
export function injectionOverridePath() {
|
|
378
|
+
const override = process.env.IMHUB_SKILLS_INJECTION_OVERRIDE_PATH;
|
|
379
|
+
if (override)
|
|
380
|
+
return override;
|
|
381
|
+
return join(AGIM_HOME, INJECTION_OVERRIDE_FILENAME);
|
|
382
|
+
}
|
|
383
|
+
/** Read the override file. Returns the trimmed body, or null when the
|
|
384
|
+
* file is missing / empty / unreadable. Never throws. */
|
|
385
|
+
export function readInjectionOverride() {
|
|
386
|
+
const path = injectionOverridePath();
|
|
387
|
+
try {
|
|
388
|
+
if (!existsSync(path))
|
|
389
|
+
return null;
|
|
390
|
+
const raw = readFileSync(path, 'utf-8').trim();
|
|
391
|
+
return raw || null;
|
|
392
|
+
}
|
|
393
|
+
catch (err) {
|
|
394
|
+
log.warn({ event: 'skills.injection_override.read_failed', path, err: String(err) });
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/** Write (or replace) the override file. The caller is responsible for
|
|
399
|
+
* authorization — this is a thin filesystem helper. Returns true on
|
|
400
|
+
* success, false on any disk error. */
|
|
401
|
+
export function writeInjectionOverride(body) {
|
|
402
|
+
const path = injectionOverridePath();
|
|
403
|
+
try {
|
|
404
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
405
|
+
writeFileSync(path, body, 'utf-8');
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
catch (err) {
|
|
409
|
+
log.warn({ event: 'skills.injection_override.write_failed', path, err: String(err) });
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/** Delete the override file. Returns true when a file was actually
|
|
414
|
+
* removed (or already gone), false on filesystem error. */
|
|
415
|
+
export function deleteInjectionOverride() {
|
|
416
|
+
const path = injectionOverridePath();
|
|
417
|
+
try {
|
|
418
|
+
if (!existsSync(path))
|
|
419
|
+
return true;
|
|
420
|
+
rmSync(path, { force: true });
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
log.warn({ event: 'skills.injection_override.delete_failed', path, err: String(err) });
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
329
428
|
/**
|
|
330
429
|
* v1.2.149 — Rank a skill into one of four buckets for system-prompt
|
|
331
430
|
* injection. Lower rank wins (fills the visible 32 first). Within a
|
|
@@ -368,7 +467,7 @@ export function rankSkillBucket(s) {
|
|
|
368
467
|
const isEcc = s.source === 'builtin'
|
|
369
468
|
&& (s.description.startsWith('[ECC] ') || /^ECC\b/i.test(s.origin ?? ''));
|
|
370
469
|
if (isEcc)
|
|
371
|
-
return
|
|
470
|
+
return resolveEccTopPicks().has(s.name) ? 2 : 4;
|
|
372
471
|
if (s.source === 'workspace')
|
|
373
472
|
return 3;
|
|
374
473
|
// non-ECC builtin (agim's own small in-tree pack)
|
|
@@ -441,6 +540,14 @@ export function clusterSkills(skills, minSize = 3) {
|
|
|
441
540
|
used.add(s.name);
|
|
442
541
|
}
|
|
443
542
|
}
|
|
543
|
+
else if (qualified.length === 1 && sub.size === 1) {
|
|
544
|
+
// v1.2.151 — single sub-key contains ALL members (e.g. all `fin-*`
|
|
545
|
+
// are `fin-data-*` at depth 2). Recurse deeper to split by depth+1
|
|
546
|
+
// instead of collapsing into a single coarse `fin-data-*` group.
|
|
547
|
+
// Without this fix, 69 fin-data skills land in one cluster and
|
|
548
|
+
// the LLM can't tell aspd / stock / fund families apart by name.
|
|
549
|
+
refine(sub.get(qualified[0]), segDepth + 1);
|
|
550
|
+
}
|
|
444
551
|
else {
|
|
445
552
|
emitCluster(group, segDepth - 1);
|
|
446
553
|
}
|
|
@@ -513,118 +620,136 @@ const BUCKET_HEADINGS = {
|
|
|
513
620
|
3: 'Workspace skills (operator-installed business)',
|
|
514
621
|
4: 'ECC remainder (read full description via mcp__imhub__read_skill)',
|
|
515
622
|
};
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
623
|
+
/**
|
|
624
|
+
* v1.2.137 — Routing rule prepended to every turn's skill block.
|
|
625
|
+
* v1.2.151 — Extracted into a constant so the override path and the
|
|
626
|
+
* auto path share the same header verbatim.
|
|
627
|
+
*/
|
|
628
|
+
const SKILLS_ROUTING_HEADER = [
|
|
629
|
+
'[agim tool routing — skills first]',
|
|
630
|
+
'Before calling any generic tool (web_fetch / web_search / native_exec /',
|
|
631
|
+
'shell-style commands), you MUST scan the skill list below. If any entry\'s',
|
|
632
|
+
'description matches the user\'s intent — even loosely — you MUST call',
|
|
633
|
+
'mcp__imhub__read_skill(\'<name>\') first to load that skill\'s body. Skill',
|
|
634
|
+
'bodies contain dedicated tools, endpoints, or queries that produce',
|
|
635
|
+
'higher-quality, structured results than free-text web pages for the',
|
|
636
|
+
'same intent. Falling back to the generic tool is only valid when:',
|
|
637
|
+
' (a) no skill description plausibly matches, OR',
|
|
638
|
+
' (b) you already read a relevant skill and its body explicitly says',
|
|
639
|
+
' "this skill is not suitable for X" or lacks the needed coverage.',
|
|
640
|
+
'This is a routing discipline, not a hint. Skipping it counts as a',
|
|
641
|
+
'tool-routing error in this conversation.',
|
|
642
|
+
].join('\n');
|
|
643
|
+
/**
|
|
644
|
+
* v1.2.151 — Render one skill as a tier-1 row with full description.
|
|
645
|
+
* The body is defensive against malformed YAML block-scalar leakage.
|
|
646
|
+
*
|
|
647
|
+
* NOTE: workspace skills (bucket 3) MUST always go through this path
|
|
648
|
+
* — operator-installed business skills are an "I want this" signal
|
|
649
|
+
* from the deployment, so we keep their full descriptions for routing
|
|
650
|
+
* precision regardless of how many there are. The token cost is real
|
|
651
|
+
* but intentional; operators with 100+ workspace skills can use the
|
|
652
|
+
* SPA `/settings/skill-injection` editor to prune (see override path).
|
|
653
|
+
*/
|
|
654
|
+
function renderSkillRow(s) {
|
|
655
|
+
const reason = s.available ? '' : ` (unavailable: ${s.unavailableReason ?? 'requires not met'})`;
|
|
656
|
+
const flag = s.always ? ' [always]' : '';
|
|
657
|
+
const descClean = (s.description || '').trim();
|
|
658
|
+
const description = descClean && descClean !== '>-' && descClean !== '|'
|
|
659
|
+
? descClean
|
|
660
|
+
: '(no description in SKILL.md — read body via mcp__imhub__read_skill)';
|
|
661
|
+
return `- ${s.name}: ${description}${reason}${flag}`;
|
|
662
|
+
}
|
|
663
|
+
/** Inline `always: true` skill bodies. Shared between override + auto. */
|
|
664
|
+
function appendAlwaysOnBodies(all, lines) {
|
|
665
|
+
const alwaysOn = all.filter((s) => s.always && s.available);
|
|
666
|
+
for (const s of alwaysOn) {
|
|
667
|
+
const body = readSkillBody(s.name);
|
|
668
|
+
if (!body)
|
|
669
|
+
continue;
|
|
670
|
+
lines.push('');
|
|
671
|
+
lines.push(`### Always-on skill: ${s.name}`);
|
|
672
|
+
lines.push(body);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* v1.2.151 — Build the auto-generated tier-1 block (no header, no
|
|
677
|
+
* always-on bodies — caller wraps). Separated so the SPA editor can
|
|
678
|
+
* preview "what would auto produce right now" via the admin API.
|
|
679
|
+
*
|
|
680
|
+
* Bucket render order:
|
|
681
|
+
* 0 framework → 1 builtin → **3 workspace** → 2 ECC picks → 4 ECC remainder
|
|
682
|
+
*
|
|
683
|
+
* Operator-installed workspace skills out-rank ECC pinned picks because
|
|
684
|
+
* they are the strongest "I want this" signal. ECC picks (curated
|
|
685
|
+
* harness vocabulary) come right after so the LLM still has them
|
|
686
|
+
* within reach. ECC remainder lives at the bottom as the on-demand
|
|
687
|
+
* pool.
|
|
688
|
+
*
|
|
689
|
+
* Buckets 0/1/2/3 all emit full rows (renderSkillRow). Only bucket 4
|
|
690
|
+
* (ECC remainder) clusters — and even then, the cluster path can be
|
|
691
|
+
* disabled or scoped via `IMHUB_SKILLS_INJECT_ECC_REMAINDER`.
|
|
692
|
+
*/
|
|
693
|
+
export function buildAutoInjectionBlock(all) {
|
|
531
694
|
const byBucket = { 0: [], 1: [], 2: [], 3: [], 4: [] };
|
|
532
695
|
for (const s of all)
|
|
533
696
|
byBucket[rankSkillBucket(s)].push(s);
|
|
534
697
|
for (const b of [0, 1, 2, 3, 4]) {
|
|
535
698
|
byBucket[b].sort((a, b2) => a.name.localeCompare(b2.name));
|
|
536
699
|
}
|
|
537
|
-
const lines = [
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
// any specific skill name, so users with zero skills installed see
|
|
543
|
-
// an empty block (early return above) and aren't burdened with the
|
|
544
|
-
// rule text. The "MUST" framing + explicit fallback whitelist is
|
|
545
|
-
// tuned to be hard enough that models don't drift back to web_fetch
|
|
546
|
-
// out of habit when a relevant skill exists.
|
|
547
|
-
'[agim tool routing — skills first]',
|
|
548
|
-
'Before calling any generic tool (web_fetch / web_search / native_exec /',
|
|
549
|
-
'shell-style commands), you MUST scan the skill list below. If any entry\'s',
|
|
550
|
-
'description matches the user\'s intent — even loosely — you MUST call',
|
|
551
|
-
'mcp__imhub__read_skill(\'<name>\') first to load that skill\'s body. Skill',
|
|
552
|
-
'bodies contain dedicated tools, endpoints, or queries that produce',
|
|
553
|
-
'higher-quality, structured results than free-text web pages for the',
|
|
554
|
-
'same intent. Falling back to the generic tool is only valid when:',
|
|
555
|
-
' (a) no skill description plausibly matches, OR',
|
|
556
|
-
' (b) you already read a relevant skill and its body explicitly says',
|
|
557
|
-
' "this skill is not suitable for X" or lacks the needed coverage.',
|
|
558
|
-
'This is a routing discipline, not a hint. Skipping it counts as a',
|
|
559
|
-
'tool-routing error in this conversation.',
|
|
560
|
-
'',
|
|
561
|
-
'[agim skills available — read full body with mcp__imhub__read_skill(name)]',
|
|
562
|
-
];
|
|
563
|
-
// Helper: render one skill as an individual row with full description.
|
|
564
|
-
// Same shape as v1.2.149; defensive fallback for malformed descriptions.
|
|
565
|
-
const renderRow = (s) => {
|
|
566
|
-
const reason = s.available ? '' : ` (unavailable: ${s.unavailableReason ?? 'requires not met'})`;
|
|
567
|
-
const flag = s.always ? ' [always]' : '';
|
|
568
|
-
const descClean = (s.description || '').trim();
|
|
569
|
-
const description = descClean && descClean !== '>-' && descClean !== '|'
|
|
570
|
-
? descClean
|
|
571
|
-
: '(no description in SKILL.md — read body via mcp__imhub__read_skill)';
|
|
572
|
-
return `- ${s.name}: ${description}${reason}${flag}`;
|
|
573
|
-
};
|
|
574
|
-
// Buckets 0, 1, 2: individual rows (curated, small).
|
|
575
|
-
for (const b of [0, 1, 2]) {
|
|
700
|
+
const lines = ['[agim skills available — read full body with mcp__imhub__read_skill(name)]'];
|
|
701
|
+
// Render order: 0 framework, 1 builtin, 3 workspace, 2 ECC picks.
|
|
702
|
+
// Workspace before ECC picks per v1.2.151 iron rule: operator-installed
|
|
703
|
+
// business skills rank above framework-curated harness picks.
|
|
704
|
+
for (const b of [0, 1, 3, 2]) {
|
|
576
705
|
const items = byBucket[b];
|
|
577
706
|
if (items.length === 0)
|
|
578
707
|
continue;
|
|
579
708
|
lines.push('');
|
|
580
709
|
lines.push(`## ${BUCKET_HEADINGS[b]} (${items.length})`);
|
|
581
710
|
for (const s of items)
|
|
582
|
-
lines.push(
|
|
711
|
+
lines.push(renderSkillRow(s));
|
|
583
712
|
}
|
|
584
|
-
// Bucket
|
|
585
|
-
// else individual rows. Per-cluster trigger hint included (the LLM is
|
|
586
|
-
// most likely to route into this bucket on operator-domain queries).
|
|
587
|
-
const ws = byBucket[3];
|
|
588
|
-
if (ws.length > 0) {
|
|
589
|
-
lines.push('');
|
|
590
|
-
lines.push(`## ${BUCKET_HEADINGS[3]} (${ws.length})`);
|
|
591
|
-
const { clusters, singletons } = clusterSkills(ws, 3);
|
|
592
|
-
for (const c of clusters) {
|
|
593
|
-
lines.push(`- ${c.prefix}-* (${c.names.length}): ${c.names.join(' · ')}`);
|
|
594
|
-
if (c.triggerHint)
|
|
595
|
-
lines.push(` → ${c.triggerHint}`);
|
|
596
|
-
}
|
|
597
|
-
for (const s of singletons)
|
|
598
|
-
lines.push(renderRow(s));
|
|
599
|
-
}
|
|
600
|
-
// Bucket 4 (ECC remainder): cluster aggressively, name-only (no per-
|
|
601
|
-
// cluster trigger hint — these are the "on-demand" pool, the LLM gets
|
|
602
|
-
// a per-skill description if it actually calls read_skill).
|
|
713
|
+
// Bucket 4 (ECC remainder) — cluster, with operator opt-out / allowlist.
|
|
603
714
|
const eccRem = byBucket[4];
|
|
604
715
|
if (eccRem.length > 0) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
716
|
+
const remainderMode = resolveEccRemainderMode();
|
|
717
|
+
const filtered = remainderMode.mode === 'off' ? []
|
|
718
|
+
: remainderMode.mode === 'allowlist'
|
|
719
|
+
? eccRem.filter((s) => remainderMode.names.has(s.name))
|
|
720
|
+
: eccRem;
|
|
721
|
+
if (filtered.length > 0) {
|
|
722
|
+
lines.push('');
|
|
723
|
+
lines.push(`## ${BUCKET_HEADINGS[4]} (${filtered.length})`);
|
|
724
|
+
const { clusters, singletons } = clusterSkills(filtered, 3);
|
|
725
|
+
for (const c of clusters) {
|
|
726
|
+
lines.push(`- ${c.prefix}-* (${c.names.length}): ${c.names.join(' · ')}`);
|
|
727
|
+
}
|
|
728
|
+
if (singletons.length > 0) {
|
|
729
|
+
const names = singletons.map((s) => s.name).join(' · ');
|
|
730
|
+
lines.push(`- (other ECC, ${singletons.length}): ${names}`);
|
|
731
|
+
}
|
|
614
732
|
}
|
|
615
733
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
734
|
+
return lines.join('\n');
|
|
735
|
+
}
|
|
736
|
+
export function buildSkillsSummary() {
|
|
737
|
+
const all = listSkills();
|
|
738
|
+
if (all.length === 0)
|
|
739
|
+
return '';
|
|
740
|
+
// v1.2.151 — operator override path: if `~/.agim/skill-injection-
|
|
741
|
+
// override.md` exists, return its body verbatim (still wrapped by
|
|
742
|
+
// the routing header + always-on bodies). The auto block is
|
|
743
|
+
// suppressed; the operator gets full editorial control. The SPA at
|
|
744
|
+
// `/settings/skill-injection` is the recommended way to author this.
|
|
745
|
+
const override = readInjectionOverride();
|
|
746
|
+
if (override) {
|
|
747
|
+
const lines = [SKILLS_ROUTING_HEADER, '', override];
|
|
748
|
+
appendAlwaysOnBodies(all, lines);
|
|
749
|
+
return `${lines.join('\n')}\n`;
|
|
627
750
|
}
|
|
751
|
+
const lines = [SKILLS_ROUTING_HEADER, '', buildAutoInjectionBlock(all)];
|
|
752
|
+
appendAlwaysOnBodies(all, lines);
|
|
628
753
|
return `${lines.join('\n')}\n`;
|
|
629
754
|
}
|
|
630
755
|
// ─── Scanning ────────────────────────────────────────────────────────
|