@profullstack/qryptchat 0.4.1 → 0.4.2
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/dist/{chunk-7ane8p3w.js → chunk-7mn96363.js} +29 -6
- package/dist/commands.js +1 -1
- package/dist/mcp.js +1 -1
- package/dist/tui.js +0 -4
- package/package.json +1 -1
|
@@ -964,19 +964,28 @@ class QcClient {
|
|
|
964
964
|
await this.refresh();
|
|
965
965
|
return this.session.access_token;
|
|
966
966
|
}
|
|
967
|
-
async
|
|
967
|
+
async reauth(usedToken) {
|
|
968
|
+
if (this.session.access_token === usedToken)
|
|
969
|
+
await this.refresh();
|
|
970
|
+
}
|
|
971
|
+
async request(path, { method = "GET", body, signal, retry = true, throttled = 0 } = {}) {
|
|
972
|
+
const used = await this.token();
|
|
968
973
|
const res = await this.fetch(`${this.base}${path}`, {
|
|
969
974
|
method,
|
|
970
975
|
signal,
|
|
971
976
|
headers: {
|
|
972
|
-
Authorization: `Bearer ${
|
|
977
|
+
Authorization: `Bearer ${used}`,
|
|
973
978
|
...body !== undefined ? { "Content-Type": "application/json" } : {}
|
|
974
979
|
},
|
|
975
980
|
body: body !== undefined ? JSON.stringify(body) : undefined
|
|
976
981
|
});
|
|
977
982
|
if (res.status === 401 && retry) {
|
|
978
|
-
await this.
|
|
979
|
-
return this.request(path, { method, body, signal, retry: false });
|
|
983
|
+
await this.reauth(used);
|
|
984
|
+
return this.request(path, { method, body, signal, retry: false, throttled });
|
|
985
|
+
}
|
|
986
|
+
if (res.status === 429 && throttled < 3) {
|
|
987
|
+
await sleep(retryAfterMs(res, throttled), signal);
|
|
988
|
+
return this.request(path, { method, body, signal, retry, throttled: throttled + 1 });
|
|
980
989
|
}
|
|
981
990
|
const data = await res.json().catch(() => ({}));
|
|
982
991
|
if (!res.ok)
|
|
@@ -1047,21 +1056,31 @@ class QcClient {
|
|
|
1047
1056
|
}
|
|
1048
1057
|
async events(onEvent, { signal, onStatus = () => {} } = {}) {
|
|
1049
1058
|
let delay = 1000;
|
|
1059
|
+
let reauthed = false;
|
|
1050
1060
|
while (!signal?.aborted) {
|
|
1051
1061
|
onStatus("connecting");
|
|
1052
1062
|
try {
|
|
1063
|
+
const used = await this.token();
|
|
1053
1064
|
const res = await this.fetch(`${this.base}/api/events`, {
|
|
1054
|
-
headers: { Authorization: `Bearer ${
|
|
1065
|
+
headers: { Authorization: `Bearer ${used}`, Accept: "text/event-stream" },
|
|
1055
1066
|
signal
|
|
1056
1067
|
});
|
|
1057
1068
|
if (res.status === 401) {
|
|
1058
|
-
|
|
1069
|
+
if (reauthed)
|
|
1070
|
+
throw new QcError("The server refused this session. Run qc login.", 401);
|
|
1071
|
+
reauthed = true;
|
|
1072
|
+
await this.reauth(used);
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
if (res.status === 429) {
|
|
1076
|
+
await sleep(retryAfterMs(res, 2), signal);
|
|
1059
1077
|
continue;
|
|
1060
1078
|
}
|
|
1061
1079
|
if (!res.ok || !res.body)
|
|
1062
1080
|
throw new Error(`HTTP ${res.status}`);
|
|
1063
1081
|
onStatus("live");
|
|
1064
1082
|
delay = 1000;
|
|
1083
|
+
reauthed = false;
|
|
1065
1084
|
await readSse(res.body, onEvent);
|
|
1066
1085
|
} catch (err) {
|
|
1067
1086
|
if (signal?.aborted)
|
|
@@ -1111,6 +1130,10 @@ async function readSse(body, onEvent) {
|
|
|
1111
1130
|
}
|
|
1112
1131
|
}
|
|
1113
1132
|
}
|
|
1133
|
+
function retryAfterMs(res, attempt = 0) {
|
|
1134
|
+
const s = Number(res.headers?.get?.("retry-after"));
|
|
1135
|
+
return Number.isFinite(s) && s > 0 ? Math.min(s, 60) * 1000 : 2000 * 2 ** attempt;
|
|
1136
|
+
}
|
|
1114
1137
|
function sleep(ms, signal) {
|
|
1115
1138
|
return new Promise((resolve) => {
|
|
1116
1139
|
const t = setTimeout(resolve, ms);
|
package/dist/commands.js
CHANGED
package/dist/mcp.js
CHANGED
package/dist/tui.js
CHANGED
|
@@ -243,10 +243,6 @@ async function runTui(client, { initialChat } = {}) {
|
|
|
243
243
|
state.selected = Math.max(0, state.conversations.findIndex((c) => c.id === before));
|
|
244
244
|
}
|
|
245
245
|
redraw();
|
|
246
|
-
for (const c of state.conversations.slice(0, 40)) {
|
|
247
|
-
if (c.id !== state.activeId && !state.messages[c.id])
|
|
248
|
-
await loadMessages(c.id);
|
|
249
|
-
}
|
|
250
246
|
} catch (err) {
|
|
251
247
|
state.loading = false;
|
|
252
248
|
note(err.status === 401 ? "Session ended: run qc login" : `Could not load chats: ${err.message}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/qryptchat",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "qc: qrypt.chat in your terminal. A full-screen end-to-end encrypted chat client (ML-KEM-1024), plus a scriptable CLI and an MCP server.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|