@172ai/containers-mcp-server 1.12.5 → 1.12.7

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/dist/server.js CHANGED
@@ -7,6 +7,7 @@ import { config } from './config.js';
7
7
  import { authManager } from './auth.js';
8
8
  import { containerService } from './services/containerService.js';
9
9
  import { buildService } from './services/buildService.js';
10
+ import { fixService } from './services/fixService.js';
10
11
  import { fileService } from './services/fileService.js';
11
12
  import { capabilityService } from './services/capabilityService.js';
12
13
  import { executionService } from './services/executionService.js';
@@ -15,6 +16,7 @@ import { exportService } from './services/exportService.js';
15
16
  import { streamingService } from './services/streamingService.js';
16
17
  import { userNotificationManager } from './services/userNotificationManager.js';
17
18
  import { userService } from './services/userService.js';
19
+ import { modificationService } from './services/modificationService.js';
18
20
  import { ErrorHandler } from './utils/errorHandler.js';
19
21
  /**
20
22
  * 172.ai Container Management MCP Server
@@ -30,9 +32,11 @@ class ContainerMCPServer {
30
32
  });
31
33
  // Initialize MCP server reference for progress notifications
32
34
  buildService.setMCPServer(this.server);
35
+ fixService.setMCPServer(this.server);
33
36
  executionService.setMCPServer(this.server);
34
37
  importService.setMCPServer(this.server);
35
38
  exportService.setMCPServer(this.server);
39
+ modificationService.setMCPServer(this.server);
36
40
  this.setupTools();
37
41
  this.setupErrorHandlers();
38
42
  this.initializeStreaming();
@@ -83,6 +87,8 @@ class ContainerMCPServer {
83
87
  this.setupContainerTools();
84
88
  // Build Management Tools
85
89
  this.setupBuildTools();
90
+ // Fix Management Tools
91
+ this.setupFixTools();
86
92
  // File Management Tools
87
93
  this.setupFileTools();
88
94
  // Capability Management Tools
@@ -90,6 +96,13 @@ class ContainerMCPServer {
90
96
  // Execution Management Tools
91
97
  this.setupExecutionTools();
92
98
  }
99
+ /**
100
+ * Set up container fix management tools
101
+ */
102
+ setupFixTools() {
103
+ // Fix tools are registered via CallToolRequestSchema handler
104
+ // No separate setup needed - they share the same request handler
105
+ }
93
106
  /**
94
107
  * Set up container management tools
95
108
  */
@@ -158,6 +171,16 @@ class ContainerMCPServer {
158
171
  return await this.handleCancelBuildMonitoring(args);
159
172
  case 'get_stream_analytics':
160
173
  return await this.handleGetStreamAnalytics(args);
174
+ case 'fix_container':
175
+ return await this.handleFixContainer(args);
176
+ case 'analyze_container_failure':
177
+ return await this.handleAnalyzeContainerFailure(args);
178
+ case 'approve_and_apply_fix':
179
+ return await this.handleApproveAndApplyFix(args);
180
+ case 'get_fix_history':
181
+ return await this.handleGetFixHistory(args);
182
+ case 'get_fix_status':
183
+ return await this.handleGetFixStatus(args);
161
184
  case 'import_container':
162
185
  return await this.handleImportContainer(args);
163
186
  case 'get_import_status':
@@ -236,6 +259,16 @@ class ContainerMCPServer {
236
259
  return await this.handleGetExecutionProgressUpdate(args);
237
260
  case 'get_all_progress_updates':
238
261
  return await this.handleGetAllProgressUpdates(args);
262
+ case 'list_modifications':
263
+ return await this.handleListModifications(args);
264
+ case 'suggest_container_modifications':
265
+ return await this.handleSuggestContainerModifications(args);
266
+ case 'apply_container_modification':
267
+ return await this.handleApplyContainerModification(args);
268
+ case 'get_modification_status':
269
+ return await this.handleGetModificationStatus(args);
270
+ case 'list_applied_modifications':
271
+ return await this.handleListAppliedModifications(args);
239
272
  default:
240
273
  throw ErrorHandler.createValidationError(`Unknown tool: ${name}`);
241
274
  }
@@ -765,6 +798,109 @@ Follow same metadata requirements as create_container.`,
765
798
  }
766
799
  }
767
800
  },
801
+ // Fix Management Tools
802
+ {
803
+ name: 'fix_container',
804
+ description: 'Analyze container build failure, apply AI-generated fix, and rebuild automatically. This is the primary fix workflow that combines analysis, application, and rebuild into one operation.',
805
+ inputSchema: {
806
+ type: 'object',
807
+ properties: {
808
+ containerId: {
809
+ type: 'string',
810
+ description: 'ID of the container to fix'
811
+ },
812
+ autoApply: {
813
+ type: 'boolean',
814
+ description: 'Whether to automatically apply the fix after analysis (default: true). Set to false for analyze-only mode.',
815
+ default: true
816
+ },
817
+ progressToken: {
818
+ type: 'string',
819
+ description: 'Optional token for receiving real-time progress notifications during fix operation'
820
+ }
821
+ },
822
+ required: ['containerId']
823
+ }
824
+ },
825
+ {
826
+ name: 'analyze_container_failure',
827
+ description: 'Analyze container build/execution failure and generate fix suggestions WITHOUT automatically applying them. Returns fixAttemptId for later approval.',
828
+ inputSchema: {
829
+ type: 'object',
830
+ properties: {
831
+ containerId: {
832
+ type: 'string',
833
+ description: 'ID of the container to analyze'
834
+ },
835
+ progressToken: {
836
+ type: 'string',
837
+ description: 'Optional token for receiving real-time progress notifications'
838
+ }
839
+ },
840
+ required: ['containerId']
841
+ }
842
+ },
843
+ {
844
+ name: 'approve_and_apply_fix',
845
+ description: 'Apply a specific fix attempt and trigger automatic rebuild. Use this after reviewing analysis results from analyze_container_failure.',
846
+ inputSchema: {
847
+ type: 'object',
848
+ properties: {
849
+ containerId: {
850
+ type: 'string',
851
+ description: 'ID of the container'
852
+ },
853
+ fixAttemptId: {
854
+ type: 'string',
855
+ description: 'ID of the fix attempt to apply (from analyze_container_failure result)'
856
+ },
857
+ progressToken: {
858
+ type: 'string',
859
+ description: 'Optional token for receiving real-time progress notifications'
860
+ }
861
+ },
862
+ required: ['containerId', 'fixAttemptId']
863
+ }
864
+ },
865
+ {
866
+ name: 'get_fix_history',
867
+ description: 'Get the history of fix attempts for a container, showing all previous fixes and their outcomes',
868
+ inputSchema: {
869
+ type: 'object',
870
+ properties: {
871
+ containerId: {
872
+ type: 'string',
873
+ description: 'ID of the container'
874
+ },
875
+ limit: {
876
+ type: 'number',
877
+ minimum: 1,
878
+ maximum: 100,
879
+ description: 'Maximum number of fix attempts to return (default: 10)',
880
+ default: 10
881
+ }
882
+ },
883
+ required: ['containerId']
884
+ }
885
+ },
886
+ {
887
+ name: 'get_fix_status',
888
+ description: 'Get detailed status and information about a specific fix attempt',
889
+ inputSchema: {
890
+ type: 'object',
891
+ properties: {
892
+ containerId: {
893
+ type: 'string',
894
+ description: 'ID of the container'
895
+ },
896
+ fixAttemptId: {
897
+ type: 'string',
898
+ description: 'ID of the fix attempt to retrieve'
899
+ }
900
+ },
901
+ required: ['containerId', 'fixAttemptId']
902
+ }
903
+ },
768
904
  // Import Management Tools
769
905
  {
770
906
  name: 'import_container',
@@ -1616,6 +1752,130 @@ Follow same metadata requirements as create_container.`,
1616
1752
  type: 'object',
1617
1753
  properties: {}
1618
1754
  }
1755
+ },
1756
+ // Modification Management Tools
1757
+ {
1758
+ name: 'list_modifications',
1759
+ description: 'List all available modifications in the catalog',
1760
+ inputSchema: {
1761
+ type: 'object',
1762
+ properties: {
1763
+ category: {
1764
+ type: 'string',
1765
+ description: 'Filter by category (optional)'
1766
+ },
1767
+ tags: {
1768
+ type: 'string',
1769
+ description: 'Filter by tags (comma-separated, optional)'
1770
+ },
1771
+ active: {
1772
+ type: 'boolean',
1773
+ default: true,
1774
+ description: 'Filter by active status (default: true)'
1775
+ }
1776
+ }
1777
+ }
1778
+ },
1779
+ {
1780
+ name: 'suggest_container_modifications',
1781
+ description: 'Get AI-powered modification suggestions for a container',
1782
+ inputSchema: {
1783
+ type: 'object',
1784
+ properties: {
1785
+ containerId: {
1786
+ type: 'string',
1787
+ description: 'ID of the container to analyze'
1788
+ },
1789
+ categories: {
1790
+ type: 'array',
1791
+ items: { type: 'string' },
1792
+ description: 'Filter suggestions by categories (optional)'
1793
+ },
1794
+ includeRisks: {
1795
+ type: 'boolean',
1796
+ default: true,
1797
+ description: 'Include risk assessment (default: true)'
1798
+ }
1799
+ },
1800
+ required: ['containerId']
1801
+ }
1802
+ },
1803
+ {
1804
+ name: 'apply_container_modification',
1805
+ description: 'Apply a modification to a container',
1806
+ inputSchema: {
1807
+ type: 'object',
1808
+ properties: {
1809
+ containerId: {
1810
+ type: 'string',
1811
+ description: 'ID of the container'
1812
+ },
1813
+ modificationId: {
1814
+ type: 'string',
1815
+ description: 'ID of the modification to apply'
1816
+ },
1817
+ autoBuild: {
1818
+ type: 'boolean',
1819
+ default: true,
1820
+ description: 'Automatically build after applying (default: true)'
1821
+ },
1822
+ notes: {
1823
+ type: 'string',
1824
+ description: 'Optional notes about this application'
1825
+ }
1826
+ },
1827
+ required: ['containerId', 'modificationId']
1828
+ }
1829
+ },
1830
+ {
1831
+ name: 'get_modification_status',
1832
+ description: 'Get detailed information about a specific modification application',
1833
+ inputSchema: {
1834
+ type: 'object',
1835
+ properties: {
1836
+ containerId: {
1837
+ type: 'string',
1838
+ description: 'ID of the container'
1839
+ },
1840
+ modificationApplicationId: {
1841
+ type: 'string',
1842
+ description: 'ID of the modification application'
1843
+ }
1844
+ },
1845
+ required: ['containerId', 'modificationApplicationId']
1846
+ }
1847
+ },
1848
+ {
1849
+ name: 'list_applied_modifications',
1850
+ description: 'List modifications applied to a specific container',
1851
+ inputSchema: {
1852
+ type: 'object',
1853
+ properties: {
1854
+ containerId: {
1855
+ type: 'string',
1856
+ description: 'ID of the container'
1857
+ },
1858
+ status: {
1859
+ type: 'string',
1860
+ enum: ['in_progress', 'completed', 'failed'],
1861
+ description: 'Filter by status (optional)'
1862
+ },
1863
+ limit: {
1864
+ type: 'number',
1865
+ minimum: 1,
1866
+ maximum: 100,
1867
+ default: 50,
1868
+ description: 'Maximum number of results (default: 50)'
1869
+ },
1870
+ offset: {
1871
+ type: 'number',
1872
+ minimum: 0,
1873
+ default: 0,
1874
+ description: 'Number of results to skip (default: 0)'
1875
+ }
1876
+ },
1877
+ required: ['containerId']
1878
+ }
1619
1879
  }
1620
1880
  ];
1621
1881
  }
@@ -1939,6 +2199,151 @@ Follow same metadata requirements as create_container.`,
1939
2199
  ],
1940
2200
  };
1941
2201
  }
2202
+ // Fix handler methods
2203
+ async handleFixContainer(args) {
2204
+ const { progressToken, autoApply = true, ...fixParams } = args;
2205
+ const result = await fixService.fixContainer({
2206
+ containerId: args.containerId,
2207
+ autoApply,
2208
+ progressToken
2209
+ });
2210
+ return {
2211
+ content: [
2212
+ {
2213
+ type: 'text',
2214
+ text: `🔧 Fix operation ${autoApply ? 'started' : 'analyzed'} for container ${args.containerId}!\n\n` +
2215
+ `Fix Attempt ID: ${result.fixAttemptId}\n` +
2216
+ `Status: ${autoApply ? 'Applying fix and rebuilding' : 'Analysis complete - awaiting approval'}\n` +
2217
+ `Message: ${result.message}\n` +
2218
+ `${result.analysis ? `\nDiagnostic: ${result.analysis.diagnosticSummary}\nRoot Cause: ${result.analysis.rootCause}\n` : ''}` +
2219
+ `${result.buildStatus ? `Build Status: ${result.buildStatus}\n` : ''}` +
2220
+ `${progressToken ? `\n🔄 Progress updates will be sent via notifications using token: ${progressToken}` : ''}`,
2221
+ },
2222
+ ],
2223
+ };
2224
+ }
2225
+ async handleAnalyzeContainerFailure(args) {
2226
+ const { progressToken } = args;
2227
+ const result = await fixService.analyzeFailure({
2228
+ containerId: args.containerId,
2229
+ progressToken
2230
+ });
2231
+ return {
2232
+ content: [
2233
+ {
2234
+ type: 'text',
2235
+ text: `**Container Failure Analysis**\n\n` +
2236
+ `Fix Attempt ID: ${result.fixAttemptId}\n` +
2237
+ `Attempt: ${result.attemptNumber} of ${result.maxAttempts}\n` +
2238
+ `Previous Attempts: ${result.previousAttempts}\n\n` +
2239
+ `**Diagnostic Summary**\n${result.diagnosticSummary}\n\n` +
2240
+ `**Root Cause**\n${result.rootCause}\n\n` +
2241
+ `**Proposed Fix**\n${result.fixApproach}\n\n` +
2242
+ `**Severity**: ${result.severity}\n` +
2243
+ `**Fix Confidence**: ${result.fixConfidence}\n` +
2244
+ `**Affected Files**: ${result.affectedFiles.join(', ')}\n\n` +
2245
+ `💡 Use approve_and_apply_fix with fixAttemptId: ${result.fixAttemptId} to apply this fix`,
2246
+ },
2247
+ ],
2248
+ };
2249
+ }
2250
+ async handleApproveAndApplyFix(args) {
2251
+ const { progressToken } = args;
2252
+ const result = await fixService.applyFix({
2253
+ containerId: args.containerId,
2254
+ fixAttemptId: args.fixAttemptId,
2255
+ progressToken
2256
+ });
2257
+ return {
2258
+ content: [
2259
+ {
2260
+ type: 'text',
2261
+ text: `✅ Fix approved and applied!\n\n` +
2262
+ `Fix Attempt ID: ${result.fixAttemptId}\n` +
2263
+ `Container ID: ${result.containerId}\n` +
2264
+ `Message: ${result.message}\n` +
2265
+ `Build Status: ${result.buildStatus}\n` +
2266
+ `${progressToken ? `\n🔄 Progress updates will be sent via notifications using token: ${progressToken}` : ''}`,
2267
+ },
2268
+ ],
2269
+ };
2270
+ }
2271
+ async handleGetFixHistory(args) {
2272
+ const result = await fixService.getFixHistory({
2273
+ containerId: args.containerId,
2274
+ limit: args.limit || 10
2275
+ });
2276
+ if (result.fixes.length === 0) {
2277
+ return {
2278
+ content: [
2279
+ {
2280
+ type: 'text',
2281
+ text: `No fix attempts found for container ${args.containerId}`,
2282
+ },
2283
+ ],
2284
+ };
2285
+ }
2286
+ let historyText = `**Fix History for Container ${args.containerId}**\n\n` +
2287
+ `Found ${result.totalCount} fix attempt(s):\n\n`;
2288
+ result.fixes.forEach((fix, index) => {
2289
+ historyText += `${index + 1}. **Fix ${fix.id}**\n` +
2290
+ ` • Attempt Number: ${fix.attemptNumber}\n` +
2291
+ ` • Status: ${fix.status}\n` +
2292
+ ` • Severity: ${fix.severity}\n` +
2293
+ ` • Confidence: ${fix.fixConfidence}\n` +
2294
+ ` • Created: ${fix.createdAt}\n` +
2295
+ ` ${fix.appliedAt ? `• Applied: ${fix.appliedAt}\n` : ''}` +
2296
+ ` ${fix.completedAt ? `• Completed: ${fix.completedAt}\n` : ''}` +
2297
+ ` ${fix.errorMessage ? `• Error: ${fix.errorMessage}\n` : ''}\n`;
2298
+ });
2299
+ return {
2300
+ content: [
2301
+ {
2302
+ type: 'text',
2303
+ text: historyText,
2304
+ },
2305
+ ],
2306
+ };
2307
+ }
2308
+ async handleGetFixStatus(args) {
2309
+ const result = await fixService.getFixStatus({
2310
+ containerId: args.containerId,
2311
+ fixAttemptId: args.fixAttemptId
2312
+ });
2313
+ let statusText = `**Fix Attempt Status**\n\n` +
2314
+ `Fix ID: ${result.id}\n` +
2315
+ `Container ID: ${result.containerId}\n` +
2316
+ `Attempt Number: ${result.attemptNumber}\n` +
2317
+ `Status: ${result.status}\n` +
2318
+ `Severity: ${result.severity}\n` +
2319
+ `Fix Confidence: ${result.fixConfidence}\n\n` +
2320
+ `**Diagnostic Summary**\n${result.diagnosticSummary}\n\n` +
2321
+ `**Root Cause**\n${result.rootCause}\n\n` +
2322
+ `**Fix Approach**\n${result.fixApproach}\n\n` +
2323
+ `**Timeline**\n` +
2324
+ `• Created: ${result.createdAt}\n` +
2325
+ `${result.updatedAt ? `• Updated: ${result.updatedAt}\n` : ''}` +
2326
+ `${result.appliedAt ? `• Applied: ${result.appliedAt}\n` : ''}` +
2327
+ `${result.completedAt ? `• Completed: ${result.completedAt}\n` : ''}`;
2328
+ if (result.fileChanges && result.fileChanges.length > 0) {
2329
+ statusText += `\n**File Changes (${result.fileChanges.length})**\n`;
2330
+ result.fileChanges.forEach((change, index) => {
2331
+ statusText += `${index + 1}. ${change.filePath} (${change.changeType})\n` +
2332
+ ` Reason: ${change.changeReason}\n`;
2333
+ });
2334
+ }
2335
+ if (result.errorMessage) {
2336
+ statusText += `\n❌ **Error**: ${result.errorMessage}\n`;
2337
+ }
2338
+ return {
2339
+ content: [
2340
+ {
2341
+ type: 'text',
2342
+ text: statusText,
2343
+ },
2344
+ ],
2345
+ };
2346
+ }
1942
2347
  // Import handler methods
1943
2348
  async handleImportContainer(args) {
1944
2349
  const { progressToken, ...importParams } = args;
@@ -2856,6 +3261,148 @@ Follow same metadata requirements as create_container.`,
2856
3261
  ],
2857
3262
  };
2858
3263
  }
3264
+ /**
3265
+ * Handle list modifications
3266
+ */
3267
+ async handleListModifications(args) {
3268
+ const { category, tags, active = true } = args;
3269
+ const result = await modificationService.listModifications(category, tags, active);
3270
+ let responseText = `**Available Modifications**\n\n`;
3271
+ responseText += `Found ${result.count} modification(s)\n\n`;
3272
+ result.modifications.forEach((mod, index) => {
3273
+ responseText += `${index + 1}. **${mod.name}** (${mod.modificationId})\n`;
3274
+ responseText += ` Category: ${mod.category}\n`;
3275
+ responseText += ` Description: ${mod.description}\n`;
3276
+ if (mod.estimatedImpact) {
3277
+ responseText += ` Impact: ${mod.estimatedImpact}\n`;
3278
+ }
3279
+ if (mod.priority) {
3280
+ responseText += ` Priority: ${mod.priority}\n`;
3281
+ }
3282
+ if (mod.tags && mod.tags.length > 0) {
3283
+ responseText += ` Tags: ${mod.tags.join(', ')}\n`;
3284
+ }
3285
+ if (mod.risks) {
3286
+ responseText += ` ⚠️ Risks: ${mod.risks}\n`;
3287
+ }
3288
+ responseText += `\n`;
3289
+ });
3290
+ return {
3291
+ content: [
3292
+ {
3293
+ type: 'text',
3294
+ text: responseText,
3295
+ },
3296
+ ],
3297
+ };
3298
+ }
3299
+ /**
3300
+ * Handle suggest container modifications
3301
+ */
3302
+ async handleSuggestContainerModifications(args) {
3303
+ const { containerId, categories, includeRisks = true } = args;
3304
+ const result = await modificationService.suggestModifications(containerId, categories, includeRisks);
3305
+ let responseText = `**AI-Powered Modification Suggestions**\n\n`;
3306
+ if (result.recommendations.length > 0) {
3307
+ responseText += `📋 **Recommended Modifications (${result.recommendations.length})**\n\n`;
3308
+ result.recommendations.forEach((rec, index) => {
3309
+ responseText += modificationService.formatRecommendation(rec);
3310
+ responseText += `\n`;
3311
+ });
3312
+ }
3313
+ if (result.alreadyApplied.length > 0) {
3314
+ responseText += `\n✅ **Already Applied (${result.alreadyApplied.length})**\n`;
3315
+ result.alreadyApplied.forEach((id) => {
3316
+ responseText += `- ${id}\n`;
3317
+ });
3318
+ }
3319
+ if (result.notApplicable.length > 0) {
3320
+ responseText += `\n❌ **Not Applicable (${result.notApplicable.length})**\n`;
3321
+ result.notApplicable.forEach((item) => {
3322
+ responseText += `- ${item.name}: ${item.reason}\n`;
3323
+ });
3324
+ }
3325
+ return {
3326
+ content: [
3327
+ {
3328
+ type: 'text',
3329
+ text: responseText,
3330
+ },
3331
+ ],
3332
+ };
3333
+ }
3334
+ /**
3335
+ * Handle apply container modification
3336
+ */
3337
+ async handleApplyContainerModification(args) {
3338
+ const { containerId, modificationId, autoBuild = true, notes } = args;
3339
+ const result = await modificationService.applyModification({
3340
+ containerId,
3341
+ modificationId,
3342
+ autoBuild,
3343
+ notes
3344
+ });
3345
+ let responseText = `**Modification Applied**\n\n`;
3346
+ responseText += `🔄 Application ID: ${result.modificationApplicationId}\n`;
3347
+ responseText += `📊 Status: ${result.status}\n`;
3348
+ responseText += `⏱️ Estimated Completion: ${result.estimatedCompletionTime}\n`;
3349
+ responseText += `🔗 Stream Token: ${result.streamToken}\n\n`;
3350
+ responseText += `Progress notifications will be sent automatically via user-notifications stream.\n`;
3351
+ return {
3352
+ content: [
3353
+ {
3354
+ type: 'text',
3355
+ text: responseText,
3356
+ },
3357
+ ],
3358
+ };
3359
+ }
3360
+ /**
3361
+ * Handle get modification status
3362
+ */
3363
+ async handleGetModificationStatus(args) {
3364
+ const { containerId, modificationApplicationId } = args;
3365
+ const result = await modificationService.getModificationDetails(containerId, modificationApplicationId);
3366
+ const responseText = modificationService.formatAppliedModification(result);
3367
+ return {
3368
+ content: [
3369
+ {
3370
+ type: 'text',
3371
+ text: responseText,
3372
+ },
3373
+ ],
3374
+ };
3375
+ }
3376
+ /**
3377
+ * Handle list applied modifications
3378
+ */
3379
+ async handleListAppliedModifications(args) {
3380
+ const { containerId, status, limit = 50, offset = 0 } = args;
3381
+ const result = await modificationService.listAppliedModifications(containerId, status, limit, offset);
3382
+ let responseText = `**Applied Modifications**\n\n`;
3383
+ responseText += `Found ${result.count} modification(s)`;
3384
+ if (result.hasMore) {
3385
+ responseText += ` (showing ${result.appliedModifications.length})`;
3386
+ }
3387
+ responseText += `\n\n`;
3388
+ if (result.appliedModifications.length === 0) {
3389
+ responseText += `No modifications have been applied to this container yet.\n`;
3390
+ }
3391
+ else {
3392
+ result.appliedModifications.forEach((mod, index) => {
3393
+ responseText += modificationService.formatAppliedModification(mod);
3394
+ responseText += `\n`;
3395
+ });
3396
+ }
3397
+ return {
3398
+ content: [
3399
+ {
3400
+ type: 'text',
3401
+ text: responseText,
3402
+ },
3403
+ ],
3404
+ };
3405
+ }
2859
3406
  /**
2860
3407
  * Get container development workflow content
2861
3408
  */