@plannotator/opencode 0.27.10 → 0.27.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/embedded.js +543 -250
- package/package.json +1 -1
- package/plannotator.html +132 -132
- package/review-editor.html +2 -2
package/dist/embedded.js
CHANGED
|
@@ -443,6 +443,13 @@ function resolveAnnotateHistory(config) {
|
|
|
443
443
|
}
|
|
444
444
|
return coerceConfigBoolean(config.annotateHistory, true);
|
|
445
445
|
}
|
|
446
|
+
function resolveFeedbackHistory(config) {
|
|
447
|
+
const envVal = process.env.PLANNOTATOR_FEEDBACK_HISTORY;
|
|
448
|
+
if (envVal !== undefined) {
|
|
449
|
+
return envVal === "1" || envVal.toLowerCase() === "true";
|
|
450
|
+
}
|
|
451
|
+
return coerceConfigBoolean(config.feedbackHistory, true);
|
|
452
|
+
}
|
|
446
453
|
function resolveGuideHistory(config) {
|
|
447
454
|
const envVal = process.env.PLANNOTATOR_GUIDE_HISTORY;
|
|
448
455
|
if (envVal !== undefined) {
|
|
@@ -2045,14 +2052,210 @@ var init_config2 = __esm(() => {
|
|
|
2045
2052
|
init_config();
|
|
2046
2053
|
});
|
|
2047
2054
|
|
|
2048
|
-
// ../../packages/shared/
|
|
2055
|
+
// ../../packages/shared/feedback-archive.ts
|
|
2056
|
+
import { appendFileSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
2049
2057
|
import { join as join7 } from "path";
|
|
2058
|
+
function normalizeFeedbackProject(project2) {
|
|
2059
|
+
if (!project2)
|
|
2060
|
+
return "_unknown";
|
|
2061
|
+
if (project2 === "_unknown")
|
|
2062
|
+
return project2;
|
|
2063
|
+
return sanitizeTag(project2) ?? "_unknown";
|
|
2064
|
+
}
|
|
2065
|
+
function deriveFeedbackProject(cwd) {
|
|
2066
|
+
if (!cwd)
|
|
2067
|
+
return "_unknown";
|
|
2068
|
+
return extractDirName(cwd) ?? extractRepoName(cwd) ?? "_unknown";
|
|
2069
|
+
}
|
|
2070
|
+
function feedbackProjectDir(project2) {
|
|
2071
|
+
return join7(getPlannotatorDataDir(), "feedback", normalizeFeedbackProject(project2));
|
|
2072
|
+
}
|
|
2073
|
+
function stamp(now) {
|
|
2074
|
+
return now.toISOString().replace(/[:.]/g, "-");
|
|
2075
|
+
}
|
|
2076
|
+
function asString(value) {
|
|
2077
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
2078
|
+
}
|
|
2079
|
+
function asNumber(value) {
|
|
2080
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
2081
|
+
}
|
|
2082
|
+
function normalizeAnnotation(raw) {
|
|
2083
|
+
if (typeof raw !== "object" || raw === null)
|
|
2084
|
+
return {};
|
|
2085
|
+
const a = raw;
|
|
2086
|
+
const record = {};
|
|
2087
|
+
const id = asString(a.id);
|
|
2088
|
+
if (id)
|
|
2089
|
+
record.id = id;
|
|
2090
|
+
const type = asString(a.type);
|
|
2091
|
+
if (type)
|
|
2092
|
+
record.type = type;
|
|
2093
|
+
const text = asString(a.text);
|
|
2094
|
+
if (text)
|
|
2095
|
+
record.text = text;
|
|
2096
|
+
const originalText = asString(a.originalText) ?? asString(a.selectedText) ?? asString(a.tokenText);
|
|
2097
|
+
if (originalText)
|
|
2098
|
+
record.originalText = originalText;
|
|
2099
|
+
const file = asString(a.filePath) ?? asString(a.file);
|
|
2100
|
+
if (file)
|
|
2101
|
+
record.file = file;
|
|
2102
|
+
const lineStart = asNumber(a.lineStart);
|
|
2103
|
+
if (lineStart !== undefined)
|
|
2104
|
+
record.lineStart = lineStart;
|
|
2105
|
+
const lineEnd = asNumber(a.lineEnd);
|
|
2106
|
+
if (lineEnd !== undefined)
|
|
2107
|
+
record.lineEnd = lineEnd;
|
|
2108
|
+
const side = asString(a.side);
|
|
2109
|
+
if (side)
|
|
2110
|
+
record.side = side;
|
|
2111
|
+
const blockId = asString(a.blockId);
|
|
2112
|
+
if (blockId)
|
|
2113
|
+
record.blockId = blockId;
|
|
2114
|
+
const diffContext = asString(a.diffContext);
|
|
2115
|
+
if (diffContext)
|
|
2116
|
+
record.diffContext = diffContext;
|
|
2117
|
+
const severity = asString(a.severity);
|
|
2118
|
+
if (severity)
|
|
2119
|
+
record.severity = severity;
|
|
2120
|
+
const inReplyTo = asString(a.inReplyTo);
|
|
2121
|
+
if (inReplyTo)
|
|
2122
|
+
record.inReplyTo = inReplyTo;
|
|
2123
|
+
const source = asString(a.source);
|
|
2124
|
+
if (source)
|
|
2125
|
+
record.source = source;
|
|
2126
|
+
const author = asString(a.author);
|
|
2127
|
+
if (author)
|
|
2128
|
+
record.author = author;
|
|
2129
|
+
if (Array.isArray(a.images) && a.images.length > 0)
|
|
2130
|
+
record.images = a.images.length;
|
|
2131
|
+
return record;
|
|
2132
|
+
}
|
|
2133
|
+
function renderFeedbackRecordMarkdown(record) {
|
|
2134
|
+
const lines = [`# ${SURFACE_TITLES[record.surface] ?? "Feedback"}`, ""];
|
|
2135
|
+
lines.push(`- Submitted: ${record.ts}`);
|
|
2136
|
+
lines.push(`- Surface: ${record.surface}`);
|
|
2137
|
+
lines.push(`- Decision: ${record.decision}`);
|
|
2138
|
+
lines.push(`- Project: ${record.project}`);
|
|
2139
|
+
if (record.origin)
|
|
2140
|
+
lines.push(`- Origin: ${record.origin}`);
|
|
2141
|
+
const target = record.target;
|
|
2142
|
+
if (target?.filePath)
|
|
2143
|
+
lines.push(`- File: ${target.filePath}`);
|
|
2144
|
+
if (target?.url)
|
|
2145
|
+
lines.push(`- URL: ${target.url}`);
|
|
2146
|
+
if (target?.slug) {
|
|
2147
|
+
lines.push(`- Plan: ${target.slug}${target.planVersion ? ` (version ${target.planVersion})` : ""}`);
|
|
2148
|
+
}
|
|
2149
|
+
if (target?.planVersionFile)
|
|
2150
|
+
lines.push(`- Plan version file: ${target.planVersionFile}`);
|
|
2151
|
+
const review = target?.review;
|
|
2152
|
+
if (review) {
|
|
2153
|
+
const bits = [review.diffType, review.base ? `base ${review.base}` : null, review.gitRef ? `ref ${review.gitRef}` : null].filter(Boolean).join(", ");
|
|
2154
|
+
if (bits)
|
|
2155
|
+
lines.push(`- Diff: ${bits}`);
|
|
2156
|
+
if (review.cwd)
|
|
2157
|
+
lines.push(`- Repository: ${review.cwd}`);
|
|
2158
|
+
if (review.pr)
|
|
2159
|
+
lines.push(`- Pull request: ${review.pr.provider} ${review.pr.repo}#${review.pr.number}`);
|
|
2160
|
+
}
|
|
2161
|
+
lines.push(`- Annotations: ${record.counts.annotations}${record.counts.external > 0 ? ` (${record.counts.external} external)` : ""}`);
|
|
2162
|
+
lines.push("", "---", "");
|
|
2163
|
+
lines.push(record.feedback && record.feedback.trim() ? record.feedback : "_No feedback text submitted._");
|
|
2164
|
+
lines.push("");
|
|
2165
|
+
return lines.join(`
|
|
2166
|
+
`);
|
|
2167
|
+
}
|
|
2168
|
+
function appendFeedbackRecord(input) {
|
|
2169
|
+
try {
|
|
2170
|
+
const now = input.now ?? new Date;
|
|
2171
|
+
const project2 = normalizeFeedbackProject(input.project);
|
|
2172
|
+
const feedback = typeof input.feedback === "string" ? input.feedback : "";
|
|
2173
|
+
const rawAnnotations = Array.isArray(input.annotations) ? input.annotations : [];
|
|
2174
|
+
const annotations = rawAnnotations.map(normalizeAnnotation);
|
|
2175
|
+
const counts = {
|
|
2176
|
+
annotations: annotations.length,
|
|
2177
|
+
external: annotations.filter((a) => a.source !== undefined).length,
|
|
2178
|
+
images: annotations.reduce((sum, a) => sum + (a.images ?? 0), 0)
|
|
2179
|
+
};
|
|
2180
|
+
const hasContent = feedback.trim().length > 0 || annotations.length > 0;
|
|
2181
|
+
const record = {
|
|
2182
|
+
v: FEEDBACK_RECORD_VERSION,
|
|
2183
|
+
ts: now.toISOString(),
|
|
2184
|
+
client: FEEDBACK_RECORD_CLIENT,
|
|
2185
|
+
project: project2,
|
|
2186
|
+
...input.origin ? { origin: input.origin } : {},
|
|
2187
|
+
surface: input.surface,
|
|
2188
|
+
decision: input.decision,
|
|
2189
|
+
...input.target ? { target: input.target } : {},
|
|
2190
|
+
...feedback ? { feedback } : {},
|
|
2191
|
+
...annotations.length > 0 ? { annotations } : {},
|
|
2192
|
+
counts
|
|
2193
|
+
};
|
|
2194
|
+
const projectDir = feedbackProjectDir(project2);
|
|
2195
|
+
mkdirSync4(projectDir, { recursive: true });
|
|
2196
|
+
if (hasContent) {
|
|
2197
|
+
const recordsDir = join7(projectDir, "records");
|
|
2198
|
+
mkdirSync4(recordsDir, { recursive: true });
|
|
2199
|
+
const base = `${stamp(now)}-${input.surface}-${input.decision}`;
|
|
2200
|
+
let name = `${base}.md`;
|
|
2201
|
+
const body = renderFeedbackRecordMarkdown(record);
|
|
2202
|
+
for (let n = 2;; n++) {
|
|
2203
|
+
try {
|
|
2204
|
+
writeFileSync3(join7(recordsDir, name), body, { encoding: "utf-8", flag: "wx" });
|
|
2205
|
+
break;
|
|
2206
|
+
} catch (err) {
|
|
2207
|
+
if (err?.code !== "EEXIST")
|
|
2208
|
+
throw err;
|
|
2209
|
+
if (n > 100) {
|
|
2210
|
+
throw new Error(`sidecar name collision exceeded 100 attempts for ${base}.md (clock stuck or runaway writer)`);
|
|
2211
|
+
}
|
|
2212
|
+
name = `${base}-${n}.md`;
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
record.recordFile = `records/${name}`;
|
|
2216
|
+
}
|
|
2217
|
+
const indexPath = join7(projectDir, "index.jsonl");
|
|
2218
|
+
appendFileSync(indexPath, `${JSON.stringify(record)}
|
|
2219
|
+
`, "utf-8");
|
|
2220
|
+
return indexPath;
|
|
2221
|
+
} catch (error) {
|
|
2222
|
+
console.error(`[plannotator] warning: could not archive submitted feedback (${error instanceof Error ? error.message : String(error)}); keeping the annotation draft as the recovery copy`);
|
|
2223
|
+
return null;
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
function countChangedFiles(patch) {
|
|
2227
|
+
if (!patch)
|
|
2228
|
+
return 0;
|
|
2229
|
+
const files = new Set;
|
|
2230
|
+
const re = /^diff --git a\/(.+?) b\/(.+)$/gm;
|
|
2231
|
+
let match;
|
|
2232
|
+
while ((match = re.exec(patch)) !== null)
|
|
2233
|
+
files.add(match[2]);
|
|
2234
|
+
return files.size;
|
|
2235
|
+
}
|
|
2236
|
+
var FEEDBACK_RECORD_VERSION = 1, FEEDBACK_RECORD_CLIENT = "plannotator", SURFACE_TITLES;
|
|
2237
|
+
var init_feedback_archive = __esm(() => {
|
|
2238
|
+
init_data_dir();
|
|
2239
|
+
init_project();
|
|
2240
|
+
SURFACE_TITLES = {
|
|
2241
|
+
plan: "Plan review feedback",
|
|
2242
|
+
review: "Code review feedback",
|
|
2243
|
+
annotate: "Annotate feedback",
|
|
2244
|
+
"annotate-url": "Annotate feedback (URL)",
|
|
2245
|
+
"annotate-app": "Annotate feedback (live app)",
|
|
2246
|
+
"annotate-last": "Annotate feedback (agent message)",
|
|
2247
|
+
"annotate-folder": "Annotate feedback (folder)"
|
|
2248
|
+
};
|
|
2249
|
+
});
|
|
2250
|
+
|
|
2251
|
+
// ../../packages/shared/improvement-hooks.ts
|
|
2252
|
+
import { join as join8 } from "path";
|
|
2050
2253
|
import { readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
2051
2254
|
function getImprovementHookExpectedPath(hookName) {
|
|
2052
2255
|
const entry = KNOWN_HOOKS[hookName];
|
|
2053
2256
|
if (!entry)
|
|
2054
2257
|
return null;
|
|
2055
|
-
return
|
|
2258
|
+
return join8(HOOKS_BASE_DIR, entry.path);
|
|
2056
2259
|
}
|
|
2057
2260
|
function fileExists2(path) {
|
|
2058
2261
|
try {
|
|
@@ -2079,18 +2282,18 @@ function readImprovementHook(hookName) {
|
|
|
2079
2282
|
const entry = KNOWN_HOOKS[hookName];
|
|
2080
2283
|
if (!entry)
|
|
2081
2284
|
return null;
|
|
2082
|
-
const newPath =
|
|
2285
|
+
const newPath = join8(HOOKS_BASE_DIR, entry.path);
|
|
2083
2286
|
if (fileExists2(newPath)) {
|
|
2084
2287
|
return tryReadHookFile(newPath, hookName);
|
|
2085
2288
|
}
|
|
2086
|
-
const legacyFilePath =
|
|
2289
|
+
const legacyFilePath = join8(LEGACY_BASE_DIR, entry.legacyPath);
|
|
2087
2290
|
return tryReadHookFile(legacyFilePath, hookName);
|
|
2088
2291
|
}
|
|
2089
2292
|
var DATA_DIR2, HOOKS_BASE_DIR, LEGACY_BASE_DIR, MAX_FILE_SIZE, KNOWN_HOOKS;
|
|
2090
2293
|
var init_improvement_hooks = __esm(() => {
|
|
2091
2294
|
init_data_dir();
|
|
2092
2295
|
DATA_DIR2 = getPlannotatorDataDir();
|
|
2093
|
-
HOOKS_BASE_DIR =
|
|
2296
|
+
HOOKS_BASE_DIR = join8(DATA_DIR2, "hooks");
|
|
2094
2297
|
LEGACY_BASE_DIR = DATA_DIR2;
|
|
2095
2298
|
MAX_FILE_SIZE = 50 * 1024;
|
|
2096
2299
|
KNOWN_HOOKS = {
|
|
@@ -2975,7 +3178,7 @@ var init_qr = __esm(() => {
|
|
|
2975
3178
|
});
|
|
2976
3179
|
|
|
2977
3180
|
// ../../packages/server/image.ts
|
|
2978
|
-
import { resolve as resolve4, join as
|
|
3181
|
+
import { resolve as resolve4, join as join9 } from "path";
|
|
2979
3182
|
import { tmpdir } from "os";
|
|
2980
3183
|
function getExtension(filePath) {
|
|
2981
3184
|
const lastDot = filePath.lastIndexOf(".");
|
|
@@ -3023,26 +3226,26 @@ var init_image = __esm(() => {
|
|
|
3023
3226
|
"tif",
|
|
3024
3227
|
"avif"
|
|
3025
3228
|
]);
|
|
3026
|
-
UPLOAD_DIR =
|
|
3229
|
+
UPLOAD_DIR = join9(tmpdir(), "plannotator");
|
|
3027
3230
|
});
|
|
3028
3231
|
|
|
3029
3232
|
// ../../packages/shared/draft.ts
|
|
3030
|
-
import { join as
|
|
3031
|
-
import { mkdirSync as
|
|
3233
|
+
import { join as join10 } from "path";
|
|
3234
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4, readFileSync as readFileSync5, renameSync as renameSync2, unlinkSync as unlinkSync2, existsSync as existsSync7 } from "fs";
|
|
3032
3235
|
import { createHash } from "crypto";
|
|
3033
3236
|
function getDraftDir() {
|
|
3034
|
-
const dir =
|
|
3035
|
-
|
|
3237
|
+
const dir = join10(getPlannotatorDataDir(), "drafts");
|
|
3238
|
+
mkdirSync5(dir, { recursive: true });
|
|
3036
3239
|
return dir;
|
|
3037
3240
|
}
|
|
3038
3241
|
function contentHash(content) {
|
|
3039
3242
|
return createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
3040
3243
|
}
|
|
3041
3244
|
function draftPath(key) {
|
|
3042
|
-
return
|
|
3245
|
+
return join10(getDraftDir(), `${key}.json`);
|
|
3043
3246
|
}
|
|
3044
3247
|
function tombstonePath(key) {
|
|
3045
|
-
return
|
|
3248
|
+
return join10(getDraftDir(), `${key}.deleted.json`);
|
|
3046
3249
|
}
|
|
3047
3250
|
function readGeneration(value) {
|
|
3048
3251
|
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : null;
|
|
@@ -3078,7 +3281,7 @@ function getDraftGeneration(key) {
|
|
|
3078
3281
|
}
|
|
3079
3282
|
function writeTombstoneGeneration(key, draftGeneration) {
|
|
3080
3283
|
const filePath = tombstonePath(key);
|
|
3081
|
-
|
|
3284
|
+
writeFileSync4(filePath, JSON.stringify({ draftGeneration }), "utf-8");
|
|
3082
3285
|
}
|
|
3083
3286
|
function clearTombstone(key) {
|
|
3084
3287
|
const filePath = tombstonePath(key);
|
|
@@ -3099,7 +3302,7 @@ function saveDraft(key, data) {
|
|
|
3099
3302
|
}
|
|
3100
3303
|
const finalPath = draftPath(key);
|
|
3101
3304
|
const tmpPath = `${finalPath}.tmp`;
|
|
3102
|
-
|
|
3305
|
+
writeFileSync4(tmpPath, JSON.stringify(data), "utf-8");
|
|
3103
3306
|
renameSync2(tmpPath, finalPath);
|
|
3104
3307
|
if (draftGeneration === null) {
|
|
3105
3308
|
clearTombstone(key);
|
|
@@ -3196,27 +3399,27 @@ import {
|
|
|
3196
3399
|
closeSync as closeSync2,
|
|
3197
3400
|
existsSync as existsSync8,
|
|
3198
3401
|
fstatSync,
|
|
3199
|
-
mkdirSync as
|
|
3402
|
+
mkdirSync as mkdirSync6,
|
|
3200
3403
|
openSync as openSync2,
|
|
3201
3404
|
readdirSync as readdirSync3,
|
|
3202
3405
|
readFileSync as readFileSync6,
|
|
3203
3406
|
readSync,
|
|
3204
3407
|
realpathSync as realpathSync2,
|
|
3205
3408
|
statSync as statSync5,
|
|
3206
|
-
writeFileSync as
|
|
3409
|
+
writeFileSync as writeFileSync5
|
|
3207
3410
|
} from "fs";
|
|
3208
3411
|
import { homedir as homedir3 } from "os";
|
|
3209
|
-
import { join as
|
|
3412
|
+
import { join as join11 } from "path";
|
|
3210
3413
|
function resolveGlobalSkillRoots() {
|
|
3211
3414
|
const home = process.env.HOME?.trim() || homedir3();
|
|
3212
|
-
const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
3213
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
3214
|
-
const configHome = process.env.XDG_CONFIG_HOME?.trim() ||
|
|
3415
|
+
const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join11(home, ".claude");
|
|
3416
|
+
const codexHome = process.env.CODEX_HOME?.trim() || join11(home, ".codex");
|
|
3417
|
+
const configHome = process.env.XDG_CONFIG_HOME?.trim() || join11(home, ".config");
|
|
3215
3418
|
const candidates = [
|
|
3216
|
-
{ dir:
|
|
3217
|
-
{ dir:
|
|
3218
|
-
{ dir:
|
|
3219
|
-
{ dir:
|
|
3419
|
+
{ dir: join11(claudeHome, "skills"), root: "claude" },
|
|
3420
|
+
{ dir: join11(codexHome, "skills"), root: "codex" },
|
|
3421
|
+
{ dir: join11(home, ".agents", "skills"), root: "universal" },
|
|
3422
|
+
{ dir: join11(configHome, "agents", "skills"), root: "universal" }
|
|
3220
3423
|
];
|
|
3221
3424
|
const seen = new Set;
|
|
3222
3425
|
const roots = [];
|
|
@@ -3236,7 +3439,7 @@ function resolveGlobalSkillRoots() {
|
|
|
3236
3439
|
}
|
|
3237
3440
|
function hasSkillMd(dir) {
|
|
3238
3441
|
try {
|
|
3239
|
-
return statSync5(
|
|
3442
|
+
return statSync5(join11(dir, "SKILL.md")).isFile();
|
|
3240
3443
|
} catch {
|
|
3241
3444
|
return false;
|
|
3242
3445
|
}
|
|
@@ -3256,7 +3459,7 @@ function listSubdirs(dir) {
|
|
|
3256
3459
|
return true;
|
|
3257
3460
|
if (e.isSymbolicLink()) {
|
|
3258
3461
|
try {
|
|
3259
|
-
return statSync5(
|
|
3462
|
+
return statSync5(join11(dir, e.name)).isDirectory();
|
|
3260
3463
|
} catch {
|
|
3261
3464
|
return false;
|
|
3262
3465
|
}
|
|
@@ -3273,7 +3476,7 @@ function discoverSkills() {
|
|
|
3273
3476
|
byName.set(name, {
|
|
3274
3477
|
name,
|
|
3275
3478
|
sourcePath: dir,
|
|
3276
|
-
skillMdPath:
|
|
3479
|
+
skillMdPath: join11(dir, "SKILL.md"),
|
|
3277
3480
|
root
|
|
3278
3481
|
});
|
|
3279
3482
|
};
|
|
@@ -3281,13 +3484,13 @@ function discoverSkills() {
|
|
|
3281
3484
|
if (!existsSync8(rootDir))
|
|
3282
3485
|
continue;
|
|
3283
3486
|
for (const childName of listSubdirs(rootDir)) {
|
|
3284
|
-
const childDir =
|
|
3487
|
+
const childDir = join11(rootDir, childName);
|
|
3285
3488
|
if (hasSkillMd(childDir)) {
|
|
3286
3489
|
add(childDir, root);
|
|
3287
3490
|
continue;
|
|
3288
3491
|
}
|
|
3289
3492
|
for (const grandName of listSubdirs(childDir)) {
|
|
3290
|
-
const grandDir =
|
|
3493
|
+
const grandDir = join11(childDir, grandName);
|
|
3291
3494
|
if (hasSkillMd(grandDir))
|
|
3292
3495
|
add(grandDir, root);
|
|
3293
3496
|
}
|
|
@@ -3438,7 +3641,7 @@ function readReferenceSkillContent(name) {
|
|
|
3438
3641
|
};
|
|
3439
3642
|
}
|
|
3440
3643
|
function readCuratedSkillNames() {
|
|
3441
|
-
const path2 =
|
|
3644
|
+
const path2 = join11(getPlannotatorDataDir(), "review-skills.json");
|
|
3442
3645
|
if (!existsSync8(path2))
|
|
3443
3646
|
return null;
|
|
3444
3647
|
let parsed;
|
|
@@ -3481,8 +3684,8 @@ function enableReviewSkill(name) {
|
|
|
3481
3684
|
current.add(name);
|
|
3482
3685
|
const enabled = [...current];
|
|
3483
3686
|
const dir = getPlannotatorDataDir();
|
|
3484
|
-
|
|
3485
|
-
|
|
3687
|
+
mkdirSync6(dir, { recursive: true });
|
|
3688
|
+
writeFileSync5(join11(dir, "review-skills.json"), JSON.stringify({ version: 1, enabled }, null, 2) + `
|
|
3486
3689
|
`);
|
|
3487
3690
|
return { enabled };
|
|
3488
3691
|
}
|
|
@@ -3554,7 +3757,7 @@ var init_review_skill_loader = __esm(() => {
|
|
|
3554
3757
|
});
|
|
3555
3758
|
|
|
3556
3759
|
// ../../packages/server/shared-handlers.ts
|
|
3557
|
-
import { appendFileSync, mkdirSync as
|
|
3760
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "fs";
|
|
3558
3761
|
import { dirname } from "path";
|
|
3559
3762
|
function normalizeDraftGeneration(value) {
|
|
3560
3763
|
if (typeof value !== "number")
|
|
@@ -3617,7 +3820,7 @@ async function handleUpload(req) {
|
|
|
3617
3820
|
if (!extResult.valid) {
|
|
3618
3821
|
return Response.json({ error: extResult.error }, { status: 400 });
|
|
3619
3822
|
}
|
|
3620
|
-
|
|
3823
|
+
mkdirSync7(UPLOAD_DIR, { recursive: true });
|
|
3621
3824
|
const tempPath = `${UPLOAD_DIR}/${crypto.randomUUID()}.${extResult.ext}`;
|
|
3622
3825
|
await Bun.write(tempPath, file);
|
|
3623
3826
|
return Response.json({ path: tempPath, originalName: file.name });
|
|
@@ -3696,8 +3899,8 @@ function handleFavicon() {
|
|
|
3696
3899
|
});
|
|
3697
3900
|
}
|
|
3698
3901
|
function writeServerReadyMetadata(readyFile, metadata) {
|
|
3699
|
-
|
|
3700
|
-
|
|
3902
|
+
mkdirSync7(dirname(readyFile), { recursive: true });
|
|
3903
|
+
appendFileSync2(readyFile, `${JSON.stringify(metadata)}
|
|
3701
3904
|
`, "utf8");
|
|
3702
3905
|
}
|
|
3703
3906
|
function isCodexDesktopHost(env = process.env) {
|
|
@@ -20458,14 +20661,14 @@ function process2(parentNode) {
|
|
|
20458
20661
|
} else if (node.nodeType === 1) {
|
|
20459
20662
|
replacement = replacementForNode.call(self2, node);
|
|
20460
20663
|
}
|
|
20461
|
-
return
|
|
20664
|
+
return join12(output, replacement);
|
|
20462
20665
|
}, "");
|
|
20463
20666
|
}
|
|
20464
20667
|
function postProcess(output) {
|
|
20465
20668
|
var self2 = this;
|
|
20466
20669
|
this.rules.forEach(function(rule) {
|
|
20467
20670
|
if (typeof rule.append === "function") {
|
|
20468
|
-
output =
|
|
20671
|
+
output = join12(output, rule.append(self2.options));
|
|
20469
20672
|
}
|
|
20470
20673
|
});
|
|
20471
20674
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -20478,7 +20681,7 @@ function replacementForNode(node) {
|
|
|
20478
20681
|
content = content.trim();
|
|
20479
20682
|
return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
|
|
20480
20683
|
}
|
|
20481
|
-
function
|
|
20684
|
+
function join12(output, replacement) {
|
|
20482
20685
|
var s1 = trimTrailingNewlines(output);
|
|
20483
20686
|
var s2 = trimLeadingNewlines(replacement);
|
|
20484
20687
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -21291,9 +21494,9 @@ import {
|
|
|
21291
21494
|
renameSync as renameSync3,
|
|
21292
21495
|
statSync as statSync7,
|
|
21293
21496
|
unlinkSync as unlinkSync3,
|
|
21294
|
-
writeFileSync as
|
|
21497
|
+
writeFileSync as writeFileSync6
|
|
21295
21498
|
} from "fs";
|
|
21296
|
-
import { basename, dirname as dirname2, join as
|
|
21499
|
+
import { basename, dirname as dirname2, join as join13 } from "path";
|
|
21297
21500
|
function hashSourceBytes(bytes) {
|
|
21298
21501
|
return `sha256:${createHash2("sha256").update(bytes).digest("hex")}`;
|
|
21299
21502
|
}
|
|
@@ -21379,7 +21582,7 @@ function resolveFolderSourceFileForSave(filePath, folderPath) {
|
|
|
21379
21582
|
const realParent = realpathSync4(dirname2(candidate));
|
|
21380
21583
|
if (!isWithinProjectRoot(realParent, root2))
|
|
21381
21584
|
return null;
|
|
21382
|
-
const resolvedMissingLeaf =
|
|
21585
|
+
const resolvedMissingLeaf = join13(realParent, basename(candidate));
|
|
21383
21586
|
if (!isWithinProjectRoot(resolvedMissingLeaf, root2))
|
|
21384
21587
|
return null;
|
|
21385
21588
|
return resolvedMissingLeaf;
|
|
@@ -21441,7 +21644,7 @@ function createSourceSaveCapabilityFromText(scope, filePath, text, folderPath) {
|
|
|
21441
21644
|
return enabledSourceSave(scope, real, sourceFileSnapshotFromText(text));
|
|
21442
21645
|
}
|
|
21443
21646
|
const realParent = realpathSync4(dirname2(resolved));
|
|
21444
|
-
return enabledSourceSave(scope,
|
|
21647
|
+
return enabledSourceSave(scope, join13(realParent, basename(resolved)), sourceFileSnapshotFromText(text));
|
|
21445
21648
|
} catch {
|
|
21446
21649
|
return disabledSourceSave("missing-file");
|
|
21447
21650
|
}
|
|
@@ -21534,7 +21737,7 @@ function saveSourceFileAtomic(filePath, text, baseHash, options = {}) {
|
|
|
21534
21737
|
}
|
|
21535
21738
|
try {
|
|
21536
21739
|
const realParent = realpathSync4(dirname2(filePath));
|
|
21537
|
-
filePath =
|
|
21740
|
+
filePath = join13(realParent, basename(filePath));
|
|
21538
21741
|
if (allowedRoot && !isWithinProjectRoot(filePath, allowedRoot)) {
|
|
21539
21742
|
return {
|
|
21540
21743
|
ok: false,
|
|
@@ -21573,9 +21776,9 @@ function saveSourceFileAtomic(filePath, text, baseHash, options = {}) {
|
|
|
21573
21776
|
}
|
|
21574
21777
|
const output = applySourceEolPolicy(text, outputEol);
|
|
21575
21778
|
const dir = dirname2(filePath);
|
|
21576
|
-
const tmp =
|
|
21779
|
+
const tmp = join13(dir, `.plannotator-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}.tmp`);
|
|
21577
21780
|
try {
|
|
21578
|
-
|
|
21781
|
+
writeFileSync6(tmp, output, { encoding: "utf8", mode });
|
|
21579
21782
|
if (mode !== undefined)
|
|
21580
21783
|
chmodSync(tmp, mode);
|
|
21581
21784
|
if (recreateMissingBase) {
|
|
@@ -42529,7 +42732,7 @@ var init_ssr = __esm(() => {
|
|
|
42529
42732
|
// ../../packages/server/reference-handlers.ts
|
|
42530
42733
|
import { existsSync as existsSync10, statSync as statSync8 } from "fs";
|
|
42531
42734
|
import { readdir as readdir2 } from "fs/promises";
|
|
42532
|
-
import { join as
|
|
42735
|
+
import { join as join14, relative as relative2, resolve as resolve6 } from "path";
|
|
42533
42736
|
function getAllowedRootPaths(options) {
|
|
42534
42737
|
const rawRoots = options?.rootPaths?.length ? options.rootPaths : [options?.rootPath ?? process.cwd()];
|
|
42535
42738
|
const roots = [];
|
|
@@ -42945,7 +43148,7 @@ async function walkFileBrowserFiles(dir, root3, state) {
|
|
|
42945
43148
|
for (const entry of entries) {
|
|
42946
43149
|
if (state.truncated)
|
|
42947
43150
|
return;
|
|
42948
|
-
const fullPath =
|
|
43151
|
+
const fullPath = join14(dir, entry.name);
|
|
42949
43152
|
const relativePath = relative2(root3, fullPath).replace(/\\/g, "/");
|
|
42950
43153
|
if (entry.isDirectory()) {
|
|
42951
43154
|
if (isFileBrowserExcludedPath(relativePath))
|
|
@@ -76866,7 +77069,8 @@ class OpenCodeProvider {
|
|
|
76866
77069
|
server = null;
|
|
76867
77070
|
client = null;
|
|
76868
77071
|
startPromise = null;
|
|
76869
|
-
|
|
77072
|
+
exitHandler = null;
|
|
77073
|
+
startEpoch = 0;
|
|
76870
77074
|
constructor(config) {
|
|
76871
77075
|
this.config = config;
|
|
76872
77076
|
}
|
|
@@ -76880,50 +77084,40 @@ class OpenCodeProvider {
|
|
|
76880
77084
|
return this.startPromise;
|
|
76881
77085
|
}
|
|
76882
77086
|
async doStart() {
|
|
76883
|
-
|
|
77087
|
+
const epoch = this.startEpoch;
|
|
76884
77088
|
const { createOpencodeServer: createOpencodeServer2, createOpencodeClient: createOpencodeClient2 } = await getSDK();
|
|
76885
|
-
const
|
|
76886
|
-
|
|
76887
|
-
this.
|
|
76888
|
-
|
|
77089
|
+
const server2 = await createOpencodeServer2({
|
|
77090
|
+
hostname: this.config.hostname ?? "127.0.0.1",
|
|
77091
|
+
port: this.config.port ?? 0,
|
|
77092
|
+
timeout: 15000
|
|
77093
|
+
});
|
|
77094
|
+
const exitHandler = () => {
|
|
77095
|
+
try {
|
|
77096
|
+
server2.close();
|
|
77097
|
+
} catch {}
|
|
77098
|
+
};
|
|
77099
|
+
process.once("exit", exitHandler);
|
|
77100
|
+
const reap = () => {
|
|
77101
|
+
process.removeListener("exit", exitHandler);
|
|
77102
|
+
try {
|
|
77103
|
+
server2.close();
|
|
77104
|
+
} catch {}
|
|
77105
|
+
};
|
|
77106
|
+
if (epoch !== this.startEpoch) {
|
|
77107
|
+
reap();
|
|
77108
|
+
throw new Error("OpenCode provider was disposed during startup.");
|
|
76889
77109
|
}
|
|
76890
77110
|
try {
|
|
76891
|
-
this.
|
|
76892
|
-
|
|
76893
|
-
|
|
76894
|
-
timeout: 15000
|
|
77111
|
+
this.client = createOpencodeClient2({
|
|
77112
|
+
baseUrl: server2.url,
|
|
77113
|
+
directory: this.config.cwd ?? process.cwd()
|
|
76895
77114
|
});
|
|
76896
77115
|
} catch (err) {
|
|
76897
|
-
|
|
76898
|
-
if (this.lastAttachError) {
|
|
76899
|
-
throw new Error(`${this.lastAttachError}
|
|
76900
|
-
Fallback startup also failed: ${spawnMessage}`);
|
|
76901
|
-
}
|
|
77116
|
+
reap();
|
|
76902
77117
|
throw err;
|
|
76903
77118
|
}
|
|
76904
|
-
this.
|
|
76905
|
-
|
|
76906
|
-
directory: this.config.cwd ?? process.cwd()
|
|
76907
|
-
});
|
|
76908
|
-
}
|
|
76909
|
-
async tryAttachExistingServer(createOpencodeClient2) {
|
|
76910
|
-
const cwd = this.config.cwd ?? process.cwd();
|
|
76911
|
-
const baseUrl = `http://${this.config.hostname ?? "127.0.0.1"}:${this.config.port ?? 4096}`;
|
|
76912
|
-
const client3 = createOpencodeClient2({
|
|
76913
|
-
baseUrl,
|
|
76914
|
-
directory: cwd
|
|
76915
|
-
});
|
|
76916
|
-
try {
|
|
76917
|
-
await client3.config.get({
|
|
76918
|
-
throwOnError: true,
|
|
76919
|
-
signal: AbortSignal.timeout(1000)
|
|
76920
|
-
});
|
|
76921
|
-
return client3;
|
|
76922
|
-
} catch (err) {
|
|
76923
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
76924
|
-
this.lastAttachError = `Failed to attach to existing OpenCode server at ${baseUrl}: ${message}`;
|
|
76925
|
-
return null;
|
|
76926
|
-
}
|
|
77119
|
+
this.server = server2;
|
|
77120
|
+
this.exitHandler = exitHandler;
|
|
76927
77121
|
}
|
|
76928
77122
|
getClient() {
|
|
76929
77123
|
if (!this.client) {
|
|
@@ -76985,6 +77179,11 @@ Fallback startup also failed: ${spawnMessage}`);
|
|
|
76985
77179
|
});
|
|
76986
77180
|
}
|
|
76987
77181
|
dispose() {
|
|
77182
|
+
this.startEpoch++;
|
|
77183
|
+
if (this.exitHandler) {
|
|
77184
|
+
process.removeListener("exit", this.exitHandler);
|
|
77185
|
+
this.exitHandler = null;
|
|
77186
|
+
}
|
|
76988
77187
|
if (this.server) {
|
|
76989
77188
|
this.server.close();
|
|
76990
77189
|
this.server = null;
|
|
@@ -77292,17 +77491,17 @@ async function createAIRuntime(options = {}) {
|
|
|
77292
77491
|
}
|
|
77293
77492
|
} catch {}
|
|
77294
77493
|
try {
|
|
77295
|
-
|
|
77494
|
+
await Promise.resolve().then(() => (init_opencode_sdk(), exports_opencode_sdk));
|
|
77296
77495
|
const opencodePath = Bun.which("opencode");
|
|
77297
77496
|
if (opencodePath) {
|
|
77298
77497
|
const provider = await createProvider({
|
|
77299
77498
|
type: "opencode-sdk",
|
|
77300
77499
|
cwd
|
|
77301
77500
|
});
|
|
77302
|
-
|
|
77303
|
-
|
|
77501
|
+
const providerId = registry2.register(provider);
|
|
77502
|
+
if ("fetchModels" in provider) {
|
|
77503
|
+
providerInitializers.set(providerId, createBestEffortOnce(() => provider.fetchModels()));
|
|
77304
77504
|
}
|
|
77305
|
-
registry2.register(provider);
|
|
77306
77505
|
}
|
|
77307
77506
|
} catch {}
|
|
77308
77507
|
const endpoints = createAIEndpoints({
|
|
@@ -77427,6 +77626,26 @@ async function startPlannotatorServer(options) {
|
|
|
77427
77626
|
} else {
|
|
77428
77627
|
decisionPromise = new Promise(() => {});
|
|
77429
77628
|
}
|
|
77629
|
+
const archivePlanDecision = (decision, feedback) => {
|
|
77630
|
+
if (mode === "archive")
|
|
77631
|
+
return;
|
|
77632
|
+
if (!resolveFeedbackHistory(loadConfig()))
|
|
77633
|
+
return;
|
|
77634
|
+
appendFeedbackRecord({
|
|
77635
|
+
project: project2,
|
|
77636
|
+
origin,
|
|
77637
|
+
surface: "plan",
|
|
77638
|
+
decision,
|
|
77639
|
+
target: {
|
|
77640
|
+
slug,
|
|
77641
|
+
...versionInfo.version > 0 ? {
|
|
77642
|
+
planVersion: versionInfo.version,
|
|
77643
|
+
planVersionFile: getPlanVersionPath(project2, slug, versionInfo.version) ?? undefined
|
|
77644
|
+
} : {}
|
|
77645
|
+
},
|
|
77646
|
+
feedback
|
|
77647
|
+
});
|
|
77648
|
+
};
|
|
77430
77649
|
const server2 = await startBunServerOnAvailablePort((port2) => Bun.serve({
|
|
77431
77650
|
hostname: getServerHostname(),
|
|
77432
77651
|
port: port2,
|
|
@@ -77691,6 +77910,7 @@ async function startPlannotatorServer(options) {
|
|
|
77691
77910
|
}
|
|
77692
77911
|
savedPath = saveFinalSnapshot(slug, "approved", plan, annotations, planSaveCustomPath);
|
|
77693
77912
|
}
|
|
77913
|
+
archivePlanDecision(typeof feedback === "string" && feedback.trim() ? "approved-with-notes" : "approved", feedback);
|
|
77694
77914
|
deleteDraft(draftKey, draftGeneration);
|
|
77695
77915
|
const effectivePermissionMode = requestedPermissionMode || permissionMode;
|
|
77696
77916
|
resolveDecision({ approved: true, feedback, savedPath, agentSwitch, permissionMode: effectivePermissionMode });
|
|
@@ -77715,6 +77935,7 @@ async function startPlannotatorServer(options) {
|
|
|
77715
77935
|
saveAnnotations(slug, feedback, planSaveCustomPath);
|
|
77716
77936
|
savedPath = saveFinalSnapshot(slug, "denied", plan, feedback, planSaveCustomPath);
|
|
77717
77937
|
}
|
|
77938
|
+
archivePlanDecision("denied", feedback);
|
|
77718
77939
|
deleteDraft(draftKey, draftGeneration);
|
|
77719
77940
|
resolveDecision({ approved: false, feedback, savedPath });
|
|
77720
77941
|
return Response.json({ ok: true, savedPath });
|
|
@@ -77772,6 +77993,7 @@ var init_server2 = __esm(() => {
|
|
|
77772
77993
|
init_repo();
|
|
77773
77994
|
init_project2();
|
|
77774
77995
|
init_config2();
|
|
77996
|
+
init_feedback_archive();
|
|
77775
77997
|
init_favicon2();
|
|
77776
77998
|
init_improvement_hooks();
|
|
77777
77999
|
init_shared_handlers();
|
|
@@ -80231,7 +80453,7 @@ var init_gitbutler_core = __esm(() => {
|
|
|
80231
80453
|
// ../../packages/shared/vcs-core.ts
|
|
80232
80454
|
import { mkdtemp } from "fs/promises";
|
|
80233
80455
|
import { tmpdir as tmpdir2 } from "os";
|
|
80234
|
-
import { isAbsolute as isAbsolute6, join as
|
|
80456
|
+
import { isAbsolute as isAbsolute6, join as join17, relative as relative6, resolve as resolve11 } from "path";
|
|
80235
80457
|
import { rmSync as rmSync2 } from "fs";
|
|
80236
80458
|
function selectNearestProvider(candidates, cwd) {
|
|
80237
80459
|
if (candidates.length === 0)
|
|
@@ -80612,8 +80834,8 @@ function removeDirectoryBestEffort(path2) {
|
|
|
80612
80834
|
} catch {}
|
|
80613
80835
|
}
|
|
80614
80836
|
async function createSyntheticSnapshot(runtime, sourceCwd, baseCommit, patches) {
|
|
80615
|
-
const tempRoot = await mkdtemp(
|
|
80616
|
-
const snapshotCwd =
|
|
80837
|
+
const tempRoot = await mkdtemp(join17(tmpdir2(), "plannotator-review-snapshot-"));
|
|
80838
|
+
const snapshotCwd = join17(tempRoot, "repo");
|
|
80617
80839
|
const cleanup = () => removeDirectoryBestEffort(tempRoot);
|
|
80618
80840
|
try {
|
|
80619
80841
|
await git(runtime, sourceCwd, ["clone", "--shared", "--no-checkout", "--quiet", "--", sourceCwd, snapshotCwd]);
|
|
@@ -80718,8 +80940,8 @@ async function materializeJjSnapshot(jjRuntime, gitRuntime, options) {
|
|
|
80718
80940
|
const fromRevision = await resolveJjSnapshotEndpoint(jjRuntime, endpoints.from, options.cwd);
|
|
80719
80941
|
const toRevision = await resolveJjSnapshotEndpoint(jjRuntime, endpoints.to, options.cwd);
|
|
80720
80942
|
const filesets = options.includedExtensions.map((extension) => `root-glob-i:"**/*${extension}"`);
|
|
80721
|
-
const tempRoot = await mkdtemp(
|
|
80722
|
-
const snapshotCwd =
|
|
80943
|
+
const tempRoot = await mkdtemp(join17(tmpdir2(), "plannotator-review-jj-snapshot-"));
|
|
80944
|
+
const snapshotCwd = join17(tempRoot, "repo");
|
|
80723
80945
|
const cleanup = () => removeDirectoryBestEffort(tempRoot);
|
|
80724
80946
|
try {
|
|
80725
80947
|
await git(gitRuntime, tempRoot, ["init", "--quiet", "--", snapshotCwd]);
|
|
@@ -81438,9 +81660,9 @@ var init_worktree_pool = () => {};
|
|
|
81438
81660
|
// ../../packages/shared/semantic-diff.ts
|
|
81439
81661
|
import { spawn as spawn4 } from "child_process";
|
|
81440
81662
|
import { createHash as createHash3 } from "crypto";
|
|
81441
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
81663
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9 } from "fs";
|
|
81442
81664
|
import { tmpdir as tmpdir3 } from "os";
|
|
81443
|
-
import { delimiter, join as
|
|
81665
|
+
import { delimiter, join as join18 } from "path";
|
|
81444
81666
|
function defaultRunCommand(command, args, options = {}) {
|
|
81445
81667
|
return new Promise((resolveResult) => {
|
|
81446
81668
|
let settled = false;
|
|
@@ -81531,17 +81753,17 @@ function semBinaryName(platform) {
|
|
|
81531
81753
|
return platform === "win32" ? "sem.exe" : "sem";
|
|
81532
81754
|
}
|
|
81533
81755
|
function getManagedSemBinaryPath(dataDir = getPlannotatorDataDir(), platform = process.platform) {
|
|
81534
|
-
return
|
|
81756
|
+
return join18(dataDir, "vendor", "sem", PLANNOTATOR_SEM_VERSION, semBinaryName(platform));
|
|
81535
81757
|
}
|
|
81536
81758
|
function getSemanticDiffScratchCwd(dataDir = getPlannotatorDataDir()) {
|
|
81537
|
-
const primary =
|
|
81759
|
+
const primary = join18(dataDir, "semantic-diff", "patch-only");
|
|
81538
81760
|
try {
|
|
81539
|
-
|
|
81761
|
+
mkdirSync9(primary, { recursive: true });
|
|
81540
81762
|
return primary;
|
|
81541
81763
|
} catch {
|
|
81542
|
-
const fallback =
|
|
81764
|
+
const fallback = join18(tmpdir3(), "plannotator-semantic-diff");
|
|
81543
81765
|
try {
|
|
81544
|
-
|
|
81766
|
+
mkdirSync9(fallback, { recursive: true });
|
|
81545
81767
|
return fallback;
|
|
81546
81768
|
} catch {
|
|
81547
81769
|
return tmpdir3();
|
|
@@ -81556,7 +81778,7 @@ function pathCandidates(runtime4) {
|
|
|
81556
81778
|
const pathext = (runtime4.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";").map((ext) => ext.trim()).filter(Boolean);
|
|
81557
81779
|
for (const dir of (runtime4.env.PATH || "").split(runtime4.pathDelimiter)) {
|
|
81558
81780
|
for (const ext of pathext) {
|
|
81559
|
-
const candidate =
|
|
81781
|
+
const candidate = join18(dir, `sem${ext.toLowerCase()}`);
|
|
81560
81782
|
if (runtime4.fileExists(candidate)) {
|
|
81561
81783
|
return [{ command: candidate, source: "path", explicit: false }];
|
|
81562
81784
|
}
|
|
@@ -83610,14 +83832,14 @@ var init_call_flow_pack_locks = __esm(() => {
|
|
|
83610
83832
|
import { randomUUID } from "crypto";
|
|
83611
83833
|
import {
|
|
83612
83834
|
closeSync as closeSync4,
|
|
83613
|
-
mkdirSync as
|
|
83835
|
+
mkdirSync as mkdirSync10,
|
|
83614
83836
|
openSync as openSync4,
|
|
83615
83837
|
readFileSync as readFileSync10,
|
|
83616
83838
|
rmSync as rmSync3,
|
|
83617
83839
|
statSync as statSync12,
|
|
83618
|
-
writeFileSync as
|
|
83840
|
+
writeFileSync as writeFileSync7
|
|
83619
83841
|
} from "fs";
|
|
83620
|
-
import { dirname as dirname6, join as
|
|
83842
|
+
import { dirname as dirname6, join as join19 } from "path";
|
|
83621
83843
|
function hasErrorCode(error, code) {
|
|
83622
83844
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
83623
83845
|
}
|
|
@@ -83628,7 +83850,7 @@ function removeOwnedLock(lockPath, token2) {
|
|
|
83628
83850
|
} catch {}
|
|
83629
83851
|
}
|
|
83630
83852
|
async function withCallFlowInstallLock(work, options = {}) {
|
|
83631
|
-
const lockPath = options.lockPath ??
|
|
83853
|
+
const lockPath = options.lockPath ?? join19(getPlannotatorDataDir(), "vendor", "call-flow", ".install.lock");
|
|
83632
83854
|
const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
83633
83855
|
const waitTimeoutMs = options.waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
83634
83856
|
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
@@ -83636,12 +83858,12 @@ async function withCallFlowInstallLock(work, options = {}) {
|
|
|
83636
83858
|
const sleep = options.sleep ?? ((milliseconds) => new Promise((resolve12) => setTimeout(resolve12, milliseconds)));
|
|
83637
83859
|
const token2 = `${process.pid}:${randomUUID()}`;
|
|
83638
83860
|
const deadline = now() + waitTimeoutMs;
|
|
83639
|
-
|
|
83861
|
+
mkdirSync10(dirname6(lockPath), { recursive: true });
|
|
83640
83862
|
while (true) {
|
|
83641
83863
|
try {
|
|
83642
83864
|
const descriptor = openSync4(lockPath, "wx", 384);
|
|
83643
83865
|
try {
|
|
83644
|
-
|
|
83866
|
+
writeFileSync7(descriptor, token2, "utf8");
|
|
83645
83867
|
} finally {
|
|
83646
83868
|
closeSync4(descriptor);
|
|
83647
83869
|
}
|
|
@@ -83961,24 +84183,24 @@ var init_call_flow_types = __esm(() => {
|
|
|
83961
84183
|
|
|
83962
84184
|
// ../../packages/shared/call-flow.ts
|
|
83963
84185
|
import { createHash as createHash4 } from "crypto";
|
|
83964
|
-
import { chmodSync as chmodSync2, cpSync, existsSync as existsSync15, mkdirSync as
|
|
84186
|
+
import { chmodSync as chmodSync2, cpSync, existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync11, readdirSync as readdirSync5, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync13, writeFileSync as writeFileSync8 } from "fs";
|
|
83965
84187
|
import { mkdtemp as mkdtemp2 } from "fs/promises";
|
|
83966
84188
|
import { tmpdir as tmpdir4 } from "os";
|
|
83967
|
-
import { basename as basename7, dirname as dirname7, isAbsolute as isAbsolute7, join as
|
|
84189
|
+
import { basename as basename7, dirname as dirname7, isAbsolute as isAbsolute7, join as join20 } from "path";
|
|
83968
84190
|
import { spawn as spawn5, spawnSync as spawnSync5 } from "child_process";
|
|
83969
84191
|
function getCallFlowManagedRuntimeDir(dataDir = getPlannotatorDataDir()) {
|
|
83970
|
-
return
|
|
84192
|
+
return join20(dataDir, "vendor", "call-flow", `calldiff-${CALLDIFF_VERSION}`);
|
|
83971
84193
|
}
|
|
83972
84194
|
function getCallFlowGrammarCacheDir(runtimeDir) {
|
|
83973
|
-
return
|
|
84195
|
+
return join20(runtimeDir, "grammar-cache");
|
|
83974
84196
|
}
|
|
83975
84197
|
function getLanguagePackageRoot(runtimeDir, language) {
|
|
83976
84198
|
if (language.kind === "core")
|
|
83977
|
-
return
|
|
83978
|
-
return
|
|
84199
|
+
return join20(runtimeDir, "node_modules", "tree-sitter-typescript");
|
|
84200
|
+
return join20(getCallFlowGrammarCacheDir(runtimeDir), "node_modules", ...(language.packageName ?? "").split("/"));
|
|
83979
84201
|
}
|
|
83980
84202
|
function getLanguageLockMarker(runtimeDir, id) {
|
|
83981
|
-
return
|
|
84203
|
+
return join20(getCallFlowGrammarCacheDir(runtimeDir), ".plannotator-locks", `${id}.json`);
|
|
83982
84204
|
}
|
|
83983
84205
|
function packHasCommittedLock(runtimeDir, id) {
|
|
83984
84206
|
try {
|
|
@@ -83990,7 +84212,7 @@ function packHasCommittedLock(runtimeDir, id) {
|
|
|
83990
84212
|
}
|
|
83991
84213
|
function installDirHasCommittedPackLock(installDir, id) {
|
|
83992
84214
|
try {
|
|
83993
|
-
const installed = JSON.parse(readFileSync11(
|
|
84215
|
+
const installed = JSON.parse(readFileSync11(join20(installDir, "package-lock.json"), "utf8"));
|
|
83994
84216
|
return JSON.stringify(installed) === JSON.stringify(CALL_FLOW_PACK_LOCKS[id]);
|
|
83995
84217
|
} catch {
|
|
83996
84218
|
return false;
|
|
@@ -83999,21 +84221,21 @@ function installDirHasCommittedPackLock(installDir, id) {
|
|
|
83999
84221
|
function isLanguageInstalled(runtimeDir, language, managed) {
|
|
84000
84222
|
if (language.kind === "core")
|
|
84001
84223
|
return true;
|
|
84002
|
-
const packageRoot = managed ? getLanguagePackageRoot(runtimeDir, language) :
|
|
84224
|
+
const packageRoot = managed ? getLanguagePackageRoot(runtimeDir, language) : join20(runtimeDir, "node_modules", ...(language.packageName ?? "").split("/"));
|
|
84003
84225
|
if (readPackageVersion(packageRoot) !== language.packageVersion)
|
|
84004
84226
|
return false;
|
|
84005
84227
|
return !managed || packHasCommittedLock(runtimeDir, language.id);
|
|
84006
84228
|
}
|
|
84007
84229
|
function readPackageVersion(packageRoot) {
|
|
84008
84230
|
try {
|
|
84009
|
-
const parsed = JSON.parse(readFileSync11(
|
|
84231
|
+
const parsed = JSON.parse(readFileSync11(join20(packageRoot, "package.json"), "utf8"));
|
|
84010
84232
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
84011
84233
|
} catch {
|
|
84012
84234
|
return null;
|
|
84013
84235
|
}
|
|
84014
84236
|
}
|
|
84015
84237
|
function resolvePackageEntry(packageRoot) {
|
|
84016
|
-
const entry =
|
|
84238
|
+
const entry = join20(packageRoot, "dist", "run.js");
|
|
84017
84239
|
return existsSync15(entry) ? entry : null;
|
|
84018
84240
|
}
|
|
84019
84241
|
function runtimeJson(value) {
|
|
@@ -84022,7 +84244,7 @@ function runtimeJson(value) {
|
|
|
84022
84244
|
}
|
|
84023
84245
|
function hasCommittedRuntimeLock(runtimeDir) {
|
|
84024
84246
|
try {
|
|
84025
|
-
const lock = JSON.parse(readFileSync11(
|
|
84247
|
+
const lock = JSON.parse(readFileSync11(join20(runtimeDir, "package-lock.json"), "utf8"));
|
|
84026
84248
|
return JSON.stringify(lock) === JSON.stringify(package_lock_default);
|
|
84027
84249
|
} catch {
|
|
84028
84250
|
return false;
|
|
@@ -84046,7 +84268,7 @@ function findExecutable(name) {
|
|
|
84046
84268
|
if (!directory)
|
|
84047
84269
|
continue;
|
|
84048
84270
|
for (const extension of extensions) {
|
|
84049
|
-
const candidate =
|
|
84271
|
+
const candidate = join20(directory, `${name}${extension}`);
|
|
84050
84272
|
if (existsSync15(candidate))
|
|
84051
84273
|
return candidate;
|
|
84052
84274
|
}
|
|
@@ -84079,7 +84301,7 @@ async function resolveCallFlowRuntime() {
|
|
|
84079
84301
|
}
|
|
84080
84302
|
const runtimeDir = override ?? getCallFlowManagedRuntimeDir();
|
|
84081
84303
|
const managed = !override;
|
|
84082
|
-
const packageRoot = override ? runtimeDir :
|
|
84304
|
+
const packageRoot = override ? runtimeDir : join20(runtimeDir, "node_modules", "calldiff");
|
|
84083
84305
|
const version = readPackageVersion(packageRoot);
|
|
84084
84306
|
const packageEntry = resolvePackageEntry(packageRoot);
|
|
84085
84307
|
if (!version || !packageEntry) {
|
|
@@ -84093,7 +84315,7 @@ async function resolveCallFlowRuntime() {
|
|
|
84093
84315
|
return { ok: false, reason: "version-mismatch", message: `CallDiff ${version} is installed; Plannotator requires ${CALLDIFF_VERSION}.` };
|
|
84094
84316
|
}
|
|
84095
84317
|
if (!override) {
|
|
84096
|
-
const revisionPath =
|
|
84318
|
+
const revisionPath = join20(runtimeDir, ".calldiff-revision");
|
|
84097
84319
|
const installedRevision = existsSync15(revisionPath) ? readFileSync11(revisionPath, "utf8").trim() : "";
|
|
84098
84320
|
if (installedRevision !== CALLDIFF_COMMIT) {
|
|
84099
84321
|
return { ok: false, reason: "revision-mismatch", message: "The managed Call flow core is stale and needs reinstalling." };
|
|
@@ -84102,7 +84324,7 @@ async function resolveCallFlowRuntime() {
|
|
|
84102
84324
|
return { ok: false, reason: "runtime-lock-mismatch", message: "The managed Call flow core dependency lock is stale and needs reinstalling." };
|
|
84103
84325
|
}
|
|
84104
84326
|
}
|
|
84105
|
-
const invalidCore = CORE_RUNTIME_DEPENDENCIES.filter(({ packageName, version: expected }) => readPackageVersion(
|
|
84327
|
+
const invalidCore = CORE_RUNTIME_DEPENDENCIES.filter(({ packageName, version: expected }) => readPackageVersion(join20(runtimeDir, "node_modules", packageName)) !== expected);
|
|
84106
84328
|
if (invalidCore.length > 0) {
|
|
84107
84329
|
return {
|
|
84108
84330
|
ok: false,
|
|
@@ -84125,8 +84347,8 @@ async function resolveCallFlowRuntime() {
|
|
|
84125
84347
|
};
|
|
84126
84348
|
}
|
|
84127
84349
|
function writeRuntimeManifest(runtimeDir) {
|
|
84128
|
-
|
|
84129
|
-
|
|
84350
|
+
writeFileSync8(join20(runtimeDir, "package.json"), runtimeJson(package_default), "utf8");
|
|
84351
|
+
writeFileSync8(join20(runtimeDir, "package-lock.json"), runtimeJson(package_lock_default), "utf8");
|
|
84130
84352
|
}
|
|
84131
84353
|
function removeDirectoryBestEffort2(path2) {
|
|
84132
84354
|
try {
|
|
@@ -84164,7 +84386,7 @@ async function downloadVerifiedCallDiffArchive(destination, onStage) {
|
|
|
84164
84386
|
if (integrity !== CALLDIFF_SOURCE_INTEGRITY) {
|
|
84165
84387
|
throw new Error("CallDiff source archive failed its repository-pinned SHA-512 check.");
|
|
84166
84388
|
}
|
|
84167
|
-
|
|
84389
|
+
writeFileSync8(destination, Buffer.concat(chunks, totalBytes));
|
|
84168
84390
|
}
|
|
84169
84391
|
async function downloadVerifiedLockArtifacts(lock, destination, onStage) {
|
|
84170
84392
|
const packages = lock.packages;
|
|
@@ -84208,21 +84430,21 @@ async function downloadVerifiedLockArtifacts(lock, destination, onStage) {
|
|
|
84208
84430
|
downloaded.push({ ...spec, bytes: Buffer.concat(chunks, artifactBytes) });
|
|
84209
84431
|
}
|
|
84210
84432
|
onStage("verifying");
|
|
84211
|
-
|
|
84433
|
+
mkdirSync11(destination, { recursive: true });
|
|
84212
84434
|
const verifiedPaths = [];
|
|
84213
84435
|
for (const [index, artifact] of downloaded.entries()) {
|
|
84214
84436
|
const integrity = `sha512-${createHash4("sha512").update(artifact.bytes).digest("base64")}`;
|
|
84215
84437
|
if (integrity !== artifact.integrity) {
|
|
84216
84438
|
throw new Error(`Pinned grammar package failed its repository-owned SHA-512 check: ${artifact.url}`);
|
|
84217
84439
|
}
|
|
84218
|
-
const path2 =
|
|
84219
|
-
|
|
84440
|
+
const path2 = join20(destination, `artifact-${index}.tgz`);
|
|
84441
|
+
writeFileSync8(path2, artifact.bytes);
|
|
84220
84442
|
verifiedPaths.push(path2);
|
|
84221
84443
|
}
|
|
84222
84444
|
return verifiedPaths;
|
|
84223
84445
|
}
|
|
84224
84446
|
async function seedVerifiedNpmCache(npmPath, installDir, artifacts) {
|
|
84225
|
-
const cacheDir =
|
|
84447
|
+
const cacheDir = join20(installDir, ".verified-npm-cache");
|
|
84226
84448
|
for (const artifact of artifacts) {
|
|
84227
84449
|
const cached2 = await runCommand(npmPath, [
|
|
84228
84450
|
"cache",
|
|
@@ -84257,26 +84479,26 @@ function assertPathRemoved(path2, description) {
|
|
|
84257
84479
|
throw new Error(`Call-flow pruning did not remove ${description}.`);
|
|
84258
84480
|
}
|
|
84259
84481
|
function prunePrebuilds(packageRoot) {
|
|
84260
|
-
const prebuilds =
|
|
84482
|
+
const prebuilds = join20(packageRoot, "prebuilds");
|
|
84261
84483
|
if (!existsSync15(prebuilds))
|
|
84262
84484
|
return;
|
|
84263
84485
|
const currentPlatform = `${process.platform}-${process.arch}`;
|
|
84264
84486
|
for (const entry of readdirSync5(prebuilds)) {
|
|
84265
84487
|
if (entry !== currentPlatform)
|
|
84266
|
-
removeDirectoryStrict(
|
|
84488
|
+
removeDirectoryStrict(join20(prebuilds, entry));
|
|
84267
84489
|
}
|
|
84268
84490
|
}
|
|
84269
84491
|
function assertNativePackagePruned(packageRoot) {
|
|
84270
84492
|
for (const directory of PRUNED_PACKAGE_DIRECTORIES) {
|
|
84271
84493
|
if (directory !== "build") {
|
|
84272
|
-
assertPathRemoved(
|
|
84494
|
+
assertPathRemoved(join20(packageRoot, directory), `${basename7(packageRoot)}/${directory}`);
|
|
84273
84495
|
}
|
|
84274
84496
|
}
|
|
84275
|
-
assertPathRemoved(
|
|
84497
|
+
assertPathRemoved(join20(packageRoot, "node_modules"), `${basename7(packageRoot)}/node_modules`);
|
|
84276
84498
|
for (const file of ["binding.gyp", "grammar.js", "tree-sitter.json"]) {
|
|
84277
|
-
assertPathRemoved(
|
|
84499
|
+
assertPathRemoved(join20(packageRoot, file), `${basename7(packageRoot)}/${file}`);
|
|
84278
84500
|
}
|
|
84279
|
-
const prebuilds =
|
|
84501
|
+
const prebuilds = join20(packageRoot, "prebuilds");
|
|
84280
84502
|
if (existsSync15(prebuilds)) {
|
|
84281
84503
|
const currentPlatform = `${process.platform}-${process.arch}`;
|
|
84282
84504
|
const foreign = readdirSync5(prebuilds).filter((entry) => entry !== currentPlatform);
|
|
@@ -84288,7 +84510,7 @@ function assertNativePackagePruned(packageRoot) {
|
|
|
84288
84510
|
if (!existsSync15(directory))
|
|
84289
84511
|
return;
|
|
84290
84512
|
for (const entry of readdirSync5(directory, { withFileTypes: true })) {
|
|
84291
|
-
const path2 =
|
|
84513
|
+
const path2 = join20(directory, entry.name);
|
|
84292
84514
|
if (entry.isDirectory())
|
|
84293
84515
|
assertOnlyNativeAddons(path2);
|
|
84294
84516
|
else if (!entry.isFile() || !entry.name.endsWith(".node")) {
|
|
@@ -84296,8 +84518,8 @@ function assertNativePackagePruned(packageRoot) {
|
|
|
84296
84518
|
}
|
|
84297
84519
|
}
|
|
84298
84520
|
};
|
|
84299
|
-
assertOnlyNativeAddons(
|
|
84300
|
-
const bindings =
|
|
84521
|
+
assertOnlyNativeAddons(join20(packageRoot, "build"));
|
|
84522
|
+
const bindings = join20(packageRoot, "bindings", "node");
|
|
84301
84523
|
if (existsSync15(bindings)) {
|
|
84302
84524
|
const retainedSource = readdirSync5(bindings).find((file) => file === "binding.cc" || file.endsWith("_test.js"));
|
|
84303
84525
|
if (retainedSource)
|
|
@@ -84315,7 +84537,7 @@ function pruneCallFlowNativePackage(packageRoot) {
|
|
|
84315
84537
|
if (!existsSync15(directory))
|
|
84316
84538
|
return;
|
|
84317
84539
|
for (const entry of readdirSync5(directory, { withFileTypes: true })) {
|
|
84318
|
-
const path2 =
|
|
84540
|
+
const path2 = join20(directory, entry.name);
|
|
84319
84541
|
if (entry.isDirectory())
|
|
84320
84542
|
collectBuiltAddons(path2);
|
|
84321
84543
|
else if (entry.isFile() && entry.name.endsWith(".node")) {
|
|
@@ -84323,56 +84545,56 @@ function pruneCallFlowNativePackage(packageRoot) {
|
|
|
84323
84545
|
}
|
|
84324
84546
|
}
|
|
84325
84547
|
};
|
|
84326
|
-
collectBuiltAddons(
|
|
84548
|
+
collectBuiltAddons(join20(packageRoot, "build"));
|
|
84327
84549
|
prunePrebuilds(packageRoot);
|
|
84328
84550
|
for (const directory of PRUNED_PACKAGE_DIRECTORIES) {
|
|
84329
|
-
removeDirectoryStrict(
|
|
84551
|
+
removeDirectoryStrict(join20(packageRoot, directory));
|
|
84330
84552
|
}
|
|
84331
|
-
removeDirectoryStrict(
|
|
84332
|
-
const bindings =
|
|
84553
|
+
removeDirectoryStrict(join20(packageRoot, "node_modules"));
|
|
84554
|
+
const bindings = join20(packageRoot, "bindings", "node");
|
|
84333
84555
|
if (existsSync15(bindings)) {
|
|
84334
84556
|
for (const file of readdirSync5(bindings)) {
|
|
84335
84557
|
if (file === "binding.cc" || file.endsWith("_test.js"))
|
|
84336
|
-
rmSync4(
|
|
84558
|
+
rmSync4(join20(bindings, file), { force: true });
|
|
84337
84559
|
}
|
|
84338
84560
|
}
|
|
84339
84561
|
for (const file of ["binding.gyp", "grammar.js", "tree-sitter.json"]) {
|
|
84340
|
-
rmSync4(
|
|
84562
|
+
rmSync4(join20(packageRoot, file), { force: true });
|
|
84341
84563
|
}
|
|
84342
84564
|
if (builtAddons.length > 0) {
|
|
84343
|
-
const releaseDir =
|
|
84344
|
-
|
|
84565
|
+
const releaseDir = join20(packageRoot, "build", "Release");
|
|
84566
|
+
mkdirSync11(releaseDir, { recursive: true });
|
|
84345
84567
|
for (const addon of builtAddons)
|
|
84346
|
-
|
|
84568
|
+
writeFileSync8(join20(releaseDir, addon.name), addon.bytes);
|
|
84347
84569
|
}
|
|
84348
84570
|
if (existsSync15(packageRoot)) {
|
|
84349
84571
|
for (const file of readdirSync5(packageRoot)) {
|
|
84350
84572
|
if (file.endsWith(".wasm"))
|
|
84351
|
-
rmSync4(
|
|
84573
|
+
rmSync4(join20(packageRoot, file), { force: true });
|
|
84352
84574
|
}
|
|
84353
84575
|
}
|
|
84354
84576
|
assertNativePackagePruned(packageRoot);
|
|
84355
84577
|
}
|
|
84356
84578
|
function pruneCoreRuntime(runtimeDir) {
|
|
84357
84579
|
for (const packageName of ["tree-sitter", ...CORE_GRAMMAR_PACKAGES]) {
|
|
84358
|
-
pruneCallFlowNativePackage(
|
|
84580
|
+
pruneCallFlowNativePackage(join20(runtimeDir, "node_modules", packageName));
|
|
84359
84581
|
}
|
|
84360
|
-
const packageRoot =
|
|
84361
|
-
removeDirectoryStrict(
|
|
84362
|
-
for (const file of readdirSync5(
|
|
84582
|
+
const packageRoot = join20(runtimeDir, "node_modules", "calldiff");
|
|
84583
|
+
removeDirectoryStrict(join20(packageRoot, "src"));
|
|
84584
|
+
for (const file of readdirSync5(join20(packageRoot, "dist"))) {
|
|
84363
84585
|
if (file.startsWith("cli.") || file === "index.js" || file === "index.d.ts") {
|
|
84364
|
-
rmSync4(
|
|
84586
|
+
rmSync4(join20(packageRoot, "dist", file), { force: true });
|
|
84365
84587
|
}
|
|
84366
84588
|
}
|
|
84367
84589
|
for (const packagePath of CORE_PRUNED_PACKAGES) {
|
|
84368
|
-
removeDirectoryStrict(
|
|
84590
|
+
removeDirectoryStrict(join20(runtimeDir, "node_modules", ...packagePath.split("/")));
|
|
84369
84591
|
}
|
|
84370
|
-
removeDirectoryStrict(
|
|
84371
|
-
assertPathRemoved(
|
|
84592
|
+
removeDirectoryStrict(join20(runtimeDir, "node_modules", ".bin"));
|
|
84593
|
+
assertPathRemoved(join20(packageRoot, "src"), "calldiff/src");
|
|
84372
84594
|
for (const packagePath of CORE_PRUNED_PACKAGES) {
|
|
84373
|
-
assertPathRemoved(
|
|
84595
|
+
assertPathRemoved(join20(runtimeDir, "node_modules", ...packagePath.split("/")), `node_modules/${packagePath}`);
|
|
84374
84596
|
}
|
|
84375
|
-
assertPathRemoved(
|
|
84597
|
+
assertPathRemoved(join20(runtimeDir, "node_modules", ".bin"), "node_modules/.bin");
|
|
84376
84598
|
}
|
|
84377
84599
|
function validationFilesForLanguage(id) {
|
|
84378
84600
|
if (id === CALL_FLOW_CORE_LANGUAGE_ID) {
|
|
@@ -84382,7 +84604,7 @@ function validationFilesForLanguage(id) {
|
|
|
84382
84604
|
return [`validation${extension}`];
|
|
84383
84605
|
}
|
|
84384
84606
|
async function validatePrunedLanguage(nodePath, runtimeDir, grammarCacheDir, ids) {
|
|
84385
|
-
const extractEntry =
|
|
84607
|
+
const extractEntry = join20(runtimeDir, "node_modules", "calldiff", "dist", "extract.js");
|
|
84386
84608
|
const script = String.raw`
|
|
84387
84609
|
import { pathToFileURL } from "node:url";
|
|
84388
84610
|
const request = JSON.parse(process.argv[1]);
|
|
@@ -84416,8 +84638,8 @@ for (const file of request.files) mod.extractFunctions(file, "");
|
|
|
84416
84638
|
}
|
|
84417
84639
|
}
|
|
84418
84640
|
function ensureGrammarCacheManifest(cacheDir) {
|
|
84419
|
-
|
|
84420
|
-
|
|
84641
|
+
mkdirSync11(cacheDir, { recursive: true });
|
|
84642
|
+
writeFileSync8(join20(cacheDir, "package.json"), runtimeJson({
|
|
84421
84643
|
name: "plannotator-calldiff-grammar-cache",
|
|
84422
84644
|
private: true
|
|
84423
84645
|
}), "utf8");
|
|
@@ -84431,13 +84653,13 @@ async function preserveValidatedLanguagePacks(nodePath, currentRuntimeDir, candi
|
|
|
84431
84653
|
const packId = language.id;
|
|
84432
84654
|
const currentRoot = getLanguagePackageRoot(currentRuntimeDir, language);
|
|
84433
84655
|
const candidateRoot = getLanguagePackageRoot(candidateRuntimeDir, language);
|
|
84434
|
-
|
|
84656
|
+
mkdirSync11(dirname7(candidateRoot), { recursive: true });
|
|
84435
84657
|
cpSync(currentRoot, candidateRoot, { recursive: true, force: true });
|
|
84436
84658
|
try {
|
|
84437
84659
|
await validatePrunedLanguage(nodePath, candidateRuntimeDir, candidateCache, [language.id]);
|
|
84438
84660
|
const marker = getLanguageLockMarker(candidateRuntimeDir, language.id);
|
|
84439
|
-
|
|
84440
|
-
|
|
84661
|
+
mkdirSync11(dirname7(marker), { recursive: true });
|
|
84662
|
+
writeFileSync8(marker, runtimeJson(CALL_FLOW_PACK_LOCKS[packId]), "utf8");
|
|
84441
84663
|
} catch {
|
|
84442
84664
|
removeDirectoryStrict(candidateRoot);
|
|
84443
84665
|
}
|
|
@@ -84449,7 +84671,7 @@ function measureCallFlowDirectoryBytes(path2) {
|
|
|
84449
84671
|
const stat5 = statSync13(path2);
|
|
84450
84672
|
if (!stat5.isDirectory())
|
|
84451
84673
|
return stat5.size;
|
|
84452
|
-
return readdirSync5(path2).reduce((total, entry) => total + measureCallFlowDirectoryBytes(
|
|
84674
|
+
return readdirSync5(path2).reduce((total, entry) => total + measureCallFlowDirectoryBytes(join20(path2, entry)), 0);
|
|
84453
84675
|
}
|
|
84454
84676
|
async function installCallFlowRuntime(onStage = () => {}) {
|
|
84455
84677
|
return await withCallFlowInstallLock(() => installCallFlowRuntimeUnlocked(onStage));
|
|
@@ -84469,12 +84691,12 @@ async function installCallFlowRuntimeUnlocked(onStage) {
|
|
|
84469
84691
|
return { ok: true, status: "already-installed", runtimeDir, languageId: CALL_FLOW_CORE_LANGUAGE_ID, message: `Call-flow core already installed at ${runtimeDir}.` };
|
|
84470
84692
|
}
|
|
84471
84693
|
const runtimeParent = dirname7(runtimeDir);
|
|
84472
|
-
|
|
84473
|
-
const installDir = await mkdtemp2(
|
|
84694
|
+
mkdirSync11(runtimeParent, { recursive: true });
|
|
84695
|
+
const installDir = await mkdtemp2(join20(runtimeParent, ".calldiff-install-"));
|
|
84474
84696
|
const backupDir = `${runtimeDir}.previous-${process.pid}-${Date.now()}`;
|
|
84475
84697
|
try {
|
|
84476
84698
|
writeRuntimeManifest(installDir);
|
|
84477
|
-
await downloadVerifiedCallDiffArchive(
|
|
84699
|
+
await downloadVerifiedCallDiffArchive(join20(installDir, CALLDIFF_ARCHIVE_FILE), onStage);
|
|
84478
84700
|
onStage("installing-deps");
|
|
84479
84701
|
const install = await runCommand(npmPath, [
|
|
84480
84702
|
"ci",
|
|
@@ -84508,8 +84730,8 @@ async function installCallFlowRuntimeUnlocked(onStage) {
|
|
|
84508
84730
|
throw new Error(rebuild.stderr.trim() || rebuild.stdout.trim() || "grammar rebuild failed");
|
|
84509
84731
|
}
|
|
84510
84732
|
onStage("building");
|
|
84511
|
-
const packageRoot =
|
|
84512
|
-
const tscPath = process.platform === "win32" ?
|
|
84733
|
+
const packageRoot = join20(installDir, "node_modules", "calldiff");
|
|
84734
|
+
const tscPath = process.platform === "win32" ? join20(installDir, "node_modules", ".bin", "tsc.cmd") : join20(installDir, "node_modules", ".bin", "tsc");
|
|
84513
84735
|
const build = await runCommand(tscPath, ["-p", "tsconfig.json"], {
|
|
84514
84736
|
cwd: packageRoot,
|
|
84515
84737
|
timeoutMs: 120000,
|
|
@@ -84518,8 +84740,8 @@ async function installCallFlowRuntimeUnlocked(onStage) {
|
|
|
84518
84740
|
if (build.exitCode !== 0) {
|
|
84519
84741
|
throw new Error(build.stderr.trim() || build.stdout.trim() || "CallDiff TypeScript build failed");
|
|
84520
84742
|
}
|
|
84521
|
-
rmSync4(
|
|
84522
|
-
|
|
84743
|
+
rmSync4(join20(installDir, CALLDIFF_ARCHIVE_FILE), { force: true });
|
|
84744
|
+
writeFileSync8(join20(installDir, ".calldiff-revision"), `${CALLDIFF_COMMIT}
|
|
84523
84745
|
`, "utf8");
|
|
84524
84746
|
if (readPackageVersion(packageRoot) !== CALLDIFF_VERSION || !resolvePackageEntry(packageRoot)) {
|
|
84525
84747
|
throw new Error("The verified CallDiff package did not produce the expected runtime entry.");
|
|
@@ -84588,16 +84810,16 @@ async function installCallFlowLanguagePackUnlocked(id, onStage) {
|
|
|
84588
84810
|
return { ok: true, status: "already-installed", runtimeDir, languageId: id, message: `${language.label} support is already installed.` };
|
|
84589
84811
|
}
|
|
84590
84812
|
const runtimeParent = dirname7(runtimeDir);
|
|
84591
|
-
const installDir = await mkdtemp2(
|
|
84592
|
-
const stagingCache = await mkdtemp2(
|
|
84593
|
-
const packageRoot =
|
|
84594
|
-
const stagedPackageRoot =
|
|
84813
|
+
const installDir = await mkdtemp2(join20(runtimeParent, `.calldiff-${id}-install-`));
|
|
84814
|
+
const stagingCache = await mkdtemp2(join20(runtimeDir, `.grammar-cache-${id}-`));
|
|
84815
|
+
const packageRoot = join20(installDir, "node_modules", ...(language.packageName ?? "").split("/"));
|
|
84816
|
+
const stagedPackageRoot = join20(stagingCache, "node_modules", ...(language.packageName ?? "").split("/"));
|
|
84595
84817
|
const finalPackageRoot = getLanguagePackageRoot(runtimeDir, language);
|
|
84596
84818
|
const backupPackageRoot = `${finalPackageRoot}.previous-${process.pid}-${Date.now()}`;
|
|
84597
84819
|
try {
|
|
84598
|
-
|
|
84599
|
-
|
|
84600
|
-
const verifiedArtifacts = await downloadVerifiedLockArtifacts(CALL_FLOW_PACK_LOCKS[id],
|
|
84820
|
+
writeFileSync8(join20(installDir, "package.json"), runtimeJson(packManifest(id)), "utf8");
|
|
84821
|
+
writeFileSync8(join20(installDir, "package-lock.json"), runtimeJson(CALL_FLOW_PACK_LOCKS[id]), "utf8");
|
|
84822
|
+
const verifiedArtifacts = await downloadVerifiedLockArtifacts(CALL_FLOW_PACK_LOCKS[id], join20(installDir, ".verified-artifacts"), onStage);
|
|
84601
84823
|
const npmCacheDir = await seedVerifiedNpmCache(npmPath, installDir, verifiedArtifacts);
|
|
84602
84824
|
onStage("installing-deps");
|
|
84603
84825
|
const install = await runCommand(npmPath, [
|
|
@@ -84648,18 +84870,18 @@ async function installCallFlowLanguagePackUnlocked(id, onStage) {
|
|
|
84648
84870
|
const sizeBeforePruneBytes = measureCallFlowDirectoryBytes(packageRoot);
|
|
84649
84871
|
pruneCallFlowNativePackage(packageRoot);
|
|
84650
84872
|
const sizeAfterPruneBytes = measureCallFlowDirectoryBytes(packageRoot);
|
|
84651
|
-
|
|
84873
|
+
mkdirSync11(dirname7(stagedPackageRoot), { recursive: true });
|
|
84652
84874
|
cpSync(packageRoot, stagedPackageRoot, { recursive: true });
|
|
84653
84875
|
ensureGrammarCacheManifest(stagingCache);
|
|
84654
84876
|
await validatePrunedLanguage(nodePath, runtimeDir, stagingCache, [id]);
|
|
84655
84877
|
ensureGrammarCacheManifest(getCallFlowGrammarCacheDir(runtimeDir));
|
|
84656
|
-
|
|
84878
|
+
mkdirSync11(dirname7(finalPackageRoot), { recursive: true });
|
|
84657
84879
|
if (existsSync15(finalPackageRoot))
|
|
84658
84880
|
renameSync5(finalPackageRoot, backupPackageRoot);
|
|
84659
84881
|
try {
|
|
84660
84882
|
renameSync5(stagedPackageRoot, finalPackageRoot);
|
|
84661
|
-
|
|
84662
|
-
|
|
84883
|
+
mkdirSync11(dirname7(getLanguageLockMarker(runtimeDir, id)), { recursive: true });
|
|
84884
|
+
writeFileSync8(getLanguageLockMarker(runtimeDir, id), runtimeJson(CALL_FLOW_PACK_LOCKS[id]), "utf8");
|
|
84663
84885
|
} catch (error) {
|
|
84664
84886
|
removeDirectoryBestEffort2(finalPackageRoot);
|
|
84665
84887
|
if (existsSync15(backupPackageRoot))
|
|
@@ -84772,15 +84994,15 @@ async function runCommand(executable, args, options = {}) {
|
|
|
84772
84994
|
}
|
|
84773
84995
|
function grammarChecksForLanguages(runtime4, ids) {
|
|
84774
84996
|
const checks2 = new Map;
|
|
84775
|
-
const callDiffRoot = runtime4.managed ?
|
|
84997
|
+
const callDiffRoot = runtime4.managed ? join20(runtime4.runtimeDir, "node_modules", "calldiff") : runtime4.runtimeDir;
|
|
84776
84998
|
checks2.set("calldiff", {
|
|
84777
|
-
packageJson:
|
|
84999
|
+
packageJson: join20(callDiffRoot, "package.json"),
|
|
84778
85000
|
version: CALLDIFF_VERSION,
|
|
84779
85001
|
message: `CallDiff ${CALLDIFF_VERSION} is not installed.`
|
|
84780
85002
|
});
|
|
84781
85003
|
for (const dependency of CORE_RUNTIME_DEPENDENCIES) {
|
|
84782
85004
|
checks2.set(dependency.packageName, {
|
|
84783
|
-
packageJson:
|
|
85005
|
+
packageJson: join20(runtime4.runtimeDir, "node_modules", dependency.packageName, "package.json"),
|
|
84784
85006
|
version: dependency.version,
|
|
84785
85007
|
message: `${dependency.label} support is not installed at the required version.`
|
|
84786
85008
|
});
|
|
@@ -84789,9 +85011,9 @@ function grammarChecksForLanguages(runtime4, ids) {
|
|
|
84789
85011
|
const language = getCallFlowLanguage(id);
|
|
84790
85012
|
if (language.kind !== "pack" || !language.packageName || !language.packageVersion)
|
|
84791
85013
|
continue;
|
|
84792
|
-
const packageRoot = runtime4.managed ? getLanguagePackageRoot(runtime4.runtimeDir, language) :
|
|
85014
|
+
const packageRoot = runtime4.managed ? getLanguagePackageRoot(runtime4.runtimeDir, language) : join20(runtime4.runtimeDir, "node_modules", ...language.packageName.split("/"));
|
|
84793
85015
|
checks2.set(language.packageName, {
|
|
84794
|
-
packageJson:
|
|
85016
|
+
packageJson: join20(packageRoot, "package.json"),
|
|
84795
85017
|
version: language.packageVersion,
|
|
84796
85018
|
message: `${language.label} support is not installed.`
|
|
84797
85019
|
});
|
|
@@ -84799,15 +85021,15 @@ function grammarChecksForLanguages(runtime4, ids) {
|
|
|
84799
85021
|
return [...checks2.values()];
|
|
84800
85022
|
}
|
|
84801
85023
|
async function createNpmBlocker() {
|
|
84802
|
-
const root3 = await mkdtemp2(
|
|
85024
|
+
const root3 = await mkdtemp2(join20(tmpdir4(), "plannotator-call-flow-path-"));
|
|
84803
85025
|
if (process.platform === "win32") {
|
|
84804
|
-
|
|
85026
|
+
writeFileSync8(join20(root3, "npm.cmd"), `@echo CallDiff package installation is disabled during analysis. 1>&2\r
|
|
84805
85027
|
@exit /b 91\r
|
|
84806
85028
|
`, "utf8");
|
|
84807
|
-
|
|
85029
|
+
writeFileSync8(join20(root3, "npm.exe"), "", "utf8");
|
|
84808
85030
|
} else {
|
|
84809
|
-
const blocker =
|
|
84810
|
-
|
|
85031
|
+
const blocker = join20(root3, "npm");
|
|
85032
|
+
writeFileSync8(blocker, `#!/bin/sh
|
|
84811
85033
|
echo 'CallDiff package installation is disabled during analysis.' >&2
|
|
84812
85034
|
exit 91
|
|
84813
85035
|
`, "utf8");
|
|
@@ -86892,10 +87114,10 @@ var init_guide2 = __esm(() => {
|
|
|
86892
87114
|
});
|
|
86893
87115
|
|
|
86894
87116
|
// ../../packages/shared/guide-instructions-store.ts
|
|
86895
|
-
import { mkdirSync as
|
|
86896
|
-
import { dirname as dirname8, join as
|
|
87117
|
+
import { mkdirSync as mkdirSync12, readFileSync as readFileSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
87118
|
+
import { dirname as dirname8, join as join21 } from "path";
|
|
86897
87119
|
function instructionsPath() {
|
|
86898
|
-
return
|
|
87120
|
+
return join21(getPlannotatorDataDir(), "guide-instructions.md");
|
|
86899
87121
|
}
|
|
86900
87122
|
function bound(value) {
|
|
86901
87123
|
const trimmed = value.trim();
|
|
@@ -86917,8 +87139,8 @@ function writeGuideInstructions(value) {
|
|
|
86917
87139
|
} catch {}
|
|
86918
87140
|
return "";
|
|
86919
87141
|
}
|
|
86920
|
-
|
|
86921
|
-
|
|
87142
|
+
mkdirSync12(dirname8(path2), { recursive: true });
|
|
87143
|
+
writeFileSync9(path2, bounded + `
|
|
86922
87144
|
`, "utf8");
|
|
86923
87145
|
return bounded;
|
|
86924
87146
|
}
|
|
@@ -87469,7 +87691,7 @@ var init_agent_jobs2 = __esm(() => {
|
|
|
87469
87691
|
});
|
|
87470
87692
|
|
|
87471
87693
|
// ../../packages/server/codex-review.ts
|
|
87472
|
-
import { join as
|
|
87694
|
+
import { join as join22 } from "path";
|
|
87473
87695
|
import { tmpdir as tmpdir5 } from "os";
|
|
87474
87696
|
import { appendFile, mkdir, unlink, writeFile, readFile as readFile2 } from "fs/promises";
|
|
87475
87697
|
import { existsSync as existsSync16 } from "fs";
|
|
@@ -87525,7 +87747,7 @@ async function buildCodexCommand(options) {
|
|
|
87525
87747
|
return command;
|
|
87526
87748
|
}
|
|
87527
87749
|
function generateOutputPath() {
|
|
87528
|
-
return
|
|
87750
|
+
return join22(tmpdir5(), `plannotator-codex-${crypto.randomUUID()}.json`);
|
|
87529
87751
|
}
|
|
87530
87752
|
async function parseCodexOutput(outputPath) {
|
|
87531
87753
|
await debugLog("PARSE_OUTPUT_START", { outputPath });
|
|
@@ -87659,7 +87881,7 @@ var init_codex_review = __esm(() => {
|
|
|
87659
87881
|
init_external_annotation2();
|
|
87660
87882
|
DATA_DIR3 = getPlannotatorDataDir();
|
|
87661
87883
|
DEBUG_ENABLED = !!process.env.PLANNOTATOR_DEBUG;
|
|
87662
|
-
DEBUG_LOG_PATH =
|
|
87884
|
+
DEBUG_LOG_PATH = join22(DATA_DIR3, "codex-review-debug.log");
|
|
87663
87885
|
CODEX_REVIEW_SCHEMA = JSON.stringify({
|
|
87664
87886
|
type: "object",
|
|
87665
87887
|
properties: {
|
|
@@ -87702,7 +87924,7 @@ var init_codex_review = __esm(() => {
|
|
|
87702
87924
|
additionalProperties: false
|
|
87703
87925
|
});
|
|
87704
87926
|
SCHEMA_DIR = DATA_DIR3;
|
|
87705
|
-
SCHEMA_FILE =
|
|
87927
|
+
SCHEMA_FILE = join22(SCHEMA_DIR, "codex-review-schema.json");
|
|
87706
87928
|
});
|
|
87707
87929
|
|
|
87708
87930
|
// ../../packages/server/agent-review-message.ts
|
|
@@ -87903,7 +88125,7 @@ var init_agent_review_message = __esm(() => {
|
|
|
87903
88125
|
});
|
|
87904
88126
|
|
|
87905
88127
|
// ../../packages/server/tour/tour-review.ts
|
|
87906
|
-
import { join as
|
|
88128
|
+
import { join as join23 } from "path";
|
|
87907
88129
|
import { tmpdir as tmpdir6 } from "os";
|
|
87908
88130
|
import { mkdir as mkdir2, writeFile as writeFile2, readFile as readFile3, unlink as unlink2 } from "fs/promises";
|
|
87909
88131
|
function buildTourUserMessage(patch, diffType, options, prMetadata) {
|
|
@@ -88055,7 +88277,7 @@ async function ensureTourSchemaFile() {
|
|
|
88055
88277
|
return TOUR_SCHEMA_FILE;
|
|
88056
88278
|
}
|
|
88057
88279
|
function generateTourOutputPath() {
|
|
88058
|
-
return
|
|
88280
|
+
return join23(tmpdir6(), `plannotator-tour-${crypto.randomUUID()}.json`);
|
|
88059
88281
|
}
|
|
88060
88282
|
async function buildTourCodexCommand(options) {
|
|
88061
88283
|
const { cwd, outputPath, prompt, model, reasoningEffort, fastMode } = options;
|
|
@@ -88458,11 +88680,11 @@ var init_tour_review = __esm(() => {
|
|
|
88458
88680
|
additionalProperties: false
|
|
88459
88681
|
});
|
|
88460
88682
|
TOUR_SCHEMA_DIR = getPlannotatorDataDir();
|
|
88461
|
-
TOUR_SCHEMA_FILE =
|
|
88683
|
+
TOUR_SCHEMA_FILE = join23(TOUR_SCHEMA_DIR, "tour-schema.json");
|
|
88462
88684
|
});
|
|
88463
88685
|
|
|
88464
88686
|
// ../../packages/server/guide/guide-review.ts
|
|
88465
|
-
import { join as
|
|
88687
|
+
import { join as join24 } from "path";
|
|
88466
88688
|
import { tmpdir as tmpdir7 } from "os";
|
|
88467
88689
|
import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile4, unlink as unlink3 } from "fs/promises";
|
|
88468
88690
|
function composeGuideMethodology(extraInstructions) {
|
|
@@ -88656,7 +88878,7 @@ async function ensureGuideSchemaFile() {
|
|
|
88656
88878
|
return GUIDE_SCHEMA_FILE;
|
|
88657
88879
|
}
|
|
88658
88880
|
function generateGuideOutputPath() {
|
|
88659
|
-
return
|
|
88881
|
+
return join24(tmpdir7(), `plannotator-guide-${crypto.randomUUID()}.json`);
|
|
88660
88882
|
}
|
|
88661
88883
|
async function buildGuideCodexCommand(options) {
|
|
88662
88884
|
const { cwd, outputPath, prompt, model, reasoningEffort, fastMode } = options;
|
|
@@ -89480,7 +89702,7 @@ var init_guide_review = __esm(() => {
|
|
|
89480
89702
|
additionalProperties: false
|
|
89481
89703
|
});
|
|
89482
89704
|
GUIDE_SCHEMA_DIR = getPlannotatorDataDir();
|
|
89483
|
-
GUIDE_SCHEMA_FILE =
|
|
89705
|
+
GUIDE_SCHEMA_FILE = join24(GUIDE_SCHEMA_DIR, "guide-schema.json");
|
|
89484
89706
|
});
|
|
89485
89707
|
|
|
89486
89708
|
// ../../packages/core/compress.ts
|
|
@@ -90111,8 +90333,8 @@ function parsePRUrl(url) {
|
|
|
90111
90333
|
}
|
|
90112
90334
|
|
|
90113
90335
|
// ../../packages/shared/guide-store.ts
|
|
90114
|
-
import { join as
|
|
90115
|
-
import { mkdirSync as
|
|
90336
|
+
import { join as join25, resolve as resolve12, basename as basename8 } from "path";
|
|
90337
|
+
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync10, readFileSync as readFileSync13, readdirSync as readdirSync6, renameSync as renameSync6, unlinkSync as unlinkSync6, existsSync as existsSync17 } from "fs";
|
|
90116
90338
|
import { createHash as createHash5 } from "crypto";
|
|
90117
90339
|
function sanitizeKeySegment(segment) {
|
|
90118
90340
|
const cleaned = segment.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "");
|
|
@@ -90151,13 +90373,13 @@ function makeGuideId(title, now = Date.now()) {
|
|
|
90151
90373
|
return `${now}-${slug || "guide"}`;
|
|
90152
90374
|
}
|
|
90153
90375
|
function guidesDir(repoKey) {
|
|
90154
|
-
return
|
|
90376
|
+
return join25(getPlannotatorDataDir(), "guides", repoKey);
|
|
90155
90377
|
}
|
|
90156
90378
|
function guidePath(repoKey, id) {
|
|
90157
|
-
return
|
|
90379
|
+
return join25(guidesDir(repoKey), `${id}.json`);
|
|
90158
90380
|
}
|
|
90159
90381
|
function guidePatchPath(repoKey, id) {
|
|
90160
|
-
return
|
|
90382
|
+
return join25(guidesDir(repoKey), `${id}.patch`);
|
|
90161
90383
|
}
|
|
90162
90384
|
function coerceReviewed(value, sectionCount) {
|
|
90163
90385
|
const out = new Array(sectionCount).fill(false);
|
|
@@ -90255,10 +90477,10 @@ function saveGuide(repoKey, id, envelope) {
|
|
|
90255
90477
|
if (!isValidGuideId(id))
|
|
90256
90478
|
return false;
|
|
90257
90479
|
try {
|
|
90258
|
-
|
|
90480
|
+
mkdirSync13(guidesDir(repoKey), { recursive: true });
|
|
90259
90481
|
const finalPath = guidePath(repoKey, id);
|
|
90260
90482
|
const tmpPath = `${finalPath}.tmp`;
|
|
90261
|
-
|
|
90483
|
+
writeFileSync10(tmpPath, JSON.stringify(envelope, null, 2), "utf-8");
|
|
90262
90484
|
renameSync6(tmpPath, finalPath);
|
|
90263
90485
|
return true;
|
|
90264
90486
|
} catch (e10) {
|
|
@@ -90270,10 +90492,10 @@ function saveGuidePatch(repoKey, id, rawPatch) {
|
|
|
90270
90492
|
if (!isValidGuideId(id))
|
|
90271
90493
|
return false;
|
|
90272
90494
|
try {
|
|
90273
|
-
|
|
90495
|
+
mkdirSync13(guidesDir(repoKey), { recursive: true });
|
|
90274
90496
|
const finalPath = guidePatchPath(repoKey, id);
|
|
90275
90497
|
const tmpPath = `${finalPath}.tmp`;
|
|
90276
|
-
|
|
90498
|
+
writeFileSync10(tmpPath, rawPatch, "utf-8");
|
|
90277
90499
|
renameSync6(tmpPath, finalPath);
|
|
90278
90500
|
return true;
|
|
90279
90501
|
} catch (e10) {
|
|
@@ -90285,7 +90507,7 @@ function loadGuidePatch(repoKey, envelope) {
|
|
|
90285
90507
|
if (!envelope.review)
|
|
90286
90508
|
return null;
|
|
90287
90509
|
try {
|
|
90288
|
-
const filePath =
|
|
90510
|
+
const filePath = join25(guidesDir(repoKey), envelope.review.patchFile);
|
|
90289
90511
|
if (!existsSync17(filePath))
|
|
90290
90512
|
return null;
|
|
90291
90513
|
return readFileSync13(filePath, "utf-8");
|
|
@@ -91310,8 +91532,8 @@ var init_pr_github = __esm(() => {
|
|
|
91310
91532
|
});
|
|
91311
91533
|
|
|
91312
91534
|
// ../../packages/shared/pr-gitlab.ts
|
|
91313
|
-
import { join as
|
|
91314
|
-
import { mkdirSync as
|
|
91535
|
+
import { join as join26 } from "path";
|
|
91536
|
+
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync11 } from "fs";
|
|
91315
91537
|
function encodeProject(projectPath) {
|
|
91316
91538
|
return encodeURIComponent(projectPath);
|
|
91317
91539
|
}
|
|
@@ -91786,11 +92008,11 @@ async function submitGlMRReview(runtime4, ref, headSha, action, body3, fileComme
|
|
|
91786
92008
|
const failed = failedFileComments.map((failure) => failure.comment);
|
|
91787
92009
|
let savedTo = null;
|
|
91788
92010
|
try {
|
|
91789
|
-
const dir =
|
|
91790
|
-
|
|
92011
|
+
const dir = join26(getPlannotatorDataDir(), "failed-comments");
|
|
92012
|
+
mkdirSync14(dir, { recursive: true });
|
|
91791
92013
|
const slug = `${ref.host}-${ref.projectPath.replace(/\//g, "_")}-mr${ref.iid}-${Date.now()}`;
|
|
91792
|
-
savedTo =
|
|
91793
|
-
|
|
92014
|
+
savedTo = join26(dir, `${slug}.json`);
|
|
92015
|
+
writeFileSync11(savedTo, JSON.stringify({ ref, headSha, baseSha, startSha, errors, failedComments: failed }, null, 2));
|
|
91794
92016
|
} catch (writeErr) {
|
|
91795
92017
|
console.error(`[plannotator] Failed to persist unposted comments: ${writeErr instanceof Error ? writeErr.message : String(writeErr)}`);
|
|
91796
92018
|
}
|
|
@@ -101625,6 +101847,49 @@ async function startReviewServer(options) {
|
|
|
101625
101847
|
};
|
|
101626
101848
|
let currentContextRevision = getGitButlerContextRevision(clientGitContext) ?? "";
|
|
101627
101849
|
const currentSnapshotId = () => `${draftKey}:${currentDiffType}${isPRMode ? `:${currentPRDiffScope}` : ""}${currentContextRevision ? `:${currentContextRevision}` : ""}`;
|
|
101850
|
+
const feedbackProject = () => options.project?.trim() ? options.project : deriveFeedbackProject(gitContext?.cwd ?? options.agentCwd ?? process.cwd());
|
|
101851
|
+
const feedbackReviewTarget = () => {
|
|
101852
|
+
const target = {
|
|
101853
|
+
diffType: String(currentDiffType),
|
|
101854
|
+
base: currentBase,
|
|
101855
|
+
gitRef: currentGitRef,
|
|
101856
|
+
snapshotId: currentSnapshotId(),
|
|
101857
|
+
changedFiles: countChangedFiles(currentPatch),
|
|
101858
|
+
patchBytes: currentPatch.length
|
|
101859
|
+
};
|
|
101860
|
+
if (sessionVcsType)
|
|
101861
|
+
target.vcsType = sessionVcsType;
|
|
101862
|
+
else if (workspace)
|
|
101863
|
+
target.vcsType = "workspace";
|
|
101864
|
+
const cwd = gitContext?.cwd ?? options.agentCwd;
|
|
101865
|
+
if (cwd)
|
|
101866
|
+
target.cwd = cwd;
|
|
101867
|
+
if (prMetadata) {
|
|
101868
|
+
target.pr = {
|
|
101869
|
+
provider: prMetadata.platform,
|
|
101870
|
+
repo: prMetadata.platform === "github" ? `${prMetadata.owner}/${prMetadata.repo}` : prMetadata.projectPath,
|
|
101871
|
+
number: prMetadata.platform === "github" ? prMetadata.number : prMetadata.iid
|
|
101872
|
+
};
|
|
101873
|
+
}
|
|
101874
|
+
return target;
|
|
101875
|
+
};
|
|
101876
|
+
const archiveReviewSubmission = (feedback, annotations, decision) => {
|
|
101877
|
+
if (!resolveFeedbackHistory(loadConfig()))
|
|
101878
|
+
return true;
|
|
101879
|
+
const feedbackText = typeof feedback === "string" ? feedback : "";
|
|
101880
|
+
const annotationList = Array.isArray(annotations) ? annotations : [];
|
|
101881
|
+
const hasContent = feedbackText.trim().length > 0 || annotationList.length > 0;
|
|
101882
|
+
const written = appendFeedbackRecord({
|
|
101883
|
+
project: feedbackProject(),
|
|
101884
|
+
origin,
|
|
101885
|
+
surface: "review",
|
|
101886
|
+
decision,
|
|
101887
|
+
target: { review: feedbackReviewTarget() },
|
|
101888
|
+
feedback: feedbackText,
|
|
101889
|
+
annotations: annotationList
|
|
101890
|
+
});
|
|
101891
|
+
return written !== null || !hasContent;
|
|
101892
|
+
};
|
|
101628
101893
|
const buildCurrentAiReviewContext = (patch = currentPatch, base = currentBase, diffType = currentDiffType) => {
|
|
101629
101894
|
if (!aiEnabled)
|
|
101630
101895
|
return;
|
|
@@ -103285,6 +103550,7 @@ async function startReviewServer(options) {
|
|
|
103285
103550
|
if (agentResponse)
|
|
103286
103551
|
return agentResponse;
|
|
103287
103552
|
if (url.pathname === "/api/exit" && req.method === "POST") {
|
|
103553
|
+
archiveReviewSubmission("", [], "dismissed");
|
|
103288
103554
|
deleteDraft(draftKey, readDraftGenerationFromUrl(req));
|
|
103289
103555
|
resolveDecision({ approved: false, feedback: "", annotations: [], exit: true });
|
|
103290
103556
|
return Response.json({ ok: true });
|
|
@@ -103292,11 +103558,17 @@ async function startReviewServer(options) {
|
|
|
103292
103558
|
if (url.pathname === "/api/feedback" && req.method === "POST") {
|
|
103293
103559
|
try {
|
|
103294
103560
|
const body3 = await req.json();
|
|
103295
|
-
|
|
103561
|
+
const approved = body3.approved ?? false;
|
|
103562
|
+
const feedbackValue = body3.feedback || "";
|
|
103563
|
+
const annotationsValue = body3.annotations || [];
|
|
103564
|
+
const hasContent = typeof feedbackValue === "string" && feedbackValue.trim().length > 0 || Array.isArray(annotationsValue) && annotationsValue.length > 0;
|
|
103565
|
+
const durable = archiveReviewSubmission(feedbackValue, annotationsValue, approved ? hasContent ? "approved-with-notes" : "lgtm" : "feedback");
|
|
103566
|
+
if (durable)
|
|
103567
|
+
deleteDraft(draftKey, readDraftGenerationFromBody(body3));
|
|
103296
103568
|
resolveDecision({
|
|
103297
|
-
approved
|
|
103298
|
-
feedback:
|
|
103299
|
-
annotations:
|
|
103569
|
+
approved,
|
|
103570
|
+
feedback: feedbackValue,
|
|
103571
|
+
annotations: annotationsValue,
|
|
103300
103572
|
agentSwitch: body3.agentSwitch
|
|
103301
103573
|
});
|
|
103302
103574
|
return Response.json({ ok: true });
|
|
@@ -103463,6 +103735,7 @@ var init_review = __esm(() => {
|
|
|
103463
103735
|
init_guide_viewer_manifest2();
|
|
103464
103736
|
init_marker_review();
|
|
103465
103737
|
init_config2();
|
|
103738
|
+
init_feedback_archive();
|
|
103466
103739
|
init_favicon2();
|
|
103467
103740
|
init_pr();
|
|
103468
103741
|
init_pr_artifact_document();
|
|
@@ -104280,11 +104553,11 @@ function shutdown() {
|
|
|
104280
104553
|
var init_agent_terminal_node_sidecar = () => {};
|
|
104281
104554
|
|
|
104282
104555
|
// ../../packages/server/agent-terminal-runtime.ts
|
|
104283
|
-
import { existsSync as existsSync20, mkdirSync as
|
|
104284
|
-
import { join as
|
|
104556
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync15, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
104557
|
+
import { join as join27 } from "path";
|
|
104285
104558
|
import { fileURLToPath } from "url";
|
|
104286
104559
|
function getAgentTerminalManagedRuntimeDir(dataDir = getPlannotatorDataDir()) {
|
|
104287
|
-
return
|
|
104560
|
+
return join27(dataDir, "vendor", "agent-terminal", `webtui-${AGENT_TERMINAL_WEBTUI_VERSION}`);
|
|
104288
104561
|
}
|
|
104289
104562
|
function isAgentTerminalRemoteEnabled(env = process.env) {
|
|
104290
104563
|
return isTruthy(env.PLANNOTATOR_AGENT_TERMINAL_REMOTE);
|
|
@@ -104364,9 +104637,9 @@ async function resolveManagedAgentTerminalRuntime(nodePath) {
|
|
|
104364
104637
|
};
|
|
104365
104638
|
}
|
|
104366
104639
|
function materializeAgentTerminalSidecar(runtimeDir) {
|
|
104367
|
-
|
|
104368
|
-
const sidecarPath =
|
|
104369
|
-
|
|
104640
|
+
mkdirSync15(runtimeDir, { recursive: true });
|
|
104641
|
+
const sidecarPath = join27(runtimeDir, "agent-terminal-node-sidecar.mjs");
|
|
104642
|
+
writeFileSync12(sidecarPath, agent_terminal_node_sidecar_default, "utf8");
|
|
104370
104643
|
return sidecarPath;
|
|
104371
104644
|
}
|
|
104372
104645
|
function tryMaterializeAgentTerminalSidecar(runtimeDir) {
|
|
@@ -104381,7 +104654,7 @@ function tryMaterializeAgentTerminalSidecar(runtimeDir) {
|
|
|
104381
104654
|
}
|
|
104382
104655
|
}
|
|
104383
104656
|
function readInstalledWebTuiVersion(runtimeDir) {
|
|
104384
|
-
const packageJsonPath =
|
|
104657
|
+
const packageJsonPath = join27(runtimeDir, "node_modules", "@plannotator", "webtui", "package.json");
|
|
104385
104658
|
if (!existsSync20(packageJsonPath))
|
|
104386
104659
|
return null;
|
|
104387
104660
|
try {
|
|
@@ -106088,23 +106361,40 @@ async function startAnnotateServer(options) {
|
|
|
106088
106361
|
}
|
|
106089
106362
|
const draftSource = mode === "annotate-app" && liveApp ? `annotate-app\x00${liveAppDraftIdentity(liveApp.targetUrl)}` : mode === "annotate-folder" && folderPath ? `folder:${resolvePath4(folderPath)}` : renderHtml && rawHtml ? rawHtml : markdown;
|
|
106090
106363
|
const draftKey = contentHash(draftSource);
|
|
106091
|
-
const
|
|
106092
|
-
|
|
106093
|
-
|
|
106094
|
-
if (!feedbackText.trim() && annotationList.length === 0)
|
|
106364
|
+
const annotateFeedbackSurface = mode === "annotate-app" ? "annotate-app" : mode === "annotate-last" ? "annotate-last" : mode === "annotate-folder" ? "annotate-folder" : singleFileLocalAnnotate ? "annotate" : "annotate-url";
|
|
106365
|
+
const archiveAnnotateDecision = (feedbackText, annotationList, decision2) => {
|
|
106366
|
+
if (!resolveFeedbackHistory(loadConfig()))
|
|
106095
106367
|
return true;
|
|
106096
106368
|
if (!annotateHistoryEnabled)
|
|
106097
106369
|
return true;
|
|
106098
|
-
|
|
106099
|
-
|
|
106100
|
-
return persistAnnotateSubmission({
|
|
106370
|
+
const isUrlTarget = /^https?:\/\//i.test(filePath);
|
|
106371
|
+
return appendFeedbackRecord({
|
|
106101
106372
|
project: annotateProjectName,
|
|
106102
|
-
|
|
106373
|
+
origin,
|
|
106374
|
+
surface: annotateFeedbackSurface,
|
|
106375
|
+
decision: decision2,
|
|
106376
|
+
target: mode === "annotate-app" && liveApp ? { url: liveApp.targetUrl } : isUrlTarget ? { url: filePath } : mode === "annotate-last" ? { filePath } : { filePath: resolvePath4(filePath) },
|
|
106103
106377
|
feedback: feedbackText,
|
|
106104
|
-
annotations: annotationList
|
|
106105
|
-
approved
|
|
106378
|
+
annotations: annotationList
|
|
106106
106379
|
}) !== null;
|
|
106107
106380
|
};
|
|
106381
|
+
const persistSubmittedDecision = (feedback, annotations, approved) => {
|
|
106382
|
+
const feedbackText = typeof feedback === "string" ? feedback : "";
|
|
106383
|
+
const annotationList = Array.isArray(annotations) ? annotations : [];
|
|
106384
|
+
const hasContent = feedbackText.trim().length > 0 || annotationList.length > 0;
|
|
106385
|
+
const archived = archiveAnnotateDecision(feedbackText, annotationList, approved ? hasContent ? "approved-with-notes" : "approved" : "feedback");
|
|
106386
|
+
let legacyDurable = true;
|
|
106387
|
+
if (hasContent && annotateHistoryEnabled && singleFileLocalAnnotate) {
|
|
106388
|
+
legacyDurable = persistAnnotateSubmission({
|
|
106389
|
+
project: annotateProjectName,
|
|
106390
|
+
sessionPath: resolvePath4(filePath),
|
|
106391
|
+
feedback: feedbackText,
|
|
106392
|
+
annotations: annotationList,
|
|
106393
|
+
approved
|
|
106394
|
+
}) !== null;
|
|
106395
|
+
}
|
|
106396
|
+
return legacyDurable && (archived || !hasContent);
|
|
106397
|
+
};
|
|
106108
106398
|
const externalAnnotations = createExternalAnnotationHandler("plan");
|
|
106109
106399
|
const aiRuntime = resolveAIEnabled() ? await createAIRuntime() : null;
|
|
106110
106400
|
const htmlAssets = createHtmlAssetRegistry();
|
|
@@ -106587,6 +106877,7 @@ async function startAnnotateServer(options) {
|
|
|
106587
106877
|
if (!decision.settle({ feedback: "", annotations: [], exit: true })) {
|
|
106588
106878
|
return alreadyDecided();
|
|
106589
106879
|
}
|
|
106880
|
+
archiveAnnotateDecision("", [], "dismissed");
|
|
106590
106881
|
deleteDraft(draftKey, readDraftGenerationFromUrl(req));
|
|
106591
106882
|
clientLease.cancel();
|
|
106592
106883
|
return Response.json({ ok: true });
|
|
@@ -106726,6 +107017,7 @@ var init_annotate = __esm(() => {
|
|
|
106726
107017
|
init_source_save_node();
|
|
106727
107018
|
init_external_annotations();
|
|
106728
107019
|
init_config2();
|
|
107020
|
+
init_feedback_archive();
|
|
106729
107021
|
init_favicon2();
|
|
106730
107022
|
init_html_assets_node();
|
|
106731
107023
|
init_browser();
|
|
@@ -107911,6 +108203,7 @@ async function handleReviewCommand(event, deps) {
|
|
|
107911
108203
|
gitRef,
|
|
107912
108204
|
error: diffError,
|
|
107913
108205
|
origin: "opencode",
|
|
108206
|
+
project: await detectProjectName() ?? undefined,
|
|
107914
108207
|
diffType: isPRMode ? undefined : userDiffType,
|
|
107915
108208
|
gitContext,
|
|
107916
108209
|
initialFingerprint,
|