@cecwxf/dsh-room 0.2.0 → 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.
- package/README.md +17 -1
- package/dist/client.js +1030 -46
- package/dist/index.js +1572 -82
- package/dist/types/adapter.d.ts +2 -0
- package/dist/types/adapter.d.ts.map +1 -1
- package/dist/types/command-handler.d.ts.map +1 -1
- package/dist/types/commands.d.ts +16 -0
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/http.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/isolation.d.ts +82 -0
- package/dist/types/isolation.d.ts.map +1 -0
- package/dist/types/local-agents.d.ts +59 -0
- package/dist/types/local-agents.d.ts.map +1 -0
- package/dist/types/orchestrator.d.ts +96 -0
- package/dist/types/orchestrator.d.ts.map +1 -0
- package/dist/types/plugin.d.ts +335 -10
- package/dist/types/plugin.d.ts.map +1 -1
- package/dist/types/state.d.ts +7 -0
- package/dist/types/state.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -37,7 +37,7 @@ var import_react = require("react");
|
|
|
37
37
|
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
38
38
|
|
|
39
39
|
// src/client/rooms.css
|
|
40
|
-
var rooms_default = '/* Collab Rooms UI \u2014 original surface inside the dsh shell. Uses only dsh --dsw-* tokens.\n Independent Rooms surface. Prefix: rm- (rooms). */\n\n.rm-root {\n --rm-accent: var(--dsw-alias-state-business-primary);\n --rm-hover: var(--dsw-alias-interactive-bg-hover);\n --rm-border: var(--dsw-alias-border-l2);\n --rm-bg: var(--dsw-alias-bg-base);\n --rm-panel: var(--dsw-alias-bg-module-platform);\n --rm-label: var(--dsw-alias-label-primary);\n --rm-muted: var(--dsw-alias-label-secondary);\n --rm-quiet: var(--dsw-alias-label-tertiary);\n font: 13px/1.5 var(--dsw-font-family);\n color: var(--rm-label);\n box-sizing: border-box;\n}\n.rm-root *, .rm-root *::before, .rm-root *::after { box-sizing: border-box; }\n.rm-root button, .rm-root input, .rm-root textarea { font: inherit; }\n\n/* \u2500\u2500 sidebar (joined rooms + public search) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-side {\n display: flex; flex-direction: column; height: 100%; min-height: 0;\n padding: 0 8px 8px 0; gap: 8px;\n}\n.rm-side-toolbar {\n display: flex; align-items: center; gap: 6px; flex: none; padding: 4px 0 2px;\n}\n.rm-side-title {\n flex: 1; font-size: 12px; font-weight: 600; letter-spacing: .04em;\n text-transform: uppercase; color: var(--rm-quiet);\n}\n.rm-icon-btn {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; padding: 0;\n}\n.rm-icon-btn:hover { background: var(--rm-hover); color: var(--rm-label); }\n.rm-search {\n display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px;\n border: .5px solid var(--rm-border); border-radius: 8px; background: var(--rm-panel);\n}\n.rm-search input {\n flex: 1; min-width: 0; border: 0; background: transparent; outline: none; color: var(--rm-label); font-size: 13px;\n}\n.rm-search input::placeholder { color: var(--rm-quiet); }\n.rm-side-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 12px; }\n.rm-group-label { font-size: 11px; font-weight: 600; color: var(--rm-quiet); padding: 0 4px 4px; text-transform: uppercase; letter-spacing: .03em; }\n.rm-room-list { display: flex; flex-direction: column; gap: 2px; }\n.rm-room-item {\n display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;\n border: 0; border-radius: 10px; background: transparent; color: inherit; cursor: pointer; text-align: left;\n}\n.rm-room-item:hover { background: var(--rm-hover); }\n.rm-room-item[aria-current="true"] { background: var(--rm-hover); }\n.rm-room-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n.rm-room-item-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-meta { font-size: 11.5px; color: var(--rm-quiet); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-trail { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }\n.rm-badge {\n display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px;\n border-radius: 999px; font-size: 10.5px; font-weight: 500; background: var(--rm-panel); color: var(--rm-muted);\n border: .5px solid var(--rm-border);\n}\n.rm-badge-public { color: var(--rm-accent); border-color: color-mix(in srgb, var(--rm-accent) 35%, transparent); background: color-mix(in srgb, var(--rm-accent) 8%, transparent); }\n.rm-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--rm-quiet); }\n.rm-dot-online { background: var(--dsw-alias-state-success-primary, #2bb673); }\n.rm-dot-connecting { background: var(--dsw-alias-state-warn-primary, #e9a23b); }\n.rm-dot-offline { background: var(--dsw-alias-state-error-primary, #e5484d); }\n.rm-empty-hint { padding: 8px 10px; font-size: 12px; color: var(--rm-quiet); line-height: 1.45; }\n.rm-dir-item {\n display: flex; align-items: flex-start; gap: 10px; padding: 10px; border-radius: 10px;\n border: .5px solid var(--rm-border); background: var(--rm-bg); margin-bottom: 6px;\n}\n.rm-dir-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\n.rm-dir-tags { display: flex; flex-wrap: wrap; gap: 4px; }\n.rm-tag { font-size: 11px; color: var(--rm-muted); background: var(--rm-hover); border-radius: 4px; padding: 0 5px; }\n.rm-menu {\n position: fixed; z-index: 1000; min-width: 180px; padding: 4px;\n border-radius: 10px; background: var(--dsw-alias-bg-layer-1, var(--rm-bg));\n border: .5px solid var(--rm-border);\n box-shadow: 0 8px 24px color-mix(in srgb, var(--rm-label) 12%, transparent);\n display: flex; flex-direction: column;\n}\n.rm-menu button {\n display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-menu button:hover { background: var(--rm-hover); }\n\n/* \u2500\u2500 main: room workspace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-main { display: flex; flex: 1; min-height: 0; height: 100%; width: 100%; background: var(--rm-bg); }\n.rm-workspace { display: flex; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat-header {\n flex: none; display: flex; align-items: center; gap: 10px; height: 48px;\n padding: 0 16px; border-bottom: .5px solid var(--rm-border);\n}\n.rm-chat-header-title { font-size: 14px; font-weight: 600; }\n.rm-chat-header-sub { font-size: 12px; color: var(--rm-quiet); }\n.rm-messages {\n flex: 1; min-height: 0; overflow: auto; padding: 16px 18px 8px;\n display: flex; flex-direction: column; gap: 2px;\n}\n.rm-day {\n align-self: center; margin: 10px 0 12px; padding: 2px 10px; border-radius: 999px;\n font-size: 11px; color: var(--rm-quiet); background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n}\n.rm-msg {\n display: grid; grid-template-columns: 32px 1fr; gap: 0 10px; padding: 4px 6px; border-radius: 8px;\n max-width: 720px;\n}\n.rm-msg:hover { background: color-mix(in srgb, var(--rm-hover) 60%, transparent); }\n.rm-msg-self { margin-left: auto; grid-template-columns: 1fr; max-width: 640px; }\n.rm-msg-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 1px; }\n.rm-msg-author { font-size: 12px; font-weight: 600; color: var(--rm-muted); }\n.rm-msg-time { font-size: 11px; color: var(--rm-quiet); }\n.rm-msg-body { font-size: 13.5px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }\n.rm-msg-self .rm-msg-body {\n background: var(--dsw-alias-label-primary); color: var(--dsw-alias-label-primary-foreground);\n padding: 8px 12px; border-radius: 12px 12px 4px 12px; width: fit-content; margin-left: auto;\n}\n.rm-msg-event {\n grid-template-columns: 1fr; max-width: 560px; margin: 6px 0;\n padding: 8px 12px; border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-panel);\n}\n.rm-mention { color: var(--rm-accent); font-weight: 500; }\n.rm-msg-self .rm-mention { color: inherit; text-decoration: underline; text-underline-offset: 2px; }\n.rm-task-card { display: flex; flex-direction: column; gap: 4px; }\n.rm-task-head { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--rm-muted); }\n.rm-task-title { font-weight: 600; font-size: 13.5px; }\n.rm-composer {\n flex: none; display: flex; align-items: flex-end; gap: 8px; padding: 10px 16px 14px;\n border-top: .5px solid var(--rm-border);\n}\n.rm-composer-box {\n flex: 1; display: flex; align-items: flex-end; gap: 6px; min-height: 44px;\n padding: 8px 10px; border: .5px solid var(--rm-border); border-radius: 12px; background: var(--rm-panel);\n}\n.rm-composer-box:focus-within { border-color: color-mix(in srgb, var(--rm-accent) 50%, var(--rm-border)); }\n.rm-composer-box textarea {\n flex: 1; min-height: 28px; max-height: 120px; border: 0; background: transparent; outline: none;\n resize: none; color: var(--rm-label); line-height: 1.45;\n}\n.rm-composer-box textarea::placeholder { color: var(--rm-quiet); }\n.rm-composer-mode {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; flex: none;\n}\n.rm-composer-mode:hover, .rm-composer-mode[aria-pressed="true"] {\n color: var(--rm-accent); background: color-mix(in srgb, var(--rm-accent) 12%, transparent);\n}\n.rm-chat-hint { margin: 48px auto; text-align: center; color: var(--rm-quiet); font-size: 13px; max-width: 360px; line-height: 1.5; }\n\n/* \u2500\u2500 detail column (members / invite / about) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-detail {\n flex: 0 0 280px; width: 280px; display: flex; flex-direction: column; min-height: 0;\n border-left: .5px solid var(--rm-border); background: var(--rm-bg); overflow: auto;\n}\n.rm-detail-section { padding: 14px 14px 8px; border-bottom: .5px solid var(--rm-border); }\n.rm-detail-section:last-child { border-bottom: 0; }\n.rm-detail-h {\n display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600;\n text-transform: uppercase; letter-spacing: .04em; color: var(--rm-quiet); margin-bottom: 8px;\n}\n.rm-member {\n display: flex; align-items: center; gap: 8px; padding: 5px 4px; border-radius: 8px; min-height: 34px;\n}\n.rm-member:hover { background: var(--rm-hover); }\n.rm-member-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }\n.rm-member-actions { display: none; gap: 2px; }\n.rm-member:hover .rm-member-actions, .rm-member:focus-within .rm-member-actions { display: inline-flex; }\n.rm-mini {\n width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-muted); cursor: pointer; font-size: 12px;\n}\n.rm-mini:hover { background: var(--dsw-alias-interactive-bg-active); color: var(--rm-label); }\n.rm-task-row { display: flex; align-items: center; gap: 6px; padding: 4px; font-size: 12.5px; }\n.rm-task-row-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-about { display: grid; grid-template-columns: 88px 1fr; gap: 6px 8px; font-size: 12.5px; margin: 0; }\n.rm-about dt { color: var(--rm-quiet); margin: 0; }\n.rm-about dd { margin: 0; min-width: 0; overflow-wrap: anywhere; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }\n.rm-mono { font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace); font-size: 11.5px; }\n.rm-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }\n.rm-danger { color: var(--dsw-alias-state-error-primary, #e5484d) !important; }\n.rm-note { font-size: 12px; color: var(--rm-quiet); line-height: 1.45; margin: 0 0 8px; }\n\n/* \u2500\u2500 empty / welcome \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-welcome-wrap {\n flex: 1; display: flex; align-items: center; justify-content: center; padding: 32px; background: var(--rm-bg);\n}\n.rm-welcome {\n width: min(420px, 100%); display: flex; flex-direction: column; gap: 10px;\n padding: 20px; border-radius: 14px; border: .5px solid var(--rm-border); background: var(--rm-panel);\n}\n.rm-welcome h1 { margin: 0; font-size: 16px; font-weight: 600; }\n.rm-welcome p { margin: 0; font-size: 13px; color: var(--rm-muted); line-height: 1.5; }\n.rm-welcome-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }\n.rm-welcome-action {\n display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 10px 12px;\n border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-bg);\n color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-welcome-action:hover { background: var(--rm-hover); }\n.rm-welcome-action b { display: block; font-size: 13px; }\n.rm-welcome-action span { display: block; font-size: 12px; color: var(--rm-quiet); margin-top: 2px; }\n\n/* \u2500\u2500 avatars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-avatar {\n display: inline-flex; align-items: center; justify-content: center; flex: none;\n font-weight: 600; letter-spacing: .02em; user-select: none;\n}\n.rm-avatar-wrap { position: relative; display: inline-flex; flex: none; }\n\n/* \u2500\u2500 dialogs (inside dsh Modal) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-form { display: flex; flex-direction: column; gap: 14px; }\n.rm-field { display: flex; flex-direction: column; gap: 6px; }\n.rm-field-label { font-size: 13px; font-weight: 500; }\n.rm-field-hint { font-size: 12px; color: var(--rm-quiet); }\n.rm-name-row { display: flex; align-items: center; gap: 10px; }\n.rm-name-row > :last-child { flex: 1; }\n.rm-switch-row {\n display: flex; align-items: center; justify-content: space-between; gap: 14px;\n padding: 10px 12px; border-radius: 10px; background: var(--rm-panel);\n}\n.rm-error { color: var(--dsw-alias-state-error-primary, #e5484d); font-size: 12.5px; }\n.rm-invite {\n display: block; padding: 10px 12px; border-radius: 8px; background: var(--rm-panel);\n font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace);\n font-size: 12px; word-break: break-all; user-select: all;\n}\n\n/* Dual transport + approvals + agent config */\n.rm-mode-row { display: flex; gap: 8px; }\n.rm-mode-btn {\n flex: 1; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer; font: inherit;\n}\n.rm-mode-btn.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent); }\n.rm-lan-browse { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; align-items: center; }\n.rm-lan-peer {\n font-size: 12px; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer;\n}\n.rm-approvals { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); background: color-mix(in srgb, #f5a524 12%, transparent); }\n.rm-approval { display: flex; gap: 12px; align-items: center; justify-content: space-between; }\n.rm-approval-body { font-size: 13px; }\n.rm-approval-actions { display: flex; gap: 6px; flex-shrink: 0; }\n.rm-input { width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; font: inherit; }\n\n.rm-ws-bar { display: flex; flex-direction: column; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); }\n.rm-ws-chip { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; cursor: pointer; font: inherit; font-size: 12.5px; }\n.rm-ws-path { font-size: 11px; color: var(--rm-quiet, #8b93a7); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item.is-active { background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); }\n\n/* Native-aligned room composer (mirrors dsh conversation control row) */\n.rm-composer-card {\n box-sizing: border-box;\n width: 100%;\n max-width: 920px;\n margin: 0 auto;\n border-radius: 16px;\n background: var(--rm-elev, var(--rm-panel, #12151c));\n border: 1px solid var(--rm-border, #2a2f3a);\n box-shadow: 0 1px 2px rgba(0,0,0,.06);\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 0 6px;\n}\n.rm-composer-grow { position: relative; padding: 0 4px; }\n.rm-composer-grow textarea {\n box-sizing: border-box; width: 100%; min-height: 36px; max-height: 160px;\n resize: none; border: none; outline: none; background: transparent;\n color: inherit; font: inherit; font-size: 14px; line-height: 22px;\n padding: 4px 12px 0 14px;\n}\n.rm-composer-grow textarea:disabled { opacity: .55; cursor: not-allowed; }\n.rm-composer-row {\n display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;\n gap: 10px; min-width: 0; padding: 2px 8px 4px;\n}\n.rm-composer-tools, .rm-composer-modes, .rm-composer-trailing {\n display: flex; align-items: center; min-width: 0; gap: 8px;\n}\n.rm-composer-trailing { flex: none; margin-left: auto; }\n.rm-composer-add {\n width: 28px; height: 28px; border: none; border-radius: 999px;\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n color: inherit; cursor: pointer; display: grid; place-items: center;\n}\n.rm-composer-add:hover, .rm-composer-add[aria-pressed="true"] {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 22%, transparent);\n}\n.rm-composer-select {\n max-width: 220px; height: 28px; border: none; border-radius: 8px;\n background: transparent; color: var(--rm-quiet, #8b93a7);\n font: inherit; font-size: 13px; font-weight: 500; line-height: 20px;\n padding: 0 8px; cursor: pointer; white-space: nowrap;\n}\n.rm-composer-select:hover:not(:disabled) {\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n}\n.rm-composer-select:disabled { opacity: .5; cursor: default; }\n.rm-composer-model-text { display: inline; }\n.rm-composer-model-icon { display: none; font-size: 10px; }\n.rm-composer-effort {\n margin-left: 6px; font-size: 11px; opacity: .75;\n text-transform: uppercase; letter-spacing: .02em;\n}\n.rm-composer-send {\n width: 34px; height: 34px; border: none; border-radius: 999px;\n background: var(--rm-accent, #5b8cff); color: #fff; cursor: pointer;\n display: grid; place-items: center; transform: translateY(-2px);\n}\n.rm-composer-send:hover:not(:disabled) { filter: brightness(1.08); }\n.rm-composer-send:disabled { opacity: .4; cursor: default; }\n.rm-composer-popwrap { position: relative; }\n.rm-composer-menu {\n position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 40;\n min-width: 200px; max-height: 320px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 8px 24px rgba(0,0,0,.28);\n padding: 6px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-composer-menu-wide { min-width: 280px; max-width: 340px; }\n.rm-composer-menu-label {\n font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;\n color: var(--rm-quiet, #8b93a7); padding: 6px 8px 2px;\n}\n.rm-composer-menu button[role="menuitem"] {\n text-align: left; border: none; background: transparent; color: inherit;\n font: inherit; font-size: 13px; padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-composer-menu button[role="menuitem"]:hover,\n.rm-composer-menu button[role="menuitem"].is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent);\n}\n.rm-composer-check {\n display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 4px 8px; cursor: pointer;\n}\n.rm-grant-row {\n display: flex; align-items: center; justify-content: space-between; gap: 8px;\n padding: 2px 8px; font-size: 12.5px;\n}\n.rm-grant-row select {\n font: inherit; font-size: 12px; border-radius: 6px;\n border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; padding: 2px 6px;\n}\n.rm-peer-grant-block { border-top: 1px solid var(--rm-border, #2a2f3a); padding-top: 4px; margin-top: 4px; }\n.rm-peer-grant-name { font-size: 12px; font-weight: 600; padding: 4px 8px; overflow: hidden; text-overflow: ellipsis; }\n\n/* Hide legacy tight composer if still referenced */\n.rm-composer { display: none; }\n\n.rm-composer-grow { position: relative; }\n.rm-mention-menu {\n position: absolute; left: 8px; right: 8px; bottom: calc(100% + 6px); z-index: 50;\n max-height: 240px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 10px 28px rgba(0,0,0,.32);\n padding: 4px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-mention-item {\n display: flex; align-items: center; gap: 8px; text-align: left;\n border: none; background: transparent; color: inherit; font: inherit;\n padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-mention-item:hover, .rm-mention-item.is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 18%, transparent);\n}\n.rm-mention-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }\n.rm-mention-item-name { font-size: 13px; font-weight: 600; }\n.rm-mention-item-meta { font-size: 11px; color: var(--rm-quiet, #8b93a7); }\n\n\n/* New Room shortcut under workspace (mirrors New Session affordance) */\n.rm-new-room {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n width: 100%; height: 36px; margin-top: 8px;\n border: .5px solid var(--rm-border); border-radius: 10px;\n background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n color: var(--rm-label); cursor: pointer; font-weight: 500; font-size: 13.5px;\n}\n.rm-new-room:hover { background: var(--dsw-alias-button-floating-hover, var(--rm-hover)); }\n.rm-new-room svg { flex: none; }\n\n/* Wide / landscape create + browse modals (overrides default 380px Modal card) */\n.rm-modal-wide {\n width: min(720px, calc(100vw - 48px)) !important;\n max-height: min(640px, calc(100vh - 48px));\n}\n.rm-form-wide {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n align-items: start;\n}\n.rm-form-wide .rm-span-2 { grid-column: 1 / -1; }\n.rm-browse { display: flex; flex-direction: column; gap: 12px; min-height: 280px; max-height: 420px; }\n.rm-browse-search { flex: none; }\n.rm-browse-status { font-size: 11.5px; color: var(--rm-quiet); white-space: nowrap; }\n.rm-browse-list { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 6px; }\n@media (max-width: 640px) {\n .rm-form-wide { grid-template-columns: 1fr; }\n .rm-modal-wide { width: min(420px, calc(100vw - 32px)) !important; }\n}\n\n\n/* \u2500\u2500 panel layout: rooms nav (grouped by native dsh workspace) + content \u2500\u2500 */\n.rm-main { flex-direction: row; }\n.rm-main-body { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-main-body > .rm-welcome-wrap { flex: 1; }\n.rm-main-body > .rm-workspace { flex: 1; }\n.rm-nav {\n flex: 0 0 248px; width: 248px; display: flex; flex-direction: column; gap: 8px; min-height: 0;\n padding: 10px 8px; border-right: .5px solid var(--rm-border); background: var(--rm-bg);\n}\n.rm-nav-head { display: flex; align-items: center; gap: 4px; padding: 0 4px; }\n.rm-nav-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 10px; }\n.rm-ws-group { display: flex; flex-direction: column; gap: 2px; }\n.rm-ws-head {\n display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 2px 0 8px;\n font-size: 12.5px; font-weight: 600; color: var(--rm-muted);\n}\n.rm-ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-ws-add { width: 24px; height: 24px; }\n.rm-ws-empty { padding: 2px 10px 6px 30px; font-size: 11.5px; }\n.rm-nav .rm-room-item { padding: 6px 8px 6px 14px; }\n.rm-session-mark { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; color: var(--rm-accent, var(--dsw-alias-state-business-primary)); }\n';
|
|
40
|
+
var rooms_default = '/* Collab Rooms UI \u2014 original surface inside the dsh shell. Uses only dsh --dsw-* tokens.\n Independent Rooms surface. Prefix: rm- (rooms). */\n\n.rm-root {\n --rm-accent: var(--dsw-alias-state-business-primary);\n --rm-hover: var(--dsw-alias-interactive-bg-hover);\n --rm-border: var(--dsw-alias-border-l2);\n --rm-bg: var(--dsw-alias-bg-base);\n --rm-panel: var(--dsw-alias-bg-module-platform);\n --rm-label: var(--dsw-alias-label-primary);\n --rm-muted: var(--dsw-alias-label-secondary);\n --rm-quiet: var(--dsw-alias-label-tertiary);\n font: 13px/1.5 var(--dsw-font-family);\n color: var(--rm-label);\n box-sizing: border-box;\n}\n.rm-root *, .rm-root *::before, .rm-root *::after { box-sizing: border-box; }\n.rm-root button, .rm-root input, .rm-root textarea { font: inherit; }\n\n/* \u2500\u2500 sidebar (joined rooms + public search) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-side {\n display: flex; flex-direction: column; height: 100%; min-height: 0;\n padding: 0 8px 8px 0; gap: 8px;\n}\n.rm-side-toolbar {\n display: flex; align-items: center; gap: 6px; flex: none; padding: 4px 0 2px;\n}\n.rm-side-title {\n flex: 1; font-size: 12px; font-weight: 600; letter-spacing: .04em;\n text-transform: uppercase; color: var(--rm-quiet);\n}\n.rm-icon-btn {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; padding: 0;\n}\n.rm-icon-btn:hover { background: var(--rm-hover); color: var(--rm-label); }\n.rm-search {\n display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px;\n border: .5px solid var(--rm-border); border-radius: 8px; background: var(--rm-panel);\n}\n.rm-search input {\n flex: 1; min-width: 0; border: 0; background: transparent; outline: none; color: var(--rm-label); font-size: 13px;\n}\n.rm-search input::placeholder { color: var(--rm-quiet); }\n.rm-side-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 12px; }\n.rm-group-label { font-size: 11px; font-weight: 600; color: var(--rm-quiet); padding: 0 4px 4px; text-transform: uppercase; letter-spacing: .03em; }\n.rm-room-list { display: flex; flex-direction: column; gap: 2px; }\n.rm-room-item {\n display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;\n border: 0; border-radius: 10px; background: transparent; color: inherit; cursor: pointer; text-align: left;\n}\n.rm-room-item:hover { background: var(--rm-hover); }\n.rm-room-item[aria-current="true"] { background: var(--rm-hover); }\n.rm-room-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n.rm-room-item-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-meta { font-size: 11.5px; color: var(--rm-quiet); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-trail { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }\n.rm-badge {\n display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px;\n border-radius: 999px; font-size: 10.5px; font-weight: 500; background: var(--rm-panel); color: var(--rm-muted);\n border: .5px solid var(--rm-border);\n}\n.rm-badge-public { color: var(--rm-accent); border-color: color-mix(in srgb, var(--rm-accent) 35%, transparent); background: color-mix(in srgb, var(--rm-accent) 8%, transparent); }\n.rm-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--rm-quiet); }\n.rm-dot-online { background: var(--dsw-alias-state-success-primary, #2bb673); }\n.rm-dot-connecting { background: var(--dsw-alias-state-warn-primary, #e9a23b); }\n.rm-dot-offline { background: var(--dsw-alias-state-error-primary, #e5484d); }\n.rm-empty-hint { padding: 8px 10px; font-size: 12px; color: var(--rm-quiet); line-height: 1.45; }\n.rm-dir-item {\n display: flex; align-items: flex-start; gap: 10px; padding: 10px; border-radius: 10px;\n border: .5px solid var(--rm-border); background: var(--rm-bg); margin-bottom: 6px;\n}\n.rm-dir-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\n.rm-dir-tags { display: flex; flex-wrap: wrap; gap: 4px; }\n.rm-tag { font-size: 11px; color: var(--rm-muted); background: var(--rm-hover); border-radius: 4px; padding: 0 5px; }\n.rm-menu {\n position: fixed; z-index: 1000; min-width: 180px; padding: 4px;\n border-radius: 10px; background: var(--dsw-alias-bg-layer-1, var(--rm-bg));\n border: .5px solid var(--rm-border);\n box-shadow: 0 8px 24px color-mix(in srgb, var(--rm-label) 12%, transparent);\n display: flex; flex-direction: column;\n}\n.rm-menu button {\n display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-menu button:hover { background: var(--rm-hover); }\n\n/* \u2500\u2500 main: room workspace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-main { display: flex; flex: 1; min-height: 0; height: 100%; width: 100%; background: var(--rm-bg); }\n.rm-workspace { display: flex; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat-header {\n flex: none; display: flex; align-items: center; gap: 10px; height: 48px;\n padding: 0 16px; border-bottom: .5px solid var(--rm-border);\n}\n.rm-chat-header-title { font-size: 14px; font-weight: 600; }\n.rm-chat-header-sub { font-size: 12px; color: var(--rm-quiet); }\n.rm-messages {\n flex: 1; min-height: 0; overflow: auto; padding: 16px 18px 8px;\n display: flex; flex-direction: column; gap: 2px;\n}\n.rm-day {\n align-self: center; margin: 10px 0 12px; padding: 2px 10px; border-radius: 999px;\n font-size: 11px; color: var(--rm-quiet); background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n}\n.rm-msg {\n display: grid; grid-template-columns: 32px 1fr; gap: 0 10px; padding: 4px 6px; border-radius: 8px;\n max-width: 720px;\n}\n.rm-msg:hover { background: color-mix(in srgb, var(--rm-hover) 60%, transparent); }\n.rm-msg-self { margin-left: auto; grid-template-columns: 1fr; max-width: 640px; }\n.rm-msg-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 1px; }\n.rm-msg-author { font-size: 12px; font-weight: 600; color: var(--rm-muted); }\n.rm-msg-time { font-size: 11px; color: var(--rm-quiet); }\n.rm-msg-body { font-size: 13.5px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }\n.rm-msg-self .rm-msg-body {\n background: var(--dsw-alias-label-primary); color: var(--dsw-alias-label-primary-foreground);\n padding: 8px 12px; border-radius: 12px 12px 4px 12px; width: fit-content; margin-left: auto;\n}\n.rm-msg-event {\n grid-template-columns: 1fr; max-width: 560px; margin: 6px 0;\n padding: 8px 12px; border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-panel);\n}\n.rm-mention { color: var(--rm-accent); font-weight: 500; }\n.rm-msg-self .rm-mention { color: inherit; text-decoration: underline; text-underline-offset: 2px; }\n.rm-task-card { display: flex; flex-direction: column; gap: 4px; }\n.rm-task-head { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--rm-muted); }\n.rm-task-title { font-weight: 600; font-size: 13.5px; }\n.rm-composer {\n flex: none; display: flex; align-items: flex-end; gap: 8px; padding: 10px 16px 14px;\n border-top: .5px solid var(--rm-border);\n}\n.rm-composer-box {\n flex: 1; display: flex; align-items: flex-end; gap: 6px; min-height: 44px;\n padding: 8px 10px; border: .5px solid var(--rm-border); border-radius: 12px; background: var(--rm-panel);\n}\n.rm-composer-box:focus-within { border-color: color-mix(in srgb, var(--rm-accent) 50%, var(--rm-border)); }\n.rm-composer-box textarea {\n flex: 1; min-height: 28px; max-height: 120px; border: 0; background: transparent; outline: none;\n resize: none; color: var(--rm-label); line-height: 1.45;\n}\n.rm-composer-box textarea::placeholder { color: var(--rm-quiet); }\n.rm-composer-mode {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; flex: none;\n}\n.rm-composer-mode:hover, .rm-composer-mode[aria-pressed="true"] {\n color: var(--rm-accent); background: color-mix(in srgb, var(--rm-accent) 12%, transparent);\n}\n.rm-chat-hint { margin: 48px auto; text-align: center; color: var(--rm-quiet); font-size: 13px; max-width: 360px; line-height: 1.5; }\n\n/* \u2500\u2500 detail column (members / invite / about) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-detail {\n flex: 0 0 280px; width: 280px; display: flex; flex-direction: column; min-height: 0;\n border-left: .5px solid var(--rm-border); background: var(--rm-bg); overflow: auto;\n}\n.rm-detail-section { padding: 14px 14px 8px; border-bottom: .5px solid var(--rm-border); }\n.rm-detail-section:last-child { border-bottom: 0; }\n.rm-detail-h {\n display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600;\n text-transform: uppercase; letter-spacing: .04em; color: var(--rm-quiet); margin-bottom: 8px;\n}\n.rm-member {\n display: flex; align-items: center; gap: 8px; padding: 5px 4px; border-radius: 8px; min-height: 34px;\n}\n.rm-member:hover { background: var(--rm-hover); }\n.rm-member-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }\n.rm-member-actions { display: none; gap: 2px; }\n.rm-member:hover .rm-member-actions, .rm-member:focus-within .rm-member-actions { display: inline-flex; }\n.rm-mini {\n width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-muted); cursor: pointer; font-size: 12px;\n}\n.rm-mini:hover { background: var(--dsw-alias-interactive-bg-active); color: var(--rm-label); }\n.rm-task-row { display: flex; align-items: center; gap: 6px; padding: 4px; font-size: 12.5px; }\n.rm-task-row-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-about { display: grid; grid-template-columns: 88px 1fr; gap: 6px 8px; font-size: 12.5px; margin: 0; }\n.rm-about dt { color: var(--rm-quiet); margin: 0; }\n.rm-about dd { margin: 0; min-width: 0; overflow-wrap: anywhere; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }\n.rm-mono { font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace); font-size: 11.5px; }\n.rm-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }\n.rm-danger { color: var(--dsw-alias-state-error-primary, #e5484d) !important; }\n.rm-note { font-size: 12px; color: var(--rm-quiet); line-height: 1.45; margin: 0 0 8px; }\n\n/* \u2500\u2500 empty / welcome \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-welcome-wrap {\n flex: 1; display: flex; align-items: center; justify-content: center; padding: 32px; background: var(--rm-bg);\n}\n.rm-welcome {\n width: min(420px, 100%); display: flex; flex-direction: column; gap: 10px;\n padding: 20px; border-radius: 14px; border: .5px solid var(--rm-border); background: var(--rm-panel);\n}\n.rm-welcome h1 { margin: 0; font-size: 16px; font-weight: 600; }\n.rm-welcome p { margin: 0; font-size: 13px; color: var(--rm-muted); line-height: 1.5; }\n.rm-welcome-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }\n.rm-welcome-action {\n display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 10px 12px;\n border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-bg);\n color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-welcome-action:hover { background: var(--rm-hover); }\n.rm-welcome-action b { display: block; font-size: 13px; }\n.rm-welcome-action span { display: block; font-size: 12px; color: var(--rm-quiet); margin-top: 2px; }\n\n/* \u2500\u2500 avatars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-avatar {\n display: inline-flex; align-items: center; justify-content: center; flex: none;\n font-weight: 600; letter-spacing: .02em; user-select: none;\n}\n.rm-avatar-wrap { position: relative; display: inline-flex; flex: none; }\n\n/* \u2500\u2500 dialogs (inside dsh Modal) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-form { display: flex; flex-direction: column; gap: 14px; }\n.rm-field { display: flex; flex-direction: column; gap: 6px; }\n.rm-field-label { font-size: 13px; font-weight: 500; }\n.rm-field-hint { font-size: 12px; color: var(--rm-quiet); }\n.rm-name-row { display: flex; align-items: center; gap: 10px; }\n.rm-name-row > :last-child { flex: 1; }\n.rm-switch-row {\n display: flex; align-items: center; justify-content: space-between; gap: 14px;\n padding: 10px 12px; border-radius: 10px; background: var(--rm-panel);\n}\n.rm-error { color: var(--dsw-alias-state-error-primary, #e5484d); font-size: 12.5px; }\n.rm-invite {\n display: block; padding: 10px 12px; border-radius: 8px; background: var(--rm-panel);\n font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace);\n font-size: 12px; word-break: break-all; user-select: all;\n}\n\n/* Dual transport + approvals + agent config */\n.rm-mode-row { display: flex; gap: 8px; }\n.rm-mode-btn {\n flex: 1; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer; font: inherit;\n}\n.rm-mode-btn.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent); }\n.rm-lan-browse { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; align-items: center; }\n.rm-lan-peer {\n font-size: 12px; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer;\n}\n.rm-approvals { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); background: color-mix(in srgb, #f5a524 12%, transparent); }\n.rm-approval { display: flex; gap: 12px; align-items: center; justify-content: space-between; }\n.rm-approval-body { font-size: 13px; }\n.rm-approval-actions { display: flex; gap: 6px; flex-shrink: 0; }\n.rm-input { width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; font: inherit; }\n\n.rm-ws-bar { display: flex; flex-direction: column; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); }\n.rm-ws-chip { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; cursor: pointer; font: inherit; font-size: 12.5px; }\n.rm-ws-path { font-size: 11px; color: var(--rm-quiet, #8b93a7); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item.is-active { background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); }\n\n/* Native-aligned room composer (mirrors dsh conversation control row) */\n.rm-composer-card {\n box-sizing: border-box;\n width: 100%;\n max-width: 920px;\n margin: 0 auto;\n border-radius: 16px;\n background: var(--rm-elev, var(--rm-panel, #12151c));\n border: 1px solid var(--rm-border, #2a2f3a);\n box-shadow: 0 1px 2px rgba(0,0,0,.06);\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 0 6px;\n}\n.rm-composer-grow { position: relative; padding: 0 4px; }\n.rm-composer-grow textarea {\n box-sizing: border-box; width: 100%; min-height: 36px; max-height: 160px;\n resize: none; border: none; outline: none; background: transparent;\n color: inherit; font: inherit; font-size: 14px; line-height: 22px;\n padding: 4px 12px 0 14px;\n}\n.rm-composer-grow textarea:disabled { opacity: .55; cursor: not-allowed; }\n.rm-composer-row {\n display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;\n gap: 10px; min-width: 0; padding: 2px 8px 4px;\n}\n.rm-composer-tools, .rm-composer-modes, .rm-composer-trailing {\n display: flex; align-items: center; min-width: 0; gap: 8px;\n}\n.rm-composer-trailing { flex: none; margin-left: auto; }\n.rm-composer-add {\n width: 28px; height: 28px; border: none; border-radius: 999px;\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n color: inherit; cursor: pointer; display: grid; place-items: center;\n}\n.rm-composer-add:hover, .rm-composer-add[aria-pressed="true"] {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 22%, transparent);\n}\n.rm-composer-select {\n max-width: 220px; height: 28px; border: none; border-radius: 8px;\n background: transparent; color: var(--rm-quiet, #8b93a7);\n font: inherit; font-size: 13px; font-weight: 500; line-height: 20px;\n padding: 0 8px; cursor: pointer; white-space: nowrap;\n}\n.rm-composer-select:hover:not(:disabled) {\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n}\n.rm-composer-select:disabled { opacity: .5; cursor: default; }\n.rm-composer-model-text { display: inline; }\n.rm-composer-model-icon { display: none; font-size: 10px; }\n.rm-composer-effort {\n margin-left: 6px; font-size: 11px; opacity: .75;\n text-transform: uppercase; letter-spacing: .02em;\n}\n.rm-composer-send {\n width: 34px; height: 34px; border: none; border-radius: 999px;\n background: var(--rm-accent, #5b8cff); color: #fff; cursor: pointer;\n display: grid; place-items: center; transform: translateY(-2px);\n}\n.rm-composer-send:hover:not(:disabled) { filter: brightness(1.08); }\n.rm-composer-send:disabled { opacity: .4; cursor: default; }\n.rm-composer-popwrap { position: relative; }\n.rm-composer-menu {\n position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 40;\n min-width: 200px; max-height: 320px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 8px 24px rgba(0,0,0,.28);\n padding: 6px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-composer-menu-wide { min-width: 280px; max-width: 340px; }\n.rm-composer-menu-label {\n font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;\n color: var(--rm-quiet, #8b93a7); padding: 6px 8px 2px;\n}\n.rm-composer-menu button[role="menuitem"] {\n text-align: left; border: none; background: transparent; color: inherit;\n font: inherit; font-size: 13px; padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-composer-menu button[role="menuitem"]:hover,\n.rm-composer-menu button[role="menuitem"].is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent);\n}\n.rm-composer-check {\n display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 4px 8px; cursor: pointer;\n}\n.rm-grant-row {\n display: flex; align-items: center; justify-content: space-between; gap: 8px;\n padding: 2px 8px; font-size: 12.5px;\n}\n.rm-grant-row select {\n font: inherit; font-size: 12px; border-radius: 6px;\n border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; padding: 2px 6px;\n}\n.rm-peer-grant-block { border-top: 1px solid var(--rm-border, #2a2f3a); padding-top: 4px; margin-top: 4px; }\n.rm-peer-grant-name { font-size: 12px; font-weight: 600; padding: 4px 8px; overflow: hidden; text-overflow: ellipsis; }\n\n/* Hide legacy tight composer if still referenced */\n.rm-composer { display: none; }\n\n.rm-composer-grow { position: relative; }\n.rm-mention-menu {\n position: absolute; left: 8px; right: 8px; bottom: calc(100% + 6px); z-index: 50;\n max-height: 240px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 10px 28px rgba(0,0,0,.32);\n padding: 4px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-mention-item {\n display: flex; align-items: center; gap: 8px; text-align: left;\n border: none; background: transparent; color: inherit; font: inherit;\n padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-mention-item:hover, .rm-mention-item.is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 18%, transparent);\n}\n.rm-mention-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }\n.rm-mention-item-name { font-size: 13px; font-weight: 600; }\n.rm-mention-item-meta { font-size: 11px; color: var(--rm-quiet, #8b93a7); }\n\n\n/* New Room shortcut under workspace (mirrors New Session affordance) */\n.rm-new-room {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n width: 100%; height: 36px; margin-top: 8px;\n border: .5px solid var(--rm-border); border-radius: 10px;\n background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n color: var(--rm-label); cursor: pointer; font-weight: 500; font-size: 13.5px;\n}\n.rm-new-room:hover { background: var(--dsw-alias-button-floating-hover, var(--rm-hover)); }\n.rm-new-room svg { flex: none; }\n\n/* Wide / landscape create + browse modals (overrides default 380px Modal card) */\n.rm-modal-wide {\n width: min(720px, calc(100vw - 48px)) !important;\n max-height: min(640px, calc(100vh - 48px));\n}\n.rm-form-wide {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n align-items: start;\n}\n.rm-form-wide .rm-span-2 { grid-column: 1 / -1; }\n.rm-browse { display: flex; flex-direction: column; gap: 12px; min-height: 280px; max-height: 420px; }\n.rm-browse-search { flex: none; }\n.rm-browse-status { font-size: 11.5px; color: var(--rm-quiet); white-space: nowrap; }\n.rm-browse-list { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 6px; }\n@media (max-width: 640px) {\n .rm-form-wide { grid-template-columns: 1fr; }\n .rm-modal-wide { width: min(420px, calc(100vw - 32px)) !important; }\n}\n\n\n/* \u2500\u2500 panel layout: rooms nav (grouped by native dsh workspace) + content \u2500\u2500 */\n.rm-main { flex-direction: row; }\n.rm-main-body { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-main-body > .rm-welcome-wrap { flex: 1; }\n.rm-main-body > .rm-workspace { flex: 1; }\n.rm-nav {\n flex: 0 0 248px; width: 248px; display: flex; flex-direction: column; gap: 8px; min-height: 0;\n padding: 10px 8px; border-right: .5px solid var(--rm-border); background: var(--rm-bg);\n}\n.rm-nav-head { display: flex; align-items: center; gap: 4px; padding: 0 4px; }\n.rm-nav-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 10px; }\n.rm-ws-group { display: flex; flex-direction: column; gap: 2px; }\n.rm-ws-head {\n display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 2px 0 8px;\n font-size: 12.5px; font-weight: 600; color: var(--rm-muted);\n}\n.rm-ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-ws-add { width: 24px; height: 24px; }\n.rm-ws-empty { padding: 2px 10px 6px 30px; font-size: 11.5px; }\n.rm-nav .rm-room-item { padding: 6px 8px 6px 14px; }\n.rm-session-mark { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; color: var(--rm-accent, var(--dsw-alias-state-business-primary)); }\n\n/* \u2500\u2500 local multi-agent (0.3) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-dot-busy { background: var(--dsw-alias-state-warning-primary, #f0a020); }\n.rm-agent-tag { display: inline-flex; align-items: center; gap: 3px; margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 10.5px; line-height: 17px; color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); white-space: nowrap; }\n.rm-msg-id { margin-left: 6px; font-size: 11px; color: var(--rm-quiet); font-family: var(--dsw-font-mono, ui-monospace, monospace); }\n.rm-agent-row { display: flex; align-items: center; gap: 8px; padding: 6px 4px; border-radius: 8px; }\n.rm-agent-row:hover { background: var(--rm-hover); }\n.rm-agent-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }\n.rm-agent-name { font-size: 13px; font-weight: 600; color: var(--rm-label); display: flex; align-items: center; }\n.rm-agent-sub { font-size: 11px; color: var(--rm-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.rm-agent-row .rm-member-actions { display: inline-flex !important; opacity: 0.65; }\n.rm-agent-row:hover .rm-member-actions { opacity: 1; }\n.rm-num-row { display: flex; gap: 8px; margin: 4px 0 8px; }\n.rm-num-setting { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--rm-muted); }\n.rm-num-setting input { width: 100%; box-sizing: border-box; padding: 5px 8px; border: 1px solid var(--rm-border); border-radius: 7px; background: var(--rm-bg); color: var(--rm-label); font: inherit; font-size: 13px; }\n.rm-runs { display: flex; flex-direction: column; gap: 4px; }\n.rm-run { display: grid; grid-template-columns: 22px auto 1fr auto; align-items: center; gap: 6px; padding: 5px 6px; border-radius: 7px; font-size: 12px; border: 1px solid var(--rm-border); }\n.rm-run-running { border-color: color-mix(in srgb, var(--dsw-alias-state-warning-primary, #f0a020) 55%, transparent); background: color-mix(in srgb, var(--dsw-alias-state-warning-primary, #f0a020) 8%, transparent); }\n.rm-run-queued, .rm-run-approval { border-style: dashed; }\n.rm-run-done, .rm-run-stopped, .rm-run-failed { opacity: 0.7; }\n.rm-run-pos { font-size: 11px; color: var(--rm-quiet); text-align: center; font-variant-numeric: tabular-nums; }\n.rm-run-who { font-weight: 600; color: var(--rm-label); white-space: nowrap; }\n.rm-run-what { color: var(--rm-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }\n.rm-stop-btn { display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e5484d) 60%, transparent); background: color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e5484d) 10%, transparent); color: var(--dsw-alias-state-danger-primary, #e5484d); font-size: 12px; cursor: pointer; white-space: nowrap; }\n.rm-stop-btn:hover { background: color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e5484d) 18%, transparent); }\n.rm-badge-local { color: var(--dsw-alias-state-success-primary, #2bb673); }\n.rm-session-agent { color: var(--rm-accent, #5b8cff); }\n.rm-preset-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }\n.rm-preset { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 150px; flex: 1; padding: 8px 10px; border: 1px solid var(--rm-border); border-radius: 10px; background: transparent; color: var(--rm-label); text-align: left; cursor: pointer; font: inherit; font-size: 12px; }\n.rm-preset span { color: var(--rm-muted); font-size: 11px; line-height: 1.35; }\n.rm-preset.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); }\n.rm-preset-check { flex-direction: row; align-items: center; gap: 8px; min-width: 120px; flex: 0 1 auto; }\n.rm-local-box { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border: 1px dashed var(--rm-border); border-radius: 12px; }\n.rm-textarea { width: 100%; box-sizing: border-box; min-height: 84px; resize: vertical; font: inherit; font-size: 13px; padding: 8px 10px; }\n.rm-switch-col { display: flex; flex-direction: column; gap: 6px; }\n.rm-modal-xl { width: min(1180px, 96vw) !important; max-width: 96vw !important; }\n.rm-merge { display: grid; grid-template-columns: 260px 1fr; gap: 14px; min-height: 420px; }\n.rm-merge-list { display: flex; flex-direction: column; gap: 6px; border-right: 1px solid var(--rm-border); padding-right: 12px; }\n.rm-merge-agent { display: flex; align-items: center; gap: 8px; padding: 8px; border: 1px solid transparent; border-radius: 10px; background: transparent; color: var(--rm-label); cursor: pointer; text-align: left; font: inherit; }\n.rm-merge-agent:hover { background: var(--rm-hover); }\n.rm-merge-agent.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 10%, transparent); }\n.rm-merge-agent-body { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 12px; }\n.rm-merge-agent-body .rm-mono { font-size: 10.5px; color: var(--rm-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.rm-merge-main { min-width: 0; display: flex; flex-direction: column; gap: 8px; }\n.rm-merge-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 13px; }\n.rm-merge-files { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; }\n.rm-confirm-text { font-size: 12px; color: var(--rm-label); margin-right: 4px; }\n.rm-diff { margin: 0; max-height: 52vh; overflow: auto; padding: 8px 0; border: 1px solid var(--rm-border); border-radius: 10px; background: var(--rm-panel); font-family: var(--dsw-font-mono, ui-monospace, monospace); font-size: 12px; line-height: 1.5; }\n.rm-diff > div { padding: 0 12px; white-space: pre; }\n.rm-diff-add { background: color-mix(in srgb, #2bb673 16%, transparent); }\n.rm-diff-del { background: color-mix(in srgb, #e5484d 16%, transparent); }\n.rm-diff-hunk { color: var(--rm-accent, #5b8cff); }\n.rm-diff-head, .rm-diff-file { color: var(--rm-muted); font-weight: 600; }\n.rm-diff-addn { color: #2bb673; }\n.rm-diff-deln { color: #e5484d; }\n.rm-ok { padding: 8px 10px; border-radius: 8px; font-size: 12.5px; color: var(--dsw-alias-state-success-primary, #2bb673); background: color-mix(in srgb, #2bb673 10%, transparent); }\n';
|
|
41
41
|
|
|
42
42
|
// src/client/store.js
|
|
43
43
|
var API = "/api/collab";
|
|
@@ -215,6 +215,37 @@ function createRoomsStore() {
|
|
|
215
215
|
},
|
|
216
216
|
async mcp(roomId, tool, args, target) {
|
|
217
217
|
return post(`/rooms/${encodeURIComponent(roomId)}/mcp`, { tool, args, target });
|
|
218
|
+
},
|
|
219
|
+
// ── local multi-agent ──
|
|
220
|
+
async presets() {
|
|
221
|
+
return (await call("/presets")).presets;
|
|
222
|
+
},
|
|
223
|
+
async addAgent(roomId, body) {
|
|
224
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/agents`, body);
|
|
225
|
+
},
|
|
226
|
+
async updateAgent(roomId, id, body) {
|
|
227
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/agents/${encodeURIComponent(id)}`, body);
|
|
228
|
+
},
|
|
229
|
+
async removeAgent(roomId, id) {
|
|
230
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/agents/${encodeURIComponent(id)}?op=delete`);
|
|
231
|
+
},
|
|
232
|
+
async saveLocal(roomId, patch) {
|
|
233
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/local`, patch);
|
|
234
|
+
},
|
|
235
|
+
async setTransport(roomId, target, force) {
|
|
236
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/transport`, { target, force: !!force });
|
|
237
|
+
},
|
|
238
|
+
async stop(roomId, agentId) {
|
|
239
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/stop`, agentId ? { agentId } : {});
|
|
240
|
+
},
|
|
241
|
+
async diffs(roomId) {
|
|
242
|
+
return call(`/rooms/${encodeURIComponent(roomId)}/diffs`);
|
|
243
|
+
},
|
|
244
|
+
async merge(roomId, agentId) {
|
|
245
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/merge`, { agentId, approve: true });
|
|
246
|
+
},
|
|
247
|
+
async discard(roomId, agentId) {
|
|
248
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/discard`, { agentId, approve: true });
|
|
218
249
|
}
|
|
219
250
|
};
|
|
220
251
|
const api = {
|
|
@@ -270,6 +301,17 @@ var LockIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size: 1
|
|
|
270
301
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3.5", y: "7", width: "9", height: "6.25", rx: "1.5" }),
|
|
271
302
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5.5 7V5.25a2.5 2.5 0 0 1 5 0V7" })
|
|
272
303
|
] });
|
|
304
|
+
var BotIcon = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size, children: [
|
|
305
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "5", width: "10", height: "7.5", rx: "2" }),
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 2.5V5M6 8.5h.01M10 8.5h.01M6.25 10.75h3.5" })
|
|
307
|
+
] });
|
|
308
|
+
var StopIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Svg, { size: 12, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5" }) });
|
|
309
|
+
var MergeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size: 14, children: [
|
|
310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "5", cy: "3.75", r: "1.5" }),
|
|
311
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "5", cy: "12.25", r: "1.5" }),
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "11", cy: "8", r: "1.5" }),
|
|
313
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 5.25v5.5M5 5.5c0 2 1.5 2.5 4.5 2.5" })
|
|
314
|
+
] });
|
|
273
315
|
var PeopleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size: 14, children: [
|
|
274
316
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "6", cy: "5.5", r: "2.25" }),
|
|
275
317
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M2.5 13c.4-2 1.8-3.25 3.5-3.25S9.1 11 9.5 13" }),
|
|
@@ -390,6 +432,10 @@ function RoomsNav({ store }) {
|
|
|
390
432
|
}
|
|
391
433
|
function RoomSessionMark({ store, sessionId }) {
|
|
392
434
|
const s = useStore(store);
|
|
435
|
+
for (const r of s.rooms || []) {
|
|
436
|
+
const ag = (r.local && r.local.agents || []).find((x) => x.sessionId === sessionId);
|
|
437
|
+
if (ag) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-session-mark rm-session-agent", title: `DSH Room \xB7 ${r.name} \xB7 ${ag.name} (${ag.agentId})`, "aria-label": `DSH Room ${r.name} agent ${ag.name}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 13 }) });
|
|
438
|
+
}
|
|
393
439
|
const room = (s.rooms || []).find((r) => r.sessionId === sessionId);
|
|
394
440
|
if (!room) return null;
|
|
395
441
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-session-mark", title: `DSH Room \xB7 ${room.name}`, "aria-label": `DSH Room ${room.name}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RoomsIcon, { size: 13 }) });
|
|
@@ -415,14 +461,14 @@ function renderMentions(text) {
|
|
|
415
461
|
function PanelIcon({ size }) {
|
|
416
462
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RoomsIcon, { size });
|
|
417
463
|
}
|
|
418
|
-
function Message({ m, showAuthor }) {
|
|
464
|
+
function Message({ m, showAuthor, who }) {
|
|
419
465
|
if (m.kind === "task.create") {
|
|
420
466
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-msg rm-msg-event", "data-message-id": m.id, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-task-card", children: [
|
|
421
467
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-task-head", children: [
|
|
422
468
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}),
|
|
423
469
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
424
470
|
"Task \xB7 ",
|
|
425
|
-
m.from
|
|
471
|
+
who && who.name || m.from
|
|
426
472
|
] }),
|
|
427
473
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "info", children: "open" }),
|
|
428
474
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-time", children: fmtTime(m.ts) })
|
|
@@ -435,7 +481,7 @@ function Message({ m, showAuthor }) {
|
|
|
435
481
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-msg rm-msg-event", "data-message-id": m.id, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-task-head", children: [
|
|
436
482
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}),
|
|
437
483
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
438
|
-
m.self ? "You" : m.from,
|
|
484
|
+
m.self ? "You" : who && who.name || m.from,
|
|
439
485
|
" ",
|
|
440
486
|
m.kind === "task.claim" ? "claimed" : "updated",
|
|
441
487
|
" task"
|
|
@@ -455,14 +501,20 @@ function Message({ m, showAuthor }) {
|
|
|
455
501
|
showAuthor ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: m.from, size: 28 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
|
|
456
502
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
457
503
|
showAuthor ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-msg-head", children: [
|
|
458
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-author", children: m.from }),
|
|
504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-author", children: who && who.name ? who.name : m.from }),
|
|
505
|
+
who && who.name ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-id", children: m.from }) : null,
|
|
506
|
+
who && who.local ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-tag", children: [
|
|
507
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 11 }),
|
|
508
|
+
who.moderator ? "moderator" : "local agent"
|
|
509
|
+
] }) : null,
|
|
459
510
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-time", children: fmtTime(m.ts) })
|
|
460
511
|
] }) : null,
|
|
461
512
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-msg-body", children: renderMentions(m.text) })
|
|
462
513
|
] })
|
|
463
514
|
] });
|
|
464
515
|
}
|
|
465
|
-
function ChatBody({ messages }) {
|
|
516
|
+
function ChatBody({ messages, members }) {
|
|
517
|
+
const byId = (0, import_react.useMemo)(() => Object.fromEntries((members || []).map((x) => [x.agentId, x])), [members]);
|
|
466
518
|
const ref = (0, import_react.useRef)(null);
|
|
467
519
|
(0, import_react.useEffect)(() => {
|
|
468
520
|
const el = ref.current;
|
|
@@ -478,7 +530,7 @@ function ChatBody({ messages }) {
|
|
|
478
530
|
prev = null;
|
|
479
531
|
}
|
|
480
532
|
const showAuthor = !prev || prev.from !== m.from || m.ts - prev.ts > 5 * 6e4;
|
|
481
|
-
nodes.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Message, { m, showAuthor }, m.id));
|
|
533
|
+
nodes.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Message, { m, showAuthor, who: byId[m.from] }, m.id));
|
|
482
534
|
prev = m;
|
|
483
535
|
}
|
|
484
536
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-messages", ref, children: nodes.length ? nodes : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-chat-hint", children: "No messages yet. Send a message, @mention an agent to wake it, or create a task from the composer." }) });
|
|
@@ -505,7 +557,7 @@ function MentionMenu({ items, active, onPick, onHover }) {
|
|
|
505
557
|
onPick(it);
|
|
506
558
|
},
|
|
507
559
|
children: [
|
|
508
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: it.id === "all" ? "all" : it.id, size: 22 }),
|
|
560
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: it.id === "all" ? "all" : it.name || it.id, size: 22 }),
|
|
509
561
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-mention-item-body", children: [
|
|
510
562
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-mention-item-name", children: [
|
|
511
563
|
"@",
|
|
@@ -513,6 +565,10 @@ function MentionMenu({ items, active, onPick, onHover }) {
|
|
|
513
565
|
] }),
|
|
514
566
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mention-item-meta", children: it.hint })
|
|
515
567
|
] }),
|
|
568
|
+
it.local ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-tag", children: [
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 11 }),
|
|
570
|
+
"local"
|
|
571
|
+
] }) : null,
|
|
516
572
|
it.online === false ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: "offline" }) : null
|
|
517
573
|
]
|
|
518
574
|
},
|
|
@@ -537,14 +593,20 @@ function Composer({ room, store, draft, setDraft }) {
|
|
|
537
593
|
if (!mq) return [];
|
|
538
594
|
const q = mq.query.toLowerCase();
|
|
539
595
|
const members = (room.members || []).filter((m) => !m.self);
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
596
|
+
const localAgents = room.local && room.local.agents || [];
|
|
597
|
+
const seen = /* @__PURE__ */ new Set();
|
|
598
|
+
const known = [];
|
|
599
|
+
for (const la of localAgents) {
|
|
600
|
+
seen.add(la.agentId);
|
|
601
|
+
known.push({ id: la.agentId, name: la.name, local: true, hint: `${la.name} \xB7 local agent${la.moderator ? " \xB7 moderator" : ""}${la.state && la.state !== "idle" ? ` \xB7 ${la.state}` : ""}`, online: la.online !== false });
|
|
602
|
+
}
|
|
603
|
+
for (const m of members) {
|
|
604
|
+
if (seen.has(m.agentId)) continue;
|
|
605
|
+
known.push({ id: m.agentId, name: m.name, hint: `${m.name ? m.name + " \xB7 " : ""}${m.hostedBy ? "remote agent" : "member"}${m.online === false ? " \xB7 offline" : " \xB7 wake"}`, online: m.online !== false });
|
|
606
|
+
}
|
|
607
|
+
const all = { id: "all", hint: localAgents.length ? "Everyone \xB7 wakes all local agents in parallel" : "Everyone \xB7 wake all members", online: true };
|
|
546
608
|
const list = [all, ...known];
|
|
547
|
-
return list.filter((it) => !q || it.id.toLowerCase().startsWith(q) ||
|
|
609
|
+
return list.filter((it) => !q || it.id.toLowerCase().startsWith(q) || it.name && it.name.toLowerCase().startsWith(q));
|
|
548
610
|
})();
|
|
549
611
|
const mc = room.memberConfig || {};
|
|
550
612
|
const modelLabel = mc.model || "Default model";
|
|
@@ -582,6 +644,23 @@ function Composer({ room, store, draft, setDraft }) {
|
|
|
582
644
|
a.toast(e.message);
|
|
583
645
|
}
|
|
584
646
|
};
|
|
647
|
+
const syncCaret = (el) => {
|
|
648
|
+
if (el) setCaret(el.selectionStart == null ? el.value.length : el.selectionStart);
|
|
649
|
+
};
|
|
650
|
+
const insertMention = (it) => {
|
|
651
|
+
if (!mq || !it) return;
|
|
652
|
+
const next = draft.slice(0, mq.start) + "@" + it.id + " " + draft.slice(mq.end);
|
|
653
|
+
const pos = mq.start + it.id.length + 2;
|
|
654
|
+
setDraft(next);
|
|
655
|
+
setCaret(pos);
|
|
656
|
+
requestAnimationFrame(() => {
|
|
657
|
+
const el = taRef.current;
|
|
658
|
+
if (el) {
|
|
659
|
+
el.focus();
|
|
660
|
+
el.setSelectionRange(pos, pos);
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
};
|
|
585
664
|
const submit = async () => {
|
|
586
665
|
const text = draft.trim();
|
|
587
666
|
if (!text || busy) return;
|
|
@@ -778,7 +857,15 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
778
857
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: m.agentId, size: 26 }),
|
|
779
858
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-dot rm-dot-" + (m.online === false ? "offline" : "online"), style: { position: "absolute", right: -1, bottom: -1, border: "2px solid var(--rm-bg)" } })
|
|
780
859
|
] }),
|
|
781
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-member-name", children: m.
|
|
860
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-member-name", children: m.name ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
861
|
+
m.name,
|
|
862
|
+
" ",
|
|
863
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-id", children: m.agentId })
|
|
864
|
+
] }) : m.agentId }),
|
|
865
|
+
m.local ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-tag", children: [
|
|
866
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 11 }),
|
|
867
|
+
m.moderator ? "moderator" : "local"
|
|
868
|
+
] }) : m.hostedBy && !m.self ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-agent-tag", children: "remote agent" }) : null,
|
|
782
869
|
m.self ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: "you" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-member-actions", children: [
|
|
783
870
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `@mention ${m.agentId}`, onClick: () => mention(m.agentId), children: "@" }),
|
|
784
871
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `Assign a task to ${m.agentId}`, onClick: () => assign(m.agentId), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}) })
|
|
@@ -786,6 +873,9 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
786
873
|
] }, m.agentId)),
|
|
787
874
|
!room.members.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: room.status === "online" ? "Only you are here." : "Offline." }) : null
|
|
788
875
|
] }),
|
|
876
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LocalAgentsSection, { room, store, mention }),
|
|
877
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(OrchestrationSection, { room, store }),
|
|
878
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(IsolationSection, { room, store }),
|
|
789
879
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", children: [
|
|
790
880
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
791
881
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}),
|
|
@@ -808,8 +898,10 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
808
898
|
"Invite"
|
|
809
899
|
] }),
|
|
810
900
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: room.public ? "Public: listed in the relay directory with its key. Anyone can find, join, and read this room." : "Private: only agents holding the invite can join. The invite contains the room key \u2014 share it only with agents you trust." }),
|
|
901
|
+
room.transport === "local" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Local-only room: switch Transport to Relay or LAN before inviting remote hosts." }) : null,
|
|
811
902
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", onClick: copyInvite, icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkIcon, {}), children: "Copy invite" }) })
|
|
812
903
|
] }),
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransportSection, { room, store }),
|
|
813
905
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", children: [
|
|
814
906
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-detail-h", children: "About" }),
|
|
815
907
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", { className: "rm-about", children: [
|
|
@@ -822,7 +914,7 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
822
914
|
" Private"
|
|
823
915
|
] }) }),
|
|
824
916
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Transport" }),
|
|
825
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: room.transport === "lan" ? "LAN / VPS (Node relay)" : "Relay (Cloudflare)" }),
|
|
917
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: room.transport === "local" ? "Local only (in-process loopback)" : room.transport === "lan" ? "LAN / VPS (Node relay)" : "Relay (Cloudflare)" }),
|
|
826
918
|
room.memberConfig?.workspaceLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
827
919
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Workspace" }),
|
|
828
920
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: room.memberConfig.workspaceLabel })
|
|
@@ -849,6 +941,371 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
849
941
|
] })
|
|
850
942
|
] });
|
|
851
943
|
}
|
|
944
|
+
var RUN_TONE = { running: "warning", queued: "info", approval: "info", done: "success", failed: "danger", stopped: "quiet" };
|
|
945
|
+
var MODEL_CHOICES = ["", "deepseek-chat", "deepseek-reasoner"];
|
|
946
|
+
function LocalAgentsSection({ room, store, mention }) {
|
|
947
|
+
const a = store.actions;
|
|
948
|
+
const local = room.local || { agents: [] };
|
|
949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-local-agents": "", children: [
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
951
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, {}),
|
|
952
|
+
"Local agents \xB7 ",
|
|
953
|
+
local.agents.length
|
|
954
|
+
] }),
|
|
955
|
+
local.agents.map((ag) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-agent-row", "data-agent-id": ag.agentId, children: [
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-avatar-wrap", children: [
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: ag.name, size: 26 }),
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-dot rm-dot-" + (ag.state === "running" ? "busy" : ag.online ? "online" : "offline"), style: { position: "absolute", right: -1, bottom: -1, border: "2px solid var(--rm-bg)" } })
|
|
959
|
+
] }),
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-main", children: [
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-name", children: [
|
|
962
|
+
ag.name,
|
|
963
|
+
ag.moderator ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-agent-tag", children: "moderator" }) : null
|
|
964
|
+
] }),
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-sub rm-mono", children: [
|
|
966
|
+
"@",
|
|
967
|
+
ag.agentId
|
|
968
|
+
] }),
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-sub", children: [
|
|
970
|
+
ag.scope === "write" ? ag.isolation === "worktree" ? "writes \xB7 own worktree" : ag.isolation === "locks" ? "writes \xB7 file locks" : "writes" : "read-only",
|
|
971
|
+
ag.approvalRequired ? " \xB7 approval" : "",
|
|
972
|
+
ag.model ? ` \xB7 ${ag.model}` : "",
|
|
973
|
+
ag.reasoningEffort ? ` \xB7 ${ag.reasoningEffort}` : ""
|
|
974
|
+
] })
|
|
975
|
+
] }),
|
|
976
|
+
ag.state !== "idle" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: RUN_TONE[ag.state] || "neutral", children: ag.state }) : null,
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-member-actions", children: [
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `@mention ${ag.name}`, onClick: () => mention(ag.agentId), children: "@" }),
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `Edit ${ag.name}`, "aria-label": `Edit ${ag.name}`, onClick: () => a.openDialog({ kind: "agent", roomId: room.roomId, agentId: ag.agentId }), children: "\u270E" })
|
|
980
|
+
] })
|
|
981
|
+
] }, ag.agentId)),
|
|
982
|
+
!local.agents.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Host several agents from this dsh as separate members \u2014 each with its own identity, session and scope." }) : null,
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlusIcon, {}), onClick: () => a.openDialog({ kind: "agent", roomId: room.roomId }), children: "Add local agent" }) })
|
|
984
|
+
] });
|
|
985
|
+
}
|
|
986
|
+
function NumberSetting({ label, value, min, max, onSave, hint }) {
|
|
987
|
+
const [v, setV] = (0, import_react.useState)(String(value));
|
|
988
|
+
(0, import_react.useEffect)(() => setV(String(value)), [value]);
|
|
989
|
+
const commit = () => {
|
|
990
|
+
const n = Number(v);
|
|
991
|
+
if (Number.isFinite(n) && n !== value) onSave(Math.min(max, Math.max(min, Math.round(n))));
|
|
992
|
+
else setV(String(value));
|
|
993
|
+
};
|
|
994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "rm-num-setting", title: hint, children: [
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", min, max, value: v, "aria-label": label, onChange: (e) => setV(e.target.value), onBlur: commit, onKeyDown: (e) => e.key === "Enter" && e.target.blur() })
|
|
997
|
+
] });
|
|
998
|
+
}
|
|
999
|
+
function RunQueue({ room, store, compact }) {
|
|
1000
|
+
const a = store.actions;
|
|
1001
|
+
const runs = room.runs || [];
|
|
1002
|
+
const nameOf = (id) => (room.local && room.local.agents || []).find((x) => x.agentId === id)?.name || id;
|
|
1003
|
+
const active = runs.filter((r) => r.state === "running" || r.state === "queued" || r.state === "approval");
|
|
1004
|
+
const recent = runs.filter((r) => !active.includes(r)).slice(-3).reverse();
|
|
1005
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-runs", "data-rm-runs": "", children: [
|
|
1006
|
+
active.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-run rm-run-" + r.state, children: [
|
|
1007
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-pos", children: r.state === "running" ? "\u25B6" : r.state === "approval" ? "?" : `#${i + 1 - active.filter((x) => x.state === "running").length}` }),
|
|
1008
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-who", children: nameOf(r.agentId) }),
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-what", title: r.summary, children: r.summary }),
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: RUN_TONE[r.state], children: r.state === "approval" ? "needs approval" : r.state })
|
|
1011
|
+
] }, r.id)),
|
|
1012
|
+
!compact ? recent.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-run rm-run-" + r.state, children: [
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-pos", children: "\u2713" }),
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-who", children: nameOf(r.agentId) }),
|
|
1015
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-what", title: r.error || r.summary, children: r.error || r.summary }),
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: RUN_TONE[r.state], children: r.state })
|
|
1017
|
+
] }, r.id)) : null,
|
|
1018
|
+
!active.length && !recent.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "No agent runs yet." }) : null,
|
|
1019
|
+
active.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", className: "rm-danger", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StopIcon, {}), onClick: () => a.stop(room.roomId).then((r) => a.toast(`Stopped ${r.stopped} run(s)`)).catch((e) => a.toast(e.message)), children: "Stop all agents" }) }) : null
|
|
1020
|
+
] });
|
|
1021
|
+
}
|
|
1022
|
+
function OrchestrationSection({ room, store }) {
|
|
1023
|
+
const a = store.actions;
|
|
1024
|
+
const local = room.local;
|
|
1025
|
+
if (!local || !local.agents.length) return null;
|
|
1026
|
+
const save = (patch) => a.saveLocal(room.roomId, patch).catch((e) => a.toast(e.message));
|
|
1027
|
+
const active = (room.runs || []).filter((r) => r.state === "running" || r.state === "queued" || r.state === "approval");
|
|
1028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-orchestration": "", children: [
|
|
1029
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
1030
|
+
"Runs \xB7 ",
|
|
1031
|
+
active.filter((r) => r.state === "running").length,
|
|
1032
|
+
"/",
|
|
1033
|
+
local.concurrency,
|
|
1034
|
+
" running",
|
|
1035
|
+
active.length > local.concurrency ? ` \xB7 ${active.length - Math.min(local.concurrency, active.filter((r) => r.state === "running").length)} queued` : ""
|
|
1036
|
+
] }),
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-num-row", children: [
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(NumberSetting, { label: "Parallel runs", value: local.concurrency, min: 1, max: 16, onSave: (n) => save({ concurrency: n }), hint: "Max local agent runs at once; the rest wait in the queue." }),
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(NumberSetting, { label: "Turn limit", value: local.turnLimit, min: 1, max: 100, onSave: (n) => save({ turnLimit: n }), hint: "Max agent-to-agent hand-offs per task/thread. A human message resets it." })
|
|
1040
|
+
] }),
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunQueue, { room, store })
|
|
1042
|
+
] });
|
|
1043
|
+
}
|
|
1044
|
+
function IsolationSection({ room, store }) {
|
|
1045
|
+
const a = store.actions;
|
|
1046
|
+
const local = room.local;
|
|
1047
|
+
if (!local || !local.agents.some((x) => x.scope === "write")) return null;
|
|
1048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-isolation": "", children: [
|
|
1049
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
1050
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeIcon, {}),
|
|
1051
|
+
"Workspace isolation"
|
|
1052
|
+
] }),
|
|
1053
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { className: "rm-input", "aria-label": "Isolation mode", value: local.isolation, onChange: (e) => a.saveLocal(room.roomId, { isolation: e.target.value }).catch((x) => a.toast(x.message)), children: [
|
|
1054
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "auto", children: "Auto \u2014 git worktree per writing agent, else file locks" }),
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "worktree", children: "Git worktree per agent" }),
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "locks", children: "File locks (shared workspace)" }),
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "off", children: "Off (shared, no locks)" })
|
|
1058
|
+
] }),
|
|
1059
|
+
local.locks && local.locks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-note", children: [
|
|
1060
|
+
local.locks.length,
|
|
1061
|
+
" file lock(s): ",
|
|
1062
|
+
local.locks.slice(0, 4).map((l) => `${l.path} (${l.owner})`).join(", ")
|
|
1063
|
+
] }) : null,
|
|
1064
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeIcon, {}), onClick: () => a.openDialog({ kind: "merge", roomId: room.roomId }), children: "Review & merge" }) })
|
|
1065
|
+
] });
|
|
1066
|
+
}
|
|
1067
|
+
function TransportSection({ room, store }) {
|
|
1068
|
+
const a = store.actions;
|
|
1069
|
+
const [busy, setBusy] = (0, import_react.useState)(null);
|
|
1070
|
+
const cur = room.transport === "local" ? "local" : room.transport === "lan" ? "relay" : "relay";
|
|
1071
|
+
const go = async (target) => {
|
|
1072
|
+
setBusy(target);
|
|
1073
|
+
try {
|
|
1074
|
+
await a.setTransport(room.roomId, target);
|
|
1075
|
+
a.toast(target === "local" ? "Local only \u2014 in-process, no network" : target === "lan" ? "Now on this machine's LAN relay \u2014 invite remote hosts" : "Now on the relay \u2014 invite remote hosts");
|
|
1076
|
+
} catch (e) {
|
|
1077
|
+
a.toast(e.message);
|
|
1078
|
+
} finally {
|
|
1079
|
+
setBusy(null);
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-transport": "", children: [
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-detail-h", children: "Transport" }),
|
|
1084
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-mode-row", children: [
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: !!busy || room.public, className: "rm-mode-btn" + (cur === "local" ? " is-on" : ""), onClick: () => go("local"), title: room.public ? "Public rooms need a relay" : "In-process loopback: no network", children: busy === "local" ? "\u2026" : "Local only" }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: !!busy, className: "rm-mode-btn" + (cur === "relay" && room.transport !== "local" ? " is-on" : ""), onClick: () => go("relay"), children: busy === "relay" ? "\u2026" : "Relay (VPS)" }),
|
|
1087
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: !!busy, className: "rm-mode-btn", onClick: () => go("lan"), title: "Embedded LAN relay on this machine (mDNS)", children: busy === "lan" ? "\u2026" : "LAN" })
|
|
1088
|
+
] }),
|
|
1089
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: room.transport === "local" ? "All members are on this dsh \u2014 nothing leaves the process. Switch to Relay or LAN to invite remote hosts; local agents stay members." : "Local agents connect as separate members over this transport, alongside remote hosts." })
|
|
1090
|
+
] });
|
|
1091
|
+
}
|
|
1092
|
+
function AgentDialog({ store, d }) {
|
|
1093
|
+
const a = store.actions;
|
|
1094
|
+
const s = useStore(store);
|
|
1095
|
+
const room = (s.rooms || []).find((r) => r.roomId === d.roomId);
|
|
1096
|
+
const existing = room && room.local ? room.local.agents.find((x) => x.agentId === d.agentId) : null;
|
|
1097
|
+
const [presets, setPresets] = (0, import_react.useState)([]);
|
|
1098
|
+
const [f, setF] = (0, import_react.useState)(() => existing ? { name: existing.name, persona: existing.persona || "", systemPrompt: existing.systemPrompt || "", model: existing.model || "", reasoningEffort: existing.reasoningEffort || "medium", scope: existing.scope, approvalRequired: !!existing.approvalRequired, moderator: !!existing.moderator } : { preset: "", name: "", persona: "", systemPrompt: "", model: "", reasoningEffort: "medium", scope: "read", approvalRequired: false, moderator: false });
|
|
1099
|
+
const [err, setErr] = (0, import_react.useState)(null);
|
|
1100
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
1101
|
+
(0, import_react.useEffect)(() => {
|
|
1102
|
+
a.presets().then(setPresets).catch(() => {
|
|
1103
|
+
});
|
|
1104
|
+
}, []);
|
|
1105
|
+
const pick = (p) => setF({ ...f, preset: p.key, name: p.name, persona: p.persona, systemPrompt: p.systemPrompt, scope: p.scope, moderator: !!p.moderator, reasoningEffort: p.reasoningEffort || "medium" });
|
|
1106
|
+
const submit = async () => {
|
|
1107
|
+
if (!f.name.trim()) {
|
|
1108
|
+
setErr("Name required");
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
setBusy(true);
|
|
1112
|
+
setErr(null);
|
|
1113
|
+
try {
|
|
1114
|
+
const body = { name: f.name, persona: f.persona, systemPrompt: f.systemPrompt, model: f.model, reasoningEffort: f.reasoningEffort, scope: f.scope, approvalRequired: f.approvalRequired, moderator: f.moderator, preset: f.preset || void 0 };
|
|
1115
|
+
if (existing) await a.updateAgent(d.roomId, existing.agentId, body);
|
|
1116
|
+
else {
|
|
1117
|
+
const r = await a.addAgent(d.roomId, body);
|
|
1118
|
+
a.toast(`${r.name} joined as @${r.agentId}`);
|
|
1119
|
+
}
|
|
1120
|
+
a.closeDialog();
|
|
1121
|
+
} catch (e) {
|
|
1122
|
+
setErr(e.message);
|
|
1123
|
+
setBusy(false);
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
const remove = async () => {
|
|
1127
|
+
setBusy(true);
|
|
1128
|
+
try {
|
|
1129
|
+
const r = await a.removeAgent(d.roomId, existing.agentId);
|
|
1130
|
+
a.toast(`Removed ${existing.name}${r.branchKept ? ` \xB7 branch ${r.branchKept} kept` : ""}`);
|
|
1131
|
+
a.closeDialog();
|
|
1132
|
+
} catch (e) {
|
|
1133
|
+
setErr(e.message);
|
|
1134
|
+
setBusy(false);
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1138
|
+
import_dsh_client_ui_primitives.Modal,
|
|
1139
|
+
{
|
|
1140
|
+
open: true,
|
|
1141
|
+
onClose: a.closeDialog,
|
|
1142
|
+
title: existing ? `Edit ${existing.name}` : "Add local agent",
|
|
1143
|
+
closeLabel: "Close",
|
|
1144
|
+
className: "rm-modal-wide",
|
|
1145
|
+
description: existing ? `Member @${existing.agentId} \xB7 own identity and dsh session in this room's workspace.` : "Runs on this dsh as a separate room member: own keypair, own session, own scope. Remote peers see it as a member.",
|
|
1146
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1147
|
+
existing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", className: "rm-danger", disabled: busy, onClick: remove, children: "Remove" }) : null,
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
1149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", onClick: a.closeDialog, children: "Cancel" }),
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", disabled: busy, onClick: submit, children: busy ? "Saving\u2026" : existing ? "Save" : "Add agent" })
|
|
1151
|
+
] }),
|
|
1152
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-root rm-form rm-form-wide", "data-rm-agent-form": "", children: [
|
|
1153
|
+
!existing ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-span-2", children: [
|
|
1154
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Preset" }),
|
|
1155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-preset-row", children: presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "rm-preset" + (f.preset === p.key ? " is-on" : ""), onClick: () => pick(p), children: [
|
|
1156
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: p.name }),
|
|
1157
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.persona })
|
|
1158
|
+
] }, p.key)) })
|
|
1159
|
+
] }) : null,
|
|
1160
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Name", htmlFor: "rm-ag-name", hint: "Member id is derived from it (e.g. coder.ab12).", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Input, { id: "rm-ag-name", value: f.name, maxLength: 40, onChange: (e) => setF({ ...f, name: e.target.value }), placeholder: "e.g. Coder" }) }),
|
|
1161
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Persona", htmlFor: "rm-ag-persona", hint: "One line other members see.", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Input, { id: "rm-ag-persona", value: f.persona, maxLength: 200, onChange: (e) => setF({ ...f, persona: e.target.value }), placeholder: "e.g. Implements changes" }) }),
|
|
1162
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "System prompt", htmlFor: "rm-ag-sp", hint: "Prepended to every wake of this agent.", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { id: "rm-ag-sp", className: "rm-input rm-textarea", rows: 4, value: f.systemPrompt, maxLength: 4e3, onChange: (e) => setF({ ...f, systemPrompt: e.target.value }) }) }) }),
|
|
1163
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Model", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { className: "rm-input", "aria-label": "Model", value: f.model, onChange: (e) => setF({ ...f, model: e.target.value }), children: [
|
|
1164
|
+
MODEL_CHOICES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: m, children: m || "dsh default model" }, m)),
|
|
1165
|
+
f.model && !MODEL_CHOICES.includes(f.model) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: f.model, children: f.model }) : null
|
|
1166
|
+
] }) }),
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Reasoning effort", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { className: "rm-input", "aria-label": "Reasoning effort", value: f.reasoningEffort, onChange: (e) => setF({ ...f, reasoningEffort: e.target.value }), children: ["low", "medium", "high", "max"].map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: x, children: x }, x)) }) }),
|
|
1168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Workspace scope", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-mode-row", children: [
|
|
1169
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mode-btn" + (f.scope === "read" ? " is-on" : ""), onClick: () => setF({ ...f, scope: "read" }), children: "Read-only" }),
|
|
1170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mode-btn" + (f.scope === "write" ? " is-on" : ""), onClick: () => setF({ ...f, scope: "write" }), children: "Read + write" })
|
|
1171
|
+
] }) }),
|
|
1172
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-col", children: [
|
|
1173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-row", children: [
|
|
1174
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1175
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Approval required" }),
|
|
1176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "Each run waits for your OK." })
|
|
1177
|
+
] }),
|
|
1178
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.approvalRequired, onChange: (v) => setF({ ...f, approvalRequired: v }), label: "Approval required" })
|
|
1179
|
+
] }),
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-row", children: [
|
|
1181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Moderator" }),
|
|
1183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "Splits requests into tasks and summarizes. One per room." })
|
|
1184
|
+
] }),
|
|
1185
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.moderator, onChange: (v) => setF({ ...f, moderator: v }), label: "Moderator" })
|
|
1186
|
+
] })
|
|
1187
|
+
] }),
|
|
1188
|
+
f.scope === "write" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2 rm-note", children: "Writes go to its own git worktree (branch room/<room>/<agent>) when the workspace is a git repo; you merge from \u201CReview & merge\u201D. Non-git workspaces use file locks." }) : null,
|
|
1189
|
+
err ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2 rm-error", children: err }) : null
|
|
1190
|
+
] })
|
|
1191
|
+
}
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
function DiffView({ patch }) {
|
|
1195
|
+
if (!patch) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "No changes." });
|
|
1196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: "rm-diff", "data-rm-diff": "", children: patch.split("\n").map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: l.startsWith("+++") || l.startsWith("---") ? "rm-diff-file" : l.startsWith("+") ? "rm-diff-add" : l.startsWith("-") ? "rm-diff-del" : l.startsWith("@@") ? "rm-diff-hunk" : l.startsWith("diff ") ? "rm-diff-head" : "", children: l || " " }, i)) });
|
|
1197
|
+
}
|
|
1198
|
+
function MergeDialog({ store, d }) {
|
|
1199
|
+
const a = store.actions;
|
|
1200
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
1201
|
+
const [sel, setSel] = (0, import_react.useState)(null);
|
|
1202
|
+
const [confirm, setConfirm] = (0, import_react.useState)(null);
|
|
1203
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
1204
|
+
const [result, setResult] = (0, import_react.useState)(null);
|
|
1205
|
+
const load = async () => {
|
|
1206
|
+
try {
|
|
1207
|
+
const r = await a.diffs(d.roomId);
|
|
1208
|
+
setData(r);
|
|
1209
|
+
setSel((cur) => cur && r.agents.some((x) => x.agentId === cur) ? cur : (r.agents.find((x) => x.ahead) || r.agents[0] || {}).agentId || null);
|
|
1210
|
+
} catch (e) {
|
|
1211
|
+
setData({ error: e.message, agents: [] });
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
(0, import_react.useEffect)(() => {
|
|
1215
|
+
void load();
|
|
1216
|
+
}, [d.roomId]);
|
|
1217
|
+
const ag = data && data.agents.find((x) => x.agentId === sel);
|
|
1218
|
+
const run = async (kind) => {
|
|
1219
|
+
setBusy(true);
|
|
1220
|
+
setResult(null);
|
|
1221
|
+
try {
|
|
1222
|
+
const r = kind === "merge" ? await a.merge(d.roomId, sel) : await a.discard(d.roomId, sel);
|
|
1223
|
+
setResult(kind === "merge" ? r.merged ? { ok: true, text: `Merged into the main workspace (${r.commit}).` } : { ok: false, text: `${r.error || "Not merged"}${r.conflicts && r.conflicts.length ? ": " + r.conflicts.join(", ") : ""}` } : { ok: true, text: r.discarded ? `Discarded ${r.branch}.` : "Nothing to discard." });
|
|
1224
|
+
await load();
|
|
1225
|
+
} catch (e) {
|
|
1226
|
+
setResult({ ok: false, text: e.message });
|
|
1227
|
+
} finally {
|
|
1228
|
+
setBusy(false);
|
|
1229
|
+
setConfirm(null);
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1233
|
+
import_dsh_client_ui_primitives.Modal,
|
|
1234
|
+
{
|
|
1235
|
+
open: true,
|
|
1236
|
+
onClose: a.closeDialog,
|
|
1237
|
+
title: "Review & merge agent changes",
|
|
1238
|
+
closeLabel: "Close",
|
|
1239
|
+
className: "rm-modal-wide rm-modal-xl",
|
|
1240
|
+
description: "Each writing agent works on its own branch. Review the diff, then merge into (or discard from) your main workspace. Nothing is merged without your confirmation.",
|
|
1241
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", onClick: a.closeDialog, children: "Close" }),
|
|
1242
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-root rm-merge", "data-rm-merge": "", children: !data ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Loading diffs\u2026" }) : data.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-error", children: data.error }) : !data.agents.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "No writing agents in this room." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1243
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-merge-list", children: data.agents.map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "rm-merge-agent" + (x.agentId === sel ? " is-on" : ""), onClick: () => {
|
|
1244
|
+
setSel(x.agentId);
|
|
1245
|
+
setConfirm(null);
|
|
1246
|
+
setResult(null);
|
|
1247
|
+
}, children: [
|
|
1248
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: x.name, size: 24 }),
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-merge-agent-body", children: [
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: x.name }),
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mono", children: x.branch || (x.isolation === "locks" ? "shared workspace \xB7 locks" : "no worktree yet") })
|
|
1252
|
+
] }),
|
|
1253
|
+
x.conflicts && x.conflicts.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "danger", children: "conflict" }) : x.ahead ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Tag, { tone: "info", children: [
|
|
1254
|
+
x.files.length,
|
|
1255
|
+
" file",
|
|
1256
|
+
x.files.length === 1 ? "" : "s"
|
|
1257
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: "clean" })
|
|
1258
|
+
] }, x.agentId)) }),
|
|
1259
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-merge-main", children: ag ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-merge-head", children: [
|
|
1261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: ag.name }),
|
|
1263
|
+
" ",
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mono", children: ag.branch || "" }),
|
|
1265
|
+
ag.ahead ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-note", style: { margin: "0 0 0 8px" }, children: [
|
|
1266
|
+
ag.ahead,
|
|
1267
|
+
" commit(s) ahead"
|
|
1268
|
+
] }) : null
|
|
1269
|
+
] }),
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", style: { margin: 0 }, children: confirm ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1271
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-confirm-text", children: confirm === "merge" ? `Merge ${ag.files.length} file(s) into the main workspace?` : `Discard ${ag.name}'s branch and worktree?` }),
|
|
1272
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", onClick: () => setConfirm(null), children: "Cancel" }),
|
|
1273
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "primary", disabled: busy, onClick: () => run(confirm), children: busy ? "Working\u2026" : confirm === "merge" ? "Confirm merge" : "Confirm discard" })
|
|
1274
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "ghost", className: "rm-danger", disabled: !ag.branch || busy, onClick: () => setConfirm("discard"), children: "Discard" }),
|
|
1276
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeIcon, {}), disabled: !ag.ahead || busy, onClick: () => setConfirm("merge"), children: "Merge into main" })
|
|
1277
|
+
] }) })
|
|
1278
|
+
] }),
|
|
1279
|
+
result ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: result.ok ? "rm-ok" : "rm-error", children: result.text }) : null,
|
|
1280
|
+
ag.conflicts && ag.conflicts.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-error", children: [
|
|
1281
|
+
"Would conflict with the main workspace: ",
|
|
1282
|
+
ag.conflicts.join(", "),
|
|
1283
|
+
" \u2014 resolve on the branch or discard."
|
|
1284
|
+
] }) : null,
|
|
1285
|
+
ag.mainDirty && ag.mainDirty.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-error", children: [
|
|
1286
|
+
"Uncommitted changes in the main workspace touch: ",
|
|
1287
|
+
ag.mainDirty.join(", ")
|
|
1288
|
+
] }) : null,
|
|
1289
|
+
ag.files && ag.files.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-merge-files", children: ag.files.map((f) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-merge-file", children: [
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mono", children: f.path }),
|
|
1291
|
+
" ",
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-diff-addn", children: [
|
|
1293
|
+
"+",
|
|
1294
|
+
f.adds
|
|
1295
|
+
] }),
|
|
1296
|
+
" ",
|
|
1297
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-diff-deln", children: [
|
|
1298
|
+
"\u2212",
|
|
1299
|
+
f.dels
|
|
1300
|
+
] })
|
|
1301
|
+
] }, f.path)) }) : null,
|
|
1302
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffView, { patch: ag.patch }),
|
|
1303
|
+
ag.truncated ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Diff truncated." }) : null
|
|
1304
|
+
] }) : null })
|
|
1305
|
+
] }) })
|
|
1306
|
+
}
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
852
1309
|
function EmptyMain({ store }) {
|
|
853
1310
|
const a = store.actions;
|
|
854
1311
|
const workspaces = useNativeWorkspaces(store);
|
|
@@ -908,11 +1365,25 @@ function RoomsMain({ store }) {
|
|
|
908
1365
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-chat-header-title", children: room.name }),
|
|
909
1366
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-chat-header-sub", children: [
|
|
910
1367
|
room.members.filter((m) => m.online !== false).length,
|
|
911
|
-
" online
|
|
1368
|
+
" online",
|
|
1369
|
+
room.local && room.local.agents.length ? ` \xB7 ${room.local.agents.length} local agent${room.local.agents.length === 1 ? "" : "s"}` : "",
|
|
1370
|
+
" \xB7 ",
|
|
912
1371
|
room.public ? "public" : "private",
|
|
913
1372
|
room.status !== "online" ? ` \xB7 room ${room.status}` : ""
|
|
914
1373
|
] })
|
|
915
1374
|
] }),
|
|
1375
|
+
(() => {
|
|
1376
|
+
const act = (room.runs || []).filter((r) => r.state === "running" || r.state === "queued" || r.state === "approval");
|
|
1377
|
+
if (!act.length) return null;
|
|
1378
|
+
const running = act.filter((r) => r.state === "running").length;
|
|
1379
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "rm-stop-btn", "data-rm-stop": "", title: "Stop all local agent runs", onClick: () => store.actions.stop(room.roomId).then((r) => store.actions.toast(`Stopped ${r.stopped} run(s)`)).catch((e) => store.actions.toast(e.message)), children: [
|
|
1380
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StopIcon, {}),
|
|
1381
|
+
"Stop \xB7 ",
|
|
1382
|
+
running,
|
|
1383
|
+
" running",
|
|
1384
|
+
act.length > running ? `, ${act.length - running} queued` : ""
|
|
1385
|
+
] });
|
|
1386
|
+
})(),
|
|
916
1387
|
room.public ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-badge rm-badge-public", children: [
|
|
917
1388
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GlobeIcon, {}),
|
|
918
1389
|
"Public"
|
|
@@ -920,10 +1391,10 @@ function RoomsMain({ store }) {
|
|
|
920
1391
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LockIcon, {}),
|
|
921
1392
|
"Private"
|
|
922
1393
|
] }),
|
|
923
|
-
room.transport === "lan" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-badge", children: "LAN/VPS" }) : null,
|
|
1394
|
+
room.transport === "local" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-badge rm-badge-local", children: "Local only" }) : room.transport === "lan" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-badge", children: "LAN/VPS" }) : null,
|
|
924
1395
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: room.status === "online" ? "done" : room.status === "connecting" ? "ongoing" : "error", size: 8 })
|
|
925
1396
|
] }),
|
|
926
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatBody, { messages }),
|
|
1397
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatBody, { messages, members: room.members }),
|
|
927
1398
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Composer, { room, store, draft, setDraft })
|
|
928
1399
|
] }),
|
|
929
1400
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -953,7 +1424,7 @@ function Field({ label, hint, children, htmlFor }) {
|
|
|
953
1424
|
function CreateDialog({ store, d }) {
|
|
954
1425
|
const s = useStore(store);
|
|
955
1426
|
const a = store.actions;
|
|
956
|
-
const [f, setF] = (0, import_react.useState)({ name: "", description: "", tags: "", public: false, mode: "lan", lanHostPort: "62.234.113.56:80" });
|
|
1427
|
+
const [f, setF] = (0, import_react.useState)({ name: "", description: "", tags: "", public: false, mode: "lan", lanHostPort: "62.234.113.56:80", localOnly: false, agents: [] });
|
|
957
1428
|
const [err, setErr] = (0, import_react.useState)(null);
|
|
958
1429
|
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
959
1430
|
const [lanPeers, setLanPeers] = (0, import_react.useState)([]);
|
|
@@ -976,7 +1447,9 @@ function CreateDialog({ store, d }) {
|
|
|
976
1447
|
mode: f.mode,
|
|
977
1448
|
lanHostPort: f.mode === "lan" ? f.lanHostPort.trim() : void 0,
|
|
978
1449
|
workspacePath: ws.path,
|
|
979
|
-
workspaceName: ws.title
|
|
1450
|
+
workspaceName: ws.title,
|
|
1451
|
+
localOnly: f.localOnly,
|
|
1452
|
+
agents: f.agents
|
|
980
1453
|
});
|
|
981
1454
|
} catch (e) {
|
|
982
1455
|
setErr(e.message);
|
|
@@ -1026,12 +1499,29 @@ function CreateDialog({ store, d }) {
|
|
|
1026
1499
|
] }, p.hostPort))
|
|
1027
1500
|
] })
|
|
1028
1501
|
] }) }) : null,
|
|
1502
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-span-2 rm-local-box", children: [
|
|
1503
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-switch-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Local agents" }),
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "Host several agents from this dsh as separate members (own identity, session, scope). Edit them later in room details." })
|
|
1506
|
+
] }) }),
|
|
1507
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-preset-row", children: [["moderator", "Moderator"], ["architect", "Architect"], ["coder", "Coder"], ["reviewer", "Reviewer"]].map(([k, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "rm-preset rm-preset-check" + (f.agents.includes(k) ? " is-on" : ""), children: [
|
|
1508
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: f.agents.includes(k), onChange: (e) => setF({ ...f, agents: e.target.checked ? [...f.agents, k] : f.agents.filter((x) => x !== k) }) }),
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: label })
|
|
1510
|
+
] }, k)) }),
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-row", children: [
|
|
1512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1513
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Local only (no network)" }),
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "In-process loopback \u2014 nothing leaves this machine. One click to switch to Relay/LAN later." })
|
|
1515
|
+
] }),
|
|
1516
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.localOnly, onChange: (v) => setF({ ...f, localOnly: v, public: v ? false : f.public }), label: "Local only" })
|
|
1517
|
+
] })
|
|
1518
|
+
] }),
|
|
1029
1519
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-span-2 rm-switch-row", children: [
|
|
1030
1520
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1031
1521
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "List in public directory" }),
|
|
1032
1522
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: f.public ? "Anyone can find and join \u2014 key is published with the listing." : "Private: invite only." })
|
|
1033
1523
|
] }),
|
|
1034
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.public, onChange: (v) => setF({ ...f, public: v }), label: "List in public directory" })
|
|
1524
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.public, onChange: (v) => setF({ ...f, public: v, localOnly: v ? false : f.localOnly }), label: "List in public directory" })
|
|
1035
1525
|
] }),
|
|
1036
1526
|
err ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2 rm-error", children: err }) : null
|
|
1037
1527
|
] })
|
|
@@ -1373,6 +1863,8 @@ function Overlay({ store }) {
|
|
|
1373
1863
|
d?.kind === "config" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfigDialog, { store, d }) : null,
|
|
1374
1864
|
d?.kind === "workspace" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceDialog, { store }) : null,
|
|
1375
1865
|
d?.kind === "browse" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BrowseDialog, { store }) : null,
|
|
1866
|
+
d?.kind === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentDialog, { store, d }) : null,
|
|
1867
|
+
d?.kind === "merge" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeDialog, { store, d }) : null,
|
|
1376
1868
|
s.toast ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Toast, { text: s.toast, onDone: store.actions.clearToast, holdMs: 2200 }) : null
|
|
1377
1869
|
] });
|
|
1378
1870
|
}
|
|
@@ -1555,7 +2047,7 @@ var import_react = require("react");
|
|
|
1555
2047
|
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1556
2048
|
|
|
1557
2049
|
// src/client/rooms.css
|
|
1558
|
-
var rooms_default = '/* Collab Rooms UI \u2014 original surface inside the dsh shell. Uses only dsh --dsw-* tokens.\n Independent Rooms surface. Prefix: rm- (rooms). */\n\n.rm-root {\n --rm-accent: var(--dsw-alias-state-business-primary);\n --rm-hover: var(--dsw-alias-interactive-bg-hover);\n --rm-border: var(--dsw-alias-border-l2);\n --rm-bg: var(--dsw-alias-bg-base);\n --rm-panel: var(--dsw-alias-bg-module-platform);\n --rm-label: var(--dsw-alias-label-primary);\n --rm-muted: var(--dsw-alias-label-secondary);\n --rm-quiet: var(--dsw-alias-label-tertiary);\n font: 13px/1.5 var(--dsw-font-family);\n color: var(--rm-label);\n box-sizing: border-box;\n}\n.rm-root *, .rm-root *::before, .rm-root *::after { box-sizing: border-box; }\n.rm-root button, .rm-root input, .rm-root textarea { font: inherit; }\n\n/* \u2500\u2500 sidebar (joined rooms + public search) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-side {\n display: flex; flex-direction: column; height: 100%; min-height: 0;\n padding: 0 8px 8px 0; gap: 8px;\n}\n.rm-side-toolbar {\n display: flex; align-items: center; gap: 6px; flex: none; padding: 4px 0 2px;\n}\n.rm-side-title {\n flex: 1; font-size: 12px; font-weight: 600; letter-spacing: .04em;\n text-transform: uppercase; color: var(--rm-quiet);\n}\n.rm-icon-btn {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; padding: 0;\n}\n.rm-icon-btn:hover { background: var(--rm-hover); color: var(--rm-label); }\n.rm-search {\n display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px;\n border: .5px solid var(--rm-border); border-radius: 8px; background: var(--rm-panel);\n}\n.rm-search input {\n flex: 1; min-width: 0; border: 0; background: transparent; outline: none; color: var(--rm-label); font-size: 13px;\n}\n.rm-search input::placeholder { color: var(--rm-quiet); }\n.rm-side-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 12px; }\n.rm-group-label { font-size: 11px; font-weight: 600; color: var(--rm-quiet); padding: 0 4px 4px; text-transform: uppercase; letter-spacing: .03em; }\n.rm-room-list { display: flex; flex-direction: column; gap: 2px; }\n.rm-room-item {\n display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;\n border: 0; border-radius: 10px; background: transparent; color: inherit; cursor: pointer; text-align: left;\n}\n.rm-room-item:hover { background: var(--rm-hover); }\n.rm-room-item[aria-current="true"] { background: var(--rm-hover); }\n.rm-room-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n.rm-room-item-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-meta { font-size: 11.5px; color: var(--rm-quiet); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-trail { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }\n.rm-badge {\n display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px;\n border-radius: 999px; font-size: 10.5px; font-weight: 500; background: var(--rm-panel); color: var(--rm-muted);\n border: .5px solid var(--rm-border);\n}\n.rm-badge-public { color: var(--rm-accent); border-color: color-mix(in srgb, var(--rm-accent) 35%, transparent); background: color-mix(in srgb, var(--rm-accent) 8%, transparent); }\n.rm-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--rm-quiet); }\n.rm-dot-online { background: var(--dsw-alias-state-success-primary, #2bb673); }\n.rm-dot-connecting { background: var(--dsw-alias-state-warn-primary, #e9a23b); }\n.rm-dot-offline { background: var(--dsw-alias-state-error-primary, #e5484d); }\n.rm-empty-hint { padding: 8px 10px; font-size: 12px; color: var(--rm-quiet); line-height: 1.45; }\n.rm-dir-item {\n display: flex; align-items: flex-start; gap: 10px; padding: 10px; border-radius: 10px;\n border: .5px solid var(--rm-border); background: var(--rm-bg); margin-bottom: 6px;\n}\n.rm-dir-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\n.rm-dir-tags { display: flex; flex-wrap: wrap; gap: 4px; }\n.rm-tag { font-size: 11px; color: var(--rm-muted); background: var(--rm-hover); border-radius: 4px; padding: 0 5px; }\n.rm-menu {\n position: fixed; z-index: 1000; min-width: 180px; padding: 4px;\n border-radius: 10px; background: var(--dsw-alias-bg-layer-1, var(--rm-bg));\n border: .5px solid var(--rm-border);\n box-shadow: 0 8px 24px color-mix(in srgb, var(--rm-label) 12%, transparent);\n display: flex; flex-direction: column;\n}\n.rm-menu button {\n display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-menu button:hover { background: var(--rm-hover); }\n\n/* \u2500\u2500 main: room workspace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-main { display: flex; flex: 1; min-height: 0; height: 100%; width: 100%; background: var(--rm-bg); }\n.rm-workspace { display: flex; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat-header {\n flex: none; display: flex; align-items: center; gap: 10px; height: 48px;\n padding: 0 16px; border-bottom: .5px solid var(--rm-border);\n}\n.rm-chat-header-title { font-size: 14px; font-weight: 600; }\n.rm-chat-header-sub { font-size: 12px; color: var(--rm-quiet); }\n.rm-messages {\n flex: 1; min-height: 0; overflow: auto; padding: 16px 18px 8px;\n display: flex; flex-direction: column; gap: 2px;\n}\n.rm-day {\n align-self: center; margin: 10px 0 12px; padding: 2px 10px; border-radius: 999px;\n font-size: 11px; color: var(--rm-quiet); background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n}\n.rm-msg {\n display: grid; grid-template-columns: 32px 1fr; gap: 0 10px; padding: 4px 6px; border-radius: 8px;\n max-width: 720px;\n}\n.rm-msg:hover { background: color-mix(in srgb, var(--rm-hover) 60%, transparent); }\n.rm-msg-self { margin-left: auto; grid-template-columns: 1fr; max-width: 640px; }\n.rm-msg-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 1px; }\n.rm-msg-author { font-size: 12px; font-weight: 600; color: var(--rm-muted); }\n.rm-msg-time { font-size: 11px; color: var(--rm-quiet); }\n.rm-msg-body { font-size: 13.5px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }\n.rm-msg-self .rm-msg-body {\n background: var(--dsw-alias-label-primary); color: var(--dsw-alias-label-primary-foreground);\n padding: 8px 12px; border-radius: 12px 12px 4px 12px; width: fit-content; margin-left: auto;\n}\n.rm-msg-event {\n grid-template-columns: 1fr; max-width: 560px; margin: 6px 0;\n padding: 8px 12px; border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-panel);\n}\n.rm-mention { color: var(--rm-accent); font-weight: 500; }\n.rm-msg-self .rm-mention { color: inherit; text-decoration: underline; text-underline-offset: 2px; }\n.rm-task-card { display: flex; flex-direction: column; gap: 4px; }\n.rm-task-head { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--rm-muted); }\n.rm-task-title { font-weight: 600; font-size: 13.5px; }\n.rm-composer {\n flex: none; display: flex; align-items: flex-end; gap: 8px; padding: 10px 16px 14px;\n border-top: .5px solid var(--rm-border);\n}\n.rm-composer-box {\n flex: 1; display: flex; align-items: flex-end; gap: 6px; min-height: 44px;\n padding: 8px 10px; border: .5px solid var(--rm-border); border-radius: 12px; background: var(--rm-panel);\n}\n.rm-composer-box:focus-within { border-color: color-mix(in srgb, var(--rm-accent) 50%, var(--rm-border)); }\n.rm-composer-box textarea {\n flex: 1; min-height: 28px; max-height: 120px; border: 0; background: transparent; outline: none;\n resize: none; color: var(--rm-label); line-height: 1.45;\n}\n.rm-composer-box textarea::placeholder { color: var(--rm-quiet); }\n.rm-composer-mode {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; flex: none;\n}\n.rm-composer-mode:hover, .rm-composer-mode[aria-pressed="true"] {\n color: var(--rm-accent); background: color-mix(in srgb, var(--rm-accent) 12%, transparent);\n}\n.rm-chat-hint { margin: 48px auto; text-align: center; color: var(--rm-quiet); font-size: 13px; max-width: 360px; line-height: 1.5; }\n\n/* \u2500\u2500 detail column (members / invite / about) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-detail {\n flex: 0 0 280px; width: 280px; display: flex; flex-direction: column; min-height: 0;\n border-left: .5px solid var(--rm-border); background: var(--rm-bg); overflow: auto;\n}\n.rm-detail-section { padding: 14px 14px 8px; border-bottom: .5px solid var(--rm-border); }\n.rm-detail-section:last-child { border-bottom: 0; }\n.rm-detail-h {\n display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600;\n text-transform: uppercase; letter-spacing: .04em; color: var(--rm-quiet); margin-bottom: 8px;\n}\n.rm-member {\n display: flex; align-items: center; gap: 8px; padding: 5px 4px; border-radius: 8px; min-height: 34px;\n}\n.rm-member:hover { background: var(--rm-hover); }\n.rm-member-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }\n.rm-member-actions { display: none; gap: 2px; }\n.rm-member:hover .rm-member-actions, .rm-member:focus-within .rm-member-actions { display: inline-flex; }\n.rm-mini {\n width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-muted); cursor: pointer; font-size: 12px;\n}\n.rm-mini:hover { background: var(--dsw-alias-interactive-bg-active); color: var(--rm-label); }\n.rm-task-row { display: flex; align-items: center; gap: 6px; padding: 4px; font-size: 12.5px; }\n.rm-task-row-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-about { display: grid; grid-template-columns: 88px 1fr; gap: 6px 8px; font-size: 12.5px; margin: 0; }\n.rm-about dt { color: var(--rm-quiet); margin: 0; }\n.rm-about dd { margin: 0; min-width: 0; overflow-wrap: anywhere; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }\n.rm-mono { font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace); font-size: 11.5px; }\n.rm-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }\n.rm-danger { color: var(--dsw-alias-state-error-primary, #e5484d) !important; }\n.rm-note { font-size: 12px; color: var(--rm-quiet); line-height: 1.45; margin: 0 0 8px; }\n\n/* \u2500\u2500 empty / welcome \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-welcome-wrap {\n flex: 1; display: flex; align-items: center; justify-content: center; padding: 32px; background: var(--rm-bg);\n}\n.rm-welcome {\n width: min(420px, 100%); display: flex; flex-direction: column; gap: 10px;\n padding: 20px; border-radius: 14px; border: .5px solid var(--rm-border); background: var(--rm-panel);\n}\n.rm-welcome h1 { margin: 0; font-size: 16px; font-weight: 600; }\n.rm-welcome p { margin: 0; font-size: 13px; color: var(--rm-muted); line-height: 1.5; }\n.rm-welcome-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }\n.rm-welcome-action {\n display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 10px 12px;\n border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-bg);\n color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-welcome-action:hover { background: var(--rm-hover); }\n.rm-welcome-action b { display: block; font-size: 13px; }\n.rm-welcome-action span { display: block; font-size: 12px; color: var(--rm-quiet); margin-top: 2px; }\n\n/* \u2500\u2500 avatars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-avatar {\n display: inline-flex; align-items: center; justify-content: center; flex: none;\n font-weight: 600; letter-spacing: .02em; user-select: none;\n}\n.rm-avatar-wrap { position: relative; display: inline-flex; flex: none; }\n\n/* \u2500\u2500 dialogs (inside dsh Modal) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-form { display: flex; flex-direction: column; gap: 14px; }\n.rm-field { display: flex; flex-direction: column; gap: 6px; }\n.rm-field-label { font-size: 13px; font-weight: 500; }\n.rm-field-hint { font-size: 12px; color: var(--rm-quiet); }\n.rm-name-row { display: flex; align-items: center; gap: 10px; }\n.rm-name-row > :last-child { flex: 1; }\n.rm-switch-row {\n display: flex; align-items: center; justify-content: space-between; gap: 14px;\n padding: 10px 12px; border-radius: 10px; background: var(--rm-panel);\n}\n.rm-error { color: var(--dsw-alias-state-error-primary, #e5484d); font-size: 12.5px; }\n.rm-invite {\n display: block; padding: 10px 12px; border-radius: 8px; background: var(--rm-panel);\n font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace);\n font-size: 12px; word-break: break-all; user-select: all;\n}\n\n/* Dual transport + approvals + agent config */\n.rm-mode-row { display: flex; gap: 8px; }\n.rm-mode-btn {\n flex: 1; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer; font: inherit;\n}\n.rm-mode-btn.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent); }\n.rm-lan-browse { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; align-items: center; }\n.rm-lan-peer {\n font-size: 12px; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer;\n}\n.rm-approvals { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); background: color-mix(in srgb, #f5a524 12%, transparent); }\n.rm-approval { display: flex; gap: 12px; align-items: center; justify-content: space-between; }\n.rm-approval-body { font-size: 13px; }\n.rm-approval-actions { display: flex; gap: 6px; flex-shrink: 0; }\n.rm-input { width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; font: inherit; }\n\n.rm-ws-bar { display: flex; flex-direction: column; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); }\n.rm-ws-chip { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; cursor: pointer; font: inherit; font-size: 12.5px; }\n.rm-ws-path { font-size: 11px; color: var(--rm-quiet, #8b93a7); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item.is-active { background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); }\n\n/* Native-aligned room composer (mirrors dsh conversation control row) */\n.rm-composer-card {\n box-sizing: border-box;\n width: 100%;\n max-width: 920px;\n margin: 0 auto;\n border-radius: 16px;\n background: var(--rm-elev, var(--rm-panel, #12151c));\n border: 1px solid var(--rm-border, #2a2f3a);\n box-shadow: 0 1px 2px rgba(0,0,0,.06);\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 0 6px;\n}\n.rm-composer-grow { position: relative; padding: 0 4px; }\n.rm-composer-grow textarea {\n box-sizing: border-box; width: 100%; min-height: 36px; max-height: 160px;\n resize: none; border: none; outline: none; background: transparent;\n color: inherit; font: inherit; font-size: 14px; line-height: 22px;\n padding: 4px 12px 0 14px;\n}\n.rm-composer-grow textarea:disabled { opacity: .55; cursor: not-allowed; }\n.rm-composer-row {\n display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;\n gap: 10px; min-width: 0; padding: 2px 8px 4px;\n}\n.rm-composer-tools, .rm-composer-modes, .rm-composer-trailing {\n display: flex; align-items: center; min-width: 0; gap: 8px;\n}\n.rm-composer-trailing { flex: none; margin-left: auto; }\n.rm-composer-add {\n width: 28px; height: 28px; border: none; border-radius: 999px;\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n color: inherit; cursor: pointer; display: grid; place-items: center;\n}\n.rm-composer-add:hover, .rm-composer-add[aria-pressed="true"] {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 22%, transparent);\n}\n.rm-composer-select {\n max-width: 220px; height: 28px; border: none; border-radius: 8px;\n background: transparent; color: var(--rm-quiet, #8b93a7);\n font: inherit; font-size: 13px; font-weight: 500; line-height: 20px;\n padding: 0 8px; cursor: pointer; white-space: nowrap;\n}\n.rm-composer-select:hover:not(:disabled) {\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n}\n.rm-composer-select:disabled { opacity: .5; cursor: default; }\n.rm-composer-model-text { display: inline; }\n.rm-composer-model-icon { display: none; font-size: 10px; }\n.rm-composer-effort {\n margin-left: 6px; font-size: 11px; opacity: .75;\n text-transform: uppercase; letter-spacing: .02em;\n}\n.rm-composer-send {\n width: 34px; height: 34px; border: none; border-radius: 999px;\n background: var(--rm-accent, #5b8cff); color: #fff; cursor: pointer;\n display: grid; place-items: center; transform: translateY(-2px);\n}\n.rm-composer-send:hover:not(:disabled) { filter: brightness(1.08); }\n.rm-composer-send:disabled { opacity: .4; cursor: default; }\n.rm-composer-popwrap { position: relative; }\n.rm-composer-menu {\n position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 40;\n min-width: 200px; max-height: 320px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 8px 24px rgba(0,0,0,.28);\n padding: 6px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-composer-menu-wide { min-width: 280px; max-width: 340px; }\n.rm-composer-menu-label {\n font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;\n color: var(--rm-quiet, #8b93a7); padding: 6px 8px 2px;\n}\n.rm-composer-menu button[role="menuitem"] {\n text-align: left; border: none; background: transparent; color: inherit;\n font: inherit; font-size: 13px; padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-composer-menu button[role="menuitem"]:hover,\n.rm-composer-menu button[role="menuitem"].is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent);\n}\n.rm-composer-check {\n display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 4px 8px; cursor: pointer;\n}\n.rm-grant-row {\n display: flex; align-items: center; justify-content: space-between; gap: 8px;\n padding: 2px 8px; font-size: 12.5px;\n}\n.rm-grant-row select {\n font: inherit; font-size: 12px; border-radius: 6px;\n border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; padding: 2px 6px;\n}\n.rm-peer-grant-block { border-top: 1px solid var(--rm-border, #2a2f3a); padding-top: 4px; margin-top: 4px; }\n.rm-peer-grant-name { font-size: 12px; font-weight: 600; padding: 4px 8px; overflow: hidden; text-overflow: ellipsis; }\n\n/* Hide legacy tight composer if still referenced */\n.rm-composer { display: none; }\n\n.rm-composer-grow { position: relative; }\n.rm-mention-menu {\n position: absolute; left: 8px; right: 8px; bottom: calc(100% + 6px); z-index: 50;\n max-height: 240px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 10px 28px rgba(0,0,0,.32);\n padding: 4px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-mention-item {\n display: flex; align-items: center; gap: 8px; text-align: left;\n border: none; background: transparent; color: inherit; font: inherit;\n padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-mention-item:hover, .rm-mention-item.is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 18%, transparent);\n}\n.rm-mention-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }\n.rm-mention-item-name { font-size: 13px; font-weight: 600; }\n.rm-mention-item-meta { font-size: 11px; color: var(--rm-quiet, #8b93a7); }\n\n\n/* New Room shortcut under workspace (mirrors New Session affordance) */\n.rm-new-room {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n width: 100%; height: 36px; margin-top: 8px;\n border: .5px solid var(--rm-border); border-radius: 10px;\n background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n color: var(--rm-label); cursor: pointer; font-weight: 500; font-size: 13.5px;\n}\n.rm-new-room:hover { background: var(--dsw-alias-button-floating-hover, var(--rm-hover)); }\n.rm-new-room svg { flex: none; }\n\n/* Wide / landscape create + browse modals (overrides default 380px Modal card) */\n.rm-modal-wide {\n width: min(720px, calc(100vw - 48px)) !important;\n max-height: min(640px, calc(100vh - 48px));\n}\n.rm-form-wide {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n align-items: start;\n}\n.rm-form-wide .rm-span-2 { grid-column: 1 / -1; }\n.rm-browse { display: flex; flex-direction: column; gap: 12px; min-height: 280px; max-height: 420px; }\n.rm-browse-search { flex: none; }\n.rm-browse-status { font-size: 11.5px; color: var(--rm-quiet); white-space: nowrap; }\n.rm-browse-list { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 6px; }\n@media (max-width: 640px) {\n .rm-form-wide { grid-template-columns: 1fr; }\n .rm-modal-wide { width: min(420px, calc(100vw - 32px)) !important; }\n}\n\n\n/* \u2500\u2500 panel layout: rooms nav (grouped by native dsh workspace) + content \u2500\u2500 */\n.rm-main { flex-direction: row; }\n.rm-main-body { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-main-body > .rm-welcome-wrap { flex: 1; }\n.rm-main-body > .rm-workspace { flex: 1; }\n.rm-nav {\n flex: 0 0 248px; width: 248px; display: flex; flex-direction: column; gap: 8px; min-height: 0;\n padding: 10px 8px; border-right: .5px solid var(--rm-border); background: var(--rm-bg);\n}\n.rm-nav-head { display: flex; align-items: center; gap: 4px; padding: 0 4px; }\n.rm-nav-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 10px; }\n.rm-ws-group { display: flex; flex-direction: column; gap: 2px; }\n.rm-ws-head {\n display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 2px 0 8px;\n font-size: 12.5px; font-weight: 600; color: var(--rm-muted);\n}\n.rm-ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-ws-add { width: 24px; height: 24px; }\n.rm-ws-empty { padding: 2px 10px 6px 30px; font-size: 11.5px; }\n.rm-nav .rm-room-item { padding: 6px 8px 6px 14px; }\n.rm-session-mark { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; color: var(--rm-accent, var(--dsw-alias-state-business-primary)); }\n';
|
|
2050
|
+
var rooms_default = '/* Collab Rooms UI \u2014 original surface inside the dsh shell. Uses only dsh --dsw-* tokens.\n Independent Rooms surface. Prefix: rm- (rooms). */\n\n.rm-root {\n --rm-accent: var(--dsw-alias-state-business-primary);\n --rm-hover: var(--dsw-alias-interactive-bg-hover);\n --rm-border: var(--dsw-alias-border-l2);\n --rm-bg: var(--dsw-alias-bg-base);\n --rm-panel: var(--dsw-alias-bg-module-platform);\n --rm-label: var(--dsw-alias-label-primary);\n --rm-muted: var(--dsw-alias-label-secondary);\n --rm-quiet: var(--dsw-alias-label-tertiary);\n font: 13px/1.5 var(--dsw-font-family);\n color: var(--rm-label);\n box-sizing: border-box;\n}\n.rm-root *, .rm-root *::before, .rm-root *::after { box-sizing: border-box; }\n.rm-root button, .rm-root input, .rm-root textarea { font: inherit; }\n\n/* \u2500\u2500 sidebar (joined rooms + public search) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-side {\n display: flex; flex-direction: column; height: 100%; min-height: 0;\n padding: 0 8px 8px 0; gap: 8px;\n}\n.rm-side-toolbar {\n display: flex; align-items: center; gap: 6px; flex: none; padding: 4px 0 2px;\n}\n.rm-side-title {\n flex: 1; font-size: 12px; font-weight: 600; letter-spacing: .04em;\n text-transform: uppercase; color: var(--rm-quiet);\n}\n.rm-icon-btn {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; padding: 0;\n}\n.rm-icon-btn:hover { background: var(--rm-hover); color: var(--rm-label); }\n.rm-search {\n display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px;\n border: .5px solid var(--rm-border); border-radius: 8px; background: var(--rm-panel);\n}\n.rm-search input {\n flex: 1; min-width: 0; border: 0; background: transparent; outline: none; color: var(--rm-label); font-size: 13px;\n}\n.rm-search input::placeholder { color: var(--rm-quiet); }\n.rm-side-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 12px; }\n.rm-group-label { font-size: 11px; font-weight: 600; color: var(--rm-quiet); padding: 0 4px 4px; text-transform: uppercase; letter-spacing: .03em; }\n.rm-room-list { display: flex; flex-direction: column; gap: 2px; }\n.rm-room-item {\n display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;\n border: 0; border-radius: 10px; background: transparent; color: inherit; cursor: pointer; text-align: left;\n}\n.rm-room-item:hover { background: var(--rm-hover); }\n.rm-room-item[aria-current="true"] { background: var(--rm-hover); }\n.rm-room-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n.rm-room-item-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-meta { font-size: 11.5px; color: var(--rm-quiet); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item-trail { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }\n.rm-badge {\n display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px;\n border-radius: 999px; font-size: 10.5px; font-weight: 500; background: var(--rm-panel); color: var(--rm-muted);\n border: .5px solid var(--rm-border);\n}\n.rm-badge-public { color: var(--rm-accent); border-color: color-mix(in srgb, var(--rm-accent) 35%, transparent); background: color-mix(in srgb, var(--rm-accent) 8%, transparent); }\n.rm-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--rm-quiet); }\n.rm-dot-online { background: var(--dsw-alias-state-success-primary, #2bb673); }\n.rm-dot-connecting { background: var(--dsw-alias-state-warn-primary, #e9a23b); }\n.rm-dot-offline { background: var(--dsw-alias-state-error-primary, #e5484d); }\n.rm-empty-hint { padding: 8px 10px; font-size: 12px; color: var(--rm-quiet); line-height: 1.45; }\n.rm-dir-item {\n display: flex; align-items: flex-start; gap: 10px; padding: 10px; border-radius: 10px;\n border: .5px solid var(--rm-border); background: var(--rm-bg); margin-bottom: 6px;\n}\n.rm-dir-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\n.rm-dir-tags { display: flex; flex-wrap: wrap; gap: 4px; }\n.rm-tag { font-size: 11px; color: var(--rm-muted); background: var(--rm-hover); border-radius: 4px; padding: 0 5px; }\n.rm-menu {\n position: fixed; z-index: 1000; min-width: 180px; padding: 4px;\n border-radius: 10px; background: var(--dsw-alias-bg-layer-1, var(--rm-bg));\n border: .5px solid var(--rm-border);\n box-shadow: 0 8px 24px color-mix(in srgb, var(--rm-label) 12%, transparent);\n display: flex; flex-direction: column;\n}\n.rm-menu button {\n display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-menu button:hover { background: var(--rm-hover); }\n\n/* \u2500\u2500 main: room workspace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-main { display: flex; flex: 1; min-height: 0; height: 100%; width: 100%; background: var(--rm-bg); }\n.rm-workspace { display: flex; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-chat-header {\n flex: none; display: flex; align-items: center; gap: 10px; height: 48px;\n padding: 0 16px; border-bottom: .5px solid var(--rm-border);\n}\n.rm-chat-header-title { font-size: 14px; font-weight: 600; }\n.rm-chat-header-sub { font-size: 12px; color: var(--rm-quiet); }\n.rm-messages {\n flex: 1; min-height: 0; overflow: auto; padding: 16px 18px 8px;\n display: flex; flex-direction: column; gap: 2px;\n}\n.rm-day {\n align-self: center; margin: 10px 0 12px; padding: 2px 10px; border-radius: 999px;\n font-size: 11px; color: var(--rm-quiet); background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n}\n.rm-msg {\n display: grid; grid-template-columns: 32px 1fr; gap: 0 10px; padding: 4px 6px; border-radius: 8px;\n max-width: 720px;\n}\n.rm-msg:hover { background: color-mix(in srgb, var(--rm-hover) 60%, transparent); }\n.rm-msg-self { margin-left: auto; grid-template-columns: 1fr; max-width: 640px; }\n.rm-msg-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 1px; }\n.rm-msg-author { font-size: 12px; font-weight: 600; color: var(--rm-muted); }\n.rm-msg-time { font-size: 11px; color: var(--rm-quiet); }\n.rm-msg-body { font-size: 13.5px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }\n.rm-msg-self .rm-msg-body {\n background: var(--dsw-alias-label-primary); color: var(--dsw-alias-label-primary-foreground);\n padding: 8px 12px; border-radius: 12px 12px 4px 12px; width: fit-content; margin-left: auto;\n}\n.rm-msg-event {\n grid-template-columns: 1fr; max-width: 560px; margin: 6px 0;\n padding: 8px 12px; border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-panel);\n}\n.rm-mention { color: var(--rm-accent); font-weight: 500; }\n.rm-msg-self .rm-mention { color: inherit; text-decoration: underline; text-underline-offset: 2px; }\n.rm-task-card { display: flex; flex-direction: column; gap: 4px; }\n.rm-task-head { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--rm-muted); }\n.rm-task-title { font-weight: 600; font-size: 13.5px; }\n.rm-composer {\n flex: none; display: flex; align-items: flex-end; gap: 8px; padding: 10px 16px 14px;\n border-top: .5px solid var(--rm-border);\n}\n.rm-composer-box {\n flex: 1; display: flex; align-items: flex-end; gap: 6px; min-height: 44px;\n padding: 8px 10px; border: .5px solid var(--rm-border); border-radius: 12px; background: var(--rm-panel);\n}\n.rm-composer-box:focus-within { border-color: color-mix(in srgb, var(--rm-accent) 50%, var(--rm-border)); }\n.rm-composer-box textarea {\n flex: 1; min-height: 28px; max-height: 120px; border: 0; background: transparent; outline: none;\n resize: none; color: var(--rm-label); line-height: 1.45;\n}\n.rm-composer-box textarea::placeholder { color: var(--rm-quiet); }\n.rm-composer-mode {\n width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px; background: transparent; color: var(--rm-muted); cursor: pointer; flex: none;\n}\n.rm-composer-mode:hover, .rm-composer-mode[aria-pressed="true"] {\n color: var(--rm-accent); background: color-mix(in srgb, var(--rm-accent) 12%, transparent);\n}\n.rm-chat-hint { margin: 48px auto; text-align: center; color: var(--rm-quiet); font-size: 13px; max-width: 360px; line-height: 1.5; }\n\n/* \u2500\u2500 detail column (members / invite / about) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-detail {\n flex: 0 0 280px; width: 280px; display: flex; flex-direction: column; min-height: 0;\n border-left: .5px solid var(--rm-border); background: var(--rm-bg); overflow: auto;\n}\n.rm-detail-section { padding: 14px 14px 8px; border-bottom: .5px solid var(--rm-border); }\n.rm-detail-section:last-child { border-bottom: 0; }\n.rm-detail-h {\n display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600;\n text-transform: uppercase; letter-spacing: .04em; color: var(--rm-quiet); margin-bottom: 8px;\n}\n.rm-member {\n display: flex; align-items: center; gap: 8px; padding: 5px 4px; border-radius: 8px; min-height: 34px;\n}\n.rm-member:hover { background: var(--rm-hover); }\n.rm-member-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }\n.rm-member-actions { display: none; gap: 2px; }\n.rm-member:hover .rm-member-actions, .rm-member:focus-within .rm-member-actions { display: inline-flex; }\n.rm-mini {\n width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 6px; background: transparent; color: var(--rm-muted); cursor: pointer; font-size: 12px;\n}\n.rm-mini:hover { background: var(--dsw-alias-interactive-bg-active); color: var(--rm-label); }\n.rm-task-row { display: flex; align-items: center; gap: 6px; padding: 4px; font-size: 12.5px; }\n.rm-task-row-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-about { display: grid; grid-template-columns: 88px 1fr; gap: 6px 8px; font-size: 12.5px; margin: 0; }\n.rm-about dt { color: var(--rm-quiet); margin: 0; }\n.rm-about dd { margin: 0; min-width: 0; overflow-wrap: anywhere; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }\n.rm-mono { font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace); font-size: 11.5px; }\n.rm-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }\n.rm-danger { color: var(--dsw-alias-state-error-primary, #e5484d) !important; }\n.rm-note { font-size: 12px; color: var(--rm-quiet); line-height: 1.45; margin: 0 0 8px; }\n\n/* \u2500\u2500 empty / welcome \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-welcome-wrap {\n flex: 1; display: flex; align-items: center; justify-content: center; padding: 32px; background: var(--rm-bg);\n}\n.rm-welcome {\n width: min(420px, 100%); display: flex; flex-direction: column; gap: 10px;\n padding: 20px; border-radius: 14px; border: .5px solid var(--rm-border); background: var(--rm-panel);\n}\n.rm-welcome h1 { margin: 0; font-size: 16px; font-weight: 600; }\n.rm-welcome p { margin: 0; font-size: 13px; color: var(--rm-muted); line-height: 1.5; }\n.rm-welcome-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }\n.rm-welcome-action {\n display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 10px 12px;\n border: .5px solid var(--rm-border); border-radius: 10px; background: var(--rm-bg);\n color: var(--rm-label); cursor: pointer; text-align: left;\n}\n.rm-welcome-action:hover { background: var(--rm-hover); }\n.rm-welcome-action b { display: block; font-size: 13px; }\n.rm-welcome-action span { display: block; font-size: 12px; color: var(--rm-quiet); margin-top: 2px; }\n\n/* \u2500\u2500 avatars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-avatar {\n display: inline-flex; align-items: center; justify-content: center; flex: none;\n font-weight: 600; letter-spacing: .02em; user-select: none;\n}\n.rm-avatar-wrap { position: relative; display: inline-flex; flex: none; }\n\n/* \u2500\u2500 dialogs (inside dsh Modal) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-form { display: flex; flex-direction: column; gap: 14px; }\n.rm-field { display: flex; flex-direction: column; gap: 6px; }\n.rm-field-label { font-size: 13px; font-weight: 500; }\n.rm-field-hint { font-size: 12px; color: var(--rm-quiet); }\n.rm-name-row { display: flex; align-items: center; gap: 10px; }\n.rm-name-row > :last-child { flex: 1; }\n.rm-switch-row {\n display: flex; align-items: center; justify-content: space-between; gap: 14px;\n padding: 10px 12px; border-radius: 10px; background: var(--rm-panel);\n}\n.rm-error { color: var(--dsw-alias-state-error-primary, #e5484d); font-size: 12.5px; }\n.rm-invite {\n display: block; padding: 10px 12px; border-radius: 8px; background: var(--rm-panel);\n font-family: var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace);\n font-size: 12px; word-break: break-all; user-select: all;\n}\n\n/* Dual transport + approvals + agent config */\n.rm-mode-row { display: flex; gap: 8px; }\n.rm-mode-btn {\n flex: 1; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer; font: inherit;\n}\n.rm-mode-btn.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent); }\n.rm-lan-browse { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; align-items: center; }\n.rm-lan-peer {\n font-size: 12px; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a);\n background: transparent; color: inherit; cursor: pointer;\n}\n.rm-approvals { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); background: color-mix(in srgb, #f5a524 12%, transparent); }\n.rm-approval { display: flex; gap: 12px; align-items: center; justify-content: space-between; }\n.rm-approval-body { font-size: 13px; }\n.rm-approval-actions { display: flex; gap: 6px; flex-shrink: 0; }\n.rm-input { width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; font: inherit; }\n\n.rm-ws-bar { display: flex; flex-direction: column; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--rm-border, #2a2f3a); }\n.rm-ws-chip { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; cursor: pointer; font: inherit; font-size: 12.5px; }\n.rm-ws-path { font-size: 11px; color: var(--rm-quiet, #8b93a7); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-room-item.is-active { background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); }\n\n/* Native-aligned room composer (mirrors dsh conversation control row) */\n.rm-composer-card {\n box-sizing: border-box;\n width: 100%;\n max-width: 920px;\n margin: 0 auto;\n border-radius: 16px;\n background: var(--rm-elev, var(--rm-panel, #12151c));\n border: 1px solid var(--rm-border, #2a2f3a);\n box-shadow: 0 1px 2px rgba(0,0,0,.06);\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 0 6px;\n}\n.rm-composer-grow { position: relative; padding: 0 4px; }\n.rm-composer-grow textarea {\n box-sizing: border-box; width: 100%; min-height: 36px; max-height: 160px;\n resize: none; border: none; outline: none; background: transparent;\n color: inherit; font: inherit; font-size: 14px; line-height: 22px;\n padding: 4px 12px 0 14px;\n}\n.rm-composer-grow textarea:disabled { opacity: .55; cursor: not-allowed; }\n.rm-composer-row {\n display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;\n gap: 10px; min-width: 0; padding: 2px 8px 4px;\n}\n.rm-composer-tools, .rm-composer-modes, .rm-composer-trailing {\n display: flex; align-items: center; min-width: 0; gap: 8px;\n}\n.rm-composer-trailing { flex: none; margin-left: auto; }\n.rm-composer-add {\n width: 28px; height: 28px; border: none; border-radius: 999px;\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n color: inherit; cursor: pointer; display: grid; place-items: center;\n}\n.rm-composer-add:hover, .rm-composer-add[aria-pressed="true"] {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 22%, transparent);\n}\n.rm-composer-select {\n max-width: 220px; height: 28px; border: none; border-radius: 8px;\n background: transparent; color: var(--rm-quiet, #8b93a7);\n font: inherit; font-size: 13px; font-weight: 500; line-height: 20px;\n padding: 0 8px; cursor: pointer; white-space: nowrap;\n}\n.rm-composer-select:hover:not(:disabled) {\n background: color-mix(in srgb, var(--rm-fg, #e8eaed) 8%, transparent);\n}\n.rm-composer-select:disabled { opacity: .5; cursor: default; }\n.rm-composer-model-text { display: inline; }\n.rm-composer-model-icon { display: none; font-size: 10px; }\n.rm-composer-effort {\n margin-left: 6px; font-size: 11px; opacity: .75;\n text-transform: uppercase; letter-spacing: .02em;\n}\n.rm-composer-send {\n width: 34px; height: 34px; border: none; border-radius: 999px;\n background: var(--rm-accent, #5b8cff); color: #fff; cursor: pointer;\n display: grid; place-items: center; transform: translateY(-2px);\n}\n.rm-composer-send:hover:not(:disabled) { filter: brightness(1.08); }\n.rm-composer-send:disabled { opacity: .4; cursor: default; }\n.rm-composer-popwrap { position: relative; }\n.rm-composer-menu {\n position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 40;\n min-width: 200px; max-height: 320px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 8px 24px rgba(0,0,0,.28);\n padding: 6px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-composer-menu-wide { min-width: 280px; max-width: 340px; }\n.rm-composer-menu-label {\n font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;\n color: var(--rm-quiet, #8b93a7); padding: 6px 8px 2px;\n}\n.rm-composer-menu button[role="menuitem"] {\n text-align: left; border: none; background: transparent; color: inherit;\n font: inherit; font-size: 13px; padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-composer-menu button[role="menuitem"]:hover,\n.rm-composer-menu button[role="menuitem"].is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 16%, transparent);\n}\n.rm-composer-check {\n display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 4px 8px; cursor: pointer;\n}\n.rm-grant-row {\n display: flex; align-items: center; justify-content: space-between; gap: 8px;\n padding: 2px 8px; font-size: 12.5px;\n}\n.rm-grant-row select {\n font: inherit; font-size: 12px; border-radius: 6px;\n border: 1px solid var(--rm-border, #2a2f3a); background: transparent; color: inherit; padding: 2px 6px;\n}\n.rm-peer-grant-block { border-top: 1px solid var(--rm-border, #2a2f3a); padding-top: 4px; margin-top: 4px; }\n.rm-peer-grant-name { font-size: 12px; font-weight: 600; padding: 4px 8px; overflow: hidden; text-overflow: ellipsis; }\n\n/* Hide legacy tight composer if still referenced */\n.rm-composer { display: none; }\n\n.rm-composer-grow { position: relative; }\n.rm-mention-menu {\n position: absolute; left: 8px; right: 8px; bottom: calc(100% + 6px); z-index: 50;\n max-height: 240px; overflow: auto;\n border: 1px solid var(--rm-border, #2a2f3a); border-radius: 12px;\n background: var(--rm-elev, #12151c); box-shadow: 0 10px 28px rgba(0,0,0,.32);\n padding: 4px; display: flex; flex-direction: column; gap: 2px;\n}\n.rm-mention-item {\n display: flex; align-items: center; gap: 8px; text-align: left;\n border: none; background: transparent; color: inherit; font: inherit;\n padding: 6px 8px; border-radius: 8px; cursor: pointer;\n}\n.rm-mention-item:hover, .rm-mention-item.is-active {\n background: color-mix(in srgb, var(--rm-accent, #5b8cff) 18%, transparent);\n}\n.rm-mention-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }\n.rm-mention-item-name { font-size: 13px; font-weight: 600; }\n.rm-mention-item-meta { font-size: 11px; color: var(--rm-quiet, #8b93a7); }\n\n\n/* New Room shortcut under workspace (mirrors New Session affordance) */\n.rm-new-room {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n width: 100%; height: 36px; margin-top: 8px;\n border: .5px solid var(--rm-border); border-radius: 10px;\n background: var(--dsw-alias-button-elevated-fill, var(--rm-panel));\n color: var(--rm-label); cursor: pointer; font-weight: 500; font-size: 13.5px;\n}\n.rm-new-room:hover { background: var(--dsw-alias-button-floating-hover, var(--rm-hover)); }\n.rm-new-room svg { flex: none; }\n\n/* Wide / landscape create + browse modals (overrides default 380px Modal card) */\n.rm-modal-wide {\n width: min(720px, calc(100vw - 48px)) !important;\n max-height: min(640px, calc(100vh - 48px));\n}\n.rm-form-wide {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n align-items: start;\n}\n.rm-form-wide .rm-span-2 { grid-column: 1 / -1; }\n.rm-browse { display: flex; flex-direction: column; gap: 12px; min-height: 280px; max-height: 420px; }\n.rm-browse-search { flex: none; }\n.rm-browse-status { font-size: 11.5px; color: var(--rm-quiet); white-space: nowrap; }\n.rm-browse-list { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 6px; }\n@media (max-width: 640px) {\n .rm-form-wide { grid-template-columns: 1fr; }\n .rm-modal-wide { width: min(420px, calc(100vw - 32px)) !important; }\n}\n\n\n/* \u2500\u2500 panel layout: rooms nav (grouped by native dsh workspace) + content \u2500\u2500 */\n.rm-main { flex-direction: row; }\n.rm-main-body { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }\n.rm-main-body > .rm-welcome-wrap { flex: 1; }\n.rm-main-body > .rm-workspace { flex: 1; }\n.rm-nav {\n flex: 0 0 248px; width: 248px; display: flex; flex-direction: column; gap: 8px; min-height: 0;\n padding: 10px 8px; border-right: .5px solid var(--rm-border); background: var(--rm-bg);\n}\n.rm-nav-head { display: flex; align-items: center; gap: 4px; padding: 0 4px; }\n.rm-nav-scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 10px; }\n.rm-ws-group { display: flex; flex-direction: column; gap: 2px; }\n.rm-ws-head {\n display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 2px 0 8px;\n font-size: 12.5px; font-weight: 600; color: var(--rm-muted);\n}\n.rm-ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.rm-ws-add { width: 24px; height: 24px; }\n.rm-ws-empty { padding: 2px 10px 6px 30px; font-size: 11.5px; }\n.rm-nav .rm-room-item { padding: 6px 8px 6px 14px; }\n.rm-session-mark { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; color: var(--rm-accent, var(--dsw-alias-state-business-primary)); }\n\n/* \u2500\u2500 local multi-agent (0.3) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rm-dot-busy { background: var(--dsw-alias-state-warning-primary, #f0a020); }\n.rm-agent-tag { display: inline-flex; align-items: center; gap: 3px; margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 10.5px; line-height: 17px; color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); white-space: nowrap; }\n.rm-msg-id { margin-left: 6px; font-size: 11px; color: var(--rm-quiet); font-family: var(--dsw-font-mono, ui-monospace, monospace); }\n.rm-agent-row { display: flex; align-items: center; gap: 8px; padding: 6px 4px; border-radius: 8px; }\n.rm-agent-row:hover { background: var(--rm-hover); }\n.rm-agent-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }\n.rm-agent-name { font-size: 13px; font-weight: 600; color: var(--rm-label); display: flex; align-items: center; }\n.rm-agent-sub { font-size: 11px; color: var(--rm-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.rm-agent-row .rm-member-actions { display: inline-flex !important; opacity: 0.65; }\n.rm-agent-row:hover .rm-member-actions { opacity: 1; }\n.rm-num-row { display: flex; gap: 8px; margin: 4px 0 8px; }\n.rm-num-setting { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--rm-muted); }\n.rm-num-setting input { width: 100%; box-sizing: border-box; padding: 5px 8px; border: 1px solid var(--rm-border); border-radius: 7px; background: var(--rm-bg); color: var(--rm-label); font: inherit; font-size: 13px; }\n.rm-runs { display: flex; flex-direction: column; gap: 4px; }\n.rm-run { display: grid; grid-template-columns: 22px auto 1fr auto; align-items: center; gap: 6px; padding: 5px 6px; border-radius: 7px; font-size: 12px; border: 1px solid var(--rm-border); }\n.rm-run-running { border-color: color-mix(in srgb, var(--dsw-alias-state-warning-primary, #f0a020) 55%, transparent); background: color-mix(in srgb, var(--dsw-alias-state-warning-primary, #f0a020) 8%, transparent); }\n.rm-run-queued, .rm-run-approval { border-style: dashed; }\n.rm-run-done, .rm-run-stopped, .rm-run-failed { opacity: 0.7; }\n.rm-run-pos { font-size: 11px; color: var(--rm-quiet); text-align: center; font-variant-numeric: tabular-nums; }\n.rm-run-who { font-weight: 600; color: var(--rm-label); white-space: nowrap; }\n.rm-run-what { color: var(--rm-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }\n.rm-stop-btn { display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e5484d) 60%, transparent); background: color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e5484d) 10%, transparent); color: var(--dsw-alias-state-danger-primary, #e5484d); font-size: 12px; cursor: pointer; white-space: nowrap; }\n.rm-stop-btn:hover { background: color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e5484d) 18%, transparent); }\n.rm-badge-local { color: var(--dsw-alias-state-success-primary, #2bb673); }\n.rm-session-agent { color: var(--rm-accent, #5b8cff); }\n.rm-preset-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }\n.rm-preset { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 150px; flex: 1; padding: 8px 10px; border: 1px solid var(--rm-border); border-radius: 10px; background: transparent; color: var(--rm-label); text-align: left; cursor: pointer; font: inherit; font-size: 12px; }\n.rm-preset span { color: var(--rm-muted); font-size: 11px; line-height: 1.35; }\n.rm-preset.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 12%, transparent); }\n.rm-preset-check { flex-direction: row; align-items: center; gap: 8px; min-width: 120px; flex: 0 1 auto; }\n.rm-local-box { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border: 1px dashed var(--rm-border); border-radius: 12px; }\n.rm-textarea { width: 100%; box-sizing: border-box; min-height: 84px; resize: vertical; font: inherit; font-size: 13px; padding: 8px 10px; }\n.rm-switch-col { display: flex; flex-direction: column; gap: 6px; }\n.rm-modal-xl { width: min(1180px, 96vw) !important; max-width: 96vw !important; }\n.rm-merge { display: grid; grid-template-columns: 260px 1fr; gap: 14px; min-height: 420px; }\n.rm-merge-list { display: flex; flex-direction: column; gap: 6px; border-right: 1px solid var(--rm-border); padding-right: 12px; }\n.rm-merge-agent { display: flex; align-items: center; gap: 8px; padding: 8px; border: 1px solid transparent; border-radius: 10px; background: transparent; color: var(--rm-label); cursor: pointer; text-align: left; font: inherit; }\n.rm-merge-agent:hover { background: var(--rm-hover); }\n.rm-merge-agent.is-on { border-color: var(--rm-accent, #5b8cff); background: color-mix(in srgb, var(--rm-accent, #5b8cff) 10%, transparent); }\n.rm-merge-agent-body { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 12px; }\n.rm-merge-agent-body .rm-mono { font-size: 10.5px; color: var(--rm-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.rm-merge-main { min-width: 0; display: flex; flex-direction: column; gap: 8px; }\n.rm-merge-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 13px; }\n.rm-merge-files { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; }\n.rm-confirm-text { font-size: 12px; color: var(--rm-label); margin-right: 4px; }\n.rm-diff { margin: 0; max-height: 52vh; overflow: auto; padding: 8px 0; border: 1px solid var(--rm-border); border-radius: 10px; background: var(--rm-panel); font-family: var(--dsw-font-mono, ui-monospace, monospace); font-size: 12px; line-height: 1.5; }\n.rm-diff > div { padding: 0 12px; white-space: pre; }\n.rm-diff-add { background: color-mix(in srgb, #2bb673 16%, transparent); }\n.rm-diff-del { background: color-mix(in srgb, #e5484d 16%, transparent); }\n.rm-diff-hunk { color: var(--rm-accent, #5b8cff); }\n.rm-diff-head, .rm-diff-file { color: var(--rm-muted); font-weight: 600; }\n.rm-diff-addn { color: #2bb673; }\n.rm-diff-deln { color: #e5484d; }\n.rm-ok { padding: 8px 10px; border-radius: 8px; font-size: 12.5px; color: var(--dsw-alias-state-success-primary, #2bb673); background: color-mix(in srgb, #2bb673 10%, transparent); }\n';
|
|
1559
2051
|
|
|
1560
2052
|
// src/client/store.js
|
|
1561
2053
|
var API = "/api/collab";
|
|
@@ -1733,6 +2225,37 @@ function createRoomsStore() {
|
|
|
1733
2225
|
},
|
|
1734
2226
|
async mcp(roomId, tool, args, target) {
|
|
1735
2227
|
return post(`/rooms/${encodeURIComponent(roomId)}/mcp`, { tool, args, target });
|
|
2228
|
+
},
|
|
2229
|
+
// ── local multi-agent ──
|
|
2230
|
+
async presets() {
|
|
2231
|
+
return (await call("/presets")).presets;
|
|
2232
|
+
},
|
|
2233
|
+
async addAgent(roomId, body) {
|
|
2234
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/agents`, body);
|
|
2235
|
+
},
|
|
2236
|
+
async updateAgent(roomId, id, body) {
|
|
2237
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/agents/${encodeURIComponent(id)}`, body);
|
|
2238
|
+
},
|
|
2239
|
+
async removeAgent(roomId, id) {
|
|
2240
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/agents/${encodeURIComponent(id)}?op=delete`);
|
|
2241
|
+
},
|
|
2242
|
+
async saveLocal(roomId, patch) {
|
|
2243
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/local`, patch);
|
|
2244
|
+
},
|
|
2245
|
+
async setTransport(roomId, target, force) {
|
|
2246
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/transport`, { target, force: !!force });
|
|
2247
|
+
},
|
|
2248
|
+
async stop(roomId, agentId) {
|
|
2249
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/stop`, agentId ? { agentId } : {});
|
|
2250
|
+
},
|
|
2251
|
+
async diffs(roomId) {
|
|
2252
|
+
return call(`/rooms/${encodeURIComponent(roomId)}/diffs`);
|
|
2253
|
+
},
|
|
2254
|
+
async merge(roomId, agentId) {
|
|
2255
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/merge`, { agentId, approve: true });
|
|
2256
|
+
},
|
|
2257
|
+
async discard(roomId, agentId) {
|
|
2258
|
+
return post(`/rooms/${encodeURIComponent(roomId)}/discard`, { agentId, approve: true });
|
|
1736
2259
|
}
|
|
1737
2260
|
};
|
|
1738
2261
|
const api = {
|
|
@@ -1788,6 +2311,17 @@ var LockIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size: 1
|
|
|
1788
2311
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3.5", y: "7", width: "9", height: "6.25", rx: "1.5" }),
|
|
1789
2312
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5.5 7V5.25a2.5 2.5 0 0 1 5 0V7" })
|
|
1790
2313
|
] });
|
|
2314
|
+
var BotIcon = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size, children: [
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "5", width: "10", height: "7.5", rx: "2" }),
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 2.5V5M6 8.5h.01M10 8.5h.01M6.25 10.75h3.5" })
|
|
2317
|
+
] });
|
|
2318
|
+
var StopIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Svg, { size: 12, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5" }) });
|
|
2319
|
+
var MergeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size: 14, children: [
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "5", cy: "3.75", r: "1.5" }),
|
|
2321
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "5", cy: "12.25", r: "1.5" }),
|
|
2322
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "11", cy: "8", r: "1.5" }),
|
|
2323
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 5.25v5.5M5 5.5c0 2 1.5 2.5 4.5 2.5" })
|
|
2324
|
+
] });
|
|
1791
2325
|
var PeopleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Svg, { size: 14, children: [
|
|
1792
2326
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "6", cy: "5.5", r: "2.25" }),
|
|
1793
2327
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M2.5 13c.4-2 1.8-3.25 3.5-3.25S9.1 11 9.5 13" }),
|
|
@@ -1908,6 +2442,10 @@ function RoomsNav({ store }) {
|
|
|
1908
2442
|
}
|
|
1909
2443
|
function RoomSessionMark({ store, sessionId }) {
|
|
1910
2444
|
const s = useStore(store);
|
|
2445
|
+
for (const r of s.rooms || []) {
|
|
2446
|
+
const ag = (r.local && r.local.agents || []).find((x) => x.sessionId === sessionId);
|
|
2447
|
+
if (ag) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-session-mark rm-session-agent", title: `DSH Room \xB7 ${r.name} \xB7 ${ag.name} (${ag.agentId})`, "aria-label": `DSH Room ${r.name} agent ${ag.name}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 13 }) });
|
|
2448
|
+
}
|
|
1911
2449
|
const room = (s.rooms || []).find((r) => r.sessionId === sessionId);
|
|
1912
2450
|
if (!room) return null;
|
|
1913
2451
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-session-mark", title: `DSH Room \xB7 ${room.name}`, "aria-label": `DSH Room ${room.name}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RoomsIcon, { size: 13 }) });
|
|
@@ -1933,14 +2471,14 @@ function renderMentions(text) {
|
|
|
1933
2471
|
function PanelIcon({ size }) {
|
|
1934
2472
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RoomsIcon, { size });
|
|
1935
2473
|
}
|
|
1936
|
-
function Message({ m, showAuthor }) {
|
|
2474
|
+
function Message({ m, showAuthor, who }) {
|
|
1937
2475
|
if (m.kind === "task.create") {
|
|
1938
2476
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-msg rm-msg-event", "data-message-id": m.id, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-task-card", children: [
|
|
1939
2477
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-task-head", children: [
|
|
1940
2478
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}),
|
|
1941
2479
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1942
2480
|
"Task \xB7 ",
|
|
1943
|
-
m.from
|
|
2481
|
+
who && who.name || m.from
|
|
1944
2482
|
] }),
|
|
1945
2483
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "info", children: "open" }),
|
|
1946
2484
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-time", children: fmtTime(m.ts) })
|
|
@@ -1953,7 +2491,7 @@ function Message({ m, showAuthor }) {
|
|
|
1953
2491
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-msg rm-msg-event", "data-message-id": m.id, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-task-head", children: [
|
|
1954
2492
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}),
|
|
1955
2493
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1956
|
-
m.self ? "You" : m.from,
|
|
2494
|
+
m.self ? "You" : who && who.name || m.from,
|
|
1957
2495
|
" ",
|
|
1958
2496
|
m.kind === "task.claim" ? "claimed" : "updated",
|
|
1959
2497
|
" task"
|
|
@@ -1973,14 +2511,20 @@ function Message({ m, showAuthor }) {
|
|
|
1973
2511
|
showAuthor ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: m.from, size: 28 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
|
|
1974
2512
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1975
2513
|
showAuthor ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-msg-head", children: [
|
|
1976
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-author", children: m.from }),
|
|
2514
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-author", children: who && who.name ? who.name : m.from }),
|
|
2515
|
+
who && who.name ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-id", children: m.from }) : null,
|
|
2516
|
+
who && who.local ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-tag", children: [
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 11 }),
|
|
2518
|
+
who.moderator ? "moderator" : "local agent"
|
|
2519
|
+
] }) : null,
|
|
1977
2520
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-time", children: fmtTime(m.ts) })
|
|
1978
2521
|
] }) : null,
|
|
1979
2522
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-msg-body", children: renderMentions(m.text) })
|
|
1980
2523
|
] })
|
|
1981
2524
|
] });
|
|
1982
2525
|
}
|
|
1983
|
-
function ChatBody({ messages }) {
|
|
2526
|
+
function ChatBody({ messages, members }) {
|
|
2527
|
+
const byId = (0, import_react.useMemo)(() => Object.fromEntries((members || []).map((x) => [x.agentId, x])), [members]);
|
|
1984
2528
|
const ref = (0, import_react.useRef)(null);
|
|
1985
2529
|
(0, import_react.useEffect)(() => {
|
|
1986
2530
|
const el = ref.current;
|
|
@@ -1996,7 +2540,7 @@ function ChatBody({ messages }) {
|
|
|
1996
2540
|
prev = null;
|
|
1997
2541
|
}
|
|
1998
2542
|
const showAuthor = !prev || prev.from !== m.from || m.ts - prev.ts > 5 * 6e4;
|
|
1999
|
-
nodes.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Message, { m, showAuthor }, m.id));
|
|
2543
|
+
nodes.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Message, { m, showAuthor, who: byId[m.from] }, m.id));
|
|
2000
2544
|
prev = m;
|
|
2001
2545
|
}
|
|
2002
2546
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-messages", ref, children: nodes.length ? nodes : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-chat-hint", children: "No messages yet. Send a message, @mention an agent to wake it, or create a task from the composer." }) });
|
|
@@ -2023,7 +2567,7 @@ function MentionMenu({ items, active, onPick, onHover }) {
|
|
|
2023
2567
|
onPick(it);
|
|
2024
2568
|
},
|
|
2025
2569
|
children: [
|
|
2026
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: it.id === "all" ? "all" : it.id, size: 22 }),
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: it.id === "all" ? "all" : it.name || it.id, size: 22 }),
|
|
2027
2571
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-mention-item-body", children: [
|
|
2028
2572
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-mention-item-name", children: [
|
|
2029
2573
|
"@",
|
|
@@ -2031,6 +2575,10 @@ function MentionMenu({ items, active, onPick, onHover }) {
|
|
|
2031
2575
|
] }),
|
|
2032
2576
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mention-item-meta", children: it.hint })
|
|
2033
2577
|
] }),
|
|
2578
|
+
it.local ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-tag", children: [
|
|
2579
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 11 }),
|
|
2580
|
+
"local"
|
|
2581
|
+
] }) : null,
|
|
2034
2582
|
it.online === false ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: "offline" }) : null
|
|
2035
2583
|
]
|
|
2036
2584
|
},
|
|
@@ -2055,14 +2603,20 @@ function Composer({ room, store, draft, setDraft }) {
|
|
|
2055
2603
|
if (!mq) return [];
|
|
2056
2604
|
const q = mq.query.toLowerCase();
|
|
2057
2605
|
const members = (room.members || []).filter((m) => !m.self);
|
|
2058
|
-
const
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2606
|
+
const localAgents = room.local && room.local.agents || [];
|
|
2607
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2608
|
+
const known = [];
|
|
2609
|
+
for (const la of localAgents) {
|
|
2610
|
+
seen.add(la.agentId);
|
|
2611
|
+
known.push({ id: la.agentId, name: la.name, local: true, hint: `${la.name} \xB7 local agent${la.moderator ? " \xB7 moderator" : ""}${la.state && la.state !== "idle" ? ` \xB7 ${la.state}` : ""}`, online: la.online !== false });
|
|
2612
|
+
}
|
|
2613
|
+
for (const m of members) {
|
|
2614
|
+
if (seen.has(m.agentId)) continue;
|
|
2615
|
+
known.push({ id: m.agentId, name: m.name, hint: `${m.name ? m.name + " \xB7 " : ""}${m.hostedBy ? "remote agent" : "member"}${m.online === false ? " \xB7 offline" : " \xB7 wake"}`, online: m.online !== false });
|
|
2616
|
+
}
|
|
2617
|
+
const all = { id: "all", hint: localAgents.length ? "Everyone \xB7 wakes all local agents in parallel" : "Everyone \xB7 wake all members", online: true };
|
|
2064
2618
|
const list = [all, ...known];
|
|
2065
|
-
return list.filter((it) => !q || it.id.toLowerCase().startsWith(q) ||
|
|
2619
|
+
return list.filter((it) => !q || it.id.toLowerCase().startsWith(q) || it.name && it.name.toLowerCase().startsWith(q));
|
|
2066
2620
|
})();
|
|
2067
2621
|
const mc = room.memberConfig || {};
|
|
2068
2622
|
const modelLabel = mc.model || "Default model";
|
|
@@ -2100,6 +2654,23 @@ function Composer({ room, store, draft, setDraft }) {
|
|
|
2100
2654
|
a.toast(e.message);
|
|
2101
2655
|
}
|
|
2102
2656
|
};
|
|
2657
|
+
const syncCaret = (el) => {
|
|
2658
|
+
if (el) setCaret(el.selectionStart == null ? el.value.length : el.selectionStart);
|
|
2659
|
+
};
|
|
2660
|
+
const insertMention = (it) => {
|
|
2661
|
+
if (!mq || !it) return;
|
|
2662
|
+
const next = draft.slice(0, mq.start) + "@" + it.id + " " + draft.slice(mq.end);
|
|
2663
|
+
const pos = mq.start + it.id.length + 2;
|
|
2664
|
+
setDraft(next);
|
|
2665
|
+
setCaret(pos);
|
|
2666
|
+
requestAnimationFrame(() => {
|
|
2667
|
+
const el = taRef.current;
|
|
2668
|
+
if (el) {
|
|
2669
|
+
el.focus();
|
|
2670
|
+
el.setSelectionRange(pos, pos);
|
|
2671
|
+
}
|
|
2672
|
+
});
|
|
2673
|
+
};
|
|
2103
2674
|
const submit = async () => {
|
|
2104
2675
|
const text = draft.trim();
|
|
2105
2676
|
if (!text || busy) return;
|
|
@@ -2296,7 +2867,15 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
2296
2867
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: m.agentId, size: 26 }),
|
|
2297
2868
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-dot rm-dot-" + (m.online === false ? "offline" : "online"), style: { position: "absolute", right: -1, bottom: -1, border: "2px solid var(--rm-bg)" } })
|
|
2298
2869
|
] }),
|
|
2299
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-member-name", children: m.
|
|
2870
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-member-name", children: m.name ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2871
|
+
m.name,
|
|
2872
|
+
" ",
|
|
2873
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-msg-id", children: m.agentId })
|
|
2874
|
+
] }) : m.agentId }),
|
|
2875
|
+
m.local ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-tag", children: [
|
|
2876
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, { size: 11 }),
|
|
2877
|
+
m.moderator ? "moderator" : "local"
|
|
2878
|
+
] }) : m.hostedBy && !m.self ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-agent-tag", children: "remote agent" }) : null,
|
|
2300
2879
|
m.self ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: "you" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-member-actions", children: [
|
|
2301
2880
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `@mention ${m.agentId}`, onClick: () => mention(m.agentId), children: "@" }),
|
|
2302
2881
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `Assign a task to ${m.agentId}`, onClick: () => assign(m.agentId), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}) })
|
|
@@ -2304,6 +2883,9 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
2304
2883
|
] }, m.agentId)),
|
|
2305
2884
|
!room.members.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: room.status === "online" ? "Only you are here." : "Offline." }) : null
|
|
2306
2885
|
] }),
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LocalAgentsSection, { room, store, mention }),
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(OrchestrationSection, { room, store }),
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(IsolationSection, { room, store }),
|
|
2307
2889
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", children: [
|
|
2308
2890
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
2309
2891
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskIcon, {}),
|
|
@@ -2326,8 +2908,10 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
2326
2908
|
"Invite"
|
|
2327
2909
|
] }),
|
|
2328
2910
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: room.public ? "Public: listed in the relay directory with its key. Anyone can find, join, and read this room." : "Private: only agents holding the invite can join. The invite contains the room key \u2014 share it only with agents you trust." }),
|
|
2911
|
+
room.transport === "local" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Local-only room: switch Transport to Relay or LAN before inviting remote hosts." }) : null,
|
|
2329
2912
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", onClick: copyInvite, icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkIcon, {}), children: "Copy invite" }) })
|
|
2330
2913
|
] }),
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransportSection, { room, store }),
|
|
2331
2915
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", children: [
|
|
2332
2916
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-detail-h", children: "About" }),
|
|
2333
2917
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", { className: "rm-about", children: [
|
|
@@ -2340,7 +2924,7 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
2340
2924
|
" Private"
|
|
2341
2925
|
] }) }),
|
|
2342
2926
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Transport" }),
|
|
2343
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: room.transport === "lan" ? "LAN / VPS (Node relay)" : "Relay (Cloudflare)" }),
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: room.transport === "local" ? "Local only (in-process loopback)" : room.transport === "lan" ? "LAN / VPS (Node relay)" : "Relay (Cloudflare)" }),
|
|
2344
2928
|
room.memberConfig?.workspaceLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2345
2929
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Workspace" }),
|
|
2346
2930
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: room.memberConfig.workspaceLabel })
|
|
@@ -2367,6 +2951,371 @@ function RoomDetail({ room, messages, store, mention, assign }) {
|
|
|
2367
2951
|
] })
|
|
2368
2952
|
] });
|
|
2369
2953
|
}
|
|
2954
|
+
var RUN_TONE = { running: "warning", queued: "info", approval: "info", done: "success", failed: "danger", stopped: "quiet" };
|
|
2955
|
+
var MODEL_CHOICES = ["", "deepseek-chat", "deepseek-reasoner"];
|
|
2956
|
+
function LocalAgentsSection({ room, store, mention }) {
|
|
2957
|
+
const a = store.actions;
|
|
2958
|
+
const local = room.local || { agents: [] };
|
|
2959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-local-agents": "", children: [
|
|
2960
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
2961
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BotIcon, {}),
|
|
2962
|
+
"Local agents \xB7 ",
|
|
2963
|
+
local.agents.length
|
|
2964
|
+
] }),
|
|
2965
|
+
local.agents.map((ag) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-agent-row", "data-agent-id": ag.agentId, children: [
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-avatar-wrap", children: [
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: ag.name, size: 26 }),
|
|
2968
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-dot rm-dot-" + (ag.state === "running" ? "busy" : ag.online ? "online" : "offline"), style: { position: "absolute", right: -1, bottom: -1, border: "2px solid var(--rm-bg)" } })
|
|
2969
|
+
] }),
|
|
2970
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-main", children: [
|
|
2971
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-name", children: [
|
|
2972
|
+
ag.name,
|
|
2973
|
+
ag.moderator ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-agent-tag", children: "moderator" }) : null
|
|
2974
|
+
] }),
|
|
2975
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-sub rm-mono", children: [
|
|
2976
|
+
"@",
|
|
2977
|
+
ag.agentId
|
|
2978
|
+
] }),
|
|
2979
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-agent-sub", children: [
|
|
2980
|
+
ag.scope === "write" ? ag.isolation === "worktree" ? "writes \xB7 own worktree" : ag.isolation === "locks" ? "writes \xB7 file locks" : "writes" : "read-only",
|
|
2981
|
+
ag.approvalRequired ? " \xB7 approval" : "",
|
|
2982
|
+
ag.model ? ` \xB7 ${ag.model}` : "",
|
|
2983
|
+
ag.reasoningEffort ? ` \xB7 ${ag.reasoningEffort}` : ""
|
|
2984
|
+
] })
|
|
2985
|
+
] }),
|
|
2986
|
+
ag.state !== "idle" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: RUN_TONE[ag.state] || "neutral", children: ag.state }) : null,
|
|
2987
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-member-actions", children: [
|
|
2988
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `@mention ${ag.name}`, onClick: () => mention(ag.agentId), children: "@" }),
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mini", title: `Edit ${ag.name}`, "aria-label": `Edit ${ag.name}`, onClick: () => a.openDialog({ kind: "agent", roomId: room.roomId, agentId: ag.agentId }), children: "\u270E" })
|
|
2990
|
+
] })
|
|
2991
|
+
] }, ag.agentId)),
|
|
2992
|
+
!local.agents.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Host several agents from this dsh as separate members \u2014 each with its own identity, session and scope." }) : null,
|
|
2993
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlusIcon, {}), onClick: () => a.openDialog({ kind: "agent", roomId: room.roomId }), children: "Add local agent" }) })
|
|
2994
|
+
] });
|
|
2995
|
+
}
|
|
2996
|
+
function NumberSetting({ label, value, min, max, onSave, hint }) {
|
|
2997
|
+
const [v, setV] = (0, import_react.useState)(String(value));
|
|
2998
|
+
(0, import_react.useEffect)(() => setV(String(value)), [value]);
|
|
2999
|
+
const commit = () => {
|
|
3000
|
+
const n = Number(v);
|
|
3001
|
+
if (Number.isFinite(n) && n !== value) onSave(Math.min(max, Math.max(min, Math.round(n))));
|
|
3002
|
+
else setV(String(value));
|
|
3003
|
+
};
|
|
3004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "rm-num-setting", title: hint, children: [
|
|
3005
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label }),
|
|
3006
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", min, max, value: v, "aria-label": label, onChange: (e) => setV(e.target.value), onBlur: commit, onKeyDown: (e) => e.key === "Enter" && e.target.blur() })
|
|
3007
|
+
] });
|
|
3008
|
+
}
|
|
3009
|
+
function RunQueue({ room, store, compact }) {
|
|
3010
|
+
const a = store.actions;
|
|
3011
|
+
const runs = room.runs || [];
|
|
3012
|
+
const nameOf = (id) => (room.local && room.local.agents || []).find((x) => x.agentId === id)?.name || id;
|
|
3013
|
+
const active = runs.filter((r) => r.state === "running" || r.state === "queued" || r.state === "approval");
|
|
3014
|
+
const recent = runs.filter((r) => !active.includes(r)).slice(-3).reverse();
|
|
3015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-runs", "data-rm-runs": "", children: [
|
|
3016
|
+
active.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-run rm-run-" + r.state, children: [
|
|
3017
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-pos", children: r.state === "running" ? "\u25B6" : r.state === "approval" ? "?" : `#${i + 1 - active.filter((x) => x.state === "running").length}` }),
|
|
3018
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-who", children: nameOf(r.agentId) }),
|
|
3019
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-what", title: r.summary, children: r.summary }),
|
|
3020
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: RUN_TONE[r.state], children: r.state === "approval" ? "needs approval" : r.state })
|
|
3021
|
+
] }, r.id)),
|
|
3022
|
+
!compact ? recent.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-run rm-run-" + r.state, children: [
|
|
3023
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-pos", children: "\u2713" }),
|
|
3024
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-who", children: nameOf(r.agentId) }),
|
|
3025
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-run-what", title: r.error || r.summary, children: r.error || r.summary }),
|
|
3026
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: RUN_TONE[r.state], children: r.state })
|
|
3027
|
+
] }, r.id)) : null,
|
|
3028
|
+
!active.length && !recent.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "No agent runs yet." }) : null,
|
|
3029
|
+
active.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", className: "rm-danger", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StopIcon, {}), onClick: () => a.stop(room.roomId).then((r) => a.toast(`Stopped ${r.stopped} run(s)`)).catch((e) => a.toast(e.message)), children: "Stop all agents" }) }) : null
|
|
3030
|
+
] });
|
|
3031
|
+
}
|
|
3032
|
+
function OrchestrationSection({ room, store }) {
|
|
3033
|
+
const a = store.actions;
|
|
3034
|
+
const local = room.local;
|
|
3035
|
+
if (!local || !local.agents.length) return null;
|
|
3036
|
+
const save = (patch) => a.saveLocal(room.roomId, patch).catch((e) => a.toast(e.message));
|
|
3037
|
+
const active = (room.runs || []).filter((r) => r.state === "running" || r.state === "queued" || r.state === "approval");
|
|
3038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-orchestration": "", children: [
|
|
3039
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
3040
|
+
"Runs \xB7 ",
|
|
3041
|
+
active.filter((r) => r.state === "running").length,
|
|
3042
|
+
"/",
|
|
3043
|
+
local.concurrency,
|
|
3044
|
+
" running",
|
|
3045
|
+
active.length > local.concurrency ? ` \xB7 ${active.length - Math.min(local.concurrency, active.filter((r) => r.state === "running").length)} queued` : ""
|
|
3046
|
+
] }),
|
|
3047
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-num-row", children: [
|
|
3048
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(NumberSetting, { label: "Parallel runs", value: local.concurrency, min: 1, max: 16, onSave: (n) => save({ concurrency: n }), hint: "Max local agent runs at once; the rest wait in the queue." }),
|
|
3049
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(NumberSetting, { label: "Turn limit", value: local.turnLimit, min: 1, max: 100, onSave: (n) => save({ turnLimit: n }), hint: "Max agent-to-agent hand-offs per task/thread. A human message resets it." })
|
|
3050
|
+
] }),
|
|
3051
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunQueue, { room, store })
|
|
3052
|
+
] });
|
|
3053
|
+
}
|
|
3054
|
+
function IsolationSection({ room, store }) {
|
|
3055
|
+
const a = store.actions;
|
|
3056
|
+
const local = room.local;
|
|
3057
|
+
if (!local || !local.agents.some((x) => x.scope === "write")) return null;
|
|
3058
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-isolation": "", children: [
|
|
3059
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-h", children: [
|
|
3060
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeIcon, {}),
|
|
3061
|
+
"Workspace isolation"
|
|
3062
|
+
] }),
|
|
3063
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { className: "rm-input", "aria-label": "Isolation mode", value: local.isolation, onChange: (e) => a.saveLocal(room.roomId, { isolation: e.target.value }).catch((x) => a.toast(x.message)), children: [
|
|
3064
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "auto", children: "Auto \u2014 git worktree per writing agent, else file locks" }),
|
|
3065
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "worktree", children: "Git worktree per agent" }),
|
|
3066
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "locks", children: "File locks (shared workspace)" }),
|
|
3067
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "off", children: "Off (shared, no locks)" })
|
|
3068
|
+
] }),
|
|
3069
|
+
local.locks && local.locks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-note", children: [
|
|
3070
|
+
local.locks.length,
|
|
3071
|
+
" file lock(s): ",
|
|
3072
|
+
local.locks.slice(0, 4).map((l) => `${l.path} (${l.owner})`).join(", ")
|
|
3073
|
+
] }) : null,
|
|
3074
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeIcon, {}), onClick: () => a.openDialog({ kind: "merge", roomId: room.roomId }), children: "Review & merge" }) })
|
|
3075
|
+
] });
|
|
3076
|
+
}
|
|
3077
|
+
function TransportSection({ room, store }) {
|
|
3078
|
+
const a = store.actions;
|
|
3079
|
+
const [busy, setBusy] = (0, import_react.useState)(null);
|
|
3080
|
+
const cur = room.transport === "local" ? "local" : room.transport === "lan" ? "relay" : "relay";
|
|
3081
|
+
const go = async (target) => {
|
|
3082
|
+
setBusy(target);
|
|
3083
|
+
try {
|
|
3084
|
+
await a.setTransport(room.roomId, target);
|
|
3085
|
+
a.toast(target === "local" ? "Local only \u2014 in-process, no network" : target === "lan" ? "Now on this machine's LAN relay \u2014 invite remote hosts" : "Now on the relay \u2014 invite remote hosts");
|
|
3086
|
+
} catch (e) {
|
|
3087
|
+
a.toast(e.message);
|
|
3088
|
+
} finally {
|
|
3089
|
+
setBusy(null);
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-detail-section", "data-rm-transport": "", children: [
|
|
3093
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-detail-h", children: "Transport" }),
|
|
3094
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-mode-row", children: [
|
|
3095
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: !!busy || room.public, className: "rm-mode-btn" + (cur === "local" ? " is-on" : ""), onClick: () => go("local"), title: room.public ? "Public rooms need a relay" : "In-process loopback: no network", children: busy === "local" ? "\u2026" : "Local only" }),
|
|
3096
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: !!busy, className: "rm-mode-btn" + (cur === "relay" && room.transport !== "local" ? " is-on" : ""), onClick: () => go("relay"), children: busy === "relay" ? "\u2026" : "Relay (VPS)" }),
|
|
3097
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: !!busy, className: "rm-mode-btn", onClick: () => go("lan"), title: "Embedded LAN relay on this machine (mDNS)", children: busy === "lan" ? "\u2026" : "LAN" })
|
|
3098
|
+
] }),
|
|
3099
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: room.transport === "local" ? "All members are on this dsh \u2014 nothing leaves the process. Switch to Relay or LAN to invite remote hosts; local agents stay members." : "Local agents connect as separate members over this transport, alongside remote hosts." })
|
|
3100
|
+
] });
|
|
3101
|
+
}
|
|
3102
|
+
function AgentDialog({ store, d }) {
|
|
3103
|
+
const a = store.actions;
|
|
3104
|
+
const s = useStore(store);
|
|
3105
|
+
const room = (s.rooms || []).find((r) => r.roomId === d.roomId);
|
|
3106
|
+
const existing = room && room.local ? room.local.agents.find((x) => x.agentId === d.agentId) : null;
|
|
3107
|
+
const [presets, setPresets] = (0, import_react.useState)([]);
|
|
3108
|
+
const [f, setF] = (0, import_react.useState)(() => existing ? { name: existing.name, persona: existing.persona || "", systemPrompt: existing.systemPrompt || "", model: existing.model || "", reasoningEffort: existing.reasoningEffort || "medium", scope: existing.scope, approvalRequired: !!existing.approvalRequired, moderator: !!existing.moderator } : { preset: "", name: "", persona: "", systemPrompt: "", model: "", reasoningEffort: "medium", scope: "read", approvalRequired: false, moderator: false });
|
|
3109
|
+
const [err, setErr] = (0, import_react.useState)(null);
|
|
3110
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
3111
|
+
(0, import_react.useEffect)(() => {
|
|
3112
|
+
a.presets().then(setPresets).catch(() => {
|
|
3113
|
+
});
|
|
3114
|
+
}, []);
|
|
3115
|
+
const pick = (p) => setF({ ...f, preset: p.key, name: p.name, persona: p.persona, systemPrompt: p.systemPrompt, scope: p.scope, moderator: !!p.moderator, reasoningEffort: p.reasoningEffort || "medium" });
|
|
3116
|
+
const submit = async () => {
|
|
3117
|
+
if (!f.name.trim()) {
|
|
3118
|
+
setErr("Name required");
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
setBusy(true);
|
|
3122
|
+
setErr(null);
|
|
3123
|
+
try {
|
|
3124
|
+
const body = { name: f.name, persona: f.persona, systemPrompt: f.systemPrompt, model: f.model, reasoningEffort: f.reasoningEffort, scope: f.scope, approvalRequired: f.approvalRequired, moderator: f.moderator, preset: f.preset || void 0 };
|
|
3125
|
+
if (existing) await a.updateAgent(d.roomId, existing.agentId, body);
|
|
3126
|
+
else {
|
|
3127
|
+
const r = await a.addAgent(d.roomId, body);
|
|
3128
|
+
a.toast(`${r.name} joined as @${r.agentId}`);
|
|
3129
|
+
}
|
|
3130
|
+
a.closeDialog();
|
|
3131
|
+
} catch (e) {
|
|
3132
|
+
setErr(e.message);
|
|
3133
|
+
setBusy(false);
|
|
3134
|
+
}
|
|
3135
|
+
};
|
|
3136
|
+
const remove = async () => {
|
|
3137
|
+
setBusy(true);
|
|
3138
|
+
try {
|
|
3139
|
+
const r = await a.removeAgent(d.roomId, existing.agentId);
|
|
3140
|
+
a.toast(`Removed ${existing.name}${r.branchKept ? ` \xB7 branch ${r.branchKept} kept` : ""}`);
|
|
3141
|
+
a.closeDialog();
|
|
3142
|
+
} catch (e) {
|
|
3143
|
+
setErr(e.message);
|
|
3144
|
+
setBusy(false);
|
|
3145
|
+
}
|
|
3146
|
+
};
|
|
3147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
3148
|
+
import_dsh_client_ui_primitives.Modal,
|
|
3149
|
+
{
|
|
3150
|
+
open: true,
|
|
3151
|
+
onClose: a.closeDialog,
|
|
3152
|
+
title: existing ? `Edit ${existing.name}` : "Add local agent",
|
|
3153
|
+
closeLabel: "Close",
|
|
3154
|
+
className: "rm-modal-wide",
|
|
3155
|
+
description: existing ? `Member @${existing.agentId} \xB7 own identity and dsh session in this room's workspace.` : "Runs on this dsh as a separate room member: own keypair, own session, own scope. Remote peers see it as a member.",
|
|
3156
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
3157
|
+
existing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", className: "rm-danger", disabled: busy, onClick: remove, children: "Remove" }) : null,
|
|
3158
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
3159
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", onClick: a.closeDialog, children: "Cancel" }),
|
|
3160
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", disabled: busy, onClick: submit, children: busy ? "Saving\u2026" : existing ? "Save" : "Add agent" })
|
|
3161
|
+
] }),
|
|
3162
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-root rm-form rm-form-wide", "data-rm-agent-form": "", children: [
|
|
3163
|
+
!existing ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-span-2", children: [
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Preset" }),
|
|
3165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-preset-row", children: presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "rm-preset" + (f.preset === p.key ? " is-on" : ""), onClick: () => pick(p), children: [
|
|
3166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: p.name }),
|
|
3167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.persona })
|
|
3168
|
+
] }, p.key)) })
|
|
3169
|
+
] }) : null,
|
|
3170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Name", htmlFor: "rm-ag-name", hint: "Member id is derived from it (e.g. coder.ab12).", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Input, { id: "rm-ag-name", value: f.name, maxLength: 40, onChange: (e) => setF({ ...f, name: e.target.value }), placeholder: "e.g. Coder" }) }),
|
|
3171
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Persona", htmlFor: "rm-ag-persona", hint: "One line other members see.", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Input, { id: "rm-ag-persona", value: f.persona, maxLength: 200, onChange: (e) => setF({ ...f, persona: e.target.value }), placeholder: "e.g. Implements changes" }) }),
|
|
3172
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "System prompt", htmlFor: "rm-ag-sp", hint: "Prepended to every wake of this agent.", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { id: "rm-ag-sp", className: "rm-input rm-textarea", rows: 4, value: f.systemPrompt, maxLength: 4e3, onChange: (e) => setF({ ...f, systemPrompt: e.target.value }) }) }) }),
|
|
3173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Model", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { className: "rm-input", "aria-label": "Model", value: f.model, onChange: (e) => setF({ ...f, model: e.target.value }), children: [
|
|
3174
|
+
MODEL_CHOICES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: m, children: m || "dsh default model" }, m)),
|
|
3175
|
+
f.model && !MODEL_CHOICES.includes(f.model) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: f.model, children: f.model }) : null
|
|
3176
|
+
] }) }),
|
|
3177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Reasoning effort", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { className: "rm-input", "aria-label": "Reasoning effort", value: f.reasoningEffort, onChange: (e) => setF({ ...f, reasoningEffort: e.target.value }), children: ["low", "medium", "high", "max"].map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: x, children: x }, x)) }) }),
|
|
3178
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Workspace scope", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-mode-row", children: [
|
|
3179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mode-btn" + (f.scope === "read" ? " is-on" : ""), onClick: () => setF({ ...f, scope: "read" }), children: "Read-only" }),
|
|
3180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "rm-mode-btn" + (f.scope === "write" ? " is-on" : ""), onClick: () => setF({ ...f, scope: "write" }), children: "Read + write" })
|
|
3181
|
+
] }) }),
|
|
3182
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-col", children: [
|
|
3183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-row", children: [
|
|
3184
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
3185
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Approval required" }),
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "Each run waits for your OK." })
|
|
3187
|
+
] }),
|
|
3188
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.approvalRequired, onChange: (v) => setF({ ...f, approvalRequired: v }), label: "Approval required" })
|
|
3189
|
+
] }),
|
|
3190
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-row", children: [
|
|
3191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
3192
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Moderator" }),
|
|
3193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "Splits requests into tasks and summarizes. One per room." })
|
|
3194
|
+
] }),
|
|
3195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.moderator, onChange: (v) => setF({ ...f, moderator: v }), label: "Moderator" })
|
|
3196
|
+
] })
|
|
3197
|
+
] }),
|
|
3198
|
+
f.scope === "write" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2 rm-note", children: "Writes go to its own git worktree (branch room/<room>/<agent>) when the workspace is a git repo; you merge from \u201CReview & merge\u201D. Non-git workspaces use file locks." }) : null,
|
|
3199
|
+
err ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2 rm-error", children: err }) : null
|
|
3200
|
+
] })
|
|
3201
|
+
}
|
|
3202
|
+
);
|
|
3203
|
+
}
|
|
3204
|
+
function DiffView({ patch }) {
|
|
3205
|
+
if (!patch) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "No changes." });
|
|
3206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: "rm-diff", "data-rm-diff": "", children: patch.split("\n").map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: l.startsWith("+++") || l.startsWith("---") ? "rm-diff-file" : l.startsWith("+") ? "rm-diff-add" : l.startsWith("-") ? "rm-diff-del" : l.startsWith("@@") ? "rm-diff-hunk" : l.startsWith("diff ") ? "rm-diff-head" : "", children: l || " " }, i)) });
|
|
3207
|
+
}
|
|
3208
|
+
function MergeDialog({ store, d }) {
|
|
3209
|
+
const a = store.actions;
|
|
3210
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
3211
|
+
const [sel, setSel] = (0, import_react.useState)(null);
|
|
3212
|
+
const [confirm, setConfirm] = (0, import_react.useState)(null);
|
|
3213
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
3214
|
+
const [result, setResult] = (0, import_react.useState)(null);
|
|
3215
|
+
const load = async () => {
|
|
3216
|
+
try {
|
|
3217
|
+
const r = await a.diffs(d.roomId);
|
|
3218
|
+
setData(r);
|
|
3219
|
+
setSel((cur) => cur && r.agents.some((x) => x.agentId === cur) ? cur : (r.agents.find((x) => x.ahead) || r.agents[0] || {}).agentId || null);
|
|
3220
|
+
} catch (e) {
|
|
3221
|
+
setData({ error: e.message, agents: [] });
|
|
3222
|
+
}
|
|
3223
|
+
};
|
|
3224
|
+
(0, import_react.useEffect)(() => {
|
|
3225
|
+
void load();
|
|
3226
|
+
}, [d.roomId]);
|
|
3227
|
+
const ag = data && data.agents.find((x) => x.agentId === sel);
|
|
3228
|
+
const run = async (kind) => {
|
|
3229
|
+
setBusy(true);
|
|
3230
|
+
setResult(null);
|
|
3231
|
+
try {
|
|
3232
|
+
const r = kind === "merge" ? await a.merge(d.roomId, sel) : await a.discard(d.roomId, sel);
|
|
3233
|
+
setResult(kind === "merge" ? r.merged ? { ok: true, text: `Merged into the main workspace (${r.commit}).` } : { ok: false, text: `${r.error || "Not merged"}${r.conflicts && r.conflicts.length ? ": " + r.conflicts.join(", ") : ""}` } : { ok: true, text: r.discarded ? `Discarded ${r.branch}.` : "Nothing to discard." });
|
|
3234
|
+
await load();
|
|
3235
|
+
} catch (e) {
|
|
3236
|
+
setResult({ ok: false, text: e.message });
|
|
3237
|
+
} finally {
|
|
3238
|
+
setBusy(false);
|
|
3239
|
+
setConfirm(null);
|
|
3240
|
+
}
|
|
3241
|
+
};
|
|
3242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
3243
|
+
import_dsh_client_ui_primitives.Modal,
|
|
3244
|
+
{
|
|
3245
|
+
open: true,
|
|
3246
|
+
onClose: a.closeDialog,
|
|
3247
|
+
title: "Review & merge agent changes",
|
|
3248
|
+
closeLabel: "Close",
|
|
3249
|
+
className: "rm-modal-wide rm-modal-xl",
|
|
3250
|
+
description: "Each writing agent works on its own branch. Review the diff, then merge into (or discard from) your main workspace. Nothing is merged without your confirmation.",
|
|
3251
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", onClick: a.closeDialog, children: "Close" }),
|
|
3252
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-root rm-merge", "data-rm-merge": "", children: !data ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Loading diffs\u2026" }) : data.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-error", children: data.error }) : !data.agents.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "No writing agents in this room." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
3253
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-merge-list", children: data.agents.map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "rm-merge-agent" + (x.agentId === sel ? " is-on" : ""), onClick: () => {
|
|
3254
|
+
setSel(x.agentId);
|
|
3255
|
+
setConfirm(null);
|
|
3256
|
+
setResult(null);
|
|
3257
|
+
}, children: [
|
|
3258
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Avatar, { name: x.name, size: 24 }),
|
|
3259
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-merge-agent-body", children: [
|
|
3260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: x.name }),
|
|
3261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mono", children: x.branch || (x.isolation === "locks" ? "shared workspace \xB7 locks" : "no worktree yet") })
|
|
3262
|
+
] }),
|
|
3263
|
+
x.conflicts && x.conflicts.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "danger", children: "conflict" }) : x.ahead ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Tag, { tone: "info", children: [
|
|
3264
|
+
x.files.length,
|
|
3265
|
+
" file",
|
|
3266
|
+
x.files.length === 1 ? "" : "s"
|
|
3267
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "quiet", children: "clean" })
|
|
3268
|
+
] }, x.agentId)) }),
|
|
3269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-merge-main", children: ag ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
3270
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-merge-head", children: [
|
|
3271
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
3272
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: ag.name }),
|
|
3273
|
+
" ",
|
|
3274
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mono", children: ag.branch || "" }),
|
|
3275
|
+
ag.ahead ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-note", style: { margin: "0 0 0 8px" }, children: [
|
|
3276
|
+
ag.ahead,
|
|
3277
|
+
" commit(s) ahead"
|
|
3278
|
+
] }) : null
|
|
3279
|
+
] }),
|
|
3280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-actions", style: { margin: 0 }, children: confirm ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-confirm-text", children: confirm === "merge" ? `Merge ${ag.files.length} file(s) into the main workspace?` : `Discard ${ag.name}'s branch and worktree?` }),
|
|
3282
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", onClick: () => setConfirm(null), children: "Cancel" }),
|
|
3283
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "primary", disabled: busy, onClick: () => run(confirm), children: busy ? "Working\u2026" : confirm === "merge" ? "Confirm merge" : "Confirm discard" })
|
|
3284
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
3285
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "ghost", className: "rm-danger", disabled: !ag.branch || busy, onClick: () => setConfirm("discard"), children: "Discard" }),
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeIcon, {}), disabled: !ag.ahead || busy, onClick: () => setConfirm("merge"), children: "Merge into main" })
|
|
3287
|
+
] }) })
|
|
3288
|
+
] }),
|
|
3289
|
+
result ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: result.ok ? "rm-ok" : "rm-error", children: result.text }) : null,
|
|
3290
|
+
ag.conflicts && ag.conflicts.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-error", children: [
|
|
3291
|
+
"Would conflict with the main workspace: ",
|
|
3292
|
+
ag.conflicts.join(", "),
|
|
3293
|
+
" \u2014 resolve on the branch or discard."
|
|
3294
|
+
] }) : null,
|
|
3295
|
+
ag.mainDirty && ag.mainDirty.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-error", children: [
|
|
3296
|
+
"Uncommitted changes in the main workspace touch: ",
|
|
3297
|
+
ag.mainDirty.join(", ")
|
|
3298
|
+
] }) : null,
|
|
3299
|
+
ag.files && ag.files.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-merge-files", children: ag.files.map((f) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-merge-file", children: [
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-mono", children: f.path }),
|
|
3301
|
+
" ",
|
|
3302
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-diff-addn", children: [
|
|
3303
|
+
"+",
|
|
3304
|
+
f.adds
|
|
3305
|
+
] }),
|
|
3306
|
+
" ",
|
|
3307
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-diff-deln", children: [
|
|
3308
|
+
"\u2212",
|
|
3309
|
+
f.dels
|
|
3310
|
+
] })
|
|
3311
|
+
] }, f.path)) }) : null,
|
|
3312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffView, { patch: ag.patch }),
|
|
3313
|
+
ag.truncated ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rm-note", children: "Diff truncated." }) : null
|
|
3314
|
+
] }) : null })
|
|
3315
|
+
] }) })
|
|
3316
|
+
}
|
|
3317
|
+
);
|
|
3318
|
+
}
|
|
2370
3319
|
function EmptyMain({ store }) {
|
|
2371
3320
|
const a = store.actions;
|
|
2372
3321
|
const workspaces = useNativeWorkspaces(store);
|
|
@@ -2426,11 +3375,25 @@ function RoomsMain({ store }) {
|
|
|
2426
3375
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-chat-header-title", children: room.name }),
|
|
2427
3376
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-chat-header-sub", children: [
|
|
2428
3377
|
room.members.filter((m) => m.online !== false).length,
|
|
2429
|
-
" online
|
|
3378
|
+
" online",
|
|
3379
|
+
room.local && room.local.agents.length ? ` \xB7 ${room.local.agents.length} local agent${room.local.agents.length === 1 ? "" : "s"}` : "",
|
|
3380
|
+
" \xB7 ",
|
|
2430
3381
|
room.public ? "public" : "private",
|
|
2431
3382
|
room.status !== "online" ? ` \xB7 room ${room.status}` : ""
|
|
2432
3383
|
] })
|
|
2433
3384
|
] }),
|
|
3385
|
+
(() => {
|
|
3386
|
+
const act = (room.runs || []).filter((r) => r.state === "running" || r.state === "queued" || r.state === "approval");
|
|
3387
|
+
if (!act.length) return null;
|
|
3388
|
+
const running = act.filter((r) => r.state === "running").length;
|
|
3389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "rm-stop-btn", "data-rm-stop": "", title: "Stop all local agent runs", onClick: () => store.actions.stop(room.roomId).then((r) => store.actions.toast(`Stopped ${r.stopped} run(s)`)).catch((e) => store.actions.toast(e.message)), children: [
|
|
3390
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StopIcon, {}),
|
|
3391
|
+
"Stop \xB7 ",
|
|
3392
|
+
running,
|
|
3393
|
+
" running",
|
|
3394
|
+
act.length > running ? `, ${act.length - running} queued` : ""
|
|
3395
|
+
] });
|
|
3396
|
+
})(),
|
|
2434
3397
|
room.public ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "rm-badge rm-badge-public", children: [
|
|
2435
3398
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GlobeIcon, {}),
|
|
2436
3399
|
"Public"
|
|
@@ -2438,10 +3401,10 @@ function RoomsMain({ store }) {
|
|
|
2438
3401
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LockIcon, {}),
|
|
2439
3402
|
"Private"
|
|
2440
3403
|
] }),
|
|
2441
|
-
room.transport === "lan" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-badge", children: "LAN/VPS" }) : null,
|
|
3404
|
+
room.transport === "local" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-badge rm-badge-local", children: "Local only" }) : room.transport === "lan" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rm-badge", children: "LAN/VPS" }) : null,
|
|
2442
3405
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: room.status === "online" ? "done" : room.status === "connecting" ? "ongoing" : "error", size: 8 })
|
|
2443
3406
|
] }),
|
|
2444
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatBody, { messages }),
|
|
3407
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatBody, { messages, members: room.members }),
|
|
2445
3408
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Composer, { room, store, draft, setDraft })
|
|
2446
3409
|
] }),
|
|
2447
3410
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -2471,7 +3434,7 @@ function Field({ label, hint, children, htmlFor }) {
|
|
|
2471
3434
|
function CreateDialog({ store, d }) {
|
|
2472
3435
|
const s = useStore(store);
|
|
2473
3436
|
const a = store.actions;
|
|
2474
|
-
const [f, setF] = (0, import_react.useState)({ name: "", description: "", tags: "", public: false, mode: "lan", lanHostPort: "62.234.113.56:80" });
|
|
3437
|
+
const [f, setF] = (0, import_react.useState)({ name: "", description: "", tags: "", public: false, mode: "lan", lanHostPort: "62.234.113.56:80", localOnly: false, agents: [] });
|
|
2475
3438
|
const [err, setErr] = (0, import_react.useState)(null);
|
|
2476
3439
|
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
2477
3440
|
const [lanPeers, setLanPeers] = (0, import_react.useState)([]);
|
|
@@ -2494,7 +3457,9 @@ function CreateDialog({ store, d }) {
|
|
|
2494
3457
|
mode: f.mode,
|
|
2495
3458
|
lanHostPort: f.mode === "lan" ? f.lanHostPort.trim() : void 0,
|
|
2496
3459
|
workspacePath: ws.path,
|
|
2497
|
-
workspaceName: ws.title
|
|
3460
|
+
workspaceName: ws.title,
|
|
3461
|
+
localOnly: f.localOnly,
|
|
3462
|
+
agents: f.agents
|
|
2498
3463
|
});
|
|
2499
3464
|
} catch (e) {
|
|
2500
3465
|
setErr(e.message);
|
|
@@ -2544,12 +3509,29 @@ function CreateDialog({ store, d }) {
|
|
|
2544
3509
|
] }, p.hostPort))
|
|
2545
3510
|
] })
|
|
2546
3511
|
] }) }) : null,
|
|
3512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-span-2 rm-local-box", children: [
|
|
3513
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-switch-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
3514
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Local agents" }),
|
|
3515
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "Host several agents from this dsh as separate members (own identity, session, scope). Edit them later in room details." })
|
|
3516
|
+
] }) }),
|
|
3517
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-preset-row", children: [["moderator", "Moderator"], ["architect", "Architect"], ["coder", "Coder"], ["reviewer", "Reviewer"]].map(([k, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "rm-preset rm-preset-check" + (f.agents.includes(k) ? " is-on" : ""), children: [
|
|
3518
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: f.agents.includes(k), onChange: (e) => setF({ ...f, agents: e.target.checked ? [...f.agents, k] : f.agents.filter((x) => x !== k) }) }),
|
|
3519
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: label })
|
|
3520
|
+
] }, k)) }),
|
|
3521
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-switch-row", children: [
|
|
3522
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
3523
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "Local only (no network)" }),
|
|
3524
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: "In-process loopback \u2014 nothing leaves this machine. One click to switch to Relay/LAN later." })
|
|
3525
|
+
] }),
|
|
3526
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.localOnly, onChange: (v) => setF({ ...f, localOnly: v, public: v ? false : f.public }), label: "Local only" })
|
|
3527
|
+
] })
|
|
3528
|
+
] }),
|
|
2547
3529
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rm-span-2 rm-switch-row", children: [
|
|
2548
3530
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
2549
3531
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-label", children: "List in public directory" }),
|
|
2550
3532
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-field-hint", children: f.public ? "Anyone can find and join \u2014 key is published with the listing." : "Private: invite only." })
|
|
2551
3533
|
] }),
|
|
2552
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.public, onChange: (v) => setF({ ...f, public: v }), label: "List in public directory" })
|
|
3534
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Switch, { checked: f.public, onChange: (v) => setF({ ...f, public: v, localOnly: v ? false : f.localOnly }), label: "List in public directory" })
|
|
2553
3535
|
] }),
|
|
2554
3536
|
err ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rm-span-2 rm-error", children: err }) : null
|
|
2555
3537
|
] })
|
|
@@ -2891,6 +3873,8 @@ function Overlay({ store }) {
|
|
|
2891
3873
|
d?.kind === "config" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfigDialog, { store, d }) : null,
|
|
2892
3874
|
d?.kind === "workspace" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceDialog, { store }) : null,
|
|
2893
3875
|
d?.kind === "browse" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BrowseDialog, { store }) : null,
|
|
3876
|
+
d?.kind === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentDialog, { store, d }) : null,
|
|
3877
|
+
d?.kind === "merge" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergeDialog, { store, d }) : null,
|
|
2894
3878
|
s.toast ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Toast, { text: s.toast, onDone: store.actions.clearToast, holdMs: 2200 }) : null
|
|
2895
3879
|
] });
|
|
2896
3880
|
}
|