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
11 changes: 11 additions & 0 deletions docs/en/api/05-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Create a new session.
# Create new session (auto-generated ID)
session = client.session()
print(f"Session URI: {session.uri}")

# Create new session with specified ID
session = client.create_session(session_id="my-custom-session-id")
print(f"Session ID: {session['session_id']}")
```

**HTTP API**
Expand All @@ -29,9 +33,16 @@ POST /api/v1/sessions
```

```bash
# Create new session (auto-generated ID)
curl -X POST http://localhost:1933/api/v1/sessions \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key"

# Create new session with specified ID
curl -X POST http://localhost:1933/api/v1/sessions \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key" \
-d '{"session_id": "my-custom-session-id"}'
```

**CLI**
Expand Down
11 changes: 11 additions & 0 deletions docs/zh/api/05-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
# 创建新会话(自动生成 ID)
session = client.session()
print(f"Session URI: {session.uri}")

# 创建指定 ID 的新会话
session = client.create_session(session_id="my-custom-session-id")
print(f"Session ID: {session['session_id']}")
```

**HTTP API**
Expand All @@ -29,9 +33,16 @@ POST /api/v1/sessions
```

```bash
# 创建新会话(自动生成 ID)
curl -X POST http://localhost:1933/api/v1/sessions \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key"

# 创建指定 ID 的新会话
curl -X POST http://localhost:1933/api/v1/sessions \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key" \
-d '{"session_id": "my-custom-session-id"}'
```

**CLI**
Expand Down
11 changes: 8 additions & 3 deletions openviking/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,15 @@ async def session_exists(self, session_id: str) -> bool:
await self._ensure_initialized()
return await self._client.session_exists(session_id)

async def create_session(self) -> Dict[str, Any]:
"""Create a new session."""
async def create_session(self, session_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a new session.

Args:
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
"""
await self._ensure_initialized()
return await self._client.create_session()
return await self._client.create_session(session_id)

async def list_sessions(self) -> List[Any]:
"""List all sessions."""
Expand Down
11 changes: 8 additions & 3 deletions openviking/client/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,11 +319,16 @@ async def unlink(self, from_uri: str, to_uri: str) -> None:

# ============= Sessions =============

async def create_session(self) -> Dict[str, Any]:
"""Create a new session."""
async def create_session(self, session_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a new session.

Args:
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
"""
await self._service.initialize_user_directories(self._ctx)
await self._service.initialize_agent_directories(self._ctx)
session = await self._service.sessions.create(self._ctx)
session = await self._service.sessions.create(self._ctx, session_id)
return {
"session_id": session.session_id,
"user": session.user.to_dict(),
Expand Down
16 changes: 14 additions & 2 deletions openviking/server/routers/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ class UsedRequest(BaseModel):
skill: Optional[Dict[str, Any]] = None


class CreateSessionRequest(BaseModel):
"""Request model for creating a session."""

session_id: Optional[str] = None


def _to_jsonable(value: Any) -> Any:
"""Convert internal objects (e.g. Context) into JSON-serializable values."""
to_dict = getattr(value, "to_dict", None)
Expand All @@ -92,13 +98,19 @@ def _to_jsonable(value: Any) -> Any:

@router.post("")
async def create_session(
request: Optional[CreateSessionRequest] = None,
_ctx: RequestContext = Depends(get_request_context),
):
"""Create a new session."""
"""Create a new session.

If session_id is provided, creates a session with the given ID.
If session_id is None, creates a new session with auto-generated ID.
"""
service = get_service()
await service.initialize_user_directories(_ctx)
await service.initialize_agent_directories(_ctx)
session = await service.sessions.create(_ctx)
session_id = request.session_id if request else None
session = await service.sessions.create(_ctx, session_id)
return Response(
status="ok",
result={
Expand Down
21 changes: 17 additions & 4 deletions openviking/service/session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from openviking.session.compressor import SessionCompressor
from openviking.storage import VikingDBManager
from openviking.storage.viking_fs import VikingFS
from openviking_cli.exceptions import NotFoundError, NotInitializedError
from openviking_cli.exceptions import AlreadyExistsError, NotFoundError, NotInitializedError
from openviking_cli.utils import get_logger

logger = get_logger(__name__)
Expand Down Expand Up @@ -68,9 +68,22 @@ def session(self, ctx: RequestContext, session_id: Optional[str] = None) -> Sess
session_id=session_id,
)

async def create(self, ctx: RequestContext) -> Session:
"""Create a session and persist its root path."""
session = self.session(ctx)
async def create(self, ctx: RequestContext, session_id: Optional[str] = None) -> Session:
"""Create a session and persist its root path.
Args:
ctx: Request context
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
Raises:
AlreadyExistsError: If a session with the given ID already exists
"""
if session_id:
existing = self.session(ctx, session_id)
if await existing.exists():
raise AlreadyExistsError(f"Session '{session_id}' already exists")
session = self.session(ctx, session_id)
await session.ensure_exists()
return session

Expand Down
11 changes: 8 additions & 3 deletions openviking/sync_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,14 @@ def session_exists(self, session_id: str) -> bool:
"""Check whether a session exists in storage."""
return run_async(self._async_client.session_exists(session_id))

def create_session(self) -> Dict[str, Any]:
"""Create a new session."""
return run_async(self._async_client.create_session())
def create_session(self, session_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a new session.

Args:
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
"""
return run_async(self._async_client.create_session(session_id))

def list_sessions(self) -> List[Any]:
"""List all sessions."""
Expand Down
9 changes: 7 additions & 2 deletions openviking_cli/client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,13 @@ async def unlink(self, from_uri: str, to_uri: str) -> None:
# ============= Sessions =============

@abstractmethod
async def create_session(self) -> Dict[str, Any]:
"""Create a new session."""
async def create_session(self, session_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a new session.

Args:
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
"""
...

@abstractmethod
Expand Down
12 changes: 9 additions & 3 deletions openviking_cli/client/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,11 +684,17 @@ async def unlink(self, from_uri: str, to_uri: str) -> None:

# ============= Sessions =============

async def create_session(self) -> Dict[str, Any]:
"""Create a new session."""
async def create_session(self, session_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a new session.

Args:
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
"""
json_body = {"session_id": session_id} if session_id else {}
response = await self._http.post(
"/api/v1/sessions",
json={},
json=json_body,
)
return self._handle_response(response)

Expand Down
11 changes: 8 additions & 3 deletions openviking_cli/client/sync_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,14 @@ def session_exists(self, session_id: str) -> bool:
"""Check whether a session exists in storage."""
return run_async(self._async_client.session_exists(session_id))

def create_session(self) -> Dict[str, Any]:
"""Create a new session."""
return run_async(self._async_client.create_session())
def create_session(self, session_id: Optional[str] = None) -> Dict[str, Any]:
"""Create a new session.

Args:
session_id: Optional session ID. If provided, creates a session with the given ID.
If None, creates a new session with auto-generated ID.
"""
return run_async(self._async_client.create_session(session_id))

def list_sessions(self) -> List[Any]:
"""List all sessions."""
Expand Down
37 changes: 37 additions & 0 deletions tests/api_test/sessions/test_create_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,40 @@ def test_create_session(self, api_client):
assert data["result"] is not None, "'result' should not be null"
assert "session_id" in data["result"], "'session_id' field should exist"
assert "user" in data["result"], "'user' field should exist"

def test_create_session_with_custom_id(self, api_client):
custom_session_id = "test-custom-session-12345"
try:
response = api_client.create_session(session_id=custom_session_id)
except requests.exceptions.ConnectionError:
pytest.fail("Could not connect to server service - service is not running")

assert response.status_code < 500, (
f"Create session with custom ID failed with status {response.status_code}"
)

if response.status_code == 200:
data = response.json()
print("\n" + "=" * 80)
print("Create Session with Custom ID Response:")
print("=" * 80)
print(json.dumps(data, indent=2, ensure_ascii=False))
print("=" * 80 + "\n")

assert data.get("status") == "ok", f"Expected status 'ok', got {data.get('status')}"
assert data.get("error") is None, f"Expected error to be null, got {data.get('error')}"
assert "result" in data, "'result' field should exist"
assert data["result"]["session_id"] == custom_session_id, (
f"Expected session_id '{custom_session_id}', got {data['result']['session_id']}"
)
assert "user" in data["result"], "'user' field should exist"

get_response = api_client.get_session(custom_session_id)
assert get_response.status_code == 200, (
f"Get session failed with status {get_response.status_code}"
)

get_data = get_response.json()
assert get_data["result"]["session_id"] == custom_session_id, (
"Retrieved session_id does not match created custom session_id"
)