@sideboard-ai/core 0.1.294 → 0.1.296
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/claude-runner.cjs +55 -0
- package/dist/agents/claude-runner.js +57 -1
- package/dist/agents/cursor-runner.cjs +128 -50
- package/dist/agents/cursor-runner.js +63 -44
- package/dist/{agents-2PDBDZPS.js → agents-DZTPUKVF.js} +5 -5
- package/dist/{agents-73JXQXF2.js → agents-ICHYDSCD.js} +8 -8
- package/dist/{chunk-SVQTKVXH.js → chunk-2O3ICR77.js} +4 -4
- package/dist/{chunk-YKO6HG74.js → chunk-67BWWLEB.js} +6 -6
- package/dist/{chunk-JEYJGQ33.js → chunk-6GTABVNG.js} +7 -7
- package/dist/{chunk-YEIPPZ5W.js → chunk-BGEECLKH.js} +2 -2
- package/dist/{chunk-AFLNFGGB.js → chunk-ED4ZXQVO.js} +1 -0
- package/dist/{chunk-MIVX7QKI.js → chunk-HO5R3ZRH.js} +1 -0
- package/dist/{chunk-7UUILVMV.js → chunk-IOY2LF3Y.js} +1 -1
- package/dist/{chunk-K6IOJI3L.js → chunk-J54UPHXZ.js} +71 -2
- package/dist/{chunk-ZEP6JIRF.js → chunk-JWXJXEA3.js} +1 -1
- package/dist/{chunk-YSLCWCMJ.js → chunk-Q3DPZ4DE.js} +1 -1
- package/dist/{chunk-NYBFYFK7.js → chunk-QDA6NXRA.js} +1 -0
- package/dist/{chunk-CECZUHA5.js → chunk-QT36F4TD.js} +55 -26
- package/dist/{chunk-YRXV3E7J.js → chunk-TVN4TDFB.js} +9 -0
- package/dist/{chunk-6SGYGYH7.js → chunk-VXNZG4J6.js} +1 -1
- package/dist/{chunk-BYAFYLLZ.js → chunk-W2A63ZOK.js} +179 -42
- package/dist/{chunk-E7G7RY6T.js → chunk-WQREAX35.js} +2 -2
- package/dist/{chunk-QB5MDOHL.js → chunk-WZLV4WNS.js} +9 -0
- package/dist/{chunk-BJUHZSZQ.js → chunk-ZXWRNA4G.js} +5 -5
- package/dist/{conductor-7DEMFEIO.js → conductor-HJFDYIZD.js} +5 -5
- package/dist/{conductor-ZQZTYXSX.js → conductor-ZXDIA6OF.js} +6 -6
- package/dist/{coordinator-prompt-AROMFCP2.js → coordinator-prompt-ILHSVPOG.js} +3 -3
- package/dist/{coordinator-prompt-K6XHUG3N.js → coordinator-prompt-L3V2CMWX.js} +3 -3
- package/dist/{global-workspace-4WAU4PAL.js → global-workspace-47G453ZU.js} +3 -3
- package/dist/{global-workspace-PX4GUVLW.js → global-workspace-NMRUGGFF.js} +3 -3
- package/dist/index.cjs +1039 -700
- package/dist/index.d.cts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +299 -125
- package/dist/mcp/run-stdio.cjs +250 -144
- package/dist/mcp/run-stdio.js +70 -11
- package/dist/{orchestrator-LIEGSQ6M.js → orchestrator-MR7TCIPP.js} +7 -7
- package/dist/{orchestrator-YNEEEP6O.js → orchestrator-ZQU62CES.js} +10 -10
- package/dist/{thread-store-DPKESDFR.js → thread-store-H6D6MDUM.js} +1 -1
- package/dist/{thread-store-X6S2GIR5.js → thread-store-SADLLKRE.js} +1 -1
- package/dist/{workspaces-MFU3IGAP.js → workspaces-PGY4UWZ3.js} +3 -3
- package/dist/{workspaces-U7SSD27C.js → workspaces-WGZPRQJX.js} +3 -3
- package/dist/{worktree-TQKASYPZ.js → worktree-3MF5J5XZ.js} +2 -2
- package/dist/{worktree-2VSHRI72.js → worktree-JZXDAKQF.js} +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,17 +19,20 @@ import {
|
|
|
19
19
|
agentBlockFields,
|
|
20
20
|
agentGitPrompt,
|
|
21
21
|
alignQueueAttachments,
|
|
22
|
+
answerToolPermission,
|
|
22
23
|
appendQueuedItem,
|
|
23
24
|
applyIssueListWindow,
|
|
24
25
|
applyPromptCacheTtlEnv,
|
|
25
26
|
applyThreadIntoMain,
|
|
26
27
|
applyWorkspaceTags,
|
|
27
28
|
armSchedules,
|
|
29
|
+
askToolPermission,
|
|
28
30
|
assembleHomeBoard,
|
|
29
31
|
boardPinIdentity,
|
|
30
32
|
captureTurnBaseline,
|
|
31
33
|
chatBlockedSuffix,
|
|
32
34
|
claimDesktopHost,
|
|
35
|
+
clampBlockReason,
|
|
33
36
|
clampMcpIssueLimit,
|
|
34
37
|
classifyWorktreeColumn,
|
|
35
38
|
classifyWorktreeListBadges,
|
|
@@ -160,6 +163,7 @@ import {
|
|
|
160
163
|
reviewLabelForRepo,
|
|
161
164
|
scheduleNeedsCaffeinate,
|
|
162
165
|
schedulesPath,
|
|
166
|
+
setToolPermissionPublisher,
|
|
163
167
|
shiftQueuedItem,
|
|
164
168
|
shouldNotifyOrchestrator,
|
|
165
169
|
shouldRemoveWorktreeOnTeardown,
|
|
@@ -185,8 +189,9 @@ import {
|
|
|
185
189
|
worktreeAgentBlock,
|
|
186
190
|
worktreeBoardStatus,
|
|
187
191
|
worktreeCleanupSettings,
|
|
192
|
+
writeAgentBlock,
|
|
188
193
|
writeWorktreeFile
|
|
189
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-W2A63ZOK.js";
|
|
190
195
|
import {
|
|
191
196
|
LEGACY_PLAN_FILE_REL,
|
|
192
197
|
PLAN_FILE_NAME,
|
|
@@ -282,7 +287,7 @@ import {
|
|
|
282
287
|
userMcpNamesToDisable,
|
|
283
288
|
worktreeMcpToolNames,
|
|
284
289
|
writeInjectedMcpConfig
|
|
285
|
-
} from "./chunk-
|
|
290
|
+
} from "./chunk-6GTABVNG.js";
|
|
286
291
|
import {
|
|
287
292
|
brightsyMcpServerName,
|
|
288
293
|
connectBrightsyTeam,
|
|
@@ -410,7 +415,7 @@ import {
|
|
|
410
415
|
workspaceAgentChatSummaries,
|
|
411
416
|
worktreeRunPortsPath,
|
|
412
417
|
wrapReviewSkillMarkdown
|
|
413
|
-
} from "./chunk-
|
|
418
|
+
} from "./chunk-67BWWLEB.js";
|
|
414
419
|
import {
|
|
415
420
|
STDERR_EVENT_MAX_CHARS,
|
|
416
421
|
STDOUT_EVENT_MAX_CHARS,
|
|
@@ -452,7 +457,7 @@ import {
|
|
|
452
457
|
visibleToolRowDetail,
|
|
453
458
|
withEventParentId,
|
|
454
459
|
withEventsParentId
|
|
455
|
-
} from "./chunk-
|
|
460
|
+
} from "./chunk-Q3DPZ4DE.js";
|
|
456
461
|
import "./chunk-7H655NEW.js";
|
|
457
462
|
import {
|
|
458
463
|
ABLETIME_OAUTH_CALLBACK_PATH,
|
|
@@ -610,7 +615,7 @@ import {
|
|
|
610
615
|
stageBuffersAsAttachments,
|
|
611
616
|
syncWorkspacesFromThreads,
|
|
612
617
|
takenTeamSlugsForOrchestration
|
|
613
|
-
} from "./chunk-
|
|
618
|
+
} from "./chunk-BGEECLKH.js";
|
|
614
619
|
import {
|
|
615
620
|
GITHUB_PR_BODY_MAX_CHARS,
|
|
616
621
|
GITHUB_PR_BODY_SAFE_CHARS,
|
|
@@ -698,7 +703,7 @@ import {
|
|
|
698
703
|
suggestSlug,
|
|
699
704
|
switchWorktreeBranch,
|
|
700
705
|
warmGithubAgentAuth
|
|
701
|
-
} from "./chunk-
|
|
706
|
+
} from "./chunk-JWXJXEA3.js";
|
|
702
707
|
import {
|
|
703
708
|
FAMOUS_SOCCER_TEAMS,
|
|
704
709
|
allocateTeamName,
|
|
@@ -730,7 +735,7 @@ import {
|
|
|
730
735
|
worktreeNameFromPath,
|
|
731
736
|
worktreeSlugForTicket,
|
|
732
737
|
writeThread
|
|
733
|
-
} from "./chunk-
|
|
738
|
+
} from "./chunk-WZLV4WNS.js";
|
|
734
739
|
import "./chunk-2P4XKWV2.js";
|
|
735
740
|
import {
|
|
736
741
|
BRIGHTSY_OAUTH_CLIENT_ID,
|
|
@@ -752,8 +757,9 @@ import {
|
|
|
752
757
|
setHttpFetchImpl
|
|
753
758
|
} from "./chunk-JAT3JFOS.js";
|
|
754
759
|
import {
|
|
755
|
-
clipMcpToolResult
|
|
756
|
-
|
|
760
|
+
clipMcpToolResult,
|
|
761
|
+
cursorToolErrorText
|
|
762
|
+
} from "./chunk-J54UPHXZ.js";
|
|
757
763
|
import "./chunk-AXQ4ZWHK.js";
|
|
758
764
|
import {
|
|
759
765
|
AGENT_RUNNER_MAX_OLD_SPACE_MB,
|
|
@@ -769,8 +775,8 @@ import {
|
|
|
769
775
|
trustSystemCertificates,
|
|
770
776
|
turnCostUsdFromCursorUsage,
|
|
771
777
|
withMaxOldSpaceSize
|
|
772
|
-
} from "./chunk-
|
|
773
|
-
import "./chunk-
|
|
778
|
+
} from "./chunk-IOY2LF3Y.js";
|
|
779
|
+
import "./chunk-HO5R3ZRH.js";
|
|
774
780
|
import {
|
|
775
781
|
ATTACHMENTS_DIR,
|
|
776
782
|
CLI_DIR,
|
|
@@ -818,7 +824,7 @@ import {
|
|
|
818
824
|
rpcNotify,
|
|
819
825
|
rpcResult,
|
|
820
826
|
writeAgentRuntimeMetadata
|
|
821
|
-
} from "./chunk-
|
|
827
|
+
} from "./chunk-QDA6NXRA.js";
|
|
822
828
|
import {
|
|
823
829
|
AGENT_DONE_SOUNDS,
|
|
824
830
|
CHAT_TEXT_SCALES,
|
|
@@ -3596,8 +3602,18 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
3596
3602
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3597
3603
|
function wrapToolCallback(fn, cwd) {
|
|
3598
3604
|
return async (...args) => {
|
|
3599
|
-
|
|
3600
|
-
|
|
3605
|
+
try {
|
|
3606
|
+
const result = await fn(...args);
|
|
3607
|
+
return clipMcpToolResult(
|
|
3608
|
+
result,
|
|
3609
|
+
cwd()
|
|
3610
|
+
);
|
|
3611
|
+
} catch (err) {
|
|
3612
|
+
return {
|
|
3613
|
+
isError: true,
|
|
3614
|
+
content: [{ type: "text", text: cursorToolErrorText(err) }]
|
|
3615
|
+
};
|
|
3616
|
+
}
|
|
3601
3617
|
};
|
|
3602
3618
|
}
|
|
3603
3619
|
function wrapRegistrar(orig, cwd) {
|
|
@@ -5038,6 +5054,124 @@ function registerScheduleTools(server) {
|
|
|
5038
5054
|
// src/agent-rpc/handlers.ts
|
|
5039
5055
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5040
5056
|
import { isAbsolute } from "path";
|
|
5057
|
+
|
|
5058
|
+
// src/remote/phone-permission.ts
|
|
5059
|
+
var PHONE_CONTROL_PREFIX = "\0sb.phone\n";
|
|
5060
|
+
var DECISIONS = /* @__PURE__ */ new Set(["allow", "deny", "allow_session"]);
|
|
5061
|
+
var push = null;
|
|
5062
|
+
function setPhonePermissionPush(next) {
|
|
5063
|
+
push = next;
|
|
5064
|
+
}
|
|
5065
|
+
function notifyPhonePermission(chatId, prompt) {
|
|
5066
|
+
const id = chatId.trim();
|
|
5067
|
+
if (!id) return;
|
|
5068
|
+
push?.(id, prompt);
|
|
5069
|
+
}
|
|
5070
|
+
function permissionViewFromBlock(block) {
|
|
5071
|
+
if (!block || block.source !== "permission") return null;
|
|
5072
|
+
const prompt = block.permission;
|
|
5073
|
+
if (!prompt?.id || !prompt.title) return null;
|
|
5074
|
+
return {
|
|
5075
|
+
id: prompt.id,
|
|
5076
|
+
title: prompt.title,
|
|
5077
|
+
detail: typeof prompt.detail === "string" ? prompt.detail : "",
|
|
5078
|
+
...prompt.path ? { path: prompt.path } : {},
|
|
5079
|
+
allowSession: prompt.allowSession !== false,
|
|
5080
|
+
...prompt.defaultToNo ? { defaultToNo: true } : {}
|
|
5081
|
+
};
|
|
5082
|
+
}
|
|
5083
|
+
function phonePermissionView(chatId) {
|
|
5084
|
+
return permissionViewFromBlock(readThread(chatId)?.agentBlock);
|
|
5085
|
+
}
|
|
5086
|
+
function textField(value, key) {
|
|
5087
|
+
const raw = value[key];
|
|
5088
|
+
return typeof raw === "string" ? raw.trim() : "";
|
|
5089
|
+
}
|
|
5090
|
+
function takePhonePermission(text5) {
|
|
5091
|
+
if (!text5.startsWith(PHONE_CONTROL_PREFIX)) return null;
|
|
5092
|
+
let parsed;
|
|
5093
|
+
try {
|
|
5094
|
+
parsed = JSON.parse(text5.slice(PHONE_CONTROL_PREFIX.length));
|
|
5095
|
+
} catch {
|
|
5096
|
+
return null;
|
|
5097
|
+
}
|
|
5098
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
5099
|
+
if (parsed.op !== "permission") return null;
|
|
5100
|
+
const chatId = textField(parsed, "chatId");
|
|
5101
|
+
const id = textField(parsed, "id");
|
|
5102
|
+
const decision = textField(parsed, "decision");
|
|
5103
|
+
if (!chatId || !id || !DECISIONS.has(decision)) return "invalid";
|
|
5104
|
+
return { op: "permission", chatId, id, decision };
|
|
5105
|
+
}
|
|
5106
|
+
function dispatchPhonePermission(text5, emit) {
|
|
5107
|
+
const cmd = takePhonePermission(text5);
|
|
5108
|
+
if (cmd == null) return false;
|
|
5109
|
+
if (cmd === "invalid") {
|
|
5110
|
+
emit({ op: "error", message: "invalid phone command" });
|
|
5111
|
+
return true;
|
|
5112
|
+
}
|
|
5113
|
+
if (!answerToolPermission(cmd.id, cmd.decision)) {
|
|
5114
|
+
emit({ op: "error", chatId: cmd.chatId, message: "That request already finished." });
|
|
5115
|
+
emit({ op: "permission", chatId: cmd.chatId, prompt: phonePermissionView(cmd.chatId) });
|
|
5116
|
+
}
|
|
5117
|
+
return true;
|
|
5118
|
+
}
|
|
5119
|
+
|
|
5120
|
+
// src/agent-rpc/permission-handler.ts
|
|
5121
|
+
setToolPermissionPublisher({
|
|
5122
|
+
show(item) {
|
|
5123
|
+
const thread = readThread(item.threadId);
|
|
5124
|
+
if (!thread || thread.status === "archived") return false;
|
|
5125
|
+
writeAgentBlock(item.threadId, {
|
|
5126
|
+
source: "permission",
|
|
5127
|
+
reason: clampBlockReason(item.prompt.title),
|
|
5128
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5129
|
+
permission: item.prompt
|
|
5130
|
+
});
|
|
5131
|
+
notifyPhonePermission(item.threadId, item.prompt);
|
|
5132
|
+
return true;
|
|
5133
|
+
},
|
|
5134
|
+
clear(threadId, id) {
|
|
5135
|
+
const thread = readThread(threadId);
|
|
5136
|
+
if (thread?.agentBlock?.source === "permission" && thread.agentBlock.permission?.id === id) {
|
|
5137
|
+
updateThread(threadId, { agentBlock: null });
|
|
5138
|
+
notifyPhonePermission(threadId, null);
|
|
5139
|
+
}
|
|
5140
|
+
}
|
|
5141
|
+
});
|
|
5142
|
+
function asRecord(value) {
|
|
5143
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
5144
|
+
return value;
|
|
5145
|
+
}
|
|
5146
|
+
function str(value) {
|
|
5147
|
+
return typeof value === "string" ? value : "";
|
|
5148
|
+
}
|
|
5149
|
+
function invalidParams(message) {
|
|
5150
|
+
return Object.assign(new Error(message), { rpcCode: -32602 });
|
|
5151
|
+
}
|
|
5152
|
+
var handlePermissionAsk = async (params, _ctx) => {
|
|
5153
|
+
const rec = asRecord(params);
|
|
5154
|
+
const threadId = str(rec.threadId).trim();
|
|
5155
|
+
const toolName = str(rec.toolName).trim();
|
|
5156
|
+
if (!threadId) throw invalidParams("threadId is required");
|
|
5157
|
+
if (!toolName) throw invalidParams("toolName is required");
|
|
5158
|
+
const input = asRecord(rec.input);
|
|
5159
|
+
const ask = {
|
|
5160
|
+
threadId,
|
|
5161
|
+
toolName,
|
|
5162
|
+
input: Object.keys(input).length > 0 ? input : void 0,
|
|
5163
|
+
blockedPath: str(rec.blockedPath).trim() || void 0,
|
|
5164
|
+
title: str(rec.title).trim() || void 0,
|
|
5165
|
+
description: str(rec.description).trim() || void 0,
|
|
5166
|
+
displayName: str(rec.displayName).trim() || void 0,
|
|
5167
|
+
suggestions: rec.suggestions,
|
|
5168
|
+
suppressAlwaysAllow: rec.suppressAlwaysAllow === true,
|
|
5169
|
+
defaultToNo: rec.defaultToNo === true
|
|
5170
|
+
};
|
|
5171
|
+
return askToolPermission(ask);
|
|
5172
|
+
};
|
|
5173
|
+
|
|
5174
|
+
// src/agent-rpc/handlers.ts
|
|
5041
5175
|
function presentArtifactResult(input) {
|
|
5042
5176
|
const id = input.artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${randomUUID3().slice(0, 8)}`;
|
|
5043
5177
|
return {
|
|
@@ -5051,20 +5185,20 @@ function presentArtifactResult(input) {
|
|
|
5051
5185
|
message: input.type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
|
|
5052
5186
|
};
|
|
5053
5187
|
}
|
|
5054
|
-
function
|
|
5188
|
+
function asRecord2(value) {
|
|
5055
5189
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
5056
5190
|
return value;
|
|
5057
5191
|
}
|
|
5058
|
-
function
|
|
5192
|
+
function str2(value) {
|
|
5059
5193
|
return typeof value === "string" ? value : "";
|
|
5060
5194
|
}
|
|
5061
|
-
function
|
|
5195
|
+
function invalidParams2(message) {
|
|
5062
5196
|
return Object.assign(new Error(message), { rpcCode: -32602 });
|
|
5063
5197
|
}
|
|
5064
5198
|
function jobCwd(rec) {
|
|
5065
|
-
const raw =
|
|
5066
|
-
if (!raw) throw
|
|
5067
|
-
if (!isAbsolute(raw)) throw
|
|
5199
|
+
const raw = str2(rec.cwd).trim();
|
|
5200
|
+
if (!raw) throw invalidParams2("cwd is required");
|
|
5201
|
+
if (!isAbsolute(raw)) throw invalidParams2("cwd must be an absolute path");
|
|
5068
5202
|
return raw;
|
|
5069
5203
|
}
|
|
5070
5204
|
async function handleRuntimePing(_params, _ctx) {
|
|
@@ -5075,33 +5209,33 @@ async function handleRuntimePing(_params, _ctx) {
|
|
|
5075
5209
|
};
|
|
5076
5210
|
}
|
|
5077
5211
|
async function handlePresentArtifact(params, _ctx) {
|
|
5078
|
-
const rec =
|
|
5079
|
-
const title =
|
|
5080
|
-
const type =
|
|
5212
|
+
const rec = asRecord2(params);
|
|
5213
|
+
const title = str2(rec.title).trim();
|
|
5214
|
+
const type = str2(rec.type).trim();
|
|
5081
5215
|
const allowed = ["html", "svg", "markdown", "react", "log"];
|
|
5082
|
-
if (!title) throw
|
|
5216
|
+
if (!title) throw invalidParams2("title is required");
|
|
5083
5217
|
if (!allowed.includes(type)) {
|
|
5084
|
-
throw
|
|
5218
|
+
throw invalidParams2("type must be html, svg, markdown, react, or log");
|
|
5085
5219
|
}
|
|
5086
|
-
const statusRaw =
|
|
5220
|
+
const statusRaw = str2(rec.status).trim();
|
|
5087
5221
|
const status = ["running", "ok", "failed", "idle"].includes(
|
|
5088
5222
|
statusRaw
|
|
5089
5223
|
) ? statusRaw : void 0;
|
|
5090
|
-
const modeRaw =
|
|
5224
|
+
const modeRaw = str2(rec.mode).trim();
|
|
5091
5225
|
const mode = modeRaw === "append" || modeRaw === "replace" ? modeRaw : void 0;
|
|
5092
5226
|
return presentArtifactResult({
|
|
5093
5227
|
title,
|
|
5094
5228
|
type,
|
|
5095
|
-
artifact_id:
|
|
5229
|
+
artifact_id: str2(rec.artifact_id) || void 0,
|
|
5096
5230
|
status,
|
|
5097
|
-
phase:
|
|
5231
|
+
phase: str2(rec.phase) || void 0,
|
|
5098
5232
|
mode
|
|
5099
5233
|
});
|
|
5100
5234
|
}
|
|
5101
5235
|
async function handleJobWait(params, ctx, waitFn = waitForDetachedJob) {
|
|
5102
|
-
const rec =
|
|
5103
|
-
const id =
|
|
5104
|
-
if (!id) throw
|
|
5236
|
+
const rec = asRecord2(params);
|
|
5237
|
+
const id = str2(rec.id).trim();
|
|
5238
|
+
if (!id) throw invalidParams2("id is required");
|
|
5105
5239
|
const cwd = jobCwd(rec);
|
|
5106
5240
|
const deadline = Date.now() + AGENT_RPC_JOB_HOLD_MAX_MS;
|
|
5107
5241
|
let last;
|
|
@@ -5123,14 +5257,14 @@ async function handleJobWait(params, ctx, waitFn = waitForDetachedJob) {
|
|
|
5123
5257
|
};
|
|
5124
5258
|
}
|
|
5125
5259
|
async function handleJobStop(params, _ctx) {
|
|
5126
|
-
const rec =
|
|
5127
|
-
const id =
|
|
5128
|
-
if (!id) throw
|
|
5129
|
-
const reason =
|
|
5260
|
+
const rec = asRecord2(params);
|
|
5261
|
+
const id = str2(rec.id).trim();
|
|
5262
|
+
if (!id) throw invalidParams2("id is required");
|
|
5263
|
+
const reason = str2(rec.reason).trim() || void 0;
|
|
5130
5264
|
return stopDetachedJob(jobCwd(rec), id, reason ? { reason } : void 0);
|
|
5131
5265
|
}
|
|
5132
5266
|
async function defaultTurnWait(ref, timeoutMs) {
|
|
5133
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
5267
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-ZQU62CES.js");
|
|
5134
5268
|
const orch = getOrchestrator2();
|
|
5135
5269
|
const thread = await orch.waitForTurn(ref, timeoutMs, {
|
|
5136
5270
|
resolveIfStillRunning: true
|
|
@@ -5151,9 +5285,9 @@ async function defaultTurnWait(ref, timeoutMs) {
|
|
|
5151
5285
|
});
|
|
5152
5286
|
}
|
|
5153
5287
|
async function handleTurnWait(params, ctx, waitFn = defaultTurnWait) {
|
|
5154
|
-
const rec =
|
|
5155
|
-
const ref =
|
|
5156
|
-
if (!ref) throw
|
|
5288
|
+
const rec = asRecord2(params);
|
|
5289
|
+
const ref = str2(rec.ref).trim();
|
|
5290
|
+
if (!ref) throw invalidParams2("ref is required");
|
|
5157
5291
|
const requested = typeof rec.timeoutMs === "number" && Number.isFinite(rec.timeoutMs) ? rec.timeoutMs : void 0;
|
|
5158
5292
|
const holdMax = requested !== void 0 ? Math.min(Math.max(1e3, Math.floor(requested)), AGENT_RPC_JOB_HOLD_MAX_MS) : AGENT_RPC_JOB_HOLD_MAX_MS;
|
|
5159
5293
|
const deadline = Date.now() + holdMax;
|
|
@@ -5186,7 +5320,8 @@ function createAgentRpcDispatcher() {
|
|
|
5186
5320
|
"ui.presentArtifact": handlePresentArtifact,
|
|
5187
5321
|
"job.wait": handleJobWait,
|
|
5188
5322
|
"job.stop": handleJobStop,
|
|
5189
|
-
"turn.wait": handleTurnWait
|
|
5323
|
+
"turn.wait": handleTurnWait,
|
|
5324
|
+
"permission.ask": handlePermissionAsk
|
|
5190
5325
|
};
|
|
5191
5326
|
}
|
|
5192
5327
|
|
|
@@ -8852,7 +8987,7 @@ var BAKED_REMOTE_RELAY_URL = `wss://relay.sideboard.cloud${REMOTE_RELAY_PATH}`;
|
|
|
8852
8987
|
function remoteRelayUrl() {
|
|
8853
8988
|
return process.env.SIDEBOARD_REMOTE_RELAY_URL?.trim() || BAKED_REMOTE_RELAY_URL;
|
|
8854
8989
|
}
|
|
8855
|
-
function
|
|
8990
|
+
function str3(value) {
|
|
8856
8991
|
return typeof value === "string" ? value.trim() : "";
|
|
8857
8992
|
}
|
|
8858
8993
|
function questions(value) {
|
|
@@ -8861,14 +8996,14 @@ function questions(value) {
|
|
|
8861
8996
|
for (const item of value) {
|
|
8862
8997
|
if (!item || typeof item !== "object") return null;
|
|
8863
8998
|
const row2 = item;
|
|
8864
|
-
const question =
|
|
8999
|
+
const question = str3(row2.question);
|
|
8865
9000
|
if (!question || !Array.isArray(row2.options)) return null;
|
|
8866
9001
|
const options = [];
|
|
8867
9002
|
for (const opt of row2.options) {
|
|
8868
9003
|
if (!opt || typeof opt !== "object") return null;
|
|
8869
|
-
const label =
|
|
9004
|
+
const label = str3(opt.label);
|
|
8870
9005
|
if (!label) return null;
|
|
8871
|
-
const description =
|
|
9006
|
+
const description = str3(opt.description);
|
|
8872
9007
|
options.push(description ? { label, description } : { label });
|
|
8873
9008
|
}
|
|
8874
9009
|
if (options.length === 0) return null;
|
|
@@ -8889,11 +9024,11 @@ function parseRemoteClientMessage(raw) {
|
|
|
8889
9024
|
if (msg.type === "host_pair") return { type: "host_pair" };
|
|
8890
9025
|
if (msg.type === "stop") return { type: "stop" };
|
|
8891
9026
|
if (msg.type === "host_register") {
|
|
8892
|
-
const deviceId =
|
|
8893
|
-
const hostSecret =
|
|
8894
|
-
const deviceLabel =
|
|
9027
|
+
const deviceId = str3(parsed.deviceId);
|
|
9028
|
+
const hostSecret = str3(parsed.hostSecret);
|
|
9029
|
+
const deviceLabel = str3(parsed.deviceLabel);
|
|
8895
9030
|
if (!deviceId || !hostSecret || !deviceLabel) return null;
|
|
8896
|
-
const accountToken =
|
|
9031
|
+
const accountToken = str3(parsed.accountToken);
|
|
8897
9032
|
return {
|
|
8898
9033
|
type: "host_register",
|
|
8899
9034
|
deviceId,
|
|
@@ -8903,12 +9038,12 @@ function parseRemoteClientMessage(raw) {
|
|
|
8903
9038
|
};
|
|
8904
9039
|
}
|
|
8905
9040
|
if (msg.type === "pair") {
|
|
8906
|
-
const code =
|
|
9041
|
+
const code = str3(parsed.code).toUpperCase();
|
|
8907
9042
|
if (!code) return null;
|
|
8908
9043
|
return { type: "pair", code };
|
|
8909
9044
|
}
|
|
8910
9045
|
if (msg.type === "resume") {
|
|
8911
|
-
const sessionToken =
|
|
9046
|
+
const sessionToken = str3(parsed.sessionToken);
|
|
8912
9047
|
if (!sessionToken) return null;
|
|
8913
9048
|
return { type: "resume", sessionToken };
|
|
8914
9049
|
}
|
|
@@ -8919,19 +9054,19 @@ function parseRemoteClientMessage(raw) {
|
|
|
8919
9054
|
return { type: "list_hosts", sessionTokens };
|
|
8920
9055
|
}
|
|
8921
9056
|
if (msg.type === "prompt") {
|
|
8922
|
-
const text5 =
|
|
9057
|
+
const text5 = str3(parsed.text);
|
|
8923
9058
|
if (!text5) return null;
|
|
8924
9059
|
return { type: "prompt", text: text5 };
|
|
8925
9060
|
}
|
|
8926
9061
|
if (msg.type === "assistant") {
|
|
8927
|
-
return { type: "assistant", text:
|
|
9062
|
+
return { type: "assistant", text: str3(parsed.text) };
|
|
8928
9063
|
}
|
|
8929
9064
|
if (msg.type === "ask_user") {
|
|
8930
9065
|
const parsedQuestions = questions(parsed.questions);
|
|
8931
9066
|
if (!parsedQuestions?.length) return null;
|
|
8932
9067
|
return {
|
|
8933
9068
|
type: "ask_user",
|
|
8934
|
-
text:
|
|
9069
|
+
text: str3(parsed.text),
|
|
8935
9070
|
questions: parsedQuestions
|
|
8936
9071
|
};
|
|
8937
9072
|
}
|
|
@@ -8957,7 +9092,7 @@ function parseRemoteServerMessage(raw) {
|
|
|
8957
9092
|
for (const item of raw2) {
|
|
8958
9093
|
if (!item || typeof item !== "object") return null;
|
|
8959
9094
|
const row2 = item;
|
|
8960
|
-
const sessionToken =
|
|
9095
|
+
const sessionToken = str3(row2.sessionToken);
|
|
8961
9096
|
if (!sessionToken || typeof row2.deviceId !== "string" || typeof row2.deviceLabel !== "string") return null;
|
|
8962
9097
|
if (typeof row2.online !== "boolean") return null;
|
|
8963
9098
|
hosts.push({
|
|
@@ -8971,43 +9106,43 @@ function parseRemoteServerMessage(raw) {
|
|
|
8971
9106
|
}
|
|
8972
9107
|
if (type === "stop") return { type: "stop" };
|
|
8973
9108
|
if (type === "registered") {
|
|
8974
|
-
const deviceId =
|
|
8975
|
-
const deviceLabel =
|
|
9109
|
+
const deviceId = str3(parsed.deviceId);
|
|
9110
|
+
const deviceLabel = str3(parsed.deviceLabel);
|
|
8976
9111
|
if (!deviceId || !deviceLabel) return null;
|
|
8977
9112
|
return { type: "registered", deviceId, deviceLabel };
|
|
8978
9113
|
}
|
|
8979
9114
|
if (type === "pairing_code") {
|
|
8980
|
-
const code =
|
|
9115
|
+
const code = str3(parsed.code);
|
|
8981
9116
|
const expiresAt = parsed.expiresAt;
|
|
8982
9117
|
if (!code || typeof expiresAt !== "number") return null;
|
|
8983
9118
|
return { type: "pairing_code", code, expiresAt };
|
|
8984
9119
|
}
|
|
8985
9120
|
if (type === "inbound") {
|
|
8986
|
-
const text5 =
|
|
9121
|
+
const text5 = str3(parsed.text);
|
|
8987
9122
|
if (!text5) return null;
|
|
8988
9123
|
return { type: "inbound", text: text5 };
|
|
8989
9124
|
}
|
|
8990
9125
|
if (type === "paired") {
|
|
8991
|
-
const deviceId =
|
|
8992
|
-
const deviceLabel =
|
|
8993
|
-
const sessionToken =
|
|
9126
|
+
const deviceId = str3(parsed.deviceId);
|
|
9127
|
+
const deviceLabel = str3(parsed.deviceLabel);
|
|
9128
|
+
const sessionToken = str3(parsed.sessionToken);
|
|
8994
9129
|
if (!deviceId || !deviceLabel || !sessionToken) return null;
|
|
8995
9130
|
return { type: "paired", deviceId, deviceLabel, sessionToken };
|
|
8996
9131
|
}
|
|
8997
9132
|
if (type === "assistant") {
|
|
8998
|
-
return { type: "assistant", text:
|
|
9133
|
+
return { type: "assistant", text: str3(parsed.text) };
|
|
8999
9134
|
}
|
|
9000
9135
|
if (type === "ask_user") {
|
|
9001
9136
|
const parsedQuestions = questions(parsed.questions);
|
|
9002
9137
|
if (!parsedQuestions?.length) return null;
|
|
9003
9138
|
return {
|
|
9004
9139
|
type: "ask_user",
|
|
9005
|
-
text:
|
|
9140
|
+
text: str3(parsed.text),
|
|
9006
9141
|
questions: parsedQuestions
|
|
9007
9142
|
};
|
|
9008
9143
|
}
|
|
9009
9144
|
if (type === "error") {
|
|
9010
|
-
const message =
|
|
9145
|
+
const message = str3(parsed.message) || "remote error";
|
|
9011
9146
|
return { type: "error", message };
|
|
9012
9147
|
}
|
|
9013
9148
|
return null;
|
|
@@ -9435,10 +9570,10 @@ var MIN_MD_CHARS = 120;
|
|
|
9435
9570
|
function oneLine(value, max) {
|
|
9436
9571
|
return value.replace(/[`\r\n]/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
|
|
9437
9572
|
}
|
|
9438
|
-
function
|
|
9573
|
+
function asRecord3(value) {
|
|
9439
9574
|
if (typeof value === "string") {
|
|
9440
9575
|
try {
|
|
9441
|
-
return
|
|
9576
|
+
return asRecord3(JSON.parse(value));
|
|
9442
9577
|
} catch {
|
|
9443
9578
|
return void 0;
|
|
9444
9579
|
}
|
|
@@ -9446,7 +9581,7 @@ function asRecord2(value) {
|
|
|
9446
9581
|
if (value && typeof value === "object" && !Array.isArray(value)) return value;
|
|
9447
9582
|
return void 0;
|
|
9448
9583
|
}
|
|
9449
|
-
function
|
|
9584
|
+
function str4(value) {
|
|
9450
9585
|
return typeof value === "string" ? value : "";
|
|
9451
9586
|
}
|
|
9452
9587
|
function normalizedBody(content) {
|
|
@@ -9513,7 +9648,7 @@ function toolContent(input) {
|
|
|
9513
9648
|
if (!input) return "";
|
|
9514
9649
|
const direct = input.content;
|
|
9515
9650
|
if (typeof direct === "string") return direct;
|
|
9516
|
-
const nested =
|
|
9651
|
+
const nested = asRecord3(direct);
|
|
9517
9652
|
if (!nested) return "";
|
|
9518
9653
|
for (const key of ["html", "markup", "text", "source", "content", "code"]) {
|
|
9519
9654
|
if (typeof nested[key] === "string") return nested[key];
|
|
@@ -9536,13 +9671,13 @@ function phoneArtifactText(text5, parts, limit = Number.POSITIVE_INFINITY) {
|
|
|
9536
9671
|
const extras = [];
|
|
9537
9672
|
for (const part of parts ?? []) {
|
|
9538
9673
|
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
9539
|
-
const input =
|
|
9674
|
+
const input = asRecord3(part.input);
|
|
9540
9675
|
const content = toolContent(input);
|
|
9541
9676
|
const hint = artifactHint(content);
|
|
9542
9677
|
if (hint && hints.has(hint)) continue;
|
|
9543
9678
|
const kind = kindFor("", content);
|
|
9544
|
-
const title = oneLine(
|
|
9545
|
-
if (!
|
|
9679
|
+
const title = oneLine(str4(input?.title), 80) || (kind ? titleFor(kind, content) : "Artifact");
|
|
9680
|
+
if (!str4(input?.title) && content.trim().length < MIN_FENCE_CHARS) continue;
|
|
9546
9681
|
if (hint) hints.add(hint);
|
|
9547
9682
|
extras.push(marker(title, hint));
|
|
9548
9683
|
}
|
|
@@ -9555,11 +9690,11 @@ function phoneArtifactText(text5, parts, limit = Number.POSITIVE_INFINITY) {
|
|
|
9555
9690
|
${tail}` : tail;
|
|
9556
9691
|
}
|
|
9557
9692
|
function parseOpenArtifact(value, chatId) {
|
|
9558
|
-
const record =
|
|
9693
|
+
const record = asRecord3(value);
|
|
9559
9694
|
if (!record) return "invalid";
|
|
9560
|
-
const title = oneLine(
|
|
9695
|
+
const title = oneLine(str4(record.title), 200);
|
|
9561
9696
|
if (!title) return "invalid";
|
|
9562
|
-
const hint = oneLine(
|
|
9697
|
+
const hint = oneLine(str4(record.hint), 200);
|
|
9563
9698
|
return { op: "open-artifact", chatId, title, ...hint ? { hint } : {} };
|
|
9564
9699
|
}
|
|
9565
9700
|
var PHONE_ARTIFACT_MAX_CHARS = 18e4;
|
|
@@ -9578,13 +9713,13 @@ function phoneArtifactDocuments(sources) {
|
|
|
9578
9713
|
}
|
|
9579
9714
|
for (const part of source.parts ?? []) {
|
|
9580
9715
|
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
9581
|
-
const input =
|
|
9716
|
+
const input = asRecord3(part.input);
|
|
9582
9717
|
const content = toolContent(input);
|
|
9583
9718
|
const hint = artifactHint(content);
|
|
9584
9719
|
if (hint && hints.has(hint)) continue;
|
|
9585
|
-
const typed = kindFor(
|
|
9586
|
-
const title = oneLine(
|
|
9587
|
-
if (!
|
|
9720
|
+
const typed = kindFor(str4(input?.type), content) ?? kindFor("", content);
|
|
9721
|
+
const title = oneLine(str4(input?.title), 80) || (typed ? titleFor(typed, content) : "Artifact");
|
|
9722
|
+
if (!str4(input?.title) && content.trim().length < MIN_FENCE_CHARS) continue;
|
|
9588
9723
|
if (hint) hints.add(hint);
|
|
9589
9724
|
docs.push({ title, content, kind: typed ?? "text" });
|
|
9590
9725
|
}
|
|
@@ -9629,13 +9764,21 @@ function pickArtifactMatch(items, request) {
|
|
|
9629
9764
|
}
|
|
9630
9765
|
|
|
9631
9766
|
// src/remote/phone-panes.ts
|
|
9767
|
+
var PHONE_CHANGE_SCOPES = ["last_turn", "uncommitted", "staged", "unstaged", "commits"];
|
|
9768
|
+
var PHONE_CHANGE_SCOPE_DEFAULT = "commits";
|
|
9769
|
+
function phoneChangeScope(value) {
|
|
9770
|
+
return typeof value === "string" && PHONE_CHANGE_SCOPES.includes(value) ? value : void 0;
|
|
9771
|
+
}
|
|
9772
|
+
function phoneCommitSha(value) {
|
|
9773
|
+
return typeof value === "string" && /^[0-9a-f]{4,40}$/i.test(value) ? value : void 0;
|
|
9774
|
+
}
|
|
9632
9775
|
var MAX_ROWS = 200;
|
|
9633
9776
|
var MAX_QUERY = 200;
|
|
9634
9777
|
function parsePhonePane(value, chatId) {
|
|
9635
9778
|
const pane = value && typeof value === "object" ? value.pane : void 0;
|
|
9636
9779
|
if (pane !== "files" && pane !== "changes" && pane !== "checks") return "invalid";
|
|
9637
|
-
const
|
|
9638
|
-
const
|
|
9780
|
+
const scope = phoneChangeScope(value.scope);
|
|
9781
|
+
const commitSha = phoneCommitSha(value.commitSha);
|
|
9639
9782
|
const queryRaw = value.query;
|
|
9640
9783
|
const query = typeof queryRaw === "string" ? queryRaw.trim().slice(0, MAX_QUERY) : "";
|
|
9641
9784
|
return {
|
|
@@ -9643,6 +9786,7 @@ function parsePhonePane(value, chatId) {
|
|
|
9643
9786
|
chatId,
|
|
9644
9787
|
pane,
|
|
9645
9788
|
...scope && pane === "changes" ? { scope } : {},
|
|
9789
|
+
...commitSha && pane === "changes" && scope === "commits" ? { commitSha } : {},
|
|
9646
9790
|
...query && pane === "files" ? { query } : {}
|
|
9647
9791
|
};
|
|
9648
9792
|
}
|
|
@@ -9651,10 +9795,10 @@ function filterPhoneFiles(paths, query) {
|
|
|
9651
9795
|
if (!q) return paths;
|
|
9652
9796
|
return paths.filter((path2) => path2.toLowerCase().includes(q));
|
|
9653
9797
|
}
|
|
9654
|
-
async function readPhonePane(thread, pane, scope, query) {
|
|
9798
|
+
async function readPhonePane(thread, pane, scope, query, commitSha) {
|
|
9655
9799
|
try {
|
|
9656
9800
|
if (pane === "files") return await readFiles(thread.id, query);
|
|
9657
|
-
if (pane === "changes") return await readChanges(thread.id, scope ??
|
|
9801
|
+
if (pane === "changes") return await readChanges(thread.id, scope ?? PHONE_CHANGE_SCOPE_DEFAULT, commitSha);
|
|
9658
9802
|
return await readChecks(thread.id);
|
|
9659
9803
|
} catch (err) {
|
|
9660
9804
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -9671,9 +9815,14 @@ async function readFiles(threadId, query) {
|
|
|
9671
9815
|
...note ? { note } : {}
|
|
9672
9816
|
};
|
|
9673
9817
|
}
|
|
9674
|
-
async function readChanges(threadId, scope) {
|
|
9675
|
-
const diff = await getOrchestrator().diff(threadId, {
|
|
9818
|
+
async function readChanges(threadId, scope, commitSha) {
|
|
9819
|
+
const diff = await getOrchestrator().diff(threadId, {
|
|
9820
|
+
includePatches: false,
|
|
9821
|
+
scope,
|
|
9822
|
+
commitSha: scope === "commits" ? commitSha ?? null : null
|
|
9823
|
+
});
|
|
9676
9824
|
const shown = diff.files.slice(0, MAX_ROWS);
|
|
9825
|
+
const selected = diff.commits.find((commit) => commit.sha === commitSha || commit.shortSha === commitSha);
|
|
9677
9826
|
return {
|
|
9678
9827
|
rows: shown.map((file) => {
|
|
9679
9828
|
const detail = changeDetail(file.additions, file.deletions);
|
|
@@ -9684,7 +9833,13 @@ async function readChanges(threadId, scope) {
|
|
|
9684
9833
|
...detail ? { detail } : {}
|
|
9685
9834
|
};
|
|
9686
9835
|
}),
|
|
9687
|
-
...diff.files.length > shown.length ? { note: `${diff.files.length - shown.length} more changed files` } : {}
|
|
9836
|
+
...diff.files.length > shown.length ? { note: `${diff.files.length - shown.length} more changed files` } : {},
|
|
9837
|
+
scope: diff.scope,
|
|
9838
|
+
commitSha: selected?.sha ?? null,
|
|
9839
|
+
...diff.base ? { base: diff.base } : {},
|
|
9840
|
+
hasLastTurnBase: diff.hasLastTurnBase,
|
|
9841
|
+
commits: diff.commits.slice(0, 40),
|
|
9842
|
+
scopeStats: diff.scopeStats
|
|
9688
9843
|
};
|
|
9689
9844
|
}
|
|
9690
9845
|
function changeDetail(additions, deletions) {
|
|
@@ -9693,13 +9848,14 @@ function changeDetail(additions, deletions) {
|
|
|
9693
9848
|
if (add === 0 && del === 0) return void 0;
|
|
9694
9849
|
return `+${add} \u2212${del}`;
|
|
9695
9850
|
}
|
|
9696
|
-
async function readPhoneChangePatch(threadId, path2) {
|
|
9851
|
+
async function readPhoneChangePatch(threadId, path2, scope = PHONE_CHANGE_SCOPE_DEFAULT, commitSha) {
|
|
9697
9852
|
const diff = await getOrchestrator().diff(threadId, {
|
|
9698
9853
|
path: path2,
|
|
9699
|
-
scope
|
|
9854
|
+
scope,
|
|
9855
|
+
commitSha: scope === "commits" ? commitSha ?? null : null,
|
|
9700
9856
|
includePatches: true,
|
|
9701
9857
|
includeMeta: false,
|
|
9702
|
-
includeUntracked:
|
|
9858
|
+
includeUntracked: scope === "uncommitted" || scope === "unstaged" || scope === "last_turn" || scope === "commits" && !commitSha
|
|
9703
9859
|
});
|
|
9704
9860
|
const file = diff.files.find((row2) => row2.path === path2) ?? diff.files[0];
|
|
9705
9861
|
if (!file) return null;
|
|
@@ -10044,7 +10200,7 @@ function listPhoneHistory(opts) {
|
|
|
10044
10200
|
}
|
|
10045
10201
|
|
|
10046
10202
|
// src/remote/phone-chats.ts
|
|
10047
|
-
var
|
|
10203
|
+
var PHONE_CONTROL_PREFIX2 = "\0sb.phone\n";
|
|
10048
10204
|
var PREVIEW_LIMIT2 = 90;
|
|
10049
10205
|
var AGENT_KINDS = /* @__PURE__ */ new Set(["claude", "codex", "opencode", "brightsy", "cursor"]);
|
|
10050
10206
|
var MAX_PHONE_FILES = 8;
|
|
@@ -10052,13 +10208,13 @@ var MAX_PHONE_FILE_CHARS = Math.ceil(8 * 1024 * 1024 * 4 / 3);
|
|
|
10052
10208
|
var MAX_PHONE_FILES_CHARS = Math.ceil(20 * 1024 * 1024 * 4 / 3);
|
|
10053
10209
|
var MAX_DICTATION_CHARS = Math.ceil(12 * 1024 * 1024 * 4 / 3);
|
|
10054
10210
|
function encodePhoneControl(payload) {
|
|
10055
|
-
return
|
|
10211
|
+
return PHONE_CONTROL_PREFIX2 + JSON.stringify(payload);
|
|
10056
10212
|
}
|
|
10057
10213
|
function takePhoneControl(text5) {
|
|
10058
|
-
if (!text5.startsWith(
|
|
10214
|
+
if (!text5.startsWith(PHONE_CONTROL_PREFIX2)) return null;
|
|
10059
10215
|
let parsed;
|
|
10060
10216
|
try {
|
|
10061
|
-
parsed = JSON.parse(text5.slice(
|
|
10217
|
+
parsed = JSON.parse(text5.slice(PHONE_CONTROL_PREFIX2.length));
|
|
10062
10218
|
} catch {
|
|
10063
10219
|
return "invalid";
|
|
10064
10220
|
}
|
|
@@ -10069,14 +10225,14 @@ function parsePhoneControl(value) {
|
|
|
10069
10225
|
const op = value.op;
|
|
10070
10226
|
if (op === "list") return { op: "list" };
|
|
10071
10227
|
if (op === "history") {
|
|
10072
|
-
const query =
|
|
10073
|
-
const after =
|
|
10228
|
+
const query = textField2(value, "query");
|
|
10229
|
+
const after = textField2(value, "after");
|
|
10074
10230
|
return { op: "history", ...query ? { query } : {}, ...after ? { after } : {} };
|
|
10075
10231
|
}
|
|
10076
10232
|
if (op === "sources") {
|
|
10077
|
-
const repoPath =
|
|
10233
|
+
const repoPath = textField2(value, "repoPath");
|
|
10078
10234
|
if (!repoPath || !isProjectPath2(repoPath)) return "invalid";
|
|
10079
|
-
const query =
|
|
10235
|
+
const query = textField2(value, "query");
|
|
10080
10236
|
return { op: "sources", repoPath, ...query ? { query } : {} };
|
|
10081
10237
|
}
|
|
10082
10238
|
if (op === "models") {
|
|
@@ -10085,7 +10241,7 @@ function parsePhoneControl(value) {
|
|
|
10085
10241
|
return { op: "models", agent };
|
|
10086
10242
|
}
|
|
10087
10243
|
if (op === "dictate") {
|
|
10088
|
-
const id =
|
|
10244
|
+
const id = textField2(value, "id");
|
|
10089
10245
|
const audioBase64 = base64Field(value, "audioBase64");
|
|
10090
10246
|
if (!id || !audioBase64 || audioBase64.length > MAX_DICTATION_CHARS) return "invalid";
|
|
10091
10247
|
return { op: "dictate", id, audioBase64 };
|
|
@@ -10097,26 +10253,30 @@ function parsePhoneControl(value) {
|
|
|
10097
10253
|
return { op, chatId };
|
|
10098
10254
|
}
|
|
10099
10255
|
if (op === "git") {
|
|
10100
|
-
const action =
|
|
10256
|
+
const action = textField2(value, "action");
|
|
10101
10257
|
if (!PHONE_HEADER_GIT_ACTIONS.includes(action)) return "invalid";
|
|
10102
10258
|
return { op: "git", chatId, action };
|
|
10103
10259
|
}
|
|
10104
10260
|
if (op === "pane") return parsePhonePane(value, chatId);
|
|
10105
10261
|
if (op === "open-artifact") return parseOpenArtifact(value, chatId);
|
|
10106
10262
|
if (op === "open-file" || op === "media") {
|
|
10107
|
-
const path2 =
|
|
10263
|
+
const path2 = textField2(value, "path");
|
|
10108
10264
|
if (!path2 || path2.length > 2e3) return "invalid";
|
|
10109
10265
|
if (op === "media") return { op, chatId, path: path2 };
|
|
10110
10266
|
const startLine = lineField(value, "startLine");
|
|
10111
10267
|
const endLine = lineField(value, "endLine");
|
|
10112
|
-
const view =
|
|
10268
|
+
const view = textField2(value, "view") === "diff" ? "diff" : void 0;
|
|
10269
|
+
const scope = phoneChangeScope(value.scope);
|
|
10270
|
+
const commitSha = phoneCommitSha(value.commitSha);
|
|
10113
10271
|
return {
|
|
10114
10272
|
op,
|
|
10115
10273
|
chatId,
|
|
10116
10274
|
path: path2,
|
|
10117
10275
|
...startLine != null ? { startLine } : {},
|
|
10118
10276
|
...endLine != null ? { endLine } : {},
|
|
10119
|
-
...view ? { view } : {}
|
|
10277
|
+
...view ? { view } : {},
|
|
10278
|
+
...view && scope ? { scope } : {},
|
|
10279
|
+
...view && scope === "commits" && commitSha ? { commitSha } : {}
|
|
10120
10280
|
};
|
|
10121
10281
|
}
|
|
10122
10282
|
const draft = parsePhoneDraft(value);
|
|
@@ -10130,7 +10290,7 @@ function parsePhoneControl(value) {
|
|
|
10130
10290
|
}
|
|
10131
10291
|
return "invalid";
|
|
10132
10292
|
}
|
|
10133
|
-
function
|
|
10293
|
+
function textField2(value, key) {
|
|
10134
10294
|
const raw = value[key];
|
|
10135
10295
|
return typeof raw === "string" ? raw.trim() : "";
|
|
10136
10296
|
}
|
|
@@ -10140,7 +10300,7 @@ function lineField(value, key) {
|
|
|
10140
10300
|
return raw;
|
|
10141
10301
|
}
|
|
10142
10302
|
function agentField(value) {
|
|
10143
|
-
const agent =
|
|
10303
|
+
const agent = textField2(value, "agent");
|
|
10144
10304
|
if (!agent) return void 0;
|
|
10145
10305
|
return AGENT_KINDS.has(agent) ? agent : void 0;
|
|
10146
10306
|
}
|
|
@@ -10151,7 +10311,7 @@ function base64Field(value, key) {
|
|
|
10151
10311
|
}
|
|
10152
10312
|
function parsePhoneDraft(value) {
|
|
10153
10313
|
const draft = {};
|
|
10154
|
-
if (
|
|
10314
|
+
if (textField2(value, "agent")) {
|
|
10155
10315
|
const agent = agentField(value);
|
|
10156
10316
|
if (!agent) return "invalid";
|
|
10157
10317
|
draft.agent = agent;
|
|
@@ -10191,7 +10351,7 @@ function parsePhoneDraft(value) {
|
|
|
10191
10351
|
const refs = parsePhoneCodeRefs(value.refs);
|
|
10192
10352
|
if (refs === "invalid") return "invalid";
|
|
10193
10353
|
if (refs.length) draft.refs = refs;
|
|
10194
|
-
const prompt =
|
|
10354
|
+
const prompt = textField2(value, "prompt");
|
|
10195
10355
|
if (prompt) draft.prompt = prompt.slice(0, 2e4);
|
|
10196
10356
|
return draft;
|
|
10197
10357
|
}
|
|
@@ -10202,7 +10362,7 @@ function parsePhoneFiles(value) {
|
|
|
10202
10362
|
let total = 0;
|
|
10203
10363
|
for (const item of value) {
|
|
10204
10364
|
if (!item || typeof item !== "object") return "invalid";
|
|
10205
|
-
const name = (
|
|
10365
|
+
const name = (textField2(item, "name").replace(/[/\\]/g, "_") || "file").slice(0, 180);
|
|
10206
10366
|
const dataBase64 = base64Field(item, "dataBase64");
|
|
10207
10367
|
if (!dataBase64 || !/^[A-Za-z0-9+/=]+$/.test(dataBase64)) return "invalid";
|
|
10208
10368
|
if (dataBase64.length > MAX_PHONE_FILE_CHARS) return "invalid";
|
|
@@ -10218,10 +10378,10 @@ function parsePhoneLinks(value) {
|
|
|
10218
10378
|
const links = [];
|
|
10219
10379
|
for (const item of value) {
|
|
10220
10380
|
if (!item || typeof item !== "object") return "invalid";
|
|
10221
|
-
const ref =
|
|
10381
|
+
const ref = textField2(item, "ref").slice(0, 80);
|
|
10222
10382
|
if (!ref) return "invalid";
|
|
10223
|
-
const title = (
|
|
10224
|
-
const url =
|
|
10383
|
+
const title = (textField2(item, "title") || ref).slice(0, 200);
|
|
10384
|
+
const url = textField2(item, "url").slice(0, 500);
|
|
10225
10385
|
links.push({ ref, title, ...url ? { url } : {} });
|
|
10226
10386
|
}
|
|
10227
10387
|
return links;
|
|
@@ -10229,7 +10389,7 @@ function parsePhoneLinks(value) {
|
|
|
10229
10389
|
function parsePhoneCreate(value) {
|
|
10230
10390
|
const draft = parsePhoneDraft(value);
|
|
10231
10391
|
if (draft === "invalid") return "invalid";
|
|
10232
|
-
const goal =
|
|
10392
|
+
const goal = textField2(value, "goal") || draft.prompt || "";
|
|
10233
10393
|
const where = value.where;
|
|
10234
10394
|
if (where == null || where === "orchestration") {
|
|
10235
10395
|
return {
|
|
@@ -10240,20 +10400,20 @@ function parsePhoneCreate(value) {
|
|
|
10240
10400
|
};
|
|
10241
10401
|
}
|
|
10242
10402
|
if (where === "worktree") {
|
|
10243
|
-
const chatId =
|
|
10403
|
+
const chatId = textField2(value, "chatId");
|
|
10244
10404
|
if (!chatId) return "invalid";
|
|
10245
10405
|
return { op: "create", where: "worktree", chatId, ...draft };
|
|
10246
10406
|
}
|
|
10247
10407
|
if (where === "project") {
|
|
10248
|
-
const repoPath =
|
|
10408
|
+
const repoPath = textField2(value, "repoPath");
|
|
10249
10409
|
if (!repoPath || !isProjectPath2(repoPath)) return "invalid";
|
|
10250
|
-
const sourceRaw =
|
|
10410
|
+
const sourceRaw = textField2(value, "sourceType");
|
|
10251
10411
|
let sourceType;
|
|
10252
10412
|
if (sourceRaw === "branch" || sourceRaw === "pr" || sourceRaw === "ticket") sourceType = sourceRaw;
|
|
10253
10413
|
else if (sourceRaw) return "invalid";
|
|
10254
|
-
const sourceRef =
|
|
10414
|
+
const sourceRef = textField2(value, "sourceRef");
|
|
10255
10415
|
if ((sourceType === "pr" || sourceType === "ticket") && !sourceRef) return "invalid";
|
|
10256
|
-
const title =
|
|
10416
|
+
const title = textField2(value, "title").slice(0, 200);
|
|
10257
10417
|
const cowboy = value.cowboy === true;
|
|
10258
10418
|
return {
|
|
10259
10419
|
op: "create",
|
|
@@ -10522,14 +10682,22 @@ function dispatchPhoneWorkspace(cmd, emit, publishOpened) {
|
|
|
10522
10682
|
emit({ op: "error", chatId: cmd.chatId, message: "That agent is not on this Mac." });
|
|
10523
10683
|
return;
|
|
10524
10684
|
}
|
|
10525
|
-
void readPhonePane(thread, cmd.pane, cmd.scope, cmd.query).then((body) => {
|
|
10685
|
+
void readPhonePane(thread, cmd.pane, cmd.scope, cmd.query, cmd.commitSha).then((body) => {
|
|
10526
10686
|
emit({
|
|
10527
10687
|
op: "pane",
|
|
10528
10688
|
chatId: cmd.chatId,
|
|
10529
10689
|
pane: cmd.pane,
|
|
10530
10690
|
rows: body.rows,
|
|
10531
10691
|
...body.note ? { note: body.note } : {},
|
|
10532
|
-
...cmd.pane === "files" ? { query: cmd.query ?? "" } : {}
|
|
10692
|
+
...cmd.pane === "files" ? { query: cmd.query ?? "" } : {},
|
|
10693
|
+
...cmd.pane === "changes" ? {
|
|
10694
|
+
scope: body.scope,
|
|
10695
|
+
commitSha: body.commitSha ?? null,
|
|
10696
|
+
...body.base ? { base: body.base } : {},
|
|
10697
|
+
hasLastTurnBase: body.hasLastTurnBase,
|
|
10698
|
+
commits: body.commits ?? [],
|
|
10699
|
+
...body.scopeStats ? { scopeStats: body.scopeStats } : {}
|
|
10700
|
+
} : {}
|
|
10533
10701
|
});
|
|
10534
10702
|
});
|
|
10535
10703
|
return;
|
|
@@ -10898,7 +11066,7 @@ function beginCoordinatorPrompt(body, opts) {
|
|
|
10898
11066
|
// src/remote/listen.ts
|
|
10899
11067
|
function emitOpened(opts, opened) {
|
|
10900
11068
|
setPhoneOpenChat(opened.chat.id);
|
|
10901
|
-
emitControl(opts, { op: "opened", ...opened });
|
|
11069
|
+
emitControl(opts, { op: "opened", ...opened, permission: phonePermissionView(opened.chat.id) });
|
|
10902
11070
|
}
|
|
10903
11071
|
function publishOpenedChat(opts, chatId) {
|
|
10904
11072
|
const opened = openPhoneChat(chatId);
|
|
@@ -11126,7 +11294,7 @@ function handlePhoneControl(cmd, opts) {
|
|
|
11126
11294
|
return;
|
|
11127
11295
|
}
|
|
11128
11296
|
if (cmd.view === "diff") {
|
|
11129
|
-
void readPhoneChangePatch(thread.id, relative).then((body) => {
|
|
11297
|
+
void readPhoneChangePatch(thread.id, relative, cmd.scope, cmd.commitSha).then((body) => {
|
|
11130
11298
|
if (!body) {
|
|
11131
11299
|
emitControl(opts, { op: "error", chatId: cmd.chatId, message: "That file has no changes to show." });
|
|
11132
11300
|
return;
|
|
@@ -11280,6 +11448,7 @@ function runPhonePrompt(opts, cmd, chatId, generation) {
|
|
|
11280
11448
|
}
|
|
11281
11449
|
function handleRemoteInbound(text5, opts) {
|
|
11282
11450
|
const body = text5.trim();
|
|
11451
|
+
if (dispatchPhonePermission(body, (reply) => emitControl(opts, reply))) return;
|
|
11283
11452
|
const control = takePhoneControl(body);
|
|
11284
11453
|
if (control) {
|
|
11285
11454
|
if (control === "invalid") {
|
|
@@ -11354,7 +11523,7 @@ function startPhoneBoardSync(opts) {
|
|
|
11354
11523
|
let timer = null;
|
|
11355
11524
|
let lastKey = "";
|
|
11356
11525
|
let stopped = false;
|
|
11357
|
-
const
|
|
11526
|
+
const push2 = () => {
|
|
11358
11527
|
timer = null;
|
|
11359
11528
|
if (stopped) return;
|
|
11360
11529
|
let sidebar;
|
|
@@ -11371,7 +11540,7 @@ function startPhoneBoardSync(opts) {
|
|
|
11371
11540
|
const schedule = () => {
|
|
11372
11541
|
if (stopped) return;
|
|
11373
11542
|
if (timer) clearTimeout(timer);
|
|
11374
|
-
timer = setTimeout(
|
|
11543
|
+
timer = setTimeout(push2, debounceMs);
|
|
11375
11544
|
};
|
|
11376
11545
|
const handle = (event) => {
|
|
11377
11546
|
if (isPhoneBoardEvent(event)) schedule();
|
|
@@ -11381,13 +11550,13 @@ function startPhoneBoardSync(opts) {
|
|
|
11381
11550
|
};
|
|
11382
11551
|
const unsubscribe = (opts.subscribe ?? subscribePhoneBoard)(schedule);
|
|
11383
11552
|
const offEvents = (opts.events ?? ((listener) => getOrchestrator().on(listener)))(handle);
|
|
11384
|
-
|
|
11553
|
+
push2();
|
|
11385
11554
|
let loginTimer = null;
|
|
11386
11555
|
const refreshViewerLogin = opts.refreshViewerLogin;
|
|
11387
11556
|
if (refreshViewerLogin) {
|
|
11388
11557
|
const afterLogin = () => {
|
|
11389
11558
|
void refreshViewerLogin().then(() => {
|
|
11390
|
-
if (!stopped)
|
|
11559
|
+
if (!stopped) push2();
|
|
11391
11560
|
});
|
|
11392
11561
|
};
|
|
11393
11562
|
afterLogin();
|
|
@@ -11624,6 +11793,10 @@ function runRemoteHost(opts) {
|
|
|
11624
11793
|
}
|
|
11625
11794
|
send3({ type: "ask_user", text: outbound.text, questions: outbound.questions });
|
|
11626
11795
|
};
|
|
11796
|
+
setPhonePermissionPush((chatId, prompt) => {
|
|
11797
|
+
if (getPhoneOpenChat() !== chatId) return;
|
|
11798
|
+
emitControl({ onOutbound: emit }, { op: "permission", chatId, prompt });
|
|
11799
|
+
});
|
|
11627
11800
|
void loop();
|
|
11628
11801
|
return {
|
|
11629
11802
|
requestPairingCode() {
|
|
@@ -13243,7 +13416,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
13243
13416
|
await continueOnReply(threadId, prompt);
|
|
13244
13417
|
return;
|
|
13245
13418
|
}
|
|
13246
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
13419
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-ZQU62CES.js");
|
|
13247
13420
|
await getOrchestrator2().send(threadId, prompt);
|
|
13248
13421
|
} catch {
|
|
13249
13422
|
}
|
|
@@ -13685,6 +13858,7 @@ export {
|
|
|
13685
13858
|
allocateTeamName,
|
|
13686
13859
|
allocateTeamSlug,
|
|
13687
13860
|
annotateDevAccessRuns,
|
|
13861
|
+
answerToolPermission,
|
|
13688
13862
|
appDataDir,
|
|
13689
13863
|
appSettingsPath,
|
|
13690
13864
|
appendCompactedMessages,
|