#!/usr/bin/env python3 # args_json: {"type":"object","required":["path","content"],"properties":{"path":{"type":"string","description":"Absolute path to create or overwrite"},"content":{"type":"string","description":"File content to write"}}} # ollie:prompt # ## file_write # # Create or overwrite a file. Produces a unified diff. # # **Args**: `[path, content]` # # ``` # file_write(path="/abs/path", content="file content here") # ``` # # **Constraints**: Absolute paths only. Parent directory must exist. # ollie:end import sys import os import difflib sys.path.insert(0, os.environ.get('OLLIE_TOOLS_PATH', os.path.dirname(os.path.abspath(__file__)))) from _lib.args import parse_args def format_diff(path, old, new): old_lines = old.splitlines(keepends=True) new_lines = new.splitlines(keepends=True) return ''.join(difflib.unified_diff(old_lines, new_lines, fromfile=path, tofile=path)) args = parse_args() file_path = args.require("path") content = args.require("content") if not os.path.isabs(file_path): print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false") print(f"error: path must be absolute, got: {file_path}") sys.exit(1) parent = os.path.dirname(file_path) if parent and not os.path.isdir(parent): print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false") print(f"error: parent directory does not exist: {parent}") sys.exit(1) old_content = "" if os.path.exists(file_path): try: with open(file_path, 'r', encoding='utf-8') as f: old_content = f.read() except UnicodeDecodeError: with open(file_path, 'r', encoding='utf-8', errors='replace') as f: old_content = f.read() try: with open(file_path, 'w', encoding='utf-8') as f: f.write(content) except OSError as e: print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false") print(f"error: {e}") sys.exit(1) diff = format_diff(file_path, old_content, content) if not diff: print("STATUS=no_change STATE_CHANGED=false RETRYABLE=false") print("(no changes)") else: print("STATUS=done STATE_CHANGED=true") print(diff, end="" if diff.endswith("\n") else "\n")