@mudlet/mudlet-web 0.3.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 (242) hide show
  1. package/LICENSE +338 -0
  2. package/README.md +150 -0
  3. package/dist-lib/App.d.ts +1 -0
  4. package/dist-lib/MudletWebApp.d.ts +11 -0
  5. package/dist-lib/ProfileSession.d.ts +15 -0
  6. package/dist-lib/assets/mapParser.worker-t-3rd1zR.js +9 -0
  7. package/dist-lib/branding.d.ts +213 -0
  8. package/dist-lib/core/EventBus.d.ts +29 -0
  9. package/dist-lib/db/sqliteClient.d.ts +25 -0
  10. package/dist-lib/hooks/useEngines.d.ts +12 -0
  11. package/dist-lib/hooks/useMudSession.d.ts +10 -0
  12. package/dist-lib/hooks/useOutput.d.ts +17 -0
  13. package/dist-lib/hooks/useViewportMode.d.ts +14 -0
  14. package/dist-lib/import/applyMudletProfile.d.ts +57 -0
  15. package/dist-lib/import/collectProfileExport.d.ts +16 -0
  16. package/dist-lib/import/defaultPackages.d.ts +81 -0
  17. package/dist-lib/import/defaults/mudlet-mapper.xml +13023 -0
  18. package/dist-lib/import/defaults/run-lua-code.mpackage +0 -0
  19. package/dist-lib/import/mudletHost.d.ts +67 -0
  20. package/dist-lib/import/mudletLink.d.ts +34 -0
  21. package/dist-lib/import/mudletProfileExport.d.ts +49 -0
  22. package/dist-lib/import/mudletProfileImport.d.ts +71 -0
  23. package/dist-lib/import/mudletVariables.d.ts +49 -0
  24. package/dist-lib/import/mudletWriteback.d.ts +12 -0
  25. package/dist-lib/import/mudletXmlExport.d.ts +16 -0
  26. package/dist-lib/import/mudletXmlImport.d.ts +21 -0
  27. package/dist-lib/import/packageInstaller.d.ts +72 -0
  28. package/dist-lib/import/packageRepository.d.ts +54 -0
  29. package/dist-lib/import/remotePackageInstall.d.ts +52 -0
  30. package/dist-lib/index.d.ts +30 -0
  31. package/dist-lib/index.js +42307 -0
  32. package/dist-lib/logging/SessionLogger.d.ts +41 -0
  33. package/dist-lib/main.d.ts +2 -0
  34. package/dist-lib/map/MapSelectionOverlay.d.ts +15 -0
  35. package/dist-lib/map/MapStore.d.ts +1067 -0
  36. package/dist-lib/map/MudixMapReader.d.ts +90 -0
  37. package/dist-lib/map/MudletHighlightOverlay.d.ts +18 -0
  38. package/dist-lib/map/mapImageExport.d.ts +26 -0
  39. package/dist-lib/map/mapParser.worker.d.ts +1 -0
  40. package/dist-lib/map/mapParserClient.d.ts +35 -0
  41. package/dist-lib/map/pathfinding.d.ts +52 -0
  42. package/dist-lib/map/xmlMapImport.d.ts +28 -0
  43. package/dist-lib/mud/MudSession.d.ts +236 -0
  44. package/dist-lib/mud/PatternEngine.d.ts +28 -0
  45. package/dist-lib/mud/aliases/AliasEngine.d.ts +15 -0
  46. package/dist-lib/mud/connection/LineAssembler.d.ts +84 -0
  47. package/dist-lib/mud/connection/MudClient.d.ts +268 -0
  48. package/dist-lib/mud/connection/PingTracker.d.ts +28 -0
  49. package/dist-lib/mud/connection/TelnetNegotiator.d.ts +188 -0
  50. package/dist-lib/mud/connection/telnetDebug.d.ts +54 -0
  51. package/dist-lib/mud/events.d.ts +160 -0
  52. package/dist-lib/mud/keybindings/KeyEngine.d.ts +36 -0
  53. package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +45 -0
  54. package/dist-lib/mud/keybindings/qtKeys.d.ts +33 -0
  55. package/dist-lib/mud/protocol/charset.d.ts +105 -0
  56. package/dist-lib/mud/protocol/constants.d.ts +116 -0
  57. package/dist-lib/mud/protocol/echo.d.ts +63 -0
  58. package/dist-lib/mud/protocol/gmcp.d.ts +28 -0
  59. package/dist-lib/mud/protocol/index.d.ts +11 -0
  60. package/dist-lib/mud/protocol/mccp.d.ts +18 -0
  61. package/dist-lib/mud/protocol/mnes.d.ts +83 -0
  62. package/dist-lib/mud/protocol/msdp.d.ts +19 -0
  63. package/dist-lib/mud/protocol/msp.d.ts +47 -0
  64. package/dist-lib/mud/protocol/mssp.d.ts +25 -0
  65. package/dist-lib/mud/protocol/mxp.d.ts +188 -0
  66. package/dist-lib/mud/protocol/naws.d.ts +7 -0
  67. package/dist-lib/mud/replay/ReplayPlayer.d.ts +31 -0
  68. package/dist-lib/mud/replay/ReplayRecorder.d.ts +18 -0
  69. package/dist-lib/mud/replay/replayFormat.d.ts +49 -0
  70. package/dist-lib/mud/text/Console.d.ts +183 -0
  71. package/dist-lib/mud/text/FormatState.d.ts +256 -0
  72. package/dist-lib/mud/text/ansiEscapes.d.ts +88 -0
  73. package/dist-lib/mud/text/cellRender.d.ts +21 -0
  74. package/dist-lib/mud/text/colorParsers.d.ts +54 -0
  75. package/dist-lib/mud/text/colors.d.ts +31 -0
  76. package/dist-lib/mud/text/controlCharacterMode.d.ts +13 -0
  77. package/dist-lib/mud/text/controlChars.d.ts +31 -0
  78. package/dist-lib/mud/text/hyperlinkConfig.d.ts +164 -0
  79. package/dist-lib/mud/text/hyperlinkVisibility.d.ts +37 -0
  80. package/dist-lib/mud/text/oscLinkManager.d.ts +35 -0
  81. package/dist-lib/mud/text/wcwidth.d.ts +44 -0
  82. package/dist-lib/mud/text/xterm256.d.ts +2 -0
  83. package/dist-lib/mud/timers/TimerEngine.d.ts +61 -0
  84. package/dist-lib/mud/triggers/ChunkProcessor.d.ts +11 -0
  85. package/dist-lib/mud/triggers/TriggerEngine.d.ts +188 -0
  86. package/dist-lib/mud/triggers/pcre/Pcre2.d.ts +26 -0
  87. package/dist-lib/scripting/EngineHost.d.ts +152 -0
  88. package/dist-lib/scripting/GlobalEventChannel.d.ts +36 -0
  89. package/dist-lib/scripting/IScriptingRuntime.d.ts +95 -0
  90. package/dist-lib/scripting/MapOpenNotifier.d.ts +19 -0
  91. package/dist-lib/scripting/ScriptingAPI.d.ts +1691 -0
  92. package/dist-lib/scripting/ScriptingEngine.d.ts +806 -0
  93. package/dist-lib/scripting/StopwatchManager.d.ts +94 -0
  94. package/dist-lib/scripting/heldModifiers.d.ts +3 -0
  95. package/dist-lib/scripting/http/HttpService.d.ts +23 -0
  96. package/dist-lib/scripting/lua/LuaRuntime.d.ts +190 -0
  97. package/dist-lib/scripting/lua/bindings/automation.d.ts +10 -0
  98. package/dist-lib/scripting/lua/bindings/commandLine.d.ts +11 -0
  99. package/dist-lib/scripting/lua/bindings/context.d.ts +87 -0
  100. package/dist-lib/scripting/lua/bindings/cursor.d.ts +10 -0
  101. package/dist-lib/scripting/lua/bindings/diagnostics.d.ts +9 -0
  102. package/dist-lib/scripting/lua/bindings/map.d.ts +14 -0
  103. package/dist-lib/scripting/lua/bindings/media.d.ts +24 -0
  104. package/dist-lib/scripting/lua/bindings/output.d.ts +10 -0
  105. package/dist-lib/scripting/lua/bindings/packages.d.ts +10 -0
  106. package/dist-lib/scripting/lua/bindings/session.d.ts +16 -0
  107. package/dist-lib/scripting/lua/bindings/textEdit.d.ts +9 -0
  108. package/dist-lib/scripting/lua/bindings/userWindows.d.ts +11 -0
  109. package/dist-lib/scripting/lua/bindings/window.d.ts +10 -0
  110. package/dist-lib/scripting/lua/imageSize.d.ts +4 -0
  111. package/dist-lib/scripting/lua/luaCompletions.d.ts +9 -0
  112. package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
  113. package/dist-lib/scripting/lua/rex.d.ts +3 -0
  114. package/dist-lib/scripting/lua/sqlRowEncoder.d.ts +1 -0
  115. package/dist-lib/scripting/lua/yajl.d.ts +11 -0
  116. package/dist-lib/scripting/profilesPresence.d.ts +50 -0
  117. package/dist-lib/scripting/vfs/ProfileVFS.d.ts +62 -0
  118. package/dist-lib/scripting/vfs/cssRewrite.d.ts +21 -0
  119. package/dist-lib/scripting/vfs/folderHandleStore.d.ts +16 -0
  120. package/dist-lib/scripting/vfs/folderSync.d.ts +59 -0
  121. package/dist-lib/scripting/vfs/htmlRewrite.d.ts +26 -0
  122. package/dist-lib/scripting/vfs/vfsBridge.d.ts +16 -0
  123. package/dist-lib/services/cloudflare.d.ts +54 -0
  124. package/dist-lib/storage/appStore.d.ts +132 -0
  125. package/dist-lib/storage/crossTabSync.d.ts +3 -0
  126. package/dist-lib/storage/debouncedStorage.d.ts +18 -0
  127. package/dist-lib/storage/hooks.d.ts +17 -0
  128. package/dist-lib/storage/index.d.ts +4 -0
  129. package/dist-lib/storage/logExport.d.ts +32 -0
  130. package/dist-lib/storage/logStorage.d.ts +45 -0
  131. package/dist-lib/storage/mapStorage.d.ts +2 -0
  132. package/dist-lib/storage/profileVfsData.d.ts +47 -0
  133. package/dist-lib/storage/schema.d.ts +638 -0
  134. package/dist-lib/styles.css +2 -0
  135. package/dist-lib/ui/AboutModal.d.ts +8 -0
  136. package/dist-lib/ui/BrandLoginFields.d.ts +25 -0
  137. package/dist-lib/ui/BrandLoginScreen.d.ts +11 -0
  138. package/dist-lib/ui/CharLoginModal.d.ts +32 -0
  139. package/dist-lib/ui/CmdLineMenuRegistry.d.ts +27 -0
  140. package/dist-lib/ui/CodeEditorPreview.d.ts +19 -0
  141. package/dist-lib/ui/CommandBar.d.ts +17 -0
  142. package/dist-lib/ui/ConnectionFormModal.d.ts +13 -0
  143. package/dist-lib/ui/ConnectionGrid.d.ts +18 -0
  144. package/dist-lib/ui/ConnectionScreen.d.ts +14 -0
  145. package/dist-lib/ui/FileBrowserModal.d.ts +20 -0
  146. package/dist-lib/ui/FilePickerModal.d.ts +21 -0
  147. package/dist-lib/ui/FolderPermissionScreen.d.ts +16 -0
  148. package/dist-lib/ui/JsonPreview.d.ts +15 -0
  149. package/dist-lib/ui/LogBrowserModal.d.ts +7 -0
  150. package/dist-lib/ui/MapEditorModal.d.ts +9 -0
  151. package/dist-lib/ui/MarkdownPreview.d.ts +15 -0
  152. package/dist-lib/ui/MergeConflictModal.d.ts +17 -0
  153. package/dist-lib/ui/ModuleResolveModal.d.ts +22 -0
  154. package/dist-lib/ui/MouseEventRegistry.d.ts +31 -0
  155. package/dist-lib/ui/ProfileBusyScreen.d.ts +12 -0
  156. package/dist-lib/ui/ProfileExportModal.d.ts +7 -0
  157. package/dist-lib/ui/ProxyInfoModal.d.ts +6 -0
  158. package/dist-lib/ui/ProxyWhyModal.d.ts +6 -0
  159. package/dist-lib/ui/ProxyWizardModal.d.ts +6 -0
  160. package/dist-lib/ui/QuickOpenPalette.d.ts +8 -0
  161. package/dist-lib/ui/ResizableModal.d.ts +17 -0
  162. package/dist-lib/ui/ScriptingDocsModal.d.ts +12 -0
  163. package/dist-lib/ui/SettingsModal.d.ts +9 -0
  164. package/dist-lib/ui/Toolbar.d.ts +29 -0
  165. package/dist-lib/ui/bufferWords.d.ts +38 -0
  166. package/dist-lib/ui/buttons/ButtonsBar.d.ts +21 -0
  167. package/dist-lib/ui/cmdline/CommandLineManager.d.ts +97 -0
  168. package/dist-lib/ui/cmdline/CommandLineOverlay.d.ts +8 -0
  169. package/dist-lib/ui/codemirror/theme.d.ts +5 -0
  170. package/dist-lib/ui/commandHistory.d.ts +31 -0
  171. package/dist-lib/ui/components/Button.d.ts +9 -0
  172. package/dist-lib/ui/components/ConfirmDialog.d.ts +29 -0
  173. package/dist-lib/ui/components/ContextMenu.d.ts +9 -0
  174. package/dist-lib/ui/components/FontPicker.d.ts +9 -0
  175. package/dist-lib/ui/components/FormField.d.ts +16 -0
  176. package/dist-lib/ui/components/HelpTip.d.ts +7 -0
  177. package/dist-lib/ui/components/Input.d.ts +6 -0
  178. package/dist-lib/ui/components/Toggle.d.ts +10 -0
  179. package/dist-lib/ui/components/index.d.ts +9 -0
  180. package/dist-lib/ui/components/useModalFocus.d.ts +18 -0
  181. package/dist-lib/ui/labels/LabelManager.d.ts +220 -0
  182. package/dist-lib/ui/labels/LabelOverlay.d.ts +9 -0
  183. package/dist-lib/ui/labels/backgroundImageSize.d.ts +10 -0
  184. package/dist-lib/ui/labels/cursorShapes.d.ts +6 -0
  185. package/dist-lib/ui/labels/gifMovie.d.ts +100 -0
  186. package/dist-lib/ui/labels/qtCss.d.ts +57 -0
  187. package/dist-lib/ui/layout/ContentLayout.d.ts +19 -0
  188. package/dist-lib/ui/layout/DockArea.d.ts +14 -0
  189. package/dist-lib/ui/layout/DockedPanel.d.ts +13 -0
  190. package/dist-lib/ui/layout/FloatingWindowLayer.d.ts +10 -0
  191. package/dist-lib/ui/layout/MobileLayout.d.ts +22 -0
  192. package/dist-lib/ui/layout/PopoutWindow.d.ts +35 -0
  193. package/dist-lib/ui/layout/ScriptWindow.d.ts +29 -0
  194. package/dist-lib/ui/layout/SplitGroupPanel.d.ts +17 -0
  195. package/dist-lib/ui/layout/TabGroupPanel.d.ts +12 -0
  196. package/dist-lib/ui/layout/WindowContextMenu.d.ts +11 -0
  197. package/dist-lib/ui/layout/dockDetect.d.ts +26 -0
  198. package/dist-lib/ui/layout/overlayLayerOrder.d.ts +71 -0
  199. package/dist-lib/ui/markdown.d.ts +1 -0
  200. package/dist-lib/ui/output/CaretReviewPanel.d.ts +22 -0
  201. package/dist-lib/ui/output/OutputArea.d.ts +9 -0
  202. package/dist-lib/ui/output/OutputContextMenu.d.ts +23 -0
  203. package/dist-lib/ui/output/OutputRenderer.d.ts +64 -0
  204. package/dist-lib/ui/output/ScreenReaderLog.d.ts +23 -0
  205. package/dist-lib/ui/output/StickyOutputPanel.d.ts +28 -0
  206. package/dist-lib/ui/output/backgroundImageStyle.d.ts +17 -0
  207. package/dist-lib/ui/output/caretMode.d.ts +40 -0
  208. package/dist-lib/ui/output/linkNavigation.d.ts +29 -0
  209. package/dist-lib/ui/output/osc8Menu.d.ts +16 -0
  210. package/dist-lib/ui/output/outputCopy.d.ts +15 -0
  211. package/dist-lib/ui/preventPinchZoom.d.ts +1 -0
  212. package/dist-lib/ui/scrollbox/ScrollBoxManager.d.ts +62 -0
  213. package/dist-lib/ui/scrollbox/ScrollBoxOverlay.d.ts +25 -0
  214. package/dist-lib/ui/sound/SoundManager.d.ts +149 -0
  215. package/dist-lib/ui/sound/closedCaption.d.ts +37 -0
  216. package/dist-lib/ui/textedit/TextEditManager.d.ts +56 -0
  217. package/dist-lib/ui/tts/TtsManager.d.ts +68 -0
  218. package/dist-lib/ui/useBrandLogin.d.ts +19 -0
  219. package/dist-lib/ui/useCommandHistory.d.ts +7 -0
  220. package/dist-lib/ui/video/VideoManager.d.ts +56 -0
  221. package/dist-lib/ui/windows/ScriptEditorModal.d.ts +13 -0
  222. package/dist-lib/ui/windows/WindowManager.d.ts +694 -0
  223. package/dist-lib/ui/windows/panels/HtmlPanel.d.ts +27 -0
  224. package/dist-lib/ui/windows/panels/LuaEditor.d.ts +14 -0
  225. package/dist-lib/ui/windows/panels/MapPanel.d.ts +8 -0
  226. package/dist-lib/ui/windows/panels/PackageRepositoryModal.d.ts +18 -0
  227. package/dist-lib/ui/windows/panels/ScriptEditorPanel.d.ts +24 -0
  228. package/dist-lib/ui/windows/panels/ScriptSearch.d.ts +12 -0
  229. package/dist-lib/ui/windows/panels/TextPanel.d.ts +35 -0
  230. package/dist-lib/ui/windows/panels/VariablesView.d.ts +21 -0
  231. package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +8 -0
  232. package/dist-lib/ui/windows/panels/WindowCmdLine.d.ts +23 -0
  233. package/dist-lib/ui/windows/types.d.ts +145 -0
  234. package/dist-lib/utils/documentTitle.d.ts +33 -0
  235. package/dist-lib/utils/fontLoader.d.ts +52 -0
  236. package/dist-lib/utils/profileLock.d.ts +26 -0
  237. package/dist-lib/utils/sessionCredentials.d.ts +16 -0
  238. package/dist-lib/version.d.ts +39 -0
  239. package/dist-lib/vfs-sw.js +131 -0
  240. package/dist-lib/vite.d.ts +2 -0
  241. package/dist-lib/vite.js +154 -0
  242. package/package.json +93 -0
@@ -0,0 +1,806 @@
1
+ import type { MudSession } from '../mud/MudSession';
2
+ import type { AliasEngine } from '../mud/aliases/AliasEngine';
3
+ import { TriggerEngine } from '../mud/triggers/TriggerEngine';
4
+ import type { TimerEngine } from '../mud/timers/TimerEngine';
5
+ import type { KeyEngine } from '../mud/keybindings/KeyEngine';
6
+ import type { ButtonNode, ScriptNode } from '../storage/schema';
7
+ import { type InstallOutcome } from './ScriptingAPI';
8
+ import type { EngineHost } from './EngineHost';
9
+ import type { LuaGlobalEntry } from './IScriptingRuntime';
10
+ import { ProfileVFS } from './vfs/ProfileVFS';
11
+ import type { PackageManifest } from '../storage/schema';
12
+ export declare class ScriptingEngine implements EngineHost {
13
+ private readonly session;
14
+ private readonly aliasEngine;
15
+ private readonly triggerEngine;
16
+ private readonly timerEngine;
17
+ private readonly keyEngine;
18
+ private readonly proxyUrlGetter;
19
+ private runtimes;
20
+ private readonly unsubs;
21
+ private readonly api;
22
+ private promptPending;
23
+ private mudCarryState;
24
+ private gmcpNegotiated;
25
+ private msdpNegotiated;
26
+ private msspNegotiated;
27
+ private mnesNegotiated;
28
+ private mxpNegotiated;
29
+ /** True once MXP (telnet option 91) has been negotiated on the live
30
+ * connection. Gates in-band MXP markup parsing in processFlushBatch so
31
+ * non-MXP MUDs (where `<grin>` is literal text) are untouched. Reset on
32
+ * connect/disconnect. */
33
+ private mxpActive;
34
+ /** Mudlet's Host::mForceMXPProcessorOn — setConfig("specialForceMXPProcessorOn")
35
+ * runs the in-band parser without an option-91 handshake, which is how a
36
+ * script can drive MXP markup through feedTriggers on a profile that never
37
+ * negotiated it. Does NOT enable the handshake replies. */
38
+ forceMxpProcessorOn: boolean;
39
+ /** Whether MXP `<SUPPORTS>`/`<VERSION>` handshake replies may be sent. Only
40
+ * true when MXP was started via the telnet option-91 handshake — an
41
+ * in-band-detected server's inbound MXP isn't confirmed, so we'd otherwise
42
+ * spam it with text it reads as invalid commands. */
43
+ private mxpHandshakeEnabled;
44
+ /** Per-session OSC 8 preset registry (`preset:NAME` definitions). Shared
45
+ * between the MXP parser and the plain-ANSI render path so a preset defined
46
+ * in either mode resolves in both. */
47
+ private readonly osc8Presets;
48
+ /** Drives expire-on-event OSC 8 visibility links (conceal on the next user
49
+ * input / prompt / output after they're clicked). Scans the live output. */
50
+ private readonly visibility;
51
+ /** Per-session MXP parser. The send callback carries the in-band
52
+ * `<SUPPORTS>`/`<VERSION>` handshake replies (gated on
53
+ * `mxpHandshakeEnabled`); `api` is read lazily at call time so this
54
+ * initializer is safe before the constructor body runs. */
55
+ private readonly mxp;
56
+ private vfs;
57
+ private readonly runtimeReady;
58
+ private readonly scriptsLoaded;
59
+ private resolveScriptsLoaded;
60
+ private scriptsLoadComplete;
61
+ private pendingConnectUrl;
62
+ private readonly mapOpen;
63
+ private readonly connectionId;
64
+ private storeUnsub;
65
+ private triggersReady;
66
+ private triggersDirty;
67
+ private prevScripts;
68
+ private resetting;
69
+ private disposed;
70
+ private moduleSyncTimers;
71
+ private static readonly MODULE_SYNC_DEBOUNCE_MS;
72
+ private profileDataSaveTimer;
73
+ private static readonly PROFILE_DATA_SAVE_DEBOUNCE_MS;
74
+ /** For a linked Mudlet profile: the timestamped current/*.xml filename this
75
+ * session writes back to (created lazily on first write, reused thereafter). */
76
+ private mudletSaveName;
77
+ private mspBaseUrl;
78
+ private gmcpMediaDefaultUrl;
79
+ private exitFired;
80
+ private readonly beforeUnload;
81
+ private uuidToNumericId;
82
+ private nextNumericId;
83
+ private numericIdFor;
84
+ constructor(session: MudSession, aliasEngine: AliasEngine, triggerEngine: TriggerEngine, timerEngine: TimerEngine, keyEngine: KeyEngine, connectionId: string, connectionName?: string, proxyUrlGetter?: () => string | undefined, injectedVfs?: ProfileVFS | null);
85
+ /**
86
+ * Subscribe to the appStore and apply diffs synchronously on every
87
+ * mutation. Zustand fires subscribers synchronously inside `set()`, so a
88
+ * UI action like `installPackage(...)` immediately propagates into the
89
+ * Lua runtime — handlers register before the caller's next line runs.
90
+ * That guarantee is what lets `notifyPackageInstalled` raise its event
91
+ * right after the store update without a React commit in between.
92
+ *
93
+ * Covers all five entity types — scripts, aliases, triggers, timers,
94
+ * keybindings — so the engine is the single owner of the
95
+ * store-to-runtime mapping. The UI just dispatches store actions.
96
+ *
97
+ * The first apply is gated on `output.ready` because some scripts open
98
+ * windows on load and the dock system needs to be wired up first.
99
+ * Triggers additionally wait for the PCRE wasm via TriggerEngine.ready()
100
+ * — patterns won't compile before that.
101
+ */
102
+ private attachToStore;
103
+ /**
104
+ * For each installed module, re-parse its on-disk XML and replace its tagged
105
+ * nodes in the store. Errors are logged but don't abort the rest of profile
106
+ * load — a corrupted module shouldn't take the whole session down.
107
+ */
108
+ private reloadModulesFromVfs;
109
+ /**
110
+ * Detect whether any node tagged with a sync-enabled module's name changed
111
+ * between two store states; for each module that changed, schedule a
112
+ * debounced write of its current XML to disk. Comparison is done per
113
+ * collection so an unrelated change in another module doesn't cause a write.
114
+ */
115
+ private scheduleModuleSyncForChanges;
116
+ private queueModuleSync;
117
+ /** Debounce a write of this profile's automation data to its VFS. */
118
+ private scheduleProfileDataSave;
119
+ /** Write this profile's automation data to its VFS now. */
120
+ private flushProfileData;
121
+ /**
122
+ * Restore this profile's saved Lua globals (Mudlet `<VariablePackage>`) into
123
+ * `_G`. Called once before the initial script load so handlers see their
124
+ * persisted state, and again after a profile reset (fresh global table).
125
+ */
126
+ private restoreSavedVariables;
127
+ /**
128
+ * Snapshot the save-listed globals out of `_G` into the store, just before a
129
+ * profile-data flush so the values land in `.mudix/profile.json`. Updates
130
+ * only the values (the save-list array reference is preserved), so the save
131
+ * subscription — which keys on the save-list — doesn't reschedule a flush.
132
+ */
133
+ private captureSavedVariables;
134
+ /**
135
+ * Write the live store state back into a linked Mudlet folder's profile save.
136
+ * Bases on the newest parseable save (so external Mudlet edits to Host/unknown
137
+ * fields are preserved), replaces the automation + variable packages with
138
+ * mudix's current data, and writes a Mudlet-style timestamped file in current/
139
+ * — one per session, overwritten on subsequent saves (the overwrite is safe
140
+ * now that the folder backend truncates). Mudlet loads the newest such file.
141
+ */
142
+ private writeBackLinkedProfile;
143
+ /** `_G` entries for the Variables view (user globals nested, built-ins
144
+ * flagged). Empty until the runtime is up. */
145
+ listGlobals(): LuaGlobalEntry[];
146
+ /**
147
+ * Write the current in-store nodes for a module back to its XML file on disk.
148
+ * Used both by the auto-sync debounce and the "Sync to file" UI action.
149
+ */
150
+ syncModuleToFile(moduleName: string): Promise<void>;
151
+ /**
152
+ * Re-read a module's XML from disk and replace its tagged nodes in the store.
153
+ * Pairs with the "Reload from file" UI action.
154
+ */
155
+ reloadModuleFromFile(moduleName: string): boolean;
156
+ /** Toggle a module's sync flag. Updates the manifest in the store. */
157
+ setModuleSync(moduleName: string, sync: boolean): void;
158
+ /** Read a module's sync flag. Returns false if the package isn't a module. */
159
+ getModuleSync(moduleName: string): boolean;
160
+ /**
161
+ * Set a module's load priority. Negative values cause its scripts to load
162
+ * before profile scripts on the next full reload. The priority is metadata
163
+ * only — changing it doesn't re-run anything; the new order takes effect on
164
+ * the next profile open or explicit reload.
165
+ */
166
+ setModulePriority(moduleName: string, priority: number): boolean;
167
+ /** Read a module's load priority (default 0). Returns 0 for non-modules. */
168
+ getModulePriority(moduleName: string): number;
169
+ /** List installed module names. Order matches install order. */
170
+ getModuleNames(): string[];
171
+ /** Snapshot of a module's manifest, or null if not installed / not a module. */
172
+ getModuleInfo(moduleName: string): PackageManifest | null;
173
+ /**
174
+ * In-memory custom info fields set via setPackageInfo / setModuleInfo. These
175
+ * mirror Mudlet's mPackageInfo / mModuleInfo — volatile string→string maps
176
+ * that overlay the manifest-derived fields, repopulated by scripts as
177
+ * needed (Mudlet itself loses them on restart too).
178
+ */
179
+ private packageInfoOverrides;
180
+ private moduleInfoOverrides;
181
+ /** Manifest's standard info fields as a string→string map (Mudlet's
182
+ * config.lua-derived package info keys). Empty values are omitted. */
183
+ private manifestInfoBase;
184
+ /** Overlay the in-memory custom fields for `name` onto `base` (mutates). */
185
+ private applyInfoOverrides;
186
+ /** Mudlet `getPackageInfo(name)`. Manifest fields overlaid with anything set
187
+ * via setPackageInfo. Empty table when the package is unknown and nothing
188
+ * was set for that name. */
189
+ getPackageInfo(name: string): Record<string, string>;
190
+ /** Mudlet `setPackageInfo(name, key, value)`. Records a custom info field.
191
+ * Always succeeds (matches Mudlet, which sets the map unconditionally). */
192
+ setPackageInfo(name: string, key: string, value: string): boolean;
193
+ /** Mudlet `setModuleInfo(name, key, value)`. Records a custom info field
194
+ * surfaced by getModuleInfo. Always succeeds. */
195
+ setModuleInfo(name: string, key: string, value: string): boolean;
196
+ /**
197
+ * Mudlet `getModulePath(name) → path`. Absolute VFS path of an installed
198
+ * module's XML. Modules referencing a file outside the managed package dir
199
+ * store it verbatim in `xmlVfsPath`; packaged modules store an XML path
200
+ * relative to `<profilePath>/<name>/`. Null when not installed, not a
201
+ * module, or no path is resolvable.
202
+ */
203
+ getModulePath(moduleName: string): string | null;
204
+ /**
205
+ * Install a module from a path inside the profile VFS. Plain XML stays in
206
+ * place (manifest holds the absolute VFS path). Zips/.mpackages extract into
207
+ * the standard pkgDir. Raises sysInstall, sysInstallPackage and
208
+ * sysInstallModule on success — sysInstallModule is the module-specific
209
+ * counterpart to sysInstallPackage. This method is reached only via the
210
+ * Lua `installModule()` binding, so it also raises Mudlet's
211
+ * `sysLuaInstallModule` (name, fileName) for ported-script parity.
212
+ */
213
+ installModuleFromPath(path: string): InstallOutcome;
214
+ /**
215
+ * Uninstall a module by name. Refuses to act on regular packages so callers
216
+ * can keep installPackage/uninstallPackage and installModule/uninstallModule
217
+ * cleanly separated. Modules unlink — the on-disk XML is left in place.
218
+ */
219
+ uninstallModuleByName(moduleName: string): boolean;
220
+ private findManifest;
221
+ private applyAliasesFromStore;
222
+ private applyTriggersFromStore;
223
+ private scheduleTriggerApply;
224
+ /**
225
+ * Drain any pending coalesced reloads synchronously. Callers that raise
226
+ * events whose handlers may depend on the just-mutated store (e.g.
227
+ * notifyPackageInstalled → sysInstallPackage) must call this between the
228
+ * store update and the event so handlers see the post-mutation engine state.
229
+ */
230
+ flushPendingApplies(): void;
231
+ private applyTimersFromStore;
232
+ private applyKeybindingsFromStore;
233
+ /**
234
+ * On profile open, warn about enabled keybindings the browser intercepts
235
+ * above the page (Ctrl+T new tab, Ctrl+W close tab, F12 devtools, …). Native
236
+ * Mudlet packages bind these freely, but in a browser they can never reach
237
+ * mudix — the warning explains why they "do nothing". Page-level shortcuts
238
+ * mudix can still capture (Ctrl+R, Ctrl+S, F5, …) are intentionally not
239
+ * flagged: they work while the client is focused, same as in Mudlet.
240
+ * Fired once at load (not on every store change) so it can't spam the output.
241
+ */
242
+ private warnBrowserReservedKeybindings;
243
+ private applyScriptsFromStore;
244
+ /** Map of module name → priority. Profile (no packageName) is implicitly 0. */
245
+ private modulePriorityMap;
246
+ private initRuntime;
247
+ /** Run a chunk of Lua on behalf of a clicked hyperlink. */
248
+ runLinkCode(code: string): void;
249
+ /** Mudlet `expandAlias` — run text through the alias pipeline, sending it
250
+ * to the MUD when nothing consumes it. */
251
+ expandAlias(text: string, echo: boolean): void;
252
+ /** Mudlet `reconnect()` — redial the last URL, refused during teardown. */
253
+ requestReconnect(): boolean;
254
+ /** Raise sysDataSendRequest; true means a handler called denyCurrentSend(). */
255
+ dispatchSendRequest(text: string): boolean;
256
+ /** Names of every package installed in this profile. */
257
+ getPackageNames(): string[];
258
+ /** Module manifest fields as a flat record, with Lua-set overrides applied. */
259
+ getModuleInfoRecord(name: string): Record<string, unknown> | null;
260
+ /** Rewrite VFS-relative url(...) references to service-worker paths. */
261
+ rewriteCss(css: string): string;
262
+ /** Rewrite VFS-relative `<img src>` / inline-style refs in Lua-supplied
263
+ * HTML to service-worker paths. */
264
+ rewriteHtml(html: string): string;
265
+ /** Raw-bytes reader for synchronous binary consumers (setMovie's GIF
266
+ * decoder). ProfileVFS resolves leading-slash paths absolutely (so
267
+ * getMudletHomeDir()-prefixed paths work) and relative ones against the
268
+ * profile root. */
269
+ readFileBytes(path: string): Uint8Array | null;
270
+ private createRuntime;
271
+ /**
272
+ * Tear down a script's event-handler registrations. Used when a script is
273
+ * removed or transitions enabled→disabled so its handlers stop firing
274
+ * before the next full runtime reload.
275
+ *
276
+ * Runs synchronously once the runtime is up so the store-subscription
277
+ * pipeline (script removed → handlers gone) completes inside the same
278
+ * tick as the store mutation. See attachToStore for the rationale.
279
+ */
280
+ unloadScript(scriptId: string): void;
281
+ /**
282
+ * Raise sysInstall / sysInstallPackage. The caller is expected to have
283
+ * just committed the package's items to the appStore — our subscription
284
+ * loads the new scripts synchronously inside that commit, so by the time
285
+ * this method runs the package's event handlers are already registered.
286
+ */
287
+ notifyPackageInstalled(packageName: string): void;
288
+ /**
289
+ * Raise sysUninstall / sysUninstallPackage. Call this BEFORE removing the
290
+ * package's items from the store so the package's own handlers (and the
291
+ * scripts they live in) are still loaded when the event fires.
292
+ */
293
+ notifyPackageUninstalled(packageName: string): void;
294
+ /**
295
+ * Stage a File dropped on a window into the profile VFS, then raise Mudlet's
296
+ * sysDropEvent(filepath, suffix, x, y, name) with the resulting VFS path. The
297
+ * bundled packageDrop handler (Other.lua) picks it up and routes acceptable
298
+ * suffixes to verbosePackageInstall / verboseModuleInstall — so dropping an
299
+ * XML/.mpackage/.zip onto the main console or a userwindow installs it, the
300
+ * same as Mudlet. Non-package files just land in the profile home dir, which
301
+ * matches the harmless no-op packageDrop does for unrecognised suffixes.
302
+ */
303
+ private stageDroppedFile;
304
+ /**
305
+ * Install a package from a path inside the VFS. Reads the bytes synchronously,
306
+ * commits to the store (which loads scripts into Lua synchronously via the
307
+ * store subscription), then raises sysInstallPackage. The disk flush happens
308
+ * in the background. Returns { ok: false, error } on any failure (file
309
+ * missing, parse error, etc.) — the error string is both printed to the
310
+ * script log and handed back to Lua for Mudlet's (ok, err) contract.
311
+ */
312
+ installPackageFromVfsPath(path: string): InstallOutcome;
313
+ /**
314
+ * Handle a `Client.GUI` GMCP message: download the URL and install the
315
+ * resulting package. Honors `client.allowMudPackageInstall` (default true,
316
+ * undefined = true). Deduplicates against previously-installed packages
317
+ * via `manifest.sourceUrl` + `manifest.sourceVersion` so the same MUD
318
+ * telling us to install on every connect doesn't churn the file system.
319
+ * The server's declared version is recorded as `sourceVersion` and never
320
+ * overwrites the package's own `version` — matching Mudlet, which keeps it
321
+ * in a separate `Host::mServerGUI_Package_version`.
322
+ */
323
+ /**
324
+ * Dispatch a parsed `!!SOUND` / `!!MUSIC` tag to the SoundManager. `Off`
325
+ * stops playback; otherwise the file is resolved against `<profile>/media/`
326
+ * (downloading from `U=` on cache miss) and the resulting VFS path is
327
+ * handed to the SoundManager.
328
+ */
329
+ /**
330
+ * Print a closed caption for a media play/stop, when `enableClosedCaption`
331
+ * is on (Mudlet's `TMedia::printClosedCaption`). The line is emitted as
332
+ * normal main-output text so it renders, is logged, and rides the screen-
333
+ * reader announce path — exactly as Mudlet's `mpConsole->print()` does.
334
+ */
335
+ private printClosedCaption;
336
+ private handleMspCommand;
337
+ /**
338
+ * Resolve an MSP `file` (+ optional `U=` base URL) to a VFS-relative path
339
+ * the SoundManager loader can read. Per the MSP spec `U=` is a *directory*
340
+ * the filename is appended to (not a full URL). Downloads land in
341
+ * `<profile>/media/` and are reused on subsequent plays and across page
342
+ * reloads. Returns null when the file can't be located or fetched.
343
+ */
344
+ private resolveMspMedia;
345
+ /**
346
+ * Resolve a media `file` (+ optional base `url` directory) to a VFS-relative
347
+ * path under `media/` the SoundManager loader can read, downloading and
348
+ * caching it on a miss. Shared by MSP (`resolveMspMedia`) and the GMCP media
349
+ * protocol (`handleClientMedia`). The whole filename — including any
350
+ * subdirectories — is appended to the base URL and mirrored under `media/`,
351
+ * so the cache layout matches the server's. `..`/`.` segments are rejected
352
+ * so a hostile server can't escape the cache root. Returns null when the
353
+ * file can't be located or fetched.
354
+ */
355
+ private resolveMediaFile;
356
+ /**
357
+ * Handle a GMCP media message (`Client.Media.Play/Load/Stop/Default`).
358
+ * Mirrors Mudlet's `TMedia` MediaProtocolGMCP. The payload is the already-
359
+ * parsed JSON body; `action` is the lowercased segment after `Client.Media`
360
+ * (defaulting to `play`, matching Mudlet's bare `Client.Media`). Server-
361
+ * driven, so playback rides the `game` mute gate like MSP.
362
+ */
363
+ private handleClientMedia;
364
+ private handleClientGuiInstall;
365
+ /** Guards against overlapping downloads — Mudlet TMap::mImportRunning. */
366
+ private mapDownloadRunning;
367
+ /**
368
+ * Mudlet TMap::downloadMap + slot_replyFinished: fetch the map the game
369
+ * published (GMCP `Client.Map` MMP location, or an explicit URL), load it
370
+ * into the map store, and raise `sysMapDownloadEvent` once it has parsed
371
+ * successfully. Like Mudlet, `.xml` locations go through the XML map
372
+ * importer and everything else through the binary `.dat` reader.
373
+ */
374
+ downloadMap(remoteUrl?: string): Promise<boolean>;
375
+ /**
376
+ * Uninstall a previously installed package by name. Raises sysUninstallPackage
377
+ * before the store removal so the package's own handlers can still run.
378
+ * Removes the on-disk package directory in the background.
379
+ */
380
+ uninstallPackageByName(packageName: string): boolean;
381
+ /**
382
+ * Toggle a script's enabled flag by name (Mudlet enableScript/disableScript).
383
+ * The store subscription picks up the change synchronously and either loads
384
+ * or unloads handlers in the runtime.
385
+ */
386
+ toggleScriptByName(name: string, enabled: boolean): boolean;
387
+ /**
388
+ * Toggle triggers' enabled flag by name (Mudlet enableTrigger/disableTrigger).
389
+ * Mudlet matches every trigger or group sharing the name, so we do the same:
390
+ * toggling a group cascades to children via isEffectivelyEnabled. All
391
+ * matching ids are flipped in one `set()` so the store subscription (and
392
+ * the trigger recompile it triggers) fires exactly once.
393
+ */
394
+ toggleTriggerByName(name: string, enabled: boolean): boolean;
395
+ /**
396
+ * Mudlet `setTriggerStayOpen(name, lines)`. Keeps every trigger matching the
397
+ * name open for `lines` more lines of input (Mudlet matches by name, which
398
+ * need not be unique). This affects only the *current* run: it adjusts the
399
+ * engine's transient chain window, leaving the persisted trigger (and its
400
+ * `fireLength`) untouched. Negative line counts clamp to 0, matching Mudlet.
401
+ */
402
+ setTriggerStayOpenByName(name: string, lines: number): boolean;
403
+ /**
404
+ * Toggle timers' enabled flag by name (Mudlet enableTimer/disableTimer).
405
+ * Same batching as toggleTriggerByName: one set() collapses N matches into
406
+ * a single subscription tick (and a single TimerEngine.loadPerm rebuild).
407
+ */
408
+ toggleTimerByName(name: string, enabled: boolean): boolean;
409
+ /**
410
+ * Toggle aliases' enabled flag by name (Mudlet enableAlias/disableAlias).
411
+ * Mirrors trigger/timer batching: flipping a group cascades to children via
412
+ * isEffectivelyEnabled at compile time, so one set() rebuilds AliasEngine once.
413
+ */
414
+ toggleAliasByName(name: string, enabled: boolean): boolean;
415
+ /**
416
+ * Toggle keybindings' enabled flag by name (Mudlet enableKey/disableKey).
417
+ * Mudlet matches every key (or group) sharing the name. The store has no
418
+ * batch keybinding update, so matches are flipped one at a time; the store
419
+ * subscription coalesces the resulting KeyEngine reloads within the tick.
420
+ */
421
+ toggleKeyByName(name: string, enabled: boolean): boolean;
422
+ /**
423
+ * Mudlet `exists(nameOrId, type)`. With a name string, returns the count of
424
+ * items matching the name in the named collection. With a numeric id, looks
425
+ * up the perm item by its monotonic id (the one permScript/permRegexTrigger
426
+ * etc. return) and reports 1 if it lives in the matching collection, else 0.
427
+ * Type aliases follow Mudlet: "key" and "keybind" both target keybindings.
428
+ * Unknown types return 0.
429
+ */
430
+ /** The saved keybinding carrying this numeric id, or null. Lets getKeyCode
431
+ * answer for a permanent key by the id permKey handed back, not just by
432
+ * name — the key engine only indexes permanent keys by name. */
433
+ keyNodeByNumericId(numericId: number): {
434
+ key: string;
435
+ modifiers: string[];
436
+ } | null;
437
+ /** enable/disable a script-created temp trigger or alias by numeric id.
438
+ * Those live in the Lua runtime, not the saved tree. */
439
+ setTempItemEnabled(id: number, enabled: boolean): boolean;
440
+ setForceMxpProcessorOn(on: boolean): void;
441
+ existsByName(nameOrId: string | number, type: string): number;
442
+ /**
443
+ * Mudlet `isActive(nameOrId, type [, checkAncestors])`. Returns the count of
444
+ * *active* items matching the name (1 or 0 for a numeric id). An item is
445
+ * active when its own enabled flag is set; with `checkAncestors` every
446
+ * ancestor group must be enabled too (isEffectivelyEnabled). Type aliases
447
+ * and the collection lookup mirror `existsByName`. Unknown types return 0.
448
+ */
449
+ isActiveByName(nameOrId: string | number, type: string, checkAncestors: boolean): number;
450
+ /**
451
+ * Shared type→node-list lookup for the tree-walking APIs (ancestors,
452
+ * findItems, isAncestorsActive). Type aliases mirror Mudlet: "key" and
453
+ * "keybind" both target keybindings. Unknown types return an empty list.
454
+ */
455
+ private nodeListForType;
456
+ private nodeTypeLabel;
457
+ /**
458
+ * Mudlet `ancestors(id, type)`. Walks from the item's immediate parent up to
459
+ * the root, returning each ancestor as `{id, name, node, isActive}` where
460
+ * `node` is "package"/"group"/"item" and `isActive` is that ancestor's own
461
+ * enabled flag. Returns null when no item of `type` carries the numeric `id`
462
+ * (the Lua wrapper turns that into a `(false, errMsg)` miss).
463
+ */
464
+ ancestorsById(id: number, type: string): Array<{
465
+ id: number;
466
+ name: string;
467
+ node: string;
468
+ isActive: boolean;
469
+ }> | null;
470
+ /**
471
+ * Mudlet `findItems(name, type [, exact [, caseSensitive]])`. Returns the
472
+ * numeric ids of every item (and group) whose name matches. `exact` (default
473
+ * true) toggles exact vs substring; `caseSensitive` (default true) toggles
474
+ * case folding. Empty array when nothing matches or the type is unknown.
475
+ */
476
+ findItemsByName(name: string, type: string, exact: boolean, caseSensitive: boolean): number[];
477
+ /**
478
+ * Mudlet `isAncestorsActive(id, type)`. True when every ancestor group of
479
+ * the item is enabled (the item's own state is ignored); true when the item
480
+ * sits at root with no ancestors. Returns null when no item of `type`
481
+ * carries the numeric `id`.
482
+ */
483
+ isAncestorsActiveById(id: number, type: string): boolean | null;
484
+ /**
485
+ * Mudlet `getProfileStats()`. Counts of total/active items per family plus
486
+ * the trigger pattern tally. Temporary items (tempTimer/tempAlias/... ) are
487
+ * not kept in the persisted node tree but live in the per-family engines, so
488
+ * their counts come from those engines: `temp` is the live temp count and
489
+ * is folded into `total`/`active` (a live temp is always active), matching
490
+ * Mudlet's report. Scripts have no temp form. There's no animated-GIF
491
+ * tracker, so `gifs` is always zero.
492
+ */
493
+ getProfileStats(): Record<string, unknown>;
494
+ /**
495
+ * Mudlet `permScript(name, parent, luaCode)`. Creates a saved Lua script
496
+ * named `name` under the script group `parent` (empty = root). Returns the
497
+ * new script's id on success, -1 if `parent` is given but no script group
498
+ * with that name exists. The store subscription loads the script's
499
+ * handlers synchronously inside the addScript commit.
500
+ */
501
+ createPermScript(name: string, parent: string, code: string): number;
502
+ /**
503
+ * Mudlet `permRegexTrigger(name, parent, regexes, luaCode)`. Creates a saved
504
+ * trigger named `name` under the trigger group `parent` (empty = root) with
505
+ * one or more regex patterns; matches fire OR-style. An empty `regexes` table
506
+ * creates a trigger group instead — matches the convention `permGroup` uses
507
+ * to bootstrap folders. Returns the new trigger's id, or -1 if `parent` is
508
+ * given but no trigger group with that name exists.
509
+ */
510
+ createPermRegexTrigger(name: string, parent: string, regexes: string[], code: string): number;
511
+ /**
512
+ * Mudlet `permSubstringTrigger(name, parent, patterns, luaCode)`. Same
513
+ * shape as createPermRegexTrigger but each pattern matches by substring
514
+ * (the temp-trigger semantics: literal `String.prototype.includes`).
515
+ */
516
+ createPermSubstringTrigger(name: string, parent: string, patterns: string[], code: string): number;
517
+ /**
518
+ * Mudlet `permBeginOfLineStringTrigger(name, parent, patterns, luaCode)`.
519
+ * Same shape as createPermSubstringTrigger but each pattern only matches at
520
+ * the start of the line (`String.prototype.startsWith`).
521
+ */
522
+ createPermBeginOfLineStringTrigger(name: string, parent: string, patterns: string[], code: string): number;
523
+ /**
524
+ * Mudlet `permExactMatchTrigger(name, parent, patterns, luaCode)`. Same
525
+ * shape as createPermSubstringTrigger but each pattern matches only on
526
+ * full-line equality (the temp-trigger `exactMatch` semantics).
527
+ */
528
+ createPermExactMatchTrigger(name: string, parent: string, patterns: string[], code: string): number;
529
+ /**
530
+ * Mudlet `permPromptTrigger(name, parent, luaCode)`. Creates a persistent
531
+ * trigger that fires on every server prompt line (GA/EOR). It carries a
532
+ * single pattern of type 'prompt' with empty text — not a group.
533
+ */
534
+ createPermPromptTrigger(name: string, parent: string, code: string): number;
535
+ private createPermTrigger;
536
+ /**
537
+ * Mudlet `permAlias(name, parent, regex, luaCode)`. Creates a saved alias
538
+ * named `name` under the alias group `parent` (empty = root). The pattern
539
+ * is treated as a PCRE regex (matches Mudlet's TAlias.mRegexCode).
540
+ * Returns the new alias id, or -1 if `parent` is non-empty but no alias
541
+ * group of that name exists.
542
+ */
543
+ createPermAlias(name: string, parent: string, pattern: string, code: string): number;
544
+ /**
545
+ * Mudlet `permTimer(name, parent, seconds, luaCode)`. Creates a saved
546
+ * one-shot timer under the timer group `parent` (empty = root). Returns
547
+ * the new timer id, or -1 if `parent` is non-empty but no timer group of
548
+ * that name exists.
549
+ */
550
+ createPermTimer(name: string, parent: string, delay: number, code: string): number;
551
+ /**
552
+ * Mudlet `permKey(name, parent, modifier, key, code)`. Creates a saved
553
+ * keybinding under the key group `parent` (empty = root). `modifier` uses
554
+ * the Qt::KeyboardModifier int (1=shift, 2=ctrl, 4=alt, 8=meta); -1 means
555
+ * "no modifier" — used by `permGroup(name,"key")` to make a key folder.
556
+ * Returns the new id or -1 when `parent` is non-empty but no key group of
557
+ * that name exists.
558
+ */
559
+ createPermKey(name: string, parent: string, modifier: number, key: string | number, code: string): number;
560
+ /**
561
+ * Mudlet `tempButton(toolbar, name, code[, orientation])`. Appends a
562
+ * transient button under an existing toolbar group. Returns the new id, or
563
+ * -1 when no toolbar of that name exists. `orientation` is round-tripped
564
+ * onto the leaf for parity with Mudlet — the renderer doesn't use it at the
565
+ * leaf, but ports that read it back via the store get a stable value.
566
+ */
567
+ createTempButton(toolbar: string, name: string, code: string, _orientation: number): number;
568
+ /**
569
+ * Mudlet `tempButtonToolbar(name [, orientation [, location]])`. Creates a
570
+ * transient toolbar (ButtonNode group). `orientation`: 0=horizontal,
571
+ * 1=vertical. `location`: 0=top, 1=bottom, 2=left, 3=right, 4=floating.
572
+ * Returns -1 when a toolbar group of that name already exists.
573
+ */
574
+ createTempButtonToolbar(name: string, orientation: number, location: number): number;
575
+ /** Mudlet `setButtonState(name, state)`. Flips the buttonState on the named
576
+ * two-state button. */
577
+ setButtonStateByName(name: string, state: boolean): boolean;
578
+ /** Mudlet `getButtonState(name)`. Reads the pressed state on a two-state
579
+ * button by name. Returns null when no such button (the Lua binding maps
580
+ * that to nil — Mudlet returns false/error). */
581
+ getButtonStateByName(name: string): boolean | null;
582
+ /** Mudlet `setButtonStyleSheet(name, css)`. Stores raw CSS on the
583
+ * ButtonNode; ButtonsBar applies it inline. */
584
+ setButtonStyleSheetByName(name: string, css: string): boolean;
585
+ /** Mudlet `showToolBar(name)` / `hideToolBar(name)`. Toggles the toolbar
586
+ * group's enabled flag (the ButtonsBar already filters by
587
+ * isEffectivelyEnabled, so this is the show/hide hook). */
588
+ toggleToolBarByName(name: string, show: boolean): boolean;
589
+ /**
590
+ * Mudlet `setScript(name, luaCode[, pos])`. Replaces the source of the
591
+ * `pos`-th script (1-indexed; default 1) named `name`. Updating via the
592
+ * store re-runs the script load through the regular subscription pipeline,
593
+ * so handlers re-register cleanly. Returns true on success, -1 if no such
594
+ * script exists.
595
+ */
596
+ setScriptByName(name: string, code: string, pos: number): number;
597
+ /**
598
+ * Mudlet `getScript(name [, pos]) → code, count`. Returns the source of the
599
+ * pos-th (1-indexed; default 1) script named `name` and how many scripts
600
+ * share that name. Returns null when none match — the Bridge.lua wrapper
601
+ * turns that into ("", 0).
602
+ */
603
+ getScriptByName(name: string, pos: number): {
604
+ code: string;
605
+ count: number;
606
+ } | null;
607
+ /**
608
+ * Mudlet `killTimer/killAlias/killTrigger/killKey(name)` deletes every
609
+ * permanent item sharing the given name. Returns true if at least one was
610
+ * removed. Mirrors `toggleTriggerByName`'s "all matches" semantics so
611
+ * groups and their sibling-named items vanish together. The store
612
+ * subscription tears down the runtime side (timers stop firing, triggers
613
+ * recompile) on the next tick.
614
+ */
615
+ killByName(kind: 'timer' | 'alias' | 'trigger' | 'key', name: string): boolean;
616
+ /**
617
+ * Run a single script on the existing runtime without restarting it.
618
+ *
619
+ * Runs synchronously when the runtime is already up. That sync path is
620
+ * load-bearing: notifyPackageInstalled raises sysInstallPackage right
621
+ * after applyScriptsFromStore returns, and the package's own event
622
+ * handlers (and the function `_G[scriptName]` they dispatch to) must be
623
+ * defined by then. An `await` here — even on an already-resolved promise
624
+ * — would defer the load to a microtask and the event would fire against
625
+ * an empty handler set.
626
+ */
627
+ reloadScript(script: ScriptNode): void;
628
+ /**
629
+ * Force-run a profile script's body right now, even if its code is unchanged.
630
+ * Backs the editor's "Run" / "Save & Run" button: the store subscription only
631
+ * re-runs a script when its code or handlers actually change (so editing one
632
+ * script doesn't re-execute its untouched siblings), which means clicking
633
+ * "Run" twice — or running a script you didn't edit — would otherwise do
634
+ * nothing. wrapScript kills the script's previously registered anonymous
635
+ * handlers before re-registering, so repeated runs stay idempotent.
636
+ */
637
+ runScript(scriptId: string): void;
638
+ private runScriptLoad;
639
+ get currentVFS(): ProfileVFS | null;
640
+ /**
641
+ * Send a command from the command bar. Raises sysDataSendRequest, then either
642
+ * sends (and echoes locally) or aborts when a handler calls denyCurrentSend().
643
+ */
644
+ sendCommand(text: string): void;
645
+ /** Run input through aliases. Returns true if an alias matched (caller should not send). */
646
+ processInput(text: string): boolean;
647
+ /** Process a keyboard event. Returns true if a keybinding consumed it. */
648
+ processKey(event: KeyboardEvent): boolean;
649
+ raiseEvent(event: string, args?: unknown[]): void;
650
+ /** Raise sysExitEvent at most once, while the Lua runtime is still alive. */
651
+ private fireExit;
652
+ notifyMapOpen(): void;
653
+ /** Hand the API a getter for the current command-line text, used until the
654
+ * first {@link setCmdLineValue} mirrors one. Pass null to clear. */
655
+ setCmdLineProvider(fn: (() => string) | null): void;
656
+ /** Mirror a command-bar edit so Lua's getCmdLine() reads it without waiting
657
+ * for a re-render. Called by ProfileSession on every change. */
658
+ setCmdLineValue(text: string): void;
659
+ /** Hand the API a startLogging hook. Wired by ProfileSession, which owns
660
+ * the actual SessionLogger lifecycle. */
661
+ setLoggingToggler(fn: ((enabled: boolean) => boolean) | null): void;
662
+ /** Mudlet's "Show errors in main console" — when on, script errors are also
663
+ * echoed (in red) into the main output window, not just the Errors tab. */
664
+ setShowErrorsInMainWindow(enabled: boolean): void;
665
+ /** Mudlet `appendLog(text)` — forward to the active SessionLogger. */
666
+ setLogAppender(fn: ((text: string) => void) | null): void;
667
+ /** Mudlet `closeMudlet()` — close the active profile (disconnect + return
668
+ * to the connection screen). */
669
+ setCloseProfileCallback(fn: (() => void) | null): void;
670
+ /**
671
+ * Mudlet `exportAreaImage(areaID, filePath[, zLevel])`. Renders the area to
672
+ * PNG bytes via the mounted map widget's renderer, then writes them to the
673
+ * profile VFS at `filePath` (relative paths resolve under the profile root,
674
+ * the same convention as `io.open`/`downloadFile`). Returns the absolute
675
+ * path written, or an error string (no VFS, mapper not open, or write
676
+ * failure). Mudlet requires the mapper open; mudix's renderer lives in the
677
+ * map widget, so the same precondition applies.
678
+ */
679
+ exportAreaImageToVfs(areaId: number, filePath: string, zLevel?: number): {
680
+ path: string;
681
+ } | {
682
+ error: string;
683
+ };
684
+ /**
685
+ * Mudlet `resetProfile()` — reload the entire profile as if just reopened:
686
+ * clear every UI surface, tear down and recreate the Lua runtime (fresh
687
+ * globals + event handlers), and re-run all scripts/aliases/triggers/timers/
688
+ * keys from the current profile state. The reinit is deferred to a fresh
689
+ * task: we are invoked from inside a Lua→JS call, and closing the lua_State
690
+ * mid-call would free the VM under the running call (WASM abort). This is
691
+ * exactly why Mudlet warns against calling it from a script-item — defer it
692
+ * (`tempTimer(0, resetProfile)` works) or run it from the command line. A
693
+ * concurrent reset is coalesced.
694
+ */
695
+ resetProfile(): void;
696
+ private performReset;
697
+ /**
698
+ * Resolves once the initial load pass has finished (scripts/aliases/timers/
699
+ * keys applied, sysLoadEvent fired, triggers compiled). The auto-connect
700
+ * path awaits this so the MUD socket isn't dialed until every handler and
701
+ * trigger is in place. Always resolves — never rejects — so a failed or
702
+ * torn-down load can't leave a profile waiting to connect forever.
703
+ */
704
+ whenScriptsLoaded(): Promise<void>;
705
+ /**
706
+ * Single entry point for dialing the MUD socket. Before the initial load
707
+ * finishes, the request is deferred (held in pendingConnectUrl) so the
708
+ * connection isn't made until every script handler and trigger is in place
709
+ * — this covers both the auto-connect on profile open and any script that
710
+ * calls connect()/connectToServer() from its body or a sysLoadEvent handler.
711
+ * Once loading is done, requests dial immediately (the normal reconnect
712
+ * path). The latest pending request wins, so exactly one socket opens.
713
+ */
714
+ /**
715
+ * Report a script-initiated call that teardown refused.
716
+ *
717
+ * Mudlet and mudix reach the same end state by opposite routes, and it is
718
+ * worth being precise about which:
719
+ *
720
+ * Mudlet guards the ARRIVAL side. `TMainConsole::closeEvent` raises
721
+ * sysExitEvent while `Host::mIsClosingDown` is still false, so a
722
+ * handler's connectToServer/reconnect is accepted and may even open a
723
+ * socket. `Host::closeChildren()` sets the flag afterwards, and every
724
+ * inbound callback is gated on it — cTelnet::slot_socketConnected,
725
+ * slot_socketDisconnected, slot_socketReadyToBeRead, postData,
726
+ * postMessage all early-return. The connection is accepted, then
727
+ * discarded.
728
+ *
729
+ * mudix guards the INITIATION side, because its teardown is synchronous:
730
+ * destroy() runs start to finish with no yield point, and MudSession
731
+ * disposes the client immediately after, so a socket opened here would
732
+ * be torn down microseconds later regardless. Refusing up front is the
733
+ * same outcome without the pointless socket.
734
+ *
735
+ * The observable difference is only what the script is told, and there
736
+ * mudix is deliberately the more honest of the two: Mudlet returns success
737
+ * for a connection that will never deliver a byte. Hence this log line —
738
+ * the divergence is intentional, but it must not be silent.
739
+ *
740
+ * Routed to script.log rather than the output window: by this point the
741
+ * console may already be unmounting, and the log buffer lives on MudSession
742
+ * so the Errors tab can still show it.
743
+ */
744
+ private refuseDuringTeardown;
745
+ requestConnect(url: string): void;
746
+ /**
747
+ * Mark the initial load complete: unblock whenScriptsLoaded() and dial any
748
+ * connect request that arrived while loading. Idempotent. Called on every
749
+ * load outcome — success, load failure, and teardown — so a connect never
750
+ * waits forever.
751
+ */
752
+ private markScriptsLoaded;
753
+ destroy(): void;
754
+ private reportEntityError;
755
+ private wrapScript;
756
+ private executePermAlias;
757
+ private executePermTrigger;
758
+ private executePermKeybinding;
759
+ /**
760
+ * Run a button's command + code. The Lua `code` runs on every click.
761
+ * For two-state buttons, `nextState=true` (going DOWN) sends `commandDown`,
762
+ * otherwise (going UP, or single-state click) sends `command`.
763
+ */
764
+ executeButton(button: ButtonNode, nextState: boolean): void;
765
+ /**
766
+ * Run a flushLines batch end-to-end: triggers, rendering, then deferred-echo
767
+ * flush. Shared between the network-driven flushLines listener and the
768
+ * scripting `feedTriggers` API so both paths preserve identical semantics
769
+ * (line ordering, ANSI carry, trigger-echo placement).
770
+ */
771
+ /** Part of {@link EngineHost} — also reached directly from the flushLines
772
+ * subscription, and by feedTriggers via the host so synthetic batches share
773
+ * ordering semantics with network output. */
774
+ processFlushBatch(groups: {
775
+ text: string;
776
+ type: string;
777
+ }[]): void;
778
+ /**
779
+ * Attach clickable hyperlinks for the MXP `<SEND>`/`<A>` ranges the parser
780
+ * found. `setHyperlink` overlays each range while preserving the segments'
781
+ * existing colours/attributes (including the underline the parser applied as
782
+ * a link cue). Link behaviour — send a MUD command, open a URL in a new tab,
783
+ * or pop up a multi-command menu — is built by ScriptingAPI.
784
+ */
785
+ private wireMxpLinks;
786
+ /**
787
+ * Turn OSC 8 hyperlinks (recorded by the ANSI/MXP parser as a bare `url` on
788
+ * the segment) into clickable links. `createOsc8Hyperlink` maps the URI's
789
+ * scheme to the action — send a command, seed the command bar, or open a
790
+ * URL — and drops links whose scheme isn't allowed. Runs after
791
+ * `wireMxpLinks` so an MXP `<SEND>` overlaid on the same text wins.
792
+ */
793
+ private wireOsc8Links;
794
+ /**
795
+ * Run all triggers against `plain` (the original ANSI-stripped text).
796
+ * Trigger handlers that call selectString/fg/bg/deleteLine modify `buffer`
797
+ * in-place. The buffer is NOT rendered here — the caller renders it after
798
+ * this returns, so the final rendered line already has all colorization.
799
+ *
800
+ * echo/cecho output from trigger handlers is deferred (via ScriptingAPI)
801
+ * and flushed after all lines in the batch are rendered.
802
+ */
803
+ private processLineTriggers;
804
+ private emit;
805
+ private bridgeEvents;
806
+ }