@garuda-agent/garuda 0.17.0 → 0.18.1
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 +243 -0
- package/README.md +3 -2
- package/SECURITY.md +1 -1
- package/dist/{acpCommand-7EY3NHPG.js → acpCommand-JAYNMIMP.js} +19 -16
- package/dist/advise-HDKJGNBL.js +195 -0
- package/dist/brief-RWKESOPT.js +91 -0
- package/dist/buildCheck-HB46NWLX.js +19 -0
- package/dist/buildInfo-K73FFI5S.js +8 -0
- package/dist/chunk-2OYTNNUJ.js +216 -0
- package/dist/{chunk-Z66BWTMD.js → chunk-34WBDQBL.js} +135 -78
- package/dist/chunk-4QRTTRVK.js +88 -0
- package/dist/{chunk-2DYMJMRQ.js → chunk-5UDYQ5MK.js} +405 -70
- package/dist/{chunk-J4346IDH.js → chunk-7KBOIPUT.js} +2 -1
- package/dist/chunk-CWVXOSAA.js +894 -0
- package/dist/{chunk-FARS4R67.js → chunk-DQSCCE77.js} +18 -1
- package/dist/chunk-DUYLVGPY.js +821 -0
- package/dist/chunk-GKU62MHQ.js +5258 -0
- package/dist/chunk-H7LIBGZT.js +9 -0
- package/dist/chunk-IKPGHM54.js +334 -0
- package/dist/chunk-IYGJWX65.js +9 -0
- package/dist/{chunk-U65DQZDB.js → chunk-JMH5W5DG.js} +2 -45
- package/dist/chunk-L55VUSX3.js +54 -0
- package/dist/{chunk-B4SJY7KT.js → chunk-LMKGSYJC.js} +77 -8
- package/dist/{chunk-23FXBNBB.js → chunk-MNE7HHX2.js} +2 -1
- package/dist/chunk-NH72AELP.js +48 -0
- package/dist/{chunk-735BKABA.js → chunk-NLS7GMF7.js} +12 -106
- package/dist/{chunk-ZAE25JM2.js → chunk-QANRZW7W.js} +8 -1
- package/dist/{chunk-JRVWH27M.js → chunk-QLBCM2YQ.js} +7 -3
- package/dist/{chunk-6XHON3Q6.js → chunk-QXTHEFKP.js} +3 -3
- package/dist/{chunk-TJIWD7R7.js → chunk-R7RCW4BQ.js} +10 -8
- package/dist/chunk-TLA2PDGM.js +156 -0
- 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-7TH3NHCQ.js → chunk-ZKT4P2PC.js} +2 -2
- package/dist/cli/index.js +289 -65
- package/dist/config-WV2H64TF.js +23 -0
- package/dist/{create-W6BV75QX.js → create-OACSGJ37.js} +5 -5
- package/dist/evalCommand-BLJJ4G76.js +696 -0
- package/dist/evalTune-W53KAD4V.js +302 -0
- package/dist/{export-SJ3DUP6W.js → export-E677HIQS.js} +27 -4
- package/dist/exportHtml-BMV73YRO.js +21 -0
- package/dist/{inkChat-FNUBK43U.js → inkChat-EVLYDC3K.js} +263 -47
- package/dist/{install-TKWN5AYH.js → install-4ST5BNRG.js} +3 -3
- package/dist/{jobCommand-FE6XN3YD.js → jobCommand-ILOTYOX3.js} +9 -8
- package/dist/{launchd-3A3ONEW5.js → launchd-QG6R5RAK.js} +4 -4
- package/dist/{lspCommand-ZZ6R4PA2.js → lspCommand-X4FTTONR.js} +3 -3
- package/dist/{manager-73MPYFTP.js → manager-L25IUXHW.js} +11 -11
- package/dist/{nightCommand-OODJNWDT.js → nightCommand-XPWT6CQZ.js} +9 -8
- package/dist/receiptView-YFDHV253.js +19 -0
- package/dist/{remove-42WQNVPX.js → remove-STX5UO7X.js} +3 -3
- package/dist/{run-ML6GSPN4.js → run-W4TK52WT.js} +6 -6
- package/dist/{server-VEYIJHEU.js → server-ASM73QVY.js} +3 -3
- package/dist/{setupCommand-GBQIVYJC.js → setupCommand-OSOMFHDQ.js} +10 -9
- package/dist/tour-CEVMAC5S.js +18 -0
- package/dist/tune-VX2WQTHS.js +52 -0
- package/dist/uiState-YFJQ43D7.js +16 -0
- package/package.json +1 -1
- package/dist/chunk-4JSUUDFQ.js +0 -118
- package/dist/chunk-BSK5T2ZG.js +0 -9
- package/dist/evalCommand-YVQAWUZE.js +0 -2833
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
PROPOSER_SYSTEM,
|
|
4
|
+
parseProposal,
|
|
5
|
+
readAddendum,
|
|
6
|
+
tune
|
|
7
|
+
} from "./chunk-IKPGHM54.js";
|
|
8
|
+
import {
|
|
9
|
+
EVAL_SUITES,
|
|
10
|
+
HELD_OUT_TASKS,
|
|
11
|
+
requiredToolchains
|
|
12
|
+
} from "./chunk-GKU62MHQ.js";
|
|
13
|
+
import {
|
|
14
|
+
formatReport,
|
|
15
|
+
reportV2,
|
|
16
|
+
runEvals
|
|
17
|
+
} from "./chunk-DUYLVGPY.js";
|
|
18
|
+
import {
|
|
19
|
+
DEFAULT_SEED,
|
|
20
|
+
TOOLCHAINS,
|
|
21
|
+
checkToolchains,
|
|
22
|
+
shuffled
|
|
23
|
+
} from "./chunk-CWVXOSAA.js";
|
|
24
|
+
import "./chunk-H7LIBGZT.js";
|
|
25
|
+
import "./chunk-YAQ6QLKB.js";
|
|
26
|
+
import "./chunk-NXJ4XLB5.js";
|
|
27
|
+
import "./chunk-5UDYQ5MK.js";
|
|
28
|
+
import "./chunk-G2AX7MGS.js";
|
|
29
|
+
import "./chunk-ULAJPMY7.js";
|
|
30
|
+
import "./chunk-JMH5W5DG.js";
|
|
31
|
+
import {
|
|
32
|
+
NO_MODEL,
|
|
33
|
+
chooseModel,
|
|
34
|
+
keepProviderKeys,
|
|
35
|
+
loadModelsConfig,
|
|
36
|
+
resolveModel
|
|
37
|
+
} from "./chunk-QLBCM2YQ.js";
|
|
38
|
+
import "./chunk-NH72AELP.js";
|
|
39
|
+
import "./chunk-4QRTTRVK.js";
|
|
40
|
+
import "./chunk-A2QAIRQL.js";
|
|
41
|
+
import {
|
|
42
|
+
newSessionId
|
|
43
|
+
} from "./chunk-NLS7GMF7.js";
|
|
44
|
+
import {
|
|
45
|
+
costOf
|
|
46
|
+
} from "./chunk-7KBOIPUT.js";
|
|
47
|
+
import "./chunk-B25VL4RU.js";
|
|
48
|
+
import "./chunk-MNE7HHX2.js";
|
|
49
|
+
import "./chunk-IYGJWX65.js";
|
|
50
|
+
import "./chunk-5DEWP3YX.js";
|
|
51
|
+
import "./chunk-PZS3V6P3.js";
|
|
52
|
+
import "./chunk-QANRZW7W.js";
|
|
53
|
+
import "./chunk-ATW7BNIG.js";
|
|
54
|
+
import "./chunk-WK5NE6RY.js";
|
|
55
|
+
import "./chunk-AOGFYUKG.js";
|
|
56
|
+
import "./chunk-QXTHEFKP.js";
|
|
57
|
+
import {
|
|
58
|
+
createExecutor
|
|
59
|
+
} from "./chunk-LMKGSYJC.js";
|
|
60
|
+
import "./chunk-BHZ6G65V.js";
|
|
61
|
+
import "./chunk-P6XWWIEK.js";
|
|
62
|
+
import "./chunk-UIRJOQQS.js";
|
|
63
|
+
import "./chunk-4LFJFDCF.js";
|
|
64
|
+
import "./chunk-3NJNVZTK.js";
|
|
65
|
+
|
|
66
|
+
// src/cli/evalTune.ts
|
|
67
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
68
|
+
import { writeFile } from "fs/promises";
|
|
69
|
+
import { join } from "path";
|
|
70
|
+
import { createInterface } from "readline/promises";
|
|
71
|
+
var DEFAULT_TUNE_PARALLEL = 4;
|
|
72
|
+
function progressLine(label, done, total, r) {
|
|
73
|
+
return `[${label} ${done}/${total}] ${r.passed ? "\u2713" : "\u2717"} ${r.id} (${r.steps} steps)${r.passed ? "" : `: ${(r.reason ?? r.stopReason).split("\n")[0]}`}`;
|
|
74
|
+
}
|
|
75
|
+
var DEFAULT_PROPOSER = "claude-opus-5-5";
|
|
76
|
+
var DEFAULT_TUNE_SUITES = ["basic", "hard", "medium"];
|
|
77
|
+
var whole = (value, fallback, min) => {
|
|
78
|
+
const v = value ?? fallback;
|
|
79
|
+
return Number.isInteger(v) && v >= min ? v : void 0;
|
|
80
|
+
};
|
|
81
|
+
async function askProposer(proposer, input) {
|
|
82
|
+
const client = await proposer.create();
|
|
83
|
+
let response;
|
|
84
|
+
for await (const event of client.stream({
|
|
85
|
+
system: PROPOSER_SYSTEM,
|
|
86
|
+
messages: [{ role: "user", content: [{ type: "text", text: input }] }],
|
|
87
|
+
tools: [],
|
|
88
|
+
maxTokens: 8e3
|
|
89
|
+
})) {
|
|
90
|
+
if (event.type === "response") response = event.response;
|
|
91
|
+
}
|
|
92
|
+
if (response === void 0) return "the proposer gave no answer";
|
|
93
|
+
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
94
|
+
const parsed = parseProposal(text);
|
|
95
|
+
if (parsed === void 0) return "the proposer's answer has no <addendum> block";
|
|
96
|
+
const price = proposer.info.price;
|
|
97
|
+
return {
|
|
98
|
+
...parsed,
|
|
99
|
+
costUsd: price === void 0 ? void 0 : costOf(response.usage, price, response.priceFactor ?? 1)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async function runEvalTune(options) {
|
|
103
|
+
const rounds = whole(options.rounds, 5, 1);
|
|
104
|
+
const repeat = whole(options.repeat, 3, 1);
|
|
105
|
+
const heldoutRepeat = whole(options.heldoutRepeat, 5, 1);
|
|
106
|
+
const margin = whole(options.margin, 2, 1);
|
|
107
|
+
const seed = whole(options.seed, DEFAULT_SEED, 0);
|
|
108
|
+
const parallel = whole(options.parallel, DEFAULT_TUNE_PARALLEL, 1);
|
|
109
|
+
const maxCost = options.maxCost ?? 20;
|
|
110
|
+
if (rounds === void 0 || repeat === void 0 || heldoutRepeat === void 0 || margin === void 0 || seed === void 0 || parallel === void 0 || !(maxCost > 0)) {
|
|
111
|
+
process.stderr.write(
|
|
112
|
+
"--rounds, --repeat, --heldout-repeat, --margin and --parallel must be whole numbers of 1 or more, --seed 0 or more, and --max-cost above 0.\n"
|
|
113
|
+
);
|
|
114
|
+
return 1;
|
|
115
|
+
}
|
|
116
|
+
const suites = options.suite ?? [...DEFAULT_TUNE_SUITES];
|
|
117
|
+
const devTasks = [];
|
|
118
|
+
for (const name of suites) {
|
|
119
|
+
const tasks = EVAL_SUITES[name];
|
|
120
|
+
if (tasks === void 0) {
|
|
121
|
+
process.stderr.write(`Unknown suite ${name}. Use: ${Object.keys(EVAL_SUITES).join(", ")}.
|
|
122
|
+
`);
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
devTasks.push(...tasks);
|
|
126
|
+
}
|
|
127
|
+
const start = await readAddendum(options.addendum, true);
|
|
128
|
+
if ("problem" in start) {
|
|
129
|
+
process.stderr.write(`${start.problem}
|
|
130
|
+
`);
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
133
|
+
const models = await loadModelsConfig();
|
|
134
|
+
if (models.problem !== void 0) {
|
|
135
|
+
process.stderr.write(`${models.problem}
|
|
136
|
+
`);
|
|
137
|
+
return 1;
|
|
138
|
+
}
|
|
139
|
+
const modelId = chooseModel(models.config, options.model);
|
|
140
|
+
if (!modelId) {
|
|
141
|
+
process.stderr.write(`${NO_MODEL}
|
|
142
|
+
`);
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
let agent;
|
|
146
|
+
let proposer;
|
|
147
|
+
try {
|
|
148
|
+
agent = resolveModel(modelId, models.config);
|
|
149
|
+
proposer = resolveModel(options.proposer ?? DEFAULT_PROPOSER, models.config);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
process.stderr.write(`${error.message}
|
|
152
|
+
`);
|
|
153
|
+
return 1;
|
|
154
|
+
}
|
|
155
|
+
const { assertModelAllowedByPolicy, loadTeamPolicy } = await import("./policy-ZJ7RMOFN.js");
|
|
156
|
+
let team;
|
|
157
|
+
try {
|
|
158
|
+
team = await loadTeamPolicy();
|
|
159
|
+
assertModelAllowedByPolicy(team?.policy, agent.spec);
|
|
160
|
+
assertModelAllowedByPolicy(team?.policy, proposer.spec);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
process.stderr.write(`Team policy: ${error.message}
|
|
163
|
+
`);
|
|
164
|
+
return 1;
|
|
165
|
+
}
|
|
166
|
+
const warning = await keepProviderKeys([agent.def.apiKeyEnv, proposer.def.apiKeyEnv]);
|
|
167
|
+
if (warning !== void 0) process.stderr.write(`${warning}
|
|
168
|
+
`);
|
|
169
|
+
const missing = (await checkToolchains(requiredToolchains([...devTasks, ...HELD_OUT_TASKS]))).filter((s) => !s.ok);
|
|
170
|
+
if (missing.length > 0) {
|
|
171
|
+
for (const status of missing) process.stderr.write(`${TOOLCHAINS[status.id].hint}
|
|
172
|
+
`);
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
const perScore = devTasks.length * repeat;
|
|
176
|
+
const heldOutRuns = 2 * HELD_OUT_TASKS.length * heldoutRepeat;
|
|
177
|
+
process.stderr.write(
|
|
178
|
+
[
|
|
179
|
+
`Tuning ${options.addendum} (${start.text.length} characters) with ${agent.spec}; ${proposer.spec} proposes.`,
|
|
180
|
+
`Dev: ${devTasks.length} task(s) from ${suites.join(", ")} \xD7 ${repeat} = ${perScore} runs a score, ${parallel} at a time; up to ${rounds + 1} scores.`,
|
|
181
|
+
`Held-out: ${HELD_OUT_TASKS.length} task(s) \xD7 ${heldoutRepeat}, twice, at the end (${heldOutRuns} runs), if a version is kept.`,
|
|
182
|
+
`Keep rule: +${margin} passing runs, or as many with a lower cost per accepted change (interval below \xD71.0).`,
|
|
183
|
+
`Budget: --max-cost $${maxCost}; the loop stops before a round that would pass it.`,
|
|
184
|
+
`Garuda changes no file outside the run's folder; ${options.addendum} stays as it is.`,
|
|
185
|
+
""
|
|
186
|
+
].join("\n")
|
|
187
|
+
);
|
|
188
|
+
if (options.yes !== true) {
|
|
189
|
+
if (!process.stdin.isTTY) {
|
|
190
|
+
process.stderr.write("Add --yes to start without a question.\n");
|
|
191
|
+
return 1;
|
|
192
|
+
}
|
|
193
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
194
|
+
const answer = await rl.question("Start? (y/N) ");
|
|
195
|
+
rl.close();
|
|
196
|
+
if (!/^y(es)?$/i.test(answer.trim())) return 1;
|
|
197
|
+
}
|
|
198
|
+
const { executor, notice } = createExecutor("auto");
|
|
199
|
+
if (notice !== void 0) process.stderr.write(`${notice}
|
|
200
|
+
`);
|
|
201
|
+
const dir = join(process.cwd(), ".garuda", "evals", `tune-${newSessionId()}`);
|
|
202
|
+
mkdirSync(dir, { recursive: true });
|
|
203
|
+
const score = async (addendum, tasks, k, label) => {
|
|
204
|
+
const listed = tasks.flatMap((t) => Array.from({ length: k }, () => t));
|
|
205
|
+
const outDir = join(dir, label);
|
|
206
|
+
let done = 0;
|
|
207
|
+
const results = await runEvals(
|
|
208
|
+
shuffled(listed, seed),
|
|
209
|
+
{
|
|
210
|
+
parallel,
|
|
211
|
+
modelId: agent.spec,
|
|
212
|
+
model: () => agent.create(),
|
|
213
|
+
modelInfo: agent.info,
|
|
214
|
+
...agent.maxTokens === void 0 ? {} : { maxTokens: agent.maxTokens },
|
|
215
|
+
...team === void 0 ? {} : { policy: team.policy },
|
|
216
|
+
outDir,
|
|
217
|
+
executor: executor.name === "host" ? "host" : "os",
|
|
218
|
+
...addendum === "" ? {} : { addendum }
|
|
219
|
+
},
|
|
220
|
+
(r) => {
|
|
221
|
+
done++;
|
|
222
|
+
process.stderr.write(`${progressLine(label, done, listed.length, r)}
|
|
223
|
+
`);
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
writeFileSync(
|
|
227
|
+
join(outDir, "report.json"),
|
|
228
|
+
`${JSON.stringify(
|
|
229
|
+
{
|
|
230
|
+
...await reportV2(
|
|
231
|
+
{
|
|
232
|
+
model: agent.spec,
|
|
233
|
+
provider: agent.provider,
|
|
234
|
+
executor: executor.name,
|
|
235
|
+
isolation: executor.isolation,
|
|
236
|
+
seed,
|
|
237
|
+
shuffle: true,
|
|
238
|
+
split: label.startsWith("heldout") ? "heldout" : "dev",
|
|
239
|
+
...addendum === "" ? {} : { addendum: { file: `${label}.md`, text: addendum } }
|
|
240
|
+
},
|
|
241
|
+
tasks,
|
|
242
|
+
results
|
|
243
|
+
),
|
|
244
|
+
results
|
|
245
|
+
},
|
|
246
|
+
null,
|
|
247
|
+
2
|
|
248
|
+
)}
|
|
249
|
+
`
|
|
250
|
+
);
|
|
251
|
+
process.stderr.write(`
|
|
252
|
+
${label}:
|
|
253
|
+
${formatReport(results, { seed })}
|
|
254
|
+
|
|
255
|
+
`);
|
|
256
|
+
return results;
|
|
257
|
+
};
|
|
258
|
+
const result = await tune({
|
|
259
|
+
start: start.text,
|
|
260
|
+
devTasks,
|
|
261
|
+
heldOutTasks: HELD_OUT_TASKS,
|
|
262
|
+
score,
|
|
263
|
+
propose: async (input) => {
|
|
264
|
+
const answer = await askProposer(proposer, input);
|
|
265
|
+
if (typeof answer === "string") {
|
|
266
|
+
return { addendum: "", reason: answer, costUsd: 0 };
|
|
267
|
+
}
|
|
268
|
+
return answer;
|
|
269
|
+
},
|
|
270
|
+
rounds,
|
|
271
|
+
repeat,
|
|
272
|
+
heldoutRepeat,
|
|
273
|
+
margin,
|
|
274
|
+
maxCostUsd: maxCost,
|
|
275
|
+
seed,
|
|
276
|
+
save: (name, text) => writeFile(join(dir, name), text),
|
|
277
|
+
log: (line) => process.stderr.write(`${line}
|
|
278
|
+
`)
|
|
279
|
+
});
|
|
280
|
+
const kept = result.history.filter((h) => h.decision?.kept === true);
|
|
281
|
+
process.stdout.write(
|
|
282
|
+
[
|
|
283
|
+
"",
|
|
284
|
+
`Rounds: ${result.history.length}; kept: ${kept.length === 0 ? "none" : kept.map((h) => h.version).join(", ")}. Spent about $${result.spentUsd.toFixed(2)}${result.stopped === "rounds" ? "" : ` (stopped: ${result.stopped})`}.`,
|
|
285
|
+
...result.heldOut === void 0 ? [] : ["", "Held-out (the only number to quote):", result.heldOut],
|
|
286
|
+
"",
|
|
287
|
+
`The final addendum: ${join(dir, "final.md")}. To use it, copy it into GARUDA.md yourself.`,
|
|
288
|
+
`Every version, the proposer's inputs and history.json: ${dir}`,
|
|
289
|
+
""
|
|
290
|
+
].join("\n")
|
|
291
|
+
);
|
|
292
|
+
return 0;
|
|
293
|
+
}
|
|
294
|
+
export {
|
|
295
|
+
DEFAULT_PROPOSER,
|
|
296
|
+
DEFAULT_TUNE_PARALLEL,
|
|
297
|
+
DEFAULT_TUNE_SUITES,
|
|
298
|
+
askProposer,
|
|
299
|
+
progressLine,
|
|
300
|
+
runEvalTune
|
|
301
|
+
};
|
|
302
|
+
//# sourceMappingURL=evalTune-W53KAD4V.js.map
|
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
import {
|
|
3
3
|
summariseCall,
|
|
4
4
|
summariseResult
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DQSCCE77.js";
|
|
6
|
+
import {
|
|
7
|
+
hasReceipt
|
|
8
|
+
} from "./chunk-4QRTTRVK.js";
|
|
6
9
|
import {
|
|
7
10
|
serverCallText,
|
|
8
11
|
serverResultSummary
|
|
9
12
|
} from "./chunk-A2QAIRQL.js";
|
|
13
|
+
import {
|
|
14
|
+
receiptText
|
|
15
|
+
} from "./chunk-2OYTNNUJ.js";
|
|
16
|
+
import "./chunk-NLS7GMF7.js";
|
|
17
|
+
import "./chunk-7KBOIPUT.js";
|
|
18
|
+
import "./chunk-BHZ6G65V.js";
|
|
10
19
|
import {
|
|
11
20
|
PathOutsideRootError,
|
|
12
21
|
displayPath,
|
|
@@ -98,6 +107,20 @@ function sessionMarkdown(records, sessionId) {
|
|
|
98
107
|
case "compaction":
|
|
99
108
|
out.push("_The conversation was compacted here to fit the context window._", "");
|
|
100
109
|
break;
|
|
110
|
+
case "fork":
|
|
111
|
+
out.push(
|
|
112
|
+
`_This session starts as a fork of session ${record.from.sessionId}, at turn ${record.from.turn}._`,
|
|
113
|
+
""
|
|
114
|
+
);
|
|
115
|
+
break;
|
|
116
|
+
case "receipt":
|
|
117
|
+
if (hasReceipt(record.receipt)) {
|
|
118
|
+
out.push(
|
|
119
|
+
...receiptText(record.receipt).split("\n").map((line) => `> ${line}`),
|
|
120
|
+
""
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
101
124
|
case "model":
|
|
102
125
|
out.push(`_The model changed to ${record.model}._`, "");
|
|
103
126
|
break;
|
|
@@ -129,8 +152,8 @@ function when(iso) {
|
|
|
129
152
|
const pad = (n) => String(n).padStart(2, "0");
|
|
130
153
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
131
154
|
}
|
|
132
|
-
async function writeExport(root, sessionId, markdown, file = "") {
|
|
133
|
-
const name = file === "" ? `garuda-${sessionId}
|
|
155
|
+
async function writeExport(root, sessionId, markdown, file = "", ext = ".md") {
|
|
156
|
+
const name = file === "" ? `garuda-${sessionId}${ext}` : file;
|
|
134
157
|
let absolute;
|
|
135
158
|
try {
|
|
136
159
|
absolute = await resolveInRoot(root, name);
|
|
@@ -155,4 +178,4 @@ export {
|
|
|
155
178
|
sessionMarkdown,
|
|
156
179
|
writeExport
|
|
157
180
|
};
|
|
158
|
-
//# sourceMappingURL=export-
|
|
181
|
+
//# sourceMappingURL=export-E677HIQS.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
OUTPUT_CHARS,
|
|
4
|
+
callChange,
|
|
5
|
+
escapeHtml,
|
|
6
|
+
sessionHtml
|
|
7
|
+
} from "./chunk-TLA2PDGM.js";
|
|
8
|
+
import "./chunk-DQSCCE77.js";
|
|
9
|
+
import "./chunk-4QRTTRVK.js";
|
|
10
|
+
import "./chunk-A2QAIRQL.js";
|
|
11
|
+
import "./chunk-2OYTNNUJ.js";
|
|
12
|
+
import "./chunk-NLS7GMF7.js";
|
|
13
|
+
import "./chunk-7KBOIPUT.js";
|
|
14
|
+
import "./chunk-BHZ6G65V.js";
|
|
15
|
+
export {
|
|
16
|
+
OUTPUT_CHARS,
|
|
17
|
+
callChange,
|
|
18
|
+
escapeHtml,
|
|
19
|
+
sessionHtml
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=exportHtml-BMV73YRO.js.map
|