@nogataka/smart-edit 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +520 -82
- package/dist/smart-edit/agent.js +2 -1
- package/dist/smart-edit/cli.js +79 -2
- package/dist/smart-edit/dashboard.js +29 -0
- package/dist/smart-edit/instance-registry.d.ts +43 -0
- package/dist/smart-edit/instance-registry.js +269 -0
- package/dist/smart-edit/resources/config/modes/careful-editor.yml +47 -0
- package/dist/smart-edit/resources/dashboard/dashboard.js +11 -11
- package/dist/smart-edit/resources/dashboard/favicon.ico +0 -0
- package/dist/smart-edit/resources/dashboard/index.css +1 -1
- package/dist/smart-edit/resources/dashboard/index.html +2 -0
- package/dist/smart-edit/resources/dashboard/logo.png +0 -0
- package/dist/smart-edit/standalone-dashboard.d.ts +32 -0
- package/dist/smart-edit/standalone-dashboard.js +223 -0
- package/dist/smart-edit/tools/workflow_tools.d.ts +5 -1
- package/dist/smart-edit/tools/workflow_tools.js +76 -3
- package/dist/smart-edit/util/git.d.ts +30 -0
- package/dist/smart-edit/util/git.js +118 -0
- package/package.json +1 -1
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--bg-primary: #f2f2f2;--bg-secondary: #ffffff;--text-primary: #1a1a1a;--text-secondary: #3d3d3d;--text-muted: #777;--border-color: #cfcfcf;--btn-primary: #2b2b2b;--btn-hover: #1e1e1e;--btn-disabled: #9c9c9c;--btn-text: #f5f5f5;--shadow: 0 2px 4px rgba(0, 0, 0, .12);--tool-highlight: #e5e5e5;--tool-highlight-text: #1a1a1a;--log-debug: #888;--log-info: #1a1a1a;--log-warning: #454545;--log-error: #111111;--stats-header: #ebebeb;--sidebar-width: 240px;--sidebar-width-collapsed: 64px;--topbar-height: 56px;--content-padding: 24px;--card-bg: var(--bg-secondary);--card-border-radius: 12px;--card-shadow: 0 2px 8px rgba(0, 0, 0, .08);--card-shadow-hover: 0 4px 16px rgba(0, 0, 0, .12);--card-padding: 20px;--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 16px;--spacing-lg: 24px;--spacing-xl: 32px;--font-size-xs: 11px;--font-size-sm: 13px;--font-size-base: 14px;--font-size-lg: 16px;--font-size-xl: 20px;--font-size-2xl: 24px;--status-success: #22c55e;--status-warning: #f59e0b;--status-error: #ef4444;--status-info: #3b82f6;--input-bg: var(--bg-primary);--input-border: var(--border-color);--input-focus-border: #3b82f6;--input-focus-ring: rgba(59, 130, 246, .3);--nav-item-hover: rgba(0, 0, 0, .04);--nav-item-active: rgba(59, 130, 246, .1);--nav-item-active-border: #3b82f6;--transition-fast: .15s ease;--transition-normal: .2s ease;--transition-slow: .3s ease}[data-theme=dark]{--bg-primary: #121212;--bg-secondary: #1e1e1e;--text-primary: #f1f1f1;--text-secondary: #d0d0d0;--text-muted: #9a9a9a;--border-color: #2c2c2c;--btn-primary: #ededed;--btn-hover: #d6d6d6;--btn-disabled: #4a4a4a;--btn-text: #111111;--shadow: 0 2px 4px rgba(0, 0, 0, .4);--tool-highlight: #2a2a2a;--tool-highlight-text: #f1f1f1;--log-debug: #a0a0a0;--log-info: #f1f1f1;--log-warning: #c7c7c7;--log-error: #ffffff;--stats-header: #262626;--card-bg: var(--bg-secondary);--card-shadow: 0 2px 8px rgba(0, 0, 0, .3);--card-shadow-hover: 0 4px 16px rgba(0, 0, 0, .4);--input-bg: #1a1a1a;--nav-item-hover: rgba(255, 255, 255, .04);--nav-item-active: rgba(59, 130, 246, .15)}*{box-sizing:border-box}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,Helvetica,Arial,"Apple Color Emoji","Segoe UI Emoji";margin:0;padding:0;background-color:var(--bg-primary);color:var(--text-primary);transition:background-color .3s ease,color .3s ease;overflow:hidden;height:100vh}#root{height:100%}.header{text-align:center;margin-bottom:20px;font-size:1.5rem;font-weight:700}.log-container{background-color:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;height:100%;min-height:400px;overflow-y:auto;overflow-x:auto;padding:var(--spacing-md);white-space:pre-wrap;font-size:12px;line-height:1.5;color:var(--text-primary);font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;transition:background-color .3s ease,border-color .3s ease,color .3s ease}.log-card{height:calc(100vh - var(--topbar-height) - var(--content-padding) * 2 - var(--spacing-md))}.controls{display:flex;align-items:center;gap:var(--spacing-sm);flex-wrap:wrap}.btn{background-color:var(--btn-primary);color:var(--btn-text);border:none;padding:8px 16px;border-radius:4px;cursor:pointer;font-size:14px;transition:background-color .3s ease}.btn:hover{background-color:var(--btn-hover)}.btn:disabled{background-color:var(--btn-disabled);color:var(--text-muted);cursor:not-allowed}.theme-toggle{display:flex;align-items:center;gap:5px;background-color:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;padding:6px 12px;cursor:pointer;transition:background-color .3s ease,border-color .3s ease}.theme-toggle:hover{background-color:var(--border-color)}.theme-toggle .icon{font-size:16px}.log-debug{color:var(--log-debug)}.log-info{color:var(--log-info)}.log-warning{color:var(--log-warning);font-weight:600}.log-error{color:var(--log-error);font-weight:700}.log-default{color:var(--log-info)}.tool-name{background-color:var(--tool-highlight);color:var(--tool-highlight-text);font-weight:700;padding:0 2px;border-radius:2px}.loading{text-align:center;color:var(--text-muted);font-style:italic}.error-message{color:var(--log-error);text-align:center;margin:10px 0}.charts-container{display:flex;flex-wrap:wrap;gap:15px;justify-content:space-between;max-width:1400px;margin:0 auto}.chart-group{flex:1;min-width:280px;max-width:320px;text-align:center}.chart-wide{flex:0 0 100%;min-width:100%;margin-top:10px}.chart-group h3{margin:0 0 10px;color:var(--text-secondary)}.stats-summary{margin:0 auto;border-collapse:collapse;background:var(--bg-secondary);border-radius:5px;overflow:hidden;box-shadow:var(--shadow);transition:background-color .3s ease,box-shadow .3s ease}.stats-summary th,.stats-summary td{padding:10px 20px;text-align:left;border-bottom:1px solid var(--border-color);color:var(--text-primary);transition:border-color .3s ease,color .3s ease}.stats-summary th{background-color:var(--stats-header);font-weight:700;transition:background-color .3s ease}.stats-summary tr:last-child td{border-bottom:none}@media(max-width:768px){.charts-container{flex-direction:column}.chart-group,.chart-wide{min-width:auto;max-width:none}.controls{flex-direction:column;gap:5px}}.main-layout{display:flex;height:100vh;overflow:hidden}.sidebar{width:var(--sidebar-width);height:100%;background-color:var(--bg-secondary);border-right:1px solid var(--border-color);display:flex;flex-direction:column;transition:width var(--transition-normal);flex-shrink:0;overflow:hidden}.sidebar.collapsed{width:var(--sidebar-width-collapsed)}.sidebar-header{height:var(--topbar-height);display:flex;align-items:center;justify-content:space-between;padding:0 var(--spacing-md);border-bottom:1px solid var(--border-color);flex-shrink:0}.sidebar-logo{display:flex;align-items:center;gap:var(--spacing-sm);font-weight:600;font-size:var(--font-size-lg);color:var(--text-primary);white-space:nowrap;overflow:hidden}.sidebar-logo-icon{width:28px;height:28px;flex-shrink:0}.sidebar.collapsed .sidebar-logo-text{display:none}.sidebar-toggle{background:none;border:none;cursor:pointer;padding:var(--spacing-xs);border-radius:4px;color:var(--text-secondary);display:flex;align-items:center;justify-content:center;transition:background-color var(--transition-fast)}.sidebar-toggle:hover{background-color:var(--nav-item-hover)}.sidebar-nav{flex:1;padding:var(--spacing-md) var(--spacing-sm);overflow-y:auto}.nav-item{display:flex;align-items:center;gap:var(--spacing-md);padding:var(--spacing-sm) var(--spacing-md);border-radius:8px;cursor:pointer;color:var(--text-secondary);transition:all var(--transition-fast);margin-bottom:var(--spacing-xs);border:none;background:none;width:100%;text-align:left;font-size:var(--font-size-base)}.nav-item:hover{background-color:var(--nav-item-hover);color:var(--text-primary)}.nav-item.active{background-color:var(--nav-item-active);color:var(--nav-item-active-border);font-weight:500}.nav-item-icon{width:20px;height:20px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.nav-item-label{white-space:nowrap;overflow:hidden}.sidebar.collapsed .nav-item-label{display:none}.sidebar.collapsed .nav-item{justify-content:center;padding:var(--spacing-sm)}.sidebar-footer{padding:var(--spacing-md) var(--spacing-sm);border-top:1px solid var(--border-color)}.shutdown-btn{color:var(--status-error)!important}.shutdown-btn:hover{background-color:#ef44441a!important;color:var(--status-error)!important}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}.topbar{height:var(--topbar-height);background-color:var(--bg-secondary);border-bottom:1px solid var(--border-color);display:flex;align-items:center;justify-content:space-between;padding:0 var(--content-padding);flex-shrink:0}.topbar-left{display:flex;align-items:center;gap:var(--spacing-md)}.topbar-title{font-size:var(--font-size-lg);font-weight:600;color:var(--text-primary)}.topbar-subtitle{font-size:var(--font-size-sm);color:var(--text-muted)}.topbar-right{display:flex;align-items:center;gap:var(--spacing-md)}.connection-indicator{display:flex;align-items:center;gap:var(--spacing-xs);font-size:var(--font-size-sm);color:var(--text-muted)}.connection-dot{width:8px;height:8px;border-radius:50%;background-color:var(--status-error)}.connection-dot.streaming{background-color:var(--status-success);animation:pulse 2s infinite}.connection-dot.polling{background-color:var(--status-warning)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.content-area{flex:1;overflow-y:auto;padding:var(--content-padding);background-color:var(--bg-primary)}.card{background-color:var(--card-bg);border-radius:var(--card-border-radius);box-shadow:var(--card-shadow);padding:var(--card-padding);transition:box-shadow var(--transition-fast)}.card:hover{box-shadow:var(--card-shadow-hover)}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-md)}.card-title{font-size:var(--font-size-lg);font-weight:600;color:var(--text-primary);margin:0}.card-subtitle{font-size:var(--font-size-sm);color:var(--text-muted);margin:var(--spacing-xs) 0 0 0}.card-actions{display:flex;gap:var(--spacing-sm)}.card-body{color:var(--text-primary)}@media(max-width:768px){.sidebar{position:fixed;left:0;top:0;z-index:100;transform:translate(-100%);transition:transform var(--transition-normal)}.sidebar.open{transform:translate(0)}.sidebar-backdrop{position:fixed;inset:0;background-color:#00000080;z-index:99;opacity:0;visibility:hidden;transition:opacity var(--transition-normal)}.sidebar-backdrop.visible{opacity:1;visibility:visible}.topbar{padding:0 var(--spacing-md)}.content-area{padding:var(--spacing-md)}.mobile-menu-btn{display:flex;background:none;border:none;cursor:pointer;padding:var(--spacing-xs);color:var(--text-primary)}}@media(min-width:769px){.mobile-menu-btn,.sidebar-backdrop{display:none}}.log-panel{display:flex;flex-direction:column;gap:var(--spacing-md);height:100%}.log-panel-header{display:flex;flex-direction:column;gap:var(--spacing-md);margin-bottom:var(--spacing-md)}.log-panel-controls{display:flex;align-items:center;gap:var(--spacing-sm)}.log-panel-content{flex:1;min-height:0}@media(max-width:768px){.log-panel-header{gap:var(--spacing-sm)}}.stats-panel{display:flex;flex-direction:column;gap:var(--spacing-lg)}.stats-panel-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--spacing-md)}.stats-panel-actions{display:flex;gap:var(--spacing-sm)}.stats-estimator{font-size:var(--font-size-sm);color:var(--text-muted)}.stats-empty{text-align:center;padding:var(--spacing-xl);color:var(--text-muted)}.stats-empty p{margin:0}.stats-empty-hint{font-size:var(--font-size-sm);margin-top:var(--spacing-sm)!important}.metrics-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--spacing-md)}.metric-card{background-color:var(--card-bg);border-radius:var(--card-border-radius);box-shadow:var(--card-shadow);padding:var(--card-padding);transition:box-shadow var(--transition-fast)}.metric-card:hover{box-shadow:var(--card-shadow-hover)}.metric-card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-sm)}.metric-card-title{font-size:var(--font-size-sm);color:var(--text-muted);font-weight:500}.metric-card-icon{color:var(--text-muted)}.metric-card-value{font-size:var(--font-size-2xl);font-weight:700;color:var(--text-primary);line-height:1.2}.metric-card-footer{display:flex;align-items:center;justify-content:space-between;margin-top:var(--spacing-sm)}.metric-card-subtitle{font-size:var(--font-size-xs);color:var(--text-muted)}.metric-card-trend{font-size:var(--font-size-xs);font-weight:600;padding:2px 6px;border-radius:4px}.metric-card-trend.up{color:var(--status-success);background-color:#22c55e1a}.metric-card-trend.down{color:var(--status-error);background-color:#ef44441a}.metric-card-trend.neutral{color:var(--text-muted);background-color:var(--nav-item-hover)}.live-counter{font-variant-numeric:tabular-nums}.stats-charts-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(400px,1fr));gap:var(--spacing-lg)}.stats-charts-row{width:100%}.pie-charts-row{display:flex;gap:var(--spacing-lg);justify-content:center;flex-wrap:wrap}.pie-chart-item{flex:1;min-width:250px;max-width:350px}.chart-container{position:relative;width:100%}.chart-empty{display:flex;align-items:center;justify-content:center;height:200px;color:var(--text-muted);font-style:italic}@media(max-width:768px){.metrics-grid{grid-template-columns:repeat(2,1fr)}.stats-charts-grid{grid-template-columns:1fr}.pie-charts-row{flex-direction:column;align-items:center}.pie-chart-item{max-width:none;width:100%}}.session-panel{display:flex;flex-direction:column;gap:var(--spacing-lg)}.session-panel-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:var(--spacing-lg);flex-wrap:wrap;gap:var(--spacing-md)}.session-panel-title{font-size:var(--font-size-lg);font-weight:600;color:var(--text-primary);margin:0}.session-panel-subtitle{font-size:var(--font-size-sm);color:var(--text-muted);margin:var(--spacing-xs) 0 0 0}.session-panel-actions{display:flex;gap:var(--spacing-sm)}.session-list{display:flex;flex-direction:column;gap:var(--spacing-md)}.session-list-empty{text-align:center;padding:var(--spacing-xl);color:var(--text-muted)}.session-list-empty p{margin:0}.session-list-empty-hint{font-size:var(--font-size-sm);margin-top:var(--spacing-sm)!important}.session-item{background-color:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;padding:var(--spacing-md);transition:border-color var(--transition-fast)}.session-item:hover{border-color:var(--text-muted)}.session-item-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:var(--spacing-sm)}.session-item-info{display:flex;flex-direction:column;gap:2px}.session-item-date{font-size:var(--font-size-base);font-weight:600;color:var(--text-primary)}.session-item-time{font-size:var(--font-size-sm);color:var(--text-muted)}.session-item-duration{font-size:var(--font-size-sm);color:var(--text-secondary);background-color:var(--nav-item-hover);padding:2px 8px;border-radius:4px}.session-item-project{font-size:var(--font-size-sm);color:var(--text-secondary);margin-bottom:var(--spacing-sm)}.session-item-stats{display:flex;gap:var(--spacing-lg);margin-bottom:var(--spacing-sm)}.session-stat{display:flex;flex-direction:column;gap:2px}.session-stat-label{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.session-stat-value{font-size:var(--font-size-base);font-weight:600;color:var(--text-primary);font-variant-numeric:tabular-nums}.session-item-actions{display:flex;gap:var(--spacing-sm);justify-content:flex-end}.session-action-btn{display:flex;align-items:center;gap:4px;padding:6px 12px;font-size:var(--font-size-sm);color:var(--text-secondary);background:none;border:1px solid var(--border-color);border-radius:4px;cursor:pointer;transition:all var(--transition-fast)}.session-action-btn:hover{color:var(--text-primary);border-color:var(--text-muted);background-color:var(--nav-item-hover)}.btn-danger{background-color:transparent;color:var(--status-error);border:1px solid var(--status-error)}.btn-danger:hover{background-color:var(--status-error);color:#fff}.export-btn{display:flex;align-items:center}@media(max-width:768px){.session-panel-header{flex-direction:column;align-items:stretch}.session-panel-actions{justify-content:flex-end}.session-item-stats{flex-wrap:wrap;gap:var(--spacing-md)}}.dashboard-overview{display:flex;flex-direction:column;gap:var(--spacing-lg)}.welcome-section{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--spacing-md)}.welcome-content{flex:1}.welcome-title{font-size:var(--font-size-xl);font-weight:600;color:var(--text-primary);margin:0 0 var(--spacing-xs) 0}.welcome-description{font-size:var(--font-size-base);color:var(--text-secondary);margin:0}.connection-badge{flex-shrink:0}.connection-status{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:20px;font-size:var(--font-size-sm);font-weight:500}.connection-status:before{content:"";width:8px;height:8px;border-radius:50%}.connection-status.streaming{background-color:#22c55e1a;color:var(--status-success)}.connection-status.streaming:before{background-color:var(--status-success);animation:pulse 2s infinite}.connection-status.polling{background-color:#f59e0b1a;color:var(--status-warning)}.connection-status.polling:before{background-color:var(--status-warning)}.connection-status.disconnected{background-color:#ef44441a;color:var(--status-error)}.connection-status.disconnected:before{background-color:var(--status-error)}.quick-nav-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:var(--spacing-md)}.quick-nav-card{display:flex;align-items:center;gap:var(--spacing-md);padding:var(--spacing-md);background-color:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;cursor:pointer;transition:all var(--transition-fast);text-align:left;width:100%}.quick-nav-card:hover{border-color:var(--input-focus-border);background-color:var(--nav-item-active)}.quick-nav-icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;background-color:var(--nav-item-active);color:var(--input-focus-border);flex-shrink:0}.quick-nav-content{flex:1;min-width:0}.quick-nav-title{font-size:var(--font-size-base);font-weight:600;color:var(--text-primary);margin:0}.quick-nav-description{font-size:var(--font-size-sm);color:var(--text-muted);margin:4px 0 0}.quick-nav-arrow{color:var(--text-muted);flex-shrink:0;transition:transform var(--transition-fast)}.quick-nav-card:hover .quick-nav-arrow{transform:translate(4px);color:var(--input-focus-border)}@media(max-width:768px){.welcome-section{flex-direction:column}.quick-nav-grid{grid-template-columns:1fr}}.search-input-wrapper{position:relative;display:flex;align-items:center}.search-input-icon{position:absolute;left:12px;color:var(--text-muted);pointer-events:none;display:flex;align-items:center}.search-input{width:100%;padding:8px 36px;border:1px solid var(--input-border);border-radius:6px;background-color:var(--input-bg);color:var(--text-primary);font-size:var(--font-size-sm);transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.search-input:focus{outline:none;border-color:var(--input-focus-border);box-shadow:0 0 0 3px var(--input-focus-ring)}.search-input::placeholder{color:var(--text-muted)}.search-input-clear{position:absolute;right:8px;display:flex;align-items:center;justify-content:center;padding:4px;border:none;background:none;color:var(--text-muted);cursor:pointer;border-radius:4px;transition:color var(--transition-fast),background-color var(--transition-fast)}.search-input-clear:hover{color:var(--text-primary);background-color:var(--nav-item-hover)}.dropdown{position:relative;display:inline-block;min-width:140px}.dropdown-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:8px 12px;border:1px solid var(--input-border);border-radius:6px;background-color:var(--input-bg);color:var(--text-primary);font-size:var(--font-size-sm);cursor:pointer;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.dropdown-trigger:hover{border-color:var(--text-muted)}.dropdown-trigger:focus{outline:none;border-color:var(--input-focus-border);box-shadow:0 0 0 3px var(--input-focus-ring)}.dropdown-text{flex:1;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-arrow{display:flex;align-items:center;margin-left:8px;color:var(--text-muted);transition:transform var(--transition-fast)}.dropdown-arrow.open{transform:rotate(180deg)}.dropdown-menu{position:absolute;top:100%;left:0;right:0;margin-top:4px;padding:4px;border:1px solid var(--border-color);border-radius:6px;background-color:var(--bg-secondary);box-shadow:var(--card-shadow);z-index:100;max-height:240px;overflow-y:auto}.dropdown-clear{display:block;width:100%;padding:6px 8px;border:none;background:none;color:var(--status-info);font-size:var(--font-size-xs);text-align:left;cursor:pointer;border-bottom:1px solid var(--border-color);margin-bottom:4px}.dropdown-clear:hover{text-decoration:underline}.dropdown-options{display:flex;flex-direction:column;gap:2px}.dropdown-option{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:4px;cursor:pointer;transition:background-color var(--transition-fast)}.dropdown-option:hover{background-color:var(--nav-item-hover)}.dropdown-option input[type=checkbox],.dropdown-option input[type=radio]{margin:0;accent-color:var(--input-focus-border)}.dropdown-option-label{font-size:var(--font-size-sm);color:var(--text-primary)}.log-filter-bar{display:flex;align-items:center;gap:var(--spacing-md);flex-wrap:wrap}.log-filter-search{flex:1;min-width:200px;max-width:300px}.log-filter-dropdowns{display:flex;align-items:center;gap:var(--spacing-sm)}.log-filter-clear{padding:8px 12px;font-size:var(--font-size-sm)}.icon-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid var(--input-border);border-radius:6px;background-color:var(--input-bg);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.icon-btn:hover{border-color:var(--text-muted);color:var(--text-primary);background-color:var(--nav-item-hover)}.icon-btn:disabled{opacity:.5;cursor:not-allowed}.reload-btn.spinning svg{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.filter-stats{display:flex;align-items:center;gap:var(--spacing-sm);font-size:var(--font-size-sm);color:var(--text-muted)}.filter-stats-count{font-weight:600;color:var(--text-primary)}@media(max-width:768px){.log-filter-bar{flex-direction:column;align-items:stretch}.log-filter-search{max-width:none}.log-filter-dropdowns{flex-wrap:wrap}.dropdown{flex:1;min-width:120px}}
|
|
1
|
+
:root{--bg-primary: #f2f2f2;--bg-secondary: #ffffff;--text-primary: #1a1a1a;--text-secondary: #3d3d3d;--text-muted: #777;--border-color: #cfcfcf;--btn-primary: #2b2b2b;--btn-hover: #1e1e1e;--btn-disabled: #9c9c9c;--btn-text: #f5f5f5;--shadow: 0 2px 4px rgba(0, 0, 0, .12);--tool-highlight: #e5e5e5;--tool-highlight-text: #1a1a1a;--log-debug: #888;--log-info: #1a1a1a;--log-warning: #454545;--log-error: #111111;--stats-header: #ebebeb;--sidebar-width: 240px;--sidebar-width-collapsed: 64px;--topbar-height: 56px;--content-padding: 24px;--card-bg: var(--bg-secondary);--card-border-radius: 12px;--card-shadow: 0 2px 8px rgba(0, 0, 0, .08);--card-shadow-hover: 0 4px 16px rgba(0, 0, 0, .12);--card-padding: 20px;--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 16px;--spacing-lg: 24px;--spacing-xl: 32px;--font-size-xs: 11px;--font-size-sm: 13px;--font-size-base: 14px;--font-size-lg: 16px;--font-size-xl: 20px;--font-size-2xl: 24px;--status-success: #22c55e;--status-warning: #f59e0b;--status-error: #ef4444;--status-info: #3b82f6;--input-bg: var(--bg-primary);--input-border: var(--border-color);--input-focus-border: #3b82f6;--input-focus-ring: rgba(59, 130, 246, .3);--nav-item-hover: rgba(0, 0, 0, .04);--nav-item-active: rgba(59, 130, 246, .1);--nav-item-active-border: #3b82f6;--transition-fast: .15s ease;--transition-normal: .2s ease;--transition-slow: .3s ease}[data-theme=dark]{--bg-primary: #121212;--bg-secondary: #1e1e1e;--text-primary: #f1f1f1;--text-secondary: #d0d0d0;--text-muted: #9a9a9a;--border-color: #2c2c2c;--btn-primary: #ededed;--btn-hover: #d6d6d6;--btn-disabled: #4a4a4a;--btn-text: #111111;--shadow: 0 2px 4px rgba(0, 0, 0, .4);--tool-highlight: #2a2a2a;--tool-highlight-text: #f1f1f1;--log-debug: #a0a0a0;--log-info: #f1f1f1;--log-warning: #c7c7c7;--log-error: #ffffff;--stats-header: #262626;--card-bg: var(--bg-secondary);--card-shadow: 0 2px 8px rgba(0, 0, 0, .3);--card-shadow-hover: 0 4px 16px rgba(0, 0, 0, .4);--input-bg: #1a1a1a;--nav-item-hover: rgba(255, 255, 255, .04);--nav-item-active: rgba(59, 130, 246, .15)}*{box-sizing:border-box}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,Helvetica,Arial,"Apple Color Emoji","Segoe UI Emoji";margin:0;padding:0;background-color:var(--bg-primary);color:var(--text-primary);transition:background-color .3s ease,color .3s ease;overflow:hidden;height:100vh}#root{height:100%}.header{text-align:center;margin-bottom:20px;font-size:1.5rem;font-weight:700}.log-container{background-color:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;height:100%;min-height:400px;overflow-y:auto;overflow-x:auto;padding:var(--spacing-md);white-space:pre-wrap;font-size:12px;line-height:1.5;color:var(--text-primary);font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;transition:background-color .3s ease,border-color .3s ease,color .3s ease}.log-card{height:calc(100vh - var(--topbar-height) - var(--content-padding) * 2 - var(--spacing-md))}.controls{display:flex;align-items:center;gap:var(--spacing-sm);flex-wrap:wrap}.btn{background-color:var(--btn-primary);color:var(--btn-text);border:none;padding:8px 16px;border-radius:4px;cursor:pointer;font-size:14px;transition:background-color .3s ease}.btn:hover{background-color:var(--btn-hover)}.btn:disabled{background-color:var(--btn-disabled);color:var(--text-muted);cursor:not-allowed}.theme-toggle{display:flex;align-items:center;justify-content:center;background-color:var(--bg-secondary);border:1px solid var(--border-color);border-radius:50%;width:36px;height:36px;padding:0;cursor:pointer;transition:background-color .3s ease,border-color .3s ease}.theme-toggle:hover{background-color:var(--border-color)}.theme-toggle .icon{font-size:18px;line-height:1}.language-toggle{display:flex;align-items:center;gap:4px;background-color:var(--bg-secondary);border:1px solid var(--border-color);border-radius:18px;padding:6px 10px;cursor:pointer;transition:background-color .3s ease,border-color .3s ease}.language-toggle:hover{background-color:var(--border-color)}.language-toggle .icon{display:flex;align-items:center;color:var(--text-primary)}.language-toggle .language-code{font-size:12px;font-weight:600;color:var(--text-primary)}.log-debug{color:var(--log-debug)}.log-info{color:var(--log-info)}.log-warning{color:var(--log-warning);font-weight:600}.log-error{color:var(--log-error);font-weight:700}.log-default{color:var(--log-info)}.tool-name{background-color:var(--tool-highlight);color:var(--tool-highlight-text);font-weight:700;padding:0 2px;border-radius:2px}.loading{text-align:center;color:var(--text-muted);font-style:italic}.error-message{color:var(--log-error);text-align:center;margin:10px 0}.charts-container{display:flex;flex-wrap:wrap;gap:15px;justify-content:space-between;max-width:1400px;margin:0 auto}.chart-group{flex:1;min-width:280px;max-width:320px;text-align:center}.chart-wide{flex:0 0 100%;min-width:100%;margin-top:10px}.chart-group h3{margin:0 0 10px;color:var(--text-secondary)}.stats-summary{margin:0 auto;border-collapse:collapse;background:var(--bg-secondary);border-radius:5px;overflow:hidden;box-shadow:var(--shadow);transition:background-color .3s ease,box-shadow .3s ease}.stats-summary th,.stats-summary td{padding:10px 20px;text-align:left;border-bottom:1px solid var(--border-color);color:var(--text-primary);transition:border-color .3s ease,color .3s ease}.stats-summary th{background-color:var(--stats-header);font-weight:700;transition:background-color .3s ease}.stats-summary tr:last-child td{border-bottom:none}@media(max-width:768px){.charts-container{flex-direction:column}.chart-group,.chart-wide{min-width:auto;max-width:none}.controls{flex-direction:column;gap:5px}}.main-layout{display:flex;height:100vh;overflow:hidden}.sidebar{width:var(--sidebar-width);height:100%;background-color:var(--bg-secondary);border-right:1px solid var(--border-color);display:flex;flex-direction:column;transition:width var(--transition-normal);flex-shrink:0;overflow:hidden}.sidebar.collapsed{width:var(--sidebar-width-collapsed)}.sidebar-header{height:var(--topbar-height);display:flex;align-items:center;justify-content:space-between;padding:0 var(--spacing-md);border-bottom:1px solid var(--border-color);flex-shrink:0}.sidebar-logo{display:flex;align-items:center;gap:var(--spacing-sm);font-weight:600;font-size:var(--font-size-lg);color:var(--text-primary);white-space:nowrap;overflow:hidden}.sidebar-logo-icon{width:28px;height:28px;flex-shrink:0}.sidebar.collapsed .sidebar-logo-text{display:none}.sidebar-toggle{background:none;border:none;cursor:pointer;padding:var(--spacing-xs);border-radius:4px;color:var(--text-secondary);display:flex;align-items:center;justify-content:center;transition:background-color var(--transition-fast)}.sidebar-toggle:hover{background-color:var(--nav-item-hover)}.sidebar-content{flex:1;padding:var(--spacing-md);overflow-y:auto}.sidebar-section{margin-bottom:var(--spacing-lg)}.sidebar-section-title{font-size:var(--font-size-xs);font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin:0 0 var(--spacing-sm) 0}.project-info{display:flex;flex-direction:column;gap:var(--spacing-sm)}.project-name{display:flex;align-items:center;gap:var(--spacing-sm);color:var(--text-primary);font-weight:600;font-size:var(--font-size-base)}.project-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.project-path{font-size:var(--font-size-xs);color:var(--text-muted);word-break:break-all;line-height:1.4}.project-empty{color:var(--text-muted);font-size:var(--font-size-sm);font-style:italic}.instance-list{display:flex;flex-direction:column;gap:var(--spacing-xs)}.instance-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border-radius:6px;cursor:pointer;border:none;background:none;color:var(--text-secondary);font-size:var(--font-size-sm);text-align:left;transition:all var(--transition-fast)}.instance-item:hover{background-color:var(--nav-item-hover);color:var(--text-primary)}.instance-item.active{background-color:var(--nav-item-active);color:var(--text-primary)}.instance-indicator{width:8px;height:8px;border-radius:50%;background-color:var(--text-muted);flex-shrink:0}.instance-indicator.active{background-color:var(--status-success)}.instance-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sidebar-footer{padding:var(--spacing-md);border-top:1px solid var(--border-color)}.sidebar-action-btn{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border-radius:6px;cursor:pointer;border:none;background:none;font-size:var(--font-size-sm);transition:all var(--transition-fast)}.sidebar-action-btn.shutdown-btn{color:var(--status-error)}.sidebar-action-btn.shutdown-btn:hover{background-color:#ef44441a}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}.topbar{height:var(--topbar-height);background-color:var(--bg-secondary);border-bottom:1px solid var(--border-color);display:flex;align-items:center;justify-content:space-between;padding:0 var(--content-padding);flex-shrink:0}.topbar-nav{display:flex;align-items:center;gap:var(--spacing-xs)}.topbar-nav-item{display:flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-xs) var(--spacing-md);border-radius:6px;cursor:pointer;color:var(--text-secondary);transition:all var(--transition-fast);border:none;background:none;font-size:var(--font-size-sm);font-weight:500}.topbar-nav-item:hover{background-color:var(--nav-item-hover);color:var(--text-primary)}.topbar-nav-item.active{background-color:var(--nav-item-active);color:var(--nav-item-active-border)}.topbar-nav-icon{display:flex;align-items:center;justify-content:center}.topbar-nav-label{white-space:nowrap}.topbar-right{display:flex;align-items:center;gap:var(--spacing-md)}.connection-indicator{display:flex;align-items:center;gap:var(--spacing-xs);font-size:var(--font-size-sm);color:var(--text-muted)}.connection-dot{width:8px;height:8px;border-radius:50%;background-color:var(--status-error)}.connection-dot.streaming{background-color:var(--status-success);animation:pulse 2s infinite}.connection-dot.polling{background-color:var(--status-warning)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.content-area{flex:1;overflow-y:auto;padding:var(--content-padding);background-color:var(--bg-primary)}.card{background-color:var(--card-bg);border-radius:var(--card-border-radius);box-shadow:var(--card-shadow);padding:var(--card-padding);transition:box-shadow var(--transition-fast)}.card:hover{box-shadow:var(--card-shadow-hover)}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-md)}.card-title{font-size:var(--font-size-lg);font-weight:600;color:var(--text-primary);margin:0}.card-subtitle{font-size:var(--font-size-sm);color:var(--text-muted);margin:var(--spacing-xs) 0 0 0}.card-actions{display:flex;gap:var(--spacing-sm)}.card-body{color:var(--text-primary)}@media(max-width:768px){.sidebar{position:fixed;left:0;top:0;z-index:100;transform:translate(-100%);transition:transform var(--transition-normal)}.sidebar.open{transform:translate(0)}.sidebar-backdrop{position:fixed;inset:0;background-color:#00000080;z-index:99;opacity:0;visibility:hidden;transition:opacity var(--transition-normal)}.sidebar-backdrop.visible{opacity:1;visibility:visible}.topbar{padding:0 var(--spacing-md)}.content-area{padding:var(--spacing-md)}.mobile-menu-btn{display:flex;background:none;border:none;cursor:pointer;padding:var(--spacing-xs);color:var(--text-primary)}}@media(min-width:769px){.mobile-menu-btn,.sidebar-backdrop{display:none}}.log-panel{display:flex;flex-direction:column;gap:var(--spacing-md);height:100%}.log-panel-header{display:flex;flex-direction:column;gap:var(--spacing-md);margin-bottom:var(--spacing-md)}.log-panel-controls{display:flex;align-items:center;gap:var(--spacing-sm)}.log-panel-content{flex:1;min-height:0}@media(max-width:768px){.log-panel-header{gap:var(--spacing-sm)}}.stats-panel{display:flex;flex-direction:column;gap:var(--spacing-lg)}.stats-panel-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--spacing-md)}.stats-panel-actions{display:flex;gap:var(--spacing-sm)}.stats-estimator{font-size:var(--font-size-sm);color:var(--text-muted)}.stats-empty{text-align:center;padding:var(--spacing-xl);color:var(--text-muted)}.stats-empty p{margin:0}.stats-empty-hint{font-size:var(--font-size-sm);margin-top:var(--spacing-sm)!important}.metrics-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--spacing-md)}.metric-card{background-color:var(--card-bg);border-radius:var(--card-border-radius);box-shadow:var(--card-shadow);padding:var(--card-padding);transition:box-shadow var(--transition-fast)}.metric-card:hover{box-shadow:var(--card-shadow-hover)}.metric-card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-sm)}.metric-card-title{font-size:var(--font-size-sm);color:var(--text-muted);font-weight:500}.metric-card-icon{color:var(--text-muted)}.metric-card-value{font-size:var(--font-size-2xl);font-weight:700;color:var(--text-primary);line-height:1.2}.metric-card-footer{display:flex;align-items:center;justify-content:space-between;margin-top:var(--spacing-sm)}.metric-card-subtitle{font-size:var(--font-size-xs);color:var(--text-muted)}.metric-card-trend{font-size:var(--font-size-xs);font-weight:600;padding:2px 6px;border-radius:4px}.metric-card-trend.up{color:var(--status-success);background-color:#22c55e1a}.metric-card-trend.down{color:var(--status-error);background-color:#ef44441a}.metric-card-trend.neutral{color:var(--text-muted);background-color:var(--nav-item-hover)}.live-counter{font-variant-numeric:tabular-nums}.stats-charts-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(400px,1fr));gap:var(--spacing-lg)}.stats-charts-row{width:100%}.pie-charts-row{display:flex;gap:var(--spacing-lg);justify-content:center;flex-wrap:wrap}.pie-chart-item{flex:1;min-width:250px;max-width:350px}.chart-container{position:relative;width:100%}.chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:200px;color:var(--text-muted);font-style:italic;text-align:center;gap:var(--spacing-xs)}.chart-empty-hint{font-size:.85em;opacity:.7}.activity-chart-wrapper{display:flex;flex-direction:column;gap:var(--spacing-sm)}.chart-actions{display:flex;justify-content:flex-end;padding-top:var(--spacing-sm)}.btn-sm{padding:4px 8px;font-size:.85em}@media(max-width:768px){.metrics-grid{grid-template-columns:repeat(2,1fr)}.stats-charts-grid{grid-template-columns:1fr}.pie-charts-row{flex-direction:column;align-items:center}.pie-chart-item{max-width:none;width:100%}}.session-panel{display:flex;flex-direction:column;gap:var(--spacing-lg)}.session-panel-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:var(--spacing-lg);flex-wrap:wrap;gap:var(--spacing-md)}.session-panel-title{font-size:var(--font-size-lg);font-weight:600;color:var(--text-primary);margin:0}.session-panel-subtitle{font-size:var(--font-size-sm);color:var(--text-muted);margin:var(--spacing-xs) 0 0 0}.session-panel-actions{display:flex;gap:var(--spacing-sm)}.session-list{display:flex;flex-direction:column;gap:var(--spacing-md)}.session-list-empty{text-align:center;padding:var(--spacing-xl);color:var(--text-muted)}.session-list-empty p{margin:0}.session-list-empty-hint{font-size:var(--font-size-sm);margin-top:var(--spacing-sm)!important}.session-item{background-color:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;padding:var(--spacing-md);transition:border-color var(--transition-fast)}.session-item:hover{border-color:var(--text-muted)}.session-item-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:var(--spacing-sm)}.session-item-info{display:flex;flex-direction:column;gap:2px}.session-item-date{font-size:var(--font-size-base);font-weight:600;color:var(--text-primary)}.session-item-time{font-size:var(--font-size-sm);color:var(--text-muted)}.session-item-duration{font-size:var(--font-size-sm);color:var(--text-secondary);background-color:var(--nav-item-hover);padding:2px 8px;border-radius:4px}.session-item-project{font-size:var(--font-size-sm);color:var(--text-secondary);margin-bottom:var(--spacing-sm)}.session-item-stats{display:flex;gap:var(--spacing-lg);margin-bottom:var(--spacing-sm)}.session-stat{display:flex;flex-direction:column;gap:2px}.session-stat-label{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.session-stat-value{font-size:var(--font-size-base);font-weight:600;color:var(--text-primary);font-variant-numeric:tabular-nums}.session-item-actions{display:flex;gap:var(--spacing-sm);justify-content:flex-end}.session-action-btn{display:flex;align-items:center;gap:4px;padding:6px 12px;font-size:var(--font-size-sm);color:var(--text-secondary);background:none;border:1px solid var(--border-color);border-radius:4px;cursor:pointer;transition:all var(--transition-fast)}.session-action-btn:hover{color:var(--text-primary);border-color:var(--text-muted);background-color:var(--nav-item-hover)}.btn-danger{background-color:transparent;color:var(--status-error);border:1px solid var(--status-error)}.btn-danger:hover{background-color:var(--status-error);color:#fff}.export-btn{display:flex;align-items:center}@media(max-width:768px){.session-panel-header{flex-direction:column;align-items:stretch}.session-panel-actions{justify-content:flex-end}.session-item-stats{flex-wrap:wrap;gap:var(--spacing-md)}}.dashboard-overview{display:flex;flex-direction:column;gap:var(--spacing-lg)}.welcome-section{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--spacing-md)}.welcome-content{flex:1}.welcome-title{font-size:var(--font-size-xl);font-weight:600;color:var(--text-primary);margin:0 0 var(--spacing-xs) 0}.welcome-description{font-size:var(--font-size-base);color:var(--text-secondary);margin:0}.connection-badge{flex-shrink:0}.connection-status{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:20px;font-size:var(--font-size-sm);font-weight:500}.connection-status:before{content:"";width:8px;height:8px;border-radius:50%}.connection-status.streaming{background-color:#22c55e1a;color:var(--status-success)}.connection-status.streaming:before{background-color:var(--status-success);animation:pulse 2s infinite}.connection-status.polling{background-color:#f59e0b1a;color:var(--status-warning)}.connection-status.polling:before{background-color:var(--status-warning)}.connection-status.disconnected{background-color:#ef44441a;color:var(--status-error)}.connection-status.disconnected:before{background-color:var(--status-error)}.quick-nav-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:var(--spacing-md)}.quick-nav-card{display:flex;align-items:center;gap:var(--spacing-md);padding:var(--spacing-md);background-color:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;cursor:pointer;transition:all var(--transition-fast);text-align:left;width:100%}.quick-nav-card:hover{border-color:var(--input-focus-border);background-color:var(--nav-item-active)}.quick-nav-icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;background-color:var(--nav-item-active);color:var(--input-focus-border);flex-shrink:0}.quick-nav-content{flex:1;min-width:0}.quick-nav-title{font-size:var(--font-size-base);font-weight:600;color:var(--text-primary);margin:0}.quick-nav-description{font-size:var(--font-size-sm);color:var(--text-muted);margin:4px 0 0}.quick-nav-arrow{color:var(--text-muted);flex-shrink:0;transition:transform var(--transition-fast)}.quick-nav-card:hover .quick-nav-arrow{transform:translate(4px);color:var(--input-focus-border)}@media(max-width:768px){.welcome-section{flex-direction:column}.quick-nav-grid{grid-template-columns:1fr}}.search-input-wrapper{position:relative;display:flex;align-items:center}.search-input-icon{position:absolute;left:12px;color:var(--text-muted);pointer-events:none;display:flex;align-items:center}.search-input{width:100%;padding:8px 36px;border:1px solid var(--input-border);border-radius:6px;background-color:var(--input-bg);color:var(--text-primary);font-size:var(--font-size-sm);transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.search-input:focus{outline:none;border-color:var(--input-focus-border);box-shadow:0 0 0 3px var(--input-focus-ring)}.search-input::placeholder{color:var(--text-muted)}.search-input-clear{position:absolute;right:8px;display:flex;align-items:center;justify-content:center;padding:4px;border:none;background:none;color:var(--text-muted);cursor:pointer;border-radius:4px;transition:color var(--transition-fast),background-color var(--transition-fast)}.search-input-clear:hover{color:var(--text-primary);background-color:var(--nav-item-hover)}.dropdown{position:relative;display:inline-block;min-width:140px}.dropdown-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:8px 12px;border:1px solid var(--input-border);border-radius:6px;background-color:var(--input-bg);color:var(--text-primary);font-size:var(--font-size-sm);cursor:pointer;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.dropdown-trigger:hover{border-color:var(--text-muted)}.dropdown-trigger:focus{outline:none;border-color:var(--input-focus-border);box-shadow:0 0 0 3px var(--input-focus-ring)}.dropdown-text{flex:1;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-arrow{display:flex;align-items:center;margin-left:8px;color:var(--text-muted);transition:transform var(--transition-fast)}.dropdown-arrow.open{transform:rotate(180deg)}.dropdown-menu{position:absolute;top:100%;left:0;right:0;margin-top:4px;padding:4px;border:1px solid var(--border-color);border-radius:6px;background-color:var(--bg-secondary);box-shadow:var(--card-shadow);z-index:100;max-height:240px;overflow-y:auto}.dropdown-clear{display:block;width:100%;padding:6px 8px;border:none;background:none;color:var(--status-info);font-size:var(--font-size-xs);text-align:left;cursor:pointer;border-bottom:1px solid var(--border-color);margin-bottom:4px}.dropdown-clear:hover{text-decoration:underline}.dropdown-options{display:flex;flex-direction:column;gap:2px}.dropdown-option{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:4px;cursor:pointer;transition:background-color var(--transition-fast)}.dropdown-option:hover{background-color:var(--nav-item-hover)}.dropdown-option input[type=checkbox],.dropdown-option input[type=radio]{margin:0;accent-color:var(--input-focus-border)}.dropdown-option-label{font-size:var(--font-size-sm);color:var(--text-primary)}.log-filter-bar{display:flex;align-items:center;gap:var(--spacing-md);flex-wrap:wrap}.log-filter-search{flex:1;min-width:200px;max-width:300px}.log-filter-dropdowns{display:flex;align-items:center;gap:var(--spacing-sm)}.log-filter-clear{padding:8px 12px;font-size:var(--font-size-sm)}.icon-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid var(--input-border);border-radius:6px;background-color:var(--input-bg);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.icon-btn:hover{border-color:var(--text-muted);color:var(--text-primary);background-color:var(--nav-item-hover)}.icon-btn:disabled{opacity:.5;cursor:not-allowed}.reload-btn.spinning svg{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.filter-stats{display:flex;align-items:center;gap:var(--spacing-sm);font-size:var(--font-size-sm);color:var(--text-muted)}.filter-stats-count{font-weight:600;color:var(--text-primary)}@media(max-width:768px){.log-filter-bar{flex-direction:column;align-items:stretch}.log-filter-search{max-width:none}.log-filter-dropdowns{flex-wrap:wrap}.dropdown{flex:1;min-width:120px}}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/png" href="/dashboard/logo.png" />
|
|
6
|
+
<link rel="apple-touch-icon" href="/dashboard/logo.png" />
|
|
5
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
8
|
<title>Smart Edit Dashboard</title>
|
|
7
9
|
<script type="module" crossorigin src="/dashboard/dashboard.js"></script>
|
|
Binary file
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone Dashboard Server for Multi-Instance Mode
|
|
3
|
+
*
|
|
4
|
+
* This server runs independently from MCP servers and provides:
|
|
5
|
+
* - Static file serving for the dashboard UI
|
|
6
|
+
* - API endpoints to list registered instances
|
|
7
|
+
* - Proxy capabilities to forward requests to individual MCP instances
|
|
8
|
+
*/
|
|
9
|
+
export interface StandaloneDashboardOptions {
|
|
10
|
+
port?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class StandaloneDashboardServer {
|
|
13
|
+
private server;
|
|
14
|
+
private listeningPort;
|
|
15
|
+
private readonly requestedPort;
|
|
16
|
+
constructor(options?: StandaloneDashboardOptions);
|
|
17
|
+
start(): Promise<number>;
|
|
18
|
+
stop(): void;
|
|
19
|
+
getPort(): number | null;
|
|
20
|
+
private startServer;
|
|
21
|
+
private listenOnPort;
|
|
22
|
+
private handleRequest;
|
|
23
|
+
private handleGetInstances;
|
|
24
|
+
private serveDashboardAsset;
|
|
25
|
+
private respondNotFound;
|
|
26
|
+
private respondMethodNotAllowed;
|
|
27
|
+
private sendJson;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Start a standalone dashboard server and wait for shutdown signal.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runStandaloneDashboard(options?: StandaloneDashboardOptions): Promise<void>;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone Dashboard Server for Multi-Instance Mode
|
|
3
|
+
*
|
|
4
|
+
* This server runs independently from MCP servers and provides:
|
|
5
|
+
* - Static file serving for the dashboard UI
|
|
6
|
+
* - API endpoints to list registered instances
|
|
7
|
+
* - Proxy capabilities to forward requests to individual MCP instances
|
|
8
|
+
*/
|
|
9
|
+
import { Buffer } from 'node:buffer';
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
import { parse as parseUrl } from 'node:url';
|
|
12
|
+
import { promises as fs } from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import process from 'node:process';
|
|
15
|
+
import { createSmartEditLogger } from './util/logging.js';
|
|
16
|
+
import { SMART_EDIT_DASHBOARD_DIR } from './constants.js';
|
|
17
|
+
import { getInstances, DEFAULT_DASHBOARD_PORT } from './instance-registry.js';
|
|
18
|
+
const { logger } = createSmartEditLogger({ name: 'smart-edit.standalone-dashboard', emitToConsole: true, level: 'info' });
|
|
19
|
+
const DASHBOARD_HOST = '127.0.0.1';
|
|
20
|
+
const CONTENT_TYPE_BY_EXTENSION = {
|
|
21
|
+
'.html': 'text/html; charset=utf-8',
|
|
22
|
+
'.js': 'application/javascript; charset=utf-8',
|
|
23
|
+
'.css': 'text/css; charset=utf-8',
|
|
24
|
+
'.png': 'image/png',
|
|
25
|
+
'.json': 'application/json; charset=utf-8',
|
|
26
|
+
'.ico': 'image/x-icon'
|
|
27
|
+
};
|
|
28
|
+
export class StandaloneDashboardServer {
|
|
29
|
+
server = null;
|
|
30
|
+
listeningPort = null;
|
|
31
|
+
requestedPort;
|
|
32
|
+
constructor(options = {}) {
|
|
33
|
+
this.requestedPort = options.port ?? DEFAULT_DASHBOARD_PORT;
|
|
34
|
+
}
|
|
35
|
+
async start() {
|
|
36
|
+
if (this.server && this.listeningPort !== null) {
|
|
37
|
+
return this.listeningPort;
|
|
38
|
+
}
|
|
39
|
+
const { server, port } = await this.startServer();
|
|
40
|
+
this.server = server;
|
|
41
|
+
this.listeningPort = port;
|
|
42
|
+
logger.info(`Smart-Edit standalone dashboard listening on http://${DASHBOARD_HOST}:${port}/dashboard/`);
|
|
43
|
+
return port;
|
|
44
|
+
}
|
|
45
|
+
stop() {
|
|
46
|
+
if (this.server) {
|
|
47
|
+
this.server.close((error) => {
|
|
48
|
+
if (error) {
|
|
49
|
+
logger.warn('Failed to stop standalone dashboard server cleanly.', error);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
this.server = null;
|
|
53
|
+
this.listeningPort = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
getPort() {
|
|
57
|
+
return this.listeningPort;
|
|
58
|
+
}
|
|
59
|
+
async startServer() {
|
|
60
|
+
let candidatePort = this.requestedPort;
|
|
61
|
+
let lastError = null;
|
|
62
|
+
while (candidatePort <= 65535) {
|
|
63
|
+
const server = createServer((req, res) => {
|
|
64
|
+
void this.handleRequest(req, res);
|
|
65
|
+
});
|
|
66
|
+
try {
|
|
67
|
+
const port = await this.listenOnPort(server, candidatePort);
|
|
68
|
+
return { server, port };
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
lastError = error;
|
|
72
|
+
try {
|
|
73
|
+
server.close();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// ignore close errors
|
|
77
|
+
}
|
|
78
|
+
if (lastError && (lastError.code === 'EADDRINUSE' || lastError.code === 'EACCES')) {
|
|
79
|
+
candidatePort += 1;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
logger.error('Failed to start standalone dashboard server.', lastError ?? undefined);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
throw new Error(lastError?.message ?? 'Unable to start standalone dashboard server; no available ports.');
|
|
87
|
+
}
|
|
88
|
+
listenOnPort(server, port) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const onError = (error) => {
|
|
91
|
+
cleanup();
|
|
92
|
+
reject(error);
|
|
93
|
+
};
|
|
94
|
+
const onListening = () => {
|
|
95
|
+
const address = server.address();
|
|
96
|
+
cleanup();
|
|
97
|
+
if (address && typeof address === 'object') {
|
|
98
|
+
resolve(address.port);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
resolve(port);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const cleanup = () => {
|
|
105
|
+
server.off('error', onError);
|
|
106
|
+
server.off('listening', onListening);
|
|
107
|
+
};
|
|
108
|
+
server.once('error', onError);
|
|
109
|
+
server.once('listening', onListening);
|
|
110
|
+
server.listen({ port, host: DASHBOARD_HOST, exclusive: true });
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async handleRequest(req, res) {
|
|
114
|
+
const method = req.method?.toUpperCase() ?? 'GET';
|
|
115
|
+
const url = parseUrl(req.url ?? '/', true);
|
|
116
|
+
const pathname = url.pathname ?? '/';
|
|
117
|
+
// Add CORS headers for cross-origin requests from dashboard UI to MCP instances
|
|
118
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
119
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS');
|
|
120
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
121
|
+
if (method === 'OPTIONS') {
|
|
122
|
+
res.statusCode = 204;
|
|
123
|
+
res.end();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
// Redirect root to dashboard
|
|
128
|
+
if (pathname === '/' || pathname === '') {
|
|
129
|
+
res.statusCode = 302;
|
|
130
|
+
res.setHeader('Location', '/dashboard/');
|
|
131
|
+
res.end();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (pathname.startsWith('/dashboard')) {
|
|
135
|
+
if (method !== 'GET') {
|
|
136
|
+
this.respondMethodNotAllowed(res);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
await this.serveDashboardAsset(pathname, res);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// API endpoints for multi-instance mode
|
|
143
|
+
if (pathname === '/api/instances') {
|
|
144
|
+
if (method !== 'GET') {
|
|
145
|
+
this.respondMethodNotAllowed(res);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
this.handleGetInstances(res);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
this.respondNotFound(res);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
logger.error('Standalone dashboard request failed.', error instanceof Error ? error : undefined);
|
|
155
|
+
this.sendJson(res, 500, { error: 'Internal server error' });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
handleGetInstances(res) {
|
|
159
|
+
const instances = getInstances();
|
|
160
|
+
this.sendJson(res, 200, { instances });
|
|
161
|
+
}
|
|
162
|
+
async serveDashboardAsset(pathname, res) {
|
|
163
|
+
let relativePath = pathname.replace(/^\/dashboard\/?/, '');
|
|
164
|
+
// Handle directory requests
|
|
165
|
+
if (relativePath === '' || relativePath.endsWith('/')) {
|
|
166
|
+
relativePath = relativePath + 'index.html';
|
|
167
|
+
}
|
|
168
|
+
const resolvedPath = path.resolve(SMART_EDIT_DASHBOARD_DIR, decodeURIComponent(relativePath));
|
|
169
|
+
if (!resolvedPath.startsWith(path.resolve(SMART_EDIT_DASHBOARD_DIR))) {
|
|
170
|
+
this.respondNotFound(res);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const file = await fs.readFile(resolvedPath);
|
|
175
|
+
const ext = path.extname(resolvedPath).toLowerCase();
|
|
176
|
+
const contentType = CONTENT_TYPE_BY_EXTENSION[ext] ?? 'application/octet-stream';
|
|
177
|
+
res.statusCode = 200;
|
|
178
|
+
res.setHeader('Content-Type', contentType);
|
|
179
|
+
res.setHeader('Content-Length', file.length);
|
|
180
|
+
res.end(file);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
if (error.code === 'ENOENT') {
|
|
184
|
+
this.respondNotFound(res);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
respondNotFound(res) {
|
|
191
|
+
res.statusCode = 404;
|
|
192
|
+
res.end('Not found');
|
|
193
|
+
}
|
|
194
|
+
respondMethodNotAllowed(res) {
|
|
195
|
+
res.statusCode = 405;
|
|
196
|
+
res.end('Method not allowed');
|
|
197
|
+
}
|
|
198
|
+
sendJson(res, statusCode, payload) {
|
|
199
|
+
const body = JSON.stringify(payload);
|
|
200
|
+
res.statusCode = statusCode;
|
|
201
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
202
|
+
res.setHeader('Content-Length', Buffer.byteLength(body, 'utf-8'));
|
|
203
|
+
res.end(body);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Start a standalone dashboard server and wait for shutdown signal.
|
|
208
|
+
*/
|
|
209
|
+
export async function runStandaloneDashboard(options = {}) {
|
|
210
|
+
const server = new StandaloneDashboardServer(options);
|
|
211
|
+
const port = await server.start();
|
|
212
|
+
console.log(`Smart-Edit Dashboard is running at: http://127.0.0.1:${port}/dashboard/`);
|
|
213
|
+
console.log('Press Ctrl+C to stop.');
|
|
214
|
+
await new Promise((resolve) => {
|
|
215
|
+
const shutdown = () => {
|
|
216
|
+
console.log('\nShutting down dashboard...');
|
|
217
|
+
server.stop();
|
|
218
|
+
resolve();
|
|
219
|
+
};
|
|
220
|
+
process.once('SIGINT', shutdown);
|
|
221
|
+
process.once('SIGTERM', shutdown);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { Tool } from './tools_base.js';
|
|
2
2
|
export declare class CheckOnboardingPerformedTool extends Tool {
|
|
3
|
-
static readonly description = "Checks whether project onboarding was already performed.";
|
|
3
|
+
static readonly description = "Checks whether project onboarding was already performed and if there are significant changes since last onboarding.";
|
|
4
4
|
apply(_args?: Record<string, unknown>): Promise<string>;
|
|
5
5
|
}
|
|
6
6
|
export declare class OnboardingTool extends Tool {
|
|
7
7
|
static readonly description = "Provides onboarding instructions (project structure, essential tasks, etc.) when onboarding has not been performed.";
|
|
8
8
|
apply(_args?: Record<string, unknown>): Promise<string>;
|
|
9
9
|
}
|
|
10
|
+
export declare class CollectProjectSymbolsTool extends Tool {
|
|
11
|
+
static readonly description: string;
|
|
12
|
+
apply(args?: Record<string, unknown>): Promise<string>;
|
|
13
|
+
}
|
|
10
14
|
export declare class ThinkAboutCollectedInformationTool extends Tool {
|
|
11
15
|
static readonly description = "Encourages the agent to reflect on whether the gathered information is sufficient and relevant.";
|
|
12
16
|
apply(_args?: Record<string, unknown>): Promise<string>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import { Tool, ToolMarkerDoesNotRequireActiveProject, ToolMarkerOptional } from './tools_base.js';
|
|
3
|
-
import { ListMemoriesTool } from './memory_tools.js';
|
|
3
|
+
import { ListMemoriesTool, ReadMemoryTool, WriteMemoryTool } from './memory_tools.js';
|
|
4
|
+
import { getCurrentCommit, hasSignificantChanges } from '../util/git.js';
|
|
5
|
+
const PROJECT_SYMBOLS_MEMORY = 'project-symbols';
|
|
4
6
|
function ensureString(value) {
|
|
5
7
|
if (typeof value === 'string') {
|
|
6
8
|
return value;
|
|
@@ -76,7 +78,7 @@ async function callAgentSystemPrompt(agent) {
|
|
|
76
78
|
throw new Error('Agent does not implement a system prompt creation method.');
|
|
77
79
|
}
|
|
78
80
|
export class CheckOnboardingPerformedTool extends Tool {
|
|
79
|
-
static description = 'Checks whether project onboarding was already performed.';
|
|
81
|
+
static description = 'Checks whether project onboarding was already performed and if there are significant changes since last onboarding.';
|
|
80
82
|
async apply(_args = {}) {
|
|
81
83
|
const listTool = getToolInstance(this.agent, ListMemoriesTool);
|
|
82
84
|
const raw = await Promise.resolve(listTool.apply());
|
|
@@ -95,13 +97,47 @@ export class CheckOnboardingPerformedTool extends Tool {
|
|
|
95
97
|
return ('Onboarding not performed yet (no memories available). ' +
|
|
96
98
|
'You should perform onboarding by calling the `onboarding` tool before proceeding with the task.');
|
|
97
99
|
}
|
|
100
|
+
// Check for significant changes since last onboarding
|
|
101
|
+
let significantChangesInfo = '';
|
|
102
|
+
if (parsed.includes(PROJECT_SYMBOLS_MEMORY)) {
|
|
103
|
+
try {
|
|
104
|
+
const readTool = getToolInstance(this.agent, ReadMemoryTool);
|
|
105
|
+
const memoryContent = await Promise.resolve(readTool.apply({ memory_file_name: PROJECT_SYMBOLS_MEMORY }));
|
|
106
|
+
const projectSymbols = JSON.parse(ensureString(memoryContent));
|
|
107
|
+
const lastCommit = projectSymbols.lastCommit;
|
|
108
|
+
if (lastCommit) {
|
|
109
|
+
const currentCommit = await getCurrentCommit();
|
|
110
|
+
if (currentCommit && currentCommit !== lastCommit) {
|
|
111
|
+
const changeInfo = await hasSignificantChanges(lastCommit);
|
|
112
|
+
if (changeInfo.significant) {
|
|
113
|
+
significantChangesInfo = [
|
|
114
|
+
'',
|
|
115
|
+
'## IMPORTANT: Significant Changes Detected',
|
|
116
|
+
'',
|
|
117
|
+
`Since your last onboarding (commit: ${lastCommit.substring(0, 7)}), there have been significant changes:`,
|
|
118
|
+
changeInfo.summary,
|
|
119
|
+
'',
|
|
120
|
+
'Consider re-running onboarding to refresh the project-symbols memory.',
|
|
121
|
+
'Use the `onboarding` tool to update your knowledge of the codebase.',
|
|
122
|
+
''
|
|
123
|
+
].join('\n');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
// If we can't read the memory or parse it, just continue without the check
|
|
130
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
131
|
+
significantChangesInfo = `\n(Note: Could not check for changes: ${message})\n`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
98
134
|
const lines = [
|
|
99
135
|
'The onboarding was already performed, below is the list of available memories.',
|
|
100
136
|
'Do not read them immediately, just remember that they exist and that you can read them later, if it is necessary',
|
|
101
137
|
'for the current task.',
|
|
102
138
|
'Some memories may be based on previous conversations, others may be general for the current project.',
|
|
103
139
|
'You should be able to tell which one you need based on the name of the memory.',
|
|
104
|
-
|
|
140
|
+
significantChangesInfo,
|
|
105
141
|
JSON.stringify(parsed)
|
|
106
142
|
];
|
|
107
143
|
return lines.join('\n');
|
|
@@ -115,6 +151,43 @@ export class OnboardingTool extends Tool {
|
|
|
115
151
|
return result;
|
|
116
152
|
}
|
|
117
153
|
}
|
|
154
|
+
export class CollectProjectSymbolsTool extends Tool {
|
|
155
|
+
static description = 'Collects and saves project symbols (utilities, components, dependencies) to the project-symbols memory. ' +
|
|
156
|
+
'Call this after onboarding to enable duplicate detection features.';
|
|
157
|
+
async apply(args = {}) {
|
|
158
|
+
const { utility_dirs = [], common_components = [], dependencies = {} } = args;
|
|
159
|
+
// Get current git commit
|
|
160
|
+
const currentCommit = await getCurrentCommit();
|
|
161
|
+
// Build the project symbols memory content
|
|
162
|
+
const projectSymbols = {
|
|
163
|
+
lastCommit: currentCommit ?? 'unknown',
|
|
164
|
+
lastUpdated: new Date().toISOString(),
|
|
165
|
+
dependencies,
|
|
166
|
+
utilityDirs: utility_dirs,
|
|
167
|
+
commonComponents: common_components
|
|
168
|
+
};
|
|
169
|
+
// Save to memory
|
|
170
|
+
const writeTool = getToolInstance(this.agent, WriteMemoryTool);
|
|
171
|
+
const memoryContent = JSON.stringify(projectSymbols, null, 2);
|
|
172
|
+
await Promise.resolve(writeTool.apply({
|
|
173
|
+
memory_name: PROJECT_SYMBOLS_MEMORY,
|
|
174
|
+
content: memoryContent
|
|
175
|
+
}));
|
|
176
|
+
const lines = [
|
|
177
|
+
`Project symbols saved to memory: ${PROJECT_SYMBOLS_MEMORY}`,
|
|
178
|
+
'',
|
|
179
|
+
`- Commit: ${projectSymbols.lastCommit}`,
|
|
180
|
+
`- Updated: ${projectSymbols.lastUpdated}`,
|
|
181
|
+
`- Utility directories: ${utility_dirs.length > 0 ? utility_dirs.join(', ') : 'none specified'}`,
|
|
182
|
+
`- Common components: ${common_components.length > 0 ? common_components.join(', ') : 'none specified'}`,
|
|
183
|
+
`- Dependencies tracked: ${Object.keys(dependencies).length}`,
|
|
184
|
+
'',
|
|
185
|
+
'This information will be used for duplicate detection in careful-editor mode.',
|
|
186
|
+
'The system will alert you when significant changes occur since this onboarding.'
|
|
187
|
+
];
|
|
188
|
+
return lines.join('\n');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
118
191
|
export class ThinkAboutCollectedInformationTool extends Tool {
|
|
119
192
|
static description = 'Encourages the agent to reflect on whether the gathered information is sufficient and relevant.';
|
|
120
193
|
async apply(_args = {}) {
|
|
@@ -4,8 +4,38 @@ export interface GitStatus {
|
|
|
4
4
|
hasStagedUncommittedChanges: boolean;
|
|
5
5
|
hasUntrackedFiles: boolean;
|
|
6
6
|
}
|
|
7
|
+
export interface GitDiffStats {
|
|
8
|
+
filesChanged: number;
|
|
9
|
+
insertions: number;
|
|
10
|
+
deletions: number;
|
|
11
|
+
newFiles: number;
|
|
12
|
+
hasNewInSrc: boolean;
|
|
13
|
+
}
|
|
7
14
|
export interface GetGitStatusOptions {
|
|
8
15
|
cwd?: string;
|
|
9
16
|
env?: NodeJS.ProcessEnv;
|
|
10
17
|
}
|
|
11
18
|
export declare function getGitStatus(options?: GetGitStatusOptions): Promise<GitStatus | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the current HEAD commit hash.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getCurrentCommit(options?: GetGitStatusOptions): Promise<string | null>;
|
|
23
|
+
/**
|
|
24
|
+
* Get diff statistics between two commits.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getGitDiffStats(fromCommit: string, toCommit?: string, options?: GetGitStatusOptions): Promise<GitDiffStats | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Check if the new files list contains files in src/ directory.
|
|
29
|
+
*/
|
|
30
|
+
export declare function hasNewFilesInSrc(fromCommit: string, toCommit?: string, options?: GetGitStatusOptions): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Determine if there are significant changes since the last commit.
|
|
33
|
+
* Significant changes are defined as:
|
|
34
|
+
* - More than 10 files changed
|
|
35
|
+
* - More than 5 new files
|
|
36
|
+
* - Any new files in src/ directory
|
|
37
|
+
*/
|
|
38
|
+
export declare function hasSignificantChanges(lastCommit: string, options?: GetGitStatusOptions): Promise<{
|
|
39
|
+
significant: boolean;
|
|
40
|
+
summary: string;
|
|
41
|
+
}>;
|