@sideboard-ai/core 0.1.284 → 0.1.285
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/{abletime-WLDBJJUI.js → abletime-4CH2IOX5.js} +4 -4
- package/dist/{abletime-X64E3GUJ.js → abletime-I4RODUKT.js} +4 -4
- package/dist/{abletime-oauth-AXR676W5.js → abletime-oauth-7OZZ3ABX.js} +3 -3
- package/dist/{abletime-oauth-UWOCEICP.js → abletime-oauth-C2HN2Q6F.js} +3 -3
- package/dist/{abletime-rest-S4XWEXV2.js → abletime-rest-E4LBRFLM.js} +3 -3
- package/dist/{abletime-rest-LPUDJUEP.js → abletime-rest-WFI2HWBU.js} +3 -3
- package/dist/agents/cursor-runner.cjs +48 -11
- package/dist/agents/cursor-runner.js +48 -11
- package/dist/{agents-PM5ICSO3.js → agents-FKMYAKFD.js} +4 -4
- package/dist/{agents-6U2RQK7P.js → agents-ITNCZ6CA.js} +4 -4
- package/dist/chunk-2GPQZZLY.js +59 -0
- package/dist/{chunk-OEJQK7CY.js → chunk-2K723QZH.js} +3 -3
- package/dist/{chunk-ROPGQRPU.js → chunk-33KDPEK4.js} +1 -1
- package/dist/{chunk-I6HSGKMZ.js → chunk-5T4YWFLD.js} +2 -2
- package/dist/{chunk-U7HAVAGJ.js → chunk-6CVVNAIU.js} +2 -2
- package/dist/{chunk-TQRSVE7D.js → chunk-7IAMHN2N.js} +1 -1
- package/dist/{chunk-WQ4M2L44.js → chunk-C6NVTLZK.js} +5 -5
- package/dist/{chunk-VA55JG2I.js → chunk-DEJALWKM.js} +5 -5
- package/dist/{chunk-XTPQEZZA.js → chunk-IJMUYHPT.js} +3 -3
- package/dist/chunk-JAT3JFOS.js +61 -0
- package/dist/{chunk-DGPROCE5.js → chunk-LS4FFCPL.js} +3 -3
- package/dist/{chunk-P2BSMNHB.js → chunk-PXMLMBMI.js} +1 -1
- package/dist/{chunk-BS3QLVPL.js → chunk-TMM4FEZ5.js} +3 -3
- package/dist/{chunk-BSN6DJ4L.js → chunk-TXHZJESB.js} +3 -3
- package/dist/{chunk-GWFVCCJZ.js → chunk-VGNLMGBK.js} +6 -6
- package/dist/{chunk-PY4UCMRI.js → chunk-VQEARG5H.js} +5 -5
- package/dist/{chunk-COQLZNKQ.js → chunk-XSPOJFTV.js} +3 -3
- package/dist/{connected-teams-JIUOSZ6C.js → connected-teams-AB7ZHJVO.js} +3 -3
- package/dist/{connected-teams-RU6VATCM.js → connected-teams-BJ6PMIST.js} +3 -3
- package/dist/index.cjs +209 -112
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +171 -96
- package/dist/mcp/run-stdio.cjs +36 -17
- package/dist/mcp/run-stdio.js +8 -8
- package/dist/{oauth-S3M7B475.js → oauth-DP4ZV2M2.js} +2 -2
- package/dist/{oauth-K6CWZEQO.js → oauth-WCUZ6Z5G.js} +2 -2
- package/dist/{orchestrator-6YVY6T5I.js → orchestrator-F7KXYDQW.js} +5 -5
- package/dist/{orchestrator-CRBIW2RG.js → orchestrator-VUIRO6NC.js} +5 -5
- package/package.json +1 -1
- package/dist/chunk-N7WZ6NIN.js +0 -41
- package/dist/chunk-VKQGAWHY.js +0 -40
package/dist/index.cjs
CHANGED
|
@@ -11999,30 +11999,49 @@ var init_config = __esm({
|
|
|
11999
11999
|
function setHttpFetchImpl(fetchImpl) {
|
|
12000
12000
|
injected = fetchImpl;
|
|
12001
12001
|
}
|
|
12002
|
-
function
|
|
12003
|
-
|
|
12004
|
-
return TLS_ISSUER_RE.test(text7) ? TLS_ISSUER_HINT : "";
|
|
12002
|
+
function isTlsIssuerFailure(code, message) {
|
|
12003
|
+
return TLS_ISSUER_RE.test(`${code ?? ""} ${message}`);
|
|
12005
12004
|
}
|
|
12006
|
-
function
|
|
12007
|
-
if (
|
|
12008
|
-
|
|
12009
|
-
|
|
12010
|
-
|
|
12005
|
+
function describeCause(cause, depth = 0) {
|
|
12006
|
+
if (depth > 5 || cause == null) return null;
|
|
12007
|
+
if (cause instanceof AggregateError) {
|
|
12008
|
+
for (const item of cause.errors) {
|
|
12009
|
+
const found = describeCause(item, depth + 1);
|
|
12010
|
+
if (found && (found.code || found.message)) return found;
|
|
12011
|
+
}
|
|
12012
|
+
return cause.message ? { message: cause.message } : null;
|
|
12013
|
+
}
|
|
12011
12014
|
if (cause instanceof Error) {
|
|
12012
12015
|
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
}
|
|
12019
|
-
|
|
12016
|
+
const nested = describeCause(cause.cause, depth + 1);
|
|
12017
|
+
if ((!cause.message || cause.message === "fetch failed") && nested) return nested;
|
|
12018
|
+
if (cause.message || code) return { code, message: cause.message };
|
|
12019
|
+
return nested;
|
|
12020
|
+
}
|
|
12021
|
+
return { message: String(cause) };
|
|
12022
|
+
}
|
|
12023
|
+
function causeSuffix(detail) {
|
|
12024
|
+
if (!detail) return "";
|
|
12025
|
+
if (detail.code && detail.message) return ` [${detail.code}: ${detail.message}]`;
|
|
12026
|
+
if (detail.code) return ` [${detail.code}]`;
|
|
12027
|
+
if (detail.message) return ` [${detail.message}]`;
|
|
12028
|
+
return "";
|
|
12029
|
+
}
|
|
12030
|
+
function formatFetchError(err, url, opts) {
|
|
12031
|
+
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
12032
|
+
const detail = describeCause(err.cause);
|
|
12033
|
+
const hintSource = `${err.message} ${detail?.code ?? ""} ${detail?.message ?? ""}`;
|
|
12034
|
+
const tls2 = isTlsIssuerFailure(detail?.code, hintSource);
|
|
12035
|
+
const hint = tls2 ? opts?.tlsHint ?? TLS_ISSUER_HINT : "";
|
|
12036
|
+
return `${err.message}${causeSuffix(detail)} (${url})${hint}`;
|
|
12037
|
+
}
|
|
12038
|
+
function currentHttpFetch() {
|
|
12039
|
+
return injected ?? globalThis.fetch.bind(globalThis);
|
|
12020
12040
|
}
|
|
12021
12041
|
async function httpFetch(input, init) {
|
|
12022
12042
|
const url = typeof input === "string" ? input : input.href;
|
|
12023
|
-
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
12024
12043
|
try {
|
|
12025
|
-
return await
|
|
12044
|
+
return await currentHttpFetch()(url, init);
|
|
12026
12045
|
} catch (err) {
|
|
12027
12046
|
throw new Error(formatFetchError(err, url));
|
|
12028
12047
|
}
|
|
@@ -14719,10 +14738,10 @@ function eventsFromClaudeSystem(obj) {
|
|
|
14719
14738
|
if (subtype === "api_retry") {
|
|
14720
14739
|
const attempt = obj.attempt;
|
|
14721
14740
|
const max = obj.max_retries;
|
|
14722
|
-
const
|
|
14741
|
+
const delay3 = obj.retry_delay_ms;
|
|
14723
14742
|
return {
|
|
14724
14743
|
type: "thinking",
|
|
14725
|
-
data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof
|
|
14744
|
+
data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay3 === "number" ? ` (wait ${delay3}ms)` : ""}`
|
|
14726
14745
|
};
|
|
14727
14746
|
}
|
|
14728
14747
|
if (subtype === "status") {
|
|
@@ -27744,8 +27763,8 @@ var init_orchestrator = __esm({
|
|
|
27744
27763
|
scheduleQuotaResume(threadId, resumeAt) {
|
|
27745
27764
|
this.clearQuotaResumeTimer(threadId);
|
|
27746
27765
|
updateThread(threadId, { quotaResumeAt: resumeAt.toISOString() });
|
|
27747
|
-
const
|
|
27748
|
-
const capped = Math.min(
|
|
27766
|
+
const delay3 = Math.max(5e3, resumeAt.getTime() - Date.now());
|
|
27767
|
+
const capped = Math.min(delay3, 2147483647);
|
|
27749
27768
|
const timer = setTimeout(() => {
|
|
27750
27769
|
this.quotaResumeTimers.delete(threadId);
|
|
27751
27770
|
void this.resumeAfterQuotaWait(threadId);
|
|
@@ -30186,14 +30205,14 @@ function armOne(schedule) {
|
|
|
30186
30205
|
if (!schedule.enabled) return;
|
|
30187
30206
|
const at = new Date(schedule.nextRunAt);
|
|
30188
30207
|
if (Number.isNaN(at.getTime())) return;
|
|
30189
|
-
const
|
|
30190
|
-
if (
|
|
30208
|
+
const delay3 = Math.max(0, at.getTime() - Date.now());
|
|
30209
|
+
if (delay3 <= 250) {
|
|
30191
30210
|
void fireSchedule(schedule.id).then(() => {
|
|
30192
30211
|
if (isThisProcessDesktopHost()) armSchedules();
|
|
30193
30212
|
});
|
|
30194
30213
|
return;
|
|
30195
30214
|
}
|
|
30196
|
-
const capped = Math.min(
|
|
30215
|
+
const capped = Math.min(delay3, SET_TIMEOUT_MAX);
|
|
30197
30216
|
const timer = setTimeout(() => {
|
|
30198
30217
|
timers.delete(schedule.id);
|
|
30199
30218
|
const live = getSchedule(schedule.id);
|
|
@@ -39738,10 +39757,7 @@ var import_ws5 = require("ws");
|
|
|
39738
39757
|
init_orchestrator_capable();
|
|
39739
39758
|
init_stage_files();
|
|
39740
39759
|
init_orchestrator();
|
|
39741
|
-
init_ask_user();
|
|
39742
39760
|
init_app_settings();
|
|
39743
|
-
init_global_workspace();
|
|
39744
|
-
init_thread_store();
|
|
39745
39761
|
init_implied_first_prompt();
|
|
39746
39762
|
|
|
39747
39763
|
// src/remote/phone-media.ts
|
|
@@ -40720,7 +40736,13 @@ function deliverPhoneTurn(opts, chatId) {
|
|
|
40720
40736
|
});
|
|
40721
40737
|
}
|
|
40722
40738
|
|
|
40723
|
-
// src/remote/
|
|
40739
|
+
// src/remote/phone-turn.ts
|
|
40740
|
+
init_orchestrator_capable();
|
|
40741
|
+
init_orchestrator();
|
|
40742
|
+
init_ask_user();
|
|
40743
|
+
init_app_settings();
|
|
40744
|
+
init_global_workspace();
|
|
40745
|
+
init_thread_store();
|
|
40724
40746
|
function formatRemotePrompt(text7) {
|
|
40725
40747
|
return `Phone
|
|
40726
40748
|
|
|
@@ -40729,6 +40751,29 @@ ${text7.trim()}`;
|
|
|
40729
40751
|
function isRemoteStopCommand(text7) {
|
|
40730
40752
|
return text7.trim().toLowerCase() === "stop";
|
|
40731
40753
|
}
|
|
40754
|
+
function phoneFollowUpQueues(status) {
|
|
40755
|
+
return followUpBehavior() === "queue" && (status === "running" || status === "queued");
|
|
40756
|
+
}
|
|
40757
|
+
var PHONE_TURN_MS = 14 * 60 * 1e3;
|
|
40758
|
+
function delay2(ms) {
|
|
40759
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
40760
|
+
}
|
|
40761
|
+
async function waitForPhoneTurn(threadId, stillCurrent) {
|
|
40762
|
+
const deadline = Date.now() + PHONE_TURN_MS;
|
|
40763
|
+
while (stillCurrent() && Date.now() < deadline) {
|
|
40764
|
+
const thread2 = readPhoneThread(threadId) ?? readThread(threadId);
|
|
40765
|
+
if (!thread2) return;
|
|
40766
|
+
if (thread2.status === "stopped" && thread2.queue.length > 0) {
|
|
40767
|
+
await delay2(40);
|
|
40768
|
+
continue;
|
|
40769
|
+
}
|
|
40770
|
+
break;
|
|
40771
|
+
}
|
|
40772
|
+
if (!stillCurrent()) return;
|
|
40773
|
+
const thread = readPhoneThread(threadId) ?? readThread(threadId);
|
|
40774
|
+
if (!thread || thread.status !== "running" && thread.status !== "queued") return;
|
|
40775
|
+
await getOrchestrator().waitForTurn(threadId, Math.max(1, deadline - Date.now()));
|
|
40776
|
+
}
|
|
40732
40777
|
var handleChain2 = Promise.resolve();
|
|
40733
40778
|
var inboundGeneration = 0;
|
|
40734
40779
|
function enqueue(fn) {
|
|
@@ -40752,6 +40797,77 @@ function interruptRemoteCoordinator(deviceId, log = () => void 0) {
|
|
|
40752
40797
|
return false;
|
|
40753
40798
|
}
|
|
40754
40799
|
}
|
|
40800
|
+
function runCoordinatorPrompt(opts, body, generation) {
|
|
40801
|
+
const current = () => generation === inboundGeneration;
|
|
40802
|
+
return (async () => {
|
|
40803
|
+
if (!current()) return;
|
|
40804
|
+
const agent = coerceOrchestratorAgent(opts.agent ?? resolveOrchestratorDefaults().agent);
|
|
40805
|
+
if (!body) return;
|
|
40806
|
+
if (isRemoteStopCommand(body)) {
|
|
40807
|
+
if (!current()) return;
|
|
40808
|
+
opts.onOutbound({ type: "assistant", text: REMOTE_STOPPED_REPLY });
|
|
40809
|
+
return;
|
|
40810
|
+
}
|
|
40811
|
+
let thread = ensureRemoteCoordinator(opts.deviceId, agent);
|
|
40812
|
+
thread = readThread(thread.id) ?? thread;
|
|
40813
|
+
const followUp = followUpBehavior();
|
|
40814
|
+
const orch = getOrchestrator();
|
|
40815
|
+
try {
|
|
40816
|
+
await orch.send(thread.id, formatRemotePrompt(body), { followUp });
|
|
40817
|
+
if (!current()) return;
|
|
40818
|
+
await waitForPhoneTurn(thread.id, current);
|
|
40819
|
+
} catch (err) {
|
|
40820
|
+
if (!current()) return;
|
|
40821
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
40822
|
+
opts.onOutbound({ type: "assistant", text: `Sideboard failed: ${message}` });
|
|
40823
|
+
return;
|
|
40824
|
+
}
|
|
40825
|
+
if (!current()) return;
|
|
40826
|
+
thread = readThread(thread.id) ?? thread;
|
|
40827
|
+
if (thread.status === "stopped") return;
|
|
40828
|
+
const result = orch.getTurnResult(thread.id);
|
|
40829
|
+
const pending = extractPendingPlanQuestions(
|
|
40830
|
+
[...thread.messages].reverse().find((m) => m.role === "agent")?.parts
|
|
40831
|
+
);
|
|
40832
|
+
if (result.taskState === "input-required" && pending) {
|
|
40833
|
+
opts.onOutbound({
|
|
40834
|
+
type: "ask_user",
|
|
40835
|
+
text: result.text.trim(),
|
|
40836
|
+
questions: pending.questions.map((q) => ({
|
|
40837
|
+
question: q.question,
|
|
40838
|
+
options: q.options.map(
|
|
40839
|
+
(o) => o.description ? { label: o.label, description: o.description } : { label: o.label }
|
|
40840
|
+
)
|
|
40841
|
+
}))
|
|
40842
|
+
});
|
|
40843
|
+
return;
|
|
40844
|
+
}
|
|
40845
|
+
const reply = outboundReplyFromTurn(result, {
|
|
40846
|
+
inputRequired: "Sideboard is waiting for an answer.",
|
|
40847
|
+
canceled: REMOTE_STOPPED_REPLY,
|
|
40848
|
+
completedEmpty: () => "",
|
|
40849
|
+
failed: (detail) => detail ? `Sideboard failed: ${detail}` : "Sideboard failed before producing a result."
|
|
40850
|
+
});
|
|
40851
|
+
if (reply.trim()) opts.onOutbound({ type: "assistant", text: reply.trim() });
|
|
40852
|
+
})();
|
|
40853
|
+
}
|
|
40854
|
+
function beginCoordinatorPrompt(body, opts) {
|
|
40855
|
+
const live = body ? findRemoteCoordinator(opts.deviceId) : null;
|
|
40856
|
+
const fresh = live ? readThread(live.id) ?? live : null;
|
|
40857
|
+
if (body && !isRemoteStopCommand(body) && phoneFollowUpQueues(fresh?.status)) {
|
|
40858
|
+
const generation2 = inboundGeneration;
|
|
40859
|
+
enqueue(() => runCoordinatorPrompt(opts, body, generation2));
|
|
40860
|
+
return;
|
|
40861
|
+
}
|
|
40862
|
+
const generation = ++inboundGeneration;
|
|
40863
|
+
if (body && isRemoteStopCommand(body)) {
|
|
40864
|
+
interruptRemoteCoordinator(opts.deviceId, opts.onLog ?? (() => void 0));
|
|
40865
|
+
}
|
|
40866
|
+
const task = runCoordinatorPrompt(opts, body, generation);
|
|
40867
|
+
enqueue(() => task);
|
|
40868
|
+
}
|
|
40869
|
+
|
|
40870
|
+
// src/remote/listen.ts
|
|
40755
40871
|
function emitOpened(opts, opened) {
|
|
40756
40872
|
setPhoneOpenChat(opened.chat.id);
|
|
40757
40873
|
emitControl(opts, { op: "opened", ...opened });
|
|
@@ -41021,23 +41137,27 @@ function handlePhoneControl(cmd, opts) {
|
|
|
41021
41137
|
return;
|
|
41022
41138
|
}
|
|
41023
41139
|
const chatId = cmd.chatId;
|
|
41140
|
+
const existing = readPhoneThread(chatId);
|
|
41141
|
+
if (phoneFollowUpQueues(existing?.status)) {
|
|
41142
|
+
deliverPhoneTurn(opts, chatId);
|
|
41143
|
+
const generation2 = chatGeneration.get(chatId) ?? bumpChat(chatId);
|
|
41144
|
+
enqueueChat(chatId, () => runPhonePrompt(opts, cmd, chatId, generation2));
|
|
41145
|
+
return;
|
|
41146
|
+
}
|
|
41024
41147
|
const generation = bumpChat(chatId);
|
|
41025
41148
|
phoneTurnGen.set(chatId, generation);
|
|
41026
|
-
|
|
41027
|
-
enqueueChat(chatId,
|
|
41028
|
-
|
|
41149
|
+
const task = runPhonePrompt(opts, cmd, chatId, generation);
|
|
41150
|
+
enqueueChat(chatId, () => task);
|
|
41151
|
+
}
|
|
41152
|
+
function runPhonePrompt(opts, cmd, chatId, generation) {
|
|
41153
|
+
const current = () => chatGeneration.get(chatId) === generation;
|
|
41154
|
+
return (async () => {
|
|
41155
|
+
if (!current()) return;
|
|
41029
41156
|
const thread = readPhoneThread(chatId);
|
|
41030
41157
|
if (!thread) {
|
|
41031
41158
|
emitControl(opts, { op: "error", chatId, message: "That agent is not on this Mac." });
|
|
41032
41159
|
return;
|
|
41033
41160
|
}
|
|
41034
|
-
if (thread.status === "running" || thread.status === "queued") {
|
|
41035
|
-
try {
|
|
41036
|
-
getOrchestrator().stop(thread.id, { clearQueue: true });
|
|
41037
|
-
} catch {
|
|
41038
|
-
}
|
|
41039
|
-
}
|
|
41040
|
-
if (chatGeneration.get(chatId) !== generation) return;
|
|
41041
41161
|
const stopStream = watchPhoneStream(opts, chatId, thread.id, generation);
|
|
41042
41162
|
try {
|
|
41043
41163
|
try {
|
|
@@ -41045,14 +41165,19 @@ function handlePhoneControl(cmd, opts) {
|
|
|
41045
41165
|
} catch (err) {
|
|
41046
41166
|
emitControl(opts, { op: "error", chatId, message: phoneError(err) });
|
|
41047
41167
|
}
|
|
41168
|
+
if (!current()) return;
|
|
41048
41169
|
const live = readPhoneThread(thread.id) ?? thread;
|
|
41170
|
+
const followUp = followUpBehavior();
|
|
41049
41171
|
const staged = stagePhoneTurnFiles(live.worktreePath, cmd);
|
|
41050
41172
|
const text7 = cmd.text.trim() || (staged.length ? "See the attached files." : "");
|
|
41051
|
-
|
|
41052
|
-
|
|
41053
|
-
|
|
41173
|
+
await getOrchestrator().send(thread.id, formatRemotePrompt(text7), {
|
|
41174
|
+
attachments: staged,
|
|
41175
|
+
followUp
|
|
41176
|
+
});
|
|
41177
|
+
if (!current()) return;
|
|
41178
|
+
await waitForPhoneTurn(thread.id, current);
|
|
41054
41179
|
} catch (err) {
|
|
41055
|
-
if (
|
|
41180
|
+
if (!current()) return;
|
|
41056
41181
|
const message = err instanceof Error ? err.message : String(err);
|
|
41057
41182
|
emitControl(opts, { op: "error", chatId, message: `Sideboard failed: ${message}` });
|
|
41058
41183
|
return;
|
|
@@ -41060,12 +41185,11 @@ function handlePhoneControl(cmd, opts) {
|
|
|
41060
41185
|
stopStream();
|
|
41061
41186
|
finishPhoneTurn(chatId, generation);
|
|
41062
41187
|
}
|
|
41063
|
-
if (
|
|
41188
|
+
if (!current()) return;
|
|
41064
41189
|
emitChatTurn(opts, chatId, thread.id);
|
|
41065
|
-
});
|
|
41190
|
+
})();
|
|
41066
41191
|
}
|
|
41067
41192
|
function handleRemoteInbound(text7, opts) {
|
|
41068
|
-
const log = opts.onLog ?? (() => void 0);
|
|
41069
41193
|
const body = text7.trim();
|
|
41070
41194
|
const control = takePhoneControl(body);
|
|
41071
41195
|
if (control) {
|
|
@@ -41076,64 +41200,7 @@ function handleRemoteInbound(text7, opts) {
|
|
|
41076
41200
|
handlePhoneControl(control, opts);
|
|
41077
41201
|
return;
|
|
41078
41202
|
}
|
|
41079
|
-
|
|
41080
|
-
if (body) interruptRemoteCoordinator(opts.deviceId, log);
|
|
41081
|
-
enqueue(async () => {
|
|
41082
|
-
if (generation !== inboundGeneration) return;
|
|
41083
|
-
const agent = coerceOrchestratorAgent(opts.agent ?? resolveOrchestratorDefaults().agent);
|
|
41084
|
-
if (!body) return;
|
|
41085
|
-
if (isRemoteStopCommand(body)) {
|
|
41086
|
-
if (generation !== inboundGeneration) return;
|
|
41087
|
-
opts.onOutbound({ type: "assistant", text: REMOTE_STOPPED_REPLY });
|
|
41088
|
-
return;
|
|
41089
|
-
}
|
|
41090
|
-
let thread = ensureRemoteCoordinator(opts.deviceId, agent);
|
|
41091
|
-
const fresh = readThread(thread.id) ?? thread;
|
|
41092
|
-
if (fresh.status === "running" || fresh.status === "queued") {
|
|
41093
|
-
try {
|
|
41094
|
-
getOrchestrator().stop(fresh.id, { clearQueue: true });
|
|
41095
|
-
} catch {
|
|
41096
|
-
}
|
|
41097
|
-
}
|
|
41098
|
-
if (generation !== inboundGeneration) return;
|
|
41099
|
-
const orch = getOrchestrator();
|
|
41100
|
-
try {
|
|
41101
|
-
await orch.send(thread.id, formatRemotePrompt(body));
|
|
41102
|
-
await orch.waitForTurn(thread.id, 14 * 60 * 1e3);
|
|
41103
|
-
} catch (err) {
|
|
41104
|
-
if (generation !== inboundGeneration) return;
|
|
41105
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
41106
|
-
opts.onOutbound({ type: "assistant", text: `Sideboard failed: ${message}` });
|
|
41107
|
-
return;
|
|
41108
|
-
}
|
|
41109
|
-
if (generation !== inboundGeneration) return;
|
|
41110
|
-
thread = readThread(thread.id) ?? thread;
|
|
41111
|
-
if (thread.status === "stopped") return;
|
|
41112
|
-
const result = orch.getTurnResult(thread.id);
|
|
41113
|
-
const pending = extractPendingPlanQuestions(
|
|
41114
|
-
[...thread.messages].reverse().find((m) => m.role === "agent")?.parts
|
|
41115
|
-
);
|
|
41116
|
-
if (result.taskState === "input-required" && pending) {
|
|
41117
|
-
opts.onOutbound({
|
|
41118
|
-
type: "ask_user",
|
|
41119
|
-
text: result.text.trim(),
|
|
41120
|
-
questions: pending.questions.map((q) => ({
|
|
41121
|
-
question: q.question,
|
|
41122
|
-
options: q.options.map(
|
|
41123
|
-
(o) => o.description ? { label: o.label, description: o.description } : { label: o.label }
|
|
41124
|
-
)
|
|
41125
|
-
}))
|
|
41126
|
-
});
|
|
41127
|
-
return;
|
|
41128
|
-
}
|
|
41129
|
-
const reply = outboundReplyFromTurn(result, {
|
|
41130
|
-
inputRequired: "Sideboard is waiting for an answer.",
|
|
41131
|
-
canceled: REMOTE_STOPPED_REPLY,
|
|
41132
|
-
completedEmpty: () => "",
|
|
41133
|
-
failed: (detail) => detail ? `Sideboard failed: ${detail}` : "Sideboard failed before producing a result."
|
|
41134
|
-
});
|
|
41135
|
-
if (reply.trim()) opts.onOutbound({ type: "assistant", text: reply.trim() });
|
|
41136
|
-
});
|
|
41203
|
+
beginCoordinatorPrompt(body, opts);
|
|
41137
41204
|
}
|
|
41138
41205
|
|
|
41139
41206
|
// src/remote/phone-board-sync.ts
|
|
@@ -41473,6 +41540,7 @@ function runRemoteHost(opts) {
|
|
|
41473
41540
|
|
|
41474
41541
|
// src/relay/account-login.ts
|
|
41475
41542
|
var import_node_crypto28 = require("crypto");
|
|
41543
|
+
init_fetch();
|
|
41476
41544
|
|
|
41477
41545
|
// src/relay/accounts.ts
|
|
41478
41546
|
var import_node_crypto27 = require("crypto");
|
|
@@ -42073,15 +42141,43 @@ function sleep2(ms, signal) {
|
|
|
42073
42141
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
42074
42142
|
});
|
|
42075
42143
|
}
|
|
42144
|
+
var RELAY_TLS_HINT = " \u2014 the TLS certificate was rejected. A work proxy often does this when Sideboard is not allowlisted, or when the app does not trust the corporate CA.";
|
|
42145
|
+
var RELAY_NETWORK_HINT = " Sideboard could not reach the relay. On a work computer this is often a VPN, a proxy, or an allowlist that does not include Sideboard.";
|
|
42146
|
+
var RELAY_NETWORK_RE = /fetch failed|Failed to fetch|ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|EAI_AGAIN|EPERM|UND_ERR_|ERR_CONNECTION|ERR_NETWORK|ERR_PROXY|ERR_TUNNEL|ERR_INTERNET|ERR_BLOCKED|ERR_NAME_NOT_RESOLVED|ERR_ADDRESS_UNREACHABLE|ERR_CERT|CERT_|UNABLE_TO_GET_ISSUER|SELF_SIGNED/i;
|
|
42147
|
+
function relayFetchError(err, url) {
|
|
42148
|
+
const formatted = formatFetchError(err, url, { tlsHint: RELAY_TLS_HINT });
|
|
42149
|
+
if (formatted.includes(RELAY_TLS_HINT) || !RELAY_NETWORK_RE.test(formatted)) {
|
|
42150
|
+
return new Error(formatted);
|
|
42151
|
+
}
|
|
42152
|
+
return new Error(`${formatted}${RELAY_NETWORK_HINT}`);
|
|
42153
|
+
}
|
|
42154
|
+
async function relayFetch(fetchImpl, url, init) {
|
|
42155
|
+
const fn = fetchImpl ?? currentHttpFetch();
|
|
42156
|
+
try {
|
|
42157
|
+
return await fn(url, init);
|
|
42158
|
+
} catch (err) {
|
|
42159
|
+
throw relayFetchError(err, url);
|
|
42160
|
+
}
|
|
42161
|
+
}
|
|
42162
|
+
async function readJson3(res, url) {
|
|
42163
|
+
try {
|
|
42164
|
+
return await res.json();
|
|
42165
|
+
} catch {
|
|
42166
|
+
const kind = (res.headers.get("content-type") ?? "").includes("html") ? "an HTML page" : "a non-JSON body";
|
|
42167
|
+
throw new Error(
|
|
42168
|
+
`Relay sign-in returned HTTP ${res.status} with ${kind} (${url}). A work proxy or allowlist often answers with a block page instead of the relay.`
|
|
42169
|
+
);
|
|
42170
|
+
}
|
|
42171
|
+
}
|
|
42076
42172
|
async function startRemoteAccountLogin(opts) {
|
|
42077
42173
|
if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
|
|
42078
42174
|
const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
|
|
42079
|
-
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
42080
42175
|
const state = (0, import_node_crypto28.randomBytes)(16).toString("hex");
|
|
42081
42176
|
const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
|
|
42082
42177
|
const pollIntervalMs = opts.pollIntervalMs ?? 400;
|
|
42083
42178
|
const linkToken = opts.linkToken?.trim() ?? "";
|
|
42084
|
-
const
|
|
42179
|
+
const startUrl = `${origin}${REMOTE_LOGIN_PATH}`;
|
|
42180
|
+
const started = await relayFetch(opts.fetchImpl, startUrl, {
|
|
42085
42181
|
method: "POST",
|
|
42086
42182
|
headers: { "Content-Type": "application/json" },
|
|
42087
42183
|
body: JSON.stringify({
|
|
@@ -42090,9 +42186,9 @@ async function startRemoteAccountLogin(opts) {
|
|
|
42090
42186
|
...linkToken ? { accountToken: linkToken } : {}
|
|
42091
42187
|
})
|
|
42092
42188
|
});
|
|
42093
|
-
const startBody = await started
|
|
42189
|
+
const startBody = await readJson3(started, startUrl);
|
|
42094
42190
|
if (!started.ok || !startBody.url) {
|
|
42095
|
-
throw new Error(startBody.error ||
|
|
42191
|
+
throw new Error(startBody.error || `Could not start sign-in (HTTP ${started.status}).`);
|
|
42096
42192
|
}
|
|
42097
42193
|
await Promise.resolve(opts.openUrl?.(startBody.url));
|
|
42098
42194
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -42101,9 +42197,11 @@ async function startRemoteAccountLogin(opts) {
|
|
|
42101
42197
|
if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
|
|
42102
42198
|
let res;
|
|
42103
42199
|
try {
|
|
42104
|
-
res = await fetchImpl
|
|
42105
|
-
} catch {
|
|
42106
|
-
if (opts.signal?.aborted
|
|
42200
|
+
res = await relayFetch(opts.fetchImpl, resultUrl);
|
|
42201
|
+
} catch (err) {
|
|
42202
|
+
if (opts.signal?.aborted || isRemoteAccountLoginCancelled(err)) {
|
|
42203
|
+
throw new RemoteAccountLoginCancelled();
|
|
42204
|
+
}
|
|
42107
42205
|
await sleep2(pollIntervalMs, opts.signal);
|
|
42108
42206
|
continue;
|
|
42109
42207
|
}
|
|
@@ -42128,8 +42226,7 @@ async function startRemoteAccountLogin(opts) {
|
|
|
42128
42226
|
}
|
|
42129
42227
|
async function disconnectRemoteAccount(opts) {
|
|
42130
42228
|
const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
|
|
42131
|
-
|
|
42132
|
-
await fetchImpl(`${origin}${REMOTE_LOGOUT_PATH}`, {
|
|
42229
|
+
await relayFetch(opts.fetchImpl, `${origin}${REMOTE_LOGOUT_PATH}`, {
|
|
42133
42230
|
method: "POST",
|
|
42134
42231
|
headers: { "Content-Type": "application/json" },
|
|
42135
42232
|
body: JSON.stringify({ accountToken: opts.accountToken })
|
package/dist/index.d.cts
CHANGED
|
@@ -3443,8 +3443,14 @@ declare function installOptionalServiceCli(id: OptionalServiceId): Promise<Agent
|
|
|
3443
3443
|
* an opaque `TypeError: fetch failed` or `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`.
|
|
3444
3444
|
*/
|
|
3445
3445
|
declare function setHttpFetchImpl(fetchImpl: typeof fetch | null): void;
|
|
3446
|
-
/**
|
|
3447
|
-
|
|
3446
|
+
/**
|
|
3447
|
+
* Expand undici/Electron `TypeError: fetch failed` with the underlying cause.
|
|
3448
|
+
* `tlsHint` replaces the default Linear certificate note when the failure is a
|
|
3449
|
+
* corporate CA rejection. Pass '' to omit that note.
|
|
3450
|
+
*/
|
|
3451
|
+
declare function formatFetchError(err: unknown, url: string, opts?: {
|
|
3452
|
+
tlsHint?: string;
|
|
3453
|
+
}): string;
|
|
3448
3454
|
declare function httpFetch(input: string | URL, init?: RequestInit): Promise<Response>;
|
|
3449
3455
|
|
|
3450
3456
|
/**
|
|
@@ -8011,6 +8017,7 @@ type RemoteOutbound = {
|
|
|
8011
8017
|
|
|
8012
8018
|
declare function formatRemotePrompt(text: string): string;
|
|
8013
8019
|
declare function isRemoteStopCommand(text: string): boolean;
|
|
8020
|
+
|
|
8014
8021
|
declare function handleRemoteInbound(text: string, opts: {
|
|
8015
8022
|
deviceId: string;
|
|
8016
8023
|
agent?: AgentKind;
|
package/dist/index.d.ts
CHANGED
|
@@ -3443,8 +3443,14 @@ declare function installOptionalServiceCli(id: OptionalServiceId): Promise<Agent
|
|
|
3443
3443
|
* an opaque `TypeError: fetch failed` or `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`.
|
|
3444
3444
|
*/
|
|
3445
3445
|
declare function setHttpFetchImpl(fetchImpl: typeof fetch | null): void;
|
|
3446
|
-
/**
|
|
3447
|
-
|
|
3446
|
+
/**
|
|
3447
|
+
* Expand undici/Electron `TypeError: fetch failed` with the underlying cause.
|
|
3448
|
+
* `tlsHint` replaces the default Linear certificate note when the failure is a
|
|
3449
|
+
* corporate CA rejection. Pass '' to omit that note.
|
|
3450
|
+
*/
|
|
3451
|
+
declare function formatFetchError(err: unknown, url: string, opts?: {
|
|
3452
|
+
tlsHint?: string;
|
|
3453
|
+
}): string;
|
|
3448
3454
|
declare function httpFetch(input: string | URL, init?: RequestInit): Promise<Response>;
|
|
3449
3455
|
|
|
3450
3456
|
/**
|
|
@@ -8011,6 +8017,7 @@ type RemoteOutbound = {
|
|
|
8011
8017
|
|
|
8012
8018
|
declare function formatRemotePrompt(text: string): string;
|
|
8013
8019
|
declare function isRemoteStopCommand(text: string): boolean;
|
|
8020
|
+
|
|
8014
8021
|
declare function handleRemoteInbound(text: string, opts: {
|
|
8015
8022
|
deviceId: string;
|
|
8016
8023
|
agent?: AgentKind;
|