@yejiming/dsh-data-agent 0.0.2 → 0.0.3

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/lib/client.js CHANGED
@@ -64,7 +64,7 @@ window.__ModuleLoader__.load({
64
64
  }
65
65
  //#endregion
66
66
  //#region \0dsh-css:/Users/yejiming/Desktop/OpenSource/dsh-data-agent/src/client/DataAgentWorkbench.module.css.mjs
67
- const css = ".Sv3uVW_workbench{box-sizing:border-box;font-family:var(--dsw-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif);color:var(--dsw-alias-label-primary,inherit);flex-direction:column;gap:10px;font-size:13px;line-height:1.5;display:flex}.Sv3uVW_strip{width:100%}.Sv3uVW_docked{width:100%;max-height:55vh;overflow-y:auto}.Sv3uVW_rail{z-index:8;border-right:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-specific-sidebar-fill,var(--dsw-alias-bg-layer-1,#ffffff08));padding:12px;overflow-y:auto}html.Sv3uVW_da-split [data-phase=active] [data-conversation-scroll]>:first-child{margin-left:380px}html.Sv3uVW_da-split [data-phase=active] [data-composer-seat]{padding-left:380px}.Sv3uVW_sections{flex-direction:column;gap:12px;display:flex}.Sv3uVW_card{border:1px solid var(--dsw-alias-border-l2,#80808059);border-radius:12px;flex-direction:column;gap:10px;padding:12px 14px;display:flex}.Sv3uVW_cardTitle{text-transform:uppercase;letter-spacing:.06em;color:var(--dsw-alias-label-tertiary,#808080b3);align-items:center;gap:6px;font-size:11px;font-weight:600;display:flex}.Sv3uVW_titleIcon{width:14px;height:14px;color:var(--dsw-alias-label-secondary,#808080cc);flex:none}.Sv3uVW_fieldGrid{flex-direction:column;gap:10px;display:flex}.Sv3uVW_fieldRow2{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;display:grid}.Sv3uVW_field{flex-direction:column;gap:4px;min-width:0;display:flex}.Sv3uVW_label{color:var(--dsw-alias-label-secondary,#808080b3);font-size:11px;font-weight:500}.Sv3uVW_rememberRow{color:var(--dsw-alias-label-primary,inherit);cursor:pointer;user-select:none;align-items:center;gap:6px;font-size:12px;display:flex}.Sv3uVW_rememberRow input[type=checkbox]{width:14px;height:14px;accent-color:var(--dsw-alias-button-info-fill,#3b82f6);cursor:pointer;flex:none;margin:0}.Sv3uVW_rememberHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11px}.Sv3uVW_input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;height:32px;color:var(--dsw-alias-label-primary,inherit);font:inherit;border-radius:8px;padding:0 10px;font-size:13px;transition:border-color .15s ease-out,box-shadow .15s ease-out}.Sv3uVW_input::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_input:focus-visible,.Sv3uVW_input:focus{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_input:disabled{opacity:.55}select.Sv3uVW_input{-webkit-appearance:none;appearance:none;cursor:pointer;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' fill='none' stroke='%23777' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 10px center;background-repeat:no-repeat;padding-right:28px}.Sv3uVW_actions{align-items:center;gap:8px;margin-top:2px;display:flex}.Sv3uVW_actions>.Sv3uVW_primary,.Sv3uVW_actions>.Sv3uVW_ghost{flex:1}.Sv3uVW_primary,.Sv3uVW_ghost{height:32px;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;justify-content:center;align-items:center;gap:6px;padding:0 14px;font-size:13px;font-weight:500;transition:background-color .15s ease-out,border-color .15s ease-out,opacity .15s ease-out;display:inline-flex}.Sv3uVW_primary{background:var(--dsw-alias-button-info-fill,#3b82f6);color:#fff}.Sv3uVW_primary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover,#3573e0)}.Sv3uVW_primary:active:not(:disabled){background:var(--dsw-static-deepseek-600,#2f5fc0)}.Sv3uVW_ghost{border-color:var(--dsw-alias-border-l2,#80808059);color:var(--dsw-alias-label-primary,inherit);background:0 0}.Sv3uVW_ghost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_ghost:active:not(:disabled){background:var(--dsw-alias-interactive-bg-active,#80808024)}.Sv3uVW_primary:focus-visible,.Sv3uVW_ghost:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 25%, transparent);outline:none}.Sv3uVW_primary:disabled,.Sv3uVW_ghost:disabled{opacity:.45;cursor:default}.Sv3uVW_small{border-radius:6px;height:24px;padding:0 10px;font-size:12px}.Sv3uVW_hint{color:var(--dsw-alias-label-tertiary,#80808099);font-size:12px}.Sv3uVW_summaryRow{align-items:center;gap:8px;min-height:28px;display:flex}.Sv3uVW_statusOk{color:var(--dsw-alias-state-success-primary,#22c55e);flex:none;align-items:center;gap:5px;font-size:12px;font-weight:500;display:inline-flex}.Sv3uVW_summaryType{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:2px 8px;font-size:11px}.Sv3uVW_summaryDb{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);flex:1;font-size:12px;overflow:hidden}.Sv3uVW_summaryActions{flex:none;gap:6px;display:flex}.Sv3uVW_browseRow{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;height:36px;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;border-radius:8px;align-items:center;gap:8px;padding:0 12px;font-size:13px;font-weight:500;transition:background-color .15s ease-out,border-color .15s ease-out;display:flex}.Sv3uVW_browseRow:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014);border-color:var(--dsw-alias-border-l3,#80808080)}.Sv3uVW_browseRow:focus-visible{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_browseIcon{width:14px;height:14px;color:var(--dsw-alias-button-info-fill,#3b82f6);flex:none}.Sv3uVW_browseChevron{width:12px;height:12px;color:var(--dsw-alias-label-tertiary,#80808099);flex:none;margin-left:auto}.Sv3uVW_sqlInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;min-height:190px;color:var(--dsw-alias-label-primary,inherit);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);resize:vertical;border-radius:10px;padding:10px 12px;font-size:12.5px;line-height:1.6;transition:border-color .15s ease-out,box-shadow .15s ease-out}.Sv3uVW_sqlInput::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_sqlInput:focus-visible,.Sv3uVW_sqlInput:focus{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_sqlInput:disabled{opacity:.55}.Sv3uVW_sqlActions{justify-content:flex-end;align-items:center;gap:10px;display:flex}.Sv3uVW_sqlActions .Sv3uVW_primary{flex:none;min-width:92px}.Sv3uVW_shortcutHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11.5px}.Sv3uVW_sqlResult{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-markdown-code-block,#ffffff0a);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);white-space:pre-wrap;word-break:break-word;border-radius:8px;max-height:200px;margin:0;padding:10px 12px;font-size:11.5px;line-height:1.55;overflow-y:auto}.Sv3uVW_errorBar{border:1px solid var(--dsw-alias-state-error-secondary,#ef444480);background:var(--dsw-alias-interactive-bg-hover-danger,#ef444414);border-radius:10px;flex-direction:column;gap:3px;padding:10px 12px;display:flex}.Sv3uVW_errorHead{color:var(--dsw-alias-state-error-primary,#ef4444);align-items:center;gap:6px;font-size:12px;font-weight:600;display:flex}.Sv3uVW_errorIcon{flex:none;width:14px;height:14px}.Sv3uVW_errorText{white-space:pre-wrap;word-break:break-word;font-size:12px}.Sv3uVW_schemaModal{width:min(900px,94vw)}.Sv3uVW_modalBody{align-items:stretch;gap:20px;height:min(540px,58vh);display:flex}.Sv3uVW_modalCol{flex-direction:column;flex:1;gap:8px;min-width:0;min-height:0;display:flex}.Sv3uVW_modalColTitle{text-transform:uppercase;letter-spacing:.06em;color:var(--dsw-alias-label-tertiary,#808080b3);flex:none;align-items:center;gap:6px;font-size:11px;font-weight:600;display:flex}.Sv3uVW_colCount{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:1px 7px;font-size:10px;font-weight:500}.Sv3uVW_treeScroll{flex:1;min-height:0;padding-right:4px;overflow-y:auto}.Sv3uVW_tree{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}.Sv3uVW_treeNode{flex-direction:column;display:flex}.Sv3uVW_treeItem{width:100%;min-height:28px;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:7px;align-items:center;gap:6px;padding:0 8px;font-size:12.5px;display:flex}.Sv3uVW_treeItem:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_treeItem.Sv3uVW_active,.Sv3uVW_treeItem.Sv3uVW_active:hover{background:var(--dsw-alias-interactive-bg-active,#3b82f62e)}.Sv3uVW_treeChevron{width:12px;height:12px;color:var(--dsw-alias-label-tertiary,#80808099);flex:none;transition:transform .15s ease-out}.Sv3uVW_treeChevron.Sv3uVW_open{transform:rotate(90deg)}.Sv3uVW_treeIcon{width:14px;height:14px;color:var(--dsw-alias-label-secondary,#808080cc);flex:none}.Sv3uVW_treeItem.Sv3uVW_active .Sv3uVW_treeIcon{color:var(--dsw-alias-button-info-fill,#3b82f6)}.Sv3uVW_treeName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);flex:1;font-size:12px;overflow:hidden}.Sv3uVW_treeCount{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:0 6px;font-size:10px}.Sv3uVW_treeChildren{border-left:1px solid var(--dsw-alias-border-l2,#80808059);flex-direction:column;gap:1px;margin-left:12px;padding-left:10px;display:flex}.Sv3uVW_colScroll{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:8px;flex:1;min-height:0;overflow:auto}.Sv3uVW_columnsTable{border-collapse:collapse;width:100%;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:12px}.Sv3uVW_columnsTable th{z-index:1;text-align:left;text-transform:uppercase;letter-spacing:.05em;color:var(--dsw-alias-label-tertiary,#808080b3);background:var(--dsw-alias-bg-layer-2,#ffffff0a);border-bottom:1px solid var(--dsw-alias-border-l2,#80808059);padding:7px 10px;font-size:10.5px;font-weight:600;position:sticky;top:0}.Sv3uVW_columnsTable td{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);color:var(--dsw-alias-label-primary,inherit);padding:5px 10px}.Sv3uVW_columnsTable tbody tr:hover td{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_typeCell{color:var(--dsw-alias-label-secondary,#808080cc)}.Sv3uVW_nullCell{color:var(--dsw-alias-label-caption,#80808080);font-size:11px}.Sv3uVW_emptyState{border:1px dashed var(--dsw-alias-border-l2,#80808059);min-height:0;color:var(--dsw-alias-label-tertiary,#808080b3);border-radius:8px;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;display:flex}.Sv3uVW_emptyStateIcon{width:20px;height:20px;color:var(--dsw-alias-label-dimmed,#80808066)}.Sv3uVW_emptyStateText{font-size:12px}.Sv3uVW_modalHint{color:var(--dsw-alias-label-caption,#80808080);flex:none;align-items:center;gap:6px;margin-top:2px;font-size:11.5px;display:flex}@media (width<=640px){.Sv3uVW_modalBody{flex-direction:column;height:auto}.Sv3uVW_treeScroll{flex:none;height:300px}.Sv3uVW_colScroll{flex:none;height:240px}.Sv3uVW_emptyState{flex:none;height:120px}}";
67
+ const css = ".Sv3uVW_workbench{box-sizing:border-box;font-family:var(--dsw-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif);color:var(--dsw-alias-label-primary,inherit);flex-direction:column;gap:10px;font-size:13px;line-height:1.5;display:flex}.Sv3uVW_strip{width:100%}.Sv3uVW_docked{width:100%;max-height:55vh;overflow-y:auto}.Sv3uVW_rail{z-index:8;border-right:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-specific-sidebar-fill,var(--dsw-alias-bg-layer-1,#ffffff08));padding:12px;overflow-y:auto}html.Sv3uVW_da-split [data-phase=active] [data-conversation-scroll]>:first-child{margin-left:380px}html.Sv3uVW_da-split [data-phase=active] [data-composer-seat]{padding-left:380px}.Sv3uVW_sections{flex-direction:column;gap:12px;display:flex}.Sv3uVW_card{border:1px solid var(--dsw-alias-border-l2,#80808059);border-radius:12px;flex-direction:column;gap:10px;padding:12px 14px;display:flex}.Sv3uVW_cardTitle{text-transform:uppercase;letter-spacing:.06em;color:var(--dsw-alias-label-tertiary,#808080b3);align-items:center;gap:6px;font-size:11px;font-weight:600;display:flex}.Sv3uVW_titleIcon{width:14px;height:14px;color:var(--dsw-alias-label-secondary,#808080cc);flex:none}.Sv3uVW_fieldGrid{flex-direction:column;gap:10px;display:flex}.Sv3uVW_fieldRow2{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;display:grid}.Sv3uVW_field{flex-direction:column;gap:4px;min-width:0;display:flex}.Sv3uVW_label{color:var(--dsw-alias-label-secondary,#808080b3);font-size:11px;font-weight:500}.Sv3uVW_rememberRow{color:var(--dsw-alias-label-primary,inherit);cursor:pointer;user-select:none;align-items:center;gap:6px;font-size:12px;display:flex}.Sv3uVW_rememberRow input[type=checkbox]{width:14px;height:14px;accent-color:var(--dsw-alias-button-info-fill,#3b82f6);cursor:pointer;flex:none;margin:0}.Sv3uVW_rememberHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11px}.Sv3uVW_input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;height:32px;color:var(--dsw-alias-label-primary,inherit);font:inherit;border-radius:8px;padding:0 10px;font-size:13px;transition:border-color .15s ease-out,box-shadow .15s ease-out}.Sv3uVW_input::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_input:focus-visible,.Sv3uVW_input:focus{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_input:disabled{opacity:.55}select.Sv3uVW_input{-webkit-appearance:none;appearance:none;cursor:pointer;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' fill='none' stroke='%23777' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 10px center;background-repeat:no-repeat;padding-right:28px}.Sv3uVW_actions{align-items:center;gap:8px;margin-top:2px;display:flex}.Sv3uVW_actions>.Sv3uVW_primary,.Sv3uVW_actions>.Sv3uVW_ghost{flex:1}.Sv3uVW_primary,.Sv3uVW_ghost{height:32px;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;justify-content:center;align-items:center;gap:6px;padding:0 14px;font-size:13px;font-weight:500;transition:background-color .15s ease-out,border-color .15s ease-out,opacity .15s ease-out;display:inline-flex}.Sv3uVW_primary{background:var(--dsw-alias-button-info-fill,#3b82f6);color:#fff}.Sv3uVW_primary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover,#3573e0)}.Sv3uVW_primary:active:not(:disabled){background:var(--dsw-static-deepseek-600,#2f5fc0)}.Sv3uVW_ghost{border-color:var(--dsw-alias-border-l2,#80808059);color:var(--dsw-alias-label-primary,inherit);background:0 0}.Sv3uVW_ghost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_ghost:active:not(:disabled){background:var(--dsw-alias-interactive-bg-active,#80808024)}.Sv3uVW_primary:focus-visible,.Sv3uVW_ghost:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 25%, transparent);outline:none}.Sv3uVW_primary:disabled,.Sv3uVW_ghost:disabled{opacity:.45;cursor:default}.Sv3uVW_small{border-radius:6px;height:24px;padding:0 10px;font-size:12px}.Sv3uVW_hint{color:var(--dsw-alias-label-tertiary,#80808099);font-size:12px}.Sv3uVW_summaryRow{align-items:center;gap:8px;min-height:28px;display:flex}.Sv3uVW_statusOk{color:var(--dsw-alias-state-success-primary,#22c55e);flex:none;align-items:center;gap:5px;font-size:12px;font-weight:500;display:inline-flex}.Sv3uVW_summaryType{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:2px 8px;font-size:11px}.Sv3uVW_summaryDb{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);flex:1;font-size:12px;overflow:hidden}.Sv3uVW_summaryActions{flex:none;gap:6px;display:flex}.Sv3uVW_heroConnect{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;border-radius:10px;align-items:center;gap:12px;padding:14px 16px;transition:background-color .15s ease-out,border-color .15s ease-out;display:flex}.Sv3uVW_heroConnect:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014);border-color:var(--dsw-alias-border-l3,#80808080)}.Sv3uVW_heroConnect:focus-visible{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_heroIcon{width:22px;height:22px;color:var(--dsw-alias-button-info-fill,#3b82f6);flex:none}.Sv3uVW_heroText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.Sv3uVW_heroTitle{color:var(--dsw-alias-label-primary,inherit);font-size:13px;font-weight:600}.Sv3uVW_heroHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11.5px;line-height:1.5}.Sv3uVW_heroChevron{width:12px;height:12px;color:var(--dsw-alias-label-tertiary,#80808099);flex:none}.Sv3uVW_browseRow{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;height:36px;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;border-radius:8px;align-items:center;gap:8px;padding:0 12px;font-size:13px;font-weight:500;transition:background-color .15s ease-out,border-color .15s ease-out;display:flex}.Sv3uVW_browseRow:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014);border-color:var(--dsw-alias-border-l3,#80808080)}.Sv3uVW_browseRow:focus-visible{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_browseIcon{width:14px;height:14px;color:var(--dsw-alias-button-info-fill,#3b82f6);flex:none}.Sv3uVW_browseChevron{width:12px;height:12px;color:var(--dsw-alias-label-tertiary,#80808099);flex:none;margin-left:auto}.Sv3uVW_sqlInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;min-height:190px;color:var(--dsw-alias-label-primary,inherit);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);resize:vertical;border-radius:10px;padding:10px 12px;font-size:12.5px;line-height:1.6;transition:border-color .15s ease-out,box-shadow .15s ease-out}.Sv3uVW_sqlInput::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_sqlInput:focus-visible,.Sv3uVW_sqlInput:focus{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_sqlInput:disabled{opacity:.55}.Sv3uVW_sqlActions{justify-content:flex-end;align-items:center;gap:10px;display:flex}.Sv3uVW_sqlActions .Sv3uVW_primary{flex:none;min-width:92px}.Sv3uVW_shortcutHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11.5px}.Sv3uVW_sqlResult{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-markdown-code-block,#ffffff0a);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);white-space:pre-wrap;word-break:break-word;border-radius:8px;max-height:200px;margin:0;padding:10px 12px;font-size:11.5px;line-height:1.55;overflow-y:auto}.Sv3uVW_errorBar{border:1px solid var(--dsw-alias-state-error-secondary,#ef444480);background:var(--dsw-alias-interactive-bg-hover-danger,#ef444414);border-radius:10px;flex-direction:column;gap:3px;padding:10px 12px;display:flex}.Sv3uVW_errorHead{color:var(--dsw-alias-state-error-primary,#ef4444);align-items:center;gap:6px;font-size:12px;font-weight:600;display:flex}.Sv3uVW_errorIcon{flex:none;width:14px;height:14px}.Sv3uVW_errorText{white-space:pre-wrap;word-break:break-word;font-size:12px}.Sv3uVW_connectModal{width:min(440px,92vw)}.Sv3uVW_connectModalBody{flex-direction:column;gap:14px;display:flex}.Sv3uVW_schemaModal{width:min(900px,94vw)}.Sv3uVW_modalBody{align-items:stretch;gap:20px;height:min(540px,58vh);display:flex}.Sv3uVW_modalCol{flex-direction:column;flex:1;gap:8px;min-width:0;min-height:0;display:flex}.Sv3uVW_modalColTitle{text-transform:uppercase;letter-spacing:.06em;color:var(--dsw-alias-label-tertiary,#808080b3);flex:none;align-items:center;gap:6px;font-size:11px;font-weight:600;display:flex}.Sv3uVW_colCount{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:1px 7px;font-size:10px;font-weight:500}.Sv3uVW_treeScroll{flex:1;min-height:0;padding-right:4px;overflow-y:auto}.Sv3uVW_tree{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}.Sv3uVW_treeNode{flex-direction:column;display:flex}.Sv3uVW_treeItem{width:100%;min-height:28px;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:7px;align-items:center;gap:6px;padding:0 8px;font-size:12.5px;display:flex}.Sv3uVW_treeItem:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_treeItem.Sv3uVW_active,.Sv3uVW_treeItem.Sv3uVW_active:hover{background:var(--dsw-alias-interactive-bg-active,#3b82f62e)}.Sv3uVW_treeChevron{width:12px;height:12px;color:var(--dsw-alias-label-tertiary,#80808099);flex:none;transition:transform .15s ease-out}.Sv3uVW_treeChevron.Sv3uVW_open{transform:rotate(90deg)}.Sv3uVW_treeIcon{width:14px;height:14px;color:var(--dsw-alias-label-secondary,#808080cc);flex:none}.Sv3uVW_treeItem.Sv3uVW_active .Sv3uVW_treeIcon{color:var(--dsw-alias-button-info-fill,#3b82f6)}.Sv3uVW_treeName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);flex:1;font-size:12px;overflow:hidden}.Sv3uVW_treeCount{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:0 6px;font-size:10px}.Sv3uVW_treeChildren{border-left:1px solid var(--dsw-alias-border-l2,#80808059);flex-direction:column;gap:1px;margin-left:12px;padding-left:10px;display:flex}.Sv3uVW_colScroll{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:8px;flex:1;min-height:0;overflow:auto}.Sv3uVW_columnsTable{border-collapse:collapse;width:100%;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:12px}.Sv3uVW_columnsTable th{z-index:1;text-align:left;text-transform:uppercase;letter-spacing:.05em;color:var(--dsw-alias-label-tertiary,#808080b3);background:var(--dsw-alias-bg-layer-2,#ffffff0a);border-bottom:1px solid var(--dsw-alias-border-l2,#80808059);padding:7px 10px;font-size:10.5px;font-weight:600;position:sticky;top:0}.Sv3uVW_columnsTable td{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);color:var(--dsw-alias-label-primary,inherit);padding:5px 10px}.Sv3uVW_columnsTable tbody tr:hover td{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_typeCell{color:var(--dsw-alias-label-secondary,#808080cc)}.Sv3uVW_nullCell{color:var(--dsw-alias-label-caption,#80808080);font-size:11px}.Sv3uVW_emptyState{border:1px dashed var(--dsw-alias-border-l2,#80808059);min-height:0;color:var(--dsw-alias-label-tertiary,#808080b3);border-radius:8px;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;display:flex}.Sv3uVW_emptyStateIcon{width:20px;height:20px;color:var(--dsw-alias-label-dimmed,#80808066)}.Sv3uVW_emptyStateText{font-size:12px}.Sv3uVW_modalHint{color:var(--dsw-alias-label-caption,#80808080);flex:none;align-items:center;gap:6px;margin-top:2px;font-size:11.5px;display:flex}@media (width<=640px){.Sv3uVW_modalBody{flex-direction:column;height:auto}.Sv3uVW_treeScroll{flex:none;height:300px}.Sv3uVW_colScroll{flex:none;height:240px}.Sv3uVW_emptyState{flex:none;height:120px}}";
68
68
  const tagId = "@yejiming/dsh-data-agent/DataAgentWorkbench.module.css";
69
69
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
70
70
  const tag = document.createElement("style");
@@ -74,67 +74,75 @@ window.__ModuleLoader__.load({
74
74
  document.head.appendChild(tag);
75
75
  }
76
76
  var DataAgentWorkbench_module_css_default = {
77
- "da-split": "Sv3uVW_da-split",
78
- "treeCount": "Sv3uVW_treeCount",
79
- "treeName": "Sv3uVW_treeName",
80
- "treeNode": "Sv3uVW_treeNode",
81
- "rememberRow": "Sv3uVW_rememberRow",
82
- "summaryType": "Sv3uVW_summaryType",
83
- "rail": "Sv3uVW_rail",
84
- "open": "Sv3uVW_open",
85
- "treeChevron": "Sv3uVW_treeChevron",
86
- "label": "Sv3uVW_label",
87
- "browseRow": "Sv3uVW_browseRow",
88
- "titleIcon": "Sv3uVW_titleIcon",
89
- "columnsTable": "Sv3uVW_columnsTable",
90
- "colCount": "Sv3uVW_colCount",
91
- "emptyStateIcon": "Sv3uVW_emptyStateIcon",
92
77
  "input": "Sv3uVW_input",
93
- "browseChevron": "Sv3uVW_browseChevron",
94
- "fieldGrid": "Sv3uVW_fieldGrid",
95
- "sqlInput": "Sv3uVW_sqlInput",
96
- "modalColTitle": "Sv3uVW_modalColTitle",
97
- "primary": "Sv3uVW_primary",
78
+ "emptyStateIcon": "Sv3uVW_emptyStateIcon",
79
+ "field": "Sv3uVW_field",
80
+ "browseRow": "Sv3uVW_browseRow",
98
81
  "treeScroll": "Sv3uVW_treeScroll",
99
- "treeItem": "Sv3uVW_treeItem",
100
82
  "treeIcon": "Sv3uVW_treeIcon",
83
+ "summaryRow": "Sv3uVW_summaryRow",
84
+ "heroHint": "Sv3uVW_heroHint",
85
+ "fieldGrid": "Sv3uVW_fieldGrid",
86
+ "heroChevron": "Sv3uVW_heroChevron",
87
+ "browseIcon": "Sv3uVW_browseIcon",
88
+ "sqlActions": "Sv3uVW_sqlActions",
89
+ "errorHead": "Sv3uVW_errorHead",
90
+ "modalCol": "Sv3uVW_modalCol",
91
+ "colScroll": "Sv3uVW_colScroll",
92
+ "heroConnect": "Sv3uVW_heroConnect",
93
+ "connectModalBody": "Sv3uVW_connectModalBody",
94
+ "strip": "Sv3uVW_strip",
95
+ "sqlInput": "Sv3uVW_sqlInput",
96
+ "rememberHint": "Sv3uVW_rememberHint",
97
+ "fieldRow2": "Sv3uVW_fieldRow2",
98
+ "rememberRow": "Sv3uVW_rememberRow",
99
+ "statusOk": "Sv3uVW_statusOk",
101
100
  "typeCell": "Sv3uVW_typeCell",
101
+ "summaryDb": "Sv3uVW_summaryDb",
102
+ "rail": "Sv3uVW_rail",
103
+ "da-split": "Sv3uVW_da-split",
104
+ "colCount": "Sv3uVW_colCount",
105
+ "errorBar": "Sv3uVW_errorBar",
106
+ "treeItem": "Sv3uVW_treeItem",
107
+ "sections": "Sv3uVW_sections",
108
+ "cardTitle": "Sv3uVW_cardTitle",
109
+ "errorText": "Sv3uVW_errorText",
110
+ "docked": "Sv3uVW_docked",
111
+ "heroIcon": "Sv3uVW_heroIcon",
112
+ "primary": "Sv3uVW_primary",
113
+ "card": "Sv3uVW_card",
114
+ "ghost": "Sv3uVW_ghost",
102
115
  "tree": "Sv3uVW_tree",
103
- "emptyStateText": "Sv3uVW_emptyStateText",
116
+ "titleIcon": "Sv3uVW_titleIcon",
104
117
  "small": "Sv3uVW_small",
105
- "sqlActions": "Sv3uVW_sqlActions",
118
+ "actions": "Sv3uVW_actions",
119
+ "emptyStateText": "Sv3uVW_emptyStateText",
120
+ "label": "Sv3uVW_label",
106
121
  "active": "Sv3uVW_active",
107
- "summaryDb": "Sv3uVW_summaryDb",
108
- "errorIcon": "Sv3uVW_errorIcon",
109
- "cardTitle": "Sv3uVW_cardTitle",
110
- "treeChildren": "Sv3uVW_treeChildren",
111
- "browseIcon": "Sv3uVW_browseIcon",
112
- "sections": "Sv3uVW_sections",
113
- "modalHint": "Sv3uVW_modalHint",
114
- "statusOk": "Sv3uVW_statusOk",
115
122
  "summaryActions": "Sv3uVW_summaryActions",
116
- "rememberHint": "Sv3uVW_rememberHint",
117
- "colScroll": "Sv3uVW_colScroll",
118
- "ghost": "Sv3uVW_ghost",
119
- "card": "Sv3uVW_card",
120
- "nullCell": "Sv3uVW_nullCell",
121
- "errorText": "Sv3uVW_errorText",
122
- "field": "Sv3uVW_field",
123
+ "shortcutHint": "Sv3uVW_shortcutHint",
124
+ "treeNode": "Sv3uVW_treeNode",
125
+ "treeCount": "Sv3uVW_treeCount",
126
+ "treeChevron": "Sv3uVW_treeChevron",
127
+ "heroTitle": "Sv3uVW_heroTitle",
128
+ "open": "Sv3uVW_open",
129
+ "modalColTitle": "Sv3uVW_modalColTitle",
123
130
  "emptyState": "Sv3uVW_emptyState",
124
- "modalBody": "Sv3uVW_modalBody",
125
- "actions": "Sv3uVW_actions",
126
- "schemaModal": "Sv3uVW_schemaModal",
127
- "errorBar": "Sv3uVW_errorBar",
128
- "workbench": "Sv3uVW_workbench",
129
- "fieldRow2": "Sv3uVW_fieldRow2",
131
+ "modalHint": "Sv3uVW_modalHint",
132
+ "errorIcon": "Sv3uVW_errorIcon",
130
133
  "hint": "Sv3uVW_hint",
131
- "summaryRow": "Sv3uVW_summaryRow",
132
- "errorHead": "Sv3uVW_errorHead",
133
- "strip": "Sv3uVW_strip",
134
- "shortcutHint": "Sv3uVW_shortcutHint",
134
+ "nullCell": "Sv3uVW_nullCell",
135
+ "workbench": "Sv3uVW_workbench",
136
+ "schemaModal": "Sv3uVW_schemaModal",
137
+ "browseChevron": "Sv3uVW_browseChevron",
138
+ "connectModal": "Sv3uVW_connectModal",
139
+ "treeName": "Sv3uVW_treeName",
140
+ "modalBody": "Sv3uVW_modalBody",
135
141
  "sqlResult": "Sv3uVW_sqlResult",
136
- "docked": "Sv3uVW_docked",
137
- "modalCol": "Sv3uVW_modalCol"
142
+ "heroText": "Sv3uVW_heroText",
143
+ "summaryType": "Sv3uVW_summaryType",
144
+ "columnsTable": "Sv3uVW_columnsTable",
145
+ "treeChildren": "Sv3uVW_treeChildren"
138
146
  };
139
147
  //#endregion
140
148
  //#region src/client/DataAgentWorkbench.tsx
@@ -395,7 +403,7 @@ window.__ModuleLoader__.load({
395
403
  const [busy, setBusy] = (0, react.useState)(false);
396
404
  const [error, setError] = (0, react.useState)(null);
397
405
  const [connected, setConnected] = (0, react.useState)(false);
398
- const [configOpen, setConfigOpen] = (0, react.useState)(false);
406
+ const [connectModalOpen, setConnectModalOpen] = (0, react.useState)(false);
399
407
  const [restoring, setRestoring] = (0, react.useState)(false);
400
408
  const [schemaModalOpen, setSchemaModalOpen] = (0, react.useState)(false);
401
409
  const [schemas, setSchemas] = (0, react.useState)([]);
@@ -500,7 +508,7 @@ window.__ModuleLoader__.load({
500
508
  if (cancelled) return;
501
509
  if (result.ok) {
502
510
  setConnected(true);
503
- setConfigOpen(false);
511
+ setConnectModalOpen(false);
504
512
  const schemasBody = await (await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)).json();
505
513
  if (!cancelled && schemasBody.ok) setSchemas(schemasBody.schemas ?? []);
506
514
  } else setError(`连接恢复失败:${result.error ?? "unknown error"}`);
@@ -538,7 +546,7 @@ window.__ModuleLoader__.load({
538
546
  const result = await performConnect(sessionId, body);
539
547
  if (result.ok) {
540
548
  setConnected(true);
541
- setConfigOpen(false);
549
+ setConnectModalOpen(false);
542
550
  const schemasBody = await (await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)).json();
543
551
  if (schemasBody.ok) setSchemas(schemasBody.schemas ?? []);
544
552
  } else setError(result.error ?? "unknown error");
@@ -558,7 +566,6 @@ window.__ModuleLoader__.load({
558
566
  body: JSON.stringify({ sessionId })
559
567
  });
560
568
  setConnected(false);
561
- setConfigOpen(false);
562
569
  setReadonly(false);
563
570
  setSchemaModalOpen(false);
564
571
  setSchemas([]);
@@ -655,7 +662,7 @@ window.__ModuleLoader__.load({
655
662
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
656
663
  className: DataAgentWorkbench_module_css_default.sections,
657
664
  children: [
658
- connected && !configOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
665
+ connected ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
659
666
  className: DataAgentWorkbench_module_css_default.card,
660
667
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
661
668
  className: DataAgentWorkbench_module_css_default.summaryRow,
@@ -683,7 +690,7 @@ window.__ModuleLoader__.load({
683
690
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
684
691
  type: "button",
685
692
  className: `${DataAgentWorkbench_module_css_default.ghost} ${DataAgentWorkbench_module_css_default.small}`,
686
- onClick: () => setConfigOpen(true),
693
+ onClick: () => setConnectModalOpen(true),
687
694
  children: t("action.config")
688
695
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
689
696
  type: "button",
@@ -697,191 +704,27 @@ window.__ModuleLoader__.load({
697
704
  })
698
705
  ]
699
706
  })
700
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
707
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
701
708
  className: DataAgentWorkbench_module_css_default.card,
702
- children: [
703
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
704
- className: DataAgentWorkbench_module_css_default.cardTitle,
705
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DatabaseIcon, { className: DataAgentWorkbench_module_css_default.titleIcon }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.title") })]
706
- }),
707
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
708
- className: DataAgentWorkbench_module_css_default.fieldGrid,
709
- children: [
710
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
711
- className: DataAgentWorkbench_module_css_default.field,
712
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
713
- className: DataAgentWorkbench_module_css_default.label,
714
- children: t("form.type")
715
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
716
- className: DataAgentWorkbench_module_css_default.input,
717
- value: type,
718
- disabled: formDisabled,
719
- onChange: (event) => {
720
- const next = event.target.value;
721
- setType(next);
722
- setPort(next === "postgres" ? "5432" : next === "mysql" ? "3306" : next === "oracle" ? "1521" : next === "hive" ? "10000" : next === "impala" ? "21050" : "");
723
- },
724
- children: [
725
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
726
- value: "mysql",
727
- children: t("type.mysql")
728
- }),
729
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
730
- value: "postgres",
731
- children: t("type.postgres")
732
- }),
733
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
734
- value: "sqlite",
735
- children: t("type.sqlite")
736
- }),
737
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
738
- value: "oracle",
739
- children: t("type.oracle")
740
- }),
741
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
742
- value: "hive",
743
- children: t("type.hive")
744
- }),
745
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
746
- value: "impala",
747
- children: t("type.impala")
748
- })
749
- ]
750
- })]
751
- }),
752
- !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
753
- className: DataAgentWorkbench_module_css_default.fieldRow2,
754
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
755
- className: DataAgentWorkbench_module_css_default.field,
756
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
757
- className: DataAgentWorkbench_module_css_default.label,
758
- children: t("form.host")
759
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
760
- className: DataAgentWorkbench_module_css_default.input,
761
- type: "text",
762
- value: host,
763
- disabled: formDisabled,
764
- onChange: (event) => setHost(event.target.value)
765
- })]
766
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
767
- className: DataAgentWorkbench_module_css_default.field,
768
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
769
- className: DataAgentWorkbench_module_css_default.label,
770
- children: t("form.port")
771
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
772
- className: DataAgentWorkbench_module_css_default.input,
773
- type: "number",
774
- min: 1,
775
- max: 65535,
776
- value: port,
777
- disabled: formDisabled,
778
- onChange: (event) => setPort(event.target.value)
779
- })]
780
- })]
781
- }),
782
- !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
783
- className: DataAgentWorkbench_module_css_default.fieldRow2,
784
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
785
- className: DataAgentWorkbench_module_css_default.field,
786
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
787
- className: DataAgentWorkbench_module_css_default.label,
788
- children: t("form.user")
789
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
790
- className: DataAgentWorkbench_module_css_default.input,
791
- type: "text",
792
- value: user,
793
- disabled: formDisabled,
794
- onChange: (event) => setUser(event.target.value)
795
- })]
796
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
797
- className: DataAgentWorkbench_module_css_default.field,
798
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
799
- className: DataAgentWorkbench_module_css_default.label,
800
- children: t("form.password")
801
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
802
- className: DataAgentWorkbench_module_css_default.input,
803
- type: "password",
804
- value: password,
805
- autoComplete: "new-password",
806
- disabled: formDisabled,
807
- onChange: (event) => setPassword(event.target.value)
808
- })]
809
- })]
810
- }),
811
- !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
812
- className: DataAgentWorkbench_module_css_default.rememberRow,
813
- children: [
814
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
815
- type: "checkbox",
816
- checked: rememberPassword,
817
- disabled: formDisabled,
818
- onChange: (event) => setRememberPassword(event.target.checked)
819
- }),
820
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.rememberPassword") }),
821
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
822
- className: DataAgentWorkbench_module_css_default.rememberHint,
823
- children: t("form.rememberPassword.hint")
824
- })
825
- ]
826
- }),
827
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
828
- className: DataAgentWorkbench_module_css_default.rememberRow,
829
- children: [
830
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
831
- type: "checkbox",
832
- checked: readonly,
833
- disabled: formDisabled,
834
- onChange: (event) => setReadonly(event.target.checked)
835
- }),
836
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.readonly") }),
837
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
838
- className: DataAgentWorkbench_module_css_default.rememberHint,
839
- children: t("form.readonly.hint")
840
- })
841
- ]
842
- }),
843
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
844
- className: DataAgentWorkbench_module_css_default.field,
845
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
846
- className: DataAgentWorkbench_module_css_default.label,
847
- children: databaseLabel
848
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
849
- className: DataAgentWorkbench_module_css_default.input,
850
- type: "text",
851
- value: database,
852
- placeholder: sqlite ? t("form.database.sqlite.placeholder") : void 0,
853
- disabled: formDisabled,
854
- onChange: (event) => setDatabase(event.target.value)
855
- })]
856
- })
857
- ]
858
- }),
859
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
860
- className: DataAgentWorkbench_module_css_default.actions,
861
- children: !connected ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
862
- type: "button",
863
- className: DataAgentWorkbench_module_css_default.primary,
864
- disabled: busy || database === "" || !sqlite && host === "",
865
- onClick: () => {
866
- connect();
867
- },
868
- children: restoring ? t("state.reconnecting") : busy ? t("state.checking") : t("action.connect")
869
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
870
- type: "button",
871
- className: DataAgentWorkbench_module_css_default.ghost,
872
- onClick: () => setConfigOpen(false),
873
- children: t("action.collapse")
874
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
875
- type: "button",
876
- className: DataAgentWorkbench_module_css_default.ghost,
877
- disabled: busy,
878
- onClick: () => {
879
- disconnect();
880
- },
881
- children: t("action.disconnect")
882
- })] })
883
- })
884
- ]
709
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
710
+ type: "button",
711
+ className: DataAgentWorkbench_module_css_default.heroConnect,
712
+ onClick: () => setConnectModalOpen(true),
713
+ children: [
714
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DatabaseIcon, { className: DataAgentWorkbench_module_css_default.heroIcon }),
715
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
716
+ className: DataAgentWorkbench_module_css_default.heroText,
717
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
718
+ className: DataAgentWorkbench_module_css_default.heroTitle,
719
+ children: t("form.hero.title")
720
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
721
+ className: DataAgentWorkbench_module_css_default.heroHint,
722
+ children: t("form.hero.hint")
723
+ })]
724
+ }),
725
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronIcon, { className: DataAgentWorkbench_module_css_default.heroChevron })
726
+ ]
727
+ })
885
728
  }),
886
729
  connected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
887
730
  className: DataAgentWorkbench_module_css_default.card,
@@ -896,7 +739,7 @@ window.__ModuleLoader__.load({
896
739
  ]
897
740
  })
898
741
  }),
899
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
742
+ connected && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
900
743
  className: DataAgentWorkbench_module_css_default.card,
901
744
  children: [
902
745
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -940,7 +783,7 @@ window.__ModuleLoader__.load({
940
783
  })
941
784
  ]
942
785
  }),
943
- error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
786
+ error !== null && !connectModalOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
944
787
  className: DataAgentWorkbench_module_css_default.errorBar,
945
788
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
946
789
  className: DataAgentWorkbench_module_css_default.errorHead,
@@ -1054,6 +897,200 @@ window.__ModuleLoader__.load({
1054
897
  })]
1055
898
  })]
1056
899
  })
900
+ }),
901
+ connectModalOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
902
+ open: connectModalOpen,
903
+ onClose: () => setConnectModalOpen(false),
904
+ title: t("form.title"),
905
+ closeLabel: t("action.close"),
906
+ className: DataAgentWorkbench_module_css_default.connectModal,
907
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
908
+ className: DataAgentWorkbench_module_css_default.connectModalBody,
909
+ children: [
910
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
911
+ className: DataAgentWorkbench_module_css_default.fieldGrid,
912
+ children: [
913
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
914
+ className: DataAgentWorkbench_module_css_default.field,
915
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
916
+ className: DataAgentWorkbench_module_css_default.label,
917
+ children: t("form.type")
918
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
919
+ className: DataAgentWorkbench_module_css_default.input,
920
+ value: type,
921
+ disabled: formDisabled,
922
+ onChange: (event) => {
923
+ const next = event.target.value;
924
+ setType(next);
925
+ setPort(next === "postgres" ? "5432" : next === "mysql" ? "3306" : next === "oracle" ? "1521" : next === "hive" ? "10000" : next === "impala" ? "21050" : "");
926
+ },
927
+ children: [
928
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
929
+ value: "mysql",
930
+ children: t("type.mysql")
931
+ }),
932
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
933
+ value: "postgres",
934
+ children: t("type.postgres")
935
+ }),
936
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
937
+ value: "sqlite",
938
+ children: t("type.sqlite")
939
+ }),
940
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
941
+ value: "oracle",
942
+ children: t("type.oracle")
943
+ }),
944
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
945
+ value: "hive",
946
+ children: t("type.hive")
947
+ }),
948
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
949
+ value: "impala",
950
+ children: t("type.impala")
951
+ })
952
+ ]
953
+ })]
954
+ }),
955
+ !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
956
+ className: DataAgentWorkbench_module_css_default.fieldRow2,
957
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
958
+ className: DataAgentWorkbench_module_css_default.field,
959
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
960
+ className: DataAgentWorkbench_module_css_default.label,
961
+ children: t("form.host")
962
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
963
+ className: DataAgentWorkbench_module_css_default.input,
964
+ type: "text",
965
+ value: host,
966
+ disabled: formDisabled,
967
+ onChange: (event) => setHost(event.target.value)
968
+ })]
969
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
970
+ className: DataAgentWorkbench_module_css_default.field,
971
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
972
+ className: DataAgentWorkbench_module_css_default.label,
973
+ children: t("form.port")
974
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
975
+ className: DataAgentWorkbench_module_css_default.input,
976
+ type: "number",
977
+ min: 1,
978
+ max: 65535,
979
+ value: port,
980
+ disabled: formDisabled,
981
+ onChange: (event) => setPort(event.target.value)
982
+ })]
983
+ })]
984
+ }),
985
+ !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
986
+ className: DataAgentWorkbench_module_css_default.fieldRow2,
987
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
988
+ className: DataAgentWorkbench_module_css_default.field,
989
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
990
+ className: DataAgentWorkbench_module_css_default.label,
991
+ children: t("form.user")
992
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
993
+ className: DataAgentWorkbench_module_css_default.input,
994
+ type: "text",
995
+ value: user,
996
+ disabled: formDisabled,
997
+ onChange: (event) => setUser(event.target.value)
998
+ })]
999
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1000
+ className: DataAgentWorkbench_module_css_default.field,
1001
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1002
+ className: DataAgentWorkbench_module_css_default.label,
1003
+ children: t("form.password")
1004
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1005
+ className: DataAgentWorkbench_module_css_default.input,
1006
+ type: "password",
1007
+ value: password,
1008
+ autoComplete: "new-password",
1009
+ disabled: formDisabled,
1010
+ onChange: (event) => setPassword(event.target.value)
1011
+ })]
1012
+ })]
1013
+ }),
1014
+ !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1015
+ className: DataAgentWorkbench_module_css_default.rememberRow,
1016
+ children: [
1017
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1018
+ type: "checkbox",
1019
+ checked: rememberPassword,
1020
+ disabled: formDisabled,
1021
+ onChange: (event) => setRememberPassword(event.target.checked)
1022
+ }),
1023
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.rememberPassword") }),
1024
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1025
+ className: DataAgentWorkbench_module_css_default.rememberHint,
1026
+ children: t("form.rememberPassword.hint")
1027
+ })
1028
+ ]
1029
+ }),
1030
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1031
+ className: DataAgentWorkbench_module_css_default.rememberRow,
1032
+ children: [
1033
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1034
+ type: "checkbox",
1035
+ checked: readonly,
1036
+ disabled: formDisabled,
1037
+ onChange: (event) => setReadonly(event.target.checked)
1038
+ }),
1039
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.readonly") }),
1040
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1041
+ className: DataAgentWorkbench_module_css_default.rememberHint,
1042
+ children: t("form.readonly.hint")
1043
+ })
1044
+ ]
1045
+ }),
1046
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1047
+ className: DataAgentWorkbench_module_css_default.field,
1048
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1049
+ className: DataAgentWorkbench_module_css_default.label,
1050
+ children: databaseLabel
1051
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1052
+ className: DataAgentWorkbench_module_css_default.input,
1053
+ type: "text",
1054
+ value: database,
1055
+ placeholder: sqlite ? t("form.database.sqlite.placeholder") : void 0,
1056
+ disabled: formDisabled,
1057
+ onChange: (event) => setDatabase(event.target.value)
1058
+ })]
1059
+ })
1060
+ ]
1061
+ }),
1062
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1063
+ className: DataAgentWorkbench_module_css_default.actions,
1064
+ children: !connected ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1065
+ type: "button",
1066
+ className: DataAgentWorkbench_module_css_default.primary,
1067
+ disabled: busy || database === "" || !sqlite && host === "",
1068
+ onClick: () => {
1069
+ connect();
1070
+ },
1071
+ children: restoring ? t("state.reconnecting") : busy ? t("state.checking") : t("action.connect")
1072
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1073
+ type: "button",
1074
+ className: DataAgentWorkbench_module_css_default.ghost,
1075
+ disabled: busy,
1076
+ onClick: () => {
1077
+ disconnect();
1078
+ },
1079
+ children: t("action.disconnect")
1080
+ })
1081
+ }),
1082
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1083
+ className: DataAgentWorkbench_module_css_default.errorBar,
1084
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1085
+ className: DataAgentWorkbench_module_css_default.errorHead,
1086
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlertIcon, { className: DataAgentWorkbench_module_css_default.errorIcon }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("error.title") })]
1087
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1088
+ className: DataAgentWorkbench_module_css_default.errorText,
1089
+ children: error
1090
+ })]
1091
+ })
1092
+ ]
1093
+ })
1057
1094
  })
1058
1095
  ]
1059
1096
  });
@@ -1066,6 +1103,8 @@ window.__ModuleLoader__.load({
1066
1103
  /** Simplified Chinese dictionary (the key-set source of truth). */
1067
1104
  const zh = {
1068
1105
  "form.title": "数据库连接",
1106
+ "form.hero.title": "连接数据库",
1107
+ "form.hero.hint": "连接 MySQL / PostgreSQL / SQLite 等,开始与数据 Agent 对话",
1069
1108
  "form.type": "数据库类型",
1070
1109
  "type.mysql": "MySQL",
1071
1110
  "type.postgres": "PostgreSQL",
@@ -1109,12 +1148,13 @@ window.__ModuleLoader__.load({
1109
1148
  "action.config": "连接配置",
1110
1149
  "action.browse": "库表",
1111
1150
  "action.close": "关闭",
1112
- "action.collapse": "收起",
1113
1151
  "error.title": "操作失败"
1114
1152
  };
1115
1153
  /** English dictionary, checked complete against the zh key set. */
1116
1154
  const en = {
1117
1155
  "form.title": "Database connection",
1156
+ "form.hero.title": "Connect database",
1157
+ "form.hero.hint": "Connect MySQL / PostgreSQL / SQLite and start chatting with the data agent",
1118
1158
  "form.type": "Database type",
1119
1159
  "type.mysql": "MySQL",
1120
1160
  "type.postgres": "PostgreSQL",
@@ -1158,7 +1198,6 @@ window.__ModuleLoader__.load({
1158
1198
  "action.config": "Connection settings",
1159
1199
  "action.browse": "Tables",
1160
1200
  "action.close": "Close",
1161
- "action.collapse": "Collapse",
1162
1201
  "error.title": "Operation failed"
1163
1202
  };
1164
1203
  //#endregion
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useRef","useState","css","StateDot","Modal"],"sources":["../src/client/persistence.ts","../src/client/DataAgentWorkbench.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Connection-config persistence for the database workbench. The most recent\n * successful connection (type/host/port/user/database/password) is kept in\n * localStorage under one key so remounts and restarts can restore the form\n * and auto-reconnect (the server-side connection store stays in-memory).\n *\n * Security note: the password is persisted in PLAIN TEXT by explicit user\n * decision (local single-user scenario) — see README 安全说明. The storage\n * key is versioned so a future shape change can migrate or ignore old data.\n * @module @yejiming/dsh-data-agent/persistence\n */\n\nimport type { DatabaseType } from './DataAgentWorkbench.tsx'\n\n/** localStorage key holding the most recent connection configuration. */\nexport const CONNECTION_STORAGE_KEY = 'dsh-data-agent.connection.v1'\n\n/** The persisted connection configuration. */\nexport interface SavedConnection {\n type: DatabaseType\n host?: string\n port?: number\n user?: string\n database: string\n /** Present only when the user explicitly opted in to persist the password. */\n password?: string\n /** Opt-in flag; when true, {@link saveConnection} may write `password`. */\n persistPassword?: boolean\n /** Diagnostic timestamp of the save. */\n savedAt: string\n}\n\n/** Runtime storage face (injectable for tests). */\nexport interface StorageLike {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/** The default storage face (localStorage; unavailable → degraded no-op). */\nfunction defaultStorage(): StorageLike | undefined {\n try {\n if (typeof localStorage !== 'undefined') {\n const probe = '__dsh_probe__'\n localStorage.setItem(probe, '1')\n localStorage.removeItem(probe)\n return localStorage\n }\n } catch {\n // localStorage disabled (privacy mode, sandboxed frame): degrade silently.\n }\n return undefined\n}\n\n/** Validate one parsed storage value into a SavedConnection (or null). */\nfunction parseSaved(value: unknown): SavedConnection | null {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return null\n const candidate = value as Record<string, unknown>\n const type = candidate.type\n if (type !== 'mysql' && type !== 'postgres' && type !== 'sqlite'\n && type !== 'oracle' && type !== 'hive' && type !== 'impala') {\n return null\n }\n const database = candidate.database\n // 草稿语义:database 允许为空串(用户可能只填了部分字段就切换会话)。\n if (typeof database !== 'string') return null\n const saved: SavedConnection = { type, database, savedAt: typeof candidate.savedAt === 'string' ? candidate.savedAt : '' }\n if (typeof candidate.host === 'string') saved.host = candidate.host\n if (typeof candidate.port === 'number' && Number.isInteger(candidate.port)) saved.port = candidate.port\n if (typeof candidate.user === 'string') saved.user = candidate.user\n // Legacy records may carry a password; strip it unless the opt-in flag is set\n // (a persisted password only survives when persistPassword was explicitly true).\n const persistPassword = candidate.persistPassword === true\n if (persistPassword) saved.persistPassword = true\n if (persistPassword && typeof candidate.password === 'string') saved.password = candidate.password\n return saved\n}\n\n/** Save one connection configuration (best-effort; storage failures degrade silently). */\nexport function saveConnection(connection: SavedConnection, storage: StorageLike | undefined = defaultStorage()): void {\n if (storage === undefined) return\n try {\n const toWrite: SavedConnection = { ...connection }\n // Password is opt-in only; strip it unless persistPassword is explicitly set.\n if (toWrite.persistPassword !== true) delete toWrite.password\n storage.setItem(CONNECTION_STORAGE_KEY, JSON.stringify(toWrite))\n } catch {\n // Quota / serialization failure: degrade silently, the UI stays usable.\n }\n}\n\n/** Load the saved connection configuration; null when absent or malformed. */\nexport function loadConnection(storage: StorageLike | undefined = defaultStorage()): SavedConnection | null {\n if (storage === undefined) return null\n try {\n const raw = storage.getItem(CONNECTION_STORAGE_KEY)\n if (raw === null) return null\n return parseSaved(JSON.parse(raw))\n } catch {\n return null\n }\n}\n\n/** Remove the saved connection configuration. */\nexport function clearConnection(storage: StorageLike | undefined = defaultStorage()): void {\n if (storage === undefined) return\n try {\n storage.removeItem(CONNECTION_STORAGE_KEY)\n } catch {\n // Degrade silently.\n }\n}\n","/**\n * The database workbench: connection config (collapsible after connect),\n * a browse button that opens the schema explorer Modal, and the SQL command\n * box, rendered into the composer input dock (the strip ABOVE the input bar)\n * for data-agent sessions.\n *\n * Layout is phase-driven by the conversation root's `data-phase` attribute:\n * - hero (blank session): the workbench is a full-width stacked strip above\n * the input bar (which stays at the bottom);\n * - active (conversation started): the workbench becomes a fixed left rail\n * (measured from the conversation column), the chat records and the input\n * bar shift right via the `da-split` CSS rules; if measurement is\n * unavailable the workbench falls back to a docked bottom panel.\n *\n * Interaction model:\n * - after a successful connect the connection form collapses into a summary\n * row (click 连接配置 to expand the readonly form again);\n * - the schema explorer lives in a Modal (ui-primitives) opened by the\n * 库表 button; a single click on a database toggles its table list in a\n * file-explorer style tree (folder rows with chevrons, indented table rows\n * with guide lines, the whole tree scrolls inside the column);\n * - clicking a table loads its columns into the Modal's structure panel.\n *\n * Non-data-agent sessions render null — zero impact on ordinary sessions.\n * Connection state lives on the server (the dataAgentConnections store), so\n * remounts never lose it — this component mirrors `/status` on mount.\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { Modal, StateDot } from '@deepseek-ai/dsh-client-ui-primitives'\n// Type-only: pulls the ui-conversation slot declarations (conversation.input.dock)\n// and the framework-standard view props into this program.\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport {\n loadConnection,\n saveConnection,\n type SavedConnection,\n} from './persistence.ts'\nimport css from './DataAgentWorkbench.module.css'\n\n/** The plugin's preset id, matching the installed agent preset directory. */\nconst DATA_AGENT_PRESET = 'data-agent'\n\n/** 16×16 stroke icons drawn inline (the primitives package does not export icon atoms). */\nfunction Icon({ className, children, size = 14 }: { className?: string; children: ReactNode; size?: number }) {\n return (\n <svg className={className} width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n {children}\n </svg>\n )\n}\n\n/** Database cylinder: section header of the connection form. */\nfunction DatabaseIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <ellipse cx=\"8\" cy=\"4\" rx=\"5.5\" ry=\"2.1\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M2.5 4V12C2.5 13.16 4.96 14.1 8 14.1C11.04 14.1 13.5 13.16 13.5 12V4\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M2.5 8C2.5 9.16 4.96 10.1 8 10.1C11.04 10.1 13.5 9.16 13.5 8\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </Icon>\n )\n}\n\n/** Table grid: browse row + table rows in the tree. */\nfunction TableIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <rect x=\"2\" y=\"3\" width=\"12\" height=\"10\" rx=\"1.5\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M2 6.5H14\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M6.5 6.5V13\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </Icon>\n )\n}\n\n/** Folder: schema rows in the tree. */\nfunction FolderIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <path\n d=\"M1.8 4.6C1.8 4.05 2.25 3.6 2.8 3.6H5.9L7.1 5.1H13.2C13.75 5.1 14.2 5.55 14.2 6.1V11.4C14.2 11.95 13.75 12.4 13.2 12.4H2.8C2.25 12.4 1.8 11.95 1.8 11.4V4.6Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />\n </Icon>\n )\n}\n\n/** Terminal prompt: section header of the SQL box. */\nfunction TerminalIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M4.5 6L6.5 8L4.5 10\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M8 10.5H11.2\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n </Icon>\n )\n}\n\n/** Chevron: tree expand indicator (rotates 90° when open). */\nfunction ChevronIcon({ className }: { className?: string }) {\n return (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M4.5 2.5L8 6L4.5 9.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\n/** Alert triangle: error bar heading. */\nfunction AlertIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <path d=\"M8 2.2L14.2 13H1.8L8 2.2Z\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinejoin=\"round\" />\n <path d=\"M8 6.4V9.2\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"11\" r=\"0.9\" fill=\"currentColor\" />\n </Icon>\n )\n}\n\n/** Play triangle: SQL run button. */\nfunction PlayIcon({ className }: { className?: string }) {\n return (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3.4 2.1C3.4 1.66 3.88 1.4 4.26 1.62L9.9 5.02C10.26 5.23 10.26 5.77 9.9 5.98L4.26 9.38C3.88 9.6 3.4 9.34 3.4 8.9V2.1Z\" />\n </svg>\n )\n}\n\n/** Database kinds offered by the connection form. */\nexport type DatabaseType = 'mysql' | 'postgres' | 'sqlite' | 'oracle' | 'hive' | 'impala'\n\n/** The sessions-list slice the workbench needs (structural; avoids a runtime import). */\nexport interface SessionListLike {\n byId: Record<string, { agentPreset?: string }>\n}\n\n/** One described column. */\ninterface ColumnInfo {\n name: string\n type: string\n nullable?: boolean\n}\n\n/** Wire shapes of the plugin routes. */\ninterface ConnectResponse { ok: boolean; tables?: string[]; error?: string }\ninterface StatusResponse {\n connected: boolean\n summary?: {\n type: DatabaseType\n host?: string\n port?: number\n user?: string\n database: string\n readonly?: boolean\n tables?: string[]\n }\n}\ninterface SchemasResponse { ok: boolean; schemas?: string[]; error?: string }\ninterface TablesResponse { ok: boolean; tables?: string[]; error?: string }\ninterface DescribeResponse { ok: boolean; columns?: ColumnInfo[]; error?: string }\ninterface QueryResponse {\n ok: boolean\n result?: { exitCode: number | null; stdout: string; stderr: string; truncated: boolean }\n error?: string\n}\n\n/** Registration-side business face: the sessions-list observable becomes `useSessions`. */\nexport interface DataAgentWorkbenchInjected {\n hooks: {\n sessions: {\n getSnapshot(): SessionListLike\n subscribe(fn: () => void): () => void\n }\n }\n}\n\n/** The workbench's full component props: the dock seat + the locale seat + the injected sessions hook. */\nexport type DataAgentWorkbenchProps =\n PropsRuntime<'conversation.input.dock'>\n & PropsLocale<'data-agent'>\n & InjectFace<DataAgentWorkbenchInjected>\n\n/** The conversation column's phase attribute value while the session is blank. */\nfunction isHeroPhase(element: HTMLElement | null): boolean {\n return element?.getAttribute('data-phase') === 'hero'\n}\n\n/**\n * 开始对话后(active 布局)左栏工作台相对会话列顶部的下移偏移(px):\n * 让工作台避开会话头部区域、整体往下沉一些,顶部露出对话记录。\n */\nconst RAIL_TOP_OFFSET = 96\n\n/** Default port per type (used to fill the form from a saved connection). */\nfunction defaultPortOf(type: DatabaseType): string {\n switch (type) {\n case 'postgres': return '5432'\n case 'oracle': return '1521'\n case 'hive': return '10000'\n case 'impala': return '21050'\n case 'sqlite': return ''\n case 'mysql': return '3306'\n }\n}\n\n/** Run one /connect request (shared by the form connect and mount auto-reconnect). */\nasync function performConnect(sessionId: string, body: Record<string, unknown>): Promise<ConnectResponse> {\n const response = await fetch('/plugins/data-agent/connect', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId, ...body }),\n })\n return response.json() as Promise<ConnectResponse>\n}\n\n/** Build the /connect payload from a saved connection. */\nfunction payloadFromSaved(saved: SavedConnection): Record<string, unknown> {\n if (saved.type === 'sqlite') return { type: saved.type, database: saved.database }\n const body: Record<string, unknown> = {\n type: saved.type,\n host: saved.host ?? '127.0.0.1',\n user: saved.user ?? '',\n database: saved.database,\n }\n if (saved.port !== undefined) body.port = saved.port\n if (saved.password !== undefined && saved.password !== '') body.password = saved.password\n return body\n}\n\n/** The database workbench body. */\nexport function DataAgentWorkbench({ sessionId, useSessions, t }: DataAgentWorkbenchProps) {\n const list = useSessions(snapshot => snapshot)\n const isDataAgent = list.byId[sessionId as never]?.agentPreset === DATA_AGENT_PRESET\n\n const rootRef = useRef<HTMLDivElement | null>(null)\n const [phase, setPhase] = useState<'hero' | 'active'>('hero')\n const [railRect, setRailRect] = useState<{ left: number; top: number; bottom: number } | null>(null)\n\n // 表单从已保存的连接配置(localStorage)惰性初始化:切换会话/刷新/重启后回填。\n const [initialSaved] = useState(loadConnection)\n const [type, setType] = useState<DatabaseType>(initialSaved?.type ?? 'mysql')\n const [host, setHost] = useState(initialSaved?.host ?? '127.0.0.1')\n const [port, setPort] = useState(\n initialSaved?.port !== undefined ? String(initialSaved.port) : defaultPortOf(initialSaved?.type ?? 'mysql'),\n )\n const [user, setUser] = useState(initialSaved?.user ?? '')\n const [password, setPassword] = useState(initialSaved?.password ?? '')\n const [rememberPassword, setRememberPassword] = useState(initialSaved?.persistPassword === true)\n const [readonly, setReadonly] = useState(false)\n const [database, setDatabase] = useState(initialSaved?.database ?? '')\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [connected, setConnected] = useState(false)\n\n // Connection form collapsed into a summary row once connected.\n const [configOpen, setConfigOpen] = useState(false)\n // Mount-time auto-reconnect in flight (from the saved connection).\n const [restoring, setRestoring] = useState(false)\n // Schema explorer Modal.\n const [schemaModalOpen, setSchemaModalOpen] = useState(false)\n\n const [schemas, setSchemas] = useState<string[]>([])\n const [activeSchema, setActiveSchema] = useState<string | null>(null)\n const [tables, setTables] = useState<string[]>([])\n const [activeTable, setActiveTable] = useState<string | null>(null)\n const [columns, setColumns] = useState<ColumnInfo[] | null>(null)\n\n const [sql, setSql] = useState('')\n const [sqlBusy, setSqlBusy] = useState(false)\n const [sqlResult, setSqlResult] = useState<string | null>(null)\n\n // Track the conversation column phase and its bounds for the left-rail\n // layout; toggle the da-split class that shifts chat + input to the right.\n useEffect(() => {\n const column = rootRef.current?.closest<HTMLElement>('[data-phase]') ?? null\n if (column === null) return\n const measure = (): void => {\n const rect = column.getBoundingClientRect()\n setRailRect({ left: rect.left, top: rect.top, bottom: window.innerHeight - rect.bottom })\n }\n const refreshPhase = (): void => { setPhase(isHeroPhase(column) ? 'hero' : 'active') }\n refreshPhase()\n measure()\n const observer = new MutationObserver(refreshPhase)\n observer.observe(column, { attributes: true, attributeFilter: ['data-phase'] })\n const resizer = new ResizeObserver(measure)\n resizer.observe(column)\n window.addEventListener('resize', measure)\n return () => {\n observer.disconnect()\n resizer.disconnect()\n window.removeEventListener('resize', measure)\n }\n }, [])\n\n // Split layout is active only for a live conversation (phase active) with\n // a measurable column; everything else stays stacked above the input.\n const split = phase === 'active' && railRect !== null\n useEffect(() => {\n const root = document.documentElement\n const splitClass = css['da-split']\n if (split && splitClass !== undefined) root.classList.add(splitClass)\n else if (splitClass !== undefined) root.classList.remove(splitClass)\n return () => { if (splitClass !== undefined) root.classList.remove(splitClass) }\n }, [split])\n\n // 草稿持久化:任何表单字段变化立即保存(含密码,用户已确认),\n // 使未连接的输入在切换会话/刷新后也能恢复。首轮跳过(初始化回填值\n // 无需重写,也避免从未输入时写入空配置)。\n const firstDraftRun = useRef(true)\n useEffect(() => {\n if (firstDraftRun.current) {\n firstDraftRun.current = false\n return\n }\n const draft: SavedConnection = {\n type,\n database,\n ...type !== 'sqlite' ? { host, user } : {},\n ...type !== 'sqlite' && port !== '' ? { port: Number(port) } : {},\n ...password !== '' ? { password } : {},\n ...rememberPassword ? { persistPassword: true } : {},\n savedAt: new Date().toISOString(),\n }\n saveConnection(draft)\n }, [type, host, port, user, database, password, rememberPassword])\n\n // Mirror the server-side connection on mount; auto-reconnect once when the\n // server store was lost (restart).\n useEffect(() => {\n let cancelled = false\n const saved = initialSaved\n setBusy(true)\n fetch(`/plugins/data-agent/status?sessionId=${encodeURIComponent(sessionId)}`)\n .then(response => response.json() as Promise<StatusResponse>)\n .then(async (body) => {\n if (cancelled) return\n if (body.connected) {\n setConnected(true)\n if (body.summary !== undefined) {\n setType(body.summary.type)\n setHost(body.summary.host ?? '')\n setPort(body.summary.port !== undefined ? String(body.summary.port) : '')\n setUser(body.summary.user ?? '')\n setDatabase(body.summary.database)\n setReadonly(body.summary.readonly === true)\n }\n const response = await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)\n const schemasBody = await response.json() as SchemasResponse\n if (!cancelled && schemasBody.ok) setSchemas(schemasBody.schemas ?? [])\n return\n }\n // Server connection lost (restart): restore with the saved config, once.\n // 草稿未完成(database 为空)时不自动重连,仅保留表单回填。\n if (saved !== null && saved.database !== '') {\n setRestoring(true)\n try {\n const result = await performConnect(sessionId, payloadFromSaved(saved))\n if (cancelled) return\n if (result.ok) {\n setConnected(true)\n setConfigOpen(false)\n const response = await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)\n const schemasBody = await response.json() as SchemasResponse\n if (!cancelled && schemasBody.ok) setSchemas(schemasBody.schemas ?? [])\n } else {\n setError(`连接恢复失败:${result.error ?? 'unknown error'}`)\n }\n } catch (cause) {\n if (!cancelled) {\n setError(`连接恢复失败:${cause instanceof Error ? cause.message : String(cause)}`)\n }\n } finally {\n if (!cancelled) setRestoring(false)\n }\n }\n })\n .catch(() => { /* the form stays usable; connect will surface errors */ })\n .finally(() => { if (!cancelled) setBusy(false) })\n return () => { cancelled = true }\n }, [sessionId])\n\n const sqlite = type === 'sqlite'\n\n const connect = async (): Promise<void> => {\n setBusy(true)\n setError(null)\n const body: Record<string, unknown> = { sessionId, type, readonly }\n if (sqlite) {\n body.database = database\n } else {\n body.host = host\n if (port !== '') body.port = Number(port)\n body.user = user\n body.database = database\n if (password !== '') body.password = password\n }\n try {\n const result = await performConnect(sessionId, body)\n if (result.ok) {\n setConnected(true)\n // Collapse the form into the summary row. 密码保留在输入框(草稿已持久化)。\n setConfigOpen(false)\n const schemasResponse = await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)\n const schemasBody = await schemasResponse.json() as SchemasResponse\n if (schemasBody.ok) setSchemas(schemasBody.schemas ?? [])\n } else {\n setError(result.error ?? 'unknown error')\n }\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n const disconnect = async (): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n await fetch('/plugins/data-agent/disconnect', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId }),\n })\n setConnected(false)\n setConfigOpen(false)\n setReadonly(false)\n setSchemaModalOpen(false)\n setSchemas([])\n setActiveSchema(null)\n setTables([])\n setActiveTable(null)\n setColumns(null)\n setSqlResult(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n /** Toggle one schema's table list (single click; only one open at a time). */\n const toggleSchema = async (schema: string): Promise<void> => {\n if (activeSchema === schema) {\n setActiveSchema(null)\n setTables([])\n setActiveTable(null)\n setColumns(null)\n return\n }\n setActiveSchema(schema)\n setActiveTable(null)\n setColumns(null)\n setTables([])\n try {\n const response = await fetch(\n `/plugins/data-agent/tables?sessionId=${encodeURIComponent(sessionId)}&schema=${encodeURIComponent(schema)}`,\n )\n const result = await response.json() as TablesResponse\n if (result.ok) setTables(result.tables ?? [])\n else setError(result.error ?? 'unknown error')\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const selectTable = async (table: string): Promise<void> => {\n setActiveTable(table)\n setColumns(null)\n const params = new URLSearchParams({ sessionId, table })\n if (activeSchema !== null) params.set('schema', activeSchema)\n try {\n const response = await fetch(`/plugins/data-agent/describe?${params.toString()}`)\n const result = await response.json() as DescribeResponse\n if (result.ok) setColumns(result.columns ?? [])\n else setError(result.error ?? 'unknown error')\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const runSql = async (): Promise<void> => {\n if (sql.trim() === '') return\n setSqlBusy(true)\n setSqlResult(null)\n try {\n const response = await fetch('/plugins/data-agent/query', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId, sql }),\n })\n const result = await response.json() as QueryResponse\n if (result.ok && result.result !== undefined) {\n const parts: string[] = []\n if (result.result.stdout !== '') parts.push(result.result.stdout)\n if (result.result.stderr !== '') parts.push(`[stderr]\\n${result.result.stderr}`)\n if (result.result.truncated) parts.push('… 输出超过上限,已截断')\n if (result.result.exitCode !== 0) parts.push(`[exit code: ${result.result.exitCode ?? 'signal'}]`)\n setSqlResult(parts.join('\\n'))\n } else {\n setSqlResult(`Error: ${result.error ?? 'unknown error'}`)\n }\n } catch (cause) {\n setSqlResult(`Error: ${cause instanceof Error ? cause.message : String(cause)}`)\n } finally {\n setSqlBusy(false)\n }\n }\n\n // A session not running the data-agent preset: nothing renders at all.\n if (!isDataAgent) return null\n\n const databaseLabel = sqlite\n ? t('form.database.sqlite')\n : type === 'oracle'\n ? t('form.database.oracle')\n : type === 'hive' || type === 'impala'\n ? t('form.database.hive')\n : t('form.database')\n\n const railStyle = split\n ? {\n position: 'fixed' as const,\n left: railRect!.left,\n top: railRect!.top + RAIL_TOP_OFFSET,\n bottom: railRect!.bottom,\n width: 380,\n }\n : undefined\n\n // Form fields are readonly while connected (edit requires disconnecting).\n const formDisabled = busy || connected\n\n return (\n <div\n ref={rootRef}\n className={`${css.workbench} ${split ? css.rail : phase === 'active' ? css.docked : css.strip}`}\n style={railStyle}\n >\n <div className={css.sections}>\n {connected && !configOpen ? (\n // ── connected summary row (form collapsed) ──────────────────────\n <section className={css.card}>\n <div className={css.summaryRow}>\n <StateDot state=\"done\" size={8} className={css.dot} />\n <span className={css.statusOk}>{t('state.connected')}</span>\n <span className={css.summaryType}>{t(`type.${type}`)}</span>\n <span className={css.summaryDb} title={database}>{database}</span>\n <span className={css.summaryActions}>\n <button type=\"button\" className={`${css.ghost} ${css.small}`} onClick={() => setConfigOpen(true)}>\n {t('action.config')}\n </button>\n <button type=\"button\" className={`${css.ghost} ${css.small}`} disabled={busy} onClick={() => { void disconnect() }}>\n {t('action.disconnect')}\n </button>\n </span>\n </div>\n </section>\n ) : (\n // ── connection form (editable when disconnected, readonly when expanded) ──\n <section className={css.card}>\n <div className={css.cardTitle}>\n <DatabaseIcon className={css.titleIcon} />\n <span>{t('form.title')}</span>\n </div>\n <div className={css.fieldGrid}>\n <label className={css.field}>\n <span className={css.label}>{t('form.type')}</span>\n <select\n className={css.input}\n value={type}\n disabled={formDisabled}\n onChange={(event) => {\n const next = event.target.value as DatabaseType\n setType(next)\n setPort(next === 'postgres' ? '5432' : next === 'mysql' ? '3306' : next === 'oracle' ? '1521' : next === 'hive' ? '10000' : next === 'impala' ? '21050' : '')\n }}\n >\n <option value=\"mysql\">{t('type.mysql')}</option>\n <option value=\"postgres\">{t('type.postgres')}</option>\n <option value=\"sqlite\">{t('type.sqlite')}</option>\n <option value=\"oracle\">{t('type.oracle')}</option>\n <option value=\"hive\">{t('type.hive')}</option>\n <option value=\"impala\">{t('type.impala')}</option>\n </select>\n </label>\n\n {!sqlite && (\n <div className={css.fieldRow2}>\n <label className={css.field}>\n <span className={css.label}>{t('form.host')}</span>\n <input className={css.input} type=\"text\" value={host} disabled={formDisabled} onChange={(event) => setHost(event.target.value)} />\n </label>\n <label className={css.field}>\n <span className={css.label}>{t('form.port')}</span>\n <input className={css.input} type=\"number\" min={1} max={65535} value={port} disabled={formDisabled} onChange={(event) => setPort(event.target.value)} />\n </label>\n </div>\n )}\n\n {!sqlite && (\n <div className={css.fieldRow2}>\n <label className={css.field}>\n <span className={css.label}>{t('form.user')}</span>\n <input className={css.input} type=\"text\" value={user} disabled={formDisabled} onChange={(event) => setUser(event.target.value)} />\n </label>\n <label className={css.field}>\n <span className={css.label}>{t('form.password')}</span>\n <input className={css.input} type=\"password\" value={password} autoComplete=\"new-password\" disabled={formDisabled} onChange={(event) => setPassword(event.target.value)} />\n </label>\n </div>\n )}\n\n {!sqlite && (\n <label className={css.rememberRow}>\n <input\n type=\"checkbox\"\n checked={rememberPassword}\n disabled={formDisabled}\n onChange={(event) => setRememberPassword(event.target.checked)}\n />\n <span>{t('form.rememberPassword')}</span>\n <span className={css.rememberHint}>{t('form.rememberPassword.hint')}</span>\n </label>\n )}\n\n <label className={css.rememberRow}>\n <input\n type=\"checkbox\"\n checked={readonly}\n disabled={formDisabled}\n onChange={(event) => setReadonly(event.target.checked)}\n />\n <span>{t('form.readonly')}</span>\n <span className={css.rememberHint}>{t('form.readonly.hint')}</span>\n </label>\n\n <label className={css.field}>\n <span className={css.label}>{databaseLabel}</span>\n <input\n className={css.input}\n type=\"text\"\n value={database}\n placeholder={sqlite ? t('form.database.sqlite.placeholder') : undefined}\n disabled={formDisabled}\n onChange={(event) => setDatabase(event.target.value)}\n />\n </label>\n </div>\n\n <div className={css.actions}>\n {!connected ? (\n <button\n type=\"button\"\n className={css.primary}\n disabled={busy || database === '' || (!sqlite && host === '')}\n onClick={() => { void connect() }}\n >\n {restoring ? t('state.reconnecting') : busy ? t('state.checking') : t('action.connect')}\n </button>\n ) : (\n <>\n <button type=\"button\" className={css.ghost} onClick={() => setConfigOpen(false)}>\n {t('action.collapse')}\n </button>\n <button type=\"button\" className={css.ghost} disabled={busy} onClick={() => { void disconnect() }}>\n {t('action.disconnect')}\n </button>\n </>\n )}\n </div>\n </section>\n )}\n\n {connected && (\n // ── schema explorer entry ───────────────────────────────────────\n <section className={css.card}>\n <button type=\"button\" className={css.browseRow} onClick={() => setSchemaModalOpen(true)}>\n <TableIcon className={css.browseIcon} />\n <span>{t('action.browse')}</span>\n <ChevronIcon className={css.browseChevron} />\n </button>\n </section>\n )}\n\n <section className={css.card}>\n <div className={css.cardTitle}>\n <TerminalIcon className={css.titleIcon} />\n <span>{t('wb.sql')}</span>\n </div>\n <textarea\n className={css.sqlInput}\n value={sql}\n rows={8}\n spellCheck={false}\n placeholder={t('wb.sql.placeholder')}\n onChange={(event) => setSql(event.target.value)}\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void runSql()\n }\n }}\n />\n <div className={css.sqlActions}>\n <span className={css.shortcutHint}>{t('wb.sql.shortcut')}</span>\n <button\n type=\"button\"\n className={css.primary}\n disabled={sqlBusy || !connected || sql.trim() === ''}\n onClick={() => { void runSql() }}\n >\n <PlayIcon />\n {sqlBusy ? t('wb.sql.running') : t('wb.sql.run')}\n </button>\n </div>\n <pre className={css.sqlResult}>{sqlResult ?? t('wb.sql.empty')}</pre>\n </section>\n </div>\n\n {error !== null && (\n <div className={css.errorBar}>\n <div className={css.errorHead}>\n <AlertIcon className={css.errorIcon} />\n <span>{t('error.title')}</span>\n </div>\n <span className={css.errorText}>{error}</span>\n </div>\n )}\n\n {schemaModalOpen && (\n <Modal\n open={schemaModalOpen}\n onClose={() => setSchemaModalOpen(false)}\n title={t('wb.modal.title')}\n closeLabel={t('action.close')}\n className={css.schemaModal}\n >\n <div className={css.modalBody}>\n <div className={css.modalCol}>\n <div className={css.modalColTitle}>\n <span>{t('wb.schemas')}</span>\n {schemas.length > 0 && <span className={css.colCount}>{schemas.length}</span>}\n </div>\n <div className={css.treeScroll}>\n {schemas.length === 0 && <div className={css.hint}>{t('wb.loading')}</div>}\n <ul className={css.tree}>\n {schemas.map(schema => (\n <li key={schema} className={css.treeNode}>\n <button\n type=\"button\"\n className={`${css.treeItem}${activeSchema === schema ? ` ${css.active}` : ''}`}\n onClick={() => { void toggleSchema(schema) }}\n >\n <ChevronIcon className={`${css.treeChevron}${activeSchema === schema ? ` ${css.open}` : ''}`} />\n <FolderIcon className={css.treeIcon} />\n <span className={css.treeName}>{schema}</span>\n {activeSchema === schema && tables.length > 0 && (\n <span className={css.treeCount}>{tables.length}</span>\n )}\n </button>\n {activeSchema === schema && (\n <div className={css.treeChildren}>\n {tables.length === 0 && <div className={css.hint}>{t('wb.empty')}</div>}\n {tables.map(table => (\n <button\n key={table}\n type=\"button\"\n className={`${css.treeItem}${activeTable === table ? ` ${css.active}` : ''}`}\n onClick={() => { void selectTable(table) }}\n >\n <TableIcon className={css.treeIcon} />\n <span className={css.treeName}>{table}</span>\n </button>\n ))}\n </div>\n )}\n </li>\n ))}\n </ul>\n </div>\n <div className={css.modalHint}>{t('wb.hint.click')}</div>\n </div>\n\n <div className={css.modalCol}>\n <div className={css.modalColTitle}>\n <span>{t('wb.columns')}{activeTable !== null && ` · ${activeTable}`}</span>\n </div>\n {columns === null ? (\n <div className={css.emptyState}>\n <TableIcon className={css.emptyStateIcon} />\n <span className={css.emptyStateText}>{t('wb.hint.click')}</span>\n </div>\n ) : (\n <div className={css.colScroll}>\n <table className={css.columnsTable}>\n <thead>\n <tr><th>name</th><th>type</th><th>null</th></tr>\n </thead>\n <tbody>\n {columns.map(column => (\n <tr key={column.name}>\n <td>{column.name}</td>\n <td className={css.typeCell}>{column.type}</td>\n <td className={css.nullCell}>{column.nullable === undefined ? '' : column.nullable ? 'YES' : 'NO'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n </Modal>\n )}\n </div>\n )\n}\n","/** `data-agent` namespace dictionaries for the database workbench. */\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'data-agent'\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'form.title': '数据库连接',\n 'form.type': '数据库类型',\n 'type.mysql': 'MySQL',\n 'type.postgres': 'PostgreSQL',\n 'type.sqlite': 'SQLite',\n 'type.oracle': 'Oracle',\n 'type.hive': 'Hive',\n 'type.impala': 'Impala',\n 'form.host': '主机',\n 'form.port': '端口',\n 'form.user': '用户名',\n 'form.password': '密码',\n 'form.rememberPassword': '记住密码',\n 'form.rememberPassword.hint': '仅勾选后才会在本机保存密码',\n 'form.readonly': '只读模式',\n 'form.readonly.hint': '仅放行查询语句,拒绝增删改、建表等写操作',\n 'form.database': '数据库名',\n 'form.database.oracle': '服务名 / SID',\n 'form.database.hive': '默认库',\n 'form.database.impala': '默认库',\n 'form.database.sqlite': '数据库文件路径',\n 'form.database.sqlite.placeholder': '/path/to/orders.db',\n 'action.connect': '连接',\n 'action.disconnect': '断开',\n 'state.connected': '已连接',\n 'state.disconnected': '未连接',\n 'state.checking': '正在检查连接…',\n 'state.reconnecting': '正在恢复连接…',\n 'wb.schemas': '库',\n 'wb.tables': '表',\n 'wb.columns': '表结构',\n 'wb.sql': 'SQL 命令',\n 'wb.sql.placeholder': '在此输入 SQL,例如 SELECT * FROM orders LIMIT 10;',\n 'wb.sql.run': '运行',\n 'wb.sql.running': '运行中…',\n 'wb.sql.shortcut': 'Ctrl / ⌘ + Enter 运行',\n 'wb.sql.empty': '-- 尚无输出 --',\n 'wb.loading': '加载中…',\n 'wb.empty': '(空)',\n 'wb.modal.title': '库表浏览',\n 'wb.hint.click': '单击库展开表 · 点击表查看结构',\n 'action.config': '连接配置',\n 'action.browse': '库表',\n 'action.close': '关闭',\n 'action.collapse': '收起',\n 'error.title': '操作失败',\n} satisfies Record<string, string>\n\n/** The data-agent namespace key union. */\nexport type DataAgentKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'form.title': 'Database connection',\n 'form.type': 'Database type',\n 'type.mysql': 'MySQL',\n 'type.postgres': 'PostgreSQL',\n 'type.sqlite': 'SQLite',\n 'type.oracle': 'Oracle',\n 'type.hive': 'Hive',\n 'type.impala': 'Impala',\n 'form.host': 'Host',\n 'form.port': 'Port',\n 'form.user': 'User',\n 'form.password': 'Password',\n 'form.rememberPassword': 'Remember password',\n 'form.rememberPassword.hint': 'Saved locally only when checked',\n 'form.readonly': 'Read-only mode',\n 'form.readonly.hint': 'Allow read queries only; reject writes (INSERT/UPDATE/DELETE/DDL)',\n 'form.database': 'Database',\n 'form.database.oracle': 'Service name / SID',\n 'form.database.hive': 'Default database',\n 'form.database.impala': 'Default database',\n 'form.database.sqlite': 'Database file path',\n 'form.database.sqlite.placeholder': '/path/to/orders.db',\n 'action.connect': 'Connect',\n 'action.disconnect': 'Disconnect',\n 'state.connected': 'Connected',\n 'state.disconnected': 'Not connected',\n 'state.checking': 'Checking connection…',\n 'state.reconnecting': 'Restoring connection…',\n 'wb.schemas': 'Databases',\n 'wb.tables': 'Tables',\n 'wb.columns': 'Columns',\n 'wb.sql': 'SQL',\n 'wb.sql.placeholder': 'Write SQL here, e.g. SELECT * FROM orders LIMIT 10;',\n 'wb.sql.run': 'Run',\n 'wb.sql.running': 'Running…',\n 'wb.sql.shortcut': 'Ctrl / ⌘ + Enter to run',\n 'wb.sql.empty': '-- no output --',\n 'wb.loading': 'Loading…',\n 'wb.empty': '(empty)',\n 'wb.modal.title': 'Database explorer',\n 'wb.hint.click': 'Click a database to expand tables · click a table for columns',\n 'action.config': 'Connection settings',\n 'action.browse': 'Tables',\n 'action.close': 'Close',\n 'action.collapse': 'Collapse',\n 'error.title': 'Operation failed',\n} satisfies Record<DataAgentKey, string>\n","/**\n * Data Agent browser half, plugin entry: registers the database workbench\n * into the composer input dock (the strip ABOVE the input bar) for\n * data-agent sessions, and the `data-agent` dictionaries. The old\n * conversation-view tab is gone — the workbench lives inside the session.\n * Connection state lives in the server-side connection store, so layout and\n * session switches never lose it — the view only mirrors what\n * `/plugins/data-agent/status` reports.\n * @module @yejiming/dsh-data-agent/client\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale) into this program.\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the ui-conversation slot declarations (conversation.input.dock)\n// and the session standard props (sessionId) into this program.\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { DataAgentWorkbench, type SessionListLike } from './DataAgentWorkbench.tsx'\nimport { NS, en, zh, type DataAgentKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** The database workbench copy. */\n 'data-agent': DataAgentKey\n }\n}\n\n/** Required services: the locale service, the slot registry, and the sessions list. */\nexport const inject = ['slots', 'locale', 'sessions']\n\n/**\n * Client plugin body: register the data-agent dictionaries and the database\n * workbench into the composer input dock. The registration rides the slot\n * service's effect wrapper, so plugin unload removes it.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'data-agent: dictionaries')\n const t = ctx.locale.bind(NS)\n ctx.inject(['slots', 'locale', 'sessions'], (scope: ClientContext) => {\n const list = scope.sessions.list\n // The sessions list is the agent-preset authority on the client: the\n // ui-agent-preset surface records `agentPreset` onto each session summary.\n const sessionsSource = {\n getSnapshot: (): SessionListLike => list.getSnapshot() as unknown as SessionListLike,\n subscribe: (fn: () => void): (() => void) => list.subscribe(fn),\n }\n // The workbench strip sits above the input bar (order 0, first entry);\n // it renders only for data-agent sessions and returns null elsewhere.\n scope.slots.inject('conversation.input.dock', () => scope.slots.register({\n name: 'conversation.input.dock',\n id: 'data-agent',\n order: 0,\n locale: NS,\n inject: () => ({ hooks: { sessions: sessionsSource } }),\n }, DataAgentWorkbench))\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useRef","useState","css","StateDot","Modal"],"sources":["../src/client/persistence.ts","../src/client/DataAgentWorkbench.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Connection-config persistence for the database workbench. The most recent\n * successful connection (type/host/port/user/database/password) is kept in\n * localStorage under one key so remounts and restarts can restore the form\n * and auto-reconnect (the server-side connection store stays in-memory).\n *\n * Security note: the password is persisted in PLAIN TEXT by explicit user\n * decision (local single-user scenario) — see README 安全说明. The storage\n * key is versioned so a future shape change can migrate or ignore old data.\n * @module @yejiming/dsh-data-agent/persistence\n */\n\nimport type { DatabaseType } from './DataAgentWorkbench.tsx'\n\n/** localStorage key holding the most recent connection configuration. */\nexport const CONNECTION_STORAGE_KEY = 'dsh-data-agent.connection.v1'\n\n/** The persisted connection configuration. */\nexport interface SavedConnection {\n type: DatabaseType\n host?: string\n port?: number\n user?: string\n database: string\n /** Present only when the user explicitly opted in to persist the password. */\n password?: string\n /** Opt-in flag; when true, {@link saveConnection} may write `password`. */\n persistPassword?: boolean\n /** Diagnostic timestamp of the save. */\n savedAt: string\n}\n\n/** Runtime storage face (injectable for tests). */\nexport interface StorageLike {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/** The default storage face (localStorage; unavailable → degraded no-op). */\nfunction defaultStorage(): StorageLike | undefined {\n try {\n if (typeof localStorage !== 'undefined') {\n const probe = '__dsh_probe__'\n localStorage.setItem(probe, '1')\n localStorage.removeItem(probe)\n return localStorage\n }\n } catch {\n // localStorage disabled (privacy mode, sandboxed frame): degrade silently.\n }\n return undefined\n}\n\n/** Validate one parsed storage value into a SavedConnection (or null). */\nfunction parseSaved(value: unknown): SavedConnection | null {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return null\n const candidate = value as Record<string, unknown>\n const type = candidate.type\n if (type !== 'mysql' && type !== 'postgres' && type !== 'sqlite'\n && type !== 'oracle' && type !== 'hive' && type !== 'impala') {\n return null\n }\n const database = candidate.database\n // 草稿语义:database 允许为空串(用户可能只填了部分字段就切换会话)。\n if (typeof database !== 'string') return null\n const saved: SavedConnection = { type, database, savedAt: typeof candidate.savedAt === 'string' ? candidate.savedAt : '' }\n if (typeof candidate.host === 'string') saved.host = candidate.host\n if (typeof candidate.port === 'number' && Number.isInteger(candidate.port)) saved.port = candidate.port\n if (typeof candidate.user === 'string') saved.user = candidate.user\n // Legacy records may carry a password; strip it unless the opt-in flag is set\n // (a persisted password only survives when persistPassword was explicitly true).\n const persistPassword = candidate.persistPassword === true\n if (persistPassword) saved.persistPassword = true\n if (persistPassword && typeof candidate.password === 'string') saved.password = candidate.password\n return saved\n}\n\n/** Save one connection configuration (best-effort; storage failures degrade silently). */\nexport function saveConnection(connection: SavedConnection, storage: StorageLike | undefined = defaultStorage()): void {\n if (storage === undefined) return\n try {\n const toWrite: SavedConnection = { ...connection }\n // Password is opt-in only; strip it unless persistPassword is explicitly set.\n if (toWrite.persistPassword !== true) delete toWrite.password\n storage.setItem(CONNECTION_STORAGE_KEY, JSON.stringify(toWrite))\n } catch {\n // Quota / serialization failure: degrade silently, the UI stays usable.\n }\n}\n\n/** Load the saved connection configuration; null when absent or malformed. */\nexport function loadConnection(storage: StorageLike | undefined = defaultStorage()): SavedConnection | null {\n if (storage === undefined) return null\n try {\n const raw = storage.getItem(CONNECTION_STORAGE_KEY)\n if (raw === null) return null\n return parseSaved(JSON.parse(raw))\n } catch {\n return null\n }\n}\n\n/** Remove the saved connection configuration. */\nexport function clearConnection(storage: StorageLike | undefined = defaultStorage()): void {\n if (storage === undefined) return\n try {\n storage.removeItem(CONNECTION_STORAGE_KEY)\n } catch {\n // Degrade silently.\n }\n}\n","/**\n * The database workbench: connection config (collapsible after connect),\n * a browse button that opens the schema explorer Modal, and the SQL command\n * box, rendered into the composer input dock (the strip ABOVE the input bar)\n * for data-agent sessions.\n *\n * Layout is phase-driven by the conversation root's `data-phase` attribute:\n * - hero (blank session): the workbench is a full-width stacked strip above\n * the input bar (which stays at the bottom);\n * - active (conversation started): the workbench becomes a fixed left rail\n * (measured from the conversation column), the chat records and the input\n * bar shift right via the `da-split` CSS rules; if measurement is\n * unavailable the workbench falls back to a docked bottom panel.\n *\n * Interaction model:\n * - after a successful connect the connection form collapses into a summary\n * row (click 连接配置 to expand the readonly form again);\n * - the schema explorer lives in a Modal (ui-primitives) opened by the\n * 库表 button; a single click on a database toggles its table list in a\n * file-explorer style tree (folder rows with chevrons, indented table rows\n * with guide lines, the whole tree scrolls inside the column);\n * - clicking a table loads its columns into the Modal's structure panel.\n *\n * Non-data-agent sessions render null — zero impact on ordinary sessions.\n * Connection state lives on the server (the dataAgentConnections store), so\n * remounts never lose it — this component mirrors `/status` on mount.\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { Modal, StateDot } from '@deepseek-ai/dsh-client-ui-primitives'\n// Type-only: pulls the ui-conversation slot declarations (conversation.input.dock)\n// and the framework-standard view props into this program.\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport {\n loadConnection,\n saveConnection,\n type SavedConnection,\n} from './persistence.ts'\nimport css from './DataAgentWorkbench.module.css'\n\n/** The plugin's preset id, matching the installed agent preset directory. */\nconst DATA_AGENT_PRESET = 'data-agent'\n\n/** 16×16 stroke icons drawn inline (the primitives package does not export icon atoms). */\nfunction Icon({ className, children, size = 14 }: { className?: string; children: ReactNode; size?: number }) {\n return (\n <svg className={className} width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n {children}\n </svg>\n )\n}\n\n/** Database cylinder: section header of the connection form. */\nfunction DatabaseIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <ellipse cx=\"8\" cy=\"4\" rx=\"5.5\" ry=\"2.1\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M2.5 4V12C2.5 13.16 4.96 14.1 8 14.1C11.04 14.1 13.5 13.16 13.5 12V4\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M2.5 8C2.5 9.16 4.96 10.1 8 10.1C11.04 10.1 13.5 9.16 13.5 8\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </Icon>\n )\n}\n\n/** Table grid: browse row + table rows in the tree. */\nfunction TableIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <rect x=\"2\" y=\"3\" width=\"12\" height=\"10\" rx=\"1.5\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M2 6.5H14\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M6.5 6.5V13\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </Icon>\n )\n}\n\n/** Folder: schema rows in the tree. */\nfunction FolderIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <path\n d=\"M1.8 4.6C1.8 4.05 2.25 3.6 2.8 3.6H5.9L7.1 5.1H13.2C13.75 5.1 14.2 5.55 14.2 6.1V11.4C14.2 11.95 13.75 12.4 13.2 12.4H2.8C2.25 12.4 1.8 11.95 1.8 11.4V4.6Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />\n </Icon>\n )\n}\n\n/** Terminal prompt: section header of the SQL box. */\nfunction TerminalIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M4.5 6L6.5 8L4.5 10\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M8 10.5H11.2\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n </Icon>\n )\n}\n\n/** Chevron: tree expand indicator (rotates 90° when open). */\nfunction ChevronIcon({ className }: { className?: string }) {\n return (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M4.5 2.5L8 6L4.5 9.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\n/** Alert triangle: error bar heading. */\nfunction AlertIcon({ className }: { className?: string }) {\n return (\n <Icon className={className}>\n <path d=\"M8 2.2L14.2 13H1.8L8 2.2Z\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinejoin=\"round\" />\n <path d=\"M8 6.4V9.2\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"11\" r=\"0.9\" fill=\"currentColor\" />\n </Icon>\n )\n}\n\n/** Play triangle: SQL run button. */\nfunction PlayIcon({ className }: { className?: string }) {\n return (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3.4 2.1C3.4 1.66 3.88 1.4 4.26 1.62L9.9 5.02C10.26 5.23 10.26 5.77 9.9 5.98L4.26 9.38C3.88 9.6 3.4 9.34 3.4 8.9V2.1Z\" />\n </svg>\n )\n}\n\n/** Database kinds offered by the connection form. */\nexport type DatabaseType = 'mysql' | 'postgres' | 'sqlite' | 'oracle' | 'hive' | 'impala'\n\n/** The sessions-list slice the workbench needs (structural; avoids a runtime import). */\nexport interface SessionListLike {\n byId: Record<string, { agentPreset?: string }>\n}\n\n/** One described column. */\ninterface ColumnInfo {\n name: string\n type: string\n nullable?: boolean\n}\n\n/** Wire shapes of the plugin routes. */\ninterface ConnectResponse { ok: boolean; tables?: string[]; error?: string }\ninterface StatusResponse {\n connected: boolean\n summary?: {\n type: DatabaseType\n host?: string\n port?: number\n user?: string\n database: string\n readonly?: boolean\n tables?: string[]\n }\n}\ninterface SchemasResponse { ok: boolean; schemas?: string[]; error?: string }\ninterface TablesResponse { ok: boolean; tables?: string[]; error?: string }\ninterface DescribeResponse { ok: boolean; columns?: ColumnInfo[]; error?: string }\ninterface QueryResponse {\n ok: boolean\n result?: { exitCode: number | null; stdout: string; stderr: string; truncated: boolean }\n error?: string\n}\n\n/** Registration-side business face: the sessions-list observable becomes `useSessions`. */\nexport interface DataAgentWorkbenchInjected {\n hooks: {\n sessions: {\n getSnapshot(): SessionListLike\n subscribe(fn: () => void): () => void\n }\n }\n}\n\n/** The workbench's full component props: the dock seat + the locale seat + the injected sessions hook. */\nexport type DataAgentWorkbenchProps =\n PropsRuntime<'conversation.input.dock'>\n & PropsLocale<'data-agent'>\n & InjectFace<DataAgentWorkbenchInjected>\n\n/** The conversation column's phase attribute value while the session is blank. */\nfunction isHeroPhase(element: HTMLElement | null): boolean {\n return element?.getAttribute('data-phase') === 'hero'\n}\n\n/**\n * 开始对话后(active 布局)左栏工作台相对会话列顶部的下移偏移(px):\n * 让工作台避开会话头部区域、整体往下沉一些,顶部露出对话记录。\n */\nconst RAIL_TOP_OFFSET = 96\n\n/** Default port per type (used to fill the form from a saved connection). */\nfunction defaultPortOf(type: DatabaseType): string {\n switch (type) {\n case 'postgres': return '5432'\n case 'oracle': return '1521'\n case 'hive': return '10000'\n case 'impala': return '21050'\n case 'sqlite': return ''\n case 'mysql': return '3306'\n }\n}\n\n/** Run one /connect request (shared by the form connect and mount auto-reconnect). */\nasync function performConnect(sessionId: string, body: Record<string, unknown>): Promise<ConnectResponse> {\n const response = await fetch('/plugins/data-agent/connect', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId, ...body }),\n })\n return response.json() as Promise<ConnectResponse>\n}\n\n/** Build the /connect payload from a saved connection. */\nfunction payloadFromSaved(saved: SavedConnection): Record<string, unknown> {\n if (saved.type === 'sqlite') return { type: saved.type, database: saved.database }\n const body: Record<string, unknown> = {\n type: saved.type,\n host: saved.host ?? '127.0.0.1',\n user: saved.user ?? '',\n database: saved.database,\n }\n if (saved.port !== undefined) body.port = saved.port\n if (saved.password !== undefined && saved.password !== '') body.password = saved.password\n return body\n}\n\n/** The database workbench body. */\nexport function DataAgentWorkbench({ sessionId, useSessions, t }: DataAgentWorkbenchProps) {\n const list = useSessions(snapshot => snapshot)\n const isDataAgent = list.byId[sessionId as never]?.agentPreset === DATA_AGENT_PRESET\n\n const rootRef = useRef<HTMLDivElement | null>(null)\n const [phase, setPhase] = useState<'hero' | 'active'>('hero')\n const [railRect, setRailRect] = useState<{ left: number; top: number; bottom: number } | null>(null)\n\n // 表单从已保存的连接配置(localStorage)惰性初始化:切换会话/刷新/重启后回填。\n const [initialSaved] = useState(loadConnection)\n const [type, setType] = useState<DatabaseType>(initialSaved?.type ?? 'mysql')\n const [host, setHost] = useState(initialSaved?.host ?? '127.0.0.1')\n const [port, setPort] = useState(\n initialSaved?.port !== undefined ? String(initialSaved.port) : defaultPortOf(initialSaved?.type ?? 'mysql'),\n )\n const [user, setUser] = useState(initialSaved?.user ?? '')\n const [password, setPassword] = useState(initialSaved?.password ?? '')\n const [rememberPassword, setRememberPassword] = useState(initialSaved?.persistPassword === true)\n const [readonly, setReadonly] = useState(false)\n const [database, setDatabase] = useState(initialSaved?.database ?? '')\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [connected, setConnected] = useState(false)\n\n // Connection config Modal (form lives here now, not inline in the strip/rail).\n const [connectModalOpen, setConnectModalOpen] = useState(false)\n // Mount-time auto-reconnect in flight (from the saved connection).\n const [restoring, setRestoring] = useState(false)\n // Schema explorer Modal.\n const [schemaModalOpen, setSchemaModalOpen] = useState(false)\n\n const [schemas, setSchemas] = useState<string[]>([])\n const [activeSchema, setActiveSchema] = useState<string | null>(null)\n const [tables, setTables] = useState<string[]>([])\n const [activeTable, setActiveTable] = useState<string | null>(null)\n const [columns, setColumns] = useState<ColumnInfo[] | null>(null)\n\n const [sql, setSql] = useState('')\n const [sqlBusy, setSqlBusy] = useState(false)\n const [sqlResult, setSqlResult] = useState<string | null>(null)\n\n // Track the conversation column phase and its bounds for the left-rail\n // layout; toggle the da-split class that shifts chat + input to the right.\n useEffect(() => {\n const column = rootRef.current?.closest<HTMLElement>('[data-phase]') ?? null\n if (column === null) return\n const measure = (): void => {\n const rect = column.getBoundingClientRect()\n setRailRect({ left: rect.left, top: rect.top, bottom: window.innerHeight - rect.bottom })\n }\n const refreshPhase = (): void => { setPhase(isHeroPhase(column) ? 'hero' : 'active') }\n refreshPhase()\n measure()\n const observer = new MutationObserver(refreshPhase)\n observer.observe(column, { attributes: true, attributeFilter: ['data-phase'] })\n const resizer = new ResizeObserver(measure)\n resizer.observe(column)\n window.addEventListener('resize', measure)\n return () => {\n observer.disconnect()\n resizer.disconnect()\n window.removeEventListener('resize', measure)\n }\n }, [])\n\n // Split layout is active only for a live conversation (phase active) with\n // a measurable column; everything else stays stacked above the input.\n const split = phase === 'active' && railRect !== null\n useEffect(() => {\n const root = document.documentElement\n const splitClass = css['da-split']\n if (split && splitClass !== undefined) root.classList.add(splitClass)\n else if (splitClass !== undefined) root.classList.remove(splitClass)\n return () => { if (splitClass !== undefined) root.classList.remove(splitClass) }\n }, [split])\n\n // 草稿持久化:任何表单字段变化立即保存(含密码,用户已确认),\n // 使未连接的输入在切换会话/刷新后也能恢复。首轮跳过(初始化回填值\n // 无需重写,也避免从未输入时写入空配置)。\n const firstDraftRun = useRef(true)\n useEffect(() => {\n if (firstDraftRun.current) {\n firstDraftRun.current = false\n return\n }\n const draft: SavedConnection = {\n type,\n database,\n ...type !== 'sqlite' ? { host, user } : {},\n ...type !== 'sqlite' && port !== '' ? { port: Number(port) } : {},\n ...password !== '' ? { password } : {},\n ...rememberPassword ? { persistPassword: true } : {},\n savedAt: new Date().toISOString(),\n }\n saveConnection(draft)\n }, [type, host, port, user, database, password, rememberPassword])\n\n // Mirror the server-side connection on mount; auto-reconnect once when the\n // server store was lost (restart).\n useEffect(() => {\n let cancelled = false\n const saved = initialSaved\n setBusy(true)\n fetch(`/plugins/data-agent/status?sessionId=${encodeURIComponent(sessionId)}`)\n .then(response => response.json() as Promise<StatusResponse>)\n .then(async (body) => {\n if (cancelled) return\n if (body.connected) {\n setConnected(true)\n if (body.summary !== undefined) {\n setType(body.summary.type)\n setHost(body.summary.host ?? '')\n setPort(body.summary.port !== undefined ? String(body.summary.port) : '')\n setUser(body.summary.user ?? '')\n setDatabase(body.summary.database)\n setReadonly(body.summary.readonly === true)\n }\n const response = await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)\n const schemasBody = await response.json() as SchemasResponse\n if (!cancelled && schemasBody.ok) setSchemas(schemasBody.schemas ?? [])\n return\n }\n // Server connection lost (restart): restore with the saved config, once.\n // 草稿未完成(database 为空)时不自动重连,仅保留表单回填。\n if (saved !== null && saved.database !== '') {\n setRestoring(true)\n try {\n const result = await performConnect(sessionId, payloadFromSaved(saved))\n if (cancelled) return\n if (result.ok) {\n setConnected(true)\n setConnectModalOpen(false)\n const response = await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)\n const schemasBody = await response.json() as SchemasResponse\n if (!cancelled && schemasBody.ok) setSchemas(schemasBody.schemas ?? [])\n } else {\n setError(`连接恢复失败:${result.error ?? 'unknown error'}`)\n }\n } catch (cause) {\n if (!cancelled) {\n setError(`连接恢复失败:${cause instanceof Error ? cause.message : String(cause)}`)\n }\n } finally {\n if (!cancelled) setRestoring(false)\n }\n }\n })\n .catch(() => { /* the form stays usable; connect will surface errors */ })\n .finally(() => { if (!cancelled) setBusy(false) })\n return () => { cancelled = true }\n }, [sessionId])\n\n const sqlite = type === 'sqlite'\n\n const connect = async (): Promise<void> => {\n setBusy(true)\n setError(null)\n const body: Record<string, unknown> = { sessionId, type, readonly }\n if (sqlite) {\n body.database = database\n } else {\n body.host = host\n if (port !== '') body.port = Number(port)\n body.user = user\n body.database = database\n if (password !== '') body.password = password\n }\n try {\n const result = await performConnect(sessionId, body)\n if (result.ok) {\n setConnected(true)\n // Close the config Modal after a successful connect.\n setConnectModalOpen(false)\n const schemasResponse = await fetch(`/plugins/data-agent/schemas?sessionId=${encodeURIComponent(sessionId)}`)\n const schemasBody = await schemasResponse.json() as SchemasResponse\n if (schemasBody.ok) setSchemas(schemasBody.schemas ?? [])\n } else {\n setError(result.error ?? 'unknown error')\n }\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n const disconnect = async (): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n await fetch('/plugins/data-agent/disconnect', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId }),\n })\n setConnected(false)\n setReadonly(false)\n setSchemaModalOpen(false)\n setSchemas([])\n setActiveSchema(null)\n setTables([])\n setActiveTable(null)\n setColumns(null)\n setSqlResult(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n /** Toggle one schema's table list (single click; only one open at a time). */\n const toggleSchema = async (schema: string): Promise<void> => {\n if (activeSchema === schema) {\n setActiveSchema(null)\n setTables([])\n setActiveTable(null)\n setColumns(null)\n return\n }\n setActiveSchema(schema)\n setActiveTable(null)\n setColumns(null)\n setTables([])\n try {\n const response = await fetch(\n `/plugins/data-agent/tables?sessionId=${encodeURIComponent(sessionId)}&schema=${encodeURIComponent(schema)}`,\n )\n const result = await response.json() as TablesResponse\n if (result.ok) setTables(result.tables ?? [])\n else setError(result.error ?? 'unknown error')\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const selectTable = async (table: string): Promise<void> => {\n setActiveTable(table)\n setColumns(null)\n const params = new URLSearchParams({ sessionId, table })\n if (activeSchema !== null) params.set('schema', activeSchema)\n try {\n const response = await fetch(`/plugins/data-agent/describe?${params.toString()}`)\n const result = await response.json() as DescribeResponse\n if (result.ok) setColumns(result.columns ?? [])\n else setError(result.error ?? 'unknown error')\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const runSql = async (): Promise<void> => {\n if (sql.trim() === '') return\n setSqlBusy(true)\n setSqlResult(null)\n try {\n const response = await fetch('/plugins/data-agent/query', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId, sql }),\n })\n const result = await response.json() as QueryResponse\n if (result.ok && result.result !== undefined) {\n const parts: string[] = []\n if (result.result.stdout !== '') parts.push(result.result.stdout)\n if (result.result.stderr !== '') parts.push(`[stderr]\\n${result.result.stderr}`)\n if (result.result.truncated) parts.push('… 输出超过上限,已截断')\n if (result.result.exitCode !== 0) parts.push(`[exit code: ${result.result.exitCode ?? 'signal'}]`)\n setSqlResult(parts.join('\\n'))\n } else {\n setSqlResult(`Error: ${result.error ?? 'unknown error'}`)\n }\n } catch (cause) {\n setSqlResult(`Error: ${cause instanceof Error ? cause.message : String(cause)}`)\n } finally {\n setSqlBusy(false)\n }\n }\n\n // A session not running the data-agent preset: nothing renders at all.\n if (!isDataAgent) return null\n\n const databaseLabel = sqlite\n ? t('form.database.sqlite')\n : type === 'oracle'\n ? t('form.database.oracle')\n : type === 'hive' || type === 'impala'\n ? t('form.database.hive')\n : t('form.database')\n\n const railStyle = split\n ? {\n position: 'fixed' as const,\n left: railRect!.left,\n top: railRect!.top + RAIL_TOP_OFFSET,\n bottom: railRect!.bottom,\n width: 380,\n }\n : undefined\n\n // Form fields are readonly while connected (edit requires disconnecting).\n const formDisabled = busy || connected\n\n return (\n <div\n ref={rootRef}\n className={`${css.workbench} ${split ? css.rail : phase === 'active' ? css.docked : css.strip}`}\n style={railStyle}\n >\n <div className={css.sections}>\n {connected ? (\n // ── connected summary row (config lives in a Modal now) ─────────\n <section className={css.card}>\n <div className={css.summaryRow}>\n <StateDot state=\"done\" size={8} className={css.dot} />\n <span className={css.statusOk}>{t('state.connected')}</span>\n <span className={css.summaryType}>{t(`type.${type}`)}</span>\n <span className={css.summaryDb} title={database}>{database}</span>\n <span className={css.summaryActions}>\n <button type=\"button\" className={`${css.ghost} ${css.small}`} onClick={() => setConnectModalOpen(true)}>\n {t('action.config')}\n </button>\n <button type=\"button\" className={`${css.ghost} ${css.small}`} disabled={busy} onClick={() => { void disconnect() }}>\n {t('action.disconnect')}\n </button>\n </span>\n </div>\n </section>\n ) : (\n // ── disconnected hero: a single connect entry, no inline form ────\n <section className={css.card}>\n <button type=\"button\" className={css.heroConnect} onClick={() => setConnectModalOpen(true)}>\n <DatabaseIcon className={css.heroIcon} />\n <span className={css.heroText}>\n <span className={css.heroTitle}>{t('form.hero.title')}</span>\n <span className={css.heroHint}>{t('form.hero.hint')}</span>\n </span>\n <ChevronIcon className={css.heroChevron} />\n </button>\n </section>\n )}\n\n {connected && (\n // ── schema explorer entry ───────────────────────────────────────\n <section className={css.card}>\n <button type=\"button\" className={css.browseRow} onClick={() => setSchemaModalOpen(true)}>\n <TableIcon className={css.browseIcon} />\n <span>{t('action.browse')}</span>\n <ChevronIcon className={css.browseChevron} />\n </button>\n </section>\n )}\n\n {connected && (\n <section className={css.card}>\n <div className={css.cardTitle}>\n <TerminalIcon className={css.titleIcon} />\n <span>{t('wb.sql')}</span>\n </div>\n <textarea\n className={css.sqlInput}\n value={sql}\n rows={8}\n spellCheck={false}\n placeholder={t('wb.sql.placeholder')}\n onChange={(event) => setSql(event.target.value)}\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void runSql()\n }\n }}\n />\n <div className={css.sqlActions}>\n <span className={css.shortcutHint}>{t('wb.sql.shortcut')}</span>\n <button\n type=\"button\"\n className={css.primary}\n disabled={sqlBusy || !connected || sql.trim() === ''}\n onClick={() => { void runSql() }}\n >\n <PlayIcon />\n {sqlBusy ? t('wb.sql.running') : t('wb.sql.run')}\n </button>\n </div>\n <pre className={css.sqlResult}>{sqlResult ?? t('wb.sql.empty')}</pre>\n </section>\n )}\n </div>\n\n {error !== null && !connectModalOpen && (\n <div className={css.errorBar}>\n <div className={css.errorHead}>\n <AlertIcon className={css.errorIcon} />\n <span>{t('error.title')}</span>\n </div>\n <span className={css.errorText}>{error}</span>\n </div>\n )}\n\n {schemaModalOpen && (\n <Modal\n open={schemaModalOpen}\n onClose={() => setSchemaModalOpen(false)}\n title={t('wb.modal.title')}\n closeLabel={t('action.close')}\n className={css.schemaModal}\n >\n <div className={css.modalBody}>\n <div className={css.modalCol}>\n <div className={css.modalColTitle}>\n <span>{t('wb.schemas')}</span>\n {schemas.length > 0 && <span className={css.colCount}>{schemas.length}</span>}\n </div>\n <div className={css.treeScroll}>\n {schemas.length === 0 && <div className={css.hint}>{t('wb.loading')}</div>}\n <ul className={css.tree}>\n {schemas.map(schema => (\n <li key={schema} className={css.treeNode}>\n <button\n type=\"button\"\n className={`${css.treeItem}${activeSchema === schema ? ` ${css.active}` : ''}`}\n onClick={() => { void toggleSchema(schema) }}\n >\n <ChevronIcon className={`${css.treeChevron}${activeSchema === schema ? ` ${css.open}` : ''}`} />\n <FolderIcon className={css.treeIcon} />\n <span className={css.treeName}>{schema}</span>\n {activeSchema === schema && tables.length > 0 && (\n <span className={css.treeCount}>{tables.length}</span>\n )}\n </button>\n {activeSchema === schema && (\n <div className={css.treeChildren}>\n {tables.length === 0 && <div className={css.hint}>{t('wb.empty')}</div>}\n {tables.map(table => (\n <button\n key={table}\n type=\"button\"\n className={`${css.treeItem}${activeTable === table ? ` ${css.active}` : ''}`}\n onClick={() => { void selectTable(table) }}\n >\n <TableIcon className={css.treeIcon} />\n <span className={css.treeName}>{table}</span>\n </button>\n ))}\n </div>\n )}\n </li>\n ))}\n </ul>\n </div>\n <div className={css.modalHint}>{t('wb.hint.click')}</div>\n </div>\n\n <div className={css.modalCol}>\n <div className={css.modalColTitle}>\n <span>{t('wb.columns')}{activeTable !== null && ` · ${activeTable}`}</span>\n </div>\n {columns === null ? (\n <div className={css.emptyState}>\n <TableIcon className={css.emptyStateIcon} />\n <span className={css.emptyStateText}>{t('wb.hint.click')}</span>\n </div>\n ) : (\n <div className={css.colScroll}>\n <table className={css.columnsTable}>\n <thead>\n <tr><th>name</th><th>type</th><th>null</th></tr>\n </thead>\n <tbody>\n {columns.map(column => (\n <tr key={column.name}>\n <td>{column.name}</td>\n <td className={css.typeCell}>{column.type}</td>\n <td className={css.nullCell}>{column.nullable === undefined ? '' : column.nullable ? 'YES' : 'NO'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n </Modal>\n )}\n\n {connectModalOpen && (\n <Modal\n open={connectModalOpen}\n onClose={() => setConnectModalOpen(false)}\n title={t('form.title')}\n closeLabel={t('action.close')}\n className={css.connectModal}\n >\n <div className={css.connectModalBody}>\n <div className={css.fieldGrid}>\n <label className={css.field}>\n <span className={css.label}>{t('form.type')}</span>\n <select\n className={css.input}\n value={type}\n disabled={formDisabled}\n onChange={(event) => {\n const next = event.target.value as DatabaseType\n setType(next)\n setPort(next === 'postgres' ? '5432' : next === 'mysql' ? '3306' : next === 'oracle' ? '1521' : next === 'hive' ? '10000' : next === 'impala' ? '21050' : '')\n }}\n >\n <option value=\"mysql\">{t('type.mysql')}</option>\n <option value=\"postgres\">{t('type.postgres')}</option>\n <option value=\"sqlite\">{t('type.sqlite')}</option>\n <option value=\"oracle\">{t('type.oracle')}</option>\n <option value=\"hive\">{t('type.hive')}</option>\n <option value=\"impala\">{t('type.impala')}</option>\n </select>\n </label>\n\n {!sqlite && (\n <div className={css.fieldRow2}>\n <label className={css.field}>\n <span className={css.label}>{t('form.host')}</span>\n <input className={css.input} type=\"text\" value={host} disabled={formDisabled} onChange={(event) => setHost(event.target.value)} />\n </label>\n <label className={css.field}>\n <span className={css.label}>{t('form.port')}</span>\n <input className={css.input} type=\"number\" min={1} max={65535} value={port} disabled={formDisabled} onChange={(event) => setPort(event.target.value)} />\n </label>\n </div>\n )}\n\n {!sqlite && (\n <div className={css.fieldRow2}>\n <label className={css.field}>\n <span className={css.label}>{t('form.user')}</span>\n <input className={css.input} type=\"text\" value={user} disabled={formDisabled} onChange={(event) => setUser(event.target.value)} />\n </label>\n <label className={css.field}>\n <span className={css.label}>{t('form.password')}</span>\n <input className={css.input} type=\"password\" value={password} autoComplete=\"new-password\" disabled={formDisabled} onChange={(event) => setPassword(event.target.value)} />\n </label>\n </div>\n )}\n\n {!sqlite && (\n <label className={css.rememberRow}>\n <input\n type=\"checkbox\"\n checked={rememberPassword}\n disabled={formDisabled}\n onChange={(event) => setRememberPassword(event.target.checked)}\n />\n <span>{t('form.rememberPassword')}</span>\n <span className={css.rememberHint}>{t('form.rememberPassword.hint')}</span>\n </label>\n )}\n\n <label className={css.rememberRow}>\n <input\n type=\"checkbox\"\n checked={readonly}\n disabled={formDisabled}\n onChange={(event) => setReadonly(event.target.checked)}\n />\n <span>{t('form.readonly')}</span>\n <span className={css.rememberHint}>{t('form.readonly.hint')}</span>\n </label>\n\n <label className={css.field}>\n <span className={css.label}>{databaseLabel}</span>\n <input\n className={css.input}\n type=\"text\"\n value={database}\n placeholder={sqlite ? t('form.database.sqlite.placeholder') : undefined}\n disabled={formDisabled}\n onChange={(event) => setDatabase(event.target.value)}\n />\n </label>\n </div>\n\n <div className={css.actions}>\n {!connected ? (\n <button\n type=\"button\"\n className={css.primary}\n disabled={busy || database === '' || (!sqlite && host === '')}\n onClick={() => { void connect() }}\n >\n {restoring ? t('state.reconnecting') : busy ? t('state.checking') : t('action.connect')}\n </button>\n ) : (\n <button type=\"button\" className={css.ghost} disabled={busy} onClick={() => { void disconnect() }}>\n {t('action.disconnect')}\n </button>\n )}\n </div>\n\n {error !== null && (\n <div className={css.errorBar}>\n <div className={css.errorHead}>\n <AlertIcon className={css.errorIcon} />\n <span>{t('error.title')}</span>\n </div>\n <span className={css.errorText}>{error}</span>\n </div>\n )}\n </div>\n </Modal>\n )}\n </div>\n )\n}\n","/** `data-agent` namespace dictionaries for the database workbench. */\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'data-agent'\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'form.title': '数据库连接',\n 'form.hero.title': '连接数据库',\n 'form.hero.hint': '连接 MySQL / PostgreSQL / SQLite 等,开始与数据 Agent 对话',\n 'form.type': '数据库类型',\n 'type.mysql': 'MySQL',\n 'type.postgres': 'PostgreSQL',\n 'type.sqlite': 'SQLite',\n 'type.oracle': 'Oracle',\n 'type.hive': 'Hive',\n 'type.impala': 'Impala',\n 'form.host': '主机',\n 'form.port': '端口',\n 'form.user': '用户名',\n 'form.password': '密码',\n 'form.rememberPassword': '记住密码',\n 'form.rememberPassword.hint': '仅勾选后才会在本机保存密码',\n 'form.readonly': '只读模式',\n 'form.readonly.hint': '仅放行查询语句,拒绝增删改、建表等写操作',\n 'form.database': '数据库名',\n 'form.database.oracle': '服务名 / SID',\n 'form.database.hive': '默认库',\n 'form.database.impala': '默认库',\n 'form.database.sqlite': '数据库文件路径',\n 'form.database.sqlite.placeholder': '/path/to/orders.db',\n 'action.connect': '连接',\n 'action.disconnect': '断开',\n 'state.connected': '已连接',\n 'state.disconnected': '未连接',\n 'state.checking': '正在检查连接…',\n 'state.reconnecting': '正在恢复连接…',\n 'wb.schemas': '库',\n 'wb.tables': '表',\n 'wb.columns': '表结构',\n 'wb.sql': 'SQL 命令',\n 'wb.sql.placeholder': '在此输入 SQL,例如 SELECT * FROM orders LIMIT 10;',\n 'wb.sql.run': '运行',\n 'wb.sql.running': '运行中…',\n 'wb.sql.shortcut': 'Ctrl / ⌘ + Enter 运行',\n 'wb.sql.empty': '-- 尚无输出 --',\n 'wb.loading': '加载中…',\n 'wb.empty': '(空)',\n 'wb.modal.title': '库表浏览',\n 'wb.hint.click': '单击库展开表 · 点击表查看结构',\n 'action.config': '连接配置',\n 'action.browse': '库表',\n 'action.close': '关闭',\n 'error.title': '操作失败',\n} satisfies Record<string, string>\n\n/** The data-agent namespace key union. */\nexport type DataAgentKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'form.title': 'Database connection',\n 'form.hero.title': 'Connect database',\n 'form.hero.hint': 'Connect MySQL / PostgreSQL / SQLite and start chatting with the data agent',\n 'form.type': 'Database type',\n 'type.mysql': 'MySQL',\n 'type.postgres': 'PostgreSQL',\n 'type.sqlite': 'SQLite',\n 'type.oracle': 'Oracle',\n 'type.hive': 'Hive',\n 'type.impala': 'Impala',\n 'form.host': 'Host',\n 'form.port': 'Port',\n 'form.user': 'User',\n 'form.password': 'Password',\n 'form.rememberPassword': 'Remember password',\n 'form.rememberPassword.hint': 'Saved locally only when checked',\n 'form.readonly': 'Read-only mode',\n 'form.readonly.hint': 'Allow read queries only; reject writes (INSERT/UPDATE/DELETE/DDL)',\n 'form.database': 'Database',\n 'form.database.oracle': 'Service name / SID',\n 'form.database.hive': 'Default database',\n 'form.database.impala': 'Default database',\n 'form.database.sqlite': 'Database file path',\n 'form.database.sqlite.placeholder': '/path/to/orders.db',\n 'action.connect': 'Connect',\n 'action.disconnect': 'Disconnect',\n 'state.connected': 'Connected',\n 'state.disconnected': 'Not connected',\n 'state.checking': 'Checking connection…',\n 'state.reconnecting': 'Restoring connection…',\n 'wb.schemas': 'Databases',\n 'wb.tables': 'Tables',\n 'wb.columns': 'Columns',\n 'wb.sql': 'SQL',\n 'wb.sql.placeholder': 'Write SQL here, e.g. SELECT * FROM orders LIMIT 10;',\n 'wb.sql.run': 'Run',\n 'wb.sql.running': 'Running…',\n 'wb.sql.shortcut': 'Ctrl / ⌘ + Enter to run',\n 'wb.sql.empty': '-- no output --',\n 'wb.loading': 'Loading…',\n 'wb.empty': '(empty)',\n 'wb.modal.title': 'Database explorer',\n 'wb.hint.click': 'Click a database to expand tables · click a table for columns',\n 'action.config': 'Connection settings',\n 'action.browse': 'Tables',\n 'action.close': 'Close',\n 'error.title': 'Operation failed',\n} satisfies Record<DataAgentKey, string>\n","/**\n * Data Agent browser half, plugin entry: registers the database workbench\n * into the composer input dock (the strip ABOVE the input bar) for\n * data-agent sessions, and the `data-agent` dictionaries. The old\n * conversation-view tab is gone — the workbench lives inside the session.\n * Connection state lives in the server-side connection store, so layout and\n * session switches never lose it — the view only mirrors what\n * `/plugins/data-agent/status` reports.\n * @module @yejiming/dsh-data-agent/client\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale) into this program.\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the ui-conversation slot declarations (conversation.input.dock)\n// and the session standard props (sessionId) into this program.\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { DataAgentWorkbench, type SessionListLike } from './DataAgentWorkbench.tsx'\nimport { NS, en, zh, type DataAgentKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** The database workbench copy. */\n 'data-agent': DataAgentKey\n }\n}\n\n/** Required services: the locale service, the slot registry, and the sessions list. */\nexport const inject = ['slots', 'locale', 'sessions']\n\n/**\n * Client plugin body: register the data-agent dictionaries and the database\n * workbench into the composer input dock. The registration rides the slot\n * service's effect wrapper, so plugin unload removes it.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'data-agent: dictionaries')\n const t = ctx.locale.bind(NS)\n ctx.inject(['slots', 'locale', 'sessions'], (scope: ClientContext) => {\n const list = scope.sessions.list\n // The sessions list is the agent-preset authority on the client: the\n // ui-agent-preset surface records `agentPreset` onto each session summary.\n const sessionsSource = {\n getSnapshot: (): SessionListLike => list.getSnapshot() as unknown as SessionListLike,\n subscribe: (fn: () => void): (() => void) => list.subscribe(fn),\n }\n // The workbench strip sits above the input bar (order 0, first entry);\n // it renders only for data-agent sessions and returns null elsewhere.\n scope.slots.inject('conversation.input.dock', () => scope.slots.register({\n name: 'conversation.input.dock',\n id: 'data-agent',\n order: 0,\n locale: NS,\n inject: () => ({ hooks: { sessions: sessionsSource } }),\n }, DataAgentWorkbench))\n })\n}\n"],"mappings":"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"}
@@ -4,6 +4,8 @@ export declare const NS = "data-agent";
4
4
  /** Simplified Chinese dictionary (the key-set source of truth). */
5
5
  export declare const zh: {
6
6
  'form.title': string;
7
+ 'form.hero.title': string;
8
+ 'form.hero.hint': string;
7
9
  'form.type': string;
8
10
  'type.mysql': string;
9
11
  'type.postgres': string;
@@ -47,7 +49,6 @@ export declare const zh: {
47
49
  'action.config': string;
48
50
  'action.browse': string;
49
51
  'action.close': string;
50
- 'action.collapse': string;
51
52
  'error.title': string;
52
53
  };
53
54
  /** The data-agent namespace key union. */
@@ -55,6 +56,8 @@ export type DataAgentKey = keyof typeof zh;
55
56
  /** English dictionary, checked complete against the zh key set. */
56
57
  export declare const en: {
57
58
  'form.title': string;
59
+ 'form.hero.title': string;
60
+ 'form.hero.hint': string;
58
61
  'form.type': string;
59
62
  'type.mysql': string;
60
63
  'type.postgres': string;
@@ -98,6 +101,5 @@ export declare const en: {
98
101
  'action.config': string;
99
102
  'action.browse': string;
100
103
  'action.close': string;
101
- 'action.collapse': string;
102
104
  'error.title': string;
103
105
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yejiming/dsh-data-agent",
3
3
  "description": "Data Agent for the dsh web GUI: session-scoped database connections (MySQL/PostgreSQL/SQLite), the sqlcmd tool, the data-agent agent preset, and the database conversation-view tab",
4
- "version": "0.0.2",
4
+ "version": "0.0.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },