@symerian/symi 3.5.20 → 3.5.21
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/dist/{agent-D0Z4r5fr.js → agent-DgVWcnlD.js} +1 -1
- package/dist/{agent-DCDT-MPE.js → agent-NT0EKnK_.js} +18 -18
- package/dist/{agent-scope-DOrZjOnW.js → agent-scope-Bnsyyeci.js} +18 -18
- package/dist/{agents-CdkBeP0d.js → agents-Dlcpc1K3.js} +3 -3
- package/dist/{agents.config-B7sNDvhz.js → agents.config-DA0ISLi7.js} +1 -1
- package/dist/{audit-B7deV4Lp.js → audit-CPloCzEZ.js} +2 -2
- package/dist/{audit-BCStg-Hv.js → audit-CXIXYDRx.js} +20 -20
- package/dist/{auth-choice-BIGcxSzP.js → auth-choice--DymOp5O.js} +2 -2
- package/dist/{auth-choice-B3DU-aBr.js → auth-choice-BtXIQPTU.js} +11 -11
- package/dist/{auth-profiles-Ce7R_25e.js → auth-profiles-D5nYBj_Z.js} +2 -2
- package/dist/{auth-token-Cr28IDKY.js → auth-token-fgnCQEHT.js} +3 -3
- package/dist/{banner-ChNdzPjD.js → banner-CY_9VW7E.js} +1 -1
- package/dist/{browser-cli-C9xaKW8l.js → browser-cli-C5VVk6C9.js} +3 -3
- package/dist/{browser-cli-BTg8SVs-.js → browser-cli-DOTM7UBC.js} +9 -9
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +4 -4
- package/dist/bundled/session-memory/handler.js +4 -4
- package/dist/{call-BccaLPi8.js → call-Bpjj5p7I.js} +9 -9
- package/dist/{call-DZg43vv8.js → call-C2urR5Fj.js} +1 -1
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{channel-options-CUptVX8c.js → channel-options-XRJiHUm5.js} +1 -1
- package/dist/{channel-options-LLmAnD_L.js → channel-options-rFgJaKzJ.js} +1 -1
- package/dist/{channels-cli-xoromnio.js → channels-cli-CQ4M05oy.js} +57 -57
- package/dist/{channels-cli-B0OQvVUL.js → channels-cli-QMHCRAb5.js} +9 -9
- package/dist/{chrome-DJChpTwP.js → chrome-38OnGyuN.js} +2 -2
- package/dist/{chrome-CmQwGAuL.js → chrome-OTJg3QKn.js} +7 -7
- package/dist/{cli-C7v-sID8.js → cli-B-uoiYP2.js} +45 -45
- package/dist/{cli-CMNR7ULk.js → cli-BafqEuaj.js} +6 -6
- package/dist/{client-k0MT6NBw.js → client-CTrfpKT3.js} +7 -2
- package/dist/{client-DCxeV1bw.js → client-yVTJ5jx5.js} +6 -1
- package/dist/{command-registry-CXcvXjUR.js → command-registry-CLm8TAH3.js} +11 -11
- package/dist/{commands-registry-Ca5hh7nh.js → commands-registry-CwXsDVuO.js} +1 -1
- package/dist/{completion-cli-DJ1YCeSg.js → completion-cli-Cn_81QBb.js} +12 -12
- package/dist/{completion-cli-B1Fg6Lmg.js → completion-cli-DOBXkVwG.js} +2 -2
- package/dist/{config-B4jkreCN.js → config-BngIfn5l.js} +2 -2
- package/dist/{config-cli-D5DlWt6T.js → config-cli-B1cPkJ4p.js} +4 -4
- package/dist/{config-cli-CQ1FAvY_.js → config-cli-BgHYqFH1.js} +1 -1
- package/dist/{config-guard-BRm3RiOi.js → config-guard-DStz4_V2.js} +6 -6
- package/dist/{config-validation-Cdyg1BZB.js → config-validation-Dxj9LRzr.js} +1 -1
- package/dist/{configure-bhJB2Dti.js → configure-C7zmSgvC.js} +14 -14
- package/dist/{configure-DG1lf0Ld.js → configure-DmzM0S7L.js} +6 -6
- package/dist/{consolidate-DymnvvYm.js → consolidate-CO32_TEx.js} +6 -6
- package/dist/{control-service-D8kKOts5.js → control-service-CUreKVeY.js} +4 -4
- package/dist/control-ui/css/style.css +270 -0
- package/dist/control-ui/index.html +44 -114
- package/dist/control-ui/js/scheduling.js +85 -224
- package/dist/control-ui/js/subagents.js +78 -394
- package/dist/control-ui/js/symframe-awaiting.js +301 -0
- package/dist/control-ui/js/symframe-pin-store.js +104 -0
- package/dist/control-ui/js/symframe.js +238 -2
- package/dist/{control-ui-assets-CJQ97d4u.js → control-ui-assets-B8B9z_Ll.js} +1 -1
- package/dist/{cost-cli-DWiVCOCx.js → cost-cli-D-ssjcRF.js} +3 -3
- package/dist/{cron-cli-8RaBr1CM.js → cron-cli-BNBs3zue.js} +3 -3
- package/dist/{cron-cli-fW3wtftG.js → cron-cli-otPeKxmi.js} +7 -7
- package/dist/{daemon-cli-Y6clFgva.js → daemon-cli-DDqeG2nd.js} +2 -2
- package/dist/{daemon-cli-0EiZTQ2A.js → daemon-cli-qDdMg615.js} +11 -11
- package/dist/daemon-cli.js +6 -1
- package/dist/{daemon-runtime-DlQla_dA.js → daemon-runtime-CKn0wmCk.js} +10 -10
- package/dist/{deliver-B04yNX82.js → deliver-BiWlR84Y.js} +4 -4
- package/dist/{deliver-lTZLIQqf.js → deliver-CWMFmMCv.js} +2 -2
- package/dist/{deps-Bf9dt2UO.js → deps-CdibsPMx.js} +1 -1
- package/dist/{devices-cli-C2gQTsB0.js → devices-cli-BJ3rVWOw.js} +2 -2
- package/dist/{devices-cli-DfiSkZ7k.js → devices-cli-DDPwF2Nx.js} +6 -6
- package/dist/{diagnostics-DlZODdRf.js → diagnostics-CYkqD5lP.js} +5 -5
- package/dist/{directory-cli-Bm5QYEo-.js → directory-cli-giqTe8Yg.js} +3 -3
- package/dist/{dm-policy-shared-CeFt0nch.js → dm-policy-shared-B61_yf6G.js} +1 -1
- package/dist/{dns-cli-CubLq4j9.js → dns-cli-Dssz4RqF.js} +3 -3
- package/dist/{docs-cli-PS8m1er7.js → docs-cli-Ct1STieY.js} +1 -1
- package/dist/{doctor-completion-CfF0J8fs.js → doctor-completion-CL7MyXlo.js} +2 -2
- package/dist/{doctor-completion-ScxFfN93.js → doctor-completion-k0HiL05o.js} +1 -1
- package/dist/{doctor-config-flow-C52W1uUK.js → doctor-config-flow-ljVnQJjo.js} +9 -9
- package/dist/entry.js +1 -1
- package/dist/{exec-approvals-cli-Cl-vWA1q.js → exec-approvals-cli-Cau1vPQI.js} +4 -4
- package/dist/{exec-approvals-cli-BaKWIf56.js → exec-approvals-cli-DsBoQu5H.js} +13 -13
- package/dist/extensionAPI.js +2 -2
- package/dist/{file-lock-BVUYnlQv.js → file-lock-2AecMjCa.js} +8 -8
- package/dist/{fs-safe-BdejYjW8.js → fs-safe-B0Is-oLk.js} +6 -6
- package/dist/{gateway-cli-kq5EWlnF.js → gateway-cli-DG_2YZ8B.js} +98 -98
- package/dist/{gateway-cli-CK-5nguV.js → gateway-cli-DgmGygc6.js} +16 -16
- package/dist/{gateway-rpc-Bzg_TTKP.js → gateway-rpc-Kv0-8W2E.js} +1 -1
- package/dist/{gateway-rpc-D12UaJS5.js → gateway-rpc-gaoD882s.js} +1 -1
- package/dist/{glass-ui-ws-B6p0iPsO.js → glass-ui-ws-Bof7krDJ.js} +67 -67
- package/dist/{glass-ui-ws-CVr0_1gT.js → glass-ui-ws-Dl45d7eU.js} +13 -13
- package/dist/{health-CPU9rQGj.js → health-CMbUI4aN.js} +4 -4
- package/dist/{health-CJb2CYtg.js → health-znS85U-F.js} +1 -1
- package/dist/{hooks-cli-DbgVZaP4.js → hooks-cli-Cb9BzCOY.js} +7 -7
- package/dist/{hooks-cli-13HCu5Xs.js → hooks-cli-Cgjor7F-.js} +59 -59
- package/dist/{image-ops-L70xVnpG.js → image-ops-BzCBIakN.js} +10 -10
- package/dist/index.js +52 -52
- package/dist/{inspect-CGKsaVZ4.js → inspect-DzYUb_Dl.js} +4 -4
- package/dist/{install-safe-path-B2JrFspY.js → install-safe-path-BrpA09f2.js} +11 -11
- package/dist/{installs-D890uIIW.js → installs-bnDlOSq2.js} +10 -10
- package/dist/{internal-DVCddhhN.js → internal-csqU78gW.js} +9 -9
- package/dist/{lifecycle-core-wFwnK_mD.js → lifecycle-core-cSR_xiIO.js} +5 -5
- package/dist/llm-slug-generator.js +4 -4
- package/dist/{local-roots-CgDCgCuM.js → local-roots-2Jb79HZ8.js} +1 -1
- package/dist/{logs-cli-R16VTptK.js → logs-cli-Kr145PO_.js} +7 -7
- package/dist/{logs-cli-CQeK5fn7.js → logs-cli-LiAjkog2.js} +3 -3
- package/dist/{manager-CxFs8Z_F.js → manager-CceVgXHV.js} +1 -1
- package/dist/{manager-B2SWSuad.js → manager-Cv4xI8sP.js} +1 -1
- package/dist/{manager-CHLdCC6u.js → manager-DG6PODgu.js} +15 -15
- package/dist/{manager-LPPGAsqn.js → manager-V4UCf0Av.js} +1 -1
- package/dist/{memory-DFpqcIst.js → memory-A2D5e8dL.js} +2 -2
- package/dist/{memory-DavRjdTi.js → memory-BFnx3v3_.js} +5 -5
- package/dist/{memory-cli-DZnq3S6s.js → memory-cli-1zjVJITN.js} +2 -2
- package/dist/{memory-cli-B-Cp1Sb1.js → memory-cli-CHNghdrm.js} +12 -12
- package/dist/{model-MUMSB_7d.js → model-Cwbcw-km.js} +1 -1
- package/dist/{model-auth-1EAQvYRv.js → model-auth-_C07_3Yr.js} +2 -2
- package/dist/{model-catalog-IWi6-nY9.js → model-catalog-BWurV7gl.js} +3 -3
- package/dist/{model-picker-Cf6UgQEh.js → model-picker-Dpkr5xBW.js} +5 -5
- package/dist/{model-selection-7wdmO-Iw.js → model-selection-CCTzD29o.js} +1 -1
- package/dist/{models-Cht7Mzvs.js → models-BYev6YAG.js} +3 -3
- package/dist/{models-cli-B_motPDX.js → models-cli-BbK8HMKa.js} +55 -55
- package/dist/{models-cli-DXswzgUR.js → models-cli-Fa5r1QYP.js} +9 -9
- package/dist/{models-config-B5Xxy-c-.js → models-config-DlXge3Sd.js} +8 -8
- package/dist/{node-cli-D-gsjRXY.js → node-cli-BPnBosC4.js} +27 -27
- package/dist/{node-cli-VmKhIXuP.js → node-cli-Cv7x1gGu.js} +1 -1
- package/dist/{node-service-BH08wY5j.js → node-service-Cc18m-uk.js} +1 -1
- package/dist/{nodes-cli-BMvxQGCp.js → nodes-cli-CN_m6PO5.js} +10 -10
- package/dist/{nodes-cli-D199d74o.js → nodes-cli-DaHOBbd4.js} +3 -3
- package/dist/{nodes-screen-De9ma6e1.js → nodes-screen-Cp5QP3ET.js} +4 -4
- package/dist/{npm-registry-spec-DTqn-NXZ.js → npm-registry-spec-C-muP97-.js} +9 -9
- package/dist/{onboard-DFJcbABp.js → onboard-B2IcTMv-.js} +15 -15
- package/dist/{onboard-CdRA8BRG.js → onboard-D-m6WTZl.js} +3 -3
- package/dist/{onboard-channels-fadyQGBK.js → onboard-channels-Z-Jkrk5-.js} +1 -1
- package/dist/{onboard-channels-Ca7ZFQ2Y.js → onboard-channels-wfGO5Zlh.js} +4 -4
- package/dist/{onboard-custom-BcRYreNG.js → onboard-custom-DnDrvxSg.js} +3 -3
- package/dist/{onboard-helpers-CQBpac8h.js → onboard-helpers-BKejzolA.js} +8 -8
- package/dist/{onboard-helpers-BcLPSb5N.js → onboard-helpers-Dhr98nj8.js} +1 -1
- package/dist/{onboard-hooks-2SCajRKc.js → onboard-hooks-D9jHwImb.js} +1 -1
- package/dist/{onboard-remote-Bo3tpC9N.js → onboard-remote-DZdMxd1Q.js} +1 -1
- package/dist/{onboard-remote-BWK5Ths4.js → onboard-remote-y3ZmP90U.js} +1 -1
- package/dist/{onboard-skills-BLl8HPJO.js → onboard-skills-2SUv-W7i.js} +1 -1
- package/dist/{onboard-skills-DvacccqZ.js → onboard-skills-BFhHfrt9.js} +3 -3
- package/dist/{onboarding-ojb2rFkA.js → onboarding-BckHLQMV.js} +7 -7
- package/dist/{onboarding-BywueA1d.js → onboarding-DqlPV372.js} +12 -12
- package/dist/{onboarding.finalize-DdxBQpUU.js → onboarding.finalize-Bwjv3jew.js} +31 -31
- package/dist/{onboarding.finalize-DHvlZi9G.js → onboarding.finalize-CbH_ShIW.js} +9 -9
- package/dist/{onboarding.gateway-config-DPBNWNV6.js → onboarding.gateway-config-CiRo9EMt.js} +8 -8
- package/dist/{onboarding.gateway-config-ZK9517uR.js → onboarding.gateway-config-sNSeEykB.js} +3 -3
- package/dist/{openai-model-default-BkuuK-Di.js → openai-model-default-De-UAjwg.js} +2 -2
- package/dist/{pairing-cli-Rsae0KnN.js → pairing-cli-CBMMCNnx.js} +5 -5
- package/dist/{pairing-store-BNhJOnWn.js → pairing-store-Be-ZQK87.js} +1 -1
- package/dist/{pairing-token-Dcy37-4s.js → pairing-token-B703A1U3.js} +7 -7
- package/dist/{paths-DObzwe08.js → paths-BWqg8NZT.js} +1 -1
- package/dist/{pi-auth-json-Db8XJVGL.js → pi-auth-json-D-vdh-nY.js} +6 -6
- package/dist/{pi-embedded-Da0QRlM0.js → pi-embedded-B9rtlNMc.js} +25 -9
- package/dist/{pi-embedded-helpers-D-OFjhdI.js → pi-embedded-helpers-j1JrlsI0.js} +6 -6
- package/dist/{pi-tools.policy-H2t-Xkfc.js → pi-tools.policy-CvAqjEH9.js} +3 -3
- package/dist/{plugin-auto-enable-DJBhDIMq.js → plugin-auto-enable-BXSJTxI7.js} +1 -1
- package/dist/{plugin-registry-tG7NXc3Y.js → plugin-registry-B43UosQh.js} +3 -3
- package/dist/{plugin-registry-Tlmjr-LX.js → plugin-registry-CS4WgHbu.js} +1 -1
- package/dist/plugin-sdk/gateway/protocol/schema/logs-chat.d.ts +1 -1
- package/dist/plugin-sdk/index.js +6 -6
- package/dist/plugin-sdk/infra/symframe-broadcast.d.ts +18 -6
- package/dist/{plugins-cli-CRKD8aho.js → plugins-cli-BV2wbjfI.js} +54 -54
- package/dist/{plugins-cli-Cm0G_-Y5.js → plugins-cli-BY42hyHP.js} +7 -7
- package/dist/{ports-r7LBic2V.js → ports-Bi3V_3n9.js} +1 -1
- package/dist/{ports-gxLM5ahL.js → ports-CB_Iu83U.js} +2 -2
- package/dist/{program-DEmAlwmD.js → program-P9F1DxBa.js} +12 -12
- package/dist/{program-context-DRCRbDpu.js → program-context-BmXxHUKe.js} +40 -40
- package/dist/{prompt-select-styled-pomsR-zf.js → prompt-select-styled-B2ah467m.js} +7 -7
- package/dist/{prompt-select-styled-B41Tx9aC.js → prompt-select-styled-BlQZX6pK.js} +38 -38
- package/dist/{provider-auth-helpers-rKWs_r7a.js → provider-auth-helpers-Bgb_Bfp9.js} +1 -1
- package/dist/{provider-auth-helpers-CdQwOam7.js → provider-auth-helpers-WLwb6tL4.js} +6 -6
- package/dist/{push-apns-eCM0qmrY.js → push-apns-CBGvXev_.js} +4 -4
- package/dist/{push-apns-CZPUHftn.js → push-apns-DnSCjFu7.js} +1 -1
- package/dist/{pw-ai-BiBvIJzd.js → pw-ai-CP5pn3eU.js} +7 -7
- package/dist/{pw-ai-DLsdzdgc.js → pw-ai-DY_6l11g.js} +1 -1
- package/dist/{qmd-manager-C8-M4Pru.js → qmd-manager-Dxyue7B1.js} +19 -19
- package/dist/{qr-cli-1sCVaPcF.js → qr-cli-DHw6muwK.js} +3 -3
- package/dist/{register.agent-BQPvYYdn.js → register.agent-BuEcmVg0.js} +12 -12
- package/dist/{register.agent-N1hoqMFR.js → register.agent-CXdTiqyP.js} +67 -67
- package/dist/{register.configure-BHHZ44xB.js → register.configure-DVcn-gCO.js} +70 -70
- package/dist/{register.configure-BAc3P4Z-.js → register.configure-YDKJ-KQg.js} +14 -14
- package/dist/{register.maintenance-lX0a3Hzl.js → register.maintenance-BiGvpEj-.js} +13 -13
- package/dist/{register.maintenance-DDgy5Iyy.js → register.maintenance-cpspl8D6.js} +67 -67
- package/dist/{register.message-Br-IH_0z.js → register.message-BIuLbESM.js} +7 -7
- package/dist/{register.message-B4lDhHpE.js → register.message-BjcYy5UG.js} +47 -47
- package/dist/{register.onboard-B-GoYJIc.js → register.onboard-C4vIASed.js} +6 -6
- package/dist/{register.onboard-Bv0s2_KV.js → register.onboard-D4RN92s2.js} +25 -25
- package/dist/{register.setup-DQ6KLkAI.js → register.setup-BvoXF0xl.js} +28 -28
- package/dist/{register.setup-4lNdC98i.js → register.setup-D-Jt2e1d.js} +6 -6
- package/dist/{register.status-health-sessions-Cg7bK5K2.js → register.status-health-sessions-BY9hMD1s.js} +8 -8
- package/dist/{register.status-health-sessions-ByGn71_M.js → register.status-health-sessions-DjDvCXBn.js} +41 -41
- package/dist/{register.subclis-FMlcLBX0.js → register.subclis-Cibmeapc.js} +20 -20
- package/dist/{replies-CbXXjn9X.js → replies-B_3j7R_Q.js} +1 -1
- package/dist/{reply-prefix-BFNeXT65.js → reply-prefix-CtZtkTJK.js} +1 -1
- package/dist/{resolve-route-C1IIA6kH.js → resolve-route-Du0VftVs.js} +1 -1
- package/dist/{routes-ivqbutvM.js → routes-BwTUoI5h.js} +10 -10
- package/dist/{rpc-Dk1Az_d8.js → rpc-BnAKPQDB.js} +1 -1
- package/dist/{rpc-JAmDaTYt.js → rpc-CwxSZZOx.js} +1 -1
- package/dist/{run-main-DSyeVDsT.js → run-main-BhEQjKtM.js} +20 -20
- package/dist/{sandbox-BkznAPKO.js → sandbox-CZGTCone.js} +18 -18
- package/dist/{sandbox-cli-Bb9cBtBH.js → sandbox-cli-DEtGT_4y.js} +13 -13
- package/dist/{security-cli-DmgGLP83.js → security-cli-CS-ZT1LE.js} +3 -3
- package/dist/{security-cli-D47LQbpf.js → security-cli-DJd7Fcdy.js} +29 -29
- package/dist/{send-B0jHSNMF.js → send-CxjvucMO.js} +7 -7
- package/dist/{server-context-ChcbJgNo.js → server-context-DXdk410X.js} +5 -5
- package/dist/{server-methods-DGBBt49x.js → server-methods-CWxr5b-w.js} +19 -13
- package/dist/{server-methods-BkHB2MOW.js → server-methods-DfVfzYqq.js} +68 -62
- package/dist/{server-node-events-C186LRm0.js → server-node-events-B0yC6hi1.js} +48 -48
- package/dist/{server-node-events-D-Akk3uq.js → server-node-events-ClDEcUTJ.js} +8 -8
- package/dist/{service-e6MzlLCd.js → service-CRZoXO_n.js} +15 -15
- package/dist/{session-dirs-C9E2G0yZ.js → session-dirs-a00Ad2SO.js} +2 -2
- package/dist/{session-utils-Cs1jlD-q.js → session-utils-CJhcRx3E.js} +14 -14
- package/dist/{sessions-Dxf5Kjig.js → sessions-BCc3THTm.js} +10 -10
- package/dist/{shared-1xPo9ygd.js → shared-C39SiDDJ.js} +1 -1
- package/dist/{shared-COtpr3Ad.js → shared-Dh-O8nRd.js} +3 -3
- package/dist/{skill-commands-DDGGlq68.js → skill-commands-DWvXs3lz.js} +4 -4
- package/dist/{skill-scanner-BCgVcIwi.js → skill-scanner-CIlHPszT.js} +5 -5
- package/dist/{skills-BwDmcZdt.js → skills-CYcBtLGH.js} +4 -4
- package/dist/{skills-cli-B-7TY-vS.js → skills-cli-CD9s3cgm.js} +7 -7
- package/dist/{skills-install-Dwzsjoc8.js → skills-install-BTa9IuQ6.js} +3 -3
- package/dist/{skills-remote-bz71Bstn.js → skills-remote-BcRQTDsZ.js} +3 -3
- package/dist/{skills-status-BKX1PjCc.js → skills-status-DLnCHUZ2.js} +1 -1
- package/dist/{sqlite-Cod7C5ba.js → sqlite-BpogPlQW.js} +5 -5
- package/dist/{status-CFgCSaDq.js → status-BWxLtb3D.js} +23 -23
- package/dist/{status-poPDyC8O.js → status-Doq8T1zj.js} +3 -3
- package/dist/{status-Bahhq7OQ.js → status-K1k4g3Ai.js} +1 -1
- package/dist/{status-D9LC5P_Y.js → status-ojZB_Lrf.js} +5 -5
- package/dist/{status.update-DGJi0OLl.js → status.update-CKfyV6zw.js} +3 -3
- package/dist/{subagent-registry-V2o45tIn.js → subagent-registry-BOt7g9hn.js} +21 -10
- package/dist/{symframe-cli-bxdpivve.js → symframe-cli-CrUtJw_7.js} +31 -7
- package/dist/{symframe-cli-ppdMo15M.js → symframe-cli-D1CtN3pf.js} +37 -13
- package/dist/{symi-root-BQ0IpoW2.js → symi-root-DeCVdZB4.js} +2 -2
- package/dist/{synthesis-B2EyHFXy.js → synthesis-BIQLrbys.js} +6 -6
- package/dist/{synthesis-DGau1ONT.js → synthesis-Bc2QkGvt.js} +2 -2
- package/dist/{synthesis-CPSq83PP.js → synthesis-VZNnlUTf.js} +45 -45
- package/dist/{synthesis-C2WbvLOI.js → synthesis-yl24Ovw4.js} +4 -4
- package/dist/{system-cli-nPyjUPBH.js → system-cli-CvN-Wq9U.js} +3 -3
- package/dist/{system-cli-BroqLjZ6.js → system-cli-r7WJj0Xh.js} +7 -7
- package/dist/{systemd-CUIM0n5P.js → systemd-CsoVnIbM.js} +5 -5
- package/dist/{systemd-hints-CsrzMCTD.js → systemd-hints-QISwLlFU.js} +6 -6
- package/dist/{systemd-linger-BzYk7A6M.js → systemd-linger-BnhuRdbt.js} +1 -1
- package/dist/{tui-Bp9k5skv.js → tui-BxgdImL_.js} +2 -2
- package/dist/{tui-DzROrE20.js → tui-J7Jxp-FF.js} +7 -7
- package/dist/{tui-cli-BHBF8O-3.js → tui-cli-DR48dU_C.js} +19 -19
- package/dist/{tui-cli-Dv4hBFdc.js → tui-cli-DqvgN5ng.js} +3 -3
- package/dist/{unified-runner-CIQIkbvi.js → unified-runner-BV5TdNFv.js} +32 -16
- package/dist/{unified-runner-CduaBH_0.js → unified-runner-DXjH-prv.js} +117 -106
- package/dist/{update-yYduAjKd.js → update-Cb0Fmxic.js} +3 -3
- package/dist/{update-check-BCL_K7kx.js → update-check-u6Jgr1cz.js} +5 -5
- package/dist/{update-cli-WcLxjBiY.js → update-cli-CKpjWtlv.js} +77 -77
- package/dist/{update-cli-BKnHBe8a.js → update-cli-Dn6QQZLd.js} +14 -14
- package/dist/{update-runner-BLV8SI96.js → update-runner-G2YgEATs.js} +15 -15
- package/dist/{webhooks-cli-D5k-Y2A8.js → webhooks-cli-DjUITimx.js} +4 -4
- package/dist/{with-timeout-DPR4A2dx.js → with-timeout-CLrF-Yr_.js} +1 -1
- package/dist/{workspace-dirs-jKFQf7of.js → workspace-dirs-DCICLTHx.js} +1 -1
- package/dist/{wsl-CglTdtlb.js → wsl-DTi7eX-V.js} +2 -2
- package/extensions/memory-core/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +6 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/outlook/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
// ── Symframe AWAITING surface ───────────────────────────────────────────────
|
|
2
|
+
// Stage C of the Dynamic Glass Panel arc — see ~/Documents/dynamic-glass-panel.md.
|
|
3
|
+
//
|
|
4
|
+
// The AWAITING surface is a footer inside the symframe that merges
|
|
5
|
+
// in-flight sub-agents and scheduled cron jobs into a single list —
|
|
6
|
+
// one mental concept: "things that aren't done yet."
|
|
7
|
+
//
|
|
8
|
+
// Sort order:
|
|
9
|
+
// 1. In-flight sub-agents first, sorted by start time (descending —
|
|
10
|
+
// most-recently-started visible at the top)
|
|
11
|
+
// 2. Then scheduled jobs sorted by next ETA (soonest first)
|
|
12
|
+
//
|
|
13
|
+
// Data flow:
|
|
14
|
+
// subagents.js + scheduling.js dispatch CustomEvents after each
|
|
15
|
+
// successful poll fetch. The AWAITING surface listens to both events
|
|
16
|
+
// and re-renders the merged list. No duplicate polling — single
|
|
17
|
+
// source of truth per data type.
|
|
18
|
+
//
|
|
19
|
+
// Click handlers:
|
|
20
|
+
// - Sub-agent row → no-op for now (subagents.list returns enough
|
|
21
|
+
// info to display, but there's no per-subagent detail modal yet;
|
|
22
|
+
// future enhancement: open a side view with the subagent transcript)
|
|
23
|
+
// - Schedule row → opens the existing schedule edit modal via
|
|
24
|
+
// window.schedulingPanel.openForEdit(job)
|
|
25
|
+
// - Schedule toggle → window.schedulingPanel.toggle(jobId)
|
|
26
|
+
// - [+ Add] → small menu: "Spawn subagent" / "Add scheduled task"
|
|
27
|
+
// → opens the corresponding existing modal.
|
|
28
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
"use strict";
|
|
31
|
+
|
|
32
|
+
(function () {
|
|
33
|
+
const root = document.getElementById("symframe-awaiting");
|
|
34
|
+
if (!root) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const list = document.getElementById("awaiting-list");
|
|
38
|
+
const countEl = document.getElementById("awaiting-count");
|
|
39
|
+
const addBtn = document.getElementById("awaiting-add-btn");
|
|
40
|
+
const addMenu = document.getElementById("awaiting-add-menu");
|
|
41
|
+
|
|
42
|
+
// ── State ──
|
|
43
|
+
let subagents = [];
|
|
44
|
+
let schedules = [];
|
|
45
|
+
|
|
46
|
+
// ── DOM helpers ──
|
|
47
|
+
function escHtml(s) {
|
|
48
|
+
return String(s ?? "")
|
|
49
|
+
.replace(/&/g, "&")
|
|
50
|
+
.replace(/</g, "<")
|
|
51
|
+
.replace(/>/g, ">")
|
|
52
|
+
.replace(/"/g, """)
|
|
53
|
+
.replace(/'/g, "'");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Formatters ──
|
|
57
|
+
function formatRuntime(sub) {
|
|
58
|
+
const start = sub.startedAt;
|
|
59
|
+
const end = sub.endedAt || Date.now();
|
|
60
|
+
if (!start) {
|
|
61
|
+
return "--";
|
|
62
|
+
}
|
|
63
|
+
const seconds = Math.floor((end - start) / 1000);
|
|
64
|
+
if (seconds < 60) {
|
|
65
|
+
return `${seconds}s`;
|
|
66
|
+
}
|
|
67
|
+
const minutes = Math.floor(seconds / 60);
|
|
68
|
+
const secs = seconds % 60;
|
|
69
|
+
if (minutes < 60) {
|
|
70
|
+
return `${minutes}m${secs > 0 ? secs + "s" : ""}`;
|
|
71
|
+
}
|
|
72
|
+
const hours = Math.floor(minutes / 60);
|
|
73
|
+
const mins = minutes % 60;
|
|
74
|
+
return `${hours}h${mins}m`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function formatEta(nextRunAtMs) {
|
|
78
|
+
if (!nextRunAtMs) {
|
|
79
|
+
return "—";
|
|
80
|
+
}
|
|
81
|
+
const ms = nextRunAtMs - Date.now();
|
|
82
|
+
if (ms <= 0) {
|
|
83
|
+
return "now";
|
|
84
|
+
}
|
|
85
|
+
const minutes = Math.floor(ms / 60_000);
|
|
86
|
+
if (minutes < 1) {
|
|
87
|
+
return "<1m";
|
|
88
|
+
}
|
|
89
|
+
if (minutes < 60) {
|
|
90
|
+
return `in ${minutes}m`;
|
|
91
|
+
}
|
|
92
|
+
const hours = Math.floor(minutes / 60);
|
|
93
|
+
const mins = minutes % 60;
|
|
94
|
+
if (hours < 24) {
|
|
95
|
+
return mins > 0 ? `in ${hours}h ${mins}m` : `in ${hours}h`;
|
|
96
|
+
}
|
|
97
|
+
const days = Math.floor(hours / 24);
|
|
98
|
+
const hrs = hours % 24;
|
|
99
|
+
return hrs > 0 ? `in ${days}d ${hrs}h` : `in ${days}d`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ── Item builders ──
|
|
103
|
+
function buildSubagentRow(sub) {
|
|
104
|
+
const item = document.createElement("div");
|
|
105
|
+
item.className = "awaiting-item awaiting-item-subagent";
|
|
106
|
+
item.dataset.runId = sub.runId || "";
|
|
107
|
+
const label = sub.label || "Subagent";
|
|
108
|
+
const status = sub.status === "active" || !sub.endedAt ? "running" : sub.status;
|
|
109
|
+
const right = status === "running" ? formatRuntime(sub) : status;
|
|
110
|
+
item.innerHTML = `
|
|
111
|
+
<span class="awaiting-glyph awaiting-glyph-subagent">◆</span>
|
|
112
|
+
<span class="awaiting-label">${escHtml(label)}</span>
|
|
113
|
+
<span class="awaiting-meta">${escHtml(right)}</span>
|
|
114
|
+
`;
|
|
115
|
+
return item;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function buildScheduleRow(job) {
|
|
119
|
+
const item = document.createElement("div");
|
|
120
|
+
item.className = "awaiting-item awaiting-item-schedule";
|
|
121
|
+
if (!job.enabled) {
|
|
122
|
+
item.classList.add("awaiting-item-disabled");
|
|
123
|
+
}
|
|
124
|
+
item.dataset.scheduleId = job.id || "";
|
|
125
|
+
item.tabIndex = 0;
|
|
126
|
+
item.setAttribute("role", "button");
|
|
127
|
+
const name = job.name || "Unnamed";
|
|
128
|
+
const eta = job.enabled ? formatEta(job.state?.nextRunAtMs) : "off";
|
|
129
|
+
item.innerHTML = `
|
|
130
|
+
<span class="awaiting-glyph awaiting-glyph-schedule" data-action="toggle" title="${job.enabled ? "Disable" : "Enable"}">⏱</span>
|
|
131
|
+
<span class="awaiting-label">${escHtml(name)}</span>
|
|
132
|
+
<span class="awaiting-meta">${escHtml(eta)}</span>
|
|
133
|
+
`;
|
|
134
|
+
// Toggle on the glyph; edit modal on the row.
|
|
135
|
+
item.addEventListener("click", (e) => {
|
|
136
|
+
if (e.target instanceof Element && e.target.dataset.action === "toggle") {
|
|
137
|
+
e.stopPropagation();
|
|
138
|
+
if (typeof window.schedulingPanel?.toggle === "function") {
|
|
139
|
+
void window.schedulingPanel.toggle(job.id);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (typeof window.schedulingPanel?.openForEdit === "function") {
|
|
144
|
+
window.schedulingPanel.openForEdit(job);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
item.addEventListener("keydown", (e) => {
|
|
148
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
if (typeof window.schedulingPanel?.openForEdit === "function") {
|
|
151
|
+
window.schedulingPanel.openForEdit(job);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return item;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ── Render ──
|
|
159
|
+
function render() {
|
|
160
|
+
const activeSubagents = subagents
|
|
161
|
+
.filter((s) => s.status === "active" || !s.endedAt)
|
|
162
|
+
.toSorted((a, b) => (b.startedAt || 0) - (a.startedAt || 0));
|
|
163
|
+
|
|
164
|
+
const sortedSchedules = schedules.toSorted((a, b) => {
|
|
165
|
+
// Enabled first; then by next ETA ascending; disabled tail
|
|
166
|
+
if (a.enabled !== b.enabled) {
|
|
167
|
+
return b.enabled ? 1 : -1;
|
|
168
|
+
}
|
|
169
|
+
return (a.state?.nextRunAtMs || Infinity) - (b.state?.nextRunAtMs || Infinity);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const totalActive = activeSubagents.length + sortedSchedules.filter((s) => s.enabled).length;
|
|
173
|
+
|
|
174
|
+
// Hide entire footer when nothing's pending and no schedules exist —
|
|
175
|
+
// a quiet panel is part of the design. Show whenever there's any
|
|
176
|
+
// activity or any scheduled job (even disabled — so user can re-enable).
|
|
177
|
+
const hasAny = activeSubagents.length > 0 || sortedSchedules.length > 0;
|
|
178
|
+
root.hidden = !hasAny && !addMenuOpen;
|
|
179
|
+
|
|
180
|
+
// Count badge: "N active" (in-flight subagents + enabled schedules)
|
|
181
|
+
if (countEl) {
|
|
182
|
+
if (totalActive === 0) {
|
|
183
|
+
countEl.textContent = "";
|
|
184
|
+
} else {
|
|
185
|
+
const subPart =
|
|
186
|
+
activeSubagents.length > 0
|
|
187
|
+
? `${activeSubagents.length} sub${activeSubagents.length !== 1 ? "s" : ""}`
|
|
188
|
+
: null;
|
|
189
|
+
const schedPart =
|
|
190
|
+
sortedSchedules.filter((s) => s.enabled).length > 0
|
|
191
|
+
? `${sortedSchedules.filter((s) => s.enabled).length} job${sortedSchedules.filter((s) => s.enabled).length !== 1 ? "s" : ""}`
|
|
192
|
+
: null;
|
|
193
|
+
countEl.textContent = [subPart, schedPart].filter(Boolean).join(" · ");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!list) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
list.innerHTML = "";
|
|
201
|
+
for (const sub of activeSubagents) {
|
|
202
|
+
list.appendChild(buildSubagentRow(sub));
|
|
203
|
+
}
|
|
204
|
+
for (const job of sortedSchedules) {
|
|
205
|
+
list.appendChild(buildScheduleRow(job));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ── Add menu ──
|
|
210
|
+
let addMenuOpen = false;
|
|
211
|
+
|
|
212
|
+
function openAddMenu() {
|
|
213
|
+
if (!addMenu || !addBtn) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
addMenuOpen = true;
|
|
217
|
+
addMenu.hidden = false;
|
|
218
|
+
addBtn.setAttribute("aria-expanded", "true");
|
|
219
|
+
// Ensure footer is visible while menu is open
|
|
220
|
+
root.hidden = false;
|
|
221
|
+
document.addEventListener("click", onOutsideClickAddMenu, true);
|
|
222
|
+
document.addEventListener("keydown", onAddMenuKey);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function closeAddMenu() {
|
|
226
|
+
if (!addMenu || !addBtn) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
addMenuOpen = false;
|
|
230
|
+
addMenu.hidden = true;
|
|
231
|
+
addBtn.setAttribute("aria-expanded", "false");
|
|
232
|
+
document.removeEventListener("click", onOutsideClickAddMenu, true);
|
|
233
|
+
document.removeEventListener("keydown", onAddMenuKey);
|
|
234
|
+
render(); // re-evaluate hidden state
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function onOutsideClickAddMenu(e) {
|
|
238
|
+
if (!addMenu || !addBtn) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (e.target instanceof Node) {
|
|
242
|
+
if (addMenu.contains(e.target) || addBtn.contains(e.target)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
closeAddMenu();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function onAddMenuKey(e) {
|
|
250
|
+
if (e.key === "Escape") {
|
|
251
|
+
closeAddMenu();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ── Init ──
|
|
256
|
+
function init() {
|
|
257
|
+
window.addEventListener("symi:subagents-updated", (e) => {
|
|
258
|
+
subagents = e.detail?.subagents || [];
|
|
259
|
+
render();
|
|
260
|
+
});
|
|
261
|
+
window.addEventListener("symi:schedules-updated", (e) => {
|
|
262
|
+
schedules = e.detail?.schedules || [];
|
|
263
|
+
render();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
if (addBtn) {
|
|
267
|
+
addBtn.addEventListener("click", (e) => {
|
|
268
|
+
e.stopPropagation();
|
|
269
|
+
if (addMenuOpen) {
|
|
270
|
+
closeAddMenu();
|
|
271
|
+
} else {
|
|
272
|
+
openAddMenu();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
if (addMenu) {
|
|
277
|
+
addMenu.addEventListener("click", (e) => {
|
|
278
|
+
const target = e.target instanceof Element ? e.target.closest("[data-add]") : null;
|
|
279
|
+
if (!target) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const which = target.getAttribute("data-add");
|
|
283
|
+
closeAddMenu();
|
|
284
|
+
if (which === "subagent" && typeof window.subagentsPanel?.open === "function") {
|
|
285
|
+
window.subagentsPanel.open();
|
|
286
|
+
} else if (which === "schedule" && typeof window.schedulingPanel?.open === "function") {
|
|
287
|
+
window.schedulingPanel.open();
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// First paint
|
|
293
|
+
render();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (document.readyState === "loading") {
|
|
297
|
+
document.addEventListener("DOMContentLoaded", init);
|
|
298
|
+
} else {
|
|
299
|
+
init();
|
|
300
|
+
}
|
|
301
|
+
})();
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// ── Symframe Pin Store ──────────────────────────────────────────────────────
|
|
2
|
+
// Stage C of the Dynamic Glass Panel arc — see ~/Documents/dynamic-glass-panel.md §9.3.
|
|
3
|
+
//
|
|
4
|
+
// Per-browser pin persistence via localStorage. Pinned cards survive
|
|
5
|
+
// page reload, /new, and gateway reconnect — they are user-curated
|
|
6
|
+
// state, not agent-pushed state.
|
|
7
|
+
//
|
|
8
|
+
// Storage shape:
|
|
9
|
+
// localStorage["symi:symframe:pins"] = JSON.stringify({
|
|
10
|
+
// version: 1,
|
|
11
|
+
// pins: [
|
|
12
|
+
// { id, card: {...}, pinnedAt: <ms> },
|
|
13
|
+
// ...
|
|
14
|
+
// ]
|
|
15
|
+
// })
|
|
16
|
+
//
|
|
17
|
+
// `card` is a snapshot of the card at pin time — frozen content. A
|
|
18
|
+
// dynamic card whose content changes after pinning will keep the
|
|
19
|
+
// pinned-time snapshot in the registry on next reload (intentional;
|
|
20
|
+
// the user pinned what they saw).
|
|
21
|
+
//
|
|
22
|
+
// Public API (window.symframePinStore):
|
|
23
|
+
// list() — snapshot of all pinned card records
|
|
24
|
+
// pin(card) — write a card to localStorage (idempotent on id)
|
|
25
|
+
// unpin(id) — remove a card from localStorage by id
|
|
26
|
+
// isPinned(id) — boolean check
|
|
27
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
"use strict";
|
|
30
|
+
|
|
31
|
+
(function () {
|
|
32
|
+
const KEY = "symi:symframe:pins";
|
|
33
|
+
const VERSION = 1;
|
|
34
|
+
|
|
35
|
+
function readStore() {
|
|
36
|
+
try {
|
|
37
|
+
const raw = localStorage.getItem(KEY);
|
|
38
|
+
if (!raw) {
|
|
39
|
+
return { version: VERSION, pins: [] };
|
|
40
|
+
}
|
|
41
|
+
const parsed = JSON.parse(raw);
|
|
42
|
+
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.pins)) {
|
|
43
|
+
return { version: VERSION, pins: [] };
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.warn("[symframe-pin-store] read failed; resetting:", err);
|
|
48
|
+
return { version: VERSION, pins: [] };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function writeStore(store) {
|
|
53
|
+
try {
|
|
54
|
+
localStorage.setItem(KEY, JSON.stringify(store));
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.warn("[symframe-pin-store] write failed:", err);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function list() {
|
|
61
|
+
return readStore().pins;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function pin(card) {
|
|
65
|
+
if (!card || typeof card !== "object" || !card.id) {
|
|
66
|
+
console.warn("[symframe-pin-store] pin: card missing id");
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const store = readStore();
|
|
70
|
+
const existing = store.pins.findIndex((p) => p.id === card.id);
|
|
71
|
+
const record = {
|
|
72
|
+
id: card.id,
|
|
73
|
+
card: { ...card, pinned: true },
|
|
74
|
+
pinnedAt: Date.now(),
|
|
75
|
+
};
|
|
76
|
+
if (existing >= 0) {
|
|
77
|
+
store.pins[existing] = record;
|
|
78
|
+
} else {
|
|
79
|
+
store.pins.push(record);
|
|
80
|
+
}
|
|
81
|
+
writeStore(store);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function unpin(id) {
|
|
86
|
+
if (!id) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const store = readStore();
|
|
90
|
+
const before = store.pins.length;
|
|
91
|
+
store.pins = store.pins.filter((p) => p.id !== id);
|
|
92
|
+
if (store.pins.length === before) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
writeStore(store);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function isPinned(id) {
|
|
100
|
+
return readStore().pins.some((p) => p.id === id);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
window.symframePinStore = { list, pin, unpin, isPinned };
|
|
104
|
+
})();
|
|
@@ -358,7 +358,21 @@
|
|
|
358
358
|
const titleSpan = document.createElement("span");
|
|
359
359
|
titleSpan.textContent = card.title || "";
|
|
360
360
|
header.appendChild(titleSpan);
|
|
361
|
-
|
|
361
|
+
// Stage C: pin glyph for pinned cards. Click toggles unpin.
|
|
362
|
+
if (card.pinned) {
|
|
363
|
+
const pinGlyph = document.createElement("button");
|
|
364
|
+
pinGlyph.className = "symframe-card-pin";
|
|
365
|
+
pinGlyph.type = "button";
|
|
366
|
+
pinGlyph.setAttribute("aria-label", "Unpin");
|
|
367
|
+
pinGlyph.title = "Pinned — click to unpin";
|
|
368
|
+
pinGlyph.textContent = "📌";
|
|
369
|
+
pinGlyph.addEventListener("click", (e) => {
|
|
370
|
+
e.preventDefault();
|
|
371
|
+
e.stopPropagation();
|
|
372
|
+
unpin(card.id);
|
|
373
|
+
});
|
|
374
|
+
header.appendChild(pinGlyph);
|
|
375
|
+
} else if (card.dismissable && !card.sticky) {
|
|
362
376
|
const dismiss = document.createElement("button");
|
|
363
377
|
dismiss.className = "symframe-card-dismiss";
|
|
364
378
|
dismiss.type = "button";
|
|
@@ -535,6 +549,12 @@
|
|
|
535
549
|
* Remove a card from the registry + DOM. Sticky cards refuse removal
|
|
536
550
|
* unless force=true is passed (defensive — the system panels really
|
|
537
551
|
* shouldn't disappear via stray API calls).
|
|
552
|
+
*
|
|
553
|
+
* Stage C: pinned cards behave like sticky for the user-side dismiss
|
|
554
|
+
* button (× hidden in the header) but `remove` still drops them when
|
|
555
|
+
* called — the pin survives in localStorage and the card re-appears
|
|
556
|
+
* on the next reload. To actually drop a pinned card permanently,
|
|
557
|
+
* the agent / user must unpin first.
|
|
538
558
|
*/
|
|
539
559
|
function remove(id, force = false) {
|
|
540
560
|
const entry = cards.get(id);
|
|
@@ -553,6 +573,180 @@
|
|
|
553
573
|
return true;
|
|
554
574
|
}
|
|
555
575
|
|
|
576
|
+
// ── Stage C: dwell / release / recall / pin / unpin ────────────────
|
|
577
|
+
// The CRUD vocabulary (add/update/remove) treats the panel as a
|
|
578
|
+
// notification list. These verbs treat it as a mind-window: cards
|
|
579
|
+
// can be foregrounded ("dwell"), softly let go of ("release"),
|
|
580
|
+
// brought back ("recall"), or persisted across sessions ("pin").
|
|
581
|
+
|
|
582
|
+
const RECENTLY_RELEASED_MAX = 10;
|
|
583
|
+
/** @type {Array<{id:string, card:object, releasedAt:number}>} */
|
|
584
|
+
const recentlyReleased = [];
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Pull a card to the top of the stack with a brief cyan border pulse.
|
|
588
|
+
* Implementation: prepend the element (newest-first stack order
|
|
589
|
+
* normally has it there if it was just added, but for older cards
|
|
590
|
+
* this lifts them up), then add a `dwelling` class for a 600ms
|
|
591
|
+
* CSS pulse animation. Sticky cards aren't reordered (they live at
|
|
592
|
+
* the anchored end of the stack by design).
|
|
593
|
+
*/
|
|
594
|
+
function dwell(id) {
|
|
595
|
+
const entry = cards.get(id);
|
|
596
|
+
if (!entry) {
|
|
597
|
+
console.warn(`[symframe] dwell: unknown id ${id}`);
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
if (!entry.element) {
|
|
601
|
+
console.warn(`[symframe] dwell: card ${id} has no element`);
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
if (!entry.sticky) {
|
|
605
|
+
// Re-prepend to bring to top of ephemeral stack.
|
|
606
|
+
container.prepend(entry.element);
|
|
607
|
+
}
|
|
608
|
+
entry.element.classList.remove("symframe-dwelling");
|
|
609
|
+
// Re-flow so the animation restarts even on repeated dwell calls.
|
|
610
|
+
void entry.element.offsetWidth;
|
|
611
|
+
entry.element.classList.add("symframe-dwelling");
|
|
612
|
+
setTimeout(() => entry.element?.classList.remove("symframe-dwelling"), 700);
|
|
613
|
+
return true;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Soft-dismiss a card. Animated fade + scale; on animation end the
|
|
618
|
+
* element is removed from the registry and DOM. Unlike `remove`,
|
|
619
|
+
* `release` records the card in a session ring buffer so `recall(id)`
|
|
620
|
+
* can bring it back. Sticky cards refuse release without force=true.
|
|
621
|
+
*/
|
|
622
|
+
function release(id, force = false) {
|
|
623
|
+
const entry = cards.get(id);
|
|
624
|
+
if (!entry) {
|
|
625
|
+
return false;
|
|
626
|
+
}
|
|
627
|
+
if (entry.sticky && !force) {
|
|
628
|
+
console.warn(`[symframe] release: refusing sticky card '${id}' without force=true`);
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
// Snapshot for recall (strip the live DOM element)
|
|
632
|
+
const snapshot = { ...entry };
|
|
633
|
+
delete snapshot.element;
|
|
634
|
+
recentlyReleased.unshift({
|
|
635
|
+
id,
|
|
636
|
+
card: snapshot,
|
|
637
|
+
releasedAt: Date.now(),
|
|
638
|
+
});
|
|
639
|
+
if (recentlyReleased.length > RECENTLY_RELEASED_MAX) {
|
|
640
|
+
recentlyReleased.length = RECENTLY_RELEASED_MAX;
|
|
641
|
+
}
|
|
642
|
+
// Animate then drop
|
|
643
|
+
const el = entry.element;
|
|
644
|
+
if (el) {
|
|
645
|
+
el.classList.add("symframe-releasing");
|
|
646
|
+
const cleanup = () => {
|
|
647
|
+
cards.delete(id);
|
|
648
|
+
if (el.parentElement === container) {
|
|
649
|
+
el.remove();
|
|
650
|
+
}
|
|
651
|
+
updateCount();
|
|
652
|
+
};
|
|
653
|
+
// Fail-safe: drop after the CSS transition window even if the
|
|
654
|
+
// transitionend event doesn't fire (browser bug, reduced motion).
|
|
655
|
+
const handle = setTimeout(cleanup, 900);
|
|
656
|
+
el.addEventListener(
|
|
657
|
+
"transitionend",
|
|
658
|
+
() => {
|
|
659
|
+
clearTimeout(handle);
|
|
660
|
+
cleanup();
|
|
661
|
+
},
|
|
662
|
+
{ once: true },
|
|
663
|
+
);
|
|
664
|
+
} else {
|
|
665
|
+
cards.delete(id);
|
|
666
|
+
updateCount();
|
|
667
|
+
}
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Re-summon a recently-released card from the session ring buffer.
|
|
673
|
+
* Calling `recall(id)` without an id recalls the most-recent release.
|
|
674
|
+
* If the id isn't in the buffer or the card already exists, no-op.
|
|
675
|
+
*/
|
|
676
|
+
function recall(id) {
|
|
677
|
+
const recordIdx = id
|
|
678
|
+
? recentlyReleased.findIndex((r) => r.id === id)
|
|
679
|
+
: recentlyReleased.length > 0
|
|
680
|
+
? 0
|
|
681
|
+
: -1;
|
|
682
|
+
if (recordIdx < 0) {
|
|
683
|
+
console.warn(`[symframe] recall: nothing to recall${id ? ` for id ${id}` : ""}`);
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
686
|
+
const [record] = recentlyReleased.splice(recordIdx, 1);
|
|
687
|
+
if (cards.has(record.id)) {
|
|
688
|
+
// Already restored elsewhere — no-op.
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
add(record.card);
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/** Snapshot of recently-released cards (most-recent first). */
|
|
696
|
+
function listRecentlyReleased() {
|
|
697
|
+
return recentlyReleased.slice();
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Pin a card to localStorage so it survives reload + /new. Idempotent
|
|
702
|
+
* on id. The card is marked `pinned: true` so the dismiss button is
|
|
703
|
+
* hidden. Calling pin on an unknown id is a no-op.
|
|
704
|
+
*/
|
|
705
|
+
function pin(id) {
|
|
706
|
+
const entry = cards.get(id);
|
|
707
|
+
if (!entry) {
|
|
708
|
+
console.warn(`[symframe] pin: unknown id ${id}`);
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
if (typeof window.symframePinStore?.pin !== "function") {
|
|
712
|
+
console.warn("[symframe] pin: pin-store unavailable");
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
const snapshot = { ...entry };
|
|
716
|
+
delete snapshot.element;
|
|
717
|
+
snapshot.pinned = true;
|
|
718
|
+
snapshot.dismissable = false;
|
|
719
|
+
window.symframePinStore.pin(snapshot);
|
|
720
|
+
// Update live entry so the chrome reflects the pin (no dismiss btn,
|
|
721
|
+
// pin glyph in header).
|
|
722
|
+
entry.pinned = true;
|
|
723
|
+
entry.dismissable = false;
|
|
724
|
+
if (entry.element) {
|
|
725
|
+
const newEl = renderCardElement(entry);
|
|
726
|
+
entry.element.replaceWith(newEl);
|
|
727
|
+
entry.element = newEl;
|
|
728
|
+
}
|
|
729
|
+
return true;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/** Inverse of pin. Removes from localStorage; does NOT drop the card. */
|
|
733
|
+
function unpin(id) {
|
|
734
|
+
const entry = cards.get(id);
|
|
735
|
+
if (typeof window.symframePinStore?.unpin === "function") {
|
|
736
|
+
window.symframePinStore.unpin(id);
|
|
737
|
+
}
|
|
738
|
+
if (entry) {
|
|
739
|
+
entry.pinned = false;
|
|
740
|
+
entry.dismissable = true;
|
|
741
|
+
if (entry.element) {
|
|
742
|
+
const newEl = renderCardElement(entry);
|
|
743
|
+
entry.element.replaceWith(newEl);
|
|
744
|
+
entry.element = newEl;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
|
|
556
750
|
/** Snapshot of all registered cards. */
|
|
557
751
|
function list() {
|
|
558
752
|
return Array.from(cards.values());
|
|
@@ -586,7 +780,20 @@
|
|
|
586
780
|
}
|
|
587
781
|
}
|
|
588
782
|
|
|
589
|
-
window.symframe = {
|
|
783
|
+
window.symframe = {
|
|
784
|
+
add,
|
|
785
|
+
update,
|
|
786
|
+
remove,
|
|
787
|
+
list,
|
|
788
|
+
register,
|
|
789
|
+
// Stage C — attention verbs
|
|
790
|
+
dwell,
|
|
791
|
+
release,
|
|
792
|
+
recall,
|
|
793
|
+
pin,
|
|
794
|
+
unpin,
|
|
795
|
+
listRecentlyReleased,
|
|
796
|
+
};
|
|
590
797
|
|
|
591
798
|
// Phase 3: server-pushed cards. The gateway's `symframe` broadcast is
|
|
592
799
|
// re-emitted as a window-level CustomEvent by gateway.js — subscribe
|
|
@@ -594,6 +801,8 @@
|
|
|
594
801
|
// chat.symframe.push RPC: { action, id?, card?, force? }.
|
|
595
802
|
// Stage A: `force` flows through to update/remove so the agent (via
|
|
596
803
|
// display_artifact) and the CLI can override the sticky-card guard.
|
|
804
|
+
// Stage C: new verbs (dwell / release / recall / pin / unpin) route
|
|
805
|
+
// alongside the existing CRUD trio.
|
|
597
806
|
window.addEventListener("symi:symframe", (e) => {
|
|
598
807
|
const payload = e.detail;
|
|
599
808
|
if (!payload || typeof payload !== "object") {
|
|
@@ -606,6 +815,33 @@
|
|
|
606
815
|
update(payload.id, payload.card, force);
|
|
607
816
|
} else if (payload.action === "remove" && payload.id) {
|
|
608
817
|
remove(payload.id, force);
|
|
818
|
+
} else if (payload.action === "dwell" && payload.id) {
|
|
819
|
+
dwell(payload.id);
|
|
820
|
+
} else if (payload.action === "release" && payload.id) {
|
|
821
|
+
release(payload.id, force);
|
|
822
|
+
} else if (payload.action === "recall") {
|
|
823
|
+
recall(payload.id);
|
|
824
|
+
} else if (payload.action === "pin" && payload.id) {
|
|
825
|
+
pin(payload.id);
|
|
826
|
+
} else if (payload.action === "unpin" && payload.id) {
|
|
827
|
+
unpin(payload.id);
|
|
609
828
|
}
|
|
610
829
|
});
|
|
830
|
+
|
|
831
|
+
// Stage C: restore pinned cards from localStorage on boot. Pinned
|
|
832
|
+
// cards are user-curated state and survive reload, /new, and gateway
|
|
833
|
+
// reconnect. Each pin is a snapshot; the registry re-adds it as a
|
|
834
|
+
// dynamic card with pinned=true (no dismiss button).
|
|
835
|
+
if (typeof window.symframePinStore?.list === "function") {
|
|
836
|
+
try {
|
|
837
|
+
const pinned = window.symframePinStore.list();
|
|
838
|
+
for (const record of pinned) {
|
|
839
|
+
if (record?.card && !cards.has(record.id)) {
|
|
840
|
+
add({ ...record.card, pinned: true, dismissable: false });
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
} catch (err) {
|
|
844
|
+
console.warn("[symframe] failed to restore pinned cards:", err);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
611
847
|
})();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { f as defaultRuntime } from "./subsystem-CHbO_DkH.js";
|
|
2
|
-
import { n as resolveSymiPackageRootSync, t as resolveSymiPackageRoot } from "./symi-root-
|
|
2
|
+
import { n as resolveSymiPackageRootSync, t as resolveSymiPackageRoot } from "./symi-root-DeCVdZB4.js";
|
|
3
3
|
import { t as runCommandWithTimeout } from "./exec-DuYbft0z.js";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import path from "node:path";
|