nolo-cli 0.180.0-alpha.1 → 0.181.0-alpha.1
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/{_executeModel-ACI2KGWO.js → _executeModel-EJUKYBFV.js} +17 -17
- package/{agentDeleteCommand-LVSLONDD.js → agentDeleteCommand-OWDZDREL.js} +22 -21
- package/{agentEmailCommands-BKH3Q6I6.js → agentEmailCommands-RJGVOJXD.js} +22 -21
- package/{agentListCommands-JPKRBHMP.js → agentListCommands-GRJAY5ZE.js} +6 -5
- package/{agentMachineCommands-HRORJN73.js → agentMachineCommands-FNYZSZQ4.js} +3 -3
- package/{agentRecordCommands-OSZF2EHL.js → agentRecordCommands-EBDTISRS.js} +21 -20
- package/{agentRunCommand-FCGNSB4D.js → agentRunCommand-GIBVOCOK.js} +22 -21
- package/{agentRuntimeLocal-SWG5ULIJ.js → agentRuntimeLocal-AG7RCTM3.js} +2 -2
- package/{agentSlice-FCDRLXVA.js → agentSlice-LD6SEBSP.js} +1 -1
- package/{appDeleteCommands-YH3BYQYK.js → appDeleteCommands-DXF3IOFE.js} +7 -6
- package/{appDeployCommands-F44TNQJG.js → appDeployCommands-JVKZ3ATD.js} +7 -6
- package/{appDeployStatusCommands-BFTGFVQY.js → appDeployStatusCommands-VLGEMFV6.js} +7 -6
- package/{appGetCommands-SFLFIXPW.js → appGetCommands-JQN7RPBD.js} +7 -6
- package/{appListCommands-RUO5SEAJ.js → appListCommands-MFPVNCVT.js} +7 -6
- package/{authCommand-UIF5UTYV.js → authCommand-AX23Q2Q5.js} +6 -5
- package/{authCommands-BKDT4ZYB.js → authCommands-PIUTADO5.js} +2 -2
- package/{chromeOpsCommands-IWKUA4C3.js → chromeOpsCommands-2KFQEE3H.js} +24 -46
- package/{chunk-6MXCQLLB.js → chunk-53HMDUG6.js} +14 -583
- package/{chunk-OBKPOFOB.js → chunk-5AIXW7RW.js} +10 -10
- package/{chunk-HS7JBDUJ.js → chunk-5LK5OYUB.js} +3 -3
- package/{chunk-QUCQVMYZ.js → chunk-7O6YJN4K.js} +6 -6
- package/{chunk-4KDYRX3O.js → chunk-CFW7JLTH.js} +2 -2
- package/{chunk-PD4KNHVU.js → chunk-CJYL3N3T.js} +2 -2
- package/{chunk-NJI5HZQA.js → chunk-DS47C2AI.js} +2 -2
- package/{chunk-DVSXZC7F.js → chunk-EP2L3JUM.js} +18 -18
- package/{chunk-SGATEZV5.js → chunk-F55WKIWE.js} +18 -18
- package/chunk-G5LNJZJH.js +584 -0
- package/{chunk-H63VHVFY.js → chunk-HZG23JG6.js} +3 -3
- package/{chunk-PT6335JZ.js → chunk-I4ZVPTAI.js} +1 -1
- package/chunk-LKZPX6YH.js +0 -0
- package/{chunk-TCCBECTT.js → chunk-MAS5KGBB.js} +5 -5
- package/{chunk-HTSXDJHA.js → chunk-OC4NVQ5S.js} +12 -12
- package/{chunk-GHKEUJ6I.js → chunk-OES4RYIG.js} +2 -2
- package/{chunk-TDX2L4W2.js → chunk-PS3GU7YU.js} +1857 -1138
- package/{chunk-CGKN34IJ.js → chunk-QZRAVGW3.js} +33 -33
- package/{chunk-GCAOOTIS.js → chunk-SCDJOWJT.js} +2 -2
- package/{chunk-YAN7XTXO.js → chunk-THZHXIKZ.js} +2 -2
- package/{chunk-WQAOAJ5Q.js → chunk-UCE66MIJ.js} +1 -1
- package/{chunk-DTA4JVXW.js → chunk-UXJ7R3EP.js} +2 -2
- package/{chunk-QOKJFYJK.js → chunk-WQ4M3IYD.js} +9 -9
- package/{commandRegistry-A2RXELBX.js → commandRegistry-XRHKJCWS.js} +80 -65
- package/{contentThunks-GZUPF67H.js → contentThunks-FBGQIS5J.js} +6 -6
- package/{cooldownCommands-NS63RGBO.js → cooldownCommands-QFV3ERZX.js} +14 -28
- package/{createAgentAutomationAction-ZOFCBZRE.js → createAgentAutomationAction-ASIS3C6Q.js} +6 -6
- package/{createDialogAction-G7QCYQT7.js → createDialogAction-XJGVTBWO.js} +7 -7
- package/{createPageAction-Z6JQZYS5.js → createPageAction-2IWTNKUE.js} +8 -8
- package/{dialogCommands-MITLWDBY.js → dialogCommands-VKBNO7EI.js} +2 -2
- package/{dialogSlice-PKFXK5WM.js → dialogSlice-BE76QRR4.js} +4 -4
- package/{docCreateCommands-G3S3LZMZ.js → docCreateCommands-HFDVOS2K.js} +11 -38
- package/{docDeleteCommands-MLRCMLVB.js → docDeleteCommands-DMKHPD5R.js} +17 -37
- package/{docReadCommands-6A6SBCOP.js → docReadCommands-VAUSL2N7.js} +12 -28
- package/{docStore-NAEY4CEK.js → docStore-FOTFZMVS.js} +1 -1
- package/{docUpdateCommands-UZQC2NDO.js → docUpdateCommands-6QQUX2IN.js} +19 -73
- package/{handleSendMessageAction-HUQLERJP.js → handleSendMessageAction-U6DQUBLF.js} +10 -10
- package/index.js +17 -7
- package/{localRuntimeAdapter-4DJDFM7A.js → localRuntimeAdapter-DM7ERZ6Z.js} +20 -19
- package/{machineCommands-A3WO3FMB.js → machineCommands-OJPPEMNZ.js} +326 -113
- package/{machineWsRunDispatch-CIJDSHTA.js → machineWsRunDispatch-I5WWJ2EY.js} +21 -20
- package/package.json +1 -1
- package/{readlineWorkspace-YCNAWRDL.js → readlineWorkspace-RMG27VY3.js} +31 -29
- package/{runAgentClientLoop-K7WRMT27.js → runAgentClientLoop-QJL24CN5.js} +15 -15
- package/{secretCommands-7S6REMJV.js → secretCommands-XEQLKDB4.js} +33 -47
- package/{spaceCommands-L537SH5I.js → spaceCommands-Z325DDJU.js} +2 -2
- package/{streamAgentChatTurn-HKUZ7OCA.js → streamAgentChatTurn-4ZA46AEJ.js} +19 -19
- package/{tools-NS37KPGT.js → tools-GWQ4POVC.js} +12 -12
- package/{updateCommands-BXGFH4VX.js → updateCommands-KDYX32JR.js} +3 -1
- package/{updateDialogTitleAction-UUZ5HDM2.js → updateDialogTitleAction-VTE36JGF.js} +6 -6
- package/windowsSelfUpdate-IYQK4IDS.js +14 -0
- package/{agentPullCommand-UXXV5KKW.js → agentPullCommand-7LHBOEYH.js} +1 -1
- package/{chunk-COXNBVP7.js → chunk-FLX5EYLQ.js} +4 -4
- package/{chunk-RV4DPEAM.js → chunk-XLQ646HU.js} +3 -3
- package/{workloadLifecycle-MZ2V5L43.js → workloadLifecycle-2F5YKFGW.js} +7 -7
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
buildMachinePermissionPromptBlock,
|
|
3
3
|
handleConnectorRunMessage,
|
|
4
4
|
resolveMachineRunPermissionPolicy
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7O6YJN4K.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_CONNECTOR_TIMER_DELAY_MS,
|
|
8
8
|
clampConnectorTimerDelayMs,
|
|
@@ -11,10 +11,11 @@ import {
|
|
|
11
11
|
resolveConnectorProbeTimeoutMs,
|
|
12
12
|
resolveConnectorWebSocketTarget
|
|
13
13
|
} from "./chunk-BLVSFYQ3.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-F55WKIWE.js";
|
|
15
15
|
import "./chunk-D2J22QSE.js";
|
|
16
16
|
import "./chunk-R4BMKAR5.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-LKZPX6YH.js";
|
|
18
|
+
import "./chunk-GKKIZRJ6.js";
|
|
18
19
|
import {
|
|
19
20
|
parsePositiveFiniteNumberOrFallback
|
|
20
21
|
} from "./chunk-Y5GCAMGP.js";
|
|
@@ -23,28 +24,30 @@ import "./chunk-CTEEJJVR.js";
|
|
|
23
24
|
import "./chunk-NBTY7YJF.js";
|
|
24
25
|
import "./chunk-VL5KOY2C.js";
|
|
25
26
|
import {
|
|
26
|
-
detectMachineInfo
|
|
27
|
+
detectMachineInfo,
|
|
28
|
+
resolveMachineId
|
|
27
29
|
} from "./chunk-S73EPYNC.js";
|
|
28
30
|
import "./chunk-ZEZC7IIM.js";
|
|
29
31
|
import "./chunk-VIWDGTDA.js";
|
|
30
32
|
import "./chunk-HGDKT2D6.js";
|
|
31
|
-
import "./chunk-GKKIZRJ6.js";
|
|
32
33
|
import "./chunk-W6E5IXIP.js";
|
|
33
34
|
import "./chunk-ATNTHIZI.js";
|
|
34
35
|
import "./chunk-INFHX73M.js";
|
|
35
|
-
import "./chunk-
|
|
36
|
+
import "./chunk-SCDJOWJT.js";
|
|
36
37
|
import "./chunk-HS7MLR74.js";
|
|
37
|
-
import "./chunk-
|
|
38
|
+
import "./chunk-QZRAVGW3.js";
|
|
38
39
|
import "./chunk-2D3YKEAQ.js";
|
|
39
40
|
import "./chunk-KFHREHUQ.js";
|
|
40
41
|
import "./chunk-OXME3PEE.js";
|
|
41
|
-
import "./chunk-
|
|
42
|
+
import "./chunk-BAWAKW7X.js";
|
|
43
|
+
import "./chunk-DS47C2AI.js";
|
|
42
44
|
import "./chunk-NF64D32W.js";
|
|
43
45
|
import {
|
|
44
46
|
CORE_DRAIN_REASON
|
|
45
47
|
} from "./chunk-3L2WKC3W.js";
|
|
46
48
|
import "./chunk-VYNMQ6HW.js";
|
|
47
49
|
import "./chunk-MYOH447Z.js";
|
|
50
|
+
import "./chunk-IF7V3CBU.js";
|
|
48
51
|
import "./chunk-3L5MSPWX.js";
|
|
49
52
|
import "./chunk-TDNAAXUQ.js";
|
|
50
53
|
import "./chunk-VIDPVFP3.js";
|
|
@@ -52,20 +55,19 @@ import "./chunk-KSTEXKL6.js";
|
|
|
52
55
|
import "./chunk-AGIM7IMJ.js";
|
|
53
56
|
import "./chunk-63W5N6P3.js";
|
|
54
57
|
import "./chunk-VF4K2QE6.js";
|
|
55
|
-
import "./chunk-
|
|
56
|
-
import "./chunk-
|
|
57
|
-
import "./chunk-
|
|
58
|
-
import "./chunk-IF7V3CBU.js";
|
|
58
|
+
import "./chunk-CFW7JLTH.js";
|
|
59
|
+
import "./chunk-CJYL3N3T.js";
|
|
60
|
+
import "./chunk-FDLDMJTM.js";
|
|
59
61
|
import "./chunk-YPG7TUQD.js";
|
|
60
|
-
import "./chunk-
|
|
61
|
-
import "./chunk-
|
|
62
|
-
import "./chunk-
|
|
62
|
+
import "./chunk-MAS5KGBB.js";
|
|
63
|
+
import "./chunk-ZJ7UHBJS.js";
|
|
64
|
+
import "./chunk-OC4NVQ5S.js";
|
|
63
65
|
import "./chunk-523DITKR.js";
|
|
66
|
+
import "./chunk-OFFL4DCR.js";
|
|
67
|
+
import "./chunk-BYXBJQAS.js";
|
|
64
68
|
import "./chunk-QYPE3TS3.js";
|
|
65
|
-
import "./chunk-
|
|
69
|
+
import "./chunk-5LK5OYUB.js";
|
|
66
70
|
import "./chunk-4JH2UMJR.js";
|
|
67
|
-
import "./chunk-ZJ7UHBJS.js";
|
|
68
|
-
import "./chunk-BYXBJQAS.js";
|
|
69
71
|
import "./chunk-ESMZW5PE.js";
|
|
70
72
|
import "./chunk-5RGU3J7P.js";
|
|
71
73
|
import "./chunk-OWYYDMGJ.js";
|
|
@@ -99,14 +101,14 @@ import {
|
|
|
99
101
|
PATH_FIELD_ALIASES,
|
|
100
102
|
createLocalWorkspaceToolExecutors,
|
|
101
103
|
resolveRequestedWorkspacePath
|
|
102
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-FLX5EYLQ.js";
|
|
103
105
|
import "./chunk-KMSMIOOL.js";
|
|
104
106
|
import "./chunk-ZNFJWEN4.js";
|
|
105
107
|
import "./chunk-YO776XHS.js";
|
|
106
108
|
import "./chunk-HNUWUO75.js";
|
|
109
|
+
import "./chunk-HIVDQPQR.js";
|
|
107
110
|
import "./chunk-CHOZJMJS.js";
|
|
108
111
|
import "./chunk-PWTNI4N7.js";
|
|
109
|
-
import "./chunk-HIVDQPQR.js";
|
|
110
112
|
import "./chunk-CR5WXQX7.js";
|
|
111
113
|
import "./chunk-2WZXXAQD.js";
|
|
112
114
|
import "./chunk-P2BGRAW7.js";
|
|
@@ -143,7 +145,6 @@ import "./chunk-U6VC4MU4.js";
|
|
|
143
145
|
import "./chunk-CI5DVWU7.js";
|
|
144
146
|
import "./chunk-PJNFNEJE.js";
|
|
145
147
|
import "./chunk-PSCNXBYA.js";
|
|
146
|
-
import "./chunk-FDLDMJTM.js";
|
|
147
148
|
import "./chunk-GLKOYSRU.js";
|
|
148
149
|
import "./chunk-EYLGAEB4.js";
|
|
149
150
|
import {
|
|
@@ -155,6 +156,9 @@ import {
|
|
|
155
156
|
import "./chunk-LCBAMY2M.js";
|
|
156
157
|
import "./chunk-R5GO3YZP.js";
|
|
157
158
|
import "./chunk-Y6ROFCZO.js";
|
|
159
|
+
import {
|
|
160
|
+
t
|
|
161
|
+
} from "./chunk-PS3GU7YU.js";
|
|
158
162
|
import "./chunk-HLAL63BZ.js";
|
|
159
163
|
import "./chunk-JOUFPRE4.js";
|
|
160
164
|
import "./chunk-WWC7I6TA.js";
|
|
@@ -194,11 +198,169 @@ async function runHeartbeatLoop(options) {
|
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
|
|
201
|
+
// packages/cli/connectorInstanceLock.ts
|
|
202
|
+
import {
|
|
203
|
+
closeSync,
|
|
204
|
+
mkdirSync,
|
|
205
|
+
openSync,
|
|
206
|
+
readFileSync,
|
|
207
|
+
renameSync,
|
|
208
|
+
statSync,
|
|
209
|
+
unlinkSync,
|
|
210
|
+
writeFileSync
|
|
211
|
+
} from "node:fs";
|
|
212
|
+
import { homedir } from "node:os";
|
|
213
|
+
import { join } from "node:path";
|
|
214
|
+
function resolveConnectorStateDir(args = {}) {
|
|
215
|
+
const homeDir = args.homeDir?.trim();
|
|
216
|
+
if (homeDir) return join(homeDir, ".nolo", "connector");
|
|
217
|
+
const noloHome = args.noloHome?.trim() || process.env.NOLO_HOME?.trim();
|
|
218
|
+
if (noloHome) return join(noloHome, "connector");
|
|
219
|
+
return join(homedir(), ".nolo", "connector");
|
|
220
|
+
}
|
|
221
|
+
function sanitizeMachineId(machineId) {
|
|
222
|
+
const safe = String(machineId ?? "").replace(/[^A-Za-z0-9._-]/g, "_");
|
|
223
|
+
return safe || "unknown";
|
|
224
|
+
}
|
|
225
|
+
function connectorInstanceLockPath(args) {
|
|
226
|
+
return join(resolveConnectorStateDir(args), `${sanitizeMachineId(args.machineId)}.lock`);
|
|
227
|
+
}
|
|
228
|
+
function connectorAliveSignalPath(args) {
|
|
229
|
+
return join(resolveConnectorStateDir(args), `${sanitizeMachineId(args.machineId)}.alive`);
|
|
230
|
+
}
|
|
231
|
+
function isProcessAlive(pid) {
|
|
232
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
233
|
+
try {
|
|
234
|
+
process.kill(pid, 0);
|
|
235
|
+
return true;
|
|
236
|
+
} catch (error) {
|
|
237
|
+
return error?.code === "EPERM";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function readLockPid(lockPath) {
|
|
241
|
+
let raw;
|
|
242
|
+
try {
|
|
243
|
+
raw = readFileSync(lockPath, "utf8");
|
|
244
|
+
} catch {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
const parsed = JSON.parse(raw);
|
|
249
|
+
const pid = Number(parsed?.pid);
|
|
250
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
251
|
+
} catch {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function isEexist(error) {
|
|
256
|
+
return error?.code === "EEXIST";
|
|
257
|
+
}
|
|
258
|
+
var CONNECTOR_LOCK_CORRUPT_RECLAIM_SECONDS = 300;
|
|
259
|
+
function inspectCorruptLock(lockPath, now = Date.now()) {
|
|
260
|
+
try {
|
|
261
|
+
const stat2 = statSync(lockPath);
|
|
262
|
+
const ageMs = now - stat2.mtimeMs;
|
|
263
|
+
return ageMs > CONNECTOR_LOCK_CORRUPT_RECLAIM_SECONDS * 1e3 ? "expired" : "fresh";
|
|
264
|
+
} catch (error) {
|
|
265
|
+
const code = error?.code;
|
|
266
|
+
if (code === "ENOENT") return "gone";
|
|
267
|
+
return "fresh";
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function acquireConnectorInstanceLock(args) {
|
|
271
|
+
const lockPath = connectorInstanceLockPath(args);
|
|
272
|
+
mkdirSync(resolveConnectorStateDir(args), { recursive: true });
|
|
273
|
+
let reclaimed;
|
|
274
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
275
|
+
let fd = null;
|
|
276
|
+
try {
|
|
277
|
+
fd = openSync(lockPath, "wx");
|
|
278
|
+
} catch (error) {
|
|
279
|
+
if (!isEexist(error)) throw error;
|
|
280
|
+
const ownerPid2 = readLockPid(lockPath);
|
|
281
|
+
if (ownerPid2 !== null) {
|
|
282
|
+
if (isProcessAlive(ownerPid2)) {
|
|
283
|
+
return { ok: false, pid: ownerPid2 };
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
unlinkSync(lockPath);
|
|
287
|
+
} catch {
|
|
288
|
+
}
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
const state = inspectCorruptLock(lockPath);
|
|
292
|
+
if (state === "gone") {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (state === "fresh") {
|
|
296
|
+
return { ok: false, pid: 0 };
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
unlinkSync(lockPath);
|
|
300
|
+
} catch {
|
|
301
|
+
}
|
|
302
|
+
reclaimed = "corrupt";
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
writeFileSync(fd, JSON.stringify({ pid: process.pid, startedAt: Date.now() }), "utf8");
|
|
307
|
+
} finally {
|
|
308
|
+
closeSync(fd);
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
ok: true,
|
|
312
|
+
release: () => releaseConnectorInstanceLock(lockPath),
|
|
313
|
+
...reclaimed ? { reclaimed } : {}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
const ownerPid = readLockPid(lockPath);
|
|
317
|
+
return { ok: false, pid: ownerPid ?? 0 };
|
|
318
|
+
}
|
|
319
|
+
function releaseConnectorInstanceLock(lockPath) {
|
|
320
|
+
const ownerPid = readLockPid(lockPath);
|
|
321
|
+
if (ownerPid !== process.pid) return;
|
|
322
|
+
try {
|
|
323
|
+
unlinkSync(lockPath);
|
|
324
|
+
} catch {
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
function markConnectorAlive(args) {
|
|
328
|
+
const path = connectorAliveSignalPath(args);
|
|
329
|
+
try {
|
|
330
|
+
mkdirSync(resolveConnectorStateDir(args), { recursive: true });
|
|
331
|
+
const tmpPath = `${path}.${process.pid}.tmp`;
|
|
332
|
+
writeFileSync(tmpPath, String(Date.now()), "utf8");
|
|
333
|
+
try {
|
|
334
|
+
renameSync(tmpPath, path);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
try {
|
|
337
|
+
unlinkSync(tmpPath);
|
|
338
|
+
} catch {
|
|
339
|
+
}
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function clearConnectorAlive(args) {
|
|
346
|
+
try {
|
|
347
|
+
unlinkSync(connectorAliveSignalPath(args));
|
|
348
|
+
} catch {
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function withConnectorAliveSignal(sendHeartbeat, args) {
|
|
352
|
+
return async () => {
|
|
353
|
+
const result = await sendHeartbeat();
|
|
354
|
+
markConnectorAlive(args);
|
|
355
|
+
return result;
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
197
359
|
// packages/cli/machineDaemonCommands.ts
|
|
198
360
|
import { spawn } from "node:child_process";
|
|
199
|
-
import { existsSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
200
|
-
import { homedir } from "node:os";
|
|
201
|
-
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
361
|
+
import { existsSync, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync2, readdirSync, realpathSync } from "node:fs";
|
|
362
|
+
import { homedir as homedir2 } from "node:os";
|
|
363
|
+
import { dirname, isAbsolute, join as join2, relative, resolve } from "node:path";
|
|
202
364
|
import { fileURLToPath } from "node:url";
|
|
203
365
|
var CONNECTOR_RUNTIME_WORKSPACE_PACKAGES = /* @__PURE__ */ new Set([
|
|
204
366
|
"connector-experimental",
|
|
@@ -206,7 +368,7 @@ var CONNECTOR_RUNTIME_WORKSPACE_PACKAGES = /* @__PURE__ */ new Set([
|
|
|
206
368
|
]);
|
|
207
369
|
function readJsonFile(path) {
|
|
208
370
|
try {
|
|
209
|
-
return JSON.parse(
|
|
371
|
+
return JSON.parse(readFileSync2(path, "utf8"));
|
|
210
372
|
} catch {
|
|
211
373
|
return null;
|
|
212
374
|
}
|
|
@@ -226,7 +388,7 @@ function isInsideOrSame(path, parent) {
|
|
|
226
388
|
function findWorkspaceRoot(startPath) {
|
|
227
389
|
let current = resolve(startPath);
|
|
228
390
|
while (true) {
|
|
229
|
-
const packageJsonPath =
|
|
391
|
+
const packageJsonPath = join2(current, "package.json");
|
|
230
392
|
if (existsSync(packageJsonPath)) {
|
|
231
393
|
const packageJson = readJsonFile(packageJsonPath);
|
|
232
394
|
if (packageJson && getWorkspacePatterns(packageJson).length > 0) {
|
|
@@ -249,7 +411,7 @@ function listWorkspacePackageJsonFiles(workspaceParent) {
|
|
|
249
411
|
for (const entry of entries) {
|
|
250
412
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
251
413
|
const relativePath = `${entry.name}/package.json`;
|
|
252
|
-
if (existsSync(
|
|
414
|
+
if (existsSync(join2(workspaceParent, relativePath))) {
|
|
253
415
|
results.push(relativePath);
|
|
254
416
|
}
|
|
255
417
|
}
|
|
@@ -258,21 +420,21 @@ function listWorkspacePackageJsonFiles(workspaceParent) {
|
|
|
258
420
|
function validateConnectorWorkspaceLinks(cwd) {
|
|
259
421
|
const repoRoot = findWorkspaceRoot(cwd);
|
|
260
422
|
if (!repoRoot) return [];
|
|
261
|
-
const rootPackageJson = readJsonFile(
|
|
423
|
+
const rootPackageJson = readJsonFile(join2(repoRoot, "package.json"));
|
|
262
424
|
if (!rootPackageJson) return [];
|
|
263
425
|
const normalizedRepoRoot = normalizePath(realpathSync(repoRoot));
|
|
264
426
|
const errors = [];
|
|
265
427
|
for (const pattern of getWorkspacePatterns(rootPackageJson)) {
|
|
266
428
|
if (!pattern.endsWith("/*")) continue;
|
|
267
|
-
const workspaceParent =
|
|
429
|
+
const workspaceParent = join2(repoRoot, pattern.slice(0, -2));
|
|
268
430
|
if (!existsSync(workspaceParent)) continue;
|
|
269
431
|
for (const entry of listWorkspacePackageJsonFiles(workspaceParent)) {
|
|
270
|
-
const packageDir =
|
|
271
|
-
const packageJson = readJsonFile(
|
|
432
|
+
const packageDir = join2(workspaceParent, dirname(entry));
|
|
433
|
+
const packageJson = readJsonFile(join2(workspaceParent, entry));
|
|
272
434
|
if (!packageJson?.name || !CONNECTOR_RUNTIME_WORKSPACE_PACKAGES.has(packageJson.name)) {
|
|
273
435
|
continue;
|
|
274
436
|
}
|
|
275
|
-
const linkPath =
|
|
437
|
+
const linkPath = join2(repoRoot, "node_modules", ...packageJson.name.split("/"));
|
|
276
438
|
if (!existsSync(linkPath)) {
|
|
277
439
|
errors.push(`${linkPath} is missing. Run bun install in ${repoRoot}.`);
|
|
278
440
|
continue;
|
|
@@ -308,7 +470,7 @@ async function checkConnectorWorkspaceLinks(cwd, output, validateWorkspaceLinks)
|
|
|
308
470
|
return false;
|
|
309
471
|
}
|
|
310
472
|
function resolveDaemonLogPath(env) {
|
|
311
|
-
return env.NOLO_CONNECT_LOG ||
|
|
473
|
+
return env.NOLO_CONNECT_LOG || join2(homedir2(), ".nolo", "logs", "connector.log");
|
|
312
474
|
}
|
|
313
475
|
function buildDaemonCommand(cliEntrypointPath) {
|
|
314
476
|
const execPath = process.execPath;
|
|
@@ -319,8 +481,8 @@ function buildDaemonCommand(cliEntrypointPath) {
|
|
|
319
481
|
return [execPath, entrypoint, "connect", "--ws"];
|
|
320
482
|
}
|
|
321
483
|
function defaultSpawnDaemon(args) {
|
|
322
|
-
|
|
323
|
-
const out =
|
|
484
|
+
mkdirSync2(dirname(args.logPath), { recursive: true });
|
|
485
|
+
const out = openSync2(args.logPath, "a");
|
|
324
486
|
const env = Object.fromEntries(
|
|
325
487
|
Object.entries(args.env).filter((entry) => typeof entry[1] === "string")
|
|
326
488
|
);
|
|
@@ -340,6 +502,20 @@ async function runMachineDaemonCommand(deps = {}) {
|
|
|
340
502
|
if (!await checkConnectorWorkspaceLinks(process.cwd(), output, validateWorkspaceLinks)) {
|
|
341
503
|
return 1;
|
|
342
504
|
}
|
|
505
|
+
const probe = acquireConnectorInstanceLock({
|
|
506
|
+
machineId: deps.machineId ?? resolveMachineId(),
|
|
507
|
+
homeDir: deps.connectorHomeDir,
|
|
508
|
+
noloHome: env.NOLO_HOME,
|
|
509
|
+
kind: "daemon"
|
|
510
|
+
});
|
|
511
|
+
if (!probe.ok) {
|
|
512
|
+
output.write(
|
|
513
|
+
`[nolo] A connector for this machine is already running (pid=${probe.pid}). Do not start two connectors at the same time \u2014 stop the running one first (or check whether it is still healthy) before starting a new one.
|
|
514
|
+
`
|
|
515
|
+
);
|
|
516
|
+
return 3;
|
|
517
|
+
}
|
|
518
|
+
probe.release();
|
|
343
519
|
const logPath = resolveDaemonLogPath(env);
|
|
344
520
|
const result = (deps.spawnDaemon ?? defaultSpawnDaemon)({
|
|
345
521
|
cmd: buildDaemonCommand(deps.cliEntrypointPath),
|
|
@@ -400,8 +576,8 @@ async function runMachineWatchCommand(deps) {
|
|
|
400
576
|
|
|
401
577
|
// packages/cli/machineToolInvokeDispatch.ts
|
|
402
578
|
import { appendFile, lstat, mkdir, realpath, stat } from "node:fs/promises";
|
|
403
|
-
import { homedir as
|
|
404
|
-
import { dirname as dirname2, isAbsolute as isAbsolute2, join as
|
|
579
|
+
import { homedir as homedir3 } from "node:os";
|
|
580
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join3, relative as relative2, resolve as resolve2, sep } from "node:path";
|
|
405
581
|
|
|
406
582
|
// packages/agent-runtime/machineToolGrants.ts
|
|
407
583
|
function isRecord2(value) {
|
|
@@ -464,8 +640,8 @@ function isMachineToolGranted(grants, toolName, agentKey) {
|
|
|
464
640
|
}
|
|
465
641
|
function resolveMachineToolAuditLogPath() {
|
|
466
642
|
const noloHome = process.env.NOLO_HOME?.trim();
|
|
467
|
-
const base = noloHome ? noloHome :
|
|
468
|
-
return
|
|
643
|
+
const base = noloHome ? noloHome : join3(homedir3(), ".nolo");
|
|
644
|
+
return join3(base, "logs", "machine-tool-audit.jsonl");
|
|
469
645
|
}
|
|
470
646
|
function auditTargetFor(executorArgs) {
|
|
471
647
|
const target = extractMachineToolRequestPath(executorArgs) ?? "";
|
|
@@ -1099,7 +1275,8 @@ function resolveAuthToken2(env) {
|
|
|
1099
1275
|
}
|
|
1100
1276
|
function writeAuthMissing2(output) {
|
|
1101
1277
|
output.write(
|
|
1102
|
-
"
|
|
1278
|
+
`${t("cliMachineAuthMissing")}
|
|
1279
|
+
`
|
|
1103
1280
|
);
|
|
1104
1281
|
}
|
|
1105
1282
|
function hasFlag(args, flag) {
|
|
@@ -1261,11 +1438,13 @@ async function runMachineConnectCommand(args, deps = {}) {
|
|
|
1261
1438
|
output,
|
|
1262
1439
|
cliEntrypointPath: deps.cliEntrypointPath,
|
|
1263
1440
|
validateWorkspaceLinks: deps.validateWorkspaceLinks,
|
|
1264
|
-
spawnDaemon: deps.spawnDaemon
|
|
1441
|
+
spawnDaemon: deps.spawnDaemon,
|
|
1442
|
+
connectorHomeDir: deps.connectorHomeDir
|
|
1265
1443
|
});
|
|
1266
1444
|
}
|
|
1267
1445
|
const machine = (deps.machineInfo ?? detectLaunchableMachineInfo)();
|
|
1268
|
-
const
|
|
1446
|
+
const machineId = machine.machineId;
|
|
1447
|
+
const sendHeartbeatBase = () => postMachineHeartbeat({
|
|
1269
1448
|
fetchImpl,
|
|
1270
1449
|
serverUrl,
|
|
1271
1450
|
authToken,
|
|
@@ -1277,96 +1456,130 @@ async function runMachineConnectCommand(args, deps = {}) {
|
|
|
1277
1456
|
if (!await checkConnectorWorkspaceLinks(process.cwd(), output, validateWorkspaceLinks)) {
|
|
1278
1457
|
return 1;
|
|
1279
1458
|
}
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
workspaceRoot: process.cwd(),
|
|
1286
|
-
// M2 修复:机器侧授权复核与握手上报共用同一来源——本次 `deps.env ??
|
|
1287
|
-
// process.env`。grants 快照与 WS URL 上报的那份逐字节相同;未配置时也
|
|
1288
|
-
// 显式传 env,工厂不再回落到 process.env(调用方经 deps.env 注入环境时
|
|
1289
|
-
// 两端曾不一致)。
|
|
1290
|
-
env,
|
|
1291
|
-
...toolGrants ? { grants: toolGrants } : {}
|
|
1459
|
+
const instanceLock = acquireConnectorInstanceLock({
|
|
1460
|
+
machineId,
|
|
1461
|
+
homeDir: deps.connectorHomeDir,
|
|
1462
|
+
noloHome: env.NOLO_HOME,
|
|
1463
|
+
kind: "ws"
|
|
1292
1464
|
});
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1465
|
+
if (!instanceLock.ok) {
|
|
1466
|
+
const owner = instanceLock.pid > 0 ? `pid=${instanceLock.pid}` : "owner pid unknown";
|
|
1467
|
+
output.write(
|
|
1468
|
+
`[nolo] A connector for this machine is already running (${owner}). Do not start two connectors at the same time \u2014 stop the running one first (or check whether it is still healthy) before starting a new one.
|
|
1469
|
+
`
|
|
1470
|
+
);
|
|
1471
|
+
return 3;
|
|
1472
|
+
}
|
|
1473
|
+
if (instanceLock.reclaimed === "corrupt") {
|
|
1474
|
+
output.write(
|
|
1475
|
+
`[nolo] Reclaimed a corrupt connector lock (no readable pid, older than ${CONNECTOR_LOCK_CORRUPT_RECLAIM_SECONDS}s) \u2014 a previous connector likely crashed while writing it.
|
|
1476
|
+
`
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
const sendHeartbeat = withConnectorAliveSignal(sendHeartbeatBase, {
|
|
1480
|
+
machineId,
|
|
1481
|
+
homeDir: deps.connectorHomeDir,
|
|
1482
|
+
noloHome: env.NOLO_HOME
|
|
1483
|
+
});
|
|
1484
|
+
try {
|
|
1485
|
+
const maxAttempts = deps.maxConnectorAttempts ?? Infinity;
|
|
1486
|
+
const sleep = deps.sleep ?? defaultSleep2;
|
|
1487
|
+
const reconnectDelayMs = resolveConnectorReconnectDelayMs(env);
|
|
1488
|
+
const toolGrants = readMachineToolGrants(env);
|
|
1489
|
+
const toolInvokeHandlers = createMachineToolInvokeHandlers({
|
|
1490
|
+
workspaceRoot: process.cwd(),
|
|
1491
|
+
// M2 修复:机器侧授权复核与握手上报共用同一来源——本次 `deps.env ??
|
|
1492
|
+
// process.env`。grants 快照与 WS URL 上报的那份逐字节相同;未配置时也
|
|
1493
|
+
// 显式传 env,工厂不再回落到 process.env(调用方经 deps.env 注入环境时
|
|
1494
|
+
// 两端曾不一致)。
|
|
1299
1495
|
env,
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
serverUrl
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1496
|
+
...toolGrants ? { grants: toolGrants } : {}
|
|
1497
|
+
});
|
|
1498
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
1499
|
+
if (deps.signal?.aborted) {
|
|
1500
|
+
return 0;
|
|
1501
|
+
}
|
|
1502
|
+
const runtimeServerUrl = env.NOLO_CONNECT_RUNTIME_SERVER_URL || env.NOLO_RUNTIME_SERVER_URL || serverUrl;
|
|
1503
|
+
const sessionResult = await runMachineWsSession({
|
|
1504
|
+
env,
|
|
1505
|
+
output,
|
|
1506
|
+
signal: deps.signal,
|
|
1507
|
+
machine,
|
|
1508
|
+
sendHeartbeat,
|
|
1509
|
+
runHeartbeatLoop: deps.runHeartbeatLoop ?? runHeartbeatLoop,
|
|
1510
|
+
connectWebSocket: deps.connectWebSocket ?? defaultConnectWebSocket,
|
|
1511
|
+
serverUrl,
|
|
1512
|
+
authToken,
|
|
1513
|
+
resolveConnectorWebSocketTarget: async (options) => appendToolGrantsToWsUrl(
|
|
1514
|
+
await resolveConnectorWebSocketTarget({
|
|
1515
|
+
...options,
|
|
1516
|
+
fetchImpl
|
|
1517
|
+
}),
|
|
1518
|
+
toolGrants
|
|
1519
|
+
),
|
|
1520
|
+
onMessage: (message, send) => handleMachineWsMessageDemux(
|
|
1320
1521
|
message,
|
|
1321
1522
|
send,
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1523
|
+
{ toolInvoke: toolInvokeHandlers },
|
|
1524
|
+
() => handleConnectorRunMessage(
|
|
1525
|
+
message,
|
|
1526
|
+
send,
|
|
1527
|
+
deps.executeCli ?? defaultExecuteCli,
|
|
1528
|
+
{
|
|
1529
|
+
...env,
|
|
1530
|
+
NOLO_SERVER: runtimeServerUrl,
|
|
1531
|
+
NOLO_SERVER_URL: runtimeServerUrl,
|
|
1532
|
+
BASE_URL: runtimeServerUrl,
|
|
1533
|
+
AUTH_TOKEN: authToken,
|
|
1534
|
+
NOLO_MACHINE_API_KEY: authToken
|
|
1535
|
+
},
|
|
1536
|
+
fetchImpl,
|
|
1537
|
+
{
|
|
1538
|
+
buildConnectorCliPrompt
|
|
1539
|
+
}
|
|
1540
|
+
)
|
|
1335
1541
|
)
|
|
1336
|
-
)
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
`[nolo] Connector websocket disconnected${reconnectContext}. Reconnecting in ${retryDelayMs}ms.
|
|
1542
|
+
});
|
|
1543
|
+
const exitCode = sessionResult.exitCode;
|
|
1544
|
+
if (exitCode === 2) return 1;
|
|
1545
|
+
if (deps.signal?.aborted) {
|
|
1546
|
+
return 0;
|
|
1547
|
+
}
|
|
1548
|
+
if (attempt >= maxAttempts) return exitCode;
|
|
1549
|
+
const retryDelayMs = Math.min(
|
|
1550
|
+
sessionResult.retryAfterMs ?? reconnectDelayMs,
|
|
1551
|
+
MAX_CONNECTOR_TIMER_DELAY_MS
|
|
1552
|
+
);
|
|
1553
|
+
const reconnectContext = sessionResult.reconnectReason === CORE_DRAIN_REASON ? " during core draining" : "";
|
|
1554
|
+
output.write(
|
|
1555
|
+
`[nolo] Connector websocket disconnected${reconnectContext}. Reconnecting in ${retryDelayMs}ms.
|
|
1351
1556
|
`
|
|
1352
|
-
|
|
1353
|
-
|
|
1557
|
+
);
|
|
1558
|
+
await sleepWithAbort(retryDelayMs, sleep, deps.signal);
|
|
1559
|
+
}
|
|
1560
|
+
return 0;
|
|
1561
|
+
} finally {
|
|
1562
|
+
instanceLock.release();
|
|
1563
|
+
clearConnectorAlive({
|
|
1564
|
+
machineId,
|
|
1565
|
+
homeDir: deps.connectorHomeDir,
|
|
1566
|
+
noloHome: env.NOLO_HOME
|
|
1567
|
+
});
|
|
1354
1568
|
}
|
|
1355
|
-
return 0;
|
|
1356
1569
|
}
|
|
1357
1570
|
if (hasFlag(args, "--watch")) {
|
|
1358
1571
|
return runMachineWatchCommand({
|
|
1359
1572
|
env,
|
|
1360
1573
|
output,
|
|
1361
1574
|
machine,
|
|
1362
|
-
sendHeartbeat,
|
|
1575
|
+
sendHeartbeat: sendHeartbeatBase,
|
|
1363
1576
|
runHeartbeatLoop: deps.runHeartbeatLoop ?? runHeartbeatLoop
|
|
1364
1577
|
});
|
|
1365
1578
|
}
|
|
1366
1579
|
return runMachineHeartbeatConnectCommand({
|
|
1367
1580
|
output,
|
|
1368
1581
|
machine,
|
|
1369
|
-
sendHeartbeat
|
|
1582
|
+
sendHeartbeat: sendHeartbeatBase
|
|
1370
1583
|
});
|
|
1371
1584
|
}
|
|
1372
1585
|
export {
|