@a9n-shoji/rvw 0.4.3 → 0.6.0
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/CHANGELOG.md +78 -0
- package/README.md +143 -38
- package/dist/cli.mjs +1590 -83
- package/dist/cli.mjs.map +4 -4
- package/dist/web/assets/{DocumentViewer-CWTnSlpG.js → DocumentViewer-D_PY7MU3.js} +2 -2
- package/dist/web/assets/StructureViewer-dhpw7G3m.js +7 -0
- package/dist/web/assets/{WalkthroughPanel-D2KqSIf9.js → WalkthroughPanel-DvyIFY5z.js} +1 -1
- package/dist/web/assets/{WalkthroughViewer-BDb-99Qk.js → WalkthroughViewer-y-grnBAx.js} +1 -1
- package/dist/web/assets/index-D6YvPSBz.css +1 -0
- package/dist/web/assets/index-k6AcFBgL.js +11 -0
- package/dist/web/index.html +3 -3
- package/migrations/018_comment_watch_tasks.sql +10 -0
- package/migrations/019_comment_watch_write_reservations.sql +11 -0
- package/migrations/020_structure_retired_region_ids.sql +6 -0
- package/package.json +3 -1
- package/skills/rvw/SKILL.md +1 -1
- package/skills/rvw-review-compose/SKILL.md +171 -0
- package/skills/rvw-review-compose/agents/openai.yaml +4 -0
- package/skills/rvw-review-compose/references/review-composition.md +311 -0
- package/skills/rvw-structure/SKILL.md +107 -22
- package/skills/rvw-structure/agents/openai.yaml +2 -2
- package/skills/rvw-structure/references/structure-authoring.md +174 -30
- package/skills/rvw-walkthrough/SKILL.md +37 -12
- package/skills/rvw-walkthrough/agents/openai.yaml +2 -2
- package/skills/rvw-walkthrough/references/walkthrough-authoring.md +29 -4
- package/skills/rvw-watch-comments/SKILL.md +58 -13
- package/skills/rvw-watch-comments/scripts/auto-ack.mjs +67 -9
- package/skills/rvw-watch-comments/scripts/preflight.mjs +2 -1
- package/skills/rvw-watch-comments/scripts/watch-driver.mjs +47 -1
- package/skills/rvw-watch-comments/scripts/watch-state.mjs +376 -42
- package/dist/web/assets/StructureViewer-EKDvAQ2a.js +0 -5
- package/dist/web/assets/index-B0xRoLW2.css +0 -1
- package/dist/web/assets/index-DC6BgBp4.js +0 -11
package/dist/cli.mjs
CHANGED
|
@@ -18698,6 +18698,52 @@ function parseStructureUri(uri) {
|
|
|
18698
18698
|
return id;
|
|
18699
18699
|
}
|
|
18700
18700
|
|
|
18701
|
+
// src/domain/structure-presentation.ts
|
|
18702
|
+
function compareStructureIds(left, right) {
|
|
18703
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
18704
|
+
}
|
|
18705
|
+
function canonicalStructureBackboneEdgeIds(edgeIds) {
|
|
18706
|
+
return [...edgeIds].sort(compareStructureIds);
|
|
18707
|
+
}
|
|
18708
|
+
function canonicalStructureRegionNodeIds(nodeIds) {
|
|
18709
|
+
return [...nodeIds].sort(compareStructureIds);
|
|
18710
|
+
}
|
|
18711
|
+
function canonicalStructurePresentationRegions(regions) {
|
|
18712
|
+
return [...regions].map((region) => ({
|
|
18713
|
+
...region,
|
|
18714
|
+
nodeIds: canonicalStructureRegionNodeIds(region.nodeIds)
|
|
18715
|
+
})).sort((left, right) => compareStructureIds(left.id, right.id));
|
|
18716
|
+
}
|
|
18717
|
+
function structureBackboneNodeIds(edges) {
|
|
18718
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
18719
|
+
for (const edge of edges) {
|
|
18720
|
+
nodeIds.add(edge.from);
|
|
18721
|
+
nodeIds.add(edge.to);
|
|
18722
|
+
}
|
|
18723
|
+
return nodeIds;
|
|
18724
|
+
}
|
|
18725
|
+
function isStructureBackboneWeaklyConnected(edges, startNodeId) {
|
|
18726
|
+
const nodeIds = structureBackboneNodeIds(edges);
|
|
18727
|
+
if (!nodeIds.has(startNodeId)) return false;
|
|
18728
|
+
const neighbors = new Map([...nodeIds].map((nodeId) => [nodeId, /* @__PURE__ */ new Set()]));
|
|
18729
|
+
for (const edge of edges) {
|
|
18730
|
+
if (edge.from === edge.to) continue;
|
|
18731
|
+
neighbors.get(edge.from).add(edge.to);
|
|
18732
|
+
neighbors.get(edge.to).add(edge.from);
|
|
18733
|
+
}
|
|
18734
|
+
const reached = /* @__PURE__ */ new Set([startNodeId]);
|
|
18735
|
+
const queue = [startNodeId];
|
|
18736
|
+
while (queue.length > 0) {
|
|
18737
|
+
const current = queue.shift();
|
|
18738
|
+
for (const neighbor of neighbors.get(current) ?? []) {
|
|
18739
|
+
if (reached.has(neighbor)) continue;
|
|
18740
|
+
reached.add(neighbor);
|
|
18741
|
+
queue.push(neighbor);
|
|
18742
|
+
}
|
|
18743
|
+
}
|
|
18744
|
+
return reached.size === nodeIds.size;
|
|
18745
|
+
}
|
|
18746
|
+
|
|
18701
18747
|
// src/domain/walkthrough-uri.ts
|
|
18702
18748
|
var prefix2 = "rvw://walkthrough/";
|
|
18703
18749
|
var walkthroughIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -18715,6 +18761,63 @@ function parseWalkthroughUri(uri) {
|
|
|
18715
18761
|
return id;
|
|
18716
18762
|
}
|
|
18717
18763
|
|
|
18764
|
+
// src/shared/constants.ts
|
|
18765
|
+
var APP_VERSION = "0.6.0";
|
|
18766
|
+
var PROTOCOL_VERSION = 5;
|
|
18767
|
+
var VIEWER_ID_HEADER = "x-rvw-viewer-id";
|
|
18768
|
+
var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
|
|
18769
|
+
var VIEWER_OPEN_LEASE_QUERY = "viewerLease";
|
|
18770
|
+
var DEFAULT_VIEWER_PORT = 43117;
|
|
18771
|
+
var GIT_OBJECT_ID_PATTERN = /^[0-9a-f]{40,64}$/i;
|
|
18772
|
+
var CONTENT_FINGERPRINT_PATTERN = /^[0-9a-f]{64}$/;
|
|
18773
|
+
var MAX_TEXT_DOCUMENT_BYTES = 1024 * 1024;
|
|
18774
|
+
var MAX_MARKDOWN_ASSET_BYTES = 5 * 1024 * 1024;
|
|
18775
|
+
var MAX_GITHUB_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
18776
|
+
var MAX_GITHUB_ATTACHMENT_STDERR_BYTES = 64 * 1024;
|
|
18777
|
+
var GITHUB_ATTACHMENT_TIMEOUT_MS = 3e4;
|
|
18778
|
+
var MAX_COMMENT_BODY_BYTES = 64 * 1024;
|
|
18779
|
+
var MAX_AUTHOR_LABEL_CHARACTERS = 100;
|
|
18780
|
+
var MAX_IDEMPOTENCY_KEY_CHARACTERS = 200;
|
|
18781
|
+
var DEFAULT_PULL_REQUEST_LIST_LIMIT = 50;
|
|
18782
|
+
var MAX_PULL_REQUEST_LIST_LIMIT = 100;
|
|
18783
|
+
var DEFAULT_COMMENT_LIST_LIMIT = 50;
|
|
18784
|
+
var MAX_COMMENT_LIST_LIMIT = 100;
|
|
18785
|
+
var DEFAULT_COMMENT_WATCH_LIMIT = 100;
|
|
18786
|
+
var MAX_COMMENT_WATCH_LIMIT = 100;
|
|
18787
|
+
var DEFAULT_COMMENT_WATCH_INTERVAL_SECONDS = 10;
|
|
18788
|
+
var MAX_COMMENT_WATCH_INTERVAL_SECONDS = 300;
|
|
18789
|
+
var MAX_COMMENT_LIST_BODY_PREVIEW_BYTES = 512;
|
|
18790
|
+
var MAX_CODE_REFERENCES = 200;
|
|
18791
|
+
var MAX_CODE_REFERENCE_LABEL_CHARACTERS = 200;
|
|
18792
|
+
var MAX_CODE_REFERENCE_PATH_CHARACTERS = 4096;
|
|
18793
|
+
var MAX_CODE_REFERENCE_DESCRIPTION_CHARACTERS = 1e3;
|
|
18794
|
+
var MAX_WALKTHROUGH_BODY_BYTES = 256 * 1024;
|
|
18795
|
+
var MAX_WALKTHROUGH_TITLE_CHARACTERS = 200;
|
|
18796
|
+
var MAX_STRUCTURE_PAYLOAD_BYTES = 2 * 1024 * 1024;
|
|
18797
|
+
var MAX_STRUCTURE_TITLE_CHARACTERS = 200;
|
|
18798
|
+
var MAX_STRUCTURE_SCOPE_CHARACTERS = 4e3;
|
|
18799
|
+
var MAX_STRUCTURE_NODES = 50;
|
|
18800
|
+
var MAX_STRUCTURE_EDGES = 200;
|
|
18801
|
+
var MAX_STRUCTURE_EDGE_ANCHORS = 20;
|
|
18802
|
+
var MAX_STRUCTURE_SOURCE_ANCHORS = 400;
|
|
18803
|
+
var MAX_STRUCTURE_ID_CHARACTERS = 64;
|
|
18804
|
+
var STRUCTURE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
18805
|
+
var MAX_STRUCTURE_LABEL_CHARACTERS = 200;
|
|
18806
|
+
var MAX_STRUCTURE_DESCRIPTION_CHARACTERS = 2e3;
|
|
18807
|
+
var MAX_STRUCTURE_KIND_CHARACTERS = 100;
|
|
18808
|
+
var MAX_STRUCTURE_PRESENTATION_THESIS_CHARACTERS = 1e3;
|
|
18809
|
+
var MAX_STRUCTURE_PRIMARY_BACKBONE_NODES = 12;
|
|
18810
|
+
var MAX_STRUCTURE_PRIMARY_BACKBONE_EDGES = 16;
|
|
18811
|
+
var MAX_STRUCTURE_PRESENTATION_REGIONS = 12;
|
|
18812
|
+
var MAX_STRUCTURE_PRESENTATION_REGION_LABEL_CHARACTERS = 100;
|
|
18813
|
+
var MAX_STRUCTURE_PRESENTATION_REGION_SUMMARY_CHARACTERS = 500;
|
|
18814
|
+
var MAX_SEARCH_QUERY_BYTES = 1024;
|
|
18815
|
+
var MAX_SEARCH_RESULTS = 500;
|
|
18816
|
+
var MAX_SEARCH_STDOUT_BYTES = 8 * 1024 * 1024;
|
|
18817
|
+
var DEFAULT_PROCESS_TIMEOUT_MS = 3e4;
|
|
18818
|
+
var DEFAULT_PROCESS_STDOUT_BYTES = 16 * 1024 * 1024;
|
|
18819
|
+
var DEFAULT_PROCESS_STDERR_BYTES = 2 * 1024 * 1024;
|
|
18820
|
+
|
|
18718
18821
|
// src/shared/preferences.ts
|
|
18719
18822
|
var themePreferences = ["light", "dark", "system"];
|
|
18720
18823
|
function isThemePreference(value) {
|
|
@@ -18791,17 +18894,122 @@ function isStructureNode(value) {
|
|
|
18791
18894
|
function isStructureEdge(value) {
|
|
18792
18895
|
return isRecord(value) && typeof value.id === "string" && typeof value.from === "string" && typeof value.to === "string" && typeof value.label === "string" && typeof value.directed === "boolean" && Array.isArray(value.anchors) && value.anchors.every(isSourceAnchor);
|
|
18793
18896
|
}
|
|
18897
|
+
function hasExactKeys(value, keys2) {
|
|
18898
|
+
const actualKeys = Object.keys(value);
|
|
18899
|
+
return actualKeys.length === keys2.length && actualKeys.every((key2) => keys2.includes(key2));
|
|
18900
|
+
}
|
|
18901
|
+
function isCanonicalPresentationText(value, maximum) {
|
|
18902
|
+
return typeof value === "string" && value === value.trim() && value.length >= 1 && value.length <= maximum;
|
|
18903
|
+
}
|
|
18904
|
+
function isStructurePresentation(value, nodes, edges) {
|
|
18905
|
+
if (!isRecord(value) || !hasExactKeys(value, ["thesis", "startNodeId", "primaryBackbone", "regions"]) || !isCanonicalPresentationText(value.thesis, MAX_STRUCTURE_PRESENTATION_THESIS_CHARACTERS) || typeof value.startNodeId !== "string" || !Array.isArray(value.regions) || value.regions.length > MAX_STRUCTURE_PRESENTATION_REGIONS) {
|
|
18906
|
+
return false;
|
|
18907
|
+
}
|
|
18908
|
+
const nodeIds = new Set(nodes.map((node2) => node2.id));
|
|
18909
|
+
if (!STRUCTURE_ID_PATTERN.test(value.startNodeId) || !nodeIds.has(value.startNodeId)) {
|
|
18910
|
+
return false;
|
|
18911
|
+
}
|
|
18912
|
+
if (value.primaryBackbone !== null) {
|
|
18913
|
+
if (!isRecord(value.primaryBackbone) || !hasExactKeys(value.primaryBackbone, ["edgeIds"]) || !Array.isArray(value.primaryBackbone.edgeIds) || value.primaryBackbone.edgeIds.length < 1 || value.primaryBackbone.edgeIds.length > MAX_STRUCTURE_PRIMARY_BACKBONE_EDGES) {
|
|
18914
|
+
return false;
|
|
18915
|
+
}
|
|
18916
|
+
const edgeById = new Map(edges.map((edge) => [edge.id, edge]));
|
|
18917
|
+
const selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
18918
|
+
const selectedEdges = [];
|
|
18919
|
+
for (const edgeId of value.primaryBackbone.edgeIds) {
|
|
18920
|
+
if (typeof edgeId !== "string" || !STRUCTURE_ID_PATTERN.test(edgeId) || selectedEdgeIds.has(edgeId)) {
|
|
18921
|
+
return false;
|
|
18922
|
+
}
|
|
18923
|
+
selectedEdgeIds.add(edgeId);
|
|
18924
|
+
const edge = edgeById.get(edgeId);
|
|
18925
|
+
if (edge === void 0) return false;
|
|
18926
|
+
selectedEdges.push(edge);
|
|
18927
|
+
}
|
|
18928
|
+
const primaryBackboneNodeIds = structureBackboneNodeIds(selectedEdges);
|
|
18929
|
+
if (primaryBackboneNodeIds.size < 2 || primaryBackboneNodeIds.size > MAX_STRUCTURE_PRIMARY_BACKBONE_NODES || !primaryBackboneNodeIds.has(value.startNodeId) || !isStructureBackboneWeaklyConnected(selectedEdges, value.startNodeId)) {
|
|
18930
|
+
return false;
|
|
18931
|
+
}
|
|
18932
|
+
}
|
|
18933
|
+
const regionIds = /* @__PURE__ */ new Set();
|
|
18934
|
+
const regionByNodeId = /* @__PURE__ */ new Map();
|
|
18935
|
+
for (const region of value.regions) {
|
|
18936
|
+
if (!isRecord(region) || !hasExactKeys(region, ["id", "label", "summary", "nodeIds"]) || typeof region.id !== "string" || !STRUCTURE_ID_PATTERN.test(region.id) || regionIds.has(region.id) || !isCanonicalPresentationText(
|
|
18937
|
+
region.label,
|
|
18938
|
+
MAX_STRUCTURE_PRESENTATION_REGION_LABEL_CHARACTERS
|
|
18939
|
+
) || !isCanonicalPresentationText(
|
|
18940
|
+
region.summary,
|
|
18941
|
+
MAX_STRUCTURE_PRESENTATION_REGION_SUMMARY_CHARACTERS
|
|
18942
|
+
) || !Array.isArray(region.nodeIds) || region.nodeIds.length < 1 || region.nodeIds.length > MAX_STRUCTURE_NODES) {
|
|
18943
|
+
return false;
|
|
18944
|
+
}
|
|
18945
|
+
regionIds.add(region.id);
|
|
18946
|
+
const currentRegionNodeIds = /* @__PURE__ */ new Set();
|
|
18947
|
+
for (const nodeId of region.nodeIds) {
|
|
18948
|
+
if (typeof nodeId !== "string" || !STRUCTURE_ID_PATTERN.test(nodeId) || !nodeIds.has(nodeId) || currentRegionNodeIds.has(nodeId) || regionByNodeId.has(nodeId)) {
|
|
18949
|
+
return false;
|
|
18950
|
+
}
|
|
18951
|
+
currentRegionNodeIds.add(nodeId);
|
|
18952
|
+
regionByNodeId.set(nodeId, region.id);
|
|
18953
|
+
}
|
|
18954
|
+
}
|
|
18955
|
+
return true;
|
|
18956
|
+
}
|
|
18794
18957
|
function structureGraphValue(row) {
|
|
18795
18958
|
try {
|
|
18796
|
-
const
|
|
18797
|
-
|
|
18798
|
-
|
|
18959
|
+
const serializedGraph = stringValue(row, "graph_json");
|
|
18960
|
+
if (Buffer.byteLength(serializedGraph, "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
18961
|
+
throw new Error("invalid Structure graph size");
|
|
18962
|
+
}
|
|
18963
|
+
const value = JSON.parse(serializedGraph);
|
|
18964
|
+
if (!isRecord(value)) throw new Error("invalid Structure graph");
|
|
18965
|
+
const originNodeId = typeof value.originNodeId === "string" ? value.originNodeId : null;
|
|
18966
|
+
const presentation = value.presentation === void 0 ? null : value.presentation;
|
|
18967
|
+
if (originNodeId === null || !Array.isArray(value.nodes) || !value.nodes.every(isStructureNode) || !Array.isArray(value.edges) || !value.edges.every(isStructureEdge)) {
|
|
18799
18968
|
throw new Error("invalid Structure graph");
|
|
18800
18969
|
}
|
|
18970
|
+
const nodes = value.nodes;
|
|
18971
|
+
const edges = value.edges;
|
|
18972
|
+
if (nodes.length < 1 || nodes.length > MAX_STRUCTURE_NODES) {
|
|
18973
|
+
throw new Error("invalid Structure Node count");
|
|
18974
|
+
}
|
|
18975
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
18976
|
+
for (const node2 of nodes) {
|
|
18977
|
+
if (!STRUCTURE_ID_PATTERN.test(node2.id) || nodeIds.has(node2.id)) {
|
|
18978
|
+
throw new Error("invalid Structure Node identity");
|
|
18979
|
+
}
|
|
18980
|
+
nodeIds.add(node2.id);
|
|
18981
|
+
}
|
|
18982
|
+
const originNode = nodes.find((node2) => node2.id === originNodeId);
|
|
18983
|
+
if (originNode === void 0 || originNode.anchor === null) {
|
|
18984
|
+
throw new Error("invalid Structure origin");
|
|
18985
|
+
}
|
|
18986
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
18987
|
+
for (const edge of edges) {
|
|
18988
|
+
if (!STRUCTURE_ID_PATTERN.test(edge.id) || edgeIds.has(edge.id)) {
|
|
18989
|
+
throw new Error("invalid Structure Edge identity");
|
|
18990
|
+
}
|
|
18991
|
+
edgeIds.add(edge.id);
|
|
18992
|
+
if (!nodeIds.has(edge.from) || !nodeIds.has(edge.to)) {
|
|
18993
|
+
throw new Error("invalid Structure Edge endpoint");
|
|
18994
|
+
}
|
|
18995
|
+
}
|
|
18996
|
+
if (presentation !== null && !isStructurePresentation(presentation, nodes, edges)) {
|
|
18997
|
+
throw new Error("invalid Structure presentation");
|
|
18998
|
+
}
|
|
18999
|
+
const normalizedPresentation = presentation === null ? null : {
|
|
19000
|
+
...presentation,
|
|
19001
|
+
primaryBackbone: presentation.primaryBackbone === null ? null : {
|
|
19002
|
+
edgeIds: canonicalStructureBackboneEdgeIds(
|
|
19003
|
+
presentation.primaryBackbone.edgeIds
|
|
19004
|
+
)
|
|
19005
|
+
},
|
|
19006
|
+
regions: canonicalStructurePresentationRegions(presentation.regions)
|
|
19007
|
+
};
|
|
18801
19008
|
return {
|
|
18802
19009
|
originNodeId,
|
|
18803
|
-
nodes:
|
|
18804
|
-
edges
|
|
19010
|
+
nodes: nodes.map((node2) => ({ ...node2, notation: node2.notation ?? "plain" })),
|
|
19011
|
+
edges,
|
|
19012
|
+
presentation: normalizedPresentation
|
|
18805
19013
|
};
|
|
18806
19014
|
} catch (error51) {
|
|
18807
19015
|
throw new RvwError("DATABASE_ERROR", "Structure graph_json\u304C\u4E0D\u6B63\u3067\u3059\u3002", { cause: error51 });
|
|
@@ -19165,6 +19373,163 @@ var RvwDatabase = class {
|
|
|
19165
19373
|
if (!row) throw new RvwError("DATABASE_ERROR", "comment watch\u306Edatabase ID\u304C\u3042\u308A\u307E\u305B\u3093\u3002");
|
|
19166
19374
|
return stringValue(row, "value");
|
|
19167
19375
|
}
|
|
19376
|
+
activateCommentWatchTask(taskId) {
|
|
19377
|
+
return this.immediateTransaction(() => {
|
|
19378
|
+
const existing = this.database.prepare(
|
|
19379
|
+
`SELECT task_id, generation, superseded_at
|
|
19380
|
+
FROM comment_watch_tasks WHERE task_id = ?`
|
|
19381
|
+
).get(taskId);
|
|
19382
|
+
if (existing) {
|
|
19383
|
+
const generation2 = numberValue(existing, "generation");
|
|
19384
|
+
if (nullableString(existing, "superseded_at") !== null) {
|
|
19385
|
+
const active = this.database.prepare(
|
|
19386
|
+
`SELECT task_id, generation FROM comment_watch_tasks
|
|
19387
|
+
WHERE superseded_at IS NULL`
|
|
19388
|
+
).get();
|
|
19389
|
+
throw new RvwError(
|
|
19390
|
+
"WATCH_TASK_SUPERSEDED",
|
|
19391
|
+
"\u3053\u306Ecomment watch task\u306F\u65E2\u306B\u5225\u306Etask\u3078\u5F15\u304D\u7D99\u304C\u308C\u3066\u3044\u307E\u3059\u3002",
|
|
19392
|
+
{
|
|
19393
|
+
details: {
|
|
19394
|
+
taskId,
|
|
19395
|
+
generation: generation2,
|
|
19396
|
+
activeTaskId: active ? stringValue(active, "task_id") : null,
|
|
19397
|
+
activeGeneration: active ? numberValue(active, "generation") : null
|
|
19398
|
+
},
|
|
19399
|
+
suggestions: ["\u73FE\u5728active\u306Awatch task\u3092resume\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
|
|
19400
|
+
}
|
|
19401
|
+
);
|
|
19402
|
+
}
|
|
19403
|
+
return {
|
|
19404
|
+
databaseId: this.getCommentWatchDatabaseId(),
|
|
19405
|
+
taskId,
|
|
19406
|
+
generation: generation2,
|
|
19407
|
+
status: "existing"
|
|
19408
|
+
};
|
|
19409
|
+
}
|
|
19410
|
+
const latest = this.database.prepare("SELECT COALESCE(MAX(generation), 0) AS generation FROM comment_watch_tasks").get();
|
|
19411
|
+
const generation = numberValue(latest, "generation") + 1;
|
|
19412
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
19413
|
+
this.database.prepare(
|
|
19414
|
+
`UPDATE comment_watch_tasks SET superseded_at = ?
|
|
19415
|
+
WHERE superseded_at IS NULL`
|
|
19416
|
+
).run(now);
|
|
19417
|
+
this.database.prepare(
|
|
19418
|
+
`INSERT INTO comment_watch_tasks(task_id, generation, activated_at, superseded_at)
|
|
19419
|
+
VALUES (?, ?, ?, NULL)`
|
|
19420
|
+
).run(taskId, generation, now);
|
|
19421
|
+
return {
|
|
19422
|
+
databaseId: this.getCommentWatchDatabaseId(),
|
|
19423
|
+
taskId,
|
|
19424
|
+
generation,
|
|
19425
|
+
status: "activated"
|
|
19426
|
+
};
|
|
19427
|
+
});
|
|
19428
|
+
}
|
|
19429
|
+
assertCommentWatchTaskAuthority(taskId, generation) {
|
|
19430
|
+
const active = this.database.prepare(
|
|
19431
|
+
`SELECT task_id, generation FROM comment_watch_tasks
|
|
19432
|
+
WHERE superseded_at IS NULL`
|
|
19433
|
+
).get();
|
|
19434
|
+
if (!active || stringValue(active, "task_id") !== taskId || numberValue(active, "generation") !== generation) {
|
|
19435
|
+
throw new RvwError(
|
|
19436
|
+
"WATCH_TASK_SUPERSEDED",
|
|
19437
|
+
"\u3053\u306Ecomment watch task\u306Factive generation\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
19438
|
+
{
|
|
19439
|
+
details: {
|
|
19440
|
+
taskId,
|
|
19441
|
+
generation,
|
|
19442
|
+
activeTaskId: active ? stringValue(active, "task_id") : null,
|
|
19443
|
+
activeGeneration: active ? numberValue(active, "generation") : null
|
|
19444
|
+
},
|
|
19445
|
+
suggestions: ["\u73FE\u5728active\u306Awatch task\u3092resume\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
|
|
19446
|
+
}
|
|
19447
|
+
);
|
|
19448
|
+
}
|
|
19449
|
+
return { databaseId: this.getCommentWatchDatabaseId(), taskId, generation };
|
|
19450
|
+
}
|
|
19451
|
+
reserveCommentWatchWriter(taskId, generation, leaseId, writeKey) {
|
|
19452
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(writeKey)) {
|
|
19453
|
+
throw new RvwError("INVALID_INPUT", "writer reservation key\u306Fowner/repository\u5F62\u5F0F\u3067\u3059\u3002");
|
|
19454
|
+
}
|
|
19455
|
+
const canonicalWriteKey = writeKey.toLowerCase();
|
|
19456
|
+
return this.immediateTransaction(() => {
|
|
19457
|
+
const authority = this.assertCommentWatchTaskAuthority(taskId, generation);
|
|
19458
|
+
const existingLease = this.database.prepare(
|
|
19459
|
+
`SELECT lease_id, write_key, task_id, generation
|
|
19460
|
+
FROM comment_watch_write_reservations WHERE lease_id = ?`
|
|
19461
|
+
).get(leaseId);
|
|
19462
|
+
if (existingLease) {
|
|
19463
|
+
if (stringValue(existingLease, "write_key") !== canonicalWriteKey || stringValue(existingLease, "task_id") !== taskId || numberValue(existingLease, "generation") !== generation) {
|
|
19464
|
+
throw new RvwError(
|
|
19465
|
+
"WATCH_WRITE_RESERVED",
|
|
19466
|
+
"\u3053\u306Elease\u306F\u5225\u306Ecomment watch writer reservation\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002",
|
|
19467
|
+
{ details: { taskId, generation, leaseId, writeKey: canonicalWriteKey } }
|
|
19468
|
+
);
|
|
19469
|
+
}
|
|
19470
|
+
return { ...authority, leaseId, writeKey: canonicalWriteKey, status: "existing" };
|
|
19471
|
+
}
|
|
19472
|
+
const existingWriter = this.database.prepare(
|
|
19473
|
+
`SELECT lease_id, task_id, generation
|
|
19474
|
+
FROM comment_watch_write_reservations WHERE write_key = ?`
|
|
19475
|
+
).get(canonicalWriteKey);
|
|
19476
|
+
if (existingWriter) {
|
|
19477
|
+
throw new RvwError(
|
|
19478
|
+
"WATCH_WRITE_RESERVED",
|
|
19479
|
+
`repository ${canonicalWriteKey} \u306F\u5225\u306Ewatch worker\u304C\u4F7F\u7528\u4E2D\u3067\u3059\u3002`,
|
|
19480
|
+
{
|
|
19481
|
+
details: {
|
|
19482
|
+
writeKey: canonicalWriteKey,
|
|
19483
|
+
ownerLeaseId: stringValue(existingWriter, "lease_id"),
|
|
19484
|
+
ownerTaskId: stringValue(existingWriter, "task_id"),
|
|
19485
|
+
ownerGeneration: numberValue(existingWriter, "generation")
|
|
19486
|
+
}
|
|
19487
|
+
}
|
|
19488
|
+
);
|
|
19489
|
+
}
|
|
19490
|
+
this.database.prepare(
|
|
19491
|
+
`INSERT INTO comment_watch_write_reservations(
|
|
19492
|
+
lease_id, write_key, task_id, generation, acquired_at
|
|
19493
|
+
) VALUES (?, ?, ?, ?, ?)`
|
|
19494
|
+
).run(leaseId, canonicalWriteKey, taskId, generation, (/* @__PURE__ */ new Date()).toISOString());
|
|
19495
|
+
return { ...authority, leaseId, writeKey: canonicalWriteKey, status: "reserved" };
|
|
19496
|
+
});
|
|
19497
|
+
}
|
|
19498
|
+
releaseCommentWatchWriter(taskId, generation, leaseId) {
|
|
19499
|
+
return this.immediateTransaction(() => {
|
|
19500
|
+
const existing = this.database.prepare(
|
|
19501
|
+
`SELECT lease_id, write_key, task_id, generation
|
|
19502
|
+
FROM comment_watch_write_reservations WHERE lease_id = ?`
|
|
19503
|
+
).get(leaseId);
|
|
19504
|
+
if (!existing) {
|
|
19505
|
+
return {
|
|
19506
|
+
databaseId: this.getCommentWatchDatabaseId(),
|
|
19507
|
+
taskId,
|
|
19508
|
+
generation,
|
|
19509
|
+
leaseId,
|
|
19510
|
+
writeKey: null,
|
|
19511
|
+
status: "absent"
|
|
19512
|
+
};
|
|
19513
|
+
}
|
|
19514
|
+
if (stringValue(existing, "task_id") !== taskId || numberValue(existing, "generation") !== generation) {
|
|
19515
|
+
throw new RvwError(
|
|
19516
|
+
"WATCH_WRITE_RESERVED",
|
|
19517
|
+
"\u5225\u306Ecomment watch task\u304C\u6240\u6709\u3059\u308Bwriter reservation\u306F\u89E3\u653E\u3067\u304D\u307E\u305B\u3093\u3002",
|
|
19518
|
+
{ details: { taskId, generation, leaseId } }
|
|
19519
|
+
);
|
|
19520
|
+
}
|
|
19521
|
+
const writeKey = stringValue(existing, "write_key");
|
|
19522
|
+
this.database.prepare("DELETE FROM comment_watch_write_reservations WHERE lease_id = ?").run(leaseId);
|
|
19523
|
+
return {
|
|
19524
|
+
databaseId: this.getCommentWatchDatabaseId(),
|
|
19525
|
+
taskId,
|
|
19526
|
+
generation,
|
|
19527
|
+
leaseId,
|
|
19528
|
+
writeKey,
|
|
19529
|
+
status: "released"
|
|
19530
|
+
};
|
|
19531
|
+
});
|
|
19532
|
+
}
|
|
19168
19533
|
getLatestCommentPostEventSequence() {
|
|
19169
19534
|
const row = this.database.prepare("SELECT COALESCE(MAX(sequence), 0) AS sequence FROM comment_post_events").get();
|
|
19170
19535
|
return numberValue(row, "sequence");
|
|
@@ -19551,13 +19916,15 @@ var RvwDatabase = class {
|
|
|
19551
19916
|
const graphJson = JSON.stringify({
|
|
19552
19917
|
originNodeId: input.originNodeId,
|
|
19553
19918
|
nodes: input.nodes,
|
|
19554
|
-
edges: input.edges
|
|
19919
|
+
edges: input.edges,
|
|
19920
|
+
presentation: input.presentation
|
|
19555
19921
|
});
|
|
19556
19922
|
this.immediateTransaction(() => {
|
|
19557
19923
|
const keyHash = hashIdempotencyKey(input.idempotencyKey);
|
|
19558
19924
|
const existingRow = this.database.prepare("SELECT * FROM structure_publish_idempotency WHERE key_hash = ?").get(keyHash);
|
|
19559
19925
|
if (existingRow) {
|
|
19560
|
-
|
|
19926
|
+
const existingRequestHash = stringValue(existingRow, "request_hash");
|
|
19927
|
+
if (existingRequestHash !== input.idempotencyRequestHash && (input.presentation !== null || existingRequestHash !== input.legacyNullPresentationIdempotencyRequestHash)) {
|
|
19561
19928
|
throw new RvwError(
|
|
19562
19929
|
"IDEMPOTENCY_CONFLICT",
|
|
19563
19930
|
"\u540C\u3058idempotencyKey\u304C\u5225\u306EStructure publish\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002"
|
|
@@ -19590,6 +19957,9 @@ var RvwDatabase = class {
|
|
|
19590
19957
|
now,
|
|
19591
19958
|
now
|
|
19592
19959
|
);
|
|
19960
|
+
if (!this.getStructure(id)) {
|
|
19961
|
+
throw new RvwError("DATABASE_ERROR", "\u4FDD\u5B58\u3057\u305FStructure\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
19962
|
+
}
|
|
19593
19963
|
this.database.prepare(
|
|
19594
19964
|
`INSERT INTO structure_publish_idempotency(
|
|
19595
19965
|
key_hash, request_hash, structure_id, created_at
|
|
@@ -19614,7 +19984,8 @@ var RvwDatabase = class {
|
|
|
19614
19984
|
const graphJson = JSON.stringify({
|
|
19615
19985
|
originNodeId: input.originNodeId,
|
|
19616
19986
|
nodes: input.nodes,
|
|
19617
|
-
edges: input.edges
|
|
19987
|
+
edges: input.edges,
|
|
19988
|
+
presentation: input.presentation
|
|
19618
19989
|
});
|
|
19619
19990
|
this.immediateTransaction(() => {
|
|
19620
19991
|
const current = this.getStructure(id);
|
|
@@ -19637,6 +20008,9 @@ var RvwDatabase = class {
|
|
|
19637
20008
|
const retiredEdgeIds = new Set(
|
|
19638
20009
|
this.database.prepare("SELECT edge_id FROM structure_retired_edge_ids WHERE structure_id = ?").all(id).map((row) => stringValue(row, "edge_id"))
|
|
19639
20010
|
);
|
|
20011
|
+
const retiredRegionIds = new Set(
|
|
20012
|
+
this.database.prepare("SELECT region_id FROM structure_retired_region_ids WHERE structure_id = ?").all(id).map((row) => stringValue(row, "region_id"))
|
|
20013
|
+
);
|
|
19640
20014
|
const reusedNode = input.nodes.find((node2) => retiredNodeIds.has(node2.id));
|
|
19641
20015
|
if (reusedNode) {
|
|
19642
20016
|
throw new RvwError(
|
|
@@ -19651,10 +20025,21 @@ var RvwDatabase = class {
|
|
|
19651
20025
|
`\u524A\u9664\u6E08\u307F\u306EStructure Edge ID\u306F\u518D\u5229\u7528\u3067\u304D\u307E\u305B\u3093: ${reusedEdge.id}`
|
|
19652
20026
|
);
|
|
19653
20027
|
}
|
|
20028
|
+
const reusedRegion = input.presentation?.regions.find(
|
|
20029
|
+
(region) => retiredRegionIds.has(region.id)
|
|
20030
|
+
);
|
|
20031
|
+
if (reusedRegion) {
|
|
20032
|
+
throw new RvwError(
|
|
20033
|
+
"INVALID_INPUT",
|
|
20034
|
+
`\u524A\u9664\u6E08\u307F\u306EStructure Region ID\u306F\u518D\u5229\u7528\u3067\u304D\u307E\u305B\u3093: ${reusedRegion.id}`
|
|
20035
|
+
);
|
|
20036
|
+
}
|
|
19654
20037
|
const nextNodeIds = new Set(input.nodes.map((node2) => node2.id));
|
|
19655
20038
|
const nextEdgeIds = new Set(input.edges.map((edge) => edge.id));
|
|
20039
|
+
const nextRegionIds = new Set(input.presentation?.regions.map((region) => region.id) ?? []);
|
|
19656
20040
|
const retiredAtThisUpdate = current.nodes.map((node2) => node2.id).filter((nodeId) => !nextNodeIds.has(nodeId));
|
|
19657
20041
|
const retiredEdgesAtThisUpdate = current.edges.map((edge) => edge.id).filter((edgeId) => !nextEdgeIds.has(edgeId));
|
|
20042
|
+
const retiredRegionsAtThisUpdate = (current.presentation?.regions ?? []).map((region) => region.id).filter((regionId) => !nextRegionIds.has(regionId));
|
|
19658
20043
|
const result = this.database.prepare(
|
|
19659
20044
|
`UPDATE structures
|
|
19660
20045
|
SET source_oid = ?, title = ?, scope = ?, graph_json = ?, updated_at = ?
|
|
@@ -19670,6 +20055,9 @@ var RvwDatabase = class {
|
|
|
19670
20055
|
}
|
|
19671
20056
|
);
|
|
19672
20057
|
}
|
|
20058
|
+
if (!this.getStructure(id)) {
|
|
20059
|
+
throw new RvwError("DATABASE_ERROR", "\u66F4\u65B0\u3057\u305FStructure\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
20060
|
+
}
|
|
19673
20061
|
const retireNode = this.database.prepare(
|
|
19674
20062
|
"INSERT OR IGNORE INTO structure_retired_node_ids(structure_id, node_id, retired_at) VALUES (?, ?, ?)"
|
|
19675
20063
|
);
|
|
@@ -19678,6 +20066,10 @@ var RvwDatabase = class {
|
|
|
19678
20066
|
"INSERT OR IGNORE INTO structure_retired_edge_ids(structure_id, edge_id, retired_at) VALUES (?, ?, ?)"
|
|
19679
20067
|
);
|
|
19680
20068
|
for (const edgeId of retiredEdgesAtThisUpdate) retireEdge.run(id, edgeId, now);
|
|
20069
|
+
const retireRegion = this.database.prepare(
|
|
20070
|
+
"INSERT OR IGNORE INTO structure_retired_region_ids(structure_id, region_id, retired_at) VALUES (?, ?, ?)"
|
|
20071
|
+
);
|
|
20072
|
+
for (const regionId of retiredRegionsAtThisUpdate) retireRegion.run(id, regionId, now);
|
|
19681
20073
|
this.incrementDomainRevisions(["structures"]);
|
|
19682
20074
|
});
|
|
19683
20075
|
const structure = this.getStructure(id);
|
|
@@ -20095,10 +20487,20 @@ var RvwDatabase = class {
|
|
|
20095
20487
|
insertReply(commentId, input, incrementSequence = true) {
|
|
20096
20488
|
let result;
|
|
20097
20489
|
const write = () => {
|
|
20490
|
+
if (input.watchTask) {
|
|
20491
|
+
this.assertCommentWatchTaskAuthority(input.watchTask.taskId, input.watchTask.generation);
|
|
20492
|
+
}
|
|
20098
20493
|
const comment3 = this.getComment(commentId);
|
|
20099
20494
|
if (!comment3) {
|
|
20100
20495
|
throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
20101
20496
|
}
|
|
20497
|
+
if (input.watchTask && comment3.resolvedAt !== null) {
|
|
20498
|
+
throw new RvwError(
|
|
20499
|
+
"COMMENT_NOT_ACTIONABLE",
|
|
20500
|
+
"\u89E3\u6C7A\u6E08\u307Fcomment\u306B\u306Fwatch acknowledgement\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002",
|
|
20501
|
+
{ details: { commentRef: comment3.ref } }
|
|
20502
|
+
);
|
|
20503
|
+
}
|
|
20102
20504
|
const pullRequest = this.getPullRequest(comment3.pullRequestId);
|
|
20103
20505
|
if (!pullRequest) throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
20104
20506
|
const relatedCommitOid = input.relatedCommitOid ?? null;
|
|
@@ -20181,9 +20583,23 @@ var RvwDatabase = class {
|
|
|
20181
20583
|
if (!result) throw new RvwError("DATABASE_ERROR", "\u8FD4\u4FE1\u7D50\u679C\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
20182
20584
|
return result;
|
|
20183
20585
|
}
|
|
20184
|
-
updateCommentPost(commentId, postId, body3, relatedCommitOid, references, lastModifiedBy) {
|
|
20586
|
+
updateCommentPost(commentId, postId, body3, relatedCommitOid, references, lastModifiedBy, watchTask) {
|
|
20185
20587
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20186
20588
|
this.immediateTransaction(() => {
|
|
20589
|
+
if (watchTask) {
|
|
20590
|
+
this.assertCommentWatchTaskAuthority(watchTask.taskId, watchTask.generation);
|
|
20591
|
+
const comment3 = this.getComment(commentId);
|
|
20592
|
+
if (!comment3) {
|
|
20593
|
+
throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
20594
|
+
}
|
|
20595
|
+
if (comment3.resolvedAt !== null) {
|
|
20596
|
+
throw new RvwError(
|
|
20597
|
+
"COMMENT_NOT_ACTIONABLE",
|
|
20598
|
+
"\u89E3\u6C7A\u6E08\u307Fcomment\u306Ewatch acknowledgement\u306F\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\u3002",
|
|
20599
|
+
{ details: { commentRef: comment3.ref } }
|
|
20600
|
+
);
|
|
20601
|
+
}
|
|
20602
|
+
}
|
|
20187
20603
|
const result = this.database.prepare(
|
|
20188
20604
|
`UPDATE comment_posts
|
|
20189
20605
|
SET body = ?, related_commit_oid = ?, last_modified_by = ?, updated_at = ?
|
|
@@ -20294,56 +20710,6 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
20294
20710
|
import path5 from "node:path";
|
|
20295
20711
|
import { TextDecoder as TextDecoder2 } from "node:util";
|
|
20296
20712
|
|
|
20297
|
-
// src/shared/constants.ts
|
|
20298
|
-
var APP_VERSION = "0.4.3";
|
|
20299
|
-
var PROTOCOL_VERSION = 4;
|
|
20300
|
-
var VIEWER_ID_HEADER = "x-rvw-viewer-id";
|
|
20301
|
-
var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
|
|
20302
|
-
var VIEWER_OPEN_LEASE_QUERY = "viewerLease";
|
|
20303
|
-
var GIT_OBJECT_ID_PATTERN = /^[0-9a-f]{40,64}$/i;
|
|
20304
|
-
var CONTENT_FINGERPRINT_PATTERN = /^[0-9a-f]{64}$/;
|
|
20305
|
-
var MAX_TEXT_DOCUMENT_BYTES = 1024 * 1024;
|
|
20306
|
-
var MAX_MARKDOWN_ASSET_BYTES = 5 * 1024 * 1024;
|
|
20307
|
-
var MAX_GITHUB_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
20308
|
-
var MAX_GITHUB_ATTACHMENT_STDERR_BYTES = 64 * 1024;
|
|
20309
|
-
var GITHUB_ATTACHMENT_TIMEOUT_MS = 3e4;
|
|
20310
|
-
var MAX_COMMENT_BODY_BYTES = 64 * 1024;
|
|
20311
|
-
var MAX_AUTHOR_LABEL_CHARACTERS = 100;
|
|
20312
|
-
var MAX_IDEMPOTENCY_KEY_CHARACTERS = 200;
|
|
20313
|
-
var DEFAULT_PULL_REQUEST_LIST_LIMIT = 50;
|
|
20314
|
-
var MAX_PULL_REQUEST_LIST_LIMIT = 100;
|
|
20315
|
-
var DEFAULT_COMMENT_LIST_LIMIT = 50;
|
|
20316
|
-
var MAX_COMMENT_LIST_LIMIT = 100;
|
|
20317
|
-
var DEFAULT_COMMENT_WATCH_LIMIT = 100;
|
|
20318
|
-
var MAX_COMMENT_WATCH_LIMIT = 100;
|
|
20319
|
-
var DEFAULT_COMMENT_WATCH_INTERVAL_SECONDS = 10;
|
|
20320
|
-
var MAX_COMMENT_WATCH_INTERVAL_SECONDS = 300;
|
|
20321
|
-
var MAX_COMMENT_LIST_BODY_PREVIEW_BYTES = 512;
|
|
20322
|
-
var MAX_CODE_REFERENCES = 200;
|
|
20323
|
-
var MAX_CODE_REFERENCE_LABEL_CHARACTERS = 200;
|
|
20324
|
-
var MAX_CODE_REFERENCE_PATH_CHARACTERS = 4096;
|
|
20325
|
-
var MAX_CODE_REFERENCE_DESCRIPTION_CHARACTERS = 1e3;
|
|
20326
|
-
var MAX_WALKTHROUGH_BODY_BYTES = 256 * 1024;
|
|
20327
|
-
var MAX_WALKTHROUGH_TITLE_CHARACTERS = 200;
|
|
20328
|
-
var MAX_STRUCTURE_PAYLOAD_BYTES = 2 * 1024 * 1024;
|
|
20329
|
-
var MAX_STRUCTURE_TITLE_CHARACTERS = 200;
|
|
20330
|
-
var MAX_STRUCTURE_SCOPE_CHARACTERS = 4e3;
|
|
20331
|
-
var MAX_STRUCTURE_NODES = 50;
|
|
20332
|
-
var MAX_STRUCTURE_EDGES = 200;
|
|
20333
|
-
var MAX_STRUCTURE_EDGE_ANCHORS = 20;
|
|
20334
|
-
var MAX_STRUCTURE_SOURCE_ANCHORS = 400;
|
|
20335
|
-
var MAX_STRUCTURE_ID_CHARACTERS = 64;
|
|
20336
|
-
var STRUCTURE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
20337
|
-
var MAX_STRUCTURE_LABEL_CHARACTERS = 200;
|
|
20338
|
-
var MAX_STRUCTURE_DESCRIPTION_CHARACTERS = 2e3;
|
|
20339
|
-
var MAX_STRUCTURE_KIND_CHARACTERS = 100;
|
|
20340
|
-
var MAX_SEARCH_QUERY_BYTES = 1024;
|
|
20341
|
-
var MAX_SEARCH_RESULTS = 500;
|
|
20342
|
-
var MAX_SEARCH_STDOUT_BYTES = 8 * 1024 * 1024;
|
|
20343
|
-
var DEFAULT_PROCESS_TIMEOUT_MS = 3e4;
|
|
20344
|
-
var DEFAULT_PROCESS_STDOUT_BYTES = 16 * 1024 * 1024;
|
|
20345
|
-
var DEFAULT_PROCESS_STDERR_BYTES = 2 * 1024 * 1024;
|
|
20346
|
-
|
|
20347
20713
|
// src/domain/search.ts
|
|
20348
20714
|
var wordCharacter = /[\p{L}\p{N}_]/u;
|
|
20349
20715
|
function escapeRegularExpression(value) {
|
|
@@ -42710,6 +43076,21 @@ var RvwService = class {
|
|
|
42710
43076
|
events
|
|
42711
43077
|
};
|
|
42712
43078
|
}
|
|
43079
|
+
activateCommentWatchTask(taskId) {
|
|
43080
|
+
return this.database.activateCommentWatchTask(taskId);
|
|
43081
|
+
}
|
|
43082
|
+
verifyCommentWatchTask(taskId, generation) {
|
|
43083
|
+
return {
|
|
43084
|
+
...this.database.assertCommentWatchTaskAuthority(taskId, generation),
|
|
43085
|
+
status: "active"
|
|
43086
|
+
};
|
|
43087
|
+
}
|
|
43088
|
+
reserveCommentWatchWriter(taskId, generation, leaseId, writeKey) {
|
|
43089
|
+
return this.database.reserveCommentWatchWriter(taskId, generation, leaseId, writeKey);
|
|
43090
|
+
}
|
|
43091
|
+
releaseCommentWatchWriter(taskId, generation, leaseId) {
|
|
43092
|
+
return this.database.releaseCommentWatchWriter(taskId, generation, leaseId);
|
|
43093
|
+
}
|
|
42713
43094
|
listComments(pullRequestId, resolved) {
|
|
42714
43095
|
this.getPullRequest(pullRequestId);
|
|
42715
43096
|
return this.database.listComments(pullRequestId, resolved);
|
|
@@ -42852,6 +43233,16 @@ var RvwService = class {
|
|
|
42852
43233
|
}
|
|
42853
43234
|
return normalized;
|
|
42854
43235
|
}
|
|
43236
|
+
assertStructurePresentationText(value, maximum, subject) {
|
|
43237
|
+
if (typeof value !== "string") {
|
|
43238
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u306F\u6587\u5B57\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);
|
|
43239
|
+
}
|
|
43240
|
+
const normalized = value.trim();
|
|
43241
|
+
if (normalized.length < 1 || normalized.length > maximum) {
|
|
43242
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u306Ftrim\u5F8C1\u301C${maximum}\u6587\u5B57\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);
|
|
43243
|
+
}
|
|
43244
|
+
return normalized;
|
|
43245
|
+
}
|
|
42855
43246
|
assertStructureId(value, subject) {
|
|
42856
43247
|
if (!STRUCTURE_ID_PATTERN.test(value)) {
|
|
42857
43248
|
throw new RvwError(
|
|
@@ -43026,7 +43417,172 @@ var RvwService = class {
|
|
|
43026
43417
|
`Structure\u306Esource anchor\u306F\u5408\u8A08${MAX_STRUCTURE_SOURCE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
43027
43418
|
);
|
|
43028
43419
|
}
|
|
43029
|
-
|
|
43420
|
+
if (input.presentation === void 0) {
|
|
43421
|
+
throw new RvwError(
|
|
43422
|
+
"INVALID_INPUT",
|
|
43423
|
+
"Structure presentation\u306Fnull\u307E\u305F\u306Fobject\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
43424
|
+
);
|
|
43425
|
+
}
|
|
43426
|
+
let presentation = null;
|
|
43427
|
+
if (input.presentation !== null) {
|
|
43428
|
+
if (typeof input.presentation !== "object" || Array.isArray(input.presentation) || Object.keys(input.presentation).some(
|
|
43429
|
+
(key2) => key2 !== "thesis" && key2 !== "startNodeId" && key2 !== "primaryBackbone" && key2 !== "regions"
|
|
43430
|
+
)) {
|
|
43431
|
+
throw new RvwError("INVALID_INPUT", "Structure presentation\u304C\u4E0D\u6B63\u3067\u3059\u3002");
|
|
43432
|
+
}
|
|
43433
|
+
const thesis = this.assertStructurePresentationText(
|
|
43434
|
+
input.presentation.thesis,
|
|
43435
|
+
MAX_STRUCTURE_PRESENTATION_THESIS_CHARACTERS,
|
|
43436
|
+
"Structure presentation thesis"
|
|
43437
|
+
);
|
|
43438
|
+
const startNodeId = this.assertStructureId(
|
|
43439
|
+
input.presentation.startNodeId,
|
|
43440
|
+
"Structure presentation startNodeId"
|
|
43441
|
+
);
|
|
43442
|
+
if (!nodeIds.has(startNodeId)) {
|
|
43443
|
+
throw new RvwError(
|
|
43444
|
+
"INVALID_INPUT",
|
|
43445
|
+
`Structure presentation startNodeId\u306ENode\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${startNodeId}`
|
|
43446
|
+
);
|
|
43447
|
+
}
|
|
43448
|
+
let primaryBackbone = null;
|
|
43449
|
+
if (input.presentation.primaryBackbone !== null) {
|
|
43450
|
+
const rawPrimaryBackbone = input.presentation.primaryBackbone;
|
|
43451
|
+
if (typeof rawPrimaryBackbone !== "object" || Array.isArray(rawPrimaryBackbone) || Object.keys(rawPrimaryBackbone).some((key2) => key2 !== "edgeIds") || !Array.isArray(rawPrimaryBackbone.edgeIds) || rawPrimaryBackbone.edgeIds.length < 1 || rawPrimaryBackbone.edgeIds.length > MAX_STRUCTURE_PRIMARY_BACKBONE_EDGES) {
|
|
43452
|
+
throw new RvwError(
|
|
43453
|
+
"INVALID_INPUT",
|
|
43454
|
+
`Structure presentation primaryBackbone.edgeIds\u306F1\u301C${MAX_STRUCTURE_PRIMARY_BACKBONE_EDGES}\u4EF6\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
43455
|
+
);
|
|
43456
|
+
}
|
|
43457
|
+
const edgeById = new Map(edges.map((edge) => [edge.id, edge]));
|
|
43458
|
+
const selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
43459
|
+
const selectedEdges = rawPrimaryBackbone.edgeIds.map((rawEdgeId) => {
|
|
43460
|
+
const edgeId = this.assertStructureId(
|
|
43461
|
+
rawEdgeId,
|
|
43462
|
+
"Structure presentation primaryBackbone Edge ID"
|
|
43463
|
+
);
|
|
43464
|
+
if (selectedEdgeIds.has(edgeId)) {
|
|
43465
|
+
throw new RvwError(
|
|
43466
|
+
"INVALID_INPUT",
|
|
43467
|
+
`Structure presentation primaryBackbone\u306EEdge ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${edgeId}`
|
|
43468
|
+
);
|
|
43469
|
+
}
|
|
43470
|
+
selectedEdgeIds.add(edgeId);
|
|
43471
|
+
const edge = edgeById.get(edgeId);
|
|
43472
|
+
if (edge === void 0) {
|
|
43473
|
+
throw new RvwError(
|
|
43474
|
+
"INVALID_INPUT",
|
|
43475
|
+
`Structure presentation primaryBackbone\u306EEdge\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${edgeId}`
|
|
43476
|
+
);
|
|
43477
|
+
}
|
|
43478
|
+
return edge;
|
|
43479
|
+
});
|
|
43480
|
+
const primaryBackboneNodeIds = structureBackboneNodeIds(selectedEdges);
|
|
43481
|
+
if (primaryBackboneNodeIds.size < 2 || primaryBackboneNodeIds.size > MAX_STRUCTURE_PRIMARY_BACKBONE_NODES) {
|
|
43482
|
+
throw new RvwError(
|
|
43483
|
+
"INVALID_INPUT",
|
|
43484
|
+
`Structure presentation primaryBackbone\u306F2\u301C${MAX_STRUCTURE_PRIMARY_BACKBONE_NODES}\u4EF6\u306ENode\u3092\u7D50\u3076\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
43485
|
+
);
|
|
43486
|
+
}
|
|
43487
|
+
if (!primaryBackboneNodeIds.has(startNodeId)) {
|
|
43488
|
+
throw new RvwError(
|
|
43489
|
+
"INVALID_INPUT",
|
|
43490
|
+
"Structure presentation startNodeId\u306FprimaryBackbone\u306EEdge endpoint\u306B\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
43491
|
+
);
|
|
43492
|
+
}
|
|
43493
|
+
if (!isStructureBackboneWeaklyConnected(selectedEdges, startNodeId)) {
|
|
43494
|
+
throw new RvwError(
|
|
43495
|
+
"INVALID_INPUT",
|
|
43496
|
+
"Structure presentation primaryBackbone\u306FstartNodeId\u304B\u3089\u8FBF\u308C\u308B\u4E00\u3064\u306Econnected graph\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
43497
|
+
);
|
|
43498
|
+
}
|
|
43499
|
+
primaryBackbone = {
|
|
43500
|
+
edgeIds: canonicalStructureBackboneEdgeIds([...selectedEdgeIds])
|
|
43501
|
+
};
|
|
43502
|
+
}
|
|
43503
|
+
if (!Array.isArray(input.presentation.regions) || input.presentation.regions.length > MAX_STRUCTURE_PRESENTATION_REGIONS) {
|
|
43504
|
+
throw new RvwError(
|
|
43505
|
+
"INVALID_INPUT",
|
|
43506
|
+
`Structure presentation regions\u306F${MAX_STRUCTURE_PRESENTATION_REGIONS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
43507
|
+
);
|
|
43508
|
+
}
|
|
43509
|
+
const regionIds = /* @__PURE__ */ new Set();
|
|
43510
|
+
const assignedRegionByNodeId = /* @__PURE__ */ new Map();
|
|
43511
|
+
const regions = input.presentation.regions.map((region, regionIndex) => {
|
|
43512
|
+
if (typeof region !== "object" || region === null || Array.isArray(region) || Object.keys(region).some(
|
|
43513
|
+
(key2) => key2 !== "id" && key2 !== "label" && key2 !== "summary" && key2 !== "nodeIds"
|
|
43514
|
+
)) {
|
|
43515
|
+
throw new RvwError(
|
|
43516
|
+
"INVALID_INPUT",
|
|
43517
|
+
`Structure presentation region ${regionIndex + 1}\u304C\u4E0D\u6B63\u3067\u3059\u3002`
|
|
43518
|
+
);
|
|
43519
|
+
}
|
|
43520
|
+
const id = this.assertStructureId(
|
|
43521
|
+
region.id,
|
|
43522
|
+
`Structure presentation region ${regionIndex + 1} ID`
|
|
43523
|
+
);
|
|
43524
|
+
if (regionIds.has(id)) {
|
|
43525
|
+
throw new RvwError(
|
|
43526
|
+
"INVALID_INPUT",
|
|
43527
|
+
`Structure presentation region ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${id}`
|
|
43528
|
+
);
|
|
43529
|
+
}
|
|
43530
|
+
regionIds.add(id);
|
|
43531
|
+
const label = this.assertStructurePresentationText(
|
|
43532
|
+
region.label,
|
|
43533
|
+
MAX_STRUCTURE_PRESENTATION_REGION_LABEL_CHARACTERS,
|
|
43534
|
+
`Structure presentation region ${regionIndex + 1} label`
|
|
43535
|
+
);
|
|
43536
|
+
const summary = this.assertStructurePresentationText(
|
|
43537
|
+
region.summary,
|
|
43538
|
+
MAX_STRUCTURE_PRESENTATION_REGION_SUMMARY_CHARACTERS,
|
|
43539
|
+
`Structure presentation region ${label} summary`
|
|
43540
|
+
);
|
|
43541
|
+
if (!Array.isArray(region.nodeIds) || region.nodeIds.length < 1 || region.nodeIds.length > MAX_STRUCTURE_NODES) {
|
|
43542
|
+
throw new RvwError(
|
|
43543
|
+
"INVALID_INPUT",
|
|
43544
|
+
`Structure presentation region ${label}\u306EnodeIds\u306F1\u301C${MAX_STRUCTURE_NODES}\u4EF6\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
43545
|
+
);
|
|
43546
|
+
}
|
|
43547
|
+
const currentRegionNodeIds = /* @__PURE__ */ new Set();
|
|
43548
|
+
const normalizedNodeIds = region.nodeIds.map((rawNodeId) => {
|
|
43549
|
+
const nodeId = this.assertStructureId(
|
|
43550
|
+
rawNodeId,
|
|
43551
|
+
`Structure presentation region ${label} Node ID`
|
|
43552
|
+
);
|
|
43553
|
+
if (currentRegionNodeIds.has(nodeId)) {
|
|
43554
|
+
throw new RvwError(
|
|
43555
|
+
"INVALID_INPUT",
|
|
43556
|
+
`Structure presentation region ${label}\u306ENode ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${nodeId}`
|
|
43557
|
+
);
|
|
43558
|
+
}
|
|
43559
|
+
if (!nodeIds.has(nodeId)) {
|
|
43560
|
+
throw new RvwError(
|
|
43561
|
+
"INVALID_INPUT",
|
|
43562
|
+
`Structure presentation region ${label}\u306ENode\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${nodeId}`
|
|
43563
|
+
);
|
|
43564
|
+
}
|
|
43565
|
+
const assignedRegion = assignedRegionByNodeId.get(nodeId);
|
|
43566
|
+
if (assignedRegion !== void 0) {
|
|
43567
|
+
throw new RvwError(
|
|
43568
|
+
"INVALID_INPUT",
|
|
43569
|
+
`Structure presentation Node ${nodeId}\u306F\u8907\u6570region\u306B\u6240\u5C5E\u3067\u304D\u307E\u305B\u3093: ${assignedRegion.label} (${assignedRegion.id}), ${label} (${id})`
|
|
43570
|
+
);
|
|
43571
|
+
}
|
|
43572
|
+
currentRegionNodeIds.add(nodeId);
|
|
43573
|
+
assignedRegionByNodeId.set(nodeId, { id, label });
|
|
43574
|
+
return nodeId;
|
|
43575
|
+
});
|
|
43576
|
+
return { id, label, summary, nodeIds: normalizedNodeIds };
|
|
43577
|
+
});
|
|
43578
|
+
presentation = {
|
|
43579
|
+
thesis,
|
|
43580
|
+
startNodeId,
|
|
43581
|
+
primaryBackbone,
|
|
43582
|
+
regions: canonicalStructurePresentationRegions(regions)
|
|
43583
|
+
};
|
|
43584
|
+
}
|
|
43585
|
+
const graph = { originNodeId, nodes, edges, presentation };
|
|
43030
43586
|
if (Buffer.byteLength(JSON.stringify(graph), "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
43031
43587
|
throw new RvwError(
|
|
43032
43588
|
"INVALID_INPUT",
|
|
@@ -43042,6 +43598,18 @@ var RvwService = class {
|
|
|
43042
43598
|
assertIdempotencyKey(input.idempotencyKey);
|
|
43043
43599
|
const pullRequest = this.resolveStoredPullRequest(input.pullRequest);
|
|
43044
43600
|
const content3 = await this.validateStructureContent(pullRequest, input);
|
|
43601
|
+
const legacyNullPresentationIdempotencyRequestHash = content3.presentation === null ? idempotencyRequestHash({
|
|
43602
|
+
operation: "structure.publish",
|
|
43603
|
+
pullRequestId: pullRequest.id,
|
|
43604
|
+
content: {
|
|
43605
|
+
sourceOid: content3.sourceOid,
|
|
43606
|
+
title: content3.title,
|
|
43607
|
+
scope: content3.scope,
|
|
43608
|
+
originNodeId: content3.originNodeId,
|
|
43609
|
+
nodes: content3.nodes,
|
|
43610
|
+
edges: content3.edges
|
|
43611
|
+
}
|
|
43612
|
+
}) : void 0;
|
|
43045
43613
|
return await this.writeWithRetainedCommit(
|
|
43046
43614
|
pullRequest,
|
|
43047
43615
|
content3.sourceOid,
|
|
@@ -43054,7 +43622,8 @@ var RvwService = class {
|
|
|
43054
43622
|
operation: "structure.publish",
|
|
43055
43623
|
pullRequestId: pullRequest.id,
|
|
43056
43624
|
content: content3
|
|
43057
|
-
})
|
|
43625
|
+
}),
|
|
43626
|
+
...legacyNullPresentationIdempotencyRequestHash === void 0 ? {} : { legacyNullPresentationIdempotencyRequestHash }
|
|
43058
43627
|
})
|
|
43059
43628
|
);
|
|
43060
43629
|
}
|
|
@@ -43475,7 +44044,8 @@ var RvwService = class {
|
|
|
43475
44044
|
body3,
|
|
43476
44045
|
relatedCommitOid,
|
|
43477
44046
|
references,
|
|
43478
|
-
input.lastModifiedBy ?? post.lastModifiedBy
|
|
44047
|
+
input.lastModifiedBy ?? post.lastModifiedBy,
|
|
44048
|
+
input.watchTask
|
|
43479
44049
|
);
|
|
43480
44050
|
return relatedCommitOid ? await this.writeWithRetainedCommit(pullRequest, relatedCommitOid, "comment", write) : write();
|
|
43481
44051
|
}
|
|
@@ -43805,6 +44375,696 @@ function createRuntime(options = {}) {
|
|
|
43805
44375
|
return { database, git, github, service, close: () => database.close() };
|
|
43806
44376
|
}
|
|
43807
44377
|
|
|
44378
|
+
// src/domain/structure-projection.ts
|
|
44379
|
+
var STRUCTURE_NODE_WIDTH = 228;
|
|
44380
|
+
var STRUCTURE_NODE_HEIGHT = 112;
|
|
44381
|
+
function stableCompare(left, right) {
|
|
44382
|
+
return left === right ? 0 : left < right ? -1 : 1;
|
|
44383
|
+
}
|
|
44384
|
+
function compareLinks([leftA, leftB], [rightA, rightB]) {
|
|
44385
|
+
const first = stableCompare(leftA, rightA);
|
|
44386
|
+
return first === 0 ? stableCompare(leftB, rightB) : first;
|
|
44387
|
+
}
|
|
44388
|
+
function simpleStructureTopology(structure) {
|
|
44389
|
+
const neighborSets = new Map(structure.nodes.map((node2) => [node2.id, /* @__PURE__ */ new Set()]));
|
|
44390
|
+
const pairNodes = /* @__PURE__ */ new Map();
|
|
44391
|
+
const pairDirections = /* @__PURE__ */ new Map();
|
|
44392
|
+
for (const edge of structure.edges) {
|
|
44393
|
+
if (edge.from === edge.to || !neighborSets.has(edge.from) || !neighborSets.has(edge.to)) {
|
|
44394
|
+
continue;
|
|
44395
|
+
}
|
|
44396
|
+
neighborSets.get(edge.from)?.add(edge.to);
|
|
44397
|
+
neighborSets.get(edge.to)?.add(edge.from);
|
|
44398
|
+
const ordered = [edge.from, edge.to].sort(stableCompare);
|
|
44399
|
+
const pairKey = JSON.stringify(ordered);
|
|
44400
|
+
pairNodes.set(pairKey, ordered);
|
|
44401
|
+
const directions = pairDirections.get(pairKey) ?? {
|
|
44402
|
+
hasUndirected: false,
|
|
44403
|
+
directions: /* @__PURE__ */ new Map()
|
|
44404
|
+
};
|
|
44405
|
+
if (edge.directed) {
|
|
44406
|
+
directions.directions.set(JSON.stringify([edge.from, edge.to]), [edge.from, edge.to]);
|
|
44407
|
+
} else {
|
|
44408
|
+
directions.hasUndirected = true;
|
|
44409
|
+
}
|
|
44410
|
+
pairDirections.set(pairKey, directions);
|
|
44411
|
+
}
|
|
44412
|
+
return {
|
|
44413
|
+
neighbors: new Map(
|
|
44414
|
+
[...neighborSets].map(([nodeId, neighbors]) => [nodeId, [...neighbors].sort(stableCompare)])
|
|
44415
|
+
),
|
|
44416
|
+
links: [...pairNodes.values()].sort(compareLinks),
|
|
44417
|
+
directionalLinks: [...pairDirections.values()].flatMap(
|
|
44418
|
+
({ hasUndirected, directions }) => !hasUndirected && directions.size === 1 ? [...directions.values()] : []
|
|
44419
|
+
).sort(compareLinks)
|
|
44420
|
+
};
|
|
44421
|
+
}
|
|
44422
|
+
function topologyComponents(topology) {
|
|
44423
|
+
const components = [];
|
|
44424
|
+
const assigned = /* @__PURE__ */ new Set();
|
|
44425
|
+
for (const first of [...topology.neighbors.keys()].sort(stableCompare)) {
|
|
44426
|
+
if (assigned.has(first)) continue;
|
|
44427
|
+
const component = [];
|
|
44428
|
+
const queue = [first];
|
|
44429
|
+
assigned.add(first);
|
|
44430
|
+
for (let index2 = 0; index2 < queue.length; index2 += 1) {
|
|
44431
|
+
const current = queue[index2];
|
|
44432
|
+
component.push(current);
|
|
44433
|
+
for (const neighbor of topology.neighbors.get(current) ?? []) {
|
|
44434
|
+
if (assigned.has(neighbor)) continue;
|
|
44435
|
+
assigned.add(neighbor);
|
|
44436
|
+
queue.push(neighbor);
|
|
44437
|
+
}
|
|
44438
|
+
}
|
|
44439
|
+
component.sort(stableCompare);
|
|
44440
|
+
components.push(component);
|
|
44441
|
+
}
|
|
44442
|
+
return components.sort(
|
|
44443
|
+
(left, right) => right.length - left.length || stableCompare(left[0], right[0])
|
|
44444
|
+
);
|
|
44445
|
+
}
|
|
44446
|
+
function topologyRoot(nodeIds, topology) {
|
|
44447
|
+
const neighborDegree = (nodeId) => (topology.neighbors.get(nodeId) ?? []).reduce(
|
|
44448
|
+
(total, neighbor) => total + (topology.neighbors.get(neighbor)?.length ?? 0),
|
|
44449
|
+
0
|
|
44450
|
+
);
|
|
44451
|
+
return [...nodeIds].sort(
|
|
44452
|
+
(left, right) => (topology.neighbors.get(right)?.length ?? 0) - (topology.neighbors.get(left)?.length ?? 0) || neighborDegree(right) - neighborDegree(left) || stableCompare(left, right)
|
|
44453
|
+
)[0];
|
|
44454
|
+
}
|
|
44455
|
+
function countNonForwardLinks(ranks, directionalLinks) {
|
|
44456
|
+
return directionalLinks.reduce((count, [from, to]) => {
|
|
44457
|
+
const fromRank = ranks.get(from);
|
|
44458
|
+
const toRank = ranks.get(to);
|
|
44459
|
+
return count + (fromRank !== void 0 && toRank !== void 0 && fromRank >= toRank ? 1 : 0);
|
|
44460
|
+
}, 0);
|
|
44461
|
+
}
|
|
44462
|
+
function normalizedRankIndexes(ranks) {
|
|
44463
|
+
return new Map(
|
|
44464
|
+
[...new Set(ranks.values())].sort((left, right) => left - right).map((rank, index2) => [rank, index2])
|
|
44465
|
+
);
|
|
44466
|
+
}
|
|
44467
|
+
function totalDirectionalSpan(ranks, directionalLinks) {
|
|
44468
|
+
const indexes = normalizedRankIndexes(ranks);
|
|
44469
|
+
return directionalLinks.reduce((total, [from, to]) => {
|
|
44470
|
+
const fromRank = ranks.get(from);
|
|
44471
|
+
const toRank = ranks.get(to);
|
|
44472
|
+
if (fromRank === void 0 || toRank === void 0) return total;
|
|
44473
|
+
return total + Math.abs(indexes.get(fromRank) - indexes.get(toRank));
|
|
44474
|
+
}, 0);
|
|
44475
|
+
}
|
|
44476
|
+
function compareNumberArrays(left, right) {
|
|
44477
|
+
for (let index2 = 0; index2 < Math.max(left.length, right.length); index2 += 1) {
|
|
44478
|
+
const difference = (left[index2] ?? 0) - (right[index2] ?? 0);
|
|
44479
|
+
if (difference !== 0) return difference;
|
|
44480
|
+
}
|
|
44481
|
+
return 0;
|
|
44482
|
+
}
|
|
44483
|
+
function canonicalTopologyStructuralColors(nodeIds, topology, originNodeId) {
|
|
44484
|
+
const nodeSet = new Set(nodeIds);
|
|
44485
|
+
const incomingNeighbors = new Map(nodeIds.map((nodeId) => [nodeId, /* @__PURE__ */ new Set()]));
|
|
44486
|
+
const outgoingNeighbors = new Map(nodeIds.map((nodeId) => [nodeId, /* @__PURE__ */ new Set()]));
|
|
44487
|
+
for (const [from, to] of topology.directionalLinks) {
|
|
44488
|
+
if (!nodeSet.has(from) || !nodeSet.has(to)) continue;
|
|
44489
|
+
outgoingNeighbors.get(from)?.add(to);
|
|
44490
|
+
incomingNeighbors.get(to)?.add(from);
|
|
44491
|
+
}
|
|
44492
|
+
const ambiguousNeighbors = new Map(
|
|
44493
|
+
nodeIds.map((nodeId) => {
|
|
44494
|
+
const directionalNeighbors = /* @__PURE__ */ new Set([
|
|
44495
|
+
...incomingNeighbors.get(nodeId),
|
|
44496
|
+
...outgoingNeighbors.get(nodeId)
|
|
44497
|
+
]);
|
|
44498
|
+
return [
|
|
44499
|
+
nodeId,
|
|
44500
|
+
new Set(
|
|
44501
|
+
(topology.neighbors.get(nodeId) ?? []).filter(
|
|
44502
|
+
(neighbor) => nodeSet.has(neighbor) && !directionalNeighbors.has(neighbor)
|
|
44503
|
+
)
|
|
44504
|
+
)
|
|
44505
|
+
];
|
|
44506
|
+
})
|
|
44507
|
+
);
|
|
44508
|
+
const assignColors = (descriptors) => {
|
|
44509
|
+
const colorByDescriptor = new Map(
|
|
44510
|
+
[...new Set(descriptors.values())].sort(stableCompare).map((descriptor, index2) => [descriptor, index2])
|
|
44511
|
+
);
|
|
44512
|
+
return new Map(
|
|
44513
|
+
nodeIds.map((nodeId) => [nodeId, colorByDescriptor.get(descriptors.get(nodeId))])
|
|
44514
|
+
);
|
|
44515
|
+
};
|
|
44516
|
+
let colors = assignColors(
|
|
44517
|
+
new Map(
|
|
44518
|
+
nodeIds.map((nodeId) => [
|
|
44519
|
+
nodeId,
|
|
44520
|
+
JSON.stringify([
|
|
44521
|
+
nodeId === originNodeId ? 1 : 0,
|
|
44522
|
+
incomingNeighbors.get(nodeId).size,
|
|
44523
|
+
outgoingNeighbors.get(nodeId).size,
|
|
44524
|
+
ambiguousNeighbors.get(nodeId).size
|
|
44525
|
+
])
|
|
44526
|
+
])
|
|
44527
|
+
)
|
|
44528
|
+
);
|
|
44529
|
+
for (let pass = 0; pass < nodeIds.length; pass += 1) {
|
|
44530
|
+
const next2 = assignColors(
|
|
44531
|
+
new Map(
|
|
44532
|
+
nodeIds.map((nodeId) => [
|
|
44533
|
+
nodeId,
|
|
44534
|
+
JSON.stringify([
|
|
44535
|
+
colors.get(nodeId),
|
|
44536
|
+
[...incomingNeighbors.get(nodeId)].map((neighbor) => colors.get(neighbor)).sort((left, right) => left - right),
|
|
44537
|
+
[...outgoingNeighbors.get(nodeId)].map((neighbor) => colors.get(neighbor)).sort((left, right) => left - right),
|
|
44538
|
+
[...ambiguousNeighbors.get(nodeId)].map((neighbor) => colors.get(neighbor)).sort((left, right) => left - right)
|
|
44539
|
+
])
|
|
44540
|
+
])
|
|
44541
|
+
)
|
|
44542
|
+
);
|
|
44543
|
+
if (nodeIds.every((nodeId) => next2.get(nodeId) === colors.get(nodeId))) break;
|
|
44544
|
+
colors = next2;
|
|
44545
|
+
}
|
|
44546
|
+
return colors;
|
|
44547
|
+
}
|
|
44548
|
+
function chooseRankProposal(nodeId, proposals, ranks, directionalLinks) {
|
|
44549
|
+
const scored = [...proposals].map((rank) => {
|
|
44550
|
+
const candidate = new Map(ranks).set(nodeId, rank);
|
|
44551
|
+
return {
|
|
44552
|
+
rank,
|
|
44553
|
+
nonForward: countNonForwardLinks(candidate, directionalLinks),
|
|
44554
|
+
occupiedColumns: new Set(candidate.values()).size,
|
|
44555
|
+
span: totalDirectionalSpan(candidate, directionalLinks)
|
|
44556
|
+
};
|
|
44557
|
+
});
|
|
44558
|
+
scored.sort(
|
|
44559
|
+
(left, right) => left.nonForward - right.nonForward || left.occupiedColumns - right.occupiedColumns || left.span - right.span || Math.abs(left.rank) - Math.abs(right.rank) || left.rank - right.rank
|
|
44560
|
+
);
|
|
44561
|
+
return scored[0].rank;
|
|
44562
|
+
}
|
|
44563
|
+
function applyForwardWaves(nodeSet, topology, ranks) {
|
|
44564
|
+
for (let pass = 0; pass < nodeSet.size; pass += 1) {
|
|
44565
|
+
const proposals = /* @__PURE__ */ new Map();
|
|
44566
|
+
for (const [from, to] of topology.directionalLinks) {
|
|
44567
|
+
if (!nodeSet.has(from) || !nodeSet.has(to) || ranks.has(to)) continue;
|
|
44568
|
+
const fromRank = ranks.get(from);
|
|
44569
|
+
if (fromRank === void 0) continue;
|
|
44570
|
+
const targetProposals = proposals.get(to) ?? /* @__PURE__ */ new Set();
|
|
44571
|
+
targetProposals.add(fromRank + 1);
|
|
44572
|
+
proposals.set(to, targetProposals);
|
|
44573
|
+
}
|
|
44574
|
+
if (proposals.size === 0) break;
|
|
44575
|
+
const accepted = [...proposals].map(
|
|
44576
|
+
([nodeId, nodeProposals]) => [
|
|
44577
|
+
nodeId,
|
|
44578
|
+
chooseRankProposal(nodeId, nodeProposals, ranks, topology.directionalLinks)
|
|
44579
|
+
]
|
|
44580
|
+
).sort(([left], [right]) => stableCompare(left, right));
|
|
44581
|
+
for (const [nodeId, rank] of accepted) ranks.set(nodeId, rank);
|
|
44582
|
+
}
|
|
44583
|
+
}
|
|
44584
|
+
function stronglyConnectedComponents(nodeIds, directionalLinks) {
|
|
44585
|
+
const nodeSet = new Set(nodeIds);
|
|
44586
|
+
const outgoing = new Map(nodeIds.map((nodeId) => [nodeId, /* @__PURE__ */ new Set()]));
|
|
44587
|
+
for (const [from, to] of directionalLinks) {
|
|
44588
|
+
if (nodeSet.has(from) && nodeSet.has(to)) outgoing.get(from)?.add(to);
|
|
44589
|
+
}
|
|
44590
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
44591
|
+
const lowLinks = /* @__PURE__ */ new Map();
|
|
44592
|
+
const stack = [];
|
|
44593
|
+
const onStack = /* @__PURE__ */ new Set();
|
|
44594
|
+
const components = [];
|
|
44595
|
+
let nextIndex = 0;
|
|
44596
|
+
const visit = (nodeId) => {
|
|
44597
|
+
const nodeIndex = nextIndex;
|
|
44598
|
+
nextIndex += 1;
|
|
44599
|
+
indexes.set(nodeId, nodeIndex);
|
|
44600
|
+
lowLinks.set(nodeId, nodeIndex);
|
|
44601
|
+
stack.push(nodeId);
|
|
44602
|
+
onStack.add(nodeId);
|
|
44603
|
+
for (const neighbor of [...outgoing.get(nodeId) ?? []].sort(stableCompare)) {
|
|
44604
|
+
if (!indexes.has(neighbor)) {
|
|
44605
|
+
visit(neighbor);
|
|
44606
|
+
lowLinks.set(nodeId, Math.min(lowLinks.get(nodeId), lowLinks.get(neighbor)));
|
|
44607
|
+
} else if (onStack.has(neighbor)) {
|
|
44608
|
+
lowLinks.set(nodeId, Math.min(lowLinks.get(nodeId), indexes.get(neighbor)));
|
|
44609
|
+
}
|
|
44610
|
+
}
|
|
44611
|
+
if (lowLinks.get(nodeId) !== indexes.get(nodeId)) return;
|
|
44612
|
+
const component = [];
|
|
44613
|
+
for (; ; ) {
|
|
44614
|
+
const member = stack.pop();
|
|
44615
|
+
onStack.delete(member);
|
|
44616
|
+
component.push(member);
|
|
44617
|
+
if (member === nodeId) break;
|
|
44618
|
+
}
|
|
44619
|
+
component.sort(stableCompare);
|
|
44620
|
+
components.push(component);
|
|
44621
|
+
};
|
|
44622
|
+
for (const nodeId of [...nodeIds].sort(stableCompare)) {
|
|
44623
|
+
if (!indexes.has(nodeId)) visit(nodeId);
|
|
44624
|
+
}
|
|
44625
|
+
return components;
|
|
44626
|
+
}
|
|
44627
|
+
function internalComponentRanks(nodeIds, directionalLinks, structuralColors, preferredAnchor, originIncomingBoundaryNodeIds, incomingBoundaryNodeIds, outgoingBoundaryNodeIds, attachmentBoundaryNodeIds) {
|
|
44628
|
+
if (nodeIds.length === 1) return /* @__PURE__ */ new Map([[nodeIds[0], 0]]);
|
|
44629
|
+
const nodeSet = new Set(nodeIds);
|
|
44630
|
+
const internalLinks = directionalLinks.filter(
|
|
44631
|
+
([from, to]) => nodeSet.has(from) && nodeSet.has(to)
|
|
44632
|
+
);
|
|
44633
|
+
const neighborSets = new Map(nodeIds.map((nodeId) => [nodeId, /* @__PURE__ */ new Set()]));
|
|
44634
|
+
for (const [from, to] of internalLinks) {
|
|
44635
|
+
neighborSets.get(from)?.add(to);
|
|
44636
|
+
neighborSets.get(to)?.add(from);
|
|
44637
|
+
}
|
|
44638
|
+
const topology = {
|
|
44639
|
+
neighbors: new Map(
|
|
44640
|
+
[...neighborSets].map(([nodeId, neighbors]) => [nodeId, [...neighbors].sort(stableCompare)])
|
|
44641
|
+
),
|
|
44642
|
+
links: internalLinks,
|
|
44643
|
+
directionalLinks: internalLinks
|
|
44644
|
+
};
|
|
44645
|
+
const ranksFromAnchor = (anchor) => {
|
|
44646
|
+
const rawRanks = /* @__PURE__ */ new Map([[anchor, 0]]);
|
|
44647
|
+
applyForwardWaves(nodeSet, topology, rawRanks);
|
|
44648
|
+
const rankIndexes = normalizedRankIndexes(rawRanks);
|
|
44649
|
+
return new Map(nodeIds.map((nodeId) => [nodeId, rankIndexes.get(rawRanks.get(nodeId)) ?? 0]));
|
|
44650
|
+
};
|
|
44651
|
+
if (preferredAnchor && nodeSet.has(preferredAnchor)) return ranksFromAnchor(preferredAnchor);
|
|
44652
|
+
const candidates = nodeIds.map((anchor) => {
|
|
44653
|
+
const ranks = ranksFromAnchor(anchor);
|
|
44654
|
+
const maxRank = Math.max(...ranks.values());
|
|
44655
|
+
const rankLoadProfile = Array.from(
|
|
44656
|
+
{ length: maxRank + 1 },
|
|
44657
|
+
(_, rank) => nodeIds.filter((nodeId) => ranks.get(nodeId) === rank).length
|
|
44658
|
+
);
|
|
44659
|
+
const rankStructuralProfile = rankLoadProfile.flatMap((_, rank) => [
|
|
44660
|
+
-1,
|
|
44661
|
+
...nodeIds.filter((nodeId) => ranks.get(nodeId) === rank).map((nodeId) => structuralColors.get(nodeId)).sort((left, right) => left - right)
|
|
44662
|
+
]);
|
|
44663
|
+
return {
|
|
44664
|
+
anchor,
|
|
44665
|
+
ranks,
|
|
44666
|
+
nonForward: countNonForwardLinks(ranks, internalLinks),
|
|
44667
|
+
originIncomingBoundaryRanks: originIncomingBoundaryNodeIds.map((nodeId) => ranks.get(nodeId)).sort((left, right) => right - left),
|
|
44668
|
+
incomingBoundaryRanks: incomingBoundaryNodeIds.map((nodeId) => ranks.get(nodeId)).sort((left, right) => right - left),
|
|
44669
|
+
outgoingBoundaryDistances: outgoingBoundaryNodeIds.map((nodeId) => maxRank - ranks.get(nodeId)).sort((left, right) => right - left),
|
|
44670
|
+
attachmentBoundaryRanks: attachmentBoundaryNodeIds.map((nodeId) => ranks.get(nodeId)).sort((left, right) => right - left),
|
|
44671
|
+
width: new Set(ranks.values()).size,
|
|
44672
|
+
span: totalDirectionalSpan(ranks, internalLinks),
|
|
44673
|
+
rankLoadProfile,
|
|
44674
|
+
rankStructuralProfile,
|
|
44675
|
+
anchorStructuralColor: structuralColors.get(anchor)
|
|
44676
|
+
};
|
|
44677
|
+
});
|
|
44678
|
+
candidates.sort(
|
|
44679
|
+
(left, right) => left.nonForward - right.nonForward || compareNumberArrays(left.originIncomingBoundaryRanks, right.originIncomingBoundaryRanks) || compareNumberArrays(left.incomingBoundaryRanks, right.incomingBoundaryRanks) || compareNumberArrays(left.outgoingBoundaryDistances, right.outgoingBoundaryDistances) || compareNumberArrays(left.attachmentBoundaryRanks, right.attachmentBoundaryRanks) || left.width - right.width || left.span - right.span || compareNumberArrays(left.rankLoadProfile, right.rankLoadProfile) || compareNumberArrays(left.rankStructuralProfile, right.rankStructuralProfile) || left.anchorStructuralColor - right.anchorStructuralColor || stableCompare(left.anchor, right.anchor)
|
|
44680
|
+
);
|
|
44681
|
+
return candidates[0].ranks;
|
|
44682
|
+
}
|
|
44683
|
+
function directionalCondensationRanks(nodeIds, topology, originNodeId) {
|
|
44684
|
+
const nodeSet = new Set(nodeIds);
|
|
44685
|
+
const directionalLinks = topology.directionalLinks.filter(
|
|
44686
|
+
([from, to]) => nodeSet.has(from) && nodeSet.has(to)
|
|
44687
|
+
);
|
|
44688
|
+
const structuralColors = canonicalTopologyStructuralColors(nodeIds, topology, originNodeId);
|
|
44689
|
+
const components = stronglyConnectedComponents(nodeIds, directionalLinks);
|
|
44690
|
+
const componentByNodeId = /* @__PURE__ */ new Map();
|
|
44691
|
+
components.forEach((component, componentIndex) => {
|
|
44692
|
+
for (const nodeId of component) componentByNodeId.set(nodeId, componentIndex);
|
|
44693
|
+
});
|
|
44694
|
+
const outgoing = new Map(components.map((_, index2) => [index2, /* @__PURE__ */ new Set()]));
|
|
44695
|
+
const incoming = new Map(components.map((_, index2) => [index2, /* @__PURE__ */ new Set()]));
|
|
44696
|
+
for (const [from, to] of directionalLinks) {
|
|
44697
|
+
const fromComponent = componentByNodeId.get(from);
|
|
44698
|
+
const toComponent = componentByNodeId.get(to);
|
|
44699
|
+
if (fromComponent === toComponent) continue;
|
|
44700
|
+
outgoing.get(fromComponent).add(toComponent);
|
|
44701
|
+
incoming.get(toComponent).add(fromComponent);
|
|
44702
|
+
}
|
|
44703
|
+
const originComponent = componentByNodeId.get(originNodeId);
|
|
44704
|
+
const directionalGroups = [];
|
|
44705
|
+
const directionalGroupByComponent = /* @__PURE__ */ new Map();
|
|
44706
|
+
for (let first = 0; first < components.length; first += 1) {
|
|
44707
|
+
if (directionalGroupByComponent.has(first)) continue;
|
|
44708
|
+
const groupIndex = directionalGroups.length;
|
|
44709
|
+
const group = [];
|
|
44710
|
+
const queue = [first];
|
|
44711
|
+
directionalGroupByComponent.set(first, groupIndex);
|
|
44712
|
+
for (let index2 = 0; index2 < queue.length; index2 += 1) {
|
|
44713
|
+
const current = queue[index2];
|
|
44714
|
+
group.push(current);
|
|
44715
|
+
for (const neighbor of [...outgoing.get(current), ...incoming.get(current)]) {
|
|
44716
|
+
if (directionalGroupByComponent.has(neighbor)) continue;
|
|
44717
|
+
directionalGroupByComponent.set(neighbor, groupIndex);
|
|
44718
|
+
queue.push(neighbor);
|
|
44719
|
+
}
|
|
44720
|
+
}
|
|
44721
|
+
directionalGroups.push(group);
|
|
44722
|
+
}
|
|
44723
|
+
const directionalGroupByNodeId = /* @__PURE__ */ new Map();
|
|
44724
|
+
for (const [nodeId, componentIndex] of componentByNodeId) {
|
|
44725
|
+
directionalGroupByNodeId.set(nodeId, directionalGroupByComponent.get(componentIndex));
|
|
44726
|
+
}
|
|
44727
|
+
const attachmentBoundaryNodeIds = new Map(
|
|
44728
|
+
components.map((_, componentIndex) => [componentIndex, []])
|
|
44729
|
+
);
|
|
44730
|
+
for (const [left, right] of topology.links) {
|
|
44731
|
+
if (directionalGroupByNodeId.get(left) === directionalGroupByNodeId.get(right)) continue;
|
|
44732
|
+
attachmentBoundaryNodeIds.get(componentByNodeId.get(left)).push(left);
|
|
44733
|
+
attachmentBoundaryNodeIds.get(componentByNodeId.get(right)).push(right);
|
|
44734
|
+
}
|
|
44735
|
+
const compareComponents = (left, right) => stableCompare(components[left][0], components[right][0]);
|
|
44736
|
+
const localRanks = /* @__PURE__ */ new Map();
|
|
44737
|
+
const componentWidths = /* @__PURE__ */ new Map();
|
|
44738
|
+
for (let componentIndex = 0; componentIndex < components.length; componentIndex += 1) {
|
|
44739
|
+
const component = components[componentIndex];
|
|
44740
|
+
const ranks2 = internalComponentRanks(
|
|
44741
|
+
component,
|
|
44742
|
+
directionalLinks,
|
|
44743
|
+
structuralColors,
|
|
44744
|
+
component.includes(originNodeId) ? originNodeId : null,
|
|
44745
|
+
directionalLinks.flatMap(
|
|
44746
|
+
([from, to]) => componentByNodeId.get(from) === originComponent && componentByNodeId.get(to) === componentIndex && componentIndex !== originComponent ? [to] : []
|
|
44747
|
+
),
|
|
44748
|
+
directionalLinks.flatMap(
|
|
44749
|
+
([from, to]) => componentByNodeId.get(to) === componentIndex && componentByNodeId.get(from) !== componentIndex ? [to] : []
|
|
44750
|
+
),
|
|
44751
|
+
directionalLinks.flatMap(
|
|
44752
|
+
([from, to]) => componentByNodeId.get(from) === componentIndex && componentByNodeId.get(to) !== componentIndex ? [from] : []
|
|
44753
|
+
),
|
|
44754
|
+
attachmentBoundaryNodeIds.get(componentIndex)
|
|
44755
|
+
);
|
|
44756
|
+
localRanks.set(componentIndex, ranks2);
|
|
44757
|
+
componentWidths.set(componentIndex, Math.max(...ranks2.values()) + 1);
|
|
44758
|
+
}
|
|
44759
|
+
const remainingIncoming = new Map(
|
|
44760
|
+
components.map((_, componentIndex) => [componentIndex, incoming.get(componentIndex).size])
|
|
44761
|
+
);
|
|
44762
|
+
const componentStarts = /* @__PURE__ */ new Map();
|
|
44763
|
+
const ready = components.map((_, componentIndex) => componentIndex).filter((componentIndex) => remainingIncoming.get(componentIndex) === 0).sort(compareComponents);
|
|
44764
|
+
for (const componentIndex of ready) componentStarts.set(componentIndex, 0);
|
|
44765
|
+
while (ready.length > 0) {
|
|
44766
|
+
const current = ready.shift();
|
|
44767
|
+
for (const target of [...outgoing.get(current)].sort(compareComponents)) {
|
|
44768
|
+
componentStarts.set(
|
|
44769
|
+
target,
|
|
44770
|
+
Math.max(
|
|
44771
|
+
componentStarts.get(target) ?? 0,
|
|
44772
|
+
componentStarts.get(current) + componentWidths.get(current)
|
|
44773
|
+
)
|
|
44774
|
+
);
|
|
44775
|
+
const unresolved = remainingIncoming.get(target) - 1;
|
|
44776
|
+
remainingIncoming.set(target, unresolved);
|
|
44777
|
+
if (unresolved === 0) {
|
|
44778
|
+
ready.push(target);
|
|
44779
|
+
ready.sort(compareComponents);
|
|
44780
|
+
}
|
|
44781
|
+
}
|
|
44782
|
+
}
|
|
44783
|
+
const unshiftedRanks = /* @__PURE__ */ new Map();
|
|
44784
|
+
for (let componentIndex = 0; componentIndex < components.length; componentIndex += 1) {
|
|
44785
|
+
for (const [nodeId, localRank] of localRanks.get(componentIndex)) {
|
|
44786
|
+
unshiftedRanks.set(nodeId, componentStarts.get(componentIndex) + localRank);
|
|
44787
|
+
}
|
|
44788
|
+
}
|
|
44789
|
+
const originGroup = directionalGroupByComponent.get(originComponent);
|
|
44790
|
+
const groupOffsets = /* @__PURE__ */ new Map([[originGroup, -unshiftedRanks.get(originNodeId)]]);
|
|
44791
|
+
while (groupOffsets.size < directionalGroups.length) {
|
|
44792
|
+
const proposals = /* @__PURE__ */ new Map();
|
|
44793
|
+
for (const [left, right] of topology.links) {
|
|
44794
|
+
const leftGroup = directionalGroupByNodeId.get(left);
|
|
44795
|
+
const rightGroup = directionalGroupByNodeId.get(right);
|
|
44796
|
+
if (leftGroup === rightGroup) continue;
|
|
44797
|
+
const leftOffset = groupOffsets.get(leftGroup);
|
|
44798
|
+
const rightOffset = groupOffsets.get(rightGroup);
|
|
44799
|
+
if (leftOffset !== void 0 && rightOffset === void 0) {
|
|
44800
|
+
const offsets = proposals.get(rightGroup) ?? /* @__PURE__ */ new Set();
|
|
44801
|
+
offsets.add(unshiftedRanks.get(left) + leftOffset + 1 - unshiftedRanks.get(right));
|
|
44802
|
+
proposals.set(rightGroup, offsets);
|
|
44803
|
+
}
|
|
44804
|
+
if (leftOffset === void 0 && rightOffset !== void 0) {
|
|
44805
|
+
const offsets = proposals.get(leftGroup) ?? /* @__PURE__ */ new Set();
|
|
44806
|
+
offsets.add(unshiftedRanks.get(right) + rightOffset + 1 - unshiftedRanks.get(left));
|
|
44807
|
+
proposals.set(leftGroup, offsets);
|
|
44808
|
+
}
|
|
44809
|
+
}
|
|
44810
|
+
if (proposals.size === 0) break;
|
|
44811
|
+
const knownGroupOffsets = new Map(groupOffsets);
|
|
44812
|
+
const rankedValues = [...unshiftedRanks].flatMap(([nodeId, rank]) => {
|
|
44813
|
+
const offset = knownGroupOffsets.get(directionalGroupByNodeId.get(nodeId));
|
|
44814
|
+
return offset === void 0 ? [] : [rank + offset];
|
|
44815
|
+
});
|
|
44816
|
+
const acceptedOffsets = /* @__PURE__ */ new Map();
|
|
44817
|
+
for (const [groupIndex, proposedOffsets] of proposals) {
|
|
44818
|
+
const candidates = [...proposedOffsets].map((offset) => {
|
|
44819
|
+
const crossGroupSpan = topology.links.reduce((total, [left, right]) => {
|
|
44820
|
+
const leftGroup = directionalGroupByNodeId.get(left);
|
|
44821
|
+
const rightGroup = directionalGroupByNodeId.get(right);
|
|
44822
|
+
const leftOffset = leftGroup === groupIndex ? offset : knownGroupOffsets.get(leftGroup);
|
|
44823
|
+
const rightOffset = rightGroup === groupIndex ? offset : knownGroupOffsets.get(rightGroup);
|
|
44824
|
+
if (leftOffset === void 0 || rightOffset === void 0) return total;
|
|
44825
|
+
return total + Math.abs(
|
|
44826
|
+
unshiftedRanks.get(left) + leftOffset - unshiftedRanks.get(right) - rightOffset
|
|
44827
|
+
);
|
|
44828
|
+
}, 0);
|
|
44829
|
+
const addedRanks = directionalGroups[groupIndex].flatMap(
|
|
44830
|
+
(componentIndex) => components[componentIndex].map((nodeId) => unshiftedRanks.get(nodeId) + offset)
|
|
44831
|
+
);
|
|
44832
|
+
return {
|
|
44833
|
+
offset,
|
|
44834
|
+
crossGroupSpan,
|
|
44835
|
+
occupiedColumns: (/* @__PURE__ */ new Set([...rankedValues, ...addedRanks])).size
|
|
44836
|
+
};
|
|
44837
|
+
});
|
|
44838
|
+
candidates.sort(
|
|
44839
|
+
(left, right) => left.crossGroupSpan - right.crossGroupSpan || left.occupiedColumns - right.occupiedColumns || Math.abs(left.offset) - Math.abs(right.offset) || left.offset - right.offset
|
|
44840
|
+
);
|
|
44841
|
+
acceptedOffsets.set(groupIndex, candidates[0].offset);
|
|
44842
|
+
}
|
|
44843
|
+
for (const [groupIndex, offset] of acceptedOffsets) groupOffsets.set(groupIndex, offset);
|
|
44844
|
+
}
|
|
44845
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
44846
|
+
for (const [nodeId, rank] of unshiftedRanks) {
|
|
44847
|
+
const groupOffset = groupOffsets.get(directionalGroupByNodeId.get(nodeId));
|
|
44848
|
+
ranks.set(nodeId, rank + (groupOffset ?? 0));
|
|
44849
|
+
}
|
|
44850
|
+
return ranks;
|
|
44851
|
+
}
|
|
44852
|
+
function componentRanks(nodeIds, topology, entrypointId) {
|
|
44853
|
+
const nodeSet = new Set(nodeIds);
|
|
44854
|
+
const entrypoint = entrypointId && nodeSet.has(entrypointId) ? entrypointId : null;
|
|
44855
|
+
if (!entrypoint) {
|
|
44856
|
+
const root3 = topologyRoot(nodeIds, topology);
|
|
44857
|
+
const ranks2 = /* @__PURE__ */ new Map();
|
|
44858
|
+
ranks2.set(root3, 0);
|
|
44859
|
+
const queue = [root3];
|
|
44860
|
+
for (let index2 = 0; index2 < queue.length; index2 += 1) {
|
|
44861
|
+
const current = queue[index2];
|
|
44862
|
+
for (const neighbor of topology.neighbors.get(current) ?? []) {
|
|
44863
|
+
if (!nodeSet.has(neighbor) || ranks2.has(neighbor)) continue;
|
|
44864
|
+
ranks2.set(neighbor, ranks2.get(current) + 1);
|
|
44865
|
+
queue.push(neighbor);
|
|
44866
|
+
}
|
|
44867
|
+
}
|
|
44868
|
+
return ranks2;
|
|
44869
|
+
}
|
|
44870
|
+
const ranks = directionalCondensationRanks(nodeIds, topology, entrypoint);
|
|
44871
|
+
const rankedQueue = [...ranks].sort(
|
|
44872
|
+
([leftId, leftRank], [rightId, rightRank]) => leftRank - rightRank || stableCompare(leftId, rightId)
|
|
44873
|
+
).map(([nodeId]) => nodeId);
|
|
44874
|
+
for (let index2 = 0; index2 < rankedQueue.length; index2 += 1) {
|
|
44875
|
+
const current = rankedQueue[index2];
|
|
44876
|
+
for (const neighbor of topology.neighbors.get(current) ?? []) {
|
|
44877
|
+
if (!nodeSet.has(neighbor) || ranks.has(neighbor)) continue;
|
|
44878
|
+
ranks.set(neighbor, ranks.get(current) + 1);
|
|
44879
|
+
rankedQueue.push(neighbor);
|
|
44880
|
+
}
|
|
44881
|
+
}
|
|
44882
|
+
return ranks;
|
|
44883
|
+
}
|
|
44884
|
+
function orderRankGroups(groups, topology) {
|
|
44885
|
+
const rankValues = [...groups.keys()].sort((left, right) => left - right);
|
|
44886
|
+
const result = new Map(
|
|
44887
|
+
rankValues.map((rank) => [rank, [...groups.get(rank)].sort(stableCompare)])
|
|
44888
|
+
);
|
|
44889
|
+
const sortAgainst = (rank, adjacentRank) => {
|
|
44890
|
+
const nodes = result.get(rank);
|
|
44891
|
+
const adjacent = result.get(adjacentRank);
|
|
44892
|
+
const adjacentOrder = new Map(adjacent.map((nodeId, index2) => [nodeId, index2]));
|
|
44893
|
+
const barycenter = (nodeId) => {
|
|
44894
|
+
const indexes = (topology.neighbors.get(nodeId) ?? []).flatMap((neighbor) => {
|
|
44895
|
+
const index2 = adjacentOrder.get(neighbor);
|
|
44896
|
+
return index2 === void 0 ? [] : [index2];
|
|
44897
|
+
});
|
|
44898
|
+
return indexes.length === 0 ? null : indexes.reduce((total, index2) => total + index2, 0) / indexes.length;
|
|
44899
|
+
};
|
|
44900
|
+
nodes.sort((left, right) => {
|
|
44901
|
+
const leftCenter = barycenter(left);
|
|
44902
|
+
const rightCenter = barycenter(right);
|
|
44903
|
+
if (leftCenter === null && rightCenter === null) return stableCompare(left, right);
|
|
44904
|
+
if (leftCenter === null) return 1;
|
|
44905
|
+
if (rightCenter === null) return -1;
|
|
44906
|
+
return leftCenter - rightCenter || stableCompare(left, right);
|
|
44907
|
+
});
|
|
44908
|
+
};
|
|
44909
|
+
for (let pass = 0; pass < 6; pass += 1) {
|
|
44910
|
+
for (let index2 = 1; index2 < rankValues.length; index2 += 1) {
|
|
44911
|
+
sortAgainst(rankValues[index2], rankValues[index2 - 1]);
|
|
44912
|
+
}
|
|
44913
|
+
for (let index2 = rankValues.length - 2; index2 >= 0; index2 -= 1) {
|
|
44914
|
+
sortAgainst(rankValues[index2], rankValues[index2 + 1]);
|
|
44915
|
+
}
|
|
44916
|
+
}
|
|
44917
|
+
return result;
|
|
44918
|
+
}
|
|
44919
|
+
var PRESENTATION_ROW_STRIDE = STRUCTURE_NODE_HEIGHT + 72;
|
|
44920
|
+
var PRESENTATION_COLUMN_STRIDE = STRUCTURE_NODE_WIDTH + 64;
|
|
44921
|
+
var PRESENTATION_TARGET_ASPECT_RATIO = 5 / 3;
|
|
44922
|
+
function layoutTopologyComponent(nodeIds, topology, entrypointId) {
|
|
44923
|
+
const ranks = componentRanks(nodeIds, topology, entrypointId);
|
|
44924
|
+
const rawGroups = /* @__PURE__ */ new Map();
|
|
44925
|
+
for (const nodeId of nodeIds) {
|
|
44926
|
+
const rank = ranks.get(nodeId) ?? 0;
|
|
44927
|
+
const group = rawGroups.get(rank) ?? [];
|
|
44928
|
+
group.push(nodeId);
|
|
44929
|
+
rawGroups.set(rank, group);
|
|
44930
|
+
}
|
|
44931
|
+
const groups = orderRankGroups(rawGroups, topology);
|
|
44932
|
+
const rankValues = [...groups.keys()].sort((left, right) => left - right);
|
|
44933
|
+
const rankStride = STRUCTURE_NODE_WIDTH + 192;
|
|
44934
|
+
const rowStride = STRUCTURE_NODE_HEIGHT + 72;
|
|
44935
|
+
const maxRows = Math.max(...[...groups.values()].map((nodes) => nodes.length));
|
|
44936
|
+
const centerY = (maxRows - 1) * rowStride / 2;
|
|
44937
|
+
const positions = /* @__PURE__ */ new Map();
|
|
44938
|
+
rankValues.forEach((rank, rankIndex) => {
|
|
44939
|
+
const group = groups.get(rank);
|
|
44940
|
+
const top = centerY - (group.length - 1) * rowStride / 2;
|
|
44941
|
+
group.forEach((nodeId, rowIndex) => {
|
|
44942
|
+
positions.set(nodeId, { x: rankIndex * rankStride, y: top + rowIndex * rowStride });
|
|
44943
|
+
});
|
|
44944
|
+
});
|
|
44945
|
+
return {
|
|
44946
|
+
nodeIds,
|
|
44947
|
+
positions,
|
|
44948
|
+
ranks,
|
|
44949
|
+
width: (rankValues.length - 1) * rankStride + STRUCTURE_NODE_WIDTH,
|
|
44950
|
+
height: (maxRows - 1) * rowStride + STRUCTURE_NODE_HEIGHT
|
|
44951
|
+
};
|
|
44952
|
+
}
|
|
44953
|
+
function projectTopologyStructureWithTopology(structure, topology) {
|
|
44954
|
+
if (structure.nodes.length === 0) {
|
|
44955
|
+
const diagnostics2 = {
|
|
44956
|
+
columnCount: 0,
|
|
44957
|
+
rowsPerColumn: [],
|
|
44958
|
+
maxRows: 0,
|
|
44959
|
+
directionalLinkCount: topology.directionalLinks.length,
|
|
44960
|
+
nonForwardDirectionalLinkCount: 0,
|
|
44961
|
+
nonForwardDirectionalLinkRatio: 0,
|
|
44962
|
+
originOutgoingDirectionalLinkCount: 0
|
|
44963
|
+
};
|
|
44964
|
+
return {
|
|
44965
|
+
positionsByNodeId: /* @__PURE__ */ new Map(),
|
|
44966
|
+
rankByNodeId: /* @__PURE__ */ new Map(),
|
|
44967
|
+
columnIndexByNodeId: /* @__PURE__ */ new Map(),
|
|
44968
|
+
columns: [],
|
|
44969
|
+
directionalLinks: topology.directionalLinks,
|
|
44970
|
+
diagnostics: diagnostics2
|
|
44971
|
+
};
|
|
44972
|
+
}
|
|
44973
|
+
const componentGap = 180;
|
|
44974
|
+
const outerPadding = 64;
|
|
44975
|
+
const components = topologyComponents(topology).map(
|
|
44976
|
+
(nodeIds) => layoutTopologyComponent(
|
|
44977
|
+
nodeIds,
|
|
44978
|
+
topology,
|
|
44979
|
+
nodeIds.includes(structure.originNodeId) ? structure.originNodeId : null
|
|
44980
|
+
)
|
|
44981
|
+
);
|
|
44982
|
+
const totalArea = components.reduce(
|
|
44983
|
+
(sum, component) => sum + (component.width + componentGap) * (component.height + componentGap),
|
|
44984
|
+
0
|
|
44985
|
+
);
|
|
44986
|
+
const targetRowWidth = Math.max(960, Math.sqrt(totalArea) * 1.45);
|
|
44987
|
+
const positions = /* @__PURE__ */ new Map();
|
|
44988
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
44989
|
+
let cursorX = outerPadding;
|
|
44990
|
+
let cursorY = outerPadding;
|
|
44991
|
+
let rowHeight = 0;
|
|
44992
|
+
for (const component of components) {
|
|
44993
|
+
if (cursorX > outerPadding && cursorX + component.width > targetRowWidth) {
|
|
44994
|
+
cursorX = outerPadding;
|
|
44995
|
+
cursorY += rowHeight + componentGap;
|
|
44996
|
+
rowHeight = 0;
|
|
44997
|
+
}
|
|
44998
|
+
for (const nodeId of component.nodeIds) {
|
|
44999
|
+
const point5 = component.positions.get(nodeId);
|
|
45000
|
+
positions.set(nodeId, { x: cursorX + point5.x, y: cursorY + point5.y });
|
|
45001
|
+
ranks.set(nodeId, component.ranks.get(nodeId) ?? 0);
|
|
45002
|
+
}
|
|
45003
|
+
cursorX += component.width + componentGap;
|
|
45004
|
+
rowHeight = Math.max(rowHeight, component.height);
|
|
45005
|
+
}
|
|
45006
|
+
const xValues = [...new Set([...positions.values()].map(({ x }) => x))].sort(
|
|
45007
|
+
(left, right) => left - right
|
|
45008
|
+
);
|
|
45009
|
+
const columnIndexByX = new Map(xValues.map((x, index2) => [x, index2]));
|
|
45010
|
+
const columns = xValues.map(
|
|
45011
|
+
(x) => [...positions].filter(([, point5]) => point5.x === x).sort(([, left], [, right]) => left.y - right.y).map(([nodeId]) => nodeId)
|
|
45012
|
+
);
|
|
45013
|
+
const columnIndexByNodeId = new Map(
|
|
45014
|
+
[...positions].map(([nodeId, point5]) => [nodeId, columnIndexByX.get(point5.x)])
|
|
45015
|
+
);
|
|
45016
|
+
const nonForwardDirectionalLinkCount = topology.directionalLinks.reduce(
|
|
45017
|
+
(count, [from, to]) => count + (columnIndexByNodeId.has(from) && columnIndexByNodeId.has(to) && columnIndexByNodeId.get(from) >= columnIndexByNodeId.get(to) ? 1 : 0),
|
|
45018
|
+
0
|
|
45019
|
+
);
|
|
45020
|
+
const directionalLinkCount = topology.directionalLinks.length;
|
|
45021
|
+
const rowsPerColumn = columns.map((column) => column.length);
|
|
45022
|
+
const diagnostics = {
|
|
45023
|
+
columnCount: columns.length,
|
|
45024
|
+
rowsPerColumn,
|
|
45025
|
+
maxRows: Math.max(0, ...rowsPerColumn),
|
|
45026
|
+
directionalLinkCount,
|
|
45027
|
+
nonForwardDirectionalLinkCount,
|
|
45028
|
+
nonForwardDirectionalLinkRatio: directionalLinkCount === 0 ? 0 : nonForwardDirectionalLinkCount / directionalLinkCount,
|
|
45029
|
+
originOutgoingDirectionalLinkCount: topology.directionalLinks.filter(
|
|
45030
|
+
([from]) => from === structure.originNodeId
|
|
45031
|
+
).length
|
|
45032
|
+
};
|
|
45033
|
+
return {
|
|
45034
|
+
positionsByNodeId: positions,
|
|
45035
|
+
rankByNodeId: ranks,
|
|
45036
|
+
columnIndexByNodeId,
|
|
45037
|
+
columns,
|
|
45038
|
+
directionalLinks: topology.directionalLinks,
|
|
45039
|
+
diagnostics
|
|
45040
|
+
};
|
|
45041
|
+
}
|
|
45042
|
+
function projectTopologyStructure(structure) {
|
|
45043
|
+
return projectTopologyStructureWithTopology(structure, simpleStructureTopology(structure));
|
|
45044
|
+
}
|
|
45045
|
+
function structureAuthoringWarnings(diagnostics) {
|
|
45046
|
+
const warnings = [];
|
|
45047
|
+
if (diagnostics.originOutgoingDirectionalLinkCount === 0) {
|
|
45048
|
+
warnings.push({
|
|
45049
|
+
code: "STRUCTURE_ORIGIN_NO_OUTGOING_DIRECTIONAL_RELATION",
|
|
45050
|
+
message: "origin has no outgoing unambiguous directed relation; verify that it is the factual code entrypoint for this behavior. A terminal or intermediate origin may still be valid. Do not change factual relation direction solely to remove this warning."
|
|
45051
|
+
});
|
|
45052
|
+
}
|
|
45053
|
+
if (diagnostics.maxRows >= 8) {
|
|
45054
|
+
warnings.push({
|
|
45055
|
+
code: "STRUCTURE_LAYOUT_MAX_ROWS_HIGH",
|
|
45056
|
+
message: "the neutral topology diagnostic has a tall column; reconsider the factual origin, node granularity, overlapping or nested claims, whether multiple behaviors are mixed, and the subject boundary."
|
|
45057
|
+
});
|
|
45058
|
+
}
|
|
45059
|
+
if (diagnostics.nonForwardDirectionalLinkRatio >= 0.25) {
|
|
45060
|
+
warnings.push({
|
|
45061
|
+
code: "STRUCTURE_LAYOUT_NON_FORWARD_DIRECTIONAL_LINK_RATIO_HIGH",
|
|
45062
|
+
message: "many unambiguous directed relations are non-forward in the neutral topology diagnostic; reconsider the factual origin, node granularity, behavior boundary, and subject boundary. A factual graph may remain above this threshold. Do not change edge direction solely to improve the score."
|
|
45063
|
+
});
|
|
45064
|
+
}
|
|
45065
|
+
return warnings;
|
|
45066
|
+
}
|
|
45067
|
+
|
|
43808
45068
|
// src/infrastructure/skills/skill-installer.ts
|
|
43809
45069
|
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
43810
45070
|
import {
|
|
@@ -43824,6 +45084,7 @@ import path7 from "node:path";
|
|
|
43824
45084
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
43825
45085
|
var skillNames = [
|
|
43826
45086
|
"rvw",
|
|
45087
|
+
"rvw-review-compose",
|
|
43827
45088
|
"rvw-walkthrough",
|
|
43828
45089
|
"rvw-structure",
|
|
43829
45090
|
"rvw-watch-comments"
|
|
@@ -47648,6 +48909,8 @@ var nullableCommentLine = external_exports.number().int().positive().nullable().
|
|
|
47648
48909
|
var idempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS).optional();
|
|
47649
48910
|
var requiredIdempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS);
|
|
47650
48911
|
var expectedUpdatedAt = external_exports.string().min(1).max(100);
|
|
48912
|
+
var commentWatchTaskFenceSchema = external_exports.object({ taskId: external_exports.uuid(), generation: external_exports.number().int().positive() }).strict();
|
|
48913
|
+
var commentWatchLeaseSchema = commentWatchTaskFenceSchema.extend({ leaseId: external_exports.uuid() }).strict();
|
|
47651
48914
|
var commentTargetInputSchema = external_exports.union([
|
|
47652
48915
|
external_exports.object({ kind: external_exports.literal("pull-request") }).strict(),
|
|
47653
48916
|
external_exports.object({
|
|
@@ -47735,14 +48998,16 @@ var commentReplyInputSchema = external_exports.object({
|
|
|
47735
48998
|
authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
|
|
47736
48999
|
relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
|
|
47737
49000
|
references: optionalCodeReferences,
|
|
47738
|
-
idempotencyKey
|
|
49001
|
+
idempotencyKey,
|
|
49002
|
+
watchTask: commentWatchTaskFenceSchema.optional()
|
|
47739
49003
|
}).strict().superRefine(requireRelatedCommitForReferences);
|
|
47740
49004
|
var commentPostEditInputSchema = external_exports.object({
|
|
47741
49005
|
body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES, {
|
|
47742
49006
|
message: `body\u306FUTF-8\u3067${MAX_COMMENT_BODY_BYTES} bytes\uFF0864 KiB\uFF09\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
47743
49007
|
}),
|
|
47744
49008
|
relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
|
|
47745
|
-
references: optionalCodeReferences
|
|
49009
|
+
references: optionalCodeReferences,
|
|
49010
|
+
watchTask: commentWatchTaskFenceSchema.optional()
|
|
47746
49011
|
}).strict();
|
|
47747
49012
|
var pullRequestSyncInputSchema = external_exports.object({
|
|
47748
49013
|
pullRequest: nonEmptyString,
|
|
@@ -47802,13 +49067,29 @@ var structureEdgeInputSchema = external_exports.object({
|
|
|
47802
49067
|
directed: external_exports.boolean(),
|
|
47803
49068
|
anchors: external_exports.array(sourceAnchorInputSchema).max(MAX_STRUCTURE_EDGE_ANCHORS).optional().default([])
|
|
47804
49069
|
}).strict();
|
|
49070
|
+
var structurePresentationInputSchema = external_exports.object({
|
|
49071
|
+
thesis: external_exports.string().transform((value) => value.trim()).pipe(external_exports.string().min(1).max(MAX_STRUCTURE_PRESENTATION_THESIS_CHARACTERS)),
|
|
49072
|
+
startNodeId: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
49073
|
+
primaryBackbone: external_exports.object({
|
|
49074
|
+
edgeIds: external_exports.array(external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN)).min(1).max(MAX_STRUCTURE_PRIMARY_BACKBONE_EDGES).transform(canonicalStructureBackboneEdgeIds)
|
|
49075
|
+
}).strict().nullable(),
|
|
49076
|
+
regions: external_exports.array(
|
|
49077
|
+
external_exports.object({
|
|
49078
|
+
id: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
49079
|
+
label: external_exports.string().transform((value) => value.trim()).pipe(external_exports.string().min(1).max(MAX_STRUCTURE_PRESENTATION_REGION_LABEL_CHARACTERS)),
|
|
49080
|
+
summary: external_exports.string().transform((value) => value.trim()).pipe(external_exports.string().min(1).max(MAX_STRUCTURE_PRESENTATION_REGION_SUMMARY_CHARACTERS)),
|
|
49081
|
+
nodeIds: external_exports.array(external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN)).min(1).max(MAX_STRUCTURE_NODES).transform(canonicalStructureRegionNodeIds)
|
|
49082
|
+
}).strict()
|
|
49083
|
+
).max(MAX_STRUCTURE_PRESENTATION_REGIONS).transform(canonicalStructurePresentationRegions)
|
|
49084
|
+
}).strict();
|
|
47805
49085
|
var structureContentShape = {
|
|
47806
49086
|
sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
47807
49087
|
title: external_exports.string().min(1).max(MAX_STRUCTURE_TITLE_CHARACTERS),
|
|
47808
49088
|
scope: external_exports.string().min(1).max(MAX_STRUCTURE_SCOPE_CHARACTERS),
|
|
47809
49089
|
originNodeId: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47810
49090
|
nodes: external_exports.array(structureNodeInputSchema).min(1).max(MAX_STRUCTURE_NODES),
|
|
47811
|
-
edges: external_exports.array(structureEdgeInputSchema).max(MAX_STRUCTURE_EDGES)
|
|
49091
|
+
edges: external_exports.array(structureEdgeInputSchema).max(MAX_STRUCTURE_EDGES),
|
|
49092
|
+
presentation: structurePresentationInputSchema.nullable()
|
|
47812
49093
|
};
|
|
47813
49094
|
function refineStructureContent(value, context) {
|
|
47814
49095
|
const nodeIds = /* @__PURE__ */ new Set();
|
|
@@ -47887,6 +49168,107 @@ function refineStructureContent(value, context) {
|
|
|
47887
49168
|
});
|
|
47888
49169
|
}
|
|
47889
49170
|
}
|
|
49171
|
+
if (value.presentation !== null) {
|
|
49172
|
+
if (!nodeIds.has(value.presentation.startNodeId)) {
|
|
49173
|
+
context.addIssue({
|
|
49174
|
+
code: "custom",
|
|
49175
|
+
path: ["presentation", "startNodeId"],
|
|
49176
|
+
message: "startNodeId\u306ENode\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
49177
|
+
});
|
|
49178
|
+
}
|
|
49179
|
+
const primaryBackbone = value.presentation.primaryBackbone;
|
|
49180
|
+
if (primaryBackbone !== null) {
|
|
49181
|
+
const selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
49182
|
+
const edgeById = new Map(value.edges.map((edge) => [edge.id, edge]));
|
|
49183
|
+
const selectedEdges = [];
|
|
49184
|
+
let allEdgeIdsValid = true;
|
|
49185
|
+
for (const [index2, edgeId] of primaryBackbone.edgeIds.entries()) {
|
|
49186
|
+
if (selectedEdgeIds.has(edgeId)) {
|
|
49187
|
+
context.addIssue({
|
|
49188
|
+
code: "custom",
|
|
49189
|
+
path: ["presentation", "primaryBackbone", "edgeIds", index2],
|
|
49190
|
+
message: "primaryBackbone\u306EEdge ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
49191
|
+
});
|
|
49192
|
+
allEdgeIdsValid = false;
|
|
49193
|
+
continue;
|
|
49194
|
+
}
|
|
49195
|
+
selectedEdgeIds.add(edgeId);
|
|
49196
|
+
const edge = edgeById.get(edgeId);
|
|
49197
|
+
if (edge === void 0) {
|
|
49198
|
+
context.addIssue({
|
|
49199
|
+
code: "custom",
|
|
49200
|
+
path: ["presentation", "primaryBackbone", "edgeIds", index2],
|
|
49201
|
+
message: "primaryBackbone\u306EEdge\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
49202
|
+
});
|
|
49203
|
+
allEdgeIdsValid = false;
|
|
49204
|
+
continue;
|
|
49205
|
+
}
|
|
49206
|
+
selectedEdges.push(edge);
|
|
49207
|
+
}
|
|
49208
|
+
if (allEdgeIdsValid) {
|
|
49209
|
+
const backboneNodeIds = structureBackboneNodeIds(selectedEdges);
|
|
49210
|
+
if (backboneNodeIds.size < 2 || backboneNodeIds.size > MAX_STRUCTURE_PRIMARY_BACKBONE_NODES) {
|
|
49211
|
+
context.addIssue({
|
|
49212
|
+
code: "custom",
|
|
49213
|
+
path: ["presentation", "primaryBackbone", "edgeIds"],
|
|
49214
|
+
message: `primaryBackbone\u306F2\u301C${MAX_STRUCTURE_PRIMARY_BACKBONE_NODES}\u4EF6\u306ENode\u3092\u7D50\u3076\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
49215
|
+
});
|
|
49216
|
+
}
|
|
49217
|
+
if (!backboneNodeIds.has(value.presentation.startNodeId)) {
|
|
49218
|
+
context.addIssue({
|
|
49219
|
+
code: "custom",
|
|
49220
|
+
path: ["presentation", "startNodeId"],
|
|
49221
|
+
message: "startNodeId\u306FprimaryBackbone\u306EEdge endpoint\u306B\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
49222
|
+
});
|
|
49223
|
+
} else if (!isStructureBackboneWeaklyConnected(selectedEdges, value.presentation.startNodeId)) {
|
|
49224
|
+
context.addIssue({
|
|
49225
|
+
code: "custom",
|
|
49226
|
+
path: ["presentation", "primaryBackbone", "edgeIds"],
|
|
49227
|
+
message: "primaryBackbone\u306FstartNodeId\u304B\u3089\u8FBF\u308C\u308B\u4E00\u3064\u306Econnected graph\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
49228
|
+
});
|
|
49229
|
+
}
|
|
49230
|
+
}
|
|
49231
|
+
}
|
|
49232
|
+
const regionIds = /* @__PURE__ */ new Set();
|
|
49233
|
+
const regionByNodeId = /* @__PURE__ */ new Map();
|
|
49234
|
+
for (const [regionIndex, region] of value.presentation.regions.entries()) {
|
|
49235
|
+
if (regionIds.has(region.id)) {
|
|
49236
|
+
context.addIssue({
|
|
49237
|
+
code: "custom",
|
|
49238
|
+
path: ["presentation", "regions", regionIndex, "id"],
|
|
49239
|
+
message: "region ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
49240
|
+
});
|
|
49241
|
+
}
|
|
49242
|
+
regionIds.add(region.id);
|
|
49243
|
+
const currentRegionNodeIds = /* @__PURE__ */ new Set();
|
|
49244
|
+
for (const [nodeIndex, nodeId] of region.nodeIds.entries()) {
|
|
49245
|
+
if (currentRegionNodeIds.has(nodeId)) {
|
|
49246
|
+
context.addIssue({
|
|
49247
|
+
code: "custom",
|
|
49248
|
+
path: ["presentation", "regions", regionIndex, "nodeIds", nodeIndex],
|
|
49249
|
+
message: "\u540C\u3058region\u5185\u3067Node ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
49250
|
+
});
|
|
49251
|
+
}
|
|
49252
|
+
currentRegionNodeIds.add(nodeId);
|
|
49253
|
+
if (!nodeIds.has(nodeId)) {
|
|
49254
|
+
context.addIssue({
|
|
49255
|
+
code: "custom",
|
|
49256
|
+
path: ["presentation", "regions", regionIndex, "nodeIds", nodeIndex],
|
|
49257
|
+
message: "region\u306ENode\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
49258
|
+
});
|
|
49259
|
+
}
|
|
49260
|
+
const assignedRegionId = regionByNodeId.get(nodeId);
|
|
49261
|
+
if (assignedRegionId !== void 0 && assignedRegionId !== region.id) {
|
|
49262
|
+
context.addIssue({
|
|
49263
|
+
code: "custom",
|
|
49264
|
+
path: ["presentation", "regions", regionIndex, "nodeIds", nodeIndex],
|
|
49265
|
+
message: "\u4E00\u3064\u306ENode\u3092\u8907\u6570region\u3078\u6240\u5C5E\u3055\u305B\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"
|
|
49266
|
+
});
|
|
49267
|
+
}
|
|
49268
|
+
if (assignedRegionId === void 0) regionByNodeId.set(nodeId, region.id);
|
|
49269
|
+
}
|
|
49270
|
+
}
|
|
49271
|
+
}
|
|
47890
49272
|
const anchorCount = value.nodes.filter((node2) => node2.anchor !== null).length + value.edges.reduce((count, edge) => count + edge.anchors.length, 0);
|
|
47891
49273
|
if (anchorCount < 1) {
|
|
47892
49274
|
context.addIssue({
|
|
@@ -47900,7 +49282,12 @@ function refineStructureContent(value, context) {
|
|
|
47900
49282
|
message: `Structure\u306Esource anchor\u306F\u5408\u8A08${MAX_STRUCTURE_SOURCE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
47901
49283
|
});
|
|
47902
49284
|
}
|
|
47903
|
-
const graph = {
|
|
49285
|
+
const graph = {
|
|
49286
|
+
originNodeId: value.originNodeId,
|
|
49287
|
+
nodes: value.nodes,
|
|
49288
|
+
edges: value.edges,
|
|
49289
|
+
presentation: value.presentation
|
|
49290
|
+
};
|
|
47904
49291
|
if (Buffer.byteLength(JSON.stringify(graph), "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
47905
49292
|
context.addIssue({
|
|
47906
49293
|
code: "custom",
|
|
@@ -47935,6 +49322,10 @@ var agentCommandInputSchemas = {
|
|
|
47935
49322
|
cursor: external_exports.string().min(1).max(512).optional(),
|
|
47936
49323
|
limit: external_exports.number().int().min(1).max(MAX_COMMENT_WATCH_LIMIT)
|
|
47937
49324
|
}).strict(),
|
|
49325
|
+
"comment.watch.activate": external_exports.object({ taskId: external_exports.uuid() }).strict(),
|
|
49326
|
+
"comment.watch.verify": commentWatchTaskFenceSchema,
|
|
49327
|
+
"comment.watch.reserveWrite": commentWatchLeaseSchema.extend({ writeKey: external_exports.string().regex(/^[^/\s]+\/[^/\s]+$/) }).strict(),
|
|
49328
|
+
"comment.watch.releaseWrite": commentWatchLeaseSchema,
|
|
47938
49329
|
"comment.create": commentCreateInputSchema,
|
|
47939
49330
|
"comment.get": external_exports.object({ uri: commentUri, live: external_exports.boolean().default(false) }).strict(),
|
|
47940
49331
|
"comment.reply": external_exports.object({ uri: commentUri, reply: commentReplyInputSchema }).strict(),
|
|
@@ -48790,7 +50181,22 @@ async function startServer(service, options = {}) {
|
|
|
48790
50181
|
});
|
|
48791
50182
|
}
|
|
48792
50183
|
);
|
|
48793
|
-
server.on("error",
|
|
50184
|
+
server.on("error", (error51) => {
|
|
50185
|
+
if (error51.code !== "EADDRINUSE" || (options.port ?? 0) === 0) {
|
|
50186
|
+
reject(error51);
|
|
50187
|
+
return;
|
|
50188
|
+
}
|
|
50189
|
+
reject(
|
|
50190
|
+
new RvwError("PROCESS_FAILED", `port ${options.port}\u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002`, {
|
|
50191
|
+
cause: error51,
|
|
50192
|
+
details: { port: options.port, reason: "address-in-use" },
|
|
50193
|
+
suggestions: [
|
|
50194
|
+
"\u8D77\u52D5\u4E2D\u306Eprocess\u3092\u505C\u6B62\u3059\u308B\u304B\u3001\u5225\u306E--port\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
50195
|
+
"\u4E00\u6642\u7684\u306B\u7A7A\u304Dport\u3092\u81EA\u52D5\u9078\u629E\u3059\u308B\u5834\u5408\u306F--port 0\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
50196
|
+
]
|
|
50197
|
+
})
|
|
50198
|
+
);
|
|
50199
|
+
});
|
|
48794
50200
|
});
|
|
48795
50201
|
}
|
|
48796
50202
|
|
|
@@ -48811,7 +50217,7 @@ import os4 from "node:os";
|
|
|
48811
50217
|
import path9 from "node:path";
|
|
48812
50218
|
var MAX_CLI_STDIN_BYTES = 40 * 1024 * 1024;
|
|
48813
50219
|
var MAX_AGENT_MESSAGE_BYTES = MAX_CLI_STDIN_BYTES + 64 * 1024;
|
|
48814
|
-
var AGENT_SOCKET_PROTOCOL_VERSION =
|
|
50220
|
+
var AGENT_SOCKET_PROTOCOL_VERSION = 5;
|
|
48815
50221
|
var RUNTIME_VIEWER_OPEN_OPERATION = "viewer.open";
|
|
48816
50222
|
var AGENT_SOCKET_RESTART_SUGGESTION = "\u8D77\u52D5\u4E2D\u306Ervw viewer\u3092\u505C\u6B62\u3057\u3001\u66F4\u65B0\u5F8C\u306Ervw open\u3067\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
48817
50223
|
var DEFAULT_CONNECT_TIMEOUT_MS = 2e3;
|
|
@@ -48976,6 +50382,27 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
|
|
|
48976
50382
|
const input = parseOperationInput("comment.watch", request.input);
|
|
48977
50383
|
return service.listCommentPostEvents(input.cursor, input.limit);
|
|
48978
50384
|
}
|
|
50385
|
+
case "comment.watch.activate": {
|
|
50386
|
+
const input = parseOperationInput("comment.watch.activate", request.input);
|
|
50387
|
+
return service.activateCommentWatchTask(input.taskId);
|
|
50388
|
+
}
|
|
50389
|
+
case "comment.watch.verify": {
|
|
50390
|
+
const input = parseOperationInput("comment.watch.verify", request.input);
|
|
50391
|
+
return service.verifyCommentWatchTask(input.taskId, input.generation);
|
|
50392
|
+
}
|
|
50393
|
+
case "comment.watch.reserveWrite": {
|
|
50394
|
+
const input = parseOperationInput("comment.watch.reserveWrite", request.input);
|
|
50395
|
+
return service.reserveCommentWatchWriter(
|
|
50396
|
+
input.taskId,
|
|
50397
|
+
input.generation,
|
|
50398
|
+
input.leaseId,
|
|
50399
|
+
input.writeKey
|
|
50400
|
+
);
|
|
50401
|
+
}
|
|
50402
|
+
case "comment.watch.releaseWrite": {
|
|
50403
|
+
const input = parseOperationInput("comment.watch.releaseWrite", request.input);
|
|
50404
|
+
return service.releaseCommentWatchWriter(input.taskId, input.generation, input.leaseId);
|
|
50405
|
+
}
|
|
48979
50406
|
case "comment.create": {
|
|
48980
50407
|
const input = parseOperationInput("comment.create", request.input);
|
|
48981
50408
|
return await service.createCommentForReference(
|
|
@@ -48999,6 +50426,7 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
|
|
|
48999
50426
|
body: input.edit.body,
|
|
49000
50427
|
...input.edit.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.edit.relatedCommitOid },
|
|
49001
50428
|
...input.edit.references === void 0 ? {} : { references: input.edit.references },
|
|
50429
|
+
...input.edit.watchTask === void 0 ? {} : { watchTask: input.edit.watchTask },
|
|
49002
50430
|
lastModifiedBy: "agent"
|
|
49003
50431
|
});
|
|
49004
50432
|
}
|
|
@@ -50080,6 +51508,10 @@ function writeJson(value) {
|
|
|
50080
51508
|
process.stdout.write(`${JSON.stringify(value)}
|
|
50081
51509
|
`);
|
|
50082
51510
|
}
|
|
51511
|
+
function structureAuthoringFeedback(structure) {
|
|
51512
|
+
const layout = projectTopologyStructure(structure).diagnostics;
|
|
51513
|
+
return { layout, warnings: structureAuthoringWarnings(layout) };
|
|
51514
|
+
}
|
|
50083
51515
|
function writeJsonSequence(value) {
|
|
50084
51516
|
process.stdout.write(`${JSON.stringify(value)}
|
|
50085
51517
|
`);
|
|
@@ -50284,12 +51716,12 @@ function staticDirectory() {
|
|
|
50284
51716
|
];
|
|
50285
51717
|
return candidates.find((candidate) => existsSync6(candidate)) ?? candidates[0];
|
|
50286
51718
|
}
|
|
50287
|
-
function forkOpenWorker(reference, port) {
|
|
51719
|
+
function forkOpenWorker(reference, port, requestedPort) {
|
|
50288
51720
|
const modulePath = process.argv[1];
|
|
50289
51721
|
if (!modulePath) {
|
|
50290
51722
|
throw new RvwError("PROCESS_FAILED", "rvw CLI\u306E\u5B9F\u884Cpath\u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002");
|
|
50291
51723
|
}
|
|
50292
|
-
const args = ["__open-worker", "--port", String(port)];
|
|
51724
|
+
const args = ["__open-worker", "--port", String(port), "--requested-port", String(requestedPort)];
|
|
50293
51725
|
if (reference !== void 0) args.push("--reference", reference);
|
|
50294
51726
|
return fork(path10.resolve(modulePath), args, {
|
|
50295
51727
|
cwd: process.cwd(),
|
|
@@ -50299,10 +51731,12 @@ function forkOpenWorker(reference, port) {
|
|
|
50299
51731
|
});
|
|
50300
51732
|
}
|
|
50301
51733
|
async function startBackgroundOpen(reference, port, dependencies = {}) {
|
|
51734
|
+
const startupPort = port ?? DEFAULT_VIEWER_PORT;
|
|
51735
|
+
const requestedPort = port ?? 0;
|
|
50302
51736
|
const input = {
|
|
50303
51737
|
...reference === void 0 ? {} : { reference },
|
|
50304
51738
|
cwd: process.cwd(),
|
|
50305
|
-
requestedPort
|
|
51739
|
+
requestedPort
|
|
50306
51740
|
};
|
|
50307
51741
|
const launchBrowser = dependencies.launchBrowser ?? (async (url2) => await open_default(url2));
|
|
50308
51742
|
let existing = null;
|
|
@@ -50322,7 +51756,7 @@ async function startBackgroundOpen(reference, port, dependencies = {}) {
|
|
|
50322
51756
|
{ details: existing.details }
|
|
50323
51757
|
);
|
|
50324
51758
|
}
|
|
50325
|
-
const child = (dependencies.forkWorker ?? forkOpenWorker)(reference,
|
|
51759
|
+
const child = (dependencies.forkWorker ?? forkOpenWorker)(reference, startupPort, requestedPort);
|
|
50326
51760
|
return await completeBackgroundOpen(child, launchBrowser);
|
|
50327
51761
|
}
|
|
50328
51762
|
async function sendOpenWorkerMessage(message) {
|
|
@@ -50515,6 +51949,8 @@ async function waitForWorkerParentDisconnect() {
|
|
|
50515
51949
|
await new Promise((resolve) => process.once("disconnect", resolve));
|
|
50516
51950
|
}
|
|
50517
51951
|
async function runOpenServer(runtimeFactory, reference, port, openAutomatically, useAgentSocket, reuseExisting) {
|
|
51952
|
+
const startupPort = port ?? DEFAULT_VIEWER_PORT;
|
|
51953
|
+
const requestedPort = port ?? 0;
|
|
50518
51954
|
let activeRuntime;
|
|
50519
51955
|
let running;
|
|
50520
51956
|
let agentSocket;
|
|
@@ -50523,7 +51959,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
|
|
|
50523
51959
|
const databaseFilePath = databasePathConfiguration().filePath;
|
|
50524
51960
|
if (reuseExisting) {
|
|
50525
51961
|
const startup = await acquireRuntimeOrReuseExisting(
|
|
50526
|
-
runtimeViewerOpenInput(reference, process.cwd(),
|
|
51962
|
+
runtimeViewerOpenInput(reference, process.cwd(), requestedPort),
|
|
50527
51963
|
databaseFilePath
|
|
50528
51964
|
);
|
|
50529
51965
|
if (startup.kind === "reused") {
|
|
@@ -50552,7 +51988,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
|
|
|
50552
51988
|
activeRuntime = runtimeFactory();
|
|
50553
51989
|
const opened = await activeRuntime.service.openPullRequest(reference, process.cwd());
|
|
50554
51990
|
running = await startServer(activeRuntime.service, {
|
|
50555
|
-
port,
|
|
51991
|
+
port: startupPort,
|
|
50556
51992
|
staticDirectory: staticDirectory(),
|
|
50557
51993
|
autoCloseWhenNoViewers: openAutomatically
|
|
50558
51994
|
});
|
|
@@ -50570,7 +52006,7 @@ async function runOpenServer(runtimeFactory, reference, port, openAutomatically,
|
|
|
50570
52006
|
await closeOwnedRuntime(agentSocket, running, activeRuntime);
|
|
50571
52007
|
}
|
|
50572
52008
|
}
|
|
50573
|
-
async function runOpenWorker(runtimeFactory, reference, port) {
|
|
52009
|
+
async function runOpenWorker(runtimeFactory, reference, port, requestedPort) {
|
|
50574
52010
|
let activeRuntime;
|
|
50575
52011
|
let running;
|
|
50576
52012
|
let agentSocket;
|
|
@@ -50580,7 +52016,7 @@ async function runOpenWorker(runtimeFactory, reference, port) {
|
|
|
50580
52016
|
}
|
|
50581
52017
|
const databaseFilePath = databasePathConfiguration().filePath;
|
|
50582
52018
|
const startup = await acquireRuntimeOrReuseExisting(
|
|
50583
|
-
runtimeViewerOpenInput(reference, process.cwd(),
|
|
52019
|
+
runtimeViewerOpenInput(reference, process.cwd(), requestedPort),
|
|
50584
52020
|
databaseFilePath
|
|
50585
52021
|
);
|
|
50586
52022
|
if (startup.kind === "reused") {
|
|
@@ -50678,6 +52114,7 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50678
52114
|
"comment.create",
|
|
50679
52115
|
"comment.list",
|
|
50680
52116
|
"comment.watch",
|
|
52117
|
+
"comment.watchOwnership",
|
|
50681
52118
|
"comment.read",
|
|
50682
52119
|
"comment.reply",
|
|
50683
52120
|
"comment.edit",
|
|
@@ -50687,6 +52124,8 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50687
52124
|
"pullRequest.sync",
|
|
50688
52125
|
"structure.list",
|
|
50689
52126
|
"structure.read",
|
|
52127
|
+
"structure.preview",
|
|
52128
|
+
"structure.presentation",
|
|
50690
52129
|
"structure.publish",
|
|
50691
52130
|
"structure.update",
|
|
50692
52131
|
"structure.delete",
|
|
@@ -50716,7 +52155,7 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50716
52155
|
writeOutput(options, { ok: ok2, ...status }, formatAgentTransportStatus(status));
|
|
50717
52156
|
if (!ok2) process.exitCode = 2;
|
|
50718
52157
|
});
|
|
50719
|
-
program2.command("open").argument("[pull-request]", "PR URL\u307E\u305F\u306F\u756A\u53F7").option("--no-open", "\u30D6\u30E9\u30A6\u30B6\u3092\u958B\u304B\u306A\u3044").option("--foreground", "terminal\u306B\u63A5\u7D9A\u3057\u305F\u307E\u307Eviewer\u3092\u5B9F\u884C").option("--port <port>",
|
|
52158
|
+
program2.command("open").argument("[pull-request]", "PR URL\u307E\u305F\u306F\u756A\u53F7").option("--no-open", "\u30D6\u30E9\u30A6\u30B6\u3092\u958B\u304B\u306A\u3044").option("--foreground", "terminal\u306B\u63A5\u7D9A\u3057\u305F\u307E\u307Eviewer\u3092\u5B9F\u884C").option("--port <port>", `listen port\uFF08\u65E2\u5B9A${DEFAULT_VIEWER_PORT}\u30010\u306F\u81EA\u52D5\uFF09`, parsePort).description("Pull Request\u3092\u958B\u3044\u3066\u30ED\u30FC\u30AB\u30EBviewer\u3092\u8D77\u52D5").action(
|
|
50720
52159
|
async (reference, options) => {
|
|
50721
52160
|
if (options.open && !options.foreground && useAgentSocket) {
|
|
50722
52161
|
const url2 = await startBackgroundOpen(reference, options.port);
|
|
@@ -50734,9 +52173,9 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50734
52173
|
);
|
|
50735
52174
|
}
|
|
50736
52175
|
);
|
|
50737
|
-
program2.command("__open-worker", { hidden: true }).option("--reference <pull-request>").requiredOption("--port <port>", "listen port", parsePort).action(async (options) => {
|
|
52176
|
+
program2.command("__open-worker", { hidden: true }).option("--reference <pull-request>").requiredOption("--port <port>", "listen port", parsePort).requiredOption("--requested-port <port>", "requested listen port", parsePort).action(async (options) => {
|
|
50738
52177
|
try {
|
|
50739
|
-
await runOpenWorker(getRuntime, options.reference, options.port);
|
|
52178
|
+
await runOpenWorker(getRuntime, options.reference, options.port, options.requestedPort);
|
|
50740
52179
|
} catch (error51) {
|
|
50741
52180
|
const rvwError = asRvwError(error51);
|
|
50742
52181
|
const sent = await sendOpenWorkerMessage({
|
|
@@ -50825,6 +52264,10 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50825
52264
|
});
|
|
50826
52265
|
const comment3 = program2.command("comment").description("\u4FDD\u5B58\u6E08\u307F\u30B3\u30E1\u30F3\u30C8\u3092\u64CD\u4F5C");
|
|
50827
52266
|
const structure = program2.command("structure").description("source anchor\u4ED8\u304DStructure\u3092\u7BA1\u7406");
|
|
52267
|
+
structure.command("preview").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure content\u3092\u4FDD\u5B58\u305B\u305Acanonical initial layout\u3067\u691C\u67FB").action(async () => {
|
|
52268
|
+
const content3 = structureContentInputSchema.parse(await readStdinJson());
|
|
52269
|
+
writeJson({ ok: true, ...structureAuthoringFeedback(content3) });
|
|
52270
|
+
});
|
|
50828
52271
|
structure.command("publish").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u3092\u767B\u9332\uFF08viewer\u306F\u958B\u304B\u305Anavigation\u3082\u5909\u66F4\u3057\u306A\u3044\uFF09").action(async () => {
|
|
50829
52272
|
const input = structurePublishInputSchema.parse(await readStdinJson());
|
|
50830
52273
|
const published = await callService(
|
|
@@ -50832,7 +52275,8 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50832
52275
|
input,
|
|
50833
52276
|
async () => await getRuntime().service.publishStructure(input)
|
|
50834
52277
|
);
|
|
50835
|
-
|
|
52278
|
+
const warnings = structureAuthoringFeedback(published).warnings;
|
|
52279
|
+
writeJson({ ok: true, structure: published, ...warnings.length > 0 ? { warnings } : {} });
|
|
50836
52280
|
});
|
|
50837
52281
|
structure.command("get").argument("<structure-uri>").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u306E\u73FE\u5728\u5185\u5BB9\u3092\u53D6\u5F97").action(async (uri) => {
|
|
50838
52282
|
const result = await callService(
|
|
@@ -50857,7 +52301,8 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
50857
52301
|
{ uri, content: content3 },
|
|
50858
52302
|
async () => await getRuntime().service.updateStructure(uri, content3)
|
|
50859
52303
|
);
|
|
50860
|
-
|
|
52304
|
+
const warnings = structureAuthoringFeedback(updated).warnings;
|
|
52305
|
+
writeJson({ ok: true, structure: updated, ...warnings.length > 0 ? { warnings } : {} });
|
|
50861
52306
|
});
|
|
50862
52307
|
structure.command("delete").argument("<structure-uri>").option("--yes", "\u4E0D\u53EF\u9006\u306A\u524A\u9664\u3092\u78BA\u8A8D").option("--expected-updated-at <timestamp>", "preview\u3067\u53D6\u5F97\u3057\u305FupdatedAt").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u3092\u524A\u9664").action(
|
|
50863
52308
|
async (uri, options) => {
|
|
@@ -51018,6 +52463,66 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
51018
52463
|
process.off("SIGTERM", stop);
|
|
51019
52464
|
}
|
|
51020
52465
|
});
|
|
52466
|
+
const watchTask = comment3.command("watch-task").description("comment watch task\u306Eshared ownership\u3092\u7BA1\u7406");
|
|
52467
|
+
watchTask.command("activate").requiredOption("--task-id <task-id>", "\u65B0\u3057\u3044logical watch task ID").requiredOption("--json", "JSON\u3067\u51FA\u529B").action(async (options) => {
|
|
52468
|
+
const input = { taskId: external_exports.uuid().parse(options.taskId) };
|
|
52469
|
+
const result = await callService(
|
|
52470
|
+
"comment.watch.activate",
|
|
52471
|
+
input,
|
|
52472
|
+
() => getRuntime().service.activateCommentWatchTask(input.taskId)
|
|
52473
|
+
);
|
|
52474
|
+
writeJson({ ok: true, ...result });
|
|
52475
|
+
});
|
|
52476
|
+
watchTask.command("verify").requiredOption("--task-id <task-id>", "logical watch task ID").requiredOption("--generation <generation>", "watch generation").requiredOption("--json", "JSON\u3067\u51FA\u529B").action(async (options) => {
|
|
52477
|
+
const input = {
|
|
52478
|
+
taskId: external_exports.uuid().parse(options.taskId),
|
|
52479
|
+
generation: external_exports.coerce.number().int().positive().parse(options.generation)
|
|
52480
|
+
};
|
|
52481
|
+
const result = await callService(
|
|
52482
|
+
"comment.watch.verify",
|
|
52483
|
+
input,
|
|
52484
|
+
() => getRuntime().service.verifyCommentWatchTask(input.taskId, input.generation)
|
|
52485
|
+
);
|
|
52486
|
+
writeJson({ ok: true, ...result });
|
|
52487
|
+
});
|
|
52488
|
+
watchTask.command("reserve-write").requiredOption("--task-id <task-id>", "logical watch task ID").requiredOption("--generation <generation>", "watch generation").requiredOption("--lease-id <lease-id>", "task-local batch lease ID").requiredOption("--write-key <owner-repository>", "\u5171\u6709\u3059\u308Bowner/repository writer key").requiredOption("--json", "JSON\u3067\u51FA\u529B").action(
|
|
52489
|
+
async (options) => {
|
|
52490
|
+
const input = {
|
|
52491
|
+
taskId: external_exports.uuid().parse(options.taskId),
|
|
52492
|
+
generation: external_exports.coerce.number().int().positive().parse(options.generation),
|
|
52493
|
+
leaseId: external_exports.uuid().parse(options.leaseId),
|
|
52494
|
+
writeKey: external_exports.string().regex(/^[^/\s]+\/[^/\s]+$/).parse(options.writeKey.toLowerCase())
|
|
52495
|
+
};
|
|
52496
|
+
const result = await callService(
|
|
52497
|
+
"comment.watch.reserveWrite",
|
|
52498
|
+
input,
|
|
52499
|
+
() => getRuntime().service.reserveCommentWatchWriter(
|
|
52500
|
+
input.taskId,
|
|
52501
|
+
input.generation,
|
|
52502
|
+
input.leaseId,
|
|
52503
|
+
input.writeKey
|
|
52504
|
+
)
|
|
52505
|
+
);
|
|
52506
|
+
writeJson({ ok: true, ...result });
|
|
52507
|
+
}
|
|
52508
|
+
);
|
|
52509
|
+
watchTask.command("release-write").requiredOption("--task-id <task-id>", "logical watch task ID").requiredOption("--generation <generation>", "watch generation").requiredOption("--lease-id <lease-id>", "task-local batch lease ID").requiredOption("--json", "JSON\u3067\u51FA\u529B").action(async (options) => {
|
|
52510
|
+
const input = {
|
|
52511
|
+
taskId: external_exports.uuid().parse(options.taskId),
|
|
52512
|
+
generation: external_exports.coerce.number().int().positive().parse(options.generation),
|
|
52513
|
+
leaseId: external_exports.uuid().parse(options.leaseId)
|
|
52514
|
+
};
|
|
52515
|
+
const result = await callService(
|
|
52516
|
+
"comment.watch.releaseWrite",
|
|
52517
|
+
input,
|
|
52518
|
+
() => getRuntime().service.releaseCommentWatchWriter(
|
|
52519
|
+
input.taskId,
|
|
52520
|
+
input.generation,
|
|
52521
|
+
input.leaseId
|
|
52522
|
+
)
|
|
52523
|
+
);
|
|
52524
|
+
writeJson({ ok: true, ...result });
|
|
52525
|
+
});
|
|
51021
52526
|
comment3.command("create").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("\u767B\u9332\u6E08\u307FPR\u3078\u672A\u89E3\u6C7A\u30B3\u30E1\u30F3\u30C8\u3092\u4E00\u4EF6\u4F5C\u6210").action(async () => {
|
|
51022
52527
|
const input = commentCreateInputSchema.parse(await readStdinJson());
|
|
51023
52528
|
const request = {
|
|
@@ -51069,7 +52574,8 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
51069
52574
|
...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel },
|
|
51070
52575
|
...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
|
|
51071
52576
|
...input.references === void 0 ? {} : { references: input.references },
|
|
51072
|
-
...input.idempotencyKey === void 0 ? {} : { idempotencyKey: input.idempotencyKey }
|
|
52577
|
+
...input.idempotencyKey === void 0 ? {} : { idempotencyKey: input.idempotencyKey },
|
|
52578
|
+
...input.watchTask === void 0 ? {} : { watchTask: input.watchTask }
|
|
51073
52579
|
};
|
|
51074
52580
|
const post = await callService(
|
|
51075
52581
|
"comment.reply",
|
|
@@ -51086,7 +52592,8 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
51086
52592
|
const edit = {
|
|
51087
52593
|
body: input.body,
|
|
51088
52594
|
...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
|
|
51089
|
-
...input.references === void 0 ? {} : { references: input.references }
|
|
52595
|
+
...input.references === void 0 ? {} : { references: input.references },
|
|
52596
|
+
...input.watchTask === void 0 ? {} : { watchTask: input.watchTask }
|
|
51090
52597
|
};
|
|
51091
52598
|
const post = await callService(
|
|
51092
52599
|
"comment.edit",
|