niahere 0.4.2 → 0.4.3
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.
- package/package.json +1 -1
- package/src/db/models/message.ts +10 -3
- package/src/db/models/session.ts +15 -11
package/package.json
CHANGED
package/src/db/models/message.ts
CHANGED
|
@@ -4,10 +4,15 @@ import type { SaveMessageParams, RoomStats, RecentMessage, SearchResult, Session
|
|
|
4
4
|
|
|
5
5
|
export type DeliveryStatus = "pending" | "sent" | "failed";
|
|
6
6
|
|
|
7
|
-
export async function save(
|
|
7
|
+
export async function save(
|
|
8
|
+
params: SaveMessageParams & { deliveryStatus?: DeliveryStatus; metadata?: Record<string, unknown> },
|
|
9
|
+
): Promise<number> {
|
|
8
10
|
const sql = getSql();
|
|
9
11
|
const status = params.deliveryStatus || "sent";
|
|
10
|
-
|
|
12
|
+
// Pass the object straight through: the postgres driver serializes it to a
|
|
13
|
+
// real jsonb object. Pre-stringifying stores a double-encoded string scalar,
|
|
14
|
+
// which silently breaks every `metadata->>'key'` filter (e.g. notifications).
|
|
15
|
+
const meta = params.metadata ? sql.json(params.metadata as Parameters<typeof sql.json>[0]) : null;
|
|
11
16
|
const rows = await sql`
|
|
12
17
|
INSERT INTO messages (session_id, room, sender, content, is_from_agent, delivery_status, metadata)
|
|
13
18
|
VALUES (${params.sessionId}, ${params.room}, ${params.sender}, ${params.content}, ${params.isFromAgent}, ${status}, ${meta})
|
|
@@ -21,7 +26,9 @@ export async function updateDeliveryStatus(id: number, status: DeliveryStatus):
|
|
|
21
26
|
await sql`UPDATE messages SET delivery_status = ${status} WHERE id = ${id}`;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
export async function getUndelivered(
|
|
29
|
+
export async function getUndelivered(
|
|
30
|
+
room?: string,
|
|
31
|
+
): Promise<Array<{ id: number; room: string; content: string; createdAt: string }>> {
|
|
25
32
|
const sql = getSql();
|
|
26
33
|
const rows = room
|
|
27
34
|
? await sql`
|
package/src/db/models/session.ts
CHANGED
|
@@ -141,7 +141,10 @@ export async function accumulateMetadata(id: string, resultMeta: Record<string,
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
// Bind deltas as jsonb via sql.json — pre-stringifying would store a
|
|
145
|
+
// double-encoded string scalar, making every `->>` extraction return NULL
|
|
146
|
+
// and silently zeroing all accumulated totals.
|
|
147
|
+
const delta = sql.json({
|
|
145
148
|
total_cost_usd: (resultMeta.cost_usd as number) || 0,
|
|
146
149
|
total_turns: (resultMeta.turns as number) || 0,
|
|
147
150
|
total_duration_ms: (resultMeta.duration_ms as number) || 0,
|
|
@@ -152,22 +155,23 @@ export async function accumulateMetadata(id: string, resultMeta: Record<string,
|
|
|
152
155
|
total_cache_creation_tokens: cacheCreationTokens,
|
|
153
156
|
message_count: 1,
|
|
154
157
|
models_used: newModels,
|
|
155
|
-
channel: resultMeta.channel || null,
|
|
158
|
+
channel: (resultMeta.channel as string) || null,
|
|
156
159
|
});
|
|
160
|
+
const modelsDelta = sql.json(newModels);
|
|
157
161
|
|
|
158
162
|
// Atomic accumulate — no read-then-write race
|
|
159
163
|
await sql`
|
|
160
164
|
UPDATE sessions SET metadata = jsonb_build_object(
|
|
161
|
-
'total_cost_usd', COALESCE((metadata->>'total_cost_usd')::real, 0) + (${delta}
|
|
162
|
-
'total_turns', COALESCE((metadata->>'total_turns')::int, 0) + (${delta}
|
|
163
|
-
'total_duration_ms', COALESCE((metadata->>'total_duration_ms')::real, 0) + (${delta}
|
|
164
|
-
'total_duration_api_ms', COALESCE((metadata->>'total_duration_api_ms')::real, 0) + (${delta}
|
|
165
|
-
'total_input_tokens', COALESCE((metadata->>'total_input_tokens')::int, 0) + (${delta}
|
|
166
|
-
'total_output_tokens', COALESCE((metadata->>'total_output_tokens')::int, 0) + (${delta}
|
|
167
|
-
'total_cache_read_tokens', COALESCE((metadata->>'total_cache_read_tokens')::int, 0) + (${delta}
|
|
168
|
-
'total_cache_creation_tokens', COALESCE((metadata->>'total_cache_creation_tokens')::int, 0) + (${delta}
|
|
165
|
+
'total_cost_usd', COALESCE((metadata->>'total_cost_usd')::real, 0) + (${delta}->>'total_cost_usd')::real,
|
|
166
|
+
'total_turns', COALESCE((metadata->>'total_turns')::int, 0) + (${delta}->>'total_turns')::int,
|
|
167
|
+
'total_duration_ms', COALESCE((metadata->>'total_duration_ms')::real, 0) + (${delta}->>'total_duration_ms')::real,
|
|
168
|
+
'total_duration_api_ms', COALESCE((metadata->>'total_duration_api_ms')::real, 0) + (${delta}->>'total_duration_api_ms')::real,
|
|
169
|
+
'total_input_tokens', COALESCE((metadata->>'total_input_tokens')::int, 0) + (${delta}->>'total_input_tokens')::int,
|
|
170
|
+
'total_output_tokens', COALESCE((metadata->>'total_output_tokens')::int, 0) + (${delta}->>'total_output_tokens')::int,
|
|
171
|
+
'total_cache_read_tokens', COALESCE((metadata->>'total_cache_read_tokens')::int, 0) + (${delta}->>'total_cache_read_tokens')::int,
|
|
172
|
+
'total_cache_creation_tokens', COALESCE((metadata->>'total_cache_creation_tokens')::int, 0) + (${delta}->>'total_cache_creation_tokens')::int,
|
|
169
173
|
'message_count', COALESCE((metadata->>'message_count')::int, 0) + 1,
|
|
170
|
-
'models_used', COALESCE(metadata->'models_used', '[]'::jsonb) || ${
|
|
174
|
+
'models_used', COALESCE(metadata->'models_used', '[]'::jsonb) || ${modelsDelta},
|
|
171
175
|
'channel', COALESCE(metadata->>'channel', ${(resultMeta.channel as string) || null})
|
|
172
176
|
)
|
|
173
177
|
WHERE id = ${id}
|