@sideboard-ai/core 0.1.289 → 0.1.291
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-EBGJXOXT.js → chunk-4VXWLY3L.js} +3 -2
- package/dist/{chunk-C546EOEF.js → chunk-QOUTSISS.js} +3 -2
- package/dist/index.cjs +599 -98
- package/dist/index.js +565 -75
- package/dist/mcp/run-stdio.cjs +2 -1
- package/dist/mcp/run-stdio.js +1 -1
- package/dist/{orchestrator-MKF3YBNK.js → orchestrator-EQSK2RMI.js} +1 -1
- package/dist/{orchestrator-IG4VU7MT.js → orchestrator-GSOW3RPA.js} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -186,7 +186,7 @@ import {
|
|
|
186
186
|
worktreeBoardStatus,
|
|
187
187
|
worktreeCleanupSettings,
|
|
188
188
|
writeWorktreeFile
|
|
189
|
-
} from "./chunk-
|
|
189
|
+
} from "./chunk-QOUTSISS.js";
|
|
190
190
|
import {
|
|
191
191
|
LEGACY_PLAN_FILE_REL,
|
|
192
192
|
PLAN_FILE_NAME,
|
|
@@ -5126,7 +5126,7 @@ async function handleJobStop(params, _ctx) {
|
|
|
5126
5126
|
return stopDetachedJob(jobCwd(rec), id, reason ? { reason } : void 0);
|
|
5127
5127
|
}
|
|
5128
5128
|
async function defaultTurnWait(ref, timeoutMs) {
|
|
5129
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
5129
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-GSOW3RPA.js");
|
|
5130
5130
|
const orch = getOrchestrator2();
|
|
5131
5131
|
const thread = await orch.waitForTurn(ref, timeoutMs, {
|
|
5132
5132
|
resolveIfStillRunning: true
|
|
@@ -9303,7 +9303,11 @@ var RemoteHub = class {
|
|
|
9303
9303
|
import { WebSocket as WsWebSocket3 } from "ws";
|
|
9304
9304
|
|
|
9305
9305
|
// src/remote/phone-media.ts
|
|
9306
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
9307
|
+
import { join as join6 } from "path";
|
|
9306
9308
|
var PHONE_IMAGE_MAX_BYTES = 15e5;
|
|
9309
|
+
var PHONE_TEXT_MAX_BYTES = 18e4;
|
|
9310
|
+
var PHONE_DIR_MAX = 200;
|
|
9307
9311
|
var IMAGE_MIME = {
|
|
9308
9312
|
png: "image/png",
|
|
9309
9313
|
jpg: "image/jpeg",
|
|
@@ -9350,9 +9354,74 @@ function phoneImageDataUrl(worktreePath, raw) {
|
|
|
9350
9354
|
return null;
|
|
9351
9355
|
}
|
|
9352
9356
|
}
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9357
|
+
function phoneDirectoryListing(worktreePath, relative) {
|
|
9358
|
+
try {
|
|
9359
|
+
const entries = readdirSync2(join6(worktreePath, relative), { withFileTypes: true });
|
|
9360
|
+
const dirs = new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
|
|
9361
|
+
const names = entries.map((entry) => entry.name).filter((name) => name && !name.includes("/") && !name.includes("\0")).sort((a, b) => a.localeCompare(b));
|
|
9362
|
+
const shown = names.slice(0, PHONE_DIR_MAX);
|
|
9363
|
+
const lines = shown.map((name) => dirs.has(name) ? `${name}/` : name);
|
|
9364
|
+
const truncated = names.length > shown.length;
|
|
9365
|
+
if (truncated) lines.push(`\u2026 ${names.length - shown.length} more`);
|
|
9366
|
+
return { content: lines.join("\n"), truncated };
|
|
9367
|
+
} catch {
|
|
9368
|
+
return null;
|
|
9369
|
+
}
|
|
9370
|
+
}
|
|
9371
|
+
function phoneFilePreview(worktreePath, relative, kind) {
|
|
9372
|
+
if (kind === "dir") {
|
|
9373
|
+
const listing = phoneDirectoryListing(worktreePath, relative);
|
|
9374
|
+
if (!listing) return null;
|
|
9375
|
+
return {
|
|
9376
|
+
content: listing.content,
|
|
9377
|
+
encoding: "utf8",
|
|
9378
|
+
binary: false,
|
|
9379
|
+
directory: true,
|
|
9380
|
+
truncated: listing.truncated
|
|
9381
|
+
};
|
|
9382
|
+
}
|
|
9383
|
+
if (relative.toLowerCase().endsWith(".svg")) {
|
|
9384
|
+
try {
|
|
9385
|
+
const buf = readFileSync5(join6(worktreePath, relative));
|
|
9386
|
+
const truncated = buf.length > PHONE_TEXT_MAX_BYTES;
|
|
9387
|
+
return {
|
|
9388
|
+
content: buf.subarray(0, PHONE_TEXT_MAX_BYTES).toString("utf8"),
|
|
9389
|
+
encoding: "utf8",
|
|
9390
|
+
binary: false,
|
|
9391
|
+
directory: false,
|
|
9392
|
+
truncated,
|
|
9393
|
+
mime: "image/svg+xml"
|
|
9394
|
+
};
|
|
9395
|
+
} catch {
|
|
9396
|
+
return null;
|
|
9397
|
+
}
|
|
9398
|
+
}
|
|
9399
|
+
const mime = phoneImageMime(relative);
|
|
9400
|
+
if (mime) {
|
|
9401
|
+
const dataUrl = phoneImageDataUrl(worktreePath, relative);
|
|
9402
|
+
if (!dataUrl) return null;
|
|
9403
|
+
return {
|
|
9404
|
+
content: dataUrl,
|
|
9405
|
+
encoding: "base64",
|
|
9406
|
+
binary: true,
|
|
9407
|
+
directory: false,
|
|
9408
|
+
truncated: false,
|
|
9409
|
+
mime
|
|
9410
|
+
};
|
|
9411
|
+
}
|
|
9412
|
+
try {
|
|
9413
|
+
const file = readWorktreeFile(worktreePath, relative, { maxBytes: PHONE_TEXT_MAX_BYTES });
|
|
9414
|
+
return {
|
|
9415
|
+
content: file.content,
|
|
9416
|
+
encoding: file.encoding,
|
|
9417
|
+
binary: file.binary,
|
|
9418
|
+
directory: false,
|
|
9419
|
+
truncated: file.truncated
|
|
9420
|
+
};
|
|
9421
|
+
} catch {
|
|
9422
|
+
return null;
|
|
9423
|
+
}
|
|
9424
|
+
}
|
|
9356
9425
|
|
|
9357
9426
|
// src/remote/phone-artifact.ts
|
|
9358
9427
|
var FENCE_RE = /```([a-zA-Z0-9_+-]*)[^\n]*\n([\s\S]*?)(?:```|$)/g;
|
|
@@ -9489,6 +9558,309 @@ function parseOpenArtifact(value, chatId) {
|
|
|
9489
9558
|
const hint = oneLine(str3(record.hint), 200);
|
|
9490
9559
|
return { op: "open-artifact", chatId, title, ...hint ? { hint } : {} };
|
|
9491
9560
|
}
|
|
9561
|
+
var PHONE_ARTIFACT_MAX_CHARS = 18e4;
|
|
9562
|
+
function phoneArtifactDocuments(sources) {
|
|
9563
|
+
const docs = [];
|
|
9564
|
+
for (const source of sources) {
|
|
9565
|
+
const hints = /* @__PURE__ */ new Set();
|
|
9566
|
+
for (const match of source.text.matchAll(new RegExp(FENCE_RE.source, "g"))) {
|
|
9567
|
+
const language = match[1] ?? "";
|
|
9568
|
+
const content = match[2] ?? "";
|
|
9569
|
+
const kind = kindFor(language, content);
|
|
9570
|
+
if (!kind) continue;
|
|
9571
|
+
const hint = artifactHint(content);
|
|
9572
|
+
if (hint) hints.add(hint);
|
|
9573
|
+
docs.push({ title: titleFor(kind, content), content, kind });
|
|
9574
|
+
}
|
|
9575
|
+
for (const part of source.parts ?? []) {
|
|
9576
|
+
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
9577
|
+
const input = asRecord2(part.input);
|
|
9578
|
+
const content = toolContent(input);
|
|
9579
|
+
const hint = artifactHint(content);
|
|
9580
|
+
if (hint && hints.has(hint)) continue;
|
|
9581
|
+
const typed = kindFor(str3(input?.type), content) ?? kindFor("", content);
|
|
9582
|
+
const title = oneLine(str3(input?.title), 80) || (typed ? titleFor(typed, content) : "Artifact");
|
|
9583
|
+
if (!str3(input?.title) && content.trim().length < MIN_FENCE_CHARS) continue;
|
|
9584
|
+
if (hint) hints.add(hint);
|
|
9585
|
+
docs.push({ title, content, kind: typed ?? "text" });
|
|
9586
|
+
}
|
|
9587
|
+
}
|
|
9588
|
+
return docs;
|
|
9589
|
+
}
|
|
9590
|
+
function phoneArtifactReply(docs, request) {
|
|
9591
|
+
const match = pickArtifactMatch(docs, request);
|
|
9592
|
+
if (!match) return null;
|
|
9593
|
+
const truncated = match.content.length > PHONE_ARTIFACT_MAX_CHARS;
|
|
9594
|
+
return {
|
|
9595
|
+
title: match.title,
|
|
9596
|
+
kind: match.kind,
|
|
9597
|
+
content: truncated ? match.content.slice(0, PHONE_ARTIFACT_MAX_CHARS) : match.content,
|
|
9598
|
+
truncated
|
|
9599
|
+
};
|
|
9600
|
+
}
|
|
9601
|
+
function newest(items) {
|
|
9602
|
+
return items.length ? items[items.length - 1] ?? null : null;
|
|
9603
|
+
}
|
|
9604
|
+
function pickArtifactMatch(items, request) {
|
|
9605
|
+
const hint = request.hint?.trim();
|
|
9606
|
+
const title = request.title.trim();
|
|
9607
|
+
if (hint) {
|
|
9608
|
+
const exact = items.filter((item) => item.content && artifactHint(item.content) === hint);
|
|
9609
|
+
const exactTitled = title ? exact.filter((item) => item.title === title) : [];
|
|
9610
|
+
const exactMatch = newest(exactTitled.length ? exactTitled : exact);
|
|
9611
|
+
if (exactMatch) return exactMatch;
|
|
9612
|
+
if (title) {
|
|
9613
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
9614
|
+
const item = items[i];
|
|
9615
|
+
if (!item?.content || item.title !== title) continue;
|
|
9616
|
+
if (normalizedBody(item.content).startsWith(hint)) return item;
|
|
9617
|
+
}
|
|
9618
|
+
}
|
|
9619
|
+
}
|
|
9620
|
+
if (!title) return null;
|
|
9621
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
9622
|
+
if (items[i]?.title === title) return items[i] ?? null;
|
|
9623
|
+
}
|
|
9624
|
+
return null;
|
|
9625
|
+
}
|
|
9626
|
+
|
|
9627
|
+
// src/remote/phone-chats.ts
|
|
9628
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
9629
|
+
|
|
9630
|
+
// src/remote/phone-header.ts
|
|
9631
|
+
var PHONE_HEADER_GIT_ACTIONS = [
|
|
9632
|
+
"commit-push",
|
|
9633
|
+
"create-draft",
|
|
9634
|
+
"resolve-conflicts",
|
|
9635
|
+
"ready-for-review",
|
|
9636
|
+
"merge"
|
|
9637
|
+
];
|
|
9638
|
+
var HIDDEN = {
|
|
9639
|
+
visible: false,
|
|
9640
|
+
branch: "",
|
|
9641
|
+
additions: 0,
|
|
9642
|
+
deletions: 0,
|
|
9643
|
+
unpushed: 0,
|
|
9644
|
+
dirty: false,
|
|
9645
|
+
ready: false,
|
|
9646
|
+
title: ""
|
|
9647
|
+
};
|
|
9648
|
+
function phoneHeaderFrom(thread, diff) {
|
|
9649
|
+
if (isGlobalThread(thread)) return HIDDEN;
|
|
9650
|
+
const branch = thread.branchName.trim().replace(/^thread\//, "");
|
|
9651
|
+
if (!branch) return HIDDEN;
|
|
9652
|
+
const ready = diff != null;
|
|
9653
|
+
const uncommitted = diff?.scopeStats?.uncommitted;
|
|
9654
|
+
const additions = ready ? Math.max(0, Math.trunc(uncommitted?.additions ?? 0)) : 0;
|
|
9655
|
+
const deletions = ready ? Math.max(0, Math.trunc(uncommitted?.deletions ?? 0)) : 0;
|
|
9656
|
+
const unpushed = ready ? Math.max(0, Math.trunc(diff?.unpushed ?? 0)) : 0;
|
|
9657
|
+
const dirty = ready && (Boolean(diff?.dirty) || additions > 0 || deletions > 0);
|
|
9658
|
+
const pr = prSnapshot(thread);
|
|
9659
|
+
const action = ready ? headerAction(pr, { dirty: Boolean(diff?.dirty), unpushed }) : null;
|
|
9660
|
+
const lines = [branch];
|
|
9661
|
+
if (!ready) lines.push("Loading git status\u2026");
|
|
9662
|
+
else if (dirty) lines.push(`Uncommitted +${additions} \u2212${deletions}`);
|
|
9663
|
+
else lines.push("Working tree clean");
|
|
9664
|
+
if (unpushed > 0) lines.push(`${unpushed} unpushed commit${unpushed === 1 ? "" : "s"}`);
|
|
9665
|
+
return {
|
|
9666
|
+
visible: true,
|
|
9667
|
+
branch,
|
|
9668
|
+
additions,
|
|
9669
|
+
deletions,
|
|
9670
|
+
unpushed,
|
|
9671
|
+
dirty,
|
|
9672
|
+
ready,
|
|
9673
|
+
title: lines.join("\n"),
|
|
9674
|
+
...pr.url ? { prUrl: pr.url } : {},
|
|
9675
|
+
...pr.number ? { prNumber: pr.number } : {},
|
|
9676
|
+
...pr.status ? { prStatus: pr.status } : {},
|
|
9677
|
+
...action ? { action: action.id, actionLabel: action.label } : {}
|
|
9678
|
+
};
|
|
9679
|
+
}
|
|
9680
|
+
function phonePrPill(thread) {
|
|
9681
|
+
const pr = prSnapshot(thread);
|
|
9682
|
+
if (!pr.url) return null;
|
|
9683
|
+
return { url: pr.url, number: pr.number, status: pr.status };
|
|
9684
|
+
}
|
|
9685
|
+
async function readPhoneHeader(thread) {
|
|
9686
|
+
const pending = phoneHeaderFrom(thread, null);
|
|
9687
|
+
if (!pending.visible) return pending;
|
|
9688
|
+
try {
|
|
9689
|
+
const diff = await getOrchestrator().diff(thread.id, { includePatches: false });
|
|
9690
|
+
return phoneHeaderFrom(thread, diff);
|
|
9691
|
+
} catch {
|
|
9692
|
+
return pending;
|
|
9693
|
+
}
|
|
9694
|
+
}
|
|
9695
|
+
function prSnapshot(thread) {
|
|
9696
|
+
const url = thread.prUrl?.trim() || "";
|
|
9697
|
+
const number = url.match(/\/pull\/(\d+)/)?.[1] ?? "";
|
|
9698
|
+
const state = (thread.prState ?? "").toUpperCase();
|
|
9699
|
+
const merged = state === "MERGED";
|
|
9700
|
+
const closed = state === "CLOSED";
|
|
9701
|
+
const open = Boolean(url) && !merged && !closed;
|
|
9702
|
+
const draft = open && Boolean(thread.prIsDraft);
|
|
9703
|
+
const inMergeQueue = open && Boolean(thread.prIsInMergeQueue);
|
|
9704
|
+
const mergeable = (thread.prMergeable ?? "").toUpperCase();
|
|
9705
|
+
const mergeState = (thread.prMergeStateStatus ?? "").toUpperCase();
|
|
9706
|
+
const mergeConflicts = open && !inMergeQueue && (mergeable === "CONFLICTING" || mergeState === "DIRTY");
|
|
9707
|
+
const branchBehind = open && !inMergeQueue && !mergeConflicts && mergeState === "BEHIND";
|
|
9708
|
+
const checksFailed = Boolean(thread.prChecksFailed);
|
|
9709
|
+
const review = (open && !draft ? thread.prReviewDecision : "") ?? "";
|
|
9710
|
+
return {
|
|
9711
|
+
url,
|
|
9712
|
+
number,
|
|
9713
|
+
status: pillStatus({ url, merged, closed, draft, inMergeQueue, mergeConflicts, branchBehind, checksFailed, review }),
|
|
9714
|
+
merged,
|
|
9715
|
+
closed,
|
|
9716
|
+
open,
|
|
9717
|
+
draft,
|
|
9718
|
+
cowboy: Boolean(thread.cowboy),
|
|
9719
|
+
inMergeQueue,
|
|
9720
|
+
mergeConflicts,
|
|
9721
|
+
branchBehind,
|
|
9722
|
+
checksFailed,
|
|
9723
|
+
review: review.toUpperCase()
|
|
9724
|
+
};
|
|
9725
|
+
}
|
|
9726
|
+
function pillStatus(pr) {
|
|
9727
|
+
if (!pr.url) return "";
|
|
9728
|
+
if (pr.merged) return "Merged";
|
|
9729
|
+
if (pr.closed) return "Closed";
|
|
9730
|
+
if (pr.inMergeQueue) return "Queued";
|
|
9731
|
+
if (pr.mergeConflicts) return "Merge conflicts";
|
|
9732
|
+
if (pr.branchBehind) return "Behind base";
|
|
9733
|
+
if (pr.draft) return "Draft";
|
|
9734
|
+
if (pr.checksFailed) return "Checks failing";
|
|
9735
|
+
if (pr.review === "CHANGES_REQUESTED") return "Changes requested";
|
|
9736
|
+
if (pr.review !== "APPROVED") return "Needs approval";
|
|
9737
|
+
return "Approved";
|
|
9738
|
+
}
|
|
9739
|
+
function headerAction(pr, diff) {
|
|
9740
|
+
const hasLocalChanges = diff.dirty || diff.unpushed > 0;
|
|
9741
|
+
const originInSync = !hasLocalChanges;
|
|
9742
|
+
if (pr.merged) return null;
|
|
9743
|
+
if (pr.closed) return { id: "open-pr", label: "Closed" };
|
|
9744
|
+
if (pr.cowboy) {
|
|
9745
|
+
return hasLocalChanges ? { id: "commit-push", label: "Commit & push" } : { id: "commit-push", label: "Push" };
|
|
9746
|
+
}
|
|
9747
|
+
if (!pr.url) return { id: "create-draft", label: "Create PR" };
|
|
9748
|
+
if (pr.inMergeQueue) return { id: "open-pr", label: "Queued" };
|
|
9749
|
+
if (pr.mergeConflicts) return { id: "resolve-conflicts", label: "Resolve" };
|
|
9750
|
+
if (pr.branchBehind) return { id: "resolve-conflicts", label: "Update" };
|
|
9751
|
+
if (hasLocalChanges) return { id: "commit-push", label: "Commit & push" };
|
|
9752
|
+
if (pr.draft) {
|
|
9753
|
+
return originInSync ? { id: "ready-for-review", label: "Ready for review" } : { id: "commit-push", label: "Commit & push" };
|
|
9754
|
+
}
|
|
9755
|
+
if (pr.checksFailed) return { id: "open-checks", label: "Checks failing" };
|
|
9756
|
+
if (pr.review === "CHANGES_REQUESTED") return { id: "open-pr", label: "Changes requested" };
|
|
9757
|
+
if (pr.review !== "APPROVED") return { id: "open-pr", label: "Needs approval" };
|
|
9758
|
+
return { id: "merge", label: "Merge" };
|
|
9759
|
+
}
|
|
9760
|
+
|
|
9761
|
+
// src/remote/phone-code-refs.ts
|
|
9762
|
+
var MAX_REFS = 8;
|
|
9763
|
+
var MAX_TEXT = 2e4;
|
|
9764
|
+
var MAX_TOTAL = 4e4;
|
|
9765
|
+
function lineNumber(value, key) {
|
|
9766
|
+
const raw = value[key];
|
|
9767
|
+
if (typeof raw !== "number" || !Number.isInteger(raw) || raw < 1 || raw > 1e6) return void 0;
|
|
9768
|
+
return raw;
|
|
9769
|
+
}
|
|
9770
|
+
function parsePhoneCodeRefs(value) {
|
|
9771
|
+
if (value == null) return [];
|
|
9772
|
+
if (!Array.isArray(value) || value.length > MAX_REFS) return "invalid";
|
|
9773
|
+
const refs = [];
|
|
9774
|
+
let total = 0;
|
|
9775
|
+
for (const item of value) {
|
|
9776
|
+
if (!item || typeof item !== "object") return "invalid";
|
|
9777
|
+
const pathRaw = item.path;
|
|
9778
|
+
const path2 = typeof pathRaw === "string" ? pathRaw.trim().replace(/\\/g, "/").slice(0, 500) : "";
|
|
9779
|
+
const startLine = lineNumber(item, "startLine");
|
|
9780
|
+
const endLine = lineNumber(item, "endLine");
|
|
9781
|
+
const textRaw = item.text;
|
|
9782
|
+
const text5 = typeof textRaw === "string" ? textRaw.replace(/\n$/, "").slice(0, MAX_TEXT) : "";
|
|
9783
|
+
if (!path2 || !startLine || !endLine || endLine < startLine || !text5.trim()) return "invalid";
|
|
9784
|
+
total += text5.length;
|
|
9785
|
+
if (total > MAX_TOTAL) return "invalid";
|
|
9786
|
+
refs.push({ path: path2, startLine, endLine, text: text5 });
|
|
9787
|
+
}
|
|
9788
|
+
return refs;
|
|
9789
|
+
}
|
|
9790
|
+
|
|
9791
|
+
// src/remote/phone-panes.ts
|
|
9792
|
+
var MAX_ROWS = 200;
|
|
9793
|
+
var MAX_QUERY = 200;
|
|
9794
|
+
function parsePhonePane(value, chatId) {
|
|
9795
|
+
const pane = value && typeof value === "object" ? value.pane : void 0;
|
|
9796
|
+
if (pane !== "files" && pane !== "changes" && pane !== "checks") return "invalid";
|
|
9797
|
+
const scopeRaw = value.scope;
|
|
9798
|
+
const scope = scopeRaw === "uncommitted" || scopeRaw === "commits" ? scopeRaw : void 0;
|
|
9799
|
+
const queryRaw = value.query;
|
|
9800
|
+
const query = typeof queryRaw === "string" ? queryRaw.trim().slice(0, MAX_QUERY) : "";
|
|
9801
|
+
return {
|
|
9802
|
+
op: "pane",
|
|
9803
|
+
chatId,
|
|
9804
|
+
pane,
|
|
9805
|
+
...scope && pane === "changes" ? { scope } : {},
|
|
9806
|
+
...query && pane === "files" ? { query } : {}
|
|
9807
|
+
};
|
|
9808
|
+
}
|
|
9809
|
+
function filterPhoneFiles(paths, query) {
|
|
9810
|
+
const q = query.trim().toLowerCase();
|
|
9811
|
+
if (!q) return paths;
|
|
9812
|
+
return paths.filter((path2) => path2.toLowerCase().includes(q));
|
|
9813
|
+
}
|
|
9814
|
+
async function readPhonePane(thread, pane, scope, query) {
|
|
9815
|
+
try {
|
|
9816
|
+
if (pane === "files") return await readFiles(thread.id, query);
|
|
9817
|
+
if (pane === "changes") return await readChanges(thread.id, scope ?? "commits");
|
|
9818
|
+
return await readChecks(thread.id);
|
|
9819
|
+
} catch (err) {
|
|
9820
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
9821
|
+
return { rows: [], note: message };
|
|
9822
|
+
}
|
|
9823
|
+
}
|
|
9824
|
+
async function readFiles(threadId, query) {
|
|
9825
|
+
const paths = filterPhoneFiles(await getOrchestrator().listFiles(threadId), query ?? "");
|
|
9826
|
+
const shown = paths.slice(0, MAX_ROWS);
|
|
9827
|
+
const extra = paths.length - shown.length;
|
|
9828
|
+
const note = extra > 0 ? query?.trim() ? `${extra} more matching files` : `${extra} more files on the Mac` : void 0;
|
|
9829
|
+
return {
|
|
9830
|
+
rows: shown.map((path2) => ({ label: path2, path: path2 })),
|
|
9831
|
+
...note ? { note } : {}
|
|
9832
|
+
};
|
|
9833
|
+
}
|
|
9834
|
+
async function readChanges(threadId, scope) {
|
|
9835
|
+
const diff = await getOrchestrator().diff(threadId, { includePatches: false, scope });
|
|
9836
|
+
const shown = diff.files.slice(0, MAX_ROWS);
|
|
9837
|
+
return {
|
|
9838
|
+
rows: shown.map((file) => ({
|
|
9839
|
+
label: file.path,
|
|
9840
|
+
path: file.path,
|
|
9841
|
+
detail: changeDetail(file.additions, file.deletions)
|
|
9842
|
+
})),
|
|
9843
|
+
...diff.files.length > shown.length ? { note: `${diff.files.length - shown.length} more changed files` } : {}
|
|
9844
|
+
};
|
|
9845
|
+
}
|
|
9846
|
+
function changeDetail(additions, deletions) {
|
|
9847
|
+
const add = additions ?? 0;
|
|
9848
|
+
const del = deletions ?? 0;
|
|
9849
|
+
if (add === 0 && del === 0) return void 0;
|
|
9850
|
+
return `+${add} \u2212${del}`;
|
|
9851
|
+
}
|
|
9852
|
+
async function readChecks(threadId) {
|
|
9853
|
+
const checks = await getOrchestrator().getPrChecks(threadId);
|
|
9854
|
+
if (!checks) return { rows: [], note: "No pull request on this branch." };
|
|
9855
|
+
const shown = checks.slice(0, MAX_ROWS);
|
|
9856
|
+
return {
|
|
9857
|
+
rows: shown.map((check) => ({
|
|
9858
|
+
label: check.name,
|
|
9859
|
+
detail: check.bucket || check.state,
|
|
9860
|
+
...check.link ? { href: check.link } : {}
|
|
9861
|
+
}))
|
|
9862
|
+
};
|
|
9863
|
+
}
|
|
9492
9864
|
|
|
9493
9865
|
// src/remote/phone-defaults.ts
|
|
9494
9866
|
function row(resolved) {
|
|
@@ -9589,10 +9961,61 @@ function listPhoneMessages(thread) {
|
|
|
9589
9961
|
return live.slice(-TRANSCRIPT_LIMIT);
|
|
9590
9962
|
}
|
|
9591
9963
|
|
|
9592
|
-
// src/remote/phone-
|
|
9593
|
-
var PHONE_CONTROL_PREFIX = "\0sb.phone\n";
|
|
9964
|
+
// src/remote/phone-history.ts
|
|
9594
9965
|
var PREVIEW_LIMIT = 90;
|
|
9595
9966
|
var HISTORY_PAGE_SIZE = 40;
|
|
9967
|
+
function previewOf(thread) {
|
|
9968
|
+
const messages = listPhoneMessages(thread);
|
|
9969
|
+
const last = messages[messages.length - 1];
|
|
9970
|
+
if (!last) return "";
|
|
9971
|
+
return clip(last.text.replace(/\s+/g, " ").trim(), PREVIEW_LIMIT);
|
|
9972
|
+
}
|
|
9973
|
+
function repoName(repoPath) {
|
|
9974
|
+
const parts = repoPath.replace(/\/$/, "").split("/");
|
|
9975
|
+
return parts[parts.length - 1] || repoPath;
|
|
9976
|
+
}
|
|
9977
|
+
function isProjectPath(path2) {
|
|
9978
|
+
if (!path2 || path2 === "/" || path2 === ".") return false;
|
|
9979
|
+
return !isGlobalThread({ repoPath: path2 });
|
|
9980
|
+
}
|
|
9981
|
+
function historyStamp(thread) {
|
|
9982
|
+
return thread.archivedAt || thread.updatedAt;
|
|
9983
|
+
}
|
|
9984
|
+
function historyCursor(chat) {
|
|
9985
|
+
return `${chat.updatedAt} ${chat.id}`;
|
|
9986
|
+
}
|
|
9987
|
+
function listPhoneHistory(opts) {
|
|
9988
|
+
const query = opts?.query?.trim().toLowerCase() ?? "";
|
|
9989
|
+
const after = opts?.after?.trim() ?? "";
|
|
9990
|
+
const all = listThreads({ includeArchived: true }).filter((thread) => thread.status === "archived").filter((thread) => isGlobalThread(thread) || isProjectPath(thread.repoPath)).sort((a, b) => historyStamp(a) < historyStamp(b) ? 1 : historyStamp(a) > historyStamp(b) ? -1 : 0).map((thread) => ({
|
|
9991
|
+
id: thread.id,
|
|
9992
|
+
title: thread.title?.trim() || "Untitled",
|
|
9993
|
+
preview: previewOf(thread),
|
|
9994
|
+
updatedAt: historyStamp(thread),
|
|
9995
|
+
where: isGlobalThread(thread) ? "Orchestration" : repoName(thread.repoPath),
|
|
9996
|
+
agent: thread.agent
|
|
9997
|
+
})).filter((chat) => {
|
|
9998
|
+
if (!query) return true;
|
|
9999
|
+
return `${chat.title} ${chat.where} ${chat.agent} ${chat.preview}`.toLowerCase().includes(query);
|
|
10000
|
+
});
|
|
10001
|
+
let start = 0;
|
|
10002
|
+
if (after) {
|
|
10003
|
+
const index = all.findIndex((chat) => historyCursor(chat) === after);
|
|
10004
|
+
start = index >= 0 ? index + 1 : all.length;
|
|
10005
|
+
}
|
|
10006
|
+
const chats = all.slice(start, start + HISTORY_PAGE_SIZE);
|
|
10007
|
+
const last = chats.at(-1);
|
|
10008
|
+
const more = start + chats.length < all.length;
|
|
10009
|
+
return {
|
|
10010
|
+
chats,
|
|
10011
|
+
total: all.length,
|
|
10012
|
+
...more && last ? { next: historyCursor(last) } : {}
|
|
10013
|
+
};
|
|
10014
|
+
}
|
|
10015
|
+
|
|
10016
|
+
// src/remote/phone-chats.ts
|
|
10017
|
+
var PHONE_CONTROL_PREFIX = "\0sb.phone\n";
|
|
10018
|
+
var PREVIEW_LIMIT2 = 90;
|
|
9596
10019
|
var AGENT_KINDS = /* @__PURE__ */ new Set(["claude", "codex", "opencode", "brightsy", "cursor"]);
|
|
9597
10020
|
var MAX_PHONE_FILES = 8;
|
|
9598
10021
|
var MAX_PHONE_FILE_CHARS = Math.ceil(8 * 1024 * 1024 * 4 / 3);
|
|
@@ -9622,7 +10045,7 @@ function parsePhoneControl(value) {
|
|
|
9622
10045
|
}
|
|
9623
10046
|
if (op === "sources") {
|
|
9624
10047
|
const repoPath = textField(value, "repoPath");
|
|
9625
|
-
if (!repoPath || !
|
|
10048
|
+
if (!repoPath || !isProjectPath2(repoPath)) return "invalid";
|
|
9626
10049
|
const query = textField(value, "query");
|
|
9627
10050
|
return { op: "sources", repoPath, ...query ? { query } : {} };
|
|
9628
10051
|
}
|
|
@@ -9640,7 +10063,15 @@ function parsePhoneControl(value) {
|
|
|
9640
10063
|
if (op === "create") return parsePhoneCreate(value);
|
|
9641
10064
|
const chatId = typeof value.chatId === "string" ? value.chatId.trim() : "";
|
|
9642
10065
|
if (!chatId) return "invalid";
|
|
9643
|
-
if (op === "open" || op === "archive" || op === "restore" || op === "stop"
|
|
10066
|
+
if (op === "open" || op === "archive" || op === "restore" || op === "stop" || op === "review" || op === "header") {
|
|
10067
|
+
return { op, chatId };
|
|
10068
|
+
}
|
|
10069
|
+
if (op === "git") {
|
|
10070
|
+
const action = textField(value, "action");
|
|
10071
|
+
if (!PHONE_HEADER_GIT_ACTIONS.includes(action)) return "invalid";
|
|
10072
|
+
return { op: "git", chatId, action };
|
|
10073
|
+
}
|
|
10074
|
+
if (op === "pane") return parsePhonePane(value, chatId);
|
|
9644
10075
|
if (op === "open-artifact") return parseOpenArtifact(value, chatId);
|
|
9645
10076
|
if (op === "open-file" || op === "media") {
|
|
9646
10077
|
const path2 = textField(value, "path");
|
|
@@ -9661,7 +10092,7 @@ function parsePhoneControl(value) {
|
|
|
9661
10092
|
if (op === "options") return { op: "options", chatId, ...draft };
|
|
9662
10093
|
if (op === "prompt") {
|
|
9663
10094
|
const text5 = typeof value.text === "string" ? value.text.trim() : "";
|
|
9664
|
-
const hasPayload = Boolean(text5 || draft.files?.length || draft.links?.length);
|
|
10095
|
+
const hasPayload = Boolean(text5 || draft.files?.length || draft.links?.length || draft.refs?.length);
|
|
9665
10096
|
if (!hasPayload) return "invalid";
|
|
9666
10097
|
return { op: "prompt", chatId, text: text5, ...draft };
|
|
9667
10098
|
}
|
|
@@ -9725,6 +10156,9 @@ function parsePhoneDraft(value) {
|
|
|
9725
10156
|
const links = parsePhoneLinks(value.links);
|
|
9726
10157
|
if (links === "invalid") return "invalid";
|
|
9727
10158
|
if (links.length) draft.links = links;
|
|
10159
|
+
const refs = parsePhoneCodeRefs(value.refs);
|
|
10160
|
+
if (refs === "invalid") return "invalid";
|
|
10161
|
+
if (refs.length) draft.refs = refs;
|
|
9728
10162
|
const prompt = textField(value, "prompt");
|
|
9729
10163
|
if (prompt) draft.prompt = prompt.slice(0, 2e4);
|
|
9730
10164
|
return draft;
|
|
@@ -9780,7 +10214,7 @@ function parsePhoneCreate(value) {
|
|
|
9780
10214
|
}
|
|
9781
10215
|
if (where === "project") {
|
|
9782
10216
|
const repoPath = textField(value, "repoPath");
|
|
9783
|
-
if (!repoPath || !
|
|
10217
|
+
if (!repoPath || !isProjectPath2(repoPath)) return "invalid";
|
|
9784
10218
|
const sourceRaw = textField(value, "sourceType");
|
|
9785
10219
|
let sourceType;
|
|
9786
10220
|
if (sourceRaw === "branch" || sourceRaw === "pr" || sourceRaw === "ticket") sourceType = sourceRaw;
|
|
@@ -9803,26 +10237,30 @@ function parsePhoneCreate(value) {
|
|
|
9803
10237
|
return "invalid";
|
|
9804
10238
|
}
|
|
9805
10239
|
function summarize(thread) {
|
|
10240
|
+
const pr = phonePrPill(thread);
|
|
9806
10241
|
return {
|
|
9807
10242
|
id: thread.id,
|
|
9808
10243
|
title: thread.title?.trim() || "Untitled",
|
|
9809
10244
|
status: thread.status,
|
|
9810
|
-
preview:
|
|
10245
|
+
preview: previewOf2(thread),
|
|
9811
10246
|
updatedAt: thread.updatedAt,
|
|
9812
|
-
agent: thread.agent
|
|
10247
|
+
agent: thread.agent,
|
|
10248
|
+
...pr?.url ? { prUrl: pr.url } : {},
|
|
10249
|
+
...pr?.number ? { prNumber: pr.number } : {},
|
|
10250
|
+
...pr?.status ? { prStatus: pr.status } : {}
|
|
9813
10251
|
};
|
|
9814
10252
|
}
|
|
9815
|
-
function
|
|
10253
|
+
function previewOf2(thread) {
|
|
9816
10254
|
const messages = listPhoneMessages(thread);
|
|
9817
10255
|
const last = messages[messages.length - 1];
|
|
9818
10256
|
if (!last) return "";
|
|
9819
|
-
return clip(last.text.replace(/\s+/g, " ").trim(),
|
|
10257
|
+
return clip(last.text.replace(/\s+/g, " ").trim(), PREVIEW_LIMIT2);
|
|
9820
10258
|
}
|
|
9821
|
-
function
|
|
10259
|
+
function repoName2(repoPath) {
|
|
9822
10260
|
const parts = repoPath.replace(/\/$/, "").split("/");
|
|
9823
10261
|
return parts[parts.length - 1] || repoPath;
|
|
9824
10262
|
}
|
|
9825
|
-
function
|
|
10263
|
+
function isProjectPath2(path2) {
|
|
9826
10264
|
if (!path2 || path2 === "/" || path2 === ".") return false;
|
|
9827
10265
|
return !isGlobalThread({ repoPath: path2 });
|
|
9828
10266
|
}
|
|
@@ -9834,17 +10272,17 @@ function listPhoneSidebar(viewerLogin = phoneViewerLogin()) {
|
|
|
9834
10272
|
const threads = listThreads();
|
|
9835
10273
|
const byRepo = /* @__PURE__ */ new Map();
|
|
9836
10274
|
for (const thread of threads) {
|
|
9837
|
-
if (!
|
|
10275
|
+
if (!isProjectPath2(thread.repoPath) || isRemovedWorkspace(thread.repoPath)) continue;
|
|
9838
10276
|
const list = byRepo.get(thread.repoPath) ?? [];
|
|
9839
10277
|
list.push(thread);
|
|
9840
10278
|
byRepo.set(thread.repoPath, list);
|
|
9841
10279
|
}
|
|
9842
10280
|
for (const workspace of listWorkspaces()) {
|
|
9843
|
-
if (!
|
|
10281
|
+
if (!isProjectPath2(workspace.path) || byRepo.has(workspace.path)) continue;
|
|
9844
10282
|
byRepo.set(workspace.path, []);
|
|
9845
10283
|
}
|
|
9846
|
-
const projects = [...byRepo.entries()].sort(([a], [b]) =>
|
|
9847
|
-
name:
|
|
10284
|
+
const projects = [...byRepo.entries()].sort(([a], [b]) => repoName2(a).localeCompare(repoName2(b))).map(([path2, repoThreads]) => ({
|
|
10285
|
+
name: repoName2(path2),
|
|
9848
10286
|
path: path2,
|
|
9849
10287
|
worktrees: groupHomeBoardWorktrees(repoThreads).map((group) => {
|
|
9850
10288
|
const tags = workspaceTagsFromGroup(group);
|
|
@@ -9863,41 +10301,6 @@ function listPhoneSidebar(viewerLogin = phoneViewerLogin()) {
|
|
|
9863
10301
|
}));
|
|
9864
10302
|
return { orchestration: listPhoneChats(), projects, defaults: phoneAccountDefaults() };
|
|
9865
10303
|
}
|
|
9866
|
-
function historyStamp(thread) {
|
|
9867
|
-
return thread.archivedAt || thread.updatedAt;
|
|
9868
|
-
}
|
|
9869
|
-
function historyCursor(chat) {
|
|
9870
|
-
return `${chat.updatedAt} ${chat.id}`;
|
|
9871
|
-
}
|
|
9872
|
-
function historyQueryMatch(chat, query) {
|
|
9873
|
-
if (!query) return true;
|
|
9874
|
-
return `${chat.title} ${chat.where} ${chat.agent} ${chat.preview}`.toLowerCase().includes(query);
|
|
9875
|
-
}
|
|
9876
|
-
function listPhoneHistory(opts) {
|
|
9877
|
-
const query = opts?.query?.trim().toLowerCase() ?? "";
|
|
9878
|
-
const after = opts?.after?.trim() ?? "";
|
|
9879
|
-
const all = listThreads({ includeArchived: true }).filter((thread) => thread.status === "archived").filter((thread) => isGlobalThread(thread) || isProjectPath(thread.repoPath)).sort((a, b) => historyStamp(a) < historyStamp(b) ? 1 : historyStamp(a) > historyStamp(b) ? -1 : 0).map((thread) => ({
|
|
9880
|
-
id: thread.id,
|
|
9881
|
-
title: thread.title?.trim() || "Untitled",
|
|
9882
|
-
preview: previewOf(thread),
|
|
9883
|
-
updatedAt: historyStamp(thread),
|
|
9884
|
-
where: isGlobalThread(thread) ? "Orchestration" : repoName(thread.repoPath),
|
|
9885
|
-
agent: thread.agent
|
|
9886
|
-
})).filter((chat) => historyQueryMatch(chat, query));
|
|
9887
|
-
let start = 0;
|
|
9888
|
-
if (after) {
|
|
9889
|
-
const index = all.findIndex((chat) => historyCursor(chat) === after);
|
|
9890
|
-
start = index >= 0 ? index + 1 : all.length;
|
|
9891
|
-
}
|
|
9892
|
-
const chats = all.slice(start, start + HISTORY_PAGE_SIZE);
|
|
9893
|
-
const last = chats.at(-1);
|
|
9894
|
-
const more = start + chats.length < all.length;
|
|
9895
|
-
return {
|
|
9896
|
-
chats,
|
|
9897
|
-
total: all.length,
|
|
9898
|
-
...more && last ? { next: historyCursor(last) } : {}
|
|
9899
|
-
};
|
|
9900
|
-
}
|
|
9901
10304
|
function matchPhoneThread(chatId) {
|
|
9902
10305
|
const id = chatId.trim();
|
|
9903
10306
|
if (!id) return null;
|
|
@@ -9910,7 +10313,7 @@ function matchPhoneThread(chatId) {
|
|
|
9910
10313
|
}
|
|
9911
10314
|
function visiblePhoneThread(thread) {
|
|
9912
10315
|
if (isGlobalThread(thread)) return true;
|
|
9913
|
-
return
|
|
10316
|
+
return isProjectPath2(thread.repoPath);
|
|
9914
10317
|
}
|
|
9915
10318
|
function findPhoneChat(chatId) {
|
|
9916
10319
|
const thread = matchPhoneThread(chatId);
|
|
@@ -9976,7 +10379,7 @@ function projectPlace(thread) {
|
|
|
9976
10379
|
}
|
|
9977
10380
|
function assertKnownProject(repoPath) {
|
|
9978
10381
|
const path2 = repoPath.trim();
|
|
9979
|
-
if (!
|
|
10382
|
+
if (!isProjectPath2(path2)) throw new Error("Pick a project on this Mac.");
|
|
9980
10383
|
const known = listWorkspaces().some((workspace) => sameRepoPath(workspace.path, path2)) || listThreads().some(
|
|
9981
10384
|
(thread) => thread.status !== "archived" && sameRepoPath(thread.repoPath, path2)
|
|
9982
10385
|
);
|
|
@@ -10079,6 +10482,56 @@ function archivePhoneChat(chatId) {
|
|
|
10079
10482
|
return true;
|
|
10080
10483
|
}
|
|
10081
10484
|
|
|
10485
|
+
// src/remote/phone-workspace-ops.ts
|
|
10486
|
+
function dispatchPhoneWorkspace(cmd, emit, publishOpened) {
|
|
10487
|
+
if (cmd.op === "pane") {
|
|
10488
|
+
const thread = readPhoneThread(cmd.chatId);
|
|
10489
|
+
if (!thread) {
|
|
10490
|
+
emit({ op: "error", chatId: cmd.chatId, message: "That agent is not on this Mac." });
|
|
10491
|
+
return;
|
|
10492
|
+
}
|
|
10493
|
+
void readPhonePane(thread, cmd.pane, cmd.scope, cmd.query).then((body) => {
|
|
10494
|
+
emit({
|
|
10495
|
+
op: "pane",
|
|
10496
|
+
chatId: cmd.chatId,
|
|
10497
|
+
pane: cmd.pane,
|
|
10498
|
+
rows: body.rows,
|
|
10499
|
+
...body.note ? { note: body.note } : {},
|
|
10500
|
+
...cmd.pane === "files" ? { query: cmd.query ?? "" } : {}
|
|
10501
|
+
});
|
|
10502
|
+
});
|
|
10503
|
+
return;
|
|
10504
|
+
}
|
|
10505
|
+
if (cmd.op === "header") {
|
|
10506
|
+
const thread = readPhoneThread(cmd.chatId);
|
|
10507
|
+
if (!thread) {
|
|
10508
|
+
emit({ op: "error", chatId: cmd.chatId, message: "That agent is not on this Mac." });
|
|
10509
|
+
return;
|
|
10510
|
+
}
|
|
10511
|
+
void readPhoneHeader(thread).then((header) => {
|
|
10512
|
+
emit({ op: "header", chatId: cmd.chatId, ...header });
|
|
10513
|
+
});
|
|
10514
|
+
return;
|
|
10515
|
+
}
|
|
10516
|
+
if (cmd.op === "git") {
|
|
10517
|
+
void getOrchestrator().askGit(cmd.chatId, cmd.action).then((tab) => publishOpened(tab.id)).catch((err) => {
|
|
10518
|
+
emit({
|
|
10519
|
+
op: "error",
|
|
10520
|
+
chatId: cmd.chatId,
|
|
10521
|
+
message: err instanceof Error ? err.message : String(err)
|
|
10522
|
+
});
|
|
10523
|
+
});
|
|
10524
|
+
return;
|
|
10525
|
+
}
|
|
10526
|
+
void getOrchestrator().requestReview(cmd.chatId).then((tab) => publishOpened(tab.id)).catch((err) => {
|
|
10527
|
+
emit({
|
|
10528
|
+
op: "error",
|
|
10529
|
+
chatId: cmd.chatId,
|
|
10530
|
+
message: err instanceof Error ? err.message : String(err)
|
|
10531
|
+
});
|
|
10532
|
+
});
|
|
10533
|
+
}
|
|
10534
|
+
|
|
10082
10535
|
// src/remote/phone-sources.ts
|
|
10083
10536
|
function sourceWarning(label, err) {
|
|
10084
10537
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -10443,7 +10896,8 @@ function stagePhoneTurnFiles(worktreePath, draft) {
|
|
|
10443
10896
|
worktreePath,
|
|
10444
10897
|
(draft.files ?? []).map((file) => ({ name: file.name, dataBase64: file.dataBase64 }))
|
|
10445
10898
|
);
|
|
10446
|
-
|
|
10899
|
+
const refs = (draft.refs ?? []).map((ref) => buildCodeRefAttachment(ref));
|
|
10900
|
+
return [...links, ...files, ...refs];
|
|
10447
10901
|
}
|
|
10448
10902
|
function handlePhoneControl(cmd, opts) {
|
|
10449
10903
|
const log = opts.onLog ?? (() => void 0);
|
|
@@ -10644,10 +11098,25 @@ function handlePhoneControl(cmd, opts) {
|
|
|
10644
11098
|
emitControl(opts, { op: "error", chatId: cmd.chatId, message: "That file is not in this worktree." });
|
|
10645
11099
|
return;
|
|
10646
11100
|
}
|
|
10647
|
-
|
|
10648
|
-
|
|
11101
|
+
const preview = phoneFilePreview(thread.worktreePath, relative, kind === "dir" ? "dir" : "file");
|
|
11102
|
+
if (!preview) {
|
|
11103
|
+
emitControl(opts, {
|
|
11104
|
+
op: "error",
|
|
11105
|
+
chatId: cmd.chatId,
|
|
11106
|
+
message: "That file could not be opened on the phone."
|
|
11107
|
+
});
|
|
11108
|
+
return;
|
|
11109
|
+
}
|
|
11110
|
+
emitControl(opts, {
|
|
11111
|
+
op: "file",
|
|
11112
|
+
chatId: cmd.chatId,
|
|
10649
11113
|
path: relative,
|
|
10650
|
-
|
|
11114
|
+
content: preview.content,
|
|
11115
|
+
encoding: preview.encoding,
|
|
11116
|
+
...preview.binary ? { binary: true } : {},
|
|
11117
|
+
...preview.directory ? { directory: true } : {},
|
|
11118
|
+
...preview.truncated ? { truncated: true } : {},
|
|
11119
|
+
...preview.mime ? { mime: preview.mime } : {},
|
|
10651
11120
|
...cmd.startLine != null ? { startLine: cmd.startLine } : {},
|
|
10652
11121
|
...cmd.endLine != null ? { endLine: cmd.endLine } : {}
|
|
10653
11122
|
});
|
|
@@ -10662,13 +11131,34 @@ function handlePhoneControl(cmd, opts) {
|
|
|
10662
11131
|
emitControl(opts, { op: "error", chatId: cmd.chatId, message: "That agent is not on this Mac." });
|
|
10663
11132
|
return;
|
|
10664
11133
|
}
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
11134
|
+
const liveParts = readTurnLiveParts(thread.id);
|
|
11135
|
+
const docs = phoneArtifactDocuments([
|
|
11136
|
+
...(thread.messages ?? []).filter((message) => message.role === "agent").map((message) => ({ text: message.text.trim(), parts: message.parts })),
|
|
11137
|
+
{ text: visibleAssistantText(void 0, liveParts), parts: liveParts }
|
|
11138
|
+
]);
|
|
11139
|
+
const body = phoneArtifactReply(docs, { title: cmd.title, ...cmd.hint ? { hint: cmd.hint } : {} });
|
|
11140
|
+
if (!body) {
|
|
11141
|
+
emitControl(opts, { op: "error", chatId: cmd.chatId, message: "That artifact is not in this chat." });
|
|
11142
|
+
return;
|
|
11143
|
+
}
|
|
11144
|
+
emitControl(opts, {
|
|
11145
|
+
op: "artifact",
|
|
11146
|
+
chatId: cmd.chatId,
|
|
11147
|
+
title: body.title,
|
|
11148
|
+
kind: body.kind,
|
|
11149
|
+
content: body.content,
|
|
11150
|
+
...body.truncated ? { truncated: true } : {}
|
|
10669
11151
|
});
|
|
10670
11152
|
return;
|
|
10671
11153
|
}
|
|
11154
|
+
if (cmd.op === "pane" || cmd.op === "header" || cmd.op === "git" || cmd.op === "review") {
|
|
11155
|
+
dispatchPhoneWorkspace(
|
|
11156
|
+
cmd,
|
|
11157
|
+
(reply) => emitControl(opts, reply),
|
|
11158
|
+
(chatId2) => publishOpenedChat(opts, chatId2)
|
|
11159
|
+
);
|
|
11160
|
+
return;
|
|
11161
|
+
}
|
|
10672
11162
|
if (cmd.op === "stop") {
|
|
10673
11163
|
if (!readPhoneThread(cmd.chatId)) {
|
|
10674
11164
|
emitControl(opts, { op: "error", chatId: cmd.chatId, message: "That agent is not on this Mac." });
|
|
@@ -11099,14 +11589,14 @@ import { randomBytes as randomBytes7 } from "crypto";
|
|
|
11099
11589
|
|
|
11100
11590
|
// src/relay/accounts.ts
|
|
11101
11591
|
import { createHash as createHash2, randomBytes as randomBytes6, randomUUID as randomUUID8, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
11102
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
11592
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync6, realpathSync } from "fs";
|
|
11103
11593
|
import { createRequire } from "module";
|
|
11104
|
-
import { dirname, join as
|
|
11594
|
+
import { dirname, join as join7 } from "path";
|
|
11105
11595
|
var GITHUB_ACCOUNT_ISSUER = "https://github.com";
|
|
11106
11596
|
var RELAY_DEVICE_CAP = 3;
|
|
11107
11597
|
function thisModuleFile() {
|
|
11108
11598
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
11109
|
-
return cjsFile || process.argv[1] ||
|
|
11599
|
+
return cjsFile || process.argv[1] || join7(process.cwd(), "package.json");
|
|
11110
11600
|
}
|
|
11111
11601
|
function openDatabase(filePath) {
|
|
11112
11602
|
const req = createRequire(thisModuleFile());
|
|
@@ -11144,7 +11634,7 @@ function assertRelayAccountsDurable(filePath) {
|
|
|
11144
11634
|
if (process.env.NODE_ENV !== "production") return;
|
|
11145
11635
|
if (process.platform !== "linux") return;
|
|
11146
11636
|
const dir = realpathSync(dirname(filePath));
|
|
11147
|
-
const mounts =
|
|
11637
|
+
const mounts = readFileSync6("/proc/mounts", "utf8");
|
|
11148
11638
|
const point = longestMountPoint(dir, mounts);
|
|
11149
11639
|
if (point === "/") {
|
|
11150
11640
|
throw new Error(
|
|
@@ -12621,8 +13111,8 @@ async function startRelayServer(opts) {
|
|
|
12621
13111
|
}
|
|
12622
13112
|
|
|
12623
13113
|
// src/slack/outbound-watch.ts
|
|
12624
|
-
import { existsSync as existsSync5, readFileSync as
|
|
12625
|
-
import { join as
|
|
13114
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
13115
|
+
import { join as join8 } from "path";
|
|
12626
13116
|
var MAX_WATCHES = 40;
|
|
12627
13117
|
var MAX_REPLIES_PER_WATCH = 30;
|
|
12628
13118
|
var WATCH_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
@@ -12630,7 +13120,7 @@ var POLL_INTERVAL_MS = 12e3;
|
|
|
12630
13120
|
var lastPollMs = 0;
|
|
12631
13121
|
var nameCache = /* @__PURE__ */ new Map();
|
|
12632
13122
|
function storePath3() {
|
|
12633
|
-
return
|
|
13123
|
+
return join8(appDataDir(), "slack-outbound-watch.json");
|
|
12634
13124
|
}
|
|
12635
13125
|
function watchId(teamId, channelId, ts) {
|
|
12636
13126
|
return `${teamId}:${channelId}:${ts}`;
|
|
@@ -12645,7 +13135,7 @@ function readStore3() {
|
|
|
12645
13135
|
const path2 = storePath3();
|
|
12646
13136
|
if (!existsSync5(path2)) return [];
|
|
12647
13137
|
try {
|
|
12648
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse(
|
|
13138
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse(readFileSync7(path2, "utf8"));
|
|
12649
13139
|
return Array.isArray(parsed?.watches) ? parsed.watches : [];
|
|
12650
13140
|
} catch {
|
|
12651
13141
|
return [];
|
|
@@ -12697,7 +13187,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
12697
13187
|
await continueOnReply(threadId, prompt);
|
|
12698
13188
|
return;
|
|
12699
13189
|
}
|
|
12700
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
13190
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-GSOW3RPA.js");
|
|
12701
13191
|
await getOrchestrator2().send(threadId, prompt);
|
|
12702
13192
|
} catch {
|
|
12703
13193
|
}
|