nolo-cli 0.6.1 → 0.8.0-alpha.10
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-CPDNUUQV.js +198 -0
- package/action-PAXRPJJF.js +27 -0
- package/addContentAction-CZVWF3QZ.js +25 -0
- package/addDialogAgentAction-CCIDTPHC.js +67 -0
- package/agentDeleteCommand-OSUMJMZM.js +323 -0
- package/agentEmailCommands-OQTJIPQU.js +621 -0
- package/agentListCommands-FATQEUYT.js +219 -0
- package/agentMachineCommands-6LZWF4GL.js +421 -0
- package/agentPullCommand-O2MTUAFR.js +122 -0
- package/agentRecordCommands-TIHFU65Z.js +89 -0
- package/agentRunCommand-R64Y3HCH.js +102 -0
- package/agentRunControl-K4VKNEHF.js +57 -0
- package/agentRuntimeLocal-6PIWAHLQ.js +99 -0
- package/agentSlice-TP4VARJF.js +41 -0
- package/authCommand-WXMD3IPR.js +574 -0
- package/authCommands-X74AFDTC.js +26 -0
- package/chunk-2EISRLRC.js +238 -0
- package/chunk-2FTTDCD4.js +675 -0
- package/chunk-2MALU52L.js +51 -0
- package/chunk-2TPUKEU7.js +1078 -0
- package/chunk-3ASDTTEI.js +1774 -0
- package/chunk-3EUW3WEO.js +8 -0
- package/chunk-3LY4F7SV.js +9293 -0
- package/chunk-4CQLVGRV.js +50 -0
- package/chunk-4IJYA27C.js +342 -0
- package/chunk-4SN6J65J.js +38 -0
- package/chunk-4VNS5WPM.js +42 -0
- package/chunk-572EKYLF.js +792 -0
- package/chunk-5MIDPSSK.js +206 -0
- package/chunk-5MMAK75Q.js +15 -0
- package/chunk-5VV37AT4.js +222 -0
- package/chunk-63W5N6P3.js +150 -0
- package/chunk-6A5EF6IR.js +929 -0
- package/chunk-6HYVJV7B.js +102 -0
- package/chunk-6P2WX5IA.js +3631 -0
- package/chunk-6WD3OOJS.js +20 -0
- package/chunk-ATNTHIZI.js +13 -0
- package/chunk-AUGHVUFE.js +69 -0
- package/chunk-AVMKZHBC.js +85 -0
- package/chunk-AZPCASRE.js +36 -0
- package/chunk-BNMT7YY5.js +34 -0
- package/chunk-BR2WP3DF.js +548 -0
- package/chunk-BSTNFPHD.js +231 -0
- package/chunk-BU4OPIXC.js +171 -0
- package/chunk-CF2WZF4N.js +134 -0
- package/chunk-CF7PE763.js +10 -0
- package/chunk-CKOJQDKR.js +198 -0
- package/chunk-CM54RSSA.js +206 -0
- package/chunk-CWMSB67P.js +34 -0
- package/chunk-DA2OEKS6.js +27 -0
- package/chunk-DFFIZ25G.js +30 -0
- package/chunk-DWLEOOGR.js +8 -0
- package/chunk-DZ3XJVET.js +231 -0
- package/chunk-EHLHSX7R.js +1433 -0
- package/chunk-ELRRLDWI.js +478 -0
- package/chunk-EYEEHCU4.js +3066 -0
- package/chunk-FQZWM5YX.js +628 -0
- package/chunk-G3SUCT4W.js +8 -0
- package/chunk-G5H7RNFL.js +807 -0
- package/chunk-GAKEBQD6.js +30 -0
- package/chunk-GBRG75BQ.js +86 -0
- package/chunk-H2RMRZJE.js +113 -0
- package/chunk-H33743XH.js +25 -0
- package/chunk-HD63YREL.js +19 -0
- package/chunk-HEIIIZBX.js +104 -0
- package/chunk-HNMXYYJR.js +12 -0
- package/chunk-HOMYP7GZ.js +2152 -0
- package/chunk-HZFOMJRA.js +4300 -0
- package/chunk-IAXBCTTE.js +175 -0
- package/chunk-IDZTNRP2.js +85 -0
- package/chunk-IHHA5Y2S.js +9013 -0
- package/chunk-ISNCLGUZ.js +146 -0
- package/chunk-IYQV26RA.js +138 -0
- package/chunk-J4576WMJ.js +91 -0
- package/chunk-JBTJAPUF.js +35 -0
- package/chunk-JZPBVBIY.js +94 -0
- package/chunk-KQHGZWSV.js +63 -0
- package/chunk-KUG52IAP.js +8 -0
- package/chunk-KX6YBIHG.js +8 -0
- package/chunk-LCBAMY2M.js +60 -0
- package/chunk-LM25IZBJ.js +902 -0
- package/chunk-LM6IYQ3F.js +16 -0
- package/chunk-M76ECQRD.js +13658 -0
- package/chunk-MRC4Q34M.js +188 -0
- package/chunk-NEMRK4EK.js +944 -0
- package/chunk-NXZGF7F7.js +2878 -0
- package/chunk-OF5H3QWS.js +300 -0
- package/chunk-OLZBQWZU.js +6 -0
- package/chunk-OOYVBFM7.js +191 -0
- package/chunk-OWOHNGCN.js +50 -0
- package/chunk-PN7AFLOK.js +3401 -0
- package/chunk-POCFIDGQ.js +562 -0
- package/chunk-Q6WACBKB.js +1949 -0
- package/chunk-QFV2OAIM.js +421 -0
- package/chunk-QJ6V2NIN.js +1447 -0
- package/chunk-QSJ3HFEF.js +8 -0
- package/chunk-QUWDTOUP.js +190 -0
- package/chunk-QYXLLLGL.js +4519 -0
- package/chunk-ROWQEJRP.js +139 -0
- package/chunk-S7Z2HMCN.js +25 -0
- package/chunk-TDIQFT2F.js +301 -0
- package/chunk-TILFE6LV.js +381 -0
- package/chunk-TKOUBWBO.js +24674 -0
- package/chunk-TYH5JE6N.js +27158 -0
- package/chunk-U4TRT5V4.js +246 -0
- package/chunk-U6VC4MU4.js +8 -0
- package/chunk-UAD2WT54.js +64 -0
- package/chunk-USZMK5UT.js +105 -0
- package/chunk-VEJLAVTC.js +2052 -0
- package/chunk-VF4K2QE6.js +21 -0
- package/chunk-VHBWHNVT.js +59 -0
- package/chunk-VIDPVFP3.js +20 -0
- package/chunk-VP4WJWKW.js +8882 -0
- package/chunk-VQ2AJRGD.js +148 -0
- package/chunk-W4NVOSFF.js +37 -0
- package/chunk-WWC7I6TA.js +8 -0
- package/chunk-X7W4TNB4.js +1550 -0
- package/chunk-XDVAYP26.js +537 -0
- package/chunk-XKIMRZO2.js +221 -0
- package/chunk-Y5GCAMGP.js +9 -0
- package/chunk-YWPXYBY7.js +360 -0
- package/chunk-Z4NR32XR.js +50 -0
- package/chunk-ZNFJWEN4.js +56 -0
- package/cliExecutor-DNE7TCC4.js +36 -0
- package/clipboardy-BVE3LVEH.js +12001 -0
- package/createAgentAutomationAction-KLKS2HGU.js +864 -0
- package/createDialogAction-Z33JMBF5.js +52 -0
- package/createPageAction-AQVNOAAI.js +169 -0
- package/db-HCJ5PRB5.js +271 -0
- package/dbSlice-C4UJLRZP.js +59 -0
- package/deleteFile-4SKGPHOZ.js +41 -0
- package/dialogCommands-W5PD6MZU.js +59 -0
- package/dialogSlice-RBJYVSAR.js +146 -0
- package/docCreateCommands-MM34S4Z3.js +215 -0
- package/docDeleteCommands-JJTU722V.js +176 -0
- package/docReadCommands-GLYDMCTU.js +129 -0
- package/docStore-5TYME4DO.js +96 -0
- package/docUpdateCommands-ZCGQ7URR.js +313 -0
- package/fetchMessages-JOCYIFKL.js +16 -0
- package/getPricing-PWPJ6MNV.js +30 -0
- package/handleSendMessageAction-KA2MRW6E.js +183 -0
- package/index.js +184 -112254
- package/lib-FYYBQIXS.js +19839 -0
- package/localDialogRead-D3BELSTF.js +26 -0
- package/localFirstLog-DHNOY2NA.js +19 -0
- package/localRuntimeAuthority-TEGCOWX4.js +471 -0
- package/localRuntimeDb-LGDF6FQP.js +12 -0
- package/machineCommands-ZB5WUSPF.js +774 -0
- package/machineInfo-M6KB6HZN.js +10 -0
- package/machineWsRunDispatch-GWCAPPCM.js +105 -0
- package/memoryCommands-O4MIPIWQ.js +476 -0
- package/models-XLEOET3E.js +9 -0
- package/offlineMarxistsAgentCommand-BCPJITJL.js +242 -0
- package/package.json +3 -25
- package/read-RIJCIVKX.js +17 -0
- package/readDocTool-GZD2N3LO.js +16 -0
- package/readlineWorkspace-FEDY44AA.js +5357 -0
- package/removeDialogAgentAction-CXLST3N6.js +72 -0
- package/runAgentClientLoop-W4NKE64V.js +288 -0
- package/runtimeDoctorCommands-LRHLPDRC.js +289 -0
- package/setDialogExtraReferencesAction-LP6VYGU7.js +59 -0
- package/setPrimaryDialogAgentAction-D3GGH23T.js +79 -0
- package/settingSlice-J4I3Z5H7.js +198 -0
- package/skillSummaryMarker-42HKSXYY.js +9 -0
- package/slateToRenderMarkdown-Y5IYN73U.js +7 -0
- package/slateUtils-2M7MUTWX.js +19 -0
- package/spaceCommands-LC4FDAKE.js +450 -0
- package/spaceSlice-32XOGBEF.js +145 -0
- package/streamAgentChatTurn-YQW32AQH.js +4503 -0
- package/tableCommands-GOFP7QKA.js +1286 -0
- package/toolApiClient-QI3YBNWB.js +26 -0
- package/tools-XGTFRYD7.js +83 -0
- package/understanding-HCSFPE7R.js +318 -0
- package/updateCommands-VOSPKXFF.js +31 -0
- package/updateDialogTitleAction-4LHQDNHQ.js +185 -0
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildLocalAgentLookupKeys,
|
|
3
|
+
normalizeAgentHandle,
|
|
4
|
+
shouldReadAgentKeyRemotely
|
|
5
|
+
} from "./chunk-HD63YREL.js";
|
|
6
|
+
import {
|
|
7
|
+
resolveCliAgentKeyInput
|
|
8
|
+
} from "./chunk-VHBWHNVT.js";
|
|
9
|
+
import {
|
|
10
|
+
readPipeText,
|
|
11
|
+
spawnProcess
|
|
12
|
+
} from "./chunk-IDZTNRP2.js";
|
|
13
|
+
import {
|
|
14
|
+
parseUserIdFromAuthToken,
|
|
15
|
+
readOption,
|
|
16
|
+
resolveAuthToken,
|
|
17
|
+
resolveServerCandidates,
|
|
18
|
+
resolveServerUrl
|
|
19
|
+
} from "./chunk-ISNCLGUZ.js";
|
|
20
|
+
import {
|
|
21
|
+
toErrorMessage
|
|
22
|
+
} from "./chunk-HNMXYYJR.js";
|
|
23
|
+
import {
|
|
24
|
+
createAgentKey
|
|
25
|
+
} from "./chunk-PN7AFLOK.js";
|
|
26
|
+
|
|
27
|
+
// packages/cli/agentRecordHelpers.ts
|
|
28
|
+
import { readFileSync } from "node:fs";
|
|
29
|
+
var PROVIDER_COPY_FIELDS = [
|
|
30
|
+
"apiSource",
|
|
31
|
+
"provider",
|
|
32
|
+
"cliProvider",
|
|
33
|
+
"model",
|
|
34
|
+
"customProviderUrl",
|
|
35
|
+
"apiKey",
|
|
36
|
+
"useServerProxy",
|
|
37
|
+
"inputPrice",
|
|
38
|
+
"outputPrice"
|
|
39
|
+
];
|
|
40
|
+
function readRepeatedOption(args, flag) {
|
|
41
|
+
const values = [];
|
|
42
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
43
|
+
if (args[index] !== flag || !args[index + 1]) continue;
|
|
44
|
+
values.push(args[index + 1]);
|
|
45
|
+
index += 1;
|
|
46
|
+
}
|
|
47
|
+
return values;
|
|
48
|
+
}
|
|
49
|
+
function parseJsonishValue(raw) {
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(raw);
|
|
52
|
+
} catch {
|
|
53
|
+
return raw;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function recordHasAgentHandle(record, handle) {
|
|
57
|
+
if (!record || typeof record !== "object") return false;
|
|
58
|
+
const normalized = normalizeAgentHandle(handle);
|
|
59
|
+
if (!normalized) return false;
|
|
60
|
+
return normalizeAgentHandle(record.handle) === normalized;
|
|
61
|
+
}
|
|
62
|
+
async function findLocalAgentRecordByHandle(args) {
|
|
63
|
+
const normalized = normalizeAgentHandle(args.handle);
|
|
64
|
+
if (!normalized) return null;
|
|
65
|
+
try {
|
|
66
|
+
const iterator = args.db.iterator({ gte: "agent-", lte: "agent-\uFFFF" });
|
|
67
|
+
for await (const [key, record] of iterator) {
|
|
68
|
+
if (!recordHasAgentHandle(record, normalized)) continue;
|
|
69
|
+
return { key, record };
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
async function findRemoteAgentRecordByHandle(args) {
|
|
76
|
+
const normalized = normalizeAgentHandle(args.handle);
|
|
77
|
+
if (!normalized) return null;
|
|
78
|
+
const records = await queryUserRecords({
|
|
79
|
+
authToken: args.authToken,
|
|
80
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
81
|
+
fetchImpl: args.fetchImpl,
|
|
82
|
+
limit: 200,
|
|
83
|
+
serverUrl: args.serverUrl,
|
|
84
|
+
userId: args.userId,
|
|
85
|
+
type: "agent" /* AGENT */
|
|
86
|
+
});
|
|
87
|
+
return records.find((record) => recordHasAgentHandle(record, normalized)) ?? null;
|
|
88
|
+
}
|
|
89
|
+
function parsePositiveIntegerOption(raw, flag) {
|
|
90
|
+
if (!raw) return void 0;
|
|
91
|
+
const value = Number(raw);
|
|
92
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
93
|
+
throw new Error(`${flag} must be a positive integer.`);
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
function parseIsoTimestampOption(raw, flag) {
|
|
98
|
+
if (!raw) return void 0;
|
|
99
|
+
const time = Date.parse(raw);
|
|
100
|
+
if (!Number.isFinite(time)) {
|
|
101
|
+
throw new Error(`${flag} must be an ISO timestamp.`);
|
|
102
|
+
}
|
|
103
|
+
return new Date(time).toISOString();
|
|
104
|
+
}
|
|
105
|
+
async function curlFetch(url, init) {
|
|
106
|
+
const method = init?.method ?? "GET";
|
|
107
|
+
const headers = new Headers(init?.headers ?? {});
|
|
108
|
+
const command = ["curl", "-sS", "-L", "-X", method, "--max-time", "10"];
|
|
109
|
+
headers.forEach((value, key) => {
|
|
110
|
+
command.push("-H", `${key}: ${value}`);
|
|
111
|
+
});
|
|
112
|
+
if (typeof init?.body === "string" && init.body.length > 0) {
|
|
113
|
+
command.push("--data", init.body);
|
|
114
|
+
}
|
|
115
|
+
command.push("-w", "\n__NOLO_STATUS__:%{http_code}", url);
|
|
116
|
+
const proc = spawnProcess({ cmd: command, stdout: "pipe", stderr: "pipe" });
|
|
117
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
118
|
+
readPipeText(proc.stdout),
|
|
119
|
+
readPipeText(proc.stderr),
|
|
120
|
+
proc.exited
|
|
121
|
+
]);
|
|
122
|
+
if (exitCode !== 0) {
|
|
123
|
+
throw new Error(stderr.trim() || `curl failed for ${url}`);
|
|
124
|
+
}
|
|
125
|
+
const marker = "\n__NOLO_STATUS__:";
|
|
126
|
+
const markerIndex = stdout.lastIndexOf(marker);
|
|
127
|
+
const body = markerIndex >= 0 ? stdout.slice(0, markerIndex) : stdout;
|
|
128
|
+
const statusText = markerIndex >= 0 ? stdout.slice(markerIndex + marker.length).trim() : "0";
|
|
129
|
+
const status = Number(statusText);
|
|
130
|
+
return new Response(body, {
|
|
131
|
+
status: Number.isFinite(status) ? status : 0,
|
|
132
|
+
headers: { "Content-Type": headers.get("Content-Type") ?? "application/json" }
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function shouldUseCurlTransportFallback(error) {
|
|
136
|
+
const name = error instanceof Error ? error.name : "";
|
|
137
|
+
if (name === "TimeoutError" || name === "AbortError") return false;
|
|
138
|
+
const message = toErrorMessage(error);
|
|
139
|
+
if (/timed out|Timeout/i.test(message)) return false;
|
|
140
|
+
return /Unable to connect|ConnectionRefused|ECONNREFUSED|Failed to connect|Was there a typo|handshake|certificate|ECONNRESET|socket|network/i.test(message);
|
|
141
|
+
}
|
|
142
|
+
async function fetchWithTransportFallback(url, init, options) {
|
|
143
|
+
const signal = init.signal ?? AbortSignal.timeout(1e4);
|
|
144
|
+
const nextInit = { ...init, signal };
|
|
145
|
+
try {
|
|
146
|
+
return await options.fetchImpl(url, nextInit);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
if (!shouldUseCurlTransportFallback(error)) throw error;
|
|
149
|
+
if (options.fallbackFetchImpl) {
|
|
150
|
+
return options.fallbackFetchImpl(url, nextInit);
|
|
151
|
+
}
|
|
152
|
+
if (options.fetchImpl !== fetch) throw error;
|
|
153
|
+
return curlFetch(url, nextInit);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function readAgentRecord(args) {
|
|
157
|
+
const res = await fetchWithTransportFallback(
|
|
158
|
+
`${args.serverUrl}/api/v1/db/read/${encodeURIComponent(args.agentKey)}`,
|
|
159
|
+
{
|
|
160
|
+
method: "GET",
|
|
161
|
+
headers: { Authorization: `Bearer ${args.authToken}` }
|
|
162
|
+
},
|
|
163
|
+
args
|
|
164
|
+
);
|
|
165
|
+
const data = await res.json().catch(() => ({}));
|
|
166
|
+
if (!res.ok) {
|
|
167
|
+
throw new Error(`read failed: HTTP ${res.status} ${JSON.stringify(data)}`);
|
|
168
|
+
}
|
|
169
|
+
return data?.data ?? data;
|
|
170
|
+
}
|
|
171
|
+
async function readDbRecord(args) {
|
|
172
|
+
const query = args.includeDeleted ? "?includeDeleted=true" : "";
|
|
173
|
+
const res = await fetchWithTransportFallback(
|
|
174
|
+
`${args.serverUrl}/api/v1/db/read/${encodeURIComponent(args.dbKey)}${query}`,
|
|
175
|
+
{
|
|
176
|
+
method: "GET",
|
|
177
|
+
headers: { Authorization: `Bearer ${args.authToken}` }
|
|
178
|
+
},
|
|
179
|
+
args
|
|
180
|
+
);
|
|
181
|
+
const data = await res.json().catch(() => ({}));
|
|
182
|
+
if (!res.ok) {
|
|
183
|
+
throw new Error(`read failed: HTTP ${res.status} ${JSON.stringify(data)}`);
|
|
184
|
+
}
|
|
185
|
+
return data?.data ?? data;
|
|
186
|
+
}
|
|
187
|
+
async function queryUserRecords(args) {
|
|
188
|
+
const query = typeof args.limit === "number" && args.limit > 0 ? `?limit=${Math.floor(args.limit)}` : "";
|
|
189
|
+
const res = await fetchWithTransportFallback(
|
|
190
|
+
`${args.serverUrl}/api/v1/db/query/${encodeURIComponent(args.userId)}${query}`,
|
|
191
|
+
{
|
|
192
|
+
method: "POST",
|
|
193
|
+
headers: {
|
|
194
|
+
Authorization: `Bearer ${args.authToken}`,
|
|
195
|
+
"Content-Type": "application/json"
|
|
196
|
+
},
|
|
197
|
+
body: JSON.stringify({
|
|
198
|
+
type: args.type,
|
|
199
|
+
...args.includeDeleted ? { includeDeleted: true } : {},
|
|
200
|
+
...args.summary ? { summary: true } : {}
|
|
201
|
+
})
|
|
202
|
+
},
|
|
203
|
+
args
|
|
204
|
+
);
|
|
205
|
+
const data = await res.json().catch(() => ({}));
|
|
206
|
+
if (!res.ok) {
|
|
207
|
+
throw new Error(`query failed: HTTP ${res.status} ${JSON.stringify(data)}`);
|
|
208
|
+
}
|
|
209
|
+
return Array.isArray(data?.data?.data) ? data.data.data : Array.isArray(data?.data) ? data.data : [];
|
|
210
|
+
}
|
|
211
|
+
async function deleteDbRecord(args) {
|
|
212
|
+
const type = args.deleteOptions?.type;
|
|
213
|
+
const query = type && type !== "single" ? `?type=${encodeURIComponent(type)}` : "";
|
|
214
|
+
const res = await fetchWithTransportFallback(
|
|
215
|
+
`${args.serverUrl}/api/v1/db/delete/${encodeURIComponent(args.dbKey)}${query}`,
|
|
216
|
+
{
|
|
217
|
+
method: "DELETE",
|
|
218
|
+
headers: { Authorization: `Bearer ${args.authToken}` }
|
|
219
|
+
},
|
|
220
|
+
args
|
|
221
|
+
);
|
|
222
|
+
const data = await res.json().catch(() => ({}));
|
|
223
|
+
if (!res.ok) {
|
|
224
|
+
throw new Error(`delete failed: HTTP ${res.status} ${JSON.stringify(data)}`);
|
|
225
|
+
}
|
|
226
|
+
return data;
|
|
227
|
+
}
|
|
228
|
+
async function writeAgentRecord(args) {
|
|
229
|
+
const res = await fetchWithTransportFallback(`${args.serverUrl}/api/v1/db/write/`, {
|
|
230
|
+
method: "POST",
|
|
231
|
+
headers: {
|
|
232
|
+
Authorization: `Bearer ${args.authToken}`,
|
|
233
|
+
"Content-Type": "application/json"
|
|
234
|
+
},
|
|
235
|
+
body: JSON.stringify({
|
|
236
|
+
customKey: args.agentKey,
|
|
237
|
+
userId: args.userId,
|
|
238
|
+
data: {
|
|
239
|
+
...args.record,
|
|
240
|
+
dbKey: args.agentKey
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
}, args);
|
|
244
|
+
const data = await res.json().catch(() => ({}));
|
|
245
|
+
if (!res.ok) {
|
|
246
|
+
throw new Error(`write failed: HTTP ${res.status} ${JSON.stringify(data)}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function resolveAgentRecordFromHybridStore(args) {
|
|
250
|
+
const agentKey = resolveCliAgentKeyInput(args.agentInput);
|
|
251
|
+
const authToken = args.cliArgs ? resolveAuthToken(args.cliArgs, args.env) : resolveAuthToken(args.env);
|
|
252
|
+
const defaultServerUrl = args.cliArgs ? resolveServerUrl(args.cliArgs, args.env) : resolveServerUrl(args.env);
|
|
253
|
+
const userId = parseUserIdFromAuthToken(authToken) || "local";
|
|
254
|
+
for (const key of buildLocalAgentLookupKeys({
|
|
255
|
+
agentRef: agentKey,
|
|
256
|
+
userId
|
|
257
|
+
})) {
|
|
258
|
+
try {
|
|
259
|
+
const record = await args.db.get(key);
|
|
260
|
+
if (record && typeof record === "object") {
|
|
261
|
+
const cacheAge = Date.now() - (Number(record?.cachedAt) || 0);
|
|
262
|
+
const STALE_CACHE_MS = 6e4;
|
|
263
|
+
if (record?.serverOrigin && shouldReadAgentKeyRemotely(key) && cacheAge > STALE_CACHE_MS) {
|
|
264
|
+
try {
|
|
265
|
+
await readAgentRecord({
|
|
266
|
+
agentKey: key,
|
|
267
|
+
authToken,
|
|
268
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
269
|
+
fetchImpl: args.fetchImpl,
|
|
270
|
+
serverUrl: record.serverOrigin
|
|
271
|
+
});
|
|
272
|
+
try {
|
|
273
|
+
await args.db.put(key, { ...record, cachedAt: Date.now() });
|
|
274
|
+
} catch {
|
|
275
|
+
}
|
|
276
|
+
} catch (err) {
|
|
277
|
+
const msg = toErrorMessage(err);
|
|
278
|
+
if (msg.includes("HTTP 404")) {
|
|
279
|
+
try {
|
|
280
|
+
await args.db.del(key);
|
|
281
|
+
} catch {
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
agentKey: key,
|
|
289
|
+
record,
|
|
290
|
+
source: record?.serverOrigin ? "remote-cache" : "local-cache"
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
} catch {
|
|
294
|
+
}
|
|
295
|
+
if (!shouldReadAgentKeyRemotely(key)) continue;
|
|
296
|
+
for (const serverUrl of args.cliArgs ? resolveServerCandidates(args.cliArgs, args.env, defaultServerUrl) : resolveServerCandidates(args.env, defaultServerUrl)) {
|
|
297
|
+
try {
|
|
298
|
+
const remoteRecord = await readAgentRecord({
|
|
299
|
+
agentKey: key,
|
|
300
|
+
authToken,
|
|
301
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
302
|
+
fetchImpl: args.fetchImpl,
|
|
303
|
+
serverUrl
|
|
304
|
+
});
|
|
305
|
+
const cached = { ...remoteRecord, dbKey: key, serverOrigin: serverUrl, cachedAt: Date.now() };
|
|
306
|
+
await args.db.put(key, cached);
|
|
307
|
+
return {
|
|
308
|
+
agentKey: key,
|
|
309
|
+
record: cached,
|
|
310
|
+
source: "remote-cache"
|
|
311
|
+
};
|
|
312
|
+
} catch {
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const localHandleRecord = await findLocalAgentRecordByHandle({
|
|
317
|
+
handle: args.agentInput,
|
|
318
|
+
db: args.db
|
|
319
|
+
});
|
|
320
|
+
if (localHandleRecord) {
|
|
321
|
+
return {
|
|
322
|
+
agentKey: localHandleRecord.key,
|
|
323
|
+
record: localHandleRecord.record,
|
|
324
|
+
source: localHandleRecord.record?.serverOrigin ? "remote-cache" : "local-cache"
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
if (authToken && userId !== "local") {
|
|
328
|
+
for (const serverUrl of args.cliArgs ? resolveServerCandidates(args.cliArgs, args.env, defaultServerUrl) : resolveServerCandidates(args.env, defaultServerUrl)) {
|
|
329
|
+
try {
|
|
330
|
+
const remoteRecord = await findRemoteAgentRecordByHandle({
|
|
331
|
+
handle: args.agentInput,
|
|
332
|
+
authToken,
|
|
333
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
334
|
+
fetchImpl: args.fetchImpl,
|
|
335
|
+
serverUrl,
|
|
336
|
+
userId
|
|
337
|
+
});
|
|
338
|
+
if (!remoteRecord || typeof remoteRecord !== "object") continue;
|
|
339
|
+
const key = typeof remoteRecord.dbKey === "string" && remoteRecord.dbKey ? remoteRecord.dbKey : typeof remoteRecord.key === "string" && remoteRecord.key ? remoteRecord.key : "";
|
|
340
|
+
if (!key) continue;
|
|
341
|
+
const cached = { ...remoteRecord, dbKey: key, serverOrigin: serverUrl };
|
|
342
|
+
await args.db.put(key, cached);
|
|
343
|
+
return {
|
|
344
|
+
agentKey: key,
|
|
345
|
+
record: cached,
|
|
346
|
+
source: "remote-cache"
|
|
347
|
+
};
|
|
348
|
+
} catch {
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
var CLI_SECRET_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
355
|
+
"apikey",
|
|
356
|
+
"password",
|
|
357
|
+
"passwd",
|
|
358
|
+
"secret",
|
|
359
|
+
"clientsecret",
|
|
360
|
+
"accesstoken",
|
|
361
|
+
"refreshtoken",
|
|
362
|
+
"sessiontoken",
|
|
363
|
+
"bearertoken",
|
|
364
|
+
"authorization",
|
|
365
|
+
"authheader",
|
|
366
|
+
"token",
|
|
367
|
+
"oauthtoken",
|
|
368
|
+
"idtoken",
|
|
369
|
+
"credentials",
|
|
370
|
+
"credential"
|
|
371
|
+
]);
|
|
372
|
+
var CLI_CREDENTIAL_REF_FIELDS = /* @__PURE__ */ new Set(["credentialref", "apikeyref"]);
|
|
373
|
+
var normalizeCredentialFieldName = (value) => value.replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
374
|
+
function isNonEmptyCredentialValue(value) {
|
|
375
|
+
if (value == null) return false;
|
|
376
|
+
if (typeof value === "string") return value.trim().length > 0;
|
|
377
|
+
if (typeof value === "object") return Object.keys(value).length > 0;
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
function agentRecordHasConfiguredCredential(record) {
|
|
381
|
+
if (!record || typeof record !== "object") return false;
|
|
382
|
+
if (Array.isArray(record)) {
|
|
383
|
+
return record.some(agentRecordHasConfiguredCredential);
|
|
384
|
+
}
|
|
385
|
+
for (const [key, value] of Object.entries(record)) {
|
|
386
|
+
const normalizedKey = normalizeCredentialFieldName(key);
|
|
387
|
+
if ((CLI_SECRET_FIELD_NAMES.has(normalizedKey) || CLI_CREDENTIAL_REF_FIELDS.has(normalizedKey)) && isNonEmptyCredentialValue(value)) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
if (typeof value === "object" && value != null && agentRecordHasConfiguredCredential(value)) {
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
function sanitizeAgentRecordForCliOutput(record) {
|
|
397
|
+
if (record == null || typeof record !== "object") return record;
|
|
398
|
+
if (Array.isArray(record)) {
|
|
399
|
+
return record.map((item) => sanitizeAgentRecordForCliOutput(item));
|
|
400
|
+
}
|
|
401
|
+
const source = record;
|
|
402
|
+
const out = {};
|
|
403
|
+
for (const [key, value] of Object.entries(source)) {
|
|
404
|
+
const normalizedKey = normalizeCredentialFieldName(key);
|
|
405
|
+
if (CLI_SECRET_FIELD_NAMES.has(normalizedKey)) continue;
|
|
406
|
+
if (CLI_CREDENTIAL_REF_FIELDS.has(normalizedKey)) {
|
|
407
|
+
if (isNonEmptyCredentialValue(value)) out[key] = value;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
if (value != null && typeof value === "object") {
|
|
411
|
+
out[key] = sanitizeAgentRecordForCliOutput(value);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
out[key] = value;
|
|
415
|
+
}
|
|
416
|
+
return out;
|
|
417
|
+
}
|
|
418
|
+
function normalizeAgentRecordForOutput(agentKey, authToken, agent) {
|
|
419
|
+
const credentialConfigured = agentRecordHasConfiguredCredential(agent);
|
|
420
|
+
const sanitizedRecord = sanitizeAgentRecordForCliOutput(agent);
|
|
421
|
+
return {
|
|
422
|
+
agentKey,
|
|
423
|
+
baseUrl: agent?.serverOrigin ?? null,
|
|
424
|
+
name: agent?.name,
|
|
425
|
+
greeting: agent?.greeting,
|
|
426
|
+
model: agent?.model,
|
|
427
|
+
provider: agent?.provider ?? agent?.apiSource ?? null,
|
|
428
|
+
cliProvider: agent?.cliProvider ?? null,
|
|
429
|
+
customProviderUrl: agent?.customProviderUrl ?? null,
|
|
430
|
+
tools: agent?.tools ?? [],
|
|
431
|
+
isPublic: agent?.isPublic,
|
|
432
|
+
credentialConfigured,
|
|
433
|
+
credentialRef: agent?.credentialRef ?? void 0,
|
|
434
|
+
apiKeyRef: agent?.apiKeyRef ?? void 0,
|
|
435
|
+
authUserId: parseUserIdFromAuthToken(authToken),
|
|
436
|
+
userId: agent?.userId,
|
|
437
|
+
record: sanitizedRecord
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
function parseAgentUpdateArgs(args) {
|
|
441
|
+
const agentInput = readOption(args, "--agent") ?? readOption(args, "--id") ?? args[0]?.trim();
|
|
442
|
+
if (!agentInput || agentInput === "--help" || agentInput === "-h") return null;
|
|
443
|
+
const updates = {};
|
|
444
|
+
const model = readOption(args, "--model");
|
|
445
|
+
const cliProvider = readOption(args, "--cli-provider");
|
|
446
|
+
const apiSource = readOption(args, "--api-source");
|
|
447
|
+
const provider = readOption(args, "--provider");
|
|
448
|
+
const prompt = readOption(args, "--prompt");
|
|
449
|
+
const promptFile = readOption(args, "--prompt-file");
|
|
450
|
+
const promptDoc = readOption(args, "--prompt-doc");
|
|
451
|
+
const tools = readOption(args, "--tools");
|
|
452
|
+
const copyProviderFrom = readOption(args, "--copy-provider-from");
|
|
453
|
+
const name = readOption(args, "--name");
|
|
454
|
+
const customProviderUrl = readOption(args, "--custom-provider-url");
|
|
455
|
+
const apiKey = readOption(args, "--api-key");
|
|
456
|
+
const maxConcurrent = parsePositiveIntegerOption(
|
|
457
|
+
readOption(args, "--max-concurrent"),
|
|
458
|
+
"--max-concurrent"
|
|
459
|
+
);
|
|
460
|
+
const expiresAt = parseIsoTimestampOption(readOption(args, "--expires-at"), "--expires-at");
|
|
461
|
+
const handle = readOption(args, "--handle")?.trim();
|
|
462
|
+
const promptSources = [prompt, promptFile, promptDoc].filter(Boolean);
|
|
463
|
+
if (promptSources.length > 1) {
|
|
464
|
+
throw new Error("--prompt / --prompt-file / --prompt-doc are mutually exclusive.");
|
|
465
|
+
}
|
|
466
|
+
if (model) updates.model = model;
|
|
467
|
+
if (cliProvider) updates.cliProvider = cliProvider;
|
|
468
|
+
if (apiSource) updates.apiSource = apiSource;
|
|
469
|
+
if (provider) updates.provider = provider;
|
|
470
|
+
if (prompt) updates.prompt = prompt;
|
|
471
|
+
if (promptFile) updates.prompt = readFileSync(promptFile, "utf8");
|
|
472
|
+
if (tools) updates.tools = parseJsonishValue(tools);
|
|
473
|
+
if (name) updates.name = name;
|
|
474
|
+
if (customProviderUrl) updates.customProviderUrl = customProviderUrl;
|
|
475
|
+
if (apiKey) updates.apiKey = apiKey;
|
|
476
|
+
if (maxConcurrent != null) updates.admission = { maxConcurrent };
|
|
477
|
+
if (expiresAt) {
|
|
478
|
+
updates.scheduling = { expiresAt };
|
|
479
|
+
}
|
|
480
|
+
if (handle) updates.handle = handle;
|
|
481
|
+
for (const entry of readRepeatedOption(args, "--field")) {
|
|
482
|
+
const index = entry.indexOf("=");
|
|
483
|
+
if (index <= 0) {
|
|
484
|
+
throw new Error(`--field must use key=value, received ${JSON.stringify(entry)}`);
|
|
485
|
+
}
|
|
486
|
+
updates[entry.slice(0, index)] = parseJsonishValue(entry.slice(index + 1));
|
|
487
|
+
}
|
|
488
|
+
if (Object.keys(updates).length === 0) {
|
|
489
|
+
if (!promptDoc && !copyProviderFrom) {
|
|
490
|
+
throw new Error("No updates provided. Use --model / --cli-provider / --api-source / --field key=value.");
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return { agentInput, updates, promptDoc, copyProviderFrom };
|
|
494
|
+
}
|
|
495
|
+
async function buildCreatedAgentRecord(args) {
|
|
496
|
+
const serverUrl = args.cliArgs ? resolveServerUrl(args.cliArgs, args.env) : resolveServerUrl(args.env);
|
|
497
|
+
const userId = parseUserIdFromAuthToken(args.authToken);
|
|
498
|
+
const resolvedAgentInput = resolveCliAgentKeyInput(args.parsed.agentInput);
|
|
499
|
+
const agentKey = resolvedAgentInput.startsWith("agent-") ? resolvedAgentInput : createAgentKey.private(userId || "local", resolvedAgentInput);
|
|
500
|
+
if (args.parsed.copyProviderFrom) {
|
|
501
|
+
const providerSource = await resolveAgentRecordFromHybridStore({
|
|
502
|
+
agentInput: args.parsed.copyProviderFrom,
|
|
503
|
+
cliArgs: args.cliArgs,
|
|
504
|
+
env: args.env,
|
|
505
|
+
db: args.db,
|
|
506
|
+
fetchImpl: args.fetchImpl,
|
|
507
|
+
fallbackFetchImpl: args.fallbackFetchImpl
|
|
508
|
+
});
|
|
509
|
+
if (!providerSource) {
|
|
510
|
+
throw new Error(`provider source agent not found: ${args.parsed.copyProviderFrom}`);
|
|
511
|
+
}
|
|
512
|
+
for (const field of PROVIDER_COPY_FIELDS) {
|
|
513
|
+
if (field in providerSource.record) {
|
|
514
|
+
args.parsed.updates[field] = providerSource.record[field];
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (args.parsed.promptDoc) {
|
|
519
|
+
const promptDoc = await readDbRecord({
|
|
520
|
+
dbKey: args.parsed.promptDoc,
|
|
521
|
+
authToken: args.authToken,
|
|
522
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
523
|
+
fetchImpl: args.fetchImpl,
|
|
524
|
+
serverUrl
|
|
525
|
+
});
|
|
526
|
+
const promptBody = typeof promptDoc?.content === "string" ? promptDoc.content : "";
|
|
527
|
+
if (!promptBody.trim()) {
|
|
528
|
+
throw new Error(`prompt doc is empty or unreadable: ${args.parsed.promptDoc}`);
|
|
529
|
+
}
|
|
530
|
+
args.parsed.updates.prompt = promptBody;
|
|
531
|
+
}
|
|
532
|
+
const nextRecord = {
|
|
533
|
+
...args.parsed.updates,
|
|
534
|
+
dbKey: agentKey,
|
|
535
|
+
key: agentKey,
|
|
536
|
+
type: "agent" /* AGENT */,
|
|
537
|
+
createdAt: Date.now(),
|
|
538
|
+
updatedAt: Date.now(),
|
|
539
|
+
userId
|
|
540
|
+
};
|
|
541
|
+
return {
|
|
542
|
+
agentKey,
|
|
543
|
+
serverUrl,
|
|
544
|
+
nextRecord,
|
|
545
|
+
updates: args.parsed.updates
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
async function buildUpdatedAgentRecord(args) {
|
|
549
|
+
const cached = await resolveAgentRecordFromHybridStore({
|
|
550
|
+
agentInput: args.parsed.agentInput,
|
|
551
|
+
cliArgs: args.cliArgs,
|
|
552
|
+
env: args.env,
|
|
553
|
+
db: args.db,
|
|
554
|
+
fetchImpl: args.fetchImpl,
|
|
555
|
+
fallbackFetchImpl: args.fallbackFetchImpl
|
|
556
|
+
});
|
|
557
|
+
const agentKey = cached?.agentKey ?? resolveCliAgentKeyInput(args.parsed.agentInput);
|
|
558
|
+
const explicitServerUrl = args.cliArgs ? readOption(args.cliArgs, "--server-url") || readOption(args.cliArgs, "--server") : void 0;
|
|
559
|
+
const envServerUrl = args.env.NOLO_SERVER || args.env.BASE_URL || args.env.NOLO_SERVER_URL;
|
|
560
|
+
const requestedServerUrl = explicitServerUrl || envServerUrl ? args.cliArgs ? resolveServerUrl(args.cliArgs, args.env) : resolveServerUrl(args.env) : void 0;
|
|
561
|
+
const serverUrl = requestedServerUrl || cached?.record?.serverOrigin || resolveServerUrl(args.env);
|
|
562
|
+
const currentRecord = await readAgentRecord({
|
|
563
|
+
agentKey,
|
|
564
|
+
authToken: args.authToken,
|
|
565
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
566
|
+
fetchImpl: args.fetchImpl,
|
|
567
|
+
serverUrl
|
|
568
|
+
});
|
|
569
|
+
if (args.parsed.copyProviderFrom) {
|
|
570
|
+
const providerSource = await resolveAgentRecordFromHybridStore({
|
|
571
|
+
agentInput: args.parsed.copyProviderFrom,
|
|
572
|
+
cliArgs: args.cliArgs,
|
|
573
|
+
env: args.env,
|
|
574
|
+
db: args.db,
|
|
575
|
+
fetchImpl: args.fetchImpl,
|
|
576
|
+
fallbackFetchImpl: args.fallbackFetchImpl
|
|
577
|
+
});
|
|
578
|
+
if (!providerSource) {
|
|
579
|
+
throw new Error(`provider source agent not found: ${args.parsed.copyProviderFrom}`);
|
|
580
|
+
}
|
|
581
|
+
for (const field of PROVIDER_COPY_FIELDS) {
|
|
582
|
+
if (field in providerSource.record) {
|
|
583
|
+
args.parsed.updates[field] = providerSource.record[field];
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (args.parsed.promptDoc) {
|
|
588
|
+
const promptDoc = await readDbRecord({
|
|
589
|
+
dbKey: args.parsed.promptDoc,
|
|
590
|
+
authToken: args.authToken,
|
|
591
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
592
|
+
fetchImpl: args.fetchImpl,
|
|
593
|
+
serverUrl
|
|
594
|
+
});
|
|
595
|
+
const promptBody = typeof promptDoc?.content === "string" ? promptDoc.content : "";
|
|
596
|
+
if (!promptBody.trim()) {
|
|
597
|
+
throw new Error(`prompt doc is empty or unreadable: ${args.parsed.promptDoc}`);
|
|
598
|
+
}
|
|
599
|
+
args.parsed.updates.prompt = promptBody;
|
|
600
|
+
}
|
|
601
|
+
const nextRecord = {
|
|
602
|
+
...currentRecord,
|
|
603
|
+
...args.parsed.updates,
|
|
604
|
+
updatedAt: Date.now()
|
|
605
|
+
};
|
|
606
|
+
return {
|
|
607
|
+
agentKey,
|
|
608
|
+
serverUrl,
|
|
609
|
+
nextRecord,
|
|
610
|
+
updates: args.parsed.updates
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export {
|
|
615
|
+
fetchWithTransportFallback,
|
|
616
|
+
readAgentRecord,
|
|
617
|
+
readDbRecord,
|
|
618
|
+
queryUserRecords,
|
|
619
|
+
deleteDbRecord,
|
|
620
|
+
writeAgentRecord,
|
|
621
|
+
resolveAgentRecordFromHybridStore,
|
|
622
|
+
agentRecordHasConfiguredCredential,
|
|
623
|
+
sanitizeAgentRecordForCliOutput,
|
|
624
|
+
normalizeAgentRecordForOutput,
|
|
625
|
+
parseAgentUpdateArgs,
|
|
626
|
+
buildCreatedAgentRecord,
|
|
627
|
+
buildUpdatedAgentRecord
|
|
628
|
+
};
|