@hienlh/ppm 0.23.13 → 0.23.15
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/CHANGELOG.md +58 -0
- package/CLAUDE.md +19 -4
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/assets/skills/ppm/SKILL.md +3 -2
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/common-tasks.md +6 -0
- package/assets/skills/ppm/references/http-api.md +13 -1
- package/bun.lock +15 -0
- package/dist/web/assets/accounts-settings-section-B5YXy0vd.js +1 -0
- package/dist/web/assets/accounts-settings-section-B5YXy0vd.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-B5YXy0vd.js.gz +0 -0
- package/dist/web/assets/adaptive-context-menu-C4jNSORA.js +1 -0
- package/dist/web/assets/adaptive-context-menu-C4jNSORA.js.br +0 -0
- package/dist/web/assets/adaptive-context-menu-C4jNSORA.js.gz +0 -0
- package/dist/web/assets/agent-session-sheet-Bj42PwCK.js +2 -0
- package/dist/web/assets/agent-session-sheet-Bj42PwCK.js.br +0 -0
- package/dist/web/assets/agent-session-sheet-Bj42PwCK.js.gz +0 -0
- package/dist/web/assets/agent-session-sheet-store-BAfLnsLX.js +1 -0
- package/dist/web/assets/agent-session-window-content-LqL6fVPU.js +1 -0
- package/dist/web/assets/agent-session-window-content-LqL6fVPU.js.br +0 -0
- package/dist/web/assets/agent-session-window-content-LqL6fVPU.js.gz +0 -0
- package/dist/web/assets/ai-resource-editor-jVv2nvAG.js +1 -0
- package/dist/web/assets/ai-resource-editor-jVv2nvAG.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-jVv2nvAG.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-C9Q-v8fY.js +1 -0
- package/dist/web/assets/ai-settings-section-C9Q-v8fY.js.br +0 -0
- package/dist/web/assets/ai-settings-section-C9Q-v8fY.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-CN5BR1ZZ.js +1 -0
- package/dist/web/assets/android-tab-CwqiuEZP.js +2 -0
- package/dist/web/assets/android-tab-CwqiuEZP.js.br +0 -0
- package/dist/web/assets/android-tab-CwqiuEZP.js.gz +0 -0
- package/dist/web/assets/api-client-xQDlhUTu.js +1 -0
- package/dist/web/assets/api-client-xQDlhUTu.js.br +0 -0
- package/dist/web/assets/api-client-xQDlhUTu.js.gz +0 -0
- package/dist/web/assets/api-client-xR05zj6r.js +1 -0
- package/dist/web/assets/api-settings-VAi0LpIJ.js +1 -0
- package/dist/web/assets/api-settings-vmIRFNwZ.js +1 -0
- package/dist/web/assets/api-settings-vmIRFNwZ.js.br +0 -0
- package/dist/web/assets/api-settings-vmIRFNwZ.js.gz +0 -0
- package/dist/web/assets/api-themes-CaXofG7d.js +1 -0
- package/dist/web/assets/appearance-settings-section-D0JIfiRx.js +1 -0
- package/dist/web/assets/appearance-settings-section-D0JIfiRx.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-D0JIfiRx.js.gz +0 -0
- package/dist/web/assets/apps-panel-Cz_KJ37M.js +1 -0
- package/dist/web/assets/apps-panel-Cz_KJ37M.js.br +0 -0
- package/dist/web/assets/apps-panel-Cz_KJ37M.js.gz +0 -0
- package/dist/web/assets/audio-preview-Dq7qZ_6i.js +1 -0
- package/dist/web/assets/audio-preview-Dq7qZ_6i.js.br +0 -0
- package/dist/web/assets/audio-preview-Dq7qZ_6i.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-C3QNpsm7.js +1 -0
- package/dist/web/assets/branch-review-tab-C3QNpsm7.js.br +0 -0
- package/dist/web/assets/branch-review-tab-C3QNpsm7.js.gz +0 -0
- package/dist/web/assets/button-C9ZXWb3b.js +1 -0
- package/dist/web/assets/button-C9ZXWb3b.js.br +0 -0
- package/dist/web/assets/button-C9ZXWb3b.js.gz +0 -0
- package/dist/web/assets/chat-preparation-cache-190LLyy7.js +1 -0
- package/dist/web/assets/chat-preparation-cache-190LLyy7.js.br +0 -0
- package/dist/web/assets/chat-preparation-cache-190LLyy7.js.gz +0 -0
- package/dist/web/assets/chat-tab-D14CUl0J.js +1 -0
- package/dist/web/assets/chat-tab-D14CUl0J.js.br +0 -0
- package/dist/web/assets/chat-tab-D14CUl0J.js.gz +0 -0
- package/dist/web/assets/chat-tab-D8iAVZKV.js +16 -0
- package/dist/web/assets/chat-tab-D8iAVZKV.js.br +0 -0
- package/dist/web/assets/chat-tab-D8iAVZKV.js.gz +0 -0
- package/dist/web/assets/code-editor-B7gbH4-x.js +10 -0
- package/dist/web/assets/code-editor-B7gbH4-x.js.br +0 -0
- package/dist/web/assets/code-editor-B7gbH4-x.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-DQDtyvnd.js +1 -0
- package/dist/web/assets/codex-reset-credit-button-DQDtyvnd.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-DQDtyvnd.js.gz +0 -0
- package/dist/web/assets/conflict-editor-ktOkrODA.js +19 -0
- package/dist/web/assets/conflict-editor-ktOkrODA.js.br +0 -0
- package/dist/web/assets/conflict-editor-ktOkrODA.js.gz +0 -0
- package/dist/web/assets/connection-form-tab-CxvExR7T.js +4 -0
- package/dist/web/assets/connection-form-tab-CxvExR7T.js.br +0 -0
- package/dist/web/assets/connection-form-tab-CxvExR7T.js.gz +0 -0
- package/dist/web/assets/context-menu-BCuZYfWC.js +1 -0
- package/dist/web/assets/context-menu-BCuZYfWC.js.br +0 -0
- package/dist/web/assets/context-menu-BCuZYfWC.js.gz +0 -0
- package/dist/web/assets/createLucideIcon-D9_fdOKS.js +1 -0
- package/dist/web/assets/createLucideIcon-D9_fdOKS.js.br +0 -0
- package/dist/web/assets/createLucideIcon-D9_fdOKS.js.gz +0 -0
- package/dist/web/assets/csv-preview-CBDMTEsF.js +10 -0
- package/dist/web/assets/csv-preview-CBDMTEsF.js.br +0 -0
- package/dist/web/assets/csv-preview-CBDMTEsF.js.gz +0 -0
- package/dist/web/assets/database-drivers-section-DJvU6bf5.js +1 -0
- package/dist/web/assets/database-drivers-section-DJvU6bf5.js.br +0 -0
- package/dist/web/assets/database-drivers-section-DJvU6bf5.js.gz +0 -0
- package/dist/web/assets/db-ai-tools-CVbbW_MZ.js +1 -0
- package/dist/web/assets/db-ai-tools-CVbbW_MZ.js.br +0 -0
- package/dist/web/assets/db-ai-tools-CVbbW_MZ.js.gz +0 -0
- package/dist/web/assets/db-explorer-store-BmpvDHz6.js +1 -0
- package/dist/web/assets/db-explorer-store-BmpvDHz6.js.br +0 -0
- package/dist/web/assets/db-explorer-store-BmpvDHz6.js.gz +0 -0
- package/dist/web/assets/db-sidebar-reveal-_qw0CliT.js +1 -0
- package/dist/web/assets/db-sidebar-reveal-_qw0CliT.js.br +0 -0
- package/dist/web/assets/db-sidebar-reveal-_qw0CliT.js.gz +0 -0
- package/dist/web/assets/db-tab-parts-BgVpKbi6.js +1 -0
- package/dist/web/assets/db-tab-parts-BgVpKbi6.js.br +0 -0
- package/dist/web/assets/db-tab-parts-BgVpKbi6.js.gz +0 -0
- package/dist/web/assets/db-types-CNhENouW.js +1 -0
- package/dist/web/assets/design-canvas-check-BIHc2d_k.js +1 -0
- package/dist/web/assets/design-canvas-check-BIHc2d_k.js.br +0 -0
- package/dist/web/assets/design-canvas-check-BIHc2d_k.js.gz +0 -0
- package/dist/web/assets/design-export-client-CJ3w7Zrk.js +1 -0
- package/dist/web/assets/design-export-client-CJ3w7Zrk.js.br +0 -0
- package/dist/web/assets/design-export-client-CJ3w7Zrk.js.gz +0 -0
- package/dist/web/assets/design-responsive-dialog-MAFgVOmv.js +1 -0
- package/dist/web/assets/design-responsive-dialog-MAFgVOmv.js.br +0 -0
- package/dist/web/assets/design-responsive-dialog-MAFgVOmv.js.gz +0 -0
- package/dist/web/assets/design-settings-section-DPGw61pY.js +2 -0
- package/dist/web/assets/design-settings-section-DPGw61pY.js.br +0 -0
- package/dist/web/assets/design-settings-section-DPGw61pY.js.gz +0 -0
- package/dist/web/assets/design-skill-suggestion-Dmmg_ap5.js +3 -0
- package/dist/web/assets/design-skill-suggestion-Dmmg_ap5.js.br +0 -0
- package/dist/web/assets/design-skill-suggestion-Dmmg_ap5.js.gz +0 -0
- package/dist/web/assets/design-tab-BiCqHNl3.js +57 -0
- package/dist/web/assets/design-tab-BiCqHNl3.js.br +0 -0
- package/dist/web/assets/design-tab-BiCqHNl3.js.gz +0 -0
- package/dist/web/assets/designs-sidebar-panel-pcJ2Rx5G.js +1 -0
- package/dist/web/assets/designs-sidebar-panel-pcJ2Rx5G.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-pcJ2Rx5G.js.gz +0 -0
- package/dist/web/assets/dialog-Dn_2tuYa.js +1 -0
- package/dist/web/assets/dialog-Dn_2tuYa.js.br +0 -0
- package/dist/web/assets/dialog-Dn_2tuYa.js.gz +0 -0
- package/dist/web/assets/diff-viewer-CLAvyqVG.js +4 -0
- package/dist/web/assets/diff-viewer-CLAvyqVG.js.br +0 -0
- package/dist/web/assets/diff-viewer-CLAvyqVG.js.gz +0 -0
- package/dist/web/assets/docx-preview-XSkD2IL6.js +12 -0
- package/dist/web/assets/docx-preview-XSkD2IL6.js.br +0 -0
- package/dist/web/assets/docx-preview-XSkD2IL6.js.gz +0 -0
- package/dist/web/assets/dropdown-menu-BQidk_OJ.js +1 -0
- package/dist/web/assets/dropdown-menu-BQidk_OJ.js.br +0 -0
- package/dist/web/assets/dropdown-menu-BQidk_OJ.js.gz +0 -0
- package/dist/web/assets/edit-diff-preview-DyWUMlkI.js +7 -0
- package/dist/web/assets/edit-diff-preview-DyWUMlkI.js.br +0 -0
- package/dist/web/assets/edit-diff-preview-DyWUMlkI.js.gz +0 -0
- package/dist/web/assets/editor-dialog-cQvqVZAR.js +1 -0
- package/dist/web/assets/editor-dialog-cQvqVZAR.js.br +0 -0
- package/dist/web/assets/editor-dialog-cQvqVZAR.js.gz +0 -0
- package/dist/web/assets/editor-language-service-6-7mS6_9.js +1 -0
- package/dist/web/assets/editor-language-service-6-7mS6_9.js.br +0 -0
- package/dist/web/assets/editor-language-service-6-7mS6_9.js.gz +0 -0
- package/dist/web/assets/explorer-body-BlGDPmNa.js +2 -0
- package/dist/web/assets/explorer-body-BlGDPmNa.js.br +0 -0
- package/dist/web/assets/explorer-body-BlGDPmNa.js.gz +0 -0
- package/dist/web/assets/explorer-model-BtJN4MZ9.js +1 -0
- package/dist/web/assets/explorer-model-BtJN4MZ9.js.br +0 -0
- package/dist/web/assets/explorer-model-BtJN4MZ9.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-BLWY8GJ_.js +1 -0
- package/dist/web/assets/explorer-window-content-BLWY8GJ_.js.br +0 -0
- package/dist/web/assets/explorer-window-content-BLWY8GJ_.js.gz +0 -0
- package/dist/web/assets/extension-manager-section-NSEt5f4z.js +1 -0
- package/dist/web/assets/extension-manager-section-NSEt5f4z.js.br +0 -0
- package/dist/web/assets/extension-manager-section-NSEt5f4z.js.gz +0 -0
- package/dist/web/assets/extension-webview-BkAEBWin.js +12 -0
- package/dist/web/assets/extension-webview-BkAEBWin.js.br +0 -0
- package/dist/web/assets/extension-webview-BkAEBWin.js.gz +0 -0
- package/dist/web/assets/file-diff-CcDhJkXB.js +1 -0
- package/dist/web/assets/file-icons-JInFtBVl.js +1 -0
- package/dist/web/assets/file-icons-JInFtBVl.js.br +0 -0
- package/dist/web/assets/file-icons-JInFtBVl.js.gz +0 -0
- package/dist/web/assets/file-store-BQ41vIs5.js +1 -0
- package/dist/web/assets/file-store-BQ41vIs5.js.br +0 -0
- package/dist/web/assets/file-store-BQ41vIs5.js.gz +0 -0
- package/dist/web/assets/files-settings-section-Bq7liJ_r.js +1 -0
- package/dist/web/assets/files-settings-section-Bq7liJ_r.js.br +0 -0
- package/dist/web/assets/files-settings-section-Bq7liJ_r.js.gz +0 -0
- package/dist/web/assets/filter-dialog-frame-BkEbqBA4.js +1 -0
- package/dist/web/assets/filter-dialog-frame-BkEbqBA4.js.br +0 -0
- package/dist/web/assets/filter-dialog-frame-BkEbqBA4.js.gz +0 -0
- package/dist/web/assets/format-file-meta-DdYtk07C.js +1 -0
- package/dist/web/assets/format-file-meta-DdYtk07C.js.br +0 -0
- package/dist/web/assets/format-file-meta-DdYtk07C.js.gz +0 -0
- package/dist/web/assets/fs-api-CFtQzsIJ.js +1 -0
- package/dist/web/assets/fs-api-CFtQzsIJ.js.br +0 -0
- package/dist/web/assets/fs-api-CFtQzsIJ.js.gz +0 -0
- package/dist/web/assets/general-settings-section-DvHROAMa.js +1 -0
- package/dist/web/assets/general-settings-section-DvHROAMa.js.br +0 -0
- package/dist/web/assets/general-settings-section-DvHROAMa.js.gz +0 -0
- package/dist/web/assets/git-commit-horizontal-BPdj2L1i.js +1 -0
- package/dist/web/assets/git-log-panel-Cu9kK48H.js +1 -0
- package/dist/web/assets/git-log-panel-Cu9kK48H.js.br +0 -0
- package/dist/web/assets/git-log-panel-Cu9kK48H.js.gz +0 -0
- package/dist/web/assets/git-repo-store-CKB5fdNP.js +1 -0
- package/dist/web/assets/git-repo-store-CKB5fdNP.js.br +0 -0
- package/dist/web/assets/git-repo-store-CKB5fdNP.js.gz +0 -0
- package/dist/web/assets/git-review-tab-B_JT649W.js +3 -0
- package/dist/web/assets/git-review-tab-B_JT649W.js.br +0 -0
- package/dist/web/assets/git-review-tab-B_JT649W.js.gz +0 -0
- package/dist/web/assets/glide-data-grid-BlposOph.js +177 -0
- package/dist/web/assets/glide-data-grid-BlposOph.js.br +0 -0
- package/dist/web/assets/glide-data-grid-BlposOph.js.gz +0 -0
- package/dist/web/assets/grid-save-dialog-B0d0qhnN.js +2 -0
- package/dist/web/assets/grid-save-dialog-B0d0qhnN.js.br +0 -0
- package/dist/web/assets/grid-save-dialog-B0d0qhnN.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-jirUsGm-.js +1 -0
- package/dist/web/assets/group-chat-tab-jirUsGm-.js.br +0 -0
- package/dist/web/assets/group-chat-tab-jirUsGm-.js.gz +0 -0
- package/dist/web/assets/html-preview-loads-CMWBC-iv.js +1 -0
- package/dist/web/assets/icons-BwyIKaTT.js +1 -0
- package/dist/web/assets/icons-BwyIKaTT.js.br +0 -0
- package/dist/web/assets/icons-BwyIKaTT.js.gz +0 -0
- package/dist/web/assets/image-preview-gOBK9zED.js +1 -0
- package/dist/web/assets/impexp-tab-HJVcOTYJ.js +1 -0
- package/dist/web/assets/impexp-tab-HJVcOTYJ.js.br +0 -0
- package/dist/web/assets/impexp-tab-HJVcOTYJ.js.gz +0 -0
- package/dist/web/assets/index-DLB3j_P0.js +59 -0
- package/dist/web/assets/index-DLB3j_P0.js.br +0 -0
- package/dist/web/assets/index-DLB3j_P0.js.gz +0 -0
- package/dist/web/assets/index-M3DUzop8.css +1 -0
- package/dist/web/assets/index-M3DUzop8.css.br +0 -0
- package/dist/web/assets/index-M3DUzop8.css.gz +0 -0
- package/dist/web/assets/input-C3oVNCMq.js +1 -0
- package/dist/web/assets/jira-watcher-section-EQvdnETB.js +1 -0
- package/dist/web/assets/keybindings-store-CEy-Sdcc.js +1 -0
- package/dist/web/assets/keyboard-shortcuts-section-DN21gB-T.js +1 -0
- package/dist/web/assets/keyboard-shortcuts-section-DN21gB-T.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-DN21gB-T.js.gz +0 -0
- package/dist/web/assets/language-servers-section-DOcZ72FJ.js +2 -0
- package/dist/web/assets/language-servers-section-DOcZ72FJ.js.br +0 -0
- package/dist/web/assets/language-servers-section-DOcZ72FJ.js.gz +0 -0
- package/dist/web/assets/lib-5Chotbwm.js +2 -0
- package/dist/web/assets/lib-5Chotbwm.js.br +0 -0
- package/dist/web/assets/lib-5Chotbwm.js.gz +0 -0
- package/dist/web/assets/logs-app-C7n9GSCn.js +13 -0
- package/dist/web/assets/logs-app-C7n9GSCn.js.br +0 -0
- package/dist/web/assets/logs-app-C7n9GSCn.js.gz +0 -0
- package/dist/web/assets/logs-tab-CSOiexvx.js +1 -0
- package/dist/web/assets/logs-window-content-C4Qs6-0q.js +1 -0
- package/dist/web/assets/lsp-client-DpYmPhXX.js +1 -0
- package/dist/web/assets/lsp-client-DpYmPhXX.js.br +0 -0
- package/dist/web/assets/lsp-client-DpYmPhXX.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-CtEl6qAt.js +4 -0
- package/dist/web/assets/markdown-renderer-CtEl6qAt.js.br +0 -0
- package/dist/web/assets/markdown-renderer-CtEl6qAt.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-Df3r-CCb.js +1 -0
- package/dist/web/assets/media-url-Cn2yRAxP.js +1 -0
- package/dist/web/assets/metric-chart-canvas-DEW16Su8.js +1 -0
- package/dist/web/assets/metric-chart-canvas-DEW16Su8.js.br +0 -0
- package/dist/web/assets/metric-chart-canvas-DEW16Su8.js.gz +0 -0
- package/dist/web/assets/mobile-bottom-sheet-DArbIyrD.js +1 -0
- package/dist/web/assets/mobile-bottom-sheet-DArbIyrD.js.br +0 -0
- package/dist/web/assets/mobile-bottom-sheet-DArbIyrD.js.gz +0 -0
- package/dist/web/assets/mobile-explorer-sheet-B-rcKEL9.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-B-rcKEL9.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-B-rcKEL9.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-DgztQK5R.js +1 -0
- package/dist/web/assets/new-design-dialog-DgztQK5R.js.br +0 -0
- package/dist/web/assets/new-design-dialog-DgztQK5R.js.gz +0 -0
- package/dist/web/assets/notification-store-B92dvP_u.js +1 -0
- package/dist/web/assets/notifications-settings-section-JiGvaCFx.js +1 -0
- package/dist/web/assets/notifications-settings-section-JiGvaCFx.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-JiGvaCFx.js.gz +0 -0
- package/dist/web/assets/onboarding-entry-eehqBvyM.js +1 -0
- package/dist/web/assets/onboarding-entry-eehqBvyM.js.br +0 -0
- package/dist/web/assets/onboarding-entry-eehqBvyM.js.gz +0 -0
- package/dist/web/assets/onboarding-quick-orientation-CTHtIRib.js +1 -0
- package/dist/web/assets/onboarding-quick-orientation-CTHtIRib.js.br +0 -0
- package/dist/web/assets/onboarding-quick-orientation-CTHtIRib.js.gz +0 -0
- package/dist/web/assets/open-db-tabs-CtWIWHOa.js +1 -0
- package/dist/web/assets/open-db-tabs-CtWIWHOa.js.br +0 -0
- package/dist/web/assets/open-db-tabs-CtWIWHOa.js.gz +0 -0
- package/dist/web/assets/open-settings-EXR4zoZG.js +1 -0
- package/dist/web/assets/overview-panel-DEGF2DmZ.js +1 -0
- package/dist/web/assets/overview-panel-DEGF2DmZ.js.br +0 -0
- package/dist/web/assets/overview-panel-DEGF2DmZ.js.gz +0 -0
- package/dist/web/assets/panel-store-BJhazigC.js +1 -0
- package/dist/web/assets/panel-store-BJhazigC.js.br +0 -0
- package/dist/web/assets/panel-store-BJhazigC.js.gz +0 -0
- package/dist/web/assets/patch-tab-metadata-C92YkrRX.js +1 -0
- package/dist/web/assets/pdf-preview-C9gMtv2a.js +1 -0
- package/dist/web/assets/pdf-preview-C9gMtv2a.js.br +0 -0
- package/dist/web/assets/pdf-preview-C9gMtv2a.js.gz +0 -0
- package/dist/web/assets/performance-panel-TkwfKIZa.js +3 -0
- package/dist/web/assets/performance-panel-TkwfKIZa.js.br +0 -0
- package/dist/web/assets/performance-panel-TkwfKIZa.js.gz +0 -0
- package/dist/web/assets/portal-container-context-NBi-KGK0.js +1 -0
- package/dist/web/assets/ppmbot-settings-section-XfrZ8VoC.js +1 -0
- package/dist/web/assets/ppmbot-settings-section-XfrZ8VoC.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-XfrZ8VoC.js.gz +0 -0
- package/dist/web/assets/pptx-export-B2wCBWlV.js +111 -0
- package/dist/web/assets/pptx-export-B2wCBWlV.js.br +0 -0
- package/dist/web/assets/pptx-export-B2wCBWlV.js.gz +0 -0
- package/dist/web/assets/problems-panel-CDzwSJn6.js +1 -0
- package/dist/web/assets/problems-panel-CDzwSJn6.js.br +0 -0
- package/dist/web/assets/problems-panel-CDzwSJn6.js.gz +0 -0
- package/dist/web/assets/process-row-format-CytRH7g2.js +1 -0
- package/dist/web/assets/process-table-C_B39GHm.js +1 -0
- package/dist/web/assets/process-table-C_B39GHm.js.br +0 -0
- package/dist/web/assets/process-table-C_B39GHm.js.gz +0 -0
- package/dist/web/assets/project-framework-store-DwLxaRan.js +1 -0
- package/dist/web/assets/project-store-BLGl9IAO.js +1 -0
- package/dist/web/assets/project-store-BLGl9IAO.js.br +0 -0
- package/dist/web/assets/project-store-BLGl9IAO.js.gz +0 -0
- package/dist/web/assets/proxy-settings-section-CvaOvYIv.js +1 -0
- package/dist/web/assets/proxy-settings-section-CvaOvYIv.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-CvaOvYIv.js.gz +0 -0
- package/dist/web/assets/query-audit-section-D_WDp1m-.js +1 -0
- package/dist/web/assets/query-audit-section-D_WDp1m-.js.br +0 -0
- package/dist/web/assets/query-audit-section-D_WDp1m-.js.gz +0 -0
- package/dist/web/assets/query-tab-B8aMpAbI.js +22 -0
- package/dist/web/assets/query-tab-B8aMpAbI.js.br +0 -0
- package/dist/web/assets/query-tab-B8aMpAbI.js.gz +0 -0
- package/dist/web/assets/react-BZ0kba1-.js +1 -0
- package/dist/web/assets/remote-access-settings-section-Bv0eawR4.js +1 -0
- package/dist/web/assets/remote-access-settings-section-Bv0eawR4.js.br +0 -0
- package/dist/web/assets/remote-access-settings-section-Bv0eawR4.js.gz +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-BpDakRY0.js +1 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-BpDakRY0.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-BpDakRY0.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-C5GQ3kzY.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-C5GQ3kzY.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-C5GQ3kzY.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-CZb5EMEK.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-view-CZb5EMEK.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-CZb5EMEK.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CipNtLX5.js +1 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CipNtLX5.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CipNtLX5.js.gz +0 -0
- package/dist/web/assets/remote-desktop-settings-section-ZAsBRwjq.js +1 -0
- package/dist/web/assets/remote-desktop-settings-section-ZAsBRwjq.js.br +0 -0
- package/dist/web/assets/remote-desktop-settings-section-ZAsBRwjq.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-B7OXXvAM.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-B7OXXvAM.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-B7OXXvAM.js.gz +0 -0
- package/dist/web/assets/rename-object-dialog-B4W6S7Xg.js +1 -0
- package/dist/web/assets/rename-object-dialog-B4W6S7Xg.js.br +0 -0
- package/dist/web/assets/rename-object-dialog-B4W6S7Xg.js.gz +0 -0
- package/dist/web/assets/review-code-B4osj0k1.js +5 -0
- package/dist/web/assets/review-code-B4osj0k1.js.br +0 -0
- package/dist/web/assets/review-code-B4osj0k1.js.gz +0 -0
- package/dist/web/assets/run-in-terminal-button-m3i-Hcou.js +1 -0
- package/dist/web/assets/run-in-terminal-ujoc25vj.js +1 -0
- package/dist/web/assets/save-as-dialog-DpXv_f1d.js +1 -0
- package/dist/web/assets/save-as-dialog-DpXv_f1d.js.br +5 -0
- package/dist/web/assets/save-as-dialog-DpXv_f1d.js.gz +0 -0
- package/dist/web/assets/schedules-settings-section-BbaPbc28.js +1 -0
- package/dist/web/assets/schedules-settings-section-BbaPbc28.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-BbaPbc28.js.gz +0 -0
- package/dist/web/assets/scroll-area-DOlQJGZp.js +1 -0
- package/dist/web/assets/scroll-area-DOlQJGZp.js.br +0 -0
- package/dist/web/assets/scroll-area-DOlQJGZp.js.gz +0 -0
- package/dist/web/assets/send-to-chat-CWV1qd3c.js +1 -0
- package/dist/web/assets/send-to-chat-CWV1qd3c.js.br +0 -0
- package/dist/web/assets/send-to-chat-CWV1qd3c.js.gz +0 -0
- package/dist/web/assets/separator-DmU9aJwq.js +1 -0
- package/dist/web/assets/services-panel-CZQOrvth.js +1 -0
- package/dist/web/assets/services-panel-CZQOrvth.js.br +0 -0
- package/dist/web/assets/services-panel-CZQOrvth.js.gz +0 -0
- package/dist/web/assets/session-changes-bar-VfS2sHuH.js +1 -0
- package/dist/web/assets/session-changes-bar-VfS2sHuH.js.br +0 -0
- package/dist/web/assets/session-changes-bar-VfS2sHuH.js.gz +0 -0
- package/dist/web/assets/session-list-sync-triggers-DtJI5KF0.js +1 -0
- package/dist/web/assets/session-list-sync-triggers-DtJI5KF0.js.br +0 -0
- package/dist/web/assets/session-list-sync-triggers-DtJI5KF0.js.gz +0 -0
- package/dist/web/assets/session-review-tab-Aq3FEooH.js +6 -0
- package/dist/web/assets/session-review-tab-Aq3FEooH.js.br +0 -0
- package/dist/web/assets/session-review-tab-Aq3FEooH.js.gz +0 -0
- package/dist/web/assets/settings-body-vXbOWchN.js +1 -0
- package/dist/web/assets/settings-body-vXbOWchN.js.br +0 -0
- package/dist/web/assets/settings-body-vXbOWchN.js.gz +0 -0
- package/dist/web/assets/settings-categories-Ajj4ui27.js +1 -0
- package/dist/web/assets/settings-categories-Ajj4ui27.js.br +0 -0
- package/dist/web/assets/settings-categories-Ajj4ui27.js.gz +0 -0
- package/dist/web/assets/settings-rows-DD7Gxmst.js +1 -0
- package/dist/web/assets/settings-rows-DD7Gxmst.js.br +0 -0
- package/dist/web/assets/settings-rows-DD7Gxmst.js.gz +0 -0
- package/dist/web/assets/settings-section-content-CVtvJ6ze.js +1 -0
- package/dist/web/assets/settings-section-content-DkUJFop6.js +2 -0
- package/dist/web/assets/settings-section-content-DkUJFop6.js.br +0 -0
- package/dist/web/assets/settings-section-content-DkUJFop6.js.gz +0 -0
- package/dist/web/assets/settings-store-B4mLp19V.js +2 -0
- package/dist/web/assets/settings-store-B4mLp19V.js.br +0 -0
- package/dist/web/assets/settings-store-B4mLp19V.js.gz +0 -0
- package/dist/web/assets/settings-tab-Cdv9_OIe.js +1 -0
- package/dist/web/assets/settings-window-content-DLa6Ph4u.js +1 -0
- package/dist/web/assets/share-BV49OI6q.css +2 -0
- package/dist/web/assets/share-BV49OI6q.css.br +0 -0
- package/dist/web/assets/share-BV49OI6q.css.gz +0 -0
- package/dist/web/assets/share-D5ufGmNI.js +9 -0
- package/dist/web/assets/share-D5ufGmNI.js.br +0 -0
- package/dist/web/assets/share-D5ufGmNI.js.gz +0 -0
- package/dist/web/assets/slash-command-picker-lILYDfK3.js +1 -0
- package/dist/web/assets/slash-command-picker-lILYDfK3.js.br +0 -0
- package/dist/web/assets/slash-command-picker-lILYDfK3.js.gz +0 -0
- package/dist/web/assets/sortable-header-DwzTFLkG.js +1 -0
- package/dist/web/assets/sortable-header-DwzTFLkG.js.br +0 -0
- package/dist/web/assets/sortable-header-DwzTFLkG.js.gz +0 -0
- package/dist/web/assets/split-sql-statements-DcAeXbk_.js +5 -0
- package/dist/web/assets/split-sql-statements-DcAeXbk_.js.br +0 -0
- package/dist/web/assets/split-sql-statements-DcAeXbk_.js.gz +0 -0
- package/dist/web/assets/sql-completion-provider-CS-ElfgJ.js +1 -0
- package/dist/web/assets/sql-completion-provider-CS-ElfgJ.js.br +0 -0
- package/dist/web/assets/sql-completion-provider-CS-ElfgJ.js.gz +0 -0
- package/dist/web/assets/sql-object-tab-Da42SMK5.js +1 -0
- package/dist/web/assets/sql-object-tab-Da42SMK5.js.br +0 -0
- package/dist/web/assets/sql-object-tab-Da42SMK5.js.gz +0 -0
- package/dist/web/assets/sqlite-viewer-V3SKNukY.js +1 -0
- package/dist/web/assets/sqlite-viewer-V3SKNukY.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-V3SKNukY.js.gz +0 -0
- package/dist/web/assets/start-ellipsis-CU8GkxaV.js +1 -0
- package/dist/web/assets/structure-save-dialog-B635iyPI.js +1 -0
- package/dist/web/assets/structure-save-dialog-B635iyPI.js.br +0 -0
- package/dist/web/assets/structure-save-dialog-B635iyPI.js.gz +0 -0
- package/dist/web/assets/structure-tab-Co9d8ktU.js +3 -0
- package/dist/web/assets/structure-tab-Co9d8ktU.js.br +0 -0
- package/dist/web/assets/structure-tab-Co9d8ktU.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-DC0j8RqP.js +2 -0
- package/dist/web/assets/system-monitor-body-DC0j8RqP.js.br +0 -0
- package/dist/web/assets/system-monitor-body-DC0j8RqP.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-DA8BcdXo.js +1 -0
- package/dist/web/assets/system-monitor-window-content-BiuLo8XW.js +1 -0
- package/dist/web/assets/tab-host-window-content-Crvt1r5F.js +1 -0
- package/dist/web/assets/tab-host-window-content-Crvt1r5F.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-Crvt1r5F.js.gz +0 -0
- package/dist/web/assets/tab-store-D5I52eLN.js +1 -0
- package/dist/web/assets/table-tab-C2cYw7a0.js +2 -0
- package/dist/web/assets/table-tab-C2cYw7a0.js.br +0 -0
- package/dist/web/assets/table-tab-C2cYw7a0.js.gz +0 -0
- package/dist/web/assets/telegram-bot-token-field-BqNtOo5n.js +1 -0
- package/dist/web/assets/telegram-bot-token-field-BqNtOo5n.js.br +0 -0
- package/dist/web/assets/telegram-bot-token-field-BqNtOo5n.js.gz +0 -0
- package/dist/web/assets/terminal-tab-CrKxibGC.js +3 -0
- package/dist/web/assets/terminal-tab-CrKxibGC.js.br +0 -0
- package/dist/web/assets/terminal-tab-CrKxibGC.js.gz +0 -0
- package/dist/web/assets/tool-cards-BRto67jM.js +15 -0
- package/dist/web/assets/tool-cards-BRto67jM.js.br +0 -0
- package/dist/web/assets/tool-cards-BRto67jM.js.gz +0 -0
- package/dist/web/assets/tools-settings-section-DEvZsrxq.js +1 -0
- package/dist/web/assets/tools-settings-section-DEvZsrxq.js.br +0 -0
- package/dist/web/assets/tools-settings-section-DEvZsrxq.js.gz +0 -0
- package/dist/web/assets/use-at-most-wide-BHsrzvv3.js +1 -0
- package/dist/web/assets/use-blob-url-Clm7wbB_.js +1 -0
- package/dist/web/assets/use-db-driver-installed-anzWkGi5.js +1 -0
- package/dist/web/assets/use-db-read-BCYhIrJM.js +1 -0
- package/dist/web/assets/use-db-read-BCYhIrJM.js.br +0 -0
- package/dist/web/assets/use-db-read-BCYhIrJM.js.gz +0 -0
- package/dist/web/assets/use-db-tab-B8LjdDb7.js +1 -0
- package/dist/web/assets/use-db-tab-B8LjdDb7.js.br +0 -0
- package/dist/web/assets/use-db-tab-B8LjdDb7.js.gz +0 -0
- package/dist/web/assets/use-design-canvas-check-DBsLf1At.js +1 -0
- package/dist/web/assets/use-design-canvas-check-DBsLf1At.js.br +0 -0
- package/dist/web/assets/use-design-canvas-check-DBsLf1At.js.gz +0 -0
- package/dist/web/assets/use-h264-canvas-decoder-_zqeiVx8.js +1 -0
- package/dist/web/assets/use-h264-canvas-decoder-_zqeiVx8.js.br +0 -0
- package/dist/web/assets/use-h264-canvas-decoder-_zqeiVx8.js.gz +0 -0
- package/dist/web/assets/use-inline-blame-CRWJU6Rq.js +16 -0
- package/dist/web/assets/use-inline-blame-CRWJU6Rq.js.br +0 -0
- package/dist/web/assets/use-inline-blame-CRWJU6Rq.js.gz +0 -0
- package/dist/web/assets/use-is-mobile-VRV9eZy1.js +1 -0
- package/dist/web/assets/use-lsp-B-otjr-6.js +6 -0
- package/dist/web/assets/use-lsp-B-otjr-6.js.br +0 -0
- package/dist/web/assets/use-lsp-B-otjr-6.js.gz +0 -0
- package/dist/web/assets/use-monaco-theme-BiDXRJ4e.js +1 -0
- package/dist/web/assets/use-opener-focus-CDRKhHwX.js +1 -0
- package/dist/web/assets/use-process-kill-BW2UW0mZ.js +1 -0
- package/dist/web/assets/use-process-kill-BW2UW0mZ.js.br +0 -0
- package/dist/web/assets/use-process-kill-BW2UW0mZ.js.gz +0 -0
- package/dist/web/assets/use-sql-schema-info-D_Kc2FI7.js +4 -0
- package/dist/web/assets/use-sql-schema-info-D_Kc2FI7.js.br +0 -0
- package/dist/web/assets/use-sql-schema-info-D_Kc2FI7.js.gz +0 -0
- package/dist/web/assets/use-visual-viewport-MmugpRg-.js +1 -0
- package/dist/web/assets/use-websocket-n3Ud9vEA.js +1 -0
- package/dist/web/assets/vendor-markdown-C-P1aR4p.js +291 -0
- package/dist/web/assets/vendor-markdown-C-P1aR4p.js.br +0 -0
- package/dist/web/assets/vendor-markdown-C-P1aR4p.js.gz +0 -0
- package/dist/web/assets/vendor-ui-BTSIXzhZ.js +45 -0
- package/dist/web/assets/vendor-ui-BTSIXzhZ.js.br +0 -0
- package/dist/web/assets/vendor-ui-BTSIXzhZ.js.gz +0 -0
- package/dist/web/assets/video-preview-CjB6wesi.js +1 -0
- package/dist/web/assets/video-preview-CjB6wesi.js.br +0 -0
- package/dist/web/assets/video-preview-CjB6wesi.js.gz +0 -0
- package/dist/web/assets/voice-settings-section-C6Wb6q5o.js +1 -0
- package/dist/web/assets/voice-settings-section-C6Wb6q5o.js.br +0 -0
- package/dist/web/assets/voice-settings-section-C6Wb6q5o.js.gz +0 -0
- package/dist/web/assets/web-preview-tab-doNpegW3.js +1 -0
- package/dist/web/assets/web-preview-tab-doNpegW3.js.br +0 -0
- package/dist/web/assets/web-preview-tab-doNpegW3.js.gz +0 -0
- package/dist/web/assets/window-store-DqX_qmkQ.js +1 -0
- package/dist/web/assets/window-store-DqX_qmkQ.js.br +0 -0
- package/dist/web/assets/window-store-DqX_qmkQ.js.gz +0 -0
- package/dist/web/assets/ws-auth-CbF6GqxP.js +1 -0
- package/dist/web/design-share-page/index.html +18 -0
- package/dist/web/index.html +47 -47
- package/dist/web/index.html.br +0 -0
- package/dist/web/index.html.gz +0 -0
- package/dist/web/sw.js +1 -1
- package/dist/web/sw.js.br +0 -0
- package/dist/web/sw.js.gz +0 -0
- package/docs/architecture/ai-chat-and-providers.md +258 -26
- package/docs/architecture/data-and-storage.md +9 -3
- package/docs/architecture/workspace-and-ui.md +42 -5
- package/docs/project-roadmap.md +5 -0
- package/package.json +6 -2
- package/scripts/gen-product-icons.ts +1 -0
- package/src/cli/commands/db-cmd.ts +79 -1
- package/src/providers/claude-agent-sdk-query-options.ts +42 -10
- package/src/providers/claude-agent-sdk.ts +19 -6
- package/src/providers/codex-app-server/codex-provider.ts +9 -3
- package/src/providers/codex-app-server/codex-thread-params.ts +34 -4
- package/src/server/index.ts +17 -5
- package/src/server/middleware/access-log.ts +6 -3
- package/src/server/routes/accounts.ts +3 -2
- package/src/server/routes/chat-file-changes.ts +15 -1
- package/src/server/routes/chat.ts +92 -18
- package/src/server/routes/database-query.ts +14 -5
- package/src/server/routes/database.ts +14 -0
- package/src/server/routes/debug-crash.ts +30 -0
- package/src/server/routes/design-comments.ts +56 -7
- package/src/server/routes/design-share-address.ts +20 -0
- package/src/server/routes/design-share-guest-comments.ts +120 -0
- package/src/server/routes/design-share-guest-files.ts +99 -0
- package/src/server/routes/design-share-guest-shared.ts +95 -0
- package/src/server/routes/design-share-guest.ts +77 -0
- package/src/server/routes/design-shares.ts +90 -0
- package/src/server/routes/designs.ts +2 -0
- package/src/server/routes/settings.ts +12 -0
- package/src/server/routes/static.ts +10 -2
- package/src/server/ws/chat.ts +113 -39
- package/src/server/ws/global.ts +10 -8
- package/src/services/account.service.ts +57 -18
- package/src/services/chat.service.ts +16 -6
- package/src/services/db-ai-tools/db-ai-connections.ts +48 -0
- package/src/services/db-ai-tools/db-ai-format.ts +107 -0
- package/src/services/db-ai-tools/db-ai-run.ts +199 -0
- package/src/services/db-ai-tools/db-ai-target.ts +59 -0
- package/src/services/db-ai-tools/db-ai-tools-endpoint.ts +225 -0
- package/src/services/db-ai-tools/db-ai-tools-tokens.ts +33 -0
- package/src/services/db-ai-tools/db-ai-tools-tool.ts +131 -0
- package/src/services/db-ai-tools/db-approval-broker.ts +157 -0
- package/src/services/db.service.ts +25 -1
- package/src/services/design/bridge/bridge-picker.ts +15 -5
- package/src/services/design/bridge/guest-bridge.ts +19 -0
- package/src/services/design/comments/design-comment-element-context.ts +28 -6
- package/src/services/design/comments/design-comment-input.ts +47 -0
- package/src/services/design/comments/design-comment-views.ts +146 -0
- package/src/services/design/comments/design-comments-revision.ts +19 -0
- package/src/services/design/comments/design-comments-store.ts +82 -9
- package/src/services/design/design-comment-replies.service.ts +126 -0
- package/src/services/design/design-comments.service.ts +77 -34
- package/src/services/design/design-restore.service.ts +6 -2
- package/src/services/design/design-snapshots.service.ts +8 -2
- package/src/services/design/design-store.service.ts +7 -1
- package/src/services/design/design-write-rate-limit.ts +11 -17
- package/src/services/design/preview/design-guest-alias.ts +64 -0
- package/src/services/design/preview/design-preview-html.ts +16 -3
- package/src/services/design/preview/design-preview-scope.ts +29 -5
- package/src/services/design/share/design-share-address.ts +81 -0
- package/src/services/design/share/design-share-changed-files.ts +74 -0
- package/src/services/design/share/design-share-client-key.ts +72 -0
- package/src/services/design/share/design-share-code.ts +116 -0
- package/src/services/design/share/design-share-comments.service.ts +162 -0
- package/src/services/design/share/design-share-guest-link.ts +109 -0
- package/src/services/design/share/design-share-guest-page.ts +86 -0
- package/src/services/design/share/design-share-link-rules.ts +83 -0
- package/src/services/design/share/design-share-links-store.ts +157 -0
- package/src/services/design/share/design-share-links.service.ts +174 -0
- package/src/services/design/share/design-share-notifier.ts +192 -0
- package/src/services/design/share/design-share-rate-limit.ts +71 -0
- package/src/services/design/share/design-share-resolve.ts +31 -0
- package/src/services/mcp-http-endpoint.ts +23 -10
- package/src/services/mysql.service.ts +6 -2
- package/src/services/notification-format.ts +10 -2
- package/src/services/notification-link.ts +1 -1
- package/src/services/notification.service.ts +47 -15
- package/src/services/ppm-password.ts +26 -0
- package/src/services/project-name-for-path.ts +18 -0
- package/src/services/query-audit/query-audit.service.ts +7 -4
- package/src/services/remote-desktop/access-unit-assembler.ts +11 -7
- package/src/services/remote-desktop/nal-splitter.ts +14 -1
- package/src/services/remote-desktop/remote-desktop-capture-wayland.ts +47 -21
- package/src/services/remote-desktop/remote-desktop-encoder-args.ts +5 -3
- package/src/services/session-file-baselines/session-file-baselines.service.ts +48 -0
- package/src/services/session-file-baselines/session-file-blame.ts +57 -24
- package/src/services/session-file-baselines/session-file-changes.service.ts +220 -22
- package/src/services/session-file-baselines/session-file-history.ts +5 -1
- package/src/services/session-file-baselines/session-file-writes.ts +28 -0
- package/src/services/sliding-window-limiter.ts +106 -0
- package/src/services/tab-tools-mcp/open-url-tool.ts +149 -0
- package/src/services/tab-tools-mcp/tab-open-broker.ts +12 -4
- package/src/services/tab-tools-mcp/tab-tools-mcp-endpoint.ts +66 -22
- package/src/services/tab-tools-mcp/tab-tools-mcp-tokens.ts +3 -1
- package/src/services/tab-tools-mcp/tab-tools-mcp-tool.ts +78 -6
- package/src/services/tab-tools-mcp/terminal-text.ts +45 -0
- package/src/services/tab-tools-mcp/terminal-tools.ts +297 -0
- package/src/services/terminal.service.ts +39 -4
- package/src/shared/db-ai-tools.ts +118 -0
- package/src/shared/db-query-script.ts +16 -0
- package/src/shared/design-comment-thread-types.ts +80 -0
- package/src/shared/design-comment-types.ts +53 -4
- package/src/shared/design-share-guest-types.ts +59 -0
- package/src/shared/design-share-types.ts +100 -0
- package/src/shared/notification-settings.ts +4 -3
- package/src/shared/ppm-tools.ts +39 -0
- package/src/shared/session-file-changes.ts +16 -0
- package/src/shared/tab-open-protocol.ts +50 -6
- package/src/shared/untrusted-text.ts +15 -1
- package/src/types/chat.ts +7 -1
- package/src/types/config.ts +5 -2
- package/src/types/database.ts +6 -0
- package/src/web/components/chat/chat-history-bar.tsx +10 -6
- package/src/web/components/chat/chat-tab.tsx +7 -1
- package/src/web/components/chat/db-execute-approval-card.tsx +100 -0
- package/src/web/components/chat/db-tool-card.tsx +42 -0
- package/src/web/components/chat/device-tool-card.tsx +45 -0
- package/src/web/components/chat/message-input.tsx +9 -6
- package/src/web/components/chat/message-list.tsx +6 -1
- package/src/web/components/chat/message-markdown.tsx +6 -3
- package/src/web/components/chat/message-user-bubble.tsx +2 -1
- package/src/web/components/chat/model-thinking-selector.tsx +6 -4
- package/src/web/components/chat/prompt-cache-chip.tsx +1 -1
- package/src/web/components/chat/running-agents-bar.tsx +164 -76
- package/src/web/components/chat/session-changes-bar.tsx +46 -13
- package/src/web/components/chat/tool-cards.tsx +29 -1
- package/src/web/components/chat/turn-change-rollup.tsx +8 -1
- package/src/web/components/chat/usage-badge.tsx +3 -3
- package/src/web/components/database/query/query-run-state.ts +11 -1
- package/src/web/components/database/query/query-tab.tsx +33 -7
- package/src/web/components/database/query/use-query-runner.ts +3 -0
- package/src/web/components/database/query/write-once-dialog.tsx +70 -0
- package/src/web/components/design/canvas/design-canvas-pane.tsx +5 -2
- package/src/web/components/design/comments/comment-author-label.tsx +23 -0
- package/src/web/components/design/comments/comment-composer.tsx +6 -14
- package/src/web/components/design/comments/comment-pins-overlay.tsx +8 -3
- package/src/web/components/design/comments/comment-thread-replies.tsx +82 -0
- package/src/web/components/design/comments/comment-thread-text-box.tsx +69 -0
- package/src/web/components/design/comments/comment-thread-view.tsx +115 -0
- package/src/web/components/design/comments/comments-panel.tsx +33 -10
- package/src/web/components/design/comments/comments-send-preview.tsx +20 -8
- package/src/web/components/design/comments/design-comments-layer.tsx +3 -1
- package/src/web/components/design/comments/use-comment-pins.ts +3 -0
- package/src/web/components/design/comments/use-design-comments-feature.ts +40 -25
- package/src/web/components/design/comments/use-design-comments.ts +44 -12
- package/src/web/components/design/design-split-layout.tsx +106 -10
- package/src/web/components/design/design-tab-context.ts +2 -0
- package/src/web/components/design/design-tab.tsx +5 -1
- package/src/web/components/design/design-toolbar.tsx +24 -4
- package/src/web/components/design/share/design-share-dialog.tsx +81 -0
- package/src/web/components/design/share/new-share-link-form.tsx +85 -0
- package/src/web/components/design/share/share-address-block.tsx +101 -0
- package/src/web/components/design/share/share-changed-files.tsx +30 -0
- package/src/web/components/design/share/share-expiry-picker.tsx +44 -0
- package/src/web/components/design/share/share-repin-panel.tsx +64 -0
- package/src/web/components/design/share/share-row-panel.tsx +35 -0
- package/src/web/components/design/share/share-version-picker.tsx +67 -0
- package/src/web/components/design/share/shared-link-action-panels.tsx +120 -0
- package/src/web/components/design/share/shared-link-row.tsx +131 -0
- package/src/web/components/design/share/shared-links-list.tsx +33 -0
- package/src/web/components/design/share/use-share-address.ts +74 -0
- package/src/web/components/design/share/use-share-links.ts +93 -0
- package/src/web/components/design/use-design-layout.ts +7 -4
- package/src/web/components/editor/diff-viewer.tsx +16 -12
- package/src/web/components/editor/docx-preview.tsx +7 -2
- package/src/web/components/floating-window/close-window.ts +32 -0
- package/src/web/components/floating-window/floating-window.tsx +65 -24
- package/src/web/components/floating-window/open-tab-in-pip.ts +3 -0
- package/src/web/components/floating-window/use-window-drag.ts +33 -7
- package/src/web/components/floating-window/use-window-meta.ts +138 -0
- package/src/web/components/floating-window/window-chrome-contract.ts +19 -2
- package/src/web/components/floating-window/window-dock-layout.ts +72 -0
- package/src/web/components/floating-window/window-dock-list.tsx +156 -0
- package/src/web/components/floating-window/window-dock.tsx +192 -0
- package/src/web/components/floating-window/window-geometry.ts +39 -1
- package/src/web/components/floating-window/window-layer.tsx +59 -23
- package/src/web/components/floating-window/window-persistence.ts +16 -3
- package/src/web/components/floating-window/window-store-types.ts +13 -2
- package/src/web/components/floating-window/window-store.ts +75 -8
- package/src/web/components/floating-window/window-title-identity.tsx +86 -0
- package/src/web/components/layout/status-bar.tsx +3 -0
- package/src/web/components/layout/tab-pop-out-menu-item.tsx +2 -2
- package/src/web/components/logs/open-logs.ts +0 -1
- package/src/web/components/os-explorer/actions/explorer-actions-upload.ts +2 -1
- package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +17 -11
- package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +14 -5
- package/src/web/components/remote-desktop/use-remote-desktop-readiness.ts +8 -3
- package/src/web/components/settings/accounts/account-add-dialog.tsx +25 -13
- package/src/web/components/settings/accounts/claude-accounts-section.tsx +3 -3
- package/src/web/components/settings/ai-settings-section.tsx +0 -20
- package/src/web/components/settings/design-settings-section.tsx +3 -0
- package/src/web/components/settings/design-window-setting.tsx +28 -0
- package/src/web/components/settings/settings-categories.ts +3 -0
- package/src/web/components/settings/settings-section-content.tsx +1 -0
- package/src/web/components/settings/tools-settings-section.tsx +120 -0
- package/src/web/components/shared/docx-html-sanitize.ts +59 -0
- package/src/web/components/shared/markdown-code-block.tsx +3 -1
- package/src/web/components/shared/markdown-renderer.tsx +15 -3
- package/src/web/components/shared/markdown-sanitize.ts +65 -0
- package/src/web/components/web-preview/web-preview-tab.tsx +6 -3
- package/src/web/design-share-page/index.html +17 -0
- package/src/web/design-share-page/main.tsx +11 -0
- package/src/web/design-share-page/share-api.ts +131 -0
- package/src/web/design-share-page/share-app.tsx +14 -0
- package/src/web/design-share-page/share-bottom-sheet.tsx +61 -0
- package/src/web/design-share-page/share-canvas.tsx +92 -0
- package/src/web/design-share-page/share-composer.tsx +104 -0
- package/src/web/design-share-page/share-entry.tsx +92 -0
- package/src/web/design-share-page/share-identity.ts +81 -0
- package/src/web/design-share-page/share-name-prompt.tsx +59 -0
- package/src/web/design-share-page/share-panel-content.tsx +57 -0
- package/src/web/design-share-page/share-pins-overlay.tsx +50 -0
- package/src/web/design-share-page/share-review.tsx +123 -0
- package/src/web/design-share-page/share-states.tsx +78 -0
- package/src/web/design-share-page/share-thread-model.ts +83 -0
- package/src/web/design-share-page/share-thread-view.tsx +61 -0
- package/src/web/design-share-page/share-threads-panel.tsx +103 -0
- package/src/web/design-share-page/share-toolbar.tsx +105 -0
- package/src/web/design-share-page/share-ui.ts +30 -0
- package/src/web/design-share-page/share.css +63 -0
- package/src/web/design-share-page/use-share-canvas.ts +51 -0
- package/src/web/design-share-page/use-share-info.ts +34 -0
- package/src/web/design-share-page/use-share-session.ts +75 -0
- package/src/web/design-share-page/use-share-threads.ts +139 -0
- package/src/web/hooks/use-chat.ts +5 -2
- package/src/web/hooks/use-design-session-redirect.ts +3 -2
- package/src/web/hooks/use-git-repo.ts +36 -16
- package/src/web/hooks/use-global-events.ts +4 -0
- package/src/web/hooks/use-inline-blame.ts +17 -11
- package/src/web/hooks/use-notification-clicks.ts +23 -5
- package/src/web/hooks/use-session-file-changes.ts +118 -41
- package/src/web/hooks/use-url-sync.ts +5 -4
- package/src/web/lib/api-settings.ts +2 -0
- package/src/web/lib/chat-attempt-lifecycle.ts +3 -1
- package/src/web/lib/db-tool-call.ts +57 -0
- package/src/web/lib/design/api-design-comments.ts +39 -9
- package/src/web/lib/design/api-design-shares.ts +47 -0
- package/src/web/lib/design/design-comments-prompt.ts +108 -23
- package/src/web/lib/design/design-layout-mode.ts +16 -1
- package/src/web/lib/design/design-share-address-state.ts +88 -0
- package/src/web/lib/design/design-share-expiry.ts +96 -0
- package/src/web/lib/design/design-share-link-status.ts +66 -0
- package/src/web/lib/design/design-view-prefs.ts +20 -1
- package/src/web/lib/design/open-design-tab.ts +54 -1
- package/src/web/lib/git-repo-scope.ts +60 -0
- package/src/web/lib/icons.generated.tsx +3 -1
- package/src/web/lib/model-display-name.ts +16 -0
- package/src/web/lib/open-ai-tab.ts +129 -19
- package/src/web/lib/running-agent-rows.ts +52 -0
- package/src/web/lib/session-file-changes-client.ts +6 -0
- package/src/web/lib/session-file-changes.ts +13 -0
- package/src/web/lib/tab-tool-call.ts +37 -1
- package/src/web/lib/utils.ts +4 -1
- package/src/web/stores/panel-store.ts +13 -1
- package/src/web/stores/panel-utils.ts +9 -4
- package/src/web/stores/settings-store.ts +14 -0
- package/src/web/stores/window-panel-actions.ts +21 -3
- package/src/web/stores/window-panel-persistence.ts +2 -1
- package/src/web/sw-notification-click.ts +12 -1
- package/templates/skill/SKILL.md.tmpl +2 -1
- package/templates/skill/common-tasks.md +6 -0
- package/vite.config.ts +10 -0
- package/vite.share.config.ts +43 -0
- package/dist/web/assets/accounts-settings-section-DU-lTifs.js +0 -1
- package/dist/web/assets/accounts-settings-section-DU-lTifs.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-DU-lTifs.js.gz +0 -0
- package/dist/web/assets/adaptive-context-menu-Cq7ynvIn.js +0 -1
- package/dist/web/assets/adaptive-context-menu-Cq7ynvIn.js.br +0 -0
- package/dist/web/assets/adaptive-context-menu-Cq7ynvIn.js.gz +0 -0
- package/dist/web/assets/agent-session-sheet-At6Rt-Yf.js +0 -2
- package/dist/web/assets/agent-session-sheet-At6Rt-Yf.js.br +0 -0
- package/dist/web/assets/agent-session-sheet-At6Rt-Yf.js.gz +0 -0
- package/dist/web/assets/agent-session-sheet-store-BoBrAw5i.js +0 -1
- package/dist/web/assets/agent-session-window-content-CB_uvabH.js +0 -1
- package/dist/web/assets/agent-session-window-content-CB_uvabH.js.br +0 -0
- package/dist/web/assets/agent-session-window-content-CB_uvabH.js.gz +0 -0
- package/dist/web/assets/ai-resource-editor-Czearm3I.js +0 -1
- package/dist/web/assets/ai-resource-editor-Czearm3I.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-Czearm3I.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-AOgAUCgH.js +0 -1
- package/dist/web/assets/ai-settings-section-B_OFMlrt.js +0 -1
- package/dist/web/assets/ai-settings-section-B_OFMlrt.js.br +0 -0
- package/dist/web/assets/ai-settings-section-B_OFMlrt.js.gz +0 -0
- package/dist/web/assets/android-tab-L7DmLfHG.js +0 -2
- package/dist/web/assets/android-tab-L7DmLfHG.js.br +0 -0
- package/dist/web/assets/android-tab-L7DmLfHG.js.gz +0 -0
- package/dist/web/assets/api-client-DAQfiXg0.js +0 -1
- package/dist/web/assets/api-client-OiA8Ida1.js +0 -1
- package/dist/web/assets/api-client-OiA8Ida1.js.br +0 -0
- package/dist/web/assets/api-client-OiA8Ida1.js.gz +0 -0
- package/dist/web/assets/api-settings-D2H6gjen.js +0 -1
- package/dist/web/assets/api-settings-D2H6gjen.js.br +0 -0
- package/dist/web/assets/api-settings-D2H6gjen.js.gz +0 -0
- package/dist/web/assets/api-settings-DHhcUHtx.js +0 -1
- package/dist/web/assets/api-themes-CE8gPZ3X.js +0 -1
- package/dist/web/assets/appearance-settings-section-s3KWKTBm.js +0 -1
- package/dist/web/assets/appearance-settings-section-s3KWKTBm.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-s3KWKTBm.js.gz +0 -0
- package/dist/web/assets/apps-panel-DaojtUvh.js +0 -1
- package/dist/web/assets/apps-panel-DaojtUvh.js.br +0 -0
- package/dist/web/assets/apps-panel-DaojtUvh.js.gz +0 -0
- package/dist/web/assets/audio-preview-CWcPZqTA.js +0 -1
- package/dist/web/assets/audio-preview-CWcPZqTA.js.br +0 -4
- package/dist/web/assets/audio-preview-CWcPZqTA.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-9UB4ccpF.js +0 -1
- package/dist/web/assets/branch-review-tab-9UB4ccpF.js.br +0 -0
- package/dist/web/assets/branch-review-tab-9UB4ccpF.js.gz +0 -0
- package/dist/web/assets/button-Br60hGkw.js +0 -1
- package/dist/web/assets/button-Br60hGkw.js.br +0 -0
- package/dist/web/assets/button-Br60hGkw.js.gz +0 -0
- package/dist/web/assets/chat-preparation-cache-CRX9WAK5.js +0 -1
- package/dist/web/assets/chat-preparation-cache-CRX9WAK5.js.br +0 -0
- package/dist/web/assets/chat-preparation-cache-CRX9WAK5.js.gz +0 -0
- package/dist/web/assets/chat-tab-DMVb_mgx.js +0 -1
- package/dist/web/assets/chat-tab-DMVb_mgx.js.br +0 -0
- package/dist/web/assets/chat-tab-DMVb_mgx.js.gz +0 -0
- package/dist/web/assets/chat-tab-s7uAnh-h.js +0 -17
- package/dist/web/assets/chat-tab-s7uAnh-h.js.br +0 -0
- package/dist/web/assets/chat-tab-s7uAnh-h.js.gz +0 -0
- package/dist/web/assets/code-editor-JK49X9EX.js +0 -10
- package/dist/web/assets/code-editor-JK49X9EX.js.br +0 -0
- package/dist/web/assets/code-editor-JK49X9EX.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-CxJsBnff.js +0 -1
- package/dist/web/assets/codex-reset-credit-button-CxJsBnff.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-CxJsBnff.js.gz +0 -0
- package/dist/web/assets/conflict-editor-rOpVkK9P.js +0 -19
- package/dist/web/assets/conflict-editor-rOpVkK9P.js.br +0 -0
- package/dist/web/assets/conflict-editor-rOpVkK9P.js.gz +0 -0
- package/dist/web/assets/connection-form-tab-BGmb918E.js +0 -4
- package/dist/web/assets/connection-form-tab-BGmb918E.js.br +0 -0
- package/dist/web/assets/connection-form-tab-BGmb918E.js.gz +0 -0
- package/dist/web/assets/context-menu-BoQ6lxte.js +0 -1
- package/dist/web/assets/context-menu-BoQ6lxte.js.br +0 -0
- package/dist/web/assets/context-menu-BoQ6lxte.js.gz +0 -0
- package/dist/web/assets/createLucideIcon-DBXq3G0e.js +0 -1
- package/dist/web/assets/createLucideIcon-DBXq3G0e.js.br +0 -0
- package/dist/web/assets/createLucideIcon-DBXq3G0e.js.gz +0 -0
- package/dist/web/assets/csv-preview-CM7su92m.js +0 -10
- package/dist/web/assets/csv-preview-CM7su92m.js.br +0 -0
- package/dist/web/assets/csv-preview-CM7su92m.js.gz +0 -0
- package/dist/web/assets/database-drivers-section-C6ZKPWaE.js +0 -1
- package/dist/web/assets/database-drivers-section-C6ZKPWaE.js.br +0 -0
- package/dist/web/assets/database-drivers-section-C6ZKPWaE.js.gz +0 -0
- package/dist/web/assets/db-explorer-store-BcLxq-X0.js +0 -1
- package/dist/web/assets/db-explorer-store-BcLxq-X0.js.br +0 -0
- package/dist/web/assets/db-explorer-store-BcLxq-X0.js.gz +0 -0
- package/dist/web/assets/db-tab-parts-DvmnlA6V.js +0 -1
- package/dist/web/assets/db-tab-parts-DvmnlA6V.js.br +0 -0
- package/dist/web/assets/db-tab-parts-DvmnlA6V.js.gz +0 -0
- package/dist/web/assets/db-types-9ac-eYxf.js +0 -1
- package/dist/web/assets/db-types-9ac-eYxf.js.br +0 -0
- package/dist/web/assets/db-types-9ac-eYxf.js.gz +0 -0
- package/dist/web/assets/design-canvas-check-Bo76Q6Qr.js +0 -1
- package/dist/web/assets/design-canvas-check-Bo76Q6Qr.js.br +0 -0
- package/dist/web/assets/design-canvas-check-Bo76Q6Qr.js.gz +0 -0
- package/dist/web/assets/design-export-client-ClwRg798.js +0 -1
- package/dist/web/assets/design-export-client-ClwRg798.js.br +0 -0
- package/dist/web/assets/design-export-client-ClwRg798.js.gz +0 -0
- package/dist/web/assets/design-responsive-dialog-Cdccv3Nw.js +0 -1
- package/dist/web/assets/design-responsive-dialog-Cdccv3Nw.js.br +0 -0
- package/dist/web/assets/design-responsive-dialog-Cdccv3Nw.js.gz +0 -0
- package/dist/web/assets/design-settings-section-CuxZSLAr.js +0 -2
- package/dist/web/assets/design-settings-section-CuxZSLAr.js.br +0 -0
- package/dist/web/assets/design-settings-section-CuxZSLAr.js.gz +0 -0
- package/dist/web/assets/design-skill-suggestion-DZQjG8FV.js +0 -3
- package/dist/web/assets/design-skill-suggestion-DZQjG8FV.js.br +0 -0
- package/dist/web/assets/design-skill-suggestion-DZQjG8FV.js.gz +0 -0
- package/dist/web/assets/design-tab-JlKmHVkd.js +0 -57
- package/dist/web/assets/design-tab-JlKmHVkd.js.br +0 -0
- package/dist/web/assets/design-tab-JlKmHVkd.js.gz +0 -0
- package/dist/web/assets/designs-sidebar-panel-C1EwWf4Z.js +0 -1
- package/dist/web/assets/designs-sidebar-panel-C1EwWf4Z.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-C1EwWf4Z.js.gz +0 -0
- package/dist/web/assets/dialog-DOaEX6AK.js +0 -1
- package/dist/web/assets/dialog-DOaEX6AK.js.br +0 -0
- package/dist/web/assets/dialog-DOaEX6AK.js.gz +0 -0
- package/dist/web/assets/diff-viewer-FidH7Nsq.js +0 -4
- package/dist/web/assets/diff-viewer-FidH7Nsq.js.br +0 -0
- package/dist/web/assets/diff-viewer-FidH7Nsq.js.gz +0 -0
- package/dist/web/assets/docx-preview-ENiLGqzy.js +0 -12
- package/dist/web/assets/docx-preview-ENiLGqzy.js.br +0 -0
- package/dist/web/assets/docx-preview-ENiLGqzy.js.gz +0 -0
- package/dist/web/assets/dropdown-menu-DB3yyoVz.js +0 -1
- package/dist/web/assets/dropdown-menu-DB3yyoVz.js.br +0 -0
- package/dist/web/assets/dropdown-menu-DB3yyoVz.js.gz +0 -0
- package/dist/web/assets/edit-diff-preview-D4EqC86X.js +0 -7
- package/dist/web/assets/edit-diff-preview-D4EqC86X.js.br +0 -0
- package/dist/web/assets/edit-diff-preview-D4EqC86X.js.gz +0 -0
- package/dist/web/assets/editor-dialog-DC7dUWAX.js +0 -1
- package/dist/web/assets/editor-dialog-DC7dUWAX.js.br +0 -0
- package/dist/web/assets/editor-dialog-DC7dUWAX.js.gz +0 -0
- package/dist/web/assets/editor-language-service-0pN0TxYN.js +0 -1
- package/dist/web/assets/editor-language-service-0pN0TxYN.js.br +0 -0
- package/dist/web/assets/editor-language-service-0pN0TxYN.js.gz +0 -0
- package/dist/web/assets/explorer-body-tFaUp9_Q.js +0 -2
- package/dist/web/assets/explorer-body-tFaUp9_Q.js.br +0 -0
- package/dist/web/assets/explorer-body-tFaUp9_Q.js.gz +0 -0
- package/dist/web/assets/explorer-model-BmgFEsj1.js +0 -1
- package/dist/web/assets/explorer-model-BmgFEsj1.js.br +0 -0
- package/dist/web/assets/explorer-model-BmgFEsj1.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-XnRTZT_X.js +0 -1
- package/dist/web/assets/explorer-window-content-XnRTZT_X.js.br +0 -0
- package/dist/web/assets/explorer-window-content-XnRTZT_X.js.gz +0 -0
- package/dist/web/assets/extension-manager-section-DEbwRPf1.js +0 -1
- package/dist/web/assets/extension-manager-section-DEbwRPf1.js.br +0 -0
- package/dist/web/assets/extension-manager-section-DEbwRPf1.js.gz +0 -0
- package/dist/web/assets/extension-webview-C9ApceLU.js +0 -12
- package/dist/web/assets/extension-webview-C9ApceLU.js.br +0 -0
- package/dist/web/assets/extension-webview-C9ApceLU.js.gz +0 -0
- package/dist/web/assets/file-diff-lX1a7RLF.js +0 -1
- package/dist/web/assets/file-icons-DpwcJLL4.js +0 -1
- package/dist/web/assets/file-icons-DpwcJLL4.js.br +0 -0
- package/dist/web/assets/file-icons-DpwcJLL4.js.gz +0 -0
- package/dist/web/assets/file-store-Bk1WYfdy.js +0 -1
- package/dist/web/assets/file-store-Bk1WYfdy.js.br +0 -0
- package/dist/web/assets/file-store-Bk1WYfdy.js.gz +0 -0
- package/dist/web/assets/files-settings-section-C8MacVFQ.js +0 -1
- package/dist/web/assets/files-settings-section-C8MacVFQ.js.br +0 -0
- package/dist/web/assets/files-settings-section-C8MacVFQ.js.gz +0 -0
- package/dist/web/assets/filter-dialog-frame-CoWlaNRy.js +0 -1
- package/dist/web/assets/filter-dialog-frame-CoWlaNRy.js.br +0 -0
- package/dist/web/assets/filter-dialog-frame-CoWlaNRy.js.gz +0 -0
- package/dist/web/assets/format-file-meta-C0LKHE3e.js +0 -1
- package/dist/web/assets/format-file-meta-C0LKHE3e.js.br +0 -0
- package/dist/web/assets/format-file-meta-C0LKHE3e.js.gz +0 -0
- package/dist/web/assets/fs-api-BQrIEcvo.js +0 -1
- package/dist/web/assets/fs-api-BQrIEcvo.js.br +0 -0
- package/dist/web/assets/fs-api-BQrIEcvo.js.gz +0 -0
- package/dist/web/assets/general-settings-section-DZRRGdlQ.js +0 -1
- package/dist/web/assets/general-settings-section-DZRRGdlQ.js.br +0 -0
- package/dist/web/assets/general-settings-section-DZRRGdlQ.js.gz +0 -0
- package/dist/web/assets/git-commit-horizontal-BVihXafd.js +0 -1
- package/dist/web/assets/git-log-panel-g2pBnu6r.js +0 -1
- package/dist/web/assets/git-log-panel-g2pBnu6r.js.br +0 -0
- package/dist/web/assets/git-log-panel-g2pBnu6r.js.gz +0 -0
- package/dist/web/assets/git-repo-store-BOYLnV67.js +0 -1
- package/dist/web/assets/git-repo-store-BOYLnV67.js.br +0 -0
- package/dist/web/assets/git-repo-store-BOYLnV67.js.gz +0 -0
- package/dist/web/assets/git-review-tab-BzI5mxWd.js +0 -3
- package/dist/web/assets/git-review-tab-BzI5mxWd.js.br +0 -0
- package/dist/web/assets/git-review-tab-BzI5mxWd.js.gz +0 -0
- package/dist/web/assets/glide-data-grid-BxvI3ehr.js +0 -177
- package/dist/web/assets/glide-data-grid-BxvI3ehr.js.br +0 -0
- package/dist/web/assets/glide-data-grid-BxvI3ehr.js.gz +0 -0
- package/dist/web/assets/grid-save-dialog-D55Po6Vu.js +0 -2
- package/dist/web/assets/grid-save-dialog-D55Po6Vu.js.br +0 -0
- package/dist/web/assets/grid-save-dialog-D55Po6Vu.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-CoMC-Fx1.js +0 -1
- package/dist/web/assets/group-chat-tab-CoMC-Fx1.js.br +0 -0
- package/dist/web/assets/group-chat-tab-CoMC-Fx1.js.gz +0 -0
- package/dist/web/assets/icons-JMA45Ifw.js +0 -1
- package/dist/web/assets/icons-JMA45Ifw.js.br +0 -0
- package/dist/web/assets/icons-JMA45Ifw.js.gz +0 -0
- package/dist/web/assets/image-preview-D7KR11Xo.js +0 -1
- package/dist/web/assets/impexp-tab-JF6JF8eO.js +0 -1
- package/dist/web/assets/impexp-tab-JF6JF8eO.js.br +0 -0
- package/dist/web/assets/impexp-tab-JF6JF8eO.js.gz +0 -0
- package/dist/web/assets/index-DyYGWFVa.css +0 -1
- package/dist/web/assets/index-DyYGWFVa.css.br +0 -0
- package/dist/web/assets/index-DyYGWFVa.css.gz +0 -0
- package/dist/web/assets/index-ItT-dTPV.js +0 -59
- package/dist/web/assets/index-ItT-dTPV.js.br +0 -0
- package/dist/web/assets/index-ItT-dTPV.js.gz +0 -0
- package/dist/web/assets/input-CKGoVpYv.js +0 -1
- package/dist/web/assets/jira-watcher-section-CvyXLyjO.js +0 -1
- package/dist/web/assets/keybindings-store-CeEtx6js.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-MUIE0Rvf.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-MUIE0Rvf.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-MUIE0Rvf.js.gz +0 -0
- package/dist/web/assets/language-servers-section-DiYURB24.js +0 -2
- package/dist/web/assets/language-servers-section-DiYURB24.js.br +0 -0
- package/dist/web/assets/language-servers-section-DiYURB24.js.gz +0 -0
- package/dist/web/assets/logs-app-CJlNqOdc.js +0 -13
- package/dist/web/assets/logs-app-CJlNqOdc.js.br +0 -0
- package/dist/web/assets/logs-app-CJlNqOdc.js.gz +0 -0
- package/dist/web/assets/logs-tab-BoAlm_8H.js +0 -1
- package/dist/web/assets/logs-window-content-nNm4jl1s.js +0 -1
- package/dist/web/assets/lsp-client-LnKiMWeG.js +0 -1
- package/dist/web/assets/lsp-client-LnKiMWeG.js.br +0 -0
- package/dist/web/assets/lsp-client-LnKiMWeG.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-8Hef5MLx.js +0 -1
- package/dist/web/assets/markdown-renderer-BH_CFPJw.js +0 -5
- package/dist/web/assets/markdown-renderer-BH_CFPJw.js.br +0 -0
- package/dist/web/assets/markdown-renderer-BH_CFPJw.js.gz +0 -0
- package/dist/web/assets/media-url-CsdZ6q_T.js +0 -1
- package/dist/web/assets/metric-chart-canvas-LAMaVJTu.js +0 -1
- package/dist/web/assets/metric-chart-canvas-LAMaVJTu.js.br +0 -0
- package/dist/web/assets/metric-chart-canvas-LAMaVJTu.js.gz +0 -0
- package/dist/web/assets/mobile-bottom-sheet-CGmmdp_5.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-CGmmdp_5.js.br +0 -0
- package/dist/web/assets/mobile-bottom-sheet-CGmmdp_5.js.gz +0 -0
- package/dist/web/assets/mobile-explorer-sheet-Dh2ZECzL.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-Dh2ZECzL.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-Dh2ZECzL.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-CgBUrVFx.js +0 -1
- package/dist/web/assets/new-design-dialog-CgBUrVFx.js.br +0 -0
- package/dist/web/assets/new-design-dialog-CgBUrVFx.js.gz +0 -0
- package/dist/web/assets/notification-store-CXC7u6MW.js +0 -1
- package/dist/web/assets/notifications-settings-section-CPbx23nU.js +0 -1
- package/dist/web/assets/notifications-settings-section-CPbx23nU.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-CPbx23nU.js.gz +0 -0
- package/dist/web/assets/onboarding-entry--MWe4amV.js +0 -1
- package/dist/web/assets/onboarding-entry--MWe4amV.js.br +0 -0
- package/dist/web/assets/onboarding-entry--MWe4amV.js.gz +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DZYQekRt.js +0 -1
- package/dist/web/assets/onboarding-quick-orientation-DZYQekRt.js.br +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DZYQekRt.js.gz +0 -0
- package/dist/web/assets/open-db-tabs-CkQe49j_.js +0 -1
- package/dist/web/assets/open-db-tabs-CkQe49j_.js.br +0 -0
- package/dist/web/assets/open-db-tabs-CkQe49j_.js.gz +0 -0
- package/dist/web/assets/open-settings-DsGBn73g.js +0 -1
- package/dist/web/assets/overview-panel-CcUGDvnt.js +0 -1
- package/dist/web/assets/overview-panel-CcUGDvnt.js.br +0 -0
- package/dist/web/assets/overview-panel-CcUGDvnt.js.gz +0 -0
- package/dist/web/assets/panel-store-DmP16Fo0.js +0 -1
- package/dist/web/assets/panel-store-DmP16Fo0.js.br +0 -0
- package/dist/web/assets/panel-store-DmP16Fo0.js.gz +0 -0
- package/dist/web/assets/patch-tab-metadata-B-jH5svY.js +0 -1
- package/dist/web/assets/pdf-preview-DMUIWb9B.js +0 -1
- package/dist/web/assets/pdf-preview-DMUIWb9B.js.br +0 -0
- package/dist/web/assets/pdf-preview-DMUIWb9B.js.gz +0 -0
- package/dist/web/assets/performance-panel-CJDLUwrs.js +0 -3
- package/dist/web/assets/performance-panel-CJDLUwrs.js.br +0 -0
- package/dist/web/assets/performance-panel-CJDLUwrs.js.gz +0 -0
- package/dist/web/assets/portal-container-context-BXAsDqrB.js +0 -1
- package/dist/web/assets/ppmbot-settings-section-DTCTPQ-R.js +0 -1
- package/dist/web/assets/ppmbot-settings-section-DTCTPQ-R.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-DTCTPQ-R.js.gz +0 -0
- package/dist/web/assets/pptx-export-BxmgltJ4.js +0 -111
- package/dist/web/assets/pptx-export-BxmgltJ4.js.br +0 -0
- package/dist/web/assets/pptx-export-BxmgltJ4.js.gz +0 -0
- package/dist/web/assets/problems-panel-DX32QDH_.js +0 -1
- package/dist/web/assets/problems-panel-DX32QDH_.js.br +0 -0
- package/dist/web/assets/problems-panel-DX32QDH_.js.gz +0 -0
- package/dist/web/assets/process-row-format-CBw-CQCx.js +0 -1
- package/dist/web/assets/process-table-CX-NhOg6.js +0 -1
- package/dist/web/assets/process-table-CX-NhOg6.js.br +0 -0
- package/dist/web/assets/process-table-CX-NhOg6.js.gz +0 -0
- package/dist/web/assets/project-framework-store-Bi5dyHdx.js +0 -1
- package/dist/web/assets/project-store-CEGoLMOl.js +0 -1
- package/dist/web/assets/project-store-CEGoLMOl.js.br +0 -0
- package/dist/web/assets/project-store-CEGoLMOl.js.gz +0 -0
- package/dist/web/assets/proxy-settings-section-BGNvFe7e.js +0 -1
- package/dist/web/assets/proxy-settings-section-BGNvFe7e.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-BGNvFe7e.js.gz +0 -0
- package/dist/web/assets/query-audit-section-DTHI5GP7.js +0 -1
- package/dist/web/assets/query-audit-section-DTHI5GP7.js.br +0 -0
- package/dist/web/assets/query-audit-section-DTHI5GP7.js.gz +0 -0
- package/dist/web/assets/query-tab-qMlIkHRk.js +0 -22
- package/dist/web/assets/query-tab-qMlIkHRk.js.br +0 -0
- package/dist/web/assets/query-tab-qMlIkHRk.js.gz +0 -0
- package/dist/web/assets/react-PkBxFcos.js +0 -1
- package/dist/web/assets/remote-access-settings-section-t2BYAA9g.js +0 -1
- package/dist/web/assets/remote-access-settings-section-t2BYAA9g.js.br +0 -0
- package/dist/web/assets/remote-access-settings-section-t2BYAA9g.js.gz +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-ChUU6Jts.js +0 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-ChUU6Jts.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-ChUU6Jts.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-_bopEtCa.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-sheet-_bopEtCa.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-_bopEtCa.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-D9G4kDfa.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-view-D9G4kDfa.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-D9G4kDfa.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-Yz9eVB3-.js +0 -1
- package/dist/web/assets/remote-desktop-readiness-gate-Yz9eVB3-.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-Yz9eVB3-.js.gz +0 -0
- package/dist/web/assets/remote-desktop-settings-section-BTGGSjZY.js +0 -1
- package/dist/web/assets/remote-desktop-settings-section-BTGGSjZY.js.br +0 -0
- package/dist/web/assets/remote-desktop-settings-section-BTGGSjZY.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-B8ZaG2bL.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-B8ZaG2bL.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-B8ZaG2bL.js.gz +0 -0
- package/dist/web/assets/rename-object-dialog-FSlcdUoB.js +0 -1
- package/dist/web/assets/rename-object-dialog-FSlcdUoB.js.br +0 -0
- package/dist/web/assets/rename-object-dialog-FSlcdUoB.js.gz +0 -0
- package/dist/web/assets/review-code-CfuJeLYd.js +0 -5
- package/dist/web/assets/review-code-CfuJeLYd.js.br +0 -0
- package/dist/web/assets/review-code-CfuJeLYd.js.gz +0 -0
- package/dist/web/assets/run-in-terminal-Bk9Bw7G1.js +0 -1
- package/dist/web/assets/run-in-terminal-button-DFPQUlZs.js +0 -1
- package/dist/web/assets/save-as-dialog-Bj9VpGYf.js +0 -1
- package/dist/web/assets/save-as-dialog-Bj9VpGYf.js.br +0 -0
- package/dist/web/assets/save-as-dialog-Bj9VpGYf.js.gz +0 -0
- package/dist/web/assets/schedules-settings-section-DNJ4K7zS.js +0 -1
- package/dist/web/assets/schedules-settings-section-DNJ4K7zS.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-DNJ4K7zS.js.gz +0 -0
- package/dist/web/assets/scroll-area-6Am1KMiB.js +0 -1
- package/dist/web/assets/scroll-area-6Am1KMiB.js.br +0 -0
- package/dist/web/assets/scroll-area-6Am1KMiB.js.gz +0 -0
- package/dist/web/assets/send-to-chat-Bcm_Lcog.js +0 -1
- package/dist/web/assets/send-to-chat-Bcm_Lcog.js.br +0 -0
- package/dist/web/assets/send-to-chat-Bcm_Lcog.js.gz +0 -0
- package/dist/web/assets/separator-BOYUIPkH.js +0 -1
- package/dist/web/assets/services-panel-CBRTsROB.js +0 -1
- package/dist/web/assets/services-panel-CBRTsROB.js.br +0 -0
- package/dist/web/assets/services-panel-CBRTsROB.js.gz +0 -0
- package/dist/web/assets/session-changes-bar-BRopa3Dh.js +0 -1
- package/dist/web/assets/session-changes-bar-BRopa3Dh.js.br +0 -0
- package/dist/web/assets/session-changes-bar-BRopa3Dh.js.gz +0 -0
- package/dist/web/assets/session-list-sync-triggers-DitiR5h1.js +0 -1
- package/dist/web/assets/session-list-sync-triggers-DitiR5h1.js.br +0 -0
- package/dist/web/assets/session-list-sync-triggers-DitiR5h1.js.gz +0 -0
- package/dist/web/assets/session-review-tab--kNB_FKQ.js +0 -6
- package/dist/web/assets/session-review-tab--kNB_FKQ.js.br +0 -0
- package/dist/web/assets/session-review-tab--kNB_FKQ.js.gz +0 -0
- package/dist/web/assets/settings-body-B-s0fEjc.js +0 -1
- package/dist/web/assets/settings-body-B-s0fEjc.js.br +0 -0
- package/dist/web/assets/settings-body-B-s0fEjc.js.gz +0 -0
- package/dist/web/assets/settings-categories-CcR9eL3x.js +0 -1
- package/dist/web/assets/settings-categories-CcR9eL3x.js.br +0 -0
- package/dist/web/assets/settings-categories-CcR9eL3x.js.gz +0 -0
- package/dist/web/assets/settings-section-content-BJ35dy5r.js +0 -1
- package/dist/web/assets/settings-section-content-DckksvTg.js +0 -2
- package/dist/web/assets/settings-section-content-DckksvTg.js.br +0 -0
- package/dist/web/assets/settings-section-content-DckksvTg.js.gz +0 -0
- package/dist/web/assets/settings-store-WeJyQVL8.js +0 -2
- package/dist/web/assets/settings-store-WeJyQVL8.js.br +0 -0
- package/dist/web/assets/settings-store-WeJyQVL8.js.gz +0 -0
- package/dist/web/assets/settings-tab-BlX33GEN.js +0 -1
- package/dist/web/assets/settings-window-content-B-7yV1_q.js +0 -1
- package/dist/web/assets/slash-command-picker-BBcy6w6m.js +0 -1
- package/dist/web/assets/slash-command-picker-BBcy6w6m.js.br +0 -0
- package/dist/web/assets/slash-command-picker-BBcy6w6m.js.gz +0 -0
- package/dist/web/assets/sortable-header-B9gfWik4.js +0 -1
- package/dist/web/assets/sortable-header-B9gfWik4.js.br +0 -0
- package/dist/web/assets/sortable-header-B9gfWik4.js.gz +0 -0
- package/dist/web/assets/sql-completion-provider-CaTHVr1l.js +0 -5
- package/dist/web/assets/sql-completion-provider-CaTHVr1l.js.br +0 -0
- package/dist/web/assets/sql-completion-provider-CaTHVr1l.js.gz +0 -0
- package/dist/web/assets/sql-object-tab-DVo4bxRI.js +0 -1
- package/dist/web/assets/sql-object-tab-DVo4bxRI.js.br +0 -0
- package/dist/web/assets/sql-object-tab-DVo4bxRI.js.gz +0 -0
- package/dist/web/assets/sqlite-viewer-BGfIpl5x.js +0 -1
- package/dist/web/assets/sqlite-viewer-BGfIpl5x.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-BGfIpl5x.js.gz +0 -0
- package/dist/web/assets/start-ellipsis-rBh37k0n.js +0 -1
- package/dist/web/assets/structure-save-dialog-STK_RFCK.js +0 -1
- package/dist/web/assets/structure-save-dialog-STK_RFCK.js.br +0 -0
- package/dist/web/assets/structure-save-dialog-STK_RFCK.js.gz +0 -0
- package/dist/web/assets/structure-tab-DuLnsTC4.js +0 -3
- package/dist/web/assets/structure-tab-DuLnsTC4.js.br +0 -0
- package/dist/web/assets/structure-tab-DuLnsTC4.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-BIjW16Pb.js +0 -2
- package/dist/web/assets/system-monitor-body-BIjW16Pb.js.br +0 -0
- package/dist/web/assets/system-monitor-body-BIjW16Pb.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-B6_tC9LO.js +0 -1
- package/dist/web/assets/system-monitor-window-content-CwBzqMUe.js +0 -1
- package/dist/web/assets/tab-host-window-content-CpdEjkZd.js +0 -1
- package/dist/web/assets/tab-host-window-content-CpdEjkZd.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-CpdEjkZd.js.gz +0 -0
- package/dist/web/assets/tab-store-nNzRNfVV.js +0 -1
- package/dist/web/assets/table-tab-B5asfTBP.js +0 -2
- package/dist/web/assets/table-tab-B5asfTBP.js.br +0 -0
- package/dist/web/assets/table-tab-B5asfTBP.js.gz +0 -0
- package/dist/web/assets/telegram-bot-token-field-BiqKbXwE.js +0 -1
- package/dist/web/assets/telegram-bot-token-field-BiqKbXwE.js.br +0 -0
- package/dist/web/assets/telegram-bot-token-field-BiqKbXwE.js.gz +0 -0
- package/dist/web/assets/terminal-tab-DpMONMVB.js +0 -3
- package/dist/web/assets/terminal-tab-DpMONMVB.js.br +0 -0
- package/dist/web/assets/terminal-tab-DpMONMVB.js.gz +0 -0
- package/dist/web/assets/tool-cards-DoDKxqN4.js +0 -14
- package/dist/web/assets/tool-cards-DoDKxqN4.js.br +0 -0
- package/dist/web/assets/tool-cards-DoDKxqN4.js.gz +0 -0
- package/dist/web/assets/use-at-most-wide-BQFi1Sjv.js +0 -1
- package/dist/web/assets/use-blob-url-D7ElNPnW.js +0 -1
- package/dist/web/assets/use-db-driver-installed-BscdI-wS.js +0 -1
- package/dist/web/assets/use-db-read-DYuyNA5i.js +0 -1
- package/dist/web/assets/use-db-read-DYuyNA5i.js.br +0 -0
- package/dist/web/assets/use-db-read-DYuyNA5i.js.gz +0 -0
- package/dist/web/assets/use-db-tab-Cr4lXxwF.js +0 -1
- package/dist/web/assets/use-db-tab-Cr4lXxwF.js.br +0 -0
- package/dist/web/assets/use-db-tab-Cr4lXxwF.js.gz +0 -0
- package/dist/web/assets/use-design-canvas-check-DKlyMp-S.js +0 -1
- package/dist/web/assets/use-design-canvas-check-DKlyMp-S.js.br +0 -0
- package/dist/web/assets/use-design-canvas-check-DKlyMp-S.js.gz +0 -0
- package/dist/web/assets/use-h264-canvas-decoder-DAjp9oHe.js +0 -1
- package/dist/web/assets/use-h264-canvas-decoder-DAjp9oHe.js.br +0 -0
- package/dist/web/assets/use-h264-canvas-decoder-DAjp9oHe.js.gz +0 -0
- package/dist/web/assets/use-inline-blame-DS0HrHJ3.js +0 -16
- package/dist/web/assets/use-inline-blame-DS0HrHJ3.js.br +0 -0
- package/dist/web/assets/use-inline-blame-DS0HrHJ3.js.gz +0 -0
- package/dist/web/assets/use-is-mobile-BXHbkfs9.js +0 -1
- package/dist/web/assets/use-lsp-BTVDYrt6.js +0 -6
- package/dist/web/assets/use-lsp-BTVDYrt6.js.br +0 -0
- package/dist/web/assets/use-lsp-BTVDYrt6.js.gz +0 -0
- package/dist/web/assets/use-monaco-theme-DqnhExsm.js +0 -1
- package/dist/web/assets/use-opener-focus-C5L5UUJs.js +0 -1
- package/dist/web/assets/use-process-kill-D-SGQxDn.js +0 -1
- package/dist/web/assets/use-process-kill-D-SGQxDn.js.br +0 -0
- package/dist/web/assets/use-process-kill-D-SGQxDn.js.gz +0 -0
- package/dist/web/assets/use-sql-schema-info-DRb9dAKi.js +0 -4
- package/dist/web/assets/use-sql-schema-info-DRb9dAKi.js.br +0 -0
- package/dist/web/assets/use-sql-schema-info-DRb9dAKi.js.gz +0 -0
- package/dist/web/assets/use-visual-viewport-CQ6-A0Dt.js +0 -1
- package/dist/web/assets/use-websocket-C6RnlNVJ.js +0 -1
- package/dist/web/assets/vendor-markdown-QKPNiWEd.js +0 -291
- package/dist/web/assets/vendor-markdown-QKPNiWEd.js.br +0 -0
- package/dist/web/assets/vendor-markdown-QKPNiWEd.js.gz +0 -0
- package/dist/web/assets/vendor-ui-CS1GvlOm.js +0 -45
- package/dist/web/assets/vendor-ui-CS1GvlOm.js.br +0 -0
- package/dist/web/assets/vendor-ui-CS1GvlOm.js.gz +0 -0
- package/dist/web/assets/video-preview-CYzeUPfH.js +0 -1
- package/dist/web/assets/video-preview-CYzeUPfH.js.br +0 -0
- package/dist/web/assets/video-preview-CYzeUPfH.js.gz +0 -0
- package/dist/web/assets/voice-settings-section-C01d-toF.js +0 -1
- package/dist/web/assets/voice-settings-section-C01d-toF.js.br +0 -0
- package/dist/web/assets/voice-settings-section-C01d-toF.js.gz +0 -0
- package/dist/web/assets/web-preview-tab-F5C3quQs.js +0 -1
- package/dist/web/assets/web-preview-tab-F5C3quQs.js.br +0 -0
- package/dist/web/assets/web-preview-tab-F5C3quQs.js.gz +0 -0
- package/dist/web/assets/window-pip-registry-DSoB7T3k.js +0 -1
- package/dist/web/assets/window-store-zJczRsv4.js +0 -1
- package/dist/web/assets/window-store-zJczRsv4.js.br +0 -0
- package/dist/web/assets/window-store-zJczRsv4.js.gz +0 -0
- package/dist/web/assets/ws-auth-cWeQ7_61.js +0 -1
- /package/dist/web/assets/{__vite-browser-external-B4VNaaaA.js → __vite-browser-external-DL4jXWNt.js} +0 -0
- /package/dist/web/assets/{clipboard-D3XnL7CB.js → clipboard-D-VCry-F.js} +0 -0
- /package/dist/web/assets/{clipboard-D3XnL7CB.js.br → clipboard-D-VCry-F.js.br} +0 -0
- /package/dist/web/assets/{clipboard-D3XnL7CB.js.gz → clipboard-D-VCry-F.js.gz} +0 -0
- /package/dist/web/assets/{code-fence-vHZyBehL.js → code-fence-BK57HRhJ.js} +0 -0
- /package/dist/web/assets/{design-system-status-label-Cus6e2Df.js → design-system-status-label-KA4ESjWe.js} +0 -0
- /package/dist/web/assets/{format-bytes-B2kC4sbB.js → format-bytes-he3TR0bV.js} +0 -0
- /package/dist/web/assets/{session-turns-gmrmXzeg.js → session-turns-D3QpTtCq.js} +0 -0
- /package/dist/web/assets/{session-turns-gmrmXzeg.js.br → session-turns-D3QpTtCq.js.br} +0 -0
- /package/dist/web/assets/{session-turns-gmrmXzeg.js.gz → session-turns-D3QpTtCq.js.gz} +0 -0
- /package/dist/web/assets/{vendor-xterm-sFX94k3w.js → vendor-xterm-DRhOk3kW.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-sFX94k3w.js.br → vendor-xterm-DRhOk3kW.js.br} +0 -0
- /package/dist/web/assets/{vendor-xterm-sFX94k3w.js.gz → vendor-xterm-DRhOk3kW.js.gz} +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { commitsByItself } from "../../shared/db-ai-tools.ts";
|
|
2
|
+
import { splitSqlScript, sqlCode } from "../../shared/split-sql-statements.ts";
|
|
3
|
+
import { dialectNameOf, type DbType, type DialectName } from "../../shared/db-types.ts";
|
|
4
|
+
import type { QueryStatementResult } from "../../shared/db-query-script.ts";
|
|
5
|
+
import type { DbQuerySession } from "../../types/database.ts";
|
|
6
|
+
import { QueryStatementError } from "../database/db-errors.ts";
|
|
7
|
+
import { QueryScriptRun, type QueryScriptSummary } from "../database/query-script-runner.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The database tools' runs, on a session the caller opened with the tool's own `readonly`:
|
|
11
|
+
*
|
|
12
|
+
* - `db_query` is the Query tab's run (`QueryScriptRun`) on a read-only session, so a write
|
|
13
|
+
* hidden in a function call is refused by the database itself, as it is everywhere in PPM.
|
|
14
|
+
* - `db_execute` runs the script the user approved, once, inside one transaction PPM opens and
|
|
15
|
+
* ends itself: committed only when every statement succeeded and the rows changed in all are
|
|
16
|
+
* the ones the AI said to expect, rolled back otherwise. MySQL and MariaDB commit a CREATE,
|
|
17
|
+
* ALTER, DROP or TRUNCATE by itself, with everything before it, so there the transaction is
|
|
18
|
+
* opened again after one, and a run rolled back says which statements were kept all the same.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export interface AiQueryRun {
|
|
22
|
+
results: QueryStatementResult[];
|
|
23
|
+
summary: QueryScriptSummary;
|
|
24
|
+
/** What the run said about itself rather than a statement: a transaction left open, rolled back. */
|
|
25
|
+
messages: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Runs `sql` statement by statement and closes the session. Never throws. */
|
|
29
|
+
export async function runAiQuery(session: DbQuerySession, opts: { sql: string; dialect: DialectName; maxRows: number; timeoutMs?: number }): Promise<AiQueryRun> {
|
|
30
|
+
const results: QueryStatementResult[] = [];
|
|
31
|
+
const messages: string[] = [];
|
|
32
|
+
const run = new QueryScriptRun({ sql: opts.sql, dialect: opts.dialect, maxRows: opts.maxRows, timeoutMs: opts.timeoutMs });
|
|
33
|
+
const summary = await run.execute(session, (event) => {
|
|
34
|
+
if (event.type === "statement") results.push(event.result);
|
|
35
|
+
else if (event.type === "message") messages.push(event.text);
|
|
36
|
+
else if (event.type === "done" && event.error !== undefined) messages.push(event.error);
|
|
37
|
+
});
|
|
38
|
+
return { results, summary, messages };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Statements that begin or end a transaction: PPM opens and ends the one `db_execute` runs in. */
|
|
42
|
+
const TRANSACTION_CONTROL = /^\s*(begin|start\s+transaction|commit|end|rollback|abort|savepoint|release|prepare\s+transaction)\b/i;
|
|
43
|
+
|
|
44
|
+
/** The first statement of `sql` that controls the transaction, or null. */
|
|
45
|
+
export function transactionControlIn(sql: string, dialect: DialectName): string | null {
|
|
46
|
+
for (const statement of splitSqlScript(sql, dialect)) {
|
|
47
|
+
if (TRANSACTION_CONTROL.test(sqlCode(statement.sql, dialect))) return statement.sql.trim().split(/\s+/).slice(0, 3).join(" ");
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type ApprovedRunReport =
|
|
53
|
+
| { committed: true; results: QueryStatementResult[]; rowsChanged: number }
|
|
54
|
+
/**
|
|
55
|
+
* Rolled back, or never begun. `kept` counts the statements, from the first, that the database
|
|
56
|
+
* had committed by itself before then — only MySQL and MariaDB do — and is 0 when nothing the
|
|
57
|
+
* script did was kept. `mayHaveKept`, more than `kept`, is set when the connection went before
|
|
58
|
+
* the database could say whether the statement then running had ended the transaction: read
|
|
59
|
+
* from the SQL, statements 1 to it may be in the database too.
|
|
60
|
+
*/
|
|
61
|
+
| { committed: false; results: QueryStatementResult[]; rowsChanged: number; kept: number; mayHaveKept?: number; reason: string };
|
|
62
|
+
|
|
63
|
+
const BEGIN: Record<DialectName, string> = { postgres: "BEGIN", sqlite: "BEGIN", mysql: "START TRANSACTION" };
|
|
64
|
+
|
|
65
|
+
const errorText = (e: unknown): string => (e instanceof Error ? e.message : String(e));
|
|
66
|
+
|
|
67
|
+
const COMMITS_BY_ITSELF = "MySQL and MariaDB commit a CREATE, ALTER, DROP or TRUNCATE by itself, with everything before it";
|
|
68
|
+
|
|
69
|
+
/** `statement 2`, or `statements 1–3`. */
|
|
70
|
+
const statementsLabel = (from: number, to: number): string => (from === to ? `statement ${from}` : `statements ${from}–${to}`);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Runs the approved script inside one transaction on `session` (writable), and closes the
|
|
74
|
+
* session. `expectedRows`, when given, must equal the rows the statements changed in all.
|
|
75
|
+
* Never throws: what went wrong is in the report.
|
|
76
|
+
*/
|
|
77
|
+
export async function runApprovedScript(session: DbQuerySession, opts: {
|
|
78
|
+
sql: string;
|
|
79
|
+
dbType: DbType;
|
|
80
|
+
maxRows: number;
|
|
81
|
+
expectedRows?: number;
|
|
82
|
+
/** How long one statement may run before it is cancelled. */
|
|
83
|
+
timeoutMs?: number;
|
|
84
|
+
}): Promise<ApprovedRunReport> {
|
|
85
|
+
const dialect = dialectNameOf(opts.dbType);
|
|
86
|
+
const results: QueryStatementResult[] = [];
|
|
87
|
+
let rowsChanged = 0;
|
|
88
|
+
let begun = false;
|
|
89
|
+
/**
|
|
90
|
+
* Statements, from the first, that are in the database whatever happens next: MySQL and MariaDB
|
|
91
|
+
* commit a CREATE, ALTER, DROP or TRUNCATE by itself, with everything before it, and end the
|
|
92
|
+
* transaction there. PPM then opens it again, so that what follows can still be rolled back.
|
|
93
|
+
*/
|
|
94
|
+
let kept = 0;
|
|
95
|
+
/**
|
|
96
|
+
* Set above `kept` when the connection went before the database could say whether the statement
|
|
97
|
+
* then running had ended the transaction. The SQL says whether it may have (`commitsByItself`),
|
|
98
|
+
* so the report says what may be in the database instead of claiming that nothing is.
|
|
99
|
+
*/
|
|
100
|
+
let mayHaveKept = 0;
|
|
101
|
+
/** False once a statement has ended the transaction, which only MySQL and MariaDB do. */
|
|
102
|
+
const stillOpen = async (): Promise<boolean> => !session.transactionOpen || await session.transactionOpen();
|
|
103
|
+
/** `cause`, and what the run left behind: nothing, the first `kept` statements, or maybe more. */
|
|
104
|
+
const notKept = (cause: string): string => {
|
|
105
|
+
if (mayHaveKept > kept) {
|
|
106
|
+
const unsure = `${statementsLabel(kept + 1, mayHaveKept)} may have been kept`;
|
|
107
|
+
const keptPart = kept === 0 ? unsure : `${statementsLabel(1, kept)} ${kept === 1 ? "was" : "were"} kept, and ${unsure} too`;
|
|
108
|
+
return `${cause}, and the database could not be asked what it kept: ${keptPart}, because ${COMMITS_BY_ITSELF}.`;
|
|
109
|
+
}
|
|
110
|
+
if (kept === 0) return `${cause}, so the transaction was rolled back and nothing changed.`;
|
|
111
|
+
const ran = results.filter((r) => r.error === undefined).length;
|
|
112
|
+
const keptPart = `${statementsLabel(1, kept)} ${kept === 1 ? "was" : "were"} kept`;
|
|
113
|
+
if (ran <= kept) return `${cause}, but nothing could be rolled back: ${keptPart}, because ${COMMITS_BY_ITSELF}.`;
|
|
114
|
+
return `${cause}, so ${statementsLabel(kept + 1, ran)} ${ran - kept === 1 ? "was" : "were"} rolled back, but ${keptPart}, because ${COMMITS_BY_ITSELF}.`;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Always `return await`ed: a promise returned unawaited from inside `try` does not hold back its
|
|
118
|
+
* `finally`, which closes the session under the rollback — and on MySQL the rollback then never
|
|
119
|
+
* answers, so the tool call hung.
|
|
120
|
+
*/
|
|
121
|
+
const rolledBack = async (reason: string): Promise<ApprovedRunReport> => {
|
|
122
|
+
let why = reason;
|
|
123
|
+
if (begun) {
|
|
124
|
+
try {
|
|
125
|
+
await session.rollbackOpenTransaction();
|
|
126
|
+
} catch (e) {
|
|
127
|
+
why += ` Rolling back failed too (${errorText(e)}); the database ends the transaction when the connection closes.`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { committed: false, results, rowsChanged, kept, ...(mayHaveKept > kept ? { mayHaveKept } : {}), reason: why };
|
|
131
|
+
};
|
|
132
|
+
try {
|
|
133
|
+
const statements = splitSqlScript(opts.sql, dialect, session.splitOptions);
|
|
134
|
+
if (statements.length === 0) return { committed: false, results, rowsChanged, kept, reason: "The script has no statements to run." };
|
|
135
|
+
try {
|
|
136
|
+
await session.run(BEGIN[dialect], 1);
|
|
137
|
+
begun = true;
|
|
138
|
+
} catch (e) {
|
|
139
|
+
return { committed: false, results, rowsChanged, kept, reason: `The transaction could not be started: ${errorText(e)}` };
|
|
140
|
+
}
|
|
141
|
+
for (const [index, statement] of statements.entries()) {
|
|
142
|
+
const started = performance.now();
|
|
143
|
+
const base = { index, startLine: statement.startLine, endLine: statement.endLine, sql: statement.sql };
|
|
144
|
+
let timedOut = false;
|
|
145
|
+
const timer = opts.timeoutMs === undefined ? null : setTimeout(() => {
|
|
146
|
+
timedOut = true;
|
|
147
|
+
session.cancel();
|
|
148
|
+
}, opts.timeoutMs);
|
|
149
|
+
try {
|
|
150
|
+
const outcome = await session.run(statement.sql, opts.maxRows);
|
|
151
|
+
results.push({
|
|
152
|
+
...base,
|
|
153
|
+
...(outcome.command ? { command: outcome.command } : {}),
|
|
154
|
+
resultSets: outcome.resultSets.map(({ columns, rows, truncated }) => ({ columns, rows, ...(truncated ? { truncated: true } : {}) })),
|
|
155
|
+
...(outcome.rowsAffected !== undefined ? { rowsAffected: outcome.rowsAffected } : {}),
|
|
156
|
+
...(outcome.notices.length > 0 ? { notices: outcome.notices } : {}),
|
|
157
|
+
durationMs: Math.round(performance.now() - started),
|
|
158
|
+
});
|
|
159
|
+
rowsChanged += outcome.rowsAffected ?? 0;
|
|
160
|
+
} catch (e) {
|
|
161
|
+
const message = e instanceof QueryStatementError || e instanceof Error ? e.message : String(e);
|
|
162
|
+
const error = timedOut ? `Stopped after ${Math.round(opts.timeoutMs! / 1000)} s: ${message}` : message;
|
|
163
|
+
results.push({ ...base, resultSets: [], durationMs: Math.round(performance.now() - started), error, ...(timedOut ? { stopped: "timeout" as const } : {}) });
|
|
164
|
+
// A statement that ends the transaction ends it before it runs, so even one that then fails
|
|
165
|
+
// keeps what came before it. When the connection went before the database could say, the
|
|
166
|
+
// SQL tells whether it may have; any other statement leaves the server to roll back.
|
|
167
|
+
const open = await stillOpen().catch(() => null);
|
|
168
|
+
if (open === false) kept = index;
|
|
169
|
+
else if (open === null && commitsByItself(opts.dbType, statement.sql)) mayHaveKept = index;
|
|
170
|
+
return await rolledBack(notKept(`Statement ${index + 1} failed`));
|
|
171
|
+
} finally {
|
|
172
|
+
if (timer) clearTimeout(timer);
|
|
173
|
+
}
|
|
174
|
+
const open = await stillOpen().catch((e: unknown) => {
|
|
175
|
+
// It ran, and the connection went before the database could say whether it ended the
|
|
176
|
+
// transaction: when the SQL says it does, it and everything before it may be in.
|
|
177
|
+
if (commitsByItself(opts.dbType, statement.sql)) mayHaveKept = index + 1;
|
|
178
|
+
throw e;
|
|
179
|
+
});
|
|
180
|
+
if (!open) {
|
|
181
|
+
kept = index + 1;
|
|
182
|
+
if (index < statements.length - 1) await session.run(BEGIN[dialect], 1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (opts.expectedRows !== undefined && rowsChanged !== opts.expectedRows) {
|
|
186
|
+
return await rolledBack(notKept(`The script changed ${rowsChanged} ${rowsChanged === 1 ? "row" : "rows"} in all, not the ${opts.expectedRows} expected`));
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
await session.run("COMMIT", 1);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
return await rolledBack(notKept(`COMMIT failed (${errorText(e)})`));
|
|
192
|
+
}
|
|
193
|
+
return { committed: true, results, rowsChanged };
|
|
194
|
+
} catch (e) {
|
|
195
|
+
return await rolledBack(notKept(`The run broke off (${errorText(e)})`));
|
|
196
|
+
} finally {
|
|
197
|
+
await session.close().catch(() => {});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { decryptConfig, type ConnectionRow } from "../db.service.ts";
|
|
2
|
+
import { DatabaseTargetError, readDatabaseParam, withDatabase } from "../database/connection-database.ts";
|
|
3
|
+
import { missingLogin } from "../database/connection-login.ts";
|
|
4
|
+
import { driverForEngine } from "../database/drivers/db-driver-catalog.ts";
|
|
5
|
+
import { DbDriverMissingError, loadDbDriver } from "../database/drivers/db-driver-loader.ts";
|
|
6
|
+
import { connConfig } from "../../server/routes/database-route-helpers.ts";
|
|
7
|
+
import type { StoredConnectionConfig } from "../../shared/db-connection-config.ts";
|
|
8
|
+
import type { DbConnectionConfig } from "../../types/database.ts";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Where a database tool's SQL runs: the connection's own database or another on its server
|
|
12
|
+
* (checked as the CONNECTIONS tree checks one), with its driver loaded and its login held.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** The `database` argument, checked the way `?database=` is for the CONNECTIONS tree. */
|
|
16
|
+
export function aiDatabaseArg(conn: ConnectionRow, raw: unknown): { ok: true; database?: string } | { ok: false; error: string } {
|
|
17
|
+
if (raw === undefined || raw === null || raw === "") return { ok: true };
|
|
18
|
+
if (typeof raw !== "string") return { ok: false, error: "`database` must be a database name." };
|
|
19
|
+
try {
|
|
20
|
+
const database = readDatabaseParam(raw);
|
|
21
|
+
if (database !== undefined) withDatabase(decryptConfig(conn.connection_config), database);
|
|
22
|
+
return { ok: true, ...(database !== undefined ? { database } : {}) };
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (e instanceof DatabaseTargetError) return { ok: false, error: e.message };
|
|
25
|
+
throw e;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function ensureDrivers(conn: ConnectionRow, saved: StoredConnectionConfig): Promise<void> {
|
|
30
|
+
const ids = [driverForEngine(conn.type)?.id, saved.type !== "sqlite" && saved.ssh?.enabled ? "ssh" as const : undefined];
|
|
31
|
+
for (const id of ids) {
|
|
32
|
+
if (!id) continue;
|
|
33
|
+
try {
|
|
34
|
+
await loadDbDriver(id);
|
|
35
|
+
} catch (e) {
|
|
36
|
+
if (e instanceof DbDriverMissingError) {
|
|
37
|
+
throw new Error(`${e.message} Ask the user to install it from Settings → Database Drivers in PPM.`);
|
|
38
|
+
}
|
|
39
|
+
throw e;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The adapter config the tools open `conn` with: `readonly` is the tool's, not the row's —
|
|
46
|
+
* `db_query` always reads inside a read-only transaction, and `db_execute` writes only once the
|
|
47
|
+
* user approved it. Throws an `Error` whose message is for the AI.
|
|
48
|
+
*/
|
|
49
|
+
export async function aiTargetConfig(conn: ConnectionRow, database: string | undefined, readonly: boolean): Promise<DbConnectionConfig> {
|
|
50
|
+
const saved = decryptConfig(conn.connection_config);
|
|
51
|
+
await ensureDrivers(conn, saved);
|
|
52
|
+
if (missingLogin(conn)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Connection "${conn.name}" asks for its password, and nobody has logged in to it since PPM started. `
|
|
55
|
+
+ "Ask the user to open it in PPM's Database panel and log in, then call again.",
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return { ...connConfig(conn, database), readonly };
|
|
59
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import type { ConnectionRow } from "../db.service.ts";
|
|
2
|
+
import { getAdapter } from "../database/adapter-registry.ts";
|
|
3
|
+
import { isReadOnlyQuery } from "../database/readonly-check.ts";
|
|
4
|
+
import { detectOperation, insertQueryLog, type QueryLogInput, type QueryOperation } from "../query-audit/query-audit.service.ts";
|
|
5
|
+
import { createMcpHttpHandler, textResult, type Json } from "../mcp-http-endpoint.ts";
|
|
6
|
+
import { tabOpenBroker, type TabOpenOutcome } from "../tab-tools-mcp/tab-open-broker.ts";
|
|
7
|
+
import { rowsToRecords } from "../../shared/db-grid.ts";
|
|
8
|
+
import { dialectNameOf, type DialectName } from "../../shared/db-types.ts";
|
|
9
|
+
import { splitSqlScript, sqlCode } from "../../shared/split-sql-statements.ts";
|
|
10
|
+
import { neutralizeFences } from "../../shared/untrusted-text.ts";
|
|
11
|
+
import { isPpmTool, ppmToolOffMessage, ppmToolOn } from "../../shared/ppm-tools.ts";
|
|
12
|
+
import {
|
|
13
|
+
DB_QUERY_TOOL, MAX_DB_TOOL_REASON_CHARS, MAX_DB_TOOL_SQL_CHARS, OPEN_QUERY_TOOL, type DbExecuteApprovalInput,
|
|
14
|
+
} from "../../shared/db-ai-tools.ts";
|
|
15
|
+
import type { TabOpenAsk } from "../../shared/tab-open-protocol.ts";
|
|
16
|
+
import type { DbQuerySession } from "../../types/database.ts";
|
|
17
|
+
import { configService } from "../config.service.ts";
|
|
18
|
+
import { describeAiConnections, findAiConnection } from "./db-ai-connections.ts";
|
|
19
|
+
import { aiDatabaseArg, aiTargetConfig } from "./db-ai-target.ts";
|
|
20
|
+
import { formatStatementResults } from "./db-ai-format.ts";
|
|
21
|
+
import { runAiQuery, runApprovedScript, transactionControlIn } from "./db-ai-run.ts";
|
|
22
|
+
import { dbApprovalBroker, type DbApprovalOutcome } from "./db-approval-broker.ts";
|
|
23
|
+
import {
|
|
24
|
+
DB_EXECUTE_RESULT_ROWS, DB_EXECUTE_STATEMENT_TIMEOUT_MS, DB_QUERY_DEFAULT_ROWS, DB_QUERY_MAX_ROWS, DB_QUERY_TIMEOUT_MS,
|
|
25
|
+
OPEN_QUERY_WAIT_MS, dbChangeHint, dbToolDefinitions,
|
|
26
|
+
} from "./db-ai-tools-tool.ts";
|
|
27
|
+
import { dbToolsMcpTokens, type DbToolsTokenBinding } from "./db-ai-tools-tokens.ts";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* `/api/db-tools-mcp` — serves `db_query`, `open_query` and `db_execute` to one chat session's
|
|
31
|
+
* own agent (the MCP plumbing is `mcp-http-endpoint.ts`). Its token reaches the connections the
|
|
32
|
+
* AI chat may use (`db-ai-connections.ts`) and nothing else: reads run inside a read-only
|
|
33
|
+
* transaction, and a write runs only once the user approved it in that session's chat, with
|
|
34
|
+
* PPM's password, exactly as shown. Every statement is in the query audit log as `source: ai`.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
type Approve = (sessionId: string, input: Omit<DbExecuteApprovalInput, "passwordRequired">, signal: AbortSignal) => Promise<DbApprovalOutcome>;
|
|
38
|
+
|
|
39
|
+
const isObj = (v: unknown): v is Json => !!v && typeof v === "object" && !Array.isArray(v);
|
|
40
|
+
const errorText = (e: unknown): string => (e instanceof Error ? e.message : String(e));
|
|
41
|
+
|
|
42
|
+
/** The connection's own query timeout (Advanced tab) when it is shorter than the tool's, else the tool's. */
|
|
43
|
+
function timeoutFor(config: object, toolMs: number): number {
|
|
44
|
+
const seconds = (config as { queryTimeoutSec?: unknown }).queryTimeoutSec;
|
|
45
|
+
return typeof seconds === "number" && Number.isFinite(seconds) && seconds > 0 ? Math.min(seconds * 1000, toolMs) : toolMs;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function operationOf(sql: string, dialect: DialectName): QueryOperation {
|
|
49
|
+
const statements = splitSqlScript(sql, dialect);
|
|
50
|
+
return statements.length > 1 ? "script" : detectOperation(sqlCode(statements[0]?.sql ?? sql, dialect).trim());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createDbToolsMcpHandler(deps: {
|
|
54
|
+
resolveToken: (token: string | null) => DbToolsTokenBinding | null;
|
|
55
|
+
openTab: (sessionId: string, req: TabOpenAsk, waitMs: number) => Promise<TabOpenOutcome>;
|
|
56
|
+
approve: Approve;
|
|
57
|
+
/** Whether the user has this tool on (Settings → Tools). */
|
|
58
|
+
enabled: (tool: string) => boolean;
|
|
59
|
+
openSession?: (conn: ConnectionRow, config: Awaited<ReturnType<typeof aiTargetConfig>>) => Promise<DbQuerySession>;
|
|
60
|
+
}) {
|
|
61
|
+
const openSession = deps.openSession ?? ((conn, config) => getAdapter(conn.type).openQuerySession(config));
|
|
62
|
+
|
|
63
|
+
function audit(conn: ConnectionRow, fields: Omit<QueryLogInput, "connectionId" | "connectionName" | "dbType" | "source" | "actor" | "callerIp" | "callerUa">): void {
|
|
64
|
+
try {
|
|
65
|
+
insertQueryLog({
|
|
66
|
+
connectionId: conn.id, connectionName: conn.name, dbType: conn.type, source: "ai", actor: "agent",
|
|
67
|
+
callerIp: null, callerUa: "ppm-db-tools", ...fields,
|
|
68
|
+
});
|
|
69
|
+
} catch (e) {
|
|
70
|
+
console.error("[query-audit] failed to log an AI tool's query:", errorText(e));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function dbQuery(conn: ConnectionRow, database: string | undefined, sql: string, args: Json): Promise<Json> {
|
|
75
|
+
const dialect = dialectNameOf(conn.type);
|
|
76
|
+
let maxRows = DB_QUERY_DEFAULT_ROWS;
|
|
77
|
+
if (args.max_rows !== undefined && args.max_rows !== null) {
|
|
78
|
+
if (typeof args.max_rows !== "number" || !Number.isInteger(args.max_rows) || args.max_rows < 1 || args.max_rows > DB_QUERY_MAX_ROWS) {
|
|
79
|
+
return textResult(`\`max_rows\` must be a whole number from 1 to ${DB_QUERY_MAX_ROWS}.`, true);
|
|
80
|
+
}
|
|
81
|
+
maxRows = args.max_rows;
|
|
82
|
+
}
|
|
83
|
+
const startedAt = Date.now();
|
|
84
|
+
const base = { operation: operationOf(sql, dialect), sql, ...(database ? { params: { database } } : {}) };
|
|
85
|
+
if (!isReadOnlyQuery(sql, dialect)) {
|
|
86
|
+
const message = `db_query only reads, and this SQL writes (or may). ${dbChangeHint(deps.enabled)}`;
|
|
87
|
+
audit(conn, { ...base, status: "blocked", error: message, durationMs: 0 });
|
|
88
|
+
return textResult(message, true);
|
|
89
|
+
}
|
|
90
|
+
let session: DbQuerySession;
|
|
91
|
+
let timeoutMs: number;
|
|
92
|
+
try {
|
|
93
|
+
const config = await aiTargetConfig(conn, database, true);
|
|
94
|
+
timeoutMs = timeoutFor(config, DB_QUERY_TIMEOUT_MS);
|
|
95
|
+
session = await openSession(conn, config);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
audit(conn, { ...base, status: "error", error: errorText(e), durationMs: Date.now() - startedAt });
|
|
98
|
+
return textResult(`Could not open ${conn.name}: ${errorText(e)}`, true);
|
|
99
|
+
}
|
|
100
|
+
const run = await runAiQuery(session, { sql, dialect, maxRows, timeoutMs });
|
|
101
|
+
const last = run.summary.lastResult;
|
|
102
|
+
audit(conn, {
|
|
103
|
+
...base, status: run.summary.status, ...(run.summary.error !== undefined ? { error: run.summary.error } : {}),
|
|
104
|
+
...(last ? { rows: rowsToRecords(last.columns, last.rows).records } : {}),
|
|
105
|
+
rowCount: run.summary.rowCount, durationMs: Date.now() - startedAt,
|
|
106
|
+
});
|
|
107
|
+
const statements = splitSqlScript(sql, dialect).length;
|
|
108
|
+
const parts = [formatStatementResults(run.results, statements, maxRows), ...run.messages.map((m) => neutralizeFences(m))];
|
|
109
|
+
if (run.summary.status === "blocked") parts.push(`The database refused a write: db_query only reads. ${dbChangeHint(deps.enabled)}`);
|
|
110
|
+
return textResult(parts.filter(Boolean).join("\n\n"), run.summary.status !== "ok");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function openQuery(sessionId: string, conn: ConnectionRow, database: string | undefined, sql: string): Promise<Json> {
|
|
114
|
+
const outcome = await deps.openTab(sessionId, {
|
|
115
|
+
tool: OPEN_QUERY_TOOL,
|
|
116
|
+
query: {
|
|
117
|
+
connectionId: conn.id, connectionName: conn.name, dbType: conn.type, connectionColor: conn.color,
|
|
118
|
+
...(database ? { database } : {}), sql,
|
|
119
|
+
},
|
|
120
|
+
}, OPEN_QUERY_WAIT_MS);
|
|
121
|
+
const where = `${conn.name}${database ? ` (database ${database})` : ""}`;
|
|
122
|
+
if (!outcome.ok) {
|
|
123
|
+
if (outcome.reason === "no-device") return textResult(`${outcome.message} Give the user the SQL to run in a Query tab on ${where} themselves.`, true);
|
|
124
|
+
return textResult(outcome.message, true);
|
|
125
|
+
}
|
|
126
|
+
if (!outcome.result.opened) {
|
|
127
|
+
const why = outcome.result.error ? neutralizeFences(outcome.result.error.replace(/[\u0000-\u001f\u007f]/g, " ")) : "it gave no reason";
|
|
128
|
+
return textResult(`The user's device could not open the Query tab: ${why}`, true);
|
|
129
|
+
}
|
|
130
|
+
return textResult(`Opened a Query tab on ${where} on the user's device, holding the SQL. Nothing ran: the user runs it from the tab.`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function dbExecute(sessionId: string, conn: ConnectionRow, database: string | undefined, sql: string, args: Json, signal: AbortSignal): Promise<Json> {
|
|
134
|
+
const dialect = dialectNameOf(conn.type);
|
|
135
|
+
const reason = typeof args.reason === "string" ? args.reason.trim() : "";
|
|
136
|
+
if (!reason) return textResult("`reason` is required: what the change does and why, for the user to read before approving.", true);
|
|
137
|
+
if (reason.length > MAX_DB_TOOL_REASON_CHARS) return textResult(`\`reason\` is longer than ${MAX_DB_TOOL_REASON_CHARS} characters; say it in a sentence or two.`, true);
|
|
138
|
+
let expectedRows: number | undefined;
|
|
139
|
+
if (args.expected_rows !== undefined && args.expected_rows !== null) {
|
|
140
|
+
if (typeof args.expected_rows !== "number" || !Number.isInteger(args.expected_rows) || args.expected_rows < 0) {
|
|
141
|
+
return textResult("`expected_rows` must be a whole number from 0.", true);
|
|
142
|
+
}
|
|
143
|
+
expectedRows = args.expected_rows;
|
|
144
|
+
}
|
|
145
|
+
const control = transactionControlIn(sql, dialect);
|
|
146
|
+
if (control) {
|
|
147
|
+
return textResult(`Take \`${control}\` out of the script: PPM runs the whole script in one transaction it opens and ends itself.`, true);
|
|
148
|
+
}
|
|
149
|
+
// Checked before the user is asked: approving something that cannot be opened wastes their time.
|
|
150
|
+
try {
|
|
151
|
+
await aiTargetConfig(conn, database, false);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return textResult(`Could not open ${conn.name}: ${errorText(e)}`, true);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const operation = operationOf(sql, dialect);
|
|
157
|
+
const base = { operation, sql, params: { ...(database ? { database } : {}), reason, ...(expectedRows !== undefined ? { expectedRows } : {}) } };
|
|
158
|
+
const answer = await deps.approve(sessionId, {
|
|
159
|
+
connectionId: conn.id, connectionName: conn.name, dbType: conn.type, group: conn.group_name, color: conn.color,
|
|
160
|
+
readonly: !!conn.readonly, ...(database ? { database } : {}), sql, reason, ...(expectedRows !== undefined ? { expectedRows } : {}),
|
|
161
|
+
}, signal);
|
|
162
|
+
if (!answer.approved) {
|
|
163
|
+
if (answer.reason === "declined" || answer.reason === "timeout") {
|
|
164
|
+
audit(conn, { ...base, status: "blocked", error: answer.message, durationMs: 0 });
|
|
165
|
+
}
|
|
166
|
+
return textResult(answer.message, true);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const startedAt = Date.now();
|
|
170
|
+
let session: DbQuerySession;
|
|
171
|
+
let timeoutMs: number;
|
|
172
|
+
try {
|
|
173
|
+
const config = await aiTargetConfig(conn, database, false);
|
|
174
|
+
timeoutMs = timeoutFor(config, DB_EXECUTE_STATEMENT_TIMEOUT_MS);
|
|
175
|
+
session = await openSession(conn, config);
|
|
176
|
+
} catch (e) {
|
|
177
|
+
audit(conn, { ...base, params: { ...base.params, approved: true }, status: "error", error: errorText(e), durationMs: Date.now() - startedAt });
|
|
178
|
+
return textResult(`The user approved, but ${conn.name} could not be opened, so nothing ran: ${errorText(e)}`, true);
|
|
179
|
+
}
|
|
180
|
+
const report = await runApprovedScript(session, { sql, dbType: conn.type, maxRows: DB_EXECUTE_RESULT_ROWS, expectedRows, timeoutMs });
|
|
181
|
+
const statements = splitSqlScript(sql, dialect).length;
|
|
182
|
+
audit(conn, {
|
|
183
|
+
...base, params: { ...base.params, approved: true, committed: report.committed },
|
|
184
|
+
status: report.committed ? "ok" : "error", ...(report.committed ? {} : { error: report.reason }),
|
|
185
|
+
rowCount: report.rowsChanged, durationMs: Date.now() - startedAt,
|
|
186
|
+
});
|
|
187
|
+
const detail = formatStatementResults(report.results, statements, DB_EXECUTE_RESULT_ROWS);
|
|
188
|
+
if (!report.committed) {
|
|
189
|
+
const kept = report.kept > 0 ? "only part of it was kept" : report.mayHaveKept ? "part of it may have been kept" : "it was not kept";
|
|
190
|
+
return textResult(`The user approved the change, but ${kept}. ${report.reason}\n\n${detail}`.trim(), true);
|
|
191
|
+
}
|
|
192
|
+
const changed = `${report.rowsChanged} ${report.rowsChanged === 1 ? "row" : "rows"} changed in all`;
|
|
193
|
+
return textResult(`The user approved the change. It ran on ${conn.name}${database ? ` (database ${database})` : ""} in one transaction and was committed: ${changed}.\n\n${detail}`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return createMcpHttpHandler<DbToolsTokenBinding>({
|
|
197
|
+
serverName: "ppm-db",
|
|
198
|
+
tokenRequired: "A chat session token is required",
|
|
199
|
+
resolveToken: deps.resolveToken,
|
|
200
|
+
tools: () => dbToolDefinitions(describeAiConnections(), deps.enabled),
|
|
201
|
+
unavailable: (name) => (deps.enabled(name) ? null : ppmToolOffMessage(name)),
|
|
202
|
+
callTool: async ({ sessionId }, name, rawArgs, signal) => {
|
|
203
|
+
const args = isObj(rawArgs) ? rawArgs : {};
|
|
204
|
+
const found = findAiConnection(args.connection);
|
|
205
|
+
if (!found.ok) return textResult(found.error, true);
|
|
206
|
+
const conn = found.conn;
|
|
207
|
+
const target = aiDatabaseArg(conn, args.database);
|
|
208
|
+
if (!target.ok) return textResult(target.error, true);
|
|
209
|
+
const sql = typeof args.sql === "string" ? args.sql : "";
|
|
210
|
+
if (!sql.trim()) return textResult("`sql` is required.", true);
|
|
211
|
+
if (sql.length > MAX_DB_TOOL_SQL_CHARS) return textResult(`\`sql\` is longer than ${MAX_DB_TOOL_SQL_CHARS} characters; split it into smaller scripts.`, true);
|
|
212
|
+
if (splitSqlScript(sql, dialectNameOf(conn.type)).length === 0) return textResult("The SQL has no statements to run: only comments or semicolons.", true);
|
|
213
|
+
if (name === DB_QUERY_TOOL) return dbQuery(conn, target.database, sql, args);
|
|
214
|
+
if (name === OPEN_QUERY_TOOL) return openQuery(sessionId, conn, target.database, sql);
|
|
215
|
+
return dbExecute(sessionId, conn, target.database, sql, args, signal);
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export const dbToolsMcpHandler = createDbToolsMcpHandler({
|
|
221
|
+
resolveToken: (token) => dbToolsMcpTokens.resolve(token),
|
|
222
|
+
openTab: (sessionId, req, waitMs) => tabOpenBroker.request(sessionId, req, waitMs),
|
|
223
|
+
approve: (sessionId, input, signal) => dbApprovalBroker.request(sessionId, input, undefined, signal),
|
|
224
|
+
enabled: (tool) => isPpmTool(tool) && ppmToolOn(configService.get("ai"), tool),
|
|
225
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { localServerBaseUrl } from "../server-listen-address.ts";
|
|
2
|
+
import { createSessionTokenStore } from "../mcp-session-tokens.ts";
|
|
3
|
+
import type { DbToolsMcpAccess } from "./db-ai-tools-tool.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Capability tokens for the database tools' MCP endpoint, one per chat session (see
|
|
7
|
+
* `mcp-session-tokens.ts`). A token reaches the connections the AI chat may use, and its writes
|
|
8
|
+
* only through an approval shown in that one session's chat. Like the tab tools' token it names
|
|
9
|
+
* the session alone, so a warm CLI's token is the one its session's first turn mints.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export const DB_TOOLS_MCP_PATH = "/api/db-tools-mcp";
|
|
13
|
+
export const MAX_DB_TOOLS_MCP_TOKENS = 256;
|
|
14
|
+
|
|
15
|
+
export interface DbToolsTokenBinding {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createDbToolsMcpTokenStore(max = MAX_DB_TOOLS_MCP_TOKENS) {
|
|
20
|
+
return createSessionTokenStore<DbToolsTokenBinding>({ max, sameBinding: () => true });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const dbToolsMcpTokens = createDbToolsMcpTokenStore();
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* How one session's agent reaches the database tools, or null when it cannot: a process that
|
|
27
|
+
* serves no HTTP (the CLI) has no endpoint to point at, and no chat to ask for approval in.
|
|
28
|
+
*/
|
|
29
|
+
export function dbToolsMcpAccessFor(sessionId: string): DbToolsMcpAccess | null {
|
|
30
|
+
const base = localServerBaseUrl();
|
|
31
|
+
if (!base) return null;
|
|
32
|
+
return { url: `${base}${DB_TOOLS_MCP_PATH}`, token: dbToolsMcpTokens.mint({ sessionId }) };
|
|
33
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { DB_EXECUTE_TOOL, DB_QUERY_TOOL, OPEN_QUERY_TOOL } from "../../shared/db-ai-tools.ts";
|
|
2
|
+
import { DB_APPROVAL_WAIT_MS } from "./db-approval-broker.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The three tools the database MCP endpoint serves. Their descriptions end with the connections
|
|
6
|
+
* the AI may use, read when a chat's agent lists the tools, so it can name one without a call.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
DB_QUERY_TOOL, OPEN_QUERY_TOOL, DB_EXECUTE_TOOL, DB_TOOLS, CLAUDE_DB_TOOLS_MCP_SERVER, CODEX_DB_TOOLS_MCP_SERVER,
|
|
11
|
+
} from "../../shared/db-ai-tools.ts";
|
|
12
|
+
|
|
13
|
+
/** Environment variable the Codex app-server reads the bearer token from. */
|
|
14
|
+
export const CODEX_DB_TOOLS_MCP_TOKEN_ENV = "PPM_DB_TOOLS_MCP_TOKEN";
|
|
15
|
+
|
|
16
|
+
/** Rows each `db_query` result keeps unless the call asks otherwise, and at most. */
|
|
17
|
+
export const DB_QUERY_DEFAULT_ROWS = 100;
|
|
18
|
+
export const DB_QUERY_MAX_ROWS = 1_000;
|
|
19
|
+
/** Rows of a `RETURNING` result `db_execute` keeps. */
|
|
20
|
+
export const DB_EXECUTE_RESULT_ROWS = 100;
|
|
21
|
+
/** One `db_query` statement's time, when the connection sets no shorter query timeout. */
|
|
22
|
+
export const DB_QUERY_TIMEOUT_MS = 2 * 60_000;
|
|
23
|
+
/** One approved statement's time, when the connection sets no query timeout. */
|
|
24
|
+
export const DB_EXECUTE_STATEMENT_TIMEOUT_MS = 30 * 60_000;
|
|
25
|
+
/** How long `open_query` waits for a device to say the tab is open. */
|
|
26
|
+
export const OPEN_QUERY_WAIT_MS = 8_000;
|
|
27
|
+
/**
|
|
28
|
+
* The providers' own timeout for a call: it must outlast the user's time to answer an approval
|
|
29
|
+
* and the approved script's run, or the agent would give up on a change that then commits.
|
|
30
|
+
*/
|
|
31
|
+
export const DB_TOOLS_TIMEOUT_MS = DB_APPROVAL_WAIT_MS + DB_EXECUTE_STATEMENT_TIMEOUT_MS + 5 * 60_000;
|
|
32
|
+
|
|
33
|
+
/** How a provider reaches the endpoint for one session; built by `chatService` per turn. */
|
|
34
|
+
export interface DbToolsMcpAccess {
|
|
35
|
+
url: string;
|
|
36
|
+
token: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const CONNECTION = { type: "string", description: "The connection's name, as listed below." };
|
|
40
|
+
const DATABASE = {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Another database on the same server, when the connection allows it; omit for the connection's own.",
|
|
43
|
+
};
|
|
44
|
+
const SQL = { type: "string", description: "One statement or a script of several, separated by semicolons." };
|
|
45
|
+
|
|
46
|
+
/** Where `db_query` sends the AI for a change, by which of the other two tools the user has on. */
|
|
47
|
+
export function dbChangeHint(on: (tool: string) => boolean): string {
|
|
48
|
+
const execute = on(DB_EXECUTE_TOOL), open = on(OPEN_QUERY_TOOL);
|
|
49
|
+
if (execute && open) return "To change data, call db_execute; to give the user a script to run themselves, call open_query.";
|
|
50
|
+
if (execute) return "To change data, call db_execute, which asks the user to approve it.";
|
|
51
|
+
if (open) return "To change data, give the user the script with open_query; they run it themselves.";
|
|
52
|
+
return "You cannot change data: the user turned PPM's tools for that off. Give them the SQL to run themselves.";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The tools, each description ending with `connections` (see `describeAiConnections`). `on` is
|
|
57
|
+
* which tools the user has on; `db_query` names only those for a change.
|
|
58
|
+
*/
|
|
59
|
+
export function dbToolDefinitions(connections: string, on: (tool: string) => boolean) {
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
name: DB_QUERY_TOOL,
|
|
63
|
+
title: "Query a database saved in PPM",
|
|
64
|
+
description:
|
|
65
|
+
"Run read-only SQL on a database connection the user saved in PPM. PPM connects with the credentials it keeps, "
|
|
66
|
+
+ "so you never need them, and runs the SQL inside a read-only transaction: it cannot change anything. Use it, "
|
|
67
|
+
+ "rather than `ppm db query`, psql or another client, to look at data and schema (information_schema, "
|
|
68
|
+
+ `pg_catalog, sqlite_master). Each result is cut at max_rows. ${dbChangeHint(on)}\n\n${connections}`,
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: {
|
|
72
|
+
connection: CONNECTION,
|
|
73
|
+
sql: SQL,
|
|
74
|
+
database: DATABASE,
|
|
75
|
+
max_rows: { type: "integer", minimum: 1, maximum: DB_QUERY_MAX_ROWS, description: `Rows each result keeps (default ${DB_QUERY_DEFAULT_ROWS}).` },
|
|
76
|
+
},
|
|
77
|
+
required: ["connection", "sql"],
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
},
|
|
80
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: OPEN_QUERY_TOOL,
|
|
84
|
+
title: "Open a Query tab in PPM",
|
|
85
|
+
description:
|
|
86
|
+
"Open a PPM Query tab on the user's device, on a database connection saved in PPM, holding SQL you wrote. "
|
|
87
|
+
+ "Nothing runs: the user reads the script and presses Run themselves. Use it when the user wants to run or "
|
|
88
|
+
+ "review a script on their side. The tab opens beside the chat. On a readonly connection the user can still "
|
|
89
|
+
+ "run a change, with \"Run with write access (once)\" and PPM's password."
|
|
90
|
+
+ `\n\n${connections}`,
|
|
91
|
+
inputSchema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: { connection: CONNECTION, sql: SQL, database: DATABASE },
|
|
94
|
+
required: ["connection", "sql"],
|
|
95
|
+
additionalProperties: false,
|
|
96
|
+
},
|
|
97
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: DB_EXECUTE_TOOL,
|
|
101
|
+
title: "Change a database, once the user approves",
|
|
102
|
+
description:
|
|
103
|
+
"Run SQL that changes data or schema on a database connection saved in PPM, after the user approves it. PPM "
|
|
104
|
+
+ "shows the user the connection, your reason and the exact SQL, and runs it only after they type PPM's "
|
|
105
|
+
+ `password; nothing runs if they decline or do not answer within ${Math.round(DB_APPROVAL_WAIT_MS / 60_000)} minutes. `
|
|
106
|
+
+ "An approval covers exactly this SQL, once: a changed script needs a new approval. The script runs in one "
|
|
107
|
+
+ "transaction PPM opens and ends, so do not put BEGIN, COMMIT or ROLLBACK in it; if a statement fails, or the "
|
|
108
|
+
+ "rows changed in all are not expected_rows, everything is rolled back. On MySQL and MariaDB, a CREATE, "
|
|
109
|
+
+ "ALTER, DROP or TRUNCATE commits by itself, with everything before it, so only what follows the last one "
|
|
110
|
+
+ "can be rolled back. Look at what the change will touch with db_query first, and pass "
|
|
111
|
+
+ "expected_rows whenever you know it. Readonly connections can be changed this way too: the approval is what "
|
|
112
|
+
+ `lifts it, for this one script.\n\n${connections}`,
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: "object",
|
|
115
|
+
properties: {
|
|
116
|
+
connection: CONNECTION,
|
|
117
|
+
sql: SQL,
|
|
118
|
+
reason: { type: "string", description: "What the change does and why, in a sentence or two the user reads before approving." },
|
|
119
|
+
database: DATABASE,
|
|
120
|
+
expected_rows: {
|
|
121
|
+
type: "integer", minimum: 0,
|
|
122
|
+
description: "Rows the script should insert, update or delete in all; any other count rolls it back.",
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
required: ["connection", "sql", "reason"],
|
|
126
|
+
additionalProperties: false,
|
|
127
|
+
},
|
|
128
|
+
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
}
|