sliccy 6.232.3 → 6.233.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/node-server/chrome-launch.d.ts +2 -0
- package/dist/node-server/chrome-launch.js +11 -1
- package/dist/node-server/index.js +1 -0
- package/dist/ui/.vite/manifest.json +282 -278
- package/dist/ui/assets/{SKILL-DfQfFV0B.js → SKILL-BcBnRJhU.js} +1 -1
- package/dist/ui/assets/{SKILL-CDWYTQKl.js → SKILL-BsfbaE8W.js} +1 -1
- package/dist/ui/assets/SKILL-Dk6kide7.js +1 -0
- package/dist/ui/assets/account-store-8pdjPGXe.js +2 -0
- package/dist/ui/assets/account-store-CYgyHiaa.js +1 -0
- package/dist/ui/assets/adobe-B4FKwftW.js +2 -0
- package/dist/ui/assets/adobe-C195sVCf.js +1 -0
- package/dist/ui/assets/agent-help-B-gfDDn0.js +103 -0
- package/dist/ui/assets/agent-images-DaBj3QYk.js +3 -0
- package/dist/ui/assets/{agent-panels-cs_l6Y3W.js → agent-panels-C968Kub9.js} +1 -1
- package/dist/ui/assets/{agent-tools-BzWhYeEw.js → agent-tools-WbCq5rUh.js} +1 -1
- package/dist/ui/assets/{almost-bash-shell-headless-B82NrHyV.js → almost-bash-shell-headless-Dw8ck55P.js} +91 -175
- package/dist/ui/assets/{apply-layout-DHjJQg3o.js → apply-layout-CHfVXHPf.js} +1 -1
- package/dist/ui/assets/{apps-CsJCa1W4.js → apps-CyIXX0a_.js} +1 -1
- package/dist/ui/assets/{azure-openai-0xShokH8.js → azure-openai-BK1yv0Sn.js} +1 -1
- package/dist/ui/assets/{azure-openai-DBSL3940.js → azure-openai-DSJ0iXpS.js} +1 -1
- package/dist/ui/assets/{backend-hostfs-DAjlRr0I.js → backend-hostfs-DmMZ1Vnt.js} +1 -1
- package/dist/ui/assets/{capability-BsxMoeMg.js → capability-6V-AYPSJ.js} +2 -2
- package/dist/ui/assets/{cdp-bOHrUn4t.js → cdp-DZ3LtBJ6.js} +1 -1
- package/dist/ui/assets/{cerebras-CJtdoZMJ.js → cerebras-B0XnBx_U.js} +1 -1
- package/dist/ui/assets/{cerebras-Sczc8yWr.js → cerebras-Cq1Qi0CT.js} +1 -1
- package/dist/ui/assets/{client-DWx5wn8j.js → client-D5zdJCVT.js} +1 -1
- package/dist/ui/assets/{codemode-tool-BH0jhnKf.js → codemode-tool-FcP24sWd.js} +1 -1
- package/dist/ui/assets/{composer-speech-Dt5JE2sh.js → composer-speech-DEsTTJ-6.js} +1 -1
- package/dist/ui/assets/{connect-surface-BO_rHeDZ.js → connect-surface-k_k7uu5o.js} +1 -1
- package/dist/ui/assets/{connection-manager-E3P4E4Le.js → connection-manager-D0LxHiWb.js} +1 -1
- package/dist/ui/assets/core-C1m4D34S.js +36 -0
- package/dist/ui/assets/{core-4boN-CgI.js → core-Cx9N3lmn.js} +1 -1
- package/dist/ui/assets/{cost-command-C_1fldSP.js → cost-command-BUgEVZCe.js} +8 -1
- package/dist/ui/assets/{directed-approval-Dig9vgFX.js → directed-approval-OOf3I27R.js} +1 -1
- package/dist/ui/assets/{discovery-preference-D1cUzn0M.js → discovery-preference-D8GXCv8i.js} +1 -1
- package/dist/ui/assets/{emscripten-vfs-hook-BJh0QvlC.js → emscripten-vfs-hook-D4rVkB6b.js} +1 -1
- package/dist/ui/assets/emscripten-vfs-hook-t32dk5w7.js +1 -0
- package/dist/ui/assets/{ensure-speech-assets-BQperrcM.js → ensure-speech-assets-CB-6d53s.js} +1 -1
- package/dist/ui/assets/{extension-ops-Ded2__AC.js → extension-ops-OtrqWANJ.js} +1 -1
- package/dist/ui/assets/{float-topology-DIH6ujZe.js → float-topology-COIC4j_U.js} +1 -1
- package/dist/ui/assets/{float-topology-C9GjBEv-.js → float-topology-C_iRKPQK.js} +1 -1
- package/dist/ui/assets/{follower-navigate-watcher-T4oXQ4JA.js → follower-navigate-watcher-C0CP4-Mn.js} +1 -1
- package/dist/ui/assets/{frozen-archive-writer-DHfEFu3h.js → frozen-archive-writer-CyeRvZhz.js} +1 -1
- package/dist/ui/assets/{fs-cmFfSwcb.js → fs-BUK-3Ws8.js} +2 -2
- package/dist/ui/assets/{fs-B7XQ_lrb.js → fs-CKSBDyCr.js} +1 -1
- package/dist/ui/assets/{gelatiere-unit-BQsQGJpu.js → gelatiere-unit-hpxCLHdA.js} +1 -1
- package/dist/ui/assets/{github-a773Oj_3.js → github-D9GRCOqL.js} +1 -1
- package/dist/ui/assets/{github-Di3NkZKj.js → github-DeZ2nDzS.js} +2 -2
- package/dist/ui/assets/{github-auth-ByvUzIEk.js → github-auth-CSG4xZUZ.js} +1 -1
- package/dist/ui/assets/{github-copilot-BoeL-U7E.js → github-copilot-C8hgcCJI.js} +1 -1
- package/dist/ui/assets/{github-copilot-DhPt4wWn.js → github-copilot-C_JPU6a6.js} +1 -1
- package/dist/ui/assets/{github-install-BNLZv80o.js → github-install-HX3c8n0G.js} +1 -1
- package/dist/ui/assets/{github-zip-CoNuW2sf.js → github-zip-CUIsX5nN.js} +1 -1
- package/dist/ui/assets/{go-driver-2ebSfg2I.js → go-driver-CR9PpQn8.js} +1 -1
- package/dist/ui/assets/{guest-tool-gate-B3vJ2BGb.js → guest-tool-gate-CXdRgkkb.js} +1 -1
- package/dist/ui/assets/{hear-Cfl4YI74.js → hear-DRUm5iko.js} +1 -1
- package/dist/ui/assets/{help-BMAczBRn.js → help-aKSKYJF6.js} +1 -1
- package/dist/ui/assets/host-command-CwRNpVLr.js +28 -0
- package/dist/ui/assets/image-processor-BlI3KRoz.js +1 -0
- package/dist/ui/assets/{installer-xdxoxN0e.js → installer-CbjJjnwg.js} +1 -1
- package/dist/ui/assets/{interrupted-work-recovery-6m6BONfO.js → interrupted-work-recovery-DSX617ic.js} +1 -1
- package/dist/ui/assets/{ipk-mamba-uom-JjRn.js → ipk-mamba-BRxsK-p_.js} +1 -1
- package/dist/ui/assets/{js-realm-worker-CD271tMz.js → js-realm-worker-C2c5HlJC.js} +3 -3
- package/dist/ui/assets/{jsh-executor-DBwez91k.js → jsh-executor-of_S2nM9.js} +2 -2
- package/dist/ui/assets/jsh-runtime-extensions-vA6JAYXY.js +1 -0
- package/dist/ui/assets/{kernel-worker-DOWZJuXM.js → kernel-worker-Dv0441oU.js} +59 -59
- package/dist/ui/assets/{lick-ws-bridge-4IBz0Msz.js → lick-ws-bridge-Kx2ffoDz.js} +1 -1
- package/dist/ui/assets/{lick-ws-bridge-DQyoaYVX.js → lick-ws-bridge-qlQXS6DR.js} +1 -1
- package/dist/ui/assets/{live-session-curation-ix1TPxM_.js → live-session-curation-DvwwvftT.js} +1 -1
- package/dist/ui/assets/{live-session-snapshot-DnyhcCE6.js → live-session-snapshot-Bk5UWNkV.js} +1 -1
- package/dist/ui/assets/live-vfs-fs-DgvdNXkS.js +1 -0
- package/dist/ui/assets/{local-llm-D5Ox2xst.js → local-llm-BcjMnaVa.js} +1 -1
- package/dist/ui/assets/{local-llm-Q3t4kvLW.js → local-llm-Ce-14HNh.js} +1 -1
- package/dist/ui/assets/main-DE492KKE.js +22 -0
- package/dist/ui/assets/{main-cherry-e40IJV67.js → main-cherry-EDccG98N.js} +1 -1
- package/dist/ui/assets/{mcp-command-Bz_9ImDN.js → mcp-command-h2MzRFNc.js} +13 -13
- package/dist/ui/assets/{memory-curation-seam-80E0snGz.js → memory-curation-seam-CgwkDbcz.js} +1 -1
- package/dist/ui/assets/{memory-health-X7Z2HJgc.js → memory-health-qcXv-xah.js} +1 -1
- package/dist/ui/assets/{memory-write-execute-CYpqPN9a.js → memory-write-execute-CSIbnXAd.js} +1 -1
- package/dist/ui/assets/{merge-folded-cost-into-frozen-DDVN7W9t.js → merge-folded-cost-into-frozen-a8XFtHLd.js} +1 -1
- package/dist/ui/assets/{mount-CxIbhZc_.js → mount-BdStwj8s.js} +2 -3
- package/dist/ui/assets/{mount-Cdhbsamk.js → mount-DROut-7D.js} +1 -1
- package/dist/ui/assets/{mount-bridge-client-DEndUe7m.js → mount-bridge-client-DEvjkZ1N.js} +1 -1
- package/dist/ui/assets/{mount-bridge-client-DZrU_hNA.js → mount-bridge-client-DTSknauQ.js} +1 -1
- package/dist/ui/assets/new-session-DSaHd_sm.js +2 -0
- package/dist/ui/assets/oauth-bootstrap-CxyjlKpR.js +2 -0
- package/dist/ui/assets/oauth-service-GpUOM3Aw.js +1 -0
- package/dist/ui/assets/oauth-service-MWzqRq2q.js +1 -0
- package/dist/ui/assets/{onboarding-orchestrator-BLrUNStK.js → onboarding-orchestrator-BOFuJPrP.js} +1 -1
- package/dist/ui/assets/{openai-codex-CePEMrS9.js → openai-codex-CS23S3lJ.js} +1 -1
- package/dist/ui/assets/{openai-codex-DEnFvLaq.js → openai-codex-DIPqOcNT.js} +1 -1
- package/dist/ui/assets/{openrouter-CMbDityB.js → openrouter-BdryGS-Z.js} +1 -1
- package/dist/ui/assets/{openrouter-C6Drz4Po.js → openrouter-BwY0foMm.js} +1 -1
- package/dist/ui/assets/{openrouter-free-jZRQi4fS.js → openrouter-free-Bmq0Tdc_.js} +1 -1
- package/dist/ui/assets/{openrouter-free-DPrVNMiX.js → openrouter-free-vIKTI0NQ.js} +1 -1
- package/dist/ui/assets/{openrouter-oauth-BSKVr_20.js → openrouter-oauth-BoMzKA4Q.js} +1 -1
- package/dist/ui/assets/{openrouter-oauth-DXfymZ6D.js → openrouter-oauth-PagZ0gy-.js} +1 -1
- package/dist/ui/assets/{opfs-mount-WSgDUNOX.js → opfs-mount-B745o1Vc.js} +1 -1
- package/dist/ui/assets/{page-approval-service-BbEv1dSc.js → page-approval-service-ja6kjLj8.js} +1 -1
- package/dist/ui/assets/panel-rpc-CR9k3qWE.js +1 -0
- package/dist/ui/assets/panel-rpc-accessor-B4BfPLSo.js +1 -0
- package/dist/ui/assets/panel-rpc-handlers-DSgDRrll.js +2 -0
- package/dist/ui/assets/panel-rpc-sLZo8PD-.js +1 -0
- package/dist/ui/assets/{panelize-shell-C3g06QW7.js → panelize-shell-C3-v83mm.js} +1 -1
- package/dist/ui/assets/{pi-edit-execution-DckrFCfi.js → pi-edit-execution-V3MrIdPo.js} +1 -1
- package/dist/ui/assets/port-bridge-client-B-gpiOVR.js +1 -0
- package/dist/ui/assets/port-bridge-client-DAxhsvxm.js +1 -0
- package/dist/ui/assets/process-worker-CXxOMS23.js +3 -0
- package/dist/ui/assets/{provider-BIKN9l0j.js → provider-CfiSsvHh.js} +2 -2
- package/dist/ui/assets/{provider-BDvld8wH.js → provider-DQ129t3D.js} +1 -1
- package/dist/ui/assets/{provider-settings-7gXmbpeE.js → provider-settings-nWfCs5Ea.js} +1 -1
- package/dist/ui/assets/provider-store-access-CJWXzYBJ.js +1 -0
- package/dist/ui/assets/provider-store-access-CR58tiUx.js +1 -0
- package/dist/ui/assets/{providers-BSPfSjHX.js → providers-CNz3-2Qt.js} +1 -1
- package/dist/ui/assets/providers-DGOyFpbk.js +2 -0
- package/dist/ui/assets/{proxied-fetch-Cplb-Tee.js → proxied-fetch-4VBgrEIu.js} +2 -2
- package/dist/ui/assets/{proxied-fetch-CoZ8jHud.js → proxied-fetch-F-dCBEfh.js} +1 -1
- package/dist/ui/assets/proxied-fetch-raw-DQ0-xn2O.js +2 -0
- package/dist/ui/assets/{proxied-fetch-raw-Cb_C44Cy.js → proxied-fetch-raw-DfWAMMUJ.js} +1 -1
- package/dist/ui/assets/{py-live-vfs-BY0JeFky.js → py-live-vfs-CPGqrKx-.js} +1 -1
- package/dist/ui/assets/{py-live-vfs-JNkDkEB1.js → py-live-vfs-CUwZTYN6.js} +1 -1
- package/dist/ui/assets/{py-realm-worker-DpNkD8fW.js → py-realm-worker-BoJbWJja.js} +1 -1
- package/dist/ui/assets/{quick-llm-B8_chMUu.js → quick-llm-gqL6GOn2.js} +1 -1
- package/dist/ui/assets/{realm-inprocess-DGI1SPvf.js → realm-inprocess-COtsY7eU.js} +3 -3
- package/dist/ui/assets/{realm-unhandled-rejections-CeQ49yI4.js → realm-unhandled-rejections-CrLvjtWH.js} +1 -1
- package/dist/ui/assets/{realm-unhandled-rejections-UooDX3DO.js → realm-unhandled-rejections-DrxZsN27.js} +1 -1
- package/dist/ui/assets/{recovery-screen-DkW3-R4h.js → recovery-screen-NUMzwXs1.js} +1 -1
- package/dist/ui/assets/{remote-terminal-view-D5iSX82V.js → remote-terminal-view-CMH4RPeK.js} +2 -2
- package/dist/ui/assets/{require-guards-BX-XDJnh.js → require-guards-DnafTLJr.js} +1 -1
- package/dist/ui/assets/{rest-ops-d6LSiWDZ.js → rest-ops-B7gv04VP.js} +1 -1
- package/dist/ui/assets/{rest-ops-DyAkn44S.js → rest-ops-j0P6ql7f.js} +1 -1
- package/dist/ui/assets/{restore-Cz3KzZZ7.js → restore-BW04JrCn.js} +1 -1
- package/dist/ui/assets/{run-CB6rAQZ1.js → run-BAmXlRlW.js} +1 -1
- package/dist/ui/assets/{run-cvQKad0O.js → run-BRFnmkzR.js} +1 -1
- package/dist/ui/assets/{run-D6sdPJoQ.js → run-BYyvGPll.js} +4 -4
- package/dist/ui/assets/{run-COcBu8_4.js → run-C-sCRUCs.js} +1 -1
- package/dist/ui/assets/{run-DKc_-F3f.js → run-CCpJxTqO.js} +1 -1
- package/dist/ui/assets/{run-BvTkhul6.js → run-D6LxdCnL.js} +1 -1
- package/dist/ui/assets/{run-DyYNRU6R.js → run-DPyr8Wk2.js} +1 -1
- package/dist/ui/assets/run-LPGSSK42.js +18 -0
- package/dist/ui/assets/{run-Cl3auc8D.js → run-X1F_4y7X.js} +2 -2
- package/dist/ui/assets/{run-B6qzuQBC.js → run-chEfqfQu.js} +1 -1
- package/dist/ui/assets/{run-ijndQJol.js → run-n9LfcCvg.js} +3 -3
- package/dist/ui/assets/{screen-DVI9ujIL.js → screen-_l91vr17.js} +1 -1
- package/dist/ui/assets/{screencapture-run-DRiSGUJ9.js → screencapture-run-DXkhPPQJ.js} +1 -1
- package/dist/ui/assets/{script-catalog-CqkljCRS.js → script-catalog-WaCMvXY3.js} +1 -1
- package/dist/ui/assets/{secret-env-DQjPh_hw.js → secret-env-z9SReONx.js} +1 -1
- package/dist/ui/assets/secret-topology-hMRoGGjt.js +1 -0
- package/dist/ui/assets/{secrets-bridge-client-CWv2_nw7.js → secrets-bridge-client-D734Xx8G.js} +1 -1
- package/dist/ui/assets/{secrets-bridge-client-EgBSROu5.js → secrets-bridge-client-GOCzDscb.js} +1 -1
- package/dist/ui/assets/{session-command-memory-Dqd2Y1nf.js → session-command-memory-B-i2MtND.js} +2 -2
- package/dist/ui/assets/{session-jsonl-D0vuq6c1.js → session-jsonl-CJdXG7pm.js} +1 -1
- package/dist/ui/assets/{session-jsonl-BFDqAk2L.js → session-jsonl-Cs_xRfDy.js} +1 -1
- package/dist/ui/assets/{session-search-index-CJRorVYP.js → session-search-index-BYv4B9UC.js} +1 -1
- package/dist/ui/assets/{setup-feature-flags-remote-CWxbzwGB.js → setup-feature-flags-remote-DsuSGakO.js} +1 -1
- package/dist/ui/assets/{setup-model-catalog-CPpt1RYm.js → setup-model-catalog-BaFKNYjt.js} +1 -1
- package/dist/ui/assets/signed-fetch-DeDG40wV.js +1 -0
- package/dist/ui/assets/{silent-renew-backoff-D19EWo5j.js → silent-renew-backoff-OCJFe0Op.js} +1 -1
- package/dist/ui/assets/slicc-version-DvppAoNW.js +1 -0
- package/dist/ui/assets/snapshot-D6YGbggk.js +5 -0
- package/dist/ui/assets/{snapshot-features-HNBCRjfP.js → snapshot-features-Dw5v6SoZ.js} +1 -1
- package/dist/ui/assets/{soundscape-mtqG6Pmf.js → soundscape-SKGGt8Ci.js} +1 -1
- package/dist/ui/assets/{speak-BOCxjk3p.js → speak-BX-VG7dD.js} +1 -1
- package/dist/ui/assets/sprinkle-manager-9aHjoMGN.js +1 -0
- package/dist/ui/assets/{sprinkle-renderer-DKK-prCv.js → sprinkle-renderer-B3wcPwka.js} +1 -1
- package/dist/ui/assets/{ssh-_x-LG4bh.js → ssh-BWPgnSgg.js} +1 -1
- package/dist/ui/assets/state-Tykh4Vum.js +42 -0
- package/dist/ui/assets/{store-DL87lgMq.js → store-Mw1jky9b.js} +1 -1
- package/dist/ui/assets/{store-CVYChuZI.js → store-wiEGJ_43.js} +1 -1
- package/dist/ui/assets/stored-accounts-ChNHYF68.js +1 -0
- package/dist/ui/assets/stored-accounts-Cx83FZwe.js +1 -0
- package/dist/ui/assets/structured-output-tool-BrnZ-LJ8.js +1 -0
- package/dist/ui/assets/{sudo-C14r7p-e.js → sudo-BQPW9CSS.js} +3 -3
- package/dist/ui/assets/{sudo-fs-mI-V4QkM.js → sudo-fs-D88yRk1b.js} +1 -1
- package/dist/ui/assets/sudo-refusal-DVwTXFRE.js +1 -0
- package/dist/ui/assets/{supervisor-CRki_wn9.js → supervisor-DkdAvZH9.js} +1 -1
- package/dist/ui/assets/{sync-dialog-BMLUDjd4.js → sync-dialog-Bybysfag.js} +1 -1
- package/dist/ui/assets/{transformers-env-C0z5rcqN.js → transformers-env-BCKpGSnX.js} +1 -1
- package/dist/ui/assets/{tray-leader-BdvK7KWc.js → tray-leader-B4FO4RQ2.js} +1 -1
- package/dist/ui/assets/{tray-leave-runtime-Chumo3x-.js → tray-leave-runtime-DMl8c2Gz.js} +1 -1
- package/dist/ui/assets/{tray-runtime-config-ConrTcOf.js → tray-runtime-config-CBx5P3dS.js} +1 -1
- package/dist/ui/assets/{tray-sidecar-gXArrwO5.js → tray-sidecar-OcV5qb0h.js} +1 -1
- package/dist/ui/assets/{turn-journal-Fz2l3QO4.js → turn-journal-EgGBqAjY.js} +1 -1
- package/dist/ui/assets/{upgrade-detection-Bl00km0Z.js → upgrade-detection-DU_DX3QI.js} +1 -1
- package/dist/ui/assets/{upskill-lick-skip-DTxpkXaG.js → upskill-lick-skip-u8HuNUy0.js} +1 -1
- package/dist/ui/assets/{voice-reply-LXLV67Nm.js → voice-reply-B_6bmqsD.js} +1 -1
- package/dist/ui/assets/{wasi-runtime-Bc01Bdaa.js → wasi-runtime-DDblHDjy.js} +1 -1
- package/dist/ui/assets/{wasm-programs-DPZtEzCA.js → wasm-programs-Bd5YaoqY.js} +1 -1
- package/dist/ui/assets/wc-attach-CBOfJjYR.js +13 -0
- package/dist/ui/assets/{wc-browser-C3BrDOs9.js → wc-browser-CSr9r__R.js} +1 -1
- package/dist/ui/assets/{wc-computers-5ZseiRnv.js → wc-computers-BEXthrMe.js} +1 -1
- package/dist/ui/assets/{wc-detached-DK9sSKZr.js → wc-detached-Cbm7H-x5.js} +1 -1
- package/dist/ui/assets/wc-extension-DspZRCam.js +2 -0
- package/dist/ui/assets/wc-follower-BNZ4sR7A.js +17 -0
- package/dist/ui/assets/{wc-follower-oauth-g_NJ62P_.js → wc-follower-oauth-V1bzfjx5.js} +1 -1
- package/dist/ui/assets/{wc-gelatiere-C_kV3iUh.js → wc-gelatiere-CNb9fe-2.js} +1 -1
- package/dist/ui/assets/{wc-live-CN_PjeIo.js → wc-live-CKe14UhT.js} +6 -6
- package/dist/ui/assets/wc-nav-BLx_lYcl.js +2 -0
- package/dist/ui/assets/{wc-onboarding-BJrwUBcv.js → wc-onboarding-C2RS0W29.js} +2 -2
- package/dist/ui/assets/{wc-permissions-D-mQCivR.js → wc-permissions-CPcpTMv_.js} +2 -2
- package/dist/ui/assets/wc-placeholder-OUaJ_3B8.js +4 -0
- package/dist/ui/assets/{wc-secret-request-BJXcNpDs.js → wc-secret-request-VG_Tn3mW.js} +1 -1
- package/dist/ui/assets/{wc-settings-DOYvmcRg.js → wc-settings-C5v1HZXM.js} +3 -3
- package/dist/ui/assets/{wc-shell-B6woD-e6.js → wc-shell-BcFO-uxW.js} +5 -5
- package/dist/ui/assets/{wc-shortcut-config-BUM7oKUu.js → wc-shortcut-config-DZGtX3og.js} +1 -1
- package/dist/ui/assets/wc-sprinkles-CVoXJ20N.js +2 -0
- package/dist/ui/assets/{wc-transcript-export-RedJl591.js → wc-transcript-export-YQXk7qbS.js} +2 -2
- package/dist/ui/assets/{wc-tray-BxsYHBdR.js → wc-tray-BWgQxTQY.js} +4 -4
- package/dist/ui/assets/welcome-detection-DtBPdXpG.js +1 -0
- package/dist/ui/assets/whisper-session-O3Gzp4bw.js +2 -0
- package/dist/ui/assets/{xai-grok-CAnhMyf-.js → xai-grok-DRR_8B5L.js} +1 -1
- package/dist/ui/assets/{xai-grok-Ch54hmZJ.js → xai-grok-DUHWrBsy.js} +1 -1
- package/dist/ui/index.html +11 -10
- package/dist/ui/packages/webapp/index.html +11 -10
- package/package.json +1 -1
- package/dist/ui/assets/SKILL-B4YYagrM.js +0 -1
- package/dist/ui/assets/account-store-CfWRzPpT.js +0 -2
- package/dist/ui/assets/account-store-bUzcsJR2.js +0 -1
- package/dist/ui/assets/adobe-CugR6QpI.js +0 -2
- package/dist/ui/assets/adobe-ytXYifQq.js +0 -1
- package/dist/ui/assets/approval-timeout-CeQbGMnv.js +0 -1
- package/dist/ui/assets/core-ButDwsf2.js +0 -36
- package/dist/ui/assets/emscripten-vfs-hook-c6XYWLDN.js +0 -1
- package/dist/ui/assets/host-command-Dn-Z4AbC.js +0 -28
- package/dist/ui/assets/jsh-runtime-extensions-DiQ9SvKe.js +0 -1
- package/dist/ui/assets/live-vfs-fs-Y4sN9OvN.js +0 -1
- package/dist/ui/assets/main-D9hbfd93.js +0 -22
- package/dist/ui/assets/new-session-CKsA3Osa.js +0 -2
- package/dist/ui/assets/oauth-bootstrap-B7RkQZg-.js +0 -2
- package/dist/ui/assets/oauth-service-B-vKfxAF.js +0 -1
- package/dist/ui/assets/oauth-service-Bx_Dy3GC.js +0 -1
- package/dist/ui/assets/panel-rpc-D3EPRnmw.js +0 -1
- package/dist/ui/assets/panel-rpc-DW7W4w6_.js +0 -1
- package/dist/ui/assets/panel-rpc-handlers-D8o2EggL.js +0 -2
- package/dist/ui/assets/port-bridge-client-BmVU5J9w.js +0 -1
- package/dist/ui/assets/port-bridge-client-D_erEovW.js +0 -2
- package/dist/ui/assets/process-worker-BKgTk6Wd.js +0 -3
- package/dist/ui/assets/provider-store-access-B3yjrPLi.js +0 -1
- package/dist/ui/assets/provider-store-access-Bq7yMlLd.js +0 -1
- package/dist/ui/assets/providers-Qqp-ZEtv.js +0 -2
- package/dist/ui/assets/proxied-fetch-raw-Di1Dm8fV.js +0 -2
- package/dist/ui/assets/run-Cu1hr00X.js +0 -18
- package/dist/ui/assets/secret-topology-Dm_PZRZx.js +0 -1
- package/dist/ui/assets/signed-fetch-AA2u7LJq.js +0 -1
- package/dist/ui/assets/slicc-version-BjIQb9Hz.js +0 -1
- package/dist/ui/assets/snapshot-DLO8RkOr.js +0 -5
- package/dist/ui/assets/sprinkle-manager-UKlMkzSm.js +0 -1
- package/dist/ui/assets/state-B892uW3H.js +0 -42
- package/dist/ui/assets/structured-output-tool-BDaIhclx.js +0 -1
- package/dist/ui/assets/wc-attach-ChUPT4oB.js +0 -13
- package/dist/ui/assets/wc-extension-BC5R5cd7.js +0 -2
- package/dist/ui/assets/wc-follower-Dn9JVmb_.js +0 -17
- package/dist/ui/assets/wc-nav-DqpOaNr_.js +0 -2
- package/dist/ui/assets/wc-placeholder-D2NGiBVr.js +0 -4
- package/dist/ui/assets/wc-sprinkles-Q2JU6sSY.js +0 -2
- package/dist/ui/assets/welcome-detection-CrnFBTZe.js +0 -1
- package/dist/ui/assets/whisper-session-BaYhywEf.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
var e="---\nname: skill-authoring\ndescription: |\n Use this when the user wants to write a new skill, edit an existing one, or\n understand SLICC's skill system. Covers SKILL.md frontmatter (name,\n description, allowed-tools), how to write a description that triggers\n reliably, native `/workspace/skills/` vs compatibility `.agents/` /\n `.claude/skills/` discovery, and when to ship companion files like `.jsh`\n scripts or `.bsh` browser hooks.\nallowed-tools: bash, read_file, write_file, edit\n---\n\n# Skill authoring\n\nA skill is a folder with a `SKILL.md` (and optional companion files) that loads into the agent's system prompt when the description matches the user's intent. This skill is about authoring those folders well.\n\n## Discovery\n\nSLICC discovers five kinds of skill roots:\n\n| Root | Source | Mutability |\n| ------------------------------------------------------------ | -------------------------------------------- | ----------------------------------- |\n| `/workspace/skills/<name>/SKILL.md` | Bundled or installed via `upskill` | Install-managed; you can edit them |\n| `.agents/skills/<name>/SKILL.md` (anywhere) | Compatibility (Cursor / SuperClaude) | Read-only (discovered, not managed) |\n| `.claude/skills/<name>/SKILL.md` (anywhere) | Compatibility (Claude Code) | Read-only (discovered, not managed) |\n| `<mount>/.claude-plugin/marketplace.json` → plugin `skills/` | Claude Code marketplace (mounted repos) | Read-only (discovered, not managed) |\n| `<plugin-root>/skills/<name>/SKILL.md` | Agent Plugins installed via `plugin install` | Read-only (discovered, not managed) |\n\nSkills under `/workspace/skills/` installed with `upskill` carry a `.upskill` provenance record (source, ref, commit, file list) that `upskill list --outdated` consults and `upskill update [--dry-run]` uses to refresh them. `upskill` never modifies or deletes a **dotfile** in a skill directory, so that is where a skill should keep its credentials and local state (`scripts/.config`) — everything else is replaced on update.\n\nThe marketplace root is auto-discovered: when a mounted directory contains `.claude-plugin/marketplace.json`, SLICC reads the manifest, resolves each plugin's `source` path, and discovers skills at `<plugin-source>/skills/<name>/SKILL.md`. No install step needed — mount the repo and the skills are live immediately. Agent Plugins (agent-plugins.org packages with a `plugin.json` manifest) require an explicit `plugin install <path|repo>` — `<repo>` may be a local directory or a GitHub reference (`owner/repo`, `owner/repo@branch`, or a `https://github.com/owner/repo[/tree/branch[/dir]]` URL, downloaded into `/workspace/.plugins/sources/`); their skills then surface automatically. Precedence: native > agents > claude > marketplace > plugin.\n\nWhen you create a new skill **for SLICC**, put it in `/workspace/skills/<name>/`. The `.agents/`, `.claude/`, and marketplace paths exist so SLICC can pick up skills authored for other agents without modification — don't create new skills there.\n\n## SKILL.md structure\n\n```markdown\n---\nname: <slug>\ndescription: |\n Use this when ...\n ... (1–3 sentences explaining trigger conditions, what's covered, and what's\n NOT covered if there's a sibling skill that handles related topics.)\nallowed-tools: bash, read_file, write_file, edit\n---\n\n# Title (matches `name`)\n\n... body ...\n```\n\n### Frontmatter fields\n\n- **`name`** — lowercase, kebab-case. Must match the folder name. This is what `skill list` shows.\n- **`description`** — the trigger string. The agent uses this to decide whether to load the skill. Get this right; everything else is secondary.\n- **`allowed-tools`** — comma-separated list of tools the skill needs. Without this, the agent may load the skill but find it can't execute the steps. Common values:\n - `bash` — almost every skill.\n - `read_file, write_file, edit` — for skills that author files (sprinkles, config edits, three-way merges).\n - Omit only for purely informational skills.\n\n### Writing a good description\n\nThe description is a trigger, not a summary. It runs through the agent at every turn — too vague and the skill loads when irrelevant; too narrow and it doesn't load when needed.\n\n**Pattern that works**: \"Use this when \\<user-facing trigger\\>. Covers \\<topics\\>. \\[For \\<adjacent topic\\> use \\<sibling skill\\>.\\]\"\n\nCompare:\n\n- ❌ `description: Licks, webhooks, cron tasks, viewing pages/images, screencapture, onboarding`\n Keyword soup. The agent has to guess what \"licks\" or \"screencapture\" mean for this user.\n- ✅ `description: Use this when setting up event-driven automation in SLICC — webhooks, cron tasks, or filesystem watchers that route events to scoops. Covers webhook, crontask, and fswatch. Read this BEFORE wiring anything that should fire on a schedule, an HTTP call, or a VFS change.`\n Names the user intent (\"setting up event-driven automation\"), names the commands the agent will reach for, and tells the agent when to load it.\n\nRules of thumb:\n\n- Lead with **\"Use this when...\"** or **\"Use this whenever...\"**.\n- Name the **user-facing trigger** (what the user said), not just the implementation.\n- If there's a closely-named sibling skill (dips vs sprinkles, mount vs other storage), say which is which inside the description so the agent doesn't load both.\n- Multi-line YAML scalars are fine for longer descriptions — use the `|` block style.\n\n## Body conventions\n\n- Lead with one sentence stating what the skill is. No preamble.\n- Use tables for option matrices (commands × flags, tradeoffs, etc.).\n- Code blocks are bash unless otherwise needed.\n- Include a \"Don't\" or \"Common errors\" section near the end if the skill is failure-prone — the agent will read it before acting.\n- If the skill is large (> ~150 lines), split a reference table or example gallery into a companion `<topic>.md` and have the SKILL.md `read_file` it on demand. The `sprinkles/` skill (style-guide.md) and `dips/` skill (patterns.md) follow this pattern.\n\n## Companion files\n\n### `.jsh` — JavaScript shell scripts\n\n`.jsh` files on the shell's `$PATH` search roots are auto-discovered as shell commands. **Full reference: `./jsh-runtime-extensions.md`.**\n\n- **Auto-discovery**: registered as callable commands by filename (without the extension), from the `$PATH` roots — `/workspace/skills`, `/workspace/.mcp/aliases`, `/workspace/bin`, `/shared/bin` by default. A skill can ship its own commands by including a `.jsh` next to `SKILL.md`. Earlier PATH roots win basename collisions, so `/workspace/skills/` beats `/workspace/bin`. Two skills under the same root that ship the same command are not silent: a `.upskill` provenance record wins over a bundled copy, a newer `installed` timestamp wins among provenanced skills, otherwise the first scan hit wins — and `skill list` / `which` name the loser. For commands elsewhere, add their dir to the PATH: `echo 'export PATH=\"$PATH:/my/tools\"' >> ~/.profile`.\n- **Direct execution**: run any script by path with `jsh /tmp/tool.jsh [args…]`. `jsh` is an alias for the Node shim, including `sliccy:` module resolution and argument passthrough; `process.argv[0]` remains `node` for Node compatibility.\n- **Dual-mode**: works in both the CLI server and the Chrome extension (sandbox iframe). Don't rely on CLI-only Node modules.\n- **Top-level `await`**: scripts are wrapped in `AsyncFunction`, so `await` at the top level works. Prefer it — errors surface instead of becoming unhandled rejections. Fire-and-forget `.then()`, unawaited `main()`, `setTimeout`, and `await fetch(…).json()` / `.text()` also keep the realm alive: like Node, the process stays up while I/O (fs/exec/fetch, including reading the response body) or timers are outstanding, and `process.exit()` skips the rest. A Promise with no handle (`new Promise(() => {})`) does **not** keep it alive. `node --check` / `-c` syntax-checks without executing (top-level `await` and ESM `import`/`export` are valid — the same entry transpile `node file.mjs` uses). `node --input-type=module` treats `-e` / stdin / `.js` as ESM.\n\n#### Runtime surface (use these — don't reinvent)\n\nNode-standard bare globals:\n\n| Global | Use for |\n| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `process` | `argv`, `env`, `cwd()`, `exit(code)`, `exitCode` (deferred status; honoured after the event-loop drain), `stdout.write`, `stderr.write`; `stdin` is one-shot buffered (no streaming) — `read()`, events, or async iterator, drain once |\n| `console` | `log`/`info`/`debug`/`dirxml`/`table`/`dir` → stdout; `warn`/`error`/`assert`/`trace` → stderr (`assert` does not throw); `group*` indent; `time*`/`count*` labeled; `clear` no-op |\n| `fetch` | Standard `fetch` routed through SLICC's proxied transport (cookies + CORS handled). |\n| `require(p)` | Synchronous CJS `require`. Use `require('sliccy:<name>')` for capability bridges and `require('fs')` for the VFS bridge (see below). |\n| `__dirname` / `__filename` | CJS scope vars — the script's own directory and absolute path. |\n\nCapability bridges via `require('sliccy:<name>')` (full reference: `./jsh-runtime-extensions.md`):\n\n| `require('sliccy:<name>')` | Use for |\n| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `sliccy:exec` | Callable `exec(cmd)` + `.spawn(argv[])`. Composes with any supplemental command or `.jsh` script. |\n| `sliccy:agent` | Callable `agent(prompt, opts?)` → sub-scoop final text (parsed when `schema` set) + `.spawn(...)` → `{ finalText, exitCode, stderr }`. `opts`: `model`, `thinking`, `cwd`, `allowedCommands`, `readOnly`, `schema`. |\n| `sliccy:skill` | `dir` / `root` / `refs` / `assets` / `config()` / `token(providerId)` — skill-root `references/` and `assets/`, script-dir `.config`, provider tokens. |\n| `sliccy:http` | `http.client({ baseUrl, token, headers, retry, timeoutMs })` — standard API-client builder. |\n| `sliccy:browser` | `findTab`, `ensureTab`, `openWindow`, `windowBounds`, `setWindowBounds`, `eval`, `evalAsync`, `cookie`, `localStorage`, `fetch`, `websocket.on(...)`. |\n| `sliccy:usb` / `sliccy:serial` / `sliccy:hid` | `list()` / `request()` + device methods. Chromium-only. |\n| `sliccy:computer` | `register(handlers)` — jsh-hosted computer backend (screenshot/input over `computer-call`; keep-alive). |\n| `sliccy:cli` | `die(msg, opts?)`, `out(value)`, `warn(msg, opts?)`, `help(text)`. |\n| `sliccy:color` | ANSI helpers (`green`, `red`, `bold`, `dim`, …) auto-disabled on non-TTY / `NO_COLOR`. |\n| `sliccy:time` | `parseDuration`, `ago`, `range`, `future`, `gmailDate`. |\n| `sliccy:fmt` | `trunc`, `col`, `table`, `date`. |\n| `sliccy:pool` | `pool(n, items, fn)` — bounded concurrency runner. |\n\nVFS bridge:\n\n| `require('fs')` / `require('node:fs')` | `readFile`, `writeFile`, `readFileBinary`, `writeFileBinary`, `appendFile`, `readDir`, `exists`, `stat`, `mkdir`, `rm`, `fetchToFile` — all paths are VFS, async. There is no bare `fs` global. |\n| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n\n#### Runtime extensions (live — prefer these over hand-rolled equivalents)\n\nReach these via `require('sliccy:<name>')`. Full reference: `./jsh-runtime-extensions.md`. Use them instead of reimplementing the cross-skill patterns they replace.\n\n- **`process.argv.parseFlags()`** — returns `{ positional, flags, subcommand }`. Replaces the per-skill `--flag=val` / `--flag val` parsing loop.\n- **`require('sliccy:browser')`** — `findTab({ domain | urlMatch })`, `ensureTab(url)`, `openWindow(url, opts?)` (frame-sized window), `windowBounds(tab)`, `setWindowBounds(tab, bounds)` (returns achieved bounds), `eval(tab, fn)`, `evalAsync(tab, fn)`, `cookie(tab, name)`, `localStorage(tab, key)`. Replaces shelling out to `playwright-cli tab-list` and regex-parsing its output.\n- **`browser.fetch(tab, url, opts)`** — page-context fetch (runs inside the tab's origin, so cookies + same-origin headers are automatic). Replaces the `eval-file` temp-file + double-JSON-unwrap dance.\n- **`browser.websocket.on(tab, …).filter({…}).forward({ sink })`** — declarative WebSocket observer with a closed sink set (`webhook` / `scoop` / `vfs` / `log`). **Required** for any new WS-watch use case; do not author page-context `WebSocket.prototype` patches in skill code.\n- **`require('sliccy:http').client({ baseUrl, token, headers, retry })`** — `get`/`post`/`put`/`delete` with merged headers, lazy token resolution, and Retry-After-aware backoff for `retry.on` statuses.\n- **`require('sliccy:skill')`** — `dir` / `root` / `refs` / `assets` / `config()` / `token(providerId)`: replace the per-skill `process.argv[1]` dirname math, ad-hoc `.config` JSON readers, and bespoke `oauth-token` shell-outs. `refs`/`assets` resolve from the skill root (parent of the `scripts/` path segment, including nested helpers).\n- **`require('sliccy:computer')`** — `register(handlers)` for a jsh-hosted computer backend. `register()` keeps a `jshd` unit alive via `computer-call` events. Drive it with the `computer` shell command.\n\nShip a `.jsh` when the skill needs deterministic, parameterizable behavior the agent shouldn't have to re-derive each time (e.g. a `slicc-handoff` helper, a custom diff formatter, a domain-specific lint).\n\n### `.bsh` — browser shell scripts\n\n`.bsh` files auto-execute when the browser navigates to a matching URL:\n\n- **Filename = hostname pattern**: `-.okta.com.bsh` matches `*.okta.com`.\n- **`// @match` directive**: restrict to specific URL patterns in the first 10 lines.\n- Same execution engine as `.jsh`.\n\nUse `.bsh` for site-specific automations — auto-fillers, lick-emitters, or page transforms that should run whenever the user lands on a particular host.\n\n## Filesystem at a glance\n\nThe VFS is stored in IndexedDB; it survives tab closes and refreshes. The `mount` shell command bridges remote storage (local folders, S3-compatible, Adobe DA) into VFS paths — see `/workspace/skills/mount/SKILL.md`.\n\nThe VFS supports symbolic links transparently:\n\n```bash\nln -s /workspace/skills /workspace/skill-link # Create symlink\nreadlink /workspace/skill-link # Read link target\nls -la /workspace/ # Shows symlinks with -> target\n```\n\n`cat`, `read_file`, `write_file` etc. follow symlinks automatically.\n\n**Mount points must be empty.** Mounting over existing files is blocked so built-in skills and scripts stay discoverable. `ln -s /mnt/… /shared/x` works: the link lives on VFS, and everything through it reaches the mount. A link cannot live _on_ a mount, though (`EINVAL`): mount backends have no symlink inode.\n\n## Don't\n\n- Don't ship a skill without a description that starts with \"Use this when...\" — the trigger field IS the skill from the agent's perspective.\n- Don't put `name:` in Title Case. Lowercase kebab-case. Match the folder.\n- Don't dump shell-command catalogs into a SKILL.md just because they're related — `commands` already lists them. Skills are for **patterns and policy**, not reference material.\n- Don't author skills under `.agents/skills/` or `.claude/skills/`. Those roots are for compatibility discovery from other agents.\n";export{e as default};
|
|
1
|
+
var e="---\nname: skill-authoring\ndescription: |\n Use this when the user wants to write a new skill, edit an existing one, or\n understand SLICC's skill system. Covers SKILL.md frontmatter (name,\n description, allowed-tools), how to write a description that triggers\n reliably, native `/workspace/skills/` vs compatibility `.agents/` /\n `.claude/skills/` discovery, and when to ship companion files like `.jsh`\n scripts or `.bsh` browser hooks.\nallowed-tools: bash, read_file, write_file, edit\n---\n\n# Skill authoring\n\nA skill is a folder with a `SKILL.md` (and optional companion files) that loads into the agent's system prompt when the description matches the user's intent. This skill is about authoring those folders well.\n\n## Discovery\n\nSLICC discovers five kinds of skill roots:\n\n| Root | Source | Mutability |\n| ------------------------------------------------------------ | -------------------------------------------- | ----------------------------------- |\n| `/workspace/skills/<name>/SKILL.md` | Bundled or installed via `upskill` | Install-managed; you can edit them |\n| `.agents/skills/<name>/SKILL.md` (anywhere) | Compatibility (Cursor / SuperClaude) | Read-only (discovered, not managed) |\n| `.claude/skills/<name>/SKILL.md` (anywhere) | Compatibility (Claude Code) | Read-only (discovered, not managed) |\n| `<mount>/.claude-plugin/marketplace.json` → plugin `skills/` | Claude Code marketplace (mounted repos) | Read-only (discovered, not managed) |\n| `<plugin-root>/skills/<name>/SKILL.md` | Agent Plugins installed via `plugin install` | Read-only (discovered, not managed) |\n\nSkills under `/workspace/skills/` installed with `upskill` carry a `.upskill` provenance record (source, ref, commit, file list) that `upskill list --outdated` consults and `upskill update [--dry-run]` uses to refresh them. `upskill` never modifies or deletes a **dotfile** in a skill directory, so that is where a skill should keep its credentials and local state (`scripts/.config`) — everything else is replaced on update.\n\nThe marketplace root is auto-discovered: when a mounted directory contains `.claude-plugin/marketplace.json`, SLICC reads the manifest, resolves each plugin's `source` path, and discovers skills at `<plugin-source>/skills/<name>/SKILL.md`. No install step needed — mount the repo and the skills are live immediately. Agent Plugins (agent-plugins.org packages with a `plugin.json` manifest) require an explicit `plugin install <path|repo>` — `<repo>` may be a local directory or a GitHub reference (`owner/repo`, `owner/repo@branch`, or a `https://github.com/owner/repo[/tree/branch[/dir]]` URL, downloaded into `/workspace/.plugins/sources/`); their skills then surface automatically. Precedence: native > agents > claude > marketplace > plugin.\n\nWhen you create a new skill **for SLICC**, put it in `/workspace/skills/<name>/`. The `.agents/`, `.claude/`, and marketplace paths exist so SLICC can pick up skills authored for other agents without modification — don't create new skills there.\n\n## SKILL.md structure\n\n```markdown\n---\nname: <slug>\ndescription: |\n Use this when ...\n ... (1–3 sentences explaining trigger conditions, what's covered, and what's\n NOT covered if there's a sibling skill that handles related topics.)\nallowed-tools: bash, read_file, write_file, edit\n---\n\n# Title (matches `name`)\n\n... body ...\n```\n\n### Frontmatter fields\n\n- **`name`** — lowercase, kebab-case. Must match the folder name. This is what `skill list` shows.\n- **`description`** — the trigger string. The agent uses this to decide whether to load the skill. Get this right; everything else is secondary.\n- **`allowed-tools`** — comma-separated list of tools the skill needs. Without this, the agent may load the skill but find it can't execute the steps. Common values:\n - `bash` — almost every skill.\n - `read_file, write_file, edit` — for skills that author files (sprinkles, config edits, three-way merges).\n - Omit only for purely informational skills.\n\n### Writing a good description\n\nThe description is a trigger, not a summary. It runs through the agent at every turn — too vague and the skill loads when irrelevant; too narrow and it doesn't load when needed.\n\n**Pattern that works**: \"Use this when \\<user-facing trigger\\>. Covers \\<topics\\>. \\[For \\<adjacent topic\\> use \\<sibling skill\\>.\\]\"\n\nCompare:\n\n- ❌ `description: Licks, webhooks, cron tasks, viewing pages/images, screencapture, onboarding`\n Keyword soup. The agent has to guess what \"licks\" or \"screencapture\" mean for this user.\n- ✅ `description: Use this when setting up event-driven automation in SLICC — webhooks, cron tasks, or filesystem watchers that route events to scoops. Covers webhook, crontask, and fswatch. Read this BEFORE wiring anything that should fire on a schedule, an HTTP call, or a VFS change.`\n Names the user intent (\"setting up event-driven automation\"), names the commands the agent will reach for, and tells the agent when to load it.\n\nRules of thumb:\n\n- Lead with **\"Use this when...\"** or **\"Use this whenever...\"**.\n- Name the **user-facing trigger** (what the user said), not just the implementation.\n- If there's a closely-named sibling skill (dips vs sprinkles, mount vs other storage), say which is which inside the description so the agent doesn't load both.\n- Multi-line YAML scalars are fine for longer descriptions — use the `|` block style.\n\n## Body conventions\n\n- Lead with one sentence stating what the skill is. No preamble.\n- Use tables for option matrices (commands × flags, tradeoffs, etc.).\n- Code blocks are bash unless otherwise needed.\n- Include a \"Don't\" or \"Common errors\" section near the end if the skill is failure-prone — the agent will read it before acting.\n- If the skill is large (> ~150 lines), split a reference table or example gallery into a companion `<topic>.md` and have the SKILL.md `read_file` it on demand. The `sprinkles/` skill (style-guide.md) and `dips/` skill (patterns.md) follow this pattern.\n\n## Companion files\n\n### `.jsh` — JavaScript shell scripts\n\n`.jsh` files on the shell's `$PATH` search roots are auto-discovered as shell commands. **Full reference: `./jsh-runtime-extensions.md`.**\n\n- **Auto-discovery**: registered as callable commands by filename (without the extension), from the `$PATH` roots — `/workspace/skills`, `/workspace/.mcp/aliases`, `/workspace/bin`, `/shared/bin` by default. A skill can ship its own commands by including a `.jsh` next to `SKILL.md`. Earlier PATH roots win basename collisions, so `/workspace/skills/` beats `/workspace/bin`. Two skills under the same root that ship the same command are not silent: a `.upskill` provenance record wins over a bundled copy, a newer `installed` timestamp wins among provenanced skills, otherwise the first scan hit wins — and `skill list` / `which` name the loser. For commands elsewhere, add their dir to the PATH: `echo 'export PATH=\"$PATH:/my/tools\"' >> ~/.profile`.\n- **Direct execution**: run any script by path with `jsh /tmp/tool.jsh [args…]`. `jsh` is an alias for the Node shim, including `sliccy:` module resolution and argument passthrough; `process.argv[0]` remains `node` for Node compatibility.\n- **Dual-mode**: works in both the CLI server and the Chrome extension (sandbox iframe). Don't rely on CLI-only Node modules.\n- **Top-level `await`**: scripts are wrapped in `AsyncFunction`, so `await` at the top level works. Prefer it — errors surface instead of becoming unhandled rejections. Fire-and-forget `.then()`, unawaited `main()`, `setTimeout`, and `await fetch(…).json()` / `.text()` also keep the realm alive: like Node, the process stays up while I/O (fs/exec/fetch, including reading the response body) or timers are outstanding, and `process.exit()` skips the rest. A Promise with no handle (`new Promise(() => {})`) does **not** keep it alive. `node --check` / `-c` syntax-checks without executing (top-level `await` and ESM `import`/`export` are valid — the same entry transpile `node file.mjs` uses). `node --input-type=module` treats `-e` / stdin / `.js` as ESM.\n\n#### Runtime surface (use these — don't reinvent)\n\nNode-standard bare globals:\n\n| Global | Use for |\n| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `process` | `argv`, `env`, `cwd()`, `exit(code)`, `exitCode` (deferred status; honoured after the event-loop drain), `stdout.write`, `stderr.write`; `stdin` is one-shot buffered (no streaming) — `read()`, events, or async iterator, drain once |\n| `console` | `log`/`info`/`debug`/`dirxml`/`table`/`dir` → stdout; `warn`/`error`/`assert`/`trace` → stderr (`assert` does not throw); `group*` indent; `time*`/`count*` labeled; `clear` no-op |\n| `fetch` | Standard `fetch` routed through SLICC's proxied transport (cookies + CORS handled). |\n| `require(p)` | Synchronous CJS `require`. Use `require('sliccy:<name>')` for capability bridges and `require('fs')` for the VFS bridge (see below). |\n| `__dirname` / `__filename` | CJS scope vars — the script's own directory and absolute path. |\n\nCapability bridges via `require('sliccy:<name>')` (full reference: `./jsh-runtime-extensions.md`):\n\n| `require('sliccy:<name>')` | Use for |\n| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `sliccy:exec` | Callable `exec(cmd)` + `.spawn(argv[])`. Composes with any supplemental command or `.jsh` script. |\n| `sliccy:agent` | Callable `agent(prompt, opts?)` → sub-scoop final text (parsed when `schema` set) + `.spawn(...)` → `{ finalText, exitCode, stderr }`. `opts`: `model`, `thinking`, `cwd`, `allowedCommands`, `readOnly`, `schema`, `images`, `escalate`. |\n| `sliccy:skill` | `dir` / `root` / `refs` / `assets` / `config()` / `token(providerId)` — skill-root `references/` and `assets/`, script-dir `.config`, provider tokens. |\n| `sliccy:http` | `http.client({ baseUrl, token, headers, retry, timeoutMs })` — standard API-client builder. |\n| `sliccy:browser` | `findTab`, `ensureTab`, `openWindow`, `windowBounds`, `setWindowBounds`, `eval`, `evalAsync`, `cookie`, `localStorage`, `fetch`, `websocket.on(...)`. |\n| `sliccy:usb` / `sliccy:serial` / `sliccy:hid` | `list()` / `request()` + device methods. Chromium-only. |\n| `sliccy:computer` | `register(handlers)` — jsh-hosted computer backend (screenshot/input over `computer-call`; keep-alive). |\n| `sliccy:cli` | `die(msg, opts?)`, `out(value)`, `warn(msg, opts?)`, `help(text)`. |\n| `sliccy:color` | ANSI helpers (`green`, `red`, `bold`, `dim`, …) auto-disabled on non-TTY / `NO_COLOR`. |\n| `sliccy:time` | `parseDuration`, `ago`, `range`, `future`, `gmailDate`. |\n| `sliccy:fmt` | `trunc`, `col`, `table`, `date`. |\n| `sliccy:pool` | `pool(n, items, fn)` — bounded concurrency runner. |\n\nVFS bridge:\n\n| `require('fs')` / `require('node:fs')` | `readFile`, `writeFile`, `readFileBinary`, `writeFileBinary`, `appendFile`, `readDir`, `exists`, `stat`, `mkdir`, `rm`, `fetchToFile` — all paths are VFS, async. There is no bare `fs` global. |\n| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n\n#### Runtime extensions (live — prefer these over hand-rolled equivalents)\n\nReach these via `require('sliccy:<name>')`. Full reference: `./jsh-runtime-extensions.md`. Use them instead of reimplementing the cross-skill patterns they replace.\n\n- **`process.argv.parseFlags()`** — returns `{ positional, flags, subcommand }`. Replaces the per-skill `--flag=val` / `--flag val` parsing loop.\n- **`require('sliccy:browser')`** — `findTab({ domain | urlMatch })`, `ensureTab(url)`, `openWindow(url, opts?)` (frame-sized window), `windowBounds(tab)`, `setWindowBounds(tab, bounds)` (returns achieved bounds), `eval(tab, fn)`, `evalAsync(tab, fn)`, `cookie(tab, name)`, `localStorage(tab, key)`. Replaces shelling out to `playwright-cli tab-list` and regex-parsing its output.\n- **`browser.fetch(tab, url, opts)`** — page-context fetch (runs inside the tab's origin, so cookies + same-origin headers are automatic). Replaces the `eval-file` temp-file + double-JSON-unwrap dance.\n- **`browser.websocket.on(tab, …).filter({…}).forward({ sink })`** — declarative WebSocket observer with a closed sink set (`webhook` / `scoop` / `vfs` / `log`). **Required** for any new WS-watch use case; do not author page-context `WebSocket.prototype` patches in skill code.\n- **`require('sliccy:http').client({ baseUrl, token, headers, retry })`** — `get`/`post`/`put`/`delete` with merged headers, lazy token resolution, and Retry-After-aware backoff for `retry.on` statuses.\n- **`require('sliccy:skill')`** — `dir` / `root` / `refs` / `assets` / `config()` / `token(providerId)`: replace the per-skill `process.argv[1]` dirname math, ad-hoc `.config` JSON readers, and bespoke `oauth-token` shell-outs. `refs`/`assets` resolve from the skill root (parent of the `scripts/` path segment, including nested helpers).\n- **`require('sliccy:computer')`** — `register(handlers)` for a jsh-hosted computer backend. `register()` keeps a `jshd` unit alive via `computer-call` events. Drive it with the `computer` shell command.\n\nShip a `.jsh` when the skill needs deterministic, parameterizable behavior the agent shouldn't have to re-derive each time (e.g. a `slicc-handoff` helper, a custom diff formatter, a domain-specific lint).\n\n### `.bsh` — browser shell scripts\n\n`.bsh` files auto-execute when the browser navigates to a matching URL:\n\n- **Filename = hostname pattern**: `-.okta.com.bsh` matches `*.okta.com`.\n- **`// @match` directive**: restrict to specific URL patterns in the first 10 lines.\n- Same execution engine as `.jsh`.\n\nUse `.bsh` for site-specific automations — auto-fillers, lick-emitters, or page transforms that should run whenever the user lands on a particular host.\n\n## Filesystem at a glance\n\nThe VFS is stored in IndexedDB; it survives tab closes and refreshes. The `mount` shell command bridges remote storage (local folders, S3-compatible, Adobe DA) into VFS paths — see `/workspace/skills/mount/SKILL.md`.\n\nThe VFS supports symbolic links transparently:\n\n```bash\nln -s /workspace/skills /workspace/skill-link # Create symlink\nreadlink /workspace/skill-link # Read link target\nls -la /workspace/ # Shows symlinks with -> target\n```\n\n`cat`, `read_file`, `write_file` etc. follow symlinks automatically.\n\n**Mount points must be empty.** Mounting over existing files is blocked so built-in skills and scripts stay discoverable. `ln -s /mnt/… /shared/x` works: the link lives on VFS, and everything through it reaches the mount. A link cannot live _on_ a mount, though (`EINVAL`): mount backends have no symlink inode.\n\n## Don't\n\n- Don't ship a skill without a description that starts with \"Use this when...\" — the trigger field IS the skill from the agent's perspective.\n- Don't put `name:` in Title Case. Lowercase kebab-case. Match the folder.\n- Don't dump shell-command catalogs into a SKILL.md just because they're related — `commands` already lists them. Skills are for **patterns and policy**, not reference material.\n- Don't author skills under `.agents/skills/` or `.claude/skills/`. Those roots are for compatibility discovery from other agents.\n";export{e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e="---\nname: package-execution\ndescription: |\n Use this when the user asks to run or install a JavaScript/npm package with\n `npx` or `ipx`, or to run a `package.json` script with `npm run`. Covers\n built-in hints, any required `ipk add` bootstrap, the `--force` bypass, and\n how script bodies resolve installed bins.\nallowed-tools: bash\n---\n\n# JavaScript package execution\n\n`ipx` runs package bins from the nearest installed `node_modules`; `npx` is an alias with the same behavior. If no local bin or installed package resolves, it normally installs the requested package and runs its bin.\n\nBefore that network install, mapped package names that duplicate SLICC built-ins redirect to the built-in instead. The command exits non-zero and prints an actionable stderr hint naming the built-in and suggesting an invocation with the original arguments. The hint may also include an exact `ipk add` bootstrap; run that bootstrap first when present, then use the suggested built-in.\n\nPrefer the built-in. To deliberately preserve install-and-run behavior for the npm package, put `--force` before its name:\n\n```bash\nnpx --force <package> [args...]\nipx --force <package> [args...]\n```\n\nAlready-installed packages, locally resolved bins, and unmapped package names keep their normal behavior. Use `commands` to discover available built-ins instead of maintaining a package mapping here.\n\n## Installing and removing packages\n\n`ipk install <pkg>` (also `npm install`, `npm i`, `ipk add`) installs into `<cwd>/node_modules` and records the package in the nearest `package.json` — in the section it already occupies, or in `dependencies` if it is new. `ipk install -D <pkg>` / `npm install --save-dev <pkg>` records new packages in `devDependencies`. A bare name that is already declared is resolved against that existing range, not latest. Versions are picked as pnpm picks them: a range takes the `latest` dist-tag whenever `latest` satisfies it (`*` always takes `latest`), and deprecated versions are passed over unless nothing else fits. Unknown install flags fail instead of being ignored. `ipk install` with no package names installs declared `dependencies`, `devDependencies` and `optionalDependencies` without rewriting `package.json`. `ipk install -g <pkg>` installs into the shared global prefix at `/shared/lib/node_modules`, records direct dependencies in `/shared/lib/package.json`, and publishes PATH-visible `.jsh` delegators under `/shared/bin` for package bins. Every downloaded tarball is checked against the registry's published hash before it is extracted. An `EINTEGRITY` error means that package's bytes did not match and it was not extracted, but packages installed before it may already be on disk and `package.json` was not updated. Check the state with `ipk list`, then retry the install; don't work around it. Installed files keep the package's executable bits (as npm sets them: 0755 for anything the tarball marks executable, 0644 otherwise), and `bin` targets are always executable, so a package's scripts and helpers (e.g. `git submodule` from `@ai-ecoverse/wasm-git`) run without `chmod +x`. A tree installed before this is repaired the next time you install into it. Platform-specific optional dependencies are skipped unless they are built for wasm (`cpu: wasm32`); the `skipping optional dependency … (unsupported platform)` notes are expected, not errors. For a napi-rs package that doesn't list its wasm binding, add `<pkg>-wasm32-wasi` (e.g. `@oxc-parser/binding-wasm32-wasi`) yourself.\n\n```bash\nipk install lodash # local project install\nipk install -D eslint # record in devDependencies\nnpm install --save-dev eslint@8.57.1\nipk install -g typescript # global install (shared prefix + PATH bin)\nnpm uninstall -g typescript # remove from global manifest and reconcile tree\nnpm list -g # list direct global dependencies\nnpm root -g # print /shared/lib/node_modules\n```\n\nGlobal bins installed with `-g` are on the default `$PATH` via `/shared/bin/<name>.jsh` delegators — invoke them by bare name from any cwd (delegators run `ipx --global <bin>` so a same-named local package does not shadow the global install). Local uninstall/list/root work without `-g` against the cwd `package.json`.\n\n## Wasm programs (`wasm`)\n\nA global package that ships wasm-realm programs (a `slicc.commands` manifest in its `package.json`, or an `@ai-ecoverse/wasm-*` package with `bin/<x>` + `bin/<x>.wasm`; `\"abi\": \"wasi\"` marks WASI programs built from Zig, Go or Rust, which have no glue) makes each program a command: `ipk add -g @ai-ecoverse/wasm-<tool>`, then run it by name. `wasm --list` lists them; `which <name>` shows the package. A built-in of the same name (`sed`, `grep`, `cat`, …) still wins, so run the program with `wasm <name> ARGS...`. `wasm -t <name>` runs it interactively on the panel terminal (a TTY: `wasm -t bash` is a real bash prompt, with job control — ^Z, `jobs`, `fg`, `bg`); the agent's own `bash` tool has no terminal to lend. Installing `@ai-ecoverse/wasm-bash` also moves your own `bash` tool onto GNU bash (real pipes, `trap`, `select`, arrays, bash's exact semantics; `cd` and exports carry between calls, shell functions do not). A WASI module you have as a file runs directly too: `wasm ./tool.wasm ARGS` (or `./tool.wasm` in GNU bash); it sees the VFS with relative paths from your working directory, pipes like any program, and WASIX builds (Wasmer's registry: bash, coreutils, python with `subprocess` and `threading`) run with fork, exec and pipes; threaded builds (`wasm32-wasip1-threads`, pthreads) run a worker per thread, at most 64 per process (`SLICC_WASM_THREADS=N` for fewer). A WASI program that crashes says `wasm trap: …` (a Zig or Rust panic is `unreachable`); run it with `SLICC_WASM_BACKTRACE=1` to see the wasm frames under that line, the functions that panicked. A WASI server gets its socket from `wasm --listen PORT ./server.wasm` (the fd is in `$SLICC_LISTEN_FDS`; Go's `net.FileListener(os.NewFile(fd, \"\"))` serves on it), reachable from your other programs at `127.0.0.1:PORT`. Supplemental commands work as before. The terminal panel then opens in GNU bash too (`wasm --login` starts it; `exit` returns to the slicc prompt, and `wasm --login` starts it again). `export SLICC_SHELL=just-bash` switches both back. Wasm programs built with socket support talk over a private loopback network: a server listening on `127.0.0.1:PORT` in one of your wasm programs is reachable from your other wasm programs while it runs (the terminal panel and each scoop have networks of their own), and a program reaches the outside over HTTP through your network's proxy: `http_proxy` / `https_proxy` point at `127.0.0.1:3128` by default (`no_proxy` keeps `localhost` direct), so `curl http://…` works the way the shell's `curl` does, masked secrets included. HTTPS works too: the proxy terminates TLS with a certificate from your network's own CA, which `SSL_CERT_FILE` / `CURL_CA_BUNDLE` / `GIT_SSL_CAINFO` point programs at (`$HOME/.config/slicc/realm-ca-*.pem`; `-k` is never needed). A redirect reaches the program as it would any HTTP client (`curl -L` follows it), except on Sliccstart, whose fetch path follows redirects itself. No other traffic leaves: only `localhost` / `127.0.0.1` resolve. Once a Go toolchain package is installed, `go build` / `go run` build Go programs here (`go` is SLICC's driver; the output is a wasip1 program you run as `./prog`, or any `GOOS`/`GOARCH` whose standard library is installed; the standard library and your module's own packages only: no cgo, `//go:embed` or module downloads yet). Once a native CPython is installed, `python3` in GNU bash is native Python, and `pyodide` stays SLICC's Pyodide under its own name. Installed Python packages are on its path by themselves. Once `@ai-ecoverse/wasm-git` is installed, `git` in GNU bash is native git (in just-bash it stays SLICC's built-in; `wasm git …` reaches native git there). Native git authenticates by itself: its default credential helper, `git-credential-slicc`, hands it your GitHub login (or `$GH_TOKEN` / `$GITHUB_TOKEN`, or a `*_TOKEN` secret scoped to the host) masked, so `git clone` / `git push` over HTTPS to a private repo just work, and it commits as SLICC's git identity. Don't put tokens in remote URLs; your `~/.gitconfig` overrides both (`$HOME/.config/slicc/gitconfig` is the realm's system config, rewritten each run).\n\n## Conda / emscripten-forge (`ipk mamba`)\n\n`ipk mamba install <pkg>[=<version>]` installs emscripten-wasm32 packages from emscripten-forge / conda-forge into `/shared/lib/conda` (not `node_modules`). Executable files (shared objects, scripts) keep their executable bit. Prefer this for **forge C/WASM libraries** (for example `zlib`, `libpng`) that provide headers, `.a`, and SIDE_MODULE `.so` under that prefix.\n\nKeep using `ipk install` / `ipk add -g` for the **npm** packages that power these built-ins — forge names are not drop-in replacements today:\n\n- `convert` → `ipk add -g @imagemagick/magick-wasm@…` (forge `imagemagick` has no runnable `convert.wasm`)\n- `ffmpeg` → `ipk add -g @ffmpeg/core@…` (forge `ffmpeg` is libav `.a` only)\n- `python` → `ipk add pyodide@…` (no forge `pyodide`)\n\n```bash\nipk mamba install zlib # newest indexed build → /shared/lib/conda\nipk mamba install zlib=1.3.1 # exact version\nipk mamba list # conda-meta inventory\nipk mamba uninstall zlib\nipk mamba --help # channels, prefix, and thin-installer limits\n```\n\n## Running package.json scripts\n\n`npm run <script>` (also `ipk run`, `npm run-script`, and the `npm test` / `start` / `stop` / `restart` shortcuts) runs a `scripts` entry from the nearest `package.json`, in that package's directory. `npm run` with no script name lists what is available — read that list instead of guessing a script name.\n\n```bash\nnpm run # list scripts\nnpm run build # run build, with prebuild/postbuild around it\nnpm run build -- --watch # pass extra args to the script body\nnpm run build --silent # no banner, script output only (either side of the name)\nnpm run lint -- --help # --help after -- goes to the script, not to npm\n```\n\n`--silent`/`-s` and `--if-present` are npm's own flags anywhere before `--`; everything after `--` reaches the script untouched. Missing `start` falls back to `node server.js` when the package has one, and missing `restart` to `npm stop --if-present && npm start`.\n\nA bare bin word in a script body (`vitest run`) is rewritten to `ipx vitest run` when that package is installed, because `$PATH` does not cover `node_modules/.bin` shims. This also applies after keywords like `if`/`then`/`do`. A SLICC built-in with the same name wins, and an unknown word is not installed implicitly — install it with `ipk add <pkg>` first.\n";export{e as default};
|
|
1
|
+
var e="---\nname: package-execution\ndescription: |\n Use this when the user asks to run or install a JavaScript/npm package with\n `npx` or `ipx`, or to run a `package.json` script with `npm run`. Covers\n built-in hints, any required `ipk add` bootstrap, the `--force` bypass, and\n how script bodies resolve installed bins.\nallowed-tools: bash\n---\n\n# JavaScript package execution\n\n`ipx` runs package bins from the nearest installed `node_modules`; `npx` is an alias with the same behavior. If no local bin or installed package resolves, it normally installs the requested package and runs its bin.\n\nBefore that network install, mapped package names that duplicate SLICC built-ins redirect to the built-in instead. The command exits non-zero and prints an actionable stderr hint naming the built-in and suggesting an invocation with the original arguments. The hint may also include an exact `ipk add` bootstrap; run that bootstrap first when present, then use the suggested built-in.\n\nPrefer the built-in. To deliberately preserve install-and-run behavior for the npm package, put `--force` before its name:\n\n```bash\nnpx --force <package> [args...]\nipx --force <package> [args...]\n```\n\nAlready-installed packages, locally resolved bins, and unmapped package names keep their normal behavior. Use `commands` to discover available built-ins instead of maintaining a package mapping here.\n\n## Installing and removing packages\n\n`ipk install <pkg>` (also `npm install`, `npm i`, `ipk add`) installs into `<cwd>/node_modules` and records the package in the nearest `package.json` — in the section it already occupies, or in `dependencies` if it is new. `ipk install -D <pkg>` / `npm install --save-dev <pkg>` records new packages in `devDependencies`. A bare name that is already declared is resolved against that existing range, not latest. Versions are picked as pnpm picks them: a range takes the `latest` dist-tag whenever `latest` satisfies it (`*` always takes `latest`), and deprecated versions are passed over unless nothing else fits. Unknown install flags fail instead of being ignored. `ipk install` with no package names installs declared `dependencies`, `devDependencies` and `optionalDependencies` without rewriting `package.json`. `ipk install -g <pkg>` installs into the shared global prefix at `/shared/lib/node_modules`, records direct dependencies in `/shared/lib/package.json`, and publishes PATH-visible `.jsh` delegators under `/shared/bin` for package bins. Every downloaded tarball is checked against the registry's published hash before it is extracted. An `EINTEGRITY` error means that package's bytes did not match and it was not extracted, but packages installed before it may already be on disk and `package.json` was not updated. Check the state with `ipk list`, then retry the install; don't work around it. Installed files keep the package's executable bits (as npm sets them: 0755 for anything the tarball marks executable, 0644 otherwise), and `bin` targets are always executable, so a package's scripts and helpers (e.g. `git submodule` from `@ai-ecoverse/wasm-git`) run without `chmod +x`. A tree installed before this is repaired the next time you install into it. Platform-specific optional dependencies are skipped unless they are built for wasm (`cpu: wasm32`); the `skipping optional dependency … (unsupported platform)` notes are expected, not errors. For a napi-rs package that doesn't list its wasm binding, add `<pkg>-wasm32-wasi` (e.g. `@oxc-parser/binding-wasm32-wasi`) yourself.\n\n```bash\nipk install lodash # local project install\nipk install -D eslint # record in devDependencies\nnpm install --save-dev eslint@8.57.1\nipk install -g typescript # global install (shared prefix + PATH bin)\nnpm uninstall -g typescript # remove from global manifest and reconcile tree\nnpm list -g # list direct global dependencies\nnpm root -g # print /shared/lib/node_modules\n```\n\nGlobal bins installed with `-g` are on the default `$PATH` via `/shared/bin/<name>.jsh` delegators — invoke them by bare name from any cwd (delegators run `ipx --global <bin>` so a same-named local package does not shadow the global install). Local uninstall/list/root work without `-g` against the cwd `package.json`.\n\n## Wasm programs (`wasm`)\n\nA global package that ships wasm-realm programs (a `slicc.commands` manifest in its `package.json`, or an `@ai-ecoverse/wasm-*` package with `bin/<x>` + `bin/<x>.wasm`; `\"abi\": \"wasi\"` marks WASI programs built from Zig, Go or Rust, which have no glue) makes each program a command: `ipk add -g @ai-ecoverse/wasm-<tool>`, then run it by name. `wasm --list` lists them; `which <name>` shows the package. A built-in of the same name (`sed`, `grep`, `cat`, …) still wins, so run the program with `wasm <name> ARGS...`. `wasm -t <name>` runs it interactively on the panel terminal (a TTY: `wasm -t bash` is a real bash prompt, with job control — ^Z, `jobs`, `fg`, `bg`); the agent's own `bash` tool has no terminal to lend. Installing `@ai-ecoverse/wasm-bash` also moves your own `bash` tool onto GNU bash (real pipes, `trap`, `select`, arrays, bash's exact semantics; `cd` and exports carry between calls, shell functions do not). A WASI module you have as a file runs directly too: `wasm ./tool.wasm ARGS` (or `./tool.wasm` in GNU bash); it sees the VFS with relative paths from your working directory, pipes like any program, and WASIX builds (Wasmer's registry: bash, coreutils, python with `subprocess` and `threading`) run with fork, exec and pipes; threaded builds (`wasm32-wasip1-threads`, pthreads) run a worker per thread, at most 64 per process (`SLICC_WASM_THREADS=N` for fewer). A WASI program that crashes says `wasm trap: …` (a Zig or Rust panic is `unreachable`); run it with `SLICC_WASM_BACKTRACE=1` to see the wasm frames under that line, the functions that panicked. A WASI server gets its socket from `wasm --listen PORT ./server.wasm` (the fd is in `$SLICC_LISTEN_FDS`; Go's `net.FileListener(os.NewFile(fd, \"\"))` serves on it), reachable from your other programs at `127.0.0.1:PORT`. Supplemental commands work as before. The terminal panel then opens in GNU bash too (`wasm --login` starts it; `exit` returns to the slicc prompt, and `wasm --login` starts it again). `export SLICC_SHELL=just-bash` switches both back. Wasm programs built with socket support talk over a private loopback network: a server listening on `127.0.0.1:PORT` in one of your wasm programs is reachable from your other wasm programs while it runs (the terminal panel and each scoop have networks of their own), and a program reaches the outside over HTTP through your network's proxy: `http_proxy` / `https_proxy` point at `127.0.0.1:3128` by default (`no_proxy` keeps `localhost` direct), so `curl http://…` works the way the shell's `curl` does, masked secrets included. HTTPS works too: the proxy terminates TLS with a certificate from your network's own CA, which `SSL_CERT_FILE` / `CURL_CA_BUNDLE` / `GIT_SSL_CAINFO` point programs at (`$HOME/.config/slicc/realm-ca-*.pem`; `-k` is never needed). A redirect reaches the program as it would any HTTP client (`curl -L` follows it), except on Sliccstart, whose fetch path follows redirects itself. No other traffic leaves: only `localhost` / `127.0.0.1` resolve. Once a Go toolchain package is installed, `go build` / `go run` build Go programs here (`go` is SLICC's driver; the output is a wasip1 program you run as `./prog`, or any `GOOS`/`GOARCH` whose standard library is installed; the standard library and your module's own packages only: no cgo, `//go:embed` or module downloads yet). Once a native CPython is installed, `python3` in GNU bash is native Python, and `pyodide` stays SLICC's Pyodide under its own name. Installed Python packages are on its path by themselves. Once `@ai-ecoverse/wasm-git` is installed, `git` in GNU bash is native git (in just-bash it stays SLICC's built-in; `wasm git …` reaches native git there). Native git authenticates by itself: its default credential helper, `git-credential-slicc`, hands it your GitHub login (or `$GH_TOKEN` / `$GITHUB_TOKEN`, or a `*_TOKEN` secret scoped to the host) masked, so `git clone` / `git push` over HTTPS to a private repo just work, and it commits as SLICC's git identity. Don't put tokens in remote URLs; your `~/.gitconfig` overrides both (`$HOME/.config/slicc/gitconfig` is the realm's system config, rewritten each run).\n\nAn installed wasm command may declare `\"args\": [\"-S\", \"gem\"]` in its `slicc.commands` manifest entry. SLICC places those fixed arguments before the arguments typed at the shell or passed by a child process. `${package}` in an argument expands to the installed package directory; use it to name a script such as `\"${package}/bin/gem\"`.\n\n## Conda / emscripten-forge (`ipk mamba`)\n\n`ipk mamba install <pkg>[=<version>]` installs emscripten-wasm32 packages from emscripten-forge / conda-forge into `/shared/lib/conda` (not `node_modules`). Executable files (shared objects, scripts) keep their executable bit. Prefer this for **forge C/WASM libraries** (for example `zlib`, `libpng`) that provide headers, `.a`, and SIDE_MODULE `.so` under that prefix.\n\nKeep using `ipk install` / `ipk add -g` for the **npm** packages that power these built-ins — forge names are not drop-in replacements today:\n\n- `convert` → `ipk add -g @imagemagick/magick-wasm@…` (forge `imagemagick` has no runnable `convert.wasm`)\n- `ffmpeg` → `ipk add -g @ffmpeg/core@…` (forge `ffmpeg` is libav `.a` only)\n- `python` → `ipk add pyodide@…` (no forge `pyodide`)\n\n```bash\nipk mamba install zlib # newest indexed build → /shared/lib/conda\nipk mamba install zlib=1.3.1 # exact version\nipk mamba list # conda-meta inventory\nipk mamba uninstall zlib\nipk mamba --help # channels, prefix, and thin-installer limits\n```\n\n## Running package.json scripts\n\n`npm run <script>` (also `ipk run`, `npm run-script`, and the `npm test` / `start` / `stop` / `restart` shortcuts) runs a `scripts` entry from the nearest `package.json`, in that package's directory. `npm run` with no script name lists what is available — read that list instead of guessing a script name.\n\n```bash\nnpm run # list scripts\nnpm run build # run build, with prebuild/postbuild around it\nnpm run build -- --watch # pass extra args to the script body\nnpm run build --silent # no banner, script output only (either side of the name)\nnpm run lint -- --help # --help after -- goes to the script, not to npm\n```\n\n`--silent`/`-s` and `--if-present` are npm's own flags anywhere before `--`; everything after `--` reaches the script untouched. Missing `start` falls back to `node server.js` when the package has one, and missing `restart` to `npm stop --if-present && npm start`.\n\nA bare bin word in a script body (`vitest run`) is rewritten to `ipx vitest run` when that package is installed, because `$PATH` does not cover `node_modules/.bin` shims. This also applies after keywords like `if`/`then`/`do`. A SLICC built-in with the same name wins, and an unknown word is not installed implicitly — install it with `ipk add <pkg>` first.\n";export{e as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e='---\nname: delegation\ndescription: |\n Use this when deciding whether to do work yourself or delegate to a scoop, when\n fanning out parallel scoops, or when picking models for sub-agents. Covers\n scoop lifecycle (when to drop), parallel orchestration (`scoop_mute`,\n `scoop_unmute`, `scoop_wait`), one-shot ephemeral sub-agents via the `agent`\n shell command, and model selection. Read this BEFORE running `scoop_scoop` for\n non-trivial work.\nallowed-tools: bash\n---\n\n# Delegation\n\nScoops do the heavy lifting; the cone orchestrates and synthesizes. This skill is about choosing how to delegate, not about administering scoops.\n\n## When to delegate\n\n**Default to delegation.** Parallel scoops almost always finish faster, and the cone\'s job is synthesis.\n\nDelegate when:\n\n- Multiple independent sources (scraping 3 sites = 3 scoops).\n- Time-consuming work that doesn\'t need direct oversight.\n- Work expressible as a clear, self-contained brief.\n\nDo it yourself when:\n\n- Single quick lookup (one page, one API call).\n- Real-time adaptation needed (navigating broken URLs).\n- Overhead of spawning exceeds benefit.\n\n## Brief for authority, not for execution\n\nThe most common delegation failure is **the cone doing too much pre-work before delegating**. The cone researches the topic, makes the design decisions, picks the approach, and then hands the scoop a pre-cooked plan to type out. This is bad on three axes:\n\n- **Pollutes the scoop\'s context.** The brief is bloated with conclusions the scoop now has to re-derive an opinion on, instead of facts it can act on.\n- **Strips the scoop of autonomy.** A scoop that\'s been told what to think can\'t push back on a bad call or notice a better path mid-task. You get a typist, not a collaborator.\n- **Wastes the cone\'s tokens.** The cone\'s strength is orchestration — picking the right scoops, synthesizing their outputs. Doing the research itself burns the cone\'s context on work that\'s parallelizable.\n\n**Heuristic: if the cone reads files, runs commands, or makes decisions before delegating, that should have been part of the scoop\'s brief.** Hand the scoop the question, the constraints, and the access — let it decide.\n\n| Bad (cone over-prepares) | Good (scoop decides) |\n| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| Cone reads 5 files, picks an approach, tells scoop "implement approach X in file Y." | Scoop is told "the user wants Z; the relevant code is under `/workspace/src/`. Pick an approach and implement it." |\n| Cone scrapes 3 docs, summarizes, then asks scoop to "write a comparison based on this summary." | Scoop is told "compare libraries A, B, C for this use case. Their docs are at <urls>. Decide and write the comparison." |\n| Cone debugs a failure, isolates the bug, then asks scoop to "fix the off-by-one in line 42." | Scoop is told "this command fails with `<output>`. Find and fix the bug." (Even better: a one-shot `agent` for cheap, deterministic bug-fixes.) |\n\nTwo carve-outs where pre-work IS the cone\'s job:\n\n1. **Routing decisions.** Picking which scoop gets which slice of a fan-out is orchestration, not pre-cooking.\n2. **Synthesis after the fact.** Reading scoop outputs to combine them is the cone\'s whole point.\n\nIf a scoop comes back with a wrong call, **drop it and re-spawn with a better brief** — don\'t feed a correction. Corrections compound the autonomy problem.\n\n## Scoop lifecycle\n\nDrop scoops when done — but **NEVER drop a scoop that owns a sprinkle**.\n\nDrop when:\n\n- Task completed and results synthesized.\n- Stuck or misbehaving (drop and re-spawn with a better brief).\n\nNever drop when:\n\n- It owns an open sprinkle (must stay alive for the sprinkle\'s lifetime).\n- Running a recurring/long-running task (feed watcher, webhook handler).\n- Work is still in progress (dropping loses all context).\n\n## Three delegation primitives\n\n| Primitive | Conversation | Sprinkle ownership | Auto-cleanup | When to use |\n| ---------------------------- | ------------------------ | ------------------ | ----------------- | ----------------------------------------------------------- |\n| `scoop_scoop` + `feed_scoop` | Persistent (multi-turn) | Yes | No (`drop_scoop`) | Long-lived work; sprinkle owners; conversational follow-ups |\n| `scoop_wait` / `scoop_mute` | Persistent (multi-turn) | Yes | No | Parallel fan-out where you want one synthesis turn |\n| `agent` (shell command) | One-shot (single prompt) | No | Yes (on exit) | Cheap, predictable, composable; no cone follow-up needed |\n\n### `agent` — one-shot ephemeral sub-agents\n\n`agent` is a shell command that spawns a one-shot sub-scoop, feeds it a prompt, blocks until the agent loop completes, and prints the final message on stdout. Runs from any bash context (terminal, `feed_scoop` prompt, `.jsh` script, dip lick handler, sprinkle button handler).\n\n```\nagent <cwd> <allowed-commands> <prompt> [--model <id>] [--workspace-mode <mode>] [--read-only <paths>] [--background-after <s>] [--image <path>]... [--no-escalate]\n```\n\n- `<cwd>` — sole writable prefix (plus `/shared/`, the scoop\'s scratch folder, and `/tmp/` — the whole shared scratch tree, so a scoop can always reach its `$TMPDIR`). Relative paths resolve against the caller\'s cwd.\n- `<allowed-commands>` — comma-separated allow-list; `*` for unrestricted.\n- `<prompt>` — forwarded verbatim. The spawned scoop has no access to the caller\'s history; pack context into the prompt.\n- `--model` — defaults to the parent scoop\'s model (or the cone\'s, when invoked from the terminal). Accepts an exact id, a shorthand (`haiku`, `sonnet`, `claude-haiku-4-5`), or the `provider:model` form `models` prints (`openrouter:openai/gpt-5.6-terra-pro`). A bare id resolves against the selected provider first, then against any other configured provider that offers it; if several do, the error lists the qualified ids to pick from. The scoop runs on the provider the model resolved from. An id that cannot be resolved is a hard error (exit 1) — it never silently falls back to the parent\'s model. Models from a provider other than the selected one must additionally be allowed in `/etc/models` (see [Model access policy](#model-access-policy)); a blocked model exits 1 and the error quotes the line to add.\n- `--workspace-mode` — isolation policy. Default `shared-readonly` is today\'s sandbox (parent workspace visible, cwd + `/shared/` + scratch writable, mounts readable). `private` is an isolated sandbox: own cwd/scratch only — no parent workspace, no implicit `/shared/`, mounts are **not** auto-visible. `snapshot` and `shared-live` are not implemented and exit 1.\n- `--read-only` — pure-replace list of read-only paths. Default: the **owning cone\'s** workspace (plus `/workspace/skills/`) and the invoking shell\'s cwd. When replacing it, name your own cone\'s workspace — a literal `/workspace/` is the primary cone\'s, not yours. Under `--workspace-mode private` the default visible list is empty.\n- `--background-after <seconds>` — how long the spawned scoop\'s `bash` waits for a command before detaching it and moving on (default 600). Nobody can cancel a spawned scoop\'s turn, so a command that never returns would otherwise burn the whole run on one call; a detached command reports its exit code back to that scoop as a `Background Command` lick. `0` detaches every command immediately.\n- `--image <path>` — attach an image (PNG, JPEG, GIF, WebP) to the prompt; repeatable, at most 8 (`--image=<path>` works too). The scoop sees it directly, so it does not need a command like `open` just to look at a screenshot. A missing file, a non-image, or a ninth image exits 1 before anything is spawned.\n- `--no-escalate` — `<allowed-commands>` and the writable paths become a hard boundary. Without it, an unlisted command or an out-of-bounds write asks **you** (the invoking cone) for approval; with it the request is refused on the spot and the scoop is told it is not permitted for this call. Stored "Always" grants do not widen it either. Use it whenever the scoop should only think about what it was handed — a decider looking at a screenshot should not be able to start driving the browser through your approvals.\n\n**Critical property: no handoff.** Ephemeral scoops do NOT notify the cone on completion. Running `agent` from a non-cone shell does not trigger an unsolicited cone turn. The caller gets the result on stdout, nothing else. This makes `agent` the right choice for cheap, predictable interactions inside dips and sprinkles where you don\'t want the cone or owning scoop woken up.\n\n```bash\n# Parallel, collected to one file. No cone turns spawned.\nfor url in site-a site-b site-c; do\n agent "$TMPDIR" "curl,jq" "Fetch https://$url/api, return the top-level title field." >> "$TMPDIR/titles.txt" &\ndone\nwait\n\n# Focused refactor with a restricted allow-list.\nagent /workspace/src "rg,sed,node" "Rename getCwd to getCurrentWorkingDirectory across *.ts"\n\n# Cheap one-shot from a faster model.\nagent . \'*\' \'Summarize the README in one sentence.\' --model claude-haiku-4-5\n```\n\nFor dip and sprinkle interaction patterns built on `agent`, see `/workspace/skills/dips/SKILL.md` and `/workspace/skills/sprinkles/SKILL.md`.\n\n## Shaping the scoop\'s sandbox: `workspaceMode`, `visiblePaths`, `writablePaths`, `allowedCommands`\n\n`scoop_scoop` accepts a named isolation mode plus three sandbox-shaping parameters. **They are how you give a scoop authority — by widening or narrowing what it can read, write, and run.** A scoop that can\'t reach the files it needs has no autonomy; pre-cooking the brief is what you do to compensate. Get the sandbox right and the brief gets shorter.\n\nA rarely used argument — `canCreateChildren: true` — is an explicit nested-delegation grant. The new scoop may then `scoop_scoop` / `feed_scoop` / `drop_scoop` its own children. Omit it (the default) so the scoop stays a leaf. A scoop that was not itself granted this cannot pass it on.\n\n| Param | What it controls | Default | Pure replace? |\n| ------------------- | --------------------------------------- | -------------------------------------------------------------------------------------- | ------------- |\n| `workspaceMode` | Sharing policy for the parent workspace | `"shared-readonly"` (today\'s scoop). `"private"` isolates. | Yes |\n| `visiblePaths` | Read-only VFS paths the scoop can SEE | shared-readonly: `["/workspace/"]`; private: `[]` | Yes |\n| `writablePaths` | VFS paths the scoop can READ AND WRITE | shared-readonly: `["/scoops/<folder>/", "/shared/"]`; private: `["/scoops/<folder>/"]` | Yes |\n| `allowedCommands` | Shell command allow-list | unrestricted (every built-in + `.jsh`) | Yes |\n| `canCreateChildren` | Nested-delegation grant | `false` (leaf scoop) | Yes |\n\n"Pure replace" means what you set is what you get — the value isn\'t merged with the default. Pass `[]` to drop it entirely. Trailing slashes recommended on path entries (e.g. `/shared/data/`).\n\nSubtleties:\n\n- **`writablePaths` are always readable too.** A true read-nothing sandbox needs both `visiblePaths: []` AND `writablePaths: []`.\n- **Mounts remain readable in `shared-readonly`** (the default) regardless of `visiblePaths`. `private` does **not** auto-include mounts — name a mount in `visiblePaths` / `writablePaths` if the scoop needs it. That\'s how a mount cannot silently expand every child\'s authority.\n- **`allowedCommands` applies recursively** — pipelines, command substitutions, and network commands are all gated. Pass `["*"]` for explicit unrestricted.\n- **List every absolute root the scoop\'s tools write to.** Include any root outside the scoop\'s folder and `/tmp/` in `writablePaths` (any spelling works: `/x`, `/x/`, `/x/**`), or every such write escalates to you for approval. `playwright-cli` needs nothing here: in a scoop its session log, snapshots and screenshot archive go to the scoop\'s own `$TMPDIR/.playwright/`, not `/.playwright/`. Prefer pointing skills at `/scoops/<folder>/`, `/shared/`, or `/tmp/` over inventing new VFS roots.\n\n### How to choose\n\nAsk three questions, in order:\n\n1. **What does the scoop need to read?** Files it must consume — source tree, docs, mounted data — go in `visiblePaths`. Default `/workspace/` is fine for most "do something in the project" briefs. Add specific paths (`/shared/data/`, `/mnt/da/`) for narrower scopes.\n2. **What is it allowed to change?** Output dirs, the file it\'s editing, the sprinkle path it owns. Default writable scratch (`/scoops/<folder>/`) plus `/shared/` is fine for scoops producing artifacts. **Tighten this when the scoop should not modify production code** — e.g. a research scoop with `writablePaths: ["/scoops/<folder>/"]` only.\n3. **What commands does it need?** Default unrestricted is right when the scoop will figure out its own toolchain. Tighten only when narrowing to a known set of tools improves reliability or safety — e.g. a scraper with `["curl","jq"]`, or a refactor scoop with `["rg","sed","node"]`.\n\n### Patterns\n\n```\n# Default sandbox (shared-readonly): full project, own scratch dir, all commands.\n# Right for most "do this in the project" briefs.\nscoop_scoop({ name: "fix-bug", prompt: "..." })\n\n# Isolated sandbox. Cannot see the parent workspace or mounts.\nscoop_scoop({ name: "scratch-only", workspaceMode: "private", prompt: "..." })\n\n# Read-only research scoop. Can read everything, can\'t change anything,\n# can use whatever commands it needs to investigate.\nscoop_scoop({\n name: "auth-research",\n visiblePaths: ["/workspace/", "/shared/"],\n writablePaths: ["/scoops/auth-research/"],\n prompt: "Map the auth flow across the codebase and write findings to /scoops/auth-research/notes.md."\n})\n\n# Sprinkle-owning scoop. Needs write access to its sprinkle path.\nscoop_scoop({\n name: "giro-winners",\n writablePaths: ["/scoops/giro-winners/", "/shared/sprinkles/giro-winners/"],\n prompt: "..."\n})\n\n# Tight scraper. Only sees public docs, only runs network/json tools,\n# writes to its own scratch.\nscoop_scoop({\n name: "scraper",\n visiblePaths: [],\n writablePaths: ["/scoops/scraper/"],\n allowedCommands: ["curl", "jq", "rg"],\n prompt: "Fetch <urls>, extract the price field from each, write a CSV to /scoops/scraper/out.csv."\n})\n\n# Mount-only scoop. Sees just the DA mount, can write back to it.\n# Under shared-readonly, mounts stay readable even with visiblePaths: [].\n# Under private, name the mount in writablePaths (or visiblePaths) or it is hidden.\nscoop_scoop({\n name: "da-editor",\n writablePaths: ["/mnt/da/", "/scoops/da-editor/"],\n prompt: "Edit /mnt/da/index.html to ..."\n})\n```\n\n### Don\'t\n\n- Don\'t widen `writablePaths` "just in case." A scoop with surprise write access can clobber files outside its task — drop and re-spawn with a tighter scope is cheaper than recovering from that.\n- Don\'t narrow `allowedCommands` to "look secure" if you don\'t know which commands the scoop will need. The agent will hit a wall mid-task and either lie ("I\'ll skip that step") or spam tool errors.\n- Don\'t forget the `writablePaths`-also-readable rule. `visiblePaths: []` alone does not produce a blind sandbox.\n\n### `background_after` — bounding a scoop\'s slow commands\n\n`scoop_scoop({ background_after: <seconds> })` sets how long that scoop\'s `bash`\ntool waits for a command before detaching it and continuing the turn (default\n600). This is a resilience knob, not a sandbox one: a scoop\'s turn cannot be\ncancelled by anyone, so a command that never returns would hang the scoop (and,\nfor a blocking `agent` call, its caller) indefinitely. When a detached command\nfinishes, that scoop receives a `Background Command` lick with the exit code, a\npreview, and the path to the full output.\n\n```\n# A scoop whose commands must never stall it for more than a minute.\nscoop_scoop({ name: "flaky-net", background_after: 60, allowedCommands: ["curl", "jq"], prompt: "..." })\n```\n\nThe scoop can also override the budget per call (`bash({ command, background_after, timeout })`). Each run is a real pid: `ps` lists a detached job and `kill <pid>` stops it, so `timeout` is a kill rather than just a detach.\n\n### Filesystem work limits\n\nScoop shell commands that use the upstream limits stop at 100,000 traversal entries,\n256 levels, 32 MiB input, or 64 MiB of tracked live buffers. Split large trees or\ninputs across calls when a command reports a limit. Environment variables cannot\nraise these limits. They are not an OPFS quota and do not cover custom `tar`,\n`unzip`, JavaScript, Python, Git, or browser command implementations. Existing\n`timeout` and `background_after` controls still apply independently.\n\n## Parallel orchestration: `scoop_mute` / `scoop_unmute` / `scoop_wait`\n\nBy default, every non-ephemeral scoop completion fires a `scoop-notify` event that wakes the cone for a fresh turn. Fanning out N scoops in parallel produces N extra cone turns whose only job is to acknowledge "scoop X finished" — expensive in tokens, disruptive to orchestration.\n\nThese three cone-only tools collapse the fan-out into a single follow-up turn:\n\n- **`scoop_mute({ scoop_names })`** — suspends `scoop-notify` for the listed scoops. Completions arriving while muted are stashed (full response persisted to `/shared/scoop-notifications/*.md`); they do NOT trigger a cone turn.\n- **`scoop_unmute({ scoop_names })`** — resumes notifications AND returns every stashed completion inline as the tool\'s result. The cone reads the summaries in the current turn instead of one extra turn per scoop.\n- **`scoop_wait({ scoop_names, timeout_ms? })`** — schedules a NON-BLOCKING wait. Returns immediately so the cone can keep working; when every listed scoop completes (or the timeout fires) the orchestrator delivers a single `scoop-wait` channel lick with all captured summaries. Target scoops are implicitly muted for the wait\'s duration so individual `scoop-notify` events don\'t pre-empt the eventual lick. `timeout_ms: 0` fires on the next tick with whatever is already done. Omit `timeout_ms` to wait indefinitely. Pre-existing `scoop_mute` state survives the wait.\n\n### When to use which\n\n> Every scoop name you pass to `feed_scoop`, `drop_scoop`, `scoop_mute`, `scoop_unmute` or `scoop_wait` is resolved against what `list_scoops` shows you. Another cone\'s identically named scoop is never matched by a bare name; the call errors instead (#2360).\n>\n> If you are the LEADING cone, `list_scoops` also shows scoops you do not own, tagged `[INHERITED]` (their owning cone is gone) or `[FOREIGN: <cone>]` (another cone owns them). You can feed, wait on, mute and drop those — but only by passing `cross_cone: true` in the same call. Omitting it is an error, not a no-op, so you never touch another cone\'s work by accident. Two things to know before you do: a cross-cone `feed_scoop` sends its completion notice to the scoop\'s OWN owner, so use `scoop_wait ({ …, cross_cone: true })` if you need the result yourself; and a batch call refuses the whole batch when any listed scoop needs the flag.\n\n- **Fan-out + synthesis** (your next useful step depends on all scoops) → `scoop_wait`.\n- **Background work you\'ll check later** → `scoop_mute` now, `scoop_unmute` when you want the summaries.\n- **Single delegation, no parallelism** → don\'t mute. Default `scoop-notify` is fine.\n\n### Examples\n\n```\n# Fan-out + synthesize:\nfeed_scoop({ scoop_name: "writer-a", prompt: "Draft intro" })\nfeed_scoop({ scoop_name: "writer-b", prompt: "Draft outro" })\nscoop_wait({ scoop_names: ["writer-a", "writer-b"], timeout_ms: 600000 })\n# Returns immediately. Cone keeps working. When both finish (or 10 min), a single\n# `scoop-wait` lick wakes the cone with both summaries; the next turn synthesizes.\n\n# Background, poll non-blockingly:\nscoop_mute({ scoop_names: ["scraper"] })\nfeed_scoop({ scoop_name: "scraper", prompt: "Collect URLs from the sitemap" })\n# ... do other work ...\nscoop_unmute({ scoop_names: ["scraper"] })\n# Tool result has the stashed summary or "No stashed completions".\n```\n\n### Liveness: a quiet fan-out is not a finished fan-out\n\n"Files look stable and the scoops are still processing" does NOT mean the work\nis done or progressing. A common stall mode: one or more scoops are blocked on\na pending approval (`sudo_request`) that never reached you, and the whole\nfan-out sits idle while you wait for a `scoop-wait` lick that can\'t arrive.\n\nWhen a fan-out goes quiet — no completions, no file changes, no progress\nmessages — run `list_sudo_requests` before concluding anything. Resolve or\ndeny each pending request, then keep waiting. Only treat a fan-out as\ncomplete when every scoop has actually reported completion (via `scoop_wait`\nlick or `scoop_unmute` summaries), not because output files stopped changing.\n\nWhen you **deny** one, pass `reason` to `lick_dismiss`. The scoop sees the\nsubject of its own request and your verdict; without a reason it cannot tell a\nrefusal from a misunderstanding, so it retries the same thing or invents a\nworkaround. Say what would make it acceptable, if anything would.\n\n### Notes\n\n- Full response is always persisted to `/shared/scoop-notifications/<timestamp>-<folder>-<id>.md` (bounded to the 200 most recent). The summary string in the tool result is truncated at 20 000 characters; read the VFS path when you need the full output.\n- Unknown scoop names are reported in the result but do not abort the call.\n- Dropping or re-registering a muted scoop is safe: `unregisterScoop` releases waiters (resolving as `timedOut: true`) and clears mute/pending state.\n\n## Inspecting delegation cost\n\nRun `cost` to inspect spend for the cone and currently live scoops. The table labels each row\'s source, and `--json` returns the same live-only scope for scripts as `{"budget": <window|null>, "scoops": [ ... ]}` — read the rows from `.scoops`. The Model column (JSON `model`) is the model that unit is running now — its provider-qualified pin, the id half of `models`\' "Currently using" line (a provider-less legacy pin yields to the latest turn when they differ) — not whichever model took the most turns. JSON `models` lists each distinct model once: a bare id and a region- or version-qualified id of the same model are one entry (a suffixed variant such as `-fast` is not), and the entry for the model in use now keeps that current spelling. Each JSON row also carries `escalations: { asked, allowed, denied }` — the sudo requests that unit raised (folded `agent` children included); `allowed > 0` means the unit leaned on an approval.\n\nOn a provider billing against a rolling allowance (rather than per token), `cost` leads with that budget: percent USED of the window and when it resets. That number, not the dollar total, is what says whether long runs will finish — the allowance is shared, so it can be most of the way gone before this session has cost a cent.\n\nUse `cost --all` only when you need the historical picture: it adds dropped scoops from the current runtime and frozen sessions recorded in `/sessions/index.json`. Combine it with `--json` for structured historical output. Legacy frozen sessions that predate cost persistence are retained with unknown cost rather than reported as zero.\n\n## Model selection for scoops\n\n**Always run `models` to verify available models before specifying one.** Model availability depends on the configured provider and API key. `model` accepts an exact id, a shorthand (`haiku`, `sonnet`, `claude-haiku-4-5`), or the `provider:model` form `models` prints (`openrouter:openai/gpt-5.6-terra-pro`). A bare id resolves against the selected provider first, then against any other configured provider that offers it; matching several is an error listing the qualified ids. The scoop runs on the provider the model resolved from. An id that cannot be resolved is rejected outright — it never silently falls back to the cone\'s model. Cross-provider models also need an `/etc/models` allow entry (see [Model access policy](#model-access-policy)).\n\nUse `models --json` to compare. Intelligence, speed, and cost are independent dimensions:\n\n- **Cost-sensitive** (renames, formatting, grep-and-replace) → low-cost models.\n- **Complex** (architecture, multi-file refactors, subtle debugging) → high-intelligence.\n- **Latency-sensitive** (interactive workflows, quick lookups) → high-speed.\n- **Default** → omit the parameter; inherits the cone\'s model.\n\n```bash\n# 1. Verify available models.\nmodels\n\n# 2. Create scoops with verified IDs.\nscoop_scoop({ name: "fix-typos", model: "claude-haiku-4-5", prompt: "Fix all typos in /workspace/docs/" })\nscoop_scoop({ name: "architect", model: "claude-opus-4-6", prompt: "Design the new plugin system..." })\n```\n\n**Error handling**: scoops retry up to 3 times with exponential backoff for transient errors (rate limits, server errors). Non-retryable errors (invalid model, auth failures) fail immediately and notify the cone, bypassing any `scoop_mute` settings.\n\n## Browser tabs\n\nBrowser-tab handling rules (track your IDs, never close tabs you didn\'t open, handle "tab not found" gracefully) live in `/workspace/skills/playwright-cli/SKILL.md` under "Multi-Agent Tab Behavior". Read that skill before delegating browser work.\n\n### Browser-driving scoops: one tab per scoop\n\nAll scoops share ONE browser, but `playwright-cli` locks **per tab**: commands\non different tabs run in parallel, and commands on the same tab serialize. One\nscoop\'s slow or hung navigation stalls only its own tab. Fan-out across tabs\ngenuinely multiplies browser throughput.\n\n- **Give every browser-driving scoop its own tab; no fan-out cap is needed\n for correctness.** Browser scoops fan out like any other work, and commands\n on distinct tabs really do run side by side.\n- **Two scoops on the SAME tab still queue.** If a slice needs a shared tab,\n hand it to one scoop rather than splitting it.\n- A hung navigation stalls only its own tab, so one stuck scoop no longer\n detaches every sibling\'s commands past `background_after`.\n- When a command emits `note: browser bridge contended — ...` on stderr (total\n lock wait + queue depth, and whether the wait was on **this tab** or\n **bridge-wide**), that is back-off guidance: instruct the scoop to stagger or\n move to its own tab, never to re-run the command — it already ran; it was\n just slow to get the lock. A bridge-wide wait points at the few genuinely\n global operations (`tab-select`, `--foreground`, attaching to a tab), not at\n your tab.\n- Scoops doing CPU/VFS/network work (curl, file edits, analysis) fan out\n freely, as before.\n\n## Model access policy\n\n`/etc/models` decides which `provider:model` combinations you may spawn against. It\nis keyed by the **selected** provider:\n\n```ini\n[adobe] # while `adobe` is selected…\nopenrouter:* # …any openrouter model may be targeted\n-adobe:claude-opus-5 # …but never adobe\'s own Opus 5\n```\n\n- The selected provider\'s own models are allowed by default — you never list them.\n- Any other provider\'s model is denied until an entry allows it. This is a spend\n boundary: the user may keep separate work and personal accounts.\n- `models` and the picker hide only what a `-` entry denies, so a model you can see\n is not automatically one you may spawn against; the rejection names the exact\n line to add.\n\nDo not edit `/etc/models` to unblock yourself — the write requires a human approval\n(`Write /etc/models` in `/etc/sudoers`). Ask the user instead, quoting the line.\n';export{e as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/oauth-service-GpUOM3Aw.js","assets/preload-helper-Czpn1I53.js","assets/proxied-fetch-4VBgrEIu.js","assets/rolldown-runtime-Dd_uD5pT.js","assets/base64-ELzoYfwP.js","assets/proxy-error-BSFYY7jj.js","assets/api-endpoint-DuEQRZ4g.js","assets/runtime-env-Dlaokqg1.js","assets/panel-rpc-accessor-B4BfPLSo.js","assets/permissions-surface-registry-CilCRwhh.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{a as e,i as t,o as n}from"./core-Cx9N3lmn.js";import{t as r}from"./preload-helper-Czpn1I53.js";import{t as i}from"./logger-DDBAeTLF.js";import"./proxied-fetch-4VBgrEIu.js";import{s as a,t as o}from"./api-endpoint-DuEQRZ4g.js";import{n as s}from"./float-topology-C_iRKPQK.js";import"./secret-topology-hMRoGGjt.js";import{n as c,t as l}from"./panel-rpc-accessor-B4BfPLSo.js";import{n as ee}from"./secrets-bridge-client-D734Xx8G.js";import{n as u,o as d,t as f}from"./providers-DGOyFpbk.js";import{n as te,t as p}from"./stored-accounts-ChNHYF68.js";import{a as ne,c as re,i as ie,l as ae}from"./bedrock-camp-compat-B1oHsbyo.js";import{r as oe,t as se}from"./bedrock-camp-extra-models-BYrxX19D.js";import{o as ce}from"./claude-model-version-DZmbk9E2.js";var m=`slicc_oauth_extra_domains`;function h(e){try{let t=e.getItem(m);if(!t)return{};let n=JSON.parse(t);if(typeof n!=`object`||!n||Array.isArray(n))return{};let r={};for(let[e,t]of Object.entries(n)){if(typeof e!=`string`||!Array.isArray(t))continue;let n=t.filter(e=>typeof e==`string`&&e.length>0);n.length>0&&(r[e]=n)}return r}catch{return{}}}function le(e,t){try{e.setItem(m,JSON.stringify(t))}catch(e){throw Error(`Failed to persist OAuth extras (localStorage quota exceeded?): ${e instanceof Error?e.message:String(e)}`)}}function ue(e,t){let n={input:0,output:0,cacheRead:0,cacheWrite:0},r=ce(e);if(!r)return n;let i;for(let e of t.values()){let t=ce(e.id);!t||t.family!==r.family||(!i||t.major>i.major||t.major===i.major&&t.minor>i.minor)&&(i={major:t.major,minor:t.minor,cost:e.cost})}return i?.cost??n}i(`model-policy`);var de=`/etc/models`;function fe(){return{sections:{}}}function g(e,t,n){return e.providerId===t?e.modelId===`*`||e.modelId===n:!1}function _(e,t){return e.sections[t]??[]}function pe(e,t,n,r){return _(e,t).some(e=>e.deny&&g(e,n,r))}function me(e,t,n,r){let i=_(e,t);return i.some(e=>e.deny&&g(e,n,r))?!1:n===t||i.some(e=>!e.deny&&g(e,n,r))}var he=fe();function ge(){return he}function _e(e,t,n){return`add \`${t}:${n}\` (or \`${t}:*\`) under \`[${e}]\` in ${de}`}var v=t,y=e,b=`selected-model`,ve=[`slicc_provider`,`slicc_api_key`,`slicc_base_url`,`anthropic_api_key`,`api_provider`,`azure_resource`,`bedrock_region`],ye=new Set([`github`]);function x(e){let t;try{t=n()}catch{return!1}return t.includes(e)&&!d(e)}var S=!1;function be(){if(!S){S=!0;for(let e of ve)try{localStorage.removeItem(e)}catch{}C()}}function C(){try{let e=localStorage.getItem(b);if(e){let t=e.indexOf(`:`);if(t>0){let n=e.slice(0,t);(ye.has(n)||x(n))&&localStorage.removeItem(b)}}}catch{}try{let e=localStorage.getItem(p);if(!e)return;let t=JSON.parse(e);if(!Array.isArray(t))return;let n=t.filter(e=>!(typeof e==`object`&&e&&typeof e.providerId==`string`&&x(e.providerId)));n.length!==t.length&&localStorage.setItem(p,JSON.stringify(n))}catch{}}function xe(){S=!1}var Se={_resetLegacyCleanup:xe};function w(){let e=n().filter(d),t=u();return[...new Set([...e,...t])].filter(e=>!f(e)?.hidden)}function T(t){try{if(O(t).length>0)return!0}catch{}try{if(e(t).length>0)return!0}catch{}let n=f(t);return!!(n?.modelOverrides&&Object.keys(n.modelOverrides).length>0)}function Ce(t,n){try{if(O(t).some(e=>e.id===n))return!0}catch{}try{if(e(t).some(e=>e.id===n))return!0}catch{}let r=f(t);return!!(r?.modelOverrides&&Object.hasOwn(r.modelOverrides,n))}function E(e){return f(e)||{id:e,name:e.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `),description:`${e} provider`,requiresApiKey:!0,requiresBaseUrl:!1}}function D(e,t){t.context_window!==void 0&&(e.contextWindow=t.context_window),t.max_tokens!==void 0&&(e.maxTokens=t.max_tokens),t.reasoning!==void 0&&(e.reasoning=t.reasoning),t.input!==void 0&&(e.input=t.input),t.cost!==void 0&&(e.cost=t.cost,e.inputCost=t.cost.input,e.outputCost=t.cost.output,e.cacheReadCost=t.cost.cacheRead,e.cacheWriteCost=t.cost.cacheWrite),t.compat!==void 0&&(e.compat={...e.compat??{},...t.compat}),t.thinkingLevelMap!==void 0&&(e.thinkingLevelMap={...e.thinkingLevelMap??{},...t.thinkingLevelMap})}function we(e){let t=ie(e);return{...e,api:`bedrock-camp-converse`,provider:`bedrock-camp`,reasoning:e.reasoning===!0&&(re(e)||t!==null),...t?{thinkingLevelMap:{...t}}:{}}}function O(e){try{if(e===`bedrock-camp`){let e=ne(W(`bedrock-camp`));return oe(y(`amazon-bedrock`),se).filter(t=>ae(t,e)).map(we)}let t=E(e);if(t.getModelIds){let r;try{r=t.getModelIds()}catch(t){return k.error(`Provider getModelIds callback failed`,{providerId:e,error:t instanceof Error?t.message:String(t)}),[]}let i=new Map;for(let e of n())try{for(let t of y(e))i.set(t.id,t)}catch{}return r.map(n=>{let r=n.api===`openai`?`openai`:`anthropic`,a=`${e}-${r}`,o=i.get(n.id),s;if(o)s={...o,api:a,provider:e};else if(s=q(e,n.id,``,a),n.name&&(s.name=n.name),r===`anthropic`){let e=ue(n.id,i);s.cost=e,s.inputCost=e.input,s.outputCost=e.output,s.cacheReadCost=e.cacheRead,s.cacheWriteCost=e.cacheWrite}let c=t.modelOverrides?.[n.id];return c&&D(s,c),D(s,n),s})}if(t.isOAuth){let n=y(`anthropic`),r=`${e}-anthropic`;return n.map(n=>{let i={...n,api:r,provider:e},a=t.modelOverrides?.[n.id];return a&&D(i,a),i})}return y(e===`azure-ai-foundry`?`anthropic`:e)}catch(t){return k.error(`Failed to load models`,{providerId:e,error:t instanceof Error?t.message:String(t)}),[]}}function Te(e){let t=N().find(t=>t.providerId===e);if(!t?.accessToken)return null;let n=!!t.tokenExpiresAt&&Date.now()>t.tokenExpiresAt-6e4;return{token:t.accessToken,maskedValue:t.maskedValue,expiresAt:t.tokenExpiresAt,userName:t.userName,userAvatar:t.userAvatar,scopes:t.scopes,expired:n}}var Ee=Object.assign({})[`/packages/webapp/providers.json`]??[],k=i(`provider-settings`);function De(e=Ee){if(e.length===0||N().length>0)return;let t=new Set(w());for(let n of e)if(!(!n.providerId||!n.apiKey)){if(!t.has(n.providerId)){k.warn(`Unknown provider "${n.providerId}" in providers.json — skipping`);continue}R(n.providerId,n.apiKey,n.baseUrl)}let n=e.find(e=>e.providerId&&e.apiKey&&t.has(e.providerId));n?.model&&!localStorage.getItem(b)&&localStorage.setItem(b,`${n.providerId}:${n.model}`)}var Oe=[/haiku/i];function A(e){return Oe.some(t=>t.test(e))}function ke(e){return e.filter(e=>!A(e.id))}function j(e,t){let n=$();if(n===null)return e;let r=ge();return e.filter(e=>!pe(r,n,t,e.id))}function M(){let e=N();if(e.length===0)return[];let t=new Map;for(let n of e){if(t.has(n.providerId))continue;let e=E(n.providerId);if(e.hidden||x(n.providerId))continue;let r=j(ke(O(n.providerId)),n.providerId);if(r.length===0)continue;let i={providerId:n.providerId,providerName:e.name,models:r};t.set(n.providerId,i)}return[...t.values()]}function Ae(e){return M().map(e=>e.providerId).filter(t=>t!==e)}function N(){return be(),te()}function P(e){return h(localStorage)[e]??[]}function F(e,t){let n=h(localStorage),r=t.map(e=>e.trim()).filter(e=>e.length>0);r.length===0?delete n[e]:n[e]=r,le(localStorage,n)}async function je(e,t){if(c()){F(e,t);return}let n=l();if(!n)throw Error(`setExtraOAuthDomainsAsync: no DOM and no panel-rpc client — cannot persist to page localStorage`);let{storeAfter:r}=await n.call(`oauth-extras-set`,{providerId:e,domains:t});try{le(localStorage,r)}catch(t){k.warn(`worker-shim mirror failed after successful page write — reload to refresh`,{providerId:e,error:t instanceof Error?t.message:String(t)})}}function Me(){return h(localStorage)}function I(e){localStorage.setItem(p,JSON.stringify(e))}async function L(e){if(c()){I(e);return}let t=l();if(!t)throw Error(`saveAccountsAsync: no DOM and no panel-rpc client — cannot persist to page localStorage`);let n=JSON.stringify(e),{storedJson:r}=await t.call(`save-oauth-accounts`,{accountsJson:n});try{localStorage.setItem(p,r)}catch(e){k.warn(`worker-shim mirror failed after successful page write — reload to refresh`,{error:e instanceof Error?e.message:String(e)})}}function R(e,t,n,r,i){let a=N().filter(t=>t.providerId!==e),o={providerId:e,apiKey:t};n&&(o.baseUrl=n),r&&(o.deployment=r),i&&(o.apiVersion=i),a.push(o),I(a)}async function Ne(e){let t=s();try{if(t===`extension-direct`){let t=await new Promise(t=>{chrome.runtime.sendMessage({type:`secrets.delete`,name:`oauth.${e}.token`},n=>{chrome.runtime.lastError&&k.error(`SW secrets.delete transport failed`,{providerId:e,error:chrome.runtime.lastError.message}),t(n??{})})});t.error&&k.error(`SW secrets.delete returned error`,{providerId:e,error:t.error})}else if(t===`extension-delegate`){let t=await ee(`secrets.delete`,{name:`oauth.${e}.token`});t?.error&&k.error(`Bridge secrets.delete returned error`,{providerId:e,error:t.error})}else if(t!==`connect`){let t=await fetch(a(`/api/secrets/oauth/${e}`),{method:`DELETE`,headers:o()});!t.ok&&t.status!==404&&k.warn(`OAuth replica DELETE non-ok`,{providerId:e,status:t.status})}}catch(n){k.error(`OAuth replica removal failed`,{providerId:e,topology:t,error:n instanceof Error?n.message:String(n)})}}async function z(e){let t=N().find(t=>t.providerId===e),n=E(e);t&&n?.isOAuth&&await Pe(e),await Ne(e),await L(N().filter(t=>t.providerId!==e));let r=localStorage.getItem(b)??``,i=r.indexOf(`:`);i>0&&r.slice(0,i)===e&&localStorage.removeItem(b)}async function Pe(e){let t=N().find(t=>t.providerId===e);if(!t)return;let n=E(e);if(n?.isOAuth){if(n.onOAuthLogout)try{await n.onOAuthLogout()}catch(t){k.warn(`onOAuthLogout failed`,{providerId:e,error:t instanceof Error?t.message:String(t)})}if(n.getOAuthLogoutUrl){let i=n.getOAuthLogoutUrl(t);if(i){let{openIdpLogoutUrl:t}=await r(async()=>{let{openIdpLogoutUrl:e}=await import(`./oauth-service-GpUOM3Aw.js`);return{openIdpLogoutUrl:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]));await t(i).catch(t=>{k.warn(`IdP logout popup failed`,{providerId:e,error:t instanceof Error?t.message:String(t)})})}}await L(N().map(t=>t.providerId===e?{providerId:t.providerId,apiKey:``,baseUrl:t.baseUrl,userName:t.userName,userAvatar:t.userAvatar,loggedOut:!0}:t)),await Ne(e)}}async function Fe(e,t={}){let n=Math.max(1,t.attempts??3),r=t.delayMs??150,i=t.sleep??(e=>new Promise(t=>setTimeout(t,e))),a;for(let t=0;t<n;t++){let o=await e();if(o.maskedValue)return{maskedValue:o.maskedValue};o.error&&(a=o.error),t<n-1&&await i(r)}return{lastError:a}}var Ie=`access token rotated during mask write`;function B(e,t,n,r){let i=r.find(t=>t.providerId===e);return i?.accessToken?i.accessToken===t?(i.maskedValue=n,{maskedValue:n}):(k.warn(`OAuth mask write raced with token rotation; discarding replica`,{providerId:e}),{error:Ie}):{error:`account gone after mask write`}}function V(e,t){return!!e&&e!==t}async function H(e,t,n){let r={providerId:e.providerId,accessToken:e.accessToken,domains:e.domains.join(`,`)},{maskedValue:i,lastError:a}=await Fe(()=>t.sendMaskRequest(r),n);if(!V(i,e.accessToken)){let t=i?`mask replica equals the access token`:a??`no error reported (cold SW or empty reply)`;return k.error(`OAuth mask give-up: no masked value after retries`,{providerId:e.providerId,reason:t}),{error:t}}let o=t.getAccounts(),s=B(e.providerId,e.accessToken,i,o);return s.maskedValue&&await t.saveAccounts(o),s}function Le(e){let t=E(e).oauthTokenDomains??[],n=P(e),r=new Set,i=[];for(let e of[...t,...n]){let t=e.toLowerCase();r.has(t)||(r.add(t),i.push(e))}return i}function Re(e){return new Promise(t=>{chrome.runtime.sendMessage({type:`secrets.mask-oauth-token`,...e},n=>{chrome.runtime.lastError&&k.error(`SW mask-oauth-token transport failed`,{providerId:e.providerId,error:chrome.runtime.lastError.message});let r=typeof n==`object`&&n?n:void 0;r?.error&&k.warn(`SW mask-oauth-token returned error`,{providerId:e.providerId,error:r.error}),t(r??{})})})}function ze(e){return ee(`secrets.mask-oauth-token`,e).then(t=>(t?.error&&k.warn(`Bridge mask-oauth-token returned error`,{providerId:e.providerId,error:t.error}),t??{})).catch(t=>(k.error(`Bridge mask-oauth-token transport failed`,{providerId:e.providerId,error:t instanceof Error?t.message:String(t)}),{}))}async function Be(e,t,n){let r=a(`/api/secrets/oauth-update`),i=await fetch(r,{method:`POST`,headers:o({"Content-Type":`application/json`}),body:JSON.stringify({providerId:e,accessToken:t,domains:n})});if(!i.ok)return k.warn(`OAuth replica POST non-ok`,{providerId:e,status:i.status,url:r}),{error:`OAuth replica POST HTTP ${i.status}`};let s=await i.json();if(typeof s.maskedValue!=`string`)return k.warn(`OAuth replica POST ok but missing maskedValue`,{providerId:e,url:r}),{error:`OAuth replica POST ok but missing maskedValue`};if(!V(s.maskedValue,t))return k.error(`OAuth mask replica equals the access token; refusing to persist`,{providerId:e}),{error:`mask replica equals the access token`};let c=N(),l=B(e,t,s.maskedValue,c);return l.maskedValue&&await L(c),l}async function Ve(e,t){let n=await He(e,t);if(n.error!==Ie)return n;let r=N().find(t=>t.providerId===e)?.accessToken;return!r||r===t?n:He(e,r)}async function He(e,t){let n=Le(e);if(n.length===0)return{error:`no oauth token domains configured`};let r=s();try{return r===`extension-direct`?H({providerId:e,accessToken:t,domains:n},{sendMaskRequest:Re,getAccounts:N,saveAccounts:L}):r===`extension-delegate`?H({providerId:e,accessToken:t,domains:n},{sendMaskRequest:ze,getAccounts:N,saveAccounts:L}):r===`connect`?{error:`no replica store in connect mode`}:await Be(e,t,n)}catch(t){let n=t instanceof Error?t.message:String(t);return k.error(`OAuth replica sync failed`,{providerId:e,topology:r,error:n}),{error:n}}}async function Ue(e){let t=N().find(t=>t.providerId===e);return t?.accessToken?V(t.maskedValue,t.accessToken)?{maskedValue:t.maskedValue}:Ve(e,t.accessToken):{error:`no access token held`}}function We(e,t){if(e.accessToken)return`scopes`in e?e.scopes:t?.scopes}async function Ge(e){let t=N().find(t=>t.providerId===e.providerId),n=N().filter(t=>t.providerId!==e.providerId);n.push({providerId:e.providerId,apiKey:``,accessToken:e.accessToken,refreshToken:e.refreshToken,tokenExpiresAt:e.tokenExpiresAt,userName:e.userName,userAvatar:e.userAvatar,baseUrl:e.baseUrl??t?.baseUrl,scopes:We(e,t)}),await L(n),await Ve(e.providerId,e.accessToken)}var Ke=`local`;function U(e){let t=N().find(t=>t.providerId===e);return t&&(t.accessToken||t.apiKey)||null}function qe(e){let t=N().find(t=>t.providerId===e);return t?t.accessToken||t.apiKey||(E(e).optionalApiKey?Ke:null):null}function W(e){return N().find(t=>t.providerId===e)?.baseUrl??null}function Je(e){return N().find(t=>t.providerId===e)?.deployment??null}function Ye(e){return N().find(t=>t.providerId===e)?.apiVersion??null}function G(){let e=localStorage.getItem(b)||``,t=e.indexOf(`:`);return t>=0?e.slice(t+1):e}function Xe(e){let t=e.indexOf(`:`);if(t>0){let n=e.slice(0,t),r=new Set([...u(),...w()]),i=n.includes(`.`);if(r.has(n)||!i){localStorage.setItem(b,e);return}}let n=K();localStorage.setItem(b,`${n}:${e}`)}function Ze(){return localStorage.getItem(b)||``}function K(){let e=Ze(),t=e.indexOf(`:`);if(t>0)return e.slice(0,t);let n=N(),r=G();if(r){let e=n.find(e=>T(e.providerId)&&Ce(e.providerId,r));if(e)return e.providerId}let i=n.find(e=>T(e.providerId));return i?i.providerId:n.length>0?n[0].providerId:`anthropic`}function Qe(e){let t=G();localStorage.setItem(b,`${e}:${t}`)}function $e(){let e=G();localStorage.setItem(b,e)}function et(){return qe(K())}function tt(e){let t=K();R(t,e,W(t)??void 0)}async function nt(){await z(K())}function rt(){return W(K())}function it(e){let t=K(),n=U(t);n&&R(t,n,e||void 0)}function at(){let e=K(),t=U(e);t&&R(e,t)}function ot(){let e=N(),t=K(),n=G();return e.map(e=>{let r={providerId:e.providerId,apiKey:e.apiKey};return e.baseUrl&&(r.baseUrl=e.baseUrl),e.providerId===t&&n&&(r.model=n),r})}async function st(){let e=N();await Promise.allSettled(e.map(e=>z(e.providerId))),localStorage.removeItem(p),localStorage.removeItem(b);for(let e of ve)localStorage.removeItem(e)}function ct(e){return/^(?:gpt[-.]?|o[0-9]|chatgpt)/i.test(e)?`openai`:`anthropic`}function q(e,t,n,r){return{id:t,name:t,provider:e,api:r??`${e}-${ct(t)}`,baseUrl:n??``,contextWindow:2e5,maxTokens:16384,input:[`text`,`image`],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},reasoning:!0}}function J(e,t){return t.isOAuth||e===`azure-ai-foundry`?`anthropic`:e===`bedrock-camp`?`amazon-bedrock`:e}function lt(){let e=new Set;for(let t of N())t.loggedOut||(e.add(t.providerId),e.add(J(t.providerId,E(t.providerId))));return[...e]}function ut(e,t,n){let r=O(e).find(e=>e.id===t);return r?n?{...r,baseUrl:n}:r:null}function dt(e,t,n,r){return n.isOAuth?O(t).find(e=>e.id===r)||{...e,api:`${t}-anthropic`,provider:t}:t===`bedrock-camp`?{...e,api:`bedrock-camp-converse`,provider:`bedrock-camp`}:e}function ft(e,t,n,r,i){let a=ut(e,n,r);if(a)return a;if(t.isOAuth)return q(e,n,r);if(i)throw Error(`Model ${n} is not available from provider ${e}`);return Y()}function pt(e,t){if(!e)return Y();let n=t??K(),r=W(n),i=E(n);if(t!==void 0){let t=ut(n,e,r);if(t)return t}try{let t=v(J(n,i),e);if(!t?.id)throw Error(`Model ${e} not found`);let a=dt(t,n,i,e);return r?{...a,baseUrl:r}:a}catch(a){return k.debug(`resolveModelById: pi-ai lookup miss, using provider fallback`,{providerId:n,modelId:e,error:a instanceof Error?a.message:String(a)}),ft(n,i,e,r,t!==void 0)}}function mt(e,t){return e.provider===t||e.provider===J(t,E(t))}function Y(){let e=K(),t=G(),n=W(e),r=O(e),i=E(e),a=i.defaultModelId?r.find(e=>e.id.toLowerCase().includes(i.defaultModelId.toLowerCase()))?.id:void 0,o=t||a||r[0]?.id||`claude-sonnet-4-6`;try{let t=J(e,i),a=v(t,o);if(!a?.id)throw Error(`Model ${o} not found in ${t} registry`);let s=a;return i.isOAuth?s=r.find(e=>e.id===o)||{...s,api:`${e}-anthropic`,provider:e}:e===`bedrock-camp`&&(s={...s,api:`bedrock-camp-converse`,provider:`bedrock-camp`}),n&&(s={...s,baseUrl:n}),s}catch(t){k.debug(`resolveCurrentModel: pi-ai lookup miss, using provider fallback`,{providerId:e,effectiveModelId:o,error:t instanceof Error?t.message:String(t)});let a=r.find(e=>e.id===o);return a?n?{...a,baseUrl:n}:a:i.isOAuth?q(e,o,n):v(`anthropic`,`claude-sonnet-4-0`)}}function ht(e){let t=e.toLowerCase();if(!t)return null;let n=null;try{n=K()}catch{}if(n!==null){let e=X(t,[n]);if(e!==null)return e}return X(t,N().map(e=>e.providerId))}function X(e,t){let n=null,r=-1;for(let i of t)for(let t of O(i)){let i=t.id.toLowerCase(),a=(t.name??``).toLowerCase();if(!i.includes(e)&&!a.includes(e))continue;let o=t.contextWindow??0;(o>r||o===r&&Tt(t.id,n??``)>0)&&(r=o,n=t.id)}return n}function Z(){let e=[];try{for(let t of N())e.includes(t.providerId)||e.push(t.providerId)}catch{}try{let t=K();e.includes(t)||e.push(t)}catch{}return e}function gt(e){let t=e.indexOf(`:`);if(t<=0||t===e.length-1)return null;let n=e.slice(0,t),r=e.slice(t+1),i=Z().includes(n);if(i)return{providerId:n,modelId:r,configured:i};let a=!1;try{a=w().includes(n)}catch{}return a?{providerId:n,modelId:r,configured:!1}:null}function Q(e,t,n=!0){let r=[e],i=n?X(e.toLowerCase(),[t]):null;i!==null&&i!==e&&r.push(i);let a=[];try{a=O(t)}catch{}for(let n of r)if(!(a.length>0&&!a.some(e=>e.id===n)))try{if(pt(n,t).id===n)return{modelId:n,providerId:t}}catch(r){k.debug(`selectModelFromProvider: candidate did not resolve`,{input:e,candidate:n,providerId:t,error:r instanceof Error?r.message:String(r)})}return null}function _t(e){return e.map(e=>`${e.providerId}:${e.modelId}`).join(`, `)}function vt(e){if(!e)return{ok:!1,error:`unknown model: (empty)`};let t=gt(e);if(t)return St(e,t);let n=null;try{n=K()}catch{}if(n!==null){let t=Q(e,n);if(t)return xt(t)}return Ct(e,n)}function $(){try{return K()}catch{return null}}function yt(e){let t=$();return t===null||me(ge(),t,e.providerId,e.modelId)}function bt(e){let t=$()??`<none>`;return{ok:!1,error:`model not allowed: ${`${e.providerId}:${e.modelId}`} is blocked by ${de} while "${t}" is selected — ${_e(t,e.providerId,e.modelId)}`}}function xt(e){return yt(e)?{ok:!0,selection:e}:bt(e)}function St(e,t){if(!t.configured){let n=Z();return{ok:!1,error:`unknown model: ${e} (provider "${t.providerId}" is not configured${n.length>0?`; configured: ${n.join(`, `)}`:``})`}}let n=Q(t.modelId,t.providerId);return n?xt(n):{ok:!1,error:`unknown model: ${e} (provider "${t.providerId}" does not offer "${t.modelId}")`}}function Ct(e,t){let n=Z().filter(e=>e!==t);for(let t of[`exact`,`shorthand`]){let r=[];for(let i of n){let n=t===`exact`?e:X(e.toLowerCase(),[i]);if(n===null)continue;let a=Q(n,i,!1);a&&r.push(a)}let i=r.filter(yt);if(i.length===0&&r.length>0)return bt(r[0]);if(i.length===1)return{ok:!0,selection:i[0]};if(i.length>1)return{ok:!1,error:`ambiguous model: ${e} matches ${_t(i)} — qualify it as provider:model`}}return{ok:!1,error:`unknown model: ${e}`}}function wt(e){let t=vt(e);return t.ok?t.selection.modelId:null}function Tt(e,t){let n=e.match(/\d+/g)?.map(Number)??[],r=t.match(/\d+/g)?.map(Number)??[],i=Math.max(n.length,r.length);for(let e=0;e<i;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t}return 0}export{V as A,pt as B,Te as C,G as D,U as E,H as F,tt as G,wt as H,j as I,je as J,it as K,T as L,Fe as M,C as N,K as O,mt as P,z as R,lt as S,O as T,vt as U,ht as V,Ge as W,Qe as X,Xe as Y,ue as Z,w as _,nt as a,Je as b,Ue as c,M as d,Me as f,Ye as g,qe as h,st as i,Pe as j,A as k,ot as l,et as m,R as n,at as o,Ae as p,F as q,De as r,$e as s,Se as t,N as u,rt as v,E as w,P as x,W as y,Y as z};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-Dd_uD5pT.js";import{t}from"./logger-LESFN7Hj.js";import"./proxied-fetch-F-dCBEfh.js";import{n,t as r}from"./panel-rpc-accessor-B4BfPLSo.js";import{n as i,o as a,t as o}from"./providers-CNz3-2Qt.js";import{s,t as c}from"./api-endpoint-D8lUKmPu.js";import{n as l,t as u}from"./stored-accounts-Cx83FZwe.js";import{a as d,i as ee,o as f}from"./core-C1m4D34S.js";import{n as te}from"./float-topology-COIC4j_U.js";import{t as ne}from"./secrets-bridge-client-GOCzDscb.js";import{a as re,c as ie,i as ae,l as oe}from"./bedrock-camp-compat-ByR2ly4i.js";import{r as se,t as ce}from"./bedrock-camp-extra-models-DIuCBjcJ.js";import{s as p}from"./claude-model-version-ceOteQ2f.js";const le=`slicc_oauth_extra_domains`;function m(e){try{let t=e.getItem(le);if(!t)return{};let n=JSON.parse(t);if(typeof n!=`object`||!n||Array.isArray(n))return{};let r={};for(let[e,t]of Object.entries(n)){if(typeof e!=`string`||!Array.isArray(t))continue;let n=t.filter(e=>typeof e==`string`&&e.length>0);n.length>0&&(r[e]=n)}return r}catch{return{}}}function h(e,t){try{e.setItem(le,JSON.stringify(t))}catch(e){throw Error(`Failed to persist OAuth extras (localStorage quota exceeded?): ${e instanceof Error?e.message:String(e)}`)}}function g(e,t){let n={input:0,output:0,cacheRead:0,cacheWrite:0},r=p(e);if(!r)return n;let i;for(let e of t.values()){let t=p(e.id);!t||t.family!==r.family||(!i||t.major>i.major||t.major===i.major&&t.minor>i.minor)&&(i={major:t.major,minor:t.minor,cost:e.cost})}return i?.cost??n}const ue=t(`model-policy`),_=`/etc/models`;function v(){return{sections:{}}}function de(e){let t=e.indexOf(`#`);return(t===-1?e:e.slice(0,t)).trim()}function fe(e){let t=v();if(typeof e!=`string`)return t;let n=null;for(let r of e.split(/\r?\n/)){let e=de(r);if(!e)continue;let i=/^\[([^\]]+)\]$/.exec(e);if(i){n=i[1].trim(),t.sections[n]??=[];continue}if(n===null){ue.warn(`model policy entry before any [provider] section — ignored`,{entry:e});continue}let a=e.startsWith(`-`),o=a?e.slice(1).trim():e,s=o.indexOf(`:`);if(s<=0||s===o.length-1){ue.warn(`model policy entry is not provider:model — ignored`,{entry:e});continue}t.sections[n].push({providerId:o.slice(0,s).trim(),modelId:o.slice(s+1).trim(),deny:a})}return t}function y(e,t,n){return e.providerId===t?e.modelId===`*`||e.modelId===n:!1}function pe(e,t){return e.sections[t]??[]}function me(e,t,n,r){return pe(e,t).some(e=>e.deny&&y(e,n,r))}function he(e,t,n,r){let i=pe(e,t);return i.some(e=>e.deny&&y(e,n,r))?!1:n===t||i.some(e=>!e.deny&&y(e,n,r))}let ge=v();function _e(e){ge=e}function ve(){return ge}function ye(e,t,n){return`add \`${t}:${n}\` (or \`${t}:*\`) under \`[${e}]\` in ${_}`}var be=e({ACCOUNTS_KEY:()=>u,__test__:()=>Te,addAccount:()=>P,applyProviderDefaults:()=>Ae,clearAllSettings:()=>ht,clearApiKey:()=>ut,clearBaseUrl:()=>pt,clearSelectedProvider:()=>st,ensureOAuthMaskReplica:()=>$e,exportProviders:()=>mt,getAccounts:()=>M,getAllAvailableModels:()=>Fe,getAllExtraOAuthDomains:()=>Be,getAlternativeModelProviders:()=>Ie,getApiKey:()=>ct,getApiKeyForProvider:()=>z,getApiVersionForProvider:()=>rt,getAvailableProviders:()=>E,getBaseUrl:()=>dt,getBaseUrlForProvider:()=>B,getDeploymentForProvider:()=>nt,getExtraOAuthDomains:()=>Le,getModelCatalogProviderIds:()=>_t,getOAuthAccountInfo:()=>Oe,getProviderConfig:()=>O,getProviderModels:()=>A,getRawApiKeyForProvider:()=>R,getSelectedModelId:()=>V,getSelectedProvider:()=>H,isModelHiddenFromPicker:()=>Me,isUsableOAuthMaskReplica:()=>I,logoutOAuthAccount:()=>Ue,maskOAuthTokenWithRetry:()=>We,migrateLegacyAuthOnlySelection:()=>T,modelRunsOnProvider:()=>xt,persistOAuthMaskViaServiceWorker:()=>L,policyVisible:()=>Pe,providerOffersLlmModels:()=>D,removeAccount:()=>F,resolveCurrentModel:()=>K,resolveModelById:()=>G,resolveModelByShorthand:()=>St,resolveModelIdForScoop:()=>Ot,resolveModelSelectionForScoop:()=>X,saveOAuthAccount:()=>tt,setApiKey:()=>lt,setBaseUrl:()=>ft,setExtraOAuthDomains:()=>Re,setExtraOAuthDomainsAsync:()=>ze,setSelectedModelId:()=>it,setSelectedProvider:()=>ot});const b=ee,x=d,S=`selected-model`,xe=[`slicc_provider`,`slicc_api_key`,`slicc_base_url`,`anthropic_api_key`,`api_provider`,`azure_resource`,`bedrock_region`],Se=new Set([`github`]);function C(e){let t;try{t=f()}catch{return!1}return t.includes(e)&&!a(e)}let w=!1;function Ce(){if(!w){w=!0;for(let e of xe)try{localStorage.removeItem(e)}catch{}T()}}function T(){try{let e=localStorage.getItem(S);if(e){let t=e.indexOf(`:`);if(t>0){let n=e.slice(0,t);(Se.has(n)||C(n))&&localStorage.removeItem(S)}}}catch{}try{let e=localStorage.getItem(u);if(!e)return;let t=JSON.parse(e);if(!Array.isArray(t))return;let n=t.filter(e=>!(typeof e==`object`&&e&&typeof e.providerId==`string`&&C(e.providerId)));n.length!==t.length&&localStorage.setItem(u,JSON.stringify(n))}catch{}}function we(){w=!1}const Te={_resetLegacyCleanup:we};function E(){let e=f().filter(a),t=i();return[...new Set([...e,...t])].filter(e=>!o(e)?.hidden)}function D(e){try{if(A(e).length>0)return!0}catch{}try{if(d(e).length>0)return!0}catch{}let t=o(e);return!!(t?.modelOverrides&&Object.keys(t.modelOverrides).length>0)}function Ee(e,t){try{if(A(e).some(e=>e.id===t))return!0}catch{}try{if(d(e).some(e=>e.id===t))return!0}catch{}let n=o(e);return!!(n?.modelOverrides&&Object.hasOwn(n.modelOverrides,t))}function O(e){return o(e)||{id:e,name:e.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `),description:`${e} provider`,requiresApiKey:!0,requiresBaseUrl:!1}}function k(e,t){t.context_window!==void 0&&(e.contextWindow=t.context_window),t.max_tokens!==void 0&&(e.maxTokens=t.max_tokens),t.reasoning!==void 0&&(e.reasoning=t.reasoning),t.input!==void 0&&(e.input=t.input),t.cost!==void 0&&(e.cost=t.cost,e.inputCost=t.cost.input,e.outputCost=t.cost.output,e.cacheReadCost=t.cost.cacheRead,e.cacheWriteCost=t.cost.cacheWrite),t.compat!==void 0&&(e.compat={...e.compat??{},...t.compat}),t.thinkingLevelMap!==void 0&&(e.thinkingLevelMap={...e.thinkingLevelMap??{},...t.thinkingLevelMap})}function De(e){let t=ae(e);return{...e,api:`bedrock-camp-converse`,provider:`bedrock-camp`,reasoning:e.reasoning===!0&&(ie(e)||t!==null),...t?{thinkingLevelMap:{...t}}:{}}}function A(e){try{if(e===`bedrock-camp`){let e=re(B(`bedrock-camp`));return se(x(`amazon-bedrock`),ce).filter(t=>oe(t,e)).map(De)}let t=O(e);if(t.getModelIds){let n;try{n=t.getModelIds()}catch(t){return j.error(`Provider getModelIds callback failed`,{providerId:e,error:t instanceof Error?t.message:String(t)}),[]}let r=new Map;for(let e of f())try{for(let t of x(e))r.set(t.id,t)}catch{}return n.map(n=>{let i=n.api===`openai`?`openai`:`anthropic`,a=`${e}-${i}`,o=r.get(n.id),s;if(o)s={...o,api:a,provider:e};else if(s=U(e,n.id,``,a),n.name&&(s.name=n.name),i===`anthropic`){let e=g(n.id,r);s.cost=e,s.inputCost=e.input,s.outputCost=e.output,s.cacheReadCost=e.cacheRead,s.cacheWriteCost=e.cacheWrite}let c=t.modelOverrides?.[n.id];return c&&k(s,c),k(s,n),s})}if(t.isOAuth){let n=x(`anthropic`),r=`${e}-anthropic`;return n.map(n=>{let i={...n,api:r,provider:e},a=t.modelOverrides?.[n.id];return a&&k(i,a),i})}return x(e===`azure-ai-foundry`?`anthropic`:e)}catch(t){return j.error(`Failed to load models`,{providerId:e,error:t instanceof Error?t.message:String(t)}),[]}}function Oe(e){let t=M().find(t=>t.providerId===e);if(!t?.accessToken)return null;let n=!!t.tokenExpiresAt&&Date.now()>t.tokenExpiresAt-6e4;return{token:t.accessToken,maskedValue:t.maskedValue,expiresAt:t.tokenExpiresAt,userName:t.userName,userAvatar:t.userAvatar,scopes:t.scopes,expired:n}}const ke=Object.assign({})[`/packages/webapp/providers.json`]??[],j=t(`provider-settings`);function Ae(e=ke){if(e.length===0||M().length>0)return;let t=new Set(E());for(let n of e)if(!(!n.providerId||!n.apiKey)){if(!t.has(n.providerId)){j.warn(`Unknown provider "${n.providerId}" in providers.json — skipping`);continue}P(n.providerId,n.apiKey,n.baseUrl)}let n=e.find(e=>e.providerId&&e.apiKey&&t.has(e.providerId));n?.model&&!localStorage.getItem(S)&&localStorage.setItem(S,`${n.providerId}:${n.model}`)}const je=[/haiku/i];function Me(e){return je.some(t=>t.test(e))}function Ne(e){return e.filter(e=>!Me(e.id))}function Pe(e,t){let n=Z();if(n===null)return e;let r=ve();return e.filter(e=>!me(r,n,t,e.id))}function Fe(){let e=M();if(e.length===0)return[];let t=new Map;for(let n of e){if(t.has(n.providerId))continue;let e=O(n.providerId);if(e.hidden||C(n.providerId))continue;let r=Pe(Ne(A(n.providerId)),n.providerId);if(r.length===0)continue;let i={providerId:n.providerId,providerName:e.name,models:r};t.set(n.providerId,i)}return[...t.values()]}function Ie(e){return Fe().map(e=>e.providerId).filter(t=>t!==e)}function M(){return Ce(),l()}function Le(e){return m(localStorage)[e]??[]}function Re(e,t){let n=m(localStorage),r=t.map(e=>e.trim()).filter(e=>e.length>0);r.length===0?delete n[e]:n[e]=r,h(localStorage,n)}async function ze(e,t){if(n()){Re(e,t);return}let i=r();if(!i)throw Error(`setExtraOAuthDomainsAsync: no DOM and no panel-rpc client — cannot persist to page localStorage`);let{storeAfter:a}=await i.call(`oauth-extras-set`,{providerId:e,domains:t});try{h(localStorage,a)}catch(t){j.warn(`worker-shim mirror failed after successful page write — reload to refresh`,{providerId:e,error:t instanceof Error?t.message:String(t)})}}function Be(){return m(localStorage)}function Ve(e){localStorage.setItem(u,JSON.stringify(e))}async function N(e){if(n()){Ve(e);return}let t=r();if(!t)throw Error(`saveAccountsAsync: no DOM and no panel-rpc client — cannot persist to page localStorage`);let i=JSON.stringify(e),{storedJson:a}=await t.call(`save-oauth-accounts`,{accountsJson:i});try{localStorage.setItem(u,a)}catch(e){j.warn(`worker-shim mirror failed after successful page write — reload to refresh`,{error:e instanceof Error?e.message:String(e)})}}function P(e,t,n,r,i){let a=M().filter(t=>t.providerId!==e),o={providerId:e,apiKey:t};n&&(o.baseUrl=n),r&&(o.deployment=r),i&&(o.apiVersion=i),a.push(o),Ve(a)}async function He(e){let t=te();try{if(t===`extension-direct`){let t=await new Promise(t=>{chrome.runtime.sendMessage({type:`secrets.delete`,name:`oauth.${e}.token`},n=>{chrome.runtime.lastError&&j.error(`SW secrets.delete transport failed`,{providerId:e,error:chrome.runtime.lastError.message}),t(n??{})})});t.error&&j.error(`SW secrets.delete returned error`,{providerId:e,error:t.error})}else if(t===`extension-delegate`){let t=await ne(`secrets.delete`,{name:`oauth.${e}.token`});t?.error&&j.error(`Bridge secrets.delete returned error`,{providerId:e,error:t.error})}else if(t!==`connect`){let t=await fetch(s(`/api/secrets/oauth/${e}`),{method:`DELETE`,headers:c()});!t.ok&&t.status!==404&&j.warn(`OAuth replica DELETE non-ok`,{providerId:e,status:t.status})}}catch(n){j.error(`OAuth replica removal failed`,{providerId:e,topology:t,error:n instanceof Error?n.message:String(n)})}}async function F(e){let t=M().find(t=>t.providerId===e),n=O(e);t&&n?.isOAuth&&await Ue(e),await He(e),await N(M().filter(t=>t.providerId!==e));let r=localStorage.getItem(S)??``,i=r.indexOf(`:`);i>0&&r.slice(0,i)===e&&localStorage.removeItem(S)}async function Ue(e){let t=M().find(t=>t.providerId===e);if(!t)return;let n=O(e);if(n?.isOAuth){if(n.onOAuthLogout)try{await n.onOAuthLogout()}catch(t){j.warn(`onOAuthLogout failed`,{providerId:e,error:t instanceof Error?t.message:String(t)})}if(n.getOAuthLogoutUrl){let r=n.getOAuthLogoutUrl(t);if(r){let{openIdpLogoutUrl:t}=await import(`./oauth-service-MWzqRq2q.js`);await t(r).catch(t=>{j.warn(`IdP logout popup failed`,{providerId:e,error:t instanceof Error?t.message:String(t)})})}}await N(M().map(t=>t.providerId===e?{providerId:t.providerId,apiKey:``,baseUrl:t.baseUrl,userName:t.userName,userAvatar:t.userAvatar,loggedOut:!0}:t)),await He(e)}}async function We(e,t={}){let n=Math.max(1,t.attempts??3),r=t.delayMs??150,i=t.sleep??(e=>new Promise(t=>setTimeout(t,e))),a;for(let t=0;t<n;t++){let o=await e();if(o.maskedValue)return{maskedValue:o.maskedValue};o.error&&(a=o.error),t<n-1&&await i(r)}return{lastError:a}}const Ge=`access token rotated during mask write`;function Ke(e,t,n,r){let i=r.find(t=>t.providerId===e);return i?.accessToken?i.accessToken===t?(i.maskedValue=n,{maskedValue:n}):(j.warn(`OAuth mask write raced with token rotation; discarding replica`,{providerId:e}),{error:Ge}):{error:`account gone after mask write`}}function I(e,t){return!!e&&e!==t}async function L(e,t,n){let r={providerId:e.providerId,accessToken:e.accessToken,domains:e.domains.join(`,`)},{maskedValue:i,lastError:a}=await We(()=>t.sendMaskRequest(r),n);if(!I(i,e.accessToken)){let t=i?`mask replica equals the access token`:a??`no error reported (cold SW or empty reply)`;return j.error(`OAuth mask give-up: no masked value after retries`,{providerId:e.providerId,reason:t}),{error:t}}let o=t.getAccounts(),s=Ke(e.providerId,e.accessToken,i,o);return s.maskedValue&&await t.saveAccounts(o),s}function qe(e){let t=O(e).oauthTokenDomains??[],n=Le(e),r=new Set,i=[];for(let e of[...t,...n]){let t=e.toLowerCase();r.has(t)||(r.add(t),i.push(e))}return i}function Je(e){return new Promise(t=>{chrome.runtime.sendMessage({type:`secrets.mask-oauth-token`,...e},n=>{chrome.runtime.lastError&&j.error(`SW mask-oauth-token transport failed`,{providerId:e.providerId,error:chrome.runtime.lastError.message});let r=typeof n==`object`&&n?n:void 0;r?.error&&j.warn(`SW mask-oauth-token returned error`,{providerId:e.providerId,error:r.error}),t(r??{})})})}function Ye(e){return ne(`secrets.mask-oauth-token`,e).then(t=>(t?.error&&j.warn(`Bridge mask-oauth-token returned error`,{providerId:e.providerId,error:t.error}),t??{})).catch(t=>(j.error(`Bridge mask-oauth-token transport failed`,{providerId:e.providerId,error:t instanceof Error?t.message:String(t)}),{}))}async function Xe(e,t,n){let r=s(`/api/secrets/oauth-update`),i=await fetch(r,{method:`POST`,headers:c({"Content-Type":`application/json`}),body:JSON.stringify({providerId:e,accessToken:t,domains:n})});if(!i.ok)return j.warn(`OAuth replica POST non-ok`,{providerId:e,status:i.status,url:r}),{error:`OAuth replica POST HTTP ${i.status}`};let a=await i.json();if(typeof a.maskedValue!=`string`)return j.warn(`OAuth replica POST ok but missing maskedValue`,{providerId:e,url:r}),{error:`OAuth replica POST ok but missing maskedValue`};if(!I(a.maskedValue,t))return j.error(`OAuth mask replica equals the access token; refusing to persist`,{providerId:e}),{error:`mask replica equals the access token`};let o=M(),l=Ke(e,t,a.maskedValue,o);return l.maskedValue&&await N(o),l}async function Ze(e,t){let n=await Qe(e,t);if(n.error!==Ge)return n;let r=M().find(t=>t.providerId===e)?.accessToken;return!r||r===t?n:Qe(e,r)}async function Qe(e,t){let n=qe(e);if(n.length===0)return{error:`no oauth token domains configured`};let r=te();try{return r===`extension-direct`?L({providerId:e,accessToken:t,domains:n},{sendMaskRequest:Je,getAccounts:M,saveAccounts:N}):r===`extension-delegate`?L({providerId:e,accessToken:t,domains:n},{sendMaskRequest:Ye,getAccounts:M,saveAccounts:N}):r===`connect`?{error:`no replica store in connect mode`}:await Xe(e,t,n)}catch(t){let n=t instanceof Error?t.message:String(t);return j.error(`OAuth replica sync failed`,{providerId:e,topology:r,error:n}),{error:n}}}async function $e(e){let t=M().find(t=>t.providerId===e);return t?.accessToken?I(t.maskedValue,t.accessToken)?{maskedValue:t.maskedValue}:Ze(e,t.accessToken):{error:`no access token held`}}function et(e,t){if(e.accessToken)return`scopes`in e?e.scopes:t?.scopes}async function tt(e){let t=M().find(t=>t.providerId===e.providerId),n=M().filter(t=>t.providerId!==e.providerId);n.push({providerId:e.providerId,apiKey:``,accessToken:e.accessToken,refreshToken:e.refreshToken,tokenExpiresAt:e.tokenExpiresAt,userName:e.userName,userAvatar:e.userAvatar,baseUrl:e.baseUrl??t?.baseUrl,scopes:et(e,t)}),await N(n),await Ze(e.providerId,e.accessToken)}function R(e){let t=M().find(t=>t.providerId===e);return t&&(t.accessToken||t.apiKey)||null}function z(e){let t=M().find(t=>t.providerId===e);return t?t.accessToken||t.apiKey||(O(e).optionalApiKey?`local`:null):null}function B(e){return M().find(t=>t.providerId===e)?.baseUrl??null}function nt(e){return M().find(t=>t.providerId===e)?.deployment??null}function rt(e){return M().find(t=>t.providerId===e)?.apiVersion??null}function V(){let e=localStorage.getItem(S)||``,t=e.indexOf(`:`);return t>=0?e.slice(t+1):e}function it(e){let t=e.indexOf(`:`);if(t>0){let n=e.slice(0,t),r=new Set([...i(),...E()]),a=n.includes(`.`);if(r.has(n)||!a){localStorage.setItem(S,e);return}}let n=H();localStorage.setItem(S,`${n}:${e}`)}function at(){return localStorage.getItem(S)||``}function H(){let e=at(),t=e.indexOf(`:`);if(t>0)return e.slice(0,t);let n=M(),r=V();if(r){let e=n.find(e=>D(e.providerId)&&Ee(e.providerId,r));if(e)return e.providerId}let i=n.find(e=>D(e.providerId));return i?i.providerId:n.length>0?n[0].providerId:`anthropic`}function ot(e){let t=V();localStorage.setItem(S,`${e}:${t}`)}function st(){let e=V();localStorage.setItem(S,e)}function ct(){return z(H())}function lt(e){let t=H();P(t,e,B(t)??void 0)}async function ut(){await F(H())}function dt(){return B(H())}function ft(e){let t=H(),n=R(t);n&&P(t,n,e||void 0)}function pt(){let e=H(),t=R(e);t&&P(e,t)}function mt(){let e=M(),t=H(),n=V();return e.map(e=>{let r={providerId:e.providerId,apiKey:e.apiKey};return e.baseUrl&&(r.baseUrl=e.baseUrl),e.providerId===t&&n&&(r.model=n),r})}async function ht(){let e=M();await Promise.allSettled(e.map(e=>F(e.providerId))),localStorage.removeItem(u),localStorage.removeItem(S);for(let e of xe)localStorage.removeItem(e)}function gt(e){return/^(?:gpt[-.]?|o[0-9]|chatgpt)/i.test(e)?`openai`:`anthropic`}function U(e,t,n,r){return{id:t,name:t,provider:e,api:r??`${e}-${gt(t)}`,baseUrl:n??``,contextWindow:2e5,maxTokens:16384,input:[`text`,`image`],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},reasoning:!0}}function W(e,t){return t.isOAuth||e===`azure-ai-foundry`?`anthropic`:e===`bedrock-camp`?`amazon-bedrock`:e}function _t(){let e=new Set;for(let t of M())t.loggedOut||(e.add(t.providerId),e.add(W(t.providerId,O(t.providerId))));return[...e]}function vt(e,t,n){let r=A(e).find(e=>e.id===t);return r?n?{...r,baseUrl:n}:r:null}function yt(e,t,n,r){return n.isOAuth?A(t).find(e=>e.id===r)||{...e,api:`${t}-anthropic`,provider:t}:t===`bedrock-camp`?{...e,api:`bedrock-camp-converse`,provider:`bedrock-camp`}:e}function bt(e,t,n,r,i){let a=vt(e,n,r);if(a)return a;if(t.isOAuth)return U(e,n,r);if(i)throw Error(`Model ${n} is not available from provider ${e}`);return K()}function G(e,t){if(!e)return K();let n=t??H(),r=B(n),i=O(n);if(t!==void 0){let t=vt(n,e,r);if(t)return t}try{let t=W(n,i),a=b(t,e);if(!a?.id)throw Error(`Model ${e} not found`);let o=yt(a,n,i,e);return r?{...o,baseUrl:r}:o}catch(a){return j.debug(`resolveModelById: pi-ai lookup miss, using provider fallback`,{providerId:n,modelId:e,error:a instanceof Error?a.message:String(a)}),bt(n,i,e,r,t!==void 0)}}function xt(e,t){return e.provider===t||e.provider===W(t,O(t))}function K(){let e=H(),t=V(),n=B(e),r=A(e),i=O(e),a=i.defaultModelId?r.find(e=>e.id.toLowerCase().includes(i.defaultModelId.toLowerCase()))?.id:void 0,o=t||a||r[0]?.id||`claude-sonnet-4-6`;try{let t=W(e,i),a=b(t,o);if(!a?.id)throw Error(`Model ${o} not found in ${t} registry`);let s=a;return i.isOAuth?s=r.find(e=>e.id===o)||{...s,api:`${e}-anthropic`,provider:e}:e===`bedrock-camp`&&(s={...s,api:`bedrock-camp-converse`,provider:`bedrock-camp`}),n&&(s={...s,baseUrl:n}),s}catch(t){j.debug(`resolveCurrentModel: pi-ai lookup miss, using provider fallback`,{providerId:e,effectiveModelId:o,error:t instanceof Error?t.message:String(t)});let a=r.find(e=>e.id===o);return a?n?{...a,baseUrl:n}:a:i.isOAuth?U(e,o,n):b(`anthropic`,`claude-sonnet-4-0`)}}function St(e){let t=e.toLowerCase();if(!t)return null;let n=null;try{n=H()}catch{}if(n!==null){let e=q(t,[n]);if(e!==null)return e}return q(t,M().map(e=>e.providerId))}function q(e,t){let n=null,r=-1;for(let i of t)for(let t of A(i)){let i=t.id.toLowerCase(),a=(t.name??``).toLowerCase();if(!i.includes(e)&&!a.includes(e))continue;let o=t.contextWindow??0;(o>r||o===r&&kt(t.id,n??``)>0)&&(r=o,n=t.id)}return n}function J(){let e=[];try{for(let t of M())e.includes(t.providerId)||e.push(t.providerId)}catch{}try{let t=H();e.includes(t)||e.push(t)}catch{}return e}function Ct(e){let t=e.indexOf(`:`);if(t<=0||t===e.length-1)return null;let n=e.slice(0,t),r=e.slice(t+1),i=J().includes(n);if(i)return{providerId:n,modelId:r,configured:i};let a=!1;try{a=E().includes(n)}catch{}return a?{providerId:n,modelId:r,configured:!1}:null}function Y(e,t,n=!0){let r=[e],i=n?q(e.toLowerCase(),[t]):null;i!==null&&i!==e&&r.push(i);let a=[];try{a=A(t)}catch{}for(let n of r)if(!(a.length>0&&!a.some(e=>e.id===n)))try{if(G(n,t).id===n)return{modelId:n,providerId:t}}catch(r){j.debug(`selectModelFromProvider: candidate did not resolve`,{input:e,candidate:n,providerId:t,error:r instanceof Error?r.message:String(r)})}return null}function wt(e){return e.map(e=>`${e.providerId}:${e.modelId}`).join(`, `)}function X(e){if(!e)return{ok:!1,error:`unknown model: (empty)`};let t=Ct(e);if(t)return Et(e,t);let n=null;try{n=H()}catch{}if(n!==null){let t=Y(e,n);if(t)return $(t)}return Dt(e,n)}function Z(){try{return H()}catch{return null}}function Tt(e){let t=Z();return t===null||he(ve(),t,e.providerId,e.modelId)}function Q(e){let t=Z()??`<none>`;return{ok:!1,error:`model not allowed: ${`${e.providerId}:${e.modelId}`} is blocked by ${_} while "${t}" is selected — ${ye(t,e.providerId,e.modelId)}`}}function $(e){return Tt(e)?{ok:!0,selection:e}:Q(e)}function Et(e,t){if(!t.configured){let n=J();return{ok:!1,error:`unknown model: ${e} (provider "${t.providerId}" is not configured${n.length>0?`; configured: ${n.join(`, `)}`:``})`}}let n=Y(t.modelId,t.providerId);return n?$(n):{ok:!1,error:`unknown model: ${e} (provider "${t.providerId}" does not offer "${t.modelId}")`}}function Dt(e,t){let n=J().filter(e=>e!==t);for(let t of[`exact`,`shorthand`]){let r=[];for(let i of n){let n=t===`exact`?e:q(e.toLowerCase(),[i]);if(n===null)continue;let a=Y(n,i,!1);a&&r.push(a)}let i=r.filter(Tt);if(i.length===0&&r.length>0)return Q(r[0]);if(i.length===1)return{ok:!0,selection:i[0]};if(i.length>1)return{ok:!1,error:`ambiguous model: ${e} matches ${wt(i)} — qualify it as provider:model`}}return{ok:!1,error:`unknown model: ${e}`}}function Ot(e){let t=X(e);return t.ok?t.selection.modelId:null}function kt(e,t){let n=e.match(/\d+/g)?.map(Number)??[],r=t.match(/\d+/g)?.map(Number)??[],i=Math.max(n.length,r.length);for(let e=0;e<i;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t}return 0}export{m as C,g as S,tt as _,z as a,fe as b,nt as c,V as d,H as f,X as g,G as h,ct as i,Oe as l,K as m,$e as n,rt as o,xt as p,M as r,B as s,be as t,A as u,_ as v,_e as x,v as y};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/oauth-service-GpUOM3Aw.js","assets/preload-helper-Czpn1I53.js","assets/proxied-fetch-4VBgrEIu.js","assets/rolldown-runtime-Dd_uD5pT.js","assets/base64-ELzoYfwP.js","assets/proxy-error-BSFYY7jj.js","assets/api-endpoint-DuEQRZ4g.js","assets/runtime-env-Dlaokqg1.js","assets/panel-rpc-accessor-B4BfPLSo.js","assets/permissions-surface-registry-CilCRwhh.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{a as e,o as t}from"./core-Cx9N3lmn.js";import{a as n}from"./diagnostics-Cag7MsZI.js";import{t as r}from"./preload-helper-Czpn1I53.js";import{a as i}from"./compat-BAGLwgqY.js";import{a,r as o,s,t as c}from"./legacy-api-aliases-BjgG1CsY.js";import{O as l,W as u,Z as d,u as f,y as p}from"./account-store-8pdjPGXe.js";import{t as m}from"./panel-rpc-accessor-B4BfPLSo.js";import{t as h}from"./providers-DGOyFpbk.js";import{i as g,n as _,r as ee}from"./claude-model-version-DZmbk9E2.js";import"./main-DE492KKE.js";import{n as v,t as te}from"./silent-renew-backoff-OCJFe0Op.js";import{i as ne}from"./provider-budget-LCzMPlKv.js";import{getOAuthPageOrigin as re}from"./oauth-service-GpUOM3Aw.js";import{n as y}from"./pi-transcript-context-miZCMig3.js";import{n as b}from"./temperature-support-DhoZT6gU.js";import{t as x}from"./llm-session-id-bZQs6gBN.js";var ie={proxyEndpoint:`https://adobe-llm-proxy.paolo-moz.workers.dev`,redirectUri:`https://www.sliccy.ai/auth/callback`,extensionRedirectUri:`https://akjjllgokmbgpbdbmafpiefnhidlmbgf.chromiumapp.org/adobe`};function ae(e,t){return _(e,t)}function S(e,t,n){return e!==`xhigh`||!t?e:g(t,n)?`xhigh`:ee(t,n)?`max`:`high`}function oe(e,t){let n=e?t?.thinkingLevelMap?.[e]:void 0;return S((()=>{if(typeof n==`string`)return n;switch(e){case`minimal`:case`low`:return`low`;case`medium`:return`medium`;case`xhigh`:return`xhigh`;default:return`high`}})(),t?.id,t?.name)}function se(e,t){return async(n,r)=>{let i=t?await t(n,r)??n:n,a=i.thinking;return a&&a.type===`enabled`&&(i.thinking={type:`adaptive`,...a.display===void 0?{}:{display:a.display}},i.output_config={...i.output_config??{},effort:e}),i}}function ce(e,t){if(!ae(e.id,e.name))return t;let n=t,r=S(n.effort??oe(n.reasoning,e),e.id,e.name);return{...t,onPayload:se(r,n.onPayload)}}function le(e,t){let n={id:e.id,name:e.name??e.id},r=t?.api??e.api,i=t?.context_window??e.context_window,a=t?.max_tokens??e.max_tokens,o=t?.reasoning??e.reasoning,s=t?.input??e.input;r&&(n.api=r),i!==void 0&&(n.context_window=i),a!==void 0&&(n.max_tokens=a),o!==void 0&&(n.reasoning=o),s&&(n.input=s);let c=t?.cost??e.cost;return c&&(n.cost=c),/haiku/i.test(e.id)&&(n.compat={supportsEagerToolInputStreaming:!1}),/sonnet-5\b/i.test(e.id)&&!n.thinkingLevelMap&&(n.thinkingLevelMap={xhigh:`xhigh`}),n}var ue=8e3;async function de(e,t,n,r={}){let i=typeof AbortController==`function`?new AbortController:null,a=i?setTimeout(()=>i.abort(),r.timeoutMs??ue):null;try{let a=await n(`${e.replace(/\/$/,``)}/v1/usage`,{headers:{...r.headers,Authorization:`Bearer ${t}`},...i?{signal:i.signal}:{}});if(a.status===404||a.status===501)return null;if(!a.ok)throw Error(`Adobe /v1/usage returned ${a.status}`);return ne(await a.json())}finally{a&&clearTimeout(a)}}var fe=6e4,pe=3e5,me=18e5,he=class{resolve;providerId;now;#e=null;#t=null;#n=null;#r=null;constructor(e,t,n=Date.now){this.resolve=e,this.providerId=t,this.now=n}#i(e){return e===`ok`?fe:e===`unsupported`?me:pe}isStale(){let e=this.#e;return!e||this.#t!==this.providerId()||this.now()-e.at>=this.#i(e.outcome)}snapshot(){return this.#t===this.providerId()?this.#e?.window??null:null}async refresh(e={}){if(!e.force&&!this.isStale())return this.snapshot();let t=this.providerId();return this.#n!==null&&this.#r===t?this.#n:(this.#n=this.resolve().then(e=>{let n=e?{...e,at:this.now()}:null;return this.#a(t,n?`ok`:`unsupported`,n),n}).catch(()=>{let e=this.snapshot();return this.#a(t,`failed`,e),e}).finally(()=>{this.#r===t&&(this.#n=null,this.#r=null)}),this.#r=t,this.#n)}#a(e,t,n){e===this.providerId()&&(this.#t=e,this.#e={outcome:t,window:n,at:this.now()})}clear(){this.#e=null,this.#t=null}};async function ge(){let e=l();if(!e)return null;let t=h(e);if(!t?.getBudgetUsage)return null;let n=await t.getBudgetUsage();return n?{...n,providerId:e}:null}function _e(){try{return l()}catch{return``}}var ve=new he(ge,_e);function C(){ve.clear()}var w=Object.assign({"/packages/webapp/providers/adobe-config.json":ie})[`/packages/webapp/providers/adobe-config.json`]??{clientId:``,proxyEndpoint:``,scopes:`openid,profile,email`};function T(){let e=p(`adobe`);if(e)return e.replace(/\/$/,``);if(w.proxyEndpoint)return w.proxyEndpoint.replace(/\/$/,``);throw Error(`Adobe proxy endpoint not configured — set it in Settings or adobe-config.json`)}var E=new Map,D=new Map,O=`slicc-adobe-models`;function k(e){try{localStorage.setItem(O,JSON.stringify(e))}catch{}}async function A(e){try{let t=await fetch(`${e}/v1/config`,{headers:{[K]:`6.233.0`}});return t.ok?await t.json():(console.warn(`[adobe] Proxy /v1/config returned ${t.status}`),null)}catch(e){return console.warn(`[adobe] Failed to fetch proxy config:`,e instanceof Error?e.message:String(e)),null}}async function j(e){let t=E.get(e);if(t)return t;let n=await A(e);return n||=(await new Promise(e=>setTimeout(e,600)),await A(e)),n?(E.set(e,n),n):{}}function M(e){let t=e.clientId||w.clientId;if(!t)throw Error(`Could not determine IMS client ID — proxy /v1/config did not return one and adobe-config.json is empty`);return t}function N(e){return e.scopes||w.scopes}function P(e){return e.imsEnvironment||w.imsEnvironment||`prod`}var F={prod:`https://ims-na1.adobelogin.com`,stg1:`https://ims-na1-stg1.adobelogin.com`};function I(e){return F[e??w.imsEnvironment??`prod`]??F.prod}var ye=1e4,be=5e3;async function L(){let e;try{e=T()}catch{return{}}return E.get(e)||new Promise(t=>{let n=setTimeout(()=>t({}),be),r=e=>{clearTimeout(n),t(e)};j(e).then(r,()=>r({}))})}function R(e){try{let t=e.split(`.`)[1];if(!t)return;let n=t.replace(/-/g,`+`).replace(/_/g,`/`),r=atob(n+`=`.repeat((4-n.length%4)%4)),i=JSON.parse(r);return typeof i.client_id==`string`?i.client_id:void 0}catch{return}}var z=typeof chrome<`u`&&!!chrome?.runtime?.id;function B(){return f().find(e=>e.providerId===`adobe`)}var xe=[`/ims/profile/v1`,`/ims/userinfo/v2`];async function Se(e,t){try{let n=await fetch(e,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok){console.warn(`[adobe] Profile fetch ${e} returned ${n.status}`);return}let r=await n.json(),i=r.displayName||r.name||r.email;return i?{name:i,avatar:r.picture||r.avatar_url}:void 0}catch(t){console.warn(`[adobe] Profile fetch ${e} failed:`,t instanceof Error?t.message:String(t));return}}async function Ce(e,t){for(let n of xe){let r=await Se(`${I(t)}${n}`,e);if(r)return r}return console.warn(`[adobe] No IMS profile endpoint named the user; account will have no display name`),{}}async function we(){let e=B(),t=e?.accessToken;if(!t)return{status:`unknown`,detail:`no stored token`};let n=await L(),r=R(t)||n.clientId||w.clientId||``;if(!r)return{status:`unknown`,detail:`no IMS client ID available`};let i=I(P(n));try{let n=await fetch(`${i}/ims/validate_token/v1`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({client_id:r,token:t,type:`access_token`}),signal:AbortSignal.timeout(ye)});if(!n.ok)return{status:`unknown`,detail:`HTTP ${n.status}${n.statusText?` ${n.statusText}`:``}`};let a=await n.json();return a.valid===!0?{status:`accepted`,userName:e?.userName}:a.valid===!1?{status:`rejected`,detail:`IMS reported the token invalid (${typeof a.reason==`string`?a.reason:`no reason given`})`}:{status:`unknown`,detail:"IMS answered 200 without a boolean `valid` verdict"}}catch(e){return{status:`unknown`,detail:e instanceof Error?e.message:String(e)}}}function V(e){let t=e.indexOf(`#`);if(t<0)return null;let n=new URLSearchParams(e.slice(t+1)),r=n.get(`access_token`);return r?{accessToken:r,expiresIn:parseInt(n.get(`expires_in`)??`86400`,10),scope:n.get(`scope`)??void 0}:null}var H={id:`adobe`,name:`Adobe`,description:`Claude via Adobe — login with your Adobe ID`,requiresApiKey:!1,requiresBaseUrl:!w.proxyEndpoint,baseUrlPlaceholder:`https://your-proxy.example.com`,baseUrlDescription:`Anthropic-compatible proxy endpoint`,isOAuth:!0,defaultModelId:`sonnet`,oauthTokenDomains:[`ims-na1.adobelogin.com`,`ims-na1-stg1.adobelogin.com`,`*.adobelogin.com`,`*.adobe.io`,`firefall.adobe.io`,`admin.hlx.page`,`admin.hlx.live`,`admin.aem.page`,`admin.aem.live`,`api.aem.live`],getBudgetUsage:Ee,getModelIds:()=>{let e=e=>le(e,D.get(e.id));for(let t of Q.values())if(t.length){let n=t.map(t=>e({id:t.id,name:t.name??t.id,reasoning:t.reasoning,input:t.input,cost:t.cost}));return k(n),n}for(let t of E.values())if(t.models?.length)return t.models.map(t=>e(t));try{let e=localStorage.getItem(O);if(e){let t=JSON.parse(e);if(t.length)return t}}catch{}return[{id:`claude-sonnet-4-6`,name:`Claude Sonnet 4.6`}]},onOAuthLogin:async(e,t,n)=>{let r=T(),i=await j(r),a=M(i),o=N(i),s=P(i),c=z?null:await re(),l=z?null:v({pageHref:c.href,pageOrigin:c.origin,configuredRedirectUri:w.redirectUri},()=>crypto.randomUUID()),d=z?w.extensionRedirectUri??`https://${chrome.runtime.id}.chromiumapp.org/`:l.redirectUri,f=l?.oauthState,p=l?.expectedNonce??null,m=new URLSearchParams({client_id:a,scope:o,response_type:`token`,redirect_uri:d});f&&m.set(`state`,f),n?.forceReauth&&m.set(`prompt`,`login`);let h=await e(`${I(s)}/ims/authorize/v2?${m}`);if(!h)return;if(p&&h)try{if(new URL(h).searchParams.get(`nonce`)!==p){console.error(`[adobe] OAuth nonce mismatch — possible CSRF`);return}}catch(e){console.warn(`[adobe] Nonce check skipped (URL parse failed):`,e instanceof Error?e.message:String(e))}let g=V(h);if(!g){console.error(`[adobe] Could not extract token from redirect URL`);return}let _=await Ce(g.accessToken,s);await u({providerId:`adobe`,accessToken:g.accessToken,tokenExpiresAt:Date.now()+g.expiresIn*1e3,userName:_.name,userAvatar:_.avatar,scopes:g.scope,baseUrl:w.proxyEndpoint?void 0:r}),C(),await $().catch(e=>console.warn(`[adobe] Failed to fetch models after login:`,e instanceof Error?e.message:String(e))),t()},onOAuthLogout:async()=>{let e=B();if(e?.accessToken)try{let t=await L(),n=R(e.accessToken)||t.clientId||w.clientId,r=P(t);if(n){let t=await fetch(`${I(r)}/ims/revoke`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({token:e.accessToken,token_type_hint:`access_token`,client_id:n})});t.ok||console.warn(`[adobe] Token revocation returned ${t.status}, token may still be valid server-side`)}}catch(e){console.warn(`[adobe] Failed to revoke token:`,e instanceof Error?e.message:String(e))}await u({providerId:`adobe`,accessToken:``}),C()},onSilentRenew:async()=>B()?.accessToken?De():null,onValidateToken:we,refreshModels:async e=>{await $(e);let t=H.getModelIds?.();t?.length&&k(t)}},U=null,Te=te();async function W(){let e=B();if(!e?.accessToken)throw Error(`Not logged in to Adobe — please log in first`);if((e.tokenExpiresAt??0)-Date.now()>6e4)return e.accessToken;console.log(`[adobe] Token expired or expiring soon, attempting silent renewal...`);let t=await Te.run(()=>De());if(t)return t;let n=B();if((n?.tokenExpiresAt??0)-Date.now()>0&&n?.accessToken)return n.accessToken;throw Error(`Adobe session expired — please log in again`)}async function Ee(){let e;try{e=T()}catch{return null}let t=B();if(!t?.accessToken||G())throw Error(`Adobe budget: not signed in`);return de(e,t.accessToken,fetch,{headers:{"X-Session-Id":x(Ne)}})}function G(){let e=B();return!e?.tokenExpiresAt||Date.now()>e.tokenExpiresAt-6e4}async function De(){if(typeof window>`u`){let e=m();if(!e)return null;try{let{accessToken:t}=await e.call(`silent-renew`,{providerId:`adobe`},{timeoutMs:13e4});return t}catch(e){return console.warn(`[adobe] worker→page silent-renew bridge failed:`,e instanceof Error?e.message:String(e)),null}}return U===null&&(U=je().finally(()=>{U=null})),U}function Oe(e,t){let n=M(t),r=N(t),i=P(t),a=z?null:v({pageHref:window.location.href,pageOrigin:window.location.origin,configuredRedirectUri:w.redirectUri},()=>crypto.randomUUID()),o=z?w.extensionRedirectUri??`https://${chrome.runtime.id}.chromiumapp.org/`:a.redirectUri,s=a?.oauthState,c=a?.expectedNonce??null,l=new URLSearchParams({client_id:n,scope:r,response_type:`token`,redirect_uri:o,prompt:`none`});return s&&l.set(`state`,s),{authorizeUrl:`${I(i)}/ims/authorize/v2?${l}`,expectedNonce:c,proxyEndpoint:e}}function ke(e,t){if(!t)return!0;try{if(new URL(e).searchParams.get(`nonce`)!==t)return console.error(`[adobe] OAuth nonce mismatch — possible CSRF`),!1}catch(e){console.warn(`[adobe] Nonce check skipped (URL parse failed):`,e instanceof Error?e.message:String(e))}return!0}async function Ae(e,t){let n=B();await u({providerId:`adobe`,accessToken:e.accessToken,tokenExpiresAt:Date.now()+e.expiresIn*1e3,userName:n?.userName,userAvatar:n?.userAvatar,scopes:e.scope,baseUrl:w.proxyEndpoint?void 0:t})}async function je(){try{let e=T(),{authorizeUrl:t,expectedNonce:n}=Oe(e,await j(e)),{createOAuthLauncher:i}=await r(async()=>{let{createOAuthLauncher:e}=await import(`./oauth-service-GpUOM3Aw.js`);return{createOAuthLauncher:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])),a=await i()(t,{interactive:!1});if(!a||!ke(a,n))return null;let o=V(a);return o?(await Ae(o,e),console.log(`[adobe] Token renewed silently`),await $().catch(e=>console.warn(`[adobe] Failed to refresh models after silent renewal:`,e instanceof Error?e.message:String(e))),o.accessToken):null}catch(e){return console.warn(`[adobe] Silent renewal error:`,e instanceof Error?e.message:String(e)),null}}var K=`X-Slicc-Version`;function q(e){let t={},n=K.toLowerCase();if(e.headers)for(let[r,i]of Object.entries(e.headers))r.toLowerCase()!==n&&(t[r]=i);return t[K]=`6.233.0`,{...e,headers:t}}var Me=`adobe-provider-fallback`,Ne=`adobe-usage-probe`,J=new Set;function Y(e,t){if(e.headers){for(let[t,n]of Object.entries(e.headers))if(t.toLowerCase()===`x-session-id`&&n!=null)return e}return J.has(t)||(J.add(t),console.warn(`[adobe] Missing X-Session-Id from ${t} — using daily fallback. Attach an X-Session-Id header at the call site (see scoop-context.ts streamWithSessionId or docs/pitfalls.md).`)),{...e,headers:{...e.headers??{},"X-Session-Id":x(Me)}}}function Pe(){J.clear()}function Fe(e,t){return{type:`error`,reason:`error`,error:{role:`assistant`,content:[],api:`adobe-anthropic`,provider:`adobe`,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:`error`,errorMessage:t instanceof Error?t.message:String(t),timestamp:Date.now()}}}function X(e){console.error(`[adobe] Stream error:`,e instanceof Error?e.message:String(e))}var Ie=(e,t,r={})=>{let i=n();return Le(i,e,t,r).catch(X),i};async function Le(e,t,n,r){try{let i=await W();if(String(t.api).includes(`openai`)){let a={...t,baseUrl:`${T()}/v1`,api:`openai-completions`,compat:{...t.compat,supportsStore:!1,supportsDeveloperRole:!1}},s=o(a,y(n),q(Y({...r,apiKey:i},`streamAdobe[openai]`)));for await(let t of s)e.push(t)}else{let a={...t,baseUrl:T(),api:`anthropic-messages`},o=c(a,y(n),q(Y(ce(t,b(t.id,t.name,{...r,apiKey:i})),`streamAdobe[anthropic]`)));for await(let t of o)e.push(t)}e.end()}catch(n){X(n),e.push(Fe(t,n)),e.end()}}var Z=(e,t,r)=>{let i=n();return Re(i,e,t,r).catch(X),i};async function Re(e,t,n,r){try{let i=await W();if(String(t.api).includes(`openai`)){let a={...t,baseUrl:`${T()}/v1`,api:`openai-completions`,compat:{...t.compat,supportsStore:!1,supportsDeveloperRole:!1}},o=s(a,y(n),q(Y({...r,apiKey:i},`streamSimpleAdobe[openai]`)));for await(let t of o)e.push(t)}else{let o={...t,baseUrl:T(),api:`anthropic-messages`},s=a(o,y(n),q(Y(ce(t,b(t.id,t.name,{...r,apiKey:i})),`streamSimpleAdobe[anthropic]`)));for await(let t of s)e.push(t)}e.end()}catch(n){X(n),e.push(Fe(t,n)),e.end()}}function ze(e){let t={id:e.id,name:e.name};return e.api!==void 0&&(t.api=e.api),e.context_window!==void 0&&(t.context_window=e.context_window),e.max_tokens!==void 0&&(t.max_tokens=e.max_tokens),e.reasoning!==void 0&&(t.reasoning=e.reasoning),e.input!==void 0&&(t.input=e.input),t}function Be(){let n=new Map;for(let r of t())try{let t=e(r);for(let e of t)n.set(e.id,e)}catch{}return n}function Ve(e,t,n){let r=`adobe-${e.api===`openai`?`openai`:`anthropic`}`,i=n.get(e.id);if(i)return{...i,provider:`adobe`,api:r};let a=d(e.id,n);return{id:e.id,name:e.name??e.id,provider:`adobe`,api:r,baseUrl:t,contextWindow:2e5,maxTokens:16384,input:[`text`,`image`],cost:a,inputCost:a.input,outputCost:a.output,cacheReadCost:a.cacheRead,cacheWriteCost:a.cacheWrite,reasoning:!0}}function He(e,t){for(let t of e)D.set(t.id,ze(t));let n=Be();return e.map(e=>Ve(e,t,n))}async function Ue(e){try{let t=e??await W(),n=T(),r=await fetch(`${n}/v1/models`,{headers:{Authorization:`Bearer ${t}`,[K]:`6.233.0`}});if(!r.ok)console.warn(`[adobe] Proxy /v1/models returned ${r.status}, falling back to Anthropic models`);else{let e=await r.json();if(e.data?.length)return He(e.data,n)}}catch(e){console.warn(`[adobe] Failed to fetch proxy models:`,e instanceof Error?e.message:String(e))}return null}var Q=new Map;function We(){return e(`anthropic`).map(e=>({...e,provider:`adobe`,api:`adobe-anthropic`}))}async function $(e){let t=T(),n=Q.get(t);if(n)return n;let r=await Ue(e);return r?(Q.set(t,r),r):We()}function Ge(){i({api:`adobe-anthropic`,stream:Ie,streamSimple:Z}),i({api:`adobe-openai`,stream:Ie,streamSimple:Z})}export{Pe as __resetAdobeSessionIdWarningCacheForTests,H as config,V as extractTokenFromUrl,$ as getAdobeModels,W as getValidAccessToken,G as isTokenExpired,Ge as register};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{S as e,_ as t,r as n,s as r}from"./account-store-CYgyHiaa.js";import{t as i}from"./panel-rpc-accessor-B4BfPLSo.js";import{a}from"./diagnostics-Cag7MsZI.js";import{a as o}from"./compat-nGhSz-U1.js";import{a as s,o as c}from"./core-C1m4D34S.js";import{a as l,r as u,s as d,t as f}from"./legacy-api-aliases--xyLjPgC.js";import{a as p,i as m,r as h}from"./claude-model-version-ceOteQ2f.js";import{r as g}from"./provider-budget-DbHWq3j6.js";import{n as _}from"./llm-session-id-BZyXP_j2.js";import{n as v}from"./pi-transcript-context-4pjVPiVC.js";import{m as y}from"./kernel-worker-Dv0441oU.js";import{n as b,t as ee}from"./silent-renew-backoff-Dmz3DJHb.js";import{getOAuthPageOrigin as te}from"./oauth-service-MWzqRq2q.js";import{n as x}from"./temperature-support-0nztUM0u.js";import"./provider-settings-nWfCs5Ea.js";var ne={proxyEndpoint:`https://adobe-llm-proxy.paolo-moz.workers.dev`,redirectUri:`https://www.sliccy.ai/auth/callback`,extensionRedirectUri:`https://akjjllgokmbgpbdbmafpiefnhidlmbgf.chromiumapp.org/adobe`};function re(e,t){return h(e,t)}function S(e,t,n){return e!==`xhigh`||!t?e:p(t,n)?`xhigh`:m(t,n)?`max`:`high`}function ie(e,t){let n=e?t?.thinkingLevelMap?.[e]:void 0;return S((()=>{if(typeof n==`string`)return n;switch(e){case`minimal`:case`low`:return`low`;case`medium`:return`medium`;case`xhigh`:return`xhigh`;default:return`high`}})(),t?.id,t?.name)}function ae(e,t){return async(n,r)=>{let i=t?await t(n,r)??n:n,a=i.thinking;return a&&a.type===`enabled`&&(i.thinking={type:`adaptive`,...a.display===void 0?{}:{display:a.display}},i.output_config={...i.output_config??{},effort:e}),i}}function C(e,t){if(!re(e.id,e.name))return t;let n=t,r=S(n.effort??ie(n.reasoning,e),e.id,e.name);return{...t,onPayload:ae(r,n.onPayload)}}function oe(e,t){let n={id:e.id,name:e.name??e.id},r=t?.api??e.api,i=t?.context_window??e.context_window,a=t?.max_tokens??e.max_tokens,o=t?.reasoning??e.reasoning,s=t?.input??e.input;r&&(n.api=r),i!==void 0&&(n.context_window=i),a!==void 0&&(n.max_tokens=a),o!==void 0&&(n.reasoning=o),s&&(n.input=s);let c=t?.cost??e.cost;return c&&(n.cost=c),/haiku/i.test(e.id)&&(n.compat={supportsEagerToolInputStreaming:!1}),/sonnet-5\b/i.test(e.id)&&!n.thinkingLevelMap&&(n.thinkingLevelMap={xhigh:`xhigh`}),n}async function se(e,t,n,r={}){let i=typeof AbortController==`function`?new AbortController:null,a=i?setTimeout(()=>i.abort(),r.timeoutMs??8e3):null;try{let a=await n(`${e.replace(/\/$/,``)}/v1/usage`,{headers:{...r.headers,Authorization:`Bearer ${t}`},...i?{signal:i.signal}:{}});if(a.status===404||a.status===501)return null;if(!a.ok)throw Error(`Adobe /v1/usage returned ${a.status}`);return g(await a.json())}finally{a&&clearTimeout(a)}}const w=Object.assign({"/packages/webapp/providers/adobe-config.json":ne})[`/packages/webapp/providers/adobe-config.json`]??{clientId:``,proxyEndpoint:``,scopes:`openid,profile,email`};function T(){let e=r(`adobe`);if(e)return e.replace(/\/$/,``);if(w.proxyEndpoint)return w.proxyEndpoint.replace(/\/$/,``);throw Error(`Adobe proxy endpoint not configured — set it in Settings or adobe-config.json`)}const E=new Map,ce=new Map,le=`slicc-adobe-models`;function ue(e){try{localStorage.setItem(le,JSON.stringify(e))}catch{}}async function D(e){try{let t=await fetch(`${e}/v1/config`,{headers:{[W]:`6.233.0`}});return t.ok?await t.json():(console.warn(`[adobe] Proxy /v1/config returned ${t.status}`),null)}catch(e){return console.warn(`[adobe] Failed to fetch proxy config:`,e instanceof Error?e.message:String(e)),null}}async function O(e){let t=E.get(e);if(t)return t;let n=await D(e);return n||=(await new Promise(e=>setTimeout(e,600)),await D(e)),n?(E.set(e,n),n):{}}function k(e){let t=e.clientId||w.clientId;if(!t)throw Error(`Could not determine IMS client ID — proxy /v1/config did not return one and adobe-config.json is empty`);return t}function A(e){return e.scopes||w.scopes}function j(e){return e.imsEnvironment||w.imsEnvironment||`prod`}const M={prod:`https://ims-na1.adobelogin.com`,stg1:`https://ims-na1-stg1.adobelogin.com`};function N(e){return M[e??w.imsEnvironment??`prod`]??M.prod}async function P(){let e;try{e=T()}catch{return{}}return E.get(e)||new Promise(t=>{let n=setTimeout(()=>t({}),5e3),r=e=>{clearTimeout(n),t(e)};O(e).then(r,()=>r({}))})}function F(e){try{let t=e.split(`.`)[1];if(!t)return;let n=t.replace(/-/g,`+`).replace(/_/g,`/`),r=atob(n+`=`.repeat((4-n.length%4)%4)),i=JSON.parse(r);return typeof i.client_id==`string`?i.client_id:void 0}catch{return}}const I=typeof chrome<`u`&&!!chrome?.runtime?.id;function L(){return n().find(e=>e.providerId===`adobe`)}const de=[`/ims/profile/v1`,`/ims/userinfo/v2`];async function fe(e,t){try{let n=await fetch(e,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok){console.warn(`[adobe] Profile fetch ${e} returned ${n.status}`);return}let r=await n.json(),i=r.displayName||r.name||r.email;return i?{name:i,avatar:r.picture||r.avatar_url}:void 0}catch(t){console.warn(`[adobe] Profile fetch ${e} failed:`,t instanceof Error?t.message:String(t));return}}async function pe(e,t){for(let n of de){let r=await fe(`${N(t)}${n}`,e);if(r)return r}return console.warn(`[adobe] No IMS profile endpoint named the user; account will have no display name`),{}}async function me(){let e=L(),t=e?.accessToken;if(!t)return{status:`unknown`,detail:`no stored token`};let n=await P(),r=F(t)||n.clientId||w.clientId||``;if(!r)return{status:`unknown`,detail:`no IMS client ID available`};let i=N(j(n));try{let n=await fetch(`${i}/ims/validate_token/v1`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({client_id:r,token:t,type:`access_token`}),signal:AbortSignal.timeout(1e4)});if(!n.ok)return{status:`unknown`,detail:`HTTP ${n.status}${n.statusText?` ${n.statusText}`:``}`};let a=await n.json();return a.valid===!0?{status:`accepted`,userName:e?.userName}:a.valid===!1?{status:`rejected`,detail:`IMS reported the token invalid (${typeof a.reason==`string`?a.reason:`no reason given`})`}:{status:`unknown`,detail:"IMS answered 200 without a boolean `valid` verdict"}}catch(e){return{status:`unknown`,detail:e instanceof Error?e.message:String(e)}}}function R(e){let t=e.indexOf(`#`);if(t<0)return null;let n=new URLSearchParams(e.slice(t+1)),r=n.get(`access_token`);return r?{accessToken:r,expiresIn:parseInt(n.get(`expires_in`)??`86400`,10),scope:n.get(`scope`)??void 0}:null}const z={id:`adobe`,name:`Adobe`,description:`Claude via Adobe — login with your Adobe ID`,requiresApiKey:!1,requiresBaseUrl:!w.proxyEndpoint,baseUrlPlaceholder:`https://your-proxy.example.com`,baseUrlDescription:`Anthropic-compatible proxy endpoint`,isOAuth:!0,defaultModelId:`sonnet`,oauthTokenDomains:[`ims-na1.adobelogin.com`,`ims-na1-stg1.adobelogin.com`,`*.adobelogin.com`,`*.adobe.io`,`firefall.adobe.io`,`admin.hlx.page`,`admin.hlx.live`,`admin.aem.page`,`admin.aem.live`,`api.aem.live`],getBudgetUsage:ge,getModelIds:()=>{let e=e=>oe(e,ce.get(e.id));for(let t of Q.values())if(t.length){let n=t.map(t=>e({id:t.id,name:t.name??t.id,reasoning:t.reasoning,input:t.input,cost:t.cost}));return ue(n),n}for(let t of E.values())if(t.models?.length)return t.models.map(t=>e(t));try{let e=localStorage.getItem(le);if(e){let t=JSON.parse(e);if(t.length)return t}}catch{}return[{id:`claude-sonnet-4-6`,name:`Claude Sonnet 4.6`}]},onOAuthLogin:async(e,n,r)=>{let i=T(),a=await O(i),o=k(a),s=A(a),c=j(a),l=I?null:await te(),u=I?null:b({pageHref:l.href,pageOrigin:l.origin,configuredRedirectUri:w.redirectUri},()=>crypto.randomUUID()),d=I?w.extensionRedirectUri??`https://${chrome.runtime.id}.chromiumapp.org/`:u.redirectUri,f=u?.oauthState,p=u?.expectedNonce??null,m=new URLSearchParams({client_id:o,scope:s,response_type:`token`,redirect_uri:d});f&&m.set(`state`,f),r?.forceReauth&&m.set(`prompt`,`login`);let h=await e(`${N(c)}/ims/authorize/v2?${m}`);if(!h)return;if(p&&h)try{if(new URL(h).searchParams.get(`nonce`)!==p){console.error(`[adobe] OAuth nonce mismatch — possible CSRF`);return}}catch(e){console.warn(`[adobe] Nonce check skipped (URL parse failed):`,e instanceof Error?e.message:String(e))}let g=R(h);if(!g){console.error(`[adobe] Could not extract token from redirect URL`);return}let _=await pe(g.accessToken,c);await t({providerId:`adobe`,accessToken:g.accessToken,tokenExpiresAt:Date.now()+g.expiresIn*1e3,userName:_.name,userAvatar:_.avatar,scopes:g.scope,baseUrl:w.proxyEndpoint?void 0:i}),y(),await $().catch(e=>console.warn(`[adobe] Failed to fetch models after login:`,e instanceof Error?e.message:String(e))),n()},onOAuthLogout:async()=>{let e=L();if(e?.accessToken)try{let t=await P(),n=F(e.accessToken)||t.clientId||w.clientId,r=j(t);if(n){let t=await fetch(`${N(r)}/ims/revoke`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({token:e.accessToken,token_type_hint:`access_token`,client_id:n})});t.ok||console.warn(`[adobe] Token revocation returned ${t.status}, token may still be valid server-side`)}}catch(e){console.warn(`[adobe] Failed to revoke token:`,e instanceof Error?e.message:String(e))}await t({providerId:`adobe`,accessToken:``}),y()},onSilentRenew:async()=>L()?.accessToken?U():null,onValidateToken:me,refreshModels:async e=>{await $(e);let t=z.getModelIds?.();t?.length&&ue(t)}};let B=null;const he=ee();async function V(){let e=L();if(!e?.accessToken)throw Error(`Not logged in to Adobe — please log in first`);if((e.tokenExpiresAt??0)-Date.now()>6e4)return e.accessToken;console.log(`[adobe] Token expired or expiring soon, attempting silent renewal...`);let t=await he.run(()=>U());if(t)return t;let n=L();if((n?.tokenExpiresAt??0)-Date.now()>0&&n?.accessToken)return n.accessToken;throw Error(`Adobe session expired — please log in again`)}async function ge(){let e;try{e=T()}catch{return null}let t=L();if(!t?.accessToken||H())throw Error(`Adobe budget: not signed in`);return se(e,t.accessToken,fetch,{headers:{"X-Session-Id":_(xe)}})}function H(){let e=L();return!e?.tokenExpiresAt||Date.now()>e.tokenExpiresAt-6e4}async function U(){if(typeof window>`u`){let e=i();if(!e)return null;try{let{accessToken:t}=await e.call(`silent-renew`,{providerId:`adobe`},{timeoutMs:13e4});return t}catch(e){return console.warn(`[adobe] worker→page silent-renew bridge failed:`,e instanceof Error?e.message:String(e)),null}}return B===null&&(B=be().finally(()=>{B=null})),B}function _e(e,t){let n=k(t),r=A(t),i=j(t),a=I?null:b({pageHref:window.location.href,pageOrigin:window.location.origin,configuredRedirectUri:w.redirectUri},()=>crypto.randomUUID()),o=I?w.extensionRedirectUri??`https://${chrome.runtime.id}.chromiumapp.org/`:a.redirectUri,s=a?.oauthState,c=a?.expectedNonce??null,l=new URLSearchParams({client_id:n,scope:r,response_type:`token`,redirect_uri:o,prompt:`none`});return s&&l.set(`state`,s),{authorizeUrl:`${N(i)}/ims/authorize/v2?${l}`,expectedNonce:c,proxyEndpoint:e}}function ve(e,t){if(!t)return!0;try{if(new URL(e).searchParams.get(`nonce`)!==t)return console.error(`[adobe] OAuth nonce mismatch — possible CSRF`),!1}catch(e){console.warn(`[adobe] Nonce check skipped (URL parse failed):`,e instanceof Error?e.message:String(e))}return!0}async function ye(e,n){let r=L();await t({providerId:`adobe`,accessToken:e.accessToken,tokenExpiresAt:Date.now()+e.expiresIn*1e3,userName:r?.userName,userAvatar:r?.userAvatar,scopes:e.scope,baseUrl:w.proxyEndpoint?void 0:n})}async function be(){try{let e=T(),{authorizeUrl:t,expectedNonce:n}=_e(e,await O(e)),{createOAuthLauncher:r}=await import(`./oauth-service-MWzqRq2q.js`),i=await r()(t,{interactive:!1});if(!i||!ve(i,n))return null;let a=R(i);return a?(await ye(a,e),console.log(`[adobe] Token renewed silently`),await $().catch(e=>console.warn(`[adobe] Failed to refresh models after silent renewal:`,e instanceof Error?e.message:String(e))),a.accessToken):null}catch(e){return console.warn(`[adobe] Silent renewal error:`,e instanceof Error?e.message:String(e)),null}}const W=`X-Slicc-Version`;function G(e){let t={};if(e.headers)for(let[n,r]of Object.entries(e.headers))n.toLowerCase()!==`x-slicc-version`&&(t[n]=r);return t[W]=`6.233.0`,{...e,headers:t}}const xe=`adobe-usage-probe`,K=new Set;function q(e,t){if(e.headers){for(let[t,n]of Object.entries(e.headers))if(t.toLowerCase()===`x-session-id`&&n!=null)return e}return K.has(t)||(K.add(t),console.warn(`[adobe] Missing X-Session-Id from ${t} — using daily fallback. Attach an X-Session-Id header at the call site (see scoop-context.ts streamWithSessionId or docs/pitfalls.md).`)),{...e,headers:{...e.headers??{},"X-Session-Id":_(`adobe-provider-fallback`)}}}function Se(){K.clear()}function J(e,t){return{type:`error`,reason:`error`,error:{role:`assistant`,content:[],api:`adobe-anthropic`,provider:`adobe`,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:`error`,errorMessage:t instanceof Error?t.message:String(t),timestamp:Date.now()}}}function Y(e){console.error(`[adobe] Stream error:`,e instanceof Error?e.message:String(e))}const X=(e,t,n={})=>{let r=a();return Ce(r,e,t,n).catch(Y),r};async function Ce(e,t,n,r){try{let i=await V();if(String(t.api).includes(`openai`)){let a={...t,baseUrl:`${T()}/v1`,api:`openai-completions`,compat:{...t.compat,supportsStore:!1,supportsDeveloperRole:!1}},o=u(a,v(n),G(q({...r,apiKey:i},`streamAdobe[openai]`)));for await(let t of o)e.push(t)}else{let a={...t,baseUrl:T(),api:`anthropic-messages`},o=f(a,v(n),G(q(C(t,x(t.id,t.name,{...r,apiKey:i})),`streamAdobe[anthropic]`)));for await(let t of o)e.push(t)}e.end()}catch(n){Y(n),e.push(J(t,n)),e.end()}}const Z=(e,t,n)=>{let r=a();return we(r,e,t,n).catch(Y),r};async function we(e,t,n,r){try{let i=await V();if(String(t.api).includes(`openai`)){let a={...t,baseUrl:`${T()}/v1`,api:`openai-completions`,compat:{...t.compat,supportsStore:!1,supportsDeveloperRole:!1}},o=d(a,v(n),G(q({...r,apiKey:i},`streamSimpleAdobe[openai]`)));for await(let t of o)e.push(t)}else{let a={...t,baseUrl:T(),api:`anthropic-messages`},o=l(a,v(n),G(q(C(t,x(t.id,t.name,{...r,apiKey:i})),`streamSimpleAdobe[anthropic]`)));for await(let t of o)e.push(t)}e.end()}catch(n){Y(n),e.push(J(t,n)),e.end()}}function Te(e){let t={id:e.id,name:e.name};return e.api!==void 0&&(t.api=e.api),e.context_window!==void 0&&(t.context_window=e.context_window),e.max_tokens!==void 0&&(t.max_tokens=e.max_tokens),e.reasoning!==void 0&&(t.reasoning=e.reasoning),e.input!==void 0&&(t.input=e.input),t}function Ee(){let e=new Map;for(let t of c())try{let n=s(t);for(let t of n)e.set(t.id,t)}catch{}return e}function De(t,n,r){let i=`adobe-${t.api===`openai`?`openai`:`anthropic`}`,a=r.get(t.id);if(a)return{...a,provider:`adobe`,api:i};let o=e(t.id,r);return{id:t.id,name:t.name??t.id,provider:`adobe`,api:i,baseUrl:n,contextWindow:2e5,maxTokens:16384,input:[`text`,`image`],cost:o,inputCost:o.input,outputCost:o.output,cacheReadCost:o.cacheRead,cacheWriteCost:o.cacheWrite,reasoning:!0}}function Oe(e,t){for(let t of e)ce.set(t.id,Te(t));let n=Ee();return e.map(e=>De(e,t,n))}async function ke(e){try{let t=e??await V(),n=T(),r=await fetch(`${n}/v1/models`,{headers:{Authorization:`Bearer ${t}`,[W]:`6.233.0`}});if(!r.ok)console.warn(`[adobe] Proxy /v1/models returned ${r.status}, falling back to Anthropic models`);else{let e=await r.json();if(e.data?.length)return Oe(e.data,n)}}catch(e){console.warn(`[adobe] Failed to fetch proxy models:`,e instanceof Error?e.message:String(e))}return null}const Q=new Map;function Ae(){return s(`anthropic`).map(e=>({...e,provider:`adobe`,api:`adobe-anthropic`}))}async function $(e){let t=T(),n=Q.get(t);if(n)return n;let r=await ke(e);return r?(Q.set(t,r),r):Ae()}function je(){o({api:`adobe-anthropic`,stream:X,streamSimple:Z}),o({api:`adobe-openai`,stream:X,streamSimple:Z})}export{Se as __resetAdobeSessionIdWarningCacheForTests,z as config,R as extractTokenFromUrl,$ as getAdobeModels,V as getValidAccessToken,H as isTokenExpired,je as register};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const e=`usage: agent <cwd> <allowed-commands> <prompt>
|
|
2
|
+
|
|
3
|
+
Spawns a sub-scoop, feeds it a task, blocks until the agent loop completes,
|
|
4
|
+
then prints the scoop's final message on stdout.
|
|
5
|
+
|
|
6
|
+
Arguments:
|
|
7
|
+
<cwd> Working directory for the spawned scoop. Becomes the
|
|
8
|
+
scoop's sole writable prefix. Relative paths are resolved
|
|
9
|
+
against the current shell's cwd; '.', '..', and absolute
|
|
10
|
+
paths are all supported.
|
|
11
|
+
<allowed-commands> Comma-separated list of bash commands the scoop may run.
|
|
12
|
+
Use '*' to allow every command. Whitespace is trimmed
|
|
13
|
+
around each entry; duplicates are tolerated.
|
|
14
|
+
<prompt> Prompt forwarded verbatim to the scoop.
|
|
15
|
+
|
|
16
|
+
Default sandbox:
|
|
17
|
+
The spawned scoop sees (read-only): the OWNING cone's workspace (+ skills)
|
|
18
|
+
+ the invoking shell's cwd
|
|
19
|
+
The spawned scoop writes to: <cwd>, /shared/, /scoops/<name>/, /tmp/
|
|
20
|
+
/tmp/ is always writable — no flag toggles it.
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--model <id> Override the model id used by the spawned scoop.
|
|
24
|
+
Accepts an exact id, a shorthand ('haiku', 'sonnet',
|
|
25
|
+
'claude-haiku-4-5'), or the 'provider:model' form
|
|
26
|
+
the 'models' command prints
|
|
27
|
+
('openrouter:openai/gpt-5.6-terra-pro'). A bare id
|
|
28
|
+
resolves against the selected provider first, then
|
|
29
|
+
against any other CONFIGURED provider that offers
|
|
30
|
+
it; matching several is an error listing the
|
|
31
|
+
qualified ids. The scoop runs on the provider the
|
|
32
|
+
model was resolved from. A model from a provider
|
|
33
|
+
other than the selected one must also be allowed in
|
|
34
|
+
/etc/models; the error quotes the line to add. An id
|
|
35
|
+
that cannot be resolved (or is not allowed) exits 1 —
|
|
36
|
+
it never falls back to the parent's model. Defaults
|
|
37
|
+
to inheriting the parent's model.
|
|
38
|
+
--thinking <level> Reasoning / thinking level for the spawned scoop.
|
|
39
|
+
One of: off, minimal, low, medium, high, xhigh.
|
|
40
|
+
Defaults to inheriting the parent's level (or 'off'
|
|
41
|
+
when there is no parent). 'xhigh' is silently
|
|
42
|
+
clamped to 'high' when the resolved model doesn't
|
|
43
|
+
support it. Ignored entirely for non-reasoning
|
|
44
|
+
models. Aliased as --effort.
|
|
45
|
+
--workspace-mode <mode> Isolation policy for the spawned scoop's filesystem
|
|
46
|
+
view. One of: private, shared-readonly (default),
|
|
47
|
+
snapshot, shared-live. Default shared-readonly is
|
|
48
|
+
today's sandbox: parent workspace + skills + the
|
|
49
|
+
invoking cwd are visible, <cwd> + /shared/ + scratch
|
|
50
|
+
are writable, mounts stay readable. private is an
|
|
51
|
+
isolated sandbox (own cwd/scratch only — no parent
|
|
52
|
+
workspace, no implicit /shared/, mounts are NOT
|
|
53
|
+
auto-visible). snapshot and shared-live are not
|
|
54
|
+
implemented and exit 1. Explicit --read-only still
|
|
55
|
+
replaces the mode's visiblePaths.
|
|
56
|
+
--read-only <paths> Comma-separated VFS paths exposed read-only to the
|
|
57
|
+
spawned scoop (visiblePaths). Pure replace — the
|
|
58
|
+
owning cone's roots AND the implicit ctx.cwd add are
|
|
59
|
+
BOTH dropped. To keep them, name your own cone's
|
|
60
|
+
workspace ("$(pwd),/workspace/skills/") — a literal
|
|
61
|
+
/workspace/ is the PRIMARY cone's. Each entry is
|
|
62
|
+
normalized to a trailing slash.
|
|
63
|
+
--background-after <s> Seconds the spawned scoop's bash tool waits for a
|
|
64
|
+
command before detaching it to the background and
|
|
65
|
+
continuing (default 600). The detached command's exit
|
|
66
|
+
code and output come back to the scoop as a
|
|
67
|
+
"Background Command" lick, so a slow or stuck command
|
|
68
|
+
never wedges an unsupervised run. Use 0 to detach
|
|
69
|
+
every command immediately. Must be >= 0.
|
|
70
|
+
--image <path> Attach an image (PNG, JPEG, GIF or WebP) to the
|
|
71
|
+
prompt, so the scoop can see it without being
|
|
72
|
+
allowed a command to open it. Repeatable, up to 8;
|
|
73
|
+
--image=<path> also works. Relative paths resolve
|
|
74
|
+
against the current shell's cwd. A missing file, a
|
|
75
|
+
non-image, or a ninth image exits 1 before anything
|
|
76
|
+
is spawned. Large images are resized to the model's
|
|
77
|
+
limits.
|
|
78
|
+
--no-escalate Hold the scoop to its grant. Normally a command not
|
|
79
|
+
in <allowed-commands>, or a write outside its
|
|
80
|
+
writable paths, asks the invoking cone for approval;
|
|
81
|
+
with this flag it is refused at once and the scoop
|
|
82
|
+
is told it is not permitted for this call. Nothing
|
|
83
|
+
reaches the cone or the user, and stored "Always"
|
|
84
|
+
grants do not apply either.
|
|
85
|
+
--persist-session Write the spawned agent's full session transcript to
|
|
86
|
+
/sessions/agent-<name>-<timestamp>.md (durable —
|
|
87
|
+
survives a new chat) for later human analysis.
|
|
88
|
+
--no-persist-session Do not write a session transcript at all. With
|
|
89
|
+
NEITHER flag, the transcript is written to
|
|
90
|
+
/tmp/agent-<name>-<timestamp>.md, which a new chat
|
|
91
|
+
clears.
|
|
92
|
+
-h, --help Show this help message and exit.
|
|
93
|
+
|
|
94
|
+
Examples:
|
|
95
|
+
agent . "*" "say hello in one word"
|
|
96
|
+
agent /home ls,wc,find "how many files do I have in my home directory"
|
|
97
|
+
agent --model claude-haiku-4-5 . "*" "summarize files in this directory"
|
|
98
|
+
agent --thinking high . "*" "design a careful plan first"
|
|
99
|
+
agent --read-only /workspace/,/shared/assets/ . "*" "review the docs"
|
|
100
|
+
agent --workspace-mode private . "*" "work only in this directory"
|
|
101
|
+
agent --background-after 60 . "*" "run the slow build and report"
|
|
102
|
+
agent --no-escalate --image shot.png . ls "what does this page show?"
|
|
103
|
+
`;export{e as AGENT_HELP};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{r as e}from"./base64-BPBW1Gzr.js";import{a as t}from"./shared-D-ZRFYou.js";function n(e){let t=(t,n)=>String.fromCharCode(...e.subarray(t,n));return e.length>=8&&e[0]===137&&t(1,8)===`PNG\r
|
|
2
|
+
|
|
3
|
+
`?`image/png`:e.length>=3&&e[0]===255&&e[1]===216&&e[2]===255?`image/jpeg`:e.length>=6&&(t(0,6)===`GIF87a`||t(0,6)===`GIF89a`)?`image/gif`:e.length>=12&&t(0,4)===`RIFF`&&t(8,12)===`WEBP`?`image/webp`:null}async function r(r,i){let a=[];for(let{arg:o,path:s}of i){let i;try{i=await r.readFileBuffer(s)}catch{return{error:`agent: --image: file not found: ${o}\n`}}let c=n(i);if(c===null)return{error:`agent: --image: unsupported image type (${t(o)}): ${o} — use PNG, JPEG, GIF or WebP\n`};a.push({type:`image`,data:e(i),mimeType:c})}return{images:a}}export{r as readImages};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./logger-DDBAeTLF.js";import{J as t}from"./wc-shell-
|
|
1
|
+
import{t as e}from"./logger-DDBAeTLF.js";import{J as t}from"./wc-shell-BcFO-uxW.js";var n=e(`agent-panels`),r=`/workspace/panels`,i=`panel.json`;function a(e,t){if(!e||typeof e!=`object`)return n.warn(`panel manifest is not an object`,{dir:t}),null;let r=e;return typeof r.id!=`string`||r.id.trim()===``?(n.warn(`panel manifest needs a non-empty id`,{dir:t}),null):typeof r.title!=`string`||r.title.trim()===``?(n.warn(`panel manifest needs a non-empty title`,{dir:t,id:r.id}),null):{id:r.id,title:r.title,icon:typeof r.icon==`string`?r.icon:void 0,minWidth:typeof r.minWidth==`number`?r.minWidth:void 0,minHeight:typeof r.minHeight==`number`?r.minHeight:void 0,preferredSize:typeof r.preferredSize==`string`||typeof r.preferredSize==`number`?r.preferredSize:void 0,presentation:r.presentation===`floating`?`floating`:void 0,anchor:r.anchor,realm:r.realm===`main`?`main`:`sandboxed`}}async function o(e){let t=[];try{if(!await e.exists(`/workspace/panels`))return t;let o=await e.readDir(r);for(let s of o){if(s.type!==`directory`)continue;let o=`${r}/${s.name}`,c=`${o}/${i}`;if(!await e.exists(c))continue;let l;try{let t=await e.readFile(c);l=JSON.parse(typeof t==`string`?t:String(t))}catch(e){n.warn(`unreadable panel manifest`,{manifestPath:c,error:e});continue}let u=a(l,o);if(!u)continue;let d=l.entry,f=typeof d==`string`&&d.length>0?`${o}/${d}`:null;t.push({meta:u,dir:o,entry:f})}}catch(e){n.warn(`agent panel discovery failed`,{error:e})}return t}async function s(e){let r=await o(e);for(let e of r)t({meta:e.meta,source:{kind:`sandboxed`,entry:e.entry??`${e.dir}/panel.shtml`},origin:`agent`});return r.length>0&&n.info(`registered agent panels`,{count:r.length}),r}export{s as registerAgentPanels};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./logger-LESFN7Hj.js";import{mcpAgentToolNames as t,resolveToolExposure as n}from"./connection-manager-
|
|
1
|
+
import{t as e}from"./logger-LESFN7Hj.js";import{mcpAgentToolNames as t,resolveToolExposure as n}from"./connection-manager-D0LxHiWb.js";const r=e(`mcp-agent-tools`),i=20480;function a(e){let{serverName:i,tools:a,connection:o,exposure:s,toolExposure:u,writeOverflow:d}=e,f=[],p=t(i,a.filter(e=>n(e.name,s,u)===`direct`).map(e=>e.name));for(let e of a){if(n(e.name,s,u)!==`direct`)continue;let t={name:p.get(e.name),label:`mcp:${i}/${e.name}`,description:e.description??`MCP tool ${e.name} from ${i}`,parameters:e.inputSchema??{type:`object`,properties:{}},...e.outputSchema?{outputSchema:e.outputSchema}:{},async execute(t,n,a){let s=n??{};try{let n=await o.callTool(e.name,s,{signal:a});return{content:await l(c(n),t,d),details:void 0,...n.structuredContent?{structuredContent:n.structuredContent}:{},...n.isError?{isError:!0}:{}}}catch(t){return r.warn(`MCP tool call failed`,{server:i,tool:e.name,error:t instanceof Error?t.message:String(t)}),{content:[{type:`text`,text:`MCP tool error: ${t instanceof Error?t.message:String(t)}`}],details:void 0,isError:!0}}}};f.push(t)}return f}function o(e){switch(e.type){case`text`:return`text`in e&&typeof e.text==`string`?{type:`text`,text:e.text}:void 0;case`image`:return`data`in e&&`mimeType`in e?{type:`image`,data:e.data,mimeType:e.mimeType}:void 0;case`resource`:return s(e);default:return{type:`text`,text:`[${e.type??`unknown`}]`}}}function s(e){if(!(`resource`in e))return{type:`text`,text:`[resource: unknown]`};let t=e.resource;return t.text?{type:`text`,text:t.text}:t.mimeType?.startsWith(`image/`)&&t.blob?{type:`image`,data:t.blob,mimeType:t.mimeType}:{type:`text`,text:`[resource: ${t.uri??`unknown`}]`}}function c(e){let t=[];for(let n of e.content){let e=o(n);e&&t.push(e)}return t.length===0&&e.structuredContent&&t.push({type:`text`,text:JSON.stringify(e.structuredContent)}),t.length===0&&t.push({type:`text`,text:`(empty result)`}),t}async function l(e,t,n){let a=new TextEncoder,o=0;for(let t of e)t.type===`text`&&(o+=a.encode(t.text).length);if(o<=i)return e;let s=i,c=[],l=!1;for(let i of e){if(i.type!==`text`){c.push(i);continue}let o=a.encode(i.text);if(o.length<=s){s-=o.length,c.push(i);continue}if(!l&&n){l=!0;let i=t.replace(/[^a-zA-Z0-9_-]/g,`_`),a=e.filter(e=>e.type===`text`).map(e=>e.text).join(`
|
|
2
2
|
`);try{await n(i,a)}catch(e){r.debug(`failed to write MCP overflow`,{id:i,error:e instanceof Error?e.message:String(e)})}}if(s<=0)continue;let u=Math.floor(s/2),d=new TextDecoder().decode(o.slice(0,u)),f=new TextDecoder().decode(o.slice(o.length-u)),p=t.replace(/[^a-zA-Z0-9_-]/g,`_`),m=`
|
|
3
3
|
|
|
4
4
|
--- [truncated; full output at /tmp/mcp/{id}.txt] ---
|