@lucenaone/coder 1.1.17 → 1.1.18
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/package.json +1 -1
- package/src/agent.js +5 -5
- package/src/main.js +29 -1
- package/src/pro-token.js +28 -0
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -68,6 +68,7 @@ export class LucenaAgent {
|
|
|
68
68
|
this.stripCwd = true; // Default: strip absolute paths (Browser Mode safety)
|
|
69
69
|
this.indexData = null; // Pre-built index from CLI-side parsing
|
|
70
70
|
this.indexPromise = null; // The in-flight indexing promise
|
|
71
|
+
this.browserConnected = false;
|
|
71
72
|
this.shell = new LucenaShell(this.cwd);
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -109,6 +110,9 @@ export class LucenaAgent {
|
|
|
109
110
|
this.indexData = result;
|
|
110
111
|
const { stats } = result;
|
|
111
112
|
process.stdout.write(`\r ${'\x1b[32m'}✔ Indexed ${stats.filesParsed} files — ${stats.symbolCount} symbols, ${stats.stringCount} strings${'\x1b[0m'} \n`);
|
|
113
|
+
if (this.browserConnected && this.db) {
|
|
114
|
+
this.pushIndexSnapshot(result);
|
|
115
|
+
}
|
|
112
116
|
return result;
|
|
113
117
|
}).catch((err) => {
|
|
114
118
|
console.warn(`\n ${'\x1b[33m'}⚠ Indexing failed: ${err.message}${'\x1b[0m'}`);
|
|
@@ -141,6 +145,7 @@ export class LucenaAgent {
|
|
|
141
145
|
const data = snapshot.val();
|
|
142
146
|
if (!data) return;
|
|
143
147
|
remove(snapshot.ref);
|
|
148
|
+
this.browserConnected = true;
|
|
144
149
|
|
|
145
150
|
// Browser tells us whether to strip cwd from output
|
|
146
151
|
if (typeof data.stripCwd === 'boolean') {
|
|
@@ -152,7 +157,6 @@ export class LucenaAgent {
|
|
|
152
157
|
console.log(` ${'\x1b[36m'}PRO token stored. Future runs can auto-launch.${'\x1b[0m'}`);
|
|
153
158
|
}
|
|
154
159
|
|
|
155
|
-
// Index is guaranteed ready (awaited in start()), push immediately
|
|
156
160
|
if (this.indexData) {
|
|
157
161
|
this.pushIndexSnapshot(this.indexData);
|
|
158
162
|
}
|
|
@@ -174,10 +178,6 @@ export class LucenaAgent {
|
|
|
174
178
|
this.startWatcher();
|
|
175
179
|
this.connected = true;
|
|
176
180
|
|
|
177
|
-
// ── Wait for indexing to finish before opening the browser ──
|
|
178
|
-
// This guarantees the snapshot is ready the instant the browser connects
|
|
179
|
-
await this.indexPromise;
|
|
180
|
-
|
|
181
181
|
return this.tunnelId;
|
|
182
182
|
}
|
|
183
183
|
|
package/src/main.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/main.js — CLI entry point for the Lucena agent
|
|
2
2
|
import { LucenaAgent } from './agent.js';
|
|
3
3
|
import { spawn } from 'child_process';
|
|
4
|
-
import { validateStoredProToken } from './pro-token.js';
|
|
4
|
+
import { registerProTunnel, validateStoredProToken } from './pro-token.js';
|
|
5
|
+
import { basename } from 'path';
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
// Standard ANSI Terminal Colors
|
|
@@ -50,6 +51,7 @@ function openBrowser(url) {
|
|
|
50
51
|
export async function main() {
|
|
51
52
|
const cwd = process.cwd();
|
|
52
53
|
const proStatus = await validateStoredProToken();
|
|
54
|
+
let activeTunnelId = null;
|
|
53
55
|
|
|
54
56
|
console.log(BANNER);
|
|
55
57
|
console.log(` ${c.cyan}📍 Scoped to:${c.reset} ${cwd}`);
|
|
@@ -63,6 +65,17 @@ export async function main() {
|
|
|
63
65
|
|
|
64
66
|
const shutdown = async () => {
|
|
65
67
|
console.log(`\n ${c.dim}Shutting down tunnel...${c.reset}`);
|
|
68
|
+
if (proStatus.valid && activeTunnelId) {
|
|
69
|
+
await registerProTunnel({
|
|
70
|
+
tokenForPro: proStatus.stored?.tokenForPro,
|
|
71
|
+
tunnelId: activeTunnelId,
|
|
72
|
+
cwdName: basename(cwd),
|
|
73
|
+
platform: process.platform,
|
|
74
|
+
pid: process.pid,
|
|
75
|
+
status: 'disconnected',
|
|
76
|
+
online: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
66
79
|
await agent.shutdown();
|
|
67
80
|
process.exit(0);
|
|
68
81
|
};
|
|
@@ -72,6 +85,21 @@ export async function main() {
|
|
|
72
85
|
|
|
73
86
|
try {
|
|
74
87
|
const tunnelId = await agent.start();
|
|
88
|
+
activeTunnelId = tunnelId;
|
|
89
|
+
if (proStatus.valid) {
|
|
90
|
+
const registered = await registerProTunnel({
|
|
91
|
+
tokenForPro: proStatus.stored?.tokenForPro,
|
|
92
|
+
tunnelId,
|
|
93
|
+
cwdName: basename(cwd),
|
|
94
|
+
platform: process.platform,
|
|
95
|
+
pid: process.pid,
|
|
96
|
+
});
|
|
97
|
+
if (registered.ok) {
|
|
98
|
+
console.log(` ${c.cyan}RemoteControl registered.${c.reset} This run is visible on rc.lucenacoder.com.`);
|
|
99
|
+
} else {
|
|
100
|
+
console.log(` ${c.yellow}RemoteControl registration failed.${c.reset} ${registered.error || 'Run will not appear in the remote list.'}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
75
103
|
console.log(` ${c.green}✔ Tunnel active!${c.reset}\n`);
|
|
76
104
|
|
|
77
105
|
const idLabel = "Tunnel ID:";
|
package/src/pro-token.js
CHANGED
|
@@ -4,6 +4,7 @@ import { homedir } from 'os';
|
|
|
4
4
|
|
|
5
5
|
const TOKEN_PATH = join(homedir(), '.lucenacoder', 'pro.json');
|
|
6
6
|
const VALIDATE_URL = process.env.LUCENA_VALIDATE_PRO_URL || 'https://lucenacoder.com/api/pro/validate-token';
|
|
7
|
+
const REGISTER_TUNNEL_URL = process.env.LUCENA_REGISTER_TUNNEL_URL || 'https://lucenacoder.com/api/remote/register-tunnel';
|
|
7
8
|
|
|
8
9
|
export async function readStoredProToken() {
|
|
9
10
|
try {
|
|
@@ -45,3 +46,30 @@ export async function validateStoredProToken() {
|
|
|
45
46
|
return { valid: false, stored };
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
|
|
50
|
+
export async function registerProTunnel({ tokenForPro, tunnelId, cwdName, platform, pid, source = 'local-npx', status = 'active', online = true }) {
|
|
51
|
+
if (!tokenForPro || !tunnelId) return { ok: false };
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const response = await fetch(REGISTER_TUNNEL_URL, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: { 'Content-Type': 'application/json' },
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
tokenForPro,
|
|
59
|
+
tunnelId,
|
|
60
|
+
cwdName,
|
|
61
|
+
displayName: cwdName,
|
|
62
|
+
platform,
|
|
63
|
+
pid,
|
|
64
|
+
source,
|
|
65
|
+
status,
|
|
66
|
+
online,
|
|
67
|
+
}),
|
|
68
|
+
});
|
|
69
|
+
const payload = await response.json().catch(() => ({}));
|
|
70
|
+
if (!response.ok) return { ok: false, ...payload };
|
|
71
|
+
return { ok: true, ...payload };
|
|
72
|
+
} catch {
|
|
73
|
+
return { ok: false };
|
|
74
|
+
}
|
|
75
|
+
}
|