Skip to content

Commit 2e88977

Browse files
authored
feat(api, sdk-py, sdk-ts): add message observing status API (#89)
* feat: Add message observing status API (Issue #75) - Query existing session_task_process_status field from messages table - Map values: success→observed, running→in_process, pending→pending - Implement Go API endpoint: GET /session/{id}/observing-status - Add Python SDK method: messages_observing_status() - Add TypeScript SDK method: messagesObservingStatus() - Returns counts of observed, in_process, pending messages Backend (Go): - Model layer: MessageObservingStatus response type - Repository layer: Direct query on messages table - Service layer: Business logic wrapper - Handler layer: HTTP endpoint with unit tests - Router: URL registration - Dependency injection: Full wiring Python SDK: - Type: MessageObservingStatus (Pydantic) - Method: sessions.messages_observing_status() TypeScript SDK: - Schema: MessageObservingStatusSchema (Zod) - Type: MessageObservingStatus - Method: sessions.messagesObservingStatus() Tests: - Handler tests with mocks (all passing) Note: Uses existing session_task_process_status field. No database migration needed. * refactor: Consolidate observing status into session handler Based on review feedback: - Moved method to SessionHandler instead of separate handler - Consolidated into existing session service/repo/model files - Added async Python client method - Deleted all separate message_observing_* files Changes: - Go: Added GetSessionObservingStatus to SessionHandler/Service/Repo - Model: Added MessageObservingStatus struct to session.go - Tests: Added handler tests to session_test.go - Python: Added async version in async_sessions.py * fix: Add GetObservingStatus mock method to service tests * fix: Auto-format code with gofmt - fixed aligment in main.go and router.go - updated swagger doc * fix: Change API path to snake_case changed /observing-status -> observing_status - Updated router registration - Updated swagger doc - Updated Python SDK (sync + async) - Updated TS SDK
1 parent 491a237 commit 2e88977

File tree

20 files changed

+484
-11
lines changed

20 files changed

+484
-11
lines changed

src/client/acontext-py/src/acontext/resources/async_sessions.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
LearningStatus,
1616
ListSessionsOutput,
1717
Message,
18+
MessageObservingStatus,
1819
Session,
1920
TokenCounts,
2021
)
@@ -346,3 +347,21 @@ async def get_token_counts(self, session_id: str) -> TokenCounts:
346347
"GET", f"/session/{session_id}/token_counts"
347348
)
348349
return TokenCounts.model_validate(data)
350+
351+
async def messages_observing_status(self, session_id: str) -> MessageObservingStatus:
352+
"""Get message observing status counts for a session.
353+
354+
Returns the count of messages by their observing status:
355+
observed, in_process, and pending.
356+
357+
Args:
358+
session_id: The UUID of the session.
359+
360+
Returns:
361+
MessageObservingStatus object containing observed, in_process,
362+
pending counts and updated_at timestamp.
363+
"""
364+
data = await self._requester.request(
365+
"GET", f"/session/{session_id}/observing_status"
366+
)
367+
return MessageObservingStatus.model_validate(data)

src/client/acontext-py/src/acontext/resources/sessions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
LearningStatus,
1616
ListSessionsOutput,
1717
Message,
18+
MessageObservingStatus,
1819
Session,
1920
TokenCounts,
2021
)
@@ -348,3 +349,20 @@ def get_token_counts(self, session_id: str) -> TokenCounts:
348349
"""
349350
data = self._requester.request("GET", f"/session/{session_id}/token_counts")
350351
return TokenCounts.model_validate(data)
352+
def messages_observing_status(self, session_id: str) -> MessageObservingStatus:
353+
"""Get message observing status counts for a session.
354+
355+
Returns the count of messages by their observing status:
356+
observed, in_process, and pending.
357+
358+
Args:
359+
session_id: The UUID of the session.
360+
361+
Returns:
362+
MessageObservingStatus object containing observed, in_process,
363+
pending counts and updated_at timestamp.
364+
"""
365+
data = self._requester.request(
366+
"GET", f"/session/{session_id}/observing_status"
367+
)
368+
return MessageObservingStatus.model_validate(data)

src/client/acontext-py/src/acontext/types/session.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,19 @@ class TokenCounts(BaseModel):
253253
...,
254254
description="Total token count for all text and tool-call parts in a session",
255255
)
256+
257+
class MessageObservingStatus(BaseModel):
258+
"""Response model for message observing status."""
259+
260+
observed: int = Field(
261+
..., description="Number of messages with observed status"
262+
)
263+
in_process: int = Field(
264+
..., description="Number of messages with in_process status"
265+
)
266+
pending: int = Field(
267+
..., description="Number of messages with pending status"
268+
)
269+
updated_at: str = Field(
270+
..., description="Timestamp when the status was retrieved"
271+
)

src/client/acontext-ts/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client/acontext-ts/src/resources/sessions.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {
1717
ListSessionsOutput,
1818
ListSessionsOutputSchema,
1919
Message,
20+
MessageObservingStatus,
21+
MessageObservingStatusSchema,
2022
MessageSchema,
2123
Session,
2224
SessionSchema,
@@ -264,5 +266,20 @@ export class SessionsAPI {
264266
const data = await this.requester.request('GET', `/session/${sessionId}/token_counts`);
265267
return TokenCountsSchema.parse(data);
266268
}
269+
270+
/**
271+
* Get message observing status counts for a session.
272+
*
273+
* Returns the count of messages by their observing status:
274+
* observed, in_process, and pending.
275+
*
276+
* @param sessionId - The UUID of the session.
277+
* @returns MessageObservingStatus object containing observed, in_process,
278+
* pending counts and updated_at timestamp.
279+
*/
280+
async messagesObservingStatus(sessionId: string): Promise<MessageObservingStatus> {
281+
const data = await this.requester.request('GET', `/session/${sessionId}/observing_status`);
282+
return MessageObservingStatusSchema.parse(data);
283+
}
267284
}
268285

src/client/acontext-ts/src/types/session.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ export const TokenCountsSchema = z.object({
127127

128128
export type TokenCounts = z.infer<typeof TokenCountsSchema>;
129129

130+
export const MessageObservingStatusSchema = z.object({
131+
observed: z.number(),
132+
in_process: z.number(),
133+
pending: z.number(),
134+
updated_at: z.string(),
135+
});
136+
137+
export type MessageObservingStatus = z.infer<typeof MessageObservingStatusSchema>;
138+
130139
/**
131140
* Parameters for the remove_tool_result edit strategy.
132141
*/

src/server/api/go/docs/docs.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,56 @@ const docTemplate = `{
12451245
]
12461246
}
12471247
},
1248+
"/session/{session_id}/observing_status": {
1249+
"get": {
1250+
"security": [
1251+
{
1252+
"BearerAuth": []
1253+
}
1254+
],
1255+
"description": "Returns the count of observed, in_process, and pending messages",
1256+
"consumes": [
1257+
"application/json"
1258+
],
1259+
"produces": [
1260+
"application/json"
1261+
],
1262+
"tags": [
1263+
"session"
1264+
],
1265+
"summary": "Get message observing status for a session",
1266+
"parameters": [
1267+
{
1268+
"type": "string",
1269+
"format": "uuid",
1270+
"description": "Session ID",
1271+
"name": "session_id",
1272+
"in": "path",
1273+
"required": true
1274+
}
1275+
],
1276+
"responses": {
1277+
"200": {
1278+
"description": "OK",
1279+
"schema": {
1280+
"allOf": [
1281+
{
1282+
"$ref": "#/definitions/serializer.Response"
1283+
},
1284+
{
1285+
"type": "object",
1286+
"properties": {
1287+
"data": {
1288+
"$ref": "#/definitions/model.MessageObservingStatus"
1289+
}
1290+
}
1291+
}
1292+
]
1293+
}
1294+
}
1295+
}
1296+
}
1297+
},
12481298
"/session/{session_id}/task": {
12491299
"get": {
12501300
"security": [
@@ -3009,6 +3059,23 @@ const docTemplate = `{
30093059
}
30103060
}
30113061
},
3062+
"model.MessageObservingStatus": {
3063+
"type": "object",
3064+
"properties": {
3065+
"in_process": {
3066+
"type": "integer"
3067+
},
3068+
"observed": {
3069+
"type": "integer"
3070+
},
3071+
"pending": {
3072+
"type": "integer"
3073+
},
3074+
"updated_at": {
3075+
"type": "string"
3076+
}
3077+
}
3078+
},
30123079
"model.Session": {
30133080
"type": "object",
30143081
"properties": {

src/server/api/go/docs/swagger.json

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,56 @@
12421242
]
12431243
}
12441244
},
1245+
"/session/{session_id}/observing_status": {
1246+
"get": {
1247+
"security": [
1248+
{
1249+
"BearerAuth": []
1250+
}
1251+
],
1252+
"description": "Returns the count of observed, in_process, and pending messages",
1253+
"consumes": [
1254+
"application/json"
1255+
],
1256+
"produces": [
1257+
"application/json"
1258+
],
1259+
"tags": [
1260+
"session"
1261+
],
1262+
"summary": "Get message observing status for a session",
1263+
"parameters": [
1264+
{
1265+
"type": "string",
1266+
"format": "uuid",
1267+
"description": "Session ID",
1268+
"name": "session_id",
1269+
"in": "path",
1270+
"required": true
1271+
}
1272+
],
1273+
"responses": {
1274+
"200": {
1275+
"description": "OK",
1276+
"schema": {
1277+
"allOf": [
1278+
{
1279+
"$ref": "#/definitions/serializer.Response"
1280+
},
1281+
{
1282+
"type": "object",
1283+
"properties": {
1284+
"data": {
1285+
"$ref": "#/definitions/model.MessageObservingStatus"
1286+
}
1287+
}
1288+
}
1289+
]
1290+
}
1291+
}
1292+
}
1293+
}
1294+
},
12451295
"/session/{session_id}/task": {
12461296
"get": {
12471297
"security": [
@@ -3006,6 +3056,23 @@
30063056
}
30073057
}
30083058
},
3059+
"model.MessageObservingStatus": {
3060+
"type": "object",
3061+
"properties": {
3062+
"in_process": {
3063+
"type": "integer"
3064+
},
3065+
"observed": {
3066+
"type": "integer"
3067+
},
3068+
"pending": {
3069+
"type": "integer"
3070+
},
3071+
"updated_at": {
3072+
"type": "string"
3073+
}
3074+
}
3075+
},
30093076
"model.Session": {
30103077
"type": "object",
30113078
"properties": {

src/server/api/go/docs/swagger.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,17 @@ definitions:
304304
updated_at:
305305
type: string
306306
type: object
307+
model.MessageObservingStatus:
308+
properties:
309+
in_process:
310+
type: integer
311+
observed:
312+
type: integer
313+
pending:
314+
type: integer
315+
updated_at:
316+
type: string
317+
type: object
307318
model.Session:
308319
properties:
309320
configs:
@@ -1607,6 +1618,35 @@ paths:
16071618
},
16081619
{ format: 'openai' }
16091620
);
1621+
/session/{session_id}/observing_status:
1622+
get:
1623+
consumes:
1624+
- application/json
1625+
description: Returns the count of observed, in_process, and pending messages
1626+
parameters:
1627+
- description: Session ID
1628+
format: uuid
1629+
in: path
1630+
name: session_id
1631+
required: true
1632+
type: string
1633+
produces:
1634+
- application/json
1635+
responses:
1636+
"200":
1637+
description: OK
1638+
schema:
1639+
allOf:
1640+
- $ref: '#/definitions/serializer.Response'
1641+
- properties:
1642+
data:
1643+
$ref: '#/definitions/model.MessageObservingStatus'
1644+
type: object
1645+
security:
1646+
- BearerAuth: []
1647+
summary: Get message observing status for a session
1648+
tags:
1649+
- session
16101650
/session/{session_id}/task:
16111651
get:
16121652
consumes:

src/server/api/go/internal/bootstrap/container.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,5 @@ func BuildContainer() *do.Injector {
240240
do.Provide(inj, func(i *do.Injector) (*handler.ToolHandler, error) {
241241
return handler.NewToolHandler(do.MustInvoke[*httpclient.CoreClient](i)), nil
242242
})
243-
244243
return inj
245244
}

0 commit comments

Comments
 (0)