@garuda-agent/garuda 0.18.0 → 0.18.2
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/CHANGELOG.md +156 -0
- package/README.md +3 -2
- package/dist/{acpCommand-IUZPLPLI.js → acpCommand-PUJHFWYU.js} +10 -8
- package/dist/advise-C777SZ5M.js +433 -0
- package/dist/brief-RWKESOPT.js +91 -0
- package/dist/buildCheck-HB46NWLX.js +19 -0
- package/dist/buildInfo-Z4P7QAQL.js +8 -0
- package/dist/chunk-2OYTNNUJ.js +216 -0
- package/dist/chunk-4BELTWP4.js +156 -0
- package/dist/chunk-4QRTTRVK.js +88 -0
- package/dist/chunk-6JQTPW3P.js +88 -0
- package/dist/chunk-A5DLAXB4.js +1780 -0
- package/dist/{chunk-FARS4R67.js → chunk-AX3A5KPH.js} +18 -1
- package/dist/chunk-CFDRP6XW.js +9 -0
- package/dist/chunk-E6YRCDSF.js +9 -0
- package/dist/{chunk-OQ26W5L4.js → chunk-HP6EGFHV.js} +132 -75
- package/dist/chunk-L55VUSX3.js +54 -0
- package/dist/{chunk-B4SJY7KT.js → chunk-LMKGSYJC.js} +77 -8
- package/dist/{chunk-Q4P3W657.js → chunk-LWNMEGDF.js} +10 -1124
- package/dist/{chunk-23FXBNBB.js → chunk-MNE7HHX2.js} +2 -1
- package/dist/{chunk-UKIE4AAM.js → chunk-NLS7GMF7.js} +11 -105
- package/dist/{chunk-6XHON3Q6.js → chunk-QXTHEFKP.js} +3 -3
- package/dist/{chunk-4BVCYCQT.js → chunk-R7RCW4BQ.js} +9 -7
- package/dist/{chunk-NHWHG3SW.js → chunk-STVFWSIL.js} +350 -57
- package/dist/{chunk-5B5HDTUR.js → chunk-TWQ7V2L6.js} +2 -2
- package/dist/chunk-ULAJPMY7.js +107 -0
- package/dist/chunk-VISKX36R.js +306 -0
- package/dist/{chunk-55CFEEIN.js → chunk-WK5NE6RY.js} +2 -2
- package/dist/chunk-Y62J7PTD.js +90 -0
- package/dist/chunk-YAQ6QLKB.js +40 -0
- package/dist/{chunk-FOPBOB7W.js → chunk-YEH2OONM.js} +6 -4
- package/dist/{chunk-7TH3NHCQ.js → chunk-ZKT4P2PC.js} +2 -2
- package/dist/cli/index.js +242 -52
- package/dist/{create-W6BV75QX.js → create-OACSGJ37.js} +5 -5
- package/dist/{evalCommand-SKJQ6CW2.js → evalCommand-MRO6ENCA.js} +77 -39
- package/dist/{evalTune-CZRCPSZ3.js → evalTune-VL5RHYOG.js} +24 -18
- package/dist/{export-SJ3DUP6W.js → export-ZPF3AMO6.js} +27 -4
- package/dist/exportHtml-ISISG5HG.js +21 -0
- package/dist/{inkChat-WYYAFZXD.js → inkChat-UDFX6GH6.js} +256 -41
- package/dist/{install-TKWN5AYH.js → install-4ST5BNRG.js} +3 -3
- package/dist/{jobCommand-2ODQLHB3.js → jobCommand-ILOTYOX3.js} +8 -7
- package/dist/{launchd-3A3ONEW5.js → launchd-QG6R5RAK.js} +4 -4
- package/dist/{lspCommand-ZZ6R4PA2.js → lspCommand-X4FTTONR.js} +3 -3
- package/dist/{manager-TCYTA5XU.js → manager-YH7722C2.js} +3 -3
- package/dist/{nightCommand-WJU6VZA6.js → nightCommand-XPWT6CQZ.js} +8 -7
- package/dist/receiptView-YFDHV253.js +19 -0
- package/dist/{remove-42WQNVPX.js → remove-STX5UO7X.js} +3 -3
- package/dist/{run-PTMRQCIU.js → run-W4TK52WT.js} +5 -5
- package/dist/runner-EBF6EOYM.js +97 -0
- package/dist/{server-VEYIJHEU.js → server-ASM73QVY.js} +3 -3
- package/dist/tour-CEVMAC5S.js +18 -0
- package/dist/tune-KSNKBPNJ.js +51 -0
- package/dist/uiState-YFJQ43D7.js +16 -0
- package/package.json +1 -1
- package/dist/chunk-4JSUUDFQ.js +0 -118
- package/dist/chunk-C57GHLKP.js +0 -9
- package/dist/chunk-DOCDCQVM.js +0 -484
- package/dist/tune-YVI2KWQF.js +0 -31
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadLspConfig
|
|
4
|
+
} from "./chunk-G2AX7MGS.js";
|
|
5
|
+
import {
|
|
6
|
+
gateProjectSettings
|
|
7
|
+
} from "./chunk-ULAJPMY7.js";
|
|
2
8
|
import {
|
|
3
9
|
mergedModels,
|
|
4
10
|
writeFileAtomic
|
|
5
11
|
} from "./chunk-65NUEOI7.js";
|
|
6
12
|
import {
|
|
7
|
-
|
|
8
|
-
} from "./chunk-
|
|
13
|
+
ReceiptCollector
|
|
14
|
+
} from "./chunk-4QRTTRVK.js";
|
|
9
15
|
import {
|
|
10
16
|
hasServerBlocks,
|
|
11
17
|
serverCallText,
|
|
@@ -29,17 +35,17 @@ import {
|
|
|
29
35
|
compacted,
|
|
30
36
|
createSession,
|
|
31
37
|
emptyUndoState,
|
|
32
|
-
gateProjectSettings,
|
|
33
38
|
isCostIncomplete,
|
|
34
39
|
newSessionId,
|
|
35
40
|
newUserMessage,
|
|
41
|
+
pendingChildTokens,
|
|
36
42
|
popPoint,
|
|
37
43
|
pushPoint,
|
|
38
44
|
redoPoint,
|
|
39
45
|
redoTurn,
|
|
40
46
|
settleChildDebits,
|
|
41
47
|
undoTurn
|
|
42
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-NLS7GMF7.js";
|
|
43
49
|
import {
|
|
44
50
|
REDACTED,
|
|
45
51
|
Redactor,
|
|
@@ -57,10 +63,10 @@ import {
|
|
|
57
63
|
} from "./chunk-B25VL4RU.js";
|
|
58
64
|
import {
|
|
59
65
|
BUILTIN_COMMANDS
|
|
60
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-MNE7HHX2.js";
|
|
61
67
|
import {
|
|
62
68
|
VERSION
|
|
63
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-CFDRP6XW.js";
|
|
64
70
|
import {
|
|
65
71
|
TrustStore
|
|
66
72
|
} from "./chunk-5DEWP3YX.js";
|
|
@@ -91,8 +97,9 @@ import {
|
|
|
91
97
|
expandAllowlist,
|
|
92
98
|
hostAllowed,
|
|
93
99
|
isSensitive,
|
|
94
|
-
loadSettings
|
|
95
|
-
|
|
100
|
+
loadSettings,
|
|
101
|
+
presetFor
|
|
102
|
+
} from "./chunk-LMKGSYJC.js";
|
|
96
103
|
import {
|
|
97
104
|
EFFORTS,
|
|
98
105
|
ZERO_USAGE,
|
|
@@ -1502,7 +1509,12 @@ ${z.prettifyError(parsed.error)}`,
|
|
|
1502
1509
|
await logRun(outcome.isError);
|
|
1503
1510
|
const final = context.hooks === void 0 ? outcome : await context.hooks.after(hookCall, outcome, context.signal);
|
|
1504
1511
|
const subagent = tool.report?.(output);
|
|
1505
|
-
|
|
1512
|
+
const command = tool.commandFacts?.(output);
|
|
1513
|
+
return {
|
|
1514
|
+
...final,
|
|
1515
|
+
...subagent === void 0 ? {} : { subagent },
|
|
1516
|
+
...command === void 0 ? {} : { command }
|
|
1517
|
+
};
|
|
1506
1518
|
} catch (error) {
|
|
1507
1519
|
if (context.signal.aborted) throw error;
|
|
1508
1520
|
if (error instanceof AuditWriteError) {
|
|
@@ -1795,7 +1807,8 @@ function createBashTool({
|
|
|
1795
1807
|
}
|
|
1796
1808
|
const result = await executor.run(run, policy, { signal });
|
|
1797
1809
|
const hints = commandHints(run, stripped);
|
|
1798
|
-
const
|
|
1810
|
+
const blocks = sandboxed ? permissions.takeNetworkBlocks?.() ?? [] : [];
|
|
1811
|
+
const network = sandboxed ? networkHint(blocks, strict) : void 0;
|
|
1799
1812
|
if (network !== void 0) hints.push(network);
|
|
1800
1813
|
const blocked = sandboxed && network === void 0 ? sandboxHint(result, policy.proxy !== void 0, strict) : void 0;
|
|
1801
1814
|
if (blocked !== void 0) hints.push(blocked);
|
|
@@ -1810,7 +1823,21 @@ function createBashTool({
|
|
|
1810
1823
|
`Garuda could not check for processes that left the command's process group (${result.reapProblem}). Such a process may still run, inside the sandbox.`
|
|
1811
1824
|
);
|
|
1812
1825
|
}
|
|
1813
|
-
return {
|
|
1826
|
+
return {
|
|
1827
|
+
...result,
|
|
1828
|
+
hints,
|
|
1829
|
+
sandboxed,
|
|
1830
|
+
blockedHosts: [...new Set(blocks.map((b) => b.host))]
|
|
1831
|
+
};
|
|
1832
|
+
},
|
|
1833
|
+
commandFacts(result) {
|
|
1834
|
+
if ("daemon" in result && result.daemon !== void 0) return void 0;
|
|
1835
|
+
return {
|
|
1836
|
+
exitCode: result.exitCode,
|
|
1837
|
+
timedOut: result.timedOut,
|
|
1838
|
+
sandboxed: result.sandboxed ?? false,
|
|
1839
|
+
blockedHosts: result.blockedHosts ?? []
|
|
1840
|
+
};
|
|
1814
1841
|
},
|
|
1815
1842
|
toText(result) {
|
|
1816
1843
|
const lines = [];
|
|
@@ -6725,7 +6752,8 @@ function rebuildState(records) {
|
|
|
6725
6752
|
unreportedTokens: 0,
|
|
6726
6753
|
childDebits: /* @__PURE__ */ new Map(),
|
|
6727
6754
|
start: void 0,
|
|
6728
|
-
undo: emptyUndoState()
|
|
6755
|
+
undo: emptyUndoState(),
|
|
6756
|
+
turns: 0
|
|
6729
6757
|
};
|
|
6730
6758
|
const addCost2 = (cost) => {
|
|
6731
6759
|
state.costUsd = state.costUsd === void 0 || cost === void 0 ? void 0 : state.costUsd + cost;
|
|
@@ -6743,10 +6771,15 @@ function rebuildState(records) {
|
|
|
6743
6771
|
case "user":
|
|
6744
6772
|
state.messages.push(record.message);
|
|
6745
6773
|
newUserMessage(state.undo);
|
|
6774
|
+
state.turns++;
|
|
6746
6775
|
break;
|
|
6747
|
-
case "snapshot":
|
|
6776
|
+
case "snapshot": {
|
|
6748
6777
|
pushPoint(state.undo, record.tree, record.messages, record.prompt);
|
|
6778
|
+
const point = state.undo.points.at(-1);
|
|
6779
|
+
const at = record.at ?? Date.parse(record.t);
|
|
6780
|
+
if (point !== void 0 && !Number.isNaN(at)) point.at = at;
|
|
6749
6781
|
break;
|
|
6782
|
+
}
|
|
6750
6783
|
case "undo":
|
|
6751
6784
|
popPoint(state.undo, state.messages, record.after);
|
|
6752
6785
|
break;
|
|
@@ -6792,6 +6825,23 @@ function rebuildState(records) {
|
|
|
6792
6825
|
case "thinking":
|
|
6793
6826
|
state.thinking = record.choice;
|
|
6794
6827
|
break;
|
|
6828
|
+
case "fork":
|
|
6829
|
+
state.messages = structuredClone(record.messages);
|
|
6830
|
+
state.turns = record.from.turn - 1;
|
|
6831
|
+
break;
|
|
6832
|
+
case "receipt": {
|
|
6833
|
+
const point = state.undo.points.at(-1);
|
|
6834
|
+
if (point !== void 0 && record.receipt.files !== void 0) {
|
|
6835
|
+
point.changedFiles = record.receipt.files.length;
|
|
6836
|
+
}
|
|
6837
|
+
if (point !== void 0 && record.receipt.costUsd !== void 0) {
|
|
6838
|
+
point.costUsd = record.receipt.costUsd;
|
|
6839
|
+
}
|
|
6840
|
+
if (record.receipt.tests?.total !== void 0) {
|
|
6841
|
+
state.lastTestTotal = record.receipt.tests.total;
|
|
6842
|
+
}
|
|
6843
|
+
break;
|
|
6844
|
+
}
|
|
6795
6845
|
case "unreported":
|
|
6796
6846
|
state.unreportedTokens += record.tokens;
|
|
6797
6847
|
state.costIncomplete = true;
|
|
@@ -6835,6 +6885,8 @@ async function resumeSession(options) {
|
|
|
6835
6885
|
session.childDebits = state.childDebits;
|
|
6836
6886
|
session.undo = state.undo;
|
|
6837
6887
|
if (state.thinking !== void 0) session.thinking = state.thinking;
|
|
6888
|
+
session.turns = state.turns;
|
|
6889
|
+
if (state.lastTestTotal !== void 0) session.lastTestTotal = state.lastTestTotal;
|
|
6838
6890
|
journal.write({ type: "resume", sessionId: id2, ...options.start });
|
|
6839
6891
|
closeOpenToolCalls(session);
|
|
6840
6892
|
return session;
|
|
@@ -6863,6 +6915,34 @@ function repairServerBlocks(message) {
|
|
|
6863
6915
|
return { ...message, content: withoutServerBlocks(message.content) };
|
|
6864
6916
|
}
|
|
6865
6917
|
|
|
6918
|
+
// src/session/list.ts
|
|
6919
|
+
var TITLE_CHARS = 60;
|
|
6920
|
+
function summariseSession(id2, updated, records) {
|
|
6921
|
+
const prompts = records.filter((r) => r.type === "user");
|
|
6922
|
+
const first = prompts[0]?.message.content.find((b) => b.type === "text");
|
|
6923
|
+
const named = records.findLast((r) => r.type === "title");
|
|
6924
|
+
const line = named?.type === "title" ? named.title : (first?.type === "text" ? first.text : "").trim().split("\n")[0] ?? "";
|
|
6925
|
+
const state = rebuildState(records);
|
|
6926
|
+
return {
|
|
6927
|
+
id: id2,
|
|
6928
|
+
updated,
|
|
6929
|
+
title: line.length <= TITLE_CHARS ? line : `${line.slice(0, TITLE_CHARS - 1)}\u2026`,
|
|
6930
|
+
turns: prompts.length,
|
|
6931
|
+
model: state.start?.model,
|
|
6932
|
+
costUsd: state.costUsd,
|
|
6933
|
+
// A child debit with no report: its USD cost is not known (Codex review of 1370184).
|
|
6934
|
+
costIncomplete: isCostIncomplete(state)
|
|
6935
|
+
};
|
|
6936
|
+
}
|
|
6937
|
+
var MAX_TITLE_CHARS = TITLE_CHARS;
|
|
6938
|
+
function cleanTitle(text) {
|
|
6939
|
+
const one = [...text].map((c) => {
|
|
6940
|
+
const code = c.codePointAt(0) ?? 0;
|
|
6941
|
+
return code < 32 || code >= 127 && code < 160 ? " " : c;
|
|
6942
|
+
}).join("").replace(/\s+/g, " ").trim();
|
|
6943
|
+
return one.length <= MAX_TITLE_CHARS ? one : `${one.slice(0, MAX_TITLE_CHARS - 1)}\u2026`;
|
|
6944
|
+
}
|
|
6945
|
+
|
|
6866
6946
|
// src/skills/load.ts
|
|
6867
6947
|
import { createHash as createHash7 } from "crypto";
|
|
6868
6948
|
import { lstat as lstat4, readdir as readdir5, readFile as readFile12, stat as stat7 } from "fs/promises";
|
|
@@ -8136,6 +8216,10 @@ function networkNote(entries, strict = false) {
|
|
|
8136
8216
|
strict ? "For any other host, also run the command in the sandbox: Garuda asks the user for that host, and the result says if it was blocked." : "For any other host, also run the command in the sandbox: Garuda asks the user for that host, and the result says if it was blocked. Use outside_sandbox only when the sandbox blocks something else (a write outside the project)."
|
|
8137
8217
|
].join("\n");
|
|
8138
8218
|
}
|
|
8219
|
+
function networkKeepHint(host2) {
|
|
8220
|
+
const entry = presetFor(host2) ?? host2;
|
|
8221
|
+
return `${host2} works for commands in this session. To keep it for this project, add "${entry}" to "network.allow" in .garuda/settings.json.`;
|
|
8222
|
+
}
|
|
8139
8223
|
function networkConsent(entries, isolation, changed) {
|
|
8140
8224
|
const lines = [
|
|
8141
8225
|
changed ? "The network allowlist in .garuda/settings.json changed since you allowed it." : "This project's .garuda/settings.json opens the network for commands in the sandbox.",
|
|
@@ -8167,34 +8251,6 @@ function nodeBinary(execPath = process.execPath, path = process.env.PATH ?? "")
|
|
|
8167
8251
|
return void 0;
|
|
8168
8252
|
}
|
|
8169
8253
|
|
|
8170
|
-
// src/session/list.ts
|
|
8171
|
-
var TITLE_CHARS = 60;
|
|
8172
|
-
function summariseSession(id2, updated, records) {
|
|
8173
|
-
const prompts = records.filter((r) => r.type === "user");
|
|
8174
|
-
const first = prompts[0]?.message.content.find((b) => b.type === "text");
|
|
8175
|
-
const named = records.findLast((r) => r.type === "title");
|
|
8176
|
-
const line = named?.type === "title" ? named.title : (first?.type === "text" ? first.text : "").trim().split("\n")[0] ?? "";
|
|
8177
|
-
const state = rebuildState(records);
|
|
8178
|
-
return {
|
|
8179
|
-
id: id2,
|
|
8180
|
-
updated,
|
|
8181
|
-
title: line.length <= TITLE_CHARS ? line : `${line.slice(0, TITLE_CHARS - 1)}\u2026`,
|
|
8182
|
-
turns: prompts.length,
|
|
8183
|
-
model: state.start?.model,
|
|
8184
|
-
costUsd: state.costUsd,
|
|
8185
|
-
// A child debit with no report: its USD cost is not known (Codex review of 1370184).
|
|
8186
|
-
costIncomplete: isCostIncomplete(state)
|
|
8187
|
-
};
|
|
8188
|
-
}
|
|
8189
|
-
var MAX_TITLE_CHARS = TITLE_CHARS;
|
|
8190
|
-
function cleanTitle(text) {
|
|
8191
|
-
const one = [...text].map((c) => {
|
|
8192
|
-
const code = c.codePointAt(0) ?? 0;
|
|
8193
|
-
return code < 32 || code >= 127 && code < 160 ? " " : c;
|
|
8194
|
-
}).join("").replace(/\s+/g, " ").trim();
|
|
8195
|
-
return one.length <= MAX_TITLE_CHARS ? one : `${one.slice(0, MAX_TITLE_CHARS - 1)}\u2026`;
|
|
8196
|
-
}
|
|
8197
|
-
|
|
8198
8254
|
// src/app/sessionManager.ts
|
|
8199
8255
|
async function findSession(ref, store) {
|
|
8200
8256
|
const all = await store.list();
|
|
@@ -8307,6 +8363,34 @@ function filesText(changes) {
|
|
|
8307
8363
|
if (changes.length === 0) return "no file changes";
|
|
8308
8364
|
return `${changes.length} file${changes.length === 1 ? "" : "s"} changed`;
|
|
8309
8365
|
}
|
|
8366
|
+
function rewindQuestion(kind, turn, prompt, count2, changes, isolation) {
|
|
8367
|
+
const lines = [`Back to the start of turn ${turn}: "${prompt}"`];
|
|
8368
|
+
if (changes.length === 0) lines.push("No file changes.");
|
|
8369
|
+
else {
|
|
8370
|
+
lines.push(`Files (${changes.length}):`);
|
|
8371
|
+
for (const c of changes.slice(0, MAX_CHANGE_LINES))
|
|
8372
|
+
lines.push(` ${MARKS[c.status]} ${cleanText(c.path).replace(/\n/g, " ")}`);
|
|
8373
|
+
if (changes.length > MAX_CHANGE_LINES) {
|
|
8374
|
+
lines.push(` \u2026 and ${changes.length - MAX_CHANGE_LINES} more.`);
|
|
8375
|
+
}
|
|
8376
|
+
lines.push(" (+ comes back, - is removed, ~ changes)");
|
|
8377
|
+
}
|
|
8378
|
+
lines.push("Files that .gitignore covers (for example build output) are not in undo.");
|
|
8379
|
+
lines.push(
|
|
8380
|
+
kind === "rewind" ? `This takes back ${count2} turn${count2 === 1 ? "" : "s"}: their file changes and their messages. /redo brings them back one at a time.` : "A new session starts with the conversation up to this turn. This session stays as it is: /sessions opens it again.",
|
|
8381
|
+
"Changes that you made to these files since then go back too."
|
|
8382
|
+
);
|
|
8383
|
+
return {
|
|
8384
|
+
tool: kind === "rewind" ? "undo" : "fork",
|
|
8385
|
+
target: { kind: "input", json: "{}" },
|
|
8386
|
+
preview: lines.join("\n"),
|
|
8387
|
+
isolation,
|
|
8388
|
+
title: kind === "rewind" ? `Rewind to turn ${turn}?` : `Fork a new session from turn ${turn}?`,
|
|
8389
|
+
question: kind === "rewind" ? "Rewind?" : "Fork?",
|
|
8390
|
+
choices: ["once", "deny"],
|
|
8391
|
+
labels: { once: kind === "rewind" ? "Yes, rewind" : "Yes, fork", deny: "No" }
|
|
8392
|
+
};
|
|
8393
|
+
}
|
|
8310
8394
|
|
|
8311
8395
|
// src/app/undoCoordinator.ts
|
|
8312
8396
|
var UndoCoordinator = class {
|
|
@@ -8361,6 +8445,81 @@ var UndoCoordinator = class {
|
|
|
8361
8445
|
return `The ${kind} failed, and no file changed: ${error.message}`;
|
|
8362
8446
|
}
|
|
8363
8447
|
}
|
|
8448
|
+
/**
|
|
8449
|
+
* /rewind <n> (UX U6): back to the start of undo point `index` (0-based) in one step: one
|
|
8450
|
+
* question, one restore, then each later turn leaves the conversation as /undo does, newest
|
|
8451
|
+
* first. Each redo entry keeps the files after its turn, so /redo brings them back in order.
|
|
8452
|
+
*/
|
|
8453
|
+
async rewind(session, index3, pendingNotes, signal) {
|
|
8454
|
+
const store = this.snapshots;
|
|
8455
|
+
if (store === void 0) return "Undo is off for this session, so /rewind cannot go back.";
|
|
8456
|
+
const points = session?.undo.points ?? [];
|
|
8457
|
+
const target = points[index3];
|
|
8458
|
+
if (session === void 0 || target === void 0) {
|
|
8459
|
+
return `There is no turn ${index3 + 1}. Type /rewind for the list.`;
|
|
8460
|
+
}
|
|
8461
|
+
try {
|
|
8462
|
+
const now = await store.take(signal);
|
|
8463
|
+
const changes = await store.changes(now, target.tree, signal);
|
|
8464
|
+
const count2 = points.length - index3;
|
|
8465
|
+
const choice = await this.approver.ask(
|
|
8466
|
+
rewindQuestion("rewind", index3 + 1, target.prompt, count2, changes, this.isolation),
|
|
8467
|
+
signal
|
|
8468
|
+
);
|
|
8469
|
+
if (choice === "deny") return "Nothing changed.";
|
|
8470
|
+
const afters = points.slice(index3).map((_, i) => points[index3 + i + 1]?.tree ?? now);
|
|
8471
|
+
await store.restore(now, target.tree, signal);
|
|
8472
|
+
let compacted2 = false;
|
|
8473
|
+
for (let i = afters.length - 1; i >= 0; i--) {
|
|
8474
|
+
const point = undoTurn(session, afters[i]);
|
|
8475
|
+
if (point !== void 0 && !point.conversation) compacted2 = true;
|
|
8476
|
+
}
|
|
8477
|
+
if (compacted2) {
|
|
8478
|
+
pendingNotes.push(
|
|
8479
|
+
`The user rewound to before the turn "${target.prompt}": the file changes of that turn and the later ones are gone. Read files again before you edit them.`
|
|
8480
|
+
);
|
|
8481
|
+
}
|
|
8482
|
+
return `Rewound to the start of turn ${index3 + 1} ("${target.prompt}"): ${count2} turn${count2 === 1 ? "" : "s"} taken back, ${filesText(changes)}. /redo brings them back one at a time.`;
|
|
8483
|
+
} catch (error) {
|
|
8484
|
+
if (!(error instanceof SnapshotError)) throw error;
|
|
8485
|
+
return `The rewind failed, and no file changed: ${error.message}`;
|
|
8486
|
+
}
|
|
8487
|
+
}
|
|
8488
|
+
/**
|
|
8489
|
+
* The files for a fork (UX U6): back to undo point `index`, after one question. The caller
|
|
8490
|
+
* starts the new session. Returns undefined when the user said no.
|
|
8491
|
+
*/
|
|
8492
|
+
async restoreForFork(session, index3, signal) {
|
|
8493
|
+
const store = this.snapshots;
|
|
8494
|
+
if (store === void 0)
|
|
8495
|
+
return {
|
|
8496
|
+
ok: false,
|
|
8497
|
+
text: "Undo is off for this session, so a fork cannot restore the files."
|
|
8498
|
+
};
|
|
8499
|
+
const target = session.undo.points[index3];
|
|
8500
|
+
if (target === void 0)
|
|
8501
|
+
return { ok: false, text: `There is no turn ${index3 + 1}. Type /rewind for the list.` };
|
|
8502
|
+
if (!target.conversation) {
|
|
8503
|
+
return {
|
|
8504
|
+
ok: false,
|
|
8505
|
+
text: `Turn ${index3 + 1} is before a compaction: its messages are no longer separate, so it cannot start a fork.`
|
|
8506
|
+
};
|
|
8507
|
+
}
|
|
8508
|
+
try {
|
|
8509
|
+
const now = await store.take(signal);
|
|
8510
|
+
const changes = await store.changes(now, target.tree, signal);
|
|
8511
|
+
const choice = await this.approver.ask(
|
|
8512
|
+
rewindQuestion("fork", index3 + 1, target.prompt, 0, changes, this.isolation),
|
|
8513
|
+
signal
|
|
8514
|
+
);
|
|
8515
|
+
if (choice === "deny") return { ok: false, text: "Nothing changed." };
|
|
8516
|
+
await store.restore(now, target.tree, signal);
|
|
8517
|
+
return { ok: true };
|
|
8518
|
+
} catch (error) {
|
|
8519
|
+
if (!(error instanceof SnapshotError)) throw error;
|
|
8520
|
+
return { ok: false, text: `The fork failed, and no file changed: ${error.message}` };
|
|
8521
|
+
}
|
|
8522
|
+
}
|
|
8364
8523
|
async undoNow(session, pendingNotes, signal) {
|
|
8365
8524
|
const store = this.snapshots;
|
|
8366
8525
|
if (store === void 0) return "Undo is off for this session.";
|
|
@@ -8534,6 +8693,8 @@ var Runtime = class _Runtime {
|
|
|
8534
8693
|
startModel;
|
|
8535
8694
|
/** The prompt of the turn that runs or ran last (0.9: the note after a stopped turn). */
|
|
8536
8695
|
lastPrompt;
|
|
8696
|
+
/** The receipt of the last turn (UX U1); undefined before a turn ends, or after a failed one. */
|
|
8697
|
+
receipt;
|
|
8537
8698
|
/** LSP diagnostics after edits are on (0.4). */
|
|
8538
8699
|
lspEnabled;
|
|
8539
8700
|
lspOptions;
|
|
@@ -8718,6 +8879,10 @@ var Runtime = class _Runtime {
|
|
|
8718
8879
|
);
|
|
8719
8880
|
}
|
|
8720
8881
|
}
|
|
8882
|
+
/** The chat's look (0.18.1); the CLI applies it. */
|
|
8883
|
+
get uiSettings() {
|
|
8884
|
+
return this.settings.ui;
|
|
8885
|
+
}
|
|
8721
8886
|
/** The notification settings for the chat (0.6); the CLI applies them. */
|
|
8722
8887
|
get notificationSettings() {
|
|
8723
8888
|
return this.settings.notifications;
|
|
@@ -9352,6 +9517,8 @@ ${neutralizeTags(output)}`
|
|
|
9352
9517
|
}
|
|
9353
9518
|
/** Run one turn: the user's prompt, then the loop until it stops. */
|
|
9354
9519
|
async runTurn(prompt, signal) {
|
|
9520
|
+
const started = Date.now();
|
|
9521
|
+
this.receipt = void 0;
|
|
9355
9522
|
this.lastPrompt = prompt;
|
|
9356
9523
|
this.turnSignal = signal;
|
|
9357
9524
|
await this.startHooks(signal);
|
|
@@ -9382,6 +9549,22 @@ ${neutralizeTags(output)}`
|
|
|
9382
9549
|
];
|
|
9383
9550
|
if (lines.length > 0) this.onEvent?.({ type: "notice", text: lines.join("\n") });
|
|
9384
9551
|
closeOpenToolCalls(session);
|
|
9552
|
+
session.turns = (session.turns ?? 0) + 1;
|
|
9553
|
+
const before = {
|
|
9554
|
+
cost: session.costUsd,
|
|
9555
|
+
unreported: session.unreportedTokens,
|
|
9556
|
+
pending: pendingChildTokens(session),
|
|
9557
|
+
incomplete: session.costIncomplete
|
|
9558
|
+
};
|
|
9559
|
+
const collector = new ReceiptCollector(detectTestCommand(this.root, this.profiles));
|
|
9560
|
+
let changesFiles = false;
|
|
9561
|
+
const onEvent = (event) => {
|
|
9562
|
+
collector.onEvent(event);
|
|
9563
|
+
if (event.type === "tool_call" && !this.tools.isReadOnly(event.call.name)) {
|
|
9564
|
+
changesFiles = true;
|
|
9565
|
+
}
|
|
9566
|
+
this.onEvent?.(event);
|
|
9567
|
+
};
|
|
9385
9568
|
addUserMessage(
|
|
9386
9569
|
session,
|
|
9387
9570
|
prompt,
|
|
@@ -9407,17 +9590,84 @@ ${neutralizeTags(output)}`
|
|
|
9407
9590
|
...this.outputTokens(),
|
|
9408
9591
|
contextWindow: this.limits.contextWindow,
|
|
9409
9592
|
...this.price === void 0 ? {} : { price: this.price },
|
|
9410
|
-
|
|
9593
|
+
onEvent,
|
|
9411
9594
|
...this.settings.thinking?.keepBlocks === false ? { keepThinking: false } : {},
|
|
9412
9595
|
...this.thinkingParams === void 0 ? {} : { thinking: this.thinkingParams },
|
|
9413
9596
|
signal
|
|
9414
9597
|
});
|
|
9598
|
+
this.receipt = await this.makeReceipt(session, result, collector, {
|
|
9599
|
+
...before,
|
|
9600
|
+
started,
|
|
9601
|
+
changesFiles,
|
|
9602
|
+
signal
|
|
9603
|
+
});
|
|
9415
9604
|
if (this.turnMode === "plan" && result.stopReason === "done") {
|
|
9416
9605
|
const plan2 = lastAssistantText(session.messages);
|
|
9417
9606
|
if (plan2 !== "") this.plan = { request: prompt, plan: plan2, sessionId: session.id };
|
|
9418
9607
|
}
|
|
9419
9608
|
return result;
|
|
9420
9609
|
}
|
|
9610
|
+
/** The receipt of the last turn (UX U1), or undefined. */
|
|
9611
|
+
get lastReceipt() {
|
|
9612
|
+
return this.receipt;
|
|
9613
|
+
}
|
|
9614
|
+
/**
|
|
9615
|
+
* The turn's receipt (UX U1; docs/lld/ux.md): the files from a snapshot at the end of the turn
|
|
9616
|
+
* (only when a tool that can change files ran), the commands' facts, and the costs.
|
|
9617
|
+
*/
|
|
9618
|
+
async makeReceipt(session, result, collector, before) {
|
|
9619
|
+
const store = this.undoCoordinator.store;
|
|
9620
|
+
const point = session.undo.points.at(-1);
|
|
9621
|
+
let files;
|
|
9622
|
+
if (store !== void 0 && point !== void 0) {
|
|
9623
|
+
files = [];
|
|
9624
|
+
if (before.changesFiles) {
|
|
9625
|
+
try {
|
|
9626
|
+
const end = await store.take(before.signal);
|
|
9627
|
+
files = (await store.stats(point.tree, end, before.signal)).map((f) => ({
|
|
9628
|
+
path: f.path,
|
|
9629
|
+
...f.added === void 0 ? {} : { added: f.added, removed: f.removed ?? 0 }
|
|
9630
|
+
}));
|
|
9631
|
+
} catch (error) {
|
|
9632
|
+
if (before.signal.aborted) throw error;
|
|
9633
|
+
files = void 0;
|
|
9634
|
+
}
|
|
9635
|
+
}
|
|
9636
|
+
if (files !== void 0) point.changedFiles = files.length;
|
|
9637
|
+
if (session.costUsd !== void 0 && before.cost !== void 0) {
|
|
9638
|
+
point.costUsd = session.costUsd - before.cost;
|
|
9639
|
+
}
|
|
9640
|
+
}
|
|
9641
|
+
const costIncomplete = session.unreportedTokens > before.unreported || pendingChildTokens(session) > before.pending || session.costIncomplete && !before.incomplete;
|
|
9642
|
+
const tests = collector.tests;
|
|
9643
|
+
if (tests !== void 0 && session.lastTestTotal !== void 0) {
|
|
9644
|
+
tests.previousTotal = session.lastTestTotal;
|
|
9645
|
+
}
|
|
9646
|
+
if (tests?.total !== void 0) session.lastTestTotal = tests.total;
|
|
9647
|
+
const receipt = {
|
|
9648
|
+
turn: session.turns ?? 1,
|
|
9649
|
+
stopReason: result.stopReason,
|
|
9650
|
+
steps: result.steps,
|
|
9651
|
+
durationMs: Date.now() - before.started,
|
|
9652
|
+
...session.costUsd === void 0 || before.cost === void 0 ? {} : { costUsd: session.costUsd - before.cost },
|
|
9653
|
+
...costIncomplete ? { costIncomplete: true } : {},
|
|
9654
|
+
...files === void 0 ? {} : { files },
|
|
9655
|
+
...tests === void 0 ? {} : { tests },
|
|
9656
|
+
commands: {
|
|
9657
|
+
sandboxed: collector.sandboxed,
|
|
9658
|
+
outside: collector.outside,
|
|
9659
|
+
blockedHosts: [...collector.blockedHosts]
|
|
9660
|
+
},
|
|
9661
|
+
contextPercent: Math.round(session.contextTokens / this.limits.contextWindow * 100),
|
|
9662
|
+
...session.costUsd === void 0 ? {} : { sessionCostUsd: session.costUsd },
|
|
9663
|
+
...isCostIncomplete(session) ? { sessionCostIncomplete: true } : {},
|
|
9664
|
+
...store === void 0 ? {} : {
|
|
9665
|
+
keptChanges: session.undo.points.filter((p) => (p.changedFiles ?? 0) > 0).length
|
|
9666
|
+
}
|
|
9667
|
+
};
|
|
9668
|
+
session.journal?.write({ type: "receipt", receipt });
|
|
9669
|
+
return receipt;
|
|
9670
|
+
}
|
|
9421
9671
|
/** The last finished plan of this process, for /schedule (0.7). */
|
|
9422
9672
|
get lastPlan() {
|
|
9423
9673
|
return this.plan;
|
|
@@ -9434,7 +9684,7 @@ ${neutralizeTags(output)}`
|
|
|
9434
9684
|
text: "There is no finished plan in this chat. Make one in plan mode (/plan), then type /schedule."
|
|
9435
9685
|
};
|
|
9436
9686
|
}
|
|
9437
|
-
const { createJob } = await import("./create-
|
|
9687
|
+
const { createJob } = await import("./create-OACSGJ37.js");
|
|
9438
9688
|
const created = await createJob({
|
|
9439
9689
|
root: this.root,
|
|
9440
9690
|
executor: this.executor,
|
|
@@ -9517,7 +9767,7 @@ ${result.stderr.text}`)
|
|
|
9517
9767
|
*/
|
|
9518
9768
|
async cancelJob(id2, agent = {}) {
|
|
9519
9769
|
const { loadJob, saveJob } = await import("./job-7JOI4YIQ.js");
|
|
9520
|
-
const { defaultAgentEnv, nightSpec, removeAgent, removeSpec } = await import("./launchd-
|
|
9770
|
+
const { defaultAgentEnv, nightSpec, removeAgent, removeSpec } = await import("./launchd-QG6R5RAK.js");
|
|
9521
9771
|
if (id2 === "night") {
|
|
9522
9772
|
const removed = await removeSpec(
|
|
9523
9773
|
agent.executor ?? this.executor,
|
|
@@ -9549,8 +9799,8 @@ ${result.stderr.text}`)
|
|
|
9549
9799
|
*/
|
|
9550
9800
|
async deleteJob(id2, signal, agent = {}) {
|
|
9551
9801
|
const { loadJob } = await import("./job-7JOI4YIQ.js");
|
|
9552
|
-
const { defaultAgentEnv, removeAgent } = await import("./launchd-
|
|
9553
|
-
const { jobLeftovers, removeJob } = await import("./remove-
|
|
9802
|
+
const { defaultAgentEnv, removeAgent } = await import("./launchd-QG6R5RAK.js");
|
|
9803
|
+
const { jobLeftovers, removeJob } = await import("./remove-STX5UO7X.js");
|
|
9554
9804
|
let job;
|
|
9555
9805
|
try {
|
|
9556
9806
|
job = await loadJob(this.root, id2);
|
|
@@ -9722,7 +9972,7 @@ ${result.stderr.text}`)
|
|
|
9722
9972
|
* The files it writes are new only; the turn's own writes go through the normal approvals.
|
|
9723
9973
|
*/
|
|
9724
9974
|
async init(signal) {
|
|
9725
|
-
const { runInit } = await import("./run-
|
|
9975
|
+
const { runInit } = await import("./run-W4TK52WT.js");
|
|
9726
9976
|
const result = await runInit({
|
|
9727
9977
|
root: this.root,
|
|
9728
9978
|
home: this.commandsHome,
|
|
@@ -9757,6 +10007,8 @@ ${result.stderr.text}`)
|
|
|
9757
10007
|
await this.staged?.remove().catch(() => {
|
|
9758
10008
|
});
|
|
9759
10009
|
}
|
|
10010
|
+
/** UX U2: the proxy runs with no host on the list, only to ask for the hosts that commands need. */
|
|
10011
|
+
watchingNetwork = false;
|
|
9760
10012
|
/** The network allowlist in effect (0.13): the settings entries, or [] when the proxy is off. */
|
|
9761
10013
|
networkAllowlist() {
|
|
9762
10014
|
return this.networkProxy === void 0 ? [] : [...this.settings.network?.allow ?? []];
|
|
@@ -9768,9 +10020,11 @@ ${result.stderr.text}`)
|
|
|
9768
10020
|
*/
|
|
9769
10021
|
async startNetwork(signal) {
|
|
9770
10022
|
const entries = this.settings.network?.allow ?? [];
|
|
9771
|
-
if (
|
|
10023
|
+
if (this.executor.isolation !== "os") return;
|
|
10024
|
+
const watch = entries.length === 0 && this.networkOptions.watch === true;
|
|
10025
|
+
if (entries.length === 0 && !watch) return;
|
|
9772
10026
|
this.networkStarted ??= (async () => {
|
|
9773
|
-
if (this.networkOptions.approved !== true) {
|
|
10027
|
+
if (!watch && this.networkOptions.approved !== true) {
|
|
9774
10028
|
const trust = await TrustStore.open(this.networkOptions.home ?? homedir5());
|
|
9775
10029
|
const hash = networkHash(entries);
|
|
9776
10030
|
const known = trust.networkHash(this.root);
|
|
@@ -9790,9 +10044,11 @@ ${result.stderr.text}`)
|
|
|
9790
10044
|
if (this.executor.name === "bwrap") {
|
|
9791
10045
|
bridge = nodeBinary();
|
|
9792
10046
|
if (bridge === void 0) {
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
10047
|
+
if (!watch) {
|
|
10048
|
+
this.onNotice?.(
|
|
10049
|
+
"Network for commands: off. On Linux the allowlist needs node on the PATH (for the bridge into the sandbox)."
|
|
10050
|
+
);
|
|
10051
|
+
}
|
|
9796
10052
|
return;
|
|
9797
10053
|
}
|
|
9798
10054
|
}
|
|
@@ -9807,6 +10063,10 @@ ${result.stderr.text}`)
|
|
|
9807
10063
|
policy: { ...started, ...bridge === void 0 ? {} : { bridge } },
|
|
9808
10064
|
takeBlocked: () => proxy.takeBlocked()
|
|
9809
10065
|
});
|
|
10066
|
+
if (watch) {
|
|
10067
|
+
this.watchingNetwork = true;
|
|
10068
|
+
return;
|
|
10069
|
+
}
|
|
9810
10070
|
this.onNotice?.(
|
|
9811
10071
|
`Network for commands: ${entries.join(", ")}, through Garuda's proxy. Other hosts ask.`
|
|
9812
10072
|
);
|
|
@@ -9840,12 +10100,15 @@ ${result.stderr.text}`)
|
|
|
9840
10100
|
readOnly: false,
|
|
9841
10101
|
info: {
|
|
9842
10102
|
target: { kind: "url", url: `https://${host2}`, host: host2 },
|
|
9843
|
-
preview: `A command in the sandbox wants to reach ${host2}:${port} through Garuda's proxy. The host is not on the network allowlist ("network.allow" in .garuda/settings.json).`,
|
|
10103
|
+
preview: this.watchingNetwork ? `A command in the sandbox wants to reach ${host2}:${port}. Commands have no network unless you allow a host; Garuda's proxy sees only the host name.` : `A command in the sandbox wants to reach ${host2}:${port} through Garuda's proxy. The host is not on the network allowlist ("network.allow" in .garuda/settings.json).`,
|
|
9844
10104
|
title: `Let a command reach ${host2}?`
|
|
9845
10105
|
}
|
|
9846
10106
|
},
|
|
9847
10107
|
this.turnSignal ?? new AbortController().signal
|
|
9848
10108
|
);
|
|
10109
|
+
if (decision.allowed && decision.remembered === true) {
|
|
10110
|
+
this.onNotice?.(networkKeepHint(host2));
|
|
10111
|
+
}
|
|
9849
10112
|
return decision.allowed ? { allowed: true } : { allowed: false, reason: decision.reason.replace(/\.$/, "") };
|
|
9850
10113
|
}
|
|
9851
10114
|
get lspHome() {
|
|
@@ -9879,7 +10142,7 @@ ${result.stderr.text}`)
|
|
|
9879
10142
|
}
|
|
9880
10143
|
/** Install a language server into ~/.garuda/lsp (the user asked for it). */
|
|
9881
10144
|
async installLsp(language, signal) {
|
|
9882
|
-
const { installServer } = await import("./install-
|
|
10145
|
+
const { installServer } = await import("./install-4ST5BNRG.js");
|
|
9883
10146
|
const result = await installServer(language, {
|
|
9884
10147
|
executor: this.executor,
|
|
9885
10148
|
home: this.lspHome,
|
|
@@ -9890,7 +10153,7 @@ ${result.stderr.text}`)
|
|
|
9890
10153
|
}
|
|
9891
10154
|
/** autoInstall (~/.garuda/lsp.json): ask before a managed install. */
|
|
9892
10155
|
async askInstall(language, signal) {
|
|
9893
|
-
const { installCommand } = await import("./install-
|
|
10156
|
+
const { installCommand } = await import("./install-4ST5BNRG.js");
|
|
9894
10157
|
const { LANGUAGE_LABELS } = await import("./manager-4PMSXT47.js");
|
|
9895
10158
|
const { managedLabel, managedDir } = await import("./servers-6YDGWOZ6.js");
|
|
9896
10159
|
const dir = managedDir(language, this.lspHome);
|
|
@@ -9923,7 +10186,7 @@ ${result.stderr.text}`)
|
|
|
9923
10186
|
async startMcp(signal) {
|
|
9924
10187
|
if (this.mcpServers.length === 0) return;
|
|
9925
10188
|
this.mcpStarted ??= (async () => {
|
|
9926
|
-
const { McpManager } = await import("./manager-
|
|
10189
|
+
const { McpManager } = await import("./manager-YH7722C2.js");
|
|
9927
10190
|
const { AuthStore } = await import("./oauth-W6OK6XXO.js");
|
|
9928
10191
|
const manager = new McpManager({
|
|
9929
10192
|
root: this.root,
|
|
@@ -10091,6 +10354,36 @@ ${result.stderr.text}`)
|
|
|
10091
10354
|
async undo(signal) {
|
|
10092
10355
|
return this.undoCoordinator.undo(this.current, this.pendingNotes, signal);
|
|
10093
10356
|
}
|
|
10357
|
+
/** The undo points of this session, oldest first (UX U6: the /rewind list). */
|
|
10358
|
+
get rewindPoints() {
|
|
10359
|
+
return this.current?.undo.points ?? [];
|
|
10360
|
+
}
|
|
10361
|
+
/** /rewind <n> (UX U6): back to the start of turn n (1-based in the list). */
|
|
10362
|
+
async rewind(turn, signal) {
|
|
10363
|
+
return this.undoCoordinator.rewind(this.current, turn - 1, this.pendingNotes, signal);
|
|
10364
|
+
}
|
|
10365
|
+
/**
|
|
10366
|
+
* /rewind fork <n> (UX U6): a new session with the conversation up to the start of turn n, and
|
|
10367
|
+
* the files as they were then. The old session stays on disk as it is.
|
|
10368
|
+
*/
|
|
10369
|
+
async fork(turn, signal) {
|
|
10370
|
+
const old = this.current;
|
|
10371
|
+
if (old === void 0) return "No turn has run in this session yet.";
|
|
10372
|
+
const restored = await this.undoCoordinator.restoreForFork(old, turn - 1, signal);
|
|
10373
|
+
if (!restored.ok) return restored.text;
|
|
10374
|
+
const point = old.undo.points[turn - 1];
|
|
10375
|
+
const messages = structuredClone(old.messages.slice(0, point.messages));
|
|
10376
|
+
this.newSession();
|
|
10377
|
+
const fresh = this.ensureSession();
|
|
10378
|
+
fresh.messages = messages;
|
|
10379
|
+
fresh.turns = turn - 1;
|
|
10380
|
+
fresh.journal?.write({ type: "fork", from: { sessionId: old.id, turn }, messages });
|
|
10381
|
+
fresh.journal?.write({
|
|
10382
|
+
type: "title",
|
|
10383
|
+
title: cleanTitle(`Fork of turn ${turn}: ${point.prompt}`)
|
|
10384
|
+
});
|
|
10385
|
+
return `New session ${fresh.id}: the conversation up to turn ${turn} ("${point.prompt}"), and the files as they were then. The old session ${old.id} stays as it was: /sessions opens it.`;
|
|
10386
|
+
}
|
|
10094
10387
|
/** /redo (0.4): bring back the last undone turn: its files and its messages. */
|
|
10095
10388
|
async redo(signal) {
|
|
10096
10389
|
return this.undoCoordinator.redo(this.current, this.pendingNotes, signal);
|
|
@@ -10192,4 +10485,4 @@ export {
|
|
|
10192
10485
|
modelFacts,
|
|
10193
10486
|
Runtime
|
|
10194
10487
|
};
|
|
10195
|
-
//# sourceMappingURL=chunk-
|
|
10488
|
+
//# sourceMappingURL=chunk-STVFWSIL.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
hostCommand,
|
|
4
4
|
shellWord
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QXTHEFKP.js";
|
|
6
6
|
import {
|
|
7
7
|
JOBS_DIR
|
|
8
8
|
} from "./chunk-VTMD5IHD.js";
|
|
@@ -154,4 +154,4 @@ export {
|
|
|
154
154
|
nightAgentTime,
|
|
155
155
|
removeAgent
|
|
156
156
|
};
|
|
157
|
-
//# sourceMappingURL=chunk-
|
|
157
|
+
//# sourceMappingURL=chunk-TWQ7V2L6.js.map
|