mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-25 07:00:48 +09:00
refactor: replace persistent subagents with ephemeral spawn tool (#280)
* refactor: replace persistent subagents with ephemeral spawn tool (#subagent) - Drop subagents table, remove all persistent subagent infrastructure - Add 'subagent' session type with parent_session_id on bot_sessions - Rewrite subagent tool as single 'spawn' tool with parallel execution - Create system_subagent.md prompt, add _subagent.md include for chat - Limit subagent tools to file, exec, web_search, web_fetch only - Merge subagent token usage into parent chat session in reporting - Remove frontend subagent management page, update chat UI for spawn - Fix UTF-8 truncation in session title, fix query not passed to agent * refactor: remove history message page
This commit is contained in:
+11
-25
@@ -154,16 +154,17 @@ type BotHistoryMessageCompact struct {
|
||||
}
|
||||
|
||||
type BotSession struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
RouteID pgtype.UUID `json:"route_id"`
|
||||
ChannelType pgtype.Text `json:"channel_type"`
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
ID pgtype.UUID `json:"id"`
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
RouteID pgtype.UUID `json:"route_id"`
|
||||
ChannelType pgtype.Text `json:"channel_type"`
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
ParentSessionID pgtype.UUID `json:"parent_session_id"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
}
|
||||
|
||||
type BotStorageBinding struct {
|
||||
@@ -435,21 +436,6 @@ type StorageProvider struct {
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Subagent struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Deleted bool `json:"deleted"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
Messages []byte `json:"messages"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
Skills []byte `json:"skills"`
|
||||
Usage []byte `json:"usage"`
|
||||
}
|
||||
|
||||
type TtsModel struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
ModelID string `json:"model_id"`
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
const createSession = `-- name: CreateSession :one
|
||||
INSERT INTO bot_sessions (
|
||||
bot_id, route_id, channel_type, type, title, metadata
|
||||
bot_id, route_id, channel_type, type, title, metadata, parent_session_id
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
@@ -21,18 +21,20 @@ VALUES (
|
||||
$3::text,
|
||||
$4,
|
||||
$5,
|
||||
$6
|
||||
$6,
|
||||
$7::uuid
|
||||
)
|
||||
RETURNING id, bot_id, route_id, channel_type, type, title, metadata, created_at, updated_at, deleted_at
|
||||
RETURNING id, bot_id, route_id, channel_type, type, title, metadata, parent_session_id, created_at, updated_at, deleted_at
|
||||
`
|
||||
|
||||
type CreateSessionParams struct {
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
RouteID pgtype.UUID `json:"route_id"`
|
||||
ChannelType pgtype.Text `json:"channel_type"`
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
RouteID pgtype.UUID `json:"route_id"`
|
||||
ChannelType pgtype.Text `json:"channel_type"`
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
ParentSessionID pgtype.UUID `json:"parent_session_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (BotSession, error) {
|
||||
@@ -43,6 +45,7 @@ func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (B
|
||||
arg.Type,
|
||||
arg.Title,
|
||||
arg.Metadata,
|
||||
arg.ParentSessionID,
|
||||
)
|
||||
var i BotSession
|
||||
err := row.Scan(
|
||||
@@ -53,6 +56,7 @@ func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (B
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
@@ -61,7 +65,7 @@ func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (B
|
||||
}
|
||||
|
||||
const getActiveSessionForRoute = `-- name: GetActiveSessionForRoute :one
|
||||
SELECT s.id, s.bot_id, s.route_id, s.channel_type, s.type, s.title, s.metadata, s.created_at, s.updated_at, s.deleted_at
|
||||
SELECT s.id, s.bot_id, s.route_id, s.channel_type, s.type, s.title, s.metadata, s.parent_session_id, s.created_at, s.updated_at, s.deleted_at
|
||||
FROM bot_sessions s
|
||||
JOIN bot_channel_routes r ON r.active_session_id = s.id
|
||||
WHERE r.id = $1
|
||||
@@ -79,6 +83,7 @@ func (q *Queries) GetActiveSessionForRoute(ctx context.Context, routeID pgtype.U
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
@@ -87,7 +92,7 @@ func (q *Queries) GetActiveSessionForRoute(ctx context.Context, routeID pgtype.U
|
||||
}
|
||||
|
||||
const getSessionByID = `-- name: GetSessionByID :one
|
||||
SELECT id, bot_id, route_id, channel_type, type, title, metadata, created_at, updated_at, deleted_at
|
||||
SELECT id, bot_id, route_id, channel_type, type, title, metadata, parent_session_id, created_at, updated_at, deleted_at
|
||||
FROM bot_sessions
|
||||
WHERE id = $1
|
||||
AND deleted_at IS NULL
|
||||
@@ -104,6 +109,7 @@ func (q *Queries) GetSessionByID(ctx context.Context, id pgtype.UUID) (BotSessio
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
@@ -173,7 +179,7 @@ func (q *Queries) ListSessionsByBot(ctx context.Context, botID pgtype.UUID) ([]L
|
||||
}
|
||||
|
||||
const listSessionsByRoute = `-- name: ListSessionsByRoute :many
|
||||
SELECT id, bot_id, route_id, channel_type, type, title, metadata, created_at, updated_at, deleted_at
|
||||
SELECT id, bot_id, route_id, channel_type, type, title, metadata, parent_session_id, created_at, updated_at, deleted_at
|
||||
FROM bot_sessions
|
||||
WHERE route_id = $1
|
||||
AND deleted_at IS NULL
|
||||
@@ -197,6 +203,47 @@ func (q *Queries) ListSessionsByRoute(ctx context.Context, routeID pgtype.UUID)
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listSubagentSessionsByParent = `-- name: ListSubagentSessionsByParent :many
|
||||
SELECT id, bot_id, route_id, channel_type, type, title, metadata, parent_session_id, created_at, updated_at, deleted_at
|
||||
FROM bot_sessions
|
||||
WHERE parent_session_id = $1
|
||||
AND deleted_at IS NULL
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListSubagentSessionsByParent(ctx context.Context, parentSessionID pgtype.UUID) ([]BotSession, error) {
|
||||
rows, err := q.db.Query(ctx, listSubagentSessionsByParent, parentSessionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []BotSession
|
||||
for rows.Next() {
|
||||
var i BotSession
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.BotID,
|
||||
&i.RouteID,
|
||||
&i.ChannelType,
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
@@ -248,7 +295,7 @@ const updateSessionMetadata = `-- name: UpdateSessionMetadata :one
|
||||
UPDATE bot_sessions
|
||||
SET metadata = $1, updated_at = now()
|
||||
WHERE id = $2 AND deleted_at IS NULL
|
||||
RETURNING id, bot_id, route_id, channel_type, type, title, metadata, created_at, updated_at, deleted_at
|
||||
RETURNING id, bot_id, route_id, channel_type, type, title, metadata, parent_session_id, created_at, updated_at, deleted_at
|
||||
`
|
||||
|
||||
type UpdateSessionMetadataParams struct {
|
||||
@@ -267,6 +314,7 @@ func (q *Queries) UpdateSessionMetadata(ctx context.Context, arg UpdateSessionMe
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
@@ -278,7 +326,7 @@ const updateSessionTitle = `-- name: UpdateSessionTitle :one
|
||||
UPDATE bot_sessions
|
||||
SET title = $1, updated_at = now()
|
||||
WHERE id = $2 AND deleted_at IS NULL
|
||||
RETURNING id, bot_id, route_id, channel_type, type, title, metadata, created_at, updated_at, deleted_at
|
||||
RETURNING id, bot_id, route_id, channel_type, type, title, metadata, parent_session_id, created_at, updated_at, deleted_at
|
||||
`
|
||||
|
||||
type UpdateSessionTitleParams struct {
|
||||
@@ -297,6 +345,7 @@ func (q *Queries) UpdateSessionTitle(ctx context.Context, arg UpdateSessionTitle
|
||||
&i.Type,
|
||||
&i.Title,
|
||||
&i.Metadata,
|
||||
&i.ParentSessionID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: subagents.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createSubagent = `-- name: CreateSubagent :one
|
||||
INSERT INTO subagents (name, description, bot_id, messages, metadata, skills)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
`
|
||||
|
||||
type CreateSubagentParams struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
Messages []byte `json:"messages"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
Skills []byte `json:"skills"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSubagent(ctx context.Context, arg CreateSubagentParams) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, createSubagent,
|
||||
arg.Name,
|
||||
arg.Description,
|
||||
arg.BotID,
|
||||
arg.Messages,
|
||||
arg.Metadata,
|
||||
arg.Skills,
|
||||
)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSubagentByBotAndName = `-- name: GetSubagentByBotAndName :one
|
||||
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
FROM subagents
|
||||
WHERE bot_id = $1 AND name = $2 AND deleted = false
|
||||
`
|
||||
|
||||
type GetSubagentByBotAndNameParams struct {
|
||||
BotID pgtype.UUID `json:"bot_id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSubagentByBotAndName(ctx context.Context, arg GetSubagentByBotAndNameParams) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, getSubagentByBotAndName, arg.BotID, arg.Name)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSubagentByID = `-- name: GetSubagentByID :one
|
||||
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
FROM subagents
|
||||
WHERE id = $1 AND deleted = false
|
||||
`
|
||||
|
||||
func (q *Queries) GetSubagentByID(ctx context.Context, id pgtype.UUID) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, getSubagentByID, id)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listSubagentsByBot = `-- name: ListSubagentsByBot :many
|
||||
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
FROM subagents
|
||||
WHERE bot_id = $1 AND deleted = false
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListSubagentsByBot(ctx context.Context, botID pgtype.UUID) ([]Subagent, error) {
|
||||
rows, err := q.db.Query(ctx, listSubagentsByBot, botID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Subagent
|
||||
for rows.Next() {
|
||||
var i Subagent
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const softDeleteSubagent = `-- name: SoftDeleteSubagent :exec
|
||||
UPDATE subagents
|
||||
SET deleted = true,
|
||||
deleted_at = now(),
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND deleted = false
|
||||
`
|
||||
|
||||
func (q *Queries) SoftDeleteSubagent(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, softDeleteSubagent, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateSubagent = `-- name: UpdateSubagent :one
|
||||
UPDATE subagents
|
||||
SET name = $2,
|
||||
description = $3,
|
||||
metadata = $4,
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND deleted = false
|
||||
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
`
|
||||
|
||||
type UpdateSubagentParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSubagent(ctx context.Context, arg UpdateSubagentParams) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, updateSubagent,
|
||||
arg.ID,
|
||||
arg.Name,
|
||||
arg.Description,
|
||||
arg.Metadata,
|
||||
)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateSubagentMessages = `-- name: UpdateSubagentMessages :one
|
||||
UPDATE subagents
|
||||
SET messages = $2,
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND deleted = false
|
||||
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
`
|
||||
|
||||
type UpdateSubagentMessagesParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Messages []byte `json:"messages"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSubagentMessages(ctx context.Context, arg UpdateSubagentMessagesParams) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, updateSubagentMessages, arg.ID, arg.Messages)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateSubagentMessagesAndUsage = `-- name: UpdateSubagentMessagesAndUsage :one
|
||||
UPDATE subagents
|
||||
SET messages = $2,
|
||||
usage = $3,
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND deleted = false
|
||||
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
`
|
||||
|
||||
type UpdateSubagentMessagesAndUsageParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Messages []byte `json:"messages"`
|
||||
Usage []byte `json:"usage"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSubagentMessagesAndUsage(ctx context.Context, arg UpdateSubagentMessagesAndUsageParams) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, updateSubagentMessagesAndUsage, arg.ID, arg.Messages, arg.Usage)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateSubagentSkills = `-- name: UpdateSubagentSkills :one
|
||||
UPDATE subagents
|
||||
SET skills = $2,
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND deleted = false
|
||||
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
|
||||
`
|
||||
|
||||
type UpdateSubagentSkillsParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Skills []byte `json:"skills"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSubagentSkills(ctx context.Context, arg UpdateSubagentSkillsParams) (Subagent, error) {
|
||||
row := q.db.QueryRow(ctx, updateSubagentSkills, arg.ID, arg.Skills)
|
||||
var i Subagent
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.BotID,
|
||||
&i.Messages,
|
||||
&i.Metadata,
|
||||
&i.Skills,
|
||||
&i.Usage,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -13,7 +13,10 @@ import (
|
||||
|
||||
const getTokenUsageByDayAndType = `-- name: GetTokenUsageByDayAndType :many
|
||||
SELECT
|
||||
COALESCE(s.type, 'chat')::text AS session_type,
|
||||
COALESCE(
|
||||
CASE WHEN s.type = 'subagent' THEN COALESCE(ps.type, 'chat') ELSE s.type END,
|
||||
'chat'
|
||||
)::text AS session_type,
|
||||
date_trunc('day', m.created_at)::date AS day,
|
||||
COALESCE(SUM((m.usage->>'inputTokens')::bigint), 0)::bigint AS input_tokens,
|
||||
COALESCE(SUM((m.usage->>'outputTokens')::bigint), 0)::bigint AS output_tokens,
|
||||
@@ -22,6 +25,7 @@ SELECT
|
||||
COALESCE(SUM((m.usage->'outputTokenDetails'->>'reasoningTokens')::bigint), 0)::bigint AS reasoning_tokens
|
||||
FROM bot_history_messages m
|
||||
LEFT JOIN bot_sessions s ON s.id = m.session_id
|
||||
LEFT JOIN bot_sessions ps ON ps.id = s.parent_session_id
|
||||
WHERE m.bot_id = $1
|
||||
AND m.usage IS NOT NULL
|
||||
AND m.created_at >= $2
|
||||
|
||||
Reference in New Issue
Block a user