@llmtune/cli 0.1.8 → 0.2.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/README.md +206 -181
- package/dist/agent/conversation.d.ts.map +1 -0
- package/dist/agent/conversation.js.map +1 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +45 -11
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/planner.d.ts.map +1 -0
- package/dist/agent/planner.js.map +1 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/commands/balance.d.ts +2 -0
- package/dist/commands/balance.d.ts.map +1 -0
- package/dist/commands/balance.js +65 -0
- package/dist/commands/balance.js.map +1 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +15 -11
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +212 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +3 -1
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/marketplace.d.ts.map +1 -0
- package/dist/commands/marketplace.js.map +1 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +9 -15
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/update.d.ts +6 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +115 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/compact/auto-compact.d.ts.map +1 -0
- package/dist/compact/auto-compact.js.map +1 -0
- package/dist/compact/budget.d.ts.map +1 -0
- package/dist/compact/budget.js +18 -0
- package/dist/compact/budget.js.map +1 -0
- package/dist/compact/history-store.d.ts.map +1 -0
- package/dist/compact/history-store.js.map +1 -0
- package/dist/compact/microcompact.d.ts.map +1 -0
- package/dist/compact/microcompact.js.map +1 -0
- package/dist/compact/service.d.ts.map +1 -0
- package/dist/compact/service.js.map +1 -0
- package/dist/context/agent-identity.d.ts.map +1 -0
- package/dist/context/agent-identity.js +19 -0
- package/dist/context/agent-identity.js.map +1 -0
- package/dist/context/analyzer.d.ts.map +1 -0
- package/dist/context/analyzer.js.map +1 -0
- package/dist/context/builder.d.ts.map +1 -0
- package/dist/context/builder.js +7 -0
- package/dist/context/builder.js.map +1 -0
- package/dist/context/cache.d.ts.map +1 -0
- package/dist/context/cache.js +110 -0
- package/dist/context/cache.js.map +1 -0
- package/dist/context/git-context.d.ts.map +1 -0
- package/dist/context/git-context.js.map +1 -0
- package/dist/context/llmtune-md.d.ts.map +1 -0
- package/dist/context/llmtune-md.js.map +1 -0
- package/dist/context/project-detect.d.ts +26 -0
- package/dist/context/project-detect.d.ts.map +1 -0
- package/dist/context/project-detect.js +213 -0
- package/dist/context/project-detect.js.map +1 -0
- package/dist/context/workspace.d.ts.map +1 -0
- package/dist/context/workspace.js +2 -1
- package/dist/context/workspace.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -5
- package/dist/index.js.map +1 -0
- package/dist/marketplace/client.d.ts.map +1 -0
- package/dist/marketplace/client.js.map +1 -0
- package/dist/memory/files.d.ts.map +1 -0
- package/dist/memory/files.js.map +1 -0
- package/dist/memory/service.d.ts +2 -1
- package/dist/memory/service.d.ts.map +1 -0
- package/dist/memory/service.js +1 -0
- package/dist/memory/service.js.map +1 -0
- package/dist/repl/auto-save.d.ts +14 -0
- package/dist/repl/auto-save.d.ts.map +1 -0
- package/dist/repl/auto-save.js +101 -0
- package/dist/repl/auto-save.js.map +1 -0
- package/dist/repl/repl.d.ts +1 -0
- package/dist/repl/repl.d.ts.map +1 -0
- package/dist/repl/repl.js +296 -34
- package/dist/repl/repl.js.map +1 -0
- package/dist/skills/args.d.ts.map +1 -0
- package/dist/skills/args.js.map +1 -0
- package/dist/skills/frontmatter.d.ts.map +1 -0
- package/dist/skills/frontmatter.js.map +1 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/signing/signer.d.ts.map +1 -0
- package/dist/skills/signing/signer.js.map +1 -0
- package/dist/skills/trust.d.ts.map +1 -0
- package/dist/skills/trust.js.map +1 -0
- package/dist/telemetry/logger.d.ts.map +1 -0
- package/dist/telemetry/logger.js.map +1 -0
- package/dist/tools/permissions.d.ts +2 -0
- package/dist/tools/permissions.d.ts.map +1 -0
- package/dist/tools/permissions.js +9 -0
- package/dist/tools/permissions.js.map +1 -0
- package/dist/tools/protocol.d.ts.map +1 -0
- package/dist/tools/protocol.js.map +1 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/sandbox/docker.d.ts.map +1 -0
- package/dist/tools/sandbox/docker.js.map +1 -0
- package/dist/tools/sandbox/index.d.ts.map +1 -0
- package/dist/tools/sandbox/index.js.map +1 -0
- package/dist/tools/sanitize.d.ts +10 -0
- package/dist/tools/sanitize.d.ts.map +1 -0
- package/dist/tools/sanitize.js +87 -0
- package/dist/tools/sanitize.js.map +1 -0
- package/dist/tools/tools/ask-user.d.ts.map +1 -0
- package/dist/tools/tools/ask-user.js.map +1 -0
- package/dist/tools/tools/bash.d.ts.map +1 -0
- package/dist/tools/tools/bash.js +52 -1
- package/dist/tools/tools/bash.js.map +1 -0
- package/dist/tools/tools/edit.d.ts.map +1 -0
- package/dist/tools/tools/edit.js +9 -2
- package/dist/tools/tools/edit.js.map +1 -0
- package/dist/tools/tools/glob.d.ts.map +1 -0
- package/dist/tools/tools/glob.js.map +1 -0
- package/dist/tools/tools/grep.d.ts.map +1 -0
- package/dist/tools/tools/grep.js +6 -8
- package/dist/tools/tools/grep.js.map +1 -0
- package/dist/tools/tools/read.d.ts.map +1 -0
- package/dist/tools/tools/read.js +7 -4
- package/dist/tools/tools/read.js.map +1 -0
- package/dist/tools/tools/web-fetch.d.ts.map +1 -0
- package/dist/tools/tools/web-fetch.js +74 -99
- package/dist/tools/tools/web-fetch.js.map +1 -0
- package/dist/tools/tools/write.d.ts.map +1 -0
- package/dist/tools/tools/write.js +13 -7
- package/dist/tools/tools/write.js.map +1 -0
- package/dist/tools/validation.d.ts.map +1 -0
- package/dist/tools/validation.js.map +1 -0
- package/dist/ui/banner.d.ts +2 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +29 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/utils/diff.d.ts +38 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +184 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/errors.d.ts +32 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +72 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/ignore.d.ts +22 -0
- package/dist/utils/ignore.d.ts.map +1 -0
- package/dist/utils/ignore.js +205 -0
- package/dist/utils/ignore.js.map +1 -0
- package/dist/utils/input-history.d.ts +37 -0
- package/dist/utils/input-history.d.ts.map +1 -0
- package/dist/utils/input-history.js +142 -0
- package/dist/utils/input-history.js.map +1 -0
- package/dist/utils/markdown.d.ts.map +1 -0
- package/dist/utils/markdown.js.map +1 -0
- package/dist/utils/rate-limit.d.ts +36 -0
- package/dist/utils/rate-limit.d.ts.map +1 -0
- package/dist/utils/rate-limit.js +71 -0
- package/dist/utils/rate-limit.js.map +1 -0
- package/dist/utils/retry.d.ts +26 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +96 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/spinner.d.ts +12 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +51 -0
- package/dist/utils/spinner.js.map +1 -0
- package/dist/utils/stats.d.ts +29 -0
- package/dist/utils/stats.d.ts.map +1 -0
- package/dist/utils/stats.js +95 -0
- package/dist/utils/stats.js.map +1 -0
- package/dist/utils/streaming.d.ts +6 -3
- package/dist/utils/streaming.d.ts.map +1 -0
- package/dist/utils/streaming.js +14 -19
- package/dist/utils/streaming.js.map +1 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js.map +1 -0
- package/dist/utils/undo-tracker.d.ts +37 -0
- package/dist/utils/undo-tracker.d.ts.map +1 -0
- package/dist/utils/undo-tracker.js +118 -0
- package/dist/utils/undo-tracker.js.map +1 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js.map +1 -0
- package/package.json +61 -45
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* .gitignore-aware file filtering.
|
|
4
|
+
* Skips files/directories that are typically ignored (node_modules, .git, etc.)
|
|
5
|
+
* and reads actual .gitignore patterns when available.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.isIgnoredByDefault = isIgnoredByDefault;
|
|
42
|
+
exports.readGitignorePatterns = readGitignorePatterns;
|
|
43
|
+
exports.matchesGitignorePattern = matchesGitignorePattern;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
/** Default patterns to always ignore (even without .gitignore) */
|
|
47
|
+
const DEFAULT_IGNORE_PATTERNS = [
|
|
48
|
+
"node_modules",
|
|
49
|
+
".git",
|
|
50
|
+
".svn",
|
|
51
|
+
".hg",
|
|
52
|
+
"__pycache__",
|
|
53
|
+
".DS_Store",
|
|
54
|
+
"Thumbs.db",
|
|
55
|
+
"*.pyc",
|
|
56
|
+
".env",
|
|
57
|
+
".env.local",
|
|
58
|
+
".env.*.local",
|
|
59
|
+
"dist",
|
|
60
|
+
"build",
|
|
61
|
+
".next",
|
|
62
|
+
".nuxt",
|
|
63
|
+
".cache",
|
|
64
|
+
".parcel-cache",
|
|
65
|
+
"coverage",
|
|
66
|
+
".nyc_output",
|
|
67
|
+
"*.min.js",
|
|
68
|
+
"*.min.css",
|
|
69
|
+
".terraform",
|
|
70
|
+
"vendor",
|
|
71
|
+
"target",
|
|
72
|
+
"*.egg-info",
|
|
73
|
+
".tox",
|
|
74
|
+
".mypy_cache",
|
|
75
|
+
".pytest_cache",
|
|
76
|
+
".ruff_cache",
|
|
77
|
+
"Cargo.lock",
|
|
78
|
+
"package-lock.json",
|
|
79
|
+
"yarn.lock",
|
|
80
|
+
"pnpm-lock.yaml",
|
|
81
|
+
"bun.lockb",
|
|
82
|
+
];
|
|
83
|
+
/**
|
|
84
|
+
* Check if a filename/path should be ignored based on default patterns.
|
|
85
|
+
* This is a fast check that doesn't require reading .gitignore.
|
|
86
|
+
*/
|
|
87
|
+
function isIgnoredByDefault(entryName, relativePath) {
|
|
88
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
89
|
+
for (const pattern of DEFAULT_IGNORE_PATTERNS) {
|
|
90
|
+
if (pattern.startsWith("*.")) {
|
|
91
|
+
// Extension pattern like *.pyc
|
|
92
|
+
if (entryName.endsWith(pattern.slice(1)))
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
else if (pattern.endsWith(".*")) {
|
|
96
|
+
// Suffix pattern like .env.*
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// Name or directory pattern
|
|
100
|
+
if (entryName === pattern)
|
|
101
|
+
return true;
|
|
102
|
+
if (normalized.includes(`/${pattern}/`))
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Skip hidden files/dirs (starting with .) except common config files
|
|
107
|
+
const ALLOWED_HIDDEN = new Set([
|
|
108
|
+
".gitignore",
|
|
109
|
+
".eslintrc",
|
|
110
|
+
".prettierrc",
|
|
111
|
+
".babelrc",
|
|
112
|
+
".npmrc",
|
|
113
|
+
".nvmrc",
|
|
114
|
+
".python-version",
|
|
115
|
+
".editorconfig",
|
|
116
|
+
".llmtune",
|
|
117
|
+
"CLAUDE.md",
|
|
118
|
+
"LLMTUNE.md",
|
|
119
|
+
".env.example",
|
|
120
|
+
".env.template",
|
|
121
|
+
".github",
|
|
122
|
+
".vscode",
|
|
123
|
+
]);
|
|
124
|
+
if (entryName.startsWith(".") && !ALLOWED_HIDDEN.has(entryName)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Try to read .gitignore patterns from the workspace root.
|
|
131
|
+
* Also reads .llmtuneignore if present for LLMTune-specific ignores.
|
|
132
|
+
* Returns a simple list of glob-like patterns.
|
|
133
|
+
*/
|
|
134
|
+
function readGitignorePatterns(workspaceRoot) {
|
|
135
|
+
const patterns = [];
|
|
136
|
+
// Read root .gitignore
|
|
137
|
+
const gitignorePath = path.join(workspaceRoot, ".gitignore");
|
|
138
|
+
try {
|
|
139
|
+
const content = fs.readFileSync(gitignorePath, "utf-8");
|
|
140
|
+
patterns.push(...content
|
|
141
|
+
.split("\n")
|
|
142
|
+
.map((l) => l.trim())
|
|
143
|
+
.filter((l) => l && !l.startsWith("#")));
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// No .gitignore — that's fine
|
|
147
|
+
}
|
|
148
|
+
// Read .llmtuneignore (LLMTune-specific ignore patterns)
|
|
149
|
+
const llmtuneIgnorePath = path.join(workspaceRoot, ".llmtuneignore");
|
|
150
|
+
try {
|
|
151
|
+
const content = fs.readFileSync(llmtuneIgnorePath, "utf-8");
|
|
152
|
+
patterns.push(...content
|
|
153
|
+
.split("\n")
|
|
154
|
+
.map((l) => l.trim())
|
|
155
|
+
.filter((l) => l && !l.startsWith("#")));
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// No .llmtuneignore — that's fine
|
|
159
|
+
}
|
|
160
|
+
return patterns;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Simple pattern matcher for .gitignore-style patterns.
|
|
164
|
+
* Handles: exact names, * globs, directory patterns (trailing /), negation (!)
|
|
165
|
+
*/
|
|
166
|
+
function matchesGitignorePattern(entryName, relativePath, pattern) {
|
|
167
|
+
if (!pattern || pattern.startsWith("#"))
|
|
168
|
+
return false;
|
|
169
|
+
// Negation — if this matches, the file is NOT ignored
|
|
170
|
+
if (pattern.startsWith("!")) {
|
|
171
|
+
return false; // Handled by caller
|
|
172
|
+
}
|
|
173
|
+
// Directory-only pattern
|
|
174
|
+
const isDirPattern = pattern.endsWith("/");
|
|
175
|
+
// Normalize
|
|
176
|
+
let p = pattern.replace(/\/$/, "").replace(/\\/g, "/");
|
|
177
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
178
|
+
// Exact match
|
|
179
|
+
if (p === entryName || p === normalized)
|
|
180
|
+
return true;
|
|
181
|
+
// Wildcard at end: *.log, *.pyc, etc.
|
|
182
|
+
if (p.startsWith("*.")) {
|
|
183
|
+
const ext = p.slice(1); // .log, .pyc
|
|
184
|
+
if (entryName.endsWith(ext))
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
// Wildcard at start: *.test.ts → matches foo.test.ts
|
|
188
|
+
if (p.includes("*")) {
|
|
189
|
+
const regex = new RegExp("^" +
|
|
190
|
+
p
|
|
191
|
+
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
192
|
+
.replace(/\*/g, ".*")
|
|
193
|
+
.replace(/\?/g, ".") +
|
|
194
|
+
"$");
|
|
195
|
+
if (regex.test(entryName) || regex.test(normalized))
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
// If the pattern has no slashes, match anywhere in path
|
|
199
|
+
if (!p.includes("/")) {
|
|
200
|
+
if (normalized.split("/").includes(p))
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/utils/ignore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input history manager — enables UP/DOWN arrow navigation through
|
|
3
|
+
* previously entered user messages, like a shell.
|
|
4
|
+
*/
|
|
5
|
+
export declare class InputHistory {
|
|
6
|
+
private entries;
|
|
7
|
+
private currentIndex;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Add a new entry to the history. Duplicates of the last entry are ignored.
|
|
11
|
+
*/
|
|
12
|
+
add(entry: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Move up in history (older entries). Returns the entry or undefined.
|
|
15
|
+
*/
|
|
16
|
+
up(): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Move down in history (newer entries). Returns the entry or undefined.
|
|
19
|
+
* When at the bottom, returns undefined (blank line).
|
|
20
|
+
*/
|
|
21
|
+
down(): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Reset navigation position to the end.
|
|
24
|
+
*/
|
|
25
|
+
resetPosition(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Search history for entries matching a prefix.
|
|
28
|
+
*/
|
|
29
|
+
search(prefix: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Get the last N entries.
|
|
32
|
+
*/
|
|
33
|
+
recent(count?: number): string[];
|
|
34
|
+
private load;
|
|
35
|
+
private save;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=input-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-history.d.ts","sourceRoot":"","sources":["../../src/utils/input-history.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,YAAY,CAAa;;IAMjC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAoBxB;;OAEG;IACH,EAAE,IAAI,MAAM,GAAG,SAAS;IAQxB;;;OAGG;IACH,IAAI,IAAI,MAAM,GAAG,SAAS;IAU1B;;OAEG;IACH,aAAa,IAAI,IAAI;IAIrB;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAKhC;;OAEG;IACH,MAAM,CAAC,KAAK,GAAE,MAAW,GAAG,MAAM,EAAE;IAIpC,OAAO,CAAC,IAAI;IAcZ,OAAO,CAAC,IAAI;CAWb"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input history manager — enables UP/DOWN arrow navigation through
|
|
4
|
+
* previously entered user messages, like a shell.
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.InputHistory = void 0;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const os = __importStar(require("os"));
|
|
44
|
+
const MAX_HISTORY = 500;
|
|
45
|
+
const HISTORY_FILE = path.join(os.homedir(), ".llmtune", "input-history.json");
|
|
46
|
+
class InputHistory {
|
|
47
|
+
entries = [];
|
|
48
|
+
currentIndex = -1;
|
|
49
|
+
constructor() {
|
|
50
|
+
this.load();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Add a new entry to the history. Duplicates of the last entry are ignored.
|
|
54
|
+
*/
|
|
55
|
+
add(entry) {
|
|
56
|
+
const trimmed = entry.trim();
|
|
57
|
+
if (!trimmed)
|
|
58
|
+
return;
|
|
59
|
+
// Don't duplicate the most recent entry
|
|
60
|
+
if (this.entries.length > 0 && this.entries[this.entries.length - 1] === trimmed) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.entries.push(trimmed);
|
|
64
|
+
// Trim old entries
|
|
65
|
+
if (this.entries.length > MAX_HISTORY) {
|
|
66
|
+
this.entries = this.entries.slice(-MAX_HISTORY);
|
|
67
|
+
}
|
|
68
|
+
this.currentIndex = this.entries.length; // Reset to "after last"
|
|
69
|
+
this.save();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Move up in history (older entries). Returns the entry or undefined.
|
|
73
|
+
*/
|
|
74
|
+
up() {
|
|
75
|
+
if (this.entries.length === 0)
|
|
76
|
+
return undefined;
|
|
77
|
+
if (this.currentIndex > 0) {
|
|
78
|
+
this.currentIndex--;
|
|
79
|
+
}
|
|
80
|
+
return this.entries[this.currentIndex];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Move down in history (newer entries). Returns the entry or undefined.
|
|
84
|
+
* When at the bottom, returns undefined (blank line).
|
|
85
|
+
*/
|
|
86
|
+
down() {
|
|
87
|
+
if (this.currentIndex < this.entries.length - 1) {
|
|
88
|
+
this.currentIndex++;
|
|
89
|
+
return this.entries[this.currentIndex];
|
|
90
|
+
}
|
|
91
|
+
// At the bottom — return blank
|
|
92
|
+
this.currentIndex = this.entries.length;
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Reset navigation position to the end.
|
|
97
|
+
*/
|
|
98
|
+
resetPosition() {
|
|
99
|
+
this.currentIndex = this.entries.length;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Search history for entries matching a prefix.
|
|
103
|
+
*/
|
|
104
|
+
search(prefix) {
|
|
105
|
+
const lower = prefix.toLowerCase();
|
|
106
|
+
return this.entries.filter((e) => e.toLowerCase().startsWith(lower)).reverse();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the last N entries.
|
|
110
|
+
*/
|
|
111
|
+
recent(count = 10) {
|
|
112
|
+
return this.entries.slice(-count);
|
|
113
|
+
}
|
|
114
|
+
load() {
|
|
115
|
+
try {
|
|
116
|
+
if (fs.existsSync(HISTORY_FILE)) {
|
|
117
|
+
const data = JSON.parse(fs.readFileSync(HISTORY_FILE, "utf-8"));
|
|
118
|
+
if (Array.isArray(data)) {
|
|
119
|
+
this.entries = data.filter((e) => typeof e === "string");
|
|
120
|
+
this.currentIndex = this.entries.length;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
this.entries = [];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
save() {
|
|
129
|
+
try {
|
|
130
|
+
const dir = path.dirname(HISTORY_FILE);
|
|
131
|
+
if (!fs.existsSync(dir)) {
|
|
132
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
133
|
+
}
|
|
134
|
+
fs.writeFileSync(HISTORY_FILE, JSON.stringify(this.entries), "utf-8");
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Silently fail — history is non-critical
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.InputHistory = InputHistory;
|
|
142
|
+
//# sourceMappingURL=input-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-history.js","sourceRoot":"","sources":["../../src/utils/input-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAS5E;AAqDD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAOvE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAavE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple rate limiter for tool calls.
|
|
3
|
+
* Prevents runaway agent loops from hammering the system.
|
|
4
|
+
*/
|
|
5
|
+
export interface RateLimiterConfig {
|
|
6
|
+
/** Maximum number of calls in the window */
|
|
7
|
+
maxCalls: number;
|
|
8
|
+
/** Time window in milliseconds */
|
|
9
|
+
windowMs: number;
|
|
10
|
+
/** Tool-specific overrides */
|
|
11
|
+
perTool?: Record<string, {
|
|
12
|
+
maxCalls: number;
|
|
13
|
+
windowMs: number;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export declare class RateLimiter {
|
|
17
|
+
private calls;
|
|
18
|
+
private config;
|
|
19
|
+
constructor(config?: Partial<RateLimiterConfig>);
|
|
20
|
+
/**
|
|
21
|
+
* Check if a tool call is allowed. Returns true if allowed, false if rate limited.
|
|
22
|
+
*/
|
|
23
|
+
isAllowed(toolName: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Get the number of remaining calls for a tool in the current window.
|
|
26
|
+
*/
|
|
27
|
+
remaining(toolName: string): number;
|
|
28
|
+
/**
|
|
29
|
+
* Reset rate limit state (e.g., on new session).
|
|
30
|
+
*/
|
|
31
|
+
reset(): void;
|
|
32
|
+
private getRecords;
|
|
33
|
+
private getMaxCalls;
|
|
34
|
+
private getWindowMs;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACjE;AAiBD,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,MAAM,CAAmB;gBAErB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC;IAI/C;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAoBpC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IASnC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;CAGpB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Simple rate limiter for tool calls.
|
|
4
|
+
* Prevents runaway agent loops from hammering the system.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RateLimiter = void 0;
|
|
8
|
+
const DEFAULT_CONFIG = {
|
|
9
|
+
maxCalls: 60,
|
|
10
|
+
windowMs: 60_000, // 1 minute
|
|
11
|
+
perTool: {
|
|
12
|
+
bash: { maxCalls: 30, windowMs: 60_000 },
|
|
13
|
+
write: { maxCalls: 40, windowMs: 60_000 },
|
|
14
|
+
edit: { maxCalls: 40, windowMs: 60_000 },
|
|
15
|
+
web_fetch: { maxCalls: 20, windowMs: 60_000 },
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
class RateLimiter {
|
|
19
|
+
calls = new Map();
|
|
20
|
+
config;
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Check if a tool call is allowed. Returns true if allowed, false if rate limited.
|
|
26
|
+
*/
|
|
27
|
+
isAllowed(toolName) {
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
const records = this.getRecords(toolName);
|
|
30
|
+
// Clean up old records
|
|
31
|
+
const windowMs = this.getWindowMs(toolName);
|
|
32
|
+
const cutoff = now - windowMs;
|
|
33
|
+
const recent = records.filter((r) => r.timestamp > cutoff);
|
|
34
|
+
const maxCalls = this.getMaxCalls(toolName);
|
|
35
|
+
if (recent.length >= maxCalls) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Record this call
|
|
39
|
+
recent.push({ timestamp: now });
|
|
40
|
+
this.calls.set(toolName, recent);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the number of remaining calls for a tool in the current window.
|
|
45
|
+
*/
|
|
46
|
+
remaining(toolName) {
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
const records = this.getRecords(toolName);
|
|
49
|
+
const windowMs = this.getWindowMs(toolName);
|
|
50
|
+
const cutoff = now - windowMs;
|
|
51
|
+
const recent = records.filter((r) => r.timestamp > cutoff);
|
|
52
|
+
return Math.max(0, this.getMaxCalls(toolName) - recent.length);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Reset rate limit state (e.g., on new session).
|
|
56
|
+
*/
|
|
57
|
+
reset() {
|
|
58
|
+
this.calls.clear();
|
|
59
|
+
}
|
|
60
|
+
getRecords(toolName) {
|
|
61
|
+
return this.calls.get(toolName) ?? [];
|
|
62
|
+
}
|
|
63
|
+
getMaxCalls(toolName) {
|
|
64
|
+
return this.config.perTool?.[toolName]?.maxCalls ?? this.config.maxCalls;
|
|
65
|
+
}
|
|
66
|
+
getWindowMs(toolName) {
|
|
67
|
+
return this.config.perTool?.[toolName]?.windowMs ?? this.config.windowMs;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.RateLimiter = RateLimiter;
|
|
71
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/utils/rate-limit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry utility for API calls with exponential backoff.
|
|
3
|
+
* Handles rate limits (429), server errors (500/502/503), and network issues.
|
|
4
|
+
*/
|
|
5
|
+
export interface RetryOptions {
|
|
6
|
+
maxRetries?: number;
|
|
7
|
+
baseDelayMs?: number;
|
|
8
|
+
maxDelayMs?: number;
|
|
9
|
+
/** Retry on these error patterns (string match against error message) */
|
|
10
|
+
retryableErrors?: string[];
|
|
11
|
+
/** Called before each retry with attempt number and delay */
|
|
12
|
+
onRetry?: (attempt: number, delay: number, error: Error) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare class RetryableError extends Error {
|
|
15
|
+
readonly statusCode?: number | undefined;
|
|
16
|
+
constructor(message: string, statusCode?: number | undefined);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Determine if an error is retryable (rate limit, server error, network issue).
|
|
20
|
+
*/
|
|
21
|
+
export declare function isRetryableError(err: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Execute a function with retry logic and exponential backoff + jitter.
|
|
24
|
+
*/
|
|
25
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
26
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjE;AAED,qBAAa,cAAe,SAAQ,KAAK;aACM,UAAU,CAAC,EAAE,MAAM;gBAApD,OAAO,EAAE,MAAM,EAAkB,UAAU,CAAC,EAAE,MAAM,YAAA;CAIjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAyBtD;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,CAAC,CAyCZ"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Retry utility for API calls with exponential backoff.
|
|
4
|
+
* Handles rate limits (429), server errors (500/502/503), and network issues.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RetryableError = void 0;
|
|
8
|
+
exports.isRetryableError = isRetryableError;
|
|
9
|
+
exports.withRetry = withRetry;
|
|
10
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
11
|
+
const DEFAULT_BASE_DELAY_MS = 1000;
|
|
12
|
+
const DEFAULT_MAX_DELAY_MS = 30_000;
|
|
13
|
+
class RetryableError extends Error {
|
|
14
|
+
statusCode;
|
|
15
|
+
constructor(message, statusCode) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.statusCode = statusCode;
|
|
18
|
+
this.name = "RetryableError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.RetryableError = RetryableError;
|
|
22
|
+
/**
|
|
23
|
+
* Determine if an error is retryable (rate limit, server error, network issue).
|
|
24
|
+
*/
|
|
25
|
+
function isRetryableError(err) {
|
|
26
|
+
if (err instanceof RetryableError)
|
|
27
|
+
return true;
|
|
28
|
+
if (err && typeof err === "object") {
|
|
29
|
+
const e = err;
|
|
30
|
+
// OpenAI API error structure
|
|
31
|
+
if (e.status === 429)
|
|
32
|
+
return true; // Rate limit
|
|
33
|
+
if (e.status === 500)
|
|
34
|
+
return true; // Internal server error
|
|
35
|
+
if (e.status === 502)
|
|
36
|
+
return true; // Bad gateway
|
|
37
|
+
if (e.status === 503)
|
|
38
|
+
return true; // Service unavailable
|
|
39
|
+
if (e.status === 529)
|
|
40
|
+
return true; // Overloaded
|
|
41
|
+
// Network errors
|
|
42
|
+
const msg = String(e.message ?? "");
|
|
43
|
+
if (msg.includes("ECONNRESET"))
|
|
44
|
+
return true;
|
|
45
|
+
if (msg.includes("ECONNREFUSED"))
|
|
46
|
+
return true;
|
|
47
|
+
if (msg.includes("ETIMEDOUT"))
|
|
48
|
+
return true;
|
|
49
|
+
if (msg.includes("socket hang up"))
|
|
50
|
+
return true;
|
|
51
|
+
if (msg.includes("network"))
|
|
52
|
+
return true;
|
|
53
|
+
if (msg.includes("fetch failed"))
|
|
54
|
+
return true;
|
|
55
|
+
if (msg.includes("abort"))
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Execute a function with retry logic and exponential backoff + jitter.
|
|
62
|
+
*/
|
|
63
|
+
async function withRetry(fn, options = {}) {
|
|
64
|
+
const { maxRetries = DEFAULT_MAX_RETRIES, baseDelayMs = DEFAULT_BASE_DELAY_MS, maxDelayMs = DEFAULT_MAX_DELAY_MS, onRetry, } = options;
|
|
65
|
+
let lastError;
|
|
66
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
67
|
+
try {
|
|
68
|
+
return await fn();
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
72
|
+
lastError = error;
|
|
73
|
+
// Don't retry non-retryable errors
|
|
74
|
+
if (!isRetryableError(err)) {
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
// Don't retry if we've exhausted attempts
|
|
78
|
+
if (attempt >= maxRetries) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
// Calculate delay with exponential backoff + jitter
|
|
82
|
+
const exponentialDelay = baseDelayMs * Math.pow(2, attempt);
|
|
83
|
+
const jitter = Math.random() * baseDelayMs;
|
|
84
|
+
const delay = Math.min(exponentialDelay + jitter, maxDelayMs);
|
|
85
|
+
if (onRetry) {
|
|
86
|
+
onRetry(attempt + 1, delay, error);
|
|
87
|
+
}
|
|
88
|
+
await sleep(delay);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
throw lastError ?? new Error("Retry failed with unknown error");
|
|
92
|
+
}
|
|
93
|
+
function sleep(ms) {
|
|
94
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=retry.js.map
|