@devframes/hub 1.2.5 → 1.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.
@@ -1,5 +1,5 @@
1
1
  import { a as resolveClientModuleSpecifier } from "./remote-url-UClKLQ5_.mjs";
2
- import { v as prepareDevframe, y as diagnostics } from "./context-DRdTViYd.mjs";
2
+ import { v as prepareDevframe, y as diagnostics } from "./context-0RunDMBy.mjs";
3
3
  import { joinURL, withTrailingSlash } from "devframe/utils/url";
4
4
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_MCP_ROUTE, DEVFRAME_WS_ROUTE } from "devframe/constants";
5
5
  import { existsSync } from "node:fs";
@@ -1,7 +1,7 @@
1
- import { A as DevframeViewIframe, C as DevframeDockUserEntry, F as RemoteConnectionInfo, P as NavTarget, S as DevframeDockPanelState, _ as DevframeDockEntry, a as DevframeCommandEntry, b as DevframeDockEntryIcon, g as DevframeDockEntriesGrouped, n as DevframeClientCommand, p as ClientScriptEntry, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings } from "../settings-DPLPzYfX.mjs";
2
- import { n as resolveTitle, t as matchLocale } from "../locale-C3-NpDlX.mjs";
3
- import { k as DevframeMessagesClient, w as DevframeMessageEntryInput } from "../context-BK50aJ-F.mjs";
4
- import "../index-BvEO3eOd.mjs";
1
+ import { A as DevframeViewIframe, C as DevframeDockUserEntry, F as RemoteConnectionInfo, P as NavTarget, S as DevframeDockPanelState, _ as DevframeDockEntry, a as DevframeCommandEntry, b as DevframeDockEntryIcon, g as DevframeDockEntriesGrouped, n as DevframeClientCommand, p as ClientScriptEntry, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings } from "../settings-UN5GnTei.mjs";
2
+ import { n as resolveTitle, t as matchLocale } from "../locale-CGR6YyCP.mjs";
3
+ import { k as DevframeMessagesClient, w as DevframeMessageEntryInput } from "../context-Iy5i89Aq.mjs";
4
+ import "../index-tijpvneP.mjs";
5
5
  import { DevframeClientRpcHost, DevframeConnection, DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions, DevframeRpcContext, RpcClientEvents, RpcClientEvents as RpcClientEvents$1 } from "devframe/client";
6
6
  import { EventEmitter } from "devframe/types";
7
7
  import { SharedState } from "devframe/utils/shared-state";
@@ -183,13 +183,18 @@ export interface DockSessionStorage {
183
183
  */
184
184
  selectedDockRoute: string | null;
185
185
  /**
186
- * The dock entry most recently selected from beyond the float bar's inline
187
- * capacity, whether from the overflow popover or from inside a dock group. A hub UI
188
- * provider raises this entry into a dedicated slot between the bar's visible
189
- * items and the overflow button, so deselecting it (or selecting a visible
190
- * neighbour) keeps it one click away instead of folding it straight back
191
- * into the overflow. `null` (or absent, for stores persisted before this
192
- * field existed) when no entry has been raised.
186
+ * The dock entries most recently selected from beyond the float bar's
187
+ * inline capacity, whether from the overflow popover or from inside a dock
188
+ * group, newest first. A hub UI provider raises these entries into their own
189
+ * slots after the bar's visible items, so they stay one click away instead
190
+ * of folding back into the overflow or the group popover. Absent (for stores
191
+ * persisted before this field existed) or empty when nothing has been raised.
192
+ */
193
+ recentDockIds?: string[];
194
+ /**
195
+ * @deprecated Superseded by {@link DockSessionStorage.recentDockIds}. Still
196
+ * read as a one-entry list when `recentDockIds` is absent, so a tab that
197
+ * persisted the older field keeps its recent dock after an upgrade.
193
198
  */
194
199
  recentDockId?: string | null;
195
200
  /**
@@ -322,6 +327,14 @@ export interface DocksEntriesContext {
322
327
  * @returns Whether the selection was changed successfully
323
328
  */
324
329
  toggleEntry: (id: string) => Promise<boolean>;
330
+ /**
331
+ * Turn a {@link import('../types/docks').DevframeViewAction.toggle toggle action}
332
+ * on or off without touching the selection. Turning it on hides an open panel;
333
+ * turning it off restores that panel.
334
+ *
335
+ * @returns Whether the action's state changed
336
+ */
337
+ setActionActive: (id: string, active: boolean) => Promise<boolean>;
325
338
  /**
326
339
  * Register a **client-only** dock entry, live in this page and merged with
327
340
  * the server-provided docks (`devframe:docks` shared state) into
@@ -353,6 +366,7 @@ export interface DockRegistration<T extends DevframeDockEntry = DevframeDockEntr
353
366
  }
354
367
  export interface DockEntryState {
355
368
  entryMeta: DevframeDockEntry;
369
+ /** Whether the entry is selected, or, for a toggle action, whether it is on. */
356
370
  readonly isActive: boolean;
357
371
  domElements: {
358
372
  iframe?: HTMLIFrameElement | null;
@@ -587,6 +587,10 @@ async function createDevframeClientRuntime(options = {}) {
587
587
  rpc.sharedState.get(DOCK_RENDERERS_STATE_KEY, { initialValue: {} })
588
588
  ]);
589
589
  let selectedId = null;
590
+ /** Toggle actions that are on; they never take the selection. */
591
+ const activeActions = /* @__PURE__ */ new Set();
592
+ /** Whether turning the last toggle action off should reopen the panel it hid. */
593
+ let reopenPanel = false;
590
594
  /** Bumped by every `switchEntry` call, so a stale one can tell it was superseded. */
591
595
  let switchRequest = 0;
592
596
  const entryToStateMap = /* @__PURE__ */ new Map();
@@ -672,7 +676,7 @@ async function createDevframeClientRuntime(options = {}) {
672
676
  return {
673
677
  entryMeta,
674
678
  get isActive() {
675
- return selectedId === entryMeta.id;
679
+ return selectedId === entryMeta.id || activeActions.has(entryMeta.id);
676
680
  },
677
681
  domElements: {},
678
682
  events: createEventEmitter()
@@ -731,6 +735,7 @@ async function createDevframeClientRuntime(options = {}) {
731
735
  if (seen.has(id)) continue;
732
736
  const removed = entryToStateMap.get(id);
733
737
  entryToStateMap.delete(id);
738
+ if (activeActions.delete(id) && activeActions.size === 0) restorePanel();
734
739
  const removedMeta = removed?.entryMeta;
735
740
  if (removedMeta?.type === "iframe" && removedMeta.subTabs) {
736
741
  const frameId = removedMeta.frameId ?? id;
@@ -775,6 +780,7 @@ async function createDevframeClientRuntime(options = {}) {
775
780
  getStateById: (id) => entryToStateMap.get(id),
776
781
  switchEntry,
777
782
  toggleEntry: (id) => selectedId === id ? switchEntry(null) : switchEntry(id),
783
+ setActionActive,
778
784
  register(entry, force) {
779
785
  if (clientDocks.has(entry.id) && !force) throw new Error(`[@devframes/hub] a client dock "${entry.id}" is already registered; pass force to overwrite`);
780
786
  clientDocks.set(entry.id, entry);
@@ -811,8 +817,56 @@ async function createDevframeClientRuntime(options = {}) {
811
817
  if (entry.type === "action") await setupClientScript(entry.id, entry.action, false);
812
818
  else if (entry.type === "custom-render") await setupClientScript(entry.id, entry.renderer);
813
819
  }
820
+ function isToggleAction(entry) {
821
+ return entry?.type === "action" && !!entry.toggle;
822
+ }
823
+ function restorePanel() {
824
+ if (reopenPanel) panel.session.open = true;
825
+ reopenPanel = false;
826
+ }
827
+ /** A new selection wins over the panel a toggle action hid, so it is not restored. */
828
+ function turnOffActions() {
829
+ reopenPanel = false;
830
+ for (const id of [...activeActions]) {
831
+ activeActions.delete(id);
832
+ entryToStateMap.get(id)?.events.emit("entry:deactivated");
833
+ }
834
+ }
835
+ async function setActionActive(id, active) {
836
+ const state = entryToStateMap.get(id);
837
+ const entry = state?.entryMeta;
838
+ if (!state || entry?.type !== "action" || !entry.toggle || activeActions.has(id) === active) return false;
839
+ if (!active) {
840
+ activeActions.delete(id);
841
+ state.events.emit("entry:deactivated");
842
+ if (activeActions.size === 0) restorePanel();
843
+ return true;
844
+ }
845
+ if (loadScriptsEnabled) {
846
+ if (!rpc.isTrusted) return false;
847
+ await setupClientScript(id, entry.action);
848
+ if (disposed || activeActions.has(id) || entryToStateMap.get(id) !== state) return false;
849
+ }
850
+ if (activeActions.size === 0) {
851
+ reopenPanel = panel.session.open;
852
+ panel.session.open = false;
853
+ }
854
+ activeActions.add(id);
855
+ state.events.emit("entry:activated");
856
+ return true;
857
+ }
858
+ /** A click flips a toggle action; clearing an empty selection still turns tools off. */
859
+ function switchToggleAction(next) {
860
+ if (next !== null && isToggleAction(entryToStateMap.get(next)?.entryMeta)) return setActionActive(next, !activeActions.has(next));
861
+ if (next === null && selectedId === null && activeActions.size > 0) {
862
+ turnOffActions();
863
+ return Promise.resolve(true);
864
+ }
865
+ }
814
866
  async function switchEntry(id) {
815
867
  const next = id ?? null;
868
+ const toggled = switchToggleAction(next);
869
+ if (toggled) return toggled;
816
870
  if (next === selectedId && entryToStateMap.get(next ?? "")?.entryMeta.type !== "action") return false;
817
871
  if (next !== null && !entryToStateMap.has(next)) return false;
818
872
  const entry = entryToStateMap.get(next ?? "")?.entryMeta;
@@ -822,6 +876,7 @@ async function createDevframeClientRuntime(options = {}) {
822
876
  if (request !== switchRequest) return false;
823
877
  const previous = selectedId;
824
878
  selectedId = next;
879
+ turnOffActions();
825
880
  panel.session.selectedDockId = next;
826
881
  if (next === null || entryToStateMap.get(next)?.entryMeta.type !== "iframe") panel.session.selectedDockRoute = null;
827
882
  if (previous) entryToStateMap.get(previous)?.events.emit("entry:deactivated");
@@ -1,4 +1,4 @@
1
- import { t as DevframeDocksUserSettings } from "./settings-DPLPzYfX.mjs";
1
+ import { t as DevframeDocksUserSettings } from "./settings-UN5GnTei.mjs";
2
2
  //#region src/events.d.ts
3
3
  /**
4
4
  * Centralized registry of every event, broadcast, RPC method, shared-state
@@ -1,3 +1,3 @@
1
- import { a as normalizeHubBase, i as DOCK_RENDERERS_STATE_KEY, n as DEFAULT_STATE_USER_SETTINGS, o as HUB_EVENTS, r as DEVFRAMES_HUB_BASE, t as DEFAULT_CATEGORIES_ORDER } from "./constants-C7cDDASI.mjs";
1
+ import { a as normalizeHubBase, i as DOCK_RENDERERS_STATE_KEY, n as DEFAULT_STATE_USER_SETTINGS, o as HUB_EVENTS, r as DEVFRAMES_HUB_BASE, t as DEFAULT_CATEGORIES_ORDER } from "./constants-H0A2VIz0.mjs";
2
2
  export * from "devframe/constants";
3
3
  export { DEFAULT_CATEGORIES_ORDER, DEFAULT_STATE_USER_SETTINGS, DEVFRAMES_HUB_BASE, DOCK_RENDERERS_STATE_KEY, HUB_EVENTS, normalizeHubBase };
@@ -12,6 +12,7 @@ import { getInternalContext, resolveBasePath } from "devframe/node/hub-internals
12
12
  import { createHostContext, createStorage } from "devframe/node";
13
13
  import { debounce } from "devframe/utils/debounce";
14
14
  import { nanoid } from "devframe/utils/nanoid";
15
+ import { extname, resolve as resolve$1 } from "node:path";
15
16
  //#region src/node/diagnostics.ts
16
17
  /**
17
18
  * Hub-side diagnostics for docks, terminals, messages, and commands.
@@ -671,6 +672,66 @@ var DevframeMessagesHost = class {
671
672
  }
672
673
  };
673
674
  //#endregion
675
+ //#region src/node/pty-command.ts
676
+ const DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
677
+ const CMD_META_CHARS = /[()[\]%!^"`<>&|;, *?]/g;
678
+ function resolvePtyCommand(command, args, { cwd, env, platform = process.platform }) {
679
+ if (platform !== "win32") return {
680
+ command,
681
+ args
682
+ };
683
+ const comSpec = getEnv(env, "ComSpec") || "cmd.exe";
684
+ if (isCmd(command, comSpec)) return {
685
+ command,
686
+ args
687
+ };
688
+ const resolved = findExecutable(command, cwd, env);
689
+ const ext = resolved ? extname(resolved).toLowerCase() : "";
690
+ if (ext === ".exe" || ext === ".com") return {
691
+ command,
692
+ args
693
+ };
694
+ const isBatch = ext === ".cmd" || ext === ".bat";
695
+ return {
696
+ command: comSpec,
697
+ args: [
698
+ "/d",
699
+ "/c",
700
+ escapeCmd(command, false),
701
+ ...args.map((arg) => escapeCmd(arg, isBatch))
702
+ ]
703
+ };
704
+ }
705
+ function getEnv(env, name) {
706
+ const key = Object.keys(env).findLast((key) => key.toLowerCase() === name.toLowerCase());
707
+ return key ? env[key] : void 0;
708
+ }
709
+ function isCmd(command, comSpec) {
710
+ const name = command.toLowerCase();
711
+ return name === comSpec.toLowerCase() || name === "cmd" || name === "cmd.exe";
712
+ }
713
+ function findExecutable(command, cwd, env) {
714
+ const extensions = (getEnv(env, "PATHEXT") || DEFAULT_PATHEXT).toLowerCase().split(";").filter(Boolean);
715
+ const candidates = extname(command) ? [command, ...extensions.map((ext) => command + ext)] : extensions.map((ext) => command + ext);
716
+ const searchCwd = getEnv(env, "NoDefaultCurrentDirectoryInExePath") === void 0;
717
+ const dirs = /[\\/]/.test(command) ? [cwd] : [...searchCwd ? [cwd] : [], ...(getEnv(env, "PATH") || "").split(";").filter(Boolean)];
718
+ for (const dir of dirs) for (const candidate of candidates) {
719
+ const file = resolve$1(dir, candidate);
720
+ if (existsSync(file)) return file;
721
+ }
722
+ }
723
+ /**
724
+ * Escape `cmd.exe` metacharacters in an argument zigpty passes unquoted.
725
+ * zigpty double-quotes empty arguments and ones with a space, tab, quote or
726
+ * backslash, and `cmd.exe` keeps quoted metacharacters literal, so those
727
+ * are left alone - a `^` added there would reach the program as-is.
728
+ */
729
+ function escapeCmd(arg, doubleEscape) {
730
+ if (!arg || /[ \t"\\]/.test(arg)) return arg;
731
+ const escaped = arg.replace(CMD_META_CHARS, "^$&");
732
+ return doubleEscape ? escaped.replace(CMD_META_CHARS, "^$&") : escaped;
733
+ }
734
+ //#endregion
674
735
  //#region src/node/host-terminals.ts
675
736
  /**
676
737
  * Channel name used for terminal stream output. Stable, well-known so
@@ -971,18 +1032,24 @@ var DevframeTerminalsHost = class {
971
1032
  });
972
1033
  const spawnPty = () => {
973
1034
  const currentRun = ++runId;
974
- const ptyProcess = spawn(executeOptions.command, executeOptions.args ?? [], {
1035
+ const cwd = executeOptions.cwd ?? process.cwd();
1036
+ const env = {
1037
+ ...process.env,
1038
+ TERM: PTY_TERM_NAME,
1039
+ COLORTERM: "truecolor",
1040
+ FORCE_COLOR: "1",
1041
+ ...executeOptions.env ?? {}
1042
+ };
1043
+ const { command, args } = resolvePtyCommand(executeOptions.command, executeOptions.args ?? [], {
1044
+ cwd,
1045
+ env
1046
+ });
1047
+ const ptyProcess = spawn(command, args, {
975
1048
  name: PTY_TERM_NAME,
976
1049
  cols,
977
1050
  rows,
978
- cwd: executeOptions.cwd ?? process.cwd(),
979
- env: {
980
- ...process.env,
981
- TERM: PTY_TERM_NAME,
982
- COLORTERM: "truecolor",
983
- FORCE_COLOR: "1",
984
- ...executeOptions.env ?? {}
985
- }
1051
+ cwd,
1052
+ env
986
1053
  });
987
1054
  const outputChunks = [];
988
1055
  let killed = false;
@@ -1,4 +1,4 @@
1
- import { A as DevframeViewIframe, T as DevframeDocksHost, b as DevframeDockEntryIcon, l as DevframeCommandsHost, m as DevframeDockActivation } from "./settings-DPLPzYfX.mjs";
1
+ import { A as DevframeViewIframe, T as DevframeDocksHost, b as DevframeDockEntryIcon, l as DevframeCommandsHost, m as DevframeDockActivation } from "./settings-UN5GnTei.mjs";
2
2
  import { CreateHostContextOptions } from "devframe/node";
3
3
  import { DevframeDefinition, DevframeHost, DevframeNodeContext, EventEmitter } from "devframe/types";
4
4
  import { ChildProcess } from "node:child_process";
@@ -1,5 +1,5 @@
1
- import "./settings-DPLPzYfX.mjs";
2
- import "./context-BK50aJ-F.mjs";
1
+ import "./settings-UN5GnTei.mjs";
2
+ import "./context-Iy5i89Aq.mjs";
3
3
  import { RpcDefinitionsFilter, RpcDefinitionsToFunctions } from "devframe/rpc";
4
4
  import { ConnectionMeta as ConnectionMeta$1, DevframeCapabilities, DevframeDiagnosticsHost, DevframeDiagnosticsLogger, DevframeHost as DevframeHost$1, DevframeNodeRpcSession, DevframeRpcClientFunctions, DevframeRpcServerFunctions, DevframeRpcSharedStates, DevframeViewHost, EventEmitter as EventEmitter$1, EventUnsubscribe, EventsMap, RpcBroadcastOptions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, RpcStreamingChannel, RpcStreamingChannelOptions, RpcStreamingHost } from "devframe/types";
5
5
  export { RpcStreamingHost as S, RpcFunctionsHost as _, DevframeHost$1 as a, RpcStreamingChannel as b, DevframeRpcServerFunctions as c, EventEmitter$1 as d, EventUnsubscribe as f, RpcDefinitionsToFunctions as g, RpcDefinitionsFilter as h, DevframeDiagnosticsLogger as i, DevframeRpcSharedStates as l, RpcBroadcastOptions as m, DevframeCapabilities as n, DevframeNodeRpcSession as o, EventsMap as p, DevframeDiagnosticsHost as r, DevframeRpcClientFunctions as s, ConnectionMeta$1 as t, DevframeViewHost as u, RpcSharedStateGetOptions as v, RpcStreamingChannelOptions as x, RpcSharedStateHost as y };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { A as DevframeViewIframe, C as DevframeDockUserEntry, D as DevframeViewBuiltin, E as DevframeViewAction, F as RemoteConnectionInfo, I as RemoteDockOptions, L as DevframeTitleLocales, M as DevframeViewLauncherStatus, N as FrameSubTabsConfig, O as DevframeViewCustomRender, P as NavTarget, R as DevframeTitled, S as DevframeDockPanelState, T as DevframeDocksHost, _ as DevframeDockEntry, a as DevframeCommandEntry, b as DevframeDockEntryIcon, c as DevframeCommandShortcutOverrides, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntriesGrouped, h as DevframeDockBadgeVariant, i as DevframeCommandBase, j as DevframeViewLauncher, k as DevframeViewGroup, l as DevframeCommandsHost, m as DevframeDockActivation, n as DevframeClientCommand, o as DevframeCommandHandle, p as ClientScriptEntry, r as DevframeCommandAgentOptions, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, u as DevframeCommandsHostEvents, v as DevframeDockEntryBase, w as DevframeDocksActiveState, x as DevframeDockEntryRegistry, y as DevframeDockEntryCategory } from "./settings-DPLPzYfX.mjs";
2
- import { n as resolveTitle, t as matchLocale } from "./locale-C3-NpDlX.mjs";
3
- import { A as DevframeMessagesHost, C as DevframeMessageEntryFrom, D as DevframeMessageLevel, E as DevframeMessageHandle, M as DevframeMessagesListDelta, O as DevframeMessageShortcutInput, S as DevframeMessageEntry, T as DevframeMessageFilePosition, _ as DevframeTerminalsHost, b as DevframeMessageCommandAction, c as DevframeChildProcessResult, d as DevframePtyOutput, f as DevframePtyResult, g as DevframeTerminalStatus, h as DevframeTerminalSessionBase, j as DevframeMessagesLevelShortcuts, k as DevframeMessagesClient, l as DevframeChildProcessTerminalSession, m as DevframeTerminalSession, n as DevframeHubContext, o as DevframeChildProcessExecuteOptions, p as DevframePtyTerminalSession, s as DevframeChildProcessOutput, t as CreateHubContextOptions, u as DevframePtyExecuteOptions, v as DevframeMessageAction, w as DevframeMessageEntryInput, x as DevframeMessageElementPosition, y as DevframeMessageActivateAction } from "./context-BK50aJ-F.mjs";
4
- import { S as RpcStreamingHost, _ as RpcFunctionsHost, a as DevframeHost, b as RpcStreamingChannel, c as DevframeRpcServerFunctions, d as EventEmitter, f as EventUnsubscribe, g as RpcDefinitionsToFunctions, h as RpcDefinitionsFilter, i as DevframeDiagnosticsLogger, l as DevframeRpcSharedStates, m as RpcBroadcastOptions, n as DevframeCapabilities, o as DevframeNodeRpcSession, p as EventsMap, r as DevframeDiagnosticsHost, s as DevframeRpcClientFunctions, t as ConnectionMeta, u as DevframeViewHost, v as RpcSharedStateGetOptions, x as RpcStreamingChannelOptions, y as RpcSharedStateHost } from "./index-BvEO3eOd.mjs";
1
+ import { A as DevframeViewIframe, C as DevframeDockUserEntry, D as DevframeViewBuiltin, E as DevframeViewAction, F as RemoteConnectionInfo, I as RemoteDockOptions, L as DevframeTitleLocales, M as DevframeViewLauncherStatus, N as FrameSubTabsConfig, O as DevframeViewCustomRender, P as NavTarget, R as DevframeTitled, S as DevframeDockPanelState, T as DevframeDocksHost, _ as DevframeDockEntry, a as DevframeCommandEntry, b as DevframeDockEntryIcon, c as DevframeCommandShortcutOverrides, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntriesGrouped, h as DevframeDockBadgeVariant, i as DevframeCommandBase, j as DevframeViewLauncher, k as DevframeViewGroup, l as DevframeCommandsHost, m as DevframeDockActivation, n as DevframeClientCommand, o as DevframeCommandHandle, p as ClientScriptEntry, r as DevframeCommandAgentOptions, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, u as DevframeCommandsHostEvents, v as DevframeDockEntryBase, w as DevframeDocksActiveState, x as DevframeDockEntryRegistry, y as DevframeDockEntryCategory } from "./settings-UN5GnTei.mjs";
2
+ import { n as resolveTitle, t as matchLocale } from "./locale-CGR6YyCP.mjs";
3
+ import { A as DevframeMessagesHost, C as DevframeMessageEntryFrom, D as DevframeMessageLevel, E as DevframeMessageHandle, M as DevframeMessagesListDelta, O as DevframeMessageShortcutInput, S as DevframeMessageEntry, T as DevframeMessageFilePosition, _ as DevframeTerminalsHost, b as DevframeMessageCommandAction, c as DevframeChildProcessResult, d as DevframePtyOutput, f as DevframePtyResult, g as DevframeTerminalStatus, h as DevframeTerminalSessionBase, j as DevframeMessagesLevelShortcuts, k as DevframeMessagesClient, l as DevframeChildProcessTerminalSession, m as DevframeTerminalSession, n as DevframeHubContext, o as DevframeChildProcessExecuteOptions, p as DevframePtyTerminalSession, s as DevframeChildProcessOutput, t as CreateHubContextOptions, u as DevframePtyExecuteOptions, v as DevframeMessageAction, w as DevframeMessageEntryInput, x as DevframeMessageElementPosition, y as DevframeMessageActivateAction } from "./context-Iy5i89Aq.mjs";
4
+ import { S as RpcStreamingHost, _ as RpcFunctionsHost, a as DevframeHost, b as RpcStreamingChannel, c as DevframeRpcServerFunctions, d as EventEmitter, f as EventUnsubscribe, g as RpcDefinitionsToFunctions, h as RpcDefinitionsFilter, i as DevframeDiagnosticsLogger, l as DevframeRpcSharedStates, m as RpcBroadcastOptions, n as DevframeCapabilities, o as DevframeNodeRpcSession, p as EventsMap, r as DevframeDiagnosticsHost, s as DevframeRpcClientFunctions, t as ConnectionMeta, u as DevframeViewHost, v as RpcSharedStateGetOptions, x as RpcStreamingChannelOptions, y as RpcSharedStateHost } from "./index-tijpvneP.mjs";
5
5
  import { WhenContext, WhenExpression } from "devframe/utils/when";
6
6
  //#region src/define.d.ts
7
7
  export declare const defineHubRpcFunction: <NAME extends string, TYPE extends import("devframe/rpc").RpcFunctionType, ARGS extends any[], RETURN = void, const AS extends import("devframe/rpc").RpcArgsSchema | undefined = undefined, const RS extends import("devframe/rpc").RpcReturnSchema | undefined = undefined>(definition: import("devframe/rpc").RpcFunctionDefinition<NAME, TYPE, ARGS, RETURN, AS, RS, DevframeHubContext>) => import("devframe/rpc").RpcFunctionDefinition<NAME, TYPE, ARGS, RETURN, AS, RS, DevframeHubContext>;
@@ -1,4 +1,4 @@
1
- import { R as DevframeTitled } from "./settings-DPLPzYfX.mjs";
1
+ import { R as DevframeTitled } from "./settings-UN5GnTei.mjs";
2
2
  //#region src/locale.d.ts
3
3
  /**
4
4
  * Pick the tag in `available` closest to `tag`: exact match first, then
@@ -1,4 +1,4 @@
1
- import { n as DevframeHubContext, t as CreateHubContextOptions } from "../context-BK50aJ-F.mjs";
1
+ import { n as DevframeHubContext, t as CreateHubContextOptions } from "../context-Iy5i89Aq.mjs";
2
2
  import { DevframeHubUi, DevframesInput, DockRendererRegistration } from "./initiate.mjs";
3
3
  import { DevframeServiceInput, DevframeStorageScope } from "devframe/types";
4
4
  //#region src/node/build.d.ts
@@ -1,6 +1,6 @@
1
1
  import { a as normalizeHubBase, i as DOCK_RENDERERS_STATE_KEY } from "../constants-BSPQmlA1.mjs";
2
- import { t as createHubContext, y as diagnostics } from "../context-DRdTViYd.mjs";
3
- import { i as resolveRendererRegistrations, n as renderClientImportsModule, r as resolveDevframesInput, t as mountDevframes } from "../assemble-CK2TX0FM.mjs";
2
+ import { t as createHubContext, y as diagnostics } from "../context-0RunDMBy.mjs";
3
+ import { i as resolveRendererRegistrations, n as renderClientImportsModule, r as resolveDevframesInput, t as mountDevframes } from "../assemble-BO0n24su.mjs";
4
4
  import { joinURL } from "devframe/utils/url";
5
5
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME } from "devframe/constants";
6
6
  import { existsSync } from "node:fs";
@@ -1,5 +1,5 @@
1
- import { C as DevframeDockUserEntry, T as DevframeDocksHost$1, _ as DevframeDockEntry, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, l as DevframeCommandsHost$1, o as DevframeCommandHandle, p as ClientScriptEntry, t as DevframeDocksUserSettings } from "../settings-DPLPzYfX.mjs";
2
- import { A as DevframeMessagesHost$1, E as DevframeMessageHandle, M as DevframeMessagesListDelta, O as DevframeMessageShortcutInput, S as DevframeMessageEntry, _ as DevframeTerminalsHost$1, a as InstallDevframeOptions, h as DevframeTerminalSessionBase, i as createHubContext, l as DevframeChildProcessTerminalSession, m as DevframeTerminalSession, n as DevframeHubContext, o as DevframeChildProcessExecuteOptions, p as DevframePtyTerminalSession, r as HubMountedFrame, t as CreateHubContextOptions, u as DevframePtyExecuteOptions, w as DevframeMessageEntryInput } from "../context-BK50aJ-F.mjs";
1
+ import { C as DevframeDockUserEntry, T as DevframeDocksHost$1, _ as DevframeDockEntry, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, l as DevframeCommandsHost$1, o as DevframeCommandHandle, p as ClientScriptEntry, t as DevframeDocksUserSettings } from "../settings-UN5GnTei.mjs";
2
+ import { A as DevframeMessagesHost$1, E as DevframeMessageHandle, M as DevframeMessagesListDelta, O as DevframeMessageShortcutInput, S as DevframeMessageEntry, _ as DevframeTerminalsHost$1, a as InstallDevframeOptions, h as DevframeTerminalSessionBase, i as createHubContext, l as DevframeChildProcessTerminalSession, m as DevframeTerminalSession, n as DevframeHubContext, o as DevframeChildProcessExecuteOptions, p as DevframePtyTerminalSession, r as HubMountedFrame, t as CreateHubContextOptions, u as DevframePtyExecuteOptions, w as DevframeMessageEntryInput } from "../context-Iy5i89Aq.mjs";
3
3
  import { RpcFunctionDefinitionAny } from "devframe/rpc";
4
4
  import { SharedState } from "devframe/utils/shared-state";
5
5
  //#region src/node/host-commands.d.ts
@@ -1,4 +1,4 @@
1
- import { _ as DevframeCommandsHost, a as hubMessagesAdd, c as hubMessagesUpdate, d as hubTerminalsRestart, f as hubTerminalsTerminate, g as DevframeDocksHost, h as DevframeMessagesHost, i as hubDocksActivate, l as hubTerminalsRemove, m as DevframeTerminalsHost, n as builtinHubRpcDeclarations, o as hubMessagesClear, p as hubTerminalsWrite, r as hubCommandsExecute, s as hubMessagesRemove, t as createHubContext, u as hubTerminalsResize } from "../context-DRdTViYd.mjs";
1
+ import { _ as DevframeCommandsHost, a as hubMessagesAdd, c as hubMessagesUpdate, d as hubTerminalsRestart, f as hubTerminalsTerminate, g as DevframeDocksHost, h as DevframeMessagesHost, i as hubDocksActivate, l as hubTerminalsRemove, m as DevframeTerminalsHost, n as builtinHubRpcDeclarations, o as hubMessagesClear, p as hubTerminalsWrite, r as hubCommandsExecute, s as hubMessagesRemove, t as createHubContext, u as hubTerminalsResize } from "../context-0RunDMBy.mjs";
2
2
  import { Buffer } from "node:buffer";
3
3
  //#region src/node/utils.ts
4
4
  function toDataURL(code) {
@@ -1,5 +1,5 @@
1
- import { a as InstallDevframeOptions, n as DevframeHubContext, t as CreateHubContextOptions } from "../context-BK50aJ-F.mjs";
2
- import { r as DEVFRAMES_HUB_BASE } from "../constants-C7cDDASI.mjs";
1
+ import { a as InstallDevframeOptions, n as DevframeHubContext, t as CreateHubContextOptions } from "../context-Iy5i89Aq.mjs";
2
+ import { r as DEVFRAMES_HUB_BASE } from "../constants-H0A2VIz0.mjs";
3
3
  import { DevframeInstanceRecord } from "devframe/internal";
4
4
  import { Buffer } from "node:buffer";
5
5
  import { AuthBannerFunction } from "devframe/recipes/interactive-auth";
@@ -1,6 +1,6 @@
1
1
  import { a as normalizeHubBase, i as DOCK_RENDERERS_STATE_KEY, r as DEVFRAMES_HUB_BASE } from "../constants-BSPQmlA1.mjs";
2
- import { t as createHubContext, y as diagnostics } from "../context-DRdTViYd.mjs";
3
- import { i as resolveRendererRegistrations, n as renderClientImportsModule, r as resolveDevframesInput, t as mountDevframes } from "../assemble-CK2TX0FM.mjs";
2
+ import { t as createHubContext, y as diagnostics } from "../context-0RunDMBy.mjs";
3
+ import { i as resolveRendererRegistrations, n as renderClientImportsModule, r as resolveDevframesInput, t as mountDevframes } from "../assemble-BO0n24su.mjs";
4
4
  import { joinURL, withoutLeadingSlash } from "devframe/utils/url";
5
5
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_MCP_ROUTE } from "devframe/constants";
6
6
  import { readFile } from "node:fs/promises";
@@ -107,7 +107,7 @@ function initHub(options) {
107
107
  */
108
108
  absoluteWsPath: true,
109
109
  resolveSidecarPort: async (sidecarHost) => {
110
- const { getPort } = await import("../dist-Q6-t0oIv.mjs");
110
+ const { getPort } = await import("../dist-BP3CGpgZ.mjs");
111
111
  return getPort({
112
112
  port: 9777,
113
113
  portRange: [9777, 9877],
@@ -150,6 +150,9 @@ function initHub(options) {
150
150
  serverName: options.name ?? "devframes-hub",
151
151
  serverVersion: options.version ?? "0.0.0",
152
152
  exposeSharedState: mcpConfig.exposeSharedState ?? true,
153
+ instructions: mcpConfig.instructions,
154
+ resourceTemplates: mcpConfig.resourceTemplates,
155
+ onResourcesChanged: mcpConfig.onResourcesChanged,
153
156
  authorization: mcpConfig.authorization,
154
157
  allowedOrigins: mcpConfig.allowedOrigins
155
158
  });
@@ -159,6 +159,12 @@ interface DevframeDockEntryBase {
159
159
  title: string;
160
160
  /** Translations of `title` by BCP 47 tag; see `resolveTitle()` from `@devframes/hub`. */
161
161
  titleLocales?: DevframeTitleLocales;
162
+ /**
163
+ * A longer, one-line hint of what the entry does. A viewer shows it under
164
+ * the {@link title} in the dock button tooltip, so a button whose icon is
165
+ * ambiguous still explains itself on hover.
166
+ */
167
+ description?: string;
162
168
  icon: DevframeDockEntryIcon;
163
169
  /**
164
170
  * The default order of the entry in the dock.
@@ -459,6 +465,27 @@ interface DevframeViewLauncher extends DevframeDockEntryBase {
459
465
  interface DevframeViewAction extends DevframeDockEntryBase {
460
466
  type: 'action';
461
467
  action: ClientScriptEntry;
468
+ /**
469
+ * Make the action an on/off tool, such as an in-page element picker.
470
+ *
471
+ * - The {@link action} script runs once (cached like other client scripts)
472
+ * and drives the tool from the entry's `entry:activated` /
473
+ * `entry:deactivated` events.
474
+ * - Activating it does not select it: the panel's selected dock stays as is.
475
+ * An open panel is hidden while the tool is on and comes back when it goes
476
+ * off.
477
+ * - While on, the dock button renders as active (`DockEntryState.isActive`).
478
+ * - `docks.switchEntry(id)` (a click) flips it on and off.
479
+ * - It also goes off on `Escape` in a viewer that supports it, on
480
+ * `docks.setActionActive(id, false)`, or when another dock is selected or
481
+ * the selection is cleared (then the panel is not restored, the new
482
+ * selection wins).
483
+ *
484
+ * When unset, the action is one-shot: each click runs the script again.
485
+ *
486
+ * @default false
487
+ */
488
+ toggle?: boolean;
462
489
  }
463
490
  interface DevframeViewCustomRender extends DevframeDockEntryBase {
464
491
  type: 'custom-render';
@@ -1,4 +1,4 @@
1
- import { A as DevframeViewIframe, C as DevframeDockUserEntry, D as DevframeViewBuiltin, E as DevframeViewAction, F as RemoteConnectionInfo, I as RemoteDockOptions, L as DevframeTitleLocales, M as DevframeViewLauncherStatus, N as FrameSubTabsConfig, O as DevframeViewCustomRender, P as NavTarget, R as DevframeTitled, S as DevframeDockPanelState, T as DevframeDocksHost, _ as DevframeDockEntry, a as DevframeCommandEntry, b as DevframeDockEntryIcon, c as DevframeCommandShortcutOverrides, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntriesGrouped, h as DevframeDockBadgeVariant, i as DevframeCommandBase, j as DevframeViewLauncher, k as DevframeViewGroup, l as DevframeCommandsHost, m as DevframeDockActivation, n as DevframeClientCommand, o as DevframeCommandHandle, p as ClientScriptEntry, r as DevframeCommandAgentOptions, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, u as DevframeCommandsHostEvents, v as DevframeDockEntryBase, w as DevframeDocksActiveState, x as DevframeDockEntryRegistry, y as DevframeDockEntryCategory } from "../settings-DPLPzYfX.mjs";
2
- import { A as DevframeMessagesHost, C as DevframeMessageEntryFrom, D as DevframeMessageLevel, E as DevframeMessageHandle, M as DevframeMessagesListDelta, O as DevframeMessageShortcutInput, S as DevframeMessageEntry, T as DevframeMessageFilePosition, _ as DevframeTerminalsHost, b as DevframeMessageCommandAction, c as DevframeChildProcessResult, d as DevframePtyOutput, f as DevframePtyResult, g as DevframeTerminalStatus, h as DevframeTerminalSessionBase, j as DevframeMessagesLevelShortcuts, k as DevframeMessagesClient, l as DevframeChildProcessTerminalSession, m as DevframeTerminalSession, n as DevframeHubContext, o as DevframeChildProcessExecuteOptions, p as DevframePtyTerminalSession, s as DevframeChildProcessOutput, t as CreateHubContextOptions, u as DevframePtyExecuteOptions, v as DevframeMessageAction, w as DevframeMessageEntryInput, x as DevframeMessageElementPosition, y as DevframeMessageActivateAction } from "../context-BK50aJ-F.mjs";
3
- import { S as RpcStreamingHost, _ as RpcFunctionsHost, a as DevframeHost, b as RpcStreamingChannel, c as DevframeRpcServerFunctions, d as EventEmitter, f as EventUnsubscribe, g as RpcDefinitionsToFunctions, h as RpcDefinitionsFilter, i as DevframeDiagnosticsLogger, l as DevframeRpcSharedStates, m as RpcBroadcastOptions, n as DevframeCapabilities, o as DevframeNodeRpcSession, p as EventsMap, r as DevframeDiagnosticsHost, s as DevframeRpcClientFunctions, t as ConnectionMeta, u as DevframeViewHost, v as RpcSharedStateGetOptions, x as RpcStreamingChannelOptions, y as RpcSharedStateHost } from "../index-BvEO3eOd.mjs";
1
+ import { A as DevframeViewIframe, C as DevframeDockUserEntry, D as DevframeViewBuiltin, E as DevframeViewAction, F as RemoteConnectionInfo, I as RemoteDockOptions, L as DevframeTitleLocales, M as DevframeViewLauncherStatus, N as FrameSubTabsConfig, O as DevframeViewCustomRender, P as NavTarget, R as DevframeTitled, S as DevframeDockPanelState, T as DevframeDocksHost, _ as DevframeDockEntry, a as DevframeCommandEntry, b as DevframeDockEntryIcon, c as DevframeCommandShortcutOverrides, d as DevframeServerCommandEntry, f as DevframeServerCommandInput, g as DevframeDockEntriesGrouped, h as DevframeDockBadgeVariant, i as DevframeCommandBase, j as DevframeViewLauncher, k as DevframeViewGroup, l as DevframeCommandsHost, m as DevframeDockActivation, n as DevframeClientCommand, o as DevframeCommandHandle, p as ClientScriptEntry, r as DevframeCommandAgentOptions, s as DevframeCommandKeybinding, t as DevframeDocksUserSettings, u as DevframeCommandsHostEvents, v as DevframeDockEntryBase, w as DevframeDocksActiveState, x as DevframeDockEntryRegistry, y as DevframeDockEntryCategory } from "../settings-UN5GnTei.mjs";
2
+ import { A as DevframeMessagesHost, C as DevframeMessageEntryFrom, D as DevframeMessageLevel, E as DevframeMessageHandle, M as DevframeMessagesListDelta, O as DevframeMessageShortcutInput, S as DevframeMessageEntry, T as DevframeMessageFilePosition, _ as DevframeTerminalsHost, b as DevframeMessageCommandAction, c as DevframeChildProcessResult, d as DevframePtyOutput, f as DevframePtyResult, g as DevframeTerminalStatus, h as DevframeTerminalSessionBase, j as DevframeMessagesLevelShortcuts, k as DevframeMessagesClient, l as DevframeChildProcessTerminalSession, m as DevframeTerminalSession, n as DevframeHubContext, o as DevframeChildProcessExecuteOptions, p as DevframePtyTerminalSession, s as DevframeChildProcessOutput, t as CreateHubContextOptions, u as DevframePtyExecuteOptions, v as DevframeMessageAction, w as DevframeMessageEntryInput, x as DevframeMessageElementPosition, y as DevframeMessageActivateAction } from "../context-Iy5i89Aq.mjs";
3
+ import { S as RpcStreamingHost, _ as RpcFunctionsHost, a as DevframeHost, b as RpcStreamingChannel, c as DevframeRpcServerFunctions, d as EventEmitter, f as EventUnsubscribe, g as RpcDefinitionsToFunctions, h as RpcDefinitionsFilter, i as DevframeDiagnosticsLogger, l as DevframeRpcSharedStates, m as RpcBroadcastOptions, n as DevframeCapabilities, o as DevframeNodeRpcSession, p as EventsMap, r as DevframeDiagnosticsHost, s as DevframeRpcClientFunctions, t as ConnectionMeta, u as DevframeViewHost, v as RpcSharedStateGetOptions, x as RpcStreamingChannelOptions, y as RpcSharedStateHost } from "../index-tijpvneP.mjs";
4
4
  export { ClientScriptEntry, type ConnectionMeta, type CreateHubContextOptions, type DevframeCapabilities, DevframeChildProcessExecuteOptions, DevframeChildProcessOutput, DevframeChildProcessResult, DevframeChildProcessTerminalSession, DevframeClientCommand, DevframeCommandAgentOptions, DevframeCommandBase, DevframeCommandEntry, DevframeCommandHandle, DevframeCommandKeybinding, DevframeCommandShortcutOverrides, DevframeCommandsHost, DevframeCommandsHostEvents, type DevframeDiagnosticsHost, type DevframeDiagnosticsLogger, DevframeDockActivation, DevframeDockBadgeVariant, DevframeDockEntriesGrouped, DevframeDockEntry, DevframeDockEntryBase, DevframeDockEntryCategory, DevframeDockEntryIcon, DevframeDockEntryRegistry, DevframeDockPanelState, DevframeDockUserEntry, DevframeDocksActiveState, DevframeDocksHost, DevframeDocksUserSettings, type DevframeHost, type DevframeHubContext, DevframeMessageAction, DevframeMessageActivateAction, DevframeMessageCommandAction, DevframeMessageElementPosition, DevframeMessageEntry, DevframeMessageEntryFrom, DevframeMessageEntryInput, DevframeMessageFilePosition, DevframeMessageHandle, DevframeMessageLevel, DevframeMessageShortcutInput, DevframeMessagesClient, DevframeMessagesHost, DevframeMessagesLevelShortcuts, DevframeMessagesListDelta, type DevframeNodeRpcSession, DevframePtyExecuteOptions, DevframePtyOutput, DevframePtyResult, DevframePtyTerminalSession, type DevframeRpcClientFunctions, type DevframeRpcServerFunctions, type DevframeRpcSharedStates, DevframeServerCommandEntry, DevframeServerCommandInput, DevframeTerminalSession, DevframeTerminalSessionBase, DevframeTerminalStatus, DevframeTerminalsHost, DevframeTitleLocales, DevframeTitled, DevframeViewAction, DevframeViewBuiltin, DevframeViewCustomRender, DevframeViewGroup, type DevframeViewHost, DevframeViewIframe, DevframeViewLauncher, DevframeViewLauncherStatus, type EventEmitter, type EventUnsubscribe, type EventsMap, FrameSubTabsConfig, NavTarget, RemoteConnectionInfo, RemoteDockOptions, type RpcBroadcastOptions, type RpcDefinitionsFilter, type RpcDefinitionsToFunctions, type RpcFunctionsHost, type RpcSharedStateGetOptions, type RpcSharedStateHost, type RpcStreamingChannel, type RpcStreamingChannelOptions, type RpcStreamingHost };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devframes/hub",
3
3
  "type": "module",
4
- "version": "1.2.5",
4
+ "version": "1.3.0",
5
5
  "description": "Hub layer that orchestrates devframe docks, terminals, messages, and commands on any host.",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -35,8 +35,8 @@
35
35
  "dist"
36
36
  ],
37
37
  "peerDependencies": {
38
- "@devframes/agentic": "1.2.5",
39
- "devframe": "1.2.5"
38
+ "@devframes/agentic": "1.3.0",
39
+ "devframe": "1.3.0"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@devframes/agentic": {
@@ -45,18 +45,18 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "destr": "^2.0.5",
48
- "h3": "^2.0.1",
48
+ "h3": "^2.0.7",
49
49
  "pathe": "^2.0.3",
50
50
  "tinyexec": "^1.3.1",
51
51
  "zigpty": "^0.2.1"
52
52
  },
53
53
  "devDependencies": {
54
- "@devframes/agentic": "1.2.5",
54
+ "@devframes/agentic": "1.3.0",
55
55
  "@standard-schema/spec": "^1.1.0",
56
- "@types/node": "^26.6.4",
57
- "devframe": "1.2.5",
56
+ "@types/node": "^26.6.5",
57
+ "devframe": "1.3.0",
58
58
  "get-port-please": "^3.2.0",
59
- "tsdown": "^0.23.0",
59
+ "tsdown": "0.23.0",
60
60
  "valibot": "^1.5.0"
61
61
  },
62
62
  "scripts": {
@@ -1,7 +1,7 @@
1
1
  import "node:fs/promises";
2
+ import "node:path";
2
3
  import { createServer } from "node:net";
3
4
  import { networkInterfaces } from "node:os";
4
- import "node:path";
5
5
  //#region ../../node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs
6
6
  const unsafePorts = /* @__PURE__ */ new Set([
7
7
  1,