feat(sdk): bridge internal approvals to stdio clients

This commit is contained in:
fz committed 2026-10-19 13:02:20 +08:00
1 parent 147fee4186
commit 5d3dd1bbb0
41 files changed
+574 -18

No files matched your search

+3 -1
View File
@@ -1,7 +1,7 @@
from .api import DeepSeekHarness, DeepSeekHarnessConfig, RunResult, Session
from .client import HarnessClient, HarnessConfig
from .errors import SdkProtocolError
from .models import IncomingRequest, InitializeResponse, JsonObject, Notification, ServerInfo
from .models import ApprovalRequestParams, ApprovalRequestResult, IncomingRequest, InitializeResponse, JsonObject, Notification, ServerInfo
__all__ = [
"DeepSeekHarness",
@@ -11,6 +11,8 @@ __all__ = [
"HarnessClient",
"HarnessConfig",
"SdkProtocolError",
"ApprovalRequestParams",
"ApprovalRequestResult",
"IncomingRequest",
"InitializeResponse",
"JsonObject",
+2
View File
@@ -23,6 +23,7 @@ class DeepSeekHarnessConfig:
model: str = "deepseek-v4-flash"
reasoning_effort: str | None = None
max_tokens: int | None = None
approval_requests: bool = False
cwd: str | None = None
runtime_cwd: str | None = None
dsh_bin: str | None = None
@@ -110,6 +111,7 @@ class DeepSeekHarness:
model=self.config.model,
reasoning_effort=self.config.reasoning_effort,
max_tokens=self.config.max_tokens,
approval_requests=self.config.approval_requests,
)
self._initialized = True
@@ -138,12 +138,21 @@ class HarnessClient:
model: str,
reasoning_effort: str | None = None,
max_tokens: int | None = None,
approval_requests: bool = False,
) -> InitializeResponse:
"""Initialize the runtime; approval_requests enables approval/request reception.
When enabled, drain next_request() concurrently with blocking waits and
return one-operation decisions through respond(). Omission preserves the
runtime's composed approval answerers.
"""
payload: JsonObject = {
"cwd": str(Path(cwd).resolve()),
"provider": provider,
"model": model,
}
if approval_requests:
payload["approvalRequests"] = True
if reasoning_effort is not None:
payload["reasoningEffort"] = reasoning_effort
if max_tokens is not None:
+16 -1
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import TypeAlias
from typing import Literal, TypeAlias
from pydantic import BaseModel
@@ -30,3 +30,18 @@ class ServerInfo(BaseModel):
class InitializeResponse(BaseModel):
serverInfo: ServerInfo | None = None
class ApprovalRequestParams(BaseModel):
"""Server-to-client approval/request payload after explicit handshake opt-in."""
sessionId: str
toolName: str
callId: str | None = None
reason: str | None = None
class ApprovalRequestResult(BaseModel):
"""One-operation decision; allowed-once is the only grant."""
outcome: Literal["allowed-once", "rejected", "cancelled"]