pinomad 0.6.0 → 0.7.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/dist/{chunk-3dnnaz4j.js → chunk-07769pqx.js} +4 -4
- package/dist/{chunk-d5ypmmr7.js → chunk-12kaxggg.js} +2 -2
- package/dist/{chunk-4btj08we.js → chunk-1nyzr0mg.js} +2264 -926
- package/dist/{chunk-ggb1taqy.js → chunk-1t58fh0k.js} +4 -4
- package/dist/{chunk-wqvp1fwh.js → chunk-6ysezfy5.js} +28 -11
- package/dist/{chunk-367n9je8.js → chunk-8yme2wep.js} +1 -1
- package/dist/{chunk-n4tjhcb7.js → chunk-e4ahjbmz.js} +198 -36
- package/dist/{chunk-k2s1hfq5.js → chunk-fbkd73zr.js} +4 -4
- package/dist/{chunk-7s1f4z4g.js → chunk-m4c5gvce.js} +2 -2
- package/dist/{chunk-c8nxym2z.js → chunk-rtwxjb90.js} +1 -1
- package/dist/{chunk-d93kvxvc.js → chunk-sj7rnvh4.js} +114 -5
- package/dist/{chunk-jn7y815x.js → chunk-sz3rzk55.js} +4 -4
- package/dist/pinomad.js +10 -10
- package/package.json +1 -1
- package/web/assets/index-C0rwAo0H.css +1 -0
- package/web/assets/index-DGee2kNU.js +394 -0
- package/web/index.html +2 -2
- package/web/assets/index-C_aU_ZiV.js +0 -383
- package/web/assets/index-DaPcXZPM.css +0 -1
- package/web/assets/montserrat-latin-ext-wght-normal-BsZE-iaG.woff2 +0 -0
- package/web/assets/montserrat-latin-wght-normal-l_AIctKy.woff2 +0 -0
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
main,
|
|
4
4
|
restartService
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-12kaxggg.js";
|
|
6
6
|
import"./chunk-kzbzacz9.js";
|
|
7
|
-
import"./chunk-
|
|
8
|
-
import"./chunk-
|
|
9
|
-
import"./chunk-
|
|
7
|
+
import"./chunk-rtwxjb90.js";
|
|
8
|
+
import"./chunk-sj7rnvh4.js";
|
|
9
|
+
import"./chunk-e4ahjbmz.js";
|
|
10
10
|
import"./chunk-znhn8af7.js";
|
|
11
11
|
import"./chunk-ngf1zatm.js";
|
|
12
12
|
import"./chunk-df32avw6.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
commandHint,
|
|
15
15
|
webRoot
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-rtwxjb90.js";
|
|
17
17
|
import {
|
|
18
18
|
normalizeHostName
|
|
19
19
|
} from "./chunk-znhn8af7.js";
|
|
@@ -402,7 +402,7 @@ async function changePassword(options) {
|
|
|
402
402
|
|
|
403
403
|
// apps/server/src/apns.ts
|
|
404
404
|
import { createPrivateKey, sign } from "node:crypto";
|
|
405
|
-
import { connect } from "node:http2";
|
|
405
|
+
import { connect, constants } from "node:http2";
|
|
406
406
|
var AUTHORITIES = {
|
|
407
407
|
production: "https://api.push.apple.com",
|
|
408
408
|
development: "https://api.sandbox.push.apple.com"
|
|
@@ -471,19 +471,25 @@ function openApns(config) {
|
|
|
471
471
|
state.token = { jwt, issuedAt: now };
|
|
472
472
|
return jwt;
|
|
473
473
|
};
|
|
474
|
+
const dropSession = (state, session) => {
|
|
475
|
+
if (state.session === session)
|
|
476
|
+
state.session = undefined;
|
|
477
|
+
if (!session.destroyed)
|
|
478
|
+
session.destroy();
|
|
479
|
+
};
|
|
480
|
+
const retireSession = (state, session) => {
|
|
481
|
+
if (state.session === session)
|
|
482
|
+
state.session = undefined;
|
|
483
|
+
if (!session.closed && !session.destroyed)
|
|
484
|
+
session.close();
|
|
485
|
+
};
|
|
474
486
|
const sessionFor = (environment, state) => {
|
|
475
487
|
const existing = state.session;
|
|
476
488
|
if (existing !== undefined && !existing.destroyed && !existing.closed)
|
|
477
489
|
return existing;
|
|
478
490
|
const session = connect(state.authority);
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
state.session = undefined;
|
|
482
|
-
if (!session.destroyed)
|
|
483
|
-
session.destroy();
|
|
484
|
-
};
|
|
485
|
-
session.once("goaway", drop);
|
|
486
|
-
session.once("error", drop);
|
|
491
|
+
session.once("goaway", () => dropSession(state, session));
|
|
492
|
+
session.once("error", () => dropSession(state, session));
|
|
487
493
|
session.once("close", () => {
|
|
488
494
|
if (state.session === session)
|
|
489
495
|
state.session = undefined;
|
|
@@ -566,6 +572,7 @@ function openApns(config) {
|
|
|
566
572
|
resolve({ result: "retry", reason: "session unavailable" });
|
|
567
573
|
return;
|
|
568
574
|
}
|
|
575
|
+
let responded = false;
|
|
569
576
|
let status = 0;
|
|
570
577
|
let responseHeaders = {};
|
|
571
578
|
const chunks = [];
|
|
@@ -580,11 +587,16 @@ function openApns(config) {
|
|
|
580
587
|
};
|
|
581
588
|
const timer = setTimeout(() => finish({ result: "retry", reason: "apns timeout" }), REQUEST_TIMEOUT_MS);
|
|
582
589
|
stream.on("response", (headers) => {
|
|
590
|
+
responded = true;
|
|
583
591
|
status = Number(headers[":status"] ?? 0);
|
|
584
592
|
responseHeaders = headers;
|
|
585
593
|
});
|
|
586
594
|
stream.on("data", (chunk) => chunks.push(chunk));
|
|
587
595
|
stream.on("end", () => {
|
|
596
|
+
if (!responded) {
|
|
597
|
+
finish({ result: "retry", reason: "connection closed" });
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
588
600
|
let body2;
|
|
589
601
|
try {
|
|
590
602
|
body2 = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
@@ -593,7 +605,12 @@ function openApns(config) {
|
|
|
593
605
|
}
|
|
594
606
|
finish(classify(request.environment, status, responseHeaders, body2, state));
|
|
595
607
|
});
|
|
596
|
-
stream.on("error", () =>
|
|
608
|
+
stream.on("error", () => {
|
|
609
|
+
const refused = stream.rstCode === constants.NGHTTP2_REFUSED_STREAM;
|
|
610
|
+
finish({ result: "retry", reason: "connection error" });
|
|
611
|
+
if (refused)
|
|
612
|
+
retireSession(state, session);
|
|
613
|
+
});
|
|
597
614
|
stream.on("aborted", () => finish({ result: "retry", reason: "connection aborted" }));
|
|
598
615
|
stream.end(body);
|
|
599
616
|
});
|
|
@@ -14,20 +14,43 @@ var conversationStream = (id) => `conversation:${id}`;
|
|
|
14
14
|
var docStream = (kind, id) => `doc:${kind}:${id}`;
|
|
15
15
|
var UNAUTHORIZED_CLOSE_CODE = 4401;
|
|
16
16
|
var INVALID_FRAME_CLOSE_CODE = 4400;
|
|
17
|
-
var PROTOCOL = { major: 5, minor:
|
|
17
|
+
var PROTOCOL = { major: 5, minor: 19 };
|
|
18
18
|
var CALL_SINCE = {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
addProject: 0,
|
|
20
|
+
removeProject: 0,
|
|
21
21
|
listFolders: 3,
|
|
22
|
+
listFiles: 10,
|
|
23
|
+
listSkills: 13,
|
|
24
|
+
listCommands: 17,
|
|
25
|
+
createConversation: 0,
|
|
26
|
+
archive: 0,
|
|
22
27
|
renameConversation: 4,
|
|
28
|
+
submit: 0,
|
|
29
|
+
withdrawQueued: 14,
|
|
30
|
+
steerQueued: 14,
|
|
31
|
+
abort: 0,
|
|
32
|
+
compact: 0,
|
|
33
|
+
runCommand: 17,
|
|
34
|
+
setModel: 0,
|
|
35
|
+
setThinkingLevel: 0,
|
|
36
|
+
setAgent: 18,
|
|
37
|
+
fork: 0,
|
|
38
|
+
answer: 0,
|
|
39
|
+
changes: 0,
|
|
40
|
+
createPairing: 0,
|
|
41
|
+
revokeDevice: 0,
|
|
42
|
+
logout: 1,
|
|
43
|
+
updateSettings: 2,
|
|
23
44
|
createAgent: 6,
|
|
24
45
|
updateAgent: 6,
|
|
25
46
|
deleteAgent: 6,
|
|
26
47
|
setPushToken: 7,
|
|
27
|
-
|
|
48
|
+
image: 15,
|
|
49
|
+
beginAttachment: 19,
|
|
50
|
+
appendAttachment: 19
|
|
28
51
|
};
|
|
29
52
|
function hostSupportsCall(hostMinor, method) {
|
|
30
|
-
return hostMinor >=
|
|
53
|
+
return hostMinor >= CALL_SINCE[method];
|
|
31
54
|
}
|
|
32
55
|
var FEATURE_SINCE = {
|
|
33
56
|
images: 5,
|
|
@@ -35,7 +58,10 @@ var FEATURE_SINCE = {
|
|
|
35
58
|
apnsPush: 9,
|
|
36
59
|
agentConversations: 10,
|
|
37
60
|
liveBranch: 11,
|
|
38
|
-
hostName: 12
|
|
61
|
+
hostName: 12,
|
|
62
|
+
imageRefs: 15,
|
|
63
|
+
boundSkills: 16,
|
|
64
|
+
attachments: 19
|
|
39
65
|
};
|
|
40
66
|
function hostSupportsFeature(hostMinor, feature) {
|
|
41
67
|
return hostMinor >= FEATURE_SINCE[feature];
|
|
@@ -48,7 +74,8 @@ function parseClientFrame(value) {
|
|
|
48
74
|
if (typeof stream !== "string")
|
|
49
75
|
return { kind: "malformed" };
|
|
50
76
|
if (isStreamName(stream)) {
|
|
51
|
-
|
|
77
|
+
const refs = value.type === "subscribe" && value.images === "ref";
|
|
78
|
+
return { kind: "frame", frame: refs ? { type: "subscribe", stream, images: "ref" } : { type: value.type, stream } };
|
|
52
79
|
}
|
|
53
80
|
const prefix = stream.slice(0, stream.indexOf(":") === -1 ? undefined : stream.indexOf(":"));
|
|
54
81
|
if (STREAM_KINDS.has(prefix))
|
|
@@ -70,31 +97,7 @@ function isStreamName(stream) {
|
|
|
70
97
|
return stream === "tasks" || HOST_STREAM_NAMES.includes(stream) || /^(?:conversation:|doc:.+:)[1-9]\d*$/.test(stream);
|
|
71
98
|
}
|
|
72
99
|
var isCallMethod = (method) => CALL_METHODS.includes(method);
|
|
73
|
-
var CALL_METHODS =
|
|
74
|
-
"addProject",
|
|
75
|
-
"removeProject",
|
|
76
|
-
"listFolders",
|
|
77
|
-
"createConversation",
|
|
78
|
-
"archive",
|
|
79
|
-
"renameConversation",
|
|
80
|
-
"submit",
|
|
81
|
-
"abort",
|
|
82
|
-
"compact",
|
|
83
|
-
"setModel",
|
|
84
|
-
"setThinkingLevel",
|
|
85
|
-
"fork",
|
|
86
|
-
"answer",
|
|
87
|
-
"changes",
|
|
88
|
-
"createPairing",
|
|
89
|
-
"revokeDevice",
|
|
90
|
-
"logout",
|
|
91
|
-
"updateSettings",
|
|
92
|
-
"createAgent",
|
|
93
|
-
"updateAgent",
|
|
94
|
-
"deleteAgent",
|
|
95
|
-
"setPushToken",
|
|
96
|
-
"listFiles"
|
|
97
|
-
];
|
|
100
|
+
var CALL_METHODS = Object.keys(CALL_SINCE);
|
|
98
101
|
var SETTING_VALIDATORS = {
|
|
99
102
|
defaultModel: (value) => value === null || record(value) && nonempty(value.provider) && nonempty(value.modelId),
|
|
100
103
|
defaultThinkingLevel: (value) => value === null || isThinkingLevel(value),
|
|
@@ -105,17 +108,29 @@ var SETTING_VALIDATORS = {
|
|
|
105
108
|
};
|
|
106
109
|
function validCallArgs(method, args) {
|
|
107
110
|
const conversationId = () => typeof args.conversationId === "number" && Number.isSafeInteger(args.conversationId) && args.conversationId >= 1;
|
|
108
|
-
const
|
|
111
|
+
const submissionId = () => typeof args.submissionId === "number" && Number.isSafeInteger(args.submissionId) && args.submissionId >= 1;
|
|
112
|
+
const images = () => args.images === undefined || Array.isArray(args.images) && args.images.every((image) => record(image) && ("data" in image ? typeof image.data === "string" && typeof image.mimeType === "string" : nonempty(image.ref)));
|
|
113
|
+
const skills = () => args.skills === undefined || Array.isArray(args.skills) && args.skills.every(nonempty);
|
|
114
|
+
const attachments = () => args.attachments === undefined || Array.isArray(args.attachments) && args.attachments.every(nonempty);
|
|
109
115
|
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");
|
|
110
116
|
switch (method) {
|
|
111
117
|
case "submit":
|
|
112
|
-
return conversationId() && typeof args.text === "string" && (args.whenBusy === "steer" || args.whenBusy === "followUp") && nonempty(args.requestId) && images();
|
|
118
|
+
return conversationId() && typeof args.text === "string" && (args.whenBusy === "steer" || args.whenBusy === "followUp") && nonempty(args.requestId) && images() && skills() && attachments();
|
|
119
|
+
case "withdrawQueued":
|
|
120
|
+
case "steerQueued":
|
|
121
|
+
return conversationId() && submissionId();
|
|
113
122
|
case "abort":
|
|
114
123
|
return conversationId();
|
|
115
124
|
case "setThinkingLevel":
|
|
116
125
|
return conversationId() && nonempty(args.level);
|
|
126
|
+
case "setAgent":
|
|
127
|
+
return conversationId() && (args.agent === null || nonempty(args.agent));
|
|
117
128
|
case "compact":
|
|
118
129
|
return conversationId() && (args.instructions === undefined || typeof args.instructions === "string");
|
|
130
|
+
case "listCommands":
|
|
131
|
+
return conversationId();
|
|
132
|
+
case "runCommand":
|
|
133
|
+
return conversationId() && nonempty(args.name) && (args.args === undefined || typeof args.args === "string");
|
|
119
134
|
case "setModel":
|
|
120
135
|
return conversationId() && record(args.model) && nonempty(args.model.provider) && nonempty(args.model.modelId);
|
|
121
136
|
case "fork":
|
|
@@ -124,15 +139,23 @@ function validCallArgs(method, args) {
|
|
|
124
139
|
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"));
|
|
125
140
|
case "changes":
|
|
126
141
|
return conversationId();
|
|
142
|
+
case "image":
|
|
143
|
+
return nonempty(args.ref);
|
|
144
|
+
case "beginAttachment":
|
|
145
|
+
return nonempty(args.name) && typeof args.size === "number" && Number.isSafeInteger(args.size) && args.size >= 0;
|
|
146
|
+
case "appendAttachment":
|
|
147
|
+
return nonempty(args.attachmentId) && typeof args.offset === "number" && Number.isSafeInteger(args.offset) && args.offset >= 0 && typeof args.data === "string";
|
|
127
148
|
case "addProject":
|
|
128
149
|
case "removeProject":
|
|
129
150
|
return nonempty(args.path);
|
|
130
151
|
case "listFolders":
|
|
131
152
|
return args.path === undefined || nonempty(args.path);
|
|
132
153
|
case "createConversation":
|
|
133
|
-
return record(args.home) && (args.home.kind === "chat" || args.home.kind === "project" && nonempty(args.home.path)) && typeof args.text === "string" && (nonempty(args.text) || Array.isArray(args.images) && args.images.length > 0) && nonempty(args.requestId) && images() && (args.checkout === undefined || args.checkout === "worktree" || args.checkout === "project") && (args.model === undefined || record(args.model) && nonempty(args.model.provider) && nonempty(args.model.modelId)) && (args.thinkingLevel === undefined || nonempty(args.thinkingLevel)) && (args.agent === undefined || nonempty(args.agent));
|
|
154
|
+
return record(args.home) && (args.home.kind === "chat" || args.home.kind === "project" && nonempty(args.home.path)) && typeof args.text === "string" && (nonempty(args.text) || Array.isArray(args.images) && args.images.length > 0 || Array.isArray(args.attachments) && args.attachments.length > 0) && nonempty(args.requestId) && images() && skills() && attachments() && (args.checkout === undefined || args.checkout === "worktree" || args.checkout === "project") && (args.model === undefined || record(args.model) && nonempty(args.model.provider) && nonempty(args.model.modelId)) && (args.thinkingLevel === undefined || nonempty(args.thinkingLevel)) && (args.agent === undefined || nonempty(args.agent));
|
|
134
155
|
case "listFiles":
|
|
135
156
|
return typeof args.query === "string" && record(args.scope) && (args.scope.kind === "conversation" && typeof args.scope.conversationId === "number" && Number.isSafeInteger(args.scope.conversationId) && args.scope.conversationId >= 1 || args.scope.kind === "project" && nonempty(args.scope.path) && (args.scope.checkout === "worktree" || args.scope.checkout === "project"));
|
|
157
|
+
case "listSkills":
|
|
158
|
+
return record(args.scope) && (args.scope.kind === "conversation" && typeof args.scope.conversationId === "number" && Number.isSafeInteger(args.scope.conversationId) && args.scope.conversationId >= 1 || args.scope.kind === "project" && nonempty(args.scope.path) && (args.scope.checkout === "worktree" || args.scope.checkout === "project") || args.scope.kind === "chat");
|
|
136
159
|
case "archive":
|
|
137
160
|
return conversationId() && typeof args.archived === "boolean";
|
|
138
161
|
case "renameConversation":
|
|
@@ -161,6 +184,145 @@ function nonempty(value) {
|
|
|
161
184
|
return typeof value === "string" && value.length > 0;
|
|
162
185
|
}
|
|
163
186
|
|
|
187
|
+
// packages/protocol/src/attachments.ts
|
|
188
|
+
var MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
189
|
+
var MAX_ATTACHMENTS_PER_MESSAGE = 10;
|
|
190
|
+
var ATTACHMENT_CHUNK_BYTES = 512 * 1024;
|
|
191
|
+
var MAX_PENDING_ATTACHMENTS = 20;
|
|
192
|
+
var MAX_PENDING_ATTACHMENT_BYTES = 200 * 1024 * 1024;
|
|
193
|
+
var ATTACHMENT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
194
|
+
var MAX_ATTACHMENT_NAME_LENGTH = 255;
|
|
195
|
+
var ATTACHMENT_ID_PATTERN = /^[A-Za-z0-9_-]{22}$/;
|
|
196
|
+
function isAttachmentId(value) {
|
|
197
|
+
return ATTACHMENT_ID_PATTERN.test(value);
|
|
198
|
+
}
|
|
199
|
+
var ATTACHMENTS_OPEN = '<attachments v="1">';
|
|
200
|
+
var ATTACHMENTS_INSTRUCTION = "The user attached these files. They are read-only originals on this machine: read them with your tools when relevant, and copy one into the working directory before changing it.";
|
|
201
|
+
var ATTACHMENTS_CLOSE = "</attachments>";
|
|
202
|
+
var BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
203
|
+
function base64DecodedLength(data) {
|
|
204
|
+
if (data.length % 4 !== 0 || !BASE64.test(data))
|
|
205
|
+
return;
|
|
206
|
+
const padding = data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0;
|
|
207
|
+
return data.length * 3 / 4 - padding;
|
|
208
|
+
}
|
|
209
|
+
function attachmentBeginProblem(name, size) {
|
|
210
|
+
if (name.trim() === "")
|
|
211
|
+
return "Attachment name cannot be empty";
|
|
212
|
+
if (!Number.isSafeInteger(size) || size < 0)
|
|
213
|
+
return "Attachment size must be a non-negative integer";
|
|
214
|
+
if (size > MAX_ATTACHMENT_BYTES)
|
|
215
|
+
return `Attachment is larger than ${MAX_ATTACHMENT_BYTES / (1024 * 1024)} MB`;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
function attachmentChunkProblem(data) {
|
|
219
|
+
const size = base64DecodedLength(data);
|
|
220
|
+
if (size === undefined)
|
|
221
|
+
return "Attachment chunk is not valid base64";
|
|
222
|
+
if (size > ATTACHMENT_CHUNK_BYTES)
|
|
223
|
+
return `Attachment chunk is larger than ${ATTACHMENT_CHUNK_BYTES / 1024} KiB`;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
function xmlAttribute(value) {
|
|
227
|
+
let out = "";
|
|
228
|
+
for (let i = 0;i < value.length; i++) {
|
|
229
|
+
const unit = value.charCodeAt(i);
|
|
230
|
+
if (unit === 38)
|
|
231
|
+
out += "&";
|
|
232
|
+
else if (unit === 60)
|
|
233
|
+
out += "<";
|
|
234
|
+
else if (unit === 62)
|
|
235
|
+
out += ">";
|
|
236
|
+
else if (unit === 34)
|
|
237
|
+
out += """;
|
|
238
|
+
else if (unit < 32 || unit === 127)
|
|
239
|
+
out += `&#x${unit.toString(16)};`;
|
|
240
|
+
else
|
|
241
|
+
out += value[i];
|
|
242
|
+
}
|
|
243
|
+
return out;
|
|
244
|
+
}
|
|
245
|
+
function attachmentBlock(files) {
|
|
246
|
+
const lines = [
|
|
247
|
+
ATTACHMENTS_OPEN,
|
|
248
|
+
ATTACHMENTS_INSTRUCTION,
|
|
249
|
+
...files.map((file) => `<file id="${xmlAttribute(file.id)}" name="${xmlAttribute(file.name)}" path="${xmlAttribute(file.path)}" size="${file.size}"/>`),
|
|
250
|
+
ATTACHMENTS_CLOSE
|
|
251
|
+
];
|
|
252
|
+
return lines.join(`
|
|
253
|
+
`);
|
|
254
|
+
}
|
|
255
|
+
var FILE_OPEN = '<file id="';
|
|
256
|
+
var FILE_NAME = '" name="';
|
|
257
|
+
var FILE_PATH = '" path="';
|
|
258
|
+
var FILE_SIZE = '" size="';
|
|
259
|
+
var FILE_END = '"/>';
|
|
260
|
+
var SIZE = /^(?:0|[1-9][0-9]*)$/;
|
|
261
|
+
function decodeXmlAttribute(value) {
|
|
262
|
+
return value.replace(/&(amp|lt|gt|quot|apos|#x[0-9A-Fa-f]+|#[0-9]+);/g, (entity, body) => {
|
|
263
|
+
if (body === "amp")
|
|
264
|
+
return "&";
|
|
265
|
+
if (body === "lt")
|
|
266
|
+
return "<";
|
|
267
|
+
if (body === "gt")
|
|
268
|
+
return ">";
|
|
269
|
+
if (body === "quot")
|
|
270
|
+
return '"';
|
|
271
|
+
if (body === "apos")
|
|
272
|
+
return "'";
|
|
273
|
+
const code = body.startsWith("#x") ? parseInt(body.slice(2), 16) : parseInt(body.slice(1), 10);
|
|
274
|
+
return code >= 0 && code <= 1114111 ? String.fromCodePoint(code) : entity;
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function quoted(text, at, marker) {
|
|
278
|
+
if (!text.startsWith(marker, at))
|
|
279
|
+
return;
|
|
280
|
+
const start = at + marker.length;
|
|
281
|
+
const end = text.indexOf('"', start);
|
|
282
|
+
if (end === -1)
|
|
283
|
+
return;
|
|
284
|
+
return { value: text.slice(start, end), next: end };
|
|
285
|
+
}
|
|
286
|
+
function parseFileLine(line) {
|
|
287
|
+
const id = quoted(line, 0, FILE_OPEN);
|
|
288
|
+
if (id === undefined)
|
|
289
|
+
return;
|
|
290
|
+
const name = quoted(line, id.next, FILE_NAME);
|
|
291
|
+
if (name === undefined)
|
|
292
|
+
return;
|
|
293
|
+
const path = quoted(line, name.next, FILE_PATH);
|
|
294
|
+
if (path === undefined)
|
|
295
|
+
return;
|
|
296
|
+
const size = quoted(line, path.next, FILE_SIZE);
|
|
297
|
+
if (size === undefined || !line.startsWith(FILE_END, size.next) || size.next + FILE_END.length !== line.length) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (!isAttachmentId(id.value) || !SIZE.test(size.value))
|
|
301
|
+
return;
|
|
302
|
+
const bytes = Number(size.value);
|
|
303
|
+
if (!Number.isSafeInteger(bytes))
|
|
304
|
+
return;
|
|
305
|
+
return { id: id.value, name: decodeXmlAttribute(name.value), size: bytes };
|
|
306
|
+
}
|
|
307
|
+
function parseAttachmentBlock(text) {
|
|
308
|
+
if (!text.startsWith(ATTACHMENTS_OPEN + `
|
|
309
|
+
`) || !text.endsWith(`
|
|
310
|
+
` + ATTACHMENTS_CLOSE))
|
|
311
|
+
return;
|
|
312
|
+
const lines = text.slice(ATTACHMENTS_OPEN.length + 1, -(ATTACHMENTS_CLOSE.length + 1)).split(`
|
|
313
|
+
`);
|
|
314
|
+
if (lines[0] !== ATTACHMENTS_INSTRUCTION || lines.length < 2)
|
|
315
|
+
return;
|
|
316
|
+
const files = [];
|
|
317
|
+
for (const line of lines.slice(1)) {
|
|
318
|
+
const file = parseFileLine(line);
|
|
319
|
+
if (file === undefined)
|
|
320
|
+
return;
|
|
321
|
+
files.push(file);
|
|
322
|
+
}
|
|
323
|
+
return files;
|
|
324
|
+
}
|
|
325
|
+
|
|
164
326
|
// packages/protocol/src/organization.ts
|
|
165
327
|
function organize(index, summaries) {
|
|
166
328
|
const summaryById = new Map(summaries.map((summary) => [summary.id, summary]));
|
|
@@ -254,4 +416,4 @@ function homeOf(index, summaries, id) {
|
|
|
254
416
|
return;
|
|
255
417
|
}
|
|
256
418
|
|
|
257
|
-
export { HOST_STREAM_NAMES, hostStreams, conversationStream, docStream, UNAUTHORIZED_CLOSE_CODE, INVALID_FRAME_CLOSE_CODE, PROTOCOL, hostSupportsCall, hostSupportsFeature, parseClientFrame, organize, checkoutOf, homeOf };
|
|
419
|
+
export { 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 };
|
|
@@ -22,14 +22,14 @@ import {
|
|
|
22
22
|
restartService,
|
|
23
23
|
serviceManager,
|
|
24
24
|
withoutRelayArgs
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-12kaxggg.js";
|
|
26
26
|
import"./chunk-kzbzacz9.js";
|
|
27
27
|
import {
|
|
28
28
|
commandHint,
|
|
29
29
|
hostEntry
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import"./chunk-
|
|
32
|
-
import"./chunk-
|
|
30
|
+
} from "./chunk-rtwxjb90.js";
|
|
31
|
+
import"./chunk-sj7rnvh4.js";
|
|
32
|
+
import"./chunk-e4ahjbmz.js";
|
|
33
33
|
import {
|
|
34
34
|
cleanHostName,
|
|
35
35
|
normalizeHostName
|
|
@@ -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.7.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}`;
|