feat(memory): implement stability stage
Some checks failed
CI / validate (push) Has been cancelled
CI / validate (pull_request) Has been cancelled

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-09-02 15:04:18 +05:00
parent 4cd0b7b390
commit 031d094867
24 changed files with 1661 additions and 79 deletions

View File

@@ -5,6 +5,14 @@ const CompletionResponseSchema = z.object({
choices: z.array(z.object({
message: z.object({ content: z.string().min(1) }),
})).min(1),
usage: z.object({
prompt_tokens: z.number().nonnegative().nullish(),
completion_tokens: z.number().nonnegative().nullish(),
input_tokens: z.number().nonnegative().nullish(),
output_tokens: z.number().nonnegative().nullish(),
cost: z.number().nonnegative().nullish(),
total_cost: z.number().nonnegative().nullish(),
}).optional(),
})
export type AiProvider = z.infer<typeof ProviderSchema>
@@ -26,10 +34,18 @@ export interface JsonCompletionRequest {
jsonSchema: Record<string, unknown>
}
interface JsonCompletion {
export interface JsonCompletion {
endpoint: string
headers: Record<string, string>
body: Record<string, unknown>
provider: AiProvider
model: string
}
export interface AiUsageSnapshot {
inputTokens: number
outputTokens: number
costUsd: number
}
const nonEmptyString = (value: unknown, name: string) => {
@@ -73,6 +89,8 @@ export function buildJsonCompletion(config: AiRuntimeConfig, request: JsonComple
if (provider.provider === 'deepseek') {
return {
endpoint: provider.endpoint,
provider: provider.provider,
model: provider.model,
headers: { Authorization: `Bearer ${provider.apiKey}`, 'Content-Type': 'application/json' },
body: {
...common,
@@ -88,6 +106,8 @@ export function buildJsonCompletion(config: AiRuntimeConfig, request: JsonComple
return {
endpoint: provider.endpoint,
provider: provider.provider,
model: provider.model,
headers: { Authorization: `Bearer ${provider.apiKey}`, 'Content-Type': 'application/json', 'X-Title': 'Dungeons & Ground' },
body: {
...common,
@@ -101,3 +121,12 @@ export function parseJsonCompletion(payload: unknown): unknown {
const completion = CompletionResponseSchema.parse(payload)
return JSON.parse(completion.choices[0]!.message.content)
}
export function parseAiUsage(payload: unknown): AiUsageSnapshot {
const completion = CompletionResponseSchema.parse(payload)
return {
inputTokens: Math.max(0, Math.trunc(completion.usage?.prompt_tokens ?? completion.usage?.input_tokens ?? 0)),
outputTokens: Math.max(0, Math.trunc(completion.usage?.completion_tokens ?? completion.usage?.output_tokens ?? 0)),
costUsd: Math.max(0, completion.usage?.cost ?? completion.usage?.total_cost ?? 0),
}
}