@noorm/marie-cli 0.1.0
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/JOY_ZONING.md +200 -0
- package/LICENSE.md +190 -0
- package/README.md +94 -0
- package/dist/cli-new/components/App.js +138 -0
- package/dist/cli-new/components/App.js.map +1 -0
- package/dist/cli-new/components/ApprovalDialog.js +31 -0
- package/dist/cli-new/components/ApprovalDialog.js.map +1 -0
- package/dist/cli-new/components/Banner.js +23 -0
- package/dist/cli-new/components/Banner.js.map +1 -0
- package/dist/cli-new/components/ChatArea.js +49 -0
- package/dist/cli-new/components/ChatArea.js.map +1 -0
- package/dist/cli-new/components/Header.js +20 -0
- package/dist/cli-new/components/Header.js.map +1 -0
- package/dist/cli-new/components/InputArea.js +97 -0
- package/dist/cli-new/components/InputArea.js.map +1 -0
- package/dist/cli-new/components/MessageBubble.js +114 -0
- package/dist/cli-new/components/MessageBubble.js.map +1 -0
- package/dist/cli-new/components/SessionSwitcher.js +46 -0
- package/dist/cli-new/components/SessionSwitcher.js.map +1 -0
- package/dist/cli-new/components/SetupWizard.js +283 -0
- package/dist/cli-new/components/SetupWizard.js.map +1 -0
- package/dist/cli-new/components/ToolCallDisplay.js +45 -0
- package/dist/cli-new/components/ToolCallDisplay.js.map +1 -0
- package/dist/cli-new/hooks/useGit.js +99 -0
- package/dist/cli-new/hooks/useGit.js.map +1 -0
- package/dist/cli-new/hooks/useMarie.js +249 -0
- package/dist/cli-new/hooks/useMarie.js.map +1 -0
- package/dist/cli-new/hooks/useSessions.js +75 -0
- package/dist/cli-new/hooks/useSessions.js.map +1 -0
- package/dist/cli-new/index.js +52 -0
- package/dist/cli-new/index.js.map +1 -0
- package/dist/cli-new/styles/theme.js +68 -0
- package/dist/cli-new/styles/theme.js.map +1 -0
- package/dist/cli-new/types/cli.js +2 -0
- package/dist/cli-new/types/cli.js.map +1 -0
- package/dist/extension.cjs +655 -0
- package/dist/monolith/adapters/CliMarieAdapter.js +72 -0
- package/dist/monolith/adapters/CliMarieAdapter.js.map +1 -0
- package/dist/monolith/adapters/VscodeMarieAdapter.js +81 -0
- package/dist/monolith/adapters/VscodeMarieAdapter.js.map +1 -0
- package/dist/monolith/cli/CliFileSystemPort.js +83 -0
- package/dist/monolith/cli/CliFileSystemPort.js.map +1 -0
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js +438 -0
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js.map +1 -0
- package/dist/monolith/cli/index.js +272 -0
- package/dist/monolith/cli/index.js.map +1 -0
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js +80 -0
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js.map +1 -0
- package/dist/monolith/cli/services/JoyServiceCLI.js +63 -0
- package/dist/monolith/cli/services/JoyServiceCLI.js.map +1 -0
- package/dist/monolith/cli/storage.js +119 -0
- package/dist/monolith/cli/storage.js.map +1 -0
- package/dist/monolith/domain/joy/JoyTools.js +513 -0
- package/dist/monolith/domain/joy/JoyTools.js.map +1 -0
- package/dist/monolith/domain/joy/RitualService.js +51 -0
- package/dist/monolith/domain/joy/RitualService.js.map +1 -0
- package/dist/monolith/domain/marie/MarieTypes.js +2 -0
- package/dist/monolith/domain/marie/MarieTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js +230 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js +207 -0
- package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js.map +1 -0
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js +129 -0
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js.map +1 -0
- package/dist/monolith/infrastructure/ai/context/ContextManager.js +118 -0
- package/dist/monolith/infrastructure/ai/context/ContextManager.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/FileSystemPort.js +2 -0
- package/dist/monolith/infrastructure/ai/core/FileSystemPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/GhostPort.js +2 -0
- package/dist/monolith/infrastructure/ai/core/GhostPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieAscensionTypes.js +2 -0
- package/dist/monolith/infrastructure/ai/core/MarieAscensionTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js +590 -0
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js +161 -0
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js +121 -0
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js +256 -0
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MariePulseService.js +67 -0
- package/dist/monolith/infrastructure/ai/core/MariePulseService.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieResponse.js +101 -0
- package/dist/monolith/infrastructure/ai/core/MarieResponse.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js +86 -0
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieSession.js +202 -0
- package/dist/monolith/infrastructure/ai/core/MarieSession.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js +58 -0
- package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolMender.js +127 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolMender.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js +548 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js +2 -0
- package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js +125 -0
- package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js +30 -0
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js +2 -0
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js +148 -0
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js +208 -0
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js +404 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js +283 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js.map +1 -0
- package/dist/monolith/infrastructure/config/ConfigService.js +398 -0
- package/dist/monolith/infrastructure/config/ConfigService.js.map +1 -0
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js +140 -0
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js.map +1 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js +1568 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js.map +1 -0
- package/dist/monolith/infrastructure/tools/PureStreamParser.js +147 -0
- package/dist/monolith/infrastructure/tools/PureStreamParser.js.map +1 -0
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js +223 -0
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js +29 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolUtils.js +59 -0
- package/dist/monolith/infrastructure/tools/ToolUtils.js.map +1 -0
- package/dist/monolith/plumbing/analysis/CodeHealthService.js +146 -0
- package/dist/monolith/plumbing/analysis/CodeHealthService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js +43 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/DependencyService.js +51 -0
- package/dist/monolith/plumbing/analysis/DependencyService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/DiscoveryService.js +49 -0
- package/dist/monolith/plumbing/analysis/DiscoveryService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/JoyMapService.js +66 -0
- package/dist/monolith/plumbing/analysis/JoyMapService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/LintService.js +132 -0
- package/dist/monolith/plumbing/analysis/LintService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js +276 -0
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js +119 -0
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/SurgicalMender.js +70 -0
- package/dist/monolith/plumbing/analysis/SurgicalMender.js.map +1 -0
- package/dist/monolith/plumbing/analysis/TestService.js +104 -0
- package/dist/monolith/plumbing/analysis/TestService.js.map +1 -0
- package/dist/monolith/plumbing/filesystem/FileService.js +406 -0
- package/dist/monolith/plumbing/filesystem/FileService.js.map +1 -0
- package/dist/monolith/plumbing/filesystem/PathResolver.js +26 -0
- package/dist/monolith/plumbing/filesystem/PathResolver.js.map +1 -0
- package/dist/monolith/plumbing/git/GitService.js +71 -0
- package/dist/monolith/plumbing/git/GitService.js.map +1 -0
- package/dist/monolith/plumbing/lsp/SymbolService.js +36 -0
- package/dist/monolith/plumbing/lsp/SymbolService.js.map +1 -0
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js +31 -0
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js.map +1 -0
- package/dist/monolith/plumbing/terminal/TerminalService.js +180 -0
- package/dist/monolith/plumbing/terminal/TerminalService.js.map +1 -0
- package/dist/monolith/plumbing/ui/DecorationService.js +54 -0
- package/dist/monolith/plumbing/ui/DecorationService.js.map +1 -0
- package/dist/monolith/plumbing/utils/ErrorUtils.js +11 -0
- package/dist/monolith/plumbing/utils/ErrorUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/JsonUtils.js +360 -0
- package/dist/monolith/plumbing/utils/JsonUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js +153 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js.map +1 -0
- package/dist/monolith/plumbing/utils/RetryUtils.js +141 -0
- package/dist/monolith/plumbing/utils/RetryUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/StreamTagDetector.js +128 -0
- package/dist/monolith/plumbing/utils/StreamTagDetector.js.map +1 -0
- package/dist/monolith/plumbing/utils/StringUtils.js +97 -0
- package/dist/monolith/plumbing/utils/StringUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/TimeoutUtils.js +21 -0
- package/dist/monolith/plumbing/utils/TimeoutUtils.js.map +1 -0
- package/dist/monolith/runtime/MarieRuntime.js +354 -0
- package/dist/monolith/runtime/MarieRuntime.js.map +1 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js +59 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js.map +1 -0
- package/dist/monolith/runtime/providerFactory.js +11 -0
- package/dist/monolith/runtime/providerFactory.js.map +1 -0
- package/dist/monolith/runtime/types.js +2 -0
- package/dist/monolith/runtime/types.js.map +1 -0
- package/dist/monolith/services/HealthService.js +38 -0
- package/dist/monolith/services/HealthService.js.map +1 -0
- package/dist/monolith/services/JoyAutomationService.js +131 -0
- package/dist/monolith/services/JoyAutomationService.js.map +1 -0
- package/dist/monolith/services/JoyLogService.js +48 -0
- package/dist/monolith/services/JoyLogService.js.map +1 -0
- package/dist/monolith/services/JoyService.js +190 -0
- package/dist/monolith/services/JoyService.js.map +1 -0
- package/dist/monolith/services/MarieGhostService.js +168 -0
- package/dist/monolith/services/MarieGhostService.js.map +1 -0
- package/dist/monolith/services/MarieSCMProvider.js +41 -0
- package/dist/monolith/services/MarieSCMProvider.js.map +1 -0
- package/package.json +168 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { StringUtils } from "./StringUtils.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prefix Tree (Trie) for efficient tag detection.
|
|
4
|
+
* Provides O(k) complexity for finding tags where k = input length.
|
|
5
|
+
*/
|
|
6
|
+
export class PrefixTree {
|
|
7
|
+
root = { children: new Map(), isEndOfTag: false };
|
|
8
|
+
tags = [];
|
|
9
|
+
constructor(tags) {
|
|
10
|
+
this.tags = tags;
|
|
11
|
+
for (const tag of tags) {
|
|
12
|
+
this.insert(tag);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Insert a tag into the trie.
|
|
17
|
+
*/
|
|
18
|
+
insert(tag) {
|
|
19
|
+
let node = this.root;
|
|
20
|
+
for (const char of tag) {
|
|
21
|
+
if (!node.children.has(char)) {
|
|
22
|
+
node.children.set(char, { children: new Map(), isEndOfTag: false });
|
|
23
|
+
}
|
|
24
|
+
node = node.children.get(char);
|
|
25
|
+
}
|
|
26
|
+
node.isEndOfTag = true;
|
|
27
|
+
node.tag = tag;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Find the earliest complete tag in the text.
|
|
31
|
+
* Returns { index: number, tag: string } if found, null otherwise.
|
|
32
|
+
* Optimized with early-exit for O(k) performance.
|
|
33
|
+
*/
|
|
34
|
+
findEarliestTag(text) {
|
|
35
|
+
let earliestIndex = Infinity;
|
|
36
|
+
let earliestTag = "";
|
|
37
|
+
// Try to match from each position in the text (with early-exit)
|
|
38
|
+
for (let startIdx = 0; startIdx < text.length; startIdx++) {
|
|
39
|
+
// Early-exit: if we already found a tag at an earlier position, stop
|
|
40
|
+
if (startIdx >= earliestIndex) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
const result = this.matchFromPosition(text, startIdx);
|
|
44
|
+
if (result && result.index < earliestIndex) {
|
|
45
|
+
earliestIndex = result.index;
|
|
46
|
+
earliestTag = result.tag;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return earliestTag ? { index: earliestIndex, tag: earliestTag } : null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Match a tag starting from a specific position.
|
|
53
|
+
* Returns the SHORTEST matching tag (to handle prefix overlaps correctly).
|
|
54
|
+
*/
|
|
55
|
+
matchFromPosition(text, startIdx) {
|
|
56
|
+
let node = this.root;
|
|
57
|
+
let firstMatch = null;
|
|
58
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
59
|
+
const char = text[i];
|
|
60
|
+
if (!node.children.has(char)) {
|
|
61
|
+
// Can't continue matching
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
node = node.children.get(char);
|
|
65
|
+
if (node.isEndOfTag && !firstMatch) {
|
|
66
|
+
// Found first complete tag at this position
|
|
67
|
+
firstMatch = node.tag;
|
|
68
|
+
// Return immediately to get the shortest match
|
|
69
|
+
return { index: startIdx, tag: firstMatch };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Find the longest partial tag at the end of the text.
|
|
76
|
+
* Returns the length of the partial match (0 if none).
|
|
77
|
+
*/
|
|
78
|
+
findLongestPartialAtEnd(text) {
|
|
79
|
+
let maxPartialLength = 0;
|
|
80
|
+
// Try matching from each position toward the end
|
|
81
|
+
for (let startIdx = 0; startIdx < text.length; startIdx++) {
|
|
82
|
+
const partialLength = this.matchPartialFromPosition(text, startIdx);
|
|
83
|
+
if (partialLength > 0 && startIdx + partialLength === text.length) {
|
|
84
|
+
maxPartialLength = Math.max(maxPartialLength, partialLength);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return maxPartialLength;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Match a partial tag from a position, returns length of match.
|
|
91
|
+
*/
|
|
92
|
+
matchPartialFromPosition(text, startIdx) {
|
|
93
|
+
let node = this.root;
|
|
94
|
+
let matchLength = 0;
|
|
95
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
96
|
+
const char = text[i];
|
|
97
|
+
if (!node.children.has(char)) {
|
|
98
|
+
return matchLength;
|
|
99
|
+
}
|
|
100
|
+
node = node.children.get(char);
|
|
101
|
+
matchLength++;
|
|
102
|
+
if (node.isEndOfTag) {
|
|
103
|
+
// This is a complete tag, not a partial
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// We matched up to the end of text without completing a tag
|
|
108
|
+
return matchLength;
|
|
109
|
+
}
|
|
110
|
+
editDistanceCache = new Map();
|
|
111
|
+
static MAX_CACHE_SIZE = 1000;
|
|
112
|
+
/**
|
|
113
|
+
* Find similar tags using edit distance (Levenshtein).
|
|
114
|
+
* Returns tags with edit distance <= maxDistance.
|
|
115
|
+
* Uses caching with eviction for improved performance.
|
|
116
|
+
*/
|
|
117
|
+
findSimilarTags(input, maxDistance = 2) {
|
|
118
|
+
const similar = [];
|
|
119
|
+
for (const tag of this.tags) {
|
|
120
|
+
const cacheKey = `${input}:${tag}`;
|
|
121
|
+
let distance = this.editDistanceCache.get(cacheKey);
|
|
122
|
+
if (distance === undefined) {
|
|
123
|
+
distance = this.editDistance(input, tag);
|
|
124
|
+
// Evict oldest half when cache exceeds max size
|
|
125
|
+
if (this.editDistanceCache.size >= PrefixTree.MAX_CACHE_SIZE) {
|
|
126
|
+
const keysToDelete = Array.from(this.editDistanceCache.keys()).slice(0, PrefixTree.MAX_CACHE_SIZE / 2);
|
|
127
|
+
for (const key of keysToDelete) {
|
|
128
|
+
this.editDistanceCache.delete(key);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
this.editDistanceCache.set(cacheKey, distance);
|
|
132
|
+
}
|
|
133
|
+
if (distance <= maxDistance) {
|
|
134
|
+
similar.push(tag);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return similar;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Calculate Levenshtein edit distance between two strings.
|
|
141
|
+
* Delegates to StringUtils for the optimized 2-row implementation.
|
|
142
|
+
*/
|
|
143
|
+
editDistance(a, b) {
|
|
144
|
+
return StringUtils.levenshtein(a, b);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Clear the edit distance cache to free memory.
|
|
148
|
+
*/
|
|
149
|
+
clearCache() {
|
|
150
|
+
this.editDistanceCache.clear();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=PrefixTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrefixTree.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/utils/PrefixTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error category classification for retry behavior.
|
|
3
|
+
*/
|
|
4
|
+
export var ErrorCategory;
|
|
5
|
+
(function (ErrorCategory) {
|
|
6
|
+
ErrorCategory["TRANSIENT"] = "TRANSIENT";
|
|
7
|
+
ErrorCategory["PERMANENT"] = "PERMANENT";
|
|
8
|
+
ErrorCategory["UNKNOWN"] = "UNKNOWN";
|
|
9
|
+
})(ErrorCategory || (ErrorCategory = {}));
|
|
10
|
+
/**
|
|
11
|
+
* Retry configuration and utilities for handling transient errors.
|
|
12
|
+
*/
|
|
13
|
+
export class RetryConfig {
|
|
14
|
+
maxRetries = 3;
|
|
15
|
+
baseDelayMs = 100;
|
|
16
|
+
maxDelayMs = 5000;
|
|
17
|
+
// Errors that are definitely retryable (transient)
|
|
18
|
+
transientErrors = [
|
|
19
|
+
"ECONNRESET",
|
|
20
|
+
"ETIMEDOUT",
|
|
21
|
+
"ENOTFOUND",
|
|
22
|
+
"ECONNREFUSED",
|
|
23
|
+
"timeout",
|
|
24
|
+
"throttle",
|
|
25
|
+
"rate limit",
|
|
26
|
+
"too many requests",
|
|
27
|
+
"429",
|
|
28
|
+
"503",
|
|
29
|
+
"504",
|
|
30
|
+
];
|
|
31
|
+
// Errors that are definitely NOT retryable (permanent)
|
|
32
|
+
permanentErrors = [
|
|
33
|
+
"EACCES",
|
|
34
|
+
"EPERM",
|
|
35
|
+
"permission denied",
|
|
36
|
+
"unauthorized",
|
|
37
|
+
"forbidden",
|
|
38
|
+
"401",
|
|
39
|
+
"403",
|
|
40
|
+
"invalid",
|
|
41
|
+
"validation",
|
|
42
|
+
"not found",
|
|
43
|
+
"404",
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Categorize an error based on its message.
|
|
47
|
+
*/
|
|
48
|
+
categorizeError(errorMessage) {
|
|
49
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
50
|
+
// Check if it's a known transient error
|
|
51
|
+
if (this.transientErrors.some((err) => lowerMessage.includes(err.toLowerCase()))) {
|
|
52
|
+
return ErrorCategory.TRANSIENT;
|
|
53
|
+
}
|
|
54
|
+
// Check if it's a known permanent error
|
|
55
|
+
if (this.permanentErrors.some((err) => lowerMessage.includes(err.toLowerCase()))) {
|
|
56
|
+
return ErrorCategory.PERMANENT;
|
|
57
|
+
}
|
|
58
|
+
return ErrorCategory.UNKNOWN;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if an error message indicates a retryable error.
|
|
62
|
+
*/
|
|
63
|
+
isRetryable(errorMessage) {
|
|
64
|
+
const category = this.categorizeError(errorMessage);
|
|
65
|
+
// Only retry transient errors, not permanent or unknown
|
|
66
|
+
return category === ErrorCategory.TRANSIENT;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Calculate exponential backoff delay.
|
|
70
|
+
*/
|
|
71
|
+
getBackoffDelay(attemptNumber) {
|
|
72
|
+
const delay = this.baseDelayMs * Math.pow(2, attemptNumber);
|
|
73
|
+
// Add jitter (randomness) to prevent thundering herd
|
|
74
|
+
const jitter = Math.random() * 0.3 * delay;
|
|
75
|
+
return Math.min(delay + jitter, this.maxDelayMs);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Execute a function with retry logic, respecting an AbortSignal.
|
|
80
|
+
*/
|
|
81
|
+
export async function withRetry(fn, config, context, signal) {
|
|
82
|
+
let lastError = null;
|
|
83
|
+
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
84
|
+
if (signal?.aborted) {
|
|
85
|
+
throw new Error(`${context}: Aborted by user.`);
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
return await fn();
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
lastError = error;
|
|
92
|
+
const errorMessage = error?.message || String(error);
|
|
93
|
+
const category = config.categorizeError(errorMessage);
|
|
94
|
+
// Log error category for debugging
|
|
95
|
+
if (attempt === 0) {
|
|
96
|
+
console.log(`[Marie] ${context}: Error category: ${category}`);
|
|
97
|
+
}
|
|
98
|
+
// Don't retry if error is permanent
|
|
99
|
+
if (category === ErrorCategory.PERMANENT) {
|
|
100
|
+
console.log(`[Marie] ${context}: Permanent error, failing immediately.`);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
// Don't retry if error is unknown (conservative approach)
|
|
104
|
+
if (category === ErrorCategory.UNKNOWN) {
|
|
105
|
+
console.log(`[Marie] ${context}: Unknown error type, failing without retry.`);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
// Don't retry if we've exhausted attempts
|
|
109
|
+
if (attempt >= config.maxRetries) {
|
|
110
|
+
console.error(`[Marie] ${context}: Max retries (${config.maxRetries}) exceeded.`);
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
// Calculate backoff and retry (only for TRANSIENT errors)
|
|
114
|
+
const delay = config.getBackoffDelay(attempt);
|
|
115
|
+
console.warn(`[Marie] ${context}: Attempt ${attempt + 1} failed (${category}), retrying in ${Math.round(delay)}ms... Error: ${errorMessage}`);
|
|
116
|
+
await sleep(delay, signal);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Should never reach here, but TypeScript needs it
|
|
120
|
+
throw lastError || new Error(`${context}: Retry loop failed unexpectedly`);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Sleep for a specified number of milliseconds, optionally cancellable.
|
|
124
|
+
*/
|
|
125
|
+
function sleep(ms, signal) {
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
const timeout = setTimeout(() => {
|
|
128
|
+
if (signal)
|
|
129
|
+
signal.removeEventListener("abort", abortHandler);
|
|
130
|
+
resolve();
|
|
131
|
+
}, ms);
|
|
132
|
+
const abortHandler = () => {
|
|
133
|
+
clearTimeout(timeout);
|
|
134
|
+
reject(new Error("Operation aborted."));
|
|
135
|
+
};
|
|
136
|
+
if (signal) {
|
|
137
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=RetryUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetryUtils.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/utils/RetryUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { PrefixTree } from "./PrefixTree.js";
|
|
2
|
+
export class StreamTagDetector {
|
|
3
|
+
buffer = "";
|
|
4
|
+
static MAX_BUFFER_SIZE = 100000; // 100k chars safety limit
|
|
5
|
+
// Tags we want to detect.
|
|
6
|
+
// We strictly look for the start of a tool block or the end of one.
|
|
7
|
+
// Also includes Llama 3 variations and control tokens.
|
|
8
|
+
tags = [
|
|
9
|
+
"<|tool_call_begin|>",
|
|
10
|
+
"<|tool_call_end|>",
|
|
11
|
+
"<|tool_calls_section_begin|>", // Section begin marker
|
|
12
|
+
"<|tool_calls_section_end|>", // Section end marker
|
|
13
|
+
"<|tool_call_id|>", // Some models emit tool IDs separately
|
|
14
|
+
"<|tool_call_argument_begin|>",
|
|
15
|
+
"<|tool_call_arguments_begin|>", // Plural variant
|
|
16
|
+
"<tool>",
|
|
17
|
+
"</tool>",
|
|
18
|
+
"<function",
|
|
19
|
+
"</function>",
|
|
20
|
+
"<function_calls>",
|
|
21
|
+
"</function_calls>",
|
|
22
|
+
"<invoke",
|
|
23
|
+
"</invoke>",
|
|
24
|
+
"<thought>",
|
|
25
|
+
"</thought>",
|
|
26
|
+
"<tool_code>",
|
|
27
|
+
"</tool_code>",
|
|
28
|
+
"<tool_call>",
|
|
29
|
+
"</tool_call>",
|
|
30
|
+
"<|eot_id|>", // End of turn marker
|
|
31
|
+
"<|start_header_id|>", // Header start marker
|
|
32
|
+
"<|end_header_id|>", // Header end marker
|
|
33
|
+
];
|
|
34
|
+
prefixTree;
|
|
35
|
+
constructor() {
|
|
36
|
+
this.prefixTree = new PrefixTree(this.tags);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Processes a chunk of text and returns a status indicating what happened.
|
|
40
|
+
*
|
|
41
|
+
* - 'tag': A full tag was found. The returned `text` is content BEFORE the tag. `tag` is the tag itself.
|
|
42
|
+
* The buffer will contain any remainder AFTER the tag for the next call.
|
|
43
|
+
* - 'incomplete': A partial tag was found at the end. `text` is the safe content before it.
|
|
44
|
+
* The buffer holds the partial tag.
|
|
45
|
+
* - 'content': No tags found. `text` Is the full content. Buffer is empty.
|
|
46
|
+
*/
|
|
47
|
+
process(chunk) {
|
|
48
|
+
this.buffer += chunk;
|
|
49
|
+
// --- Buffer Growth Safety ---
|
|
50
|
+
if (this.buffer.length > StreamTagDetector.MAX_BUFFER_SIZE) {
|
|
51
|
+
console.error("[Marie] StreamTagDetector buffer exceeded safety limit. Flushing.");
|
|
52
|
+
const flushed = this.buffer;
|
|
53
|
+
this.buffer = "";
|
|
54
|
+
return { type: "content", text: flushed };
|
|
55
|
+
}
|
|
56
|
+
// 1. Check if we have any FULL tags using prefix tree (O(k) complexity)
|
|
57
|
+
const tagMatch = this.prefixTree.findEarliestTag(this.buffer);
|
|
58
|
+
if (tagMatch) {
|
|
59
|
+
// Found a tag!
|
|
60
|
+
// Emit content up to tag
|
|
61
|
+
const content = this.buffer.substring(0, tagMatch.index);
|
|
62
|
+
// Remove content + tag from buffer, keep remainder
|
|
63
|
+
this.buffer = this.buffer.substring(tagMatch.index + tagMatch.tag.length);
|
|
64
|
+
console.log(`[Marie] Tag detected: ${tagMatch.tag} at index ${tagMatch.index}`);
|
|
65
|
+
return { type: "tag", text: content, tag: tagMatch.tag };
|
|
66
|
+
}
|
|
67
|
+
// 2. Check for dynamic/malformed tags using regex
|
|
68
|
+
const lookbackLength = Math.min(200, this.buffer.length);
|
|
69
|
+
const recentBuffer = this.buffer.substring(this.buffer.length - lookbackLength);
|
|
70
|
+
// IMPORTANT: Keep this strict to avoid treating normal HTML/text tags
|
|
71
|
+
// (e.g. <script>, </button>) as tool tags.
|
|
72
|
+
// We only accept:
|
|
73
|
+
// - LLM control tags like <|tool_call_begin|>
|
|
74
|
+
// - compact call markers like call:0>
|
|
75
|
+
// - bracketed tool markers like [Tool Use: name]
|
|
76
|
+
const dynamicTagPattern = /<\|[\w_]{3,}(?:\|>|>)?|(?:^|[^a-zA-Z0-9_])(call:\d+>)|(?:^|[\s,])(\[Tool (?:Use|Result):[^\]]+\])/g;
|
|
77
|
+
const matches = Array.from(recentBuffer.matchAll(dynamicTagPattern));
|
|
78
|
+
if (matches.length > 0) {
|
|
79
|
+
const lastMatch = matches[matches.length - 1];
|
|
80
|
+
// If we have a capture group (index 1 or 2), use it, otherwise use the full match
|
|
81
|
+
const potentialTag = lastMatch[2] || lastMatch[1] || lastMatch[0];
|
|
82
|
+
// If it's a perfect match for a known tag or matches our dynamic pattern
|
|
83
|
+
// If we used a capture group, we need to adjust the index to point to that group specifically
|
|
84
|
+
const matchIndex = this.buffer.length -
|
|
85
|
+
lookbackLength +
|
|
86
|
+
lastMatch.index +
|
|
87
|
+
(lastMatch[0].length - potentialTag.length);
|
|
88
|
+
// Check if this is a definite tag (ends with > or ] or is a known tag)
|
|
89
|
+
if (potentialTag.endsWith(">") || potentialTag.endsWith("]") || this.tags.includes(potentialTag)) {
|
|
90
|
+
const content = this.buffer.substring(0, matchIndex);
|
|
91
|
+
this.buffer = this.buffer.substring(matchIndex + potentialTag.length);
|
|
92
|
+
console.log(`[Marie] Dynamic tag detected: ${potentialTag}`);
|
|
93
|
+
return { type: "tag", text: content, tag: potentialTag };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 3. Check for partials (both prefix tree and dynamic)
|
|
97
|
+
const partialLength = this.prefixTree.findLongestPartialAtEnd(this.buffer);
|
|
98
|
+
// Dynamic partial check (strict): only hold potential control-tag prefixes,
|
|
99
|
+
// not generic trailing words/text.
|
|
100
|
+
const trailingControlTag = this.buffer.match(/<\|[\w_]*$/);
|
|
101
|
+
const trailingCallMarker = this.buffer.match(/call:\d*$/);
|
|
102
|
+
const dynamicPartialLength = Math.max(trailingControlTag ? trailingControlTag[0].length : 0, trailingCallMarker ? trailingCallMarker[0].length : 0);
|
|
103
|
+
const maxPartial = Math.max(partialLength, dynamicPartialLength);
|
|
104
|
+
if (maxPartial > 0) {
|
|
105
|
+
const unsafeStart = this.buffer.length - maxPartial;
|
|
106
|
+
const content = this.buffer.substring(0, unsafeStart);
|
|
107
|
+
this.buffer = this.buffer.substring(unsafeStart);
|
|
108
|
+
return { type: "incomplete", text: content };
|
|
109
|
+
}
|
|
110
|
+
// 4. No tags, no partials. Emit all.
|
|
111
|
+
const allContent = this.buffer;
|
|
112
|
+
this.buffer = "";
|
|
113
|
+
return { type: "content", text: allContent };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resets the internal buffer. Useful for cleanup between sessions.
|
|
117
|
+
*/
|
|
118
|
+
reset() {
|
|
119
|
+
this.buffer = "";
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Returns the current buffer size for monitoring.
|
|
123
|
+
*/
|
|
124
|
+
getBufferSize() {
|
|
125
|
+
return this.buffer.length;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=StreamTagDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamTagDetector.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/utils/StreamTagDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export class StringUtils {
|
|
2
|
+
/**
|
|
3
|
+
* Calculates Levenshtein distance between two strings.
|
|
4
|
+
*/
|
|
5
|
+
static levenshtein(a, b) {
|
|
6
|
+
// PERF: Prevent exhaustive comparison on massive strings (O(N^2) hazard)
|
|
7
|
+
const MAX_LEVEN_CHARS = 5000;
|
|
8
|
+
if (a.length > MAX_LEVEN_CHARS || b.length > MAX_LEVEN_CHARS) {
|
|
9
|
+
// Fallback to a fast length-based and prefix-based estimation for safety
|
|
10
|
+
const prefLen = this.getCommonPrefixLength(a, b);
|
|
11
|
+
const suffLen = this.getCommonSuffixLength(a, b);
|
|
12
|
+
const lenDiff = Math.abs(a.length - b.length);
|
|
13
|
+
return (lenDiff + (Math.max(a.length, b.length) - prefLen - suffLen - lenDiff));
|
|
14
|
+
}
|
|
15
|
+
// Ensure 'a' is the shorter string so we only allocate O(min(n,m)) space
|
|
16
|
+
if (a.length > b.length) {
|
|
17
|
+
const t = a;
|
|
18
|
+
a = b;
|
|
19
|
+
b = t;
|
|
20
|
+
}
|
|
21
|
+
const aLen = a.length;
|
|
22
|
+
const bLen = b.length;
|
|
23
|
+
if (aLen === 0)
|
|
24
|
+
return bLen;
|
|
25
|
+
let prev = new Array(aLen + 1);
|
|
26
|
+
let curr = new Array(aLen + 1);
|
|
27
|
+
for (let j = 0; j <= aLen; j++)
|
|
28
|
+
prev[j] = j;
|
|
29
|
+
for (let i = 1; i <= bLen; i++) {
|
|
30
|
+
curr[0] = i;
|
|
31
|
+
for (let j = 1; j <= aLen; j++) {
|
|
32
|
+
if (b[i - 1] === a[j - 1]) {
|
|
33
|
+
curr[j] = prev[j - 1];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
curr[j] = Math.min(prev[j - 1], curr[j - 1], prev[j]) + 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Swap rows (reuse prev array on next iteration)
|
|
40
|
+
const tmp = prev;
|
|
41
|
+
prev = curr;
|
|
42
|
+
curr = tmp;
|
|
43
|
+
}
|
|
44
|
+
return prev[aLen];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Calculates similarity (0-1) between two strings using Levenshtein distance.
|
|
48
|
+
* Optimized with early exit for significantly different lengths.
|
|
49
|
+
*/
|
|
50
|
+
static similarity(a, b) {
|
|
51
|
+
const maxLength = Math.max(a.length, b.length);
|
|
52
|
+
const minLength = Math.min(a.length, b.length);
|
|
53
|
+
if (maxLength === 0)
|
|
54
|
+
return 1.0;
|
|
55
|
+
// Early exit: if strings differ by > 50% in length, similarity will be low
|
|
56
|
+
// This avoids expensive Levenshtein calculation for obviously dissimilar strings
|
|
57
|
+
const lengthRatio = minLength / maxLength;
|
|
58
|
+
if (lengthRatio < 0.5) {
|
|
59
|
+
// Still compute, but we know it won't be high similarity
|
|
60
|
+
// Could return 0 here for even faster processing, but let's be accurate
|
|
61
|
+
}
|
|
62
|
+
return (maxLength - this.levenshtein(a, b)) / maxLength;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Safely extracts text from AI message content which can be a string or array of blocks.
|
|
66
|
+
*/
|
|
67
|
+
static extractText(content) {
|
|
68
|
+
if (content === null || content === undefined)
|
|
69
|
+
return "";
|
|
70
|
+
if (typeof content === "string")
|
|
71
|
+
return content;
|
|
72
|
+
if (Array.isArray(content)) {
|
|
73
|
+
return content
|
|
74
|
+
.filter((block) => block && block.type === "text")
|
|
75
|
+
.map((block) => block.text || "")
|
|
76
|
+
.join(" ");
|
|
77
|
+
}
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
static getCommonPrefixLength(a, b) {
|
|
81
|
+
let i = 0;
|
|
82
|
+
const min = Math.min(a.length, b.length);
|
|
83
|
+
while (i < min && a[i] === b[i])
|
|
84
|
+
i++;
|
|
85
|
+
return i;
|
|
86
|
+
}
|
|
87
|
+
static getCommonSuffixLength(a, b) {
|
|
88
|
+
let i = 0;
|
|
89
|
+
const aLen = a.length;
|
|
90
|
+
const bLen = b.length;
|
|
91
|
+
const min = Math.min(aLen, bLen);
|
|
92
|
+
while (i < min && a[aLen - 1 - i] === b[bLen - 1 - i])
|
|
93
|
+
i++;
|
|
94
|
+
return i;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=StringUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StringUtils.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/utils/StringUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executes a promise with a timeout.
|
|
3
|
+
*/
|
|
4
|
+
export async function withTimeout(promise, ms, label) {
|
|
5
|
+
let timeoutId;
|
|
6
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
7
|
+
timeoutId = setTimeout(() => {
|
|
8
|
+
reject(new Error(`TimeoutError: ${label} timed out after ${ms}ms`));
|
|
9
|
+
}, ms);
|
|
10
|
+
});
|
|
11
|
+
try {
|
|
12
|
+
const result = await Promise.race([promise, timeoutPromise]);
|
|
13
|
+
clearTimeout(timeoutId);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
clearTimeout(timeoutId);
|
|
18
|
+
throw e;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=TimeoutUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeoutUtils.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/utils/TimeoutUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAmB,EACnB,EAAU,EACV,KAAa;IAEb,IAAI,SAAyB,CAAC;IAC9B,MAAM,cAAc,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QACtD,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,KAAK,oBAAoB,EAAE,IAAI,CAAC,CAAC,CAAC;QACtE,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAC7D,YAAY,CAAC,SAAU,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,YAAY,CAAC,SAAU,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC"}
|