@sideboard-ai/core 0.1.288 → 0.1.289
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/{agents-GZLTMGSH.js → agents-4BBCKITL.js} +4 -4
- package/dist/{agents-UQMHFZSM.js → agents-XAKSP653.js} +4 -4
- package/dist/{chunk-HNB2HTCV.js → chunk-2IXKTAIT.js} +1 -1
- package/dist/{chunk-3W5SL5EW.js → chunk-5HPMKLJ7.js} +1 -1
- package/dist/{chunk-WW5XGEMY.js → chunk-C546EOEF.js} +12 -12
- package/dist/{chunk-442O6OXM.js → chunk-EBGJXOXT.js} +11 -11
- package/dist/{chunk-4NM72HJZ.js → chunk-G74TSBJ3.js} +4 -4
- package/dist/{chunk-WQSIUZEB.js → chunk-GBAACE3C.js} +4 -4
- package/dist/{chunk-2N77CLRQ.js → chunk-LUQ7MIVD.js} +3 -3
- package/dist/{chunk-IA4MPG7F.js → chunk-O4324MXE.js} +2 -2
- package/dist/{chunk-DBOFDEQ7.js → chunk-V3BSO2O6.js} +2 -2
- package/dist/{chunk-6NVQNTJO.js → chunk-VNCPRMIK.js} +3 -3
- package/dist/{conductor-MCU63Z5U.js → conductor-5MNGC25D.js} +4 -4
- package/dist/{conductor-ZLYZVIAV.js → conductor-UFJXJPTF.js} +4 -4
- package/dist/{coordinator-prompt-KHCXXDRO.js → coordinator-prompt-5Q66Y5KW.js} +3 -3
- package/dist/{coordinator-prompt-UV6THLMD.js → coordinator-prompt-BYPEW6DE.js} +3 -3
- package/dist/{global-workspace-GDHZSFP6.js → global-workspace-BTH2YGDZ.js} +3 -3
- package/dist/{global-workspace-AXTSYVAE.js → global-workspace-YKOYXSB2.js} +3 -3
- package/dist/index.cjs +149 -49
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +132 -32
- package/dist/mcp/run-stdio.js +6 -6
- package/dist/{orchestrator-SDH6W6ZL.js → orchestrator-IG4VU7MT.js} +6 -6
- package/dist/{orchestrator-5ZBHR6BJ.js → orchestrator-MKF3YBNK.js} +6 -6
- package/dist/{thread-store-7XBOUQ5K.js → thread-store-DPKESDFR.js} +1 -1
- package/dist/{thread-store-ZQZDREVH.js → thread-store-X6S2GIR5.js} +1 -1
- package/dist/{workspaces-Q2R2XGO3.js → workspaces-ELO2YVTU.js} +3 -3
- package/dist/{workspaces-L2UR4KC2.js → workspaces-RFD6I4FM.js} +3 -3
- package/dist/{worktree-2GOK4VYT.js → worktree-ADVQ6X6C.js} +2 -2
- package/dist/{worktree-YEUTJ7MZ.js → worktree-TN7DZDJZ.js} +2 -2
- package/package.json +1 -1
- /package/dist/{chunk-N5UGX3JL.js → chunk-QB5MDOHL.js} +0 -0
- /package/dist/{chunk-JPH7PYSK.js → chunk-YRXV3E7J.js} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1160,9 +1160,9 @@ function sumOptional(a, b) {
|
|
|
1160
1160
|
function fromInclusiveInputUsage(opts) {
|
|
1161
1161
|
const totalInput = Number(opts.inputTokens) || 0;
|
|
1162
1162
|
const outputTokens = Number(opts.outputTokens) || 0;
|
|
1163
|
-
const
|
|
1163
|
+
const cached2 = Number(opts.cachedInputTokens) || 0;
|
|
1164
1164
|
if (!totalInput && !outputTokens) return null;
|
|
1165
|
-
const cacheReadTokens =
|
|
1165
|
+
const cacheReadTokens = cached2 > 0 ? Math.min(cached2, totalInput) : 0;
|
|
1166
1166
|
return {
|
|
1167
1167
|
inputTokens: Math.max(0, totalInput - cacheReadTokens),
|
|
1168
1168
|
outputTokens,
|
|
@@ -4702,8 +4702,8 @@ function readThread(id) {
|
|
|
4702
4702
|
return null;
|
|
4703
4703
|
}
|
|
4704
4704
|
const cache2 = cacheForDir();
|
|
4705
|
-
const
|
|
4706
|
-
if (
|
|
4705
|
+
const cached2 = cache2.byId.get(id);
|
|
4706
|
+
if (cached2 && cache2.mtimeMs.get(id) === mtimeMs) return cached2;
|
|
4707
4707
|
const raw = (0, import_node_fs12.readFileSync)(path2, "utf8");
|
|
4708
4708
|
const thread = normalizeThread(JSON.parse(raw));
|
|
4709
4709
|
rememberThread(thread, mtimeMs);
|
|
@@ -6922,15 +6922,15 @@ function loadFromDisk(threadId) {
|
|
|
6922
6922
|
}
|
|
6923
6923
|
}
|
|
6924
6924
|
function memFor(threadId) {
|
|
6925
|
-
const
|
|
6926
|
-
if (
|
|
6925
|
+
const cached2 = memory.get(threadId);
|
|
6926
|
+
if (cached2) return cached2;
|
|
6927
6927
|
const mem = fromSnapshot(loadFromDisk(threadId) ?? emptySetupLog());
|
|
6928
6928
|
memory.set(threadId, mem);
|
|
6929
6929
|
return mem;
|
|
6930
6930
|
}
|
|
6931
6931
|
function readSetupLog(threadId) {
|
|
6932
|
-
const
|
|
6933
|
-
if (
|
|
6932
|
+
const cached2 = memory.get(threadId);
|
|
6933
|
+
if (cached2) return materialize(cached2);
|
|
6934
6934
|
const disk = loadFromDisk(threadId);
|
|
6935
6935
|
if (disk) {
|
|
6936
6936
|
memory.set(threadId, fromSnapshot(disk));
|
|
@@ -7076,15 +7076,15 @@ function loadFromDisk2(key) {
|
|
|
7076
7076
|
}
|
|
7077
7077
|
}
|
|
7078
7078
|
function memFor2(key) {
|
|
7079
|
-
const
|
|
7080
|
-
if (
|
|
7079
|
+
const cached2 = memory2.get(key);
|
|
7080
|
+
if (cached2) return cached2;
|
|
7081
7081
|
const mem = fromSnapshot2(loadFromDisk2(key) ?? emptyRunLog());
|
|
7082
7082
|
memory2.set(key, mem);
|
|
7083
7083
|
return mem;
|
|
7084
7084
|
}
|
|
7085
7085
|
function readRunLog(key) {
|
|
7086
|
-
const
|
|
7087
|
-
if (
|
|
7086
|
+
const cached2 = memory2.get(key);
|
|
7087
|
+
if (cached2) return materialize2(cached2);
|
|
7088
7088
|
const disk = loadFromDisk2(key);
|
|
7089
7089
|
if (disk) {
|
|
7090
7090
|
memory2.set(key, fromSnapshot2(disk));
|
|
@@ -15128,8 +15128,8 @@ var init_claude = __esm({
|
|
|
15128
15128
|
return { type: "stdout", data: line };
|
|
15129
15129
|
}
|
|
15130
15130
|
},
|
|
15131
|
-
async resolveSessionId(_worktreePath,
|
|
15132
|
-
return
|
|
15131
|
+
async resolveSessionId(_worktreePath, cached2) {
|
|
15132
|
+
return cached2;
|
|
15133
15133
|
},
|
|
15134
15134
|
async buildAttach(thread) {
|
|
15135
15135
|
const claude = resolveClaudeExecutable();
|
|
@@ -15513,8 +15513,8 @@ var init_codex = __esm({
|
|
|
15513
15513
|
return { type: "stdout", data: line };
|
|
15514
15514
|
}
|
|
15515
15515
|
},
|
|
15516
|
-
async resolveSessionId(_worktreePath,
|
|
15517
|
-
return
|
|
15516
|
+
async resolveSessionId(_worktreePath, cached2) {
|
|
15517
|
+
return cached2;
|
|
15518
15518
|
},
|
|
15519
15519
|
async buildAttach(thread) {
|
|
15520
15520
|
const codex = resolveAgentExecutable("codex");
|
|
@@ -16150,8 +16150,8 @@ var init_cursor = __esm({
|
|
|
16150
16150
|
parseEvent(line) {
|
|
16151
16151
|
return parseCursorRunnerLine(line);
|
|
16152
16152
|
},
|
|
16153
|
-
async resolveSessionId(_worktreePath,
|
|
16154
|
-
return
|
|
16153
|
+
async resolveSessionId(_worktreePath, cached2) {
|
|
16154
|
+
return cached2;
|
|
16155
16155
|
},
|
|
16156
16156
|
async buildAttach(thread) {
|
|
16157
16157
|
const which = await run("which", ["cursor"], { reject: false });
|
|
@@ -16633,8 +16633,8 @@ var init_opencode = __esm({
|
|
|
16633
16633
|
return { type: "stdout", data: line };
|
|
16634
16634
|
}
|
|
16635
16635
|
},
|
|
16636
|
-
async resolveSessionId(worktreePath,
|
|
16637
|
-
const cachedId =
|
|
16636
|
+
async resolveSessionId(worktreePath, cached2) {
|
|
16637
|
+
const cachedId = cached2?.trim() || null;
|
|
16638
16638
|
const listed = await run(
|
|
16639
16639
|
resolveAgentExecutable("opencode"),
|
|
16640
16640
|
["session", "list", "--format", "json"],
|
|
@@ -16961,7 +16961,7 @@ function numberOrUndef(value) {
|
|
|
16961
16961
|
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
16962
16962
|
return value;
|
|
16963
16963
|
}
|
|
16964
|
-
function parseClaudeUsagePayload(raw,
|
|
16964
|
+
function parseClaudeUsagePayload(raw, fetchedAt2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
16965
16965
|
if (!raw || typeof raw !== "object") return null;
|
|
16966
16966
|
const obj = raw;
|
|
16967
16967
|
const source = obj.rate_limits && typeof obj.rate_limits === "object" ? obj.rate_limits : obj;
|
|
@@ -16975,7 +16975,7 @@ function parseClaudeUsagePayload(raw, fetchedAt = (/* @__PURE__ */ new Date()).t
|
|
|
16975
16975
|
return {
|
|
16976
16976
|
windows,
|
|
16977
16977
|
...extra ? { extraUsage: extra } : {},
|
|
16978
|
-
fetchedAt
|
|
16978
|
+
fetchedAt: fetchedAt2
|
|
16979
16979
|
};
|
|
16980
16980
|
}
|
|
16981
16981
|
function hottestClaudeWindow(usage) {
|
|
@@ -17018,15 +17018,15 @@ function formatClaudeUsageResetClock(resetsAt) {
|
|
|
17018
17018
|
return at.toISOString();
|
|
17019
17019
|
}
|
|
17020
17020
|
}
|
|
17021
|
-
function formatClaudeUsageFetchedAt(
|
|
17022
|
-
const at = new Date(
|
|
17021
|
+
function formatClaudeUsageFetchedAt(fetchedAt2, now = /* @__PURE__ */ new Date()) {
|
|
17022
|
+
const at = new Date(fetchedAt2);
|
|
17023
17023
|
if (Number.isNaN(at.getTime())) return "";
|
|
17024
17024
|
const minutes = Math.max(0, Math.round((now.getTime() - at.getTime()) / 6e4));
|
|
17025
17025
|
if (minutes < 1) return "Updated just now";
|
|
17026
17026
|
if (minutes < 60) return `Updated ${minutes}m ago`;
|
|
17027
17027
|
const hours = Math.round(minutes / 60);
|
|
17028
17028
|
if (hours < 36) return `Updated ${hours}h ago`;
|
|
17029
|
-
return `Updated ${formatClaudeUsageResetClock(
|
|
17029
|
+
return `Updated ${formatClaudeUsageResetClock(fetchedAt2)}`;
|
|
17030
17030
|
}
|
|
17031
17031
|
function formatClaudeExtraUsageDetail(extra) {
|
|
17032
17032
|
if (!extra.enabled) return "Extra usage off";
|
|
@@ -36106,15 +36106,15 @@ async function getHomeBoardInputs(workspaces, opts) {
|
|
|
36106
36106
|
}
|
|
36107
36107
|
const promise = (async () => {
|
|
36108
36108
|
const inputs = await loadHomeBoardInputs(workspaces);
|
|
36109
|
-
const
|
|
36109
|
+
const fetchedAt2 = opts?.now ?? Date.now();
|
|
36110
36110
|
const pins = syncBoardPins(listBoardPins(), inputs.issues, inputs.prs);
|
|
36111
36111
|
replaceBoardPins(pins);
|
|
36112
|
-
const loaded = { ...inputs, fetchedAt, fromCache: false, pins };
|
|
36112
|
+
const loaded = { ...inputs, fetchedAt: fetchedAt2, fromCache: false, pins };
|
|
36113
36113
|
if (shouldCacheHomeBoardInputs(inputs)) {
|
|
36114
36114
|
const entry = {
|
|
36115
36115
|
version: CACHE_VERSION,
|
|
36116
36116
|
workspaceKey: key,
|
|
36117
|
-
fetchedAt,
|
|
36117
|
+
fetchedAt: fetchedAt2,
|
|
36118
36118
|
inputs
|
|
36119
36119
|
};
|
|
36120
36120
|
memory3 = entry;
|
|
@@ -39883,14 +39883,46 @@ var RemoteHub = class {
|
|
|
39883
39883
|
this.codes.delete(code);
|
|
39884
39884
|
this.attachPhone(socket, host);
|
|
39885
39885
|
}
|
|
39886
|
+
/** In-memory session, with the live Mac's label when that socket is up. */
|
|
39887
|
+
memorySession(sessionToken) {
|
|
39888
|
+
const cached2 = this.phonesByToken.get(sessionToken);
|
|
39889
|
+
if (!cached2) return null;
|
|
39890
|
+
const live = this.hosts.get(cached2.deviceId);
|
|
39891
|
+
const remembered = this.remembered.get(cached2.deviceId);
|
|
39892
|
+
const current = live?.sessionToken ?? remembered?.sessionToken ?? null;
|
|
39893
|
+
if (current && current !== sessionToken) {
|
|
39894
|
+
this.phonesByToken.delete(sessionToken);
|
|
39895
|
+
return null;
|
|
39896
|
+
}
|
|
39897
|
+
return {
|
|
39898
|
+
deviceId: cached2.deviceId,
|
|
39899
|
+
deviceLabel: live?.deviceLabel || remembered?.deviceLabel || cached2.deviceLabel
|
|
39900
|
+
};
|
|
39901
|
+
}
|
|
39902
|
+
knownSession(sessionToken) {
|
|
39903
|
+
const cached2 = this.memorySession(sessionToken);
|
|
39904
|
+
if (cached2) return cached2;
|
|
39905
|
+
const stored = this.opts.phoneSessions?.find(sessionToken) ?? null;
|
|
39906
|
+
if (!stored) return null;
|
|
39907
|
+
const live = this.hosts.get(stored.deviceId);
|
|
39908
|
+
const remembered = this.remembered.get(stored.deviceId);
|
|
39909
|
+
const current = live?.sessionToken ?? remembered?.sessionToken ?? null;
|
|
39910
|
+
if (current && current !== sessionToken) return null;
|
|
39911
|
+
this.phonesByToken.set(sessionToken, stored);
|
|
39912
|
+
if (remembered && !remembered.sessionToken) remembered.sessionToken = sessionToken;
|
|
39913
|
+
if (live && !live.sessionToken) live.sessionToken = sessionToken;
|
|
39914
|
+
return {
|
|
39915
|
+
deviceId: stored.deviceId,
|
|
39916
|
+
deviceLabel: live?.deviceLabel || remembered?.deviceLabel || stored.deviceLabel
|
|
39917
|
+
};
|
|
39918
|
+
}
|
|
39886
39919
|
resumePhone(socket, sessionToken) {
|
|
39887
|
-
const
|
|
39888
|
-
|
|
39889
|
-
if (!deviceId || !remembered || remembered.sessionToken !== sessionToken) {
|
|
39920
|
+
const known = this.knownSession(sessionToken);
|
|
39921
|
+
if (!known) {
|
|
39890
39922
|
send2(socket, { type: "error", message: "phone session expired \u2014 pair again" });
|
|
39891
39923
|
return;
|
|
39892
39924
|
}
|
|
39893
|
-
const host = this.hosts.get(deviceId);
|
|
39925
|
+
const host = this.hosts.get(known.deviceId);
|
|
39894
39926
|
if (!host) {
|
|
39895
39927
|
send2(socket, { type: "host_offline" });
|
|
39896
39928
|
return;
|
|
@@ -39899,17 +39931,13 @@ var RemoteHub = class {
|
|
|
39899
39931
|
}
|
|
39900
39932
|
listHosts(socket, sessionTokens) {
|
|
39901
39933
|
const hosts = sessionTokens.map((sessionToken) => {
|
|
39902
|
-
const
|
|
39903
|
-
|
|
39904
|
-
const
|
|
39905
|
-
if (!valid || !deviceId || !remembered) {
|
|
39906
|
-
return { sessionToken, deviceId: "", deviceLabel: "", online: false };
|
|
39907
|
-
}
|
|
39908
|
-
const host = this.hosts.get(deviceId);
|
|
39934
|
+
const known = this.knownSession(sessionToken);
|
|
39935
|
+
if (!known) return { sessionToken, deviceId: "", deviceLabel: "", online: false };
|
|
39936
|
+
const host = this.hosts.get(known.deviceId);
|
|
39909
39937
|
return {
|
|
39910
39938
|
sessionToken,
|
|
39911
|
-
deviceId,
|
|
39912
|
-
deviceLabel: host?.deviceLabel ||
|
|
39939
|
+
deviceId: known.deviceId,
|
|
39940
|
+
deviceLabel: host?.deviceLabel || known.deviceLabel,
|
|
39913
39941
|
online: Boolean(host)
|
|
39914
39942
|
};
|
|
39915
39943
|
});
|
|
@@ -39940,18 +39968,20 @@ var RemoteHub = class {
|
|
|
39940
39968
|
}
|
|
39941
39969
|
host.phone = null;
|
|
39942
39970
|
}
|
|
39971
|
+
const created = sessionToken == null;
|
|
39943
39972
|
const token = sessionToken ?? (0, import_node_crypto25.randomBytes)(24).toString("hex");
|
|
39944
39973
|
if (host.sessionToken && host.sessionToken !== token) {
|
|
39945
39974
|
this.phonesByToken.delete(host.sessionToken);
|
|
39946
39975
|
}
|
|
39947
39976
|
host.sessionToken = token;
|
|
39948
39977
|
host.phone = socket;
|
|
39949
|
-
this.phonesByToken.set(token, host.deviceId);
|
|
39978
|
+
this.phonesByToken.set(token, { deviceId: host.deviceId, deviceLabel: host.deviceLabel });
|
|
39950
39979
|
this.remembered.set(host.deviceId, {
|
|
39951
39980
|
hostSecret: host.hostSecret,
|
|
39952
39981
|
sessionToken: token,
|
|
39953
39982
|
deviceLabel: host.deviceLabel
|
|
39954
39983
|
});
|
|
39984
|
+
if (created) this.opts.phoneSessions?.save(host.deviceId, token);
|
|
39955
39985
|
this.bySocket.set(socket, { role: "phone", deviceId: host.deviceId });
|
|
39956
39986
|
this.opts.onAuthorized?.(socket);
|
|
39957
39987
|
send2(socket, {
|
|
@@ -40215,6 +40245,29 @@ function phoneAccountDefaults() {
|
|
|
40215
40245
|
};
|
|
40216
40246
|
}
|
|
40217
40247
|
|
|
40248
|
+
// src/remote/phone-viewer-login.ts
|
|
40249
|
+
var TTL_MS = 5 * 6e4;
|
|
40250
|
+
var cached = "";
|
|
40251
|
+
var fetchedAt = 0;
|
|
40252
|
+
var inflight3 = null;
|
|
40253
|
+
function phoneViewerLogin() {
|
|
40254
|
+
return cached;
|
|
40255
|
+
}
|
|
40256
|
+
function refreshPhoneViewerLogin(force = false) {
|
|
40257
|
+
const now = Date.now();
|
|
40258
|
+
if (!force && fetchedAt && now - fetchedAt < TTL_MS) return Promise.resolve(cached);
|
|
40259
|
+
if (inflight3) return inflight3;
|
|
40260
|
+
const run2 = getGitHubStatus().then((status) => {
|
|
40261
|
+
cached = status.login?.trim() ?? "";
|
|
40262
|
+
fetchedAt = Date.now();
|
|
40263
|
+
return cached;
|
|
40264
|
+
}).catch(() => cached).finally(() => {
|
|
40265
|
+
if (inflight3 === run2) inflight3 = null;
|
|
40266
|
+
});
|
|
40267
|
+
inflight3 = run2;
|
|
40268
|
+
return run2;
|
|
40269
|
+
}
|
|
40270
|
+
|
|
40218
40271
|
// src/remote/phone-transcript.ts
|
|
40219
40272
|
init_turn_live();
|
|
40220
40273
|
|
|
@@ -40519,7 +40572,8 @@ function isProjectPath(path2) {
|
|
|
40519
40572
|
function listPhoneChats() {
|
|
40520
40573
|
return listGlobalThreads().slice().sort((a, b) => a.updatedAt < b.updatedAt ? 1 : a.updatedAt > b.updatedAt ? -1 : 0).map(summarize);
|
|
40521
40574
|
}
|
|
40522
|
-
function listPhoneSidebar() {
|
|
40575
|
+
function listPhoneSidebar(viewerLogin = phoneViewerLogin()) {
|
|
40576
|
+
const settings = loadAppSettings();
|
|
40523
40577
|
const threads = listThreads();
|
|
40524
40578
|
const byRepo = /* @__PURE__ */ new Map();
|
|
40525
40579
|
for (const thread of threads) {
|
|
@@ -40537,10 +40591,16 @@ function listPhoneSidebar() {
|
|
|
40537
40591
|
path: path2,
|
|
40538
40592
|
worktrees: groupHomeBoardWorktrees(repoThreads).map((group) => {
|
|
40539
40593
|
const tags = workspaceTagsFromGroup(group);
|
|
40594
|
+
const badge = classifyWorktreeListBadges(
|
|
40595
|
+
group,
|
|
40596
|
+
viewerLogin,
|
|
40597
|
+
resolveProjectReviewLabel(settings, path2)
|
|
40598
|
+
)[0];
|
|
40540
40599
|
return {
|
|
40541
40600
|
label: worktreeDisplayLabelForGroup(group),
|
|
40542
40601
|
chats: group.map(summarize),
|
|
40543
|
-
...tags.length > 0 ? { tags } : {}
|
|
40602
|
+
...tags.length > 0 ? { tags } : {},
|
|
40603
|
+
...badge ? { badge: { id: badge.id, label: badge.label, title: badge.title } } : {}
|
|
40544
40604
|
};
|
|
40545
40605
|
})
|
|
40546
40606
|
}));
|
|
@@ -41453,7 +41513,9 @@ function chatKey(row2) {
|
|
|
41453
41513
|
function phoneBoardKey(sidebar) {
|
|
41454
41514
|
const orchestration = sidebar.orchestration.map(chatKey).join("\n");
|
|
41455
41515
|
const projects = sidebar.projects.map((project) => {
|
|
41456
|
-
const trees = project.worktrees.map(
|
|
41516
|
+
const trees = project.worktrees.map(
|
|
41517
|
+
(tree) => `${tree.label} ${tree.badge?.id ?? ""} ${(tree.tags ?? []).join(",")} ${tree.chats.map(chatKey).join("\n")}`
|
|
41518
|
+
).join("\n");
|
|
41457
41519
|
return `${project.path} ${project.name}
|
|
41458
41520
|
${trees}`;
|
|
41459
41521
|
}).join("\n---\n");
|
|
@@ -41531,10 +41593,23 @@ function startPhoneBoardSync(opts) {
|
|
|
41531
41593
|
const unsubscribe = (opts.subscribe ?? subscribePhoneBoard)(schedule);
|
|
41532
41594
|
const offEvents = (opts.events ?? ((listener) => getOrchestrator().on(listener)))(handle);
|
|
41533
41595
|
push();
|
|
41596
|
+
let loginTimer = null;
|
|
41597
|
+
const refreshViewerLogin = opts.refreshViewerLogin;
|
|
41598
|
+
if (refreshViewerLogin) {
|
|
41599
|
+
const afterLogin = () => {
|
|
41600
|
+
void refreshViewerLogin().then(() => {
|
|
41601
|
+
if (!stopped) push();
|
|
41602
|
+
});
|
|
41603
|
+
};
|
|
41604
|
+
afterLogin();
|
|
41605
|
+
loginTimer = setInterval(afterLogin, opts.viewerLoginIntervalMs ?? 5 * 6e4);
|
|
41606
|
+
}
|
|
41534
41607
|
return () => {
|
|
41535
41608
|
stopped = true;
|
|
41536
41609
|
if (timer) clearTimeout(timer);
|
|
41537
41610
|
timer = null;
|
|
41611
|
+
if (loginTimer) clearInterval(loginTimer);
|
|
41612
|
+
loginTimer = null;
|
|
41538
41613
|
unsubscribe();
|
|
41539
41614
|
offEvents();
|
|
41540
41615
|
};
|
|
@@ -41601,7 +41676,8 @@ function runRemoteHost(opts) {
|
|
|
41601
41676
|
},
|
|
41602
41677
|
onRunningChat: (chatId) => {
|
|
41603
41678
|
deliverPhoneTurn({ onOutbound: emit }, chatId);
|
|
41604
|
-
}
|
|
41679
|
+
},
|
|
41680
|
+
refreshViewerLogin: () => refreshPhoneViewerLogin(true)
|
|
41605
41681
|
});
|
|
41606
41682
|
};
|
|
41607
41683
|
const send3 = (msg) => {
|
|
@@ -41864,9 +41940,15 @@ var RelayAccountStore = class {
|
|
|
41864
41940
|
account_id TEXT NOT NULL,
|
|
41865
41941
|
host_secret_hash TEXT NOT NULL,
|
|
41866
41942
|
device_label TEXT NOT NULL,
|
|
41867
|
-
created_at INTEGER NOT NULL
|
|
41943
|
+
created_at INTEGER NOT NULL,
|
|
41944
|
+
session_token_hash TEXT
|
|
41868
41945
|
);
|
|
41869
41946
|
`);
|
|
41947
|
+
const cols = this.db.prepare("PRAGMA table_info(devices)").all();
|
|
41948
|
+
if (!cols.some((col) => col.name === "session_token_hash")) {
|
|
41949
|
+
this.db.exec("ALTER TABLE devices ADD COLUMN session_token_hash TEXT");
|
|
41950
|
+
}
|
|
41951
|
+
this.db.exec("CREATE INDEX IF NOT EXISTS devices_session ON devices(session_token_hash)");
|
|
41870
41952
|
}
|
|
41871
41953
|
close() {
|
|
41872
41954
|
this.db.close();
|
|
@@ -41995,6 +42077,20 @@ var RelayAccountStore = class {
|
|
|
41995
42077
|
throw err;
|
|
41996
42078
|
}
|
|
41997
42079
|
}
|
|
42080
|
+
/** Store a phone pairing when it is created. A later process looks it up on a memory miss. */
|
|
42081
|
+
savePhoneSession(deviceId, sessionToken) {
|
|
42082
|
+
const id = deviceId.trim();
|
|
42083
|
+
const token = sessionToken.trim();
|
|
42084
|
+
if (!id || !token) return;
|
|
42085
|
+
this.db.prepare("UPDATE devices SET session_token_hash = ? WHERE device_id = ?").run(sha256(token), id);
|
|
42086
|
+
}
|
|
42087
|
+
findPhoneSession(sessionToken) {
|
|
42088
|
+
const token = sessionToken.trim();
|
|
42089
|
+
if (!token) return null;
|
|
42090
|
+
const row2 = this.db.prepare("SELECT device_id, device_label FROM devices WHERE session_token_hash = ?").get(sha256(token));
|
|
42091
|
+
if (!row2) return null;
|
|
42092
|
+
return { deviceId: row2.device_id, deviceLabel: row2.device_label };
|
|
42093
|
+
}
|
|
41998
42094
|
requireAccount(accountId) {
|
|
41999
42095
|
const row2 = this.db.prepare("SELECT id FROM accounts WHERE id = ?").get(accountId);
|
|
42000
42096
|
if (!row2) throw new Error("That Sideboard account is no longer on the relay.");
|
|
@@ -42985,6 +43081,10 @@ async function startRelayServer(opts) {
|
|
|
42985
43081
|
const decision = accountStore.authorizeHost(input);
|
|
42986
43082
|
return decision.ok ? { ok: true } : { ok: false, message: decision.message };
|
|
42987
43083
|
} : void 0,
|
|
43084
|
+
phoneSessions: accountStore ? {
|
|
43085
|
+
find: (sessionToken) => accountStore.findPhoneSession(sessionToken),
|
|
43086
|
+
save: (deviceId, sessionToken) => accountStore.savePhoneSession(deviceId, sessionToken)
|
|
43087
|
+
} : void 0,
|
|
42988
43088
|
onAuthorized: (socket) => authMarks.get(socket)?.()
|
|
42989
43089
|
});
|
|
42990
43090
|
const handleCallback = async (reqUrl, res) => {
|
|
@@ -43470,8 +43570,8 @@ function displayName(user) {
|
|
|
43470
43570
|
return fromProfile || user.real_name?.trim() || user.name?.trim() || "";
|
|
43471
43571
|
}
|
|
43472
43572
|
async function resolveUserName(token, userId, fallback, fetchImpl) {
|
|
43473
|
-
const
|
|
43474
|
-
if (
|
|
43573
|
+
const cached2 = nameCache.get(userId);
|
|
43574
|
+
if (cached2) return cached2;
|
|
43475
43575
|
try {
|
|
43476
43576
|
const data = await slackApi(token, "users.info", { user: userId }, fetchImpl);
|
|
43477
43577
|
const name = displayName(data.user ?? {}) || fallback;
|
package/dist/index.d.cts
CHANGED
|
@@ -7891,12 +7891,24 @@ type RemoteHostAuthorizer = (input: {
|
|
|
7891
7891
|
ok: false;
|
|
7892
7892
|
message: string;
|
|
7893
7893
|
};
|
|
7894
|
+
type RemotePhoneSession = {
|
|
7895
|
+
deviceId: string;
|
|
7896
|
+
deviceLabel: string;
|
|
7897
|
+
};
|
|
7898
|
+
/**
|
|
7899
|
+
* Phone pairings on disk. `save` runs when a pairing is created.
|
|
7900
|
+
* `find` runs only when that token is not already in memory.
|
|
7901
|
+
*/
|
|
7902
|
+
type RemotePhoneSessions = {
|
|
7903
|
+
find(sessionToken: string): RemotePhoneSession | null;
|
|
7904
|
+
save(deviceId: string, sessionToken: string): void;
|
|
7905
|
+
};
|
|
7894
7906
|
/**
|
|
7895
7907
|
* In-memory phone ↔ Mac registry. One active phone socket per Mac.
|
|
7896
7908
|
* A phone may hold session tokens for several Macs and attaches to one at a time.
|
|
7897
7909
|
* Host secrets and session tokens survive that Mac reconnecting in this process.
|
|
7898
|
-
* A
|
|
7899
|
-
*
|
|
7910
|
+
* A new pairing is written to the store. A relay restart drops memory; the next
|
|
7911
|
+
* resume reads that store, then keeps the session in memory.
|
|
7900
7912
|
*/
|
|
7901
7913
|
declare class RemoteHub {
|
|
7902
7914
|
private readonly opts;
|
|
@@ -7907,6 +7919,7 @@ declare class RemoteHub {
|
|
|
7907
7919
|
private readonly phonesByToken;
|
|
7908
7920
|
constructor(opts?: {
|
|
7909
7921
|
authorizeHost?: RemoteHostAuthorizer;
|
|
7922
|
+
phoneSessions?: RemotePhoneSessions;
|
|
7910
7923
|
onAuthorized?: (socket: RemoteSocket) => void;
|
|
7911
7924
|
});
|
|
7912
7925
|
handleClientMessage(socket: RemoteSocket, raw: string): void;
|
|
@@ -7915,6 +7928,9 @@ declare class RemoteHub {
|
|
|
7915
7928
|
private registerHost;
|
|
7916
7929
|
private issueCode;
|
|
7917
7930
|
private pairPhone;
|
|
7931
|
+
/** In-memory session, with the live Mac's label when that socket is up. */
|
|
7932
|
+
private memorySession;
|
|
7933
|
+
private knownSession;
|
|
7918
7934
|
private resumePhone;
|
|
7919
7935
|
private listHosts;
|
|
7920
7936
|
private releasePhoneSocket;
|
package/dist/index.d.ts
CHANGED
|
@@ -7891,12 +7891,24 @@ type RemoteHostAuthorizer = (input: {
|
|
|
7891
7891
|
ok: false;
|
|
7892
7892
|
message: string;
|
|
7893
7893
|
};
|
|
7894
|
+
type RemotePhoneSession = {
|
|
7895
|
+
deviceId: string;
|
|
7896
|
+
deviceLabel: string;
|
|
7897
|
+
};
|
|
7898
|
+
/**
|
|
7899
|
+
* Phone pairings on disk. `save` runs when a pairing is created.
|
|
7900
|
+
* `find` runs only when that token is not already in memory.
|
|
7901
|
+
*/
|
|
7902
|
+
type RemotePhoneSessions = {
|
|
7903
|
+
find(sessionToken: string): RemotePhoneSession | null;
|
|
7904
|
+
save(deviceId: string, sessionToken: string): void;
|
|
7905
|
+
};
|
|
7894
7906
|
/**
|
|
7895
7907
|
* In-memory phone ↔ Mac registry. One active phone socket per Mac.
|
|
7896
7908
|
* A phone may hold session tokens for several Macs and attaches to one at a time.
|
|
7897
7909
|
* Host secrets and session tokens survive that Mac reconnecting in this process.
|
|
7898
|
-
* A
|
|
7899
|
-
*
|
|
7910
|
+
* A new pairing is written to the store. A relay restart drops memory; the next
|
|
7911
|
+
* resume reads that store, then keeps the session in memory.
|
|
7900
7912
|
*/
|
|
7901
7913
|
declare class RemoteHub {
|
|
7902
7914
|
private readonly opts;
|
|
@@ -7907,6 +7919,7 @@ declare class RemoteHub {
|
|
|
7907
7919
|
private readonly phonesByToken;
|
|
7908
7920
|
constructor(opts?: {
|
|
7909
7921
|
authorizeHost?: RemoteHostAuthorizer;
|
|
7922
|
+
phoneSessions?: RemotePhoneSessions;
|
|
7910
7923
|
onAuthorized?: (socket: RemoteSocket) => void;
|
|
7911
7924
|
});
|
|
7912
7925
|
handleClientMessage(socket: RemoteSocket, raw: string): void;
|
|
@@ -7915,6 +7928,9 @@ declare class RemoteHub {
|
|
|
7915
7928
|
private registerHost;
|
|
7916
7929
|
private issueCode;
|
|
7917
7930
|
private pairPhone;
|
|
7931
|
+
/** In-memory session, with the live Mac's label when that socket is up. */
|
|
7932
|
+
private memorySession;
|
|
7933
|
+
private knownSession;
|
|
7918
7934
|
private resumePhone;
|
|
7919
7935
|
private listHosts;
|
|
7920
7936
|
private releasePhoneSocket;
|