agentworkshop 0.7.9 → 0.7.11
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/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{BUPj10t4.js → 6vYobj4F.js} +1 -1
- package/.output/public/_nuxt/{BCJFMBQ6.js → B-xskWta.js} +1 -1
- package/.output/public/_nuxt/{BC8s1Guv.js → B3Psw_sL.js} +1 -1
- package/.output/public/_nuxt/B53Mp7lD.js +1 -0
- package/.output/public/_nuxt/B5CYgFAD.js +14 -0
- package/.output/public/_nuxt/{91DZTUMJ.js → B8WV7GzS.js} +1 -1
- package/.output/public/_nuxt/{BDASpD_i.js → BBwMH_hG.js} +1 -1
- package/.output/public/_nuxt/BLzCac9K2.js +1 -0
- package/.output/public/_nuxt/BNXfwXpE.js +1 -0
- package/.output/public/_nuxt/BbZAzXjZ2.js +1 -0
- package/.output/public/_nuxt/{CFn4vHwD.js → Bc3PiGGr.js} +1 -1
- package/.output/public/_nuxt/{B0HpdCKS.js → Bckshc9V.js} +1 -1
- package/.output/public/_nuxt/BcrN7QEl2.js +1 -0
- package/.output/public/_nuxt/BgOhoDTI.js +1 -0
- package/.output/public/_nuxt/Bmpvki7M.js +1 -0
- package/.output/public/_nuxt/BxPPAkGA.js +3 -0
- package/.output/public/_nuxt/{u7KWCGSb.js → BxtpDtzC.js} +1 -1
- package/.output/public/_nuxt/{DxrgFxIr2.js → C4OAdbVK2.js} +1 -1
- package/.output/public/_nuxt/C6m-kenn.js +1 -0
- package/.output/public/_nuxt/{DDdEnkdw.js → CGx-mtWf.js} +1 -1
- package/.output/public/_nuxt/Cj6139IM.js +1 -0
- package/.output/public/_nuxt/{6PZPfFcO.js → Cor9siSf.js} +1 -1
- package/.output/public/_nuxt/{wirVyscc.js → D7jiode2.js} +1 -1
- package/.output/public/_nuxt/{Ct68Z0232.js → DA4lxCWC2.js} +1 -1
- package/.output/public/_nuxt/DEaY_uvR.js +1 -0
- package/.output/public/_nuxt/{MyA0Oeqd.js → DNxVTfhe.js} +1 -1
- package/.output/public/_nuxt/DT-Wg8r1.js +1 -0
- package/.output/public/_nuxt/DTYBfjRY.js +1 -0
- package/.output/public/_nuxt/{DvgKXPgu2.js → DWcEk1ur2.js} +1 -1
- package/.output/public/_nuxt/Dhqra7NB.js +1 -0
- package/.output/public/_nuxt/DlRO_q5L.js +1 -0
- package/.output/public/_nuxt/{D8EfUxO2.js → Ds8JbqGB.js} +1 -1
- package/.output/public/_nuxt/{DN5RuZ8k.js → DyisHHzD.js} +1 -1
- package/.output/public/_nuxt/ORt9oDIy2.js +1 -0
- package/.output/public/_nuxt/{By8BpbKH.js → QoCzfpo2.js} +1 -1
- package/.output/public/_nuxt/RzXYI9FM.js +23 -0
- package/.output/public/_nuxt/{BuktKVqK2.js → arUY5dyq2.js} +2 -2
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/88479a5b-ce6a-400f-9737-1cc9f54b1fe5.json +1 -0
- package/.output/public/_nuxt/{pKv_VWR4.js → d_Sz9KGm.js} +1 -1
- package/.output/public/_nuxt/{default.BR3e5fPY.css → default.BbgdTDCk.css} +1 -1
- package/.output/public/_nuxt/{C9cU_Ujd.js → eHYnGew0.js} +1 -1
- package/.output/public/_nuxt/{DM4CNkXz.js → eUGyJdiT.js} +1 -1
- package/.output/public/_nuxt/{entry.5qf6EqfN.css → entry.B03HBJGC.css} +1 -1
- package/.output/public/_nuxt/{B1g8pJmr.js → kkEthL84.js} +1 -1
- package/.output/public/_nuxt/permissions.CwZo6t1V.css +1 -0
- package/.output/public/_nuxt/settings.BqMF2nfj.css +1 -0
- package/.output/public/_nuxt/{D0Szyn_D.js → tJuVvBSl.js} +1 -1
- package/.output/public/_nuxt/zVkqCZ78.js +1 -0
- package/.output/server/chunks/_/LeftOutlined.mjs +1 -1
- package/.output/server/chunks/_/SearchOutlined.mjs +1 -1
- package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
- package/.output/server/chunks/_/host-bindings.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +1636 -1315
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
- package/.output/server/chunks/build/Col-biaNnEPf.mjs +1 -1
- package/.output/server/chunks/build/{OmpTerminalPanel-COphA1br.mjs → OmpTerminalPanel-Ban3yJZ4.mjs} +4 -5
- package/.output/server/chunks/build/OmpTerminalPanel-Ban3yJZ4.mjs.map +1 -0
- package/.output/server/chunks/build/{TownView-D8DSdO3H.mjs → TownView-CunmEMzS.mjs} +8 -9
- package/.output/server/chunks/build/{TownView-D8DSdO3H.mjs.map → TownView-CunmEMzS.mjs.map} +1 -1
- package/.output/server/chunks/build/{_id_-BV4FfiYd.mjs → _id_-CVnMdSeG.mjs} +7 -7
- package/.output/server/chunks/build/{_id_-BV4FfiYd.mjs.map → _id_-CVnMdSeG.mjs.map} +1 -1
- package/.output/server/chunks/build/{_id_-TP9hvnBM.mjs → _id_-D265Wh_k.mjs} +7 -7
- package/.output/server/chunks/build/{_id_-TP9hvnBM.mjs.map → _id_-D265Wh_k.mjs.map} +1 -1
- package/.output/server/chunks/build/{_wsId_-Mm9sQSz2.mjs → _wsId_-eNJmBp05.mjs} +17 -17
- package/.output/server/chunks/build/{_wsId_-Mm9sQSz2.mjs.map → _wsId_-eNJmBp05.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents-To3a5xcZ.mjs → agents-B10wmFri.mjs} +9 -9
- package/.output/server/chunks/build/{agents-To3a5xcZ.mjs.map → agents-B10wmFri.mjs.map} +1 -1
- package/.output/server/chunks/build/alert-qJnjyRcP.mjs +1 -1
- package/.output/server/chunks/build/api-error-dul30BYQ.mjs +1 -1
- package/.output/server/chunks/build/button-DEcZFcqN.mjs +2 -2
- package/.output/server/chunks/build/{card-Dipvaykh.mjs → card-CCPQoKlh.mjs} +4 -4
- package/.output/server/chunks/build/{card-Dipvaykh.mjs.map → card-CCPQoKlh.mjs.map} +1 -1
- package/.output/server/chunks/build/{channel-templates-DRsP-qxl.mjs → channel-templates-CpWxVk5A.mjs} +7 -7
- package/.output/server/chunks/build/{channel-templates-DRsP-qxl.mjs.map → channel-templates-CpWxVk5A.mjs.map} +1 -1
- package/.output/server/chunks/build/{checkbox-dzcpU_Cd.mjs → checkbox-Dv1kjaUZ.mjs} +3 -3
- package/.output/server/chunks/build/{checkbox-dzcpU_Cd.mjs.map → checkbox-Dv1kjaUZ.mjs.map} +1 -1
- package/.output/server/chunks/build/client-only-D5BzSQc6.mjs +1 -1
- package/.output/server/chunks/build/{daq-_hCEaYLd.mjs → daq-DxaXk_8N.mjs} +9 -10
- package/.output/server/chunks/build/daq-DxaXk_8N.mjs.map +1 -0
- package/.output/server/chunks/build/{dcw-C7pJ4Y0p.mjs → dcw-DqjHrl5Z.mjs} +5 -5
- package/.output/server/chunks/build/{dcw-C7pJ4Y0p.mjs.map → dcw-DqjHrl5Z.mjs.map} +1 -1
- package/.output/server/chunks/build/{default-Dnjs36e8.mjs → default-YcUHc1Ev.mjs} +19 -12
- package/.output/server/chunks/build/{default-Dnjs36e8.mjs.map → default-YcUHc1Ev.mjs.map} +1 -1
- package/.output/server/chunks/build/drawer-Cmh90erI.mjs +1 -1
- package/.output/server/chunks/build/dropdown-vhn1NPFs.mjs +2 -2
- package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs +554 -0
- package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs.map +1 -0
- package/.output/server/chunks/build/initDefaultProps-DIbWwP4R.mjs +1 -1
- package/.output/server/chunks/build/{input-sf_BT6o6.mjs → input-DxDqeyQW.mjs} +5 -553
- package/.output/server/chunks/build/input-DxDqeyQW.mjs.map +1 -0
- package/.output/server/chunks/build/{input-number-Bd55elNN.mjs → input-number-CZ3ZrCsy.mjs} +3 -3
- package/.output/server/chunks/build/{input-number-Bd55elNN.mjs.map → input-number-CZ3ZrCsy.mjs.map} +1 -1
- package/.output/server/chunks/build/{logs-C039TFW1.mjs → logs-Co854R4y.mjs} +6 -7
- package/.output/server/chunks/build/logs-Co854R4y.mjs.map +1 -0
- package/.output/server/chunks/build/menu-WCrlpYVh.mjs +2 -2
- package/.output/server/chunks/build/modal-yvUquPj5.mjs +2 -2
- package/.output/server/chunks/build/{monitor-MIOvsyLa.mjs → monitor-miqq9xHB.mjs} +11 -11
- package/.output/server/chunks/build/{monitor-MIOvsyLa.mjs.map → monitor-miqq9xHB.mjs.map} +1 -1
- package/.output/server/chunks/build/{pages-C_VSGSGo.mjs → pages-DPC1Vp6w.mjs} +5 -5
- package/.output/server/chunks/build/{pages-C_VSGSGo.mjs.map → pages-DPC1Vp6w.mjs.map} +1 -1
- package/.output/server/chunks/build/permissions-Eu9e6hfZ.mjs +534 -0
- package/.output/server/chunks/build/permissions-Eu9e6hfZ.mjs.map +1 -0
- package/.output/server/chunks/build/{plugins-4FMWkN8d.mjs → plugins-D84mvK9G.mjs} +3 -4
- package/.output/server/chunks/build/plugins-D84mvK9G.mjs.map +1 -0
- package/.output/server/chunks/build/popconfirm-CRaHcz5O.mjs +2 -2
- package/.output/server/chunks/build/responsiveObserve-CS0UB6wQ.mjs +1 -1
- package/.output/server/chunks/build/{segmented-DPe9ZzLO.mjs → segmented-ChmQZwz6.mjs} +5 -4
- package/.output/server/chunks/build/{segmented-DPe9ZzLO.mjs.map → segmented-ChmQZwz6.mjs.map} +1 -1
- package/.output/server/chunks/build/select-D-CeE5vY.mjs +1 -1
- package/.output/server/chunks/build/{settings-DA8IkGLo.mjs → settings-BPBll_7K.mjs} +28 -26
- package/.output/server/chunks/build/settings-BPBll_7K.mjs.map +1 -0
- package/.output/server/chunks/build/space-CCBYAkXt.mjs +2 -2
- package/.output/server/chunks/build/spin-HVY81X_L.mjs +1 -1
- package/.output/server/chunks/build/switch-CelRXpcy.mjs +2 -2
- package/.output/server/chunks/build/{table-Cswq-l2r.mjs → table-BtksyDlQ.mjs} +5 -5
- package/.output/server/chunks/build/{table-Cswq-l2r.mjs.map → table-BtksyDlQ.mjs.map} +1 -1
- package/.output/server/chunks/build/{tabs-BM3tAh_J.mjs → tabs-DQv-_-R6.mjs} +3 -3
- package/.output/server/chunks/build/{tabs-BM3tAh_J.mjs.map → tabs-DQv-_-R6.mjs.map} +1 -1
- package/.output/server/chunks/build/{tag-NO9jEqKy.mjs → tag-A0tZ2Ouq.mjs} +4 -4
- package/.output/server/chunks/build/{tag-NO9jEqKy.mjs.map → tag-A0tZ2Ouq.mjs.map} +1 -1
- package/.output/server/chunks/build/{teams-DA1lkf1n.mjs → teams-CNflUtPh.mjs} +7 -7
- package/.output/server/chunks/build/{teams-DA1lkf1n.mjs.map → teams-CNflUtPh.mjs.map} +1 -1
- package/.output/server/chunks/build/{tokens-DKMvvk3e.mjs → tokens-CZpnEDVf.mjs} +10 -10
- package/.output/server/chunks/build/{tokens-DKMvvk3e.mjs.map → tokens-CZpnEDVf.mjs.map} +1 -1
- package/.output/server/chunks/build/town-BUqRobze.mjs +1 -1
- package/.output/server/chunks/build/{town-D0thZ7PK.mjs → town-BbaR-8io.mjs} +9 -10
- package/.output/server/chunks/build/town-BbaR-8io.mjs.map +1 -0
- package/.output/server/chunks/build/{useDaqStream-BVTRw8_H.mjs → useDaqStream-BkmyQT06.mjs} +34 -23
- package/.output/server/chunks/build/useDaqStream-BkmyQT06.mjs.map +1 -0
- package/.output/server/chunks/build/{useDcwStream-DNsivqI_.mjs → useDcwStream-DWVoU96J.mjs} +60 -46
- package/.output/server/chunks/build/useDcwStream-DWVoU96J.mjs.map +1 -0
- package/.output/server/chunks/build/{useDeviceTwins-WeIom7A6.mjs → useDeviceTwins-34WGk9aN.mjs} +2 -2
- package/.output/server/chunks/build/{useDeviceTwins-WeIom7A6.mjs.map → useDeviceTwins-34WGk9aN.mjs.map} +1 -1
- package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs +1 -1
- package/.output/server/chunks/build/{useOpsLog-DcKnPO43.mjs → useOpsLog-C9zTzYof.mjs} +27 -15
- package/.output/server/chunks/build/useOpsLog-C9zTzYof.mjs.map +1 -0
- package/.output/server/chunks/build/useSiteConfig-DJe_KMVr.mjs +1 -1
- package/.output/server/chunks/build/useWorkshopApi-D2gq06N2.mjs +1 -1
- package/.output/server/chunks/build/{useWorkshopWs-B3j5wIAK.mjs → useWorkshopWs-CprkZEdq.mjs} +2 -3
- package/.output/server/chunks/build/useWorkshopWs-CprkZEdq.mjs.map +1 -0
- package/.output/server/chunks/build/{users-CmVvb1oq.mjs → users-D6RNylrW.mjs} +10 -10
- package/.output/server/chunks/build/{users-CmVvb1oq.mjs.map → users-D6RNylrW.mjs.map} +1 -1
- package/.output/server/chunks/build/{workshop-BhWnJMWs.mjs → workshop-Crsai2Y9.mjs} +9 -9
- package/.output/server/chunks/build/{workshop-BhWnJMWs.mjs.map → workshop-Crsai2Y9.mjs.map} +1 -1
- package/.output/server/chunks/build/{workspaces-IfORCDJE.mjs → workspaces-BuydxM-3.mjs} +2 -3
- package/.output/server/chunks/build/workspaces-BuydxM-3.mjs.map +1 -0
- package/.output/server/chunks/routes/api/health.get.mjs +1 -1
- package/.output/server/chunks/routes/api/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
- package/.output/server/chunks/routes/api/metrics.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/config.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +1 -1
- package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/system/monitor.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/settings/events.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.put.mjs +1 -1
- package/.output/server/chunks/routes/api/users/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/login.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/logout.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/me.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/register.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/setup-status.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/_...path_.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +19 -8
- package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/audit.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/caller.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +3 -3
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
- package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +7 -6
- package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +5 -2
- package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +3 -2
- package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +7 -6
- package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +4 -3
- package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +4 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +8 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +4 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +4 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +7 -3
- package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +3 -2
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +3 -2
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +5 -3
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.put.mjs +41 -0
- package/.output/server/chunks/routes/api/workshop/index.put.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/index10.get.mjs +4 -3
- package/.output/server/chunks/routes/api/workshop/index10.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index11.get.mjs +27 -0
- package/.output/server/chunks/routes/api/workshop/index11.get.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs +4 -4
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.get.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/index4.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/index5.get.mjs +18 -11
- package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index5.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index6.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index8.get.mjs +24 -12
- package/.output/server/chunks/routes/api/workshop/index8.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index8.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index9.get.mjs +12 -7
- package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/runtime.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/users/me.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +3 -3
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs +3 -3
- package/.output/server/chunks/virtual/entry.mjs +271 -31
- package/.output/server/chunks/virtual/entry.mjs.map +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/index.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +15 -0
- package/README.md +20 -0
- package/app/components/AppSidebar.vue +7 -1
- package/app/composables/workshop/apiClient.ts +103 -95
- package/app/composables/workshop/useDaqStream.ts +35 -21
- package/app/composables/workshop/useDcwStream.ts +22 -5
- package/app/composables/workshop/useOpsLog.ts +26 -13
- package/app/composables/workshop/useWorkshopWs.ts +11 -2
- package/app/pages/permissions/index.vue +327 -0
- package/app/pages/settings.vue +4 -2
- package/app/plugins/http.ts +18 -2
- package/app/plugins/session-restore.client.ts +7 -2
- package/app/stores/workshop/user.ts +14 -1
- package/i18n/locales/en.ts +37 -0
- package/i18n/locales/zh-CN.ts +37 -0
- package/package.json +1 -1
- package/scripts/_dbg-acc-1-setup.mjs +57 -0
- package/scripts/_dbg-acc-2-diag.mjs +14 -0
- package/scripts/_dbg-acc-2-intervals.mjs +81 -0
- package/scripts/_dbg-acc-3-daq.mjs +48 -0
- package/scripts/_dbg-acc-4-team.mjs +92 -0
- package/scripts/_dbg-acc-5-visual.mjs +63 -0
- package/scripts/_dbg-acc-5b-ws-town.mjs +18 -0
- package/scripts/_dbg-acc-5c-town.mjs +12 -0
- package/scripts/_dbg-acc-6-i18n.mjs +19 -0
- package/scripts/_dbg-audit-neg-e2e.mjs +64 -0
- package/scripts/_dbg-final-features.mjs +155 -0
- package/scripts/_dbg-final-fixups.mjs +62 -0
- package/scripts/_dbg-final-visual.mjs +29 -0
- package/scripts/_dbg-perms-e2e.mjs +102 -0
- package/scripts/_dbg-perms-visual.mjs +36 -0
- package/scripts/_dbg-protocol-matrix.mjs +16 -0
- package/sdk/api.mjs +117 -101
- package/sdk/context.mjs +240 -219
- package/sdk/hooks.mjs +105 -103
- package/sdk/index.d.mts +142 -135
- package/sdk/lifecycle.mjs +26 -25
- package/server/api/workshop/agent-tools/bindings/index.post.ts +40 -20
- package/server/api/workshop/daq/[id]/bind.post.ts +5 -2
- package/server/api/workshop/daq/[id]/frames/content.get.ts +4 -1
- package/server/api/workshop/daq/[id]/frames.get.ts +4 -1
- package/server/api/workshop/daq/[id]/samples.get.ts +4 -1
- package/server/api/workshop/daq/[id].patch.ts +3 -0
- package/server/api/workshop/daq/alarms/[id]/ack.post.ts +20 -15
- package/server/api/workshop/daq/controller.post.ts +2 -0
- package/server/api/workshop/daq/index.get.ts +5 -3
- package/server/api/workshop/daq/index.post.ts +2 -2
- package/server/api/workshop/dcw/[id]/bind.post.ts +20 -17
- package/server/api/workshop/dcw/[id]/test.post.ts +18 -15
- package/server/api/workshop/dcw/[id]/write.post.ts +3 -0
- package/server/api/workshop/dcw/index.get.ts +22 -9
- package/server/api/workshop/dcw/line/query.get.ts +38 -31
- package/server/api/workshop/dcw/lines/[id]/start.post.ts +3 -0
- package/server/api/workshop/dcw/lines/[id]/stop.post.ts +3 -0
- package/server/api/workshop/dcw/lines/index.get.ts +8 -2
- package/server/api/workshop/dcw/lines/index.post.ts +2 -2
- package/server/api/workshop/dcw/products/index.post.ts +16 -16
- package/server/api/workshop/dcw/runs/[id]/data.get.ts +20 -15
- package/server/api/workshop/dcw/runs/index.get.ts +13 -11
- package/server/api/workshop/permissions/index.get.ts +30 -0
- package/server/api/workshop/permissions/index.put.ts +29 -0
- package/server/api/workshop/ws.ts +18 -6
- package/server/data/daqs.json +48 -48
- package/server/data/dcw-products.json +21 -0
- package/server/data/dcw-recipes.json +84 -0
- package/server/data/dcw-rollback.json +94 -6
- package/server/data/dcw-runs.json +81 -75
- package/server/data/dcw-writes.json +108 -0
- package/server/data/dcws.json +645 -382
- package/server/data/line-runs.json +8 -8
- package/server/plugins/backup.ts +119 -116
- package/server/repositories/user.repository.ts +86 -6
- package/server/services/user.service.ts +5 -3
- package/server/services/workshop/daq/bus/index.ts +5 -3
- package/server/services/workshop/daq/bus/inproc.adapter.ts +12 -3
- package/server/services/workshop/daq/bus/mqtt.adapter.ts +13 -0
- package/server/services/workshop/daq/bus/queue-port.ts +2 -0
- package/server/services/workshop/daq/daq-controller.ts +18 -1
- package/server/services/workshop/db/ops.repo.ts +6 -0
- package/server/services/workshop/dcw/dcw-controller.ts +10 -2
- package/server/services/workshop/permissions.ts +79 -0
- package/server/services/workshop/plugins/host.mjs +38 -1
- package/server/services/workshop/scene-events.ts +25 -1
- package/shared/config/single-instance.mjs +24 -0
- package/shared/daq-protocol.ts +2 -0
- package/.output/public/_nuxt/B1kA8LhC.js +0 -14
- package/.output/public/_nuxt/B9MUiDFl.js +0 -1
- package/.output/public/_nuxt/B9dLFSYI.js +0 -1
- package/.output/public/_nuxt/BaMkWl5i2.js +0 -1
- package/.output/public/_nuxt/BmHvC_OU.js +0 -1
- package/.output/public/_nuxt/CBciOiTQ.js +0 -1
- package/.output/public/_nuxt/CUMdhxg9.js +0 -1
- package/.output/public/_nuxt/CgvGu2IO.js +0 -1
- package/.output/public/_nuxt/CjDQPXfv.js +0 -1
- package/.output/public/_nuxt/CmHzfVc5.js +0 -3
- package/.output/public/_nuxt/Cn3J3NXR.js +0 -23
- package/.output/public/_nuxt/Cst47G4-.js +0 -1
- package/.output/public/_nuxt/D3VJ3lex.js +0 -1
- package/.output/public/_nuxt/D8wyHvcz2.js +0 -1
- package/.output/public/_nuxt/Dqj2h40U.js +0 -1
- package/.output/public/_nuxt/OV6PBW2z.js +0 -1
- package/.output/public/_nuxt/builds/meta/92d6bd39-dbc5-46d5-90d8-8387f36715fa.json +0 -1
- package/.output/public/_nuxt/settings.DeRNNUcP.css +0 -1
- package/.output/server/chunks/build/OmpTerminalPanel-COphA1br.mjs.map +0 -1
- package/.output/server/chunks/build/daq-_hCEaYLd.mjs.map +0 -1
- package/.output/server/chunks/build/input-sf_BT6o6.mjs.map +0 -1
- package/.output/server/chunks/build/logs-C039TFW1.mjs.map +0 -1
- package/.output/server/chunks/build/plugins-4FMWkN8d.mjs.map +0 -1
- package/.output/server/chunks/build/settings-DA8IkGLo.mjs.map +0 -1
- package/.output/server/chunks/build/town-D0thZ7PK.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqStream-BVTRw8_H.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwStream-DNsivqI_.mjs.map +0 -1
- package/.output/server/chunks/build/useOpsLog-DcKnPO43.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkshopWs-B3j5wIAK.mjs.map +0 -1
- package/.output/server/chunks/build/user-Dk-ytEUV.mjs +0 -140
- package/.output/server/chunks/build/user-Dk-ytEUV.mjs.map +0 -1
- package/.output/server/chunks/build/workspaces-IfORCDJE.mjs.map +0 -1
- /package/.output/public/_nuxt/{CNs_Ozdc2.js → CNs_Ozdc.js} +0 -0
- /package/.output/public/_nuxt/{Cno6kYiO2.js → Cno6kYiO.js} +0 -0
package/.output/server/index.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import 'node:buffer';
|
|
|
17
17
|
import 'node:fs';
|
|
18
18
|
import 'node:path';
|
|
19
19
|
import 'node:url';
|
|
20
|
+
import 'node:fs/promises';
|
|
20
21
|
import 'node:os';
|
|
21
22
|
import 'js-yaml';
|
|
22
23
|
import 'node:child_process';
|
|
@@ -24,7 +25,6 @@ import 'node:net';
|
|
|
24
25
|
import 'node:util';
|
|
25
26
|
import 'node:sqlite';
|
|
26
27
|
import 'node:module';
|
|
27
|
-
import 'node:fs/promises';
|
|
28
28
|
import 'node:zlib';
|
|
29
29
|
|
|
30
30
|
const kNodeInspect = /* @__PURE__ */ Symbol.for(
|
package/README-zh.md
CHANGED
|
@@ -309,6 +309,21 @@ curl http://localhost:3000/api/workshop/channels \
|
|
|
309
309
|
-H 'authorization: Bearer <token>'
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
+
### 产线级权限
|
|
313
|
+
|
|
314
|
+
工业数据按**产线**三态管控,由管理员在内置「权限管理」页(`/permissions`,仅 admin 侧栏可见)维护:
|
|
315
|
+
|
|
316
|
+
| 状态 | 数采节点 | 数控(写控)节点 | 可见性 |
|
|
317
|
+
|---|---|---|---|
|
|
318
|
+
| **无权**(普通用户默认) | 隐藏 | 隐藏 | 后端不返回该产线数据——产线运营/数采中心/数字孪生均不可见 |
|
|
319
|
+
| **仅查看** | 只读 | ✕ | 产线可见、实时值可看,但不可写/不可下发/不可绑定设备 |
|
|
320
|
+
| **可操控** | 读取 | 读取+写入 | 全量能力:设定值下发、参数下发、设备绑定 |
|
|
321
|
+
|
|
322
|
+
- `admin` / `editor` 为运营角色,不受授权约束(全量全权)。
|
|
323
|
+
- 普通用户**默认无权**——未授权前看不到任何产线数据。
|
|
324
|
+
- 强制点在数据面:列表接口按授权过滤,写控/下发接口返回人话 403,Agent↔节点绑定校验产线授权(数采需仅查看+,写控需可操控)。
|
|
325
|
+
- 插件经 `ctx.permissions`(`lineMode` / `visibleLineIds` / `listGrants` / `setGrants`)获得同一能力面,并有 `permissions:changed` 生命周期钩子;SDK REST 客户端提供 `client.permissions.overview()` / `client.permissions.set(...)`。
|
|
326
|
+
|
|
312
327
|
### 执行模式
|
|
313
328
|
|
|
314
329
|
在任务描述中使用模式前缀(或在 composer UI 中选择):
|
package/README.md
CHANGED
|
@@ -310,6 +310,26 @@ curl http://localhost:3000/api/workshop/channels \
|
|
|
310
310
|
-H 'authorization: Bearer <token>'
|
|
311
311
|
```
|
|
312
312
|
|
|
313
|
+
### Line-level permissions
|
|
314
|
+
|
|
315
|
+
Industrial data is gated **per production line** with three states, managed by an admin
|
|
316
|
+
in the built-in **Permissions** page (`/permissions`, admin-only in the sidebar):
|
|
317
|
+
|
|
318
|
+
| State | DAQ nodes | DCW (write) nodes | Visibility |
|
|
319
|
+
| --- | --- | --- | --- |
|
|
320
|
+
| **none** (default for regular users) | hidden | hidden | line data withheld server-side — invisible in Line Ops, DAQ center and the digital twin |
|
|
321
|
+
| **read-only** | read | ✕ | line visible, values stream, no writes / dispatch / device binding |
|
|
322
|
+
| **operate** | read | read + write | full access incl. setpoint writes, dispatch, binding |
|
|
323
|
+
|
|
324
|
+
- `admin` / `editor` roles are unrestricted (operations roles).
|
|
325
|
+
- Regular users **default to none** — they see no line data until granted.
|
|
326
|
+
- Enforcement lives in the data plane: list endpoints filter by grant, write/dispatch
|
|
327
|
+
endpoints return a human-readable 403, and Agent↔node bindings validate the line grant
|
|
328
|
+
(DAQ needs read-only+, DCW needs operate).
|
|
329
|
+
- Plugins get the same surface via `ctx.permissions` (`lineMode` / `visibleLineIds` /
|
|
330
|
+
`listGrants` / `setGrants`) plus a `permissions:changed` lifecycle hook; the SDK REST
|
|
331
|
+
client exposes `client.permissions.overview()` / `client.permissions.set(...)`.
|
|
332
|
+
|
|
313
333
|
### Execution modes
|
|
314
334
|
|
|
315
335
|
Prefix the task description (or pick in the composer UI):
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useUserStore } from '~/stores/workshop/user'
|
|
3
|
+
|
|
4
|
+
const userStore = useUserStore()
|
|
2
5
|
const { t } = useI18n()
|
|
3
6
|
const route = useRoute()
|
|
4
7
|
const site = useSiteConfig()
|
|
@@ -10,6 +13,8 @@ interface MenuItem {
|
|
|
10
13
|
label: string
|
|
11
14
|
/** 图标微动效类(im-*) */
|
|
12
15
|
motion?: string
|
|
16
|
+
/** 仅 admin 可见(权限管理) */
|
|
17
|
+
adminOnly?: boolean
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
const menuItems = computed<MenuItem[]>(() => [
|
|
@@ -21,10 +26,11 @@ const menuItems = computed<MenuItem[]>(() => [
|
|
|
21
26
|
{ key: '/dcw', icon: 'i-tabler-settings-automation', label: t('menu.dcw'), motion: 'im-pop' },
|
|
22
27
|
{ key: '/logs', icon: 'i-tabler-list-details', label: t('menu.logs'), motion: 'im-pop' },
|
|
23
28
|
{ key: '/users', icon: 'i-tabler-users-group', label: t('menu.users'), motion: 'im-pop' },
|
|
29
|
+
{ key: '/permissions', icon: 'i-tabler-shield-lock', label: t('menu.permissions'), motion: 'im-pop', adminOnly: true },
|
|
24
30
|
{ key: '/monitor', icon: 'i-tabler-cpu', label: t('menu.monitor'), motion: 'im-pulse' },
|
|
25
31
|
{ key: '/plugins', icon: 'i-tabler-puzzle', label: t('menu.plugins'), motion: 'im-pop' },
|
|
26
32
|
{ key: '/settings', icon: 'i-tabler-settings', label: t('menu.settings'), motion: 'im-rotate' },
|
|
27
|
-
])
|
|
33
|
+
].filter(m => !m.adminOnly || userStore.isAdmin))
|
|
28
34
|
|
|
29
35
|
const isActive = (key: string): boolean =>
|
|
30
36
|
key === '/' ? route.path === '/' : route.path.startsWith(key)
|
|
@@ -1,95 +1,103 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 统一 API 客户端 —— 全部手写 fetch 的单一收口。
|
|
3
|
-
* - 信封解析:{code, message, data};code !== 0 或非 2xx 一律抛 ApiError
|
|
4
|
-
* - ApiError 保留业务码与 HTTP 状态(调用方可分支),message 为后端可读文案
|
|
5
|
-
* - 网络层失败(TypeError/断网)→ ApiError('NETWORK'),不再裸奔 "Failed to fetch"
|
|
6
|
-
* - 幂等 GET 可选自动重试(5xx/网络错误;400ms 起退避);写操作永不重试
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export class ApiError extends Error {
|
|
10
|
-
readonly code: string | number
|
|
11
|
-
readonly status: number
|
|
12
|
-
|
|
13
|
-
constructor(code: string | number, status: number, message: string) {
|
|
14
|
-
super(message)
|
|
15
|
-
this.name = 'ApiError'
|
|
16
|
-
this.code = code
|
|
17
|
-
this.status = status
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** 鉴权头(cookie token → Bearer;与既有会话契约同源) */
|
|
22
|
-
function authHeaders(json = true): Record<string, string> {
|
|
23
|
-
const cookieToken = typeof document !== 'undefined'
|
|
24
|
-
? (document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] ?? '')
|
|
25
|
-
: ''
|
|
26
|
-
const h: Record<string, string> = {}
|
|
27
|
-
if (cookieToken) h.authorization = `Bearer ${decodeURIComponent(cookieToken)}`
|
|
28
|
-
if (json) h['content-type'] = 'application/json'
|
|
29
|
-
return h
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
|
|
33
|
-
|
|
34
|
-
function isIdempotent(init?: RequestInit): boolean {
|
|
35
|
-
const method = (init?.method ?? 'GET').toUpperCase()
|
|
36
|
-
return method === 'GET' || method === 'HEAD'
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** 单次请求:信封解析 + 错误归一化(所有失败路径都抛 ApiError) */
|
|
40
|
-
async function attemptOnce<T>(base: string, path: string, init?: RequestInit): Promise<T> {
|
|
41
|
-
let res: Response
|
|
42
|
-
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 统一 API 客户端 —— 全部手写 fetch 的单一收口。
|
|
3
|
+
* - 信封解析:{code, message, data};code !== 0 或非 2xx 一律抛 ApiError
|
|
4
|
+
* - ApiError 保留业务码与 HTTP 状态(调用方可分支),message 为后端可读文案
|
|
5
|
+
* - 网络层失败(TypeError/断网)→ ApiError('NETWORK'),不再裸奔 "Failed to fetch"
|
|
6
|
+
* - 幂等 GET 可选自动重试(5xx/网络错误;400ms 起退避);写操作永不重试
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export class ApiError extends Error {
|
|
10
|
+
readonly code: string | number
|
|
11
|
+
readonly status: number
|
|
12
|
+
|
|
13
|
+
constructor(code: string | number, status: number, message: string) {
|
|
14
|
+
super(message)
|
|
15
|
+
this.name = 'ApiError'
|
|
16
|
+
this.code = code
|
|
17
|
+
this.status = status
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** 鉴权头(cookie token → Bearer;与既有会话契约同源) */
|
|
22
|
+
function authHeaders(json = true): Record<string, string> {
|
|
23
|
+
const cookieToken = typeof document !== 'undefined'
|
|
24
|
+
? (document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] ?? '')
|
|
25
|
+
: ''
|
|
26
|
+
const h: Record<string, string> = {}
|
|
27
|
+
if (cookieToken) h.authorization = `Bearer ${decodeURIComponent(cookieToken)}`
|
|
28
|
+
if (json) h['content-type'] = 'application/json'
|
|
29
|
+
return h
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
|
|
33
|
+
|
|
34
|
+
function isIdempotent(init?: RequestInit): boolean {
|
|
35
|
+
const method = (init?.method ?? 'GET').toUpperCase()
|
|
36
|
+
return method === 'GET' || method === 'HEAD'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 单次请求:信封解析 + 错误归一化(所有失败路径都抛 ApiError) */
|
|
40
|
+
async function attemptOnce<T>(base: string, path: string, init?: RequestInit): Promise<T> {
|
|
41
|
+
let res: Response
|
|
42
|
+
try {
|
|
43
|
+
// 超时防挂起:无 AbortSignal 的 fetch 在连接黑洞时 promise 永不 settle,loading 永卡
|
|
44
|
+
res = await fetch(base + path, {
|
|
45
|
+
...init,
|
|
46
|
+
headers: { ...authHeaders(!!init?.body), ...init?.headers },
|
|
47
|
+
signal: init?.signal ?? AbortSignal.timeout(init?.method && init.method.toUpperCase() !== 'GET' ? 30_000 : 15_000),
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')) {
|
|
52
|
+
throw new ApiError('TIMEOUT', 0, '请求超时,请检查网络或服务状态')
|
|
53
|
+
}
|
|
54
|
+
throw new ApiError('NETWORK', 0, '无法连接服务器,请检查网络或服务状态')
|
|
55
|
+
}
|
|
56
|
+
let json: { code?: string | number, message?: string, data?: T } | null = null
|
|
57
|
+
try {
|
|
58
|
+
json = await res.json()
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// 非 JSON 响应(代理/网关 HTML 错误页等)——按状态码归一化
|
|
62
|
+
}
|
|
63
|
+
if (!res.ok) {
|
|
64
|
+
throw new ApiError(
|
|
65
|
+
json?.code ?? `HTTP_${res.status}`,
|
|
66
|
+
res.status,
|
|
67
|
+
json?.message || `请求失败(HTTP ${res.status})`,
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
if (json?.code !== 0) {
|
|
71
|
+
throw new ApiError(json?.code ?? 'REQUEST_ERROR', res.status, json?.message || '请求失败')
|
|
72
|
+
}
|
|
73
|
+
return json.data as T
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 统一请求入口。
|
|
78
|
+
* @param opts.base API 前缀(如 '/api/workshop/daq')
|
|
79
|
+
* @param opts.path 路径后缀(如 '/:id/bind')
|
|
80
|
+
* @param opts.init fetch RequestInit(body 由调用方 JSON.stringify)
|
|
81
|
+
* @param opts.retries 幂等请求额外重试次数(仅 5xx/网络错误;默认 0)
|
|
82
|
+
*/
|
|
83
|
+
export async function apiFetch<T>(opts: { base: string, path?: string, init?: RequestInit, retries?: number }): Promise<T> {
|
|
84
|
+
const { base, path = '', init, retries = 0 } = opts
|
|
85
|
+
const idempotent = isIdempotent(init)
|
|
86
|
+
const attempts = idempotent ? retries + 1 : 1
|
|
87
|
+
let lastError: ApiError | undefined
|
|
88
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
89
|
+
try {
|
|
90
|
+
return await attemptOnce<T>(base, path, init)
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
const apiErr = err instanceof ApiError
|
|
94
|
+
? err
|
|
95
|
+
: new ApiError('INTERNAL_ERROR', 0, apiErrorMessage(err))
|
|
96
|
+
const retryable = idempotent && (apiErr.code === 'NETWORK' || apiErr.status >= 500)
|
|
97
|
+
lastError = apiErr
|
|
98
|
+
if (!retryable || attempt === attempts - 1) throw apiErr
|
|
99
|
+
await sleep(400 * (attempt + 1))
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
throw lastError ?? new ApiError('INTERNAL_ERROR', 0, '请求失败')
|
|
103
|
+
}
|
|
@@ -204,30 +204,44 @@ const createStore = () => {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
/** 挂 WS 帧(townBus)
|
|
207
|
+
/** 挂 WS 帧(townBus)。引用计数:首个调用建立真实订阅,计数归零才退订
|
|
208
|
+
* (修复一次性守卫导致首个页面卸载后实时流永久死亡的缺陷)。返回退订函数。 */
|
|
209
|
+
let feedConsumers = 0
|
|
210
|
+
let feedUnsub: (() => void) | null = null
|
|
208
211
|
function ensureWsFeed(): () => void {
|
|
209
|
-
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const p = e.payload as unknown as DaqAlarmRow
|
|
221
|
-
if (!alarms.some(a => a.id === p.id)) alarms.unshift(p)
|
|
212
|
+
feedConsumers++
|
|
213
|
+
if (feedConsumers === 1) {
|
|
214
|
+
feedUnsub = useTownBus().subscribe(handler)
|
|
215
|
+
}
|
|
216
|
+
let done = false
|
|
217
|
+
return () => {
|
|
218
|
+
if (done) return
|
|
219
|
+
done = true
|
|
220
|
+
if (--feedConsumers === 0) {
|
|
221
|
+
feedUnsub?.()
|
|
222
|
+
feedUnsub = null
|
|
222
223
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function handler(e: AepEnvelope) {
|
|
228
|
+
if (e.type === 'daq.reading') applyReading(e.payload as AepDaqReading)
|
|
229
|
+
else if (e.type === 'daq.frame') applyFrame(e.payload as unknown as AepDaqFrame)
|
|
230
|
+
else if (e.type === 'daq.node.changed') applyChange(e.payload as AepDaqNodeChange)
|
|
231
|
+
else if (e.type === 'daq.controller') Object.assign(controller, e.payload as AepDaqControllerState)
|
|
232
|
+
else if (e.type === 'daq.template.changed') applyTemplateChange(e.payload as AepDaqTemplateChange)
|
|
233
|
+
// S5 实时告警:server 权威事件直推(报警进入轨插入;ack 确认后移出未确认列表)
|
|
234
|
+
else if (e.type === 'daq.alarm') {
|
|
235
|
+
const p = e.payload as unknown as DaqAlarmRow
|
|
236
|
+
if (!alarms.some(a => a.id === p.id)) alarms.unshift(p)
|
|
237
|
+
}
|
|
238
|
+
else if (e.type === 'daq.alarm.changed') {
|
|
239
|
+
const p = e.payload as unknown as { id: string, ackedAt?: string, recovered?: boolean }
|
|
240
|
+
if (p.ackedAt) {
|
|
241
|
+
const i = alarms.findIndex(a => a.id === p.id)
|
|
242
|
+
if (i >= 0) alarms.splice(i, 1)
|
|
229
243
|
}
|
|
230
|
-
}
|
|
244
|
+
}
|
|
231
245
|
}
|
|
232
246
|
|
|
233
247
|
async function load(): Promise<void> {
|
|
@@ -50,11 +50,27 @@ function createStore() {
|
|
|
50
50
|
upsert(p.node)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** 引用计数订阅(同 useDaqStream):首个调用建订阅,归零才退订 */
|
|
54
|
+
let feedConsumers = 0
|
|
55
|
+
let feedUnsub: (() => void) | null = null
|
|
53
56
|
function ensureWsFeed(): () => void {
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
feedConsumers++
|
|
58
|
+
if (feedConsumers === 1) {
|
|
59
|
+
feedUnsub = useTownBus().subscribe(handler)
|
|
60
|
+
}
|
|
61
|
+
let done = false
|
|
62
|
+
return () => {
|
|
63
|
+
if (done) return
|
|
64
|
+
done = true
|
|
65
|
+
if (--feedConsumers === 0) {
|
|
66
|
+
feedUnsub?.()
|
|
67
|
+
feedUnsub = null
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function handler(e: AepEnvelope) {
|
|
73
|
+
{
|
|
58
74
|
if (e.type === 'dcw.written') {
|
|
59
75
|
const p = e.payload as AepDcwWritten
|
|
60
76
|
const n = nodes.find(x => x.id === p.nodeId)
|
|
@@ -83,8 +99,9 @@ function createStore() {
|
|
|
83
99
|
const i = optimizations.findIndex(x => x.id === p.id)
|
|
84
100
|
if (i >= 0) optimizations[i] = p
|
|
85
101
|
else optimizations.unshift(p)
|
|
102
|
+
if (optimizations.length > 200) optimizations.length = 200
|
|
86
103
|
}
|
|
87
|
-
}
|
|
104
|
+
}
|
|
88
105
|
}
|
|
89
106
|
|
|
90
107
|
async function load(): Promise<void> {
|
|
@@ -74,21 +74,34 @@ const createStore = () => {
|
|
|
74
74
|
const loading = reactive({ list: false, posting: false })
|
|
75
75
|
const error = reactive({ list: '', post: '' })
|
|
76
76
|
|
|
77
|
-
/** 挂 WS 帧(townBus)
|
|
77
|
+
/** 挂 WS 帧(townBus)。引用计数(同 useDaqStream):归零才退订。 */
|
|
78
|
+
let feedConsumers = 0
|
|
79
|
+
let feedUnsub: (() => void) | null = null
|
|
78
80
|
function ensureLive(): () => void {
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
feedConsumers++
|
|
82
|
+
if (feedConsumers === 1) {
|
|
83
|
+
void seedRecent()
|
|
84
|
+
feedUnsub = useTownBus().subscribe(handler)
|
|
85
|
+
}
|
|
86
|
+
let done = false
|
|
87
|
+
return () => {
|
|
88
|
+
if (done) return
|
|
89
|
+
done = true
|
|
90
|
+
if (--feedConsumers === 0) {
|
|
91
|
+
feedUnsub?.()
|
|
92
|
+
feedUnsub = null
|
|
90
93
|
}
|
|
91
|
-
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function handler(e: AepEnvelope) {
|
|
98
|
+
if (e.type === 'ops.log') {
|
|
99
|
+
const row = ingestFrame(e.payload as AepOpsLog)
|
|
100
|
+
if (!recent.some(r => r.at === row.at && r.actor === row.actor && r.action === row.action)) {
|
|
101
|
+
recent.unshift(row)
|
|
102
|
+
if (recent.length > RECENT_CAP) recent.splice(RECENT_CAP)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
/** 首屏预填:最近 15 条历史摘要(实时轨不必从零等事件) */
|
|
@@ -12,6 +12,11 @@ import { useHitlStore } from '../../stores/workshop/hitl'
|
|
|
12
12
|
import { useTownBus } from './useTownBus'
|
|
13
13
|
import type { AepEnvelope, AepSnapshot } from '#shared/workshop-protocol'
|
|
14
14
|
|
|
15
|
+
// 心跳单例(模块作用域):所有 useWorkshopWs() 调用方共享一个 15s 定时器,
|
|
16
|
+
// 避免每组件实例一份冗余 ping 打向同一会话
|
|
17
|
+
let heartbeat: ReturnType<typeof setInterval> | null = null
|
|
18
|
+
let heartbeatUsers = 0
|
|
19
|
+
|
|
15
20
|
export function useWorkshopWs() {
|
|
16
21
|
const conn = useWsConnectionStore()
|
|
17
22
|
const userStore = useUserStore()
|
|
@@ -100,8 +105,9 @@ export function useWorkshopWs() {
|
|
|
100
105
|
session?.ensureConnected()
|
|
101
106
|
}
|
|
102
107
|
|
|
103
|
-
let heartbeat: ReturnType<typeof setInterval> | null = null
|
|
104
108
|
onMounted(() => {
|
|
109
|
+
heartbeatUsers++
|
|
110
|
+
if (heartbeat) return
|
|
105
111
|
// 15s 心跳:pong 停止后 checkStale 的断线感知最坏 ~20-35s(服务强杀的半开连接
|
|
106
112
|
// 无 RST,靠 pong 超时发现);ping 发送失败立即关闭走重连,不等 stale 检测
|
|
107
113
|
heartbeat = setInterval(() => {
|
|
@@ -110,7 +116,10 @@ export function useWorkshopWs() {
|
|
|
110
116
|
}, 15_000)
|
|
111
117
|
})
|
|
112
118
|
onBeforeUnmount(() => {
|
|
113
|
-
if (heartbeat)
|
|
119
|
+
if (--heartbeatUsers <= 0 && heartbeat) {
|
|
120
|
+
clearInterval(heartbeat)
|
|
121
|
+
heartbeat = null
|
|
122
|
+
}
|
|
114
123
|
})
|
|
115
124
|
|
|
116
125
|
return { subscribe, unsubscribe, ensureConnected, conn }
|