@deepseek-insight/dsi 0.8.4 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/.agents/skills/glass-dsi/SKILL.md +195 -0
  2. package/.agents/skills/glass-dsi/references/cdp-verification.md +132 -0
  3. package/.agents/skills/glass-dsi/scripts/_connect.mjs +81 -0
  4. package/.agents/skills/glass-dsi/scripts/glass-url.mjs +48 -0
  5. package/.agents/skills/glass-dsi/scripts/glass.mjs +84 -0
  6. package/.agents/skills/glass-url/SKILL.md +117 -0
  7. package/.agents/skills/glass-url/scripts/_args.mjs +49 -0
  8. package/.agents/skills/glass-url/scripts/_connect.mjs +99 -0
  9. package/.agents/skills/glass-url/scripts/glass-url.mjs +114 -0
  10. package/bin/dsi.mjs +23 -74
  11. package/bin/lib/zai-patch.mjs +115 -0
  12. package/build/client/_app/immutable/assets/0.Ch5VtsKp.css +2 -0
  13. package/build/client/_app/immutable/assets/2.D0QOh44D.css +1 -0
  14. package/build/client/_app/immutable/chunks/{DwcY-69G.js → 02Wfo2G3.js} +1 -1
  15. package/build/client/_app/immutable/chunks/0Tfhif1V.js +3 -0
  16. package/build/client/_app/immutable/chunks/{GKkjunMm.js → 0ruuBBbh.js} +2 -2
  17. package/build/client/_app/immutable/chunks/{DUCaFYlx.js → 4bHE1npv.js} +1 -1
  18. package/build/client/_app/immutable/chunks/{4cwyag_I.js → B4hDUAJl.js} +1 -1
  19. package/build/client/_app/immutable/chunks/{Cr2ck_ss.js → BIPXB-2I.js} +1 -1
  20. package/build/client/_app/immutable/chunks/{CeLBjOd9.js → BIgv-kQR.js} +1 -1
  21. package/build/client/_app/immutable/chunks/BK6k1nBs.js +1 -0
  22. package/build/client/_app/immutable/chunks/{SN3Efo-Q.js → BKwmKcDY.js} +1 -1
  23. package/build/client/_app/immutable/chunks/{CRFuOqJI.js → BORjuqef.js} +1 -1
  24. package/build/client/_app/immutable/chunks/{CH_bR_0j.js → BPmZB0-N.js} +1 -1
  25. package/build/client/_app/immutable/chunks/BROtno1Y.js +1 -0
  26. package/build/client/_app/immutable/chunks/{DEVxi5CK.js → BT5Iel00.js} +1 -1
  27. package/build/client/_app/immutable/chunks/{DdI16loP.js → BX3y_1Hh.js} +1 -1
  28. package/build/client/_app/immutable/chunks/{DuiFyTVb.js → Bea1gxLq.js} +1 -1
  29. package/build/client/_app/immutable/chunks/{D0uxHECr.js → BpkpgvVw.js} +1 -1
  30. package/build/client/_app/immutable/chunks/{CB55Rp7-.js → BreZS7EW.js} +1 -1
  31. package/build/client/_app/immutable/chunks/{BmDADyfH.js → BsS_byzk.js} +1 -1
  32. package/build/client/_app/immutable/chunks/{BWRXzjmQ.js → Bslg-dr5.js} +1 -1
  33. package/build/client/_app/immutable/chunks/{BkYT72a1.js → C-YczRN1.js} +1 -1
  34. package/build/client/_app/immutable/chunks/{DBKMIEwD.js → C2aW4lzo.js} +1 -1
  35. package/build/client/_app/immutable/chunks/{C4gs6zoI.js → C2qFXaz5.js} +1 -1
  36. package/build/client/_app/immutable/chunks/{BBd0nTHG.js → C5RyRpOh.js} +1 -1
  37. package/build/client/_app/immutable/chunks/{DJQr4efH.js → C5iHDVU_.js} +1 -1
  38. package/build/client/_app/immutable/chunks/{B4F5liKq.js → C7opVlLF.js} +1 -1
  39. package/build/client/_app/immutable/chunks/{DIxy2USu.js → CAuEkmZ4.js} +1 -1
  40. package/build/client/_app/immutable/chunks/{BO99LSSA.js → CIkiqgtA.js} +1 -1
  41. package/build/client/_app/immutable/chunks/{Bpd0I3U7.js → CJesWaZn.js} +1 -1
  42. package/build/client/_app/immutable/chunks/{at6PQqQ4.js → CRsoS5Y9.js} +1 -1
  43. package/build/client/_app/immutable/chunks/CTWtsoJD.js +6 -0
  44. package/build/client/_app/immutable/chunks/CWk5gmU2.js +1 -0
  45. package/build/client/_app/immutable/chunks/{lF8CNVOA.js → CXkrluSK.js} +1 -1
  46. package/build/client/_app/immutable/chunks/{DmRY6FWm.js → C_8kFZ_X.js} +4 -4
  47. package/build/client/_app/immutable/chunks/{D6KenyiF.js → Ch7hUoAH.js} +1 -1
  48. package/build/client/_app/immutable/chunks/{CnzmIbjr.js → ChmmHPdM.js} +1 -1
  49. package/build/client/_app/immutable/chunks/{DfUgh5E_.js → CjajmcJs.js} +1 -1
  50. package/build/client/_app/immutable/chunks/{q5PRaRZk.js → Ck6GS6Vb.js} +1 -1
  51. package/build/client/_app/immutable/chunks/{eFcFJ9Ld.js → ClGoDr_f.js} +1 -1
  52. package/build/client/_app/immutable/chunks/{BQC6O_RV.js → ClqGHlec.js} +1 -1
  53. package/build/client/_app/immutable/chunks/{zypfUZYM.js → CnW6hje6.js} +1 -1
  54. package/build/client/_app/immutable/chunks/{OW5Q7tGb.js → CpI6VYCH.js} +1 -1
  55. package/build/client/_app/immutable/chunks/{BXKc4uuX.js → CygwwaiE.js} +1 -1
  56. package/build/client/_app/immutable/chunks/{Bqwvv7Vf.js → CyhZtsZO.js} +35 -35
  57. package/build/client/_app/immutable/chunks/{BenkQ_4r.js → D-E2Noqq.js} +1 -1
  58. package/build/client/_app/immutable/chunks/{DuRZnRVw.js → D4Btzp_A.js} +1 -1
  59. package/build/client/_app/immutable/chunks/{CdaJvl_A.js → D4C3Jijv.js} +1 -1
  60. package/build/client/_app/immutable/chunks/D9jhmf3I.js +1 -0
  61. package/build/client/_app/immutable/chunks/{Cf0aMC4n.js → DCw0gAtv.js} +1 -1
  62. package/build/client/_app/immutable/chunks/{B6bTO8_7.js → DEW3KpiC.js} +1 -1
  63. package/build/client/_app/immutable/chunks/{O6xxeEm8.js → DYLFbKJe.js} +1 -1
  64. package/build/client/_app/immutable/chunks/{BsBBq-Qk.js → DYu7kgVa.js} +1 -1
  65. package/build/client/_app/immutable/chunks/Dfexc5qV.js +1 -0
  66. package/build/client/_app/immutable/chunks/{kzciT-3i.js → DhmUE8Ri.js} +1 -1
  67. package/build/client/_app/immutable/chunks/{DdJNsJBH.js → DjwX3rAC.js} +1 -1
  68. package/build/client/_app/immutable/chunks/{CajOZJDl.js → DlOfy8Sx.js} +1 -1
  69. package/build/client/_app/immutable/chunks/{CK5vhXvt.js → Do7Y1_MQ.js} +1 -1
  70. package/build/client/_app/immutable/chunks/{ap4GAVq-.js → Dq2XIb1m.js} +1 -1
  71. package/build/client/_app/immutable/chunks/{Czey8tDK.js → DuT_Qr5k.js} +1 -1
  72. package/build/client/_app/immutable/chunks/{4B6J_kM2.js → DyGggFea.js} +1 -1
  73. package/build/client/_app/immutable/chunks/{D0ChUnpi.js → Dym4i64U.js} +1 -1
  74. package/build/client/_app/immutable/chunks/FPsIAiN_.js +1 -0
  75. package/build/client/_app/immutable/chunks/{CevKuuic.js → GIczpP_D.js} +1 -1
  76. package/build/client/_app/immutable/chunks/{B2jrDnt8.js → LjOLSmU7.js} +1 -1
  77. package/build/client/_app/immutable/chunks/VtK73aN-.js +8 -0
  78. package/build/client/_app/immutable/chunks/{AcmOeh2U.js → ZqoQH_jm.js} +1 -1
  79. package/build/client/_app/immutable/chunks/{BlwWx85l.js → aXn6rE_7.js} +1 -1
  80. package/build/client/_app/immutable/chunks/{Czc4_W7v.js → dUOeoGwg.js} +1 -1
  81. package/build/client/_app/immutable/chunks/f50lp1rr.js +1 -0
  82. package/build/client/_app/immutable/chunks/{7FnrqGK9.js → lvLrv1cG.js} +1 -1
  83. package/build/client/_app/immutable/chunks/{CZoElI5B.js → pt3_jHwh.js} +1 -1
  84. package/build/client/_app/immutable/chunks/{Byu_teLA.js → q8irUX-p.js} +1 -1
  85. package/build/client/_app/immutable/chunks/{CnxoqrkQ.js → qmOgUo3c.js} +1 -1
  86. package/build/client/_app/immutable/chunks/vpNeypNM.js +1 -0
  87. package/build/client/_app/immutable/chunks/{DU8C5thd.js → xvTPLhcB.js} +1 -1
  88. package/build/client/_app/immutable/chunks/{DFBKiA2Z.js → zp7hrpsC.js} +1 -1
  89. package/build/client/_app/immutable/entry/app.D4oc_iez.js +2 -0
  90. package/build/client/_app/immutable/entry/start.Xkr2MCWg.js +1 -0
  91. package/build/client/_app/immutable/nodes/0.fsrqKU9i.js +1 -0
  92. package/build/client/_app/immutable/nodes/1.3F37GwcO.js +1 -0
  93. package/build/client/_app/immutable/nodes/2.DsWNNw0K.js +340 -0
  94. package/build/client/_app/version.json +1 -1
  95. package/build/handler.js +6 -6
  96. package/build/index.js +6 -6
  97. package/build/server/chunks/chunks/{app-config.svelte.js-BM4WbMFB.js → app-config.svelte.js-BXjvTmJu.js} +8 -3
  98. package/build/server/chunks/chunks/{config.js-vThvQeMn.js → config.js-r_jw_bQQ.js} +54 -2
  99. package/build/server/chunks/chunks/{db.js-DQm6CZ_r.js → db.js-f2PmBjyD.js} +2 -2
  100. package/build/server/chunks/chunks/{db2.js-DUhFxA3a.js → db2.js-DkwY64WO.js} +2 -2
  101. package/build/server/chunks/chunks/{dsh-connection.js-BgeraFA2.js → dsh-connection.js-BW07Aicl.js} +18 -10
  102. package/build/server/chunks/chunks/{dsh-events.js-BUkLR6ZV.js → dsh-events.js-BHf0lLZ5.js} +16 -3
  103. package/build/server/chunks/chunks/{git-probe.js-CLF37SRh.js → git-probe.js-CQqTV7XX.js} +3 -3
  104. package/build/server/chunks/chunks/{index-server.js-DmIEbDVz.js → index-server.js-CPkVoRxB.js} +2 -2
  105. package/build/server/chunks/chunks/{insight-config.js-Dp_2gB5J.js → insight-config.js-C5-Rhh5A.js} +19 -6
  106. package/build/server/chunks/chunks/{internal2.js-J3h-US64.js → internal2.js-DbC8VGqD.js} +4 -4
  107. package/build/server/chunks/chunks/ledger-stats.js-BWACyDPg.js +72 -0
  108. package/build/server/chunks/chunks/{registry.js-CZNJZ0C-.js → registry.js-CWnRQ4vx.js} +751 -53
  109. package/build/server/chunks/chunks/{registry2.js-D3Pr1Rv9.js → registry2.js-CFzpvj9c.js} +17 -1
  110. package/build/server/chunks/chunks/{server.js-B1bDXhHu.js → server.js-Dijo7DtV.js} +2 -2
  111. package/build/server/chunks/chunks/{settings-document.js-Gw1puaik.js → settings-document.js-DxKURfc_.js} +2 -2
  112. package/build/server/chunks/chunks/{state.js-8RBD56dL.js → state.js-DR4xiIVw.js} +5 -5
  113. package/build/server/chunks/chunks/{watcher.js-BVKnoQUw.js → watcher.js-DvlNn8X0.js} +5 -5
  114. package/build/server/chunks/entries/endpoints/api/a2a/_id_/{_server.ts.js-BjzdVwdY.js → _server.ts.js-DItDXV23.js} +5 -5
  115. package/build/server/chunks/entries/endpoints/api/a2a/{_server.ts.js-3kQCQuHT.js → _server.ts.js-Hor8QZb1.js} +8 -8
  116. package/build/server/chunks/entries/endpoints/api/a2a/register/{_server.ts.js-BUBTCLFn.js → _server.ts.js-CEvvsa8B.js} +8 -8
  117. package/build/server/chunks/entries/endpoints/api/browser/_id_/activate/{_server.ts.js-BdMJzENm.js → _server.ts.js-sXqf-okw.js} +5 -5
  118. package/build/server/chunks/entries/endpoints/api/browser/_id_/close/{_server.ts.js-B5z9-N8Y.js → _server.ts.js-Byj9ApJh.js} +5 -5
  119. package/build/server/chunks/entries/endpoints/api/browser/_id_/closetab/{_server.ts.js-CnZHun5r.js → _server.ts.js-DOIsrzvg.js} +16 -9
  120. package/build/server/chunks/entries/endpoints/api/browser/_id_/element/{_server.ts.js-C1oM2Ihf.js → _server.ts.js-Cq3gmRfE.js} +5 -5
  121. package/build/server/chunks/entries/endpoints/api/browser/_id_/history/_server.ts.js-BGSLIV0t.js +61 -0
  122. package/build/server/chunks/entries/endpoints/api/browser/_id_/input/{_server.ts.js-DmbqGRMg.js → _server.ts.js-8slca75-.js} +5 -5
  123. package/build/server/chunks/entries/endpoints/api/browser/_id_/mcp/{_server.ts.js-Cj80T1yH.js → _server.ts.js-CpbdTYds.js} +5 -5
  124. package/build/server/chunks/entries/endpoints/api/browser/_id_/navigate/{_server.ts.js-6gi1UYTJ.js → _server.ts.js-Bls9LtLY.js} +5 -5
  125. package/build/server/chunks/entries/endpoints/api/browser/_id_/opentab/{_server.ts.js-Bhx_J7ot.js → _server.ts.js-DqNi_iW_.js} +5 -5
  126. package/build/server/chunks/entries/endpoints/api/browser/_id_/page/{_server.ts.js-DvQXNnX9.js → _server.ts.js-DuXWwo7i.js} +5 -5
  127. package/build/server/chunks/entries/endpoints/api/browser/_id_/stream/{_server.ts.js-MflkVWUn.js → _server.ts.js-DXfqBDEw.js} +38 -9
  128. package/build/server/chunks/entries/endpoints/api/browser/_id_/tabs/{_server.ts.js-CoUSlLcP.js → _server.ts.js-Bgnl8lYs.js} +5 -5
  129. package/build/server/chunks/entries/endpoints/api/browser/_id_/viewport/{_server.ts.js-DNk4EgjJ.js → _server.ts.js-FHmQVbrv.js} +5 -5
  130. package/build/server/chunks/entries/endpoints/api/browser/_id_/zoom/_server.ts.js-BV4cBtSA.js +62 -0
  131. package/build/server/chunks/entries/endpoints/api/browser/{_server.ts.js-CECKap7O.js → _server.ts.js-4vgkwh7v.js} +9 -6
  132. package/build/server/chunks/entries/endpoints/api/config/{_server.ts.js-C8XDnDwe.js → _server.ts.js-C_9kwANR.js} +16 -6
  133. package/build/server/chunks/entries/endpoints/api/dsh/directory/{_server.ts.js-BFmWshpv.js → _server.ts.js-h1OTHcL4.js} +5 -5
  134. package/build/server/chunks/entries/endpoints/api/dsh/jobs/{_server.ts.js-DATWy5mQ.js → _server.ts.js-B6nih9Sd.js} +5 -5
  135. package/build/server/chunks/entries/endpoints/api/dsh/jobs/follow/{_server.ts.js-CugOD1Zd.js → _server.ts.js-Cf17SVmD.js} +5 -5
  136. package/build/server/chunks/entries/endpoints/api/dsh/pick-directory/{_server.ts.js-DCupM4da.js → _server.ts.js-DjNwMbdS.js} +5 -5
  137. package/build/server/chunks/entries/endpoints/api/dsh/presets/{_server.ts.js-Bh1btvr9.js → _server.ts.js-Cz5aaEhC.js} +5 -5
  138. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/attachment/_server.ts.js-BFBy5O9Y.js +78 -0
  139. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/cancel/{_server.ts.js-WI9yH2iG.js → _server.ts.js-CgEdCo3T.js} +5 -5
  140. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/catalog/{_server.ts.js-bN9adUqz.js → _server.ts.js-Bo_aEnHh.js} +5 -5
  141. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/changes/{_server.ts.js-Bxlm966G.js → _server.ts.js-Bd2G_GaH.js} +5 -5
  142. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/command/{_server.ts.js-CM-raN_Q.js → _server.ts.js-DL64FyRw.js} +5 -5
  143. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/events/{_server.ts.js-BzP30TXW.js → _server.ts.js-MhOGB66D.js} +7 -70
  144. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/fork/{_server.ts.js-DvNkrTaY.js → _server.ts.js-MjPgXgGO.js} +5 -5
  145. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/goal/{_server.ts.js-DXbCrefw.js → _server.ts.js-BUjDae5H.js} +5 -5
  146. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/history/{_server.ts.js-B7YRQhuJ.js → _server.ts.js-dTKd7Hsv.js} +6 -6
  147. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/models/{_server.ts.js-C_AEaLLJ.js → _server.ts.js-B82rvKoI.js} +5 -5
  148. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/path/{_server.ts.js-Dj-pF5ik.js → _server.ts.js-Cqijsi-c.js} +4 -4
  149. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/permission/{_server.ts.js-BX9FWJ6g.js → _server.ts.js-CL_vVv2p.js} +29 -6
  150. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/prompt/{_server.ts.js-CQ2Bmtu4.js → _server.ts.js-WS4W9Ly4.js} +5 -5
  151. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/rename/{_server.ts.js-Ha7xjnKW.js → _server.ts.js-B72KGRGh.js} +5 -5
  152. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/respond/{_server.ts.js-BOg6llHk.js → _server.ts.js-DK5xb2b5.js} +5 -5
  153. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/select-model/{_server.ts.js-DBqGALzZ.js → _server.ts.js-lhT87EQu.js} +5 -5
  154. package/build/server/chunks/entries/endpoints/api/dsh/sessions/{_server.ts.js-CvA8WDDb.js → _server.ts.js-CMhfhbkN.js} +5 -5
  155. package/build/server/chunks/entries/endpoints/api/dsh/subagents/_server.ts.js-BLvcFsg6.js +72 -0
  156. package/build/server/chunks/entries/endpoints/api/dsh/workspace-file/{_server.ts.js-BfjNH40j.js → _server.ts.js-D_rw2Uq6.js} +5 -5
  157. package/build/server/chunks/entries/endpoints/api/dsh/workspace-tree/{_server.ts.js-De_qumyr.js → _server.ts.js-DfXpMMpw.js} +5 -5
  158. package/build/server/chunks/entries/endpoints/api/dsh/workspaces/{_server.ts.js-tFpJJHCb.js → _server.ts.js-2mJCJVxk.js} +5 -5
  159. package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/delete/{_server.ts.js-DVx5GGA_.js → _server.ts.js-BCx0Lzjf.js} +5 -5
  160. package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/rename/{_server.ts.js-DuKT-aZp.js → _server.ts.js-DECaSjwp.js} +5 -5
  161. package/build/server/chunks/entries/endpoints/api/prompts/_id_/{_server.ts.js-DsWFidFY.js → _server.ts.js-i_ciJzlb.js} +5 -5
  162. package/build/server/chunks/entries/endpoints/api/prompts/{_server.ts.js-C6j0adQs.js → _server.ts.js-BO1pScn7.js} +5 -5
  163. package/build/server/chunks/entries/endpoints/api/prompts/use/{_server.ts.js-BChAg4hm.js → _server.ts.js-Buhpf7WE.js} +5 -5
  164. package/build/server/chunks/entries/endpoints/api/settings/{_server.ts.js-BPSHqbZN.js → _server.ts.js-DngUQzcT.js} +4 -4
  165. package/build/server/chunks/entries/endpoints/api/terminal/_id_/output/{_server.ts.js-BNBxebgG.js → _server.ts.js-DLETP4yQ.js} +2 -2
  166. package/build/server/chunks/entries/endpoints/api/terminal/_id_/reattach/{_server.ts.js-DDRJBGIr.js → _server.ts.js-uWl6oxPS.js} +2 -2
  167. package/build/server/chunks/entries/endpoints/api/terminal/_id_/send/{_server.ts.js-CA0vc_Cm.js → _server.ts.js-DYNmXaAd.js} +9 -2
  168. package/build/server/chunks/entries/endpoints/api/terminal/_id_/stream/{_server.ts.js-D6L8Gd_f.js → _server.ts.js-C5m3Ktho.js} +2 -2
  169. package/build/server/chunks/entries/endpoints/api/terminal/{_server.ts.js-D5CbUe5k.js → _server.ts.js-DoTNvcOa.js} +5 -5
  170. package/build/server/chunks/entries/endpoints/api/workspace/file-write/{_server.ts.js-B-5YihUA.js → _server.ts.js-BzYOJSkI.js} +7 -7
  171. package/build/server/chunks/entries/endpoints/api/workspace/git-events/{_server.ts.js-DT5jRZFE.js → _server.ts.js-xcNesei9.js} +7 -7
  172. package/build/server/chunks/entries/endpoints/api/workspace/git-file-head/{_server.ts.js-DtW-utrd.js → _server.ts.js-DsJWYdxt.js} +7 -7
  173. package/build/server/chunks/entries/endpoints/api/workspace/git-map/{_server.ts.js-8AIAo9jX.js → _server.ts.js-CNCku9BR.js} +7 -7
  174. package/build/server/chunks/entries/endpoints/api/workspace/git-status/{_server.ts.js-CMw96vjY.js → _server.ts.js-nLsNjOxj.js} +7 -7
  175. package/build/server/chunks/entries/endpoints/api/workspace/write-gate/{_server.ts.js-DKufa14_.js → _server.ts.js-urQk2-ds.js} +7 -7
  176. package/build/server/chunks/entries/{hooks.server.js-B-e4_ekh.js → hooks.server.js-CU2RE5vs.js} +3 -3
  177. package/build/server/chunks/entries/pages/{_error.svelte.js-DRPduJdP.js → _error.svelte.js-e018KpwE.js} +6 -6
  178. package/build/server/chunks/entries/pages/{_page.server.ts.js-7x6ZfGoB.js → _page.server.ts.js-BK3Y6eff.js} +3 -3
  179. package/build/server/chunks/entries/pages/{_page.svelte.js-Dek8Q1_v.js → _page.svelte.js-DQWBiRk1.js} +4185 -1734
  180. package/build/server/chunks/{handler-DUyvzXsb.js → handler-DsD7I1_u.js} +3 -3
  181. package/build/server/chunks/{index.js-BrP1SRzN.js → index.js-C_WAkwJs.js} +4 -4
  182. package/build/server/chunks/{manifest.js-C4z6aoYx.js → manifest.js-DUy52VaP.js} +85 -64
  183. package/build/server/chunks/nodes/{0.js-BuB3t8Br.js → 0.js-CuV3dXVD.js} +3 -3
  184. package/build/server/chunks/nodes/1.js-Dc5QC-NJ.js +9 -0
  185. package/build/server/chunks/nodes/{2.js-C-o9KF10.js → 2.js-PwcF4_kT.js} +10 -10
  186. package/package.json +2 -2
  187. package/skills/{dsi-kb-scenario → dsi-fc-scenario}/SKILL.md +11 -6
  188. package/template/.dsi/prompts.sqlite +0 -0
  189. package/template/.dsi/prompts.sqlite-shm +0 -0
  190. package/template/.dsi/prompts.sqlite-wal +0 -0
  191. package/template/.dsi/settings.yaml +7 -2
  192. package/build/client/_app/immutable/assets/0.cswkTiBk.css +0 -2
  193. package/build/client/_app/immutable/assets/2.BPprd30B.css +0 -1
  194. package/build/client/_app/immutable/chunks/BHDqH9nE.js +0 -1
  195. package/build/client/_app/immutable/chunks/C7Sg_49n.js +0 -1
  196. package/build/client/_app/immutable/chunks/CAneZX4t.js +0 -8
  197. package/build/client/_app/immutable/chunks/D-Rolhzs.js +0 -1
  198. package/build/client/_app/immutable/chunks/DQXo7qdJ.js +0 -1
  199. package/build/client/_app/immutable/chunks/DY0MQ1mO.js +0 -1
  200. package/build/client/_app/immutable/chunks/K3xyLTzZ.js +0 -1
  201. package/build/client/_app/immutable/chunks/NcOjFWr3.js +0 -6
  202. package/build/client/_app/immutable/chunks/cHj8EuyS.js +0 -3
  203. package/build/client/_app/immutable/chunks/o7DVZODA.js +0 -1
  204. package/build/client/_app/immutable/chunks/pdYhlwhf.js +0 -1
  205. package/build/client/_app/immutable/entry/app.DYNedUxy.js +0 -2
  206. package/build/client/_app/immutable/entry/start.BzyrBssE.js +0 -1
  207. package/build/client/_app/immutable/nodes/0.DQYP6BCS.js +0 -1
  208. package/build/client/_app/immutable/nodes/1.CHB5qqQ9.js +0 -1
  209. package/build/client/_app/immutable/nodes/2.C6No1310.js +0 -340
  210. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/attachment/_server.ts.js-Cb8SBWVw.js +0 -46
  211. package/build/server/chunks/nodes/1.js-CW4V8ni8.js +0 -9
@@ -0,0 +1,195 @@
1
+ ---
2
+ name: glass-dsi
3
+ description: Use when asked to test/verify work "live", "on the glass", "headed", or on the real DSI surface — drive the operator's own Glass Browser over its MCP tools (mcp__glass-browser__browser_*), opening a glass panel if none exists or adding a focused tab when one does. Reserved keyword /glass-dsi (legacy alias /dsi-glass still matches).
4
+ ---
5
+
6
+ # glass-dsi — verify work on the operator's own Glass Browser
7
+
8
+ **Dispatch rule (2026-10-30, the Tab-Juggling RCA):** before any glass work,
9
+ ask — is the surface I must drive the DSI workspace, or some other URL?
10
+ DSI workspace → this skill (the driver hard-requires the DSI tab on :5175).
11
+ Any other URL → the `glass-url` skill; it opens a NEW tab and NEVER touches
12
+ the DSI tab. Do NOT navigate the DSI tab to an external URL and do NOT
13
+ re-run `open` to "recover" — that dance produced a useless DSI tab, a
14
+ strike from the driver, and three tabs where one was needed.
15
+
16
+ Companion KB: `dev/feature-contract-scenario/glass-browser-verification.md`
17
+ (the why and the wire: CDP, the :9515 in-process brain, the three doors).
18
+ This skill is the DO-path.
19
+ Reference (raw-CDP DO-path when the MCP tools cannot reach the glass —
20
+ orphaned glasses, stack-trace instrumentation, no-nesting rule):
21
+ `references/cdp-verification.md` in this skill folder. The one rule above all:
22
+
23
+ **The hands are the browser.** `mcp__glass-browser__browser_*` tools drive
24
+ the SAME headed Chromium the operator's floor panel mirrors (CDP via the
25
+ in-process brain). Never launch your own Playwright browser — that
26
+ verifies a different browser.
27
+
28
+ ## Step 0 — is DSI even running? (and the circularity rule)
29
+
30
+ Port check — `lsof` on macOS; on Linux it is often not installed, so
31
+ fall back to `ss` (the dsi-ports skill is the full ledger):
32
+
33
+ ```sh
34
+ # macOS (lsof ships with the OS)
35
+ lsof -nP -iTCP:5175 -sTCP:LISTEN # vite dev server
36
+ lsof -nP -iTCP:9515 -sTCP:LISTEN # the in-process MCP brain
37
+ # Linux fallback (lsof frequently absent)
38
+ ss -ltnp 'sport = :5175'; ss -ltnp 'sport = :9515'
39
+ ```
40
+
41
+ No 5175 ⇒ the floor is not up — ask the operator (or run
42
+ `dsi dsh --sync --dev --playwright-mcp`) before anything else.
43
+
44
+ **The circularity rule (learned 2026-10-27):** the brain on :9515 exists
45
+ only while a glass session exists, and the only browser hands you have
46
+ are the `mcp__glass-browser__browser_*` tools — which are dead until the
47
+ brain exists. `fetch failed` from the MCP tools means "no glass
48
+ session", NOT "DSI is down" — do not treat it as a floor outage and do
49
+ not go fix ports.
50
+
51
+ ## Step 1 — the Glass Browser exists? (THE definitive procedure)
52
+
53
+ **Hard architecture facts (learned the hard way, 2026-10-27 — do not
54
+ re-litigate them):**
55
+
56
+ - The glass Chrome is launched `headless: true` and parked at
57
+ `--window-position=-32000,-32000` BY DESIGN (insight-config.ts,
58
+ `browser.headless` default; ADR-0041). The operator's floor PANEL is
59
+ the browser's face — a CDP screencast over SSE. There is no OS window
60
+ to look for; never "fix" this.
61
+ - The floor panel mount is CLIENT state only (`openBrowserPanel` →
62
+ in-memory floor store + localStorage blob). There is NO API that mounts
63
+ a panel. A session you `POST /api/browser` yourself is an ORPHAN: it
64
+ streams fine, but no panel can ever adopt it (the resolver persists
65
+ only ids IT opened). Do not open sessions yourself expecting the floor
66
+ to show them.
67
+
68
+ **The one correct open flow (verified end-to-end 2026-10-27):**
69
+
70
+ 1. **No glass, or your tools fail with `fetch failed`?** Ask the
71
+ OPERATOR to click the Browser chip (`OpenBrowserButton`) in the
72
+ conversation header. Only their click mounts the panel into
73
+ PanelsZoom and only the panel's own resolver opens + persists the
74
+ session. This is the one gesture the agent cannot simulate — say so
75
+ plainly and wait.
76
+ 2. **Catch the session**: the click's panel opens the NEWEST entry in
77
+
78
+ ```sh
79
+ curl -s http://127.0.0.1:5175/api/browser # → { sessions: [...] }
80
+ ```
81
+
82
+ The brain re-homes to the newest glass automatically — poll this list
83
+ (a couple of seconds) until the new id appears with
84
+ `mcpHealth: "up"` and :9515 listens. Then the `browser_*` tools
85
+ drive exactly that session.
86
+ 3. **Drive + verify the mirror**: `browser_navigate` to the target, and
87
+ confirm the panel is really painting by probing the SSE:
88
+
89
+ ```sh
90
+ curl -s -N --max-time 4 'http://127.0.0.1:5175/api/browser/<id>/stream' | head -c 60
91
+ # expect: event: frame\ndata: {"seq":N,"jpeg":"/9j/...
92
+ ```
93
+
94
+ Rising `seq` = the operator's panel is receiving live frames. Finish
95
+ by asking the operator to confirm they SEE the page — the mirror is
96
+ the surface they judge you by.
97
+ - **Glass already open with tabs** — `browser_tabs` with
98
+ `{ "action": "new", "url": <target> }` adds a tab LAST and focuses it,
99
+ then navigate/verify in that tab. Never reuse an operator's existing
100
+ tab state; never close their tabs.
101
+
102
+ ## Step 2 — drive the verification
103
+
104
+ 1. **Reach the surface** — navigate to the target (usually
105
+ `http://127.0.0.1:5175`). Seed state through the page's OWN
106
+ persistence (localStorage blobs like `dsi-panels`) and reload, so
107
+ what mounts is the production restore path, not a fixture.
108
+ 2. **Instrument BEFORE acting** — `browser_evaluate`: stamp the DOM
109
+ nodes you will judge (`el.__probe = Math.random()`), wrap
110
+ `window.fetch` with a counting shim, arm a MutationObserver. A
111
+ counter armed after the gesture proves nothing.
112
+ 3. **Reproduce the REAL gesture** — `browser_run_code_unsafe` with
113
+ `page.mouse` (down → stepped moves with waits → up), or
114
+ `browser_click`. Synthetic dispatchEvent is not the operator's
115
+ gesture; prefer real input where input is what's being tested.
116
+ 4. **Read the evidence** — `browser_evaluate`: node identity (did the
117
+ stamped probe survive?), counter deltas, innerHTML before/after.
118
+ Before/after pairs are the verification; adjectives are not.
119
+ 5. **Gate every read on a control** — assert the gesture actually moved
120
+ what it should (e.g. the panel WIDTH changed) before interpreting
121
+ other counters. A drag that moved nothing trivially "passes".
122
+
123
+ ## Failure branches (all observed 2026-10-27 — this is the baseline)
124
+
125
+ - **Geometry lies.** `boundingBox` center can land above the viewport
126
+ fold; the drag moves nothing and every counter reads clean. Fix the
127
+ coordinates (use `g.y + 200` inside a tall gutter) and re-run.
128
+ - **The wrong twin.** In-panel and floor gutters share
129
+ `data-testid=panel-gutter-0`. Scope selectors
130
+ (`[data-testid=panels-row] > [data-testid=panel-gutter-0]` = floor)
131
+ or you verify the wrong machine.
132
+ - **Dev-server HMR reloads mid-test** — the page navigates under you,
133
+ stamps and shims vanish, counters reset. Detect it (readyState /
134
+ element gone) and re-arm; never report numbers from a destroyed
135
+ context.
136
+ - **Blob drift** — the app saves panel-prefs on settle; your seeded
137
+ state can be overwritten by an earlier interaction. Re-seed + reload
138
+ when the surface looks wrong.
139
+ - **The in-memory registry** — the browser-session registry lives in the
140
+ dev server's RAM. A vite restart (crash, HMR of server modules, config
141
+ edit) silently empties `GET /api/browser` and kills every Chrome;
142
+ "down"/vanished sessions you did not close mean this happened. Re-run
143
+ Step 1 (operator clicks the chip again).
144
+ - **`DELETE /api/browser/<id>` is unreliable** — observed 500 twice
145
+ (2026-10-27) while the session stayed registered. If you must clean a
146
+ dead entry, verify with `GET /api/browser` afterwards; do not assume
147
+ the DELETE succeeded.
148
+
149
+ ## Report
150
+
151
+ Numbers before/after, the gesture that produced them, and the gates that
152
+ passed. Label anything you seeded as seeded. If a step could not run,
153
+ say so — a partial verification is a claim about what RAN, not about
154
+ the feature.
155
+ ## Tab-ID grammar (2026-10-28 — glass-tab-ids wave)
156
+
157
+ Glass prompts and the panel omnibox share ONE parser: src/lib/browser/tab-grammar.ts (`parseTabCommand`, discriminated union) — the both-doors rule; they can never disagree about what a command means. Grammar:
158
+
159
+ | Input | Meaning |
160
+ |---|---|
161
+ | `glass <url>` | open a new tab to url |
162
+ | `glass <text>` | open a new tab to a web search of text |
163
+ | `reuse tab:N [url]` | focus tab N, optionally navigate |
164
+ | `change [to] tab:N` / `tab:N` | focus tab N |
165
+ | `close tab:N` / `close active` | close that tab / the active tab |
166
+ | `active` | report the focused tab (id + URL) |
167
+ | anything else | chrome fallback — navigate or web search on the active tab |
168
+
169
+ `Alt+N` on the panel (not a grammar input) focuses the Nth tab by STRIP POSITION before the CDP relay — Alt+0 is the last tab; empty slot is a no-op and the combo never reaches the glass page.
170
+
171
+ `tab:N` is the registry-owned ordinal rendered on the strip badge (data-testid=browser-tab-ordinal) — the badge IS the prompt ID. Focus polish 2026-10-28: the badge now READS `t{index}:{id}` (the 1-based strip position, the same index Alt+N dispatches on), while PROMPTS still use the `tab:{id}` grammar — the registry is unchanged. Ordinals are never reused after close: a retired/unknown tab:N is an explicit error (404 NO_TARGET), never a silent nearest-match. When verifying live, read the number off the badge and address the tab by it.
172
+
173
+
174
+ ## Fast path — the driver script (2026-10-29)
175
+
176
+ The whole discovery dance above is codified in ONE script. Run it FIRST;
177
+ fall back to the manual steps only when it fails:
178
+
179
+ ```sh
180
+ # from the DSI repo root (playwright-core resolves there)
181
+ node .agents/skills/dsi-glass/scripts/glass.mjs open # resolve port, connect, reuse-or-create the DSI tab
182
+ node .agents/skills/dsi-glass/scripts/glass.mjs type '?adr' # real keystrokes into the composer
183
+ node .agents/skills/dsi-glass/scripts/glass.mjs strip # rows / activeIdx / ariaSel / tipCount verdict
184
+ node .agents/skills/dsi-glass/scripts/glass.mjs shot tmp/glass.png
185
+ node .agents/skills/dsi-glass/scripts/glass.mjs eval '1+1' # arbitrary page.evaluate
186
+ node .agents/skills/dsi-glass/scripts/glass.mjs pages
187
+ ```
188
+
189
+ It caches NOTHING: every run re-resolves the session from
190
+ `GET /api/browser` (rule 3 — a hardcoded port verifies a ghost). On
191
+ failure it prints the manual fallback (operator clicks the Browser chip).
192
+ Complex gestures (mouse drags, multi-step keyboards, instrumentation
193
+ shims) still go through playwright-core by hand per §2–§4 — the script
194
+ covers the connect + common verbs, not every probe.
195
+
@@ -0,0 +1,132 @@
1
+ # Reference — Driving a Glass Over Raw CDP (the orphaned-glass DO-path)
2
+
3
+ Companion to SKILL.md. Read when the `mcp__glass-browser__browser_*`
4
+ tools cannot reach the glass you need (brain re-homed, preset entry
5
+ stale) or when you need evidence the MCP tools cannot produce (stack
6
+ traces, per-frame scroll curves, wire-call counts). The KB companion
7
+ (`dev/feature-contract-scenario/glass-browser-verification.md`,
8
+ "2026-10-28 additions II") carries the WHY; this file is the HOW, every
9
+ pattern battle-tested 2026-10-28 on the operator's own glass (port 9400,
10
+ three session ids, one investigation — the floor-steal RCA).
11
+
12
+ ## 0. The rules that outrank every pattern
13
+
14
+ 1. **NO NESTING.** Never open the host DSI inside a glass tab to "drive
15
+ the GUI". The host GUI's gestures belong to the OPERATOR; you verify
16
+ effects through the glass CDP and ask the operator to click. (Operator
17
+ correction 2026-10-28: "do not nest DSI".)
18
+ 2. **A re-homed glass is not dead.** `mcpHealth: "down", mcpError:
19
+ "brain re-homed to a newer glass"` means the MCP tools left — the
20
+ chromium and its CDP port are still fully alive and still may be the
21
+ browser the operator's panel mirrors.
22
+ 3. **Re-resolve the port every session.** `GET /api/browser` rows carry
23
+ `port`; the registry cycles whenever the operator re-chips. A
24
+ hardcoded port verifies a ghost.
25
+ 4. **Instrument BEFORE the gesture.** A counter armed after the click
26
+ proves nothing.
27
+
28
+ ## 1. Resolve the target
29
+
30
+ ```sh
31
+ curl -s http://127.0.0.1:5175/api/browser
32
+ # → {"sessions":[{"id":"…","port":9400,"mcpHealth":"…"}]}
33
+ curl -s http://127.0.0.1:<port>/json/list
34
+ ```
35
+
36
+ Pick the DSI-under-test page: `type === "page"`, URL contains
37
+ `127.0.0.1:5175`. Its `title` is the FOCUSED SESSION's name — DSI sets
38
+ `document.title` to it, so the title flipping IS a focus probe. Ignore
39
+ `browser_ui` rows (Omnibox Popup) and the `data:text/html` placeholder.
40
+
41
+ ## 2. Connect (playwright-core over CDP — real input, real pages)
42
+
43
+ ```js
44
+ import { chromium } from 'playwright-core';
45
+ const browser = await chromium.connectOverCDP('http://127.0.0.1:' + port);
46
+ const page = browser.contexts()[0].pages().find(p => p.url().includes('5175'));
47
+ ```
48
+
49
+ This gives real `locator.click()` gestures (pointerdown included — the
50
+ activation verb) and `page.evaluate` into the live page. Raw-CDP
51
+ alternatives for the same doors: `Runtime.evaluate` (+`userGesture:
52
+ true`), `Input.dispatchMouseEvent/KeyEvent`, `Page.captureScreenshot`.
53
+
54
+ ## 3. Arm the instrumentation (one `page.evaluate`, before acting)
55
+
56
+ ```js
57
+ await page.evaluate(() => {
58
+ window.__ev = []; window.__sl = [];
59
+ const vp = document.querySelector('[data-testid=panels-viewport]');
60
+ // (a) rAF scroll sampler — CDP round-trips miss the smooth-scroll curve
61
+ let last = vp.scrollLeft;
62
+ const sample = () => { const s = vp.scrollLeft;
63
+ if (s !== last) { last = s; window.__sl.push({ t: Math.round(performance.now()), sl: Math.round(s * 10) / 10 }); }
64
+ requestAnimationFrame(sample); };
65
+ requestAnimationFrame(sample);
66
+ const proto = Element.prototype;
67
+ // (b) scroll watches with STACKS — the stack frame names the guilty component
68
+ if (!proto.__watched) { proto.__watched = true;
69
+ const siv = proto.scrollIntoView, sto = proto.scrollTo;
70
+ proto.scrollIntoView = function (...a) {
71
+ if (this.closest('[data-testid=panels-viewport]'))
72
+ window.__ev.push({ t: Math.round(performance.now()), kind: 'scrollIntoView',
73
+ d: (this.getAttribute?.('data-testid') ?? this.tagName),
74
+ stack: new Error().stack.split('\n')[2]?.trim() });
75
+ return siv.apply(this, a); };
76
+ proto.scrollTo = function (...a) {
77
+ if (this.matches?.('[data-testid=panels-viewport]'))
78
+ window.__ev.push({ t: Math.round(performance.now()), kind: 'floor.scrollTo', d: JSON.stringify(a[0]) });
79
+ return sto.apply(this, a); }; }
80
+ // (c) fetch shim — negative evidence (zero POSTs) kills hypotheses
81
+ if (!window.__fw) { window.__fw = true; const of_ = window.fetch;
82
+ window.fetch = function (...a) {
83
+ const u = String(a[0]);
84
+ if (u.includes('/viewport') || u.includes('/activate') || u.includes('/tabs'))
85
+ window.__ev.push({ t: Math.round(performance.now()), kind: 'fetch', d: u.split('/').pop() });
86
+ return of_.apply(this, a); }; }
87
+ // (d) selection timestamps
88
+ new MutationObserver(() => window.__ev.push({ t: Math.round(performance.now()), kind: 'selection' }))
89
+ .observe(document.querySelector('[data-testid=panels-row]'), { attributes: true, attributeFilter: ['class'], subtree: true });
90
+ });
91
+ ```
92
+
93
+ Notes: arm once (the `__watched`/`__fw` guards) — HMR reloads wipe
94
+ everything and the guards re-arm cleanly; the stack slice `[2]` is the
95
+ first APP frame (skip the wrapper).
96
+
97
+ ## 4. Gesture, then read the verdict
98
+
99
+ Perform the REAL gesture (`locator.click()` on the panel header), wait
100
+ OUT past at least one poll cadence (the tabs poll is 2000 ms — a 2s wait
101
+ verifies nothing), then:
102
+
103
+ ```js
104
+ const out = await page.evaluate(() => ({
105
+ sl: document.querySelector('[data-testid=panels-viewport]').scrollLeft,
106
+ sel: document.querySelector('.panels-row [data-testid=panel-column].selected')
107
+ ?.getBoundingClientRect().toJSON(),
108
+ vp: document.querySelector('[data-testid=panels-viewport]').getBoundingClientRect().toJSON(),
109
+ ev: window.__ev, samples: window.__sl }));
110
+ ```
111
+
112
+ Verdict = NUMBERS: selected rect fully inside viewport rect? scroll trace
113
+ monotonic (reveal settles) or snapped back (a steal)? which stack frames
114
+ appear? Report before/after pairs and the gates passed; adjectives are not
115
+ verification.
116
+
117
+ ## 5. Geometry facts that bite
118
+
119
+ - The floor viewport's left edge is NOT page x=0 (the sidebar rail sits
120
+ left of it) — compare column rects against `panels-viewport`'s OWN
121
+ rect, never against the page.
122
+ - `getBoundingClientRect` is transform-true (zoom included); `clientWidth`
123
+ is layout px. At floor zoom ≠ 1 the two disagree — use the rect.
124
+ - A 12px glass resize you did not cause is usually the mirror's
125
+ viewport-sync, not your gesture — check the fetch shim before claiming it.
126
+
127
+ ## 6. Worked example
128
+
129
+ The full live trace that convicted the tab-strip floor steal (instrument
130
+ → gesture → stack frame → fix → re-trace) is in
131
+ `dev/kb/rca/2026-10-28 - RCA — The Tab Chip That Rearranged the Room
132
+ (A Strip's Scroll Walked Into the Floor).md`.
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * _connect.mjs — shared glass connection for the glass-url / glass-dsi drivers.
4
+ *
5
+ * EXPORTS (do not guess — this header is the contract, keep it in sync):
6
+ * die(msg) — print a JSON error and exit 1.
7
+ * identityFrom(argv) — caller identity, first-wins: --owner-session
8
+ * flag > GLASS_OWNER_SESSION > DSH_SESSION_ID
9
+ * (the harness built-in is CONDITIONAL —
10
+ * dsh-shell-env index.js:89 injects it only
11
+ * when the execution carries an agent binding,
12
+ * RCA 2026-10-30 "the session id is gone" —
13
+ * so explicit beats inherited).
14
+ * pickSession(sessions, envId)
15
+ * — PURE D7 resolver (unit-tested): match the
16
+ * caller's identity to ownerSessionId. NEVER
17
+ * registry index (ADR-0045 amendment 3).
18
+ * Returns { session } | { session:null, error }.
19
+ * connect() — GET /api/browser (the ONLY source of truth,
20
+ * ADR-0030) → pickSession → CDP connect →
21
+ * { session, browser, ctx }. Dies LOUDLY on
22
+ * ambiguity; degraded single-session runs print
23
+ * a warning on stderr and proceed.
24
+ * pick(ctx, substr) — page whose URL contains substr; NEVER
25
+ * positional "newest" among foreign tabs (D2).
26
+ */
27
+ import { chromium } from 'playwright-core';
28
+
29
+ const DSI = 'http://127.0.0.1:5175';
30
+
31
+ export function die(msg) {
32
+ console.error(JSON.stringify({ error: msg, fallback: 'SKILL.md Step 1 — ask the OPERATOR to click the Browser chip IN THE RIGHT CONVERSATION, then catch the session via GET /api/browser. If DSH_SESSION_ID is absent from env, pass --owner-session <id> (the session id you already know from context).' }));
33
+ process.exit(1);
34
+ }
35
+
36
+ export function identityFrom(argv) {
37
+ const flag = argv.indexOf('--owner-session');
38
+ if (flag !== -1 && argv[flag + 1]) return argv[flag + 1];
39
+ if (process.env.GLASS_OWNER_SESSION) return process.env.GLASS_OWNER_SESSION;
40
+ if (process.env.DSH_SESSION_ID) return process.env.DSH_SESSION_ID;
41
+ return undefined;
42
+ }
43
+
44
+ export function pickSession(sessions, envId) {
45
+ const list = sessions ?? [];
46
+ if (envId) {
47
+ const mine = list.filter((s) => (s.ownerSessionId ?? null) === envId);
48
+ if (mine.length === 1) return { session: mine[0], degraded: false };
49
+ if (mine.length > 1) {
50
+ const newest = [...mine].sort((a, b) => String(a.createdAt ?? '').localeCompare(String(b.createdAt ?? ''))).at(-1);
51
+ return { session: newest, degraded: false, note: 'multiple glasses owned by ' + envId + ' — newest wins' };
52
+ }
53
+ if (list.length === 1 && (list[0].ownerSessionId ?? null) === null) {
54
+ return { session: list[0], degraded: true, note: 'legacy session without ownerSessionId — degraded match' };
55
+ }
56
+ return { session: null, error: 'no glass owned by ' + envId + ' — your glass is dead or never summoned (click the Browser chip in THIS conversation); live glasses belong to other conversations and are untouchable (D7)' };
57
+ }
58
+ if (list.length === 1) {
59
+ return { session: list[0], degraded: true, note: 'no explicit identity in env — degraded single-session resolution' };
60
+ }
61
+ return { session: null, error: 'multiple live glasses and no explicit identity — pass --owner-session <id> (or GLASS_OWNER_SESSION) from the session id you already know; refusing to guess (D7)' };
62
+ }
63
+
64
+ export async function connect() {
65
+ let reg;
66
+ try {
67
+ reg = await (await fetch(DSI + '/api/browser')).json();
68
+ } catch {
69
+ die('DSI dev server not reachable on 5175 — floor not up (dsi dsh --sync --dev --playwright-mcp)');
70
+ }
71
+ const { session, degraded, note, error } = pickSession(reg.sessions, identityFrom(process.argv));
72
+ if (!session) die(error ?? 'no glass session resolved — operator must click the Browser chip');
73
+ if (degraded || note) console.error(JSON.stringify({ warn: note ?? 'degraded', sessionId: session.id }));
74
+ const browser = await chromium.connectOverCDP('http://127.0.0.1:' + session.port).catch(() => null);
75
+ if (!browser) die('CDP connect failed on port ' + session.port);
76
+ return { session, browser, ctx: browser.contexts()[0] };
77
+ }
78
+
79
+ export function pick(ctx, substr) {
80
+ return ctx.pages().find((p) => p.url().includes(substr));
81
+ }
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * glass-url.mjs — the dsi-glass URL path (2026-10-29).
4
+ *
5
+ * For driving NON-DSI surfaces (YouTube, docs, anything) on the operator's
6
+ * glass. Never touches the DSI tab: open <url> adds a NEW tab last and
7
+ * focuses it (tab-grammar: glass <url>); the other verbs run against the
8
+ * NEWEST tab, whatever it is. The DSI server is still needed — it owns the
9
+ * session registry (see _connect.mjs).
10
+ *
11
+ * Usage (run from the DSI repo root so playwright-core resolves):
12
+ * node .agents/skills/dsi-glass/scripts/glass-url.mjs open <url>
13
+ * node …/glass-url.mjs pages
14
+ * node …/glass-url.mjs eval '<js>' # async page.evaluate on newest tab
15
+ * node …/glass-url.mjs shot <file.png> # screenshot of newest tab
16
+ */
17
+ import { connect, die } from './_connect.mjs';
18
+
19
+ const [cmd, ...args] = process.argv.slice(2);
20
+ const { session, browser, ctx } = await connect();
21
+
22
+ // newest real tab = last http(s) page; CDP page order is not insertion order
23
+ // and the glass placeholder (data:text/html,<title>Glass Browser…) can sit last
24
+ const newest = () => {
25
+ const pages = ctx.pages().filter((p) => p.url().startsWith('http'));
26
+ return pages[pages.length - 1];
27
+ };
28
+
29
+ if (cmd === 'open') {
30
+ const url = args[0];
31
+ if (!url) die('open needs a url');
32
+ const page = await ctx.newPage();
33
+ await page.goto(url, { waitUntil: 'domcontentloaded' }).catch((e) => die('goto failed: ' + e.message));
34
+ await page.waitForTimeout(1500); // let the SPA settle
35
+ console.log(JSON.stringify({ ok: true, sessionId: session.id, url: page.url(), title: await page.title() }));
36
+ } else if (cmd === 'pages') {
37
+ console.log(JSON.stringify(await Promise.all(ctx.pages().map(async (p) => ({ url: p.url(), title: await p.title() }))), null, 1));
38
+ } else if (cmd === 'eval') {
39
+ if (!args[0]) die('eval needs a js expression');
40
+ console.log(JSON.stringify(await newest().evaluate(async (src) => await eval(src), args[0]), null, 1));
41
+ } else if (cmd === 'shot') {
42
+ const file = args[0] ?? 'tmp/glass-url-shot.png';
43
+ await newest().screenshot({ path: file });
44
+ console.log(JSON.stringify({ ok: true, file }));
45
+ } else {
46
+ die('unknown command: ' + cmd);
47
+ }
48
+ await browser.close();
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * glass.mjs — the dsi-glass fast path (2026-10-29).
4
+ *
5
+ * ONE command replaces the discovery dance: port resolve (:5175 health →
6
+ * GET /api/browser → session port → /json/list → playwright-core
7
+ * connectOverCDP → reuse-or-create the DSI tab). The browser-session
8
+ * registry stays the ONLY source of truth — this script caches nothing
9
+ * (skill rule 3: a hardcoded port verifies a ghost).
10
+ *
11
+ * Usage (run from the DSI repo root so playwright-core resolves):
12
+ * node .agents/skills/dsi-glass/scripts/glass.mjs open [url]
13
+ * node …/glass.mjs eval '<js>' # async page.evaluate, JSON out
14
+ * node …/glass.mjs type '<text>' # real keystrokes into the composer
15
+ * node …/glass.mjs shot <file.png> # viewport screenshot
16
+ * node …/glass.mjs strip # suggest-strip verdict (rows,
17
+ * # activeIdx, ariaSel, tipCount)
18
+ * node …/glass.mjs pages # list glass pages (url + title)
19
+ *
20
+ * On any failure it prints the manual fallback hint (SKILL.md Step 1 —
21
+ * the operator clicks the Browser chip; agents never open sessions).
22
+ */
23
+ import { connect, die } from './_connect.mjs';
24
+
25
+ const DSI = 'http://127.0.0.1:5175';
26
+ const [cmd, ...args] = process.argv.slice(2);
27
+
28
+ const { session, browser, ctx } = await connect();
29
+
30
+ let page = ctx.pages().find((p) => p.url().includes('5175'));
31
+ if (cmd === 'open') {
32
+ if (!page) {
33
+ page = await ctx.newPage();
34
+ await page.goto(args[0] ?? DSI, { waitUntil: 'domcontentloaded' }).catch(() => {});
35
+ } else if (args[0] && args[0] !== page.url()) {
36
+ await page.goto(args[0], { waitUntil: 'domcontentloaded' }).catch(() => {});
37
+ }
38
+ await page.waitForSelector('body', { timeout: 15000 });
39
+ } else if (!page) {
40
+ die('no DSI tab in the glass — run: glass.mjs open');
41
+ }
42
+
43
+ if (cmd === 'open') {
44
+ await page.waitForTimeout(1500); // let the SPA settle
45
+ console.log(JSON.stringify({ ok: true, sessionId: session.id, port: session.port, url: page.url(), title: await page.title() }));
46
+ } else if (cmd === 'pages') {
47
+ console.log(JSON.stringify(await Promise.all(ctx.pages().map(async (p) => ({ url: p.url(), title: await p.title() }))), null, 1));
48
+ } else if (cmd === 'eval') {
49
+ if (!args[0]) die('eval needs a js expression');
50
+ console.log(JSON.stringify(await page.evaluate(async (src) => await eval(src), args[0]), null, 1));
51
+ } else if (cmd === 'type') {
52
+ if (!args[0]) die('type needs text');
53
+ const ta = page.locator('textarea').first();
54
+ await ta.click();
55
+ await page.keyboard.press('Meta+a');
56
+ await page.keyboard.press('Backspace');
57
+ await page.keyboard.type(args[0], { delay: 60 });
58
+ await page.waitForTimeout(1000); // debounce (120 ms) + fetch
59
+ console.log(JSON.stringify({ ok: true, typed: args[0] }));
60
+ } else if (cmd === 'shot') {
61
+ const file = args[0] ?? 'tmp/glass-shot.png';
62
+ await page.screenshot({ path: file });
63
+ console.log(JSON.stringify({ ok: true, file }));
64
+ } else if (cmd === 'strip') {
65
+ console.log(JSON.stringify(await page.evaluate(() => {
66
+ const strip = document.querySelector('[data-testid=suggest-strip]');
67
+ if (!strip) return { strip: false };
68
+ const chips = [...strip.querySelectorAll(':scope > .strip-chip')];
69
+ const tips = [...document.body.querySelectorAll(':scope > .strip-tip')];
70
+ return {
71
+ strip: true,
72
+ rows: chips.length,
73
+ labels: chips.map((c) => c.querySelector('.strip-label')?.textContent?.trim()),
74
+ activeIdx: chips.findIndex((c) => c.classList.contains('active')),
75
+ ariaSel: chips.map((c) => c.querySelector('.strip-pick')?.getAttribute('aria-selected')),
76
+ tipCount: tips.length,
77
+ tipText: tips[0]?.querySelector('pre')?.textContent?.slice(0, 80) ?? null,
78
+ taValue: document.querySelector('textarea')?.value
79
+ };
80
+ }), null, 1));
81
+ } else {
82
+ die('unknown command: ' + cmd);
83
+ }
84
+ await browser.close();
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: glass-url
3
+ description: Open and drive an ARBITRARY URL (YouTube, docs, any web page) in a NEW tab on the operator's glass browser via CDP — search, click, screenshot, read the page. NOT for verifying DSI work; that is glass-dsi. Reserved keyword /glass-url.
4
+ ---
5
+
6
+ # glass-url — drive an arbitrary URL on the operator's glass
7
+
8
+ Companion skill: `glass-dsi` (verify DSI work on the glass — the DSI tab,
9
+ the floor mirror, the SSE probe). This skill is the OTHER scenario: the
10
+ target is some web page, and the DSI tab is none of your business.
11
+
12
+ **The dispatch rule (Tab-Juggling RCA, ADR-0045):** before any glass work
13
+ ask ONE question — is the surface I must drive the DSI workspace, or some
14
+ other URL? DSI workspace → `glass-dsi`. Any other URL → THIS skill.
15
+ Never navigate the DSI tab, never re-run `open` to "recover".
16
+
17
+ ## Environment contract (read before the first command — RCA 2026-10-30)
18
+
19
+ - **Node lives off the default PATH here** (`~/.local/bin/node` observed
20
+ 2026-10-30). If `node` is not found, resolve it first:
21
+ `bash -lc "which node"` or check `~/.local/bin`, `/opt/homebrew/bin`.
22
+ - **Run from the DSI repo root** (`~/agentic-ai/deepseek-insight`) so
23
+ `playwright-core` resolves.
24
+ - **Never hand unquoted JS through a shell** — a stripped quote fails
25
+ after the round-trip was already spent. Use `eval --b64 <base64>`.
26
+ - **Every ad-hoc driver snippet must `process.exit()`** — a driver that
27
+ played media once hung its caller for a full 120s timeout.
28
+ - **Script headers are contracts** — `_connect.mjs` exports
29
+ `die`, `connect`, `pick(ctx, substr)`; do not guess names, read the
30
+ header; re-read the header in the same edit that changes the code.
31
+
32
+ ## The fast path — glass-url.mjs (one command per intent)
33
+
34
+ ```sh
35
+ # from the DSI repo root (playwright-core resolves there)
36
+ node .agents/skills/glass-url/scripts/glass-url.mjs yt "Dimas Senopati" --play "What's Up" --shot tmp/proof.png
37
+ # → search + normalized match + open watch tab + unmute/play + double
38
+ # gate + shot, ONE JSON with every stage, then exits. --play consumes
39
+ # EVERY term (artist AND title) — put both in it (ADR-0045 D9).
40
+
41
+ node .agents/skills/glass-url/scripts/glass-url.mjs open <url> # NEW tab, focused
42
+ node .agents/skills/glass-url/scripts/glass-url.mjs pages # list tabs
43
+ node .agents/skills/glass-url/scripts/glass-url.mjs eval '<js>' # newest non-DSI tab
44
+ node .agents/skills/glass-url/scripts/glass-url.mjs eval watch?v= '<js>' # inline: LAST arg is the js
45
+ node .agents/skills/glass-url/scripts/glass-url.mjs eval --b64 <b64-js> <url-substring>
46
+ # quote-proof eval; anything left after the payload IS the url-substring
47
+ # (ADR-0045 D10 — parsed by shape, never positional fallback)
48
+ node .agents/skills/glass-url/scripts/glass-url.mjs shot f.png [url-substring]
49
+ ```
50
+
51
+ "Newest tab" = last http(s) page that is neither the glass placeholder nor
52
+ the DSI tab (:5175). When SEVERAL foreign tabs exist, position lies —
53
+ pass the URL-substring argument (the `yt` verb does this for you).
54
+ Every run re-resolves the session from `GET /api/browser`.
55
+
56
+ ## Recipes
57
+
58
+ - **Search + play a video:** the `yt` verb IS the recipe (match
59
+ normalization included: apostrophes/case folded). Only drop to
60
+ `open` → `eval` when the flow is not search-and-play.
61
+ - **Read a page:** `open` → `eval` extract DOM text/links.
62
+
63
+ ## Rules
64
+
65
+ 1. Always `open` a NEW tab for your target — never reuse a tab you did
66
+ not create, never close operator tabs.
67
+ 2. Never navigate the DSI workspace tab; it belongs to glass-dsi.
68
+ 3. Multi-step state (click, type, drag) beyond eval/shot: drop to
69
+ playwright-core by hand over CDP (import `connect`/`pick` from
70
+ `.agents/skills/glass-url/scripts/_connect.mjs` — exports listed in
71
+ its header), same as glass-dsi §2–4.
72
+ 4. If `GET /api/browser` has no session: the operator must click the
73
+ Browser chip first (the one gesture you cannot simulate). Say so and wait.
74
+ 5. Verify with gates, not adjectives: a playback gate is `paused:false`
75
+ plus rising `currentTime`; a navigation gate is the URL/title you
76
+ expected; finish by asking the operator to confirm they SEE it.
77
+
78
+ ## Identity (2026-10-30, RCA "the session id is gone")
79
+
80
+ The driver claims YOUR glass by identity, first-wins:
81
+ 1. `--owner-session <id>` flag — pass the session id you already know from
82
+ your context when `DSH_SESSION_ID` is absent (the harness injects it
83
+ only when the execution carries an agent binding — dsh-shell-env
84
+ index.js:89 — so its absence is possible and NOT an error).
85
+ 2. `GLASS_OWNER_SESSION` env.
86
+ 3. `DSH_SESSION_ID` env.
87
+ No identity + several live glasses = loud refusal, never a guess (D7).
88
+
89
+ ## The Stop-Loss Law (2026-10-30, ADR-0045 D11 — a refusal is an answer)
90
+
91
+ - **NO_MATCH is an answer.** When the yt verb exits `stage:"match"` with a
92
+ candidate list, REPORT that list and STOP — do not open ad-hoc search
93
+ tabs, do not re-search with different words, do not drop to open/eval to
94
+ hand-roll what the verb just refused. The operator decides the next move.
95
+ - **Grammar dies are answers.** A `die` ("no tab matching …", "no
96
+ non-DSI tab …") ends the investigation, not triggers a workaround hunt.
97
+ Run `pages` once to re-orient if you must, then report.
98
+ - **Already playing is DONE.** If the media is live on the operator's glass
99
+ (they say so, or a prior gate passed), the goal is met — report and stop.
100
+ No follow-up verification, no "one more tab". Verification serves the
101
+ operator's goal; when the goal is met, the correct next action is WORDS.
102
+ - Every extra tab and round-trip after a refusal is a token burn the
103
+ operator pays for. (RCA: "The Answer That Bought Another Round".)
104
+
105
+ ## Failure branches (2026-10-30)
106
+
107
+ - `eval` on a cross-origin page still loading can return empty — wait and
108
+ re-run; do not conclude "no results".
109
+ - String matching needs normalization (case, apostrophes) or exact titles
110
+ will NO_MATCH — `yt` normalizes for you.
111
+ - A vite restart empties the registry and kills the Chrome — re-run from
112
+ the operator's chip click, same as glass-dsi.
113
+ - "Newest non-DSI tab" is positional and CAN pick a sibling foreign tab —
114
+ select by URL substring (the optional eval/shot argument), not position.
115
+ - Node/git missing from PATH, quoting mangling, guessed flags, and
116
+ non-exiting drivers each cost a full round-trip: see the environment
117
+ contract above; they are pre-paid now.