@noorm/marie-cli 0.1.18 → 0.1.25
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 +7 -15
- package/SENTINEL.md +4 -7
- package/dist/cli-new/components/App.js +16 -63
- package/dist/cli-new/components/App.js.map +1 -1
- package/dist/cli-new/components/ApprovalDialog.js +2 -1
- package/dist/cli-new/components/ApprovalDialog.js.map +1 -1
- package/dist/cli-new/components/Banner.js +4 -3
- package/dist/cli-new/components/Banner.js.map +1 -1
- package/dist/cli-new/components/ChatArea.js +6 -7
- package/dist/cli-new/components/ChatArea.js.map +1 -1
- package/dist/cli-new/components/Header.js +13 -7
- package/dist/cli-new/components/Header.js.map +1 -1
- package/dist/cli-new/components/InputArea.js +73 -12
- package/dist/cli-new/components/InputArea.js.map +1 -1
- package/dist/cli-new/components/MessageBubble.js +26 -18
- package/dist/cli-new/components/MessageBubble.js.map +1 -1
- package/dist/cli-new/components/SessionSwitcher.js +4 -7
- package/dist/cli-new/components/SessionSwitcher.js.map +1 -1
- package/dist/cli-new/components/SetupWizard.js +80 -257
- package/dist/cli-new/components/SetupWizard.js.map +1 -1
- package/dist/cli-new/components/ToolCallDisplay.js +20 -5
- package/dist/cli-new/components/ToolCallDisplay.js.map +1 -1
- package/dist/cli-new/components/WizardSteps.js +22 -0
- package/dist/cli-new/components/WizardSteps.js.map +1 -0
- package/dist/cli-new/constants/SetupConstants.js +42 -0
- package/dist/cli-new/constants/SetupConstants.js.map +1 -0
- package/dist/cli-new/hooks/useGit.js +19 -62
- package/dist/cli-new/hooks/useGit.js.map +1 -1
- package/dist/cli-new/hooks/useMarie.js +26 -18
- package/dist/cli-new/hooks/useMarie.js.map +1 -1
- package/dist/cli-new/hooks/useSessions.js +1 -1
- package/dist/cli-new/hooks/useSessions.js.map +1 -1
- package/dist/cli-new/hooks/useSetupWizard.js +88 -0
- package/dist/cli-new/hooks/useSetupWizard.js.map +1 -0
- package/dist/cli-new/hooks/useUpdateCheck.js +4 -3
- package/dist/cli-new/hooks/useUpdateCheck.js.map +1 -1
- package/dist/cli-new/index.js +2 -4
- package/dist/cli-new/index.js.map +1 -1
- package/dist/cli-new/services/CommandService.js +104 -0
- package/dist/cli-new/services/CommandService.js.map +1 -0
- package/dist/cli-new/services/GitService.js +91 -0
- package/dist/cli-new/services/GitService.js.map +1 -0
- package/dist/cli-new/services/MarieService.js +77 -0
- package/dist/cli-new/services/MarieService.js.map +1 -0
- package/dist/cli-new/services/auth-server.js +128 -0
- package/dist/cli-new/services/auth-server.js.map +1 -0
- package/dist/cli-new/utils/version.js +24 -0
- package/dist/cli-new/utils/version.js.map +1 -0
- package/dist/monolith/adapters/CliMarieAdapter.js +12 -11
- package/dist/monolith/adapters/CliMarieAdapter.js.map +1 -1
- package/dist/monolith/cli/CliFileSystemPort.js +17 -3
- package/dist/monolith/cli/CliFileSystemPort.js.map +1 -1
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js +39 -31
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js.map +1 -1
- package/dist/monolith/cli/index.js +5 -20
- package/dist/monolith/cli/index.js.map +1 -1
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js +15 -62
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js.map +1 -1
- package/dist/monolith/cli/storage.js +142 -72
- package/dist/monolith/cli/storage.js.map +1 -1
- package/dist/monolith/domain/joy/RitualService.js +44 -46
- package/dist/monolith/domain/joy/RitualService.js.map +1 -1
- package/dist/monolith/domain/marie/MarieCortex.js +148 -0
- package/dist/monolith/domain/marie/MarieCortex.js.map +1 -0
- package/dist/monolith/domain/marie/PersonalityRenderer.js +97 -0
- package/dist/monolith/domain/marie/PersonalityRenderer.js.map +1 -0
- package/dist/monolith/infrastructure/Configuration.js +68 -0
- package/dist/monolith/infrastructure/Configuration.js.map +1 -0
- package/dist/monolith/infrastructure/CoreInfrastructure.js +204 -0
- package/dist/monolith/infrastructure/CoreInfrastructure.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js +3 -3
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js.map +1 -1
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js +6 -27
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js.map +1 -1
- package/dist/monolith/infrastructure/ai/context/ContextManager.js +142 -131
- package/dist/monolith/infrastructure/ai/context/ContextManager.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js +115 -1077
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js +1 -37
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js +6 -1
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js +172 -221
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js +292 -141
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js +331 -614
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieVitality.js +238 -0
- package/dist/monolith/infrastructure/ai/core/MarieVitality.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/SessionLogService.js +9 -2
- package/dist/monolith/infrastructure/ai/core/SessionLogService.js.map +1 -1
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js +402 -1
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js.map +1 -1
- package/dist/monolith/infrastructure/ai/providers/DreamBeesProvider.js +114 -0
- package/dist/monolith/infrastructure/ai/providers/DreamBeesProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js +426 -392
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js.map +1 -1
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js +235 -241
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js.map +1 -1
- package/dist/monolith/infrastructure/ai/workerAi.js +185 -0
- package/dist/monolith/infrastructure/ai/workerAi.js.map +1 -0
- package/dist/monolith/infrastructure/config/ConfigService.js +216 -503
- package/dist/monolith/infrastructure/config/ConfigService.js.map +1 -1
- package/dist/monolith/infrastructure/joy/CognitiveRituals.js +4 -165
- package/dist/monolith/infrastructure/joy/CognitiveRituals.js.map +1 -1
- package/dist/monolith/infrastructure/joy/JoyTools.js +14 -47
- package/dist/monolith/infrastructure/joy/JoyTools.js.map +1 -1
- package/dist/monolith/infrastructure/persistence/MarieMindAutonomics.js +4 -0
- package/dist/monolith/infrastructure/persistence/MarieMindAutonomics.js.map +1 -0
- package/dist/monolith/infrastructure/persistence/MarieMindEngine.js +11 -0
- package/dist/monolith/infrastructure/persistence/MarieMindEngine.js.map +1 -0
- package/dist/monolith/infrastructure/persistence/NoormmeAutonomics.js +123 -106
- package/dist/monolith/infrastructure/persistence/NoormmeAutonomics.js.map +1 -1
- package/dist/monolith/infrastructure/persistence/NoormmeEngine.js +508 -63
- package/dist/monolith/infrastructure/persistence/NoormmeEngine.js.map +1 -1
- package/dist/monolith/infrastructure/persistence/NoormmeSchema.js +68 -39
- package/dist/monolith/infrastructure/persistence/NoormmeSchema.js.map +1 -1
- package/dist/monolith/infrastructure/persistence/NoormmeSeeder.js +80 -67
- package/dist/monolith/infrastructure/persistence/NoormmeSeeder.js.map +1 -1
- package/dist/monolith/infrastructure/persistence/NoormmeTools.js +122 -75
- package/dist/monolith/infrastructure/persistence/NoormmeTools.js.map +1 -1
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js +133 -134
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js.map +1 -1
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js +6 -30
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js.map +1 -1
- package/dist/monolith/infrastructure/tools/PureStreamParser.js +68 -80
- package/dist/monolith/infrastructure/tools/PureStreamParser.js.map +1 -1
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js +12 -11
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js.map +1 -1
- package/dist/monolith/infrastructure/tools/SovereignTools.js +326 -0
- package/dist/monolith/infrastructure/tools/SovereignTools.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js +45 -26
- package/dist/monolith/infrastructure/tools/ToolRegistry.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/AnalysisTools.js +39 -153
- package/dist/monolith/infrastructure/tools/definitions/AnalysisTools.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/AutomationTools.js +31 -46
- package/dist/monolith/infrastructure/tools/definitions/AutomationTools.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/ContextTools.js +41 -13
- package/dist/monolith/infrastructure/tools/definitions/ContextTools.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/CoreTools.js +10 -14
- package/dist/monolith/infrastructure/tools/definitions/CoreTools.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/DiagnosticTools.js +39 -70
- package/dist/monolith/infrastructure/tools/definitions/DiagnosticTools.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/NavigationTools.js +30 -181
- package/dist/monolith/infrastructure/tools/definitions/NavigationTools.js.map +1 -1
- package/dist/monolith/infrastructure/tools/definitions/PlanningTools.js +12 -9
- package/dist/monolith/infrastructure/tools/definitions/PlanningTools.js.map +1 -1
- package/dist/monolith/plumbing/Plumbing.js +238 -0
- package/dist/monolith/plumbing/Plumbing.js.map +1 -0
- package/dist/monolith/plumbing/PlumbingAnalysis.js +109 -0
- package/dist/monolith/plumbing/PlumbingAnalysis.js.map +1 -0
- package/dist/monolith/plumbing/PlumbingSystem.js +169 -0
- package/dist/monolith/plumbing/PlumbingSystem.js.map +1 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js +30 -34
- package/dist/monolith/plumbing/analysis/ComplexityService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/DependencyService.js +55 -44
- package/dist/monolith/plumbing/analysis/DependencyService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/DiscoveryService.js +40 -42
- package/dist/monolith/plumbing/analysis/DiscoveryService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/JoyMapService.js +52 -56
- package/dist/monolith/plumbing/analysis/JoyMapService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/LintService.js +118 -118
- package/dist/monolith/plumbing/analysis/LintService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js +278 -268
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js +116 -114
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js.map +1 -1
- package/dist/monolith/plumbing/analysis/SurgicalMender.js +57 -59
- package/dist/monolith/plumbing/analysis/SurgicalMender.js.map +1 -1
- package/dist/monolith/plumbing/analysis/TestService.js +89 -89
- package/dist/monolith/plumbing/analysis/TestService.js.map +1 -1
- package/dist/monolith/plumbing/filesystem/FileService.js +123 -195
- package/dist/monolith/plumbing/filesystem/FileService.js.map +1 -1
- package/dist/monolith/plumbing/filesystem/PathResolver.js +7 -8
- package/dist/monolith/plumbing/filesystem/PathResolver.js.map +1 -1
- package/dist/monolith/plumbing/git/GitService.js +4 -4
- package/dist/monolith/plumbing/git/GitService.js.map +1 -1
- package/dist/monolith/plumbing/lsp/SymbolService.js +5 -34
- package/dist/monolith/plumbing/lsp/SymbolService.js.map +1 -1
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js +20 -22
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js.map +1 -1
- package/dist/monolith/plumbing/terminal/TerminalService.js +127 -141
- package/dist/monolith/plumbing/terminal/TerminalService.js.map +1 -1
- package/dist/monolith/plumbing/utils/EnvironmentUtils.js +3 -23
- package/dist/monolith/plumbing/utils/EnvironmentUtils.js.map +1 -1
- package/dist/monolith/plumbing/utils/JsonUtils.js +252 -311
- package/dist/monolith/plumbing/utils/JsonUtils.js.map +1 -1
- package/dist/monolith/plumbing/utils/PlumbingCore.js +549 -0
- package/dist/monolith/plumbing/utils/PlumbingCore.js.map +1 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js +61 -114
- package/dist/monolith/plumbing/utils/PrefixTree.js.map +1 -1
- package/dist/monolith/plumbing/utils/StreamTagDetector.js +89 -127
- package/dist/monolith/plumbing/utils/StreamTagDetector.js.map +1 -1
- package/dist/monolith/plumbing/utils/StringUtils.js +87 -89
- package/dist/monolith/plumbing/utils/StringUtils.js.map +1 -1
- package/dist/monolith/runtime/MarieRuntime.js +76 -499
- package/dist/monolith/runtime/MarieRuntime.js.map +1 -1
- package/dist/monolith/runtime/RuntimeAdapterBase.js +1 -1
- package/dist/monolith/runtime/RuntimeAdapterBase.js.map +1 -1
- package/dist/monolith/runtime/providerFactory.js +1 -7
- package/dist/monolith/runtime/providerFactory.js.map +1 -1
- package/dist/monolith/services/HealthService.js +29 -32
- package/dist/monolith/services/HealthService.js.map +1 -1
- package/dist/monolith/services/JoyAutomationService.js +58 -95
- package/dist/monolith/services/JoyAutomationService.js.map +1 -1
- package/dist/monolith/services/MarieAutomationService.js +59 -0
- package/dist/monolith/services/MarieAutomationService.js.map +1 -0
- package/dist/monolith/services/MarieGhostService.js +46 -173
- package/dist/monolith/services/MarieGhostService.js.map +1 -1
- package/dist/monolith/services/MarieServices.js +102 -0
- package/dist/monolith/services/MarieServices.js.map +1 -0
- package/dist/monolith/services/MarieTypes.js +2 -0
- package/dist/monolith/services/MarieTypes.js.map +1 -0
- package/dist/monolith/services/UpdateService.js +47 -49
- package/dist/monolith/services/UpdateService.js.map +1 -1
- package/dist/prompts.js +11 -5
- package/dist/prompts.js.map +1 -1
- package/dist/test_prefix_tree.js +9 -9
- package/dist/test_prefix_tree.js.map +1 -1
- package/package.json +18 -89
- package/run_test.js +5 -0
- package/.marie_visual_verify_1771225696548/progress_bar_check.txt +0 -1
- package/dist/extension.cjs +0 -1155
- package/dist/extension.js +0 -474
- package/dist/extension.js.map +0 -1
- package/dist/monolith/adapters/VscodeMarieAdapter.js +0 -81
- package/dist/monolith/adapters/VscodeMarieAdapter.js.map +0 -1
- package/dist/monolith/infrastructure/ai/core/GhostPort.js +0 -2
- package/dist/monolith/infrastructure/ai/core/GhostPort.js.map +0 -1
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js +0 -33
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js.map +0 -1
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js +0 -154
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js.map +0 -1
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js +0 -214
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js.map +0 -1
- package/dist/monolith/plumbing/ui/DecorationService.js +0 -54
- package/dist/monolith/plumbing/ui/DecorationService.js.map +0 -1
- package/dist/monolith/services/JoyLogService.js +0 -48
- package/dist/monolith/services/JoyLogService.js.map +0 -1
- package/dist/monolith/services/JoyService.js +0 -209
- package/dist/monolith/services/JoyService.js.map +0 -1
- package/dist/monolith/services/MarieSCMProvider.js +0 -41
- package/dist/monolith/services/MarieSCMProvider.js.map +0 -1
- package/dist/webview-ui/main.css +0 -1
- package/dist/webview-ui/main.js +0 -108
- package/lint_output.txt +0 -705
- package/lint_output_v2.txt +0 -711
- package/test-mind-p6.sqlite +0 -0
- package/test-mind-p6.sqlite-shm +0 -0
- package/test-mind-p6.sqlite-wal +0 -0
|
@@ -1,360 +1,301 @@
|
|
|
1
|
+
import { safeGetKeys } from "../../infrastructure/ai/core/MarieSanitizer.js";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Repairs truncated or unclosed JSON strings.
|
|
4
|
+
* Returns the repaired string and a flag indicating if any changes were made.
|
|
3
5
|
*/
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
isInsideString = !isInsideString;
|
|
6
|
+
export function repairJsonDetailed(json) {
|
|
7
|
+
if (typeof json !== "string")
|
|
8
|
+
return { repaired: "{}", wasFixed: false };
|
|
9
|
+
let repaired = json.trim();
|
|
10
|
+
if (!repaired)
|
|
11
|
+
return { repaired: "{}", wasFixed: false };
|
|
12
|
+
let wasFixed = false;
|
|
13
|
+
const original = repaired;
|
|
14
|
+
// Pre-processing: Fix unquoted keys or single quotes
|
|
15
|
+
repaired = repaired.replace(/'/g, '"');
|
|
16
|
+
let isInsideString = false;
|
|
17
|
+
const stack = [];
|
|
18
|
+
let i = 0;
|
|
19
|
+
while (i < repaired.length) {
|
|
20
|
+
const char = repaired[i];
|
|
21
|
+
const prevChar = i > 0 ? repaired[i - 1] : "";
|
|
22
|
+
const isEscaped = prevChar === "\\";
|
|
23
|
+
if (char === '"' && !isEscaped) {
|
|
24
|
+
isInsideString = !isInsideString;
|
|
25
|
+
}
|
|
26
|
+
else if (!isInsideString) {
|
|
27
|
+
if (char === "{" || char === "[") {
|
|
28
|
+
stack.push(char);
|
|
28
29
|
}
|
|
29
|
-
else if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
else if (char === "}" || char === "]") {
|
|
34
|
-
const expected = char === "}" ? "{" : "[";
|
|
35
|
-
if (stack.length > 0 && stack[stack.length - 1] === expected) {
|
|
36
|
-
stack.pop();
|
|
37
|
-
}
|
|
30
|
+
else if (char === "}" || char === "]") {
|
|
31
|
+
const expected = char === "}" ? "{" : "[";
|
|
32
|
+
if (stack.length > 0 && stack[stack.length - 1] === expected) {
|
|
33
|
+
stack.pop();
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
|
-
i++;
|
|
41
|
-
}
|
|
42
|
-
if (isInsideString) {
|
|
43
|
-
repaired += '"';
|
|
44
36
|
}
|
|
45
|
-
|
|
46
|
-
const hadUnclosed = stack.length > 0;
|
|
47
|
-
while (stack.length > 0) {
|
|
48
|
-
const last = stack.pop();
|
|
49
|
-
if (last === "{")
|
|
50
|
-
repaired += "}";
|
|
51
|
-
else if (last === "[")
|
|
52
|
-
repaired += "]";
|
|
53
|
-
}
|
|
54
|
-
// Extreme: Fix unquoted property names: { name: "val" } -> { "name": "val" }
|
|
55
|
-
repaired = repaired.replace(/([{,]\s*)([a-zA-Z0-9_$]+)(\s*):/g, '$1"$2"$3:');
|
|
56
|
-
// Trailing commas
|
|
57
|
-
const hadTrailing = /,\s*[}\]]/.test(repaired);
|
|
58
|
-
repaired = repaired.replace(/,\s*([}\]])/g, "$1");
|
|
59
|
-
wasFixed =
|
|
60
|
-
repaired !== original || hadUnclosed || hadTrailing || isInsideString;
|
|
61
|
-
return { repaired, wasFixed };
|
|
37
|
+
i++;
|
|
62
38
|
}
|
|
63
|
-
|
|
64
|
-
|
|
39
|
+
if (isInsideString) {
|
|
40
|
+
repaired += '"';
|
|
65
41
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
42
|
+
// Close unclosed structures
|
|
43
|
+
const hadUnclosed = stack.length > 0;
|
|
44
|
+
while (stack.length > 0) {
|
|
45
|
+
const last = stack.pop();
|
|
46
|
+
if (last === "{")
|
|
47
|
+
repaired += "}";
|
|
48
|
+
else if (last === "[")
|
|
49
|
+
repaired += "]";
|
|
50
|
+
}
|
|
51
|
+
// Extreme: Fix unquoted property names: { name: "val" } -> { "name": "val" }
|
|
52
|
+
repaired = repaired.replace(/([{,]\s*)([a-zA-Z0-9_$]+)(\s*):/g, '$1"$2"$3:');
|
|
53
|
+
// Trailing commas
|
|
54
|
+
const hadTrailing = /,\s*[}\]]/.test(repaired);
|
|
55
|
+
repaired = repaired.replace(/,\s*([}\]])/g, "$1");
|
|
56
|
+
wasFixed =
|
|
57
|
+
repaired !== original || hadUnclosed || hadTrailing || isInsideString;
|
|
58
|
+
return { repaired, wasFixed };
|
|
59
|
+
}
|
|
60
|
+
export function repairJson(json) {
|
|
61
|
+
return repairJsonDetailed(json).repaired;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* LRU cache for repairJson + JSON.parse combined operations.
|
|
65
|
+
* Prevents redundant string repair and parsing for identical inputs.
|
|
66
|
+
*/
|
|
67
|
+
const parseCache = new Map();
|
|
68
|
+
const PARSE_CACHE_MAX = 100;
|
|
69
|
+
/**
|
|
70
|
+
* Combines repairJson + JSON.parse into a single cached operation.
|
|
71
|
+
* Returns the parsed object directly. Returns { result: null, wasFixed: false } on error.
|
|
72
|
+
*/
|
|
73
|
+
export function safeParseJson(jsonStr, cacheKey) {
|
|
74
|
+
if (typeof jsonStr !== "string") {
|
|
75
|
+
return { result: jsonStr, wasFixed: false };
|
|
90
76
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return cached;
|
|
98
|
-
const { repaired, wasFixed } = this.repairJsonDetailed(json);
|
|
77
|
+
const key = cacheKey || jsonStr;
|
|
78
|
+
if (parseCache.has(key)) {
|
|
79
|
+
return parseCache.get(key);
|
|
80
|
+
}
|
|
81
|
+
const { repaired, wasFixed } = repairJsonDetailed(jsonStr);
|
|
82
|
+
try {
|
|
99
83
|
const result = JSON.parse(repaired);
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const firstKey = this.parseCache.keys().next().value;
|
|
84
|
+
const output = { result, wasFixed };
|
|
85
|
+
if (parseCache.size >= PARSE_CACHE_MAX) {
|
|
86
|
+
const firstKey = parseCache.keys().next().value;
|
|
104
87
|
if (firstKey)
|
|
105
|
-
|
|
88
|
+
parseCache.delete(firstKey);
|
|
106
89
|
}
|
|
107
|
-
|
|
90
|
+
parseCache.set(key, output);
|
|
91
|
+
return output;
|
|
108
92
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
id: firstCall.id,
|
|
150
|
-
repaired: true,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
catch (e) {
|
|
157
|
-
// Not valid JSON or not the right format, continue with other parsers
|
|
158
|
-
}
|
|
159
|
-
// 1. Check for Llama 3 / DeepSeek style tags first (more specific)
|
|
160
|
-
const llamaMatch = contentToParse.match(/<(?:\|tool_call_begin\|>|\|tool_calls_section_begin\|>)\s*([\w.]+)(?::\d+)?(?:\s*<\|tool_call_arguments?_begin\|>)?\s*([\s\S]*?)(?:\s*(?:<\|tool_call_end\|>|<\|tool_calls_section_end\|>)|$)/);
|
|
161
|
-
// Guard: Check for empty content between markers
|
|
162
|
-
if (llamaMatch) {
|
|
163
|
-
const capturedContent = llamaMatch[2];
|
|
164
|
-
if (!capturedContent || !capturedContent.trim()) {
|
|
165
|
-
console.warn("[Marie] JsonUtils: Tool section markers found but no content between them");
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
toolName = llamaMatch[1].replace(/^functions\./, "");
|
|
169
|
-
contentToParse = capturedContent;
|
|
170
|
-
isLlama = true;
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
// 1b. Check for compact Llama 3 / OpenRouter format: tool_name:id>JSON or tool_name>JSON
|
|
174
|
-
// This often appears in raw streams
|
|
175
|
-
const compactMatch = contentToParse.match(/([\w.]+)(?::(\d+))?>(\{[\s\S]*?)(?:$)/);
|
|
176
|
-
if (compactMatch) {
|
|
177
|
-
toolName = compactMatch[1].replace(/^functions\./, "");
|
|
178
|
-
const toolId = compactMatch[2] ? `call_${compactMatch[2]}` : undefined;
|
|
179
|
-
contentToParse = compactMatch[3];
|
|
180
|
-
const { repaired, wasFixed } = this.repairJsonDetailed(contentToParse);
|
|
181
|
-
try {
|
|
182
|
-
const parsed = JSON.parse(repaired);
|
|
93
|
+
catch (e) {
|
|
94
|
+
return { result: null, wasFixed: false };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Extracts a tool call from unstructured mixed markdown/JSON text.
|
|
99
|
+
* Prioritizes custom Llama 3 markers but falls back to markdown extraction and structural analysis.
|
|
100
|
+
*/
|
|
101
|
+
export function extractToolCall(text) {
|
|
102
|
+
if (typeof text !== "string")
|
|
103
|
+
return null;
|
|
104
|
+
const trimmedText = text.trim();
|
|
105
|
+
if (!trimmedText || trimmedText.length < 5)
|
|
106
|
+
return null;
|
|
107
|
+
let contentToParse = text;
|
|
108
|
+
let isLlama = false;
|
|
109
|
+
let toolName = "";
|
|
110
|
+
// 0. Handle <thought> tags (some models emit reasoning before tools)
|
|
111
|
+
// We strip them to avoid regex confusion if they contain XML-like text
|
|
112
|
+
contentToParse = contentToParse.replace(/<thought>[\s\S]*?<\/thought>/g, "");
|
|
113
|
+
// 0b. Guard: Check if content is only section markers with nothing between them
|
|
114
|
+
const onlyMarkersPattern = /^\s*<\|tool_calls_section_begin\|>\s*<\|tool_calls_section_end\|>\s*$/;
|
|
115
|
+
if (onlyMarkersPattern.test(contentToParse)) {
|
|
116
|
+
console.warn("[Marie] JsonUtils: Empty tool section markers detected");
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
// 0c. NEW: Check for JSON tool_calls array format (e.g., from Claude)
|
|
120
|
+
// Format: { "tool_calls": [{ "id": "...", "type": "write_file", "arguments": {...} }] }
|
|
121
|
+
try {
|
|
122
|
+
const jsonStart = contentToParse.indexOf("{");
|
|
123
|
+
const jsonEnd = contentToParse.lastIndexOf("}");
|
|
124
|
+
if (jsonStart !== -1 && jsonEnd > jsonStart) {
|
|
125
|
+
const jsonCandidate = contentToParse.substring(jsonStart, jsonEnd + 1);
|
|
126
|
+
const parsed = JSON.parse(jsonCandidate);
|
|
127
|
+
if (parsed.tool_calls &&
|
|
128
|
+
Array.isArray(parsed.tool_calls) &&
|
|
129
|
+
parsed.tool_calls.length > 0) {
|
|
130
|
+
const firstCall = parsed.tool_calls[0];
|
|
131
|
+
if (firstCall.type && firstCall.arguments) {
|
|
132
|
+
console.log("[Marie] JsonUtils: Found JSON tool_calls format");
|
|
183
133
|
return {
|
|
184
|
-
name:
|
|
185
|
-
input:
|
|
186
|
-
id:
|
|
187
|
-
repaired:
|
|
134
|
+
name: firstCall.type,
|
|
135
|
+
input: firstCall.arguments,
|
|
136
|
+
id: firstCall.id,
|
|
137
|
+
repaired: true,
|
|
188
138
|
};
|
|
189
139
|
}
|
|
190
|
-
catch (e) {
|
|
191
|
-
// Fall through if not valid JSON yet
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// 2. Check for DeepSeek style <tool_code>...</tool_code>
|
|
195
|
-
const toolCodeMatch = contentToParse.match(/<tool_code>([\s\S]*?)(?:<\/tool_code>|$)/);
|
|
196
|
-
if (toolCodeMatch) {
|
|
197
|
-
contentToParse = toolCodeMatch[1];
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// 3. Check for Qwen style <tool_call>...</tool_call>
|
|
201
|
-
const toolCallTagMatch = contentToParse.match(/<tool_call>([\s\S]*?)(?:<\/tool_call>|$)/);
|
|
202
|
-
if (toolCallTagMatch) {
|
|
203
|
-
contentToParse = toolCallTagMatch[1];
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
// 4. Check for <tool>...</tool>
|
|
207
|
-
const toolTagMatch = contentToParse.match(/<tool>([\s\S]*?)(?:<\/tool>|$)/);
|
|
208
|
-
if (toolTagMatch) {
|
|
209
|
-
contentToParse = toolTagMatch[1];
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
// 5. Check for XML style <invoke name="...">...</invoke>
|
|
213
|
-
const invokeStartMatch = contentToParse.match(/<invoke\s+([^>]*?name=["']?([^"'\s>]+)["']?[^>]*?)>/i);
|
|
214
|
-
if (invokeStartMatch) {
|
|
215
|
-
toolName = invokeStartMatch[2];
|
|
216
|
-
const invokeStartIdx = invokeStartMatch.index;
|
|
217
|
-
const contentAfterStart = contentToParse.substring(invokeStartIdx + invokeStartMatch[0].length);
|
|
218
|
-
// Find closing </invoke> (handling potential nesting)
|
|
219
|
-
const invokeEndIdx = contentAfterStart.lastIndexOf("</invoke>");
|
|
220
|
-
const innerContent = invokeEndIdx !== -1
|
|
221
|
-
? contentAfterStart.substring(0, invokeEndIdx)
|
|
222
|
-
: contentAfterStart; // Auto-close if missing
|
|
223
|
-
// Robust Parameter Extraction (Nesting-Aware)
|
|
224
|
-
const params = {};
|
|
225
|
-
const paramStartRegex = /<parameter\s+[^>]*?name=["']?([^"'\s>]+)["']?[^>]*?>/gi;
|
|
226
|
-
let pMatch;
|
|
227
|
-
while ((pMatch = paramStartRegex.exec(innerContent)) !== null) {
|
|
228
|
-
const pName = pMatch[1];
|
|
229
|
-
const pStartIdx = pMatch.index + pMatch[0].length;
|
|
230
|
-
// Find corresponding </parameter>
|
|
231
|
-
const nextEndIdx = innerContent.indexOf("</parameter>", pStartIdx);
|
|
232
|
-
const pValueRaw = nextEndIdx !== -1
|
|
233
|
-
? innerContent.substring(pStartIdx, nextEndIdx)
|
|
234
|
-
: innerContent.substring(pStartIdx); // Auto-close
|
|
235
|
-
const pValue = pValueRaw.trim();
|
|
236
|
-
// Basic level-1 JSON / Type parsing
|
|
237
|
-
if (pValue.startsWith("{") || pValue.startsWith("[")) {
|
|
238
|
-
try {
|
|
239
|
-
// Attempt to repair and parse any block starting with { or [
|
|
240
|
-
params[pName] = JSON.parse(this.repairJson(pValue));
|
|
241
|
-
}
|
|
242
|
-
catch (e) {
|
|
243
|
-
params[pName] = pValue;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
else if (pValue.toLowerCase() === "true") {
|
|
247
|
-
params[pName] = true;
|
|
248
|
-
}
|
|
249
|
-
else if (pValue.toLowerCase() === "false") {
|
|
250
|
-
params[pName] = false;
|
|
251
|
-
}
|
|
252
|
-
else if (!isNaN(Number(pValue)) && pValue !== "") {
|
|
253
|
-
params[pName] = Number(pValue);
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
params[pName] = pValue;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
if (Object.keys(params).length > 0) {
|
|
260
|
-
return { name: toolName, input: params, repaired: true };
|
|
261
|
-
}
|
|
262
|
-
contentToParse = innerContent;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
140
|
}
|
|
267
141
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const bracketMatch = contentToParse.match(/\[Tool Use:\s*([\w.]+)\s*\]/i);
|
|
280
|
-
if (bracketMatch && !toolName) {
|
|
281
|
-
toolName = bracketMatch[1];
|
|
282
|
-
console.log(`[Marie] JsonUtils: Found bracketed tool name: ${toolName}`);
|
|
283
|
-
}
|
|
284
|
-
if (firstBrace === -1) {
|
|
285
|
-
// If we have a tool name but no JSON, return it with empty input (might be a parameterless tool)
|
|
286
|
-
if (toolName) {
|
|
287
|
-
return { name: toolName, input: {}, repaired: true };
|
|
288
|
-
}
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
// Not valid JSON or not the right format, continue with other parsers
|
|
145
|
+
}
|
|
146
|
+
// 1. Check for Llama 3 / DeepSeek style tags first (more specific)
|
|
147
|
+
const llamaMatch = contentToParse.match(/<(?:\|tool_call_begin\|>|\|tool_calls_section_begin\|>)\s*([\w.]+)(?::\d+)?(?:\s*<\|tool_call_arguments?_begin\|>)?\s*([\s\S]*?)(?:\s*(?:<\|tool_call_end\|>|<\|tool_calls_section_end\|>)|$)/);
|
|
148
|
+
// Guard: Check for empty content between markers
|
|
149
|
+
if (llamaMatch) {
|
|
150
|
+
const capturedContent = llamaMatch[2];
|
|
151
|
+
if (!capturedContent || !capturedContent.trim()) {
|
|
152
|
+
console.warn("[Marie] JsonUtils: Tool section markers found but no content between them");
|
|
289
153
|
return null;
|
|
290
154
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
155
|
+
toolName = llamaMatch[1].replace(/^functions\./, "");
|
|
156
|
+
contentToParse = capturedContent;
|
|
157
|
+
isLlama = true;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// 1b. Check for compact Llama 3 / OpenRouter format: tool_name:id>JSON or tool_name>JSON
|
|
161
|
+
// This often appears in raw streams
|
|
162
|
+
const compactMatch = contentToParse.match(/([\w.]+)(?::(\d+))?>(\{[\s\S]*?)(?:$)/);
|
|
163
|
+
if (compactMatch) {
|
|
164
|
+
toolName = compactMatch[1].replace(/^functions\./, "");
|
|
165
|
+
const toolId = compactMatch[2] ? `call_${compactMatch[2]}` : undefined;
|
|
166
|
+
contentToParse = compactMatch[3];
|
|
167
|
+
const { repaired, wasFixed } = repairJsonDetailed(contentToParse);
|
|
168
|
+
try {
|
|
169
|
+
const parsed = JSON.parse(repaired);
|
|
296
170
|
return {
|
|
297
171
|
name: toolName,
|
|
298
172
|
input: parsed,
|
|
299
|
-
|
|
173
|
+
id: toolId,
|
|
174
|
+
repaired: wasFixed,
|
|
300
175
|
};
|
|
301
176
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
// Heuristic: if we had to strip markdown or prefix, it was "repaired"
|
|
305
|
-
normalized.repaired = wasFixed || hasMarkdown || firstBrace > 0;
|
|
306
|
-
return normalized;
|
|
177
|
+
catch (e) {
|
|
178
|
+
// Fall through if not valid JSON yet
|
|
307
179
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
180
|
+
}
|
|
181
|
+
// 2. Check for DeepSeek style <tool_code>...</tool_code>
|
|
182
|
+
const toolCodeMatch = contentToParse.match(/<tool_code>([\s\S]*?)(?:<\/tool_code>|$)/);
|
|
183
|
+
if (toolCodeMatch) {
|
|
184
|
+
contentToParse = toolCodeMatch[1];
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// 3. Check for Qwen style <tool_call>...</tool_call>
|
|
188
|
+
const toolCallTagMatch = contentToParse.match(/<tool_call>([\s\S]*?)(?:<\/tool_call>|$)/);
|
|
189
|
+
if (toolCallTagMatch) {
|
|
190
|
+
contentToParse = toolCallTagMatch[1];
|
|
315
191
|
}
|
|
316
192
|
}
|
|
317
|
-
|
|
318
|
-
|
|
193
|
+
}
|
|
194
|
+
// 4. Try extracting from Markdown JSON blocks (e.g. ```json ... ```)
|
|
195
|
+
const jsonBlockMatch = contentToParse.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
196
|
+
const hasMarkdown = !!jsonBlockMatch && !isLlama;
|
|
197
|
+
if (jsonBlockMatch && !isLlama) {
|
|
198
|
+
contentToParse = jsonBlockMatch[1];
|
|
199
|
+
}
|
|
200
|
+
// Attempt to parse exactly what we've isolated first
|
|
201
|
+
let firstBrace = contentToParse.indexOf("{");
|
|
202
|
+
if (!isLlama && firstBrace === -1) {
|
|
203
|
+
// Very fallback: Check for loose JSON at the END of the message if no block found
|
|
204
|
+
// Model might just start spitting JSON halfway through
|
|
205
|
+
const fallbackBrace = contentToParse.lastIndexOf("{");
|
|
206
|
+
if (fallbackBrace !== -1) {
|
|
207
|
+
firstBrace = fallbackBrace;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Sometimes models prefix the JSON with the tool name without markers
|
|
211
|
+
if (firstBrace > 0 && !isLlama) {
|
|
212
|
+
const prefix = contentToParse.substring(0, firstBrace).trim();
|
|
213
|
+
if (prefix && prefix.length < 50 && !prefix.includes(" ")) {
|
|
214
|
+
console.log(`[Marie] JsonUtils: Found bracketed tool name: ${toolName}`);
|
|
215
|
+
toolName = prefix;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (firstBrace === -1) {
|
|
219
|
+
// If we have a tool name but no JSON, return it with empty input (might be a parameterless tool)
|
|
220
|
+
if (toolName) {
|
|
221
|
+
return { name: toolName, input: {}, repaired: true };
|
|
319
222
|
}
|
|
320
223
|
return null;
|
|
321
224
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
225
|
+
const jsonCandidate = contentToParse.substring(firstBrace);
|
|
226
|
+
try {
|
|
227
|
+
const { repaired, wasFixed } = repairJsonDetailed(jsonCandidate);
|
|
228
|
+
const parsed = JSON.parse(repaired);
|
|
229
|
+
if (isLlama) {
|
|
325
230
|
return {
|
|
326
|
-
name:
|
|
327
|
-
input: parsed
|
|
328
|
-
|
|
231
|
+
name: toolName,
|
|
232
|
+
input: parsed,
|
|
233
|
+
repaired: wasFixed || hasMarkdown,
|
|
329
234
|
};
|
|
330
235
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
: parsed.arguments,
|
|
337
|
-
id: parsed.id,
|
|
338
|
-
};
|
|
236
|
+
const normalized = normalizeToolCall(parsed);
|
|
237
|
+
if (normalized) {
|
|
238
|
+
// Heuristic: if we had to strip markdown or prefix, it was "repaired"
|
|
239
|
+
normalized.repaired = wasFixed || hasMarkdown || firstBrace > 0;
|
|
240
|
+
return normalized;
|
|
339
241
|
}
|
|
340
|
-
if (
|
|
242
|
+
else if (toolName) {
|
|
243
|
+
// Use the bracketed tool name if normalization failed (JSON is just arguments)
|
|
341
244
|
return {
|
|
342
|
-
name:
|
|
343
|
-
input: parsed
|
|
344
|
-
|
|
245
|
+
name: toolName,
|
|
246
|
+
input: parsed,
|
|
247
|
+
repaired: wasFixed || hasMarkdown || firstBrace > 0,
|
|
345
248
|
};
|
|
346
249
|
}
|
|
347
|
-
|
|
348
|
-
|
|
250
|
+
}
|
|
251
|
+
catch (e) {
|
|
252
|
+
// console.error("Failed to parse tool content:", e);
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
function normalizeToolCall(parsed) {
|
|
257
|
+
if (!parsed || typeof parsed !== "object")
|
|
258
|
+
return null;
|
|
259
|
+
// Handle different common formats
|
|
260
|
+
if (parsed.tool_name && parsed.tool_input) {
|
|
261
|
+
return {
|
|
262
|
+
name: parsed.tool_name,
|
|
263
|
+
input: parsed.tool_input,
|
|
264
|
+
id: parsed.tool_id,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (parsed.name && parsed.arguments) {
|
|
268
|
+
return {
|
|
269
|
+
name: parsed.name,
|
|
270
|
+
input: typeof parsed.arguments === "string"
|
|
271
|
+
? safeParseJson(parsed.arguments).result
|
|
272
|
+
: parsed.arguments,
|
|
273
|
+
id: parsed.id,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
if (parsed.name && parsed.input) {
|
|
277
|
+
return {
|
|
278
|
+
name: parsed.name,
|
|
279
|
+
input: parsed.input,
|
|
280
|
+
id: parsed.id,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
// Literal format: { "write_file": { ... } }
|
|
284
|
+
try {
|
|
285
|
+
const keys = safeGetKeys(parsed, 10);
|
|
349
286
|
if (keys.length === 1 &&
|
|
350
287
|
typeof parsed[keys[0]] === "object" &&
|
|
288
|
+
parsed[keys[0]] !== null &&
|
|
351
289
|
!Array.isArray(parsed[keys[0]])) {
|
|
352
290
|
return {
|
|
353
291
|
name: keys[0],
|
|
354
292
|
input: parsed[keys[0]],
|
|
355
293
|
};
|
|
356
294
|
}
|
|
357
|
-
return null;
|
|
358
295
|
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
// Ignore enumeration errors
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
359
300
|
}
|
|
360
301
|
//# sourceMappingURL=JsonUtils.js.map
|