opencode-courier 0.13.2 → 0.13.4

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 CHANGED
@@ -78,7 +78,7 @@ name, without a version: OpenCode offers updates only for an entry without an ex
78
78
  <!-- compat-table:start rows=3: generated by script/compat-table.ts from the release tags -->
79
79
  | opencode-courier | OpenCode V2 (`opencode` and `@opencode/plugin`) |
80
80
  |---|---|
81
- | 0.13.2 | 2.2.2 |
81
+ | 0.13.2, 0.13.3, 0.13.4 | 2.2.2 |
82
82
  | 0.13.1 | 2.2.1 |
83
83
  | 0.13.0 | 2.2.0 |
84
84
  <!-- compat-table:end -->
@@ -152,8 +152,9 @@ More: [in the terminal](docs/reference.md#in-the-terminal).
152
152
 
153
153
  ## Contributing
154
154
 
155
- Questions and bugs: [issues](https://github.com/ivopogace/opencode-courier/issues). Pull requests
156
- are welcome; start with [development.md](docs/maintainers/development.md).
155
+ Questions go to [Discussions](https://github.com/ivopogace/opencode-courier/discussions), bugs to
156
+ [issues](https://github.com/ivopogace/opencode-courier/issues). Pull requests are welcome; start with
157
+ [CONTRIBUTING.md](CONTRIBUTING.md).
157
158
 
158
159
  ## License
159
160
 
@@ -15,6 +15,8 @@ export type Cell = {
15
15
  export declare const MASCOT_EVERY = 5;
16
16
  /** He blinks on every this-many-th of his frames where his eyes are open. */
17
17
  export declare const BLINK_EVERY = 11;
18
+ /** Running, he is still and awake for this many of his frames, about 8 s, then digs for one cycle of six. */
19
+ export declare const DIG_EVERY = 18;
18
20
  /**
19
21
  * The 8×4 glyph's frames by state, pixel rows top to bottom; a state with several cycles through them, one per mascot frame.
20
22
  * No muted pixel touches the mound, here or in the 16×16, as `text.muted` is close to `background.raised.max`.
@@ -2,6 +2,8 @@
2
2
  export const MASCOT_EVERY = 5;
3
3
  /** He blinks on every this-many-th of his frames where his eyes are open. */
4
4
  export const BLINK_EVERY = 11;
5
+ /** Running, he is still and awake for this many of his frames, about 8 s, then digs for one cycle of six. */
6
+ export const DIG_EVERY = 18;
5
7
  /**
6
8
  * The 8×4 glyph's frames by state, pixel rows top to bottom; a state with several cycles through them, one per mascot frame.
7
9
  * No muted pixel touches the mound, here or in the 16×16, as `text.muted` is close to `background.raised.max`.
@@ -13,8 +15,8 @@ export const GLYPH = {
13
15
  [".g....g.", "...bb...", "ggbbbbgg", "gggggggg"],
14
16
  ],
15
17
  running: [
16
- ["..g..g..", "...bb...", ".gbbbbg.", "gggggggg"],
17
- [".g....g.", "........", ".gbbbbg.", "gggggggg"],
18
+ ...Array.from({ length: DIG_EVERY }, () => ["..bbbb..", ".bkbbkb.", "gbbaabbg", "gggggggg"]),
19
+ ...["m.bbbb.m", ".mbbbbm.", "..bbbb..", "m.bbbb.m", ".mbbbbm.", "..bbbb.."].map((top) => [top, ".bkbbkb.", "gbbaabbg", "gggggggg"]),
18
20
  ],
19
21
  waiting: [
20
22
  [".bbbbbbw", ".bkbbkbw", ".bbaabbm", "ggggggg."],
@@ -32,7 +34,7 @@ export const GLYPH = {
32
34
  gone: [["........", ".mmmmmm.", ".mkmmkm.", "mmmmmmmm"]],
33
35
  };
34
36
  /** The states in which his eyes are open, so he blinks. */
35
- const OPEN_EYES = new Set(["waiting", "report"]);
37
+ const OPEN_EYES = new Set(["waiting", "report", "running"]);
36
38
  /** The 8×4 glyph's pixels for `state` at mascot frame `frame`, its first frame with none: animations off. */
37
39
  export function glyph(state, frame) {
38
40
  const frames = GLYPH[state];
@@ -114,9 +116,27 @@ export function paint(pixels, spots) {
114
116
  }
115
117
  /** A column of `length` pixels of `pixel` from row `row`. */
116
118
  const post = (row, column, length, pixel) => Array.from({ length }, (_, at) => [row + at, column, pixel]);
117
- /** The head's top row at `rise`, where running's snout pokes up. */
119
+ /** The head's top row at `rise`. */
118
120
  const headTop = (rise) => Math.round(10 - 8 * rise);
119
- const running = (rise, shift, dirt) => paint(digby(rise, { shift }), [[headTop(rise), 7, "aa"], ...dirt]);
121
+ /** Up and awake at `rise`, his eyes `shift` columns over (0 straight ahead) when `open`. */
122
+ const awake = (rise, shift) => (open) => {
123
+ const row = headTop(rise) + 3;
124
+ return paint(digby(rise, { eyes: "open" }), [[row, 6, "b"], [row, 9, "b"], ...(open ? [[row, 6 + shift, "k"], [row, 9 + shift, "k"]] : [])]);
125
+ };
126
+ /** Where a clod flies on each side, frame by frame: out of the hole, up, over and down, a row clear of the mound's rim. */
127
+ const CLOD_LEFT = [[8, 3], [7, 2], [6, 1], [5, 0], [7, 0], [9, 0]];
128
+ const CLOD_RIGHT = [[8, 12], [7, 13], [6, 14], [5, 15], [7, 15], [9, 15]];
129
+ const CLODS = [[CLOD_LEFT, 0], [CLOD_LEFT, 3], [CLOD_RIGHT, 1], [CLOD_RIGHT, 4]];
130
+ /** Digging at frame `at`: up with his eyes open, the mound still, four clods on their arcs, one always in the air. */
131
+ const digging = (at) => (open) => paint(digby(0.6, { eyes: open ? "open" : "none" }), CLODS.map(([path, phase]) => {
132
+ const [row, column] = path[(at + phase) % path.length];
133
+ return [row, column, "m"];
134
+ }));
135
+ /** Running: still and awake, a glance left then right over twelve frames, then one dig cycle; the mound never moves. */
136
+ const running = [
137
+ ...Array.from({ length: DIG_EVERY }, (_, at) => [0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 1, 1][at % 12]).map((shift) => awake(0.6, shift)),
138
+ ...Array.from({ length: CLOD_LEFT.length }, (_, at) => digging(at)),
139
+ ];
120
140
  /** A child's head peeking out of a side mound at columns `column`–`column + 2`, `up` or half sunk. */
121
141
  const peek = (column, up) => [
122
142
  ...(up ? [[8, column, ".b."], [9, column, "bkb"]] : [[9, column, ".b."]]),
@@ -143,10 +163,7 @@ export const ART = {
143
163
  () => spawn(true, [[3, 1, "m"], [5, 3, "m"], [2, 14, "m"], [5, 12, "m"]]),
144
164
  () => spawn(false, [[1, 0, "m"], [4, 2, "m"], [3, 15, "m"], [6, 13, "m"]]),
145
165
  ],
146
- running: [
147
- () => running(0.22, 0, [[5, 2, "m"], [7, 1, "m"], [4, 13, "m"], [6, 14, "m"]]),
148
- () => running(0.12, 1, [[3, 1, "m"], [6, 3, "m"], [5, 12, "m"], [3, 15, "m"]]),
149
- ],
166
+ running,
150
167
  waiting: [waiting(true), waiting(false)],
151
168
  stalled: [stalled("e.e.e"), stalled("e"), stalled("e.e")],
152
169
  report: [report(1, [".s.", "sss", ".s."]), report(1.25, ["s.s", ".s.", "s.s"]), report(1.1, [".s.", "sss", ".s."])],
@@ -57,10 +57,14 @@ export declare function createBarFill(motion: Motion, counts: Accessor<{
57
57
  }>): () => number;
58
58
  /** True for `FLASH_MS` after a read of the tree finds a session the one before it did not have; not on the first read. */
59
59
  export declare function createSpawns(motion: Motion, rows: Accessor<ReadonlyArray<Row> | undefined>): () => boolean;
60
- /** Digby's state for the tree's rows, by `summaryLine`'s priority, unless a report or a spawn just arrived. */
61
- export declare function mascotState(rows: ReadonlyArray<Row>, { reported, spawned }?: {
62
- reported?: boolean | undefined;
63
- spawned?: boolean | undefined;
60
+ /**
61
+ * Digby's state for the tree's rows and its `top`, by `summaryLine`'s priority, unless a report or a spawn just arrived;
62
+ * gone when every row under the top is.
63
+ */
64
+ export declare function mascotState(rows: ReadonlyArray<Row>, { top, reported, spawned }?: {
65
+ top?: Row;
66
+ reported?: boolean;
67
+ spawned?: boolean;
64
68
  }): MascotState;
65
69
  /** What the tree's sessions do, as the header's second line says it: "1 waiting on you · 2 running"; empty with none live. */
66
70
  export declare function countsLine(rows: ReadonlyArray<Row>): string;
package/dist/tui.js CHANGED
@@ -1284,6 +1284,7 @@ import { batch, createEffect, createMemo, createResource, createRoot, createSign
1284
1284
  // src/tree/mascot.ts
1285
1285
  var MASCOT_EVERY = 5;
1286
1286
  var BLINK_EVERY = 11;
1287
+ var DIG_EVERY = 18;
1287
1288
  var GLYPH = {
1288
1289
  idle: [["........", "........", "..gggg..", "gggggggg"]],
1289
1290
  spawn: [
@@ -1291,8 +1292,8 @@ var GLYPH = {
1291
1292
  [".g....g.", "...bb...", "ggbbbbgg", "gggggggg"]
1292
1293
  ],
1293
1294
  running: [
1294
- ["..g..g..", "...bb...", ".gbbbbg.", "gggggggg"],
1295
- [".g....g.", "........", ".gbbbbg.", "gggggggg"]
1295
+ ...Array.from({ length: DIG_EVERY }, () => ["..bbbb..", ".bkbbkb.", "gbbaabbg", "gggggggg"]),
1296
+ ...["m.bbbb.m", ".mbbbbm.", "..bbbb..", "m.bbbb.m", ".mbbbbm.", "..bbbb.."].map((top) => [top, ".bkbbkb.", "gbbaabbg", "gggggggg"])
1296
1297
  ],
1297
1298
  waiting: [
1298
1299
  [".bbbbbbw", ".bkbbkbw", ".bbaabbm", "ggggggg."],
@@ -1309,7 +1310,7 @@ var GLYPH = {
1309
1310
  ],
1310
1311
  gone: [["........", ".mmmmmm.", ".mkmmkm.", "mmmmmmmm"]]
1311
1312
  };
1312
- var OPEN_EYES = new Set(["waiting", "report"]);
1313
+ var OPEN_EYES = new Set(["waiting", "report", "running"]);
1313
1314
  function glyph(state, frame) {
1314
1315
  const frames = GLYPH[state];
1315
1316
  const pixels = frames[(frame ?? 0) % frames.length];
@@ -1381,7 +1382,21 @@ function paint(pixels, spots) {
1381
1382
  }
1382
1383
  var post = (row, column, length, pixel) => Array.from({ length }, (_, at) => [row + at, column, pixel]);
1383
1384
  var headTop = (rise) => Math.round(10 - 8 * rise);
1384
- var running = (rise, shift, dirt) => paint(digby(rise, { shift }), [[headTop(rise), 7, "aa"], ...dirt]);
1385
+ var awake = (rise, shift) => (open) => {
1386
+ const row = headTop(rise) + 3;
1387
+ return paint(digby(rise, { eyes: "open" }), [[row, 6, "b"], [row, 9, "b"], ...open ? [[row, 6 + shift, "k"], [row, 9 + shift, "k"]] : []]);
1388
+ };
1389
+ var CLOD_LEFT = [[8, 3], [7, 2], [6, 1], [5, 0], [7, 0], [9, 0]];
1390
+ var CLOD_RIGHT = [[8, 12], [7, 13], [6, 14], [5, 15], [7, 15], [9, 15]];
1391
+ var CLODS = [[CLOD_LEFT, 0], [CLOD_LEFT, 3], [CLOD_RIGHT, 1], [CLOD_RIGHT, 4]];
1392
+ var digging = (at) => (open) => paint(digby(0.6, { eyes: open ? "open" : "none" }), CLODS.map(([path, phase]) => {
1393
+ const [row, column] = path[(at + phase) % path.length];
1394
+ return [row, column, "m"];
1395
+ }));
1396
+ var running = [
1397
+ ...Array.from({ length: DIG_EVERY }, (_, at) => [0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 1, 1][at % 12]).map((shift) => awake(0.6, shift)),
1398
+ ...Array.from({ length: CLOD_LEFT.length }, (_, at) => digging(at))
1399
+ ];
1385
1400
  var peek = (column, up) => [
1386
1401
  ...up ? [[8, column, ".b."], [9, column, "bkb"]] : [[9, column, ".b."]],
1387
1402
  [10, column, "gbg"],
@@ -1403,10 +1418,7 @@ var ART = {
1403
1418
  () => spawn(true, [[3, 1, "m"], [5, 3, "m"], [2, 14, "m"], [5, 12, "m"]]),
1404
1419
  () => spawn(false, [[1, 0, "m"], [4, 2, "m"], [3, 15, "m"], [6, 13, "m"]])
1405
1420
  ],
1406
- running: [
1407
- () => running(0.22, 0, [[5, 2, "m"], [7, 1, "m"], [4, 13, "m"], [6, 14, "m"]]),
1408
- () => running(0.12, 1, [[3, 1, "m"], [6, 3, "m"], [5, 12, "m"], [3, 15, "m"]])
1409
- ],
1421
+ running,
1410
1422
  waiting: [waiting(true), waiting(false)],
1411
1423
  stalled: [stalled("e.e.e"), stalled("e"), stalled("e.e")],
1412
1424
  report: [report(1, [".s.", "sss", ".s."]), report(1.25, ["s.s", ".s.", "s.s"]), report(1.1, [".s.", "sss", ".s."])],
@@ -1655,6 +1667,7 @@ function createSpawns(motion, rows) {
1655
1667
  };
1656
1668
  }
1657
1669
  function mascotState(rows, {
1670
+ top,
1658
1671
  reported = false,
1659
1672
  spawned = false
1660
1673
  } = {}) {
@@ -1662,11 +1675,12 @@ function mascotState(rows, {
1662
1675
  return "report";
1663
1676
  if (spawned)
1664
1677
  return "spawn";
1665
- if (rows.some((row) => row.state === "waiting"))
1678
+ const live = top ? [top, ...rows] : rows;
1679
+ if (live.some((row) => row.state === "waiting"))
1666
1680
  return "waiting";
1667
- if (rows.some((row) => row.state === "stalled"))
1681
+ if (live.some((row) => row.state === "stalled"))
1668
1682
  return "stalled";
1669
- if (rows.some((row) => row.state === "running"))
1683
+ if (live.some((row) => row.state === "running"))
1670
1684
  return "running";
1671
1685
  return rows.length && rows.every((row) => row.state === "gone") ? "gone" : "idle";
1672
1686
  }
@@ -2288,7 +2302,7 @@ function TreePanel(props) {
2288
2302
  }));
2289
2303
  const root = () => parts(rows(), view.root);
2290
2304
  const motion = createMotion(props.animations);
2291
- motion.animates(() => rows().some((row) => row.state === "running"));
2305
+ motion.animates(() => listed().some((row) => row.state === "running"));
2292
2306
  const flashes = createFlashes(motion, rows);
2293
2307
  const filled = createBarFill(motion, root);
2294
2308
  const frame = () => motion.enabled ? motion.frame() : undefined;
@@ -2308,6 +2322,7 @@ function TreePanel(props) {
2308
2322
  const belowShown = () => rows().length > 0 && listHeight() - treeLines() >= BELOW_ROWS;
2309
2323
  const headerGlyph = () => glyphShown() && !artShown() && !belowShown();
2310
2324
  const mascot = createMemo(() => mascotState(rows(), {
2325
+ top: top(),
2311
2326
  reported: flashes.reported(),
2312
2327
  spawned: spawned()
2313
2328
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-courier",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "Multi-session orchestration for OpenCode V2: spawn child sessions, be woken by them. No polling.",
5
5
  "license": "MIT",
6
6
  "author": "Ivo Pogace <71701666+ivopogace@users.noreply.github.com>",