@dev.fast/whiteboard 0.2.0 → 0.2.1-preview.20261006.100
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/build-info.json +1 -1
- package/dist/{cli-runner-D8y2_luU.js → cli-runner-CsrwxdfZ.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{headless-host-BJxf4dUU.js → headless-host-D266UVka.js} +1 -1
- package/dist/{process-error-telemetry-v9e5h6D7.js → process-error-telemetry-Dw91I1r5.js} +23 -1
- package/dist/server/desktop-host.js +1 -1
- package/package.json +5 -5
- package/src/review-api/http.ts +28 -1
- package/src/review-stack.ts +8 -3
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.2.
|
|
1
|
+
{"version":"0.2.1-preview.20261006.100","commit":"d3340667cc36422df9b7df0fea600a50b3adfc4c","dirty":true,"builtAt":"2026-10-06T16:26:56.021Z"}
|
|
@@ -4495,7 +4495,7 @@ async function runReviewCli(input) {
|
|
|
4495
4495
|
process.once("SIGINT", stop);
|
|
4496
4496
|
process.once("SIGTERM", stop);
|
|
4497
4497
|
try {
|
|
4498
|
-
const { runHeadlessServer } = await import("./headless-host-
|
|
4498
|
+
const { runHeadlessServer } = await import("./headless-host-D266UVka.js");
|
|
4499
4499
|
await runHeadlessServer({
|
|
4500
4500
|
stateDir,
|
|
4501
4501
|
port,
|
|
@@ -4546,7 +4546,7 @@ async function runReviewCli(input) {
|
|
|
4546
4546
|
if (problem) throw new Error(`Cannot tell whether a Whiteboard Desktop is using ${stateDir}: ${problem.message}`);
|
|
4547
4547
|
const inUse = () => /* @__PURE__ */ new Error(`A Whiteboard server is using ${stateDir}. Stop it first, then run whiteboard server reset-id again.`);
|
|
4548
4548
|
if (desktops.instances.some(({ discovery }) => [discovery.appPid, discovery.serverPid].some((pid) => processIsAlive(pid)))) throw inUse();
|
|
4549
|
-
const [{ openReviewProfile }, { withHeadlessServerLock }] = await Promise.all([import("./profile-Bh5FIrmf.js"), import("./headless-host-
|
|
4549
|
+
const [{ openReviewProfile }, { withHeadlessServerLock }] = await Promise.all([import("./profile-Bh5FIrmf.js"), import("./headless-host-D266UVka.js")]);
|
|
4550
4550
|
const reset = await withHeadlessServerLock(await realpath(stateDir), async () => {
|
|
4551
4551
|
const local = await openReviewProfile(stateDir, { manageWorkspaces: false });
|
|
4552
4552
|
try {
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@ import { p as isObjectValue } from "./src-X9phtB2j.js";
|
|
|
2
2
|
import { O as withFileLock, P as writePrivateJsonAtomic } from "./s3-config-CAxhO9u_.js";
|
|
3
3
|
import "./review-home-paths-6zZH-1c9.js";
|
|
4
4
|
import { t as openReviewProfile } from "./profile-4ry2f3AM.js";
|
|
5
|
-
import { i as createWhiteboardCore, l as createNodeRequestListener, n as installProcessErrorTelemetry, p as GlobalReviewDesktopVerbRelay, t as drainServerCrashReport } from "./process-error-telemetry-
|
|
5
|
+
import { i as createWhiteboardCore, l as createNodeRequestListener, n as installProcessErrorTelemetry, p as GlobalReviewDesktopVerbRelay, t as drainServerCrashReport } from "./process-error-telemetry-Dw91I1r5.js";
|
|
6
6
|
import { i as reviewServerDiscoveryPath, t as headlessServerLockPath } from "./server-discovery-Dbzn3w6Z.js";
|
|
7
7
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
8
8
|
import { mkdir, realpath, rm } from "node:fs/promises";
|
|
@@ -2081,9 +2081,10 @@ async function resolveReviewStackLayers(subject, reviews, runGitHubApi = default
|
|
|
2081
2081
|
if (!stack) return [];
|
|
2082
2082
|
const currentIndex = stack.pull_requests.findIndex((pr) => pr.number === pullRequestNumber);
|
|
2083
2083
|
return stack.pull_requests.map((pr, index) => {
|
|
2084
|
-
const
|
|
2084
|
+
const matches = reviews.filter((candidate) => {
|
|
2085
2085
|
return (candidate.origin?.pullRequestUrl?.replace(/\/pull\/\d+.*$/, "") ?? candidate.pins?.repositoryId) === repoKey && candidate.origin?.pullRequestNumber === pr.number;
|
|
2086
2086
|
});
|
|
2087
|
+
const review = matches.find((candidate) => candidate.reviewId === subject.reviewId) ?? matches.findLast((candidate) => !candidate.dismissedAt) ?? matches.at(-1);
|
|
2087
2088
|
return {
|
|
2088
2089
|
branch: pr.head.ref,
|
|
2089
2090
|
pullRequestNumber: pr.number,
|
|
@@ -3398,6 +3399,27 @@ function createReviewApi(store, data, open, shared, capabilities = () => ({
|
|
|
3398
3399
|
readReview(reviewId);
|
|
3399
3400
|
return context.json({ threads: store.askHistory.list(reviewId) });
|
|
3400
3401
|
});
|
|
3402
|
+
app.get("/:id/ask/:threadId", (context) => {
|
|
3403
|
+
const record = store.askHistory.get(context.req.param("threadId"));
|
|
3404
|
+
if (record?.reviewId !== context.req.param("id")) throw new ReviewInputError("This conversation was not found.", 404);
|
|
3405
|
+
const target = record.selection.target;
|
|
3406
|
+
return context.json({
|
|
3407
|
+
id: record.id,
|
|
3408
|
+
agent: record.agent,
|
|
3409
|
+
agentName: askAgents[record.agent].name,
|
|
3410
|
+
status: "idle",
|
|
3411
|
+
readOnly: true,
|
|
3412
|
+
bypass: false,
|
|
3413
|
+
head: record.head,
|
|
3414
|
+
cwd: record.cwd,
|
|
3415
|
+
title: record.title,
|
|
3416
|
+
selection: {
|
|
3417
|
+
title: record.selection.title,
|
|
3418
|
+
quote: target.kind === "text" ? target.quote : void 0
|
|
3419
|
+
},
|
|
3420
|
+
entries: record.entries ?? []
|
|
3421
|
+
});
|
|
3422
|
+
});
|
|
3401
3423
|
app.post("/:id/ask/:threadId/open", async (context) => {
|
|
3402
3424
|
const reviewId = context.req.param("id");
|
|
3403
3425
|
const threadId = context.req.param("threadId");
|
|
@@ -14,7 +14,7 @@ import { t as openReviewProfile } from "../profile-4ry2f3AM.js";
|
|
|
14
14
|
import { r as reviewTelemetryChannel, t as ReviewTelemetry } from "../review-telemetry-DEFnQsQ2.js";
|
|
15
15
|
import { o as REVIEW_TELEMETRY_TABS } from "../request-origin-D_4QIdoN.js";
|
|
16
16
|
import { c as removeLegacyReviewSkills, d as skipCliInstall, i as finishCliInstallUpdate, l as resetCliInstall, n as applyCliInstall, r as declineCliInstall, s as removeCliInstall, t as aliasInstallationToAccount, u as resolveCliInstallStatus } from "../account-alias-DOHN1RSH.js";
|
|
17
|
-
import { a as serverJson, c as recordClientError, d as HttpJsonError, f as ReviewServerError, i as createWhiteboardCore, l as createNodeRequestListener, n as installProcessErrorTelemetry, o as captureSanitizedUiTelemetry, p as GlobalReviewDesktopVerbRelay, r as serverCrashReportPath, s as clientErrorsForSession, t as drainServerCrashReport, u as readBoundedRequestJson } from "../process-error-telemetry-
|
|
17
|
+
import { a as serverJson, c as recordClientError, d as HttpJsonError, f as ReviewServerError, i as createWhiteboardCore, l as createNodeRequestListener, n as installProcessErrorTelemetry, o as captureSanitizedUiTelemetry, p as GlobalReviewDesktopVerbRelay, r as serverCrashReportPath, s as clientErrorsForSession, t as drainServerCrashReport, u as readBoundedRequestJson } from "../process-error-telemetry-Dw91I1r5.js";
|
|
18
18
|
import { c as readQuerySchemas } from "../authoring-tools-Cr6Kpjsx.js";
|
|
19
19
|
import crypto, { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
20
20
|
import { z } from "zod";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev.fast/whiteboard",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1-preview.20261006.100",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
"typescript": "6.0.3",
|
|
73
73
|
"vitest": "4.1.11",
|
|
74
74
|
"@dev.fast/json": "0.0.0",
|
|
75
|
-
"@dev.fast/trace-core": "0.0.0",
|
|
76
75
|
"@dev.fast/review-protocol": "0.0.0",
|
|
77
|
-
"@dev.fast/
|
|
78
|
-
"@dev.fast/
|
|
76
|
+
"@dev.fast/review-share-protocol": "0.1.2",
|
|
77
|
+
"@dev.fast/trace-core": "0.0.0",
|
|
78
|
+
"@dev.fast/trace-protocol": "0.5.0"
|
|
79
79
|
},
|
|
80
80
|
"engines": {
|
|
81
81
|
"node": ">=24 <25"
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"repo": "devdotfast/review",
|
|
86
86
|
"docs": "packages/review/instructions/authoring.md"
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "d3340667cc36422df9b7df0fea600a50b3adfc4c",
|
|
89
89
|
"scripts": {
|
|
90
90
|
"prebuild": "pnpm run build:workspace-deps",
|
|
91
91
|
"ensure:diffr": "diffr-fetch --into bin",
|
package/src/review-api/http.ts
CHANGED
|
@@ -12,11 +12,12 @@ import {
|
|
|
12
12
|
AgentSelectionSchema,
|
|
13
13
|
selectionMarkdown,
|
|
14
14
|
} from "@review/agent-selection.js";
|
|
15
|
-
import type
|
|
15
|
+
import { type AskAgentStatus, askAgents } from "@review/ask/agents.js";
|
|
16
16
|
import { checkoutFiles, mentionableFiles } from "@review/ask/checkout-files.js";
|
|
17
17
|
import { parseFileRef, resolveFileRefs } from "@review/ask/file-refs.js";
|
|
18
18
|
import {
|
|
19
19
|
type AskAgentId,
|
|
20
|
+
type AskThreadState,
|
|
20
21
|
askAgentIds,
|
|
21
22
|
askChoiceKinds,
|
|
22
23
|
askPicksSchema,
|
|
@@ -1309,6 +1310,32 @@ export function createReviewApi(
|
|
|
1309
1310
|
return context.json({ threads: store.askHistory.list(reviewId) });
|
|
1310
1311
|
});
|
|
1311
1312
|
|
|
1313
|
+
// A saved conversation, without starting its agent.
|
|
1314
|
+
app.get("/:id/ask/:threadId", (context) => {
|
|
1315
|
+
const record = store.askHistory.get(context.req.param("threadId"));
|
|
1316
|
+
|
|
1317
|
+
if (record?.reviewId !== context.req.param("id"))
|
|
1318
|
+
throw new ReviewInputError("This conversation was not found.", 404);
|
|
1319
|
+
const target = record.selection.target;
|
|
1320
|
+
|
|
1321
|
+
return context.json({
|
|
1322
|
+
id: record.id,
|
|
1323
|
+
agent: record.agent,
|
|
1324
|
+
agentName: askAgents[record.agent].name,
|
|
1325
|
+
status: "idle",
|
|
1326
|
+
readOnly: true,
|
|
1327
|
+
bypass: false,
|
|
1328
|
+
head: record.head,
|
|
1329
|
+
cwd: record.cwd,
|
|
1330
|
+
title: record.title,
|
|
1331
|
+
selection: {
|
|
1332
|
+
title: record.selection.title,
|
|
1333
|
+
quote: target.kind === "text" ? target.quote : undefined,
|
|
1334
|
+
},
|
|
1335
|
+
entries: record.entries ?? [],
|
|
1336
|
+
} satisfies AskThreadState);
|
|
1337
|
+
});
|
|
1338
|
+
|
|
1312
1339
|
// A saved conversation: attach to it if it is still running, else start
|
|
1313
1340
|
// the agent and load it, at the commit it was asked about.
|
|
1314
1341
|
app.post("/:id/ask/:threadId/open", async (context) => {
|
package/src/review-stack.ts
CHANGED
|
@@ -23,10 +23,10 @@ const GitHubStacksSchema = z.array(
|
|
|
23
23
|
export type RunGitHubApi = (host: string, endpoint: string) => Promise<string>;
|
|
24
24
|
|
|
25
25
|
export async function resolveReviewStackLayers(
|
|
26
|
-
subject: Pick<ReviewApiSummary, "origin"
|
|
26
|
+
subject: Pick<ReviewApiSummary, "origin"> & { reviewId?: string },
|
|
27
27
|
reviews: readonly Pick<
|
|
28
28
|
ReviewApiSummary,
|
|
29
|
-
"reviewId" | "title" | "origin" | "pins"
|
|
29
|
+
"reviewId" | "title" | "origin" | "pins" | "dismissedAt"
|
|
30
30
|
>[],
|
|
31
31
|
runGitHubApi: RunGitHubApi = defaultRunGitHubApi,
|
|
32
32
|
): Promise<ReviewStackLayer[]> {
|
|
@@ -66,7 +66,7 @@ export async function resolveReviewStackLayers(
|
|
|
66
66
|
);
|
|
67
67
|
|
|
68
68
|
return stack.pull_requests.map((pr, index) => {
|
|
69
|
-
const
|
|
69
|
+
const matches = reviews.filter((candidate) => {
|
|
70
70
|
const repository =
|
|
71
71
|
candidate.origin?.pullRequestUrl?.replace(/\/pull\/\d+.*$/, "") ??
|
|
72
72
|
candidate.pins?.repositoryId;
|
|
@@ -77,6 +77,11 @@ export async function resolveReviewStackLayers(
|
|
|
77
77
|
);
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
+
const review =
|
|
81
|
+
matches.find((candidate) => candidate.reviewId === subject.reviewId) ??
|
|
82
|
+
matches.findLast((candidate) => !candidate.dismissedAt) ??
|
|
83
|
+
matches.at(-1);
|
|
84
|
+
|
|
80
85
|
return {
|
|
81
86
|
branch: pr.head.ref,
|
|
82
87
|
pullRequestNumber: pr.number,
|