qoder-agent-sdk 1.0.15__tar.gz → 1.0.16__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 (41) hide show
  1. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/PKG-INFO +29 -1
  2. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/README.md +28 -0
  3. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/pyproject.toml +1 -1
  4. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/__init__.py +16 -0
  5. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_cli_version.py +1 -1
  6. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/message_parser.py +26 -8
  7. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/query.py +16 -0
  8. qoder_agent_sdk-1.0.16/src/qoder_agent_sdk/_tool_results.py +38 -0
  9. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_version.py +1 -1
  10. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/client.py +40 -0
  11. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/types.py +93 -2
  12. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/.gitignore +0 -0
  13. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/LICENSE +0 -0
  14. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_brand.py +0 -0
  15. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_bundled/.gitignore +0 -0
  16. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_errors.py +0 -0
  17. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/__init__.py +0 -0
  18. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/auth_helpers.py +0 -0
  19. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/client.py +0 -0
  20. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/cloud_agent.py +0 -0
  21. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/mcp_handler.py +0 -0
  22. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/mcp_serialize.py +0 -0
  23. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/memory.py +0 -0
  24. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/sdk_mcp_transport.py +0 -0
  25. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/session_mutations.py +0 -0
  26. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/session_storage.py +0 -0
  27. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/sessions.py +0 -0
  28. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/skill_evolution.py +0 -0
  29. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/transport/__init__.py +0 -0
  30. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/_internal/transport/subprocess_cli.py +0 -0
  31. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/auth.py +0 -0
  32. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/memory.py +0 -0
  33. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/plugins.py +0 -0
  34. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/py.typed +0 -0
  35. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/query.py +0 -0
  36. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/session_import.py +0 -0
  37. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/session_store.py +0 -0
  38. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/settings.py +0 -0
  39. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/store_sessions.py +0 -0
  40. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/testing/__init__.py +0 -0
  41. {qoder_agent_sdk-1.0.15 → qoder_agent_sdk-1.0.16}/src/qoder_agent_sdk/testing/session_store_conformance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: qoder-agent-sdk
3
- Version: 1.0.15
3
+ Version: 1.0.16
4
4
  Summary: Python SDK for Qoder Agent
5
5
  Author: Qoder
6
6
  License: Copyright (c) 2026 Qoder
@@ -315,6 +315,34 @@ cancellation, and do not reuse UUIDs within a session.
315
315
  `await client.cancel_async_message(message_uuid)` returns `True` when the
316
316
  queued message is cancelled and `False` when it can no longer be cancelled.
317
317
 
318
+ Manage background tasks from a connected `QoderSDKClient`:
319
+
320
+ ```python
321
+ await client.background_tasks(tool_use_id) # ToolUseBlock.id; omit for bulk conversion
322
+ await client.stop_task(task_id) # TaskStartedMessage.task_id
323
+ ```
324
+
325
+ `background_tasks()` moves running foreground Bash / Agent executions into the
326
+ background; it does not list tasks. A targeted call returns whether the execution
327
+ moved; bulk `True` acknowledges the request without guaranteeing a transition.
328
+ `stop_task()` returns `None` and leaves the main turn and other independent tasks
329
+ running. Unknown IDs and repeated stops are safe no-ops. Both methods require the
330
+ CLI capability `background_tasks_v1` (otherwise `UnsupportedCliCapabilityError`)
331
+ and are unavailable in Cloud Agent sessions.
332
+
333
+ `interrupt()` does not stop existing background tasks. To clean them up, continue
334
+ consuming `receive_messages()` after the main `ResultMessage`, replace the roster
335
+ on each `BackgroundTasksChangedMessage`, and stop each task separately. Bulk
336
+ conversion can detach an Agent's Bash execution as an independent task.
337
+
338
+ Use `AgentDefinition(background=True, ...)` to launch delegated agents in the
339
+ background. Merge `TaskUpdatedMessage.patch` into stored task state. Task events
340
+ retain raw `data`; optional metadata depends on the CLI. Missing progress `usage`
341
+ is `None`, and `total_tokens` can be absent within usage.
342
+
343
+ For event fields, launch result types, the Bash result guard, and examples, see
344
+ [Python SDK Reference](https://docs.qoder.com/cli/sdk/references-python#clientstop-task).
345
+
318
346
  ## External Session Storage
319
347
 
320
348
  Use `session_store` when a host needs durable transcripts outside the local
@@ -273,6 +273,34 @@ cancellation, and do not reuse UUIDs within a session.
273
273
  `await client.cancel_async_message(message_uuid)` returns `True` when the
274
274
  queued message is cancelled and `False` when it can no longer be cancelled.
275
275
 
276
+ Manage background tasks from a connected `QoderSDKClient`:
277
+
278
+ ```python
279
+ await client.background_tasks(tool_use_id) # ToolUseBlock.id; omit for bulk conversion
280
+ await client.stop_task(task_id) # TaskStartedMessage.task_id
281
+ ```
282
+
283
+ `background_tasks()` moves running foreground Bash / Agent executions into the
284
+ background; it does not list tasks. A targeted call returns whether the execution
285
+ moved; bulk `True` acknowledges the request without guaranteeing a transition.
286
+ `stop_task()` returns `None` and leaves the main turn and other independent tasks
287
+ running. Unknown IDs and repeated stops are safe no-ops. Both methods require the
288
+ CLI capability `background_tasks_v1` (otherwise `UnsupportedCliCapabilityError`)
289
+ and are unavailable in Cloud Agent sessions.
290
+
291
+ `interrupt()` does not stop existing background tasks. To clean them up, continue
292
+ consuming `receive_messages()` after the main `ResultMessage`, replace the roster
293
+ on each `BackgroundTasksChangedMessage`, and stop each task separately. Bulk
294
+ conversion can detach an Agent's Bash execution as an independent task.
295
+
296
+ Use `AgentDefinition(background=True, ...)` to launch delegated agents in the
297
+ background. Merge `TaskUpdatedMessage.patch` into stored task state. Task events
298
+ retain raw `data`; optional metadata depends on the CLI. Missing progress `usage`
299
+ is `None`, and `total_tokens` can be absent within usage.
300
+
301
+ For event fields, launch result types, the Bash result guard, and examples, see
302
+ [Python SDK Reference](https://docs.qoder.com/cli/sdk/references-python#clientstop-task).
303
+
276
304
  ## External Session Storage
277
305
 
278
306
  Use `session_store` when a host needs durable transcripts outside the local
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "qoder-agent-sdk"
7
- version = "1.0.15"
7
+ version = "1.0.16"
8
8
  description = "Python SDK for Qoder Agent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -50,6 +50,7 @@ from ._internal.sessions import (
50
50
  project_key_for_directory,
51
51
  )
52
52
  from ._internal.transport import Transport
53
+ from ._tool_results import is_bash_tool_background_launch_result
53
54
  from ._version import __version__
54
55
  from .auth import (
55
56
  DEFAULT_ACCESS_TOKEN_ENV_VAR,
@@ -129,10 +130,14 @@ from .types import (
129
130
  MAX_SKILL_EVOLUTION_REVIEW_THRESHOLD,
130
131
  AgentCreateParams,
131
132
  AgentDefinition,
133
+ AgentToolBackgroundLaunchResult,
132
134
  AssistantMessage,
133
135
  AssistantMessageWithRequestId,
134
136
  AsyncHookJSONOutput,
137
+ BackgroundTask,
138
+ BackgroundTasksChangedMessage,
135
139
  BaseHookInput,
140
+ BashToolBackgroundLaunchResult,
136
141
  BetaManagedAgentsAgentToolName,
137
142
  BetaManagedAgentsAgentToolset20260401Params,
138
143
  BetaManagedAgentsCustomSkillParams,
@@ -331,6 +336,9 @@ from .types import (
331
336
  TaskNotificationStatus,
332
337
  TaskProgressMessage,
333
338
  TaskStartedMessage,
339
+ TaskStatus,
340
+ TaskUpdatedMessage,
341
+ TaskUpdatePatch,
334
342
  TaskUsage,
335
343
  TextBlock,
336
344
  ThinkingBlock,
@@ -983,6 +991,14 @@ __all__ = [
983
991
  "TaskNotificationMessage",
984
992
  "TaskNotificationStatus",
985
993
  "TaskUsage",
994
+ "TaskStatus",
995
+ "TaskUpdatePatch",
996
+ "TaskUpdatedMessage",
997
+ "BackgroundTask",
998
+ "BackgroundTasksChangedMessage",
999
+ "BashToolBackgroundLaunchResult",
1000
+ "AgentToolBackgroundLaunchResult",
1001
+ "is_bash_tool_background_launch_result",
986
1002
  "ResultMessage",
987
1003
  "StreamEvent",
988
1004
  "CloudAgentEventMessage",
@@ -1,3 +1,3 @@
1
1
  """Bundled runtime CLI version."""
2
2
 
3
- __cli_version__ = "1.1.61"
3
+ __cli_version__ = "1.1.76"
@@ -7,6 +7,7 @@ from .._errors import MessageParseError
7
7
  from ..types import (
8
8
  AssistantMessage,
9
9
  AssistantMessageWithRequestId,
10
+ BackgroundTasksChangedMessage,
10
11
  CloudAgentEventMessage,
11
12
  ContentBlock,
12
13
  GoalClearedMessage,
@@ -24,6 +25,7 @@ from ..types import (
24
25
  TaskNotificationMessage,
25
26
  TaskProgressMessage,
26
27
  TaskStartedMessage,
28
+ TaskUpdatedMessage,
27
29
  TextBlock,
28
30
  ThinkingBlock,
29
31
  ToolResultBlock,
@@ -199,6 +201,10 @@ def parse_message(data: dict[str, Any]) -> Message | None:
199
201
  session_id=data["session_id"],
200
202
  tool_use_id=data.get("tool_use_id"),
201
203
  task_type=data.get("task_type"),
204
+ subagent_type=data.get("subagent_type"),
205
+ workflow_name=data.get("workflow_name"),
206
+ prompt=data.get("prompt"),
207
+ tools=data.get("tools"),
202
208
  )
203
209
  case "task_progress":
204
210
  return TaskProgressMessage(
@@ -206,18 +212,13 @@ def parse_message(data: dict[str, Any]) -> Message | None:
206
212
  data=data,
207
213
  task_id=data["task_id"],
208
214
  description=data["description"],
209
- usage=data.get(
210
- "usage",
211
- {
212
- "total_tokens": 0,
213
- "tool_uses": 0,
214
- "duration_ms": 0,
215
- },
216
- ),
215
+ usage=data.get("usage"),
217
216
  uuid=data["uuid"],
218
217
  session_id=data["session_id"],
219
218
  tool_use_id=data.get("tool_use_id"),
220
219
  last_tool_name=data.get("last_tool_name"),
220
+ subagent_type=data.get("subagent_type"),
221
+ summary=data.get("summary"),
221
222
  )
222
223
  case "task_notification":
223
224
  return TaskNotificationMessage(
@@ -232,6 +233,23 @@ def parse_message(data: dict[str, Any]) -> Message | None:
232
233
  tool_use_id=data.get("tool_use_id"),
233
234
  usage=data.get("usage"),
234
235
  )
236
+ case "task_updated":
237
+ return TaskUpdatedMessage(
238
+ subtype=subtype,
239
+ data=data,
240
+ task_id=data["task_id"],
241
+ patch=data["patch"],
242
+ uuid=data["uuid"],
243
+ session_id=data["session_id"],
244
+ )
245
+ case "background_tasks_changed":
246
+ return BackgroundTasksChangedMessage(
247
+ subtype=subtype,
248
+ data=data,
249
+ tasks=data["tasks"],
250
+ uuid=data["uuid"],
251
+ session_id=data["session_id"],
252
+ )
235
253
  case "goal_updated":
236
254
  return GoalUpdatedMessage(
237
255
  subtype=subtype,
@@ -585,6 +585,7 @@ class Query:
585
585
  SIDE_QUESTION_CAPABILITY = "side_question_v1"
586
586
  SKILL_EVOLUTION_CAPABILITY = "skill_evolution_v1"
587
587
  PLAN_MODE_CAPABILITY = "plan_mode_v1"
588
+ BACKGROUND_TASKS_CAPABILITY = "background_tasks_v1"
588
589
 
589
590
  def __init__(
590
591
  self,
@@ -1966,6 +1967,21 @@ class Query:
1966
1967
  """Interrupt the active turn."""
1967
1968
  await self._send_control_request({"subtype": "interrupt"})
1968
1969
 
1970
+ async def stop_task(self, task_id: str) -> None:
1971
+ """Stop exactly one task without aborting the active main-session turn."""
1972
+ await self._require_cli_capability(self.BACKGROUND_TASKS_CAPABILITY)
1973
+ await self._send_control_request({"subtype": "stop_task", "task_id": task_id})
1974
+
1975
+ async def background_tasks(self, tool_use_id: str | None = None) -> bool:
1976
+ """Background one or all eligible foreground executions in this session."""
1977
+ await self._require_cli_capability(self.BACKGROUND_TASKS_CAPABILITY)
1978
+ request: dict[str, Any] = {"subtype": "background_tasks"}
1979
+ if tool_use_id is not None:
1980
+ request["tool_use_id"] = tool_use_id
1981
+ response = await self._send_control_request(request)
1982
+ backgrounded = response.get("backgrounded")
1983
+ return backgrounded if isinstance(backgrounded, bool) else True
1984
+
1969
1985
  async def cancel_async_message(self, message_uuid: str) -> bool:
1970
1986
  """Request cancellation and return whether the queue entry was removed."""
1971
1987
  response = cast(
@@ -0,0 +1,38 @@
1
+ """Runtime guards for typed tool results without changing their wire shape."""
2
+
3
+ from typing import TypeGuard
4
+
5
+ from .types import BashToolBackgroundLaunchResult
6
+
7
+
8
+ def is_bash_tool_background_launch_result(
9
+ value: object,
10
+ ) -> TypeGuard[BashToolBackgroundLaunchResult]:
11
+ """Recognize a background Bash launch result using the TypeScript contract."""
12
+ if not isinstance(value, dict):
13
+ return False
14
+
15
+ def is_integer(number: object) -> bool:
16
+ # JSON numbers can decode as floats; booleans are not wire numbers.
17
+ return type(number) is int or (type(number) is float and number.is_integer())
18
+
19
+ return (
20
+ value.get("kind") == "backgrounded"
21
+ and is_integer(value.get("pid"))
22
+ and value["pid"] > 0
23
+ and isinstance(value.get("taskId"), str)
24
+ and isinstance(value.get("command"), str)
25
+ and isinstance(value.get("initialOutput"), str)
26
+ and all(
27
+ key not in value or isinstance(value[key], str)
28
+ for key in ("outputFile", "stdout", "telemetryExecutionId")
29
+ )
30
+ and all(
31
+ key not in value or (is_integer(value[key]) and value[key] >= 0)
32
+ for key in ("totalLines", "totalBytes")
33
+ )
34
+ and (
35
+ "backgroundReason" not in value
36
+ or value["backgroundReason"] in ("user", "model", "timeout", "auto")
37
+ )
38
+ )
@@ -1,3 +1,3 @@
1
1
  """Version information for qoder-agent-sdk."""
2
2
 
3
- __version__ = "1.0.15"
3
+ __version__ = "1.0.16"
@@ -445,6 +445,46 @@ class QoderSDKClient:
445
445
  raise CLIConnectionError("Not connected. Call connect() first.")
446
446
  await self._query.interrupt()
447
447
 
448
+ async def stop_task(self, task_id: str) -> None:
449
+ """Stop one running task without interrupting the main session turn.
450
+
451
+ Use the task ID from ``TaskStartedMessage.task_id``. The connected
452
+ CLI must advertise ``background_tasks_v1``; older CLIs raise
453
+ ``UnsupportedCliCapabilityError``. Stopping an unknown or already
454
+ finished task succeeds without affecting other tasks.
455
+
456
+ This operation is not supported by the experimental Cloud Agent runtime.
457
+ """
458
+ if not self._query:
459
+ raise CLIConnectionError("Not connected. Call connect() first.")
460
+ if self.options.experimental_cloud_agent is not None:
461
+ raise NotImplementedError(
462
+ "stop_task is not supported by the experimental Cloud Agent runtime"
463
+ )
464
+ await self._query.stop_task(task_id)
465
+
466
+ async def background_tasks(self, tool_use_id: str | None = None) -> bool:
467
+ """Move running foreground Bash/Agent executions into the background.
468
+
469
+ Pass a tool use ID to target one execution, or omit it to target all
470
+ eligible foreground executions in this session. This does not list
471
+ tasks; consume ``BackgroundTasksChangedMessage`` for the current roster.
472
+
473
+ Requires the CLI's ``background_tasks_v1`` capability. A targeted
474
+ request returns whether the execution moved into the background.
475
+ A successful bulk request may have no response body and returns True,
476
+ which acknowledges the request rather than guaranteeing a transition.
477
+ Cloud Agent sessions do not support this operation.
478
+ """
479
+ if not self._query:
480
+ raise CLIConnectionError("Not connected. Call connect() first.")
481
+ if self.options.experimental_cloud_agent is not None:
482
+ raise NotImplementedError(
483
+ "background_tasks is not supported by the experimental Cloud Agent runtime"
484
+ )
485
+ result: bool = await self._query.background_tasks(tool_use_id)
486
+ return result
487
+
448
488
  async def ask_side_question(
449
489
  self,
450
490
  question: str,
@@ -317,6 +317,8 @@ class AgentDefinition:
317
317
  maxTurns: int | None = None # noqa: N815
318
318
  effort: Literal["low", "medium", "high", "max"] | None = None
319
319
  permissionMode: PermissionMode | None = None # noqa: N815
320
+ # Run this agent asynchronously whenever it is invoked.
321
+ background: bool | None = None
320
322
 
321
323
 
322
324
  # Cloud Agent experimental runtime types.
@@ -2000,6 +2002,36 @@ class ToolResultBlock:
2000
2002
  ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
2001
2003
 
2002
2004
 
2005
+ class BashToolBackgroundLaunchResult(TypedDict):
2006
+ """Background Bash launch result; keys preserve the CLI wire spelling."""
2007
+
2008
+ kind: Literal["backgrounded"]
2009
+ # The wire guard accepts integral JSON numbers, including 123.0.
2010
+ pid: int | float
2011
+ taskId: str
2012
+ command: str
2013
+ initialOutput: str
2014
+ outputFile: NotRequired[str]
2015
+ stdout: NotRequired[str]
2016
+ backgroundReason: NotRequired[Literal["user", "model", "timeout", "auto"]]
2017
+ telemetryExecutionId: NotRequired[str]
2018
+ totalLines: NotRequired[int | float]
2019
+ totalBytes: NotRequired[int | float]
2020
+
2021
+
2022
+ class AgentToolBackgroundLaunchResult(TypedDict):
2023
+ """Background Agent launch result, available in ``tool_use_result``."""
2024
+
2025
+ isAsync: Literal[True]
2026
+ status: Literal["async_launched"]
2027
+ agentId: str
2028
+ description: str
2029
+ prompt: str
2030
+ outputFile: str
2031
+ resolvedModel: NotRequired[str]
2032
+ canReadOutputFile: NotRequired[bool]
2033
+
2034
+
2003
2035
  # Message types
2004
2036
  AssistantMessageError = Literal[
2005
2037
  "authentication_failed",
@@ -2144,7 +2176,7 @@ class SDKPermissionDenial(TypedDict):
2144
2176
  class TaskUsage(TypedDict):
2145
2177
  """Usage statistics reported in task_progress and task_notification messages."""
2146
2178
 
2147
- total_tokens: int
2179
+ total_tokens: NotRequired[int]
2148
2180
  tool_uses: int
2149
2181
  duration_ms: int
2150
2182
 
@@ -2168,6 +2200,10 @@ class TaskStartedMessage(SystemMessage):
2168
2200
  session_id: str
2169
2201
  tool_use_id: str | None = None
2170
2202
  task_type: str | None = None
2203
+ subagent_type: str | None = None
2204
+ workflow_name: str | None = None
2205
+ prompt: str | None = None
2206
+ tools: list[str] | None = None
2171
2207
 
2172
2208
 
2173
2209
  @dataclass
@@ -2181,11 +2217,13 @@ class TaskProgressMessage(SystemMessage):
2181
2217
 
2182
2218
  task_id: str
2183
2219
  description: str
2184
- usage: TaskUsage
2220
+ usage: TaskUsage | None
2185
2221
  uuid: str
2186
2222
  session_id: str
2187
2223
  tool_use_id: str | None = None
2188
2224
  last_tool_name: str | None = None
2225
+ subagent_type: str | None = None
2226
+ summary: str | None = None
2189
2227
 
2190
2228
 
2191
2229
  @dataclass
@@ -2207,6 +2245,47 @@ class TaskNotificationMessage(SystemMessage):
2207
2245
  usage: TaskUsage | None = None
2208
2246
 
2209
2247
 
2248
+ TaskStatus = Literal["pending", "running", "completed", "failed", "killed", "paused"]
2249
+
2250
+
2251
+ class TaskUpdatePatch(TypedDict, total=False):
2252
+ """Partial task update. Merge these fields into the stored task state."""
2253
+
2254
+ status: TaskStatus
2255
+ description: str
2256
+ end_time: int
2257
+ total_paused_ms: int
2258
+ error: str
2259
+ is_backgrounded: bool
2260
+
2261
+
2262
+ @dataclass
2263
+ class TaskUpdatedMessage(SystemMessage):
2264
+ """A task state patch, with the original wire message preserved in data."""
2265
+
2266
+ task_id: str
2267
+ patch: TaskUpdatePatch
2268
+ uuid: str
2269
+ session_id: str
2270
+
2271
+
2272
+ class BackgroundTask(TypedDict):
2273
+ """One live entry in a background task roster."""
2274
+
2275
+ task_id: str
2276
+ task_type: str
2277
+ description: str
2278
+
2279
+
2280
+ @dataclass
2281
+ class BackgroundTasksChangedMessage(SystemMessage):
2282
+ """Full live background task roster. Replace the previous roster with tasks."""
2283
+
2284
+ tasks: list[BackgroundTask]
2285
+ uuid: str
2286
+ session_id: str
2287
+
2288
+
2210
2289
  @dataclass
2211
2290
  class ResultMessage:
2212
2291
  """Result message with cost and usage information."""
@@ -2908,6 +2987,16 @@ class SDKControlInterruptRequest(TypedDict):
2908
2987
  subtype: Literal["interrupt"]
2909
2988
 
2910
2989
 
2990
+ class SDKControlStopTaskRequest(TypedDict):
2991
+ subtype: Literal["stop_task"]
2992
+ task_id: str
2993
+
2994
+
2995
+ class SDKControlBackgroundTasksRequest(TypedDict):
2996
+ subtype: Literal["background_tasks"]
2997
+ tool_use_id: NotRequired[str]
2998
+
2999
+
2911
3000
  class SDKControlPermissionRequest(TypedDict):
2912
3001
  subtype: Literal["can_use_tool"]
2913
3002
  tool_name: str
@@ -3119,6 +3208,8 @@ class SDKControlRequest(TypedDict):
3119
3208
  request_id: str
3120
3209
  request: (
3121
3210
  SDKControlInterruptRequest
3211
+ | SDKControlStopTaskRequest
3212
+ | SDKControlBackgroundTasksRequest
3122
3213
  | SDKControlPermissionRequest
3123
3214
  | SDKControlInitializeRequest
3124
3215
  | SDKControlSetPermissionModeRequest