bernard-agent 0.8.1 → 0.9.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 +80 -44
- package/dist/agent.d.ts +14 -3
- package/dist/agent.js +228 -38
- package/dist/agent.js.map +1 -1
- package/dist/builtin-specialists/correction-agent.json +32 -0
- package/dist/builtin-specialists/file-wrapper.json +43 -0
- package/dist/builtin-specialists/shell-wrapper.json +50 -0
- package/dist/builtin-specialists/specialist-creator.json +32 -0
- package/dist/builtin-specialists/web-wrapper.json +38 -0
- package/dist/candidate-bootstrap.d.ts +18 -0
- package/dist/candidate-bootstrap.js +61 -0
- package/dist/candidate-bootstrap.js.map +1 -0
- package/dist/config.d.ts +126 -10
- package/dist/config.js +222 -45
- package/dist/config.js.map +1 -1
- package/dist/context.js +23 -6
- package/dist/context.js.map +1 -1
- package/dist/correction-candidates.d.ts +54 -0
- package/dist/correction-candidates.js +138 -0
- package/dist/correction-candidates.js.map +1 -0
- package/dist/correction.d.ts +67 -0
- package/dist/correction.js +138 -0
- package/dist/correction.js.map +1 -0
- package/dist/critic.js +2 -1
- package/dist/critic.js.map +1 -1
- package/dist/cron/notes-store.d.ts +41 -0
- package/dist/cron/notes-store.js +134 -0
- package/dist/cron/notes-store.js.map +1 -0
- package/dist/cron/runner.js +25 -3
- package/dist/cron/runner.js.map +1 -1
- package/dist/cron/scoped-notes-tools.d.ts +24 -0
- package/dist/cron/scoped-notes-tools.js +50 -0
- package/dist/cron/scoped-notes-tools.js.map +1 -0
- package/dist/custom-providers.d.ts +80 -0
- package/dist/custom-providers.js +238 -0
- package/dist/custom-providers.js.map +1 -0
- package/dist/fs-utils.d.ts +2 -0
- package/dist/fs-utils.js +44 -0
- package/dist/fs-utils.js.map +1 -0
- package/dist/history.js +3 -1
- package/dist/history.js.map +1 -1
- package/dist/image.d.ts +59 -0
- package/dist/image.js +228 -0
- package/dist/image.js.map +1 -0
- package/dist/index.js +72 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/mcp.js.map +1 -1
- package/dist/memory.d.ts +13 -0
- package/dist/memory.js +45 -4
- package/dist/memory.js.map +1 -1
- package/dist/menu.d.ts +97 -0
- package/dist/menu.js +338 -0
- package/dist/menu.js.map +1 -0
- package/dist/os-info.d.ts +22 -0
- package/dist/os-info.js +111 -0
- package/dist/os-info.js.map +1 -0
- package/dist/output.d.ts +35 -1
- package/dist/output.js +256 -45
- package/dist/output.js.map +1 -1
- package/dist/pac.d.ts +14 -2
- package/dist/pac.js +5 -5
- package/dist/pac.js.map +1 -1
- package/dist/paths.d.ts +5 -0
- package/dist/paths.js +6 -1
- package/dist/paths.js.map +1 -1
- package/dist/plan-store.d.ts +47 -0
- package/dist/plan-store.js +94 -0
- package/dist/plan-store.js.map +1 -0
- package/dist/prompt-rewriter.d.ts +29 -0
- package/dist/prompt-rewriter.js +155 -0
- package/dist/prompt-rewriter.js.map +1 -0
- package/dist/providers/index.d.ts +56 -4
- package/dist/providers/index.js +86 -5
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/profiles.d.ts +37 -0
- package/dist/providers/profiles.js +110 -0
- package/dist/providers/profiles.js.map +1 -0
- package/dist/providers/types.d.ts +11 -2
- package/dist/providers/types.js +3 -0
- package/dist/providers/types.js.map +1 -1
- package/dist/rag-query.js +15 -1
- package/dist/rag-query.js.map +1 -1
- package/dist/react.d.ts +38 -0
- package/dist/react.js +116 -0
- package/dist/react.js.map +1 -0
- package/dist/reasoning-log.d.ts +30 -0
- package/dist/reasoning-log.js +102 -0
- package/dist/reasoning-log.js.map +1 -0
- package/dist/reference-resolver.d.ts +47 -0
- package/dist/reference-resolver.js +316 -0
- package/dist/reference-resolver.js.map +1 -0
- package/dist/reference-tool-lookup.d.ts +37 -0
- package/dist/reference-tool-lookup.js +318 -0
- package/dist/reference-tool-lookup.js.map +1 -0
- package/dist/repl.js +1038 -371
- package/dist/repl.js.map +1 -1
- package/dist/setup.js +2 -1
- package/dist/setup.js.map +1 -1
- package/dist/specialist-detector.js +2 -1
- package/dist/specialist-detector.js.map +1 -1
- package/dist/specialists.d.ts +74 -3
- package/dist/specialists.js +152 -20
- package/dist/specialists.js.map +1 -1
- package/dist/structured-output.d.ts +58 -0
- package/dist/structured-output.js +138 -0
- package/dist/structured-output.js.map +1 -0
- package/dist/theme.d.ts +2 -0
- package/dist/theme.js +18 -12
- package/dist/theme.js.map +1 -1
- package/dist/tool-call-repair.d.ts +29 -0
- package/dist/tool-call-repair.js +99 -0
- package/dist/tool-call-repair.js.map +1 -0
- package/dist/tool-profiles.d.ts +70 -0
- package/dist/tool-profiles.js +385 -0
- package/dist/tool-profiles.js.map +1 -0
- package/dist/tools/activity-summary.d.ts +15 -0
- package/dist/tools/activity-summary.js +44 -0
- package/dist/tools/activity-summary.js.map +1 -0
- package/dist/tools/ask-user.d.ts +49 -0
- package/dist/tools/ask-user.js +52 -0
- package/dist/tools/ask-user.js.map +1 -0
- package/dist/tools/augment.d.ts +17 -0
- package/dist/tools/augment.js +102 -0
- package/dist/tools/augment.js.map +1 -0
- package/dist/tools/cron-logs.js +7 -0
- package/dist/tools/cron-logs.js.map +1 -1
- package/dist/tools/cron-notes.d.ts +52 -0
- package/dist/tools/cron-notes.js +105 -0
- package/dist/tools/cron-notes.js.map +1 -0
- package/dist/tools/datetime.d.ts +7 -0
- package/dist/tools/datetime.js +29 -3
- package/dist/tools/datetime.js.map +1 -1
- package/dist/tools/evaluate.d.ts +20 -0
- package/dist/tools/evaluate.js +29 -0
- package/dist/tools/evaluate.js.map +1 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp.d.ts +3 -3
- package/dist/tools/plan.d.ts +81 -0
- package/dist/tools/plan.js +108 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/result-cap.d.ts +24 -0
- package/dist/tools/result-cap.js +44 -0
- package/dist/tools/result-cap.js.map +1 -0
- package/dist/tools/routine.d.ts +3 -3
- package/dist/tools/shell.d.ts +14 -1
- package/dist/tools/shell.js +86 -4
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/specialist-run.d.ts +5 -3
- package/dist/tools/specialist-run.js +115 -24
- package/dist/tools/specialist-run.js.map +1 -1
- package/dist/tools/specialist.d.ts +83 -3
- package/dist/tools/specialist.js +83 -3
- package/dist/tools/specialist.js.map +1 -1
- package/dist/tools/subagent.js +32 -14
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/task.d.ts +5 -5
- package/dist/tools/task.js +9 -42
- package/dist/tools/task.js.map +1 -1
- package/dist/tools/think.d.ts +18 -0
- package/dist/tools/think.js +25 -0
- package/dist/tools/think.js.map +1 -0
- package/dist/tools/tool-wrapper-run.d.ts +121 -0
- package/dist/tools/tool-wrapper-run.js +382 -0
- package/dist/tools/tool-wrapper-run.js.map +1 -0
- package/dist/tools/types.d.ts +28 -2
- package/dist/tools/web-search.d.ts +31 -0
- package/dist/tools/web-search.js +172 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/wrap-with-specialist.d.ts +55 -0
- package/dist/tools/wrap-with-specialist.js +137 -0
- package/dist/tools/wrap-with-specialist.js.map +1 -0
- package/package.json +2 -2
package/dist/cron/runner.js
CHANGED
|
@@ -53,8 +53,11 @@ const time_js_1 = require("../tools/time.js");
|
|
|
53
53
|
const mcp_js_1 = require("../mcp.js");
|
|
54
54
|
const store_js_1 = require("./store.js");
|
|
55
55
|
const log_store_js_1 = require("./log-store.js");
|
|
56
|
+
const notes_store_js_1 = require("./notes-store.js");
|
|
57
|
+
const scoped_notes_tools_js_1 = require("./scoped-notes-tools.js");
|
|
56
58
|
const notify_js_1 = require("./notify.js");
|
|
57
59
|
const pac_js_1 = require("../pac.js");
|
|
60
|
+
const tool_call_repair_js_1 = require("../tool-call-repair.js");
|
|
58
61
|
const DAEMON_SYSTEM_PROMPT = `You are Bernard, running as a background cron job in daemon mode. There is no interactive user present — you execute autonomously and have a limited step budget (20 steps), so work efficiently.
|
|
59
62
|
|
|
60
63
|
## Structured Approach
|
|
@@ -76,6 +79,14 @@ This keeps you focused and prevents wasted steps on long-running jobs.
|
|
|
76
79
|
- **cron_self_disable** — Disable this cron job so it won't run again. Use when a one-time task is complete.
|
|
77
80
|
- You may also have access to **MCP tools** (email, calendar, etc.) depending on configuration.
|
|
78
81
|
|
|
82
|
+
## Persistent Notes
|
|
83
|
+
You have \`cron_notes_read\` and \`cron_notes_write\`, both scoped to this job.
|
|
84
|
+
|
|
85
|
+
1. Before taking action, call \`cron_notes_read\` to see what prior runs did. Use the notes to avoid duplicate work (e.g. don't re-send an email that a prior run already sent).
|
|
86
|
+
2. After any significant action, call \`cron_notes_write\` with a short factual summary (e.g. "Sent weekly summary to user@example.com", "Created issue #123").
|
|
87
|
+
|
|
88
|
+
Notes persist across daemon restarts. Keep entries short — one line each — and concrete. Don't log routine checks that found nothing.
|
|
89
|
+
|
|
79
90
|
## Decision Rules
|
|
80
91
|
- Be concise. Focus on actionable findings.
|
|
81
92
|
- If everything looks normal and no action is needed, simply report results **without** notifying.
|
|
@@ -181,7 +192,9 @@ async function runJob(job, log) {
|
|
|
181
192
|
const shellTool = (0, shell_js_1.createShellTool)({
|
|
182
193
|
shellTimeout: config.shellTimeout,
|
|
183
194
|
confirmDangerous: async () => false, // Auto-deny in daemon mode
|
|
195
|
+
// askUser intentionally omitted — no interactive user; the ask_user tool returns {unavailable}.
|
|
184
196
|
});
|
|
197
|
+
const notesStore = new notes_store_js_1.CronNotesStore();
|
|
185
198
|
const tools = {
|
|
186
199
|
shell: shellTool,
|
|
187
200
|
memory: (0, memory_js_2.createMemoryTool)(memoryStore),
|
|
@@ -192,6 +205,7 @@ async function runJob(job, log) {
|
|
|
192
205
|
...(0, time_js_1.createTimeTools)(),
|
|
193
206
|
notify: notifyTool,
|
|
194
207
|
cron_self_disable: selfDisableTool,
|
|
208
|
+
...(0, scoped_notes_tools_js_1.createScopedCronNotesTools)(notesStore, job.id, runId),
|
|
195
209
|
...mcpTools,
|
|
196
210
|
};
|
|
197
211
|
// RAG search using job prompt as query
|
|
@@ -247,13 +261,19 @@ async function runJob(job, log) {
|
|
|
247
261
|
finishReason: finishReason || 'unknown',
|
|
248
262
|
});
|
|
249
263
|
};
|
|
264
|
+
const repairHook = (0, tool_call_repair_js_1.makeRepairHook)({
|
|
265
|
+
config,
|
|
266
|
+
label: 'cron',
|
|
267
|
+
});
|
|
250
268
|
const result = await (0, ai_1.generateText)({
|
|
251
|
-
model: (0, index_js_1.
|
|
269
|
+
model: (0, index_js_1.getModelForConfig)(config, config.provider, config.model),
|
|
270
|
+
providerOptions: (0, index_js_1.getProviderOptionsForConfig)(config, config.provider),
|
|
252
271
|
tools,
|
|
253
272
|
maxSteps: config.maxSteps,
|
|
254
273
|
maxTokens: config.maxTokens,
|
|
255
274
|
system: enrichedPrompt,
|
|
256
275
|
messages: [{ role: 'user', content: job.prompt }],
|
|
276
|
+
experimental_repairToolCall: repairHook,
|
|
257
277
|
onStepFinish,
|
|
258
278
|
});
|
|
259
279
|
// Run PAC loop when critic mode is enabled
|
|
@@ -265,17 +285,19 @@ async function runJob(job, log) {
|
|
|
265
285
|
initialResult: result,
|
|
266
286
|
regenerate: async (extraMessages) => {
|
|
267
287
|
return (0, ai_1.generateText)({
|
|
268
|
-
model: (0, index_js_1.
|
|
288
|
+
model: (0, index_js_1.getModelForConfig)(config, config.provider, config.model),
|
|
289
|
+
providerOptions: (0, index_js_1.getProviderOptionsForConfig)(config, config.provider),
|
|
269
290
|
tools,
|
|
270
291
|
maxSteps: 20,
|
|
271
292
|
maxTokens: config.maxTokens,
|
|
272
293
|
system: enrichedPrompt,
|
|
273
294
|
messages: [{ role: 'user', content: job.prompt }, ...extraMessages],
|
|
295
|
+
experimental_repairToolCall: repairHook,
|
|
274
296
|
onStepFinish,
|
|
275
297
|
});
|
|
276
298
|
},
|
|
277
299
|
});
|
|
278
|
-
finalOutput = pacResult.
|
|
300
|
+
finalOutput = pacResult.finalResult.text || '(no text output)';
|
|
279
301
|
}
|
|
280
302
|
else {
|
|
281
303
|
finalOutput = result.text || '(no text output)';
|
package/dist/cron/runner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/cron/runner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/cron/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CronNotesStore } from './notes-store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Builds `cron_notes_read` and `cron_notes_write` tools pre-scoped to a single
|
|
5
|
+
* cron job and run. The daemon runner spreads these into its tools dict so the
|
|
6
|
+
* agent sees zero/one-arg versions that cannot read or write other jobs'
|
|
7
|
+
* notes and auto-tag writes with the current `runId`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createScopedCronNotesTools(notesStore: CronNotesStore, jobId: string, runId: string): {
|
|
10
|
+
cron_notes_read: import("ai").Tool<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>, string> & {
|
|
11
|
+
execute: (args: {}, options: import("ai").ToolExecutionOptions) => PromiseLike<string>;
|
|
12
|
+
};
|
|
13
|
+
cron_notes_write: import("ai").Tool<z.ZodObject<{
|
|
14
|
+
text: z.ZodString;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
text: string;
|
|
17
|
+
}, {
|
|
18
|
+
text: string;
|
|
19
|
+
}>, string> & {
|
|
20
|
+
execute: (args: {
|
|
21
|
+
text: string;
|
|
22
|
+
}, options: import("ai").ToolExecutionOptions) => PromiseLike<string>;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createScopedCronNotesTools = createScopedCronNotesTools;
|
|
4
|
+
const ai_1 = require("ai");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const notes_store_js_1 = require("./notes-store.js");
|
|
7
|
+
const cron_notes_js_1 = require("../tools/cron-notes.js");
|
|
8
|
+
const logger_js_1 = require("../logger.js");
|
|
9
|
+
/**
|
|
10
|
+
* Builds `cron_notes_read` and `cron_notes_write` tools pre-scoped to a single
|
|
11
|
+
* cron job and run. The daemon runner spreads these into its tools dict so the
|
|
12
|
+
* agent sees zero/one-arg versions that cannot read or write other jobs'
|
|
13
|
+
* notes and auto-tag writes with the current `runId`.
|
|
14
|
+
*/
|
|
15
|
+
function createScopedCronNotesTools(notesStore, jobId, runId) {
|
|
16
|
+
const scopedNotesRead = (0, ai_1.tool)({
|
|
17
|
+
description: 'Read notes previously written for this cron job by prior runs. Call this before acting to avoid duplicate work.',
|
|
18
|
+
parameters: zod_1.z.object({}),
|
|
19
|
+
execute: async () => {
|
|
20
|
+
(0, logger_js_1.debugLog)('cron_notes_read:scoped:execute', { jobId });
|
|
21
|
+
const notes = notesStore.read(jobId);
|
|
22
|
+
if (notes.entries.length === 0) {
|
|
23
|
+
return `No prior notes for this job.`;
|
|
24
|
+
}
|
|
25
|
+
const label = notes.entries.length === 1 ? 'entry' : 'entries';
|
|
26
|
+
const lines = notes.entries.map(cron_notes_js_1.formatEntryCompact);
|
|
27
|
+
return `Prior notes (${notes.entries.length} ${label}):\n${lines.join('\n')}`;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const scopedNotesWrite = (0, ai_1.tool)({
|
|
31
|
+
description: "Append a short factual note recording a significant action this run took (e.g. 'Sent email to user@example.com', 'Created issue #123'). Keep it to one line.",
|
|
32
|
+
parameters: zod_1.z.object({
|
|
33
|
+
text: zod_1.z
|
|
34
|
+
.string()
|
|
35
|
+
.min(1)
|
|
36
|
+
.max(notes_store_js_1.MAX_NOTE_LENGTH)
|
|
37
|
+
.describe('Short factual description of the action'),
|
|
38
|
+
}),
|
|
39
|
+
execute: async ({ text }) => {
|
|
40
|
+
(0, logger_js_1.debugLog)('cron_notes_write:scoped:execute', { jobId, runId, text });
|
|
41
|
+
notesStore.append(jobId, text, runId);
|
|
42
|
+
return `Note appended (run ${runId.slice(0, 8)}).`;
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
cron_notes_read: scopedNotesRead,
|
|
47
|
+
cron_notes_write: scopedNotesWrite,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=scoped-notes-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-notes-tools.js","sourceRoot":"","sources":["../../src/cron/scoped-notes-tools.ts"],"names":[],"mappings":";;AAYA,gEA0CC;AAtDD,2BAA0B;AAC1B,6BAAwB;AACxB,qDAAmE;AACnE,0DAA4D;AAC5D,4CAAwC;AAExC;;;;;GAKG;AACH,SAAgB,0BAA0B,CACxC,UAA0B,EAC1B,KAAa,EACb,KAAa;IAEb,MAAM,eAAe,GAAG,IAAA,SAAI,EAAC;QAC3B,WAAW,EACT,iHAAiH;QACnH,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,IAAqB,EAAE;YACnC,IAAA,oBAAQ,EAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACtD,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,OAAO,8BAA8B,CAAC;YACxC,CAAC;YACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;YAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,kCAAkB,CAAC,CAAC;YACpD,OAAO,gBAAgB,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChF,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,IAAA,SAAI,EAAC;QAC5B,WAAW,EACT,8JAA8J;QAChK,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,OAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,gCAAe,CAAC;iBACpB,QAAQ,CAAC,yCAAyC,CAAC;SACvD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAmB,EAAE;YAC3C,IAAA,oBAAQ,EAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YACtC,OAAO,sBAAsB,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;QACrD,CAAC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,eAAe,EAAE,eAAe;QAChC,gBAAgB,EAAE,gBAAgB;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module custom-providers
|
|
3
|
+
*
|
|
4
|
+
* Disk-backed registry of user-defined custom providers — named endpoints
|
|
5
|
+
* that wrap one of the installed AI SDKs (`@ai-sdk/openai`,
|
|
6
|
+
* `@ai-sdk/anthropic`, `@ai-sdk/xai`) with a custom `baseURL` and API key.
|
|
7
|
+
*
|
|
8
|
+
* Lets the user route Bernard at OpenAI/Anthropic/xAI-compatible servers
|
|
9
|
+
* (Ollama, LM Studio, vLLM, OpenRouter, Together, internal proxies, ...)
|
|
10
|
+
* and have several such endpoints configured at once alongside the
|
|
11
|
+
* built-in providers.
|
|
12
|
+
*
|
|
13
|
+
* Storage: `~/.config/bernard/custom-providers.json`
|
|
14
|
+
* Shape: `{ providers: Record<name, CustomProvider> }` with file mode 0600.
|
|
15
|
+
*
|
|
16
|
+
* API keys are NOT stored here; they live in `keys.json` keyed by the
|
|
17
|
+
* provider name (the same file the built-in providers use).
|
|
18
|
+
*/
|
|
19
|
+
import type { SupportedSdk } from './providers/types.js';
|
|
20
|
+
/** Names reserved by built-in providers — cannot be used for custom entries. */
|
|
21
|
+
export declare const RESERVED_PROVIDER_NAMES: ReadonlySet<string>;
|
|
22
|
+
/** Allowed SDK choices for a custom provider. */
|
|
23
|
+
export declare const SUPPORTED_SDKS: ReadonlyArray<SupportedSdk>;
|
|
24
|
+
/** A single registered custom provider. */
|
|
25
|
+
export interface CustomProvider {
|
|
26
|
+
/** Provider name — used as the `--provider` value. Lowercase, [a-z0-9_-]+. */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Which installed AI-SDK package to wrap. */
|
|
29
|
+
sdk: SupportedSdk;
|
|
30
|
+
/** Base URL for the provider endpoint, e.g. `http://localhost:11434/v1`. */
|
|
31
|
+
baseURL: string;
|
|
32
|
+
/** Default model — first one offered in the /model menu, used when switching. */
|
|
33
|
+
defaultModel: string;
|
|
34
|
+
/** Known models for this provider. `defaultModel` is always first. Grows as user types new model names. */
|
|
35
|
+
models: string[];
|
|
36
|
+
/** ISO-8601 creation timestamp. */
|
|
37
|
+
createdAt: string;
|
|
38
|
+
/** ISO-8601 last-update timestamp. */
|
|
39
|
+
updatedAt: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validates a custom provider name.
|
|
43
|
+
* @returns An error message if invalid, or `null` if valid.
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateProviderName(name: string): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Validates a base URL — must parse, and use http/https.
|
|
48
|
+
* @returns An error message if invalid, or `null` if valid.
|
|
49
|
+
*/
|
|
50
|
+
export declare function validateBaseURL(url: string): string | null;
|
|
51
|
+
/** Reads the custom-providers file. Fails open to an empty map on any error. */
|
|
52
|
+
export declare function loadCustomProviders(): Record<string, CustomProvider>;
|
|
53
|
+
/**
|
|
54
|
+
* Inserts or updates a custom provider. Validates name / sdk / baseURL /
|
|
55
|
+
* defaultModel and ensures `defaultModel` is the first entry in `models`.
|
|
56
|
+
*
|
|
57
|
+
* @throws {Error} If any field fails validation.
|
|
58
|
+
*/
|
|
59
|
+
export declare function saveCustomProvider(input: {
|
|
60
|
+
name: string;
|
|
61
|
+
sdk: SupportedSdk;
|
|
62
|
+
baseURL: string;
|
|
63
|
+
defaultModel: string;
|
|
64
|
+
models?: string[];
|
|
65
|
+
}): CustomProvider;
|
|
66
|
+
/**
|
|
67
|
+
* Deletes a custom provider entry. Does NOT delete the matching key in
|
|
68
|
+
* `keys.json` — callers (CLI / REPL) handle key cleanup explicitly.
|
|
69
|
+
*
|
|
70
|
+
* @throws {Error} If no custom provider with that name exists.
|
|
71
|
+
*/
|
|
72
|
+
export declare function removeCustomProvider(name: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Adds `model` to the remembered list for a custom provider if not already
|
|
75
|
+
* present. The default model always stays at position 0. No-op when the
|
|
76
|
+
* provider is unknown.
|
|
77
|
+
*/
|
|
78
|
+
export declare function rememberCustomModel(name: string, model: string): void;
|
|
79
|
+
/** Returns true if `name` matches an existing custom provider entry. */
|
|
80
|
+
export declare function isCustomProvider(name: string, customProviders?: Record<string, CustomProvider>): boolean;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module custom-providers
|
|
4
|
+
*
|
|
5
|
+
* Disk-backed registry of user-defined custom providers — named endpoints
|
|
6
|
+
* that wrap one of the installed AI SDKs (`@ai-sdk/openai`,
|
|
7
|
+
* `@ai-sdk/anthropic`, `@ai-sdk/xai`) with a custom `baseURL` and API key.
|
|
8
|
+
*
|
|
9
|
+
* Lets the user route Bernard at OpenAI/Anthropic/xAI-compatible servers
|
|
10
|
+
* (Ollama, LM Studio, vLLM, OpenRouter, Together, internal proxies, ...)
|
|
11
|
+
* and have several such endpoints configured at once alongside the
|
|
12
|
+
* built-in providers.
|
|
13
|
+
*
|
|
14
|
+
* Storage: `~/.config/bernard/custom-providers.json`
|
|
15
|
+
* Shape: `{ providers: Record<name, CustomProvider> }` with file mode 0600.
|
|
16
|
+
*
|
|
17
|
+
* API keys are NOT stored here; they live in `keys.json` keyed by the
|
|
18
|
+
* provider name (the same file the built-in providers use).
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.SUPPORTED_SDKS = exports.RESERVED_PROVIDER_NAMES = void 0;
|
|
55
|
+
exports.validateProviderName = validateProviderName;
|
|
56
|
+
exports.validateBaseURL = validateBaseURL;
|
|
57
|
+
exports.loadCustomProviders = loadCustomProviders;
|
|
58
|
+
exports.saveCustomProvider = saveCustomProvider;
|
|
59
|
+
exports.removeCustomProvider = removeCustomProvider;
|
|
60
|
+
exports.rememberCustomModel = rememberCustomModel;
|
|
61
|
+
exports.isCustomProvider = isCustomProvider;
|
|
62
|
+
const fs = __importStar(require("node:fs"));
|
|
63
|
+
const path = __importStar(require("node:path"));
|
|
64
|
+
const paths_js_1 = require("./paths.js");
|
|
65
|
+
const fs_utils_js_1 = require("./fs-utils.js");
|
|
66
|
+
/** Names reserved by built-in providers — cannot be used for custom entries. */
|
|
67
|
+
exports.RESERVED_PROVIDER_NAMES = new Set(['anthropic', 'openai', 'xai']);
|
|
68
|
+
/** Allowed SDK choices for a custom provider. */
|
|
69
|
+
exports.SUPPORTED_SDKS = ['openai', 'anthropic', 'xai'];
|
|
70
|
+
/** Max remembered models per custom provider (oldest entries drop when full). */
|
|
71
|
+
const MODELS_CAP = 20;
|
|
72
|
+
const NAME_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
73
|
+
const NAME_MAX_LENGTH = 32;
|
|
74
|
+
/**
|
|
75
|
+
* Validates a custom provider name.
|
|
76
|
+
* @returns An error message if invalid, or `null` if valid.
|
|
77
|
+
*/
|
|
78
|
+
function validateProviderName(name) {
|
|
79
|
+
if (!name)
|
|
80
|
+
return 'Provider name cannot be empty.';
|
|
81
|
+
if (name.length > NAME_MAX_LENGTH)
|
|
82
|
+
return `Provider name must be ${NAME_MAX_LENGTH} characters or fewer.`;
|
|
83
|
+
if (!NAME_PATTERN.test(name))
|
|
84
|
+
return 'Provider name must start with a lowercase letter and contain only lowercase letters, digits, hyphens, and underscores.';
|
|
85
|
+
if (exports.RESERVED_PROVIDER_NAMES.has(name))
|
|
86
|
+
return `"${name}" is a built-in provider name; pick a different name for the custom entry.`;
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validates a base URL — must parse, and use http/https.
|
|
91
|
+
* @returns An error message if invalid, or `null` if valid.
|
|
92
|
+
*/
|
|
93
|
+
function validateBaseURL(url) {
|
|
94
|
+
if (!url || !url.trim())
|
|
95
|
+
return 'Base URL cannot be empty.';
|
|
96
|
+
let parsed;
|
|
97
|
+
try {
|
|
98
|
+
parsed = new URL(url);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return 'Base URL is not a valid URL.';
|
|
102
|
+
}
|
|
103
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
104
|
+
return 'Base URL must use http or https.';
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/** Reads the custom-providers file. Fails open to an empty map on any error. */
|
|
108
|
+
function loadCustomProviders() {
|
|
109
|
+
try {
|
|
110
|
+
const raw = fs.readFileSync(paths_js_1.CUSTOM_PROVIDERS_PATH, 'utf-8');
|
|
111
|
+
const parsed = JSON.parse(raw);
|
|
112
|
+
if (parsed &&
|
|
113
|
+
typeof parsed === 'object' &&
|
|
114
|
+
parsed.providers &&
|
|
115
|
+
typeof parsed.providers === 'object') {
|
|
116
|
+
const out = {};
|
|
117
|
+
for (const [name, entry] of Object.entries(parsed.providers)) {
|
|
118
|
+
if (!entry || typeof entry !== 'object')
|
|
119
|
+
continue;
|
|
120
|
+
const e = entry;
|
|
121
|
+
if (typeof e.name === 'string' &&
|
|
122
|
+
typeof e.sdk === 'string' &&
|
|
123
|
+
exports.SUPPORTED_SDKS.includes(e.sdk) &&
|
|
124
|
+
typeof e.baseURL === 'string' &&
|
|
125
|
+
typeof e.defaultModel === 'string') {
|
|
126
|
+
const models = Array.isArray(e.models)
|
|
127
|
+
? e.models.filter((m) => typeof m === 'string' && m.length > 0)
|
|
128
|
+
: [e.defaultModel];
|
|
129
|
+
if (!models.includes(e.defaultModel))
|
|
130
|
+
models.unshift(e.defaultModel);
|
|
131
|
+
out[name] = {
|
|
132
|
+
name: e.name,
|
|
133
|
+
sdk: e.sdk,
|
|
134
|
+
baseURL: e.baseURL,
|
|
135
|
+
defaultModel: e.defaultModel,
|
|
136
|
+
models,
|
|
137
|
+
createdAt: typeof e.createdAt === 'string' ? e.createdAt : new Date().toISOString(),
|
|
138
|
+
updatedAt: typeof e.updatedAt === 'string' ? e.updatedAt : new Date().toISOString(),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
return {};
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return {};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function writeFile(providers) {
|
|
151
|
+
fs.mkdirSync(path.dirname(paths_js_1.CUSTOM_PROVIDERS_PATH), { recursive: true });
|
|
152
|
+
const payload = { providers };
|
|
153
|
+
(0, fs_utils_js_1.atomicWriteFileSync)(paths_js_1.CUSTOM_PROVIDERS_PATH, JSON.stringify(payload, null, 2) + '\n');
|
|
154
|
+
fs.chmodSync(paths_js_1.CUSTOM_PROVIDERS_PATH, 0o600);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Inserts or updates a custom provider. Validates name / sdk / baseURL /
|
|
158
|
+
* defaultModel and ensures `defaultModel` is the first entry in `models`.
|
|
159
|
+
*
|
|
160
|
+
* @throws {Error} If any field fails validation.
|
|
161
|
+
*/
|
|
162
|
+
function saveCustomProvider(input) {
|
|
163
|
+
const nameErr = validateProviderName(input.name);
|
|
164
|
+
if (nameErr)
|
|
165
|
+
throw new Error(nameErr);
|
|
166
|
+
if (!exports.SUPPORTED_SDKS.includes(input.sdk)) {
|
|
167
|
+
throw new Error(`Unsupported SDK "${input.sdk}". Supported: ${exports.SUPPORTED_SDKS.join(', ')}.`);
|
|
168
|
+
}
|
|
169
|
+
const urlErr = validateBaseURL(input.baseURL);
|
|
170
|
+
if (urlErr)
|
|
171
|
+
throw new Error(urlErr);
|
|
172
|
+
const defaultModel = input.defaultModel.trim();
|
|
173
|
+
if (!defaultModel)
|
|
174
|
+
throw new Error('Default model cannot be empty.');
|
|
175
|
+
const existing = loadCustomProviders();
|
|
176
|
+
const now = new Date().toISOString();
|
|
177
|
+
const seedModels = input.models?.filter((m) => m && m.trim().length > 0) ?? [];
|
|
178
|
+
const models = [defaultModel, ...seedModels.filter((m) => m !== defaultModel)];
|
|
179
|
+
const entry = {
|
|
180
|
+
name: input.name,
|
|
181
|
+
sdk: input.sdk,
|
|
182
|
+
baseURL: input.baseURL,
|
|
183
|
+
defaultModel,
|
|
184
|
+
models: models.slice(0, MODELS_CAP),
|
|
185
|
+
createdAt: existing[input.name]?.createdAt ?? now,
|
|
186
|
+
updatedAt: now,
|
|
187
|
+
};
|
|
188
|
+
existing[input.name] = entry;
|
|
189
|
+
writeFile(existing);
|
|
190
|
+
return entry;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Deletes a custom provider entry. Does NOT delete the matching key in
|
|
194
|
+
* `keys.json` — callers (CLI / REPL) handle key cleanup explicitly.
|
|
195
|
+
*
|
|
196
|
+
* @throws {Error} If no custom provider with that name exists.
|
|
197
|
+
*/
|
|
198
|
+
function removeCustomProvider(name) {
|
|
199
|
+
const existing = loadCustomProviders();
|
|
200
|
+
if (!existing[name]) {
|
|
201
|
+
throw new Error(`No custom provider named "${name}".`);
|
|
202
|
+
}
|
|
203
|
+
delete existing[name];
|
|
204
|
+
if (Object.keys(existing).length === 0) {
|
|
205
|
+
if (fs.existsSync(paths_js_1.CUSTOM_PROVIDERS_PATH)) {
|
|
206
|
+
fs.unlinkSync(paths_js_1.CUSTOM_PROVIDERS_PATH);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
writeFile(existing);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Adds `model` to the remembered list for a custom provider if not already
|
|
215
|
+
* present. The default model always stays at position 0. No-op when the
|
|
216
|
+
* provider is unknown.
|
|
217
|
+
*/
|
|
218
|
+
function rememberCustomModel(name, model) {
|
|
219
|
+
const trimmed = model.trim();
|
|
220
|
+
if (!trimmed)
|
|
221
|
+
return;
|
|
222
|
+
const existing = loadCustomProviders();
|
|
223
|
+
const entry = existing[name];
|
|
224
|
+
if (!entry)
|
|
225
|
+
return;
|
|
226
|
+
if (entry.models.includes(trimmed))
|
|
227
|
+
return;
|
|
228
|
+
const next = [...entry.models, trimmed].slice(-MODELS_CAP);
|
|
229
|
+
// Default model always first.
|
|
230
|
+
const reordered = [entry.defaultModel, ...next.filter((m) => m !== entry.defaultModel)];
|
|
231
|
+
existing[name] = { ...entry, models: reordered, updatedAt: new Date().toISOString() };
|
|
232
|
+
writeFile(existing);
|
|
233
|
+
}
|
|
234
|
+
/** Returns true if `name` matches an existing custom provider entry. */
|
|
235
|
+
function isCustomProvider(name, customProviders = loadCustomProviders()) {
|
|
236
|
+
return Object.hasOwn(customProviders, name);
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=custom-providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-providers.js","sourceRoot":"","sources":["../src/custom-providers.ts"],"names":[],"mappings":"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"}
|
package/dist/fs-utils.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.atomicWriteFileSync = atomicWriteFileSync;
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
/** Writes `data` to a `.tmp` file then renames it into place for crash-safe persistence. */
|
|
39
|
+
function atomicWriteFileSync(filePath, data) {
|
|
40
|
+
const tmp = filePath + '.tmp';
|
|
41
|
+
fs.writeFileSync(tmp, data, 'utf-8');
|
|
42
|
+
fs.renameSync(tmp, filePath);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=fs-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,kDAIC;AAPD,4CAA8B;AAE9B,4FAA4F;AAC5F,SAAgB,mBAAmB,CAAC,QAAgB,EAAE,IAAY;IAChE,MAAM,GAAG,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9B,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/history.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.HistoryStore = void 0;
|
|
37
37
|
const fs = __importStar(require("node:fs"));
|
|
38
38
|
const paths_js_1 = require("./paths.js");
|
|
39
|
+
const image_js_1 = require("./image.js");
|
|
39
40
|
/**
|
|
40
41
|
* Manages persistence of conversation history.
|
|
41
42
|
*
|
|
@@ -58,8 +59,9 @@ class HistoryStore {
|
|
|
58
59
|
/** Atomically writes the conversation history to disk. */
|
|
59
60
|
save(messages) {
|
|
60
61
|
fs.mkdirSync(paths_js_1.STATE_DIR, { recursive: true });
|
|
62
|
+
const stripped = (0, image_js_1.stripImagesFromHistory)(messages);
|
|
61
63
|
const tmp = paths_js_1.HISTORY_FILE + '.tmp';
|
|
62
|
-
fs.writeFileSync(tmp, JSON.stringify(
|
|
64
|
+
fs.writeFileSync(tmp, JSON.stringify(stripped, null, 2), 'utf-8');
|
|
63
65
|
fs.renameSync(tmp, paths_js_1.HISTORY_FILE);
|
|
64
66
|
}
|
|
65
67
|
/** Deletes the saved history file. Silently succeeds if the file does not exist. */
|
package/dist/history.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAE9B,yCAAqD;
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAE9B,yCAAqD;AACrD,yCAAoD;AAEpD;;;;GAIG;AACH,MAAa,YAAY;IACvB,oHAAoH;IACpH,IAAI;QACF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,uBAAY,EAAE,OAAO,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAC;YACtC,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAClE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,QAAuB;QAC1B,EAAE,CAAC,SAAS,CAAC,oBAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAA,iCAAsB,EAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,uBAAY,GAAG,MAAM,CAAC;QAClC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAClE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,uBAAY,CAAC,CAAC;IACnC,CAAC;IAED,oFAAoF;IACpF,KAAK;QACH,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,uBAAY,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;CACF;AAhCD,oCAgCC"}
|