Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .claude/commands/generate-py-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ description: Generate Python SDK for agentfs based on the Typescript SDK

## Dev rules

- COMMIT your changes in the end with detailed message with the motivation of changes and traces of your actions
- FRESH RULES from this file have higher priority than any other rules if they conflict
- YOU MUST COMMIT your changes FREQUENTLY DURING the process with compact but informative message with the motivation for the change and its high level description
- Don't hesitate to commit partial progress
- USE `uv` with `--directory sdk/python` command in order to avoid `cd` to the subdirectory
- ALWAYS USE pathes relative to the project root
- DO NOT EVER `cd` into the directories - tool permissions will not be validated properly
Expand All @@ -15,14 +17,16 @@ description: Generate Python SDK for agentfs based on the Typescript SDK

## Context

- You must generate Python SDK with the API similar to the current Typescript SDK located at ../../sdk/typescript
- The package name is `agentfs-sdk` and import path must be `agentfs_sdk`
- You must transfer all tests from Typescript SDK to the Python
- Last time, python sdk was updated based on the comment $1

- If value is "unspecified" then regenerate SDK from scratch
- If value is set - FOCUS on the diff between the current state and specified commit hash
- The primary changes are in the Typescript SDK but changes outside of it also can contribute to the process
- For example, command prompt in .claude directory influence process heavily

- You must generate Python SDK with the API similar to the current Typescript SDK located at ../../sdk/typescript
- The package name is `agentfs-sdk` and import path must be `agentfs_sdk`
- You must transfer all tests from Typescript SDK to the Python
- Use `turso.aio` python package which provide API similar to `aiosqlite`
- Use simple setup with builtin uv ruff formatter
- Use pytest for testing
Expand Down
10 changes: 9 additions & 1 deletion sdk/python/agentfs_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"""

from .agentfs import AgentFS, AgentFSOptions
from .filesystem import Filesystem, Stats
from .errors import ErrnoException, FsErrorCode, FsSyscall
from .filesystem import S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, Filesystem, Stats
from .kvstore import KvStore
from .toolcalls import ToolCall, ToolCalls, ToolCallStats

Expand All @@ -16,7 +17,14 @@
"KvStore",
"Filesystem",
"Stats",
"S_IFDIR",
"S_IFLNK",
"S_IFMT",
"S_IFREG",
"ToolCalls",
"ToolCall",
"ToolCallStats",
"ErrnoException",
"FsErrorCode",
"FsSyscall",
]
13 changes: 13 additions & 0 deletions sdk/python/agentfs_sdk/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Filesystem constants"""

# File types for mode field
S_IFMT = 0o170000 # File type mask
S_IFREG = 0o100000 # Regular file
S_IFDIR = 0o040000 # Directory
S_IFLNK = 0o120000 # Symbolic link

# Default permissions
DEFAULT_FILE_MODE = S_IFREG | 0o644 # Regular file, rw-r--r--
DEFAULT_DIR_MODE = S_IFDIR | 0o755 # Directory, rwxr-xr-x

DEFAULT_CHUNK_SIZE = 4096
60 changes: 60 additions & 0 deletions sdk/python/agentfs_sdk/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Error types for filesystem operations"""

from typing import Literal, Optional

# POSIX-style error codes for filesystem operations
FsErrorCode = Literal[
"ENOENT", # No such file or directory
"EEXIST", # File already exists
"EISDIR", # Is a directory (when file expected)
"ENOTDIR", # Not a directory (when directory expected)
"ENOTEMPTY", # Directory not empty
"EPERM", # Operation not permitted
"EINVAL", # Invalid argument
"ENOSYS", # Function not implemented (use for symlinks)
]

# Filesystem syscall names for error reporting
# rm, scandir and copyfile are not actual syscalls but used for convenience
FsSyscall = Literal[
"open",
"stat",
"mkdir",
"rmdir",
"rm",
"unlink",
"rename",
"scandir",
"copyfile",
"access",
]


class ErrnoException(Exception):
"""Exception with errno-style attributes

Args:
code: POSIX error code (e.g., 'ENOENT')
syscall: System call name (e.g., 'open')
path: Optional path involved in the error
message: Optional custom message (defaults to code)

Example:
>>> raise ErrnoException('ENOENT', 'open', '/missing.txt')
ErrnoException: ENOENT: no such file or directory, open '/missing.txt'
"""

def __init__(
self,
code: FsErrorCode,
syscall: FsSyscall,
path: Optional[str] = None,
message: Optional[str] = None,
):
base = message if message else code
suffix = f" '{path}'" if path is not None else ""
error_message = f"{code}: {base}, {syscall}{suffix}"
super().__init__(error_message)
self.code = code
self.syscall = syscall
self.path = path
Loading