@schoolai/shipyard-mcp 0.3.2-next.518 → 0.3.2-next.523
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/apps/hook/dist/index.cjs +207 -75
- package/apps/server/dist/{chunk-XGFLIN7D.js → chunk-NNJ3ELQW.js} +349 -54
- package/apps/server/dist/chunk-WLIAQMMT.js +2779 -0
- package/apps/server/dist/{dist-GY2FDTC3.js → dist-STCVHI7H.js} +35 -3
- package/apps/server/dist/index.js +726 -3465
- package/apps/server/dist/{chunk-US64BNLQ.js → input-request-manager-OSA7HKQW.js} +97 -38
- package/package.json +1 -1
- package/apps/server/dist/input-request-manager-PGVST566.js +0 -9
|
@@ -499,7 +499,10 @@ var CursorOriginMetadataSchema = z.object({
|
|
|
499
499
|
conversationId: z.string(),
|
|
500
500
|
generationId: z.string().optional()
|
|
501
501
|
});
|
|
502
|
-
var UnknownOriginMetadataSchema = z.object({
|
|
502
|
+
var UnknownOriginMetadataSchema = z.object({
|
|
503
|
+
platform: z.literal("unknown"),
|
|
504
|
+
cwd: z.string()
|
|
505
|
+
});
|
|
503
506
|
var OriginMetadataSchema = z.discriminatedUnion("platform", [
|
|
504
507
|
ClaudeCodeOriginMetadataSchema,
|
|
505
508
|
DevinOriginMetadataSchema,
|
|
@@ -700,7 +703,19 @@ var PlanEventSchema = z.discriminatedUnion("type", [
|
|
|
700
703
|
data: z.object({
|
|
701
704
|
requestId: z.string(),
|
|
702
705
|
response: z.unknown(),
|
|
703
|
-
answeredBy: z.string()
|
|
706
|
+
answeredBy: z.string(),
|
|
707
|
+
requestMessage: z.string().optional(),
|
|
708
|
+
requestType: z.enum([
|
|
709
|
+
"text",
|
|
710
|
+
"multiline",
|
|
711
|
+
"choice",
|
|
712
|
+
"confirm",
|
|
713
|
+
"number",
|
|
714
|
+
"email",
|
|
715
|
+
"date",
|
|
716
|
+
"rating",
|
|
717
|
+
"multi"
|
|
718
|
+
]).optional()
|
|
704
719
|
})
|
|
705
720
|
}),
|
|
706
721
|
PlanEventBaseSchema.extend({
|
|
@@ -832,6 +847,18 @@ var PRReviewCommentSchema = z.object({
|
|
|
832
847
|
createdAt: z.number(),
|
|
833
848
|
resolved: z.boolean().optional()
|
|
834
849
|
});
|
|
850
|
+
var LocalDiffCommentSchema = z.object({
|
|
851
|
+
id: z.string(),
|
|
852
|
+
type: z.literal("local"),
|
|
853
|
+
path: z.string(),
|
|
854
|
+
line: z.number(),
|
|
855
|
+
body: z.string(),
|
|
856
|
+
author: z.string(),
|
|
857
|
+
createdAt: z.number(),
|
|
858
|
+
baseRef: z.string(),
|
|
859
|
+
resolved: z.boolean().optional(),
|
|
860
|
+
lineContentHash: z.string().optional()
|
|
861
|
+
});
|
|
835
862
|
function createLinkedPR(params) {
|
|
836
863
|
const linkedPR = {
|
|
837
864
|
...params,
|
|
@@ -898,7 +925,7 @@ function createHandedOffConversationVersion(params) {
|
|
|
898
925
|
return ConversationVersionSchema.parse(version);
|
|
899
926
|
}
|
|
900
927
|
|
|
901
|
-
// ../../packages/schema/dist/yjs-helpers-
|
|
928
|
+
// ../../packages/schema/dist/yjs-helpers-DzEyLz-f.mjs
|
|
902
929
|
import { z as z2 } from "zod";
|
|
903
930
|
import { nanoid as nanoid2 } from "nanoid";
|
|
904
931
|
import * as Y from "yjs";
|
|
@@ -1209,7 +1236,7 @@ var ChoiceQuestionSchema = QuestionBaseSchema.extend({
|
|
|
1209
1236
|
placeholder: z2.string().optional()
|
|
1210
1237
|
});
|
|
1211
1238
|
var ConfirmQuestionSchema = QuestionBaseSchema.extend({ type: z2.literal("confirm") });
|
|
1212
|
-
var
|
|
1239
|
+
var NumberQuestionBaseSchema = QuestionBaseSchema.extend({
|
|
1213
1240
|
type: z2.literal("number"),
|
|
1214
1241
|
min: z2.number().optional(),
|
|
1215
1242
|
max: z2.number().optional(),
|
|
@@ -1219,17 +1246,17 @@ var NumberQuestionSchema = QuestionBaseSchema.extend({
|
|
|
1219
1246
|
"currency",
|
|
1220
1247
|
"percentage"
|
|
1221
1248
|
]).optional()
|
|
1222
|
-
})
|
|
1249
|
+
});
|
|
1223
1250
|
var EmailQuestionSchema = QuestionBaseSchema.extend({
|
|
1224
1251
|
type: z2.literal("email"),
|
|
1225
1252
|
domain: z2.string().optional()
|
|
1226
1253
|
});
|
|
1227
|
-
var
|
|
1254
|
+
var DateQuestionBaseSchema = QuestionBaseSchema.extend({
|
|
1228
1255
|
type: z2.literal("date"),
|
|
1229
1256
|
min: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").optional(),
|
|
1230
1257
|
max: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").optional()
|
|
1231
|
-
})
|
|
1232
|
-
var
|
|
1258
|
+
});
|
|
1259
|
+
var RatingQuestionBaseSchema = QuestionBaseSchema.extend({
|
|
1233
1260
|
type: z2.literal("rating"),
|
|
1234
1261
|
min: z2.number().int().optional(),
|
|
1235
1262
|
max: z2.number().int().optional(),
|
|
@@ -1242,20 +1269,58 @@ var RatingQuestionSchema = QuestionBaseSchema.extend({
|
|
|
1242
1269
|
low: z2.string().optional(),
|
|
1243
1270
|
high: z2.string().optional()
|
|
1244
1271
|
}).optional()
|
|
1245
|
-
})
|
|
1246
|
-
if (data.min === void 0 || data.max === void 0) return true;
|
|
1247
|
-
return data.min <= data.max && data.max - data.min <= 20;
|
|
1248
|
-
}, { message: "Rating scale must have min <= max and at most 20 items" });
|
|
1272
|
+
});
|
|
1249
1273
|
var QuestionSchema = z2.discriminatedUnion("type", [
|
|
1250
1274
|
TextQuestionSchema,
|
|
1251
1275
|
MultilineQuestionSchema,
|
|
1252
1276
|
ChoiceQuestionSchema,
|
|
1253
1277
|
ConfirmQuestionSchema,
|
|
1254
|
-
|
|
1278
|
+
NumberQuestionBaseSchema,
|
|
1255
1279
|
EmailQuestionSchema,
|
|
1256
|
-
|
|
1257
|
-
|
|
1280
|
+
DateQuestionBaseSchema,
|
|
1281
|
+
RatingQuestionBaseSchema
|
|
1258
1282
|
]);
|
|
1283
|
+
function validateNumberQuestion(q, index, ctx) {
|
|
1284
|
+
if (q.min !== void 0 && q.max !== void 0 && q.min > q.max) ctx.addIssue({
|
|
1285
|
+
code: z2.ZodIssueCode.custom,
|
|
1286
|
+
message: "min must be <= max",
|
|
1287
|
+
path: ["questions", index]
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
function validateDateQuestion(q, index, ctx) {
|
|
1291
|
+
if (q.min !== void 0 && q.max !== void 0 && new Date(q.min) > new Date(q.max)) ctx.addIssue({
|
|
1292
|
+
code: z2.ZodIssueCode.custom,
|
|
1293
|
+
message: "min date must be before or equal to max date",
|
|
1294
|
+
path: ["questions", index]
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
function validateRatingQuestion(q, index, ctx) {
|
|
1298
|
+
if (q.min === void 0 || q.max === void 0) return;
|
|
1299
|
+
if (q.min > q.max || q.max - q.min > 20) ctx.addIssue({
|
|
1300
|
+
code: z2.ZodIssueCode.custom,
|
|
1301
|
+
message: "Rating scale must have min <= max and at most 20 items",
|
|
1302
|
+
path: ["questions", index]
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
function validateQuestionConstraints(questions, ctx) {
|
|
1306
|
+
for (let i = 0; i < questions.length; i++) {
|
|
1307
|
+
const q = questions[i];
|
|
1308
|
+
if (!q) continue;
|
|
1309
|
+
switch (q.type) {
|
|
1310
|
+
case "number":
|
|
1311
|
+
validateNumberQuestion(q, i, ctx);
|
|
1312
|
+
break;
|
|
1313
|
+
case "date":
|
|
1314
|
+
validateDateQuestion(q, i, ctx);
|
|
1315
|
+
break;
|
|
1316
|
+
case "rating":
|
|
1317
|
+
validateRatingQuestion(q, i, ctx);
|
|
1318
|
+
break;
|
|
1319
|
+
default:
|
|
1320
|
+
break;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1259
1324
|
var MultiQuestionInputRequestSchema = z2.object({
|
|
1260
1325
|
id: z2.string(),
|
|
1261
1326
|
createdAt: z2.number(),
|
|
@@ -1268,6 +1333,8 @@ var MultiQuestionInputRequestSchema = z2.object({
|
|
|
1268
1333
|
answeredAt: z2.number().optional(),
|
|
1269
1334
|
answeredBy: z2.string().optional(),
|
|
1270
1335
|
isBlocker: z2.boolean().optional()
|
|
1336
|
+
}).superRefine((data, ctx) => {
|
|
1337
|
+
validateQuestionConstraints(data.questions, ctx);
|
|
1271
1338
|
});
|
|
1272
1339
|
var AnyInputRequestSchema = z2.union([InputRequestSchema, MultiQuestionInputRequestSchema]);
|
|
1273
1340
|
function createMultiQuestionInputRequest(params) {
|
|
@@ -1298,7 +1365,8 @@ var YDOC_KEYS = {
|
|
|
1298
1365
|
PR_REVIEW_COMMENTS: "prReviewComments",
|
|
1299
1366
|
EVENTS: "events",
|
|
1300
1367
|
SNAPSHOTS: "snapshots",
|
|
1301
|
-
INPUT_REQUESTS: "inputRequests"
|
|
1368
|
+
INPUT_REQUESTS: "inputRequests",
|
|
1369
|
+
LOCAL_DIFF_COMMENTS: "localDiffComments"
|
|
1302
1370
|
};
|
|
1303
1371
|
var validKeys = new Set(Object.values(YDOC_KEYS));
|
|
1304
1372
|
function isValidYDocKey(key) {
|
|
@@ -1353,6 +1421,20 @@ function extractMentions(body) {
|
|
|
1353
1421
|
function toUnknownArray(array) {
|
|
1354
1422
|
return array.toJSON();
|
|
1355
1423
|
}
|
|
1424
|
+
function findInputRequestById(data, requestId) {
|
|
1425
|
+
for (let i = 0; i < data.length; i++) {
|
|
1426
|
+
const item = data[i];
|
|
1427
|
+
if (item && typeof item === "object" && "id" in item && item.id === requestId) {
|
|
1428
|
+
const parsed = AnyInputRequestSchema.safeParse(item);
|
|
1429
|
+
if (parsed.success) return {
|
|
1430
|
+
rawIndex: i,
|
|
1431
|
+
request: parsed.data
|
|
1432
|
+
};
|
|
1433
|
+
return null;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
return null;
|
|
1437
|
+
}
|
|
1356
1438
|
var VALID_STATUS_TRANSITIONS = {
|
|
1357
1439
|
draft: [
|
|
1358
1440
|
"pending_review",
|
|
@@ -1430,8 +1512,8 @@ function applyChangesRequestedTransition(map, transition) {
|
|
|
1430
1512
|
if (transition.reviewComment !== void 0) map.set("reviewComment", transition.reviewComment);
|
|
1431
1513
|
}
|
|
1432
1514
|
function applyInProgressTransition(map, transition) {
|
|
1433
|
-
|
|
1434
|
-
|
|
1515
|
+
map.set("reviewedAt", transition.reviewedAt);
|
|
1516
|
+
map.set("reviewedBy", transition.reviewedBy);
|
|
1435
1517
|
if (transition.reviewComment !== void 0) map.set("reviewComment", transition.reviewComment);
|
|
1436
1518
|
}
|
|
1437
1519
|
function applyCompletedTransition(map, transition) {
|
|
@@ -1757,6 +1839,39 @@ function removePRReviewComment(ydoc, commentId) {
|
|
|
1757
1839
|
array.delete(index, 1);
|
|
1758
1840
|
return true;
|
|
1759
1841
|
}
|
|
1842
|
+
function getLocalDiffComments(ydoc) {
|
|
1843
|
+
return toUnknownArray(ydoc.getArray(YDOC_KEYS.LOCAL_DIFF_COMMENTS)).map((item) => LocalDiffCommentSchema.safeParse(item)).filter((result) => result.success).map((result) => result.data);
|
|
1844
|
+
}
|
|
1845
|
+
function getLocalDiffCommentsForFile(ydoc, path) {
|
|
1846
|
+
return getLocalDiffComments(ydoc).filter((c) => c.path === path);
|
|
1847
|
+
}
|
|
1848
|
+
function addLocalDiffComment(ydoc, comment, actor) {
|
|
1849
|
+
const validated = LocalDiffCommentSchema.parse(comment);
|
|
1850
|
+
ydoc.transact(() => {
|
|
1851
|
+
ydoc.getArray(YDOC_KEYS.LOCAL_DIFF_COMMENTS).push([validated]);
|
|
1852
|
+
}, actor ? { actor } : void 0);
|
|
1853
|
+
}
|
|
1854
|
+
function resolveLocalDiffComment(ydoc, commentId, resolved) {
|
|
1855
|
+
const array = ydoc.getArray(YDOC_KEYS.LOCAL_DIFF_COMMENTS);
|
|
1856
|
+
const existing = toUnknownArray(array).map((item) => LocalDiffCommentSchema.safeParse(item)).filter((r) => r.success).map((r) => r.data);
|
|
1857
|
+
const index = existing.findIndex((c) => c.id === commentId);
|
|
1858
|
+
if (index === -1) return false;
|
|
1859
|
+
const comment = existing[index];
|
|
1860
|
+
if (!comment) return false;
|
|
1861
|
+
array.delete(index, 1);
|
|
1862
|
+
array.insert(index, [{
|
|
1863
|
+
...comment,
|
|
1864
|
+
resolved
|
|
1865
|
+
}]);
|
|
1866
|
+
return true;
|
|
1867
|
+
}
|
|
1868
|
+
function removeLocalDiffComment(ydoc, commentId) {
|
|
1869
|
+
const array = ydoc.getArray(YDOC_KEYS.LOCAL_DIFF_COMMENTS);
|
|
1870
|
+
const index = toUnknownArray(array).map((item) => LocalDiffCommentSchema.safeParse(item)).filter((r) => r.success).map((r) => r.data).findIndex((c) => c.id === commentId);
|
|
1871
|
+
if (index === -1) return false;
|
|
1872
|
+
array.delete(index, 1);
|
|
1873
|
+
return true;
|
|
1874
|
+
}
|
|
1760
1875
|
function extractViewedByFromCrdt(existingViewedBy) {
|
|
1761
1876
|
const viewedBy = {};
|
|
1762
1877
|
if (existingViewedBy instanceof Y.Map) {
|
|
@@ -1937,17 +2052,12 @@ function unarchivePlan(ydoc, actorId) {
|
|
|
1937
2052
|
}
|
|
1938
2053
|
function answerInputRequest(ydoc, requestId, response, answeredBy) {
|
|
1939
2054
|
const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
|
|
1940
|
-
const
|
|
1941
|
-
|
|
1942
|
-
if (index === -1) return {
|
|
1943
|
-
success: false,
|
|
1944
|
-
error: "Request not found"
|
|
1945
|
-
};
|
|
1946
|
-
const request = requests[index];
|
|
1947
|
-
if (!request) return {
|
|
2055
|
+
const found = findInputRequestById(toUnknownArray(requestsArray), requestId);
|
|
2056
|
+
if (!found) return {
|
|
1948
2057
|
success: false,
|
|
1949
2058
|
error: "Request not found"
|
|
1950
2059
|
};
|
|
2060
|
+
const { rawIndex: index, request } = found;
|
|
1951
2061
|
if (request.status !== "pending") switch (request.status) {
|
|
1952
2062
|
case "answered":
|
|
1953
2063
|
return {
|
|
@@ -1985,24 +2095,21 @@ function answerInputRequest(ydoc, requestId, response, answeredBy) {
|
|
|
1985
2095
|
logPlanEvent(ydoc, "input_request_answered", answeredBy, {
|
|
1986
2096
|
requestId,
|
|
1987
2097
|
response,
|
|
1988
|
-
answeredBy
|
|
2098
|
+
answeredBy,
|
|
2099
|
+
requestMessage: "message" in request ? request.message : void 0,
|
|
2100
|
+
requestType: request.type
|
|
1989
2101
|
});
|
|
1990
2102
|
});
|
|
1991
2103
|
return { success: true };
|
|
1992
2104
|
}
|
|
1993
2105
|
function answerMultiQuestionInputRequest(ydoc, requestId, responses, answeredBy) {
|
|
1994
2106
|
const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
|
|
1995
|
-
const
|
|
1996
|
-
|
|
1997
|
-
if (index === -1) return {
|
|
1998
|
-
success: false,
|
|
1999
|
-
error: "Request not found"
|
|
2000
|
-
};
|
|
2001
|
-
const request = requests[index];
|
|
2002
|
-
if (!request) return {
|
|
2107
|
+
const found = findInputRequestById(toUnknownArray(requestsArray), requestId);
|
|
2108
|
+
if (!found) return {
|
|
2003
2109
|
success: false,
|
|
2004
2110
|
error: "Request not found"
|
|
2005
2111
|
};
|
|
2112
|
+
const { rawIndex: index, request } = found;
|
|
2006
2113
|
if (request.type !== "multi") return {
|
|
2007
2114
|
success: false,
|
|
2008
2115
|
error: "Request is not pending"
|
|
@@ -2044,24 +2151,20 @@ function answerMultiQuestionInputRequest(ydoc, requestId, responses, answeredBy)
|
|
|
2044
2151
|
logPlanEvent(ydoc, "input_request_answered", answeredBy, {
|
|
2045
2152
|
requestId,
|
|
2046
2153
|
response: responses,
|
|
2047
|
-
answeredBy
|
|
2154
|
+
answeredBy,
|
|
2155
|
+
requestType: "multi"
|
|
2048
2156
|
});
|
|
2049
2157
|
});
|
|
2050
2158
|
return { success: true };
|
|
2051
2159
|
}
|
|
2052
2160
|
function cancelInputRequest(ydoc, requestId) {
|
|
2053
2161
|
const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
|
|
2054
|
-
const
|
|
2055
|
-
|
|
2056
|
-
if (index === -1) return {
|
|
2057
|
-
success: false,
|
|
2058
|
-
error: "Request not found"
|
|
2059
|
-
};
|
|
2060
|
-
const request = requests[index];
|
|
2061
|
-
if (!request) return {
|
|
2162
|
+
const found = findInputRequestById(toUnknownArray(requestsArray), requestId);
|
|
2163
|
+
if (!found) return {
|
|
2062
2164
|
success: false,
|
|
2063
2165
|
error: "Request not found"
|
|
2064
2166
|
};
|
|
2167
|
+
const { rawIndex: index, request } = found;
|
|
2065
2168
|
if (request.status !== "pending") return {
|
|
2066
2169
|
success: false,
|
|
2067
2170
|
error: `Request is not pending`
|
|
@@ -2079,17 +2182,12 @@ function cancelInputRequest(ydoc, requestId) {
|
|
|
2079
2182
|
}
|
|
2080
2183
|
function declineInputRequest(ydoc, requestId) {
|
|
2081
2184
|
const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
|
|
2082
|
-
const
|
|
2083
|
-
|
|
2084
|
-
if (index === -1) return {
|
|
2085
|
-
success: false,
|
|
2086
|
-
error: "Request not found"
|
|
2087
|
-
};
|
|
2088
|
-
const request = requests[index];
|
|
2089
|
-
if (!request) return {
|
|
2185
|
+
const found = findInputRequestById(toUnknownArray(requestsArray), requestId);
|
|
2186
|
+
if (!found) return {
|
|
2090
2187
|
success: false,
|
|
2091
2188
|
error: "Request not found"
|
|
2092
2189
|
};
|
|
2190
|
+
const { rawIndex: index, request } = found;
|
|
2093
2191
|
if (request.status !== "pending") return {
|
|
2094
2192
|
success: false,
|
|
2095
2193
|
error: `Request is not pending`
|
|
@@ -2739,6 +2837,185 @@ function extractTextFromBlock(block) {
|
|
|
2739
2837
|
if (!block.content || !Array.isArray(block.content) || block.content.length === 0) return "";
|
|
2740
2838
|
return block.content.map((item) => item.text || "").join("").trim();
|
|
2741
2839
|
}
|
|
2840
|
+
function hashLineContent(content) {
|
|
2841
|
+
let hash = 0;
|
|
2842
|
+
for (let i = 0; i < content.length; i++) {
|
|
2843
|
+
const char = content.charCodeAt(i);
|
|
2844
|
+
hash = (hash << 5) - hash + char;
|
|
2845
|
+
hash = hash & hash;
|
|
2846
|
+
}
|
|
2847
|
+
return hash.toString(16);
|
|
2848
|
+
}
|
|
2849
|
+
function computeCommentStaleness(comment, currentHeadSha, currentLineContent) {
|
|
2850
|
+
if (currentHeadSha && comment.baseRef !== currentHeadSha) return {
|
|
2851
|
+
type: "head_changed",
|
|
2852
|
+
isStale: true
|
|
2853
|
+
};
|
|
2854
|
+
if (currentLineContent !== void 0 && comment.lineContentHash) {
|
|
2855
|
+
if (hashLineContent(currentLineContent) !== comment.lineContentHash) return {
|
|
2856
|
+
type: "content_changed",
|
|
2857
|
+
isStale: true
|
|
2858
|
+
};
|
|
2859
|
+
}
|
|
2860
|
+
return {
|
|
2861
|
+
type: "none",
|
|
2862
|
+
isStale: false
|
|
2863
|
+
};
|
|
2864
|
+
}
|
|
2865
|
+
function isLineContentStale(comment, currentLineContent) {
|
|
2866
|
+
if (!comment.lineContentHash || currentLineContent === void 0) return false;
|
|
2867
|
+
const currentHash = hashLineContent(currentLineContent);
|
|
2868
|
+
return comment.lineContentHash !== currentHash;
|
|
2869
|
+
}
|
|
2870
|
+
function withStalenessInfo(comment, currentHeadSha, currentLineContent) {
|
|
2871
|
+
const staleness = computeCommentStaleness(comment, currentHeadSha, currentLineContent);
|
|
2872
|
+
return {
|
|
2873
|
+
...comment,
|
|
2874
|
+
isStale: staleness.isStale,
|
|
2875
|
+
stalenessType: staleness.type
|
|
2876
|
+
};
|
|
2877
|
+
}
|
|
2878
|
+
function withStalenessInfoBatch(comments, currentHeadSha, lineContentMap) {
|
|
2879
|
+
return comments.map((comment) => {
|
|
2880
|
+
const key = `${comment.path}:${comment.line}`;
|
|
2881
|
+
const currentLineContent = lineContentMap?.get(key);
|
|
2882
|
+
return withStalenessInfo(comment, currentHeadSha, currentLineContent);
|
|
2883
|
+
});
|
|
2884
|
+
}
|
|
2885
|
+
function isDiffHeader(line) {
|
|
2886
|
+
return line.startsWith("diff --git") || line.startsWith("index ") || line.startsWith("---") || line.startsWith("+++");
|
|
2887
|
+
}
|
|
2888
|
+
function processLineDiff(line, currentLineNumber, filePath, lineContentMap) {
|
|
2889
|
+
const hunkMatch = line.match(/^@@.*\+(\d+)/);
|
|
2890
|
+
if (hunkMatch?.[1]) return Number.parseInt(hunkMatch[1], 10);
|
|
2891
|
+
if (isDiffHeader(line)) return currentLineNumber;
|
|
2892
|
+
if (line.startsWith("-")) return currentLineNumber;
|
|
2893
|
+
if (line.startsWith("+")) {
|
|
2894
|
+
const content = line.slice(1);
|
|
2895
|
+
lineContentMap.set(`${filePath}:${currentLineNumber}`, content);
|
|
2896
|
+
return currentLineNumber + 1;
|
|
2897
|
+
}
|
|
2898
|
+
if (line.startsWith(" ") || line === "") {
|
|
2899
|
+
const content = line.startsWith(" ") ? line.slice(1) : "";
|
|
2900
|
+
lineContentMap.set(`${filePath}:${currentLineNumber}`, content);
|
|
2901
|
+
return currentLineNumber + 1;
|
|
2902
|
+
}
|
|
2903
|
+
return currentLineNumber;
|
|
2904
|
+
}
|
|
2905
|
+
function processFilePatch(file, lineContentMap) {
|
|
2906
|
+
if (!file.patch) return;
|
|
2907
|
+
const lines = file.patch.split("\n");
|
|
2908
|
+
let currentLine = 0;
|
|
2909
|
+
for (const line of lines) currentLine = processLineDiff(line, currentLine, file.path, lineContentMap);
|
|
2910
|
+
}
|
|
2911
|
+
function buildLineContentMap(files) {
|
|
2912
|
+
const lineContentMap = /* @__PURE__ */ new Map();
|
|
2913
|
+
for (const file of files) processFilePatch(file, lineContentMap);
|
|
2914
|
+
return lineContentMap;
|
|
2915
|
+
}
|
|
2916
|
+
function formatStalenessMarker(staleness) {
|
|
2917
|
+
if (!staleness.isStale) return "";
|
|
2918
|
+
switch (staleness.type) {
|
|
2919
|
+
case "head_changed":
|
|
2920
|
+
return "[STALE: HEAD changed]";
|
|
2921
|
+
case "content_changed":
|
|
2922
|
+
return "[STALE: Line content changed]";
|
|
2923
|
+
default:
|
|
2924
|
+
return "";
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
function groupBy(items, getKey, sortKeys) {
|
|
2928
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
2929
|
+
for (const item of items) {
|
|
2930
|
+
const key = getKey(item);
|
|
2931
|
+
const existing = grouped.get(key);
|
|
2932
|
+
if (existing) existing.push(item);
|
|
2933
|
+
else grouped.set(key, [item]);
|
|
2934
|
+
}
|
|
2935
|
+
return Array.from(grouped.entries()).sort(([a], [b]) => sortKeys(a, b));
|
|
2936
|
+
}
|
|
2937
|
+
function formatCommentLine(comment) {
|
|
2938
|
+
const markers = [];
|
|
2939
|
+
if (comment.resolved) markers.push("[RESOLVED]");
|
|
2940
|
+
if (comment.staleness) {
|
|
2941
|
+
const stalenessMarker = formatStalenessMarker(comment.staleness);
|
|
2942
|
+
if (stalenessMarker) markers.push(stalenessMarker);
|
|
2943
|
+
}
|
|
2944
|
+
const markerStr = markers.length > 0 ? ` ${markers.join(" ")}` : "";
|
|
2945
|
+
const body = comment.body.replace(/\n/g, " ").trim();
|
|
2946
|
+
return `- Line ${comment.line} (${comment.author})${markerStr}: ${body}`;
|
|
2947
|
+
}
|
|
2948
|
+
function formatFileSection(path, comments) {
|
|
2949
|
+
return `### ${path}
|
|
2950
|
+
${[...comments].sort((a, b) => a.line - b.line).map(formatCommentLine).join("\n")}`;
|
|
2951
|
+
}
|
|
2952
|
+
function formatLocalCommentsSection(comments) {
|
|
2953
|
+
return `## Local Changes Comments
|
|
2954
|
+
|
|
2955
|
+
${groupBy(comments, (c) => c.path, (a, b) => a.localeCompare(b)).map(([path, fileComments]) => formatFileSection(path, fileComments)).join("\n\n")}`;
|
|
2956
|
+
}
|
|
2957
|
+
function formatPRCommentsSections(comments) {
|
|
2958
|
+
return groupBy(comments, (c) => c.prNumber, (a, b) => a - b).map(([prNumber, prComments]) => {
|
|
2959
|
+
return `## PR Review Comments (PR #${prNumber})
|
|
2960
|
+
|
|
2961
|
+
${groupBy(prComments, (c) => c.path, (a, b) => a.localeCompare(b)).map(([path, fileComments]) => formatFileSection(path, fileComments)).join("\n\n")}`;
|
|
2962
|
+
});
|
|
2963
|
+
}
|
|
2964
|
+
function separateCommentTypes(comments) {
|
|
2965
|
+
return {
|
|
2966
|
+
local: comments.filter((c) => "type" in c && c.type === "local"),
|
|
2967
|
+
pr: comments.filter((c) => !("type" in c))
|
|
2968
|
+
};
|
|
2969
|
+
}
|
|
2970
|
+
function formatDiffCommentsForLLM(comments, options = {}) {
|
|
2971
|
+
const { includeResolved = false, currentHeadSha, files } = options;
|
|
2972
|
+
const lineContentMap = options.lineContentMap ?? (files ? buildLineContentMap(files) : void 0);
|
|
2973
|
+
const unresolvedComments = comments.filter((c) => !c.resolved);
|
|
2974
|
+
const resolvedCount = comments.length - unresolvedComments.length;
|
|
2975
|
+
const commentsToShow = includeResolved ? comments : unresolvedComments;
|
|
2976
|
+
if (commentsToShow.length === 0) return resolvedCount > 0 ? `All ${resolvedCount} diff comment(s) have been resolved.` : "";
|
|
2977
|
+
const { local, pr } = separateCommentTypes(commentsToShow);
|
|
2978
|
+
const sections = [];
|
|
2979
|
+
if (local.length > 0) {
|
|
2980
|
+
const localWithStaleness = local.map((comment) => {
|
|
2981
|
+
const key = `${comment.path}:${comment.line}`;
|
|
2982
|
+
const currentLineContent = lineContentMap?.get(key);
|
|
2983
|
+
const staleness = computeCommentStaleness(comment, currentHeadSha, currentLineContent);
|
|
2984
|
+
return {
|
|
2985
|
+
...comment,
|
|
2986
|
+
staleness
|
|
2987
|
+
};
|
|
2988
|
+
});
|
|
2989
|
+
sections.push(formatLocalCommentsSection(localWithStaleness));
|
|
2990
|
+
}
|
|
2991
|
+
if (pr.length > 0) sections.push(...formatPRCommentsSections(pr));
|
|
2992
|
+
let output = sections.join("\n\n");
|
|
2993
|
+
if (!includeResolved && resolvedCount > 0) output += `
|
|
2994
|
+
|
|
2995
|
+
---
|
|
2996
|
+
(${resolvedCount} resolved comment(s) not shown)`;
|
|
2997
|
+
return output;
|
|
2998
|
+
}
|
|
2999
|
+
function formatPRCommentsForLLM(comments, options = {}) {
|
|
3000
|
+
return formatDiffCommentsForLLM(comments, options);
|
|
3001
|
+
}
|
|
3002
|
+
function getPRCommentsSummary(comments) {
|
|
3003
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
3004
|
+
let unresolved = 0;
|
|
3005
|
+
let resolved = 0;
|
|
3006
|
+
for (const comment of comments) {
|
|
3007
|
+
if (comment.resolved) resolved++;
|
|
3008
|
+
else unresolved++;
|
|
3009
|
+
const count = byFile.get(comment.path) ?? 0;
|
|
3010
|
+
byFile.set(comment.path, count + 1);
|
|
3011
|
+
}
|
|
3012
|
+
return {
|
|
3013
|
+
total: comments.length,
|
|
3014
|
+
unresolved,
|
|
3015
|
+
resolved,
|
|
3016
|
+
byFile
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
2742
3019
|
var EnvironmentContextSchema = z4.object({
|
|
2743
3020
|
projectName: z4.string().optional(),
|
|
2744
3021
|
branch: z4.string().optional(),
|
|
@@ -2868,6 +3145,7 @@ var LocalChangesResponseSchema = z4.object({
|
|
|
2868
3145
|
available: z4.literal(true),
|
|
2869
3146
|
branch: z4.string(),
|
|
2870
3147
|
baseBranch: z4.string(),
|
|
3148
|
+
headSha: z4.string().optional(),
|
|
2871
3149
|
staged: z4.array(LocalFileChangeSchema),
|
|
2872
3150
|
unstaged: z4.array(LocalFileChangeSchema),
|
|
2873
3151
|
untracked: z4.array(z4.string()),
|
|
@@ -3184,6 +3462,7 @@ var TOOL_NAMES = {
|
|
|
3184
3462
|
CREATE_PLAN: "create_plan",
|
|
3185
3463
|
EXECUTE_CODE: "execute_code",
|
|
3186
3464
|
LINK_PR: "link_pr",
|
|
3465
|
+
READ_DIFF_COMMENTS: "read_diff_comments",
|
|
3187
3466
|
READ_PLAN: "read_plan",
|
|
3188
3467
|
REGENERATE_SESSION_TOKEN: "regenerate_session_token",
|
|
3189
3468
|
REQUEST_USER_INPUT: "request_user_input",
|
|
@@ -3314,7 +3593,7 @@ var planRouter = router({
|
|
|
3314
3593
|
message: "Plan not found"
|
|
3315
3594
|
});
|
|
3316
3595
|
const origin = metadata.origin;
|
|
3317
|
-
const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
|
|
3596
|
+
const cwd = origin?.platform === "claude-code" || origin?.platform === "unknown" ? origin.cwd : void 0;
|
|
3318
3597
|
if (!cwd) return {
|
|
3319
3598
|
available: false,
|
|
3320
3599
|
reason: "no_cwd",
|
|
@@ -3335,7 +3614,7 @@ var planRouter = router({
|
|
|
3335
3614
|
message: "Plan not found"
|
|
3336
3615
|
});
|
|
3337
3616
|
const origin = metadata.origin;
|
|
3338
|
-
const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
|
|
3617
|
+
const cwd = origin?.platform === "claude-code" || origin?.platform === "unknown" ? origin.cwd : void 0;
|
|
3339
3618
|
if (!cwd) return {
|
|
3340
3619
|
content: null,
|
|
3341
3620
|
error: "No working directory available"
|
|
@@ -3432,6 +3711,7 @@ export {
|
|
|
3432
3711
|
LinkedPRStatusValues,
|
|
3433
3712
|
LinkedPRSchema,
|
|
3434
3713
|
PRReviewCommentSchema,
|
|
3714
|
+
LocalDiffCommentSchema,
|
|
3435
3715
|
createLinkedPR,
|
|
3436
3716
|
createGitHubArtifact,
|
|
3437
3717
|
createLocalArtifact,
|
|
@@ -3517,6 +3797,11 @@ export {
|
|
|
3517
3797
|
addPRReviewComment,
|
|
3518
3798
|
resolvePRReviewComment,
|
|
3519
3799
|
removePRReviewComment,
|
|
3800
|
+
getLocalDiffComments,
|
|
3801
|
+
getLocalDiffCommentsForFile,
|
|
3802
|
+
addLocalDiffComment,
|
|
3803
|
+
resolveLocalDiffComment,
|
|
3804
|
+
removeLocalDiffComment,
|
|
3520
3805
|
markPlanAsViewed,
|
|
3521
3806
|
getViewedBy,
|
|
3522
3807
|
isPlanUnread,
|
|
@@ -3561,6 +3846,16 @@ export {
|
|
|
3561
3846
|
formatAsClaudeCodeJSONL,
|
|
3562
3847
|
formatDeliverablesForLLM,
|
|
3563
3848
|
extractDeliverables,
|
|
3849
|
+
hashLineContent,
|
|
3850
|
+
computeCommentStaleness,
|
|
3851
|
+
isLineContentStale,
|
|
3852
|
+
withStalenessInfo,
|
|
3853
|
+
withStalenessInfoBatch,
|
|
3854
|
+
buildLineContentMap,
|
|
3855
|
+
formatStalenessMarker,
|
|
3856
|
+
formatDiffCommentsForLLM,
|
|
3857
|
+
formatPRCommentsForLLM,
|
|
3858
|
+
getPRCommentsSummary,
|
|
3564
3859
|
EnvironmentContextSchema,
|
|
3565
3860
|
GitHubPRResponseSchema,
|
|
3566
3861
|
asPlanId,
|