@codemieai/cdk 0.1.626 → 0.1.628

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 CHANGED
@@ -321,6 +321,11 @@ npm run deploy # Deploy (updates state file with current checksums)
321
321
  - This happens when assistant doesn't exist in backup (e.g., deleted or from another project)
322
322
  - Manually replace with correct assistant name or ID in workflow YAML file
323
323
 
324
+ **All MCP Assistants Show as Changed After an Upgrade?**
325
+ - After upgrading to the release containing EPMCDME-14873, MCP server configuration is normalized before hashing, so every assistant with `mcp_servers` gets a new `configChecksum` once
326
+ - `preview` and `deploy` list each of them under `⚠️ UPDATE:` as `- assistant:<name>` with `Prompt or configuration changed` and no per-field diff
327
+ - Expected, not a configuration error - `deploy` stores the new `configChecksum` in `.codemie/state.json` and the next run reports them as unchanged
328
+
324
329
  **Resume From Specific Point?**
325
330
  - Transaction file tracks what's completed: `transaction.json`
326
331
  - Contains: `completed: ['ast-1', 'ast-2']` and `failed: [{id: 'ast-3', error: '...'}]`
@@ -792,6 +797,12 @@ Changes to prompts and configuration are detected via SHA256 checksums, ensuring
792
797
  - On deployment: Compare stored checksums with current checksums
793
798
  - Only update if either checksum differs
794
799
 
800
+ **One-time checksum change for assistants with MCP servers**
801
+
802
+ After upgrading to the release that contains EPMCDME-14873, MCP server configuration is normalized before it is hashed: keys with no value (`null`) and an empty top-level `mcp_connect_url` no longer contribute to the hash, and the remaining keys are hashed in a fixed order at every depth, so the order the platform or your YAML uses for MCP fields never affects the checksum. Every assistant that has `mcp_servers` therefore gets a new `configChecksum` once - and only once.
803
+
804
+ The first `npm run preview` (or `codemie preview`) and `npm run deploy` after the upgrade list each such assistant under `⚠️ UPDATE:` as `- assistant:<name>` followed by `Prompt or configuration changed`, with no per-field diff. This is expected and is not a configuration error - nothing in your `codemie.yaml` changed. `deploy` writes the new `configChecksum` back to `.codemie/state.json`, and the second run reports the same assistants as unchanged.
805
+
795
806
  ### Orphaned Resource Cleanup
796
807
 
797
808
  Resources removed from `codemie.yaml` are NOT automatically deleted by default. To remove them, you must explicitly use the `--prune` flag.
package/dist/cli/index.js CHANGED
@@ -243,6 +243,34 @@ var init_logger = __esm({
243
243
  logger = Logger.getInstance();
244
244
  }
245
245
  });
246
+
247
+ // src/lib/mcpSanitizer.ts
248
+ function isPlainObject(value) {
249
+ return typeof value === "object" && value !== null && !Array.isArray(value);
250
+ }
251
+ function sanitizeObject(obj, isTopLevel) {
252
+ const result = {};
253
+ for (const [key, value] of Object.entries(obj)) {
254
+ if (value === null || value === void 0) {
255
+ continue;
256
+ }
257
+ if (isTopLevel && key === "mcp_connect_url" && value === "") {
258
+ continue;
259
+ }
260
+ result[key] = isPlainObject(value) ? sanitizeObject(value, false) : value;
261
+ }
262
+ return result;
263
+ }
264
+ function sanitizeMcpServer(server) {
265
+ if (!isPlainObject(server)) {
266
+ return server;
267
+ }
268
+ return sanitizeObject(server, true);
269
+ }
270
+ var init_mcpSanitizer = __esm({
271
+ "src/lib/mcpSanitizer.ts"() {
272
+ }
273
+ });
246
274
  function normalizeIntegrationSettings(settings) {
247
275
  if (!settings || typeof settings !== "object") {
248
276
  return settings;
@@ -277,15 +305,34 @@ function normalizeToolkits(toolkits) {
277
305
  settings: normalizeIntegrationSettings(settings)
278
306
  }));
279
307
  }
308
+ function isPlainObject2(value) {
309
+ return typeof value === "object" && value !== null && !Array.isArray(value);
310
+ }
311
+ function sortKeysDeep(value) {
312
+ if (!isPlainObject2(value)) {
313
+ return value;
314
+ }
315
+ const sorted = {};
316
+ for (const key of Object.keys(value).sort()) {
317
+ sorted[key] = sortKeysDeep(value[key]);
318
+ }
319
+ return sorted;
320
+ }
280
321
  function normalizeMcpServers(mcpServers) {
281
322
  if (!mcpServers) {
282
323
  return [];
283
324
  }
284
- return mcpServers.map((mcp) => ({
285
- ...mcp,
286
- settings: normalizeIntegrationSettings(mcp.settings),
287
- mcp_connect_auth_token: normalizeIntegrationSettings(mcp.mcp_connect_auth_token)
288
- }));
325
+ return mcpServers.map((mcp) => {
326
+ const sanitized = sanitizeMcpServer(mcp);
327
+ if (!isPlainObject2(sanitized)) {
328
+ return sanitized;
329
+ }
330
+ return sortKeysDeep({
331
+ ...sanitized,
332
+ settings: normalizeIntegrationSettings(sanitized.settings),
333
+ mcp_connect_auth_token: normalizeIntegrationSettings(sanitized.mcp_connect_auth_token)
334
+ });
335
+ });
289
336
  }
290
337
  function calculateChecksum(content) {
291
338
  if (typeof content !== "string") {
@@ -324,6 +371,7 @@ var DEFAULT_LLM_MODEL;
324
371
  var init_checksumUtils = __esm({
325
372
  "src/lib/checksumUtils.ts"() {
326
373
  init_logger();
374
+ init_mcpSanitizer();
327
375
  DEFAULT_LLM_MODEL = "gpt-4";
328
376
  }
329
377
  });
@@ -432,10 +480,11 @@ function isValidMcpServer(server) {
432
480
  const hasConfigUrl = s.config && typeof s.config === "object" && typeof s.config.url === "string" && s.config.url.length > 0;
433
481
  const hasUrl = hasTopLevelUrl || hasConfigUrl;
434
482
  const hasSettings = s.settings != null;
483
+ const hasMcpConfigId = typeof s.mcp_config_id === "string" && s.mcp_config_id.length > 0;
435
484
  if (hasCommand && hasUrl) {
436
485
  return false;
437
486
  }
438
- if (!hasCommand && !hasUrl && !hasSettings) {
487
+ if (!hasCommand && !hasUrl && !hasSettings && !hasMcpConfigId) {
439
488
  return false;
440
489
  }
441
490
  if (hasCommand && !validateMcpCommandArgs(s, hasTopLevelCommand)) {
@@ -457,7 +506,7 @@ function convertMcpServers(servers) {
457
506
  if (validServers.length === 0) {
458
507
  return void 0;
459
508
  }
460
- return validServers;
509
+ return validServers.map((server) => sanitizeMcpServer(server));
461
510
  }
462
511
  function assistantResponseToResource(assistant) {
463
512
  const safeName = assistant.name || assistant.id || "assistant";
@@ -645,11 +694,12 @@ function iacToolkitToSdk(toolkit) {
645
694
  };
646
695
  }
647
696
  function iacMcpServerToSdk(mcp) {
697
+ const sanitized = sanitizeMcpServer(mcp);
648
698
  return {
649
- ...mcp,
650
- enabled: mcp.enabled ?? true,
651
- settings: isResolvedIntegration(mcp.settings) ? mcp.settings : void 0,
652
- mcp_connect_auth_token: isResolvedIntegration(mcp.mcp_connect_auth_token) ? mcp.mcp_connect_auth_token : void 0
699
+ ...sanitized,
700
+ enabled: sanitized.enabled ?? true,
701
+ settings: isResolvedIntegration(sanitized.settings) ? sanitized.settings : void 0,
702
+ mcp_connect_auth_token: isResolvedIntegration(sanitized.mcp_connect_auth_token) ? sanitized.mcp_connect_auth_token : void 0
653
703
  };
654
704
  }
655
705
  function assistantResourceToCreateParams(assistant, projectName, promptContent) {
@@ -685,6 +735,7 @@ var init_converters = __esm({
685
735
  "src/lib/converters.ts"() {
686
736
  init_checksumUtils();
687
737
  init_logger();
738
+ init_mcpSanitizer();
688
739
  init_typeGuards();
689
740
  CHUNK_SUMMARY_ALIASES = /* @__PURE__ */ new Set(["chunk_summary", "chunk-summary"]);
690
741
  FILE_SUMMARY_ALIASES = /* @__PURE__ */ new Set(["file_summary", "file-summary", "file-summay"]);
@@ -808,17 +859,7 @@ function transformTool(tool, integrationIdToAlias, integrationSpecPaths) {
808
859
  return result;
809
860
  }
810
861
  function transformMcpServer(mcp, integrationIdToAlias) {
811
- const result = {
812
- name: mcp.name,
813
- description: mcp.description,
814
- enabled: mcp.enabled,
815
- command: mcp.command,
816
- arguments: mcp.arguments,
817
- config: mcp.config,
818
- mcp_connect_url: mcp.mcp_connect_url,
819
- mcp_connect_auth_token: mcp.mcp_connect_auth_token,
820
- tools_tokens_size_limit: mcp.tools_tokens_size_limit
821
- };
862
+ const result = { ...mcp };
822
863
  if (mcp.settings && isResolvedIntegration(mcp.settings)) {
823
864
  const alias = mcp.settings.alias || integrationIdToAlias.get(mcp.settings.id);
824
865
  if (alias) {
@@ -840,7 +881,7 @@ function transformMcpServer(mcp, integrationIdToAlias) {
840
881
  );
841
882
  }
842
883
  }
843
- return result;
884
+ return sanitizeMcpServer(result);
844
885
  }
845
886
  function transformToolkits(toolkits, integrationIdToAlias, integrationSpecPaths) {
846
887
  return toolkits?.map(({ toolkit, tools, label, settings_config, is_external, settings }) => ({
@@ -974,6 +1015,7 @@ var init_backupTransformers = __esm({
974
1015
  init_converters();
975
1016
  init_fileUtils();
976
1017
  init_logger();
1018
+ init_mcpSanitizer();
977
1019
  init_skillUtils();
978
1020
  init_typeGuards();
979
1021
  }
@@ -981,7 +1023,7 @@ var init_backupTransformers = __esm({
981
1023
 
982
1024
  // package.json
983
1025
  var package_default = {
984
- version: "0.1.626"};
1026
+ version: "0.1.628"};
985
1027
  var appConfigSchema = z.object({
986
1028
  rootDir: z.string(),
987
1029
  codemieConfig: z.string(),
package/dist/index.js CHANGED
@@ -181,6 +181,34 @@ var init_logger = __esm({
181
181
  logger = Logger.getInstance();
182
182
  }
183
183
  });
184
+
185
+ // src/lib/mcpSanitizer.ts
186
+ function isPlainObject(value) {
187
+ return typeof value === "object" && value !== null && !Array.isArray(value);
188
+ }
189
+ function sanitizeObject(obj, isTopLevel) {
190
+ const result = {};
191
+ for (const [key, value] of Object.entries(obj)) {
192
+ if (value === null || value === void 0) {
193
+ continue;
194
+ }
195
+ if (isTopLevel && key === "mcp_connect_url" && value === "") {
196
+ continue;
197
+ }
198
+ result[key] = isPlainObject(value) ? sanitizeObject(value, false) : value;
199
+ }
200
+ return result;
201
+ }
202
+ function sanitizeMcpServer(server) {
203
+ if (!isPlainObject(server)) {
204
+ return server;
205
+ }
206
+ return sanitizeObject(server, true);
207
+ }
208
+ var init_mcpSanitizer = __esm({
209
+ "src/lib/mcpSanitizer.ts"() {
210
+ }
211
+ });
184
212
  function normalizeIntegrationSettings(settings) {
185
213
  if (!settings || typeof settings !== "object") {
186
214
  return settings;
@@ -215,15 +243,34 @@ function normalizeToolkits(toolkits) {
215
243
  settings: normalizeIntegrationSettings(settings)
216
244
  }));
217
245
  }
246
+ function isPlainObject2(value) {
247
+ return typeof value === "object" && value !== null && !Array.isArray(value);
248
+ }
249
+ function sortKeysDeep(value) {
250
+ if (!isPlainObject2(value)) {
251
+ return value;
252
+ }
253
+ const sorted = {};
254
+ for (const key of Object.keys(value).sort()) {
255
+ sorted[key] = sortKeysDeep(value[key]);
256
+ }
257
+ return sorted;
258
+ }
218
259
  function normalizeMcpServers(mcpServers) {
219
260
  if (!mcpServers) {
220
261
  return [];
221
262
  }
222
- return mcpServers.map((mcp) => ({
223
- ...mcp,
224
- settings: normalizeIntegrationSettings(mcp.settings),
225
- mcp_connect_auth_token: normalizeIntegrationSettings(mcp.mcp_connect_auth_token)
226
- }));
263
+ return mcpServers.map((mcp) => {
264
+ const sanitized = sanitizeMcpServer(mcp);
265
+ if (!isPlainObject2(sanitized)) {
266
+ return sanitized;
267
+ }
268
+ return sortKeysDeep({
269
+ ...sanitized,
270
+ settings: normalizeIntegrationSettings(sanitized.settings),
271
+ mcp_connect_auth_token: normalizeIntegrationSettings(sanitized.mcp_connect_auth_token)
272
+ });
273
+ });
227
274
  }
228
275
  function calculateChecksum(content) {
229
276
  if (typeof content !== "string") {
@@ -262,6 +309,7 @@ var DEFAULT_LLM_MODEL;
262
309
  var init_checksumUtils = __esm({
263
310
  "src/lib/checksumUtils.ts"() {
264
311
  init_logger();
312
+ init_mcpSanitizer();
265
313
  DEFAULT_LLM_MODEL = "gpt-4";
266
314
  }
267
315
  });
@@ -370,10 +418,11 @@ function isValidMcpServer(server) {
370
418
  const hasConfigUrl = s.config && typeof s.config === "object" && typeof s.config.url === "string" && s.config.url.length > 0;
371
419
  const hasUrl = hasTopLevelUrl || hasConfigUrl;
372
420
  const hasSettings = s.settings != null;
421
+ const hasMcpConfigId = typeof s.mcp_config_id === "string" && s.mcp_config_id.length > 0;
373
422
  if (hasCommand && hasUrl) {
374
423
  return false;
375
424
  }
376
- if (!hasCommand && !hasUrl && !hasSettings) {
425
+ if (!hasCommand && !hasUrl && !hasSettings && !hasMcpConfigId) {
377
426
  return false;
378
427
  }
379
428
  if (hasCommand && !validateMcpCommandArgs(s, hasTopLevelCommand)) {
@@ -395,7 +444,7 @@ function convertMcpServers(servers) {
395
444
  if (validServers.length === 0) {
396
445
  return void 0;
397
446
  }
398
- return validServers;
447
+ return validServers.map((server) => sanitizeMcpServer(server));
399
448
  }
400
449
  function assistantResponseToResource(assistant) {
401
450
  const safeName = assistant.name || assistant.id || "assistant";
@@ -583,11 +632,12 @@ function iacToolkitToSdk(toolkit) {
583
632
  };
584
633
  }
585
634
  function iacMcpServerToSdk(mcp) {
635
+ const sanitized = sanitizeMcpServer(mcp);
586
636
  return {
587
- ...mcp,
588
- enabled: mcp.enabled ?? true,
589
- settings: isResolvedIntegration(mcp.settings) ? mcp.settings : void 0,
590
- mcp_connect_auth_token: isResolvedIntegration(mcp.mcp_connect_auth_token) ? mcp.mcp_connect_auth_token : void 0
637
+ ...sanitized,
638
+ enabled: sanitized.enabled ?? true,
639
+ settings: isResolvedIntegration(sanitized.settings) ? sanitized.settings : void 0,
640
+ mcp_connect_auth_token: isResolvedIntegration(sanitized.mcp_connect_auth_token) ? sanitized.mcp_connect_auth_token : void 0
591
641
  };
592
642
  }
593
643
  function assistantResourceToCreateParams(assistant, projectName, promptContent) {
@@ -623,6 +673,7 @@ var init_converters = __esm({
623
673
  "src/lib/converters.ts"() {
624
674
  init_checksumUtils();
625
675
  init_logger();
676
+ init_mcpSanitizer();
626
677
  init_typeGuards();
627
678
  CHUNK_SUMMARY_ALIASES = /* @__PURE__ */ new Set(["chunk_summary", "chunk-summary"]);
628
679
  FILE_SUMMARY_ALIASES = /* @__PURE__ */ new Set(["file_summary", "file-summary", "file-summay"]);
@@ -746,17 +797,7 @@ function transformTool(tool, integrationIdToAlias, integrationSpecPaths) {
746
797
  return result;
747
798
  }
748
799
  function transformMcpServer(mcp, integrationIdToAlias) {
749
- const result = {
750
- name: mcp.name,
751
- description: mcp.description,
752
- enabled: mcp.enabled,
753
- command: mcp.command,
754
- arguments: mcp.arguments,
755
- config: mcp.config,
756
- mcp_connect_url: mcp.mcp_connect_url,
757
- mcp_connect_auth_token: mcp.mcp_connect_auth_token,
758
- tools_tokens_size_limit: mcp.tools_tokens_size_limit
759
- };
800
+ const result = { ...mcp };
760
801
  if (mcp.settings && isResolvedIntegration(mcp.settings)) {
761
802
  const alias = mcp.settings.alias || integrationIdToAlias.get(mcp.settings.id);
762
803
  if (alias) {
@@ -778,7 +819,7 @@ function transformMcpServer(mcp, integrationIdToAlias) {
778
819
  );
779
820
  }
780
821
  }
781
- return result;
822
+ return sanitizeMcpServer(result);
782
823
  }
783
824
  function transformToolkits(toolkits, integrationIdToAlias, integrationSpecPaths) {
784
825
  return toolkits?.map(({ toolkit, tools, label, settings_config, is_external, settings }) => ({
@@ -912,6 +953,7 @@ var init_backupTransformers = __esm({
912
953
  init_converters();
913
954
  init_fileUtils();
914
955
  init_logger();
956
+ init_mcpSanitizer();
915
957
  init_skillUtils();
916
958
  init_typeGuards();
917
959
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemieai/cdk",
3
- "version": "0.1.626",
3
+ "version": "0.1.628",
4
4
  "type": "module",
5
5
  "description": "Infrastructure as Code solution for managing Codemie AI assistants, datasources, and workflows through declarative YAML configuration",
6
6
  "main": "./dist/index.js",
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@commander-js/extra-typings": "^14.0.0",
44
- "codemie-sdk": "0.1.440",
44
+ "codemie-sdk": "0.1.626",
45
45
  "dotenv": "^17.2.3",
46
46
  "ora": "^8.2.0",
47
47
  "p-limit": "^7.2.0",