opencode-courier 0.6.0 → 0.7.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/README.md +31 -26
- package/dist/index.js +3 -2
- package/dist/person/events.d.ts +2 -2
- package/dist/person/events.js +4 -3
- package/dist/skill.js +11 -6
- package/dist/tree/events.js +26 -1
- package/dist/tree/index.d.ts +1 -0
- package/dist/tree/index.js +2 -1
- package/dist/tree/panel.d.ts +1 -1
- package/dist/tree/panel.js +16 -7
- package/dist/tree/ports.d.ts +29 -0
- package/dist/tree/rpc-handlers.d.ts +14 -5
- package/dist/tree/rpc.d.ts +39 -10
- package/dist/tree/rpc.js +11 -2
- package/dist/tree/stop.js +2 -0
- package/dist/tree/store.d.ts +4 -1
- package/dist/tree/store.js +51 -0
- package/dist/tree/summary.d.ts +2 -2
- package/dist/tree/summary.js +14 -5
- package/dist/tree/text.js +1 -1
- package/dist/tree/tui.d.ts +6 -2
- package/dist/tree/wake.d.ts +69 -0
- package/dist/tree/wake.js +122 -0
- package/dist/tui.js +78 -51
- package/package.json +4 -4
package/dist/tui.js
CHANGED
|
@@ -808,6 +808,7 @@ var Summary = Schema2.Struct({
|
|
|
808
808
|
running: Count2,
|
|
809
809
|
waiting: Count2,
|
|
810
810
|
idle: Count2,
|
|
811
|
+
stalled: Schema2.optionalKey(Count2),
|
|
811
812
|
groups: Schema2.Array(Group)
|
|
812
813
|
});
|
|
813
814
|
var Wait = Schema2.Union([
|
|
@@ -820,7 +821,8 @@ var Row = Schema2.Struct({
|
|
|
820
821
|
parentID: Schema2.String,
|
|
821
822
|
title: Schema2.String,
|
|
822
823
|
depth: Count2,
|
|
823
|
-
state: Schema2.Literals(["running", "waiting", "idle", "gone"]),
|
|
824
|
+
state: Schema2.Literals(["running", "waiting", "idle", "stalled", "gone"]),
|
|
825
|
+
stalled: Schema2.optionalKey(Schema2.Number),
|
|
824
826
|
outcome: Schema2.optionalKey(Schema2.Literals(["succeeded", "failed", "interrupted"])),
|
|
825
827
|
stopped: Schema2.optionalKey(Schema2.Boolean),
|
|
826
828
|
report: Schema2.optionalKey(Schema2.Struct({ state: Schema2.Literals(["owed", "reported", "ended"]), status: Schema2.optionalKey(Schema2.String), progressed: Schema2.Boolean })),
|
|
@@ -834,7 +836,8 @@ var Row = Schema2.Struct({
|
|
|
834
836
|
});
|
|
835
837
|
var Tree = Schema2.Struct({
|
|
836
838
|
rows: Schema2.Array(Row),
|
|
837
|
-
truncated: Schema2.optionalKey(Count2)
|
|
839
|
+
truncated: Schema2.optionalKey(Count2),
|
|
840
|
+
stalled: Schema2.optionalKey(Schema2.Number)
|
|
838
841
|
});
|
|
839
842
|
var Stopped = Schema2.Struct({
|
|
840
843
|
stopped: Schema2.Array(Schema2.Struct({ sessionID: Schema2.String, title: Schema2.String, outcome: Schema2.String })),
|
|
@@ -878,7 +881,7 @@ var PANEL = "courier-tree";
|
|
|
878
881
|
var TICK_MS = 1000;
|
|
879
882
|
function summaryLine(summary, maxWidth = Infinity) {
|
|
880
883
|
const groups = summary.groups.map((group) => `group ${group.name} ${group.reported}/${group.members}`);
|
|
881
|
-
const parts = [summary.waiting ? `${summary.waiting} waiting on you` : "", summary.running ? `${summary.running} running` : "", ...groups, summary.idle ? `${summary.idle} idle` : ""].filter(Boolean);
|
|
884
|
+
const parts = [summary.waiting ? `${summary.waiting} waiting on you` : "", summary.stalled ? `${summary.stalled} stalled` : "", summary.running ? `${summary.running} running` : "", ...groups, summary.idle ? `${summary.idle} idle` : ""].filter(Boolean);
|
|
882
885
|
if (!parts.length)
|
|
883
886
|
return "";
|
|
884
887
|
const line = (kept) => {
|
|
@@ -924,6 +927,8 @@ function statusLine(row) {
|
|
|
924
927
|
function stateWord(row) {
|
|
925
928
|
if (row.state === "waiting")
|
|
926
929
|
return "waiting on you";
|
|
930
|
+
if (row.state === "stalled")
|
|
931
|
+
return "stalled";
|
|
927
932
|
if (row.state === "idle" && row.stopped)
|
|
928
933
|
return "stopped";
|
|
929
934
|
if (row.state === "idle" && (row.outcome === "failed" || row.outcome === "interrupted"))
|
|
@@ -943,10 +948,15 @@ var counted = (count, noun) => `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
|
943
948
|
function activityLine(row, now) {
|
|
944
949
|
return [`ran ${duration((row.idle ?? now) - row.created)}`, row.tool ? `last ${row.tool.name} ${duration(now - row.tool.at)} ago` : "no tool call yet", row.cost !== undefined ? `$${row.cost.toFixed(2)}` : ""].filter(Boolean).join(" \xB7 ");
|
|
945
950
|
}
|
|
951
|
+
function stalledLine(since, now) {
|
|
952
|
+
return `a message waits in its inbox since ${duration(now - since)}, woken again in vain`;
|
|
953
|
+
}
|
|
946
954
|
function detailLines(row, rows, now) {
|
|
947
955
|
const started = parts(rows, row.sessionID);
|
|
948
956
|
if (row.waits.length)
|
|
949
957
|
return [...started.started ? [bar(started)] : [], ...row.waits.map(waitLine)];
|
|
958
|
+
if (row.stalled !== undefined)
|
|
959
|
+
return [...started.started ? [bar(started)] : [], stalledLine(row.stalled, now)];
|
|
950
960
|
if (started.started)
|
|
951
961
|
return [bar(started)];
|
|
952
962
|
return row.state === "gone" ? [] : [activityLine(row, now)];
|
|
@@ -959,8 +969,10 @@ function courierOf(ctx) {
|
|
|
959
969
|
location
|
|
960
970
|
};
|
|
961
971
|
}
|
|
972
|
+
var REREAD_MS = 15000;
|
|
962
973
|
function changes(ctx, types, settle) {
|
|
963
974
|
const [changed, setChanged] = createSignal(0);
|
|
975
|
+
const reread = setInterval(() => setChanged((count) => count + 1), REREAD_MS);
|
|
964
976
|
let settling;
|
|
965
977
|
const unlisten = ctx.data.listen(({
|
|
966
978
|
details
|
|
@@ -974,6 +986,7 @@ function changes(ctx, types, settle) {
|
|
|
974
986
|
});
|
|
975
987
|
return [changed, () => {
|
|
976
988
|
clearTimeout(settling);
|
|
989
|
+
clearInterval(reread);
|
|
977
990
|
unlisten();
|
|
978
991
|
}];
|
|
979
992
|
}
|
|
@@ -1138,7 +1151,7 @@ async function confirmForget(ctx, courier, location, by, target, done) {
|
|
|
1138
1151
|
return true;
|
|
1139
1152
|
}
|
|
1140
1153
|
var FOCUS_PROMPT = "pane.focus.left";
|
|
1141
|
-
var SPLIT_WIDTH =
|
|
1154
|
+
var SPLIT_WIDTH = 108;
|
|
1142
1155
|
var oneLine = (title) => title.replace(/[\r\n]+/g, " ");
|
|
1143
1156
|
function TreePanel(props) {
|
|
1144
1157
|
const {
|
|
@@ -1184,7 +1197,7 @@ function TreePanel(props) {
|
|
|
1184
1197
|
presentation,
|
|
1185
1198
|
focused
|
|
1186
1199
|
} = input;
|
|
1187
|
-
view.note(ctx.renderer.width
|
|
1200
|
+
view.note(ctx.renderer.width >= SPLIT_WIDTH ? {
|
|
1188
1201
|
presentation,
|
|
1189
1202
|
focused
|
|
1190
1203
|
} : {
|
|
@@ -1323,15 +1336,17 @@ function TreePanel(props) {
|
|
|
1323
1336
|
}));
|
|
1324
1337
|
const root = () => parts(rows(), view.root);
|
|
1325
1338
|
const rowColor = (row) => {
|
|
1339
|
+
if (row.state === "stalled")
|
|
1340
|
+
return theme.text.feedback.error.base;
|
|
1326
1341
|
if (row.state === "waiting")
|
|
1327
1342
|
return theme.text.feedback.warning.base;
|
|
1328
1343
|
return row.state === "gone" ? theme.text.muted : theme.text.base;
|
|
1329
1344
|
};
|
|
1330
1345
|
return (() => {
|
|
1331
|
-
var _el$4 = _$createElement("box"), _el$5 = _$createElement("box"), _el$6 = _$createElement("text"), _el$
|
|
1346
|
+
var _el$4 = _$createElement("box"), _el$5 = _$createElement("box"), _el$6 = _$createElement("text"), _el$15 = _$createElement("scrollbox"), _el$16 = _$createElement("text");
|
|
1332
1347
|
_$insertNode(_el$4, _el$5);
|
|
1333
|
-
_$insertNode(_el$4, _el$
|
|
1334
|
-
_$insertNode(_el$4, _el$
|
|
1348
|
+
_$insertNode(_el$4, _el$15);
|
|
1349
|
+
_$insertNode(_el$4, _el$16);
|
|
1335
1350
|
_$setProp(_el$4, "flexDirection", "column");
|
|
1336
1351
|
_$setProp(_el$4, "flexGrow", 1);
|
|
1337
1352
|
_$setProp(_el$4, "paddingLeft", 1);
|
|
@@ -1378,21 +1393,33 @@ function TreePanel(props) {
|
|
|
1378
1393
|
_$effect((_$p) => _$setProp(_el$1, "fg", theme.text.feedback.error.base, _$p));
|
|
1379
1394
|
return _el$1;
|
|
1380
1395
|
}
|
|
1381
|
-
}), _el$
|
|
1396
|
+
}), _el$15);
|
|
1382
1397
|
_$insert(_el$4, _$createComponent(Show, {
|
|
1383
1398
|
get when() {
|
|
1384
|
-
return
|
|
1399
|
+
return latest()?.tree?.stalled;
|
|
1385
1400
|
},
|
|
1386
1401
|
get children() {
|
|
1387
|
-
var _el$11 = _$createElement("text");
|
|
1388
|
-
_$insertNode(_el$11,
|
|
1389
|
-
_$
|
|
1402
|
+
var _el$11 = _$createElement("text"), _el$12 = _$createTextNode(`This session is stalled: `);
|
|
1403
|
+
_$insertNode(_el$11, _el$12);
|
|
1404
|
+
_$insert(_el$11, () => stalledLine(latest().tree.stalled, now()), null);
|
|
1405
|
+
_$effect((_$p) => _$setProp(_el$11, "fg", theme.text.feedback.error.base, _$p));
|
|
1390
1406
|
return _el$11;
|
|
1391
1407
|
}
|
|
1392
|
-
}), _el$
|
|
1393
|
-
_$
|
|
1394
|
-
|
|
1395
|
-
|
|
1408
|
+
}), _el$15);
|
|
1409
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
1410
|
+
get when() {
|
|
1411
|
+
return _$memo(() => !!latest()?.tree)() && !rows().length;
|
|
1412
|
+
},
|
|
1413
|
+
get children() {
|
|
1414
|
+
var _el$13 = _$createElement("text");
|
|
1415
|
+
_$insertNode(_el$13, _$createTextNode(`No session started with courier_spawn under this one.`));
|
|
1416
|
+
_$effect((_$p) => _$setProp(_el$13, "fg", theme.text.muted, _$p));
|
|
1417
|
+
return _el$13;
|
|
1418
|
+
}
|
|
1419
|
+
}), _el$15);
|
|
1420
|
+
_$use((value) => scroll = value, _el$15);
|
|
1421
|
+
_$setProp(_el$15, "flexGrow", 1);
|
|
1422
|
+
_$insert(_el$15, _$createComponent(For, {
|
|
1396
1423
|
get each() {
|
|
1397
1424
|
return rows();
|
|
1398
1425
|
},
|
|
@@ -1400,45 +1427,45 @@ function TreePanel(props) {
|
|
|
1400
1427
|
const chosen = () => index() === selected();
|
|
1401
1428
|
const indent = " ".repeat(row.depth - 1);
|
|
1402
1429
|
return (() => {
|
|
1403
|
-
var _el$
|
|
1404
|
-
_$insertNode(_el$
|
|
1405
|
-
_$setProp(_el$
|
|
1406
|
-
_$setProp(_el$
|
|
1407
|
-
_$insertNode(_el$17, _el$18);
|
|
1408
|
-
_$insertNode(_el$17, _el$19);
|
|
1409
|
-
_$setProp(_el$17, "flexDirection", "row");
|
|
1410
|
-
_$setProp(_el$17, "flexShrink", 0);
|
|
1411
|
-
_$setProp(_el$18, "wrapMode", "none");
|
|
1412
|
-
_$setProp(_el$18, "flexShrink", 1);
|
|
1413
|
-
_$setProp(_el$18, "minWidth", 0);
|
|
1414
|
-
_$insert(_el$18, indent, null);
|
|
1415
|
-
_$insert(_el$18, () => chosen() ? "\u25B8 " : " ", null);
|
|
1416
|
-
_$insert(_el$18, () => oneLine(row.title), null);
|
|
1417
|
-
_$insert(_el$18, () => row.sessionID === input.sessionID ? " (on screen)" : "", null);
|
|
1430
|
+
var _el$18 = _$createElement("box"), _el$19 = _$createElement("box"), _el$20 = _$createElement("text"), _el$21 = _$createElement("text"), _el$22 = _$createTextNode(` `);
|
|
1431
|
+
_$insertNode(_el$18, _el$19);
|
|
1432
|
+
_$setProp(_el$18, "flexDirection", "column");
|
|
1433
|
+
_$setProp(_el$18, "flexShrink", 0);
|
|
1418
1434
|
_$insertNode(_el$19, _el$20);
|
|
1419
|
-
_$
|
|
1435
|
+
_$insertNode(_el$19, _el$21);
|
|
1436
|
+
_$setProp(_el$19, "flexDirection", "row");
|
|
1420
1437
|
_$setProp(_el$19, "flexShrink", 0);
|
|
1421
|
-
_$
|
|
1422
|
-
_$
|
|
1438
|
+
_$setProp(_el$20, "wrapMode", "none");
|
|
1439
|
+
_$setProp(_el$20, "flexShrink", 1);
|
|
1440
|
+
_$setProp(_el$20, "minWidth", 0);
|
|
1441
|
+
_$insert(_el$20, indent, null);
|
|
1442
|
+
_$insert(_el$20, () => chosen() ? "\u25B8 " : " ", null);
|
|
1443
|
+
_$insert(_el$20, () => oneLine(row.title), null);
|
|
1444
|
+
_$insert(_el$20, () => row.sessionID === input.sessionID ? " (on screen)" : "", null);
|
|
1445
|
+
_$insertNode(_el$21, _el$22);
|
|
1446
|
+
_$setProp(_el$21, "wrapMode", "none");
|
|
1447
|
+
_$setProp(_el$21, "flexShrink", 0);
|
|
1448
|
+
_$insert(_el$21, () => statusLine(row), null);
|
|
1449
|
+
_$insert(_el$18, _$createComponent(For, {
|
|
1423
1450
|
get each() {
|
|
1424
1451
|
return detailLines(row, rows(), now());
|
|
1425
1452
|
},
|
|
1426
1453
|
children: (line) => (() => {
|
|
1427
|
-
var _el$
|
|
1428
|
-
_$insertNode(_el$
|
|
1429
|
-
_$setProp(_el$
|
|
1430
|
-
_$insert(_el$
|
|
1431
|
-
_$insert(_el$
|
|
1432
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1433
|
-
return _el$
|
|
1454
|
+
var _el$23 = _$createElement("text"), _el$24 = _$createTextNode(` `);
|
|
1455
|
+
_$insertNode(_el$23, _el$24);
|
|
1456
|
+
_$setProp(_el$23, "wrapMode", "none");
|
|
1457
|
+
_$insert(_el$23, indent, _el$24);
|
|
1458
|
+
_$insert(_el$23, line, null);
|
|
1459
|
+
_$effect((_$p) => _$setProp(_el$23, "fg", theme.text.muted, _$p));
|
|
1460
|
+
return _el$23;
|
|
1434
1461
|
})()
|
|
1435
1462
|
}), null);
|
|
1436
1463
|
_$effect((_p$) => {
|
|
1437
1464
|
var _v$3 = `courier-row-${index()}`, _v$4 = chosen() && input.focused ? theme.background.raised.high : undefined, _v$5 = rowColor(row), _v$6 = theme.text.muted;
|
|
1438
|
-
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
1439
|
-
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
1440
|
-
_v$5 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
1441
|
-
_v$6 !== _p$.o && (_p$.o = _$setProp(_el$
|
|
1465
|
+
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$18, "id", _v$3, _p$.e));
|
|
1466
|
+
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$18, "backgroundColor", _v$4, _p$.t));
|
|
1467
|
+
_v$5 !== _p$.a && (_p$.a = _$setProp(_el$20, "fg", _v$5, _p$.a));
|
|
1468
|
+
_v$6 !== _p$.o && (_p$.o = _$setProp(_el$21, "fg", _v$6, _p$.o));
|
|
1442
1469
|
return _p$;
|
|
1443
1470
|
}, {
|
|
1444
1471
|
e: undefined,
|
|
@@ -1446,17 +1473,17 @@ function TreePanel(props) {
|
|
|
1446
1473
|
a: undefined,
|
|
1447
1474
|
o: undefined
|
|
1448
1475
|
});
|
|
1449
|
-
return _el$
|
|
1476
|
+
return _el$18;
|
|
1450
1477
|
})();
|
|
1451
1478
|
}
|
|
1452
1479
|
}));
|
|
1453
|
-
_$insertNode(_el$
|
|
1454
|
-
_$setProp(_el$
|
|
1455
|
-
_$setProp(_el$
|
|
1480
|
+
_$insertNode(_el$16, _$createTextNode(`\u2191\u2193 select \xB7 enter open \xB7 s stop \xB7 x forget \xB7 r refresh \xB7 f fullscreen \xB7 q close`));
|
|
1481
|
+
_$setProp(_el$16, "wrapMode", "none");
|
|
1482
|
+
_$setProp(_el$16, "flexShrink", 0);
|
|
1456
1483
|
_$effect((_p$) => {
|
|
1457
1484
|
var _v$ = theme.text.base, _v$2 = theme.text.muted;
|
|
1458
1485
|
_v$ !== _p$.e && (_p$.e = _$setProp(_el$6, "fg", _v$, _p$.e));
|
|
1459
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
1486
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$16, "fg", _v$2, _p$.t));
|
|
1460
1487
|
return _p$;
|
|
1461
1488
|
}, {
|
|
1462
1489
|
e: undefined,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-courier",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
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>",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
"test:e2e": "e2e/run.sh"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@opencode/plugin": "2.0.
|
|
59
|
+
"@opencode/plugin": "2.0.30",
|
|
60
60
|
"effect": "4.0.1"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@opencode/plugin": "2.0.
|
|
64
|
-
"@opencode/theme": "2.0.
|
|
63
|
+
"@opencode/plugin": "2.0.30",
|
|
64
|
+
"@opencode/theme": "2.0.30",
|
|
65
65
|
"@opentui/core": "0.5.17",
|
|
66
66
|
"@opentui/solid": "0.5.17",
|
|
67
67
|
"@types/bun": "1.3.14",
|