nolo-cli 0.80.0-alpha.1 → 0.80.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/README.md +2 -2
- package/{_executeModel-T3FPYFVF.js → _executeModel-UXVEB3GO.js} +46 -46
- package/{action-D22U6CTH.js → action-YVYQEAAV.js} +11 -11
- package/{addContentAction-XAPUTGL4.js → addContentAction-O7R66HEX.js} +9 -9
- package/{addDialogAgentAction-M7VLLBZM.js → addDialogAgentAction-74OA7KYP.js} +8 -8
- package/{agentDeleteCommand-2TYFURBN.js → agentDeleteCommand-OODHSL4K.js} +30 -28
- package/{agentEmailCommands-7P35ZMUA.js → agentEmailCommands-3R73WSCD.js} +64 -60
- package/{agentGrantCommands-R3VQEZJR.js → agentGrantCommands-M3XFO6EN.js} +2 -2
- package/{agentListCommands-IFUOWXP3.js → agentListCommands-TBTEXV2E.js} +38 -30
- package/{agentMachineCommands-G46ZZ2ZQ.js → agentMachineCommands-3GKE6ZHG.js} +30 -28
- package/{agentProviderCommands-65ZC2WB4.js → agentProviderCommands-GNPTL5XR.js} +87 -0
- package/{agentPullCommand-N7L2CT7L.js → agentPullCommand-O5MPVJ5E.js} +3 -3
- package/{agentRecordCommands-R74LTQEQ.js → agentRecordCommands-3664GLRE.js} +61 -57
- package/{agentRunCommand-UKJAECQ6.js → agentRunCommand-YNSEOBTR.js} +62 -58
- package/{agentRunControl-T44MESII.js → agentRunControl-XLGD3UZ5.js} +1 -1
- package/{agentRuntimeLocal-PUZINLWJ.js → agentRuntimeLocal-5BX6PI4X.js} +28 -26
- package/{agentSlice-EACXUOWW.js → agentSlice-KTVOEUDX.js} +10 -10
- package/{appDeleteCommands-U4NTEJYQ.js → appDeleteCommands-UNTBD55Y.js} +30 -28
- package/{appDeployCommands-FXF45Q7F.js → appDeployCommands-LOF4JNBZ.js} +30 -28
- package/{appDeployStatusCommands-KONVRM53.js → appDeployStatusCommands-MMLE6BDW.js} +30 -28
- package/{appGetCommands-3VOGIZ7T.js → appGetCommands-WFJAJK6B.js} +30 -28
- package/{appListCommands-A6ROBW7P.js → appListCommands-NC265RGX.js} +30 -28
- package/{authCommand-EVGFLAHO.js → authCommand-F4EFRRX6.js} +164 -24
- package/{authCommands-ILTBI6JV.js → authCommands-RGOGCPP6.js} +4 -5
- package/builtinSkillRegistry-FUAVTRVZ.js +33 -0
- package/{chatQueueReduxAdapter-XEIJO5WR.js → chatQueueReduxAdapter-4YQF4NHY.js} +24 -24
- package/{chromeCommands-VOIRNJBL.js → chromeCommands-FZYAU75D.js} +1 -1
- package/{chromeOpsCommands-M7DPCX2T.js → chromeOpsCommands-62P2Q2YB.js} +31 -1
- package/{chunk-C3FZR5EC.js → chunk-2F7RJC6L.js} +1 -1
- package/{chunk-MGU5ADIQ.js → chunk-35EWBHJO.js} +10 -10
- package/{chunk-HQUORJTM.js → chunk-3BMYXEUW.js} +1 -1
- package/{chunk-3QPYFHAH.js → chunk-3DII57IT.js} +1 -1
- package/{chunk-KIS76A2P.js → chunk-3IIEFNGY.js} +38 -4
- package/{chunk-MEVSATIF.js → chunk-4OZYL5FG.js} +66 -792
- package/{chunk-GBPZKFYK.js → chunk-53HEEOTT.js} +4 -4
- package/{chunk-5XTOKQLW.js → chunk-5UTFL4QJ.js} +6 -2
- package/chunk-5ZUL4CUO.js +10 -0
- package/{chunk-E6RGHPDR.js → chunk-6D6VBVEW.js} +4 -6
- package/{chunk-CMH2SYHX.js → chunk-6OZ36FXI.js} +2 -2
- package/{chunk-QA6YKM3H.js → chunk-76WEAXJB.js} +49 -10
- package/{chunk-BYEJ7K2Z.js → chunk-7S4YWN7P.js} +1 -1
- package/{chunk-SREASRV5.js → chunk-ABQYVJBJ.js} +1 -1
- package/chunk-ACTMNVHM.js +93 -0
- package/{chunk-XWNRAIUL.js → chunk-AFUORTY4.js} +6 -16
- package/{chunk-AFIWC5NH.js → chunk-BLJWCTRL.js} +1 -1
- package/chunk-BNGW5ASC.js +344 -0
- package/{chunk-SZLVDREM.js → chunk-BP4XNZRM.js} +3 -3
- package/{chunk-2KDR4CWE.js → chunk-BYMV6QZG.js} +24 -1
- package/{chunk-HH65VA5U.js → chunk-CPH3W5A7.js} +15 -3
- package/{chunk-U6LKJRJB.js → chunk-D2P6UDPQ.js} +42 -26
- package/{chunk-L2Y24GRM.js → chunk-DEUUPHOO.js} +16 -12
- package/{chunk-MYU3MJCF.js → chunk-DHDMC6FO.js} +175 -7
- package/{chunk-CDVGNZDA.js → chunk-EFVDQUCT.js} +11 -173
- package/{chunk-EXMHJN7C.js → chunk-EYAQT56M.js} +4 -3
- package/{chunk-733J6D44.js → chunk-FLLFOP5L.js} +6 -6
- package/{chunk-H7UKKEIS.js → chunk-GFD4ALW3.js} +1 -1
- package/{chunk-PYXL2CJL.js → chunk-GPCZ7UXG.js} +1 -1
- package/{chunk-K7AG465Q.js → chunk-GQBOR3G6.js} +4 -2
- package/{chunk-QUH3XHL5.js → chunk-H3PIH2EO.js} +7 -7
- package/{chunk-YFADVSZE.js → chunk-H62HCIUP.js} +6 -6
- package/{chunk-PZM3EENV.js → chunk-HJUYAD4A.js} +1 -1
- package/{chunk-ALGK6TIE.js → chunk-HMPEO3ZE.js} +3 -3
- package/{chunk-3JQ2NRYU.js → chunk-HVURBGF3.js} +4 -4
- package/{chunk-FPTQQSS6.js → chunk-IAO6JBYW.js} +26 -5
- package/{chunk-V3ZKNK5D.js → chunk-IIVGDG4I.js} +11 -10
- package/{chunk-UDQWGU7F.js → chunk-J4MOO56S.js} +1 -1
- package/{chunk-DSRXPQWA.js → chunk-JAXOVNM4.js} +43 -43
- package/{chunk-KC5FAHVS.js → chunk-JEDZAO7L.js} +1 -1
- package/{chunk-6XIE5ZGI.js → chunk-JPGCXHNM.js} +1 -1
- package/chunk-JRQFUXY7.js +1625 -0
- package/chunk-KQ4ONNQD.js +677 -0
- package/{chunk-D74EWXL4.js → chunk-LBEDNSMY.js} +419 -72
- package/{chunk-X7Z7U4Z6.js → chunk-LIIKM7DD.js} +15 -15
- package/{chunk-RXX4GDIH.js → chunk-LS2ZANRJ.js} +1 -1
- package/{chunk-BJIRLHJR.js → chunk-M2EJHDJP.js} +4 -0
- package/{chunk-EVBFYPDC.js → chunk-MC4XLIJ7.js} +6 -2
- package/{chunk-G3NT6BM3.js → chunk-MPV6E6WR.js} +608 -60
- package/{chunk-ZY4K4CZR.js → chunk-MWAO7TZZ.js} +909 -304
- package/{chunk-QRBAZ5PW.js → chunk-NKRYKK7T.js} +3 -3
- package/{chunk-ZLPA7K55.js → chunk-OA6Q2A4I.js} +29 -10
- package/{chunk-QC5LGHYP.js → chunk-OF7AQZUG.js} +10 -5
- package/{chunk-UJ63UXGE.js → chunk-OIVSQH2O.js} +1006 -801
- package/{chunk-AETZ7AD6.js → chunk-Q554LLSI.js} +1 -1
- package/chunk-Q5FJJ6XI.js +103 -0
- package/{chunk-AJHEFRGJ.js → chunk-Q67DOFOO.js} +214 -5
- package/{chunk-UZ6XXCVR.js → chunk-QDSINZM3.js} +15 -2
- package/{chunk-AFIKMMGC.js → chunk-QIAVMDHY.js} +1 -1
- package/{chunk-QCZX4FTW.js → chunk-SH43IESU.js} +173 -15
- package/{chunk-FSFQ3A7S.js → chunk-SNPMM7H3.js} +137 -12
- package/{chunk-P7FA2HMM.js → chunk-SQZDZXP5.js} +13 -15
- package/{chunk-SPAQ4PVV.js → chunk-SV5IJK6K.js} +1 -1
- package/{chunk-BJCWNHVU.js → chunk-TOP2VXOR.js} +2 -2
- package/{chunk-EOU7ZSTU.js → chunk-TRCMIJA7.js} +1198 -50
- package/{chunk-4EJ5QYB5.js → chunk-UKZDAFYT.js} +1 -1
- package/{chunk-PGSKWZCB.js → chunk-UZGQNTVW.js} +1 -1
- package/{chunk-ZZCJUXUI.js → chunk-V4MJDUSR.js} +2 -2
- package/{chunk-JYYZCK2Z.js → chunk-V7E4PXQD.js} +1 -1
- package/{chunk-OZX2IPKM.js → chunk-VLTIYV3X.js} +1 -1
- package/{chunk-NHRQCXIQ.js → chunk-VMFTFOWF.js} +13 -3
- package/{chunk-E36HZARC.js → chunk-WADCY6G6.js} +3 -3
- package/{chunk-5J7W2VWW.js → chunk-WV42OMV7.js} +6 -265
- package/{chunk-DWPNOYMB.js → chunk-YQTQQX2H.js} +1 -1
- package/{chunk-Q6FF2MCK.js → chunk-Z77CRGTW.js} +1 -1
- package/{contentThunks-3SPROFG5.js → contentThunks-2USKJBI4.js} +25 -25
- package/{createAgentAutomationAction-EIP2EG3O.js → createAgentAutomationAction-NTLU42X2.js} +25 -25
- package/{createDialogAction-RLUSTN4D.js → createDialogAction-UCYF4BUN.js} +28 -28
- package/{createPageAction-4Y52G7WG.js → createPageAction-QFGUGZ5M.js} +26 -26
- package/{dbSlice-GKGGFNOB.js → dbSlice-XVWBAGYN.js} +8 -8
- package/{deleteFile-LWSR674W.js → deleteFile-YG6QMJLU.js} +3 -3
- package/{dialogCommands-G223U5WU.js → dialogCommands-X4OB6SC6.js} +34 -30
- package/{dialogSlice-THY45JWM.js → dialogSlice-HQFQIQDZ.js} +24 -24
- package/{docCreateCommands-2P47IJDK.js → docCreateCommands-DFST4PFR.js} +31 -29
- package/{docDeleteCommands-N3EGDOIC.js → docDeleteCommands-V37JZOSP.js} +32 -30
- package/{docReadCommands-6BFV2HI7.js → docReadCommands-Z64VDPDQ.js} +31 -29
- package/{docStore-ZQ3ECOPY.js → docStore-GVWEDN5E.js} +9 -9
- package/{docUpdateCommands-ZTMPXHC5.js → docUpdateCommands-I6FB6ENK.js} +31 -29
- package/{fetchMessages-DRABNDPZ.js → fetchMessages-EIU7UFFK.js} +3 -4
- package/{getPricing-HRMSOF3E.js → getPricing-LUSEABA6.js} +4 -4
- package/{handleSendMessageAction-CE4M5XIE.js → handleSendMessageAction-TLB2SAU4.js} +24 -24
- package/index.js +101 -84
- package/{localDialogRead-PUQKFI73.js → localDialogRead-BTFJ4V2I.js} +2 -2
- package/{localRuntimeDb-P37ZTX55.js → localRuntimeDb-SYQGUF4U.js} +1 -1
- package/{machineCommands-4OT7KVCD.js → machineCommands-PV5XA7UF.js} +61 -57
- package/{machineWsRunDispatch-TR3EYESP.js → machineWsRunDispatch-W2DPC7TZ.js} +59 -55
- package/{memberThunks-KATHH3F4.js → memberThunks-QGFLFVCI.js} +9 -9
- package/{models-GS72DVJS.js → models-T3SG6MJ5.js} +2 -2
- package/{offlineMarxistsAgentCommand-GEH6SNNA.js → offlineMarxistsAgentCommand-HGXZV4XJ.js} +1 -1
- package/package.json +1 -1
- package/providerPresetApply-FG6NZ57W.js +214 -0
- package/providerRegistry-757OWH3O.js +31 -0
- package/{read-LC6HVYBN.js → read-COE3ZYR6.js} +5 -4
- package/{readDocTool-N3ERJHHF.js → readDocTool-5USN4A6V.js} +1 -1
- package/{readlineWorkspace-RE3P324X.js → readlineWorkspace-PHZXJKJM.js} +194 -109
- package/{removeDialogAgentAction-F5GPTALR.js → removeDialogAgentAction-IX3MN2ZO.js} +11 -11
- package/{runAgentClientLoop-NE5EHXSS.js → runAgentClientLoop-26DG6ZEY.js} +45 -45
- package/{runtimeDoctorCommands-CROTMULY.js → runtimeDoctorCommands-X6WDBEQX.js} +2 -2
- package/{setDialogExtraReferencesAction-AY4ZCF3A.js → setDialogExtraReferencesAction-X4HCPNZL.js} +9 -9
- package/{setPrimaryDialogAgentAction-HPMG7V3R.js → setPrimaryDialogAgentAction-4GMIQLOD.js} +11 -11
- package/{settingSlice-OEJA4NQO.js → settingSlice-ZQZVUPKK.js} +10 -10
- package/{spaceCommands-MRP5U3C3.js → spaceCommands-3QH2QFNW.js} +29 -27
- package/{streamAgentChatTurn-A6L6O22P.js → streamAgentChatTurn-BY7IPY5C.js} +57 -56
- package/{switchDialogAgentAction-HMDZTZ4I.js → switchDialogAgentAction-N52LRPA3.js} +8 -8
- package/{tableCommands-SUNTHAYX.js → tableCommands-O6NWHFKV.js} +1 -1
- package/{toolApiClient-VGYUB4P5.js → toolApiClient-QVJ6HDNN.js} +2 -2
- package/{tools-JS475NYO.js → tools-4Y2EYH5D.js} +41 -39
- package/tuiSummaryLlmCaller-T2SHYMDZ.js +127 -0
- package/{updateCommands-Y363MC3L.js → updateCommands-2M74UL7P.js} +2 -2
- package/{updateDialogTitleAction-GMZUT6RP.js → updateDialogTitleAction-2S4DCP35.js} +45 -28
- package/chunk-3IT2PFHL.js +0 -611
- package/chunk-I42VC5KR.js +0 -15
- package/chunk-NG4UT4K4.js +0 -79
- package/codingSkills-E6KSDNSJ.js +0 -48
- package/tuiSummaryLlmCaller-3Z24VUWM.js +0 -116
- package/{chunk-3RAG2NAD.js → chunk-UKWGR5SS.js} +3 -3
- package/{db-VQSAOWAO.js → db-WK5MDZVN.js} +1 -1
- package/{localRuntimeAuthority-R5UBODT3.js → localRuntimeAuthority-6IR6BBXE.js} +3 -3
|
@@ -6,19 +6,146 @@ import {
|
|
|
6
6
|
} from "./chunk-KUG52IAP.js";
|
|
7
7
|
|
|
8
8
|
// packages/desktop-chrome-connector/chromeConnector.ts
|
|
9
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
-
import { resolve } from "node:path";
|
|
9
|
+
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
10
|
+
import { resolve as resolve2 } from "node:path";
|
|
11
|
+
|
|
12
|
+
// packages/desktop-chrome-connector/uploadSecurity.mjs
|
|
13
|
+
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
14
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
15
|
+
var DEFAULT_MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
16
|
+
var DEFAULT_MAX_FILES = 10;
|
|
17
|
+
var UploadSecurityError = class extends Error {
|
|
18
|
+
constructor(code, message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "UploadSecurityError";
|
|
21
|
+
this.code = code;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function createUploadSecurityError(code, message) {
|
|
25
|
+
return new UploadSecurityError(code, message);
|
|
26
|
+
}
|
|
27
|
+
function isSubpath(parent, child) {
|
|
28
|
+
const rel = relative(parent, child);
|
|
29
|
+
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
30
|
+
}
|
|
31
|
+
function parseAllowedRoots(env = process.env) {
|
|
32
|
+
const raw = env?.NOLO_CHROME_UPLOAD_ROOTS;
|
|
33
|
+
if (!raw || typeof raw !== "string") {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
return raw.split(",").map((entry) => entry.trim()).filter(Boolean).filter((entry) => isAbsolute(entry)).map((entry) => {
|
|
37
|
+
const resolved = resolve(entry);
|
|
38
|
+
if (existsSync(resolved)) {
|
|
39
|
+
try {
|
|
40
|
+
return realpathSync(resolved);
|
|
41
|
+
} catch {
|
|
42
|
+
return resolved;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return resolved;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function validateUploadFiles(options = {}) {
|
|
49
|
+
const {
|
|
50
|
+
files,
|
|
51
|
+
env = process.env,
|
|
52
|
+
maxFiles = DEFAULT_MAX_FILES,
|
|
53
|
+
maxFileBytes = DEFAULT_MAX_FILE_BYTES
|
|
54
|
+
} = options;
|
|
55
|
+
if (!Array.isArray(files) || files.length === 0) {
|
|
56
|
+
throw createUploadSecurityError("no_files", "Provide at least one file to upload.");
|
|
57
|
+
}
|
|
58
|
+
if (files.length > maxFiles) {
|
|
59
|
+
throw createUploadSecurityError(
|
|
60
|
+
"too_many_files",
|
|
61
|
+
`Too many files: ${files.length} provided, maximum allowed is ${maxFiles}.`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const allowedRoots = parseAllowedRoots(env);
|
|
65
|
+
if (allowedRoots.length === 0) {
|
|
66
|
+
throw createUploadSecurityError(
|
|
67
|
+
"path_not_allowed",
|
|
68
|
+
"Upload roots not configured in NOLO_CHROME_UPLOAD_ROOTS; all uploads are refused."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const fileStats = [];
|
|
72
|
+
const canonicalFiles = [];
|
|
73
|
+
let totalBytes = 0;
|
|
74
|
+
for (const rawFile of files) {
|
|
75
|
+
if (typeof rawFile !== "string" || !rawFile.trim()) {
|
|
76
|
+
throw createUploadSecurityError("path_not_allowed", "File path must be a non-empty string.");
|
|
77
|
+
}
|
|
78
|
+
const trimmed = rawFile.trim();
|
|
79
|
+
const resolvedCandidate = resolve(trimmed);
|
|
80
|
+
if (!existsSync(resolvedCandidate)) {
|
|
81
|
+
throw createUploadSecurityError("path_not_allowed", `File not found or inaccessible: ${rawFile}`);
|
|
82
|
+
}
|
|
83
|
+
let real;
|
|
84
|
+
try {
|
|
85
|
+
real = realpathSync(resolvedCandidate);
|
|
86
|
+
} catch {
|
|
87
|
+
throw createUploadSecurityError("path_not_allowed", `Could not resolve canonical path for: ${rawFile}`);
|
|
88
|
+
}
|
|
89
|
+
let st;
|
|
90
|
+
try {
|
|
91
|
+
st = statSync(real);
|
|
92
|
+
} catch {
|
|
93
|
+
throw createUploadSecurityError("path_not_allowed", `Could not stat file: ${rawFile}`);
|
|
94
|
+
}
|
|
95
|
+
if (!st.isFile()) {
|
|
96
|
+
throw createUploadSecurityError("path_not_allowed", `Target path is not a regular file: ${rawFile}`);
|
|
97
|
+
}
|
|
98
|
+
if (st.size > maxFileBytes) {
|
|
99
|
+
throw createUploadSecurityError(
|
|
100
|
+
"too_large",
|
|
101
|
+
`File size ${st.size} bytes exceeds maximum allowed limit of ${maxFileBytes} bytes: ${rawFile}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const realInside = allowedRoots.some((root) => isSubpath(root, real));
|
|
105
|
+
if (!realInside) {
|
|
106
|
+
throw createUploadSecurityError(
|
|
107
|
+
"path_not_allowed",
|
|
108
|
+
`Path '${rawFile}' (resolved: '${real}') is not within allowed upload roots.`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
canonicalFiles.push(real);
|
|
112
|
+
fileStats.push({ path: real, bytes: st.size });
|
|
113
|
+
totalBytes += st.size;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
ok: true,
|
|
117
|
+
files: canonicalFiles,
|
|
118
|
+
fileStats,
|
|
119
|
+
totalBytes
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function formatUploadAuditLog(entry = {}) {
|
|
123
|
+
const ts = entry.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
124
|
+
const safeTabId = String(entry.tabId ?? "").replace(/[\x00-\x1f\x7f-\x9f]+/g, " ");
|
|
125
|
+
const safeTarget = String(entry.target ?? "").replace(/[\x00-\x1f\x7f-\x9f]+/g, " ");
|
|
126
|
+
const files = Array.isArray(entry.files) ? entry.files : [];
|
|
127
|
+
const totalBytes = files.reduce((sum, f) => sum + (Number(f.bytes) || 0), 0);
|
|
128
|
+
const fileDetails = files.map((f) => `${String(f.path || "").replace(/[\x00-\x1f\x7f-\x9f]+/g, " ")}(${f.bytes || 0}B)`).join(", ");
|
|
129
|
+
return `[chrome-upload] ${ts} tabId=${safeTabId} target=${safeTarget} files=[${fileDetails}] totalBytes=${totalBytes}`;
|
|
130
|
+
}
|
|
131
|
+
function logUploadAudit(entry, logFn = console.warn) {
|
|
132
|
+
const line = formatUploadAuditLog(entry);
|
|
133
|
+
logFn(line);
|
|
134
|
+
return line;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// packages/desktop-chrome-connector/chromeConnector.ts
|
|
11
138
|
var NOLO_CHROME_CONNECTOR_EXTENSION_ID = "ahpdoopadkamnglhlacfjdfnonpjdplg";
|
|
12
139
|
var NOLO_CHROME_CONNECTOR_PROTOCOL_VERSION = "2";
|
|
13
140
|
function defaultTokenPath() {
|
|
14
|
-
return
|
|
141
|
+
return resolve2(
|
|
15
142
|
process.env.HOME || "",
|
|
16
143
|
"Library/Application Support/Nolo/ChromeConnector/token"
|
|
17
144
|
);
|
|
18
145
|
}
|
|
19
146
|
function readConnectorToken(tokenPath = defaultTokenPath()) {
|
|
20
147
|
if (process.env.NOLO_CHROME_CONNECTOR_TOKEN) return process.env.NOLO_CHROME_CONNECTOR_TOKEN;
|
|
21
|
-
if (!
|
|
148
|
+
if (!existsSync2(tokenPath)) return "";
|
|
22
149
|
return readFileSync(tokenPath, "utf8").trim();
|
|
23
150
|
}
|
|
24
151
|
var CHROME_TOOL_ACTIONS = {
|
|
@@ -32,7 +159,10 @@ var CHROME_TOOL_ACTIONS = {
|
|
|
32
159
|
chrome_scroll: "scroll",
|
|
33
160
|
chrome_screenshot: "screenshot",
|
|
34
161
|
chrome_read_console: "read_console",
|
|
35
|
-
chrome_read_network: "read_network"
|
|
162
|
+
chrome_read_network: "read_network",
|
|
163
|
+
chrome_set_files: "set_files",
|
|
164
|
+
chrome_upload_file: "set_files",
|
|
165
|
+
chrome_upload: "set_files"
|
|
36
166
|
};
|
|
37
167
|
function createConnectorError(code, message, details) {
|
|
38
168
|
const error = new Error(message);
|
|
@@ -59,8 +189,8 @@ function errorPayload(error) {
|
|
|
59
189
|
...error?.details !== void 0 ? { details: error.details } : {}
|
|
60
190
|
};
|
|
61
191
|
}
|
|
62
|
-
var TARGET_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["click", "type"]);
|
|
63
|
-
var TAB_ID_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["close_tab", "detach"]);
|
|
192
|
+
var TARGET_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["click", "type", "set_files"]);
|
|
193
|
+
var TAB_ID_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["close_tab", "detach", "set_files"]);
|
|
64
194
|
function validateChromeConnectorPayload(action, payload) {
|
|
65
195
|
if (TAB_ID_REQUIRED_ACTIONS.has(action)) {
|
|
66
196
|
const raw = payload.tabId;
|
|
@@ -71,16 +201,42 @@ function validateChromeConnectorPayload(action, payload) {
|
|
|
71
201
|
`Provide the tabId from chrome_list_tabs before calling ${action}.`
|
|
72
202
|
);
|
|
73
203
|
}
|
|
74
|
-
return;
|
|
204
|
+
if (!TARGET_REQUIRED_ACTIONS.has(action)) return;
|
|
75
205
|
}
|
|
76
206
|
if (!TARGET_REQUIRED_ACTIONS.has(action)) return;
|
|
77
|
-
const
|
|
207
|
+
const rawRef = typeof payload.elementRef === "string" ? payload.elementRef : typeof payload.ref === "string" ? payload.ref : "";
|
|
208
|
+
const elementRef = rawRef.trim();
|
|
78
209
|
const selector = typeof payload.selector === "string" ? payload.selector.trim() : "";
|
|
79
|
-
if (elementRef
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
210
|
+
if (!elementRef && !selector) {
|
|
211
|
+
throw createConnectorError(
|
|
212
|
+
"ELEMENT_TARGET_REQUIRED",
|
|
213
|
+
"Provide elementRef from chrome_read_page or a CSS selector."
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (action === "set_files") {
|
|
217
|
+
if (!Array.isArray(payload.files) || payload.files.length === 0) {
|
|
218
|
+
throw createConnectorError(
|
|
219
|
+
"no_files",
|
|
220
|
+
"Provide at least one file path in files array."
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
const validated = validateUploadFiles({
|
|
225
|
+
files: payload.files,
|
|
226
|
+
env: process.env
|
|
227
|
+
});
|
|
228
|
+
payload.files = validated.files;
|
|
229
|
+
const targetStr = elementRef ? `ref:${elementRef}` : `selector:${selector}`;
|
|
230
|
+
logUploadAudit({
|
|
231
|
+
tabId: String(payload.tabId),
|
|
232
|
+
target: targetStr,
|
|
233
|
+
files: validated.fileStats
|
|
234
|
+
});
|
|
235
|
+
} catch (err) {
|
|
236
|
+
const code = err?.code ?? "path_not_allowed";
|
|
237
|
+
throw createConnectorError(code, toErrorMessage(err));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
84
240
|
}
|
|
85
241
|
function createChromeConnectorClient(args) {
|
|
86
242
|
if (args?.request) return { request: args.request };
|
|
@@ -90,6 +246,7 @@ function createChromeConnectorClient(args) {
|
|
|
90
246
|
const token = args?.token ?? readConnectorToken(args?.tokenPath);
|
|
91
247
|
return {
|
|
92
248
|
async request(action, payload) {
|
|
249
|
+
validateChromeConnectorPayload(action, payload);
|
|
93
250
|
let response;
|
|
94
251
|
try {
|
|
95
252
|
response = await fetchImpl(endpoint, {
|
|
@@ -131,7 +288,8 @@ var REQUIRED_CHROME_CONNECTOR_FEATURES = {
|
|
|
131
288
|
screenshot: ["browser_debug"],
|
|
132
289
|
read_console: ["browser_debug"],
|
|
133
290
|
read_network: ["browser_debug"],
|
|
134
|
-
detach: ["browser_debug"]
|
|
291
|
+
detach: ["browser_debug"],
|
|
292
|
+
set_files: ["compact_observation_v2", "file_upload"]
|
|
135
293
|
};
|
|
136
294
|
function requiredFeaturesForConnectorAction(action) {
|
|
137
295
|
return [...REQUIRED_CHROME_CONNECTOR_FEATURES[action] ?? []];
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
listUserRecordsFromServers,
|
|
8
8
|
readDbRecordFromServers,
|
|
9
9
|
readLiveDbRecordAfterTombstoneMerge
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BLJWCTRL.js";
|
|
11
11
|
import {
|
|
12
12
|
fetchWithTransientRetry
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-5UTFL4QJ.js";
|
|
14
14
|
import {
|
|
15
15
|
DRAIN_EXHAUSTED_USER_MESSAGE,
|
|
16
16
|
isDrainExhaustedResponse
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import {
|
|
19
19
|
buildDialogAttachmentPlan,
|
|
20
20
|
extractFileContentIds
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-3BMYXEUW.js";
|
|
22
22
|
import {
|
|
23
23
|
isLevelLockError
|
|
24
24
|
} from "./chunk-URMS4XY2.js";
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
boundSummaryText,
|
|
31
31
|
buildDialogReadEnvelope,
|
|
32
32
|
projectDialogReadForAgent
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-IIVGDG4I.js";
|
|
34
34
|
import {
|
|
35
35
|
toErrorMessage
|
|
36
36
|
} from "./chunk-HNMXYYJR.js";
|
|
@@ -51,19 +51,19 @@ import {
|
|
|
51
51
|
import {
|
|
52
52
|
asNonEmptyStringArray,
|
|
53
53
|
asTrimmedNonEmptyStringArray
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-VMFTFOWF.js";
|
|
55
55
|
import {
|
|
56
56
|
createClientLogger
|
|
57
57
|
} from "./chunk-QOKAKDPE.js";
|
|
58
58
|
import {
|
|
59
59
|
isLevelNotFoundError
|
|
60
60
|
} from "./chunk-OW765XBU.js";
|
|
61
|
-
import {
|
|
62
|
-
asTrimmedString
|
|
63
|
-
} from "./chunk-3EUW3WEO.js";
|
|
64
61
|
import {
|
|
65
62
|
isRecord
|
|
66
63
|
} from "./chunk-KUG52IAP.js";
|
|
64
|
+
import {
|
|
65
|
+
asTrimmedString
|
|
66
|
+
} from "./chunk-3EUW3WEO.js";
|
|
67
67
|
import {
|
|
68
68
|
DEFAULT_LOCAL_API_ORIGIN
|
|
69
69
|
} from "./chunk-4SN6J65J.js";
|
|
@@ -210,7 +210,8 @@ var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
210
210
|
"--token",
|
|
211
211
|
"--machine-key",
|
|
212
212
|
"--user",
|
|
213
|
-
"--max-response-chars"
|
|
213
|
+
"--max-response-chars",
|
|
214
|
+
"--per-dialog"
|
|
214
215
|
]);
|
|
215
216
|
function hasFlag(args, flag) {
|
|
216
217
|
return args.includes(flag);
|
|
@@ -724,7 +725,7 @@ function isExplicitDialogIdMismatch(meta, dialogId) {
|
|
|
724
725
|
return meta && typeof meta === "object" && "id" in meta && meta.id != null && String(meta.id) !== dialogId;
|
|
725
726
|
}
|
|
726
727
|
async function readDialogFromLocalDb(dialogKey, dialogId, limit, readLocalDialog) {
|
|
727
|
-
const reader = readLocalDialog ?? (await import("./localDialogRead-
|
|
728
|
+
const reader = readLocalDialog ?? (await import("./localDialogRead-BTFJ4V2I.js")).readDialogFromLocalDb;
|
|
728
729
|
const result = await reader({ dialogKey, dialogId, limit });
|
|
729
730
|
return {
|
|
730
731
|
...result,
|
|
@@ -741,7 +742,7 @@ async function readLocalDialogAtDbPathDefault(args) {
|
|
|
741
742
|
const [{ Level }, { safeJsonEncoding }, { fetchMessages }] = await Promise.all([
|
|
742
743
|
import("./levelLazyShim-GZBKODGI.js"),
|
|
743
744
|
import("./serverStoreFactory-YMXDF4NI.js"),
|
|
744
|
-
import("./fetchMessages-
|
|
745
|
+
import("./fetchMessages-EIU7UFFK.js")
|
|
745
746
|
]);
|
|
746
747
|
const db = new Level(args.dbPath, {
|
|
747
748
|
valueEncoding: safeJsonEncoding,
|
|
@@ -1820,6 +1821,129 @@ async function runDialogDeleteCommand(args, deps = {}) {
|
|
|
1820
1821
|
}
|
|
1821
1822
|
return hasErrors ? 1 : 0;
|
|
1822
1823
|
}
|
|
1824
|
+
function printSearchUsage(output) {
|
|
1825
|
+
output.write(`Usage:
|
|
1826
|
+
nolo dialog search <query> [--limit <n>] [--per-dialog <n>] [--json]
|
|
1827
|
+
|
|
1828
|
+
Options:
|
|
1829
|
+
--limit <n> Max dialogs to return (default 20, max 50).
|
|
1830
|
+
--per-dialog <n> Max match snippets per dialog (default 3, max 10).
|
|
1831
|
+
--json Print machine-readable JSON.
|
|
1832
|
+
--server <url> Override NOLO_SERVER/BASE_URL.
|
|
1833
|
+
--token <jwt> Override AUTH_TOKEN.
|
|
1834
|
+
|
|
1835
|
+
Searches messages across the current user's dialogs via the server endpoint.
|
|
1836
|
+
Server requires NOLO_DIALOG_SEARCH=1 to be enabled.
|
|
1837
|
+
`);
|
|
1838
|
+
}
|
|
1839
|
+
async function runDialogSearchCommand(args, deps = {}) {
|
|
1840
|
+
const env = deps.env ?? process.env;
|
|
1841
|
+
const output = deps.output ?? process.stdout;
|
|
1842
|
+
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
1843
|
+
printSearchUsage(output);
|
|
1844
|
+
return 0;
|
|
1845
|
+
}
|
|
1846
|
+
const query = readFirstPositional(args);
|
|
1847
|
+
if (!query) {
|
|
1848
|
+
output.write("[nolo] dialog search requires a search query.\n\n");
|
|
1849
|
+
printSearchUsage(output);
|
|
1850
|
+
return 1;
|
|
1851
|
+
}
|
|
1852
|
+
const authToken = resolveAuthToken(args, env);
|
|
1853
|
+
if (!authToken) {
|
|
1854
|
+
output.write("[nolo] dialog search requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
|
|
1855
|
+
return 1;
|
|
1856
|
+
}
|
|
1857
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
1858
|
+
const serverUrl = resolveServerUrl(args, env);
|
|
1859
|
+
const serverUrls = resolveServerCandidates(args, env, serverUrl);
|
|
1860
|
+
const limitRaw = readOption(args, "--limit");
|
|
1861
|
+
const perDialogRaw = readOption(args, "--per-dialog");
|
|
1862
|
+
const queryParams = new URLSearchParams({ q: query });
|
|
1863
|
+
if (limitRaw) queryParams.set("limit", limitRaw);
|
|
1864
|
+
if (perDialogRaw) queryParams.set("perDialog", perDialogRaw);
|
|
1865
|
+
const isJson = hasFlag(args, "--json");
|
|
1866
|
+
let lastError = null;
|
|
1867
|
+
let lastStatus = null;
|
|
1868
|
+
let searchResult = null;
|
|
1869
|
+
for (const candidateBase of serverUrls) {
|
|
1870
|
+
const trimmedBase = candidateBase.replace(/\/+$/, "");
|
|
1871
|
+
const targetUrl = `${trimmedBase}/api/dialog-search?${queryParams.toString()}`;
|
|
1872
|
+
try {
|
|
1873
|
+
const res = await fetchImpl(targetUrl, {
|
|
1874
|
+
method: "GET",
|
|
1875
|
+
headers: {
|
|
1876
|
+
Authorization: `Bearer ${authToken}`
|
|
1877
|
+
}
|
|
1878
|
+
});
|
|
1879
|
+
lastStatus = res.status;
|
|
1880
|
+
if (!res.ok) {
|
|
1881
|
+
const errorData = await res.json().catch(() => ({}));
|
|
1882
|
+
if (res.status === 403) {
|
|
1883
|
+
const hint = errorData?.hint ? ` (${errorData.hint})` : "";
|
|
1884
|
+
const msg = errorData?.message ? `: ${errorData.message}` : "";
|
|
1885
|
+
throw new Error(`Server returned 403 Forbidden${hint}${msg}. Please ensure NOLO_DIALOG_SEARCH=1 is enabled on the server.`);
|
|
1886
|
+
}
|
|
1887
|
+
if (res.status === 401) {
|
|
1888
|
+
throw new Error(`Server returned 401 Unauthorized. Please check your AUTH_TOKEN.`);
|
|
1889
|
+
}
|
|
1890
|
+
throw new Error(`HTTP ${res.status}: ${JSON.stringify(errorData)}`);
|
|
1891
|
+
}
|
|
1892
|
+
searchResult = await res.json();
|
|
1893
|
+
break;
|
|
1894
|
+
} catch (err) {
|
|
1895
|
+
lastError = err;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
if (!searchResult) {
|
|
1899
|
+
const errorMsg = lastError ? toErrorMessage(lastError) : "Failed to connect to candidate servers";
|
|
1900
|
+
if (isJson) {
|
|
1901
|
+
output.write(JSON.stringify({ error: errorMsg, status: lastStatus }, null, 2) + "\n");
|
|
1902
|
+
} else {
|
|
1903
|
+
output.write(`[nolo] dialog search failed: ${errorMsg}
|
|
1904
|
+
`);
|
|
1905
|
+
}
|
|
1906
|
+
return 1;
|
|
1907
|
+
}
|
|
1908
|
+
if (isJson) {
|
|
1909
|
+
output.write(JSON.stringify(searchResult, null, 2) + "\n");
|
|
1910
|
+
return 0;
|
|
1911
|
+
}
|
|
1912
|
+
const { dialogs, totalMatches, scannedDialogs, scannedMessages, elapsedMs, truncated } = searchResult;
|
|
1913
|
+
output.write(`query: ${query}
|
|
1914
|
+
`);
|
|
1915
|
+
output.write(`scanned: ${scannedDialogs} dialogs, ${scannedMessages} messages (${elapsedMs}ms)
|
|
1916
|
+
`);
|
|
1917
|
+
output.write(`matches: ${totalMatches} total match(es) across ${dialogs?.length ?? 0} dialog(s)`);
|
|
1918
|
+
if (truncated) {
|
|
1919
|
+
output.write(" [truncated]");
|
|
1920
|
+
}
|
|
1921
|
+
output.write("\n");
|
|
1922
|
+
if (!Array.isArray(dialogs) || dialogs.length === 0) {
|
|
1923
|
+
output.write("\nNo matching dialog messages found.\n");
|
|
1924
|
+
return 0;
|
|
1925
|
+
}
|
|
1926
|
+
for (const d of dialogs) {
|
|
1927
|
+
output.write(`
|
|
1928
|
+
${d.title}
|
|
1929
|
+
`);
|
|
1930
|
+
output.write(`id=${d.dialogId}
|
|
1931
|
+
`);
|
|
1932
|
+
output.write(`updatedAt=${d.updatedAt ?? "-"}
|
|
1933
|
+
`);
|
|
1934
|
+
output.write(`matches=${d.matchCount}
|
|
1935
|
+
`);
|
|
1936
|
+
if (Array.isArray(d.matches) && d.matches.length > 0) {
|
|
1937
|
+
for (const m of d.matches) {
|
|
1938
|
+
const role = m.role ? `[${m.role}]` : "";
|
|
1939
|
+
const snippet = String(m.snippet ?? "").replace(/\r?\n/g, " ");
|
|
1940
|
+
output.write(` - ${role} ${snippet}
|
|
1941
|
+
`);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
return 0;
|
|
1946
|
+
}
|
|
1823
1947
|
|
|
1824
1948
|
export {
|
|
1825
1949
|
normalizeDialogRecord,
|
|
@@ -1832,5 +1956,6 @@ export {
|
|
|
1832
1956
|
runDialogStatusCommand,
|
|
1833
1957
|
runDialogQueryCommand,
|
|
1834
1958
|
runDialogListCommand,
|
|
1835
|
-
runDialogDeleteCommand
|
|
1959
|
+
runDialogDeleteCommand,
|
|
1960
|
+
runDialogSearchCommand
|
|
1836
1961
|
};
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
initReactI18next,
|
|
10
10
|
instance,
|
|
11
11
|
toast
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-LBEDNSMY.js";
|
|
13
13
|
import {
|
|
14
14
|
require_date_fns
|
|
15
15
|
} from "./chunk-M76ECQRD.js";
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from "./chunk-YDH3FDFQ.js";
|
|
19
19
|
import {
|
|
20
20
|
isSystemAdmin
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-QDSINZM3.js";
|
|
22
22
|
import {
|
|
23
23
|
asRecordOrEmpty
|
|
24
24
|
} from "./chunk-KX6YBIHG.js";
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
addContentAction,
|
|
28
28
|
checkSpaceMembership,
|
|
29
29
|
localSpaceAuthorityPatchStamp
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-V4MJDUSR.js";
|
|
31
31
|
import {
|
|
32
32
|
createSpaceKey,
|
|
33
33
|
normalizeSpaceId
|
|
@@ -41,9 +41,10 @@ import {
|
|
|
41
41
|
uploadFileAction,
|
|
42
42
|
upsertSSREntity,
|
|
43
43
|
write
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-H62HCIUP.js";
|
|
45
45
|
import {
|
|
46
46
|
SEPARATOR,
|
|
47
|
+
asTrimmedNonEmptyStringArray,
|
|
47
48
|
createKey,
|
|
48
49
|
fileKey,
|
|
49
50
|
isAgentKey,
|
|
@@ -52,16 +53,13 @@ import {
|
|
|
52
53
|
rowKey,
|
|
53
54
|
splitKey,
|
|
54
55
|
ulid
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-VMFTFOWF.js";
|
|
56
57
|
import {
|
|
57
58
|
asOptionalFiniteNumber
|
|
58
59
|
} from "./chunk-WWC7I6TA.js";
|
|
59
|
-
import {
|
|
60
|
-
asTrimmedNonEmptyStringArray
|
|
61
|
-
} from "./chunk-I42VC5KR.js";
|
|
62
60
|
import {
|
|
63
61
|
extractUserId
|
|
64
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-M2EJHDJP.js";
|
|
65
63
|
import {
|
|
66
64
|
DEVICE_LOCAL_OWNER_ID,
|
|
67
65
|
createAsyncThunk,
|
|
@@ -70,7 +68,7 @@ import {
|
|
|
70
68
|
resolveReplicationServers,
|
|
71
69
|
scheduleDeleteReplication,
|
|
72
70
|
scheduleWriteReplication
|
|
73
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-UKWGR5SS.js";
|
|
74
72
|
import {
|
|
75
73
|
createClientLogger,
|
|
76
74
|
isAbortError
|
|
@@ -81,15 +79,15 @@ import {
|
|
|
81
79
|
import {
|
|
82
80
|
buildTombstoneRecord
|
|
83
81
|
} from "./chunk-GBRG75BQ.js";
|
|
82
|
+
import {
|
|
83
|
+
isRecord
|
|
84
|
+
} from "./chunk-KUG52IAP.js";
|
|
84
85
|
import {
|
|
85
86
|
asTrimmedString
|
|
86
87
|
} from "./chunk-3EUW3WEO.js";
|
|
87
88
|
import {
|
|
88
89
|
asOptionalPositiveFiniteNumber
|
|
89
90
|
} from "./chunk-U6VC4MU4.js";
|
|
90
|
-
import {
|
|
91
|
-
isRecord
|
|
92
|
-
} from "./chunk-KUG52IAP.js";
|
|
93
91
|
import {
|
|
94
92
|
asOptionalTrimmedString
|
|
95
93
|
} from "./chunk-G3SUCT4W.js";
|
|
@@ -1455,11 +1453,11 @@ var ENTITY_DELETE_STRATEGIES = {
|
|
|
1455
1453
|
await dispatch(deleteTable({ dbKey: key })).unwrap();
|
|
1456
1454
|
},
|
|
1457
1455
|
file: async (key, { thunkAPI }) => {
|
|
1458
|
-
const { deleteFileAction } = await import("./deleteFile-
|
|
1456
|
+
const { deleteFileAction } = await import("./deleteFile-YG6QMJLU.js");
|
|
1459
1457
|
await deleteFileAction(key, thunkAPI);
|
|
1460
1458
|
},
|
|
1461
1459
|
image: async (key, { thunkAPI }) => {
|
|
1462
|
-
const { deleteFileAction } = await import("./deleteFile-
|
|
1460
|
+
const { deleteFileAction } = await import("./deleteFile-YG6QMJLU.js");
|
|
1463
1461
|
await deleteFileAction(key, thunkAPI);
|
|
1464
1462
|
},
|
|
1465
1463
|
agent: async (key, { dispatch, userId, sourceServerOrigin }) => {
|