@fengye404/termpilot 0.1.1 → 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/README.md +59 -3
- package/app/dist/assets/index-CCXqowYd.css +1 -0
- package/app/dist/assets/index-CyNBuXm-.js +20 -0
- package/app/dist/index.html +2 -2
- package/app/dist/sw.js +1 -1
- package/dist/cli.js +244 -15
- package/docs/development.md +6 -1
- package/package.json +2 -2
- package/app/dist/assets/index-CahDnY4p.js +0 -20
- package/app/dist/assets/index-nVgFrQ_J.css +0 -1
package/app/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
6
|
<meta name="theme-color" content="#0f172a" />
|
|
7
7
|
<title>TermPilot</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CyNBuXm-.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CCXqowYd.css">
|
|
10
10
|
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
|
|
11
11
|
<body class="bg-slate-950">
|
|
12
12
|
<div id="root"></div>
|
package/app/dist/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let o={};const c=e=>i(e,t),
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let o={};const c=e=>i(e,t),d={module:{uri:t},exports:o,require:c};s[t]=Promise.all(n.map(e=>d[e]||c(e))).then(e=>(r(...e),o))}}define(["./workbox-1d3d89e3"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"index.html",revision:"62d1459fd4ff940e1a94025c3dc4d076"},{url:"assets/index-CyNBuXm-.js",revision:null},{url:"assets/index-CCXqowYd.css",revision:null},{url:"manifest.webmanifest",revision:"97cf47c913710ef5ce3dc79cf9c7c245"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,10 @@ import path3 from "path";
|
|
|
5
5
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6
6
|
|
|
7
7
|
// agent/src/cli.ts
|
|
8
|
+
import { spawn as spawn2 } from "child_process";
|
|
9
|
+
import { openSync as openSync2 } from "fs";
|
|
8
10
|
import { cwd as processCwd2 } from "process";
|
|
11
|
+
import { setTimeout as delay2 } from "timers/promises";
|
|
9
12
|
|
|
10
13
|
// agent/src/daemon.ts
|
|
11
14
|
import { setTimeout as delay } from "timers/promises";
|
|
@@ -44,6 +47,12 @@ function getAgentHome() {
|
|
|
44
47
|
function getStateFilePath() {
|
|
45
48
|
return path.join(getAgentHome(), "state.json");
|
|
46
49
|
}
|
|
50
|
+
function getAgentRuntimeFilePath() {
|
|
51
|
+
return path.join(getAgentHome(), "agent-runtime.json");
|
|
52
|
+
}
|
|
53
|
+
function getAgentLogFilePath() {
|
|
54
|
+
return path.join(getAgentHome(), "agent.log");
|
|
55
|
+
}
|
|
47
56
|
function getStateLockPath() {
|
|
48
57
|
return `${getStateFilePath()}.lock`;
|
|
49
58
|
}
|
|
@@ -136,6 +145,36 @@ function updateSession(sid, updater) {
|
|
|
136
145
|
return nextState;
|
|
137
146
|
});
|
|
138
147
|
}
|
|
148
|
+
function loadAgentRuntime() {
|
|
149
|
+
ensureAgentHome();
|
|
150
|
+
try {
|
|
151
|
+
const raw = readFileSync(getAgentRuntimeFilePath(), "utf8");
|
|
152
|
+
const parsed = JSON.parse(raw);
|
|
153
|
+
if (typeof parsed.pid !== "number" || typeof parsed.relayUrl !== "string" || typeof parsed.deviceId !== "string" || typeof parsed.startedAt !== "string") {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
pid: parsed.pid,
|
|
158
|
+
relayUrl: parsed.relayUrl,
|
|
159
|
+
deviceId: parsed.deviceId,
|
|
160
|
+
startedAt: parsed.startedAt
|
|
161
|
+
};
|
|
162
|
+
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function saveAgentRuntime(runtime) {
|
|
167
|
+
ensureAgentHome();
|
|
168
|
+
writeFileSync(getAgentRuntimeFilePath(), `${JSON.stringify(runtime, null, 2)}
|
|
169
|
+
`, "utf8");
|
|
170
|
+
}
|
|
171
|
+
function clearAgentRuntime(expectedPid) {
|
|
172
|
+
const current = loadAgentRuntime();
|
|
173
|
+
if (expectedPid !== void 0 && current?.pid !== expectedPid) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
rmSync(getAgentRuntimeFilePath(), { force: true });
|
|
177
|
+
}
|
|
139
178
|
|
|
140
179
|
// agent/src/tmux-backend.ts
|
|
141
180
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -182,7 +221,7 @@ async function createSession(input = {}) {
|
|
|
182
221
|
const name = input.name?.trim() || `session-${sid.slice(0, 6)}`;
|
|
183
222
|
const shell = input.shell?.trim() || process.env.SHELL || "/bin/zsh";
|
|
184
223
|
const workingDirectory = input.cwd?.trim() || processCwd();
|
|
185
|
-
const deviceId = input.deviceId || DEFAULT_DEVICE_ID;
|
|
224
|
+
const deviceId = input.deviceId?.trim() || process.env.TERMPILOT_DEVICE_ID || DEFAULT_DEVICE_ID;
|
|
186
225
|
const startedAt = now();
|
|
187
226
|
const tmuxSessionName = buildTmuxSessionName(sid, name);
|
|
188
227
|
await runTmux(["new-session", "-d", "-s", tmuxSessionName, "-c", workingDirectory, shell]);
|
|
@@ -677,6 +716,11 @@ function printHelp() {
|
|
|
677
716
|
console.log(`TermPilot agent \u7528\u6CD5\uFF1A
|
|
678
717
|
|
|
679
718
|
termpilot agent
|
|
719
|
+
termpilot agent --foreground
|
|
720
|
+
termpilot agent status
|
|
721
|
+
termpilot agent stop
|
|
722
|
+
termpilot claude code
|
|
723
|
+
termpilot run -- claude code
|
|
680
724
|
termpilot create --name claude-main --cwd /path/to/project
|
|
681
725
|
termpilot list
|
|
682
726
|
termpilot kill --sid <sid>
|
|
@@ -771,6 +815,175 @@ function getDeviceId(argv) {
|
|
|
771
815
|
const args = parseArgs(argv);
|
|
772
816
|
return resolveDeviceId(typeof args.deviceId === "string" ? args.deviceId : void 0);
|
|
773
817
|
}
|
|
818
|
+
function getRelayUrl() {
|
|
819
|
+
return process.env.TERMPILOT_RELAY_URL ?? "ws://127.0.0.1:8787/ws";
|
|
820
|
+
}
|
|
821
|
+
function isProcessAlive(pid) {
|
|
822
|
+
try {
|
|
823
|
+
process.kill(pid, 0);
|
|
824
|
+
return true;
|
|
825
|
+
} catch {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
function readRuntimeStatus() {
|
|
830
|
+
const runtime = loadAgentRuntime();
|
|
831
|
+
if (!runtime) {
|
|
832
|
+
return { runtime: null, alive: false };
|
|
833
|
+
}
|
|
834
|
+
const alive = isProcessAlive(runtime.pid);
|
|
835
|
+
if (!alive) {
|
|
836
|
+
clearAgentRuntime(runtime.pid);
|
|
837
|
+
return { runtime: null, alive: false };
|
|
838
|
+
}
|
|
839
|
+
return { runtime, alive };
|
|
840
|
+
}
|
|
841
|
+
async function waitForPairingCode(deviceId) {
|
|
842
|
+
let lastError = null;
|
|
843
|
+
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
844
|
+
try {
|
|
845
|
+
return await createPairingCode(deviceId);
|
|
846
|
+
} catch (error) {
|
|
847
|
+
lastError = error;
|
|
848
|
+
await delay2(500);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
if (lastError instanceof Error) {
|
|
852
|
+
console.warn(`\u540E\u53F0 agent \u5DF2\u542F\u52A8\uFF0C\u4F46\u6682\u65F6\u8FD8\u6CA1\u62FF\u5230\u914D\u5BF9\u7801\uFF1A${lastError.message}`);
|
|
853
|
+
}
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
async function runStart(argv) {
|
|
857
|
+
const args = parseArgs(argv);
|
|
858
|
+
if (args.foreground) {
|
|
859
|
+
await runDaemon();
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
const deviceId = getDeviceId(argv);
|
|
863
|
+
const relayUrl = getRelayUrl();
|
|
864
|
+
const existing = readRuntimeStatus();
|
|
865
|
+
if (existing.runtime && existing.alive) {
|
|
866
|
+
console.log(`\u540E\u53F0 agent \u5DF2\u5728\u8FD0\u884C\uFF0CPID: ${existing.runtime.pid}`);
|
|
867
|
+
console.log(`\u8BBE\u5907: ${existing.runtime.deviceId}`);
|
|
868
|
+
console.log(`relay: ${existing.runtime.relayUrl}`);
|
|
869
|
+
const pairing2 = await waitForPairingCode(deviceId);
|
|
870
|
+
if (pairing2) {
|
|
871
|
+
console.log(`\u914D\u5BF9\u7801: ${pairing2.pairingCode}`);
|
|
872
|
+
console.log(`\u6709\u6548\u671F\u81F3: ${pairing2.expiresAt}`);
|
|
873
|
+
}
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
clearAgentRuntime();
|
|
877
|
+
const logFilePath = getAgentLogFilePath();
|
|
878
|
+
const logFd = openSync2(logFilePath, "a");
|
|
879
|
+
const child = spawn2(process.execPath, [process.argv[1], "agent-daemon"], {
|
|
880
|
+
detached: true,
|
|
881
|
+
stdio: ["ignore", logFd, logFd],
|
|
882
|
+
env: process.env
|
|
883
|
+
});
|
|
884
|
+
child.unref();
|
|
885
|
+
if (!child.pid) {
|
|
886
|
+
throw new Error("\u540E\u53F0 agent \u542F\u52A8\u5931\u8D25\uFF0C\u672A\u83B7\u53D6\u5230\u5B50\u8FDB\u7A0B PID\u3002");
|
|
887
|
+
}
|
|
888
|
+
saveAgentRuntime({
|
|
889
|
+
pid: child.pid,
|
|
890
|
+
relayUrl,
|
|
891
|
+
deviceId,
|
|
892
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
893
|
+
});
|
|
894
|
+
console.log(`\u540E\u53F0 agent \u5DF2\u542F\u52A8\uFF0CPID: ${child.pid}`);
|
|
895
|
+
console.log(`\u8BBE\u5907: ${deviceId}`);
|
|
896
|
+
console.log(`relay: ${relayUrl}`);
|
|
897
|
+
console.log(`\u65E5\u5FD7: ${logFilePath}`);
|
|
898
|
+
const pairing = await waitForPairingCode(deviceId);
|
|
899
|
+
if (pairing) {
|
|
900
|
+
console.log(`\u914D\u5BF9\u7801: ${pairing.pairingCode}`);
|
|
901
|
+
console.log(`\u6709\u6548\u671F\u81F3: ${pairing.expiresAt}`);
|
|
902
|
+
console.log("\u624B\u673A\u7AEF\u76F4\u63A5\u6253\u5F00 relay \u9875\u9762\u5E76\u8F93\u5165\u8FD9\u4E2A\u914D\u5BF9\u7801\u5373\u53EF\u3002");
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
function runStatus() {
|
|
906
|
+
const { runtime, alive } = readRuntimeStatus();
|
|
907
|
+
if (!runtime || !alive) {
|
|
908
|
+
console.log("\u540E\u53F0 agent \u5F53\u524D\u672A\u8FD0\u884C\u3002");
|
|
909
|
+
console.log(`\u72B6\u6001\u76EE\u5F55: ${getAgentHome()}`);
|
|
910
|
+
console.log(`\u65E5\u5FD7: ${getAgentLogFilePath()}`);
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const sessions = loadState().sessions.filter((session) => session.deviceId === runtime.deviceId);
|
|
914
|
+
const runningSessions = sessions.filter((session) => session.status === "running").length;
|
|
915
|
+
console.log("\u540E\u53F0 agent \u6B63\u5728\u8FD0\u884C\u3002");
|
|
916
|
+
console.log(`PID: ${runtime.pid}`);
|
|
917
|
+
console.log(`\u8BBE\u5907: ${runtime.deviceId}`);
|
|
918
|
+
console.log(`relay: ${runtime.relayUrl}`);
|
|
919
|
+
console.log(`\u542F\u52A8\u65F6\u95F4: ${runtime.startedAt}`);
|
|
920
|
+
console.log(`\u65E5\u5FD7: ${getAgentLogFilePath()}`);
|
|
921
|
+
console.log(`\u4F1A\u8BDD: ${runningSessions} \u4E2A\u8FD0\u884C\u4E2D / ${sessions.length} \u4E2A\u603B\u8BA1`);
|
|
922
|
+
}
|
|
923
|
+
async function runStop() {
|
|
924
|
+
const { runtime, alive } = readRuntimeStatus();
|
|
925
|
+
if (!runtime || !alive) {
|
|
926
|
+
console.log("\u540E\u53F0 agent \u5F53\u524D\u672A\u8FD0\u884C\u3002");
|
|
927
|
+
clearAgentRuntime();
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
process.kill(runtime.pid, "SIGTERM");
|
|
931
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
932
|
+
if (!isProcessAlive(runtime.pid)) {
|
|
933
|
+
clearAgentRuntime(runtime.pid);
|
|
934
|
+
console.log(`\u540E\u53F0 agent \u5DF2\u505C\u6B62\uFF0CPID: ${runtime.pid}`);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
await delay2(100);
|
|
938
|
+
}
|
|
939
|
+
process.kill(runtime.pid, "SIGKILL");
|
|
940
|
+
clearAgentRuntime(runtime.pid);
|
|
941
|
+
console.log(`\u540E\u53F0 agent \u5DF2\u5F3A\u5236\u505C\u6B62\uFF0CPID: ${runtime.pid}`);
|
|
942
|
+
}
|
|
943
|
+
function buildQuickSessionName(commandArgs) {
|
|
944
|
+
const raw = commandArgs.join("-").trim().toLowerCase();
|
|
945
|
+
const normalized = raw.replace(/[^a-z0-9_-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
946
|
+
return normalized.slice(0, 32) || "task";
|
|
947
|
+
}
|
|
948
|
+
async function runManagedCommand(argv) {
|
|
949
|
+
const commandArgs = argv[0] === "--" ? argv.slice(1) : argv;
|
|
950
|
+
if (commandArgs.length === 0) {
|
|
951
|
+
throw new Error("\u8BF7\u5728 termpilot \u540E\u9762\u63D0\u4F9B\u8981\u8FD0\u884C\u7684\u547D\u4EE4\uFF0C\u4F8B\u5982\uFF1Atermpilot claude code");
|
|
952
|
+
}
|
|
953
|
+
const session = await createSession({
|
|
954
|
+
name: buildQuickSessionName(commandArgs),
|
|
955
|
+
cwd: processCwd2(),
|
|
956
|
+
deviceId: resolveDeviceId()
|
|
957
|
+
});
|
|
958
|
+
console.log(`\u5DF2\u521B\u5EFA\u4F1A\u8BDD ${session.sid} (${session.name})`);
|
|
959
|
+
await sendInput(session, `${commandArgs.join(" ")}
|
|
960
|
+
`);
|
|
961
|
+
await attachSession(session);
|
|
962
|
+
}
|
|
963
|
+
async function runDaemon() {
|
|
964
|
+
await ensureTmuxAvailable();
|
|
965
|
+
const relayUrl = getRelayUrl();
|
|
966
|
+
const deviceId = resolveDeviceId();
|
|
967
|
+
saveAgentRuntime({
|
|
968
|
+
pid: process.pid,
|
|
969
|
+
relayUrl,
|
|
970
|
+
deviceId,
|
|
971
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
972
|
+
});
|
|
973
|
+
const daemon = createDaemonFromEnv();
|
|
974
|
+
const stop = () => {
|
|
975
|
+
void daemon.stop().finally(() => {
|
|
976
|
+
clearAgentRuntime(process.pid);
|
|
977
|
+
process.exit(0);
|
|
978
|
+
});
|
|
979
|
+
};
|
|
980
|
+
process.on("SIGINT", stop);
|
|
981
|
+
process.on("SIGTERM", stop);
|
|
982
|
+
process.on("exit", () => {
|
|
983
|
+
clearAgentRuntime(process.pid);
|
|
984
|
+
});
|
|
985
|
+
await daemon.start();
|
|
986
|
+
}
|
|
774
987
|
async function runPair(argv) {
|
|
775
988
|
const deviceId = getDeviceId(argv);
|
|
776
989
|
const payload = await createPairingCode(deviceId);
|
|
@@ -833,16 +1046,17 @@ async function runAgentCli(argv = process.argv.slice(2)) {
|
|
|
833
1046
|
return;
|
|
834
1047
|
}
|
|
835
1048
|
switch (command) {
|
|
1049
|
+
case "start":
|
|
1050
|
+
await runStart(rest);
|
|
1051
|
+
return;
|
|
1052
|
+
case "status":
|
|
1053
|
+
runStatus();
|
|
1054
|
+
return;
|
|
1055
|
+
case "stop":
|
|
1056
|
+
await runStop();
|
|
1057
|
+
return;
|
|
836
1058
|
case "daemon": {
|
|
837
|
-
await
|
|
838
|
-
const daemon = createDaemonFromEnv();
|
|
839
|
-
process.on("SIGINT", () => {
|
|
840
|
-
void daemon.stop().finally(() => process.exit(0));
|
|
841
|
-
});
|
|
842
|
-
process.on("SIGTERM", () => {
|
|
843
|
-
void daemon.stop().finally(() => process.exit(0));
|
|
844
|
-
});
|
|
845
|
-
await daemon.start();
|
|
1059
|
+
await runDaemon();
|
|
846
1060
|
return;
|
|
847
1061
|
}
|
|
848
1062
|
case "create":
|
|
@@ -875,9 +1089,13 @@ async function runAgentCli(argv = process.argv.slice(2)) {
|
|
|
875
1089
|
case "revoke":
|
|
876
1090
|
await runRevoke(rest);
|
|
877
1091
|
return;
|
|
1092
|
+
case "run":
|
|
1093
|
+
await ensureTmuxAvailable();
|
|
1094
|
+
await runManagedCommand(rest);
|
|
1095
|
+
return;
|
|
878
1096
|
default:
|
|
879
|
-
|
|
880
|
-
|
|
1097
|
+
await ensureTmuxAvailable();
|
|
1098
|
+
await runManagedCommand(argv);
|
|
881
1099
|
}
|
|
882
1100
|
}
|
|
883
1101
|
|
|
@@ -1883,6 +2101,10 @@ function printHelp2() {
|
|
|
1883
2101
|
|
|
1884
2102
|
termpilot relay [--host 0.0.0.0] [--port 8787]
|
|
1885
2103
|
termpilot agent [--relay ws://127.0.0.1:8787/ws] [--device-id pc-main]
|
|
2104
|
+
termpilot agent status
|
|
2105
|
+
termpilot agent stop
|
|
2106
|
+
termpilot claude code
|
|
2107
|
+
termpilot run -- claude code
|
|
1886
2108
|
|
|
1887
2109
|
termpilot pair [--device-id pc-main]
|
|
1888
2110
|
termpilot create --name claude-main [--cwd /path/to/project]
|
|
@@ -1935,7 +2157,15 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
1935
2157
|
}
|
|
1936
2158
|
case "agent": {
|
|
1937
2159
|
const agentArgs = applyEnvFlags(rest, AGENT_ENV_FLAGS);
|
|
1938
|
-
|
|
2160
|
+
if (agentArgs[0] === "status" || agentArgs[0] === "stop" || agentArgs[0] === "daemon") {
|
|
2161
|
+
await runAgentCli(agentArgs);
|
|
2162
|
+
} else {
|
|
2163
|
+
await runAgentCli(["start", ...agentArgs]);
|
|
2164
|
+
}
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
case "agent-daemon": {
|
|
2168
|
+
await runAgentCli(["daemon", ...rest]);
|
|
1939
2169
|
return;
|
|
1940
2170
|
}
|
|
1941
2171
|
case "pair":
|
|
@@ -1952,8 +2182,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
1952
2182
|
return;
|
|
1953
2183
|
}
|
|
1954
2184
|
default:
|
|
1955
|
-
|
|
1956
|
-
process.exitCode = 1;
|
|
2185
|
+
await runAgentCli([command, ...rest]);
|
|
1957
2186
|
}
|
|
1958
2187
|
}
|
|
1959
2188
|
void main().catch((error) => {
|
package/docs/development.md
CHANGED
|
@@ -18,6 +18,11 @@ pnpm test:ui-smoke
|
|
|
18
18
|
pnpm check:stability
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
说明:
|
|
22
|
+
|
|
23
|
+
- `pnpm test:ui-smoke` 现在按手机视口跑,覆盖配对、切会话、关闭会话、清除绑定,以及“查看后终端区进入可视区”
|
|
24
|
+
- `pnpm check:stability` 会验证 relay / agent 长时间运行下的输出缓冲和重连一致性
|
|
25
|
+
|
|
21
26
|
## 当前仓库形态
|
|
22
27
|
|
|
23
28
|
- 根入口:`src/cli.ts`
|
|
@@ -32,7 +37,7 @@ pnpm check:stability
|
|
|
32
37
|
2. 运行 `pnpm build`
|
|
33
38
|
3. 运行 `pnpm test:ui-smoke`
|
|
34
39
|
4. 运行 `pnpm check:stability`
|
|
35
|
-
5. 执行 `npm publish`
|
|
40
|
+
5. 执行 `npm publish --access public`
|
|
36
41
|
|
|
37
42
|
当前已发布包名:
|
|
38
43
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fengye404/termpilot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "pnpm@10.31.0",
|
|
6
6
|
"description": "一个基于 tmux 的终端会话跨端查看与控制原型。",
|
|
7
7
|
"bin": {
|
|
8
|
-
"termpilot": "
|
|
8
|
+
"termpilot": "dist/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|