@three333/termbuddy 0.1.3 → 0.1.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/.claude/settings.local.json +3 -1
- package/dist/cli.js +282 -128
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AiConsole.tsx +3 -1
- package/src/components/InfoPanel.tsx +67 -0
- package/src/components/index.ts +2 -0
- package/src/components/tool/createBubbleTool.ts +31 -11
- package/src/hooks/useAiAgent.ts +22 -10
- package/src/hooks/useTcpSync.ts +9 -0
- package/src/page/Session.tsx +156 -86
package/dist/cli.js
CHANGED
|
@@ -300,15 +300,34 @@ function createBubbleTool(options) {
|
|
|
300
300
|
async (input) => {
|
|
301
301
|
const text = String(input.text ?? "").trim();
|
|
302
302
|
if (!text) return "\u6C14\u6CE1\u5185\u5BB9\u4E3A\u7A7A\u3002";
|
|
303
|
-
|
|
303
|
+
let target = 1;
|
|
304
|
+
if (typeof input.target === "number") {
|
|
305
|
+
target = Math.max(1, Math.min(4, Math.floor(input.target)));
|
|
306
|
+
} else if (typeof input.target === "string") {
|
|
307
|
+
const t = input.target.toLowerCase();
|
|
308
|
+
if (t === "local" || t === "1") {
|
|
309
|
+
target = 1;
|
|
310
|
+
} else if (t === "buddy" || t === "2") {
|
|
311
|
+
target = 2;
|
|
312
|
+
} else if (t === "3") {
|
|
313
|
+
target = 3;
|
|
314
|
+
} else if (t === "4") {
|
|
315
|
+
target = 4;
|
|
316
|
+
} else {
|
|
317
|
+
const parsed = parseInt(t, 10);
|
|
318
|
+
if (!isNaN(parsed) && parsed >= 1 && parsed <= 4) {
|
|
319
|
+
target = parsed;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
304
323
|
const durationRaw = Number(input.durationMs ?? 2500);
|
|
305
324
|
const durationMs = Number.isFinite(durationRaw) && durationRaw > 0 ? Math.min(15e3, Math.max(300, Math.floor(durationRaw))) : 2500;
|
|
306
325
|
options.onShowBubble?.({ text, target, durationMs });
|
|
307
|
-
return `\u5DF2\u663E\u793A\u6C14\u6CE1\uFF1A${text}`;
|
|
326
|
+
return `\u5DF2\u663E\u793A\u6C14\u6CE1\u7ED9 No.${target}\uFF1A${text}`;
|
|
308
327
|
},
|
|
309
328
|
{
|
|
310
329
|
name: "show_bubble",
|
|
311
|
-
description: "\u5728\u5C0F\u732B\u5934\u50CF\u4E0A\u663E\u793A\u4E00\u4E2A\u6C14\u6CE1\uFF08\u77ED\u6D88\u606F\u63D0\u793A\uFF09\u3002",
|
|
330
|
+
description: "\u5728\u6307\u5B9A\u7528\u6237\u7684\u5C0F\u732B\u5934\u50CF\u4E0A\u663E\u793A\u4E00\u4E2A\u6C14\u6CE1\uFF08\u77ED\u6D88\u606F\u63D0\u793A\uFF09\u3002",
|
|
312
331
|
schema: {
|
|
313
332
|
type: "object",
|
|
314
333
|
properties: {
|
|
@@ -319,9 +338,10 @@ function createBubbleTool(options) {
|
|
|
319
338
|
description: "\u6C14\u6CE1\u91CC\u7684\u6587\u5B57"
|
|
320
339
|
},
|
|
321
340
|
target: {
|
|
322
|
-
type: "
|
|
323
|
-
|
|
324
|
-
|
|
341
|
+
type: "integer",
|
|
342
|
+
minimum: 1,
|
|
343
|
+
maximum: 4,
|
|
344
|
+
description: "\u663E\u793A\u5728\u54EA\u4E2A\u7528\u6237\u7684\u5C0F\u732B\u4E0A\uFF081=No.1/\u672C\u5730\u7528\u6237\uFF0C2=No.2\uFF0C3=No.3\uFF0C4=No.4\uFF09"
|
|
325
345
|
},
|
|
326
346
|
durationMs: {
|
|
327
347
|
type: "integer",
|
|
@@ -477,15 +497,23 @@ function lastAiText(messages) {
|
|
|
477
497
|
return null;
|
|
478
498
|
}
|
|
479
499
|
function createSystemPrompt(context) {
|
|
500
|
+
const peerList = context.peers ?? [];
|
|
501
|
+
const userList = [
|
|
502
|
+
`No.1: ${context.localName} (\u6211/\u672C\u5730\u7528\u6237)`,
|
|
503
|
+
peerList[0] ? `No.2: ${peerList[0].name}` : "No.2: (\u7A7A\u4F4D)",
|
|
504
|
+
peerList[1] ? `No.3: ${peerList[1].name}` : "No.3: (\u7A7A\u4F4D)",
|
|
505
|
+
peerList[2] ? `No.4: ${peerList[2].name}` : "No.4: (\u7A7A\u4F4D)"
|
|
506
|
+
].join("\u3001");
|
|
480
507
|
return [
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
`\u5F53\u524D\
|
|
508
|
+
`\u4F60\u662F TermBuddy \u91CC\u7684\u300C\u58F3\u4E2D\u5E7D\u7075 (Ghost in the Shell)\u300D\u3002`,
|
|
509
|
+
`\u9ED8\u8BA4\u9690\u5F62\uFF1B\u88AB / \u5524\u9192\u65F6\u51FA\u73B0\u3002\u98CE\u683C\uFF1A\u6781\u7B80\u3001\u5E72\u7EC3\u3001\u5C11\u5E9F\u8BDD\u3002`,
|
|
510
|
+
`\u4F60\u53EF\u4EE5\u4F7F\u7528\u5DE5\u5177\u6765\u64CD\u63A7\u5E94\u7528\u529F\u80FD\uFF08\u4F8B\u5982\u5012\u8BA1\u65F6\uFF09\u3002`,
|
|
511
|
+
`\u5982\u679C\u7528\u6237\u63D0\u5230\u300C\u5012\u8BA1\u65F6/\u4E13\u6CE8/\u8BA1\u65F6/countdown\u300D\uFF0C\u4F18\u5148\u8C03\u7528 start_countdown\u3002`,
|
|
512
|
+
`\u5982\u679C\u7528\u6237\u63D0\u5230\u300C\u6C14\u6CE1/\u6CE1\u6CE1/\u63D0\u793A/\u8BF4\u4E00\u53E5/\u548C\u67D0\u4EBA\u8BF4\u300D\uFF0C\u4F18\u5148\u8C03\u7528 show_bubble\uFF0C\u5E76\u6839\u636E\u76EE\u6807\u7528\u6237\u8BBE\u7F6E target \u53C2\u6570\uFF081-4\uFF09\u3002`,
|
|
513
|
+
`\u5982\u679C\u7528\u6237\u63D0\u5230\u300C\u4E92\u52A8/\u6254/\u6295\u63B7/throw\u300D\uFF0C\u4F18\u5148\u8C03\u7528 throw_projectile\u3002`,
|
|
514
|
+
`\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u6295\u63B7 N \u6B21\u4E14 1<=N<=100 \u65F6\uFF0C\u5FC5\u987B\u6309 N \u6267\u884C\uFF1A\u91CD\u590D\u8C03\u7528 throw_projectile \u5171 N \u6B21\uFF0C\u4E0D\u8981\u6539\u6210\u300C\u793A\u610F/\u5C11\u91CF\u51E0\u6B21\u300D\u3002\u8D85\u8FC7 100 \u5219\u5206\u6279\u591A\u6B21\u8C03\u7528\u3002`,
|
|
515
|
+
`\u5F53\u524D\u623F\u95F4\u67094\u4E2A\u4F4D\u7F6E\uFF0C\u7528\u6237\u5217\u8868\uFF1A${userList}\u3002`,
|
|
516
|
+
`\u6211\u662F ${context.localName}\uFF08No.1\uFF09\u3002`
|
|
489
517
|
].join("\n");
|
|
490
518
|
}
|
|
491
519
|
function useAiAgent(options) {
|
|
@@ -547,7 +575,8 @@ function useAiAgent(options) {
|
|
|
547
575
|
tools: [startCountdown, showBubble, interaction, sessionInfo],
|
|
548
576
|
systemPrompt: createSystemPrompt({
|
|
549
577
|
localName: options.localName,
|
|
550
|
-
peerName: options.peerName
|
|
578
|
+
peerName: options.peerName,
|
|
579
|
+
peers: options.peers
|
|
551
580
|
}),
|
|
552
581
|
name: "ghost"
|
|
553
582
|
});
|
|
@@ -560,7 +589,8 @@ function useAiAgent(options) {
|
|
|
560
589
|
options.onStartCountdown,
|
|
561
590
|
options.onShowBubble,
|
|
562
591
|
options.onThrowProjectile,
|
|
563
|
-
options.peerName
|
|
592
|
+
options.peerName,
|
|
593
|
+
options.peers
|
|
564
594
|
]);
|
|
565
595
|
const ask = useCallback2(
|
|
566
596
|
async (text) => {
|
|
@@ -829,7 +859,13 @@ function useTcpSync(options) {
|
|
|
829
859
|
syncPeersState();
|
|
830
860
|
}
|
|
831
861
|
}, [broadcastPacket, syncPeersState]);
|
|
862
|
+
const MAX_PEERS = 4;
|
|
832
863
|
const attachPeerSocket = useCallback3((socket) => {
|
|
864
|
+
if (peerConnectionsRef.current.size >= MAX_PEERS - 1) {
|
|
865
|
+
socket.end();
|
|
866
|
+
socket.destroy();
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
833
869
|
const peerId = generatePeerId();
|
|
834
870
|
let buf = "";
|
|
835
871
|
socket.setNoDelay(true);
|
|
@@ -1287,6 +1323,7 @@ function AiConsole(props) {
|
|
|
1287
1323
|
const agent = useAiAgent({
|
|
1288
1324
|
localName: props.localName,
|
|
1289
1325
|
peerName: props.peerName,
|
|
1326
|
+
peers: props.peers,
|
|
1290
1327
|
onStartCountdown: props.onStartCountdown,
|
|
1291
1328
|
onShowBubble: props.onShowBubble,
|
|
1292
1329
|
onThrowProjectile: props.onThrowProjectile,
|
|
@@ -1712,6 +1749,75 @@ var init_StatusHeader = __esm({
|
|
|
1712
1749
|
}
|
|
1713
1750
|
});
|
|
1714
1751
|
|
|
1752
|
+
// src/components/InfoPanel.tsx
|
|
1753
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
1754
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1755
|
+
function InfoPanel(props) {
|
|
1756
|
+
const maxRecords = props.maxRecords ?? 8;
|
|
1757
|
+
const displayRecords = props.records.slice(-maxRecords);
|
|
1758
|
+
const formatTime = (ts) => {
|
|
1759
|
+
const d = new Date(ts);
|
|
1760
|
+
return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
1761
|
+
};
|
|
1762
|
+
const getTypeIcon = (type) => {
|
|
1763
|
+
switch (type) {
|
|
1764
|
+
case "bubble":
|
|
1765
|
+
return "[Msg]";
|
|
1766
|
+
case "countdown":
|
|
1767
|
+
return "[Tmr]";
|
|
1768
|
+
case "projectile":
|
|
1769
|
+
return "[Thr]";
|
|
1770
|
+
case "join":
|
|
1771
|
+
return "[+]";
|
|
1772
|
+
case "leave":
|
|
1773
|
+
return "[-]";
|
|
1774
|
+
default:
|
|
1775
|
+
return "[*]";
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1778
|
+
const getTypeColor = (type) => {
|
|
1779
|
+
switch (type) {
|
|
1780
|
+
case "bubble":
|
|
1781
|
+
return "cyan";
|
|
1782
|
+
case "countdown":
|
|
1783
|
+
return "green";
|
|
1784
|
+
case "projectile":
|
|
1785
|
+
return "magenta";
|
|
1786
|
+
case "join":
|
|
1787
|
+
return "green";
|
|
1788
|
+
case "leave":
|
|
1789
|
+
return "red";
|
|
1790
|
+
default:
|
|
1791
|
+
return "gray";
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", borderStyle: "round", paddingX: 1, paddingY: 0, children: [
|
|
1795
|
+
/* @__PURE__ */ jsxs10(Box11, { justifyContent: "space-between", marginBottom: 0, children: [
|
|
1796
|
+
/* @__PURE__ */ jsx11(Text11, { color: "yellow", children: "Info Log" }),
|
|
1797
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "gray", children: [
|
|
1798
|
+
displayRecords.length,
|
|
1799
|
+
" records"
|
|
1800
|
+
] })
|
|
1801
|
+
] }),
|
|
1802
|
+
/* @__PURE__ */ jsx11(Box11, { flexDirection: "column", minHeight: 6, children: displayRecords.length === 0 ? /* @__PURE__ */ jsx11(Text11, { color: "gray", children: "No records yet..." }) : displayRecords.map((record) => /* @__PURE__ */ jsxs10(Text11, { wrap: "truncate-end", children: [
|
|
1803
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "gray", children: [
|
|
1804
|
+
formatTime(record.timestamp),
|
|
1805
|
+
" "
|
|
1806
|
+
] }),
|
|
1807
|
+
/* @__PURE__ */ jsxs10(Text11, { color: getTypeColor(record.type), children: [
|
|
1808
|
+
getTypeIcon(record.type),
|
|
1809
|
+
" "
|
|
1810
|
+
] }),
|
|
1811
|
+
/* @__PURE__ */ jsx11(Text11, { children: record.content })
|
|
1812
|
+
] }, record.id)) })
|
|
1813
|
+
] });
|
|
1814
|
+
}
|
|
1815
|
+
var init_InfoPanel = __esm({
|
|
1816
|
+
"src/components/InfoPanel.tsx"() {
|
|
1817
|
+
"use strict";
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
|
|
1715
1821
|
// src/components/index.ts
|
|
1716
1822
|
var init_components = __esm({
|
|
1717
1823
|
"src/components/index.ts"() {
|
|
@@ -1721,13 +1827,14 @@ var init_components = __esm({
|
|
|
1721
1827
|
init_CountdownClockSprite();
|
|
1722
1828
|
init_ProjectileThrowSprite();
|
|
1723
1829
|
init_StatusHeader();
|
|
1830
|
+
init_InfoPanel();
|
|
1724
1831
|
}
|
|
1725
1832
|
});
|
|
1726
1833
|
|
|
1727
1834
|
// src/page/Session.tsx
|
|
1728
1835
|
import { useCallback as useCallback4, useEffect as useEffect8, useMemo as useMemo8, useRef as useRef4, useState as useState8 } from "react";
|
|
1729
|
-
import { Box as
|
|
1730
|
-
import { Fragment as Fragment2, jsx as
|
|
1836
|
+
import { Box as Box12, Text as Text12, useInput as useInput7 } from "ink";
|
|
1837
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1731
1838
|
function formatMMSS(totalSeconds) {
|
|
1732
1839
|
const m = Math.floor(totalSeconds / 60);
|
|
1733
1840
|
const s = totalSeconds % 60;
|
|
@@ -1741,9 +1848,19 @@ function Session(props) {
|
|
|
1741
1848
|
const [showAi, setShowAi] = useState8(false);
|
|
1742
1849
|
const [countdown, setCountdown] = useState8(null);
|
|
1743
1850
|
const [shots, setShots] = useState8([]);
|
|
1744
|
-
const [
|
|
1745
|
-
const [
|
|
1746
|
-
const
|
|
1851
|
+
const [peerBubbles, setPeerBubbles] = useState8([null, null, null, null]);
|
|
1852
|
+
const bubbleTimersRef = useRef4([null, null, null, null]);
|
|
1853
|
+
const [infoRecords, setInfoRecords] = useState8([]);
|
|
1854
|
+
const nextRecordIdRef = useRef4(1);
|
|
1855
|
+
const addInfoRecord = useCallback4((type, content) => {
|
|
1856
|
+
const record = {
|
|
1857
|
+
id: nextRecordIdRef.current++,
|
|
1858
|
+
timestamp: Date.now(),
|
|
1859
|
+
type,
|
|
1860
|
+
content
|
|
1861
|
+
};
|
|
1862
|
+
setInfoRecords((prev) => [...prev, record]);
|
|
1863
|
+
}, []);
|
|
1747
1864
|
const tcpOptions = useMemo8(() => {
|
|
1748
1865
|
return props.role === "host" ? { role: "host", localName: props.localName } : {
|
|
1749
1866
|
role: "client",
|
|
@@ -1772,6 +1889,23 @@ function Session(props) {
|
|
|
1772
1889
|
const localActivity = useActivityMonitor();
|
|
1773
1890
|
const peers = tcp.peers;
|
|
1774
1891
|
const firstPeerName = peers.length > 0 ? peers[0].name : void 0;
|
|
1892
|
+
const prevPeersRef = useRef4([]);
|
|
1893
|
+
useEffect8(() => {
|
|
1894
|
+
const prevPeers = prevPeersRef.current;
|
|
1895
|
+
const prevNames = new Set(prevPeers.map((p) => p.name));
|
|
1896
|
+
const currentNames = new Set(peers.map((p) => p.name));
|
|
1897
|
+
peers.forEach((p) => {
|
|
1898
|
+
if (!prevNames.has(p.name)) {
|
|
1899
|
+
addInfoRecord("join", `${p.name} joined`);
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
prevPeers.forEach((p) => {
|
|
1903
|
+
if (!currentNames.has(p.name)) {
|
|
1904
|
+
addInfoRecord("leave", `${p.name} left`);
|
|
1905
|
+
}
|
|
1906
|
+
});
|
|
1907
|
+
prevPeersRef.current = [...peers];
|
|
1908
|
+
}, [peers, addInfoRecord]);
|
|
1775
1909
|
const onToggleAi = useCallback4(() => setShowAi((v) => !v), []);
|
|
1776
1910
|
const onCloseAi = useCallback4(() => setShowAi(false), []);
|
|
1777
1911
|
const sessionStartAtRef = useRef4(Date.now());
|
|
@@ -1846,7 +1980,8 @@ function Session(props) {
|
|
|
1846
1980
|
remainingSeconds: totalSeconds,
|
|
1847
1981
|
type
|
|
1848
1982
|
});
|
|
1849
|
-
|
|
1983
|
+
addInfoRecord("countdown", `Started ${minutes}min countdown`);
|
|
1984
|
+
}, [addInfoRecord]);
|
|
1850
1985
|
const nextShotIdRef = useRef4(1);
|
|
1851
1986
|
const shotQueueRef = useRef4([]);
|
|
1852
1987
|
const pumpShotQueue = useCallback4(() => {
|
|
@@ -1866,27 +2001,35 @@ function Session(props) {
|
|
|
1866
2001
|
shotQueueRef.current.push({ kind, direction });
|
|
1867
2002
|
pumpShotQueue();
|
|
1868
2003
|
if (tcp.status === "connected") tcp.sendProjectile(kind, direction);
|
|
2004
|
+
addInfoRecord("projectile", `Threw ${kind}`);
|
|
1869
2005
|
},
|
|
1870
|
-
[pumpShotQueue, tcp]
|
|
2006
|
+
[pumpShotQueue, tcp, addInfoRecord]
|
|
1871
2007
|
);
|
|
1872
2008
|
const showBubble = useCallback4(
|
|
1873
2009
|
(args) => {
|
|
1874
2010
|
const text = args.text.trim();
|
|
1875
2011
|
if (!text) return;
|
|
1876
2012
|
const durationMs = Math.max(300, Math.min(15e3, Math.floor(args.durationMs)));
|
|
1877
|
-
const
|
|
1878
|
-
|
|
1879
|
-
|
|
2013
|
+
const targetIndex = Math.max(0, Math.min(3, args.target - 1));
|
|
2014
|
+
setPeerBubbles((prev) => {
|
|
2015
|
+
const next = [...prev];
|
|
2016
|
+
next[targetIndex] = text;
|
|
2017
|
+
return next;
|
|
2018
|
+
});
|
|
2019
|
+
const prevTimer = bubbleTimersRef.current[targetIndex];
|
|
1880
2020
|
if (prevTimer) clearTimeout(prevTimer);
|
|
1881
2021
|
const handle = setTimeout(() => {
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
2022
|
+
setPeerBubbles((prev) => {
|
|
2023
|
+
const next = [...prev];
|
|
2024
|
+
next[targetIndex] = null;
|
|
2025
|
+
return next;
|
|
2026
|
+
});
|
|
2027
|
+
bubbleTimersRef.current[targetIndex] = null;
|
|
1885
2028
|
}, durationMs);
|
|
1886
|
-
|
|
1887
|
-
|
|
2029
|
+
bubbleTimersRef.current[targetIndex] = handle;
|
|
2030
|
+
addInfoRecord("bubble", `No.${args.target}: "${text}"`);
|
|
1888
2031
|
},
|
|
1889
|
-
[]
|
|
2032
|
+
[addInfoRecord]
|
|
1890
2033
|
);
|
|
1891
2034
|
useInput7(
|
|
1892
2035
|
(input, key) => {
|
|
@@ -1932,12 +2075,13 @@ function Session(props) {
|
|
|
1932
2075
|
}, [countdown?.endsAt]);
|
|
1933
2076
|
useEffect8(() => {
|
|
1934
2077
|
return () => {
|
|
1935
|
-
|
|
1936
|
-
|
|
2078
|
+
bubbleTimersRef.current.forEach((timer) => {
|
|
2079
|
+
if (timer) clearTimeout(timer);
|
|
2080
|
+
});
|
|
1937
2081
|
};
|
|
1938
2082
|
}, []);
|
|
1939
|
-
return /* @__PURE__ */
|
|
1940
|
-
/* @__PURE__ */
|
|
2083
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", padding: 1, children: [
|
|
2084
|
+
/* @__PURE__ */ jsx12(
|
|
1941
2085
|
StatusHeader,
|
|
1942
2086
|
{
|
|
1943
2087
|
role: props.role,
|
|
@@ -1947,108 +2091,118 @@ function Session(props) {
|
|
|
1947
2091
|
peerCount: peers.length
|
|
1948
2092
|
}
|
|
1949
2093
|
),
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2094
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", marginTop: 1, children: [
|
|
2095
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", width: "100%", alignItems: "center", marginBottom: 1, children: [
|
|
2096
|
+
shots.map((s) => /* @__PURE__ */ jsx12(
|
|
2097
|
+
ProjectileThrowSprite,
|
|
2098
|
+
{
|
|
2099
|
+
kind: s.kind,
|
|
2100
|
+
direction: s.direction,
|
|
2101
|
+
shotId: s.id,
|
|
2102
|
+
width: 50,
|
|
2103
|
+
onDone: () => setShots((prev) => prev.filter((x) => x.id !== s.id))
|
|
2104
|
+
},
|
|
2105
|
+
String(s.id)
|
|
2106
|
+
)),
|
|
2107
|
+
shots.length === 0 ? /* @__PURE__ */ jsx12(Box12, { height: 1 }) : null
|
|
2108
|
+
] }),
|
|
2109
|
+
countdown ? /* @__PURE__ */ jsx12(Box12, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", alignItems: "center", children: [
|
|
2110
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: formatMMSS(countdown.remainingSeconds) }),
|
|
2111
|
+
/* @__PURE__ */ jsx12(
|
|
2112
|
+
CountdownClockSprite,
|
|
2113
|
+
{
|
|
2114
|
+
variant: "COMPACT",
|
|
2115
|
+
type: countdown.type,
|
|
2116
|
+
minutes: countdown.minutes,
|
|
2117
|
+
totalSeconds: countdown.totalSeconds,
|
|
2118
|
+
remainingSeconds: countdown.remainingSeconds,
|
|
2119
|
+
showLabel: false
|
|
2120
|
+
}
|
|
2121
|
+
)
|
|
2122
|
+
] }) }) : null,
|
|
2123
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", alignItems: "center", children: [
|
|
2124
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", justifyContent: "center", gap: 4, children: [
|
|
2125
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", alignItems: "center", minWidth: 18, children: [
|
|
2126
|
+
/* @__PURE__ */ jsxs11(Text12, { color: "cyan", bold: true, children: [
|
|
2127
|
+
"No.1 ",
|
|
2128
|
+
props.localName
|
|
2129
|
+
] }),
|
|
2130
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: localState, marginTop: 0, bubbleText: peerBubbles[0] ?? null })
|
|
1976
2131
|
] }),
|
|
1977
|
-
/* @__PURE__ */
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
ProjectileThrowSprite,
|
|
1987
|
-
{
|
|
1988
|
-
kind: s.kind,
|
|
1989
|
-
direction: s.direction,
|
|
1990
|
-
shotId: s.id,
|
|
1991
|
-
width: 36,
|
|
1992
|
-
onDone: () => setShots((prev) => prev.filter((x) => x.id !== s.id))
|
|
1993
|
-
},
|
|
1994
|
-
String(s.id)
|
|
1995
|
-
)),
|
|
1996
|
-
shots.length === 0 ? /* @__PURE__ */ jsx11(Box11, { height: 1 }) : null
|
|
1997
|
-
] })
|
|
1998
|
-
}
|
|
1999
|
-
),
|
|
2000
|
-
/* @__PURE__ */ jsx11(Box11, { flexDirection: "column", alignItems: "center", minWidth: 20, children: peers.length === 0 ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
2001
|
-
/* @__PURE__ */ jsx11(Box11, { height: 4 }),
|
|
2002
|
-
/* @__PURE__ */ jsx11(BuddyAvatar, { state: "OFFLINE", marginTop: 0, bubbleText: buddyBubble }),
|
|
2003
|
-
/* @__PURE__ */ jsx11(Text11, { color: "gray", children: "Waiting..." })
|
|
2004
|
-
] }) : /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", gap: 2, flexWrap: "wrap", justifyContent: "center", children: [
|
|
2005
|
-
peers.slice(0, 4).map((peer) => /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", alignItems: "center", children: [
|
|
2006
|
-
/* @__PURE__ */ jsx11(BuddyAvatar, { state: peer.state, marginTop: 0, bubbleText: buddyBubble }),
|
|
2007
|
-
/* @__PURE__ */ jsx11(Text11, { color: "magenta", children: peer.name })
|
|
2008
|
-
] }, peer.id)),
|
|
2009
|
-
peers.length > 4 && /* @__PURE__ */ jsxs10(Text11, { color: "gray", children: [
|
|
2010
|
-
"+",
|
|
2011
|
-
peers.length - 4,
|
|
2012
|
-
" more"
|
|
2013
|
-
] })
|
|
2132
|
+
/* @__PURE__ */ jsx12(Box12, { flexDirection: "column", alignItems: "center", minWidth: 18, children: peers.length >= 1 ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2133
|
+
/* @__PURE__ */ jsxs11(Text12, { color: "magenta", bold: true, children: [
|
|
2134
|
+
"No.2 ",
|
|
2135
|
+
peers[0].name
|
|
2136
|
+
] }),
|
|
2137
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: peers[0].state, marginTop: 0, bubbleText: peerBubbles[1] ?? null })
|
|
2138
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2139
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: "No.2 (Empty)" }),
|
|
2140
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: "OFFLINE", marginTop: 0 })
|
|
2014
2141
|
] }) })
|
|
2015
|
-
]
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2142
|
+
] }),
|
|
2143
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", justifyContent: "center", gap: 4, marginTop: 1, children: [
|
|
2144
|
+
/* @__PURE__ */ jsx12(Box12, { flexDirection: "column", alignItems: "center", minWidth: 18, children: peers.length >= 2 ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2145
|
+
/* @__PURE__ */ jsxs11(Text12, { color: "magenta", bold: true, children: [
|
|
2146
|
+
"No.3 ",
|
|
2147
|
+
peers[1].name
|
|
2148
|
+
] }),
|
|
2149
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: peers[1].state, marginTop: 0, bubbleText: peerBubbles[2] ?? null })
|
|
2150
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2151
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: "No.3 (Empty)" }),
|
|
2152
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: "OFFLINE", marginTop: 0 })
|
|
2153
|
+
] }) }),
|
|
2154
|
+
/* @__PURE__ */ jsx12(Box12, { flexDirection: "column", alignItems: "center", minWidth: 18, children: peers.length >= 3 ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2155
|
+
/* @__PURE__ */ jsxs11(Text12, { color: "magenta", bold: true, children: [
|
|
2156
|
+
"No.4 ",
|
|
2157
|
+
peers[2].name
|
|
2158
|
+
] }),
|
|
2159
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: peers[2].state, marginTop: 0, bubbleText: peerBubbles[3] ?? null })
|
|
2160
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2161
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: "No.4 (Empty)" }),
|
|
2162
|
+
/* @__PURE__ */ jsx12(BuddyAvatar, { state: "OFFLINE", marginTop: 0 })
|
|
2163
|
+
] }) })
|
|
2164
|
+
] })
|
|
2165
|
+
] })
|
|
2166
|
+
] }),
|
|
2167
|
+
!showAi ? /* @__PURE__ */ jsx12(Box12, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsxs11(Text12, { color: "gray", children: [
|
|
2019
2168
|
"\u6309 ",
|
|
2020
|
-
/* @__PURE__ */
|
|
2169
|
+
/* @__PURE__ */ jsx12(Text12, { color: "cyan", children: "/" }),
|
|
2021
2170
|
" \u53EC\u5524 AI Console\uFF0C\u6309",
|
|
2022
2171
|
" ",
|
|
2023
|
-
/* @__PURE__ */
|
|
2172
|
+
/* @__PURE__ */ jsx12(Text12, { color: "cyan", children: "q" }),
|
|
2024
2173
|
" \u7ED3\u675F\u672C\u6B21\u966A\u4F34\u3002",
|
|
2025
|
-
countdown ? /* @__PURE__ */
|
|
2174
|
+
countdown ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2026
2175
|
" ",
|
|
2027
|
-
/* @__PURE__ */
|
|
2176
|
+
/* @__PURE__ */ jsxs11(Text12, { color: "gray", children: [
|
|
2028
2177
|
"(\u5012\u8BA1\u65F6\u4E2D\uFF1A\u6309 ",
|
|
2029
|
-
/* @__PURE__ */
|
|
2178
|
+
/* @__PURE__ */ jsx12(Text12, { color: "cyan", children: "x" }),
|
|
2030
2179
|
" \u53D6\u6D88)"
|
|
2031
2180
|
] })
|
|
2032
2181
|
] }) : null
|
|
2033
2182
|
] }) }) : null,
|
|
2034
|
-
showAi ? /* @__PURE__ */
|
|
2035
|
-
|
|
2183
|
+
showAi ? /* @__PURE__ */ jsxs11(
|
|
2184
|
+
Box12,
|
|
2036
2185
|
{
|
|
2037
2186
|
marginTop: 1,
|
|
2038
2187
|
width: "100%",
|
|
2039
2188
|
flexDirection: "row",
|
|
2040
2189
|
justifyContent: "center",
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
{
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2190
|
+
gap: 2,
|
|
2191
|
+
children: [
|
|
2192
|
+
/* @__PURE__ */ jsx12(Box12, { width: 48, children: /* @__PURE__ */ jsx12(
|
|
2193
|
+
AiConsole,
|
|
2194
|
+
{
|
|
2195
|
+
onClose: onCloseAi,
|
|
2196
|
+
onStartCountdown: startCountdown,
|
|
2197
|
+
onShowBubble: showBubble,
|
|
2198
|
+
onThrowProjectile: throwProjectile,
|
|
2199
|
+
localName: props.localName,
|
|
2200
|
+
peerName: firstPeerName ?? (props.role === "client" ? props.hostName : void 0) ?? "Buddy",
|
|
2201
|
+
peers
|
|
2202
|
+
}
|
|
2203
|
+
) }),
|
|
2204
|
+
/* @__PURE__ */ jsx12(Box12, { width: 32, children: /* @__PURE__ */ jsx12(InfoPanel, { records: infoRecords, maxRecords: 6 }) })
|
|
2205
|
+
]
|
|
2052
2206
|
}
|
|
2053
2207
|
) : null
|
|
2054
2208
|
] });
|
|
@@ -2078,7 +2232,7 @@ var init_page = __esm({
|
|
|
2078
2232
|
import { useCallback as useCallback5, useMemo as useMemo9, useState as useState9 } from "react";
|
|
2079
2233
|
import os3 from "os";
|
|
2080
2234
|
import { useApp } from "ink";
|
|
2081
|
-
import { jsx as
|
|
2235
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
2082
2236
|
function App() {
|
|
2083
2237
|
const { exit } = useApp();
|
|
2084
2238
|
const [view, setView] = useState9({ name: "NICKNAME" });
|
|
@@ -2086,7 +2240,7 @@ function App() {
|
|
|
2086
2240
|
const localName = useMemo9(() => nickname ?? os3.hostname(), [nickname]);
|
|
2087
2241
|
const goMenu = useCallback5(() => setView({ name: "MENU" }), []);
|
|
2088
2242
|
if (view.name === "NICKNAME") {
|
|
2089
|
-
return /* @__PURE__ */
|
|
2243
|
+
return /* @__PURE__ */ jsx13(
|
|
2090
2244
|
NicknamePrompt,
|
|
2091
2245
|
{
|
|
2092
2246
|
onExit: () => exit(),
|
|
@@ -2098,7 +2252,7 @@ function App() {
|
|
|
2098
2252
|
);
|
|
2099
2253
|
}
|
|
2100
2254
|
if (view.name === "MENU") {
|
|
2101
|
-
return /* @__PURE__ */
|
|
2255
|
+
return /* @__PURE__ */ jsx13(
|
|
2102
2256
|
MainMenu,
|
|
2103
2257
|
{
|
|
2104
2258
|
onHost: () => setView({ name: "SESSION", role: "host" }),
|
|
@@ -2108,10 +2262,10 @@ function App() {
|
|
|
2108
2262
|
);
|
|
2109
2263
|
}
|
|
2110
2264
|
if (view.name === "LEAVE") {
|
|
2111
|
-
return /* @__PURE__ */
|
|
2265
|
+
return /* @__PURE__ */ jsx13(LeavePage, { stats: view.stats, onBack: goMenu, onExit: () => exit() });
|
|
2112
2266
|
}
|
|
2113
2267
|
if (view.name === "SCANNING") {
|
|
2114
|
-
return /* @__PURE__ */
|
|
2268
|
+
return /* @__PURE__ */ jsx13(
|
|
2115
2269
|
RoomScanner,
|
|
2116
2270
|
{
|
|
2117
2271
|
onBack: goMenu,
|
|
@@ -2128,7 +2282,7 @@ function App() {
|
|
|
2128
2282
|
);
|
|
2129
2283
|
}
|
|
2130
2284
|
if (view.name === "SESSION" && view.role === "host") {
|
|
2131
|
-
return /* @__PURE__ */
|
|
2285
|
+
return /* @__PURE__ */ jsx13(
|
|
2132
2286
|
Session,
|
|
2133
2287
|
{
|
|
2134
2288
|
localName,
|
|
@@ -2137,7 +2291,7 @@ function App() {
|
|
|
2137
2291
|
}
|
|
2138
2292
|
);
|
|
2139
2293
|
}
|
|
2140
|
-
return /* @__PURE__ */
|
|
2294
|
+
return /* @__PURE__ */ jsx13(
|
|
2141
2295
|
Session,
|
|
2142
2296
|
{
|
|
2143
2297
|
localName,
|