Skip to content

feat(agfs): make binding client optional, add server bootstrap, tune logging and CI#451

Merged
MaojiaSheng merged 1 commit intomainfrom
feat/optional-binding-client-and-server-bootstrap
Mar 5, 2026
Merged

feat(agfs): make binding client optional, add server bootstrap, tune logging and CI#451
MaojiaSheng merged 1 commit intomainfrom
feat/optional-binding-client-and-server-bootstrap

Conversation

@qin-ctx
Copy link
Collaborator

@qin-ctx qin-ctx commented Mar 5, 2026

Description

Make AGFSBindingClient import optional and add a lightweight server bootstrap entry point, along with logging improvements and CI optimization.

Related Issue

Fixes #445
Fixes #424

N/A

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test update

Changes Made

  • pyagfs/init.py: AGFSBindingClient 改为可选导入,当 native library 不可用时优雅降级为 None,不影响纯 HTTP 模式
  • openviking/utils/agfs_utils.py: 适配可选导入逻辑,检查 AGFSBindingClient is None 而非捕获 ImportError
  • openviking/storage/viking_fs.py: 将 FileNotFoundError 替换为 NotFoundError 保持错误处理一致性;将冗余的 info 日志降级为 debug
  • openviking/server/app.py: 将未处理异常的 logger.exception 降级为 logger.warning,减少日志噪音
  • openviking_cli/server_bootstrap.py: 新增轻量级 server 入口,在导入 openviking 前预解析 --config,避免 config 单例过早初始化
  • pyproject.toml: server 入口指向新的 bootstrap 模块
  • build-docker-image.yml: Docker 构建仅在发布 tag 和手动触发时执行,移除 PR 和 main push 触发

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have tested this on the following platforms:
    • Linux
    • macOS
    • Windows

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Screenshots (if applicable)

N/A

Additional Notes

Generated with Claude Code

…logging and CI

- Make AGFSBindingClient import optional so pure-HTTP AGFSClient works without native lib
- Add lightweight server entry point that pre-parses --config before openviking imports
- Downgrade noisy info/exception logs to debug/warning level
- Replace FileNotFoundError with NotFoundError for consistent error handling
- Docker image build now only triggers on release tags and manual dispatch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@MaojiaSheng MaojiaSheng merged commit ee2786c into main Mar 5, 2026
20 of 22 checks passed
@MaojiaSheng MaojiaSheng deleted the feat/optional-binding-client-and-server-bootstrap branch March 5, 2026 14:25
@github-project-automation github-project-automation bot moved this from Backlog to Done in OpenViking project Mar 5, 2026
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

445 - Partially compliant

Compliant requirements:

  • Added a lightweight server bootstrap entry point (openviking_cli/server_bootstrap.py) that pre-parses --config and sets the environment variable before importing openviking modules

Non-compliant requirements:

Requires further human verification:

424 - Partially compliant

Compliant requirements:

  • Made AGFSBindingClient optional in pyagfs/init.py (sets to None when native library not available)
  • Updated agfs_utils.py to check AGFSBindingClient is None instead of catching ImportError

Non-compliant requirements:

Requires further human verification:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Overly Broad Exception Handling

Catching all exceptions and treating them as NotFoundError could mask other errors like permission issues, I/O errors, etc. This changes the original behavior which only caught FileNotFoundError.

except Exception:
    raise NotFoundError(uri, "file")
Overly Broad Exception Handling

Same issue as above: catching all exceptions and treating them as NotFoundError.

except Exception:
    raise NotFoundError(uri, "file")
Overly Broad Exception Handling

Same issue as above: catching all exceptions and treating them as NotFoundError.

except Exception:
    raise NotFoundError(uri, "directory")
Overly Broad Exception Handling

Same issue as above: catching all exceptions and treating them as NotFoundError.

except Exception:
    raise NotFoundError(uri, "directory")
Reduced Error Observability

Changed from logger.exception (which logs full traceback) to logger.warning with only the exception message, losing important debugging information for unhandled exceptions.

logger.warning("Unhandled exception: %s", exc)

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Restore traceback for unhandled exceptions

Using logger.warning instead of logger.exception loses the traceback for unhandled
exceptions, which is critical for debugging. Restore logger.exception to retain full
error context, or use logger.warning with exc_info=True to include the traceback.

openviking/server/app.py [137-139]

 @app.exception_handler(Exception)
 async def general_error_handler(request: Request, exc: Exception):
-    logger.warning("Unhandled exception: %s", exc)
+    logger.exception("Unhandled exception: %s", exc)
Suggestion importance[1-10]: 8

__

Why: Replacing logger.exception with logger.warning loses the traceback, which is critical for debugging unhandled exceptions. This change could significantly hinder issue diagnosis.

Medium
Fix overbroad exception handling

Catching all exceptions and re-raising as NotFoundError misclassifies non-not-found
errors (e.g., permission denied, I/O errors). Also, exception chaining is lost.
Catch specific exceptions (like AGFSHTTPError with 404 status) and use raise ...
from e to preserve context.

openviking/storage/viking_fs.py [1255-1258]

 try:
     content = self.agfs.read(path)
-except Exception:
-    raise NotFoundError(uri, "file")
+except AGFSHTTPError as e:
+    if e.status_code == 404:
+        raise NotFoundError(uri, "file") from e
+    raise
Suggestion importance[1-10]: 7

__

Why: Catching all exceptions and re-raising as NotFoundError misclassifies non-not-found errors and loses context. The suggestion improves error handling by targeting specific 404 cases and preserving exception chaining.

Medium
Narrow exception handling for read_file_bytes

This overbroad exception catch converts all errors to NotFoundError, losing original
error context and misclassifying issues. Limit to specific not-found exceptions and
use exception chaining with raise ... from e.

openviking/storage/viking_fs.py [1274-1277]

 try:
     return self._handle_agfs_read(self.agfs.read(path))
-except Exception:
-    raise NotFoundError(uri, "file")
+except AGFSHTTPError as e:
+    if e.status_code == 404:
+        raise NotFoundError(uri, "file") from e
+    raise
Suggestion importance[1-10]: 7

__

Why: This addresses the same overbroad exception handling issue as the previous suggestion, but for the read_file_bytes method. It improves error accuracy and preserves debugging context.

Medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

3 participants