qoder-agent-sdk 1.0.13__tar.gz → 1.0.15__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 (40) hide show
  1. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/.gitignore +1 -0
  2. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/PKG-INFO +65 -1
  3. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/README.md +64 -0
  4. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/pyproject.toml +1 -1
  5. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/__init__.py +106 -0
  6. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_brand.py +1 -0
  7. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_cli_version.py +1 -1
  8. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_errors.py +11 -0
  9. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/client.py +17 -2
  10. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/cloud_agent.py +9 -0
  11. qoder_agent_sdk-1.0.15/src/qoder_agent_sdk/_internal/memory.py +186 -0
  12. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/message_parser.py +47 -0
  13. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/query.py +618 -62
  14. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/session_mutations.py +27 -25
  15. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/sessions.py +187 -73
  16. qoder_agent_sdk-1.0.15/src/qoder_agent_sdk/_internal/skill_evolution.py +276 -0
  17. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/transport/subprocess_cli.py +62 -11
  18. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_version.py +1 -1
  19. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/auth.py +3 -1
  20. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/client.py +200 -11
  21. qoder_agent_sdk-1.0.15/src/qoder_agent_sdk/memory.py +142 -0
  22. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/plugins.py +25 -10
  23. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/query.py +15 -0
  24. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/store_sessions.py +15 -16
  25. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/types.py +439 -8
  26. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/LICENSE +0 -0
  27. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_bundled/.gitignore +0 -0
  28. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/__init__.py +0 -0
  29. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/auth_helpers.py +0 -0
  30. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/mcp_handler.py +0 -0
  31. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/mcp_serialize.py +0 -0
  32. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/sdk_mcp_transport.py +0 -0
  33. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/session_storage.py +0 -0
  34. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/_internal/transport/__init__.py +0 -0
  35. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/py.typed +0 -0
  36. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/session_import.py +0 -0
  37. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/session_store.py +0 -0
  38. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/settings.py +0 -0
  39. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/testing/__init__.py +0 -0
  40. {qoder_agent_sdk-1.0.13 → qoder_agent_sdk-1.0.15}/src/qoder_agent_sdk/testing/session_store_conformance.py +0 -0
@@ -27,6 +27,7 @@ ENV/
27
27
  env/
28
28
  .venv
29
29
  .venv-release/
30
+ .venv-e2e-build/
30
31
  .tmp-brand-packages/
31
32
  .tmp-qoder-python-release-plan.json
32
33
  uv.lock
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: qoder-agent-sdk
3
- Version: 1.0.13
3
+ Version: 1.0.15
4
4
  Summary: Python SDK for Qoder Agent
5
5
  Author: Qoder
6
6
  License: Copyright (c) 2026 Qoder
@@ -160,6 +160,27 @@ async for message in query(prompt="Explain this repository", options=options):
160
160
  print(block.text)
161
161
  ```
162
162
 
163
+ ## Code Security
164
+
165
+ Built-in code security is disabled by default in SDK sessions. Enable only the
166
+ capabilities the integration needs:
167
+
168
+ ```python
169
+ options = QoderAgentOptions(
170
+ auth=qodercli_auth(),
171
+ cwd="/path/to/project",
172
+ security_scan={
173
+ "l1_static_check": True,
174
+ "l2_lightweight_scan": True,
175
+ "l3_deep_scan": False,
176
+ },
177
+ )
178
+ ```
179
+
180
+ Omitted switches remain disabled. The top-level option is authoritative for
181
+ the SDK session. Enabling any switch also makes the native security skill
182
+ available; project and file scans do not have a separate switch.
183
+
163
184
  ## Tools and Permissions
164
185
 
165
186
  Qoder Agent can use tools such as file reads, file edits, shell commands, and
@@ -213,6 +234,30 @@ options = QoderAgentOptions(
213
234
  )
214
235
  ```
215
236
 
237
+ ## Plan Mode
238
+
239
+ Plan Mode is independent from tool permissions. Set its initial state with
240
+ `plan_mode`; the SDK applies it after the CLI handshake and before the first
241
+ user message, while preserving the underlying `permission_mode`:
242
+
243
+ ```python
244
+ options = QoderAgentOptions(
245
+ auth=qodercli_auth(),
246
+ permission_mode="default",
247
+ plan_mode=True,
248
+ )
249
+ ```
250
+
251
+ For a live session, use `await client.set_plan_mode(True | False)` to switch
252
+ the state and `await client.get_plan_mode()` to read the authoritative current
253
+ state. These APIs require a CLI that advertises the `plan_mode_v1` capability.
254
+
255
+ For compatibility with existing consumers, `SystemMessage` init data projects
256
+ `permissionMode` as `"plan"` while Plan Mode is active. This does not replace
257
+ the underlying tool permission mode; after leaving Plan Mode, the field reports
258
+ that mode again. Use the Plan APIs and `PlanModeChangedMessage` as the
259
+ authoritative Plan state.
260
+
216
261
  ## Working Directory
217
262
 
218
263
  Use `cwd` to run the agent in a specific project directory:
@@ -337,6 +382,21 @@ available through `list_subagents` / `get_subagent_messages` and
337
382
  `import_session_to_store` to copy an existing local main transcript,
338
383
  child-agent transcripts, and metadata into a store.
339
384
 
385
+ Session message readers default to `view="runtime"`, which returns the latest
386
+ Compact Summary and messages written after it. Pass `view="historical"` to
387
+ `get_session_messages` or `get_session_messages_from_store` to read the real
388
+ active lineage across Compact boundaries; Compact Boundary and Summary records
389
+ are hidden from that projection. The local and external `fork_session` helpers
390
+ use the same historical lineage, so `up_to_message_id` may target a message
391
+ before Compact.
392
+
393
+ For a running local session, `QoderSDKClient.rewind()` previews or executes a
394
+ `conversation`, `files`, or `both` rewind when the bundled CLI advertises
395
+ `session_rewind_v1`. To start a new process from a persisted historical node,
396
+ set `QoderAgentOptions.resume`, `resume_session_at`, and optionally
397
+ `resume_drops_turn`; combine them with `fork_session=True` to preserve the
398
+ source session.
399
+
340
400
  ### Production stores
341
401
 
342
402
  The SDK exports the `SessionStore` protocol but does not ship a
@@ -345,6 +405,10 @@ against shared storage operated by your application, then validate its
345
405
  append/load ordering, project isolation, subkey handling, and deletion behavior
346
406
  with `run_session_store_conformance`.
347
407
 
408
+ ## Memory
409
+
410
+ Configure native or custom memory with `QoderAgentOptions(memory=...)`. Interactive clients expose `flush_memory()` and `refresh_memory()`. See [Memory](doc/memory.md) for configuration, generation callbacks, and lifecycle behavior.
411
+
348
412
  ## Custom Tools
349
413
 
350
414
  You can expose Python functions to Qoder Agent as in-process SDK MCP servers.
@@ -118,6 +118,27 @@ async for message in query(prompt="Explain this repository", options=options):
118
118
  print(block.text)
119
119
  ```
120
120
 
121
+ ## Code Security
122
+
123
+ Built-in code security is disabled by default in SDK sessions. Enable only the
124
+ capabilities the integration needs:
125
+
126
+ ```python
127
+ options = QoderAgentOptions(
128
+ auth=qodercli_auth(),
129
+ cwd="/path/to/project",
130
+ security_scan={
131
+ "l1_static_check": True,
132
+ "l2_lightweight_scan": True,
133
+ "l3_deep_scan": False,
134
+ },
135
+ )
136
+ ```
137
+
138
+ Omitted switches remain disabled. The top-level option is authoritative for
139
+ the SDK session. Enabling any switch also makes the native security skill
140
+ available; project and file scans do not have a separate switch.
141
+
121
142
  ## Tools and Permissions
122
143
 
123
144
  Qoder Agent can use tools such as file reads, file edits, shell commands, and
@@ -171,6 +192,30 @@ options = QoderAgentOptions(
171
192
  )
172
193
  ```
173
194
 
195
+ ## Plan Mode
196
+
197
+ Plan Mode is independent from tool permissions. Set its initial state with
198
+ `plan_mode`; the SDK applies it after the CLI handshake and before the first
199
+ user message, while preserving the underlying `permission_mode`:
200
+
201
+ ```python
202
+ options = QoderAgentOptions(
203
+ auth=qodercli_auth(),
204
+ permission_mode="default",
205
+ plan_mode=True,
206
+ )
207
+ ```
208
+
209
+ For a live session, use `await client.set_plan_mode(True | False)` to switch
210
+ the state and `await client.get_plan_mode()` to read the authoritative current
211
+ state. These APIs require a CLI that advertises the `plan_mode_v1` capability.
212
+
213
+ For compatibility with existing consumers, `SystemMessage` init data projects
214
+ `permissionMode` as `"plan"` while Plan Mode is active. This does not replace
215
+ the underlying tool permission mode; after leaving Plan Mode, the field reports
216
+ that mode again. Use the Plan APIs and `PlanModeChangedMessage` as the
217
+ authoritative Plan state.
218
+
174
219
  ## Working Directory
175
220
 
176
221
  Use `cwd` to run the agent in a specific project directory:
@@ -295,6 +340,21 @@ available through `list_subagents` / `get_subagent_messages` and
295
340
  `import_session_to_store` to copy an existing local main transcript,
296
341
  child-agent transcripts, and metadata into a store.
297
342
 
343
+ Session message readers default to `view="runtime"`, which returns the latest
344
+ Compact Summary and messages written after it. Pass `view="historical"` to
345
+ `get_session_messages` or `get_session_messages_from_store` to read the real
346
+ active lineage across Compact boundaries; Compact Boundary and Summary records
347
+ are hidden from that projection. The local and external `fork_session` helpers
348
+ use the same historical lineage, so `up_to_message_id` may target a message
349
+ before Compact.
350
+
351
+ For a running local session, `QoderSDKClient.rewind()` previews or executes a
352
+ `conversation`, `files`, or `both` rewind when the bundled CLI advertises
353
+ `session_rewind_v1`. To start a new process from a persisted historical node,
354
+ set `QoderAgentOptions.resume`, `resume_session_at`, and optionally
355
+ `resume_drops_turn`; combine them with `fork_session=True` to preserve the
356
+ source session.
357
+
298
358
  ### Production stores
299
359
 
300
360
  The SDK exports the `SessionStore` protocol but does not ship a
@@ -303,6 +363,10 @@ against shared storage operated by your application, then validate its
303
363
  append/load ordering, project isolation, subkey handling, and deletion behavior
304
364
  with `run_session_store_conformance`.
305
365
 
366
+ ## Memory
367
+
368
+ Configure native or custom memory with `QoderAgentOptions(memory=...)`. Interactive clients expose `flush_memory()` and `refresh_memory()`. See [Memory](doc/memory.md) for configuration, generation callbacks, and lifecycle behavior.
369
+
306
370
  ## Custom Tools
307
371
 
308
372
  You can expose Python functions to Qoder Agent as in-process SDK MCP servers.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "qoder-agent-sdk"
7
- version = "1.0.13"
7
+ version = "1.0.15"
8
8
  description = "Python SDK for Qoder Agent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -32,6 +32,7 @@ from ._errors import (
32
32
  ModelPolicyTimeoutError,
33
33
  ProcessError,
34
34
  QoderSDKError,
35
+ UnsupportedCliCapabilityError,
35
36
  )
36
37
  from ._internal.session_mutations import (
37
38
  ForkSessionResult,
@@ -77,6 +78,29 @@ from .auth import (
77
78
  service_account_from_env,
78
79
  )
79
80
  from .client import QoderSDKClient
81
+ from .memory import (
82
+ EffectiveMemoryConfig,
83
+ EffectiveMemoryRoot,
84
+ MemoryConsumptionCallback,
85
+ MemoryConsumptionFile,
86
+ MemoryConsumptionFileResult,
87
+ MemoryConsumptionOptions,
88
+ MemoryConsumptionResult,
89
+ MemoryGateContext,
90
+ MemoryGenerationCallback,
91
+ MemoryGenerationFailedFile,
92
+ MemoryGenerationGateInput,
93
+ MemoryGenerationGateResult,
94
+ MemoryGenerationOptions,
95
+ MemoryGenerationResult,
96
+ MemoryMode,
97
+ MemoryOptions,
98
+ MemoryRoot,
99
+ MemoryRootAccess,
100
+ MemoryShouldGenerate,
101
+ MemoryTurnCompleteOptions,
102
+ MemoryWrittenFile,
103
+ )
80
104
  from .plugins import (
81
105
  PluginError,
82
106
  disable_plugin,
@@ -102,6 +126,7 @@ from .store_sessions import (
102
126
  tag_session_via_store,
103
127
  )
104
128
  from .types import (
129
+ MAX_SKILL_EVOLUTION_REVIEW_THRESHOLD,
105
130
  AgentCreateParams,
106
131
  AgentDefinition,
107
132
  AssistantMessage,
@@ -145,10 +170,15 @@ from .types import (
145
170
  CwdChangedHookSpecificOutput,
146
171
  ElicitationRequest,
147
172
  ElicitationResult,
173
+ EvolutionOptions,
148
174
  ExitPlanModeApprovalDetails,
149
175
  ExitReason,
150
176
  FileChangedHookInput,
151
177
  FileChangedHookSpecificOutput,
178
+ GoalClearedMessage,
179
+ GoalSnapshot,
180
+ GoalStatus,
181
+ GoalUpdatedMessage,
152
182
  HookCallback,
153
183
  HookContext,
154
184
  HookEvent,
@@ -179,6 +209,8 @@ from .types import (
179
209
  McpStatusResponse,
180
210
  McpToolAnnotations,
181
211
  McpToolInfo,
212
+ MemoryConsumptionMessage,
213
+ MemoryGenerationMessage,
182
214
  Message,
183
215
  ModelContextConfig,
184
216
  ModelContextWindowEntry,
@@ -209,9 +241,12 @@ from .types import (
209
241
  PermissionResultAllow,
210
242
  PermissionResultDeny,
211
243
  PermissionUpdate,
244
+ PlanModeChangedMessage,
245
+ PlanModeSnapshot,
212
246
  PluginDetails,
213
247
  PluginInfo,
214
248
  PluginResources,
249
+ PluginScope,
215
250
  PluginValidationDiagnostic,
216
251
  PluginValidationLocation,
217
252
  PluginValidationPhase,
@@ -237,7 +272,11 @@ from .types import (
237
272
  ResolvedSettings,
238
273
  ResolvedSettingsSource,
239
274
  ResultMessage,
275
+ RewindFileFailure,
240
276
  RewindFilesResult,
277
+ RewindResult,
278
+ RewindScope,
279
+ RewindStatus,
241
280
  SDKCapabilities,
242
281
  SDKControlGetByokConfigRequest,
243
282
  SDKControlGetByokConfigResponse,
@@ -249,6 +288,7 @@ from .types import (
249
288
  SDKPermissionDeniedMessage,
250
289
  SdkPluginConfig,
251
290
  SDKSessionInfo,
291
+ SecurityScanOptions,
252
292
  ServerModelJson,
253
293
  ServerModelJsonValue,
254
294
  SessionCreateParams,
@@ -258,6 +298,7 @@ from .types import (
258
298
  SessionKey,
259
299
  SessionListSubkeysKey,
260
300
  SessionMessage,
301
+ SessionMessageView,
261
302
  SessionStartHookInput,
262
303
  SessionStartHookSpecificOutput,
263
304
  SessionStore,
@@ -266,6 +307,19 @@ from .types import (
266
307
  SessionStoreListEntry,
267
308
  Settings,
268
309
  SettingSource,
310
+ SideQuestionHistoryEntry,
311
+ SideQuestionRefusalFallback,
312
+ SideQuestionResult,
313
+ SkillEvolutionGateRequest,
314
+ SkillEvolutionGateResult,
315
+ SkillEvolutionGenerationOptions,
316
+ SkillEvolutionMessage,
317
+ SkillEvolutionOptions,
318
+ SkillEvolutionResult,
319
+ SkillEvolutionResultCallback,
320
+ SkillEvolutionShouldReview,
321
+ SkillEvolutionSuggestion,
322
+ SkillEvolutionTurnCompleteOptions,
269
323
  StopHookInput,
270
324
  StreamEvent,
271
325
  SubagentStartHookInput,
@@ -815,6 +869,35 @@ def create_sdk_mcp_server(
815
869
 
816
870
 
817
871
  __all__ = [
872
+ "EffectiveMemoryConfig",
873
+ "EffectiveMemoryRoot",
874
+ "MemoryMode",
875
+ "MemoryRootAccess",
876
+ "MemoryRoot",
877
+ "MemoryConsumptionFile",
878
+ "MemoryGenerationGateInput",
879
+ "MemoryGenerationGateResult",
880
+ "MemoryGateContext",
881
+ "MemoryWrittenFile",
882
+ "MemoryGenerationFailedFile",
883
+ "MemoryGenerationResult",
884
+ "MemoryConsumptionFileResult",
885
+ "MemoryConsumptionResult",
886
+ "MemoryShouldGenerate",
887
+ "MemoryGenerationCallback",
888
+ "MemoryConsumptionCallback",
889
+ "MemoryTurnCompleteOptions",
890
+ "MemoryGenerationOptions",
891
+ "MemoryConsumptionOptions",
892
+ "MemoryOptions",
893
+ "MemoryGenerationMessage",
894
+ "MemoryConsumptionMessage",
895
+ "GoalClearedMessage",
896
+ "GoalSnapshot",
897
+ "GoalStatus",
898
+ "GoalUpdatedMessage",
899
+ "PlanModeChangedMessage",
900
+ "PlanModeSnapshot",
818
901
  # Main exports
819
902
  "query",
820
903
  "__version__",
@@ -905,6 +988,19 @@ __all__ = [
905
988
  "CloudAgentEventMessage",
906
989
  "Message",
907
990
  "QoderAgentOptions",
991
+ "SecurityScanOptions",
992
+ "EvolutionOptions",
993
+ "SkillEvolutionOptions",
994
+ "MAX_SKILL_EVOLUTION_REVIEW_THRESHOLD",
995
+ "SkillEvolutionGenerationOptions",
996
+ "SkillEvolutionTurnCompleteOptions",
997
+ "SkillEvolutionMessage",
998
+ "SkillEvolutionResult",
999
+ "SkillEvolutionSuggestion",
1000
+ "SkillEvolutionGateRequest",
1001
+ "SkillEvolutionGateResult",
1002
+ "SkillEvolutionShouldReview",
1003
+ "SkillEvolutionResultCallback",
908
1004
  "TextBlock",
909
1005
  "ThinkingBlock",
910
1006
  "ToolUseBlock",
@@ -920,6 +1016,9 @@ __all__ = [
920
1016
  "ContextUsageSkills",
921
1017
  "ContextUsageToolCalls",
922
1018
  "ContextUsageWindow",
1019
+ "SideQuestionHistoryEntry",
1020
+ "SideQuestionRefusalFallback",
1021
+ "SideQuestionResult",
923
1022
  "NonNullableUsage",
924
1023
  "ModelUsage",
925
1024
  "SessionCreditsModelUsage",
@@ -1013,6 +1112,7 @@ __all__ = [
1013
1112
  "PluginInfo",
1014
1113
  "PluginDetails",
1015
1114
  "PluginResources",
1115
+ "PluginScope",
1016
1116
  "InstallPluginResult",
1017
1117
  "UninstallPluginResult",
1018
1118
  "PluginValidationSeverity",
@@ -1036,6 +1136,10 @@ __all__ = [
1036
1136
  "PluginError",
1037
1137
  # File checkpointing
1038
1138
  "RewindFilesResult",
1139
+ "RewindFileFailure",
1140
+ "RewindResult",
1141
+ "RewindScope",
1142
+ "RewindStatus",
1039
1143
  # Session listing
1040
1144
  "list_sessions",
1041
1145
  "get_session_info",
@@ -1044,6 +1148,7 @@ __all__ = [
1044
1148
  "get_subagent_messages",
1045
1149
  "SDKSessionInfo",
1046
1150
  "SessionMessage",
1151
+ "SessionMessageView",
1047
1152
  # Session mutations
1048
1153
  "rename_session",
1049
1154
  "tag_session",
@@ -1068,6 +1173,7 @@ __all__ = [
1068
1173
  "ProcessError",
1069
1174
  "CLIJSONDecodeError",
1070
1175
  "ModelPolicyTimeoutError",
1176
+ "UnsupportedCliCapabilityError",
1071
1177
  # Model Policy
1072
1178
  "ModelInfo",
1073
1179
  "ModelContextConfig",
@@ -16,3 +16,4 @@ ACCESS_TOKEN_ENV = (
16
16
  SERVICE_ACCOUNT_ENV = (
17
17
  "QODERCN_SERVICE_ACCOUNT_KEY" if IS_CN_SDK else "QODER_SERVICE_ACCOUNT_KEY"
18
18
  )
19
+ VPC_ENDPOINT_ENV = "QODERCN_VPC_ENDPOINT" if IS_CN_SDK else "QODER_VPC_ENDPOINT"
@@ -1,3 +1,3 @@
1
1
  """Bundled runtime CLI version."""
2
2
 
3
- __cli_version__ = "1.1.23"
3
+ __cli_version__ = "1.1.61"
@@ -111,6 +111,17 @@ class CLIJSONDecodeError(QoderSDKError):
111
111
  super().__init__(f"Failed to decode JSON: {line[:100]}...")
112
112
 
113
113
 
114
+ class UnsupportedCliCapabilityError(QoderSDKError):
115
+ """Raised when the running CLI does not advertise a required capability."""
116
+
117
+ def __init__(self, capability: str):
118
+ self.capability = capability
119
+ super().__init__(
120
+ "The running qodercli does not advertise the required capability "
121
+ f'"{capability}". Upgrade qodercli or use a matching bundled SDK runtime.'
122
+ )
123
+
124
+
114
125
  class MessageParseError(QoderSDKError):
115
126
  """Raised when unable to parse a message from CLI output."""
116
127
 
@@ -1,6 +1,5 @@
1
1
  """Internal client implementation."""
2
2
 
3
- import json
4
3
  from collections.abc import AsyncIterable, AsyncIterator
5
4
  from dataclasses import asdict, replace
6
5
  from typing import Any
@@ -17,12 +16,16 @@ from .auth_helpers import (
17
16
  get_fetch_service_account_token,
18
17
  once_callback,
19
18
  )
19
+ from .memory import prepare_memory_options
20
20
  from .message_parser import parse_message
21
21
  from .query import Query, resolve_initialize_timeout
22
22
  from .session_storage import (
23
23
  materialize_session_from_store,
24
24
  validate_session_storage_options,
25
25
  )
26
+ from .skill_evolution import (
27
+ prepare_evolution_options,
28
+ )
26
29
  from .transport import Transport
27
30
  from .transport.subprocess_cli import SubprocessCLITransport
28
31
 
@@ -61,6 +64,13 @@ class InternalClient:
61
64
 
62
65
  # Validate and configure permission settings (matching TypeScript SDK logic)
63
66
  configured_options = options
67
+ normalized_evolution, normalized_skill_evolution = prepare_evolution_options(
68
+ configured_options.evolution
69
+ )
70
+ if normalized_evolution is not configured_options.evolution:
71
+ configured_options = replace(
72
+ configured_options, evolution=normalized_evolution
73
+ )
64
74
  validate_session_storage_options(
65
75
  options.session_store,
66
76
  options.session_store_flush,
@@ -92,6 +102,7 @@ class InternalClient:
92
102
  configured_options, on_auth_expired=on_auth_expired
93
103
  )
94
104
 
105
+ prepared_memory = prepare_memory_options(configured_options.memory)
95
106
  requires_store_resume = configured_options.session_store is not None and (
96
107
  configured_options.resume is not None
97
108
  or configured_options.continue_conversation
@@ -161,6 +172,7 @@ class InternalClient:
161
172
  try:
162
173
  query = Query(
163
174
  transport=chosen_transport,
175
+ memory=prepared_memory,
164
176
  is_streaming_mode=True, # Always streaming internally
165
177
  can_use_tool=configured_options.can_use_tool,
166
178
  hooks=convert_hooks_to_internal_format(configured_options.hooks)
@@ -172,6 +184,7 @@ class InternalClient:
172
184
  skills=configured_options.skills
173
185
  if isinstance(configured_options.skills, list)
174
186
  else None,
187
+ initial_plan_mode=configured_options.plan_mode,
175
188
  enable_file_checkpointing=configured_options.enable_file_checkpointing,
176
189
  on_mcp_oauth_required=configured_options.on_mcp_oauth_required,
177
190
  on_mcp_status_change=configured_options.on_mcp_status_change,
@@ -186,6 +199,8 @@ class InternalClient:
186
199
  resolve_model_timeout_ms=configured_options.resolve_model_timeout_ms,
187
200
  session_store=configured_options.session_store,
188
201
  session_store_flush=configured_options.session_store_flush,
202
+ default_custom_context=configured_options.custom_context,
203
+ skill_evolution=normalized_skill_evolution,
189
204
  )
190
205
  except BaseException:
191
206
  await chosen_transport.close()
@@ -210,7 +225,7 @@ class InternalClient:
210
225
  "message": {"role": "user", "content": prompt},
211
226
  "parent_tool_use_id": None,
212
227
  }
213
- await chosen_transport.write(json.dumps(user_message) + "\n")
228
+ await query.write_user_message(user_message)
214
229
  query.spawn_task(query.wait_for_result_and_end_input())
215
230
  elif isinstance(prompt, AsyncIterable):
216
231
  # Stream input in background for async iterables
@@ -950,6 +950,15 @@ class CloudAgentClientSession:
950
950
  _ = dry_run
951
951
  self._unsupported("rewind_files")
952
952
 
953
+ async def rewind(
954
+ self,
955
+ _user_message_id: str,
956
+ scope: str = "both",
957
+ dry_run: bool = False,
958
+ ) -> Any:
959
+ _ = (scope, dry_run)
960
+ self._unsupported("rewind")
961
+
953
962
  async def reload_plugins(self) -> Any:
954
963
  self._unsupported("reload_plugins")
955
964