ms-tau-sdk 2.0.22.dev73__tar.gz → 2.0.23.dev75__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.
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/CHANGELOG.md +17 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/PKG-INFO +1 -1
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/pyproject.toml +1 -1
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/a2a.py +190 -128
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/.gitignore +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/README.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/app.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/cli.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/config.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/env_file.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/logs.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/proxy.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/state.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/static/BULMA-LICENSE.txt +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/static/app.js +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/static/board.css +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/static/bulma.min.css +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/static/index.html +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/agent_skills/tau_a2a_runtime_adapter/SKILL.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/agent_skills/tau_local_development/SKILL.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/agent_skills/tau_project_customization/SKILL.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/agent_skills/tau_repository_integration/SKILL.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/agent_skills/tau_security_and_access/SKILL.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/chat.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/conversations.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/dependencies.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/health.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/inspection.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/local_chat.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/models.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/request_identity.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/api/sessions.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/app.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/application.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/assertions.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/auth.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/client.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/local.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/mcp.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/models.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/routes.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/team_memberships.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/cli.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/errors.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/logging.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/a2a_failure.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/a2a_message.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/a2a_roles.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/assistant_ui.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/chat_history.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/strict_json.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/providers/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/providers/definitions.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/providers/factory.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/providers/tau_compat.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/resources/SYSTEM.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/resources/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/resources/loader.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/resources/prompts/review-code-repository.md +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/deployment_health.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/events.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/extensions.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/failures.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/live_turns.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/manager.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/observability.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/provenance.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/requester.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/session.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/snapshots.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/task_context.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/sessions/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/sessions/storage.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/settings.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/skills.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/__init__.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/mainsequence_mcp.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/mcp_applications.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/mcp_connection.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/skill_read.py +0 -0
- {ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/task_control.py +0 -0
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.23 — 2026-10-21
|
|
4
|
+
|
|
5
|
+
- **A hosted Task's answer reaches the platform in a few writes, and none of it is lost
|
|
6
|
+
([#116](https://github.com/mainsequence-sdk/ms-tau-sdk/issues/116)).** While a Task attempt
|
|
7
|
+
checked for cancellation or wrote its answer, it stopped reading the model. With platform calls
|
|
8
|
+
slower than the 200-millisecond write interval, every small piece of text became its own write,
|
|
9
|
+
each preceded by another read of the Task, so an answer took minutes to reach the platform. The
|
|
10
|
+
check and the writes now run in the background, one of each at a time, while the turn keeps
|
|
11
|
+
reading the model; text that arrives meanwhile joins the next write. In a test with 60-millisecond
|
|
12
|
+
platform calls, a 40-piece answer takes 4 writes and 9 reads instead of 41 and 86. Cancellation,
|
|
13
|
+
the lease check on each write, the order of the text and settlement are unchanged, and nothing the
|
|
14
|
+
writer started keeps running once the attempt ends.
|
|
15
|
+
- When an answer was written in more than one batch, the text still waiting at the end was
|
|
16
|
+
dropped: the output was finalized without writing it. It is now written first.
|
|
17
|
+
- The poll interval now runs from when the previous cancellation check ended, not when it
|
|
18
|
+
started.
|
|
19
|
+
|
|
3
20
|
## 2.0.22 — 2026-10-21
|
|
4
21
|
|
|
5
22
|
- **A hosted Task's answer reaches the caller of GetTask
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ms-tau-sdk
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.23.dev75
|
|
4
4
|
Summary: Workspace-bound Tau application primitives for Main Sequence projects
|
|
5
5
|
Project-URL: Changelog, https://github.com/mainsequence-sdk/ms-tau-sdk/blob/development/CHANGELOG.md
|
|
6
6
|
Project-URL: Documentation, https://github.com/mainsequence-sdk/ms-tau-sdk/tree/development/docs
|
|
@@ -1289,6 +1289,15 @@ async def _settle_execution_failure(
|
|
|
1289
1289
|
|
|
1290
1290
|
@dataclass(slots=True)
|
|
1291
1291
|
class _DurableArtifactWriter:
|
|
1292
|
+
"""Write a Task attempt's text answer as one durable output.
|
|
1293
|
+
|
|
1294
|
+
The routine cancellation read and each batch's write run in the background, one of each at a
|
|
1295
|
+
time, so the turn keeps reading the model while the platform answers; text that arrives
|
|
1296
|
+
meanwhile joins the next batch. A batch that reaches ``flush_bytes`` waits for the write before
|
|
1297
|
+
it, which bounds the text held. A failure or cancellation found in the background is raised by
|
|
1298
|
+
the writer's next call. ``close()`` stops background work before the attempt settles.
|
|
1299
|
+
"""
|
|
1300
|
+
|
|
1292
1301
|
client: MainSequenceClient
|
|
1293
1302
|
manager: SessionRuntimeManager
|
|
1294
1303
|
task: AgentTask
|
|
@@ -1303,16 +1312,35 @@ class _DurableArtifactWriter:
|
|
|
1303
1312
|
pending_bytes: int = 0
|
|
1304
1313
|
last_flush_at: float = field(default_factory=time.monotonic)
|
|
1305
1314
|
last_cancellation_check_at: float = 0.0
|
|
1315
|
+
writing: asyncio.Task[None] | None = None
|
|
1316
|
+
polling: asyncio.Task[None] | None = None
|
|
1306
1317
|
|
|
1307
1318
|
async def ensure_not_canceled(self, *, force: bool = False) -> None:
|
|
1308
|
-
now
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1319
|
+
"""Raise when the Task was canceled; ``force`` reads the Task now and waits for it.
|
|
1320
|
+
|
|
1321
|
+
Otherwise the read starts in the background once the poll interval has passed, and what
|
|
1322
|
+
it finds is raised by a later call.
|
|
1323
|
+
"""
|
|
1324
|
+
|
|
1325
|
+
self._observe_cancellation_read()
|
|
1326
|
+
if force:
|
|
1327
|
+
await self._read_cancellation()
|
|
1328
|
+
elif (
|
|
1329
|
+
self.polling is None
|
|
1330
|
+
and time.monotonic() - self.last_cancellation_check_at
|
|
1331
|
+
>= self.cancellation_poll_interval_seconds
|
|
1312
1332
|
):
|
|
1313
|
-
|
|
1333
|
+
self.polling = asyncio.create_task(self._read_cancellation())
|
|
1334
|
+
|
|
1335
|
+
def _observe_cancellation_read(self) -> None:
|
|
1336
|
+
polling = self.polling
|
|
1337
|
+
if polling is not None and polling.done():
|
|
1338
|
+
self.polling = None
|
|
1339
|
+
polling.result()
|
|
1340
|
+
|
|
1341
|
+
async def _read_cancellation(self) -> None:
|
|
1314
1342
|
current = await self.client.get_task(self.task.uid)
|
|
1315
|
-
self.last_cancellation_check_at =
|
|
1343
|
+
self.last_cancellation_check_at = time.monotonic()
|
|
1316
1344
|
if current.cancellation_requested or current.status == "canceled":
|
|
1317
1345
|
raise _TaskCancellationRequested(current)
|
|
1318
1346
|
|
|
@@ -1321,15 +1349,39 @@ class _DurableArtifactWriter:
|
|
|
1321
1349
|
return
|
|
1322
1350
|
self.pending.append(value)
|
|
1323
1351
|
self.pending_bytes += len(value.encode("utf-8"))
|
|
1352
|
+
if self.writing is not None:
|
|
1353
|
+
if not self.writing.done() and self.pending_bytes < self.flush_bytes:
|
|
1354
|
+
return
|
|
1355
|
+
await self._finish_write()
|
|
1324
1356
|
elapsed_ms = (time.monotonic() - self.last_flush_at) * 1000
|
|
1325
1357
|
if self.pending_bytes >= self.flush_bytes or elapsed_ms >= self.flush_interval_ms:
|
|
1326
|
-
|
|
1358
|
+
self.writing = asyncio.create_task(self._write())
|
|
1359
|
+
|
|
1360
|
+
async def _finish_write(self) -> None:
|
|
1361
|
+
writing, self.writing = self.writing, None
|
|
1362
|
+
if writing is not None:
|
|
1363
|
+
await writing
|
|
1327
1364
|
|
|
1328
1365
|
async def flush(self, *, final: bool = False) -> None:
|
|
1366
|
+
await self._finish_write()
|
|
1367
|
+
await self._write(final=final)
|
|
1368
|
+
|
|
1369
|
+
async def close(self) -> None:
|
|
1370
|
+
"""Stop the background read and write, keeping none of their results."""
|
|
1371
|
+
|
|
1372
|
+
running = [work for work in (self.writing, self.polling) if work is not None]
|
|
1373
|
+
self.writing = self.polling = None
|
|
1374
|
+
for work in running:
|
|
1375
|
+
work.cancel()
|
|
1376
|
+
await asyncio.gather(*running, return_exceptions=True)
|
|
1377
|
+
|
|
1378
|
+
async def _write(self, *, final: bool = False) -> None:
|
|
1329
1379
|
text = "".join(self.pending)
|
|
1330
1380
|
if not text and not final:
|
|
1331
1381
|
return
|
|
1332
|
-
|
|
1382
|
+
self.pending.clear()
|
|
1383
|
+
self.pending_bytes = 0
|
|
1384
|
+
await self._read_cancellation()
|
|
1333
1385
|
fence = await _current_task_fence(self.manager, self.task, self.claim)
|
|
1334
1386
|
created = self.revision == 0
|
|
1335
1387
|
if created:
|
|
@@ -1343,35 +1395,34 @@ class _DurableArtifactWriter:
|
|
|
1343
1395
|
name="Agent response",
|
|
1344
1396
|
)
|
|
1345
1397
|
self.output_uid = str(result["uid"])
|
|
1346
|
-
elif
|
|
1398
|
+
elif text:
|
|
1347
1399
|
if self.output_uid is None:
|
|
1348
1400
|
raise RuntimeError("Backend Task output UID is unavailable")
|
|
1349
|
-
result = await self.client.
|
|
1401
|
+
result = await self.client.append_task_output(
|
|
1350
1402
|
self.task.uid,
|
|
1351
1403
|
attempt_uid=self.claim.attempt_uid,
|
|
1352
1404
|
holder_id=fence.holder_id,
|
|
1353
1405
|
lease_token=fence.lease_token,
|
|
1354
1406
|
output_uid=self.output_uid,
|
|
1355
1407
|
expected_revision=self.revision,
|
|
1408
|
+
parts=[{"text": text}],
|
|
1356
1409
|
)
|
|
1357
1410
|
else:
|
|
1358
1411
|
if self.output_uid is None:
|
|
1359
1412
|
raise RuntimeError("Backend Task output UID is unavailable")
|
|
1360
|
-
result = await self.client.
|
|
1413
|
+
result = await self.client.finalize_task_output(
|
|
1361
1414
|
self.task.uid,
|
|
1362
1415
|
attempt_uid=self.claim.attempt_uid,
|
|
1363
1416
|
holder_id=fence.holder_id,
|
|
1364
1417
|
lease_token=fence.lease_token,
|
|
1365
1418
|
output_uid=self.output_uid,
|
|
1366
1419
|
expected_revision=self.revision,
|
|
1367
|
-
parts=[{"text": text}] if text else [],
|
|
1368
1420
|
)
|
|
1369
1421
|
self.revision = int(result.get("revision") or self.revision + 1)
|
|
1370
|
-
self.pending.clear()
|
|
1371
|
-
self.pending_bytes = 0
|
|
1372
1422
|
self.last_flush_at = time.monotonic()
|
|
1373
|
-
if final and created:
|
|
1374
|
-
|
|
1423
|
+
if final and (created or text):
|
|
1424
|
+
# The output is finalized after the text still pending is written, never instead.
|
|
1425
|
+
await self._write(final=True)
|
|
1375
1426
|
|
|
1376
1427
|
async def write_strict_json(self, text: str) -> None:
|
|
1377
1428
|
await self.ensure_not_canceled(force=True)
|
|
@@ -1419,26 +1470,32 @@ async def _collect_task_turn(
|
|
|
1419
1470
|
return text
|
|
1420
1471
|
|
|
1421
1472
|
accumulator = _TurnAccumulator(max_output_bytes=max_output_bytes)
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1473
|
+
try:
|
|
1474
|
+
async for event in manager.prompt(
|
|
1475
|
+
task.context_id,
|
|
1476
|
+
prompt,
|
|
1477
|
+
provenance=provenance,
|
|
1478
|
+
turn_uid=writer.claim.turn_uid,
|
|
1479
|
+
):
|
|
1480
|
+
await writer.ensure_not_canceled()
|
|
1481
|
+
accumulator.consume(event)
|
|
1482
|
+
value = _event_text(
|
|
1483
|
+
event.type, event.data, has_chunks=bool(accumulator.delta_chunks[:-1])
|
|
1484
|
+
)
|
|
1485
|
+
if event.type in {"text_delta", "text-delta"} and value:
|
|
1486
|
+
await writer.append_text(value)
|
|
1487
|
+
context = active_task_execution()
|
|
1488
|
+
if context is not None and context.interruption_status is not None:
|
|
1489
|
+
await writer.flush()
|
|
1490
|
+
return ""
|
|
1491
|
+
text = accumulator.result()
|
|
1492
|
+
if not accumulator.delta_chunks:
|
|
1493
|
+
await writer.append_text(text)
|
|
1494
|
+
await writer.flush(final=True)
|
|
1495
|
+
return text
|
|
1496
|
+
finally:
|
|
1497
|
+
# Nothing the writer started in the background outlives the turn or reaches settlement.
|
|
1498
|
+
await writer.close()
|
|
1442
1499
|
|
|
1443
1500
|
|
|
1444
1501
|
async def _execute_task(
|
|
@@ -1884,111 +1941,116 @@ async def _stream_task_events(
|
|
|
1884
1941
|
text = ""
|
|
1885
1942
|
emitted = False
|
|
1886
1943
|
try:
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
if text and task_context.interruption_status is None:
|
|
1900
|
-
await writer.write_strict_json(text)
|
|
1901
|
-
yield _artifact_update(
|
|
1902
|
-
task,
|
|
1903
|
-
artifact_id=artifact_id,
|
|
1904
|
-
part={
|
|
1905
|
-
"data": json.loads(text),
|
|
1906
|
-
"mediaType": "application/json",
|
|
1907
|
-
},
|
|
1908
|
-
append=False,
|
|
1909
|
-
last_chunk=True,
|
|
1910
|
-
)
|
|
1911
|
-
emitted = True
|
|
1912
|
-
else:
|
|
1913
|
-
accumulator = _TurnAccumulator(max_output_bytes=max_output_bytes)
|
|
1914
|
-
with task_execution_scope(task_context):
|
|
1915
|
-
async for event in manager.prompt(
|
|
1916
|
-
task.context_id,
|
|
1917
|
-
prompt,
|
|
1918
|
-
provenance=provenance,
|
|
1919
|
-
turn_uid=claim.turn_uid,
|
|
1920
|
-
):
|
|
1921
|
-
await writer.ensure_not_canceled()
|
|
1922
|
-
accumulator.consume(event)
|
|
1923
|
-
if event.type not in {"text_delta", "text-delta"}:
|
|
1924
|
-
continue
|
|
1925
|
-
value = _event_text(
|
|
1926
|
-
event.type,
|
|
1927
|
-
event.data,
|
|
1928
|
-
has_chunks=bool(accumulator.delta_chunks[:-1]),
|
|
1929
|
-
)
|
|
1930
|
-
if not value:
|
|
1931
|
-
continue
|
|
1932
|
-
await writer.append_text(value)
|
|
1933
|
-
yield _artifact_update(
|
|
1934
|
-
task,
|
|
1935
|
-
artifact_id=artifact_id,
|
|
1936
|
-
part={"text": value},
|
|
1937
|
-
append=emitted,
|
|
1938
|
-
last_chunk=False,
|
|
1944
|
+
try:
|
|
1945
|
+
await writer.ensure_not_canceled(force=True)
|
|
1946
|
+
if output_contract.enabled:
|
|
1947
|
+
with task_execution_scope(task_context):
|
|
1948
|
+
text = await _collect_validated_turn(
|
|
1949
|
+
manager,
|
|
1950
|
+
task.context_id,
|
|
1951
|
+
prompt,
|
|
1952
|
+
output_contract,
|
|
1953
|
+
max_output_bytes=max_output_bytes,
|
|
1954
|
+
provenance=provenance,
|
|
1955
|
+
turn_uid=claim.turn_uid,
|
|
1939
1956
|
)
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
text = accumulator.result()
|
|
1943
|
-
if not accumulator.delta_chunks:
|
|
1944
|
-
await writer.append_text(text)
|
|
1957
|
+
if text and task_context.interruption_status is None:
|
|
1958
|
+
await writer.write_strict_json(text)
|
|
1945
1959
|
yield _artifact_update(
|
|
1946
1960
|
task,
|
|
1947
1961
|
artifact_id=artifact_id,
|
|
1948
|
-
part={
|
|
1962
|
+
part={
|
|
1963
|
+
"data": json.loads(text),
|
|
1964
|
+
"mediaType": "application/json",
|
|
1965
|
+
},
|
|
1949
1966
|
append=False,
|
|
1950
|
-
last_chunk=
|
|
1967
|
+
last_chunk=True,
|
|
1951
1968
|
)
|
|
1952
1969
|
emitted = True
|
|
1953
|
-
|
|
1954
|
-
|
|
1970
|
+
else:
|
|
1971
|
+
accumulator = _TurnAccumulator(max_output_bytes=max_output_bytes)
|
|
1972
|
+
with task_execution_scope(task_context):
|
|
1973
|
+
async for event in manager.prompt(
|
|
1974
|
+
task.context_id,
|
|
1975
|
+
prompt,
|
|
1976
|
+
provenance=provenance,
|
|
1977
|
+
turn_uid=claim.turn_uid,
|
|
1978
|
+
):
|
|
1979
|
+
await writer.ensure_not_canceled()
|
|
1980
|
+
accumulator.consume(event)
|
|
1981
|
+
if event.type not in {"text_delta", "text-delta"}:
|
|
1982
|
+
continue
|
|
1983
|
+
value = _event_text(
|
|
1984
|
+
event.type,
|
|
1985
|
+
event.data,
|
|
1986
|
+
has_chunks=bool(accumulator.delta_chunks[:-1]),
|
|
1987
|
+
)
|
|
1988
|
+
if not value:
|
|
1989
|
+
continue
|
|
1990
|
+
await writer.append_text(value)
|
|
1991
|
+
yield _artifact_update(
|
|
1992
|
+
task,
|
|
1993
|
+
artifact_id=artifact_id,
|
|
1994
|
+
part={"text": value},
|
|
1995
|
+
append=emitted,
|
|
1996
|
+
last_chunk=False,
|
|
1997
|
+
)
|
|
1998
|
+
emitted = True
|
|
1999
|
+
if task_context.interruption_status is None:
|
|
2000
|
+
text = accumulator.result()
|
|
2001
|
+
if not accumulator.delta_chunks:
|
|
2002
|
+
await writer.append_text(text)
|
|
2003
|
+
yield _artifact_update(
|
|
2004
|
+
task,
|
|
2005
|
+
artifact_id=artifact_id,
|
|
2006
|
+
part={"text": text},
|
|
2007
|
+
append=False,
|
|
2008
|
+
last_chunk=False,
|
|
2009
|
+
)
|
|
2010
|
+
emitted = True
|
|
2011
|
+
if task_context.interruption_status is not None:
|
|
2012
|
+
await writer.flush()
|
|
2013
|
+
await writer.ensure_not_canceled(force=True)
|
|
2014
|
+
interrupted = await _settle_claimed_task(
|
|
2015
|
+
client,
|
|
2016
|
+
manager,
|
|
2017
|
+
task,
|
|
2018
|
+
claim,
|
|
2019
|
+
status=task_context.interruption_status,
|
|
2020
|
+
status_message=task_context.interruption_message,
|
|
2021
|
+
)
|
|
2022
|
+
interrupted = await _task_with_history(
|
|
2023
|
+
client, interrupted, history_length=history_length
|
|
2024
|
+
)
|
|
2025
|
+
yield {"task": _task_payload(interrupted, history_length=history_length)}
|
|
2026
|
+
return
|
|
2027
|
+
if not output_contract.enabled:
|
|
2028
|
+
await writer.flush(final=True)
|
|
1955
2029
|
await writer.ensure_not_canceled(force=True)
|
|
1956
|
-
|
|
2030
|
+
completed = await _settle_claimed_task(
|
|
1957
2031
|
client,
|
|
1958
2032
|
manager,
|
|
1959
2033
|
task,
|
|
1960
2034
|
claim,
|
|
1961
|
-
status=
|
|
1962
|
-
status_message=task_context.interruption_message,
|
|
1963
|
-
)
|
|
1964
|
-
interrupted = await _task_with_history(
|
|
1965
|
-
client, interrupted, history_length=history_length
|
|
2035
|
+
status="completed",
|
|
1966
2036
|
)
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
append=True,
|
|
1985
|
-
last_chunk=True,
|
|
1986
|
-
)
|
|
1987
|
-
completed = await _task_with_history(client, completed, history_length=history_length)
|
|
1988
|
-
yield {
|
|
1989
|
-
"task": _task_payload(completed, history_length=history_length),
|
|
1990
|
-
"final": True,
|
|
1991
|
-
}
|
|
2037
|
+
if emitted and not output_contract.enabled:
|
|
2038
|
+
yield _artifact_update(
|
|
2039
|
+
task,
|
|
2040
|
+
artifact_id=artifact_id,
|
|
2041
|
+
part={"text": ""},
|
|
2042
|
+
append=True,
|
|
2043
|
+
last_chunk=True,
|
|
2044
|
+
)
|
|
2045
|
+
completed = await _task_with_history(client, completed, history_length=history_length)
|
|
2046
|
+
yield {
|
|
2047
|
+
"task": _task_payload(completed, history_length=history_length),
|
|
2048
|
+
"final": True,
|
|
2049
|
+
}
|
|
2050
|
+
finally:
|
|
2051
|
+
# Nothing the writer started in the background outlives the turn or reaches
|
|
2052
|
+
# settlement.
|
|
2053
|
+
await writer.close()
|
|
1992
2054
|
except _TaskCancellationRequested as cancellation:
|
|
1993
2055
|
canceled = cancellation.task
|
|
1994
2056
|
if canceled.status != "canceled":
|
|
File without changes
|
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/__init__.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/app.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/cli.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/config.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/env_file.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/logs.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/proxy.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/packages/tau-board/src/ms_tau_board/state.py
RENAMED
|
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
|
|
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
|
|
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
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/backend/team_memberships.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/assistant_ui.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/protocols/chat_history.py
RENAMED
|
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
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/runtime/deployment_health.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/mainsequence_mcp.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.22.dev73 → ms_tau_sdk-2.0.23.dev75}/src/ms_tau_sdk/tools/mcp_applications.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|