acontext 0.0.7__py3-none-any.whl → 0.0.9__py3-none-any.whl

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.
acontext/__init__.py CHANGED
@@ -19,6 +19,7 @@ from .resources import (
19
19
  SessionsAPI,
20
20
  SpacesAPI,
21
21
  )
22
+ from .types import Task, TaskData
22
23
 
23
24
  __all__ = [
24
25
  "AcontextClient",
@@ -36,6 +37,8 @@ __all__ = [
36
37
  "AsyncBlocksAPI",
37
38
  "AsyncSessionsAPI",
38
39
  "AsyncSpacesAPI",
40
+ "Task",
41
+ "TaskData",
39
42
  "__version__",
40
43
  ]
41
44
 
acontext/messages.py CHANGED
@@ -31,22 +31,22 @@ class AcontextMessage:
31
31
  Represents an Acontext-format message payload.
32
32
  """
33
33
 
34
- role: Literal["user", "assistant", "system"]
34
+ role: Literal["user", "assistant"]
35
35
  parts: list[MessagePart]
36
36
  meta: Mapping[str, Any] | None = None
37
37
 
38
38
 
39
39
  def build_acontext_message(
40
40
  *,
41
- role: Literal["user", "assistant", "system"],
41
+ role: Literal["user", "assistant"],
42
42
  parts: Sequence[MessagePart | str | Mapping[str, Any]],
43
43
  meta: Mapping[str, Any] | None = None,
44
44
  ) -> AcontextMessage:
45
45
  """
46
46
  Construct an Acontext-format message blob and associated multipart files.
47
47
  """
48
- if role not in {"user", "assistant", "system"}:
49
- raise ValueError("role must be one of {'user', 'assistant', 'system'}")
48
+ if role not in {"user", "assistant"}:
49
+ raise ValueError("role must be one of {'user', 'assistant'}")
50
50
 
51
51
  normalized_parts = [normalize_message_part(part) for part in parts]
52
52
 
@@ -3,12 +3,13 @@
3
3
  import json
4
4
  from collections.abc import Mapping
5
5
  from dataclasses import asdict
6
- from typing import Any, BinaryIO, Literal
6
+ from typing import Any, BinaryIO, Literal, Optional, List
7
7
 
8
8
  from .._utils import build_params
9
9
  from ..client_types import AsyncRequesterProtocol
10
10
  from ..messages import AcontextMessage
11
11
  from ..types.session import (
12
+ EditStrategy,
12
13
  GetMessagesOutput,
13
14
  GetTasksOutput,
14
15
  LearningStatus,
@@ -264,6 +265,7 @@ class AsyncSessionsAPI:
264
265
  with_asset_public_url: bool | None = None,
265
266
  format: Literal["acontext", "openai", "anthropic"] = "openai",
266
267
  time_desc: bool | None = None,
268
+ edit_strategies: Optional[List[EditStrategy]] = None,
267
269
  ) -> GetMessagesOutput:
268
270
  """Get messages for a session.
269
271
 
@@ -272,8 +274,14 @@ class AsyncSessionsAPI:
272
274
  limit: Maximum number of messages to return. Defaults to None.
273
275
  cursor: Cursor for pagination. Defaults to None.
274
276
  with_asset_public_url: Whether to include presigned URLs for assets. Defaults to None.
275
- format: The format of the messages. Defaults to "acontext".
277
+ format: The format of the messages. Defaults to "openai".
276
278
  time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
279
+ edit_strategies: Optional list of edit strategies to apply before format conversion.
280
+ Each strategy is a dict with 'type' and 'params' keys.
281
+ Examples:
282
+ - Remove tool results: [{"type": "remove_tool_result", "params": {"keep_recent_n_tool_results": 3}}]
283
+ - Token limit: [{"type": "token_limit", "params": {"limit_tokens": 20000}}]
284
+ Defaults to None.
277
285
 
278
286
  Returns:
279
287
  GetMessagesOutput containing the list of messages and pagination information.
@@ -289,6 +297,8 @@ class AsyncSessionsAPI:
289
297
  time_desc=time_desc,
290
298
  )
291
299
  )
300
+ if edit_strategies is not None:
301
+ params["edit_strategies"] = json.dumps(edit_strategies)
292
302
  data = await self._requester.request(
293
303
  "GET", f"/session/{session_id}/messages", params=params or None
294
304
  )
@@ -181,7 +181,7 @@ class AsyncSpacesAPI:
181
181
  """
182
182
  payload = {"save": save}
183
183
  data = await self._requester.request(
184
- "PATCH",
184
+ "PUT",
185
185
  f"/space/{space_id}/experience_confirmations/{experience_id}",
186
186
  json_data=payload,
187
187
  )
@@ -3,12 +3,13 @@
3
3
  import json
4
4
  from collections.abc import Mapping
5
5
  from dataclasses import asdict
6
- from typing import Any, BinaryIO, Literal
6
+ from typing import Any, BinaryIO, Literal, Optional, List
7
7
 
8
8
  from .._utils import build_params
9
9
  from ..client_types import RequesterProtocol
10
10
  from ..messages import AcontextMessage
11
11
  from ..types.session import (
12
+ EditStrategy,
12
13
  GetMessagesOutput,
13
14
  GetTasksOutput,
14
15
  LearningStatus,
@@ -71,12 +72,14 @@ class SessionsAPI:
71
72
  self,
72
73
  *,
73
74
  space_id: str | None = None,
75
+ disable_task_tracking: bool | None = None,
74
76
  configs: Mapping[str, Any] | None = None,
75
77
  ) -> Session:
76
78
  """Create a new session.
77
79
 
78
80
  Args:
79
81
  space_id: Optional space ID to associate with the session. Defaults to None.
82
+ disable_task_tracking: Whether to disable task tracking for this session. Defaults to None (server default: False).
80
83
  configs: Optional session configuration dictionary. Defaults to None.
81
84
 
82
85
  Returns:
@@ -85,6 +88,8 @@ class SessionsAPI:
85
88
  payload: dict[str, Any] = {}
86
89
  if space_id:
87
90
  payload["space_id"] = space_id
91
+ if disable_task_tracking is not None:
92
+ payload["disable_task_tracking"] = disable_task_tracking
88
93
  if configs is not None:
89
94
  payload["configs"] = configs
90
95
  data = self._requester.request("POST", "/session", json_data=payload)
@@ -264,6 +269,7 @@ class SessionsAPI:
264
269
  with_asset_public_url: bool | None = None,
265
270
  format: Literal["acontext", "openai", "anthropic"] = "openai",
266
271
  time_desc: bool | None = None,
272
+ edit_strategies: Optional[List[EditStrategy]] = None,
267
273
  ) -> GetMessagesOutput:
268
274
  """Get messages for a session.
269
275
 
@@ -272,8 +278,14 @@ class SessionsAPI:
272
278
  limit: Maximum number of messages to return. Defaults to None.
273
279
  cursor: Cursor for pagination. Defaults to None.
274
280
  with_asset_public_url: Whether to include presigned URLs for assets. Defaults to None.
275
- format: The format of the messages. Defaults to "acontext".
281
+ format: The format of the messages. Defaults to "openai".
276
282
  time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
283
+ edit_strategies: Optional list of edit strategies to apply before format conversion.
284
+ Each strategy is a dict with 'type' and 'params' keys.
285
+ Examples:
286
+ - Remove tool results: [{"type": "remove_tool_result", "params": {"keep_recent_n_tool_results": 3}}]
287
+ - Token limit: [{"type": "token_limit", "params": {"limit_tokens": 20000}}]
288
+ Defaults to None.
277
289
 
278
290
  Returns:
279
291
  GetMessagesOutput containing the list of messages and pagination information.
@@ -289,6 +301,8 @@ class SessionsAPI:
289
301
  time_desc=time_desc,
290
302
  )
291
303
  )
304
+ if edit_strategies is not None:
305
+ params["edit_strategies"] = json.dumps(edit_strategies)
292
306
  data = self._requester.request(
293
307
  "GET", f"/session/{session_id}/messages", params=params or None
294
308
  )
@@ -332,7 +346,5 @@ class SessionsAPI:
332
346
  Returns:
333
347
  TokenCounts object containing total_tokens.
334
348
  """
335
- data = self._requester.request(
336
- "GET", f"/session/{session_id}/token_counts"
337
- )
349
+ data = self._requester.request("GET", f"/session/{session_id}/token_counts")
338
350
  return TokenCounts.model_validate(data)
@@ -179,7 +179,7 @@ class SpacesAPI:
179
179
  """
180
180
  payload = {"save": save}
181
181
  data = self._requester.request(
182
- "PATCH",
182
+ "PUT",
183
183
  f"/space/{space_id}/experience_confirmations/{experience_id}",
184
184
  json_data=payload,
185
185
  )
@@ -20,6 +20,7 @@ from .session import (
20
20
  PublicURL,
21
21
  Session,
22
22
  Task,
23
+ TaskData,
23
24
  TokenCounts,
24
25
  )
25
26
  from .block import Block
@@ -58,6 +59,7 @@ __all__ = [
58
59
  "PublicURL",
59
60
  "Session",
60
61
  "Task",
62
+ "TaskData",
61
63
  "TokenCounts",
62
64
  # Space types
63
65
  "ExperienceConfirmation",
acontext/types/session.py CHANGED
@@ -1,10 +1,67 @@
1
1
  """Type definitions for session, message, and task resources."""
2
2
 
3
- from typing import Any
3
+ from typing import Any, Literal, NotRequired, TypedDict, Union
4
4
 
5
5
  from pydantic import BaseModel, Field
6
6
 
7
7
 
8
+ class RemoveToolResultParams(TypedDict, total=False):
9
+ """Parameters for the remove_tool_result edit strategy.
10
+
11
+ Attributes:
12
+ keep_recent_n_tool_results: Number of most recent tool results to keep with original content.
13
+ Defaults to 3 if not specified.
14
+ tool_result_placeholder: Custom text to replace old tool results with.
15
+ Defaults to "Done" if not specified.
16
+ """
17
+
18
+ keep_recent_n_tool_results: NotRequired[int]
19
+ tool_result_placeholder: NotRequired[str]
20
+
21
+
22
+ class RemoveToolResultStrategy(TypedDict):
23
+ """Edit strategy to replace old tool results with placeholder text.
24
+
25
+ Example:
26
+ {"type": "remove_tool_result", "params": {"keep_recent_n_tool_results": 5, "tool_result_placeholder": "Cleared"}}
27
+ """
28
+
29
+ type: Literal["remove_tool_result"]
30
+ params: RemoveToolResultParams
31
+
32
+
33
+ class TokenLimitParams(TypedDict):
34
+ """Parameters for the token_limit edit strategy.
35
+
36
+ Attributes:
37
+ limit_tokens: Maximum number of tokens to keep. Required parameter.
38
+ Messages will be removed from oldest to newest until total tokens <= limit_tokens.
39
+ Tool-call and tool-result pairs are always removed together.
40
+ """
41
+
42
+ limit_tokens: int
43
+
44
+
45
+ class TokenLimitStrategy(TypedDict):
46
+ """Edit strategy to truncate messages based on token count.
47
+
48
+ Removes oldest messages until the total token count is within the specified limit.
49
+ Maintains tool-call/tool-result pairing - when removing a message with tool-calls,
50
+ the corresponding tool-result messages are also removed.
51
+
52
+ Example:
53
+ {"type": "token_limit", "params": {"limit_tokens": 20000}}
54
+ """
55
+
56
+ type: Literal["token_limit"]
57
+ params: TokenLimitParams
58
+
59
+
60
+ # Union type for all edit strategies
61
+ # When adding new strategies, add them to this Union: EditStrategy = Union[RemoveToolResultStrategy, OtherStrategy, ...]
62
+ EditStrategy = Union[RemoveToolResultStrategy, TokenLimitStrategy]
63
+
64
+
8
65
  class Asset(BaseModel):
9
66
  """Asset model representing a file asset."""
10
67
 
@@ -35,7 +92,7 @@ class Message(BaseModel):
35
92
  id: str = Field(..., description="Message UUID")
36
93
  session_id: str = Field(..., description="Session UUID")
37
94
  parent_id: str | None = Field(None, description="Parent message UUID")
38
- role: str = Field(..., description="Message role: 'user', 'assistant', or 'system'")
95
+ role: str = Field(..., description="Message role: 'user' or 'assistant'")
39
96
  meta: dict[str, Any] = Field(..., description="Message metadata")
40
97
  parts: list[Part] = Field(..., description="List of message parts")
41
98
  task_id: str | None = Field(None, description="Task UUID if associated with a task")
@@ -52,6 +109,9 @@ class Session(BaseModel):
52
109
 
53
110
  id: str = Field(..., description="Session UUID")
54
111
  project_id: str = Field(..., description="Project UUID")
112
+ disable_task_tracking: bool = Field(
113
+ False, description="Whether task tracking is disabled for this session"
114
+ )
55
115
  space_id: str | None = Field(None, description="Space UUID, optional")
56
116
  configs: dict[str, Any] | None = Field(
57
117
  None, description="Session configuration dictionary"
@@ -60,6 +120,25 @@ class Session(BaseModel):
60
120
  updated_at: str = Field(..., description="ISO 8601 formatted update timestamp")
61
121
 
62
122
 
123
+ class TaskData(BaseModel):
124
+ """Task data model representing the structured data stored in a task.
125
+
126
+ This schema matches the TaskData model in acontext_core/schema/session/task.py
127
+ and the Go API TaskData struct.
128
+ """
129
+
130
+ task_description: str = Field(..., description="Description of the task")
131
+ progresses: list[str] | None = Field(
132
+ None, description="List of progress updates for the task"
133
+ )
134
+ user_preferences: list[str] | None = Field(
135
+ None, description="List of user preferences related to the task"
136
+ )
137
+ sop_thinking: str | None = Field(
138
+ None, description="Standard Operating Procedure thinking notes"
139
+ )
140
+
141
+
63
142
  class Task(BaseModel):
64
143
  """Task model representing a task in a session."""
65
144
 
@@ -67,7 +146,7 @@ class Task(BaseModel):
67
146
  session_id: str = Field(..., description="Session UUID")
68
147
  project_id: str = Field(..., description="Project UUID")
69
148
  order: int = Field(..., description="Task order")
70
- data: dict[str, Any] = Field(..., description="Task data dictionary")
149
+ data: TaskData = Field(..., description="Structured task data")
71
150
  status: str = Field(
72
151
  ...,
73
152
  description="Task status: 'success', 'failed', 'running', or 'pending'",
@@ -138,4 +217,7 @@ class LearningStatus(BaseModel):
138
217
  class TokenCounts(BaseModel):
139
218
  """Response model for token counts."""
140
219
 
141
- total_tokens: int = Field(..., description="Total token count for all text and tool-call parts in a session")
220
+ total_tokens: int = Field(
221
+ ...,
222
+ description="Total token count for all text and tool-call parts in a session",
223
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: acontext
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: Python SDK for the Acontext API
5
5
  Keywords: acontext,sdk,client,api
6
6
  Requires-Dist: httpx>=0.28.1
@@ -1,4 +1,4 @@
1
- acontext/__init__.py,sha256=CZzHIZ2VEtNQFj0MkH3eDx-A78fSCYsUklDvhYUsD2Y,965
1
+ acontext/__init__.py,sha256=jAgRawWIjyMd6g3gq7Xm_3vNB31cPj8rMFPO4LGQKdM,1027
2
2
  acontext/_constants.py,sha256=-OxfFwn4UdkQiNkyWhBmpM7KnZv6SgR-gMPEkjLKtDA,362
3
3
  acontext/_utils.py,sha256=GKQH45arKh0sDu64u-5jwrII_ctnU_oChYlgR5lRkfE,1250
4
4
  acontext/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -8,26 +8,26 @@ acontext/async_client.py,sha256=mfyR-WVy_LEOXjrkTcXLNaPDC5euaZ9zFI_5e1gapGs,8153
8
8
  acontext/client.py,sha256=jFr5-Q8obdcZBamUNtY3fCklpOJiNiIKLzEApTmbnTg,7920
9
9
  acontext/client_types.py,sha256=uVBWzLbZyXrqkljG49ojdQL_xX6N3n_HGt4Bs_TEE48,987
10
10
  acontext/errors.py,sha256=W9i7_t46q9kbci3XAyZiyQhS154d4R9rSon3na-gjgs,1296
11
- acontext/messages.py,sha256=L-fCnnZ9OIzK3zmumAhHhQ4YdBgoFdDXrb91yz5hGXk,2350
11
+ acontext/messages.py,sha256=oNRZStfhcPFt6DPOfs_-Q7R1Xui6dOMr3wmpmC8pzvE,2310
12
12
  acontext/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  acontext/resources/__init__.py,sha256=KSVQ3YJ-wuU6OWGWJ47gDGbjjetP102aEsVSR8JUb_4,721
14
14
  acontext/resources/async_blocks.py,sha256=e_iJpgcAdwS2tXQ16MMCnySlddp5JV3BadN_EyqZSF4,5555
15
15
  acontext/resources/async_disks.py,sha256=2JjLpUkz5YZEkLt_jCts_khTG_b7lvf4cUMfoaJcnI8,6471
16
- acontext/resources/async_sessions.py,sha256=b5oha4np1-RmNf2eRsnuJ2UJjdPyztExYQF-7_1pIAc,11894
17
- acontext/resources/async_spaces.py,sha256=s3CrIDmabh2tOOPtuDn40aAsFaG2oAVFonjoNPHtiV0,6410
16
+ acontext/resources/async_sessions.py,sha256=oFVcU0rBGD5Mhue7HdKxRQermmSHSlI05eNRgPV-8J4,12541
17
+ acontext/resources/async_spaces.py,sha256=5lIZjI8GmgoMBcftAMD2vDj2FmbLZ6pi1-yNCWKv4cM,6408
18
18
  acontext/resources/async_tools.py,sha256=RbGaF2kX65Mun-q-Fp5H1J8waWTLIdCOfbdY19jpn1o,1091
19
19
  acontext/resources/blocks.py,sha256=HJdAy5HdyTcHCYCPmqNdvApYKZ6aWs-ORIi_wQt3TUM,5447
20
20
  acontext/resources/disks.py,sha256=BjVhVXoujHWhg6L0TG9GmW9HLTTldJYEPxCbuppRkc4,6336
21
- acontext/resources/sessions.py,sha256=9iVd_2ZCxwuUFIfdsp1lRSTHb9JoFTHFkhzT7065kwY,11715
22
- acontext/resources/spaces.py,sha256=krPC836R9FDFrgdxZ-hmcF-mMwrGhI0Cac3zszG0URA,6269
21
+ acontext/resources/sessions.py,sha256=mETp0dtGBi9e20L5f_KbCzw-6oP0pjtUmx-9Vlb8vYA,12634
22
+ acontext/resources/spaces.py,sha256=LJP9krygZGdktMDtYGudCpk7yBxe_4v34QLk3SdejwQ,6267
23
23
  acontext/resources/tools.py,sha256=II_185B0HYKSP43hizE6C1zs7kjkkPLKihuEG8s-DRY,1046
24
- acontext/types/__init__.py,sha256=vrKXYUO8zZ4uIBFqRdnp-DRY0tzTDk7rNSUn0bdpTA8,1418
24
+ acontext/types/__init__.py,sha256=QWNLmdSnLE2b5XRXxnI2OKnHVdKQPJH0nJvvOYwhB1o,1448
25
25
  acontext/types/block.py,sha256=CzKByunk642rWXNNnh8cx67UzKLKDAxODmC_whwjP90,1078
26
26
  acontext/types/disk.py,sha256=g9u3rgCh05rK-gay19NUi-WyzI5Vt1GQwcyKv-5TSC4,2361
27
- acontext/types/session.py,sha256=OprkkCsEbDHrQ_Kpd6yv8lcyoCfV54IcTmNft-gAyPI,5656
27
+ acontext/types/session.py,sha256=HU8i8zxHGfGkHS9YRlh4JDst3aWZLfqSIUVq-HX4GYg,8444
28
28
  acontext/types/space.py,sha256=uxbPrOHYpsntPHqhMCLQ2KovM7BngHC5Q2j7qexVrN8,2537
29
29
  acontext/types/tool.py,sha256=-mVn-vgk2SENK0Ubt-ZgWFZxKa-ddABqcAgXQ69YY-E,805
30
30
  acontext/uploads.py,sha256=6twnqQOY_eerNuEjeSKsE_3S0IfJUiczXtAy4aXqDl8,1379
31
- acontext-0.0.7.dist-info/WHEEL,sha256=z-mOpxbJHqy3cq6SvUThBZdaLGFZzdZPtgWLcP2NKjQ,79
32
- acontext-0.0.7.dist-info/METADATA,sha256=pGwq18SKhhmwrXpVWKB7FHuTplaAmkxEEK4QwidULQI,14395
33
- acontext-0.0.7.dist-info/RECORD,,
31
+ acontext-0.0.9.dist-info/WHEEL,sha256=xDCZ-UyfvkGuEHPeI7BcJzYKIZzdqN8A8o1M5Om8IyA,79
32
+ acontext-0.0.9.dist-info/METADATA,sha256=O1dmjGIvaW5EisSVf5E9huYMe2jo_SmrYUUhy6JVv_Q,14395
33
+ acontext-0.0.9.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.15
2
+ Generator: uv 0.9.17
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any