@ema.co/mcp-toolkit 2026.1.24 → 2026.1.26-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.
Potentially problematic release.
This version of @ema.co/mcp-toolkit might be problematic. Click here for more details.
- package/README.md +10 -2
- package/dist/mcp/handlers/action/index.js +3 -18
- package/dist/mcp/handlers/data/index.js +385 -41
- package/dist/mcp/handlers/data/templates.js +107 -0
- package/dist/mcp/handlers/deprecation.js +50 -0
- package/dist/mcp/handlers/env/index.js +8 -4
- package/dist/mcp/handlers/knowledge/index.js +44 -237
- package/dist/mcp/handlers/persona/create.js +5 -11
- package/dist/mcp/handlers/persona/index.js +5 -1
- package/dist/mcp/handlers/persona/version.js +234 -0
- package/dist/mcp/handlers/reference/index.js +101 -1
- package/dist/mcp/handlers/sync/index.js +3 -18
- package/dist/mcp/handlers/template/index.js +75 -10
- package/dist/mcp/handlers/workflow/analyze.js +171 -0
- package/dist/mcp/handlers/workflow/compare.js +70 -0
- package/dist/mcp/handlers/workflow/compile.js +39 -0
- package/dist/mcp/handlers/workflow/deploy.js +73 -0
- package/dist/mcp/handlers/workflow/generate.js +350 -0
- package/dist/mcp/handlers/workflow/index.js +136 -0
- package/dist/mcp/handlers/workflow/modify.js +456 -0
- package/dist/mcp/handlers/workflow/optimize.js +136 -0
- package/dist/mcp/handlers/workflow/types.js +4 -0
- package/dist/mcp/handlers/workflow/utils.js +132 -0
- package/dist/mcp/handlers-consolidated.js +62 -2691
- package/dist/mcp/prompts.js +13 -14
- package/dist/mcp/resources.js +55 -54
- package/dist/mcp/server.js +93 -124
- package/dist/mcp/{tools-v2.js → tools.js} +1 -1
- package/dist/mcp/workflow-operations.js +2 -2
- package/dist/sdk/client-adapter.js +267 -32
- package/dist/sdk/client.js +31 -15
- package/dist/sdk/ema-client.js +183 -0
- package/dist/sdk/generated/template-fallbacks.js +123 -0
- package/dist/sdk/guidance.js +65 -11
- package/dist/sdk/index.js +3 -1
- package/dist/sdk/knowledge.js +16 -86
- package/dist/sdk/workflow-intent.js +27 -0
- package/dist/sdk/workflow-transformer.js +0 -342
- package/docs/DEBUG-ANALYSIS-unused-category-type-mismatch.md +481 -0
- package/docs/TODO-fix-analyzer-and-modify.md +182 -0
- package/package.json +9 -4
- package/dist/mcp/tools-consolidated.js +0 -866
- package/dist/mcp/tools-legacy.js +0 -736
- package/docs/CODEBASE-ANALYSIS-2026-01-23.md +0 -936
- package/docs/CODEBASE-ANALYSIS-PRIORITIZED.md +0 -774
- package/docs/api-contracts.md +0 -216
- package/docs/auto-builder-analysis.md +0 -271
- package/docs/blog/mcp-tool-design-lessons.md +0 -309
- package/docs/data-architecture.md +0 -166
- package/docs/ema-auto-builder-guide.html +0 -394
- package/docs/lessons-learned.md +0 -209
- package/docs/llm-native-workflow-design.md +0 -252
- package/docs/local-generation.md +0 -508
- package/docs/mcp-flow-diagram.md +0 -135
- package/docs/migration/action-composition-migration.md +0 -270
- package/docs/naming-conventions.md +0 -278
- package/docs/proposals/HANDOFF-tool-restructure.md +0 -526
- package/docs/proposals/action-composition.md +0 -490
- package/docs/proposals/explicit-method-restructure.md +0 -328
- package/docs/proposals/mcp-tool-restructure-2026-01.md +0 -366
- package/docs/proposals/self-contained-guidance.md +0 -427
- package/docs/proto-sdk-generation.md +0 -242
- package/docs/release-impact.md +0 -102
- package/docs/release-process.md +0 -157
- package/docs/staging.RULE.md +0 -142
- package/docs/test-persona-creation.md +0 -196
- package/docs/tool-consolidation-v2.md +0 -225
- package/docs/tool-response-standards.md +0 -256
- package/resources/docs/getting-started.md +0 -97
- package/resources/templates/auto-builder-rules.md +0 -224
- package/resources/templates/chat-ai/README.md +0 -119
- package/resources/templates/chat-ai/persona-config.json +0 -111
- package/resources/templates/dashboard-ai/README.md +0 -156
- package/resources/templates/dashboard-ai/persona-config.json +0 -180
- package/resources/templates/demo-scenarios/README.md +0 -63
- package/resources/templates/demo-scenarios/test-published-package.md +0 -116
- package/resources/templates/document-gen-ai/README.md +0 -132
- package/resources/templates/document-gen-ai/persona-config.json +0 -316
- package/resources/templates/voice-ai/README.md +0 -123
- package/resources/templates/voice-ai/persona-config.json +0 -74
- package/resources/templates/voice-ai/workflow-prompt.md +0 -121
|
@@ -655,345 +655,3 @@ Return ONLY the modified WorkflowSpec JSON, no explanation needed:
|
|
|
655
655
|
\`\`\`json
|
|
656
656
|
`;
|
|
657
657
|
}
|
|
658
|
-
/**
|
|
659
|
-
* @deprecated MCP should not parse natural language - the Agent IS the LLM.
|
|
660
|
-
* Use agent reasoning instead. Will be removed in future version.
|
|
661
|
-
*
|
|
662
|
-
* Parse natural language intent into deterministic operations.
|
|
663
|
-
* Returns operations that can be executed directly, or indicates LLM is needed.
|
|
664
|
-
*/
|
|
665
|
-
export function parseIntent(input, spec) {
|
|
666
|
-
const ops = [];
|
|
667
|
-
const lowerInput = input.toLowerCase();
|
|
668
|
-
const nodeIds = spec.nodes.map(n => n.id);
|
|
669
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
670
|
-
// REMOVE NODE: "remove node X", "delete X", "remove X"
|
|
671
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
672
|
-
if (lowerInput.includes("remove") || lowerInput.includes("delete")) {
|
|
673
|
-
// Strategy 1: Exact node ID in input
|
|
674
|
-
for (const nodeId of nodeIds) {
|
|
675
|
-
if (input.includes(nodeId)) {
|
|
676
|
-
ops.push({ type: "remove", nodeId });
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
// Strategy 2: "remove the node X" pattern
|
|
680
|
-
if (ops.length === 0) {
|
|
681
|
-
const match = input.match(/(?:remove|delete)\s+(?:the\s+)?node\s+["']?([a-zA-Z0-9_]+)["']?/i);
|
|
682
|
-
if (match) {
|
|
683
|
-
const nodeId = nodeIds.find(id => id.toLowerCase() === match[1].toLowerCase());
|
|
684
|
-
if (nodeId) {
|
|
685
|
-
ops.push({ type: "remove", nodeId });
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
691
|
-
// RENAME NODE: "rename X to Y", "change displayName of X to Y"
|
|
692
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
693
|
-
if (lowerInput.includes("rename") || lowerInput.includes("displayname")) {
|
|
694
|
-
const match = input.match(/(?:rename|change\s+displayName\s+of)\s+["']?([a-zA-Z0-9_]+)["']?\s+to\s+["']?([^"'\n]+)["']?/i);
|
|
695
|
-
if (match) {
|
|
696
|
-
const nodeId = nodeIds.find(id => id.toLowerCase() === match[1].toLowerCase());
|
|
697
|
-
if (nodeId) {
|
|
698
|
-
ops.push({ type: "rename", nodeId, newDisplayName: match[2].trim() });
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
703
|
-
// ADD RUNIF: "add runIf to X when Y.Z equals V"
|
|
704
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
705
|
-
if (lowerInput.includes("runif") || lowerInput.includes("conditional") ||
|
|
706
|
-
(lowerInput.includes("only run") && lowerInput.includes("when"))) {
|
|
707
|
-
// Pattern: "add runIf to NODE when SOURCE.OUTPUT equals VALUE"
|
|
708
|
-
const match = input.match(/(?:add\s+)?runIf\s+to\s+["']?([a-zA-Z0-9_]+)["']?\s+when\s+["']?([a-zA-Z0-9_]+)["']?\.["']?([a-zA-Z0-9_]+)["']?\s+(?:equals?|==|eq)\s+["']?([^"'\n]+)["']?/i);
|
|
709
|
-
if (match) {
|
|
710
|
-
const nodeId = nodeIds.find(id => id.toLowerCase() === match[1].toLowerCase());
|
|
711
|
-
const sourceAction = nodeIds.find(id => id.toLowerCase() === match[2].toLowerCase());
|
|
712
|
-
if (nodeId && sourceAction) {
|
|
713
|
-
ops.push({
|
|
714
|
-
type: "add_runif",
|
|
715
|
-
nodeId,
|
|
716
|
-
condition: {
|
|
717
|
-
sourceAction,
|
|
718
|
-
sourceOutput: match[3],
|
|
719
|
-
operator: "eq",
|
|
720
|
-
value: match[4].trim(),
|
|
721
|
-
},
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
727
|
-
// ADD TO RESULTS: "add X to results", "include X in output"
|
|
728
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
729
|
-
if (lowerInput.includes("add") && (lowerInput.includes("result") || lowerInput.includes("output"))) {
|
|
730
|
-
for (const nodeId of nodeIds) {
|
|
731
|
-
if (input.includes(nodeId)) {
|
|
732
|
-
// Determine output name based on node type
|
|
733
|
-
const node = spec.nodes.find(n => n.id === nodeId);
|
|
734
|
-
const output = node?.actionType === "search" ? "search_results" : "response_with_sources";
|
|
735
|
-
ops.push({ type: "add_to_results", nodeId, output });
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
// If we found deterministic ops, return them
|
|
740
|
-
if (ops.length > 0) {
|
|
741
|
-
return { ops, needs_llm: false };
|
|
742
|
-
}
|
|
743
|
-
// Otherwise, this needs LLM for complex interpretation
|
|
744
|
-
return {
|
|
745
|
-
ops: [],
|
|
746
|
-
needs_llm: true,
|
|
747
|
-
reason: "Could not parse deterministic operations from input. LLM interpretation needed."
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* @deprecated MCP should not apply operations - the Agent builds workflow_spec.
|
|
752
|
-
* Will be removed in future version.
|
|
753
|
-
*
|
|
754
|
-
* Apply deterministic modifications to a WorkflowSpec.
|
|
755
|
-
*/
|
|
756
|
-
export function applyOperations(spec, ops) {
|
|
757
|
-
// Deep clone to avoid mutations
|
|
758
|
-
const newSpec = JSON.parse(JSON.stringify(spec));
|
|
759
|
-
const changes = [];
|
|
760
|
-
const errors = [];
|
|
761
|
-
for (const op of ops) {
|
|
762
|
-
switch (op.type) {
|
|
763
|
-
case "remove": {
|
|
764
|
-
const idx = newSpec.nodes.findIndex(n => n.id === op.nodeId);
|
|
765
|
-
if (idx >= 0) {
|
|
766
|
-
newSpec.nodes.splice(idx, 1);
|
|
767
|
-
// Also remove from resultMappings
|
|
768
|
-
newSpec.resultMappings = newSpec.resultMappings.filter(rm => rm.nodeId !== op.nodeId);
|
|
769
|
-
// Clean up any references in other nodes' inputs - REMOVE them, don't just warn
|
|
770
|
-
for (const node of newSpec.nodes) {
|
|
771
|
-
if (node.inputs) {
|
|
772
|
-
for (const [key, binding] of Object.entries(node.inputs)) {
|
|
773
|
-
if (binding.actionName === op.nodeId) {
|
|
774
|
-
// Remove the dangling reference to prevent API errors
|
|
775
|
-
delete node.inputs[key];
|
|
776
|
-
errors.push(`Warning: Removed dangling reference ${node.id}.${key} → ${op.nodeId}`);
|
|
777
|
-
}
|
|
778
|
-
// Also check namedInputs for dangling refs
|
|
779
|
-
if (binding.namedInputs) {
|
|
780
|
-
const originalLen = binding.namedInputs.length;
|
|
781
|
-
binding.namedInputs = binding.namedInputs.filter(ni => ni.binding?.actionName !== op.nodeId);
|
|
782
|
-
if (binding.namedInputs.length < originalLen) {
|
|
783
|
-
errors.push(`Warning: Removed dangling namedInput reference in ${node.id}.${key} → ${op.nodeId}`);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
changes.push(`Removed node: ${op.nodeId}`);
|
|
790
|
-
}
|
|
791
|
-
else {
|
|
792
|
-
errors.push(`Node not found: ${op.nodeId}`);
|
|
793
|
-
}
|
|
794
|
-
break;
|
|
795
|
-
}
|
|
796
|
-
case "rename": {
|
|
797
|
-
const node = newSpec.nodes.find(n => n.id === op.nodeId);
|
|
798
|
-
if (node) {
|
|
799
|
-
const oldName = node.displayName;
|
|
800
|
-
node.displayName = op.newDisplayName;
|
|
801
|
-
changes.push(`Renamed ${op.nodeId}: "${oldName}" → "${op.newDisplayName}"`);
|
|
802
|
-
}
|
|
803
|
-
else {
|
|
804
|
-
errors.push(`Node not found: ${op.nodeId}`);
|
|
805
|
-
}
|
|
806
|
-
break;
|
|
807
|
-
}
|
|
808
|
-
case "add_runif": {
|
|
809
|
-
const node = newSpec.nodes.find(n => n.id === op.nodeId);
|
|
810
|
-
if (node) {
|
|
811
|
-
node.runIf = op.condition;
|
|
812
|
-
changes.push(`Added runIf to ${op.nodeId}: when ${op.condition.sourceAction}.${op.condition.sourceOutput} ${op.condition.operator} "${op.condition.value}"`);
|
|
813
|
-
}
|
|
814
|
-
else {
|
|
815
|
-
errors.push(`Node not found: ${op.nodeId}`);
|
|
816
|
-
}
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
|
-
case "remove_runif": {
|
|
820
|
-
const node = newSpec.nodes.find(n => n.id === op.nodeId);
|
|
821
|
-
if (node) {
|
|
822
|
-
delete node.runIf;
|
|
823
|
-
changes.push(`Removed runIf from ${op.nodeId}`);
|
|
824
|
-
}
|
|
825
|
-
else {
|
|
826
|
-
errors.push(`Node not found: ${op.nodeId}`);
|
|
827
|
-
}
|
|
828
|
-
break;
|
|
829
|
-
}
|
|
830
|
-
case "add_to_results": {
|
|
831
|
-
const exists = newSpec.resultMappings.some(rm => rm.nodeId === op.nodeId);
|
|
832
|
-
if (!exists) {
|
|
833
|
-
newSpec.resultMappings.push({ nodeId: op.nodeId, output: op.output });
|
|
834
|
-
changes.push(`Added ${op.nodeId}.${op.output} to results`);
|
|
835
|
-
}
|
|
836
|
-
else {
|
|
837
|
-
changes.push(`${op.nodeId} already in results`);
|
|
838
|
-
}
|
|
839
|
-
break;
|
|
840
|
-
}
|
|
841
|
-
case "remove_from_results": {
|
|
842
|
-
const idx = newSpec.resultMappings.findIndex(rm => rm.nodeId === op.nodeId);
|
|
843
|
-
if (idx >= 0) {
|
|
844
|
-
newSpec.resultMappings.splice(idx, 1);
|
|
845
|
-
changes.push(`Removed ${op.nodeId} from results`);
|
|
846
|
-
}
|
|
847
|
-
break;
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
return { spec: newSpec, changes, errors };
|
|
852
|
-
}
|
|
853
|
-
/**
|
|
854
|
-
* Directly patch a workflow_def without recompilation.
|
|
855
|
-
* This preserves ALL original fields and only modifies what's necessary.
|
|
856
|
-
*
|
|
857
|
-
* Use this for simple operations like remove/rename that don't need full recompile.
|
|
858
|
-
*/
|
|
859
|
-
function patchWorkflowDef(workflowDef, ops) {
|
|
860
|
-
const patched = JSON.parse(JSON.stringify(workflowDef));
|
|
861
|
-
const actions = patched.actions;
|
|
862
|
-
const results = patched.results;
|
|
863
|
-
const changes = [];
|
|
864
|
-
const errors = [];
|
|
865
|
-
for (const op of ops) {
|
|
866
|
-
switch (op.type) {
|
|
867
|
-
case "remove": {
|
|
868
|
-
const idx = actions.findIndex((a) => a.name === op.nodeId);
|
|
869
|
-
if (idx >= 0) {
|
|
870
|
-
actions.splice(idx, 1);
|
|
871
|
-
changes.push(`Removed node: ${op.nodeId}`);
|
|
872
|
-
// Remove from results
|
|
873
|
-
for (const key of Object.keys(results)) {
|
|
874
|
-
if (results[key].actionName === op.nodeId) {
|
|
875
|
-
delete results[key];
|
|
876
|
-
changes.push(`Removed result mapping: ${key}`);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
// Clean up dangling input references
|
|
880
|
-
for (const action of actions) {
|
|
881
|
-
const inputs = action.inputs;
|
|
882
|
-
if (inputs) {
|
|
883
|
-
for (const [inputKey, inputVal] of Object.entries(inputs)) {
|
|
884
|
-
const actionOutput = inputVal.actionOutput;
|
|
885
|
-
if (actionOutput?.actionName === op.nodeId) {
|
|
886
|
-
delete inputs[inputKey];
|
|
887
|
-
errors.push(`Warning: Removed dangling reference ${action.name}.${inputKey} → ${op.nodeId}`);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
else {
|
|
894
|
-
errors.push(`Node not found: ${op.nodeId}`);
|
|
895
|
-
}
|
|
896
|
-
break;
|
|
897
|
-
}
|
|
898
|
-
case "rename": {
|
|
899
|
-
const action = actions.find((a) => a.name === op.nodeId);
|
|
900
|
-
if (action) {
|
|
901
|
-
const displaySettings = action.displaySettings;
|
|
902
|
-
if (displaySettings) {
|
|
903
|
-
displaySettings.displayName = op.newDisplayName;
|
|
904
|
-
changes.push(`Renamed ${op.nodeId} to "${op.newDisplayName}"`);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
else {
|
|
908
|
-
errors.push(`Node not found for rename: ${op.nodeId}`);
|
|
909
|
-
}
|
|
910
|
-
break;
|
|
911
|
-
}
|
|
912
|
-
// For other operations, we'd need full recompile
|
|
913
|
-
default:
|
|
914
|
-
errors.push(`Direct patch not supported for operation: ${op.type}`);
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
return { workflow_def: patched, changes, errors };
|
|
918
|
-
}
|
|
919
|
-
/**
|
|
920
|
-
* @deprecated MCP should not transform from intent - the Agent builds workflow_spec.
|
|
921
|
-
* The agent uses analyze to get current spec, reasons about changes, and calls
|
|
922
|
-
* update with the new workflow_spec it built.
|
|
923
|
-
* Will be removed in future version.
|
|
924
|
-
*
|
|
925
|
-
* Transform a workflow based on natural language intent.
|
|
926
|
-
*
|
|
927
|
-
* @param workflowDef - The existing workflow_def JSON
|
|
928
|
-
* @param input - Natural language modification request
|
|
929
|
-
* @param personaType - The persona type (voice, chat, dashboard)
|
|
930
|
-
* @returns IntentTransformResult with modified workflow or LLM prompt
|
|
931
|
-
*/
|
|
932
|
-
export function transformWorkflowFromIntent(workflowDef, input, personaType = "chat") {
|
|
933
|
-
// Step 1: Decompile to spec (for parsing)
|
|
934
|
-
const spec = decompileWorkflow(workflowDef, personaType);
|
|
935
|
-
// Step 2: Parse intent into operations
|
|
936
|
-
const { ops, needs_llm, reason } = parseIntent(input, spec);
|
|
937
|
-
if (needs_llm) {
|
|
938
|
-
// Complex modification - return LLM prompt
|
|
939
|
-
return {
|
|
940
|
-
success: false,
|
|
941
|
-
needs_llm: true,
|
|
942
|
-
llm_prompt: createModificationPrompt(spec, input),
|
|
943
|
-
changes: [],
|
|
944
|
-
errors: [reason || "LLM interpretation needed"],
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
|
-
// Step 3: Check if we can use direct patching (simpler, preserves all fields)
|
|
948
|
-
const simpleOps = ["remove", "rename"];
|
|
949
|
-
const allSimple = ops.every(op => simpleOps.includes(op.type));
|
|
950
|
-
if (allSimple && ops.length > 0) {
|
|
951
|
-
// Use direct patching - no recompilation needed
|
|
952
|
-
const { workflow_def, changes, errors } = patchWorkflowDef(workflowDef, ops);
|
|
953
|
-
if (errors.some(e => !e.startsWith("Warning"))) {
|
|
954
|
-
return {
|
|
955
|
-
success: false,
|
|
956
|
-
workflow_def,
|
|
957
|
-
changes,
|
|
958
|
-
errors,
|
|
959
|
-
};
|
|
960
|
-
}
|
|
961
|
-
return {
|
|
962
|
-
success: true,
|
|
963
|
-
workflow_def,
|
|
964
|
-
changes,
|
|
965
|
-
errors,
|
|
966
|
-
};
|
|
967
|
-
}
|
|
968
|
-
// Step 4: Complex operations - use full decompile → transform → compile
|
|
969
|
-
const { spec: modifiedSpec, changes, errors } = applyOperations(spec, ops);
|
|
970
|
-
if (errors.some(e => !e.startsWith("Warning"))) {
|
|
971
|
-
return {
|
|
972
|
-
success: false,
|
|
973
|
-
spec: modifiedSpec,
|
|
974
|
-
changes,
|
|
975
|
-
errors,
|
|
976
|
-
};
|
|
977
|
-
}
|
|
978
|
-
// Step 5: Compile back to workflow_def
|
|
979
|
-
try {
|
|
980
|
-
const compiled = compileWorkflow(modifiedSpec);
|
|
981
|
-
// Preserve original workflowName
|
|
982
|
-
compiled.workflow_def.workflowName = workflowDef.workflowName;
|
|
983
|
-
return {
|
|
984
|
-
success: true,
|
|
985
|
-
spec: modifiedSpec,
|
|
986
|
-
workflow_def: compiled.workflow_def,
|
|
987
|
-
changes,
|
|
988
|
-
errors,
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
catch (e) {
|
|
992
|
-
return {
|
|
993
|
-
success: false,
|
|
994
|
-
spec: modifiedSpec,
|
|
995
|
-
changes,
|
|
996
|
-
errors: [...errors, `Compilation failed: ${e instanceof Error ? e.message : String(e)}`],
|
|
997
|
-
};
|
|
998
|
-
}
|
|
999
|
-
}
|