@plannotator/pi-extension 0.19.23 → 0.19.24
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/generated/codex-review.ts +6 -4
- package/generated/config.ts +3 -2
- package/generated/data-dir.ts +43 -0
- package/generated/draft.ts +2 -2
- package/generated/improvement-hooks.ts +7 -5
- package/generated/pr-gitlab.ts +2 -2
- package/generated/prompts.ts +1 -0
- package/generated/storage.ts +10 -8
- package/generated/tour-review.ts +3 -2
- package/index.ts +3 -3
- package/package.json +1 -1
- package/plannotator.html +6 -6
- package/review-editor.html +5 -5
- package/skills/plannotator-compound/SKILL.md +7 -6
- package/skills/plannotator-compound/references/claude-code-fallback.md +3 -3
|
@@ -7,22 +7,24 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
|
-
import {
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
11
|
import { appendFile, mkdir, unlink, writeFile, readFile } from "node:fs/promises";
|
|
12
12
|
import { existsSync } from "node:fs";
|
|
13
13
|
import { toRelativePath } from "./path-utils.js";
|
|
14
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Debug log — only active when PLANNOTATOR_DEBUG is set
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
18
19
|
|
|
20
|
+
const DATA_DIR = getPlannotatorDataDir();
|
|
19
21
|
const DEBUG_ENABLED = !!process.env.PLANNOTATOR_DEBUG;
|
|
20
|
-
const DEBUG_LOG_PATH = join(
|
|
22
|
+
const DEBUG_LOG_PATH = join(DATA_DIR, "codex-review-debug.log");
|
|
21
23
|
|
|
22
24
|
async function debugLog(label: string, data?: unknown): Promise<void> {
|
|
23
25
|
if (!DEBUG_ENABLED) return;
|
|
24
26
|
try {
|
|
25
|
-
await mkdir(
|
|
27
|
+
await mkdir(DATA_DIR, { recursive: true });
|
|
26
28
|
const timestamp = new Date().toISOString();
|
|
27
29
|
const line = data !== undefined
|
|
28
30
|
? `[${timestamp}] ${label}: ${typeof data === "string" ? data : JSON.stringify(data, null, 2)}\n`
|
|
@@ -79,7 +81,7 @@ const CODEX_REVIEW_SCHEMA = JSON.stringify({
|
|
|
79
81
|
additionalProperties: false,
|
|
80
82
|
});
|
|
81
83
|
|
|
82
|
-
const SCHEMA_DIR =
|
|
84
|
+
const SCHEMA_DIR = DATA_DIR;
|
|
83
85
|
const SCHEMA_FILE = join(SCHEMA_DIR, "codex-review-schema.json");
|
|
84
86
|
let schemaMaterialized = false;
|
|
85
87
|
|
package/generated/config.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* Runtime-agnostic: uses only node:fs, node:os, node:child_process.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { homedir } from "os";
|
|
10
9
|
import { join } from "path";
|
|
10
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
11
11
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
12
12
|
import { execSync } from "child_process";
|
|
13
13
|
|
|
@@ -40,6 +40,7 @@ export type PromptSectionOverrides = Record<string, string | undefined>;
|
|
|
40
40
|
|
|
41
41
|
export type PromptRuntime =
|
|
42
42
|
| "claude-code"
|
|
43
|
+
| "amp"
|
|
43
44
|
| "droid"
|
|
44
45
|
| "opencode"
|
|
45
46
|
| "copilot-cli"
|
|
@@ -128,7 +129,7 @@ export interface PlannotatorConfig {
|
|
|
128
129
|
pfmReminder?: boolean;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
const CONFIG_DIR =
|
|
132
|
+
const CONFIG_DIR = getPlannotatorDataDir();
|
|
132
133
|
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
133
134
|
|
|
134
135
|
/**
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// @generated — DO NOT EDIT. Source: packages/shared/data-dir.ts
|
|
2
|
+
/**
|
|
3
|
+
* Plannotator Data Directory
|
|
4
|
+
*
|
|
5
|
+
* Returns the base directory for all Plannotator data files.
|
|
6
|
+
*
|
|
7
|
+
* Priority:
|
|
8
|
+
* 1. PLANNOTATOR_DATA_DIR environment variable (with ~ expansion)
|
|
9
|
+
* 2. Default: ~/.plannotator
|
|
10
|
+
*
|
|
11
|
+
* This mirrors PASTE_DATA_DIR for the paste service and allows users
|
|
12
|
+
* to relocate all data (plans, history, drafts, config, hooks, sessions,
|
|
13
|
+
* debug logs, IPC registry, etc.) via a single variable — useful for
|
|
14
|
+
* XDG-style home directory cleanliness on Unix systems.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { homedir } from "os";
|
|
18
|
+
import { join, resolve } from "path";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the Plannotator data directory.
|
|
22
|
+
*
|
|
23
|
+
* If PLANNOTATOR_DATA_DIR is set and non-empty, the value is used
|
|
24
|
+
* as the base directory. Leading ~ is expanded to the user's home
|
|
25
|
+
* directory.
|
|
26
|
+
*
|
|
27
|
+
* Falls back to ~/.plannotator when the env var is absent or empty.
|
|
28
|
+
*/
|
|
29
|
+
export function getPlannotatorDataDir(): string {
|
|
30
|
+
const envDir = process.env.PLANNOTATOR_DATA_DIR?.trim();
|
|
31
|
+
if (!envDir) {
|
|
32
|
+
return join(homedir(), ".plannotator");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Expand ~ to home directory
|
|
36
|
+
const home = homedir();
|
|
37
|
+
if (envDir === "~") return home;
|
|
38
|
+
if (envDir.startsWith("~/") || envDir.startsWith("~\\")) {
|
|
39
|
+
return join(home, envDir.slice(2));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return resolve(envDir);
|
|
43
|
+
}
|
package/generated/draft.ts
CHANGED
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
* Runtime-agnostic: uses only node:fs, node:path, node:os, node:crypto.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { homedir } from "os";
|
|
13
12
|
import { join } from "path";
|
|
14
13
|
import { mkdirSync, writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
|
|
15
14
|
import { createHash } from "crypto";
|
|
15
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Get the drafts directory, creating it if needed.
|
|
19
19
|
*/
|
|
20
20
|
export function getDraftDir(): string {
|
|
21
|
-
const dir = join(
|
|
21
|
+
const dir = join(getPlannotatorDataDir(), "drafts");
|
|
22
22
|
mkdirSync(dir, { recursive: true });
|
|
23
23
|
return dir;
|
|
24
24
|
}
|
|
@@ -18,15 +18,17 @@
|
|
|
18
18
|
* - Same trust model as ~/.plannotator/config.json
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { homedir } from "os";
|
|
22
21
|
import { join } from "path";
|
|
23
22
|
import { readFileSync, statSync } from "fs";
|
|
23
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
const HOOKS_BASE_DIR = join(homedir(), ".plannotator", "hooks");
|
|
25
|
+
const DATA_DIR = getPlannotatorDataDir();
|
|
27
26
|
|
|
28
|
-
/**
|
|
29
|
-
const
|
|
27
|
+
/** Hooks subdirectory (preferred location) */
|
|
28
|
+
const HOOKS_BASE_DIR = join(DATA_DIR, "hooks");
|
|
29
|
+
|
|
30
|
+
/** Fallback: hooks placed directly in the data dir (pre-hooks-subdir layout) */
|
|
31
|
+
const LEGACY_BASE_DIR = DATA_DIR;
|
|
30
32
|
|
|
31
33
|
/** Maximum file size to read (50 KB) */
|
|
32
34
|
const MAX_FILE_SIZE = 50 * 1024;
|
package/generated/pr-gitlab.ts
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
* Self-hosted instances are supported via the --hostname flag.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { homedir } from "os";
|
|
10
9
|
import { join } from "path";
|
|
11
10
|
import { mkdirSync, writeFileSync } from "fs";
|
|
12
11
|
import type { PRRuntime, PRMetadata, PRContext, PRReviewFileComment, CommandResult } from "./pr-types";
|
|
13
12
|
import { encodeApiFilePath } from "./pr-types";
|
|
13
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
14
14
|
|
|
15
15
|
// GitLab-specific MRRef shape (used internally)
|
|
16
16
|
interface GlMRRef {
|
|
@@ -563,7 +563,7 @@ export async function submitGlMRReview(
|
|
|
563
563
|
.filter((c): c is PRReviewFileComment => c !== null);
|
|
564
564
|
let savedTo: string | null = null;
|
|
565
565
|
try {
|
|
566
|
-
const dir = join(
|
|
566
|
+
const dir = join(getPlannotatorDataDir(), "failed-comments");
|
|
567
567
|
mkdirSync(dir, { recursive: true });
|
|
568
568
|
const slug = `${ref.host}-${ref.projectPath.replace(/\//g, "_")}-mr${ref.iid}-${Date.now()}`;
|
|
569
569
|
savedTo = join(dir, `${slug}.json`);
|
package/generated/prompts.ts
CHANGED
package/generated/storage.ts
CHANGED
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
* Runtime-agnostic: uses only node:fs, node:path, node:os.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { homedir } from "os";
|
|
12
11
|
import { join, resolve, sep } from "path";
|
|
13
12
|
import { mkdirSync, writeFileSync, readFileSync, readdirSync, statSync, existsSync } from "fs";
|
|
14
13
|
import { sanitizeTag } from "./project";
|
|
15
14
|
import { resolveUserPath } from "./resolve-file";
|
|
15
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
16
|
+
|
|
17
|
+
const DATA_DIR = getPlannotatorDataDir();
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Get the plan storage directory, creating it if needed.
|
|
@@ -25,7 +27,7 @@ export function getPlanDir(customPath?: string | null): string {
|
|
|
25
27
|
if (customPath?.trim()) {
|
|
26
28
|
planDir = resolveUserPath(customPath);
|
|
27
29
|
} else {
|
|
28
|
-
planDir = join(
|
|
30
|
+
planDir = join(DATA_DIR, "plans");
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
mkdirSync(planDir, { recursive: true });
|
|
@@ -200,7 +202,7 @@ export function readArchivedPlan(filename: string, customPath?: string | null):
|
|
|
200
202
|
* Not affected by the customPath setting (that only affects decision saves).
|
|
201
203
|
*/
|
|
202
204
|
export function getHistoryDir(project: string, slug: string): string {
|
|
203
|
-
const historyDir = join(
|
|
205
|
+
const historyDir = join(DATA_DIR, "history", project, slug);
|
|
204
206
|
mkdirSync(historyDir, { recursive: true });
|
|
205
207
|
return historyDir;
|
|
206
208
|
}
|
|
@@ -267,7 +269,7 @@ export function getPlanVersion(
|
|
|
267
269
|
slug: string,
|
|
268
270
|
version: number
|
|
269
271
|
): string | null {
|
|
270
|
-
const historyDir = join(
|
|
272
|
+
const historyDir = join(DATA_DIR, "history", project, slug);
|
|
271
273
|
const fileName = `${String(version).padStart(3, "0")}.md`;
|
|
272
274
|
const filePath = join(historyDir, fileName);
|
|
273
275
|
|
|
@@ -287,7 +289,7 @@ export function getPlanVersionPath(
|
|
|
287
289
|
slug: string,
|
|
288
290
|
version: number
|
|
289
291
|
): string | null {
|
|
290
|
-
const historyDir = join(
|
|
292
|
+
const historyDir = join(DATA_DIR, "history", project, slug);
|
|
291
293
|
const fileName = `${String(version).padStart(3, "0")}.md`;
|
|
292
294
|
const filePath = join(historyDir, fileName);
|
|
293
295
|
return existsSync(filePath) ? filePath : null;
|
|
@@ -298,7 +300,7 @@ export function getPlanVersionPath(
|
|
|
298
300
|
* Returns 0 if the directory doesn't exist.
|
|
299
301
|
*/
|
|
300
302
|
export function getVersionCount(project: string, slug: string): number {
|
|
301
|
-
const historyDir = join(
|
|
303
|
+
const historyDir = join(DATA_DIR, "history", project, slug);
|
|
302
304
|
try {
|
|
303
305
|
const entries = readdirSync(historyDir);
|
|
304
306
|
return entries.filter((e) => /^\d+\.md$/.test(e)).length;
|
|
@@ -315,7 +317,7 @@ export function listVersions(
|
|
|
315
317
|
project: string,
|
|
316
318
|
slug: string
|
|
317
319
|
): Array<{ version: number; timestamp: string }> {
|
|
318
|
-
const historyDir = join(
|
|
320
|
+
const historyDir = join(DATA_DIR, "history", project, slug);
|
|
319
321
|
try {
|
|
320
322
|
const entries = readdirSync(historyDir);
|
|
321
323
|
const versions: Array<{ version: number; timestamp: string }> = [];
|
|
@@ -345,7 +347,7 @@ export function listVersions(
|
|
|
345
347
|
export function listProjectPlans(
|
|
346
348
|
project: string
|
|
347
349
|
): Array<{ slug: string; versions: number; lastModified: string }> {
|
|
348
|
-
const projectDir = join(
|
|
350
|
+
const projectDir = join(DATA_DIR, "history", project);
|
|
349
351
|
try {
|
|
350
352
|
const entries = readdirSync(projectDir, { withFileTypes: true });
|
|
351
353
|
const plans: Array<{ slug: string; versions: number; lastModified: string }> = [];
|
package/generated/tour-review.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// @generated — DO NOT EDIT. Source: packages/server/tour/tour-review.ts
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
4
|
import { mkdir, writeFile, readFile, unlink } from "node:fs/promises";
|
|
5
|
+
import { getPlannotatorDataDir } from "./data-dir";
|
|
5
6
|
import type { DiffType } from "./review-core.js";
|
|
6
7
|
import type { PRMetadata } from "./pr-provider.js";
|
|
7
8
|
import { getLocalDiffInstruction } from "./agent-review-message.js";
|
|
@@ -384,7 +385,7 @@ export function buildTourClaudeCommand(prompt: string, model: string = "sonnet",
|
|
|
384
385
|
};
|
|
385
386
|
}
|
|
386
387
|
|
|
387
|
-
const TOUR_SCHEMA_DIR =
|
|
388
|
+
const TOUR_SCHEMA_DIR = getPlannotatorDataDir();
|
|
388
389
|
const TOUR_SCHEMA_FILE = join(TOUR_SCHEMA_DIR, "tour-schema.json");
|
|
389
390
|
let tourSchemaMaterialized = false;
|
|
390
391
|
|
package/index.ts
CHANGED
|
@@ -1165,9 +1165,9 @@ Execute each step in order. After completing a step, include [DONE:n] in your re
|
|
|
1165
1165
|
pi.on("agent_end", async (_event, ctx) => {
|
|
1166
1166
|
if (phase === "executing" && justApprovedPlan) {
|
|
1167
1167
|
justApprovedPlan = false;
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
}
|
|
1168
|
+
pi.sendUserMessage("Continue with the approved plan.", {
|
|
1169
|
+
deliverAs: "followUp",
|
|
1170
|
+
});
|
|
1171
1171
|
return;
|
|
1172
1172
|
}
|
|
1173
1173
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plannotator/pi-extension",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Plannotator Pi extension - interactive plan review with annotations, annotate agent messages, and review code/PRs",
|
|
6
6
|
"author": "backnotprop",
|