a3s-code 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {a3s_code-0.1.0 → a3s_code-0.2.0}/PKG-INFO +1 -1
  2. {a3s_code-0.1.0 → a3s_code-0.2.0}/a3s_code/__init__.py +2 -0
  3. {a3s_code-0.1.0 → a3s_code-0.2.0}/a3s_code/client.py +118 -8
  4. {a3s_code-0.1.0 → a3s_code-0.2.0}/a3s_code/types.py +13 -0
  5. {a3s_code-0.1.0 → a3s_code-0.2.0}/pyproject.toml +1 -1
  6. {a3s_code-0.1.0 → a3s_code-0.2.0}/.git +0 -0
  7. {a3s_code-0.1.0 → a3s_code-0.2.0}/.gitignore +0 -0
  8. {a3s_code-0.1.0 → a3s_code-0.2.0}/LICENSE +0 -0
  9. {a3s_code-0.1.0 → a3s_code-0.2.0}/MANIFEST.in +0 -0
  10. {a3s_code-0.1.0 → a3s_code-0.2.0}/README.md +0 -0
  11. {a3s_code-0.1.0 → a3s_code-0.2.0}/a3s_code/py.typed +0 -0
  12. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/README.md +0 -0
  13. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/basic_usage.py +0 -0
  14. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/claude_code_skills_example.py +0 -0
  15. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/code_review_agent.py +0 -0
  16. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/context_management.py +0 -0
  17. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/event_streaming.py +0 -0
  18. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/external_tasks.py +0 -0
  19. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/hitl_confirmation.py +0 -0
  20. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/lsp_example.py +0 -0
  21. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/memory_events_example.py +0 -0
  22. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/memory_example.py +0 -0
  23. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/permission_policy.py +0 -0
  24. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/planning_example.py +0 -0
  25. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/provider_config.py +0 -0
  26. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/skill_management.py +0 -0
  27. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/storage_configuration.py +0 -0
  28. {a3s_code-0.1.0 → a3s_code-0.2.0}/examples/todo_tracking.py +0 -0
  29. {a3s_code-0.1.0 → a3s_code-0.2.0}/justfile +0 -0
  30. {a3s_code-0.1.0 → a3s_code-0.2.0}/proto/code_agent.proto +0 -0
  31. {a3s_code-0.1.0 → a3s_code-0.2.0}/pytest.ini +0 -0
  32. {a3s_code-0.1.0 → a3s_code-0.2.0}/tests/conftest.py +0 -0
  33. {a3s_code-0.1.0 → a3s_code-0.2.0}/tests/test_client.py +0 -0
  34. {a3s_code-0.1.0 → a3s_code-0.2.0}/tests/test_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: a3s-code
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: A3S Code Agent Python SDK
5
5
  Project-URL: Homepage, https://github.com/A3S-Lab/Code
6
6
  Project-URL: Documentation, https://github.com/A3S-Lab/Code#readme
@@ -28,6 +28,7 @@ from .types import (
28
28
  MemoryType,
29
29
  CronJobStatus,
30
30
  CronExecutionStatus,
31
+ StorageType,
31
32
  # Types
32
33
  AgentInfo,
33
34
  ToolCapability,
@@ -106,6 +107,7 @@ __all__ = [
106
107
  "MemoryType",
107
108
  "CronJobStatus",
108
109
  "CronExecutionStatus",
110
+ "StorageType",
109
111
  # Types
110
112
  "AgentInfo",
111
113
  "ToolCapability",
@@ -8,7 +8,7 @@ import grpc
8
8
  import json
9
9
  import os
10
10
  from pathlib import Path
11
- from typing import Optional, List, Dict, Iterator, Any
11
+ from typing import Optional, List, Dict, Iterator, Any, Union
12
12
 
13
13
  from .types import (
14
14
  ProviderInfo,
@@ -17,6 +17,8 @@ from .types import (
17
17
  ModelLimitInfo,
18
18
  ModelModalitiesInfo,
19
19
  SessionConfig,
20
+ LLMConfig,
21
+ StorageType,
20
22
  Message,
21
23
  Todo,
22
24
  ConfirmationPolicy,
@@ -290,8 +292,91 @@ class A3sClient:
290
292
  config: Optional[SessionConfig] = None,
291
293
  session_id: Optional[str] = None,
292
294
  initial_context: Optional[List[Message]] = None,
295
+ *,
296
+ name: str = "",
297
+ workspace: str = "",
298
+ llm: Optional[Union[LLMConfig, Dict[str, Any]]] = None,
299
+ system_prompt: Optional[str] = None,
300
+ max_context_length: Optional[int] = None,
301
+ auto_compact: Optional[bool] = None,
302
+ storage_type: Optional[StorageType] = None,
293
303
  ) -> Dict[str, Any]:
294
- """Create a new session."""
304
+ """Create a new session.
305
+
306
+ Accepts either a SessionConfig object or keyword arguments to build one.
307
+ If both are provided, keyword arguments override the config fields.
308
+
309
+ Args:
310
+ config: Optional SessionConfig object.
311
+ session_id: Optional session ID (server generates one if omitted).
312
+ initial_context: Optional list of messages to seed the session.
313
+ name: Session name.
314
+ workspace: Working directory for tool sandboxing. Each session gets
315
+ its own workspace-scoped ToolContext. If empty, falls back to
316
+ the server-level default workspace.
317
+ llm: LLM configuration (LLMConfig object or plain dict with keys:
318
+ provider, model, api_key, base_url, temperature, max_tokens).
319
+ system_prompt: Custom system prompt for the session.
320
+ max_context_length: Maximum context window length.
321
+ auto_compact: Enable automatic context compaction.
322
+ storage_type: Storage backend (StorageType.MEMORY or StorageType.FILE).
323
+
324
+ Returns:
325
+ Dict with session_id and session.
326
+ """
327
+ # Build config from kwargs when no config object is provided
328
+ has_kwargs = any(v for v in [name, workspace, llm, system_prompt,
329
+ max_context_length, auto_compact, storage_type])
330
+ if config is None and has_kwargs:
331
+ llm_config = None
332
+ if llm is not None:
333
+ if isinstance(llm, dict):
334
+ llm_config = LLMConfig(
335
+ provider=llm.get("provider", ""),
336
+ model=llm.get("model", ""),
337
+ api_key=llm.get("api_key"),
338
+ base_url=llm.get("base_url"),
339
+ temperature=llm.get("temperature"),
340
+ max_tokens=llm.get("max_tokens"),
341
+ )
342
+ else:
343
+ llm_config = llm
344
+ config = SessionConfig(
345
+ name=name,
346
+ workspace=workspace,
347
+ llm=llm_config,
348
+ system_prompt=system_prompt,
349
+ max_context_length=max_context_length,
350
+ auto_compact=auto_compact,
351
+ storage_type=storage_type,
352
+ )
353
+ elif config is not None and has_kwargs:
354
+ # kwargs override config fields
355
+ if name:
356
+ config.name = name
357
+ if workspace:
358
+ config.workspace = workspace
359
+ if llm is not None:
360
+ if isinstance(llm, dict):
361
+ config.llm = LLMConfig(
362
+ provider=llm.get("provider", ""),
363
+ model=llm.get("model", ""),
364
+ api_key=llm.get("api_key"),
365
+ base_url=llm.get("base_url"),
366
+ temperature=llm.get("temperature"),
367
+ max_tokens=llm.get("max_tokens"),
368
+ )
369
+ else:
370
+ config.llm = llm
371
+ if system_prompt is not None:
372
+ config.system_prompt = system_prompt
373
+ if max_context_length is not None:
374
+ config.max_context_length = max_context_length
375
+ if auto_compact is not None:
376
+ config.auto_compact = auto_compact
377
+ if storage_type is not None:
378
+ config.storage_type = storage_type
379
+
295
380
  request = {
296
381
  "session_id": session_id,
297
382
  "config": self._session_config_to_proto(config) if config else None,
@@ -1741,18 +1826,43 @@ class A3sClient:
1741
1826
  "workspace": config.workspace,
1742
1827
  }
1743
1828
  if config.llm:
1744
- result["llm"] = {
1745
- "provider": config.llm.provider,
1746
- "model": config.llm.model,
1747
- "api_key": config.llm.api_key or "",
1748
- "base_url": config.llm.base_url or "",
1749
- }
1829
+ if isinstance(config.llm, dict):
1830
+ llm_proto = {
1831
+ "provider": config.llm.get("provider", ""),
1832
+ "model": config.llm.get("model", ""),
1833
+ "api_key": config.llm.get("api_key", ""),
1834
+ "base_url": config.llm.get("base_url", ""),
1835
+ }
1836
+ if config.llm.get("temperature") is not None:
1837
+ llm_proto["temperature"] = config.llm["temperature"]
1838
+ if config.llm.get("max_tokens") is not None:
1839
+ llm_proto["max_tokens"] = config.llm["max_tokens"]
1840
+ else:
1841
+ llm_proto = {
1842
+ "provider": config.llm.provider,
1843
+ "model": config.llm.model,
1844
+ "api_key": config.llm.api_key or "",
1845
+ "base_url": config.llm.base_url or "",
1846
+ }
1847
+ if config.llm.temperature is not None:
1848
+ llm_proto["temperature"] = config.llm.temperature
1849
+ if config.llm.max_tokens is not None:
1850
+ llm_proto["max_tokens"] = config.llm.max_tokens
1851
+ result["llm"] = llm_proto
1750
1852
  if config.system_prompt:
1751
1853
  result["system_prompt"] = config.system_prompt
1752
1854
  if config.max_context_length:
1753
1855
  result["max_context_length"] = config.max_context_length
1754
1856
  if config.auto_compact is not None:
1755
1857
  result["auto_compact"] = config.auto_compact
1858
+ if config.storage_type is not None:
1859
+ # Map enum value to proto int; use .value to normalize aliases
1860
+ storage_value_map = {
1861
+ "STORAGE_TYPE_UNSPECIFIED": 0,
1862
+ "STORAGE_TYPE_MEMORY": 1,
1863
+ "STORAGE_TYPE_FILE": 2,
1864
+ }
1865
+ result["storage_type"] = storage_value_map.get(config.storage_type.value, 0)
1756
1866
  return result
1757
1867
 
1758
1868
  def _message_to_proto(self, msg: Message) -> Dict[str, Any]:
@@ -155,6 +155,18 @@ class ResourceLimits:
155
155
  # ============================================================================
156
156
 
157
157
 
158
+ class StorageType(Enum):
159
+ """Storage backend type for session persistence."""
160
+ UNSPECIFIED = "STORAGE_TYPE_UNSPECIFIED"
161
+ MEMORY = "STORAGE_TYPE_MEMORY"
162
+ FILE = "STORAGE_TYPE_FILE"
163
+
164
+ # Aliases for proto-style naming (used by examples and TS SDK parity)
165
+ STORAGE_TYPE_UNSPECIFIED = "STORAGE_TYPE_UNSPECIFIED"
166
+ STORAGE_TYPE_MEMORY = "STORAGE_TYPE_MEMORY"
167
+ STORAGE_TYPE_FILE = "STORAGE_TYPE_FILE"
168
+
169
+
158
170
  @dataclass
159
171
  class LLMConfig:
160
172
  provider: str = ""
@@ -173,6 +185,7 @@ class SessionConfig:
173
185
  system_prompt: Optional[str] = None
174
186
  max_context_length: Optional[int] = None
175
187
  auto_compact: Optional[bool] = None
188
+ storage_type: Optional[StorageType] = None
176
189
 
177
190
 
178
191
  @dataclass
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "a3s-code"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "A3S Code Agent Python SDK"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes