vg-coder-cli 2.0.3 → 2.0.5

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.
Files changed (84) hide show
  1. package/README.md +318 -92
  2. package/{vg/apps/api/src/assets/.gitkeep → change.sh} +0 -0
  3. package/package.json +4 -11
  4. package/src/index.js +0 -60
  5. package/src/server/views/dashboard.html +432 -619
  6. package/vg-coder-cli-1.0.17.tgz +0 -0
  7. package/vg-coder-cli-2.0.4.tgz +0 -0
  8. package/vg-coder-cli-2.0.5.tgz +0 -0
  9. package/CHANGELOG.md +0 -59
  10. package/PUBLISHING.md +0 -86
  11. package/SYSTEM_PROMPT.md +0 -157
  12. package/init-nx-monorepo.sh +0 -107
  13. package/vg/.vscode/extensions.json +0 -8
  14. package/vg/.vscode/launch.json +0 -23
  15. package/vg/README-WORKSPACE.md +0 -82
  16. package/vg/README.md +0 -85
  17. package/vg/apps/api/project.json +0 -83
  18. package/vg/apps/api/src/app/analyze.controller.ts +0 -17
  19. package/vg/apps/api/src/app/analyze.service.ts +0 -57
  20. package/vg/apps/api/src/app/app.controller.ts +0 -12
  21. package/vg/apps/api/src/app/app.module.ts +0 -29
  22. package/vg/apps/api/src/app/app.service.ts +0 -8
  23. package/vg/apps/api/src/app/clean.controller.ts +0 -40
  24. package/vg/apps/api/src/app/execute.controller.ts +0 -19
  25. package/vg/apps/api/src/app/execute.service.ts +0 -46
  26. package/vg/apps/api/src/app/info.controller.ts +0 -12
  27. package/vg/apps/api/src/app/info.service.ts +0 -65
  28. package/vg/apps/api/src/main.ts +0 -28
  29. package/vg/apps/api/webpack.config.js +0 -25
  30. package/vg/apps/api-e2e/jest.config.cts +0 -18
  31. package/vg/apps/api-e2e/project.json +0 -17
  32. package/vg/apps/api-e2e/src/support/global-setup.ts +0 -16
  33. package/vg/apps/api-e2e/src/support/global-teardown.ts +0 -10
  34. package/vg/apps/api-e2e/src/support/test-setup.ts +0 -9
  35. package/vg/apps/ng-app/jest.config.ts +0 -21
  36. package/vg/apps/ng-app/project.json +0 -110
  37. package/vg/apps/ng-app/proxy.conf.json +0 -8
  38. package/vg/apps/ng-app/public/favicon.ico +0 -0
  39. package/vg/apps/ng-app/src/app/app.config.ts +0 -17
  40. package/vg/apps/ng-app/src/app/app.html +0 -1
  41. package/vg/apps/ng-app/src/app/app.routes.ts +0 -7
  42. package/vg/apps/ng-app/src/app/app.scss +0 -0
  43. package/vg/apps/ng-app/src/app/app.ts +0 -12
  44. package/vg/apps/ng-app/src/app/dashboard/dashboard.component.html +0 -87
  45. package/vg/apps/ng-app/src/app/dashboard/dashboard.component.scss +0 -290
  46. package/vg/apps/ng-app/src/app/dashboard/dashboard.component.ts +0 -236
  47. package/vg/apps/ng-app/src/app/nx-welcome.ts +0 -872
  48. package/vg/apps/ng-app/src/app/services/api.service.ts +0 -28
  49. package/vg/apps/ng-app/src/index.html +0 -13
  50. package/vg/apps/ng-app/src/main.ts +0 -5
  51. package/vg/apps/ng-app/src/styles.scss +0 -1
  52. package/vg/apps/ng-app/src/test-setup.ts +0 -6
  53. package/vg/bin/vg-workspace.js +0 -43
  54. package/vg/jest.config.ts +0 -6
  55. package/vg/nx.json +0 -85
  56. package/vg/package-lock.json +0 -30707
  57. package/vg/package-workspace.json +0 -38
  58. package/vg/package.json +0 -38
  59. package/vg/packages/client/data-access/README.md +0 -7
  60. package/vg/packages/client/data-access/jest.config.ts +0 -21
  61. package/vg/packages/client/data-access/project.json +0 -21
  62. package/vg/packages/client/data-access/src/index.ts +0 -1
  63. package/vg/packages/client/data-access/src/lib/data-access/data-access.html +0 -1
  64. package/vg/packages/client/data-access/src/lib/data-access/data-access.scss +0 -0
  65. package/vg/packages/client/data-access/src/lib/data-access/data-access.ts +0 -9
  66. package/vg/packages/client/data-access/src/test-setup.ts +0 -6
  67. package/vg/packages/core/README.md +0 -11
  68. package/vg/packages/core/jest.config.ts +0 -10
  69. package/vg/packages/core/package.json +0 -11
  70. package/vg/packages/core/project.json +0 -26
  71. package/vg/packages/core/src/index.ts +0 -6
  72. package/vg/packages/core/src/lib/core.ts +0 -3
  73. package/vg/packages/core/src/lib/detectors/project-detector.ts +0 -343
  74. package/vg/packages/core/src/lib/ignore/ignore-manager.ts +0 -315
  75. package/vg/packages/core/src/lib/scanner/file-scanner.ts +0 -675
  76. package/vg/packages/core/src/lib/tokenizer/token-manager.ts +0 -435
  77. package/vg/packages/core/src/lib/utils/bash-executor.ts +0 -146
  78. package/vg/packages/shared/data-types/README.md +0 -11
  79. package/vg/packages/shared/data-types/jest.config.ts +0 -10
  80. package/vg/packages/shared/data-types/package.json +0 -11
  81. package/vg/packages/shared/data-types/project.json +0 -26
  82. package/vg/packages/shared/data-types/src/index.ts +0 -1
  83. package/vg/packages/shared/data-types/src/lib/data-types.ts +0 -3
  84. package/vg/start-dev.sh +0 -22
@@ -1,87 +0,0 @@
1
- <div class="container">
2
- <div class="header">
3
- <h1>🚀 VG Coder API Dashboard</h1>
4
- <p>Phân tích dự án và thực thi bash scripts</p>
5
- <span class="status" id="status">● Server Running</span>
6
- </div>
7
-
8
- <!-- System Prompt Section -->
9
- <div class="system-prompt-card">
10
- <div class="system-prompt-header" (click)="toggleSystemPrompt()">
11
- <h2>
12
- <span>📝</span>
13
- <span>AI System Prompt</span>
14
- </h2>
15
- <span class="toggle-icon" [class.open]="isPromptOpen">▼</span>
16
- </div>
17
- <div class="system-prompt-content" [class.open]="isPromptOpen">
18
- <div class="prompt-text">{{ systemPrompt }}</div>
19
- <button class="btn btn-copy" (click)="copySystemPrompt()">
20
- <span>📋</span>
21
- <span>Copy System Prompt</span>
22
- </button>
23
- </div>
24
- </div>
25
-
26
- <div class="endpoints">
27
- <!-- Analyze -->
28
- <div class="endpoint-card">
29
- <div class="endpoint-header">
30
- <span class="method post">POST</span>
31
- <span class="endpoint-path">/api/analyze</span>
32
- </div>
33
- <p class="endpoint-desc">📊 Phân tích dự án và lấy toàn bộ source code</p>
34
- <div class="form-group">
35
- <label>📁 Project Path:</label>
36
- <input type="text" [(ngModel)]="analyzePath" placeholder=".">
37
- </div>
38
- <div class="btn-group">
39
- <button class="btn" (click)="analyze()" [disabled]="analyzeLoading">
40
- <span *ngIf="!analyzeLoading">📥</span>
41
- <span *ngIf="analyzeLoading" class="loading"></span>
42
- <span>{{ analyzeLoading ? 'Loading...' : 'Download File' }}</span>
43
- </button>
44
- <button class="btn btn-copy" (click)="copyAnalyzeResult()">
45
- <span>📋</span>
46
- <span>Copy to Clipboard</span>
47
- </button>
48
- </div>
49
- <div class="response" *ngIf="analyzeResult" [class.success]="true">
50
- <pre>{{ analyzeResult | slice:0:500 }}...</pre>
51
- </div>
52
- </div>
53
-
54
- <!-- Execute Bash -->
55
- <div class="endpoint-card">
56
- <div class="endpoint-header">
57
- <span class="method post">POST</span>
58
- <span class="endpoint-path">/api/execute</span>
59
- </div>
60
- <p class="endpoint-desc">⚡ Thực thi bash script với syntax validation</p>
61
- <div class="form-group">
62
- <label>💻 Bash Script:</label>
63
- <textarea [(ngModel)]="bashScript"
64
- placeholder="mkdir -p $(dirname &quot;src/test.js&quot;)&#10;cat <<'EOF' > src/test.js&#10;console.log('Hello World');&#10;EOF"></textarea>
65
- </div>
66
- <div class="btn-group">
67
- <button class="btn" (click)="execute()" [disabled]="executeLoading">
68
- <span *ngIf="!executeLoading">▶️</span>
69
- <span *ngIf="executeLoading" class="loading"></span>
70
- <span>{{ executeLoading ? 'Executing...' : 'Execute Script' }}</span>
71
- </button>
72
- <button class="btn" (click)="executeFromClipboard()" [disabled]="executeLoading">
73
- <span>📋</span>
74
- <span>Execute from Clipboard</span>
75
- </button>
76
- </div>
77
- <div class="response" *ngIf="executeResult" [class.success]="executeResult.success"
78
- [class.error]="!executeResult.success">
79
- <pre>{{ executeResult | json }}</pre>
80
- </div>
81
- </div>
82
- </div>
83
- </div>
84
-
85
- <div class="toast" [class.show]="showToast" [ngClass]="toastType">
86
- {{ toastMessage }}
87
- </div>
@@ -1,290 +0,0 @@
1
- .container {
2
- max-width: 1000px;
3
- margin: 0 auto;
4
- padding: 20px;
5
- }
6
-
7
- .header {
8
- background: white;
9
- border-radius: 12px;
10
- padding: 30px;
11
- margin-bottom: 30px;
12
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
13
- }
14
-
15
- .header h1 {
16
- color: #667eea;
17
- font-size: 2.5em;
18
- margin-bottom: 10px;
19
- }
20
-
21
- .header p {
22
- color: #666;
23
- font-size: 1.1em;
24
- }
25
-
26
- .status {
27
- display: inline-block;
28
- padding: 8px 16px;
29
- background: #10b981;
30
- color: white;
31
- border-radius: 20px;
32
- font-size: 0.9em;
33
- margin-top: 10px;
34
- }
35
-
36
- .system-prompt-card {
37
- background: white;
38
- border-radius: 12px;
39
- padding: 25px;
40
- margin-bottom: 30px;
41
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
42
- }
43
-
44
- .system-prompt-header {
45
- display: flex;
46
- justify-content: space-between;
47
- align-items: center;
48
- margin-bottom: 15px;
49
- cursor: pointer;
50
- user-select: none;
51
- }
52
-
53
- .system-prompt-header h2 {
54
- color: #667eea;
55
- font-size: 1.5em;
56
- display: flex;
57
- align-items: center;
58
- gap: 10px;
59
- }
60
-
61
- .toggle-icon {
62
- transition: transform 0.3s ease;
63
- }
64
-
65
- .toggle-icon.open {
66
- transform: rotate(180deg);
67
- }
68
-
69
- .system-prompt-content {
70
- max-height: 0;
71
- overflow: hidden;
72
- transition: max-height 0.3s ease;
73
- }
74
-
75
- .system-prompt-content.open {
76
- max-height: 2000px;
77
- }
78
-
79
- .prompt-text {
80
- background: #f9fafb;
81
- border: 2px solid #e5e7eb;
82
- border-radius: 8px;
83
- padding: 20px;
84
- font-family: 'Courier New', monospace;
85
- font-size: 0.9em;
86
- line-height: 1.6;
87
- white-space: pre-wrap;
88
- max-height: 400px;
89
- overflow-y: auto;
90
- margin-bottom: 15px;
91
- }
92
-
93
- .endpoints {
94
- display: grid;
95
- gap: 20px;
96
- }
97
-
98
- .endpoint-card {
99
- background: white;
100
- border-radius: 12px;
101
- padding: 30px;
102
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
103
- }
104
-
105
- .endpoint-header {
106
- display: flex;
107
- align-items: center;
108
- gap: 15px;
109
- margin-bottom: 20px;
110
- }
111
-
112
- .method {
113
- padding: 8px 16px;
114
- border-radius: 6px;
115
- font-weight: bold;
116
- font-size: 0.9em;
117
- }
118
-
119
- .method.post {
120
- background: #10b981;
121
- color: white;
122
- }
123
-
124
- .endpoint-path {
125
- font-family: 'Courier New', monospace;
126
- color: #333;
127
- font-size: 1.2em;
128
- font-weight: 600;
129
- }
130
-
131
- .endpoint-desc {
132
- color: #666;
133
- margin-bottom: 20px;
134
- line-height: 1.6;
135
- font-size: 1.05em;
136
- }
137
-
138
- .form-group {
139
- margin-bottom: 20px;
140
- }
141
-
142
- .form-group label {
143
- display: block;
144
- margin-bottom: 8px;
145
- color: #333;
146
- font-weight: 600;
147
- font-size: 1em;
148
- }
149
-
150
- .form-group input,
151
- .form-group textarea {
152
- width: 100%;
153
- padding: 12px;
154
- border: 2px solid #e5e7eb;
155
- border-radius: 8px;
156
- font-size: 1em;
157
- font-family: 'Courier New', monospace;
158
- transition: border-color 0.3s ease;
159
- }
160
-
161
- .form-group input:focus,
162
- .form-group textarea:focus {
163
- outline: none;
164
- border-color: #667eea;
165
- }
166
-
167
- .form-group textarea {
168
- min-height: 150px;
169
- resize: vertical;
170
- }
171
-
172
- .btn-group {
173
- display: flex;
174
- gap: 10px;
175
- margin-top: 20px;
176
- }
177
-
178
- .btn {
179
- background: #667eea;
180
- color: white;
181
- border: none;
182
- padding: 14px 28px;
183
- border-radius: 8px;
184
- cursor: pointer;
185
- font-size: 1em;
186
- font-weight: 600;
187
- transition: all 0.3s ease;
188
- display: inline-flex;
189
- align-items: center;
190
- gap: 8px;
191
- }
192
-
193
- .btn:hover {
194
- background: #5568d3;
195
- transform: translateY(-2px);
196
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
197
- }
198
-
199
- .btn:disabled {
200
- background: #9ca3af;
201
- cursor: not-allowed;
202
- transform: none;
203
- }
204
-
205
- .btn-copy {
206
- background: #10b981;
207
- }
208
-
209
- .btn-copy:hover {
210
- background: #059669;
211
- box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
212
- }
213
-
214
- .btn-copy.copied {
215
- background: #6366f1;
216
- }
217
-
218
- .response {
219
- margin-top: 20px;
220
- padding: 20px;
221
- border-radius: 8px;
222
- background: #f9fafb;
223
- border-left: 4px solid #667eea;
224
- }
225
-
226
- .response.success {
227
- border-left-color: #10b981;
228
- background: #f0fdf4;
229
- }
230
-
231
- .response.error {
232
- border-left-color: #ef4444;
233
- background: #fef2f2;
234
- }
235
-
236
- .response pre {
237
- margin: 0;
238
- font-family: 'Courier New', monospace;
239
- font-size: 0.95em;
240
- white-space: pre-wrap;
241
- word-wrap: break-word;
242
- }
243
-
244
- .loading {
245
- display: inline-block;
246
- width: 16px;
247
- height: 16px;
248
- border: 3px solid rgba(255, 255, 255, .3);
249
- border-radius: 50%;
250
- border-top-color: white;
251
- animation: spin 1s ease-in-out infinite;
252
- }
253
-
254
- @keyframes spin {
255
- to {
256
- transform: rotate(360deg);
257
- }
258
- }
259
-
260
- .toast {
261
- position: fixed;
262
- top: 20px;
263
- right: 20px;
264
- padding: 16px 24px;
265
- border-radius: 8px;
266
- color: white;
267
- font-weight: 600;
268
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
269
- opacity: 0;
270
- transform: translateY(-20px);
271
- transition: all 0.3s ease;
272
- z-index: 1000;
273
- }
274
-
275
- .toast.show {
276
- opacity: 1;
277
- transform: translateY(0);
278
- }
279
-
280
- .toast.success {
281
- background: #10b981;
282
- }
283
-
284
- .toast.error {
285
- background: #ef4444;
286
- }
287
-
288
- .toast.info {
289
- background: #3b82f6;
290
- }
@@ -1,236 +0,0 @@
1
- import { Component, OnInit } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
- import { ApiService } from '../services/api.service';
5
-
6
- @Component({
7
- selector: 'app-dashboard',
8
- standalone: true,
9
- imports: [CommonModule, FormsModule],
10
- templateUrl: './dashboard.component.html',
11
- styleUrls: ['./dashboard.component.scss']
12
- })
13
- export class DashboardComponent implements OnInit {
14
- systemPrompt = '';
15
- isPromptOpen = false;
16
- analyzePath = '.';
17
- analyzeResult: string | null = null;
18
- analyzeLoading = false;
19
-
20
- bashScript = '';
21
- executeResult: any = null;
22
- executeLoading = false;
23
-
24
- toastMessage = '';
25
- toastType = 'success';
26
- showToast = false;
27
-
28
- constructor(private apiService: ApiService) { }
29
-
30
- ngOnInit() {
31
- this.systemPrompt = `# VG Coder AI System Prompt
32
-
33
- ## Command Prefixes
34
-
35
- ### /ask - Question & Answer Mode
36
- Khi người dùng hỏi với prefix /ask, họ đang muốn tìm hiểu hoặc được giải thích về một vấn đề.
37
-
38
- **Response Format:** Markdown
39
- - Trả lời chi tiết, rõ ràng
40
- - Sử dụng code blocks, lists, tables khi cần
41
- - Cung cấp ví dụ minh họa
42
-
43
- ---
44
-
45
- ### /plan - Planning Mode
46
- Khi người dùng muốn lên kế hoạch với prefix /plan, tạo một implementation plan chi tiết.
47
-
48
- **Response Format:** Markdown checklist với bash commands
49
- - Chia nhỏ thành các bước cụ thể
50
- - Mỗi bước có bash command tương ứng
51
- - Sắp xếp theo thứ tự logic
52
-
53
- ---
54
-
55
- ### /fix - Bug Fix Mode
56
- Khi người dùng cần fix bug với prefix /fix, phân tích lỗi và đưa ra giải pháp.
57
-
58
- **Response Format:** Markdown + Bash script
59
- 1. **Phân tích lỗi:** Giải thích nguyên nhân
60
- 2. **Giải pháp:** Mô tả cách fix
61
- 3. **Bash script:** Code để fix (nếu cần)
62
-
63
- ---
64
-
65
- ### /code - Code Generation Mode
66
- Khi người dùng hỏi với prefix /code, trả về **BASH SCRIPT DUY NHẤT** để tạo/cập nhật files.
67
-
68
- ## ⚠️ QUY TẮC BẮT BUỘC
69
-
70
- ### 1. Chỉ bao gồm files có thay đổi
71
- - ❌ **KHÔNG** bao gồm files không có sự thay đổi nội dung
72
- - ✅ Nếu nội dung file sau chỉnh sửa giống 100% bản cũ → **BỎ QUA**
73
-
74
- ### 2. Format Script Chuẩn
75
-
76
- **Mỗi file PHẢI theo cú pháp:**
77
- \`\`\`bash
78
- mkdir -p $(dirname "path/to/file.ext")
79
- cat <<'EOF' > path/to/file.ext
80
- ... toàn bộ nội dung file sau khi chỉnh sửa ...
81
- EOF
82
- \`\`\`
83
-
84
- ### 3. Chi tiết quan trọng
85
- - ✅ **LUÔN** có \`mkdir -p $(dirname "...")\` trước mỗi file
86
- - ✅ Sử dụng \`<<'EOF'\` (có dấu nháy đơn) để tránh bash expansion
87
- - ✅ Ghi đè hoàn toàn file bằng nội dung mới
88
- - ✅ Tự động tạo file và thư mục cha nếu chưa tồn tại
89
- - ✅ Đường dẫn giống với file mẫu đính kèm
90
-
91
- ### 4. Example Output
92
-
93
- \`\`\`bash
94
- # Create/Update component file
95
- mkdir -p $(dirname "src/components/Button/index.tsx")
96
- cat <<'EOF' > src/components/Button/index.tsx
97
- import React from 'react';
98
-
99
- export const Button = () => {
100
- return <button>Click me</button>;
101
- };
102
- EOF
103
-
104
- # Create/Update styles
105
- mkdir -p $(dirname "src/components/Button/styles.css")
106
- cat <<'EOF' > src/components/Button/styles.css
107
- .button {
108
- padding: 10px 20px;
109
- background: blue;
110
- }
111
- EOF
112
- \`\`\`
113
-
114
- ---
115
-
116
- ## Integration với VG Coder CLI
117
-
118
- Bash scripts được generate sẽ được thực thi qua:
119
- \`\`\`bash
120
- POST http://localhost:6868/api/execute
121
- {
122
- "bash": "mkdir -p $(dirname \\"src/...\\")\\\\ncat <<'EOF' > ..."
123
- }
124
- \`\`\`
125
-
126
- API sẽ:
127
- 1. ✅ Validate bash syntax trong \`.vg/temp-execute\`
128
- 2. ✅ Execute tại working directory nếu syntax OK
129
- 3. ✅ Trả về stdout/stderr/exitCode
130
- 4. ✅ Auto cleanup temp directory
131
-
132
- ---
133
-
134
- ## Best Practices
135
-
136
- ### DO ✅
137
- - Luôn dùng \`mkdir -p $(dirname "...")\` trước mỗi file
138
- - Sử dụng \`<<'EOF'\` để tránh variable expansion
139
- - Ghi đè toàn bộ nội dung file
140
- - Chỉ include files có thay đổi thực sự
141
-
142
- ### DON'T ❌
143
- - Không tạo file mà không tạo thư mục cha
144
- - Không dùng \`<<EOF\` (thiếu quotes) nếu có \`$\` trong content
145
- - Không include files không thay đổi
146
- - Không dùng relative paths phức tạp`;
147
- }
148
-
149
- toggleSystemPrompt() {
150
- this.isPromptOpen = !this.isPromptOpen;
151
- }
152
-
153
- copySystemPrompt() {
154
- navigator.clipboard.writeText(this.systemPrompt).then(() => {
155
- this.showToastMessage('✅ Copied System Prompt!', 'success');
156
- });
157
- }
158
-
159
- async analyze() {
160
- this.analyzeLoading = true;
161
- this.apiService.analyze(this.analyzePath).subscribe({
162
- next: (res) => {
163
- this.analyzeResult = res;
164
- this.analyzeLoading = false;
165
-
166
- // Download file
167
- const blob = new Blob([res], { type: 'text/plain' });
168
- const url = window.URL.createObjectURL(blob);
169
- const a = document.createElement('a');
170
- a.href = url;
171
- a.download = 'project.txt';
172
- a.click();
173
-
174
- this.showToastMessage('✅ Analysis completed & downloaded!', 'success');
175
- },
176
- error: (err) => {
177
- this.analyzeLoading = false;
178
- this.showToastMessage('❌ Analysis failed: ' + err.message, 'error');
179
- }
180
- });
181
- }
182
-
183
- copyAnalyzeResult() {
184
- if (this.analyzeResult) {
185
- navigator.clipboard.writeText(this.analyzeResult).then(() => {
186
- this.showToastMessage('✅ Copied project.txt!', 'success');
187
- });
188
- }
189
- }
190
-
191
- async execute() {
192
- if (!this.bashScript.trim()) return;
193
-
194
- this.executeLoading = true;
195
- this.apiService.execute(this.bashScript).subscribe({
196
- next: (res) => {
197
- this.executeResult = res;
198
- this.executeLoading = false;
199
- if (res.success) {
200
- this.showToastMessage('✅ Execution successful!', 'success');
201
- } else {
202
- this.showToastMessage('❌ Execution failed!', 'error');
203
- }
204
- },
205
- error: (err) => {
206
- this.executeLoading = false;
207
- this.executeResult = { error: err.message };
208
- this.showToastMessage('❌ Execution error: ' + err.message, 'error');
209
- }
210
- });
211
- }
212
-
213
- async executeFromClipboard() {
214
- try {
215
- const text = await navigator.clipboard.readText();
216
- if (!text.trim()) {
217
- this.showToastMessage('⚠️ Clipboard is empty!', 'error');
218
- return;
219
- }
220
-
221
- this.bashScript = text;
222
- this.execute();
223
- } catch (err: any) {
224
- this.showToastMessage('❌ Clipboard error: ' + err.message, 'error');
225
- }
226
- }
227
-
228
- showToastMessage(msg: string, type: 'success' | 'error' | 'info') {
229
- this.toastMessage = msg;
230
- this.toastType = type;
231
- this.showToast = true;
232
- setTimeout(() => {
233
- this.showToast = false;
234
- }, 3000);
235
- }
236
- }