@plannotator/pi-extension 0.17.10 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,6 +23,7 @@ import {
23
23
  detectObsidianVaults,
24
24
  } from "../generated/integrations-common.js";
25
25
  import { sanitizeTag } from "../generated/project.js";
26
+ import { resolveUserPath } from "../generated/resolve-file.js";
26
27
 
27
28
  export type { ObsidianConfig, BearConfig, OctarineConfig, IntegrationResult };
28
29
  export {
@@ -111,11 +112,10 @@ export async function saveToObsidian(
111
112
  ): Promise<IntegrationResult> {
112
113
  try {
113
114
  const { vaultPath, folder, plan } = config;
114
- let normalizedVault = vaultPath.trim();
115
- if (normalizedVault.startsWith("~")) {
116
- const home = process.env.HOME || process.env.USERPROFILE || "";
117
- normalizedVault = join(home, normalizedVault.slice(1));
115
+ if (!vaultPath?.trim()) {
116
+ return { success: false, error: "Vault path is required" };
118
117
  }
118
+ const normalizedVault = resolveUserPath(vaultPath);
119
119
  if (!existsSync(normalizedVault))
120
120
  return {
121
121
  success: false,
@@ -22,7 +22,12 @@ import {
22
22
  FILE_BROWSER_EXCLUDED,
23
23
  } from "../generated/reference-common.js";
24
24
  import { detectObsidianVaults } from "../generated/integrations-common.js";
25
- import { resolveMarkdownFile, isWithinProjectRoot } from "../generated/resolve-file.js";
25
+ import {
26
+ isAbsoluteUserPath,
27
+ resolveMarkdownFile,
28
+ resolveUserPath,
29
+ isWithinProjectRoot,
30
+ } from "../generated/resolve-file.js";
26
31
  import { htmlToMarkdown } from "../generated/html-to-markdown.js";
27
32
 
28
33
  type Res = ServerResponse;
@@ -62,12 +67,13 @@ export function handleDocRequest(res: Res, url: URL): void {
62
67
  // server (see serverAnnotate.ts /api/doc route). The standalone HTML
63
68
  // block below (no base) retains its cwd-based containment check.
64
69
  const base = url.searchParams.get("base");
70
+ const resolvedBase = base ? resolveUserPath(base) : null;
65
71
  if (
66
- base &&
67
- !requestedPath.startsWith("/") &&
72
+ resolvedBase &&
73
+ !isAbsoluteUserPath(requestedPath) &&
68
74
  /\.(mdx?|html?)$/i.test(requestedPath)
69
75
  ) {
70
- const fromBase = resolvePath(base, requestedPath);
76
+ const fromBase = resolveUserPath(requestedPath, resolvedBase);
71
77
  try {
72
78
  if (existsSync(fromBase)) {
73
79
  const raw = readFileSync(fromBase, "utf-8");
@@ -83,7 +89,7 @@ export function handleDocRequest(res: Res, url: URL): void {
83
89
  // HTML files: resolve directly (not via resolveMarkdownFile which only handles .md/.mdx)
84
90
  const projectRoot = process.cwd();
85
91
  if (/\.html?$/i.test(requestedPath)) {
86
- const resolvedHtml = resolvePath(base || projectRoot, requestedPath);
92
+ const resolvedHtml = resolveUserPath(requestedPath, resolvedBase || projectRoot);
87
93
  if (!isWithinProjectRoot(resolvedHtml, projectRoot)) {
88
94
  json(res, { error: "Access denied: path is outside project root" }, 403);
89
95
  return;
@@ -136,7 +142,7 @@ export function handleObsidianFilesRequest(res: Res, url: URL): void {
136
142
  json(res, { error: "Missing vaultPath parameter" }, 400);
137
143
  return;
138
144
  }
139
- const resolvedVault = resolvePath(vaultPath);
145
+ const resolvedVault = resolveUserPath(vaultPath);
140
146
  if (!existsSync(resolvedVault) || !statSync(resolvedVault).isDirectory()) {
141
147
  json(res, { error: "Invalid vault path" }, 400);
142
148
  return;
@@ -162,7 +168,7 @@ export function handleObsidianDocRequest(res: Res, url: URL): void {
162
168
  json(res, { error: "Only markdown files are supported" }, 400);
163
169
  return;
164
170
  }
165
- const resolvedVault = resolvePath(vaultPath);
171
+ const resolvedVault = resolveUserPath(vaultPath);
166
172
  let resolvedFile = resolvePath(resolvedVault, filePath);
167
173
 
168
174
  // Bare filename search within vault
@@ -214,7 +220,7 @@ export function handleFileBrowserRequest(res: Res, url: URL): void {
214
220
  json(res, { error: "Missing dirPath parameter" }, 400);
215
221
  return;
216
222
  }
217
- const resolvedDir = resolvePath(dirPath);
223
+ const resolvedDir = resolveUserPath(dirPath);
218
224
  if (!existsSync(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
219
225
  json(res, { error: "Invalid directory path" }, 400);
220
226
  return;
@@ -147,6 +147,7 @@ export async function startReviewServer(options: {
147
147
  error?: string;
148
148
  sharingEnabled?: boolean;
149
149
  shareBaseUrl?: string;
150
+ pasteApiUrl?: string;
150
151
  prMetadata?: PRMetadata;
151
152
  /** Working directory for agent processes (e.g., --local worktree). Independent of diff pipeline. */
152
153
  agentCwd?: string;
@@ -281,6 +282,8 @@ export async function startReviewServer(options: {
281
282
  options.sharingEnabled ?? process.env.PLANNOTATOR_SHARE !== "disabled";
282
283
  const shareBaseUrl =
283
284
  (options.shareBaseUrl ?? process.env.PLANNOTATOR_SHARE_URL) || undefined;
285
+ const pasteApiUrl =
286
+ (options.pasteApiUrl ?? process.env.PLANNOTATOR_PASTE_URL) || undefined;
284
287
  let resolveDecision!: (result: {
285
288
  approved: boolean;
286
289
  feedback: string;
@@ -421,6 +424,7 @@ export async function startReviewServer(options: {
421
424
  gitContext: hasLocalAccess ? options.gitContext : undefined,
422
425
  sharingEnabled,
423
426
  shareBaseUrl,
427
+ pasteApiUrl,
424
428
  repoInfo,
425
429
  isWSL: wslFlag,
426
430
  ...(options.agentCwd && { agentCwd: options.agentCwd }),