refactor: subagent usage and related tools

This commit is contained in:
Acbox
2026-02-22 16:35:50 +08:00
parent 6a6600a440
commit 928b0c0ee5
18 changed files with 403 additions and 68 deletions
+1
View File
@@ -346,6 +346,7 @@ CREATE TABLE IF NOT EXISTS subagents (
messages JSONB NOT NULL DEFAULT '[]'::jsonb,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
skills JSONB NOT NULL DEFAULT '[]'::jsonb,
usage JSONB NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT subagents_name_unique UNIQUE (bot_id, name)
);
@@ -0,0 +1,5 @@
-- 0012_subagent_usage (rollback)
-- Remove usage column from subagents table.
ALTER TABLE subagents DROP COLUMN IF EXISTS usage;
+5
View File
@@ -0,0 +1,5 @@
-- 0012_subagent_usage
-- Add usage JSONB column to subagents table for tracking cumulative token usage.
ALTER TABLE subagents ADD COLUMN IF NOT EXISTS usage JSONB NOT NULL DEFAULT '{}'::jsonb;
+19 -7
View File
@@ -1,15 +1,20 @@
-- 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;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage;
-- name: GetSubagentByID :one
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills
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;
-- 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;
-- name: ListSubagentsByBot :many
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills
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;
@@ -21,21 +26,29 @@ SET name = $2,
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;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage;
-- 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;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage;
-- 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;
-- 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;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage;
-- name: SoftDeleteSubagent :exec
UPDATE subagents
@@ -43,4 +56,3 @@ SET deleted = true,
deleted_at = now(),
updated_at = now()
WHERE id = $1 AND deleted = false;
+1
View File
@@ -291,6 +291,7 @@ type Subagent struct {
Messages []byte `json:"messages"`
Metadata []byte `json:"metadata"`
Skills []byte `json:"skills"`
Usage []byte `json:"usage"`
}
type User struct {
+78 -6
View File
@@ -14,7 +14,7 @@ import (
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
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
`
type CreateSubagentParams struct {
@@ -48,12 +48,44 @@ func (q *Queries) CreateSubagent(ctx context.Context, arg CreateSubagentParams)
&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
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
`
@@ -73,12 +105,13 @@ func (q *Queries) GetSubagentByID(ctx context.Context, id pgtype.UUID) (Subagent
&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
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
@@ -105,6 +138,7 @@ func (q *Queries) ListSubagentsByBot(ctx context.Context, botID pgtype.UUID) ([]
&i.Messages,
&i.Metadata,
&i.Skills,
&i.Usage,
); err != nil {
return nil, err
}
@@ -136,7 +170,7 @@ SET name = $2,
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
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
`
type UpdateSubagentParams struct {
@@ -166,6 +200,7 @@ func (q *Queries) UpdateSubagent(ctx context.Context, arg UpdateSubagentParams)
&i.Messages,
&i.Metadata,
&i.Skills,
&i.Usage,
)
return i, err
}
@@ -175,7 +210,7 @@ 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
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
`
type UpdateSubagentMessagesParams struct {
@@ -198,6 +233,42 @@ func (q *Queries) UpdateSubagentMessages(ctx context.Context, arg UpdateSubagent
&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
}
@@ -207,7 +278,7 @@ 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
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills, usage
`
type UpdateSubagentSkillsParams struct {
@@ -230,6 +301,7 @@ func (q *Queries) UpdateSubagentSkills(ctx context.Context, arg UpdateSubagentSk
&i.Messages,
&i.Metadata,
&i.Skills,
&i.Usage,
)
return i, err
}
+2 -2
View File
@@ -255,7 +255,7 @@ func (h *SubagentHandler) GetContext(c echo.Context) error {
if _, err := h.authorizeBotAccess(c.Request().Context(), channelIdentityID, botID); err != nil {
return err
}
return c.JSON(http.StatusOK, subagent.ContextResponse{Messages: item.Messages})
return c.JSON(http.StatusOK, subagent.ContextResponse{Messages: item.Messages, Usage: item.Usage})
}
// UpdateContext godoc
@@ -300,7 +300,7 @@ func (h *SubagentHandler) UpdateContext(c echo.Context) error {
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
return c.JSON(http.StatusOK, subagent.ContextResponse{Messages: updated.Messages})
return c.JSON(http.StatusOK, subagent.ContextResponse{Messages: updated.Messages, Usage: updated.Usage})
}
// GetSkills godoc
+67 -1
View File
@@ -83,6 +83,32 @@ func (s *Service) Get(ctx context.Context, id string) (Subagent, error) {
return toSubagent(row)
}
func (s *Service) GetByBotAndName(ctx context.Context, botID string, name string) (Subagent, error) {
pgBotID, err := db.ParseUUID(botID)
if err != nil {
return Subagent{}, err
}
row, err := s.queries.GetSubagentByBotAndName(ctx, sqlc.GetSubagentByBotAndNameParams{
BotID: pgBotID,
Name: strings.TrimSpace(name),
})
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return Subagent{}, fmt.Errorf("subagent not found")
}
return Subagent{}, err
}
return toSubagent(row)
}
func (s *Service) GetOrCreate(ctx context.Context, botID string, req CreateRequest) (Subagent, error) {
existing, err := s.GetByBotAndName(ctx, botID, req.Name)
if err == nil {
return existing, nil
}
return s.Create(ctx, botID, req)
}
func (s *Service) List(ctx context.Context, botID string) ([]Subagent, error) {
pgBotID, err := db.ParseUUID(botID)
if err != nil {
@@ -155,6 +181,21 @@ func (s *Service) UpdateContext(ctx context.Context, id string, req UpdateContex
if err != nil {
return Subagent{}, err
}
if req.Usage != nil {
usagePayload, err := marshalUsage(req.Usage)
if err != nil {
return Subagent{}, err
}
row, err := s.queries.UpdateSubagentMessagesAndUsage(ctx, sqlc.UpdateSubagentMessagesAndUsageParams{
ID: pgID,
Messages: messagesPayload,
Usage: usagePayload,
})
if err != nil {
return Subagent{}, err
}
return toSubagent(row)
}
row, err := s.queries.UpdateSubagentMessages(ctx, sqlc.UpdateSubagentMessagesParams{
ID: pgID,
Messages: messagesPayload,
@@ -229,6 +270,10 @@ func toSubagent(row sqlc.Subagent) (Subagent, error) {
if err != nil {
return Subagent{}, err
}
usage, err := unmarshalUsage(row.Usage)
if err != nil {
return Subagent{}, err
}
item := Subagent{
ID: row.ID.String(),
Name: row.Name,
@@ -237,6 +282,7 @@ func toSubagent(row sqlc.Subagent) (Subagent, error) {
Messages: messages,
Metadata: metadata,
Skills: skills,
Usage: usage,
Deleted: row.Deleted,
}
if row.CreatedAt.Valid {
@@ -294,6 +340,27 @@ func unmarshalMetadata(payload []byte) (map[string]any, error) {
return metadata, nil
}
func marshalUsage(usage map[string]any) ([]byte, error) {
if usage == nil {
usage = map[string]any{}
}
return json.Marshal(usage)
}
func unmarshalUsage(payload []byte) (map[string]any, error) {
if len(payload) == 0 {
return map[string]any{}, nil
}
var usage map[string]any
if err := json.Unmarshal(payload, &usage); err != nil {
return nil, err
}
if usage == nil {
usage = map[string]any{}
}
return usage, nil
}
func marshalSkills(skills []string) ([]byte, error) {
return json.Marshal(normalizeSkills(skills))
}
@@ -334,4 +401,3 @@ func mergeSkills(existing []string, incoming []string) []string {
merged = append(merged, incoming...)
return normalizeSkills(merged)
}
+3
View File
@@ -10,6 +10,7 @@ type Subagent struct {
Messages []map[string]any `json:"messages"`
Metadata map[string]any `json:"metadata"`
Skills []string `json:"skills"`
Usage map[string]any `json:"usage"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Deleted bool `json:"deleted"`
@@ -32,6 +33,7 @@ type UpdateRequest struct {
type UpdateContextRequest struct {
Messages []map[string]any `json:"messages"`
Usage map[string]any `json:"usage,omitempty"`
}
type UpdateSkillsRequest struct {
@@ -48,6 +50,7 @@ type ListResponse struct {
type ContextResponse struct {
Messages []map[string]any `json:"messages"`
Usage map[string]any `json:"usage"`
}
type SkillsResponse struct {
+2
View File
@@ -17,6 +17,8 @@
"@ai-sdk/mcp": "^1.0.6",
"@ai-sdk/openai": "^3.0.7",
"@mozilla/readability": "^0.6.0",
"@types/jsdom": "^27.0.0",
"@types/turndown": "^5.0.6",
"ai": "^6.0.25",
"jsdom": "^27.4.0",
"toml": "^3.0.0",
+39 -51
View File
@@ -1,9 +1,13 @@
import { tool } from 'ai'
import { tool, type ModelMessage } from 'ai'
import { z } from 'zod'
import { createAgent } from '../agent'
import { ModelConfig, AgentAuthContext } from '../types'
import { AuthFetcher } from '../types'
import { AgentAction, IdentityContext } from '../types/agent'
import type { ModelConfig, AgentAuthContext, AuthFetcher } from '../types'
import { AgentAction, type IdentityContext } from '../types/agent'
import {
createSubagentClient,
toSubagentUsage,
addUsage,
} from '../utils/subagent'
export interface SubagentToolParams {
fetch: AuthFetcher
@@ -14,7 +18,7 @@ export interface SubagentToolParams {
export const getSubagentTools = ({ fetch, model, identity, auth }: SubagentToolParams) => {
const botId = identity.botId.trim()
const base = `/bots/${botId}/subagents`
const client = createSubagentClient(fetch, botId)
const listSubagents = tool({
description: 'List subagents for current user',
@@ -23,27 +27,7 @@ export const getSubagentTools = ({ fetch, model, identity, auth }: SubagentToolP
if (!botId) {
throw new Error('bot_id is required')
}
const response = await fetch(base, { method: 'GET' })
return response.json()
},
})
const createSubagent = tool({
description: 'Create a new subagent',
inputSchema: z.object({
name: z.string(),
description: z.string(),
}),
execute: async ({ name, description }) => {
if (!botId) {
throw new Error('bot_id is required')
}
const response = await fetch(base, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, description }),
})
return response.json()
return client.list()
},
})
@@ -56,51 +40,56 @@ export const getSubagentTools = ({ fetch, model, identity, auth }: SubagentToolP
if (!botId) {
throw new Error('bot_id is required')
}
const response = await fetch(`${base}/${id}`, { method: 'DELETE' })
return response.status === 204 ? { success: true } : response.json()
return client.remove(id)
},
})
const querySubagent = tool({
description: 'Query a subagent',
description: 'Query a subagent. If the subagent does not exist it will be created automatically.',
inputSchema: z.object({
name: z.string(),
name: z.string().describe('The name of the subagent'),
description: z.string().describe('A short description of the subagent purpose (used when creating)'),
query: z.string().describe('The prompt to ask the subagent to do.'),
}),
execute: async ({ name, query }) => {
execute: async ({ name, description, query }) => {
if (!botId) {
throw new Error('bot_id is required')
}
const listResponse = await fetch(base, { method: 'GET' })
const listPayload = await listResponse.json()
const items = Array.isArray(listPayload?.items) ? listPayload.items : []
const target = items.find((item: { name?: string }) => item?.name === name)
if (!target?.id) {
throw new Error(`subagent not found: ${name}`)
}
const contextResponse = await fetch(`${base}/${target.id}/context`, { method: 'GET' })
const contextPayload = await contextResponse.json()
const contextMessages = Array.isArray(contextPayload?.messages) ? contextPayload.messages : []
// Get or create the subagent
const target = await client.getOrCreate({ name, description })
// Load persisted context (messages + usage)
const ctx = await client.getContext(target.id)
const contextMessages = (Array.isArray(ctx.messages) ? ctx.messages : []) as ModelMessage[]
const existingUsage = toSubagentUsage(ctx.usage)
// Create a scoped agent instance for the subagent
const { askAsSubagent } = createAgent({
model,
allowedActions: [
AgentAction.Web,
],
allowedActions: [AgentAction.Web],
identity,
auth,
}, fetch)
const result = await askAsSubagent({
messages: contextMessages,
input: query,
name: target.name,
description: target.description,
})
// Accumulate usage
const newUsage = addUsage(existingUsage, result.usage)
// Persist updated messages + usage
const updatedMessages = [...contextMessages, ...result.messages]
await fetch(`${base}/${target.id}/context`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: updatedMessages }),
})
await client.updateContext(
target.id,
updatedMessages as Record<string, unknown>[],
newUsage,
)
return {
success: true,
result: result.messages[result.messages.length - 1].content,
@@ -110,8 +99,7 @@ export const getSubagentTools = ({ fetch, model, identity, auth }: SubagentToolP
return {
'list_subagents': listSubagents,
'create_subagent': createSubagent,
'delete_subagent': deleteSubagent,
'query_subagent': querySubagent,
}
}
}
+2 -1
View File
@@ -1,2 +1,3 @@
export * from './attachments'
export * from './headers'
export * from './headers'
export * from './subagent'
+131
View File
@@ -0,0 +1,131 @@
import type { AuthFetcher } from '../types'
import type { LanguageModelUsage } from 'ai'
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
export interface SubagentItem {
id: string
name: string
description: string
bot_id: string
messages: Record<string, unknown>[]
metadata: Record<string, unknown>
skills: string[]
usage: SubagentUsage
created_at: string
updated_at: string
deleted: boolean
deleted_at?: string
}
export interface SubagentUsage {
inputTokens: number
outputTokens: number
totalTokens: number
}
export interface SubagentListResponse {
items: SubagentItem[]
}
export interface SubagentContextResponse {
messages: Record<string, unknown>[]
usage: SubagentUsage
}
// ---------------------------------------------------------------------------
// Usage helpers
// ---------------------------------------------------------------------------
const emptyUsage: SubagentUsage = {
inputTokens: 0,
outputTokens: 0,
totalTokens: 0,
}
export const toSubagentUsage = (raw: unknown): SubagentUsage => {
if (!raw || typeof raw !== 'object') return { ...emptyUsage }
const obj = raw as Record<string, unknown>
return {
inputTokens: typeof obj.inputTokens === 'number' ? obj.inputTokens : 0,
outputTokens: typeof obj.outputTokens === 'number' ? obj.outputTokens : 0,
totalTokens: typeof obj.totalTokens === 'number' ? obj.totalTokens : 0,
}
}
export const addUsage = (
existing: SubagentUsage,
delta: LanguageModelUsage,
): SubagentUsage => ({
inputTokens: existing.inputTokens + (delta.inputTokens ?? 0),
outputTokens: existing.outputTokens + (delta.outputTokens ?? 0),
totalTokens: existing.totalTokens + (delta.totalTokens ?? 0),
})
// ---------------------------------------------------------------------------
// Client factory
// ---------------------------------------------------------------------------
export const createSubagentClient = (fetch: AuthFetcher, botId: string) => {
const base = `/bots/${botId}/subagents`
const list = async (): Promise<SubagentListResponse> => {
const res = await fetch(base, { method: 'GET' })
return res.json() as Promise<SubagentListResponse>
}
const create = async (params: {
name: string
description: string
}): Promise<SubagentItem> => {
const res = await fetch(base, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
})
return res.json() as Promise<SubagentItem>
}
const get = async (id: string): Promise<SubagentItem> => {
const res = await fetch(`${base}/${id}`, { method: 'GET' })
return res.json() as Promise<SubagentItem>
}
const getContext = async (id: string): Promise<SubagentContextResponse> => {
const res = await fetch(`${base}/${id}/context`, { method: 'GET' })
return res.json() as Promise<SubagentContextResponse>
}
const updateContext = async (
id: string,
messages: Record<string, unknown>[],
usage: SubagentUsage,
): Promise<SubagentContextResponse> => {
const res = await fetch(`${base}/${id}/context`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages, usage }),
})
return res.json() as Promise<SubagentContextResponse>
}
const getOrCreate = async (params: {
name: string
description: string
}): Promise<SubagentItem> => {
const { items } = await list()
const existing = items.find((item) => item.name === params.name)
if (existing) return existing
return create(params)
}
const remove = async (id: string): Promise<{ success: boolean }> => {
const res = await fetch(`${base}/${id}`, { method: 'DELETE' })
return res.status === 204 ? { success: true } : (res.json() as Promise<{ success: boolean }>)
}
return { list, create, get, getContext, updateContext, getOrCreate, remove }
}
+9
View File
@@ -944,6 +944,9 @@ export type SubagentContextResponse = {
messages?: Array<{
[key: string]: unknown;
}>;
usage?: {
[key: string]: unknown;
};
};
export type SubagentCreateRequest = {
@@ -982,12 +985,18 @@ export type SubagentSubagent = {
name?: string;
skills?: Array<string>;
updated_at?: string;
usage?: {
[key: string]: unknown;
};
};
export type SubagentUpdateContextRequest = {
messages?: Array<{
[key: string]: unknown;
}>;
usage?: {
[key: string]: unknown;
};
};
export type SubagentUpdateRequest = {
+6
View File
@@ -121,6 +121,12 @@ importers:
'@mozilla/readability':
specifier: ^0.6.0
version: 0.6.0
'@types/jsdom':
specifier: ^27.0.0
version: 27.0.0
'@types/turndown':
specifier: ^5.0.6
version: 5.0.6
ai:
specifier: ^6.0.25
version: 6.0.25(zod@4.3.6)
+12
View File
@@ -7657,6 +7657,10 @@ const docTemplate = `{
"type": "object",
"additionalProperties": {}
}
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
@@ -7753,6 +7757,10 @@ const docTemplate = `{
},
"updated_at": {
"type": "string"
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
@@ -7765,6 +7773,10 @@ const docTemplate = `{
"type": "object",
"additionalProperties": {}
}
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
+12
View File
@@ -7648,6 +7648,10 @@
"type": "object",
"additionalProperties": {}
}
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
@@ -7744,6 +7748,10 @@
},
"updated_at": {
"type": "string"
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
@@ -7756,6 +7764,10 @@
"type": "object",
"additionalProperties": {}
}
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
+9
View File
@@ -1553,6 +1553,9 @@ definitions:
additionalProperties: {}
type: object
type: array
usage:
additionalProperties: {}
type: object
type: object
subagent.CreateRequest:
properties:
@@ -1617,6 +1620,9 @@ definitions:
type: array
updated_at:
type: string
usage:
additionalProperties: {}
type: object
type: object
subagent.UpdateContextRequest:
properties:
@@ -1625,6 +1631,9 @@ definitions:
additionalProperties: {}
type: object
type: array
usage:
additionalProperties: {}
type: object
type: object
subagent.UpdateRequest:
properties: