opencode-subagent-magazine 1.2.1-beta.0 → 1.3.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/LICENSE +21 -21
- package/README.md +187 -187
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/index.js +14 -2
- package/dist/tui.js +123 -69
- package/install.mjs +103 -103
- package/package.json +62 -62
- package/src/_version.ts +1 -1
- package/src/index.tsx +1805 -1782
package/dist/tui.js
CHANGED
|
@@ -11,7 +11,7 @@ import { createElement as _$createElement } from "@opentui/solid";
|
|
|
11
11
|
import { createMemo, createSignal, createEffect, onMount, onCleanup, untrack, Show, For } from "solid-js";
|
|
12
12
|
|
|
13
13
|
// src/_version.ts
|
|
14
|
-
var PLUGIN_VERSION = "1.
|
|
14
|
+
var PLUGIN_VERSION = "1.3.0";
|
|
15
15
|
|
|
16
16
|
// src/index.tsx
|
|
17
17
|
var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["task", "delegate", "call_omo_agent"]);
|
|
@@ -26,6 +26,8 @@ var I18N = {
|
|
|
26
26
|
"error.label": "\u9519\u8BEF",
|
|
27
27
|
"model.label": "\u6A21\u578B",
|
|
28
28
|
"todo.label": "\u8FDB\u5EA6",
|
|
29
|
+
"session.label": "\u4F1A\u8BDD ID",
|
|
30
|
+
"session.toast.copy": "\u53EF\u624B\u52A8\u590D\u5236\u4E0A\u65B9 ID",
|
|
29
31
|
"open.label": "\u8FDB\u5165\u4F1A\u8BDD",
|
|
30
32
|
"cost.label": "\u8D39\u7528",
|
|
31
33
|
"scroll.more": "\u66F4\u591A",
|
|
@@ -50,6 +52,8 @@ var I18N = {
|
|
|
50
52
|
"error.label": "error",
|
|
51
53
|
"model.label": "model",
|
|
52
54
|
"todo.label": "todo",
|
|
55
|
+
"session.label": "session ID",
|
|
56
|
+
"session.toast.copy": "Copy the ID above manually",
|
|
53
57
|
"open.label": "Open session",
|
|
54
58
|
"cost.label": "cost",
|
|
55
59
|
"scroll.more": "more",
|
|
@@ -1017,7 +1021,7 @@ function SubAgentPanel(props) {
|
|
|
1017
1021
|
};
|
|
1018
1022
|
const sep = () => "\u2500".repeat(Math.max(1, panelWidth()));
|
|
1019
1023
|
const expandedMaxLabelW = createMemo(() => {
|
|
1020
|
-
const labels = [t("agent.label"), t("status.label"), t("time.label"), t("tokens.label"), t("error.label"), t("cost.label"), t("model.label"), t("todo.label")];
|
|
1024
|
+
const labels = [t("agent.label"), t("status.label"), t("time.label"), t("tokens.label"), t("error.label"), t("cost.label"), t("model.label"), t("todo.label"), t("session.label")];
|
|
1021
1025
|
return Math.max(...labels.map((l) => visualWidth(l + ": ")));
|
|
1022
1026
|
});
|
|
1023
1027
|
const expandedPad = (label) => Math.max(0, expandedMaxLabelW() - visualWidth(label + ": "));
|
|
@@ -1293,23 +1297,23 @@ function SubAgentPanel(props) {
|
|
|
1293
1297
|
_$insert(_el$25, (() => {
|
|
1294
1298
|
var _c$2 = _$memo(() => !!timeText());
|
|
1295
1299
|
return () => _c$2() ? [" ", (() => {
|
|
1296
|
-
var _el$
|
|
1297
|
-
_$insert(_el$
|
|
1298
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1300
|
+
var _el$89 = _$createElement("span");
|
|
1301
|
+
_$insert(_el$89, timeText);
|
|
1302
|
+
_$effect((_$p) => _$setProp(_el$89, "style", {
|
|
1299
1303
|
fg: timeColor()
|
|
1300
1304
|
}, _$p));
|
|
1301
|
-
return _el$
|
|
1305
|
+
return _el$89;
|
|
1302
1306
|
})()] : null;
|
|
1303
1307
|
})(), null);
|
|
1304
1308
|
_$insert(_el$25, (() => {
|
|
1305
1309
|
var _c$3 = _$memo(() => !!tokenText());
|
|
1306
1310
|
return () => _c$3() ? (() => {
|
|
1307
|
-
var _el$
|
|
1308
|
-
_$insert(_el$
|
|
1309
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1311
|
+
var _el$90 = _$createElement("span");
|
|
1312
|
+
_$insert(_el$90, tokenText);
|
|
1313
|
+
_$effect((_$p) => _$setProp(_el$90, "style", {
|
|
1310
1314
|
fg: pal().muted
|
|
1311
1315
|
}, _$p));
|
|
1312
|
-
return _el$
|
|
1316
|
+
return _el$90;
|
|
1313
1317
|
})() : null;
|
|
1314
1318
|
})(), null);
|
|
1315
1319
|
_$effect((_p$) => {
|
|
@@ -1592,6 +1596,56 @@ function SubAgentPanel(props) {
|
|
|
1592
1596
|
});
|
|
1593
1597
|
return _el$74;
|
|
1594
1598
|
}
|
|
1599
|
+
}), _$createComponent(Show, {
|
|
1600
|
+
get when() {
|
|
1601
|
+
return entry.sessionId;
|
|
1602
|
+
},
|
|
1603
|
+
get children() {
|
|
1604
|
+
var _el$81 = _$createElement("text"), _el$82 = _$createTextNode(` `), _el$83 = _$createElement("span"), _el$84 = _$createTextNode(`: `), _el$85 = _$createElement("span"), _el$86 = _$createElement("span"), _el$87 = _$createElement("span");
|
|
1605
|
+
_$insertNode(_el$81, _el$82);
|
|
1606
|
+
_$insertNode(_el$81, _el$83);
|
|
1607
|
+
_$insertNode(_el$81, _el$85);
|
|
1608
|
+
_$insertNode(_el$81, _el$86);
|
|
1609
|
+
_$insertNode(_el$81, _el$87);
|
|
1610
|
+
_$setProp(_el$81, "onMouseUp", () => {
|
|
1611
|
+
if (entry.sessionId) {
|
|
1612
|
+
props.api.ui.toast({
|
|
1613
|
+
title: entry.title || entry.agent,
|
|
1614
|
+
message: `${entry.sessionId}
|
|
1615
|
+
|
|
1616
|
+
${t("session.toast.copy")}`,
|
|
1617
|
+
duration: 8e3
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
_$insertNode(_el$83, _el$84);
|
|
1622
|
+
_$insert(_el$83, () => t("session.label"), _el$84);
|
|
1623
|
+
_$insert(_el$85, () => " ".repeat(expandedPad(t("session.label"))));
|
|
1624
|
+
_$insert(_el$86, () => truncate(entry.sessionId, expandedValAvail() - visualWidth(" \u2398")));
|
|
1625
|
+
_$insertNode(_el$87, _$createTextNode(` \u2398`));
|
|
1626
|
+
_$effect((_p$) => {
|
|
1627
|
+
var _v$28 = {
|
|
1628
|
+
fg: pal().primary
|
|
1629
|
+
}, _v$29 = {
|
|
1630
|
+
fg: pal().muted
|
|
1631
|
+
}, _v$30 = {
|
|
1632
|
+
fg: pal().muted
|
|
1633
|
+
}, _v$31 = {
|
|
1634
|
+
fg: pal().warning
|
|
1635
|
+
};
|
|
1636
|
+
_v$28 !== _p$.e && (_p$.e = _$setProp(_el$83, "style", _v$28, _p$.e));
|
|
1637
|
+
_v$29 !== _p$.t && (_p$.t = _$setProp(_el$85, "style", _v$29, _p$.t));
|
|
1638
|
+
_v$30 !== _p$.a && (_p$.a = _$setProp(_el$86, "style", _v$30, _p$.a));
|
|
1639
|
+
_v$31 !== _p$.o && (_p$.o = _$setProp(_el$87, "style", _v$31, _p$.o));
|
|
1640
|
+
return _p$;
|
|
1641
|
+
}, {
|
|
1642
|
+
e: void 0,
|
|
1643
|
+
t: void 0,
|
|
1644
|
+
a: void 0,
|
|
1645
|
+
o: void 0
|
|
1646
|
+
});
|
|
1647
|
+
return _el$81;
|
|
1648
|
+
}
|
|
1595
1649
|
}), _$createComponent(Show, {
|
|
1596
1650
|
get when() {
|
|
1597
1651
|
return entry.sessionId || isRunning;
|
|
@@ -1608,66 +1662,66 @@ function SubAgentPanel(props) {
|
|
|
1608
1662
|
/* indent */
|
|
1609
1663
|
);
|
|
1610
1664
|
return (() => {
|
|
1611
|
-
var _el$
|
|
1612
|
-
_$setProp(_el$
|
|
1613
|
-
_$insert(_el$
|
|
1665
|
+
var _el$91 = _$createElement("box");
|
|
1666
|
+
_$setProp(_el$91, "flexDirection", "row");
|
|
1667
|
+
_$insert(_el$91, _$createComponent(Show, {
|
|
1614
1668
|
get when() {
|
|
1615
1669
|
return entry.sessionId;
|
|
1616
1670
|
},
|
|
1617
1671
|
get fallback() {
|
|
1618
1672
|
return (() => {
|
|
1619
|
-
var _el$
|
|
1620
|
-
_$insertNode(_el$
|
|
1621
|
-
return _el$
|
|
1673
|
+
var _el$98 = _$createElement("text");
|
|
1674
|
+
_$insertNode(_el$98, _$createTextNode(` `));
|
|
1675
|
+
return _el$98;
|
|
1622
1676
|
})();
|
|
1623
1677
|
},
|
|
1624
1678
|
get children() {
|
|
1625
|
-
var _el$
|
|
1626
|
-
_$insertNode(_el$
|
|
1627
|
-
_$insertNode(_el$
|
|
1628
|
-
_$setProp(_el$
|
|
1629
|
-
_$setProp(_el$
|
|
1630
|
-
_$setProp(_el$
|
|
1679
|
+
var _el$92 = _$createElement("text"), _el$93 = _$createElement("span"), _el$94 = _$createElement("span");
|
|
1680
|
+
_$insertNode(_el$92, _el$93);
|
|
1681
|
+
_$insertNode(_el$92, _el$94);
|
|
1682
|
+
_$setProp(_el$92, "onMouseOver", () => setHoveredOpen(entry.id));
|
|
1683
|
+
_$setProp(_el$92, "onMouseOut", () => setHoveredOpen(void 0));
|
|
1684
|
+
_$setProp(_el$92, "onMouseUp", () => {
|
|
1631
1685
|
if (entry.sessionId) {
|
|
1632
1686
|
props.api.route.navigate("session", {
|
|
1633
1687
|
sessionID: entry.sessionId
|
|
1634
1688
|
});
|
|
1635
1689
|
}
|
|
1636
1690
|
});
|
|
1637
|
-
_$insert(_el$
|
|
1638
|
-
_$insert(_el$
|
|
1691
|
+
_$insert(_el$93, openPrefix);
|
|
1692
|
+
_$insert(_el$94, () => t("open.label"));
|
|
1639
1693
|
_$effect((_p$) => {
|
|
1640
|
-
var _v$
|
|
1694
|
+
var _v$32 = {
|
|
1641
1695
|
fg: hoveredOpen() === entry.id ? pal().warning : pal().primary
|
|
1642
|
-
}, _v$
|
|
1696
|
+
}, _v$33 = {
|
|
1643
1697
|
fg: hoveredOpen() === entry.id ? pal().warning : pal().primary
|
|
1644
1698
|
};
|
|
1645
|
-
_v$
|
|
1646
|
-
_v$
|
|
1699
|
+
_v$32 !== _p$.e && (_p$.e = _$setProp(_el$93, "style", _v$32, _p$.e));
|
|
1700
|
+
_v$33 !== _p$.t && (_p$.t = _$setProp(_el$94, "style", _v$33, _p$.t));
|
|
1647
1701
|
return _p$;
|
|
1648
1702
|
}, {
|
|
1649
1703
|
e: void 0,
|
|
1650
1704
|
t: void 0
|
|
1651
1705
|
});
|
|
1652
|
-
return _el$
|
|
1706
|
+
return _el$92;
|
|
1653
1707
|
}
|
|
1654
1708
|
}), null);
|
|
1655
|
-
_$insert(_el$
|
|
1709
|
+
_$insert(_el$91, _$createComponent(Show, {
|
|
1656
1710
|
when: isRunning,
|
|
1657
1711
|
get children() {
|
|
1658
1712
|
return [(() => {
|
|
1659
|
-
var _el$
|
|
1660
|
-
_$insert(_el$
|
|
1661
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1713
|
+
var _el$95 = _$createElement("text");
|
|
1714
|
+
_$insert(_el$95, () => " ".repeat(spacerW()));
|
|
1715
|
+
_$effect((_$p) => _$setProp(_el$95, "style", {
|
|
1662
1716
|
fg: pal().muted
|
|
1663
1717
|
}, _$p));
|
|
1664
|
-
return _el$
|
|
1718
|
+
return _el$95;
|
|
1665
1719
|
})(), (() => {
|
|
1666
|
-
var _el$
|
|
1667
|
-
_$insertNode(_el$
|
|
1668
|
-
_$setProp(_el$
|
|
1669
|
-
_$setProp(_el$
|
|
1670
|
-
_$setProp(_el$
|
|
1720
|
+
var _el$96 = _$createElement("text"), _el$97 = _$createElement("span");
|
|
1721
|
+
_$insertNode(_el$96, _el$97);
|
|
1722
|
+
_$setProp(_el$96, "onMouseOver", () => setHoveredDismiss(entry.id));
|
|
1723
|
+
_$setProp(_el$96, "onMouseOut", () => setHoveredDismiss(void 0));
|
|
1724
|
+
_$setProp(_el$96, "onMouseUp", () => {
|
|
1671
1725
|
upsertEntry({
|
|
1672
1726
|
id: entry.id,
|
|
1673
1727
|
title: entry.title,
|
|
@@ -1676,15 +1730,15 @@ function SubAgentPanel(props) {
|
|
|
1676
1730
|
status: "done"
|
|
1677
1731
|
});
|
|
1678
1732
|
});
|
|
1679
|
-
_$insert(_el$
|
|
1680
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1733
|
+
_$insert(_el$97, dismissLabel);
|
|
1734
|
+
_$effect((_$p) => _$setProp(_el$97, "style", {
|
|
1681
1735
|
fg: hoveredDismiss() === entry.id ? pal().warning : pal().muted
|
|
1682
1736
|
}, _$p));
|
|
1683
|
-
return _el$
|
|
1737
|
+
return _el$96;
|
|
1684
1738
|
})()];
|
|
1685
1739
|
}
|
|
1686
1740
|
}), null);
|
|
1687
|
-
return _el$
|
|
1741
|
+
return _el$91;
|
|
1688
1742
|
})();
|
|
1689
1743
|
})();
|
|
1690
1744
|
}
|
|
@@ -1705,13 +1759,13 @@ function SubAgentPanel(props) {
|
|
|
1705
1759
|
const right = props.sortOrder() === "desc" ? `\u2191 ${t("scroll.top")}` : `\u2193 ${t("scroll.bottom")}`;
|
|
1706
1760
|
const pad = showTop ? Math.max(1, panelWidth() - visualWidth(left) - visualWidth(right)) : 0;
|
|
1707
1761
|
return (() => {
|
|
1708
|
-
var _el$
|
|
1709
|
-
_$insertNode(_el$
|
|
1710
|
-
_$setProp(_el$
|
|
1711
|
-
_$insertNode(_el$
|
|
1712
|
-
_$setProp(_el$
|
|
1713
|
-
_$setProp(_el$
|
|
1714
|
-
_$setProp(_el$
|
|
1762
|
+
var _el$100 = _$createElement("box"), _el$101 = _$createElement("text"), _el$102 = _$createElement("span");
|
|
1763
|
+
_$insertNode(_el$100, _el$101);
|
|
1764
|
+
_$setProp(_el$100, "flexDirection", "row");
|
|
1765
|
+
_$insertNode(_el$101, _el$102);
|
|
1766
|
+
_$setProp(_el$101, "onMouseOver", () => showMore && setHoveredMoreBelow(true));
|
|
1767
|
+
_$setProp(_el$101, "onMouseOut", () => setHoveredMoreBelow(false));
|
|
1768
|
+
_$setProp(_el$101, "onMouseUp", () => {
|
|
1715
1769
|
if (!showMore) return;
|
|
1716
1770
|
const total = entryList().length;
|
|
1717
1771
|
const m = max();
|
|
@@ -1723,20 +1777,20 @@ function SubAgentPanel(props) {
|
|
|
1723
1777
|
}
|
|
1724
1778
|
setHoveredMoreBelow(false);
|
|
1725
1779
|
});
|
|
1726
|
-
_$insert(_el$
|
|
1727
|
-
_$insert(_el$
|
|
1728
|
-
var _el$
|
|
1729
|
-
_$insert(_el$
|
|
1730
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1780
|
+
_$insert(_el$102, left);
|
|
1781
|
+
_$insert(_el$100, showTop ? [(() => {
|
|
1782
|
+
var _el$103 = _$createElement("text");
|
|
1783
|
+
_$insert(_el$103, () => " ".repeat(pad));
|
|
1784
|
+
_$effect((_$p) => _$setProp(_el$103, "style", {
|
|
1731
1785
|
fg: pal().muted
|
|
1732
1786
|
}, _$p));
|
|
1733
|
-
return _el$
|
|
1787
|
+
return _el$103;
|
|
1734
1788
|
})(), (() => {
|
|
1735
|
-
var _el$
|
|
1736
|
-
_$insertNode(_el$
|
|
1737
|
-
_$setProp(_el$
|
|
1738
|
-
_$setProp(_el$
|
|
1739
|
-
_$setProp(_el$
|
|
1789
|
+
var _el$104 = _$createElement("text"), _el$105 = _$createElement("span");
|
|
1790
|
+
_$insertNode(_el$104, _el$105);
|
|
1791
|
+
_$setProp(_el$104, "onMouseOver", () => setHoveredTop(true));
|
|
1792
|
+
_$setProp(_el$104, "onMouseOut", () => setHoveredTop(false));
|
|
1793
|
+
_$setProp(_el$104, "onMouseUp", () => {
|
|
1740
1794
|
const total = entryList().length;
|
|
1741
1795
|
const m = max();
|
|
1742
1796
|
if (props.sortOrder() === "desc") {
|
|
@@ -1746,16 +1800,16 @@ function SubAgentPanel(props) {
|
|
|
1746
1800
|
}
|
|
1747
1801
|
setHoveredTop(false);
|
|
1748
1802
|
});
|
|
1749
|
-
_$insert(_el$
|
|
1750
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1803
|
+
_$insert(_el$105, right);
|
|
1804
|
+
_$effect((_$p) => _$setProp(_el$105, "style", {
|
|
1751
1805
|
fg: hoveredTop() ? pal().warning : pal().muted
|
|
1752
1806
|
}, _$p));
|
|
1753
|
-
return _el$
|
|
1807
|
+
return _el$104;
|
|
1754
1808
|
})()] : null, null);
|
|
1755
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1809
|
+
_$effect((_$p) => _$setProp(_el$102, "style", {
|
|
1756
1810
|
fg: showMore && hoveredMoreBelow() ? pal().warning : pal().muted
|
|
1757
1811
|
}, _$p));
|
|
1758
|
-
return _el$
|
|
1812
|
+
return _el$100;
|
|
1759
1813
|
})();
|
|
1760
1814
|
})();
|
|
1761
1815
|
}
|
|
@@ -1933,9 +1987,9 @@ var tui = async (api) => {
|
|
|
1933
1987
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
1934
1988
|
title: "Max Visible Entries",
|
|
1935
1989
|
description: () => (() => {
|
|
1936
|
-
var _el$
|
|
1937
|
-
_$insertNode(_el$
|
|
1938
|
-
return _el$
|
|
1990
|
+
var _el$106 = _$createElement("text");
|
|
1991
|
+
_$insertNode(_el$106, _$createTextNode(`Number of entries to show in the sidebar (1\u201350)`));
|
|
1992
|
+
return _el$106;
|
|
1939
1993
|
})(),
|
|
1940
1994
|
get value() {
|
|
1941
1995
|
return String(maxEntries());
|
package/install.mjs
CHANGED
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Install script for opencode-subagent-magazine.
|
|
5
|
-
*
|
|
6
|
-
* Creates or updates `~/.config/opencode/tui.jsonc` so OpenCode loads
|
|
7
|
-
* the TUI sidebar plugin.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* node install.mjs
|
|
11
|
-
* npm explore opencode-subagent-magazine -- node install.mjs
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { readFile, writeFile, mkdir, access } from "node:fs/promises"
|
|
15
|
-
import { constants } from "node:fs"
|
|
16
|
-
import { homedir, platform } from "node:os"
|
|
17
|
-
import { join, dirname } from "node:path"
|
|
18
|
-
|
|
19
|
-
const PLUGIN_SPEC = "opencode-subagent-magazine"
|
|
20
|
-
|
|
21
|
-
function configDir() {
|
|
22
|
-
if (platform() === "win32") {
|
|
23
|
-
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "opencode")
|
|
24
|
-
}
|
|
25
|
-
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "opencode")
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function exists(p) {
|
|
29
|
-
try { await access(p, constants.F_OK); return true }
|
|
30
|
-
catch { return false }
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function readJSONC(p) {
|
|
34
|
-
const raw = await readFile(p, "utf-8")
|
|
35
|
-
const stripped = raw.replace(/^\s*\/\/.*$/gm, "")
|
|
36
|
-
return JSON.parse(stripped)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function formatJSONC(obj) {
|
|
40
|
-
return JSON.stringify(obj, null, 2) + "\n"
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function mergePlugin(existing, spec) {
|
|
44
|
-
const plugins = existing.plugin ?? []
|
|
45
|
-
if (plugins.some((p) => (typeof p === "string" ? p : p[0]) === spec)) {
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
existing.plugin = [...plugins, spec]
|
|
49
|
-
return true
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function main() {
|
|
53
|
-
const dir = configDir()
|
|
54
|
-
await mkdir(dir, { recursive: true })
|
|
55
|
-
|
|
56
|
-
// ---- tui.jsonc ----
|
|
57
|
-
const tuiPath = join(dir, "tui.jsonc")
|
|
58
|
-
let tuiChanged = false
|
|
59
|
-
|
|
60
|
-
if (await exists(tuiPath)) {
|
|
61
|
-
const cfg = await readJSONC(tuiPath)
|
|
62
|
-
tuiChanged = mergePlugin(cfg, PLUGIN_SPEC)
|
|
63
|
-
if (tuiChanged) {
|
|
64
|
-
await writeFile(tuiPath, formatJSONC(cfg))
|
|
65
|
-
console.log(`[opencode-subagent-magazine] Added to ${tuiPath}`)
|
|
66
|
-
} else {
|
|
67
|
-
console.log(`[opencode-subagent-magazine] Already in ${tuiPath}`)
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
const cfg = {
|
|
71
|
-
$schema: "https://opencode.ai/tui.json",
|
|
72
|
-
plugin: [PLUGIN_SPEC],
|
|
73
|
-
}
|
|
74
|
-
await writeFile(tuiPath, formatJSONC(cfg))
|
|
75
|
-
console.log(`[opencode-subagent-magazine] Created ${tuiPath}`)
|
|
76
|
-
tuiChanged = true
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ---- opencode.jsonc (forward compat) ----
|
|
80
|
-
const ocPath = join(dir, "opencode.jsonc")
|
|
81
|
-
let ocChanged = false
|
|
82
|
-
|
|
83
|
-
if (await exists(ocPath)) {
|
|
84
|
-
const cfg = await readJSONC(ocPath)
|
|
85
|
-
ocChanged = mergePlugin(cfg, PLUGIN_SPEC)
|
|
86
|
-
if (ocChanged) {
|
|
87
|
-
await writeFile(ocPath, formatJSONC(cfg))
|
|
88
|
-
console.log(`[opencode-subagent-magazine] Also added to ${ocPath}`)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ---- done ----
|
|
93
|
-
if (tuiChanged || ocChanged) {
|
|
94
|
-
console.log("\nDone! Restart OpenCode to see the SubAgent Monitor sidebar panel.")
|
|
95
|
-
} else {
|
|
96
|
-
console.log("\nAlready installed. Restart OpenCode if you haven't yet.")
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
main().catch((err) => {
|
|
101
|
-
console.error("Install failed:", err.message)
|
|
102
|
-
process.exit(1)
|
|
103
|
-
})
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Install script for opencode-subagent-magazine.
|
|
5
|
+
*
|
|
6
|
+
* Creates or updates `~/.config/opencode/tui.jsonc` so OpenCode loads
|
|
7
|
+
* the TUI sidebar plugin.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node install.mjs
|
|
11
|
+
* npm explore opencode-subagent-magazine -- node install.mjs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFile, writeFile, mkdir, access } from "node:fs/promises"
|
|
15
|
+
import { constants } from "node:fs"
|
|
16
|
+
import { homedir, platform } from "node:os"
|
|
17
|
+
import { join, dirname } from "node:path"
|
|
18
|
+
|
|
19
|
+
const PLUGIN_SPEC = "opencode-subagent-magazine"
|
|
20
|
+
|
|
21
|
+
function configDir() {
|
|
22
|
+
if (platform() === "win32") {
|
|
23
|
+
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "opencode")
|
|
24
|
+
}
|
|
25
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "opencode")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function exists(p) {
|
|
29
|
+
try { await access(p, constants.F_OK); return true }
|
|
30
|
+
catch { return false }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function readJSONC(p) {
|
|
34
|
+
const raw = await readFile(p, "utf-8")
|
|
35
|
+
const stripped = raw.replace(/^\s*\/\/.*$/gm, "")
|
|
36
|
+
return JSON.parse(stripped)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function formatJSONC(obj) {
|
|
40
|
+
return JSON.stringify(obj, null, 2) + "\n"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function mergePlugin(existing, spec) {
|
|
44
|
+
const plugins = existing.plugin ?? []
|
|
45
|
+
if (plugins.some((p) => (typeof p === "string" ? p : p[0]) === spec)) {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
existing.plugin = [...plugins, spec]
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function main() {
|
|
53
|
+
const dir = configDir()
|
|
54
|
+
await mkdir(dir, { recursive: true })
|
|
55
|
+
|
|
56
|
+
// ---- tui.jsonc ----
|
|
57
|
+
const tuiPath = join(dir, "tui.jsonc")
|
|
58
|
+
let tuiChanged = false
|
|
59
|
+
|
|
60
|
+
if (await exists(tuiPath)) {
|
|
61
|
+
const cfg = await readJSONC(tuiPath)
|
|
62
|
+
tuiChanged = mergePlugin(cfg, PLUGIN_SPEC)
|
|
63
|
+
if (tuiChanged) {
|
|
64
|
+
await writeFile(tuiPath, formatJSONC(cfg))
|
|
65
|
+
console.log(`[opencode-subagent-magazine] Added to ${tuiPath}`)
|
|
66
|
+
} else {
|
|
67
|
+
console.log(`[opencode-subagent-magazine] Already in ${tuiPath}`)
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
const cfg = {
|
|
71
|
+
$schema: "https://opencode.ai/tui.json",
|
|
72
|
+
plugin: [PLUGIN_SPEC],
|
|
73
|
+
}
|
|
74
|
+
await writeFile(tuiPath, formatJSONC(cfg))
|
|
75
|
+
console.log(`[opencode-subagent-magazine] Created ${tuiPath}`)
|
|
76
|
+
tuiChanged = true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---- opencode.jsonc (forward compat) ----
|
|
80
|
+
const ocPath = join(dir, "opencode.jsonc")
|
|
81
|
+
let ocChanged = false
|
|
82
|
+
|
|
83
|
+
if (await exists(ocPath)) {
|
|
84
|
+
const cfg = await readJSONC(ocPath)
|
|
85
|
+
ocChanged = mergePlugin(cfg, PLUGIN_SPEC)
|
|
86
|
+
if (ocChanged) {
|
|
87
|
+
await writeFile(ocPath, formatJSONC(cfg))
|
|
88
|
+
console.log(`[opencode-subagent-magazine] Also added to ${ocPath}`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ---- done ----
|
|
93
|
+
if (tuiChanged || ocChanged) {
|
|
94
|
+
console.log("\nDone! Restart OpenCode to see the SubAgent Monitor sidebar panel.")
|
|
95
|
+
} else {
|
|
96
|
+
console.log("\nAlready installed. Restart OpenCode if you haven't yet.")
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main().catch((err) => {
|
|
101
|
+
console.error("Install failed:", err.message)
|
|
102
|
+
process.exit(1)
|
|
103
|
+
})
|
package/package.json
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "opencode-subagent-magazine",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "OpenCode TUI plugin monitoring sub-agent invocation status in real time",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
"./server": {
|
|
9
|
-
"import": "./dist/server.js",
|
|
10
|
-
"types": "./dist/server.d.ts"
|
|
11
|
-
},
|
|
12
|
-
"./tui": {
|
|
13
|
-
"import": "./dist/tui.js",
|
|
14
|
-
"config": {
|
|
15
|
-
"enabled": true
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"files": [
|
|
20
|
-
"dist",
|
|
21
|
-
"src",
|
|
22
|
-
"install.mjs",
|
|
23
|
-
"README.md"
|
|
24
|
-
],
|
|
25
|
-
"bin": {
|
|
26
|
-
"opencode-subagent-magazine": "install.mjs"
|
|
27
|
-
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "tsc && node build.tui.mjs",
|
|
30
|
-
"build:tui": "node build.tui.mjs",
|
|
31
|
-
"typecheck": "tsc --noEmit",
|
|
32
|
-
"version": "node -e \"require('fs').writeFileSync('src/_version.ts','// auto-generated\\nexport const PLUGIN_VERSION='+JSON.stringify(require('./package.json').version)+';\\n')\"",
|
|
33
|
-
"prepublishOnly": "tsc"
|
|
34
|
-
},
|
|
35
|
-
"keywords": [
|
|
36
|
-
"opencode",
|
|
37
|
-
"opencode-plugin",
|
|
38
|
-
"tui",
|
|
39
|
-
"subagent",
|
|
40
|
-
"subtask"
|
|
41
|
-
],
|
|
42
|
-
"repository": {
|
|
43
|
-
"type": "git",
|
|
44
|
-
"url": "git+https://github.com/Hotakus/opencode-subagent-magazine.git"
|
|
45
|
-
},
|
|
46
|
-
"license": "MIT",
|
|
47
|
-
"peerDependencies": {
|
|
48
|
-
"@opencode-ai/plugin": ">=1.14.0",
|
|
49
|
-
"@opencode-ai/sdk": ">=1.14.0",
|
|
50
|
-
"@opentui/core": ">=0.2.0",
|
|
51
|
-
"@opentui/solid": ">=0.2.0",
|
|
52
|
-
"solid-js": ">=1.9.0"
|
|
53
|
-
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"@opencode-ai/plugin": "^1.14.50",
|
|
56
|
-
"@opencode-ai/sdk": "^1.14.50",
|
|
57
|
-
"esbuild": "^0.25.0",
|
|
58
|
-
"esbuild-plugin-solid": "^0.5.0",
|
|
59
|
-
"tsx": "^4.22.3",
|
|
60
|
-
"typescript": "^5.8.0"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-subagent-magazine",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "OpenCode TUI plugin monitoring sub-agent invocation status in real time",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./server": {
|
|
9
|
+
"import": "./dist/server.js",
|
|
10
|
+
"types": "./dist/server.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./tui": {
|
|
13
|
+
"import": "./dist/tui.js",
|
|
14
|
+
"config": {
|
|
15
|
+
"enabled": true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src",
|
|
22
|
+
"install.mjs",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"bin": {
|
|
26
|
+
"opencode-subagent-magazine": "install.mjs"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc && node build.tui.mjs",
|
|
30
|
+
"build:tui": "node build.tui.mjs",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"version": "node -e \"require('fs').writeFileSync('src/_version.ts','// auto-generated\\nexport const PLUGIN_VERSION='+JSON.stringify(require('./package.json').version)+';\\n')\"",
|
|
33
|
+
"prepublishOnly": "tsc"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"opencode",
|
|
37
|
+
"opencode-plugin",
|
|
38
|
+
"tui",
|
|
39
|
+
"subagent",
|
|
40
|
+
"subtask"
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/Hotakus/opencode-subagent-magazine.git"
|
|
45
|
+
},
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@opencode-ai/plugin": ">=1.14.0",
|
|
49
|
+
"@opencode-ai/sdk": ">=1.14.0",
|
|
50
|
+
"@opentui/core": ">=0.2.0",
|
|
51
|
+
"@opentui/solid": ">=0.2.0",
|
|
52
|
+
"solid-js": ">=1.9.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@opencode-ai/plugin": "^1.14.50",
|
|
56
|
+
"@opencode-ai/sdk": "^1.14.50",
|
|
57
|
+
"esbuild": "^0.25.0",
|
|
58
|
+
"esbuild-plugin-solid": "^0.5.0",
|
|
59
|
+
"tsx": "^4.22.3",
|
|
60
|
+
"typescript": "^5.8.0"
|
|
61
|
+
}
|
|
62
|
+
}
|