healthcloud-cli 3.7.6__tar.gz → 3.7.7__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 (92) hide show
  1. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/PKG-INFO +22 -8
  2. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/README.md +21 -7
  3. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/context.py +25 -9
  4. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/sessions/commands.py +2 -2
  5. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/sessions/operations.py +42 -15
  6. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/pyproject.toml +1 -1
  7. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/.gitignore +0 -0
  8. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/hatch_build.py +0 -0
  9. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/__init__.py +0 -0
  10. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/admins/__init__.py +0 -0
  11. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/admins/commands.py +0 -0
  12. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/admins/group.py +0 -0
  13. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/admins/operations.py +0 -0
  14. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/__init__.py +0 -0
  15. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/agents/__init__.py +0 -0
  16. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/agents/commands.py +0 -0
  17. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/agents/group.py +0 -0
  18. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/agents/operations.py +0 -0
  19. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/agents/projections.py +0 -0
  20. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/auth.py +0 -0
  21. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/commands.py +0 -0
  22. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/compatibility.py +0 -0
  23. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/data_sources/__init__.py +0 -0
  24. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/data_sources/commands.py +0 -0
  25. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/data_sources/group.py +0 -0
  26. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/data_sources/operations.py +0 -0
  27. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/data_sources/projections.py +0 -0
  28. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/departments/__init__.py +0 -0
  29. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/departments/commands.py +0 -0
  30. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/departments/group.py +0 -0
  31. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/departments/operations.py +0 -0
  32. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/departments/projections.py +0 -0
  33. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/domain_errors.py +0 -0
  34. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/errors.py +0 -0
  35. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/group.py +0 -0
  36. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/guardrails/__init__.py +0 -0
  37. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/guardrails/commands.py +0 -0
  38. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/guardrails/group.py +0 -0
  39. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/guardrails/operations.py +0 -0
  40. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/guardrails/projections.py +0 -0
  41. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/organization/__init__.py +0 -0
  42. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/organization/commands.py +0 -0
  43. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/organization/group.py +0 -0
  44. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/organization/operations.py +0 -0
  45. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/organization/projections.py +0 -0
  46. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/output.py +0 -0
  47. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/policies/__init__.py +0 -0
  48. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/policies/commands.py +0 -0
  49. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/policies/group.py +0 -0
  50. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/policies/operations.py +0 -0
  51. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/policies/projections.py +0 -0
  52. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/pretty.py +0 -0
  53. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/registry.py +0 -0
  54. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/results.py +0 -0
  55. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/session.py +0 -0
  56. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/sessions/__init__.py +0 -0
  57. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/sessions/group.py +0 -0
  58. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/sessions/projections.py +0 -0
  59. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/skills/__init__.py +0 -0
  60. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/skills/commands.py +0 -0
  61. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/skills/group.py +0 -0
  62. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/skills/operations.py +0 -0
  63. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/skills/projections.py +0 -0
  64. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/target.py +0 -0
  65. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/teams/__init__.py +0 -0
  66. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/teams/commands.py +0 -0
  67. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/teams/group.py +0 -0
  68. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/teams/operations.py +0 -0
  69. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/teams/projections.py +0 -0
  70. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/tools/__init__.py +0 -0
  71. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/tools/commands.py +0 -0
  72. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/tools/group.py +0 -0
  73. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/tools/operations.py +0 -0
  74. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/tools/projections.py +0 -0
  75. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/tuning.py +0 -0
  76. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/ui.py +0 -0
  77. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/ams/windows_files.py +0 -0
  78. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/cli.py +0 -0
  79. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/context.py +0 -0
  80. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/contracts/__init__.py +0 -0
  81. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/contracts/mcp-tools.manifest.json +0 -0
  82. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/main.py +0 -0
  83. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/manifest.py +0 -0
  84. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/output.py +0 -0
  85. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/params.py +0 -0
  86. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/tenants/__init__.py +0 -0
  87. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/tenants/commands.py +0 -0
  88. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/tenants/group.py +0 -0
  89. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/tenants/operations.py +0 -0
  90. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/healthcloud_cli/util.py +0 -0
  91. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/scripts/__init__.py +0 -0
  92. {healthcloud_cli-3.7.6 → healthcloud_cli-3.7.7}/scripts/bundle_manifest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: healthcloud-cli
3
- Version: 3.7.6
3
+ Version: 3.7.7
4
4
  Summary: Command-line interface for the HealthCloud MCP gateway, generated from the shared MCP tool manifest.
5
5
  Project-URL: Issues, https://github.com/healthcloudservices/healthcloud-services/issues
6
6
  Project-URL: Repository, https://github.com/healthcloudservices/healthcloud-services
@@ -1082,9 +1082,14 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
1082
1082
 
1083
1083
  - `list` emits `operation: "sessions.list"`, `data.sessions` (bounded projections
1084
1084
  of session ID, agent ID, operation, mode, status and audit timestamps) and a
1085
- `page` block (`{"kind": "limit", "limit": N, "returned_count": N,
1086
- "continuation": null}`). `get` emits `operation: "sessions.get"` and
1087
- `data.session`. The projections never include the session's protected
1085
+ `page` block. These routes page with a limit only, so the block always says
1086
+ which limit was in force: with `--limit N` it is
1087
+ `{"kind": "limit", "limit": N, "returned_count": N, "continuation": null}`,
1088
+ and without it the server's own default page was applied, which the block
1089
+ reports as `{"kind": "server_default", "server_default_limit": 50,
1090
+ "returned_count": N, "continuation": null}` (50 sessions, 100 messages) — so
1091
+ a truncated page is never mistaken for a complete list. `get` emits
1092
+ `operation: "sessions.get"` and `data.session`. The projections never include the session's protected
1088
1093
  `initial_prompt`, tenant or user identity, or arbitrary response fields.
1089
1094
  - Default `pretty` output prints `list` as a table with honest headers —
1090
1095
  `ID`, `AGENT ID`, `OPERATION`, `STATUS`, `EXPIRES AT` for sessions and `ID`,
@@ -1133,7 +1138,11 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
1133
1138
  - `--initial-prompt` becomes the session's first `user` message in the same
1134
1139
  server transaction; `hc ams sessions messages list` shows it afterwards.
1135
1140
  - `--mode implement` is not available from the server yet: `create` reports one
1136
- `unsupported` refusal (the server answers 501) and creates nothing. A message
1141
+ `unsupported` refusal (the server answers 501) and creates nothing, and a
1142
+ `messages add` the server answers 501 for is the same `unsupported` refusal
1143
+ with no message added. Both refusals report the 501 the server actually sent
1144
+ and name implement mode as the documented reason, rather than asserting the
1145
+ requested mode was the cause. A message
1137
1146
  whose `--mode` differs from its session's mode is refused by the server with
1138
1147
  409 and reported as one write-worded `conflict` refusal that names the
1139
1148
  session, mentions a mode mismatch as one possible cause, and points at
@@ -1156,9 +1165,14 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
1156
1165
  - Reads refuse target files, root credentials or base URLs, raw output, blank or
1157
1166
  dot-segment session IDs, out-of-range limits, and installed SDKs without the
1158
1167
  session list/get and message list methods before tenant-admin login or any
1159
- read; `messages list` needs only `messages.list` — the write method `add` is
1160
- not required for the read, and `messages add` still refuses `unsupported`
1161
- without it. The existing `hc ams plan|show|apply|restore` tuning commands and their
1168
+ read. `messages list` needs only `messages.list` — the write method `add` is
1169
+ not required for the read. The writes check their own methods in the same
1170
+ preflight — each command requires exactly the write method it calls, so
1171
+ `create` refuses an installed SDK without `sessions.create` and `messages add`
1172
+ one without `messages.add` before tenant-admin login and before any read or
1173
+ write, and neither is refused for the write the other command performs. A single-object route whose 2xx body is not a JSON
1174
+ object is refused as a `validation` error, never reported as an internal
1175
+ failure. The existing `hc ams plan|show|apply|restore` tuning commands and their
1162
1176
  signatures are unchanged.
1163
1177
  - These session and message commands do not attach files, apply or roll back
1164
1178
  configuration, or send session history to a model. Plan review is its own
@@ -1064,9 +1064,14 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
1064
1064
 
1065
1065
  - `list` emits `operation: "sessions.list"`, `data.sessions` (bounded projections
1066
1066
  of session ID, agent ID, operation, mode, status and audit timestamps) and a
1067
- `page` block (`{"kind": "limit", "limit": N, "returned_count": N,
1068
- "continuation": null}`). `get` emits `operation: "sessions.get"` and
1069
- `data.session`. The projections never include the session's protected
1067
+ `page` block. These routes page with a limit only, so the block always says
1068
+ which limit was in force: with `--limit N` it is
1069
+ `{"kind": "limit", "limit": N, "returned_count": N, "continuation": null}`,
1070
+ and without it the server's own default page was applied, which the block
1071
+ reports as `{"kind": "server_default", "server_default_limit": 50,
1072
+ "returned_count": N, "continuation": null}` (50 sessions, 100 messages) — so
1073
+ a truncated page is never mistaken for a complete list. `get` emits
1074
+ `operation: "sessions.get"` and `data.session`. The projections never include the session's protected
1070
1075
  `initial_prompt`, tenant or user identity, or arbitrary response fields.
1071
1076
  - Default `pretty` output prints `list` as a table with honest headers —
1072
1077
  `ID`, `AGENT ID`, `OPERATION`, `STATUS`, `EXPIRES AT` for sessions and `ID`,
@@ -1115,7 +1120,11 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
1115
1120
  - `--initial-prompt` becomes the session's first `user` message in the same
1116
1121
  server transaction; `hc ams sessions messages list` shows it afterwards.
1117
1122
  - `--mode implement` is not available from the server yet: `create` reports one
1118
- `unsupported` refusal (the server answers 501) and creates nothing. A message
1123
+ `unsupported` refusal (the server answers 501) and creates nothing, and a
1124
+ `messages add` the server answers 501 for is the same `unsupported` refusal
1125
+ with no message added. Both refusals report the 501 the server actually sent
1126
+ and name implement mode as the documented reason, rather than asserting the
1127
+ requested mode was the cause. A message
1119
1128
  whose `--mode` differs from its session's mode is refused by the server with
1120
1129
  409 and reported as one write-worded `conflict` refusal that names the
1121
1130
  session, mentions a mode mismatch as one possible cause, and points at
@@ -1138,9 +1147,14 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
1138
1147
  - Reads refuse target files, root credentials or base URLs, raw output, blank or
1139
1148
  dot-segment session IDs, out-of-range limits, and installed SDKs without the
1140
1149
  session list/get and message list methods before tenant-admin login or any
1141
- read; `messages list` needs only `messages.list` — the write method `add` is
1142
- not required for the read, and `messages add` still refuses `unsupported`
1143
- without it. The existing `hc ams plan|show|apply|restore` tuning commands and their
1150
+ read. `messages list` needs only `messages.list` — the write method `add` is
1151
+ not required for the read. The writes check their own methods in the same
1152
+ preflight — each command requires exactly the write method it calls, so
1153
+ `create` refuses an installed SDK without `sessions.create` and `messages add`
1154
+ one without `messages.add` before tenant-admin login and before any read or
1155
+ write, and neither is refused for the write the other command performs. A single-object route whose 2xx body is not a JSON
1156
+ object is refused as a `validation` error, never reported as an internal
1157
+ failure. The existing `hc ams plan|show|apply|restore` tuning commands and their
1144
1158
  signatures are unchanged.
1145
1159
  - These session and message commands do not attach files, apply or roll back
1146
1160
  configuration, or send session history to a model. Plan review is its own
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Callable
5
+ from collections.abc import Callable, Sequence
6
6
  from contextlib import AbstractContextManager
7
7
  from dataclasses import dataclass
8
8
  from pathlib import Path
@@ -236,8 +236,20 @@ def preflight_policies(invocation: AmsContext, target: TenantTarget) -> None:
236
236
  sdk.close()
237
237
 
238
238
 
239
- def preflight_sessions(invocation: AmsContext, target: TenantTarget) -> None:
240
- """Validate local session-read compatibility before login or any read."""
239
+ def preflight_sessions(
240
+ invocation: AmsContext,
241
+ target: TenantTarget,
242
+ *,
243
+ write_methods: Sequence[str] = (),
244
+ ) -> None:
245
+ """Validate local session compatibility before login or any request.
246
+
247
+ ``write_methods`` names exactly the write methods the calling command will
248
+ call, as ``"<resource>.<method>"`` (``sessions.create``, ``messages.add``),
249
+ so a write command is refused here — before tenant-admin login and before any
250
+ read or write — only for a method it actually needs; a write it never
251
+ performs is never required of the installed SDK.
252
+ """
241
253
 
242
254
  _check_root(invocation)
243
255
  if invocation.target_file is not None:
@@ -245,12 +257,16 @@ def preflight_sessions(invocation: AmsContext, target: TenantTarget) -> None:
245
257
  sdk = _public_sdk(target.environment, target.tenant_id)
246
258
  try:
247
259
  resource = getattr(getattr(sdk, "ams_admin", None), "sessions", None)
248
- if (
249
- resource is None
250
- or not callable(getattr(resource, "list", None))
251
- or not callable(getattr(resource, "get", None))
252
- or not callable(getattr(getattr(resource, "messages", None), "list", None))
253
- ):
260
+ messages = getattr(resource, "messages", None)
261
+ resources = {"sessions": resource, "messages": messages}
262
+ required = (resource, "list"), (resource, "get"), (messages, "list")
263
+ missing = any(not callable(getattr(holder, method, None)) for holder, method in required)
264
+ for qualified in write_methods:
265
+ owner, _, method = qualified.partition(".")
266
+ holder = resources.get(owner)
267
+ if not method or not callable(getattr(holder, method, None)):
268
+ missing = True
269
+ if missing:
254
270
  raise click.ClickException(
255
271
  "SDK missing ams_admin sessions; use the reviewed SDK version required by this CLI."
256
272
  )
@@ -125,7 +125,7 @@ def create_create_command(dependencies: AmsDependencies) -> click.Command:
125
125
  _require_login()
126
126
  target = resolve_tenant_target(environment, tenant_id)
127
127
  target_data.update(environment=target.environment, tenant_id=target.tenant_id)
128
- preflight_sessions(invocation, target)
128
+ preflight_sessions(invocation, target, write_methods=("sessions.create",))
129
129
  return create_session(
130
130
  dependencies,
131
131
  target,
@@ -561,7 +561,7 @@ def create_messages_add_command(dependencies: AmsDependencies) -> click.Command:
561
561
  _require_login()
562
562
  target = resolve_tenant_target(environment, tenant_id)
563
563
  target_data.update(environment=target.environment, tenant_id=target.tenant_id)
564
- preflight_sessions(invocation, target)
564
+ preflight_sessions(invocation, target, write_methods=("messages.add",))
565
565
  return add_message(
566
566
  dependencies,
567
567
  target,
@@ -25,7 +25,11 @@ from .projections import (
25
25
  )
26
26
 
27
27
  SESSION_LIMIT_MAX = 100
28
+ # The server's own defaults when ``--limit`` is omitted: an omitted limit is a
29
+ # real, truncating page, so the envelope reports which default was applied.
30
+ SESSION_LIMIT_DEFAULT = 50
28
31
  MESSAGE_LIMIT_MAX = 200
32
+ MESSAGE_LIMIT_DEFAULT = 100
29
33
  # Mirror the server's own bounds so an obviously unacceptable file is never
30
34
  # put on the wire; the server's refusal still wins when it disagrees.
31
35
  ATTACHMENT_MAX_BYTES = 5 * 1024 * 1024
@@ -562,6 +566,26 @@ def _identity(session, target: TenantTarget, session_id: str | None) -> None:
562
566
  )
563
567
 
564
568
 
569
+ def _page(limit: int | None, server_default: int, returned: int) -> dict:
570
+ """The page block, honest about an omitted ``--limit``.
571
+
572
+ These routes page with a limit only: an omitted limit is not "unpaged", it
573
+ is the server's own default page, which can truncate the list. The block
574
+ therefore reports either the limit that was sent, or the server default
575
+ that was applied instead, so a consumer can always tell whether more rows
576
+ may exist.
577
+ """
578
+
579
+ if limit is None:
580
+ return {
581
+ "kind": "server_default",
582
+ "server_default_limit": server_default,
583
+ "returned_count": returned,
584
+ "continuation": None,
585
+ }
586
+ return {"kind": "limit", "limit": limit, "returned_count": returned, "continuation": None}
587
+
588
+
565
589
  def list_sessions(dependencies: AmsDependencies, target: TenantTarget, *, limit: int | None = None) -> dict:
566
590
  """`hc ams sessions list`: the caller's non-expired sessions, newest first."""
567
591
 
@@ -576,12 +600,7 @@ def list_sessions(dependencies: AmsDependencies, target: TenantTarget, *, limit:
576
600
  _target(target),
577
601
  {
578
602
  "sessions": projections,
579
- "page": {
580
- "kind": "limit",
581
- "limit": limit,
582
- "returned_count": len(projections),
583
- "continuation": None,
584
- },
603
+ "page": _page(limit, SESSION_LIMIT_DEFAULT, len(projections)),
585
604
  },
586
605
  read_only=True,
587
606
  )
@@ -653,13 +672,26 @@ def _message_conflict(error: BaseException, session_id: str) -> SessionWriteRefu
653
672
 
654
673
 
655
674
  def _not_implemented(error: BaseException, *, session: bool) -> SessionWriteRefused | None:
675
+ """A 501 is the server saying it does not serve this write yet.
676
+
677
+ Both routes report the 501 the server actually sent rather than asserting
678
+ the requested mode was the cause; implement mode is named as the documented
679
+ reason, not as a certainty.
680
+ """
681
+
656
682
  if getattr(error, "status_code", None) != 501:
657
683
  return None
658
- what = "Sessions in" if session else "Messages in"
684
+ if session:
685
+ return SessionWriteRefused(
686
+ "unsupported",
687
+ "The server does not serve this session write yet (it answered 501, not implemented); the "
688
+ "write was refused and no changes were made. Implement mode is the documented reason: "
689
+ "implement-mode authoring is not available from this server yet.",
690
+ )
659
691
  return SessionWriteRefused(
660
692
  "unsupported",
661
- f"{what} implement mode are not available from this server yet; the write was refused and "
662
- "no changes were made.",
693
+ "The server does not serve this message write yet (it answered 501, not implemented); no "
694
+ "message was added. Implement-mode messages are not available from this server yet.",
663
695
  )
664
696
 
665
697
 
@@ -748,12 +780,7 @@ def list_messages(
748
780
  _target(target, session_id),
749
781
  {
750
782
  "messages": projections,
751
- "page": {
752
- "kind": "limit",
753
- "limit": limit,
754
- "returned_count": len(projections),
755
- "continuation": None,
756
- },
783
+ "page": _page(limit, MESSAGE_LIMIT_DEFAULT, len(projections)),
757
784
  },
758
785
  read_only=True,
759
786
  )
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "healthcloud-cli"
7
- version = "3.7.6"
7
+ version = "3.7.7"
8
8
  description = "Command-line interface for the HealthCloud MCP gateway, generated from the shared MCP tool manifest."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"