pinomad 0.11.0 → 0.13.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 +1 -1
- package/dist/{chunk-wb10efyq.js → chunk-445cevpm.js} +1 -1
- package/dist/{chunk-jt34g8st.js → chunk-4fferbxw.js} +247 -27
- package/dist/{chunk-67gq282t.js → chunk-53xv3fny.js} +725 -75
- package/dist/{chunk-44pnts98.js → chunk-563fnad9.js} +1 -1
- package/dist/{chunk-b457q0tm.js → chunk-6th9xv39.js} +11 -8
- package/dist/{chunk-ncbqa8jk.js → chunk-7mn38n4f.js} +1 -1
- package/dist/{chunk-as6pyf00.js → chunk-90g1cg9n.js} +1 -1
- package/dist/{chunk-9h5vawnm.js → chunk-aapsc9g0.js} +270 -66
- package/dist/{chunk-n1m1tjrk.js → chunk-d4tq62yr.js} +57 -16
- package/dist/{chunk-gtdpjqa3.js → chunk-d9mq5d46.js} +205 -49
- package/dist/{chunk-y127fe1a.js → chunk-g3ahp7b9.js} +11 -0
- package/dist/{chunk-xqycs43g.js → chunk-kmzzjv53.js} +83 -8
- package/dist/{chunk-4dcs8sbj.js → chunk-m51mq8vh.js} +43 -21
- package/dist/{chunk-tj57aqav.js → chunk-maqv34cs.js} +2 -2
- package/dist/chunk-nq57fdnq.js +106 -0
- package/dist/{chunk-h5q2y57m.js → chunk-ra86wjp5.js} +10 -4
- package/dist/{chunk-sd5fkxjj.js → chunk-s0h7c7da.js} +1 -1
- package/dist/chunk-sd640dt7.js +22 -0
- package/dist/{chunk-6d16c2fv.js → chunk-t6fw0wa9.js} +13 -6
- package/dist/{chunk-vvj9b1gc.js → chunk-wd7aracm.js} +188 -54
- package/dist/pinomad.js +15 -14
- package/package.json +13 -11
- package/web/assets/astro-DOly5024.js +1 -0
- package/web/assets/c-BIGW1oBm.js +1 -0
- package/web/assets/core-BHm2gdHL.js +4 -0
- package/web/assets/cpp-DddhVWhK.js +1 -0
- package/web/assets/csharp-B_TYUkTI.js +1 -0
- package/web/assets/css-Z72CF80r.js +1 -0
- package/web/assets/dart-CtKP3W-j.js +1 -0
- package/web/assets/diff-D97Zzqfu.js +1 -0
- package/web/assets/dockerfile-BcOcwvcX.js +1 -0
- package/web/assets/elixir-DkJLSxtU.js +1 -0
- package/web/assets/engine-javascript-BHPwbUfN.js +141 -0
- package/web/assets/engine-oniguruma-CQjQPVHy.js +1 -0
- package/web/assets/fish-BvzEVeQv.js +1 -0
- package/web/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/web/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/web/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/web/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/web/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/web/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/web/assets/go-C27-OAKa.js +1 -0
- package/web/assets/graphql-ChdNCCLP.js +1 -0
- package/web/assets/haskell-Df6bDoY_.js +1 -0
- package/web/assets/hcl-BWvSN4gD.js +1 -0
- package/web/assets/highlighted-diff-DrHvSLK9.js +175 -0
- package/web/assets/highlights-1aLwssz-.js +4 -0
- package/web/assets/highlights-themes-C1p4pFYS.js +1 -0
- package/web/assets/html-BlS82ilI.js +1 -0
- package/web/assets/index-A_AUJoO6.css +1 -0
- package/web/assets/index-BafYMKiN.js +396 -0
- package/web/assets/ini-BEwlwnbL.js +1 -0
- package/web/assets/java-CylS5w8V.js +1 -0
- package/web/assets/javascript-wDzz0qaB.js +1 -0
- package/web/assets/json-Cp-IABpG.js +1 -0
- package/web/assets/jsonc-Des-eS-w.js +1 -0
- package/web/assets/jsx-g9-lgVsj.js +1 -0
- package/web/assets/kotlin-BdnUsdx6.js +1 -0
- package/web/assets/less-B1dDrJ26.js +1 -0
- package/web/assets/lua-BaeVxFsk.js +1 -0
- package/web/assets/make-CHLpvVh8.js +1 -0
- package/web/assets/markdown-Cvjx9yec.js +1 -0
- package/web/assets/nix-CwoSXNpI.js +1 -0
- package/web/assets/objective-c-DXmwc3jG.js +1 -0
- package/web/assets/php-DoruYMF0.js +1 -0
- package/web/assets/pierre-dark-CyvmCCZW.js +1 -0
- package/web/assets/pierre-dark-VKo95ZgA.js +1 -0
- package/web/assets/pierre-light-480U9XYS.js +1 -0
- package/web/assets/pierre-light-BVSW-Xev.js +1 -0
- package/web/assets/postcss-DnzrXTVv.js +1 -0
- package/web/assets/powershell-Dd0kTxKP.js +1 -0
- package/web/assets/prisma-Vru482bI.js +1 -0
- package/web/assets/proto-C7zT0LnQ.js +1 -0
- package/web/assets/python-B6aJPvgy.js +1 -0
- package/web/assets/ruby-B43yHlf9.js +1 -0
- package/web/assets/rust-DPvrY3IQ.js +1 -0
- package/web/assets/scala-CqE71os6.js +1 -0
- package/web/assets/scss-Cw6XMfVs.js +1 -0
- package/web/assets/shellscript-Yzrsuije.js +1 -0
- package/web/assets/shiki-BwyCm3kZ.js +2 -0
- package/web/assets/shiki-langs-CMlALLSg.js +2 -0
- package/web/assets/shiki-wasm-CgFRq91U.js +1 -0
- package/web/assets/sql-DkvoVjww.js +1 -0
- package/web/assets/stream-tokenizer-BlgIhw0y.js +4 -0
- package/web/assets/svelte-DoIXUgJc.js +1 -0
- package/web/assets/swift-C2oV4EkX.js +1 -0
- package/web/assets/terraform-BETggiCN.js +1 -0
- package/web/assets/theming-themes-DDvoqEqT.js +1 -0
- package/web/assets/toml-vGWfd6FD.js +1 -0
- package/web/assets/tsx-COt5Ahok.js +1 -0
- package/web/assets/typescript-BPQ3VLAy.js +1 -0
- package/web/assets/vue-CwSeJimo.js +1 -0
- package/web/assets/xml-sdJ4AIDG.js +1 -0
- package/web/assets/xterm-view-6GBZ9nXN.css +32 -0
- package/web/assets/xterm-view-BnKOnF3C.js +38 -0
- package/web/assets/yaml-Buea-lGh.js +1 -0
- package/web/assets/zig-VOosw3JB.js +1 -0
- package/web/index.html +2 -2
- package/dist/chunk-etf7ef97.js +0 -55
- package/dist/chunk-greb3dp6.js +0 -22
- package/web/assets/index-BhHrKpoo.js +0 -395
- package/web/assets/index-DoyHMPwf.css +0 -1
|
@@ -187,7 +187,7 @@ var conversationStream = (id) => `conversation:${id}`;
|
|
|
187
187
|
var docStream = (kind, id) => `doc:${kind}:${id}`;
|
|
188
188
|
var UNAUTHORIZED_CLOSE_CODE = 4401;
|
|
189
189
|
var INVALID_FRAME_CLOSE_CODE = 4400;
|
|
190
|
-
var PROTOCOL = { major: 5, minor:
|
|
190
|
+
var PROTOCOL = { major: 5, minor: 29 };
|
|
191
191
|
var CALL_SINCE = {
|
|
192
192
|
addProject: 0,
|
|
193
193
|
removeProject: 0,
|
|
@@ -202,6 +202,7 @@ var CALL_SINCE = {
|
|
|
202
202
|
submission: 25,
|
|
203
203
|
withdrawQueued: 14,
|
|
204
204
|
steerQueued: 14,
|
|
205
|
+
reorderQueued: 29,
|
|
205
206
|
abort: 0,
|
|
206
207
|
compact: 0,
|
|
207
208
|
runCommand: 17,
|
|
@@ -226,10 +227,17 @@ var CALL_SINCE = {
|
|
|
226
227
|
deleteAgent: 6,
|
|
227
228
|
setPushToken: 7,
|
|
228
229
|
image: 15,
|
|
230
|
+
earlierEntries: 28,
|
|
229
231
|
beginAttachment: 19,
|
|
230
232
|
appendAttachment: 19,
|
|
231
233
|
rtcOffer: 23,
|
|
232
|
-
ping: 23
|
|
234
|
+
ping: 23,
|
|
235
|
+
openTerminal: 27,
|
|
236
|
+
terminalInput: 27,
|
|
237
|
+
resizeTerminal: 27,
|
|
238
|
+
renameTerminal: 27,
|
|
239
|
+
restartTerminal: 27,
|
|
240
|
+
closeTerminal: 27
|
|
233
241
|
};
|
|
234
242
|
function hostSupportsCall(hostMinor, method) {
|
|
235
243
|
return hostMinor >= CALL_SINCE[method];
|
|
@@ -246,7 +254,9 @@ var FEATURE_SINCE = {
|
|
|
246
254
|
attachments: 19,
|
|
247
255
|
imageVariants: 20,
|
|
248
256
|
rtc: 23,
|
|
249
|
-
submitEntry: 25
|
|
257
|
+
submitEntry: 25,
|
|
258
|
+
terminals: 27,
|
|
259
|
+
transcriptPaging: 28
|
|
250
260
|
};
|
|
251
261
|
function hostSupportsFeature(hostMinor, feature) {
|
|
252
262
|
return hostMinor >= FEATURE_SINCE[feature];
|
|
@@ -259,8 +269,27 @@ function parseClientFrame(value) {
|
|
|
259
269
|
if (typeof stream !== "string")
|
|
260
270
|
return { kind: "malformed" };
|
|
261
271
|
if (isStreamName(stream)) {
|
|
262
|
-
|
|
263
|
-
|
|
272
|
+
if (value.type === "unsubscribe")
|
|
273
|
+
return { kind: "frame", frame: { type: "unsubscribe", stream } };
|
|
274
|
+
if (stream.startsWith("terminal:") && value.since !== undefined) {
|
|
275
|
+
const since = value.since;
|
|
276
|
+
if (typeof since !== "number" || !Number.isSafeInteger(since) || since < 0)
|
|
277
|
+
return { kind: "malformed" };
|
|
278
|
+
return { kind: "frame", frame: { type: "subscribe", stream, since } };
|
|
279
|
+
}
|
|
280
|
+
const refs = value.images === "ref";
|
|
281
|
+
let window;
|
|
282
|
+
if (stream.startsWith("conversation:") && value.window !== undefined) {
|
|
283
|
+
if (!record(value.window) || !positive(value.window.limit) || !(value.window.from === undefined || positive(value.window.from))) {
|
|
284
|
+
return { kind: "malformed" };
|
|
285
|
+
}
|
|
286
|
+
const limit = value.window.limit;
|
|
287
|
+
window = value.window.from === undefined ? { limit } : { limit, from: value.window.from };
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
kind: "frame",
|
|
291
|
+
frame: { type: "subscribe", stream, ...refs ? { images: "ref" } : {}, ...window === undefined ? {} : { window } }
|
|
292
|
+
};
|
|
264
293
|
}
|
|
265
294
|
const prefix = stream.slice(0, stream.indexOf(":") === -1 ? undefined : stream.indexOf(":"));
|
|
266
295
|
if (STREAM_KINDS.has(prefix))
|
|
@@ -277,9 +306,9 @@ function parseClientFrame(value) {
|
|
|
277
306
|
return { kind: "unsupportedCall", id, method };
|
|
278
307
|
return validCallArgs(method, args) ? { kind: "frame", frame: { type: "call", id, method, args } } : { kind: "malformed" };
|
|
279
308
|
}
|
|
280
|
-
var STREAM_KINDS = new Set(["conversation", "doc", "tasks", ...HOST_STREAM_NAMES]);
|
|
309
|
+
var STREAM_KINDS = new Set(["conversation", "doc", "tasks", "terminals", "terminal", ...HOST_STREAM_NAMES]);
|
|
281
310
|
function isStreamName(stream) {
|
|
282
|
-
return stream === "tasks" || HOST_STREAM_NAMES.includes(stream) || /^(?:conversation:|doc
|
|
311
|
+
return stream === "tasks" || HOST_STREAM_NAMES.includes(stream) || /^(?:conversation:|doc:.+:|terminals:)[1-9]\d*$/.test(stream) || /^terminal:[\w-]+$/.test(stream);
|
|
283
312
|
}
|
|
284
313
|
var isCallMethod = (method) => CALL_METHODS.includes(method);
|
|
285
314
|
var CALL_METHODS = Object.keys(CALL_SINCE);
|
|
@@ -299,7 +328,20 @@ function validCallArgs(method, args) {
|
|
|
299
328
|
const skills = () => args.skills === undefined || Array.isArray(args.skills) && args.skills.every(nonempty);
|
|
300
329
|
const attachments = () => args.attachments === undefined || Array.isArray(args.attachments) && args.attachments.every(nonempty);
|
|
301
330
|
const role = () => record(args.role) && typeof args.role.name === "string" && typeof args.role.description === "string" && typeof args.role.prompt === "string" && (args.role.model === undefined || typeof args.role.model === "string") && (args.role.thinkingLevel === undefined || typeof args.role.thinkingLevel === "string");
|
|
331
|
+
const terminalId = () => nonempty(args.terminalId);
|
|
332
|
+
const size = () => [args.cols, args.rows].every((n) => typeof n === "number" && Number.isSafeInteger(n) && n >= 1);
|
|
302
333
|
switch (method) {
|
|
334
|
+
case "openTerminal":
|
|
335
|
+
return conversationId() && size();
|
|
336
|
+
case "terminalInput":
|
|
337
|
+
return terminalId() && typeof args.data === "string";
|
|
338
|
+
case "resizeTerminal":
|
|
339
|
+
case "restartTerminal":
|
|
340
|
+
return terminalId() && size();
|
|
341
|
+
case "renameTerminal":
|
|
342
|
+
return terminalId() && (args.name === null || typeof args.name === "string");
|
|
343
|
+
case "closeTerminal":
|
|
344
|
+
return terminalId();
|
|
303
345
|
case "submit":
|
|
304
346
|
return conversationId() && typeof args.text === "string" && (args.whenBusy === "steer" || args.whenBusy === "followUp") && nonempty(args.requestId) && images() && skills() && attachments();
|
|
305
347
|
case "submission":
|
|
@@ -307,6 +349,8 @@ function validCallArgs(method, args) {
|
|
|
307
349
|
case "withdrawQueued":
|
|
308
350
|
case "steerQueued":
|
|
309
351
|
return conversationId() && submissionId();
|
|
352
|
+
case "reorderQueued":
|
|
353
|
+
return conversationId() && submissionId() && (args.before === undefined || typeof args.before === "number" && Number.isSafeInteger(args.before) && args.before >= 1);
|
|
310
354
|
case "abort":
|
|
311
355
|
return conversationId();
|
|
312
356
|
case "setThinkingLevel":
|
|
@@ -327,6 +371,8 @@ function validCallArgs(method, args) {
|
|
|
327
371
|
return conversationId() && nonempty(args.kind) && nonempty(args.requestId) && Array.isArray(args.answers) && args.answers.every((answer) => record(answer) && Array.isArray(answer.selected) && answer.selected.every((l) => typeof l === "string") && (answer.other === undefined || typeof answer.other === "string"));
|
|
328
372
|
case "changes":
|
|
329
373
|
return conversationId();
|
|
374
|
+
case "earlierEntries":
|
|
375
|
+
return conversationId() && positive(args.before) && positive(args.limit);
|
|
330
376
|
case "image":
|
|
331
377
|
return nonempty(args.ref) && (args.variant === undefined || args.variant === "thumbnail" || args.variant === "preview");
|
|
332
378
|
case "beginAttachment":
|
|
@@ -383,6 +429,9 @@ function validCallArgs(method, args) {
|
|
|
383
429
|
function record(value) {
|
|
384
430
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
385
431
|
}
|
|
432
|
+
function positive(value) {
|
|
433
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
434
|
+
}
|
|
386
435
|
function nonempty(value) {
|
|
387
436
|
return typeof value === "string" && value.length > 0;
|
|
388
437
|
}
|
|
@@ -619,4 +668,30 @@ function homeOf(index, summaries, id) {
|
|
|
619
668
|
return;
|
|
620
669
|
}
|
|
621
670
|
|
|
622
|
-
|
|
671
|
+
// packages/protocol/src/transcript.ts
|
|
672
|
+
var TRANSCRIPT_PAGE = 50;
|
|
673
|
+
var MAX_TRANSCRIPT_PAGE = 500;
|
|
674
|
+
function withEarlier(view, earlier) {
|
|
675
|
+
if (earlier === undefined)
|
|
676
|
+
return view;
|
|
677
|
+
const { before: _window, ...rest } = view;
|
|
678
|
+
return {
|
|
679
|
+
...rest,
|
|
680
|
+
entries: [...earlier.entries, ...view.entries],
|
|
681
|
+
...earlier.before === undefined ? {} : { before: earlier.before }
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function addEarlier(shown, earlier, requested, page) {
|
|
685
|
+
if (shown.before !== requested)
|
|
686
|
+
return earlier;
|
|
687
|
+
return {
|
|
688
|
+
entries: [...page.entries, ...earlier?.entries ?? []],
|
|
689
|
+
...page.before === undefined ? {} : { before: page.before }
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
function isBusy(view) {
|
|
693
|
+
const live = view.docs?.["pi.live"];
|
|
694
|
+
return live?.run !== undefined;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
export { rtcSelectedPair, RTC_DEFAULT_STUN, RTC_DATA_CHANNEL_LABEL, RTC_MAX_RECORD_BYTES, isRtcHello, rtcCandidateType, sdpCandidates, withRtcCandidates, parseRtcMaxMessageSize, isCustomProviderApi, HOST_STREAM_NAMES, hostStreams, conversationStream, docStream, UNAUTHORIZED_CLOSE_CODE, INVALID_FRAME_CLOSE_CODE, PROTOCOL, hostSupportsCall, hostSupportsFeature, parseClientFrame, MAX_ATTACHMENTS_PER_MESSAGE, MAX_PENDING_ATTACHMENTS, MAX_PENDING_ATTACHMENT_BYTES, ATTACHMENT_TTL_MS, MAX_ATTACHMENT_NAME_LENGTH, isAttachmentId, base64DecodedLength, attachmentBeginProblem, attachmentChunkProblem, attachmentBlock, parseAttachmentBlock, organize, checkoutOf, homeOf, TRANSCRIPT_PAGE, MAX_TRANSCRIPT_PAGE, withEarlier, addEarlier, isBusy };
|
|
@@ -3,32 +3,35 @@ import {
|
|
|
3
3
|
assertSecureServerOrigin,
|
|
4
4
|
probeServerAccounts,
|
|
5
5
|
runServerOperation
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7mn38n4f.js";
|
|
7
7
|
import {
|
|
8
8
|
loadHostKey,
|
|
9
9
|
loadRelayKey
|
|
10
10
|
} from "./chunk-t91zt5f0.js";
|
|
11
11
|
import {
|
|
12
|
+
readRemovalNotice,
|
|
12
13
|
readServerConfig,
|
|
13
14
|
removeServerConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-nq57fdnq.js";
|
|
15
16
|
import {
|
|
16
17
|
relayHostId
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-g3ahp7b9.js";
|
|
18
19
|
import {
|
|
19
20
|
argValue,
|
|
20
21
|
restartService,
|
|
21
22
|
serviceManager,
|
|
22
23
|
withoutRelayArgs
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import"./chunk-
|
|
24
|
+
} from "./chunk-wd7aracm.js";
|
|
25
|
+
import"./chunk-4fferbxw.js";
|
|
25
26
|
import"./chunk-kzbzacz9.js";
|
|
26
|
-
import"./chunk-
|
|
27
|
+
import"./chunk-kmzzjv53.js";
|
|
27
28
|
import"./chunk-pqe7q1s7.js";
|
|
28
29
|
import {
|
|
29
30
|
DEFAULT_DATA_DIR
|
|
30
31
|
} from "./chunk-ngf1zatm.js";
|
|
31
|
-
import
|
|
32
|
+
import {
|
|
33
|
+
commandHint
|
|
34
|
+
} from "./chunk-s0h7c7da.js";
|
|
32
35
|
import"./chunk-df32avw6.js";
|
|
33
36
|
|
|
34
37
|
// apps/host/src/cli/leave.ts
|
|
@@ -39,8 +42,13 @@ var message = (error) => error instanceof Error ? error.message : String(error);
|
|
|
39
42
|
async function leaveServer(args, deps) {
|
|
40
43
|
const dataDir = resolve(args.dataDir);
|
|
41
44
|
const config = await readServerConfig(dataDir);
|
|
42
|
-
if (config === undefined)
|
|
43
|
-
|
|
45
|
+
if (config === undefined) {
|
|
46
|
+
const removed = await readRemovalNotice(dataDir);
|
|
47
|
+
if (removed === undefined)
|
|
48
|
+
throw new Error(`not joined — no server.json in ${dataDir}`);
|
|
49
|
+
await removeServerConfig(dataDir);
|
|
50
|
+
return { origin: removed.origin, warnings: [], notes: ["the account had already removed this host"] };
|
|
51
|
+
}
|
|
44
52
|
const origin = config.origin;
|
|
45
53
|
const warnings = [];
|
|
46
54
|
const notes = [];
|
|
@@ -78,7 +86,10 @@ async function leaveServer(args, deps) {
|
|
|
78
86
|
await removeServerConfig(dataDir);
|
|
79
87
|
const manager = deps?.manager ?? serviceManager();
|
|
80
88
|
try {
|
|
81
|
-
const
|
|
89
|
+
const state = await manager.state().catch(() => {
|
|
90
|
+
return;
|
|
91
|
+
});
|
|
92
|
+
const installed = state?.installed === true;
|
|
82
93
|
const previous = installed ? await manager.read() : undefined;
|
|
83
94
|
if (!installed) {
|
|
84
95
|
notes.push("no service installed — restart any running host so it stops dialing the server");
|
|
@@ -87,19 +98,30 @@ async function leaveServer(args, deps) {
|
|
|
87
98
|
} else {
|
|
88
99
|
const stripped = previous === undefined ? undefined : { ...previous, hostArgs: withoutRelayArgs(previous.hostArgs) };
|
|
89
100
|
const rewriting = stripped !== undefined && stripped.hostArgs.length !== previous.hostArgs.length;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
argv: ["--data-dir", dataDir, ...port === undefined ? [] : ["--url", `ws://127.0.0.1:${port}`]],
|
|
94
|
-
manager,
|
|
95
|
-
...rewriting ? {
|
|
96
|
-
restart: async () => {
|
|
101
|
+
if (state.stopped) {
|
|
102
|
+
if (rewriting) {
|
|
103
|
+
try {
|
|
97
104
|
await manager.install(stripped);
|
|
105
|
+
} finally {
|
|
106
|
+
await manager.stop();
|
|
98
107
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
}
|
|
109
|
+
notes.push(`the service is stopped and stays off until \`${commandHint("service")} start\``);
|
|
110
|
+
} else {
|
|
111
|
+
const port = argValue(previous?.hostArgs ?? [], "--port");
|
|
112
|
+
const code = await restartService({
|
|
113
|
+
force: false,
|
|
114
|
+
argv: ["--data-dir", dataDir, ...port === undefined ? [] : ["--url", `ws://127.0.0.1:${port}`]],
|
|
115
|
+
manager,
|
|
116
|
+
...rewriting ? {
|
|
117
|
+
restart: async () => {
|
|
118
|
+
await manager.install(stripped);
|
|
119
|
+
}
|
|
120
|
+
} : {}
|
|
121
|
+
});
|
|
122
|
+
if (code !== 0)
|
|
123
|
+
warnings.push("the service restart did not finish — check `service status`");
|
|
124
|
+
}
|
|
103
125
|
}
|
|
104
126
|
} catch (error) {
|
|
105
127
|
warnings.push(`could not update the service definition: ${message(error)} — remove --relay from it and restart manually`);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// apps/host/src/server-config.ts
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
var SERVER_CONFIG_FILE = "server.json";
|
|
6
|
+
var REMOVAL_NOTICE_FILE = "server-removed.json";
|
|
7
|
+
var normalizeOrigin = (origin) => origin.replace(/\/+$/, "");
|
|
8
|
+
async function readServerConfig(dataDir) {
|
|
9
|
+
const config = await readServerConfigAt(join(dataDir, SERVER_CONFIG_FILE));
|
|
10
|
+
if (config === undefined)
|
|
11
|
+
return;
|
|
12
|
+
const notice = await readRemovalNotice(dataDir).catch(() => {
|
|
13
|
+
return;
|
|
14
|
+
});
|
|
15
|
+
return notice !== undefined && endsJoin(notice, config) ? undefined : config;
|
|
16
|
+
}
|
|
17
|
+
var endsJoin = (notice, config) => normalizeOrigin(notice.origin) === normalizeOrigin(config.origin) && notice.binding === config.binding;
|
|
18
|
+
async function readServerConfigAt(path) {
|
|
19
|
+
let text;
|
|
20
|
+
try {
|
|
21
|
+
text = await readFile(path, "utf8");
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error.code === "ENOENT")
|
|
24
|
+
return;
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
let value;
|
|
28
|
+
try {
|
|
29
|
+
value = JSON.parse(text);
|
|
30
|
+
} catch {
|
|
31
|
+
throw new Error(`${path} is not valid JSON — delete it or run \`pinomad leave\``);
|
|
32
|
+
}
|
|
33
|
+
const origin = value?.origin;
|
|
34
|
+
if (typeof origin !== "string" || origin.trim() === "") {
|
|
35
|
+
throw new Error(`${path} is missing a string "origin"`);
|
|
36
|
+
}
|
|
37
|
+
const { binding, username } = value;
|
|
38
|
+
return {
|
|
39
|
+
origin,
|
|
40
|
+
...typeof binding === "string" && binding !== "" ? { binding } : {},
|
|
41
|
+
...typeof username === "string" && username !== "" ? { username } : {}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function writeJsonFile(path, value) {
|
|
45
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
46
|
+
await writeFile(tmp, `${JSON.stringify(value)}
|
|
47
|
+
`, { mode: 384 });
|
|
48
|
+
await rename(tmp, path);
|
|
49
|
+
}
|
|
50
|
+
async function writeServerConfig(dataDir, config) {
|
|
51
|
+
await writeJsonFile(join(dataDir, SERVER_CONFIG_FILE), {
|
|
52
|
+
origin: normalizeOrigin(config.origin),
|
|
53
|
+
binding: randomBytes(16).toString("base64url"),
|
|
54
|
+
...config.username === undefined ? {} : { username: config.username }
|
|
55
|
+
});
|
|
56
|
+
await rm(join(dataDir, REMOVAL_NOTICE_FILE), { force: true });
|
|
57
|
+
}
|
|
58
|
+
async function markRemoved(dataDir, removed, removedAt = Date.now()) {
|
|
59
|
+
await writeJsonFile(join(dataDir, REMOVAL_NOTICE_FILE), {
|
|
60
|
+
origin: normalizeOrigin(removed.origin),
|
|
61
|
+
...removed.binding === undefined ? {} : { binding: removed.binding },
|
|
62
|
+
...removed.username === undefined ? {} : { username: removed.username },
|
|
63
|
+
removedAt
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async function readRemovalNotice(dataDir) {
|
|
67
|
+
const path = join(dataDir, REMOVAL_NOTICE_FILE);
|
|
68
|
+
let text;
|
|
69
|
+
try {
|
|
70
|
+
text = await readFile(path, "utf8");
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error.code === "ENOENT")
|
|
73
|
+
return;
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
let value;
|
|
77
|
+
try {
|
|
78
|
+
value = JSON.parse(text);
|
|
79
|
+
} catch {
|
|
80
|
+
throw new Error(`${path} is not valid JSON — delete it`);
|
|
81
|
+
}
|
|
82
|
+
const { origin, binding, username, removedAt } = value ?? {};
|
|
83
|
+
if (typeof origin !== "string" || typeof removedAt !== "number")
|
|
84
|
+
throw new Error(`${path} is missing "origin" or "removedAt" — delete it`);
|
|
85
|
+
return {
|
|
86
|
+
origin,
|
|
87
|
+
...typeof binding === "string" && binding !== "" ? { binding } : {},
|
|
88
|
+
...typeof username === "string" && username !== "" ? { username } : {},
|
|
89
|
+
removedAt
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async function removeServerConfig(dataDir) {
|
|
93
|
+
await rm(join(dataDir, SERVER_CONFIG_FILE), { force: true });
|
|
94
|
+
await rm(join(dataDir, REMOVAL_NOTICE_FILE), { force: true });
|
|
95
|
+
}
|
|
96
|
+
async function readServerBinding(dataDir) {
|
|
97
|
+
return (await readServerConfig(dataDir))?.binding;
|
|
98
|
+
}
|
|
99
|
+
function resolveRelayOrigin(flag, config) {
|
|
100
|
+
if (flag !== undefined && config !== undefined && normalizeOrigin(flag) !== normalizeOrigin(config.origin)) {
|
|
101
|
+
throw new Error(`--relay ${flag} disagrees with ${SERVER_CONFIG_FILE} (${config.origin}) — remove one`);
|
|
102
|
+
}
|
|
103
|
+
return flag ?? config?.origin;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { REMOVAL_NOTICE_FILE, normalizeOrigin, readServerConfig, writeServerConfig, markRemoved, readRemovalNotice, removeServerConfig, readServerBinding, resolveRelayOrigin };
|
|
@@ -3,17 +3,23 @@ import {
|
|
|
3
3
|
main,
|
|
4
4
|
reachabilityLine,
|
|
5
5
|
restartService,
|
|
6
|
+
serviceStatusJson,
|
|
7
|
+
startService,
|
|
8
|
+
stopService,
|
|
6
9
|
versionLine
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import"./chunk-
|
|
10
|
+
} from "./chunk-wd7aracm.js";
|
|
11
|
+
import"./chunk-4fferbxw.js";
|
|
9
12
|
import"./chunk-kzbzacz9.js";
|
|
10
|
-
import"./chunk-
|
|
13
|
+
import"./chunk-kmzzjv53.js";
|
|
11
14
|
import"./chunk-pqe7q1s7.js";
|
|
12
15
|
import"./chunk-ngf1zatm.js";
|
|
13
|
-
import"./chunk-
|
|
16
|
+
import"./chunk-s0h7c7da.js";
|
|
14
17
|
import"./chunk-df32avw6.js";
|
|
15
18
|
export {
|
|
16
19
|
versionLine,
|
|
20
|
+
stopService,
|
|
21
|
+
startService,
|
|
22
|
+
serviceStatusJson,
|
|
17
23
|
restartService,
|
|
18
24
|
reachabilityLine,
|
|
19
25
|
main
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// apps/host/src/distribution.ts
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
var packagedVersion = "0.
|
|
3
|
+
var packagedVersion = "0.13.0";
|
|
4
4
|
var webRoot = fileURLToPath(new URL(packagedVersion === undefined ? "../../web/dist" : "../web/", import.meta.url));
|
|
5
5
|
var hostEntry = packagedVersion === undefined ? { script: fileURLToPath(new URL("./main.ts", import.meta.url)), args: [] } : { script: fileURLToPath(new URL("./pinomad.js", import.meta.url)), args: ["host"] };
|
|
6
6
|
var commandHint = (name) => packagedVersion === undefined ? `bun run ${name}` : `pinomad ${name}`;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
joinServer,
|
|
4
|
+
main
|
|
5
|
+
} from "./chunk-d9mq5d46.js";
|
|
6
|
+
import"./chunk-7mn38n4f.js";
|
|
7
|
+
import"./chunk-563fnad9.js";
|
|
8
|
+
import"./chunk-t91zt5f0.js";
|
|
9
|
+
import"./chunk-nq57fdnq.js";
|
|
10
|
+
import"./chunk-g3ahp7b9.js";
|
|
11
|
+
import"./chunk-wd7aracm.js";
|
|
12
|
+
import"./chunk-4fferbxw.js";
|
|
13
|
+
import"./chunk-kzbzacz9.js";
|
|
14
|
+
import"./chunk-kmzzjv53.js";
|
|
15
|
+
import"./chunk-pqe7q1s7.js";
|
|
16
|
+
import"./chunk-ngf1zatm.js";
|
|
17
|
+
import"./chunk-s0h7c7da.js";
|
|
18
|
+
import"./chunk-df32avw6.js";
|
|
19
|
+
export {
|
|
20
|
+
main,
|
|
21
|
+
joinServer
|
|
22
|
+
};
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
import {
|
|
3
3
|
restartService,
|
|
4
4
|
serviceManager
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import"./chunk-
|
|
5
|
+
} from "./chunk-wd7aracm.js";
|
|
6
|
+
import"./chunk-4fferbxw.js";
|
|
7
7
|
import"./chunk-kzbzacz9.js";
|
|
8
|
-
import"./chunk-
|
|
8
|
+
import"./chunk-kmzzjv53.js";
|
|
9
9
|
import"./chunk-pqe7q1s7.js";
|
|
10
10
|
import {
|
|
11
11
|
hostAddressOptions
|
|
12
12
|
} from "./chunk-ngf1zatm.js";
|
|
13
13
|
import {
|
|
14
|
+
commandHint,
|
|
14
15
|
globalPrefixOf,
|
|
15
16
|
packageDir,
|
|
16
17
|
packagedVersion
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-s0h7c7da.js";
|
|
18
19
|
import"./chunk-df32avw6.js";
|
|
19
20
|
|
|
20
21
|
// apps/host/src/cli/upgrade.ts
|
|
@@ -34,7 +35,7 @@ function npmBeside(execPath) {
|
|
|
34
35
|
const cli = join(binDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js");
|
|
35
36
|
return existsSync(cli) ? { command: execPath, args: [cli], binDir } : { command: "npm", args: [] };
|
|
36
37
|
}
|
|
37
|
-
var
|
|
38
|
+
var serviceState = () => Promise.resolve().then(() => serviceManager().state()).catch(() => ({ installed: false, stopped: false }));
|
|
38
39
|
async function main(argv, deps = {}) {
|
|
39
40
|
const { values } = parseArgs({
|
|
40
41
|
args: [...argv],
|
|
@@ -75,11 +76,17 @@ async function main(argv, deps = {}) {
|
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
+
const service = await (deps.serviceState ?? serviceState)();
|
|
80
|
+
if (!service.installed) {
|
|
79
81
|
console.log("service not installed; upgrade done, nothing restarted");
|
|
80
82
|
process.exitCode = 0;
|
|
81
83
|
return;
|
|
82
84
|
}
|
|
85
|
+
if (service.stopped) {
|
|
86
|
+
console.log(`service stopped; upgrade done, it stays off until \`${commandHint("service")} start\``);
|
|
87
|
+
process.exitCode = 0;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
83
90
|
(deps.exit ?? process.exit)(await restart({ force: values.force, argv: argv.filter((arg) => arg !== "--force") }));
|
|
84
91
|
}
|
|
85
92
|
if (false) {}
|