@plannotator/pi-extension 0.16.5 → 0.16.6
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/README.md +26 -0
- package/generated/review-core.ts +18 -1
- package/index.ts +78 -229
- package/package.json +3 -1
- package/plannotator-browser.ts +250 -0
- package/plannotator-events.ts +316 -0
- package/plannotator.html +2 -2
- package/review-editor.html +65 -65
- package/server/serverPlan.ts +45 -17
- package/server/serverReview.ts +2 -2
package/server/serverPlan.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { createServer } from "node:http";
|
|
2
3
|
|
|
3
4
|
import { contentHash, deleteDraft } from "../generated/draft.js";
|
|
@@ -45,11 +46,21 @@ import {
|
|
|
45
46
|
handleObsidianVaultsRequest,
|
|
46
47
|
} from "./reference.js";
|
|
47
48
|
|
|
49
|
+
export interface PlanReviewDecision {
|
|
50
|
+
approved: boolean;
|
|
51
|
+
feedback?: string;
|
|
52
|
+
savedPath?: string;
|
|
53
|
+
agentSwitch?: string;
|
|
54
|
+
permissionMode?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
export interface PlanServerResult {
|
|
58
|
+
reviewId: string;
|
|
49
59
|
port: number;
|
|
50
60
|
portSource: "env" | "remote-default" | "random";
|
|
51
61
|
url: string;
|
|
52
|
-
waitForDecision: () => Promise<
|
|
62
|
+
waitForDecision: () => Promise<PlanReviewDecision>;
|
|
63
|
+
onDecision: (listener: (result: PlanReviewDecision) => void | Promise<void>) => () => void;
|
|
53
64
|
waitForDone?: () => Promise<void>;
|
|
54
65
|
stop: () => void;
|
|
55
66
|
}
|
|
@@ -114,22 +125,24 @@ export async function startPlanReviewServer(options: {
|
|
|
114
125
|
}
|
|
115
126
|
: null;
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
permissionMode?: string;
|
|
123
|
-
}) => void;
|
|
124
|
-
const decisionPromise = new Promise<{
|
|
125
|
-
approved: boolean;
|
|
126
|
-
feedback?: string;
|
|
127
|
-
savedPath?: string;
|
|
128
|
-
agentSwitch?: string;
|
|
129
|
-
permissionMode?: string;
|
|
130
|
-
}>((r) => {
|
|
128
|
+
const reviewId = randomUUID();
|
|
129
|
+
let resolveDecision!: (result: PlanReviewDecision) => void;
|
|
130
|
+
const decisionListeners = new Set<(result: PlanReviewDecision) => void | Promise<void>>();
|
|
131
|
+
let decisionSettled = false;
|
|
132
|
+
const decisionPromise = new Promise<PlanReviewDecision>((r) => {
|
|
131
133
|
resolveDecision = r;
|
|
132
134
|
});
|
|
135
|
+
const publishDecision = (result: PlanReviewDecision): boolean => {
|
|
136
|
+
if (decisionSettled) return false;
|
|
137
|
+
decisionSettled = true;
|
|
138
|
+
resolveDecision(result);
|
|
139
|
+
for (const listener of decisionListeners) {
|
|
140
|
+
Promise.resolve(listener(result)).catch((error) => {
|
|
141
|
+
console.error("[Plan Review] Decision listener failed:", error);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
};
|
|
133
146
|
|
|
134
147
|
// Draft key for annotation persistence
|
|
135
148
|
const draftKey = options.mode !== "archive" ? contentHash(options.plan) : "";
|
|
@@ -324,6 +337,10 @@ export async function startPlanReviewServer(options: {
|
|
|
324
337
|
}
|
|
325
338
|
json(res, { ok: true, results });
|
|
326
339
|
} else if (url.pathname === "/api/approve" && req.method === "POST") {
|
|
340
|
+
if (decisionSettled) {
|
|
341
|
+
json(res, { ok: true, duplicate: true });
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
327
344
|
let feedback: string | undefined;
|
|
328
345
|
let agentSwitch: string | undefined;
|
|
329
346
|
let requestedPermissionMode: string | undefined;
|
|
@@ -390,7 +407,7 @@ export async function startPlanReviewServer(options: {
|
|
|
390
407
|
}
|
|
391
408
|
deleteDraft(draftKey);
|
|
392
409
|
const effectivePermissionMode = requestedPermissionMode || options.permissionMode;
|
|
393
|
-
|
|
410
|
+
publishDecision({
|
|
394
411
|
approved: true,
|
|
395
412
|
feedback,
|
|
396
413
|
savedPath,
|
|
@@ -399,6 +416,10 @@ export async function startPlanReviewServer(options: {
|
|
|
399
416
|
});
|
|
400
417
|
json(res, { ok: true, savedPath });
|
|
401
418
|
} else if (url.pathname === "/api/deny" && req.method === "POST") {
|
|
419
|
+
if (decisionSettled) {
|
|
420
|
+
json(res, { ok: true, duplicate: true });
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
402
423
|
let feedback = "Plan rejected by user";
|
|
403
424
|
let planSaveEnabled = true;
|
|
404
425
|
let planSaveCustomPath: string | undefined;
|
|
@@ -425,7 +446,7 @@ export async function startPlanReviewServer(options: {
|
|
|
425
446
|
);
|
|
426
447
|
}
|
|
427
448
|
deleteDraft(draftKey);
|
|
428
|
-
|
|
449
|
+
publishDecision({ approved: false, feedback, savedPath });
|
|
429
450
|
json(res, { ok: true, savedPath });
|
|
430
451
|
} else {
|
|
431
452
|
html(res, options.htmlContent);
|
|
@@ -435,10 +456,17 @@ export async function startPlanReviewServer(options: {
|
|
|
435
456
|
const { port, portSource } = await listenOnPort(server);
|
|
436
457
|
|
|
437
458
|
return {
|
|
459
|
+
reviewId,
|
|
438
460
|
port,
|
|
439
461
|
portSource,
|
|
440
462
|
url: `http://localhost:${port}`,
|
|
441
463
|
waitForDecision: () => decisionPromise,
|
|
464
|
+
onDecision: (listener) => {
|
|
465
|
+
decisionListeners.add(listener);
|
|
466
|
+
return () => {
|
|
467
|
+
decisionListeners.delete(listener);
|
|
468
|
+
};
|
|
469
|
+
},
|
|
442
470
|
...(donePromise && { waitForDone: () => donePromise }),
|
|
443
471
|
stop: () => server.close(),
|
|
444
472
|
};
|
package/server/serverReview.ts
CHANGED
|
@@ -95,8 +95,8 @@ const reviewRuntime: ReviewGitRuntime = {
|
|
|
95
95
|
},
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
export function getGitContext(): Promise<GitContext> {
|
|
99
|
-
return getGitContextCore(reviewRuntime);
|
|
98
|
+
export function getGitContext(cwd?: string): Promise<GitContext> {
|
|
99
|
+
return getGitContextCore(reviewRuntime, cwd);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export function runGitDiff(
|