opencode-mobile 1.0.11 → 1.2.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/bin/audit +31 -0
- package/bin/qr +13 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +545 -3
- package/dist/index.js.map +1 -1
- package/dist/src/cli/endpoint-tester.d.ts +19 -0
- package/dist/src/cli/endpoint-tester.d.ts.map +1 -0
- package/dist/src/cli/endpoint-tester.js +233 -0
- package/dist/src/cli/endpoint-tester.js.map +1 -0
- package/dist/src/cli/index.d.ts +20 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js +166 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/push-tester.d.ts +16 -0
- package/dist/src/cli/push-tester.d.ts.map +1 -0
- package/dist/src/cli/push-tester.js +293 -0
- package/dist/src/cli/push-tester.js.map +1 -0
- package/dist/src/cli/qr.d.ts +5 -0
- package/dist/src/cli/qr.d.ts.map +1 -0
- package/dist/src/cli/qr.js +127 -0
- package/dist/src/cli/qr.js.map +1 -0
- package/dist/src/cli/report.d.ts +25 -0
- package/dist/src/cli/report.d.ts.map +1 -0
- package/dist/src/cli/report.js +215 -0
- package/dist/src/cli/report.js.map +1 -0
- package/dist/src/cli/server-manager.d.ts +28 -0
- package/dist/src/cli/server-manager.d.ts.map +1 -0
- package/dist/src/cli/server-manager.js +340 -0
- package/dist/src/cli/server-manager.js.map +1 -0
- package/dist/src/cli/test-runner.d.ts +16 -0
- package/dist/src/cli/test-runner.d.ts.map +1 -0
- package/dist/src/cli/test-runner.js +201 -0
- package/dist/src/cli/test-runner.js.map +1 -0
- package/dist/src/cli/tunnel-qr.d.ts +8 -0
- package/dist/src/cli/tunnel-qr.d.ts.map +1 -0
- package/dist/src/cli/tunnel-qr.js +163 -0
- package/dist/src/cli/tunnel-qr.js.map +1 -0
- package/dist/src/cli/tunnel-tester.d.ts +22 -0
- package/dist/src/cli/tunnel-tester.d.ts.map +1 -0
- package/dist/src/cli/tunnel-tester.js +360 -0
- package/dist/src/cli/tunnel-tester.js.map +1 -0
- package/dist/src/cli/types.d.ts +112 -0
- package/dist/src/cli/types.d.ts.map +1 -0
- package/dist/src/cli/types.js +5 -0
- package/dist/src/cli/types.js.map +1 -0
- package/dist/src/push/index.d.ts +1 -0
- package/dist/src/push/index.d.ts.map +1 -1
- package/dist/src/push/index.js +1 -0
- package/dist/src/push/index.js.map +1 -1
- package/dist/src/push/notification-handler.d.ts +58 -0
- package/dist/src/push/notification-handler.d.ts.map +1 -0
- package/dist/src/push/notification-handler.js +110 -0
- package/dist/src/push/notification-handler.js.map +1 -0
- package/dist/src/tunnel/cloudflare.d.ts +38 -1
- package/dist/src/tunnel/cloudflare.d.ts.map +1 -1
- package/dist/src/tunnel/cloudflare.js +148 -51
- package/dist/src/tunnel/cloudflare.js.map +1 -1
- package/dist/src/tunnel/localtunnel.d.ts +32 -1
- package/dist/src/tunnel/localtunnel.d.ts.map +1 -1
- package/dist/src/tunnel/localtunnel.js +75 -16
- package/dist/src/tunnel/localtunnel.js.map +1 -1
- package/dist/src/tunnel/metadata.d.ts +29 -0
- package/dist/src/tunnel/metadata.d.ts.map +1 -0
- package/dist/src/tunnel/metadata.js +83 -0
- package/dist/src/tunnel/metadata.js.map +1 -0
- package/dist/src/tunnel/ngrok.d.ts +24 -1
- package/dist/src/tunnel/ngrok.d.ts.map +1 -1
- package/dist/src/tunnel/ngrok.js +381 -20
- package/dist/src/tunnel/ngrok.js.map +1 -1
- package/dist/src/tunnel/qrcode.d.ts +14 -2
- package/dist/src/tunnel/qrcode.d.ts.map +1 -1
- package/dist/src/tunnel/qrcode.js +96 -8
- package/dist/src/tunnel/qrcode.js.map +1 -1
- package/package.json +22 -4
- package/dist/push-notifications.d.ts +0 -4
- package/dist/push-notifications.d.ts.map +0 -1
- package/dist/push-notifications.js +0 -260
- package/dist/push-notifications.js.map +0 -1
- package/dist/reverse-proxy.d.ts +0 -9
- package/dist/reverse-proxy.d.ts.map +0 -1
- package/dist/reverse-proxy.js +0 -78
- package/dist/reverse-proxy.js.map +0 -1
- package/dist/sdk-logger.d.ts +0 -19
- package/dist/sdk-logger.d.ts.map +0 -1
- package/dist/sdk-logger.js +0 -103
- package/dist/sdk-logger.js.map +0 -1
- package/dist/src/tunnel/index.d.ts +0 -29
- package/dist/src/tunnel/index.d.ts.map +0 -1
- package/dist/src/tunnel/index.js +0 -125
- package/dist/src/tunnel/index.js.map +0 -1
- package/dist/src/utils/port.d.ts +0 -12
- package/dist/src/utils/port.d.ts.map +0 -1
- package/dist/src/utils/port.js +0 -41
- package/dist/src/utils/port.js.map +0 -1
- package/dist/tunnel-manager.d.ts +0 -30
- package/dist/tunnel-manager.d.ts.map +0 -1
- package/dist/tunnel-manager.js +0 -641
- package/dist/tunnel-manager.js.map +0 -1
package/bin/audit
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OpenCode Mobile Plugin - Endpoint Audit Utility
|
|
5
|
+
* Run with: npx opencode-mobile audit
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { main as auditMain } from "../dist/src/cli/index.js";
|
|
9
|
+
import { main as qrMain } from "../dist/src/cli/qr.js";
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const subcommand = args[0];
|
|
13
|
+
|
|
14
|
+
const run = async () => {
|
|
15
|
+
if (subcommand === "qr") {
|
|
16
|
+
await qrMain(args.slice(1));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (subcommand === "audit") {
|
|
21
|
+
await auditMain(args.slice(1));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
await auditMain(args);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
run().catch((error) => {
|
|
29
|
+
console.error("Fatal error:", error instanceof Error ? error.message : String(error));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
});
|
package/bin/qr
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OpenCode Mobile Plugin - Tunnel QR Utility
|
|
5
|
+
* Run with: npx opencode-mobile-qr /path/to/tunnels.json
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { main } from "../dist/src/cli/qr.js";
|
|
9
|
+
|
|
10
|
+
main().catch((error) => {
|
|
11
|
+
console.error("Fatal error:", error instanceof Error ? error.message : String(error));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* opencode-mobile plugin - LAN-only push notification server
|
|
3
|
+
*
|
|
4
|
+
* Architecture:
|
|
5
|
+
* - Plugin server: LAN only (127.0.0.1) - handles /push-token and /tunnel endpoints
|
|
6
|
+
* - Tunnel: Points directly to OpenCode server (not through plugin)
|
|
7
|
+
* - Mobile connects: tunnel → OpenCode (SSE), or LAN → plugin (push tokens)
|
|
8
|
+
*/
|
|
9
|
+
import type { Plugin } from "@opencode-ai/plugin";
|
|
10
|
+
export declare const PushNotificationPlugin: Plugin;
|
|
11
|
+
export default PushNotificationPlugin;
|
|
4
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA4dlD,eAAO,MAAM,sBAAsB,EAAE,MA2GpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,546 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* opencode-mobile plugin - LAN-only push notification server
|
|
3
|
+
*
|
|
4
|
+
* Architecture:
|
|
5
|
+
* - Plugin server: LAN only (127.0.0.1) - handles /push-token and /tunnel endpoints
|
|
6
|
+
* - Tunnel: Points directly to OpenCode server (not through plugin)
|
|
7
|
+
* - Mobile connects: tunnel → OpenCode (SSE), or LAN → plugin (push tokens)
|
|
8
|
+
*/
|
|
9
|
+
const DEBUG_ENABLED = process.env.OPENCODE_MOBILE_DEBUG === "1";
|
|
10
|
+
const debugLog = (...args) => {
|
|
11
|
+
if (DEBUG_ENABLED) {
|
|
12
|
+
console.log(...args);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
debugLog("\n=== opencode-mobile DEV ===");
|
|
16
|
+
debugLog("LAN-only architecture: plugin handles push tokens, tunnel goes to OpenCode directly");
|
|
17
|
+
debugLog("[PushPlugin][Mobile] Entry loaded: index.ts");
|
|
18
|
+
import * as fs from "fs";
|
|
19
|
+
import * as path from "path";
|
|
20
|
+
import http from "http";
|
|
21
|
+
import { tool } from "@opencode-ai/plugin";
|
|
22
|
+
import { loadTokens, saveTokens } from "./src/push/token-store";
|
|
23
|
+
import { startLocaltunnel, stopLocaltunnel, getLocaltunnelUrl } from "./src/tunnel/localtunnel";
|
|
24
|
+
import { displayQRCode, generateQRCodeAscii, generateQRCodeAsciiPlain } from "./src/tunnel/qrcode";
|
|
25
|
+
import { startNgrokTunnel, stopNgrokTunnel } from "./src/tunnel/ngrok";
|
|
26
|
+
import { updateTunnelMetadata, clearTunnelMetadata, loadTunnelMetadata } from "./src/tunnel/metadata";
|
|
27
|
+
const CONFIG_DIR = path.join(process.env.HOME || "", ".config/opencode");
|
|
28
|
+
// Server state
|
|
29
|
+
let httpServer = null;
|
|
30
|
+
let activeTunnel = null;
|
|
31
|
+
const cors = {
|
|
32
|
+
"Access-Control-Allow-Origin": "*",
|
|
33
|
+
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
|
|
34
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
35
|
+
};
|
|
36
|
+
const MOBILE_COMMAND = "mobile";
|
|
37
|
+
function formatMobileQrMessage(url, qr) {
|
|
38
|
+
if (!qr) {
|
|
39
|
+
return url;
|
|
40
|
+
}
|
|
41
|
+
return `${qr}\n${url}`;
|
|
42
|
+
}
|
|
43
|
+
function loadTunnelUrlFromPath(tunnelPath) {
|
|
44
|
+
try {
|
|
45
|
+
if (!fs.existsSync(tunnelPath)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const raw = fs.readFileSync(tunnelPath, "utf-8");
|
|
49
|
+
const data = JSON.parse(raw);
|
|
50
|
+
if (typeof data.url === "string" && data.url.startsWith("http")) {
|
|
51
|
+
return data.url;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error("[PushPlugin] Failed to read tunnel path:", error);
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const mobileTool = tool({
|
|
60
|
+
description: "Generate a mobile connection QR code",
|
|
61
|
+
args: {
|
|
62
|
+
url: tool.schema.string().optional().describe("Tunnel URL to render as QR"),
|
|
63
|
+
tunnelPath: tool.schema
|
|
64
|
+
.string()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("Path to tunnel.json containing a URL"),
|
|
67
|
+
},
|
|
68
|
+
async execute(args) {
|
|
69
|
+
const rawUrl = args.url?.trim();
|
|
70
|
+
const urlFromPath = args.tunnelPath ? loadTunnelUrlFromPath(args.tunnelPath) : null;
|
|
71
|
+
const metadataUrl = loadTunnelMetadata().url;
|
|
72
|
+
const url = rawUrl || urlFromPath || metadataUrl || "";
|
|
73
|
+
if (!url || !url.startsWith("http")) {
|
|
74
|
+
return "No tunnel URL found.";
|
|
75
|
+
}
|
|
76
|
+
const qr = await generateQRCodeAsciiPlain(url) || await generateQRCodeAscii(url);
|
|
77
|
+
return formatMobileQrMessage(url, qr);
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
async function publishReply(ctx, sessionID, message, messageID) {
|
|
81
|
+
try {
|
|
82
|
+
const rawCtx = ctx;
|
|
83
|
+
const client = rawCtx?.client ?? rawCtx?.sdk ?? rawCtx;
|
|
84
|
+
const directory = rawCtx?.directory ?? rawCtx?.worktree;
|
|
85
|
+
const sessionApi = client?.Session ?? client?.session;
|
|
86
|
+
const prompt = sessionApi?.prompt?.bind(sessionApi)
|
|
87
|
+
?? sessionApi?.message?.bind(sessionApi)
|
|
88
|
+
?? sessionApi?.create?.bind(sessionApi);
|
|
89
|
+
if (typeof prompt !== "function") {
|
|
90
|
+
debugLog("[PushPlugin] Reply client keys:", Object.keys(client || {}));
|
|
91
|
+
debugLog("[PushPlugin] Reply session keys:", Object.keys(sessionApi || {}));
|
|
92
|
+
throw new Error("Session prompt API unavailable");
|
|
93
|
+
}
|
|
94
|
+
const doPrompt = async () => {
|
|
95
|
+
await prompt({
|
|
96
|
+
path: { id: sessionID },
|
|
97
|
+
query: directory ? { directory } : undefined,
|
|
98
|
+
body: {
|
|
99
|
+
messageID,
|
|
100
|
+
noReply: true,
|
|
101
|
+
parts: [
|
|
102
|
+
{
|
|
103
|
+
type: "text",
|
|
104
|
+
text: message,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
let attempt = 0;
|
|
111
|
+
while (true) {
|
|
112
|
+
try {
|
|
113
|
+
if (!sessionID) {
|
|
114
|
+
console.log("[PushPlugin] No sessionID to send reply");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await doPrompt();
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
const errorMessage = error?.message || "";
|
|
122
|
+
const isNotFound = error?.name === "NotFoundError" || errorMessage.includes("Resource not found");
|
|
123
|
+
attempt += 1;
|
|
124
|
+
if (!isNotFound || attempt >= 4) {
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
await new Promise((resolve) => setTimeout(resolve, 150 * attempt));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
const errorMessage = error?.message || error;
|
|
133
|
+
console.error("[PushPlugin] Failed to publish reply:", errorMessage);
|
|
134
|
+
const rawCtx = ctx;
|
|
135
|
+
const client = rawCtx?.client ?? rawCtx?.sdk ?? rawCtx;
|
|
136
|
+
const tui = client?.tui ?? client?.Tui;
|
|
137
|
+
const showToast = tui?.showToast?.bind(tui);
|
|
138
|
+
const publish = tui?.publish?.bind(tui);
|
|
139
|
+
if (typeof showToast === "function" || typeof publish === "function") {
|
|
140
|
+
const urlMatch = typeof message === "string" ? message.match(/https?:\/\/\S+/) : null;
|
|
141
|
+
const toastMessage = urlMatch ? `QR ready: ${urlMatch[0]}` : "Reply failed. QR printed in terminal.";
|
|
142
|
+
const body = {
|
|
143
|
+
title: "OpenCode Mobile",
|
|
144
|
+
message: toastMessage,
|
|
145
|
+
variant: "warning",
|
|
146
|
+
duration: 8000,
|
|
147
|
+
};
|
|
148
|
+
try {
|
|
149
|
+
if (typeof showToast === "function") {
|
|
150
|
+
await showToast({ body });
|
|
151
|
+
}
|
|
152
|
+
else if (typeof publish === "function") {
|
|
153
|
+
await publish({ body: { type: "tui.toast.show", properties: body } });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (toastError) {
|
|
157
|
+
console.error("[PushPlugin] Failed to show toast:", toastError?.message || toastError);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async function publishToTui(ctx, text) {
|
|
163
|
+
try {
|
|
164
|
+
const rawCtx = ctx;
|
|
165
|
+
const client = rawCtx?.client ?? rawCtx?.sdk ?? rawCtx;
|
|
166
|
+
const tui = client?.tui ?? client?.Tui;
|
|
167
|
+
const publish = tui?.publish?.bind(tui);
|
|
168
|
+
if (typeof publish !== "function") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
await publish({ body: { type: "tui.prompt.append", properties: { text } } });
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error("[PushPlugin] Failed to publish TUI prompt:", error?.message || error);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function registerPushToken(token) {
|
|
178
|
+
const trimmed = token.trim();
|
|
179
|
+
const tokens = loadTokens();
|
|
180
|
+
const existingIndex = tokens.findIndex((t) => t.token === trimmed || t.deviceId === trimmed);
|
|
181
|
+
const now = new Date().toISOString();
|
|
182
|
+
const newToken = {
|
|
183
|
+
token: trimmed,
|
|
184
|
+
platform: "ios",
|
|
185
|
+
deviceId: trimmed,
|
|
186
|
+
registeredAt: now,
|
|
187
|
+
};
|
|
188
|
+
if (existingIndex >= 0) {
|
|
189
|
+
tokens[existingIndex] = { ...tokens[existingIndex], ...newToken };
|
|
190
|
+
saveTokens(tokens);
|
|
191
|
+
return { added: false, total: tokens.length };
|
|
192
|
+
}
|
|
193
|
+
tokens.push(newToken);
|
|
194
|
+
saveTokens(tokens);
|
|
195
|
+
return { added: true, total: tokens.length };
|
|
196
|
+
}
|
|
197
|
+
async function handleMobileCommand(ctx, args, sessionID, messageID) {
|
|
198
|
+
const trimmed = args.trim();
|
|
199
|
+
if (!trimmed) {
|
|
200
|
+
const metadata = loadTunnelMetadata();
|
|
201
|
+
if (!metadata.url) {
|
|
202
|
+
debugLog("[Tunnel] No tunnel URL found in tunnel.json");
|
|
203
|
+
await publishReply(ctx, sessionID, "No tunnel URL found.", messageID);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
debugLog("[Tunnel] /mobile displaying QR for:", metadata.url);
|
|
207
|
+
await displayQRCode(metadata.url);
|
|
208
|
+
const qr = await generateQRCodeAsciiPlain(metadata.url) || await generateQRCodeAscii(metadata.url);
|
|
209
|
+
const message = formatMobileQrMessage(metadata.url, qr);
|
|
210
|
+
await publishToTui(ctx, message);
|
|
211
|
+
await publishReply(ctx, sessionID, message, messageID);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const result = registerPushToken(trimmed);
|
|
215
|
+
const action = result.added ? "Registered" : "Updated";
|
|
216
|
+
debugLog(`[Push] ${action} token via /mobile (count=${result.total})`);
|
|
217
|
+
await publishReply(ctx, sessionID, `Push token ${action.toLowerCase()}.`, messageID);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Handle push-token requests (LAN only)
|
|
221
|
+
*/
|
|
222
|
+
async function handlePushToken(req, res) {
|
|
223
|
+
let body = "";
|
|
224
|
+
req.on("data", (chunk) => { body += chunk; });
|
|
225
|
+
await new Promise((resolve) => req.on("end", resolve));
|
|
226
|
+
if (req.url === "/push-token" && req.method === "POST") {
|
|
227
|
+
try {
|
|
228
|
+
const data = JSON.parse(body);
|
|
229
|
+
const { token, platform, deviceId } = data;
|
|
230
|
+
if (!token || !deviceId) {
|
|
231
|
+
res.writeHead(400, { ...cors, "Content-Type": "application/json" });
|
|
232
|
+
res.end(JSON.stringify({ error: "Missing fields" }));
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const validPlatform = (platform === "ios" || platform === "android") ? platform : "ios";
|
|
236
|
+
const tokens = loadTokens();
|
|
237
|
+
const idx = tokens.findIndex((t) => t.deviceId === deviceId);
|
|
238
|
+
const newToken = { token, platform: validPlatform, deviceId, registeredAt: new Date().toISOString() };
|
|
239
|
+
if (idx >= 0)
|
|
240
|
+
tokens[idx] = newToken;
|
|
241
|
+
else
|
|
242
|
+
tokens.push(newToken);
|
|
243
|
+
saveTokens(tokens);
|
|
244
|
+
console.log("[Push] Token registered:", deviceId);
|
|
245
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
246
|
+
res.end(JSON.stringify({ success: true }));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
res.writeHead(400, { ...cors, "Content-Type": "application/json" });
|
|
251
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (req.url === "/push-token" && req.method === "GET") {
|
|
256
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
257
|
+
res.end(JSON.stringify({ count: loadTokens().length }));
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (req.url === "/push-token" && req.method === "DELETE") {
|
|
261
|
+
try {
|
|
262
|
+
const data = JSON.parse(body);
|
|
263
|
+
const { deviceId } = data;
|
|
264
|
+
if (!deviceId) {
|
|
265
|
+
res.writeHead(400, { ...cors, "Content-Type": "application/json" });
|
|
266
|
+
res.end(JSON.stringify({ error: "Missing deviceId" }));
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
saveTokens(loadTokens().filter((t) => t.deviceId !== deviceId));
|
|
270
|
+
console.log("[Push] Token removed:", deviceId);
|
|
271
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
272
|
+
res.end(JSON.stringify({ success: true }));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
res.writeHead(400, { ...cors, "Content-Type": "application/json" });
|
|
277
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// 404 for other push-token paths
|
|
282
|
+
res.writeHead(404, cors);
|
|
283
|
+
res.end("Not found");
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Handle tunnel requests (LAN only)
|
|
287
|
+
*/
|
|
288
|
+
async function handleTunnel(req, res, openCodePort) {
|
|
289
|
+
let body = "";
|
|
290
|
+
if (req.method === "POST") {
|
|
291
|
+
req.on("data", (chunk) => { body += chunk; });
|
|
292
|
+
await new Promise((resolve) => req.on("end", resolve));
|
|
293
|
+
}
|
|
294
|
+
if (req.url === "/tunnel" && req.method === "POST") {
|
|
295
|
+
try {
|
|
296
|
+
const data = JSON.parse(body);
|
|
297
|
+
const targetPort = data.port || openCodePort;
|
|
298
|
+
console.log("[Tunnel] Starting to port:", targetPort);
|
|
299
|
+
let tunnel;
|
|
300
|
+
try {
|
|
301
|
+
tunnel = await startNgrokTunnel({ port: targetPort });
|
|
302
|
+
console.log("[Tunnel] Ngrok started:", tunnel.url);
|
|
303
|
+
}
|
|
304
|
+
catch (ngrokError) {
|
|
305
|
+
console.log("[Tunnel] Ngrok failed, trying localtunnel...");
|
|
306
|
+
tunnel = await startLocaltunnel({ port: targetPort });
|
|
307
|
+
console.log("[Tunnel] Localtunnel started:", tunnel.url);
|
|
308
|
+
}
|
|
309
|
+
activeTunnel = tunnel;
|
|
310
|
+
await displayQRCode(tunnel.url);
|
|
311
|
+
// Save tunnel metadata to .config/opencode/tunnel.json
|
|
312
|
+
updateTunnelMetadata(tunnel.url, tunnel.tunnelId, tunnel.provider, tunnel.port, targetPort);
|
|
313
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
314
|
+
res.end(JSON.stringify({
|
|
315
|
+
success: true,
|
|
316
|
+
type: tunnel.provider,
|
|
317
|
+
url: tunnel.url,
|
|
318
|
+
tunnelId: tunnel.tunnelId,
|
|
319
|
+
port: tunnel.port,
|
|
320
|
+
targetPort: targetPort,
|
|
321
|
+
note: "Tunnel points directly to OpenCode server"
|
|
322
|
+
}));
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
console.error("[Tunnel] Failed:", error.message);
|
|
327
|
+
res.writeHead(500, { ...cors, "Content-Type": "application/json" });
|
|
328
|
+
res.end(JSON.stringify({ error: error.message }));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (req.url === "/tunnel" && req.method === "DELETE") {
|
|
333
|
+
try {
|
|
334
|
+
if (activeTunnel?.provider === "ngrok") {
|
|
335
|
+
await stopNgrokTunnel();
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
await stopLocaltunnel();
|
|
339
|
+
}
|
|
340
|
+
activeTunnel = null;
|
|
341
|
+
// Clear tunnel metadata from .config/opencode/tunnel.json
|
|
342
|
+
clearTunnelMetadata();
|
|
343
|
+
console.log("[Tunnel] Stopped");
|
|
344
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
345
|
+
res.end(JSON.stringify({ success: true }));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
res.writeHead(500, { ...cors, "Content-Type": "application/json" });
|
|
350
|
+
res.end(JSON.stringify({ error: error.message }));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (req.url === "/tunnel" && req.method === "GET") {
|
|
355
|
+
// Load stored metadata from .config/opencode/tunnel.json
|
|
356
|
+
const storedMetadata = loadTunnelMetadata();
|
|
357
|
+
if (activeTunnel) {
|
|
358
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
359
|
+
res.end(JSON.stringify({
|
|
360
|
+
type: activeTunnel.provider,
|
|
361
|
+
url: activeTunnel.url,
|
|
362
|
+
tunnelId: activeTunnel.tunnelId,
|
|
363
|
+
port: activeTunnel.port,
|
|
364
|
+
targetPort: openCodePort,
|
|
365
|
+
metadata: storedMetadata
|
|
366
|
+
}));
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const localtunnelUrl = getLocaltunnelUrl();
|
|
370
|
+
if (localtunnelUrl) {
|
|
371
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
372
|
+
res.end(JSON.stringify({
|
|
373
|
+
type: "localtunnel",
|
|
374
|
+
url: localtunnelUrl,
|
|
375
|
+
tunnelId: localtunnelUrl.split("://")[1].split(".")[0],
|
|
376
|
+
metadata: storedMetadata
|
|
377
|
+
}));
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
381
|
+
res.end(JSON.stringify({
|
|
382
|
+
type: "none",
|
|
383
|
+
url: null,
|
|
384
|
+
metadata: storedMetadata
|
|
385
|
+
}));
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
// 404 for other tunnel paths
|
|
389
|
+
res.writeHead(404, cors);
|
|
390
|
+
res.end("Not found");
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Start LAN-only HTTP server
|
|
394
|
+
* Returns true if server started successfully, false if port was in use
|
|
395
|
+
*/
|
|
396
|
+
async function startServer(port, openCodePort) {
|
|
397
|
+
return new Promise((resolve) => {
|
|
398
|
+
httpServer = http.createServer((clientReq, clientRes) => {
|
|
399
|
+
// CORS preflight
|
|
400
|
+
if (clientReq.method === "OPTIONS") {
|
|
401
|
+
clientRes.writeHead(204, cors);
|
|
402
|
+
clientRes.end();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const url = clientReq.url || "";
|
|
406
|
+
// Handle /push-token endpoints (LAN only)
|
|
407
|
+
if (url.startsWith("/push-token")) {
|
|
408
|
+
handlePushToken(clientReq, clientRes);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
// Handle /tunnel endpoints (LAN only)
|
|
412
|
+
if (url.startsWith("/tunnel")) {
|
|
413
|
+
handleTunnel(clientReq, clientRes, openCodePort);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Everything else: 404 (LAN only, no proxy)
|
|
417
|
+
clientRes.writeHead(404, cors);
|
|
418
|
+
clientRes.end("Not found - LAN-only server");
|
|
419
|
+
});
|
|
420
|
+
httpServer.on("error", (err) => {
|
|
421
|
+
if (err.code === "EADDRINUSE") {
|
|
422
|
+
debugLog("[Push] Port in use, skipping");
|
|
423
|
+
resolve(false);
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
console.error("[Push] Failed:", err.message);
|
|
427
|
+
resolve(false);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
// Listen on 127.0.0.1 only (LAN only, not exposed externally)
|
|
431
|
+
httpServer.listen(port, "127.0.0.1", () => {
|
|
432
|
+
console.log(`[Push] LAN-only server running on port ${port}`);
|
|
433
|
+
console.log(`[Push] /push-token/* → push token management`);
|
|
434
|
+
console.log(`[Push] /tunnel/* → tunnel management`);
|
|
435
|
+
console.log(`[Push] Tunnel target: OpenCode on port ${openCodePort}`);
|
|
436
|
+
resolve(true);
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
export const PushNotificationPlugin = async (ctx) => {
|
|
441
|
+
debugLog("[PushPlugin][Mobile] Initialized");
|
|
442
|
+
// Check if we're running in "serve" mode (subcommand, not option)
|
|
443
|
+
const isServeMode = process.argv.includes("serve");
|
|
444
|
+
debugLog("[PushPlugin] isServeMode:", isServeMode);
|
|
445
|
+
debugLog("[PushPlugin] process.argv:", process.argv.join(", "));
|
|
446
|
+
if (!isServeMode) {
|
|
447
|
+
debugLog("[PushPlugin] Not in serve mode, skipping plugin");
|
|
448
|
+
return {
|
|
449
|
+
tool: {
|
|
450
|
+
mobile: mobileTool,
|
|
451
|
+
},
|
|
452
|
+
event: async ({ event }) => {
|
|
453
|
+
if (event.type === "command.executed") {
|
|
454
|
+
debugLog("[PushPlugin] command.executed payload:", JSON.stringify(event.properties));
|
|
455
|
+
}
|
|
456
|
+
if (event.type === "command.executed" && event.properties.name === MOBILE_COMMAND) {
|
|
457
|
+
debugLog("[PushPlugin] Handling /mobile command");
|
|
458
|
+
await handleMobileCommand(ctx, event.properties.arguments || "", event.properties.sessionID, event.properties.messageID);
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const openCodePort = Number(ctx.serverUrl?.port) || 4096;
|
|
464
|
+
const pluginPort = openCodePort + 1; // Plugin on next port
|
|
465
|
+
debugLog("[DEV] openCodePort:", openCodePort, "| pluginPort:", pluginPort);
|
|
466
|
+
// Start LAN-only server
|
|
467
|
+
const serverStarted = await startServer(pluginPort, openCodePort);
|
|
468
|
+
// Only start tunnel if server started successfully (port wasn't in use)
|
|
469
|
+
if (!serverStarted) {
|
|
470
|
+
debugLog("[PushPlugin] Server already running, skipping plugin initialization");
|
|
471
|
+
return {
|
|
472
|
+
tool: {
|
|
473
|
+
mobile: mobileTool,
|
|
474
|
+
},
|
|
475
|
+
event: async ({ event }) => {
|
|
476
|
+
// No-op when another instance is running
|
|
477
|
+
},
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
// Auto-start tunnel pointing to OpenCode DIRECTLY (not through plugin!)
|
|
481
|
+
debugLog("[DEV] Auto-starting tunnel...");
|
|
482
|
+
try {
|
|
483
|
+
const tunnel = await startNgrokTunnel({ port: openCodePort });
|
|
484
|
+
debugLog("[DEV] Tunnel started:", tunnel.url);
|
|
485
|
+
activeTunnel = tunnel;
|
|
486
|
+
await displayQRCode(tunnel.url);
|
|
487
|
+
// Save tunnel metadata to .config/opencode/tunnel.json
|
|
488
|
+
updateTunnelMetadata(tunnel.url, tunnel.tunnelId, tunnel.provider, tunnel.port, openCodePort);
|
|
489
|
+
}
|
|
490
|
+
catch (ngrokError) {
|
|
491
|
+
debugLog("[DEV] Ngrok failed, trying localtunnel...");
|
|
492
|
+
try {
|
|
493
|
+
const tunnel = await startLocaltunnel({ port: openCodePort });
|
|
494
|
+
debugLog("[DEV] Tunnel started:", tunnel.url);
|
|
495
|
+
activeTunnel = tunnel;
|
|
496
|
+
await displayQRCode(tunnel.url);
|
|
497
|
+
// Save tunnel metadata to .config/opencode/tunnel.json
|
|
498
|
+
updateTunnelMetadata(tunnel.url, tunnel.tunnelId, tunnel.provider, tunnel.port, openCodePort);
|
|
499
|
+
}
|
|
500
|
+
catch (localError) {
|
|
501
|
+
console.error("[DEV] All tunnels failed:", localError.message);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
tool: {
|
|
506
|
+
mobile: mobileTool,
|
|
507
|
+
},
|
|
508
|
+
event: async ({ event }) => {
|
|
509
|
+
if (event.type === "command.executed") {
|
|
510
|
+
debugLog("[PushPlugin] command.executed payload:", JSON.stringify(event.properties));
|
|
511
|
+
}
|
|
512
|
+
if (event.type === "command.executed" && event.properties.name === MOBILE_COMMAND) {
|
|
513
|
+
debugLog("[PushPlugin] Handling /mobile command");
|
|
514
|
+
await handleMobileCommand(ctx, event.properties.arguments || "", event.properties.sessionID, event.properties.messageID);
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
};
|
|
518
|
+
};
|
|
519
|
+
export default PushNotificationPlugin;
|
|
520
|
+
if (import.meta.main) {
|
|
521
|
+
const main = async () => {
|
|
522
|
+
const args = process.argv.slice(2);
|
|
523
|
+
if (args.length === 0) {
|
|
524
|
+
const metadata = loadTunnelMetadata();
|
|
525
|
+
if (!metadata.url) {
|
|
526
|
+
console.log("No tunnel URL found.");
|
|
527
|
+
process.exit(1);
|
|
528
|
+
}
|
|
529
|
+
const qr = await generateQRCodeAscii(metadata.url);
|
|
530
|
+
if (qr) {
|
|
531
|
+
console.log(`${qr}\n${metadata.url}`);
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
console.log(metadata.url);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
const token = args.join(" ");
|
|
539
|
+
const result = registerPushToken(token);
|
|
540
|
+
const action = result.added ? "Registered" : "Updated";
|
|
541
|
+
console.log(`Push token ${action.toLowerCase()}.`);
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
main();
|
|
545
|
+
}
|
|
4
546
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACvE,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|