@thedevlabs-io/labd 0.6.0 → 0.7.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 +1 -1
- package/dist/labd.js +243 -14
- package/dist/labd.js.map +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ more columns.
|
|
|
129
129
|
| `/sessions`, `/session` | earlier sessions here (a dialog; `enter` resumes); where this one is stored |
|
|
130
130
|
| `/new` | start a fresh session; the current one stays saved |
|
|
131
131
|
| `/sidebar`, `/clear` | show or hide the side panel; clear the screen |
|
|
132
|
-
| `/usage` | what's left of this month's allowance |
|
|
132
|
+
| `/usage` | what's left of this month's allowance, and a heatmap of your activity |
|
|
133
133
|
| `/trust` | let this project load its own extensions |
|
|
134
134
|
| `/reload` | reload extensions and the file list |
|
|
135
135
|
| `/quit` | leave - the session is saved, and `labd --resume <id>` continues it |
|
package/dist/labd.js
CHANGED
|
@@ -3,6 +3,117 @@
|
|
|
3
3
|
// packages/cli/src/index.ts
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
|
|
6
|
+
// vendor/labd/packages/protocol/src/activity.ts
|
|
7
|
+
var ACTIVITY_WEEKS = 53;
|
|
8
|
+
function utcOffsetMinutes(at2 = /* @__PURE__ */ new Date()) {
|
|
9
|
+
return -at2.getTimezoneOffset();
|
|
10
|
+
}
|
|
11
|
+
var DAY_MS = 864e5;
|
|
12
|
+
function localDate(at2 = /* @__PURE__ */ new Date()) {
|
|
13
|
+
const pad4 = (n) => String(n).padStart(2, "0");
|
|
14
|
+
return `${at2.getFullYear()}-${pad4(at2.getMonth() + 1)}-${pad4(at2.getDate())}`;
|
|
15
|
+
}
|
|
16
|
+
function dayNumber(date) {
|
|
17
|
+
return Math.floor(Date.parse(`${date}T00:00:00Z`) / DAY_MS);
|
|
18
|
+
}
|
|
19
|
+
function dateOf(day) {
|
|
20
|
+
return new Date(day * DAY_MS).toISOString().slice(0, 10);
|
|
21
|
+
}
|
|
22
|
+
function summariseActivity(activity, weeks, today = localDate()) {
|
|
23
|
+
const span = Math.max(1, Math.min(ACTIVITY_WEEKS, Math.floor(weeks)));
|
|
24
|
+
const last = dayNumber(today);
|
|
25
|
+
const monday = last - (last + 3) % 7;
|
|
26
|
+
const first = monday - (span - 1) * 7;
|
|
27
|
+
const earliest = monday - (ACTIVITY_WEEKS - 1) * 7;
|
|
28
|
+
const perDay = /* @__PURE__ */ new Map();
|
|
29
|
+
const perSurface = /* @__PURE__ */ new Map();
|
|
30
|
+
const totals = { turns: 0, input: 0, output: 0, activeDays: 0 };
|
|
31
|
+
for (const bucket of activity.days) {
|
|
32
|
+
const day = dayNumber(bucket.day);
|
|
33
|
+
if (!(day >= earliest && day <= last)) continue;
|
|
34
|
+
const tokens = bucket.input + bucket.output;
|
|
35
|
+
const d = perDay.get(day) ?? { turns: 0, tokens: 0 };
|
|
36
|
+
d.turns += bucket.turns;
|
|
37
|
+
d.tokens += tokens;
|
|
38
|
+
perDay.set(day, d);
|
|
39
|
+
if (day < first) continue;
|
|
40
|
+
const s = perSurface.get(bucket.surface) ?? { turns: 0, tokens: 0 };
|
|
41
|
+
s.turns += bucket.turns;
|
|
42
|
+
s.tokens += tokens;
|
|
43
|
+
perSurface.set(bucket.surface, s);
|
|
44
|
+
totals.turns += bucket.turns;
|
|
45
|
+
totals.input += bucket.input;
|
|
46
|
+
totals.output += bucket.output;
|
|
47
|
+
}
|
|
48
|
+
let run = 0;
|
|
49
|
+
let longest = 0;
|
|
50
|
+
for (let day = earliest; day <= last; day++) {
|
|
51
|
+
if ((perDay.get(day)?.turns ?? 0) > 0) {
|
|
52
|
+
run += 1;
|
|
53
|
+
longest = Math.max(longest, run);
|
|
54
|
+
} else if (day !== last) {
|
|
55
|
+
run = 0;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const shown = [...perDay.entries()].filter(([day]) => day >= first).map(([, d]) => d.tokens);
|
|
59
|
+
const ranked = [...new Set(shown.filter((t) => t > 0))].sort((a, b) => a - b);
|
|
60
|
+
const days = [];
|
|
61
|
+
let busiest = null;
|
|
62
|
+
for (let day = first; day <= last; day++) {
|
|
63
|
+
const d = perDay.get(day) ?? { turns: 0, tokens: 0 };
|
|
64
|
+
const entry = { date: dateOf(day), turns: d.turns, tokens: d.tokens, level: levelFor(d.tokens, ranked) };
|
|
65
|
+
days.push(entry);
|
|
66
|
+
if (d.turns > 0) totals.activeDays += 1;
|
|
67
|
+
if (d.tokens > 0 && (!busiest || d.tokens > busiest.tokens)) busiest = entry;
|
|
68
|
+
}
|
|
69
|
+
const hours = activity.hours.length === 24 ? activity.hours : [];
|
|
70
|
+
const peak = Math.max(0, ...hours);
|
|
71
|
+
return {
|
|
72
|
+
days,
|
|
73
|
+
totals,
|
|
74
|
+
streak: { current: run, longest },
|
|
75
|
+
peakHour: peak > 0 ? hours.indexOf(peak) : null,
|
|
76
|
+
busiest,
|
|
77
|
+
surfaces: [...perSurface.entries()].map(([surface, s]) => ({ surface, ...s })).sort((a, b) => b.tokens - a.tokens || a.surface.localeCompare(b.surface))
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function levelFor(tokens, ranked) {
|
|
81
|
+
if (!(tokens > 0)) return 0;
|
|
82
|
+
if (ranked.length === 1) return 4;
|
|
83
|
+
return 1 + Math.round(3 * ranked.indexOf(tokens) / (ranked.length - 1));
|
|
84
|
+
}
|
|
85
|
+
function formatTokens(n) {
|
|
86
|
+
const units = ["", "k", "M", "B"];
|
|
87
|
+
let value = n;
|
|
88
|
+
let unit = 0;
|
|
89
|
+
while (value >= 999.5 && unit < units.length - 1) {
|
|
90
|
+
value /= 1e3;
|
|
91
|
+
unit += 1;
|
|
92
|
+
}
|
|
93
|
+
const shown = unit === 0 || value >= 10 ? String(Math.round(value)) : value.toFixed(1).replace(/\.0$/, "");
|
|
94
|
+
return `${shown}${units[unit]}`;
|
|
95
|
+
}
|
|
96
|
+
function surfaceLabel(surface) {
|
|
97
|
+
switch (surface) {
|
|
98
|
+
case "web":
|
|
99
|
+
return "portal";
|
|
100
|
+
case "vscode":
|
|
101
|
+
return "editor";
|
|
102
|
+
case "cli":
|
|
103
|
+
return "terminal";
|
|
104
|
+
case "memory":
|
|
105
|
+
return "memory (background)";
|
|
106
|
+
case "api":
|
|
107
|
+
return "API";
|
|
108
|
+
default:
|
|
109
|
+
return surface;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function formatHour(hour) {
|
|
113
|
+
const h = hour % 12 === 0 ? 12 : hour % 12;
|
|
114
|
+
return `${h}${hour < 12 ? "am" : "pm"}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
6
117
|
// vendor/labd/packages/protocol/src/tags.ts
|
|
7
118
|
var TAG = /(^|[\s([])@(?:"([^"\n]+)"|([^\s"]+))/g;
|
|
8
119
|
var TRAILING = /[.,;:!?)\]}'"]+$/;
|
|
@@ -1556,8 +1667,6 @@ async function runTurn(question, opts) {
|
|
|
1556
1667
|
needTools = true;
|
|
1557
1668
|
return "go";
|
|
1558
1669
|
case "done":
|
|
1559
|
-
result.context = event.context;
|
|
1560
|
-
result.credits = event.credits;
|
|
1561
1670
|
ui.done?.({ credits: event.credits, context: event.context });
|
|
1562
1671
|
return "go";
|
|
1563
1672
|
case "error":
|
|
@@ -2001,6 +2110,18 @@ var AgentClient = class {
|
|
|
2001
2110
|
return null;
|
|
2002
2111
|
}
|
|
2003
2112
|
}
|
|
2113
|
+
/** The learner's usage by local hour, for the heatmap under `/usage`. */
|
|
2114
|
+
async activity(offsetMinutes) {
|
|
2115
|
+
try {
|
|
2116
|
+
const res = await this.fetch(`${this.opts.baseUrl}/v1/usage/activity?offset=${offsetMinutes}`, { headers: this.headers() });
|
|
2117
|
+
if (!res.ok) return null;
|
|
2118
|
+
const body2 = await res.json();
|
|
2119
|
+
if (!Array.isArray(body2.days) || !Array.isArray(body2.hours)) return null;
|
|
2120
|
+
return { days: body2.days.filter(isBucket), hours: body2.hours.map((n) => isCount(n) ? n : 0) };
|
|
2121
|
+
} catch {
|
|
2122
|
+
return null;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2004
2125
|
/**
|
|
2005
2126
|
* Tell the server this conversation is over and can be distilled into memory.
|
|
2006
2127
|
*
|
|
@@ -2078,6 +2199,13 @@ var AgentClient = class {
|
|
|
2078
2199
|
}
|
|
2079
2200
|
}
|
|
2080
2201
|
};
|
|
2202
|
+
function isBucket(value) {
|
|
2203
|
+
const b = value;
|
|
2204
|
+
return typeof b?.day === "string" && typeof b.surface === "string" && [b.turns, b.input, b.output].every(isCount);
|
|
2205
|
+
}
|
|
2206
|
+
function isCount(n) {
|
|
2207
|
+
return typeof n === "number" && Number.isFinite(n);
|
|
2208
|
+
}
|
|
2081
2209
|
|
|
2082
2210
|
// packages/tui/src/theme.ts
|
|
2083
2211
|
var ESC = "\x1B";
|
|
@@ -2103,6 +2231,14 @@ var paint = {
|
|
|
2103
2231
|
* Closes the foreground only, so it can sit inside a `band` without ending it.
|
|
2104
2232
|
*/
|
|
2105
2233
|
accent: wrap("38;5;214", "39"),
|
|
2234
|
+
/**
|
|
2235
|
+
* The heatmap's lower steps, walking the same orange down the cube towards
|
|
2236
|
+
* brown, with `accent` as the top one. The heatmap changes glyph with each
|
|
2237
|
+
* step too, so a light terminal where brown reads heavier is still legible.
|
|
2238
|
+
*/
|
|
2239
|
+
heat1: wrap("38;5;94", "39"),
|
|
2240
|
+
heat2: wrap("38;5;130", "39"),
|
|
2241
|
+
heat3: wrap("38;5;172", "39"),
|
|
2106
2242
|
bold: wrap("1", "22"),
|
|
2107
2243
|
dim: wrap("2", "22"),
|
|
2108
2244
|
muted: wrap("90"),
|
|
@@ -2383,8 +2519,7 @@ function statusLine(info2) {
|
|
|
2383
2519
|
if (info2.effort) bits.push(paint.muted(`think ${info2.effort}`));
|
|
2384
2520
|
const mode = info2.mode === "agent" ? paint.red(paint.bold("agent")) : info2.mode === "auto" ? paint.accent("auto") : paint.muted("ask");
|
|
2385
2521
|
bits.push(mode);
|
|
2386
|
-
|
|
2387
|
-
return `${left} ${paint.dim("|")} ${bits.join(paint.dim(" | "))}`;
|
|
2522
|
+
return `${paint.dim(FACE)} ${paint.dim("|")} ${bits.join(paint.dim(" | "))}`;
|
|
2388
2523
|
}
|
|
2389
2524
|
function spinnerFrame(tick) {
|
|
2390
2525
|
const dots = ".".repeat(tick % 3 + 1).padEnd(3);
|
|
@@ -3391,7 +3526,6 @@ function wrap2(text, width, first, rest) {
|
|
|
3391
3526
|
}
|
|
3392
3527
|
|
|
3393
3528
|
// packages/tui/src/transcript.ts
|
|
3394
|
-
var MAX_PROSE_WIDTH = 100;
|
|
3395
3529
|
var LIVE_LINES = 8;
|
|
3396
3530
|
var Transcript = class {
|
|
3397
3531
|
entries = [];
|
|
@@ -3493,7 +3627,7 @@ function splitStreaming(text) {
|
|
|
3493
3627
|
return { complete: complete2.join("\n"), tail };
|
|
3494
3628
|
}
|
|
3495
3629
|
function proseWidth(width) {
|
|
3496
|
-
return Math.max(20,
|
|
3630
|
+
return Math.max(20, width - 2);
|
|
3497
3631
|
}
|
|
3498
3632
|
function renderBlock(block, width) {
|
|
3499
3633
|
const inner = proseWidth(width);
|
|
@@ -3502,7 +3636,7 @@ function renderBlock(block, width) {
|
|
|
3502
3636
|
return block.text.split("\n").flatMap(
|
|
3503
3637
|
(line, i) => wrapPlain(line, inner - 2).map((piece, j) => {
|
|
3504
3638
|
const text = i === 0 && j === 0 ? `${paint.accent(">")} ${piece}` : ` ${piece}`;
|
|
3505
|
-
return band(text, visibleWidth(text),
|
|
3639
|
+
return band(text, visibleWidth(text), width);
|
|
3506
3640
|
})
|
|
3507
3641
|
);
|
|
3508
3642
|
case "assistant":
|
|
@@ -3612,6 +3746,78 @@ var Viewport = class {
|
|
|
3612
3746
|
}
|
|
3613
3747
|
};
|
|
3614
3748
|
|
|
3749
|
+
// packages/tui/src/heatmap.ts
|
|
3750
|
+
var INDENT = " ";
|
|
3751
|
+
var DAY_LABEL = ["Mon", " ", "Wed", " ", "Fri", " ", "Sun"];
|
|
3752
|
+
var GUTTER = INDENT.length + 4;
|
|
3753
|
+
var MIN_WEEKS = 4;
|
|
3754
|
+
var GLYPH = { 0: "\xB7", 1: "\u2591", 2: "\u2592", 3: "\u2593", 4: "\u2588" };
|
|
3755
|
+
var SHADE = {
|
|
3756
|
+
0: paint.dim,
|
|
3757
|
+
1: paint.heat1,
|
|
3758
|
+
2: paint.heat2,
|
|
3759
|
+
3: paint.heat3,
|
|
3760
|
+
4: paint.accent
|
|
3761
|
+
};
|
|
3762
|
+
function heatmapWeeks(width) {
|
|
3763
|
+
return Math.max(MIN_WEEKS, Math.min(ACTIVITY_WEEKS, Math.floor((width - GUTTER) / 2)));
|
|
3764
|
+
}
|
|
3765
|
+
function heatmapLines(summary, width) {
|
|
3766
|
+
const { days, totals, streak } = summary;
|
|
3767
|
+
const columns = Math.ceil(days.length / 7);
|
|
3768
|
+
const lines = [`${INDENT}${paint.muted(`last ${columns} weeks`)}`, `${" ".repeat(GUTTER)}${monthRow(days, columns)}`];
|
|
3769
|
+
for (let row2 = 0; row2 < 7; row2++) {
|
|
3770
|
+
let cells = "";
|
|
3771
|
+
for (let column = 0; column < columns; column++) {
|
|
3772
|
+
const day = days[column * 7 + row2];
|
|
3773
|
+
cells += day ? `${SHADE[day.level](GLYPH[day.level])} ` : " ";
|
|
3774
|
+
}
|
|
3775
|
+
lines.push(`${INDENT}${paint.dim(DAY_LABEL[row2])} ${cells.trimEnd()}`);
|
|
3776
|
+
}
|
|
3777
|
+
const legend = [0, 1, 2, 3, 4].map((l) => SHADE[l](GLYPH[l])).join(" ");
|
|
3778
|
+
lines.push(`${" ".repeat(GUTTER)}${paint.dim("less")} ${legend} ${paint.dim("more")}`, "");
|
|
3779
|
+
const row = (label2, value) => `${INDENT}${paint.muted(label2.padEnd(10))}${value}`;
|
|
3780
|
+
lines.push(
|
|
3781
|
+
row("tokens", `${paint.bold(formatTokens(totals.input + totals.output))} ${paint.dim(`${formatTokens(totals.input)} in \xB7 ${formatTokens(totals.output)} out`)}`),
|
|
3782
|
+
row("requests", `${paint.bold(String(totals.turns))} ${paint.dim(`on ${plural(totals.activeDays, "day")}`)}`),
|
|
3783
|
+
row("streak", `${paint.bold(plural(streak.current, "day"))} ${paint.dim(`longest ${plural(streak.longest, "day")}`)}`)
|
|
3784
|
+
);
|
|
3785
|
+
if (summary.busiest) {
|
|
3786
|
+
lines.push(row("busiest", `${paint.bold(dayName(summary.busiest.date))} ${paint.dim(`${formatTokens(summary.busiest.tokens)} tokens`)}`));
|
|
3787
|
+
}
|
|
3788
|
+
if (summary.peakHour !== null) lines.push(row("peak hour", paint.bold(formatHour(summary.peakHour))));
|
|
3789
|
+
const where = summary.surfaces.map((s) => `${surfaceLabel(s.surface)} ${paint.bold(formatTokens(s.tokens))}`);
|
|
3790
|
+
const joined = row("where", where.join(paint.dim(" \xB7 ")));
|
|
3791
|
+
if (!where.length) return lines;
|
|
3792
|
+
if (visibleWidth(joined) <= width) lines.push(joined);
|
|
3793
|
+
else where.forEach((w, i) => lines.push(row(i === 0 ? "where" : "", w)));
|
|
3794
|
+
return lines;
|
|
3795
|
+
}
|
|
3796
|
+
function monthRow(days, columns) {
|
|
3797
|
+
const starts = [];
|
|
3798
|
+
for (let column = 0; column < columns; column++) {
|
|
3799
|
+
const week = days.slice(column * 7, column * 7 + 7);
|
|
3800
|
+
const first = column === 0 ? week[0] : week.find((d) => d.date.endsWith("-01"));
|
|
3801
|
+
if (first && column + 1 < columns) starts.push({ column, date: first.date });
|
|
3802
|
+
}
|
|
3803
|
+
if (starts.length > 1 && starts[1].column < 2) starts.shift();
|
|
3804
|
+
let out = "";
|
|
3805
|
+
for (const { column, date } of starts) {
|
|
3806
|
+
out = out.padEnd(column * 2) + localDay(date).toLocaleDateString("en-GB", { month: "short" }).slice(0, 3);
|
|
3807
|
+
}
|
|
3808
|
+
return paint.dim(out);
|
|
3809
|
+
}
|
|
3810
|
+
function localDay(date) {
|
|
3811
|
+
const [y, m, d] = date.split("-").map(Number);
|
|
3812
|
+
return new Date(y, m - 1, d);
|
|
3813
|
+
}
|
|
3814
|
+
function dayName(date) {
|
|
3815
|
+
return localDay(date).toLocaleDateString("en-GB", { day: "numeric", month: "short" });
|
|
3816
|
+
}
|
|
3817
|
+
function plural(n, word) {
|
|
3818
|
+
return `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
3819
|
+
}
|
|
3820
|
+
|
|
3615
3821
|
// packages/tui/src/face.ts
|
|
3616
3822
|
var FACE_ART = [
|
|
3617
3823
|
" \u250F\u2501 \u2501\u2513 ",
|
|
@@ -4131,7 +4337,7 @@ var BUILTIN_COMMANDS = [
|
|
|
4131
4337
|
{ name: "session", what: "where this one is stored" },
|
|
4132
4338
|
{ name: "rename", args: "<name>", what: "name this session, so /sessions and --resume show it" },
|
|
4133
4339
|
{ name: "new", what: "start a fresh session; this one stays saved" },
|
|
4134
|
-
{ name: "usage", what: "what's left of this month's allowance" },
|
|
4340
|
+
{ name: "usage", what: "what's left of this month's allowance, and your activity" },
|
|
4135
4341
|
{ name: "trust", what: "let this project load its own extensions" },
|
|
4136
4342
|
{ name: "logout", what: "sign this machine out and leave" },
|
|
4137
4343
|
{ name: "reload", what: "reload extensions and the file list" },
|
|
@@ -4441,12 +4647,23 @@ async function handleCommand(input, ctx) {
|
|
|
4441
4647
|
return { effort: args };
|
|
4442
4648
|
}
|
|
4443
4649
|
case "usage": {
|
|
4444
|
-
const credits = await
|
|
4650
|
+
const [credits, activity] = await Promise.all([
|
|
4651
|
+
runtime.client.credits(),
|
|
4652
|
+
runtime.client.activity(utcOffsetMinutes())
|
|
4653
|
+
]);
|
|
4445
4654
|
if (!credits) {
|
|
4446
4655
|
print(` ${paint.muted("Couldn't check that just now.")}`);
|
|
4447
4656
|
} else {
|
|
4448
4657
|
print(` ${paint.bold(`${credits.percentLeft}%`)} ${paint.muted("of this month left")}`);
|
|
4449
4658
|
}
|
|
4659
|
+
if (activity && !activity.days.length) {
|
|
4660
|
+
print(` ${paint.muted("No activity yet. Ask labd something and it shows up here.")}`);
|
|
4661
|
+
} else if (activity) {
|
|
4662
|
+
print("");
|
|
4663
|
+
print(heatmapLines(summariseActivity(activity, heatmapWeeks(ctx.width)), ctx.width).join("\n"));
|
|
4664
|
+
} else if (credits) {
|
|
4665
|
+
print(` ${paint.muted("Couldn't read your activity just now.")}`);
|
|
4666
|
+
}
|
|
4450
4667
|
return {};
|
|
4451
4668
|
}
|
|
4452
4669
|
case "tree": {
|
|
@@ -4475,9 +4692,12 @@ async function handleCommand(input, ctx) {
|
|
|
4475
4692
|
print(` ${paint.yellow("!")} ${paint.muted(`no point here starts with "${args}"`)}`);
|
|
4476
4693
|
return {};
|
|
4477
4694
|
}
|
|
4695
|
+
const moved = match.id !== runtime.session.headId;
|
|
4478
4696
|
runtime.session.moveTo(match.id);
|
|
4479
|
-
print(
|
|
4480
|
-
|
|
4697
|
+
print(
|
|
4698
|
+
` ${paint.muted(moved ? `continuing from ${match.id.slice(0, 8)}. The other branch is still in the file.` : `already at ${match.id.slice(0, 8)}.`)}`
|
|
4699
|
+
);
|
|
4700
|
+
return { moved };
|
|
4481
4701
|
}
|
|
4482
4702
|
case "sessions": {
|
|
4483
4703
|
const bucket = dirname3(runtime.session.file);
|
|
@@ -4793,6 +5013,7 @@ async function runInteractive(runtime) {
|
|
|
4793
5013
|
mode: state.mode,
|
|
4794
5014
|
effort: state.effort,
|
|
4795
5015
|
asked: answered > 0,
|
|
5016
|
+
width: process.stdout.columns ?? 80,
|
|
4796
5017
|
print: (text) => renderer.print(text)
|
|
4797
5018
|
});
|
|
4798
5019
|
if (outcome.farewell) process.stderr.write(`${outcome.farewell}
|
|
@@ -4800,6 +5021,7 @@ async function runInteractive(runtime) {
|
|
|
4800
5021
|
if (outcome.exit) break;
|
|
4801
5022
|
if (outcome.mode) state.mode = outcome.mode;
|
|
4802
5023
|
if (outcome.effort !== void 0) state.effort = outcome.effort;
|
|
5024
|
+
if (outcome.moved) state.context = null;
|
|
4803
5025
|
continue;
|
|
4804
5026
|
}
|
|
4805
5027
|
const tags = taggedPaths(input);
|
|
@@ -4914,6 +5136,7 @@ async function runInteractive(runtime) {
|
|
|
4914
5136
|
if (state.context && state.context.percentUsed >= COMPACT_AT) {
|
|
4915
5137
|
startSpinner("summarising, to make room");
|
|
4916
5138
|
const ok = await compact({ session: runtime.session, client: runtime.client, root: runtime.root });
|
|
5139
|
+
if (ok) state.context = null;
|
|
4917
5140
|
stopSpinner();
|
|
4918
5141
|
renderer.print(paint.dim(ok ? " summarised the conversation so far." : " (could not summarise; carrying on)"));
|
|
4919
5142
|
}
|
|
@@ -5512,6 +5735,7 @@ async function runScreen(runtime, opts) {
|
|
|
5512
5735
|
mode: state.mode,
|
|
5513
5736
|
effort: state.effort,
|
|
5514
5737
|
asked: state.asked,
|
|
5738
|
+
width: layout({ rows: screen.rows, columns: screen.columns, editorLines: editor.lineCount, sidebar: state.sidebar }).transcript.width,
|
|
5515
5739
|
print: (text) => note(text)
|
|
5516
5740
|
});
|
|
5517
5741
|
if (outcome.farewell) state.farewell = outcome.farewell;
|
|
@@ -5521,6 +5745,7 @@ async function runScreen(runtime, opts) {
|
|
|
5521
5745
|
state.heldMode = null;
|
|
5522
5746
|
}
|
|
5523
5747
|
if (outcome.effort !== void 0) state.effort = outcome.effort;
|
|
5748
|
+
if (outcome.moved) state.context = null;
|
|
5524
5749
|
schedule();
|
|
5525
5750
|
}
|
|
5526
5751
|
function helpLines() {
|
|
@@ -5593,6 +5818,7 @@ async function runScreen(runtime, opts) {
|
|
|
5593
5818
|
if (state.asked) await closeConversation(runtime);
|
|
5594
5819
|
runtime.session = Session.open(file);
|
|
5595
5820
|
state.asked = false;
|
|
5821
|
+
state.context = null;
|
|
5596
5822
|
transcript.clear();
|
|
5597
5823
|
state.toolBlocks.clear();
|
|
5598
5824
|
state.answer = null;
|
|
@@ -5603,6 +5829,7 @@ async function runScreen(runtime, opts) {
|
|
|
5603
5829
|
if (state.asked) await closeConversation(runtime);
|
|
5604
5830
|
runtime.session = Session.create(bucketFor(runtime.stateDir, runtime.root));
|
|
5605
5831
|
state.asked = false;
|
|
5832
|
+
state.context = null;
|
|
5606
5833
|
transcript.clear();
|
|
5607
5834
|
state.toolBlocks.clear();
|
|
5608
5835
|
state.answer = null;
|
|
@@ -5729,8 +5956,10 @@ async function runScreen(runtime, opts) {
|
|
|
5729
5956
|
if (!abort.signal.aborted && state.context && state.context.percentUsed >= COMPACT_AT) {
|
|
5730
5957
|
setBusy("summarising, to make room");
|
|
5731
5958
|
const ok = await compact({ session: runtime.session, client: runtime.client, root: runtime.root });
|
|
5732
|
-
if (ok)
|
|
5733
|
-
|
|
5959
|
+
if (ok) {
|
|
5960
|
+
state.context = null;
|
|
5961
|
+
transcript.add({ kind: "compaction" });
|
|
5962
|
+
} else note(paint.dim(" (could not summarise; carrying on)"));
|
|
5734
5963
|
}
|
|
5735
5964
|
} catch (err) {
|
|
5736
5965
|
transcript.add({ kind: "error", text: err instanceof Error ? err.message : String(err) });
|
|
@@ -6154,7 +6383,7 @@ async function runRpc(runtime) {
|
|
|
6154
6383
|
}
|
|
6155
6384
|
|
|
6156
6385
|
// packages/cli/src/index.ts
|
|
6157
|
-
var VERSION = true ? "0.
|
|
6386
|
+
var VERSION = true ? "0.7.0" : "0.0.0-dev";
|
|
6158
6387
|
async function main(argv) {
|
|
6159
6388
|
const args = parse(argv);
|
|
6160
6389
|
if (args.color !== void 0) setColor(args.color);
|