@plannotator/opencode 0.19.2 → 0.19.3
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/index.js +220 -51
- package/package.json +2 -2
- package/plannotator.html +2 -2
- package/review-editor.html +130 -130
package/dist/index.js
CHANGED
|
@@ -41684,6 +41684,24 @@ import { homedir as homedir3 } from "os";
|
|
|
41684
41684
|
import { join as join5 } from "path";
|
|
41685
41685
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync5 } from "fs";
|
|
41686
41686
|
import { execSync } from "child_process";
|
|
41687
|
+
var PROMPT_SECTIONS = ["review", "plan", "annotate"];
|
|
41688
|
+
function mergePromptConfig(current, partial) {
|
|
41689
|
+
if (!current && !partial)
|
|
41690
|
+
return;
|
|
41691
|
+
const result = { ...current, ...partial };
|
|
41692
|
+
for (const section of PROMPT_SECTIONS) {
|
|
41693
|
+
const cur = current?.[section];
|
|
41694
|
+
const par = partial?.[section];
|
|
41695
|
+
if (cur || par) {
|
|
41696
|
+
result[section] = {
|
|
41697
|
+
...cur,
|
|
41698
|
+
...par,
|
|
41699
|
+
runtimes: cur?.runtimes || par?.runtimes ? { ...cur?.runtimes, ...par?.runtimes } : undefined
|
|
41700
|
+
};
|
|
41701
|
+
}
|
|
41702
|
+
}
|
|
41703
|
+
return result;
|
|
41704
|
+
}
|
|
41687
41705
|
var CONFIG_DIR = join5(homedir3(), ".plannotator");
|
|
41688
41706
|
var CONFIG_PATH = join5(CONFIG_DIR, "config.json");
|
|
41689
41707
|
function loadConfig() {
|
|
@@ -41703,7 +41721,13 @@ function saveConfig(partial) {
|
|
|
41703
41721
|
try {
|
|
41704
41722
|
const current = loadConfig();
|
|
41705
41723
|
const mergedDiffOptions = current.diffOptions || partial.diffOptions ? { ...current.diffOptions, ...partial.diffOptions } : undefined;
|
|
41706
|
-
const
|
|
41724
|
+
const mergedPrompts = mergePromptConfig(current.prompts, partial.prompts);
|
|
41725
|
+
const merged = {
|
|
41726
|
+
...current,
|
|
41727
|
+
...partial,
|
|
41728
|
+
diffOptions: mergedDiffOptions,
|
|
41729
|
+
prompts: mergedPrompts
|
|
41730
|
+
};
|
|
41707
41731
|
mkdirSync3(CONFIG_DIR, { recursive: true });
|
|
41708
41732
|
writeFileSync2(CONFIG_PATH, JSON.stringify(merged, null, 2) + `
|
|
41709
41733
|
`, "utf-8");
|
|
@@ -46477,7 +46501,7 @@ function stackPRQuery(kind) {
|
|
|
46477
46501
|
query($owner: String!, $repo: String!, $${varName}: String!) {
|
|
46478
46502
|
repository(owner: $owner, name: $repo) {
|
|
46479
46503
|
pullRequests(first: ${first}, ${varName}: $${varName}, states: [OPEN, MERGED]) {
|
|
46480
|
-
nodes { number title url baseRefName headRefName }
|
|
46504
|
+
nodes { number title url baseRefName headRefName state }
|
|
46481
46505
|
}
|
|
46482
46506
|
}
|
|
46483
46507
|
}`;
|
|
@@ -46534,7 +46558,8 @@ async function fetchGhPRStack(runtime2, ref, metadata) {
|
|
|
46534
46558
|
title: pr.title,
|
|
46535
46559
|
url: pr.url,
|
|
46536
46560
|
isCurrent: false,
|
|
46537
|
-
isDefaultBranch: false
|
|
46561
|
+
isDefaultBranch: false,
|
|
46562
|
+
state: pr.state === "MERGED" ? "merged" : pr.state === "CLOSED" ? "closed" : "open"
|
|
46538
46563
|
});
|
|
46539
46564
|
nextHead = pr.baseRefName;
|
|
46540
46565
|
}
|
|
@@ -46551,7 +46576,8 @@ async function fetchGhPRStack(runtime2, ref, metadata) {
|
|
|
46551
46576
|
title: pr.title,
|
|
46552
46577
|
url: pr.url,
|
|
46553
46578
|
isCurrent: false,
|
|
46554
|
-
isDefaultBranch: false
|
|
46579
|
+
isDefaultBranch: false,
|
|
46580
|
+
state: pr.state === "MERGED" ? "merged" : pr.state === "CLOSED" ? "closed" : "open"
|
|
46555
46581
|
});
|
|
46556
46582
|
nextBase = pr.headRefName;
|
|
46557
46583
|
}
|
|
@@ -48288,6 +48314,175 @@ async function startAnnotateServer(options) {
|
|
|
48288
48314
|
};
|
|
48289
48315
|
}
|
|
48290
48316
|
|
|
48317
|
+
// ../../packages/shared/prompts.ts
|
|
48318
|
+
function resolveTemplate(template, vars) {
|
|
48319
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
48320
|
+
const val = vars[key];
|
|
48321
|
+
return val !== undefined ? val : match;
|
|
48322
|
+
});
|
|
48323
|
+
}
|
|
48324
|
+
var PLAN_TOOL_NAMES = {
|
|
48325
|
+
"claude-code": "ExitPlanMode",
|
|
48326
|
+
opencode: "submit_plan",
|
|
48327
|
+
"copilot-cli": "exit_plan_mode",
|
|
48328
|
+
pi: "plannotator_submit_plan",
|
|
48329
|
+
codex: "ExitPlanMode",
|
|
48330
|
+
"gemini-cli": "exit_plan_mode"
|
|
48331
|
+
};
|
|
48332
|
+
function getPlanToolName(runtime3) {
|
|
48333
|
+
return runtime3 && PLAN_TOOL_NAMES[runtime3] || "ExitPlanMode";
|
|
48334
|
+
}
|
|
48335
|
+
function buildPlanFileRule(toolName, planFilePath) {
|
|
48336
|
+
if (!planFilePath)
|
|
48337
|
+
return "";
|
|
48338
|
+
return `- Your plan is saved at: ${planFilePath}
|
|
48339
|
+
You can edit this file to make targeted changes, then pass its path to ${toolName}.
|
|
48340
|
+
`;
|
|
48341
|
+
}
|
|
48342
|
+
var DEFAULT_REVIEW_APPROVED_PROMPT = `# Code Review
|
|
48343
|
+
|
|
48344
|
+
Code review completed \u2014 no changes requested.`;
|
|
48345
|
+
var DEFAULT_REVIEW_DENIED_SUFFIX = `
|
|
48346
|
+
The reviewer has identified issues above. You must address all of them.`;
|
|
48347
|
+
var DEFAULT_PLAN_DENIED_PROMPT = `YOUR PLAN WAS NOT APPROVED.
|
|
48348
|
+
|
|
48349
|
+
You MUST revise the plan to address ALL of the feedback below before calling {{toolName}} again.
|
|
48350
|
+
|
|
48351
|
+
Rules:
|
|
48352
|
+
{{planFileRule}}- Do not resubmit the same plan unchanged.
|
|
48353
|
+
- Do NOT change the plan title (first # heading) unless the user explicitly asks you to.
|
|
48354
|
+
|
|
48355
|
+
{{feedback}}`;
|
|
48356
|
+
var DEFAULT_PLAN_APPROVED_PROMPT = "Plan approved. You now have full tool access (read, bash, edit, write). Execute the plan in {{planFilePath}}. {{doneMsg}}";
|
|
48357
|
+
var DEFAULT_PLAN_APPROVED_WITH_NOTES_PROMPT = `Plan approved with notes! You now have full tool access (read, bash, edit, write). Execute the plan in {{planFilePath}}. {{doneMsg}}
|
|
48358
|
+
|
|
48359
|
+
## Implementation Notes
|
|
48360
|
+
|
|
48361
|
+
The user approved your plan but added the following notes to consider during implementation:
|
|
48362
|
+
|
|
48363
|
+
{{feedback}}
|
|
48364
|
+
|
|
48365
|
+
Proceed with implementation, incorporating these notes where applicable.`;
|
|
48366
|
+
var DEFAULT_ANNOTATE_FILE_FEEDBACK_PROMPT = `# Markdown Annotations
|
|
48367
|
+
|
|
48368
|
+
{{fileHeader}}: {{filePath}}
|
|
48369
|
+
|
|
48370
|
+
{{feedback}}
|
|
48371
|
+
|
|
48372
|
+
Please address the annotation feedback above.`;
|
|
48373
|
+
var DEFAULT_ANNOTATE_MESSAGE_FEEDBACK_PROMPT = `# Message Annotations
|
|
48374
|
+
|
|
48375
|
+
{{feedback}}
|
|
48376
|
+
|
|
48377
|
+
Please address the annotation feedback above.`;
|
|
48378
|
+
function normalizePrompt(prompt) {
|
|
48379
|
+
if (typeof prompt !== "string")
|
|
48380
|
+
return;
|
|
48381
|
+
return prompt.trim() ? prompt : undefined;
|
|
48382
|
+
}
|
|
48383
|
+
function getConfiguredPrompt(options) {
|
|
48384
|
+
const resolvedConfig = options.config ?? loadConfig();
|
|
48385
|
+
const section = resolvedConfig.prompts?.[options.section];
|
|
48386
|
+
const runtimePrompt = options.runtime ? normalizePrompt(section?.runtimes?.[options.runtime]?.[options.key]) : undefined;
|
|
48387
|
+
const genericPrompt = normalizePrompt(section?.[options.key]);
|
|
48388
|
+
const runtimeFallback = options.runtime ? options.runtimeFallbacks?.[options.runtime] : undefined;
|
|
48389
|
+
return runtimePrompt ?? genericPrompt ?? runtimeFallback ?? options.fallback;
|
|
48390
|
+
}
|
|
48391
|
+
function getReviewApprovedPrompt(runtime3, config) {
|
|
48392
|
+
return getConfiguredPrompt({
|
|
48393
|
+
section: "review",
|
|
48394
|
+
key: "approved",
|
|
48395
|
+
runtime: runtime3,
|
|
48396
|
+
config,
|
|
48397
|
+
fallback: DEFAULT_REVIEW_APPROVED_PROMPT
|
|
48398
|
+
});
|
|
48399
|
+
}
|
|
48400
|
+
var REVIEW_DENIED_RUNTIME_DEFAULTS = {
|
|
48401
|
+
opencode: `
|
|
48402
|
+
|
|
48403
|
+
Please address this feedback.`,
|
|
48404
|
+
pi: `
|
|
48405
|
+
|
|
48406
|
+
Please address this feedback.`
|
|
48407
|
+
};
|
|
48408
|
+
function getReviewDeniedSuffix(runtime3, config) {
|
|
48409
|
+
return getConfiguredPrompt({
|
|
48410
|
+
section: "review",
|
|
48411
|
+
key: "denied",
|
|
48412
|
+
runtime: runtime3,
|
|
48413
|
+
config,
|
|
48414
|
+
fallback: DEFAULT_REVIEW_DENIED_SUFFIX,
|
|
48415
|
+
runtimeFallbacks: REVIEW_DENIED_RUNTIME_DEFAULTS
|
|
48416
|
+
});
|
|
48417
|
+
}
|
|
48418
|
+
function getPlanDeniedPrompt(runtime3, config, vars) {
|
|
48419
|
+
const template = getConfiguredPrompt({
|
|
48420
|
+
section: "plan",
|
|
48421
|
+
key: "denied",
|
|
48422
|
+
runtime: runtime3,
|
|
48423
|
+
config,
|
|
48424
|
+
fallback: DEFAULT_PLAN_DENIED_PROMPT
|
|
48425
|
+
});
|
|
48426
|
+
return resolveTemplate(template, vars ?? {});
|
|
48427
|
+
}
|
|
48428
|
+
var PLAN_APPROVED_RUNTIME_DEFAULTS = {
|
|
48429
|
+
opencode: "Plan approved!{{doneMsg}}"
|
|
48430
|
+
};
|
|
48431
|
+
function getPlanApprovedPrompt(runtime3, config, vars) {
|
|
48432
|
+
const template = getConfiguredPrompt({
|
|
48433
|
+
section: "plan",
|
|
48434
|
+
key: "approved",
|
|
48435
|
+
runtime: runtime3,
|
|
48436
|
+
config,
|
|
48437
|
+
fallback: DEFAULT_PLAN_APPROVED_PROMPT,
|
|
48438
|
+
runtimeFallbacks: PLAN_APPROVED_RUNTIME_DEFAULTS
|
|
48439
|
+
});
|
|
48440
|
+
return resolveTemplate(template, vars ?? {});
|
|
48441
|
+
}
|
|
48442
|
+
var PLAN_APPROVED_WITH_NOTES_RUNTIME_DEFAULTS = {
|
|
48443
|
+
opencode: `Plan approved with notes!
|
|
48444
|
+
{{doneMsg}}
|
|
48445
|
+
|
|
48446
|
+
## Implementation Notes
|
|
48447
|
+
|
|
48448
|
+
The user approved your plan but added the following notes to consider during implementation:
|
|
48449
|
+
|
|
48450
|
+
{{feedback}}
|
|
48451
|
+
|
|
48452
|
+
Proceed with implementation, incorporating these notes where applicable.`
|
|
48453
|
+
};
|
|
48454
|
+
function getPlanApprovedWithNotesPrompt(runtime3, config, vars) {
|
|
48455
|
+
const template = getConfiguredPrompt({
|
|
48456
|
+
section: "plan",
|
|
48457
|
+
key: "approvedWithNotes",
|
|
48458
|
+
runtime: runtime3,
|
|
48459
|
+
config,
|
|
48460
|
+
fallback: DEFAULT_PLAN_APPROVED_WITH_NOTES_PROMPT,
|
|
48461
|
+
runtimeFallbacks: PLAN_APPROVED_WITH_NOTES_RUNTIME_DEFAULTS
|
|
48462
|
+
});
|
|
48463
|
+
return resolveTemplate(template, vars ?? {});
|
|
48464
|
+
}
|
|
48465
|
+
function getAnnotateFileFeedbackPrompt(runtime3, config, vars) {
|
|
48466
|
+
const template = getConfiguredPrompt({
|
|
48467
|
+
section: "annotate",
|
|
48468
|
+
key: "fileFeedback",
|
|
48469
|
+
runtime: runtime3,
|
|
48470
|
+
config,
|
|
48471
|
+
fallback: DEFAULT_ANNOTATE_FILE_FEEDBACK_PROMPT
|
|
48472
|
+
});
|
|
48473
|
+
return resolveTemplate(template, vars ?? {});
|
|
48474
|
+
}
|
|
48475
|
+
function getAnnotateMessageFeedbackPrompt(runtime3, config, vars) {
|
|
48476
|
+
const template = getConfiguredPrompt({
|
|
48477
|
+
section: "annotate",
|
|
48478
|
+
key: "messageFeedback",
|
|
48479
|
+
runtime: runtime3,
|
|
48480
|
+
config,
|
|
48481
|
+
fallback: DEFAULT_ANNOTATE_MESSAGE_FEEDBACK_PROMPT
|
|
48482
|
+
});
|
|
48483
|
+
return resolveTemplate(template, vars ?? {});
|
|
48484
|
+
}
|
|
48485
|
+
|
|
48291
48486
|
// ../../packages/shared/at-reference.ts
|
|
48292
48487
|
function stripAtPrefix(input) {
|
|
48293
48488
|
const unquoted = stripWrappingQuotes(input);
|
|
@@ -48637,11 +48832,7 @@ async function handleReviewCommand(event, deps) {
|
|
|
48637
48832
|
if (sessionId) {
|
|
48638
48833
|
const shouldSwitchAgent = result.agentSwitch && result.agentSwitch !== "disabled";
|
|
48639
48834
|
const targetAgent = result.agentSwitch || "build";
|
|
48640
|
-
const message = result.approved ?
|
|
48641
|
-
|
|
48642
|
-
Code review completed \u2014 no changes requested.` : isPRMode ? result.feedback : `${result.feedback}
|
|
48643
|
-
|
|
48644
|
-
Please address this feedback.`;
|
|
48835
|
+
const message = result.approved ? getReviewApprovedPrompt("opencode") : isPRMode ? result.feedback : `${result.feedback}${getReviewDeniedSuffix("opencode")}`;
|
|
48645
48836
|
try {
|
|
48646
48837
|
await client3.session.prompt({
|
|
48647
48838
|
path: { id: sessionId },
|
|
@@ -48666,6 +48857,7 @@ async function handleAnnotateCommand(event, deps) {
|
|
|
48666
48857
|
let absolutePath;
|
|
48667
48858
|
let folderPath;
|
|
48668
48859
|
let annotateMode = "annotate";
|
|
48860
|
+
let isFolder = false;
|
|
48669
48861
|
let sourceInfo;
|
|
48670
48862
|
let sourceConverted = false;
|
|
48671
48863
|
const isUrl = /^https?:\/\//i.test(filePath);
|
|
@@ -48685,7 +48877,6 @@ async function handleAnnotateCommand(event, deps) {
|
|
|
48685
48877
|
} else {
|
|
48686
48878
|
const projectRoot = directory || process.cwd();
|
|
48687
48879
|
const resolvedArg = resolveUserPath(filePath, projectRoot);
|
|
48688
|
-
let isFolder = false;
|
|
48689
48880
|
try {
|
|
48690
48881
|
isFolder = statSync5(resolvedArg).isDirectory();
|
|
48691
48882
|
} catch {}
|
|
@@ -48771,13 +48962,11 @@ ${resolved.matches.map((m3) => ` ${m3}`).join(`
|
|
|
48771
48962
|
body: {
|
|
48772
48963
|
parts: [{
|
|
48773
48964
|
type: "text",
|
|
48774
|
-
text:
|
|
48775
|
-
|
|
48776
|
-
|
|
48777
|
-
|
|
48778
|
-
|
|
48779
|
-
|
|
48780
|
-
Please address the annotation feedback above.`
|
|
48965
|
+
text: getAnnotateFileFeedbackPrompt("opencode", undefined, {
|
|
48966
|
+
fileHeader: isFolder ? "Folder" : "File",
|
|
48967
|
+
filePath: absolutePath,
|
|
48968
|
+
feedback: result.feedback
|
|
48969
|
+
})
|
|
48781
48970
|
}]
|
|
48782
48971
|
}
|
|
48783
48972
|
});
|
|
@@ -48857,22 +49046,6 @@ async function handleArchiveCommand(event, deps) {
|
|
|
48857
49046
|
server2.stop();
|
|
48858
49047
|
}
|
|
48859
49048
|
|
|
48860
|
-
// ../../packages/shared/feedback-templates.ts
|
|
48861
|
-
var planDenyFeedback = (feedback, toolName = "ExitPlanMode", options) => {
|
|
48862
|
-
const planFileRule = options?.planFilePath ? `- Your plan is saved at: ${options.planFilePath}
|
|
48863
|
-
You can edit this file to make targeted changes, then pass its path to ${toolName}.
|
|
48864
|
-
` : "";
|
|
48865
|
-
return `YOUR PLAN WAS NOT APPROVED.
|
|
48866
|
-
|
|
48867
|
-
You MUST revise the plan to address ALL of the feedback below before calling ${toolName} again.
|
|
48868
|
-
|
|
48869
|
-
Rules:
|
|
48870
|
-
${planFileRule}- Do not resubmit the same plan unchanged.
|
|
48871
|
-
- Do NOT change the plan title (first # heading) unless the user explicitly asks you to.
|
|
48872
|
-
|
|
48873
|
-
${feedback || "Plan changes requested"}`;
|
|
48874
|
-
};
|
|
48875
|
-
|
|
48876
49049
|
// plan-mode.ts
|
|
48877
49050
|
function normalizeEditPermission(edit) {
|
|
48878
49051
|
if (typeof edit === "string") {
|
|
@@ -49261,11 +49434,7 @@ Do NOT proceed with implementation until your plan is approved.`);
|
|
|
49261
49434
|
body: {
|
|
49262
49435
|
parts: [{
|
|
49263
49436
|
type: "text",
|
|
49264
|
-
text:
|
|
49265
|
-
|
|
49266
|
-
${feedback}
|
|
49267
|
-
|
|
49268
|
-
Please address the annotation feedback above.`
|
|
49437
|
+
text: getAnnotateMessageFeedbackPrompt("opencode", undefined, { feedback })
|
|
49269
49438
|
}]
|
|
49270
49439
|
}
|
|
49271
49440
|
});
|
|
@@ -49363,21 +49532,21 @@ Use /plannotator-last or /plannotator-annotate for manual review, or set workflo
|
|
|
49363
49532
|
} catch {}
|
|
49364
49533
|
}
|
|
49365
49534
|
if (result.feedback) {
|
|
49366
|
-
return
|
|
49367
|
-
|
|
49368
|
-
|
|
49369
|
-
|
|
49370
|
-
|
|
49371
|
-
The user approved your plan but added the following notes to consider during implementation:
|
|
49372
|
-
|
|
49373
|
-
${result.feedback}
|
|
49374
|
-
|
|
49375
|
-
Proceed with implementation, incorporating these notes where applicable.`;
|
|
49535
|
+
return getPlanApprovedWithNotesPrompt("opencode", undefined, {
|
|
49536
|
+
planFilePath: sourceFilePath,
|
|
49537
|
+
doneMsg: result.savedPath ? `Saved to: ${result.savedPath}` : "",
|
|
49538
|
+
feedback: result.feedback
|
|
49539
|
+
});
|
|
49376
49540
|
}
|
|
49377
|
-
return
|
|
49541
|
+
return getPlanApprovedPrompt("opencode", undefined, {
|
|
49542
|
+
planFilePath: sourceFilePath,
|
|
49543
|
+
doneMsg: result.savedPath ? ` Saved to: ${result.savedPath}` : ""
|
|
49544
|
+
});
|
|
49378
49545
|
} else {
|
|
49379
|
-
return
|
|
49380
|
-
|
|
49546
|
+
return getPlanDeniedPrompt("opencode", undefined, {
|
|
49547
|
+
toolName: getPlanToolName("opencode"),
|
|
49548
|
+
planFileRule: buildPlanFileRule(getPlanToolName("opencode"), sourceFilePath),
|
|
49549
|
+
feedback: result.feedback || "Plan changes requested"
|
|
49381
49550
|
}) + "\n\nAfter making your revisions, call `submit_plan` again to resubmit for review.";
|
|
49382
49551
|
}
|
|
49383
49552
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plannotator/opencode",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"description": "Plannotator plugin for OpenCode - interactive plan review with visual annotation",
|
|
5
5
|
"author": "backnotprop",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@opencode-ai/plugin": "^1.1.10"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@plannotator/server": "0.19.
|
|
41
|
+
"@plannotator/server": "0.19.3",
|
|
42
42
|
"@plannotator/shared": "0.0.1"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|