diff options
Diffstat (limited to 'modules/core/core-bundle.js')
| -rw-r--r-- | modules/core/core-bundle.js | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js index a9a8de5..00043bc 100644 --- a/modules/core/core-bundle.js +++ b/modules/core/core-bundle.js @@ -2716,7 +2716,12 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm this._baseDestructive = ['delete','del','write','save','overwrite','format','kill','stop','shutdown','reboot']; this._baseSystem = ['reboot','shutdown','format','kill','halt','poweroff']; this._baseSuspiciousFlags = ['--dump','--execute','--eval','--exec','--shell','--script']; - this._baseWhitelist = ['help','clear','ls','cat','pwd','whoami','df','free','top','ps','echo','date','env','history','find','grep','tree','head','tail','sed','wc','sort','du','diff','which','hostname','cal','basename','dirname','yes','seq','cut','uniq','expand','printf','base64','sleep','ll','h','mem','status','health-check','system-health','alias','unalias','modules','listmods','modules-list','nvfs-index','nvfs-status','nvfs-resolve','nvfs-tree','nvfs-config','nvfs-alias','nvfs-sync','floating-add','floating-remove','floating-list','floating-pos','floating-clear','floating-toggle','mem-debug','reset-mem','reset','factory-reset','reset-vfs','js','js-run','node','debug','debug-ai','debug-stats','debug-history','debug-analyze','debug-trends','debug-fix','debug-health','session-new','orchestrate','orchestrate-parallel','orchestrate-decompose','orchestrate-result','orchestrator-status','orchestrator-spawn','orchestrator-kill','orchestrator-purge','orchestrator-config','orchestrator-list','orchestrator-sleep','orchestrator-wake','orchestrator-restart-policy','a2a-send','a2a-list','a2a-post','a2a-poll','a2a-ack','a2a-reject','a2a-status','a2a-prune','consensus','consensus-status','consensus-history','pipeline','agent-list','agent-register','agent-status','agent-unregister','contract-list','contract-register','voice','speak','analyze','dashboard','context-auto']; + this._baseWhitelist = ['help','clear','ls','cat','pwd','whoami','df','free','top','ps','echo','date','env','history','find','grep','tree','head','tail','sed','wc','sort','du','diff','which','hostname','cal','basename','dirname','yes','seq','cut','uniq','expand','printf','base64','sleep','ll','h','mem','status','health-check','system-health','alias','unalias','modules','listmods','modules-list','nvfs-index','nvfs-status','nvfs-resolve','nvfs-tree','nvfs-config','nvfs-alias','nvfs-sync','floating-add','floating-remove','floating-list','floating-pos','floating-clear','floating-toggle','mem-debug','reset-mem','reset','factory-reset','reset-vfs','js','js-run','node','debug','debug-ai','debug-stats','debug-history','debug-analyze','debug-trends','debug-fix','debug-health','session-new','orchestrate','orchestrate-parallel','orchestrate-decompose','orchestrate-result','orchestrator-status','orchestrator-spawn','orchestrator-kill','orchestrator-purge','orchestrator-config','orchestrator-list','orchestrator-sleep','orchestrator-wake','orchestrator-restart-policy','a2a-send','a2a-list','a2a-post','a2a-poll','a2a-ack','a2a-reject','a2a-status','a2a-prune','consensus','consensus-status','consensus-history','pipeline','agent-list','agent-register','agent-status','agent-unregister','contract-list','contract-register','voice','speak','analyze','dashboard','context-auto', + // 'ui' is a SAFE, non-destructive switch command. It used to be known only while the + // shell module was registered, so in classic the security layer classified it unknown + // (level 1) and routed it to the AI instead of dispatching — "Ui command don't work" + // (2026-11-12). Never leave a navigation command dependent on the UI it navigates. + 'ui']; this.destructiveCmds = new Set(this._baseDestructive); this.systemCmds = new Set(this._baseSystem); this.suspiciousFlags = new Set(this._baseSuspiciousFlags); @@ -4134,6 +4139,47 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm } } } + /** Register + initialise the UI shell on demand, then run a `ui …` request through it. + * + * The boot path registers UIShellModule only when the visitor opted in (v4.6.162 gate), + * which made the `ui` command itself unavailable in classic — the one place a user would + * type it. registerModule() wires commands, but init() is what the boot loop calls for + * every module, so it is called here too. + */ + async _uiEnsureShell(args) { + const mm = this.moduleManager; + let shell = mm && mm.modules ? mm.modules['UIShellModule'] : null; + if (!shell) { + shell = this._mountUIShell(); + if (!shell) { this.print('Interface modes are not available in this browser.', 'error'); return; } + } + if (!shell || typeof shell.handle !== 'function') { + this.print('Interface modes are not available in this browser — the UI shell did not register.', 'error'); + return; + } + // Same opt-in the picker writes, so the next visit keeps the interface. + try { localStorage.setItem('webx11_ui_experimental', '1'); } catch (e) {} + return shell.handle(args && args.length ? args : ['picker']); + } + /** Construct, register and initialise the UI shell on demand (the `ui` command's own mount). + * + * Deliberately NOT the boot-time safe-registration path (the one guarded by `_uiExp`): that is + * verify-newos4-ui-gate.py fails on any bare occurrence of it — a guard that allows one + * exception has to allow whatever is written next to it. This path is distinguishable by + * intent, so it is distinguishable by name. + */ + _mountUIShell() { + if (typeof UIShellModule === 'undefined') return null; + const shell = new UIShellModule(); + try { + this.moduleManager.registerModule(shell); // wires shell.commands['ui'] + if (typeof shell.init === 'function') shell.init(this); + } catch (e) { + console.error('[Terminal] UI shell mount failed:', e); + return null; + } + return shell; + } _safeRegister(className, label) { // Safe class lookup — no eval(). Classes are registered in global scope by the bundle. const registry = { @@ -4723,6 +4769,11 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm } } } + // `ui` must work in CLASSIC too. The command is owned by UIShellModule, which is only + // registered when the visitor has already opted in — so the switch command was missing + // in exactly the state you need it from ("Ui command don't work", 2026-11-12). Mount the + // shell on demand instead of telling anyone to edit the URL. + if (cmd === 'ui') { await this._uiEnsureShell(args); return; } // Enhanced: check fuzzy suggestions before showing "not found" const suggestion = this.security.suggest(cmd); if (suggestion && suggestion.dist <= 2 && suggestion.dist > 0) { |