@posthog/agent 2.3.18 → 2.3.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/agent",
3
- "version": "2.3.18",
3
+ "version": "2.3.21",
4
4
  "repository": "https://github.com/PostHog/code",
5
5
  "description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
6
6
  "exports": {
@@ -1,3 +1,4 @@
1
+ import fs from "node:fs";
1
2
  import path from "node:path";
2
3
  import type {
3
4
  PlanEntry,
@@ -179,18 +180,22 @@ export function toolInfoFromToolUse(
179
180
  : null;
180
181
  let newText: string = input?.new_string ? String(input.new_string) : "";
181
182
 
182
- // If we have cached file content, show a full-file diff
183
- if (
184
- filePath &&
185
- options?.cachedFileContent &&
186
- filePath in options.cachedFileContent
187
- ) {
188
- const oldContent = options.cachedFileContent[filePath];
189
- const newContent = input?.replace_all
190
- ? oldContent.replaceAll(oldText ?? "", newText)
191
- : oldContent.replace(oldText ?? "", newText);
192
- oldText = oldContent;
193
- newText = newContent;
183
+ // try to display a rich diff by first checking if file content is cached
184
+ // and valid (old_text exists in the content), then fall back to reading
185
+ // file from disk, then fall back to fragemented snippet diff
186
+ if (filePath && oldText !== null) {
187
+ const fileContent = resolveFileContent(
188
+ filePath,
189
+ oldText,
190
+ options?.cachedFileContent,
191
+ );
192
+ if (fileContent) {
193
+ const newContent = input?.replace_all
194
+ ? fileContent.replaceAll(oldText, newText)
195
+ : fileContent.replace(oldText, newText);
196
+ oldText = fileContent;
197
+ newText = newContent;
198
+ }
194
199
  }
195
200
 
196
201
  return {
@@ -759,6 +764,37 @@ export function planEntries(input: { todos: ClaudePlanEntry[] }): PlanEntry[] {
759
764
  }));
760
765
  }
761
766
 
767
+ /**
768
+ * attempt to resolve full file contents for diff generation
769
+ *
770
+ * 1) check file content cache exists, and is valid (old_text in content)
771
+ * 2) if missing or invalid, read file from disk
772
+ * 3) if both fail, return null, we'll fall back to fragmented snippet diff
773
+ */
774
+ function resolveFileContent(
775
+ filePath: string,
776
+ oldText: string,
777
+ cachedFileContent?: Record<string, string>,
778
+ ): string | null {
779
+ if (cachedFileContent && filePath in cachedFileContent) {
780
+ const cached = cachedFileContent[filePath];
781
+ if (cached.includes(oldText)) {
782
+ return cached;
783
+ }
784
+ }
785
+
786
+ try {
787
+ const content = fs.readFileSync(filePath, "utf-8");
788
+ if (content.includes(oldText)) {
789
+ return content;
790
+ }
791
+ } catch {
792
+ return null;
793
+ }
794
+
795
+ return null;
796
+ }
797
+
762
798
  function markdownEscape(text: string): string {
763
799
  let escapedText = "```";
764
800
  for (const [m] of text.matchAll(/^```+/gm)) {