Merge d9907fb15ede84e8093d053807f5adddc5073a31 into 8a05c05596ca9ba0735dafd8e359885de4c2c969
This commit is contained in:
commit
4331b68430
@ -68,10 +68,17 @@ export async function updateSessionStoreAfterAgentRun(params: {
|
|||||||
updatedAt: Date.now(),
|
updatedAt: Date.now(),
|
||||||
contextTokens,
|
contextTokens,
|
||||||
};
|
};
|
||||||
|
const modelChanged =
|
||||||
|
(entry.model !== undefined && entry.model !== modelUsed) ||
|
||||||
|
(entry.modelProvider !== undefined && entry.modelProvider !== providerUsed);
|
||||||
setSessionRuntimeModel(next, {
|
setSessionRuntimeModel(next, {
|
||||||
provider: providerUsed,
|
provider: providerUsed,
|
||||||
model: modelUsed,
|
model: modelUsed,
|
||||||
});
|
});
|
||||||
|
if (modelChanged) {
|
||||||
|
next.totalTokens = undefined;
|
||||||
|
next.totalTokensFresh = false;
|
||||||
|
}
|
||||||
if (isCliProvider(providerUsed, cfg)) {
|
if (isCliProvider(providerUsed, cfg)) {
|
||||||
const cliSessionId = result.meta.agentMeta?.sessionId?.trim();
|
const cliSessionId = result.meta.agentMeta?.sessionId?.trim();
|
||||||
if (cliSessionId) {
|
if (cliSessionId) {
|
||||||
@ -105,9 +112,13 @@ export async function updateSessionStoreAfterAgentRun(params: {
|
|||||||
if (typeof totalTokens === "number" && Number.isFinite(totalTokens) && totalTokens > 0) {
|
if (typeof totalTokens === "number" && Number.isFinite(totalTokens) && totalTokens > 0) {
|
||||||
next.totalTokens = totalTokens;
|
next.totalTokens = totalTokens;
|
||||||
next.totalTokensFresh = true;
|
next.totalTokensFresh = true;
|
||||||
|
next.totalTokensEstimate = totalTokens;
|
||||||
} else {
|
} else {
|
||||||
next.totalTokens = undefined;
|
next.totalTokens = undefined;
|
||||||
next.totalTokensFresh = false;
|
next.totalTokensFresh = false;
|
||||||
|
if (typeof totalTokens === "number" && Number.isFinite(totalTokens)) {
|
||||||
|
next.totalTokensEstimate = totalTokens;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
next.cacheRead = usage.cacheRead ?? 0;
|
next.cacheRead = usage.cacheRead ?? 0;
|
||||||
next.cacheWrite = usage.cacheWrite ?? 0;
|
next.cacheWrite = usage.cacheWrite ?? 0;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { resolveTotalTokens } from "../shared/subagents-format.js";
|
||||||
import { resolveQueueSettings } from "../auto-reply/reply/queue.js";
|
import { resolveQueueSettings } from "../auto-reply/reply/queue.js";
|
||||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||||
import { DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH } from "../config/agent-limits.js";
|
import { DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH } from "../config/agent-limits.js";
|
||||||
@ -550,7 +551,7 @@ async function buildCompactAnnounceStatsLine(params: {
|
|||||||
const input = typeof entry?.inputTokens === "number" ? entry.inputTokens : 0;
|
const input = typeof entry?.inputTokens === "number" ? entry.inputTokens : 0;
|
||||||
const output = typeof entry?.outputTokens === "number" ? entry.outputTokens : 0;
|
const output = typeof entry?.outputTokens === "number" ? entry.outputTokens : 0;
|
||||||
const ioTotal = input + output;
|
const ioTotal = input + output;
|
||||||
const promptCache = typeof entry?.totalTokens === "number" ? entry.totalTokens : undefined;
|
const promptCache = resolveTotalTokens(entry as any);
|
||||||
const runtimeMs =
|
const runtimeMs =
|
||||||
typeof params.startedAt === "number" && typeof params.endedAt === "number"
|
typeof params.startedAt === "number" && typeof params.endedAt === "number"
|
||||||
? Math.max(0, params.endedAt - params.startedAt)
|
? Math.max(0, params.endedAt - params.startedAt)
|
||||||
|
|||||||
@ -4,7 +4,10 @@ import {
|
|||||||
resolveBootstrapTotalMaxChars,
|
resolveBootstrapTotalMaxChars,
|
||||||
} from "../../agents/pi-embedded-helpers.js";
|
} from "../../agents/pi-embedded-helpers.js";
|
||||||
import { buildSystemPromptReport } from "../../agents/system-prompt-report.js";
|
import { buildSystemPromptReport } from "../../agents/system-prompt-report.js";
|
||||||
import type { SessionSystemPromptReport } from "../../config/sessions/types.js";
|
import {
|
||||||
|
resolveFreshSessionTotalTokens,
|
||||||
|
type SessionSystemPromptReport,
|
||||||
|
} from "../../config/sessions/types.js";
|
||||||
import type { ReplyPayload } from "../types.js";
|
import type { ReplyPayload } from "../types.js";
|
||||||
import { resolveCommandsSystemPromptBundle } from "./commands-system-prompt.js";
|
import { resolveCommandsSystemPromptBundle } from "./commands-system-prompt.js";
|
||||||
import type { HandleCommandsParams } from "./commands-types.js";
|
import type { HandleCommandsParams } from "./commands-types.js";
|
||||||
@ -96,8 +99,10 @@ export async function buildContextReply(params: HandleCommandsParams): Promise<R
|
|||||||
}
|
}
|
||||||
|
|
||||||
const report = await resolveContextReport(params);
|
const report = await resolveContextReport(params);
|
||||||
|
const totalTokens = resolveFreshSessionTotalTokens(params.sessionEntry);
|
||||||
const session = {
|
const session = {
|
||||||
totalTokens: params.sessionEntry?.totalTokens ?? null,
|
totalTokens: totalTokens ?? null,
|
||||||
|
totalTokensFresh: params.sessionEntry?.totalTokensFresh ?? false,
|
||||||
inputTokens: params.sessionEntry?.inputTokens ?? null,
|
inputTokens: params.sessionEntry?.inputTokens ?? null,
|
||||||
outputTokens: params.sessionEntry?.outputTokens ?? null,
|
outputTokens: params.sessionEntry?.outputTokens ?? null,
|
||||||
contextTokens: params.contextTokens ?? null,
|
contextTokens: params.contextTokens ?? null,
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import {
|
|||||||
resolveThreadFlag,
|
resolveThreadFlag,
|
||||||
resolveSessionResetPolicy,
|
resolveSessionResetPolicy,
|
||||||
resolveSessionResetType,
|
resolveSessionResetType,
|
||||||
|
resolveFreshSessionTotalTokens,
|
||||||
resolveGroupSessionKey,
|
resolveGroupSessionKey,
|
||||||
resolveSessionKey,
|
resolveSessionKey,
|
||||||
resolveSessionTranscriptPath,
|
resolveSessionTranscriptPath,
|
||||||
@ -478,7 +479,7 @@ export async function initSessionState(params: {
|
|||||||
sessionStore[parentSessionKey] &&
|
sessionStore[parentSessionKey] &&
|
||||||
!alreadyForked
|
!alreadyForked
|
||||||
) {
|
) {
|
||||||
const parentTokens = sessionStore[parentSessionKey].totalTokens ?? 0;
|
const parentTokens = resolveFreshSessionTotalTokens(sessionStore[parentSessionKey]) ?? 0;
|
||||||
if (parentForkMaxTokens > 0 && parentTokens > parentForkMaxTokens) {
|
if (parentForkMaxTokens > 0 && parentTokens > parentForkMaxTokens) {
|
||||||
// Parent context is too large — forking would create a thread session
|
// Parent context is too large — forking would create a thread session
|
||||||
// that immediately overflows the model's context window. Start fresh
|
// that immediately overflows the model's context window. Start fresh
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { resolveChannelModelOverride } from "../channels/model-overrides.js";
|
|||||||
import { isCommandFlagEnabled } from "../config/commands.js";
|
import { isCommandFlagEnabled } from "../config/commands.js";
|
||||||
import type { OpenClawConfig } from "../config/config.js";
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
import {
|
import {
|
||||||
|
resolveFreshSessionTotalTokens,
|
||||||
resolveMainSessionKey,
|
resolveMainSessionKey,
|
||||||
resolveSessionFilePath,
|
resolveSessionFilePath,
|
||||||
resolveSessionFilePathOptions,
|
resolveSessionFilePathOptions,
|
||||||
@ -460,7 +461,7 @@ export function buildStatusMessage(args: StatusArgs): string {
|
|||||||
let outputTokens = entry?.outputTokens;
|
let outputTokens = entry?.outputTokens;
|
||||||
let cacheRead = entry?.cacheRead;
|
let cacheRead = entry?.cacheRead;
|
||||||
let cacheWrite = entry?.cacheWrite;
|
let cacheWrite = entry?.cacheWrite;
|
||||||
let totalTokens = entry?.totalTokens ?? (entry?.inputTokens ?? 0) + (entry?.outputTokens ?? 0);
|
let totalTokens = resolveFreshSessionTotalTokens(entry) ?? (entry?.inputTokens ?? 0) + (entry?.outputTokens ?? 0);
|
||||||
|
|
||||||
// Prefer prompt-size tokens from the session transcript when it looks larger
|
// Prefer prompt-size tokens from the session transcript when it looks larger
|
||||||
// (cached prompt tokens are often missing from agent meta/store).
|
// (cached prompt tokens are often missing from agent meta/store).
|
||||||
|
|||||||
@ -142,6 +142,11 @@ export type SessionEntry = {
|
|||||||
inputTokens?: number;
|
inputTokens?: number;
|
||||||
outputTokens?: number;
|
outputTokens?: number;
|
||||||
totalTokens?: number;
|
totalTokens?: number;
|
||||||
|
/**
|
||||||
|
* Last known total tokens (including summaries), used for display when
|
||||||
|
* a fresh model-reported count is unavailable.
|
||||||
|
*/
|
||||||
|
totalTokensEstimate?: number;
|
||||||
/**
|
/**
|
||||||
* Whether totalTokens reflects a fresh context snapshot for the latest run.
|
* Whether totalTokens reflects a fresh context snapshot for the latest run.
|
||||||
* Undefined means legacy/unknown freshness; false forces consumers to treat
|
* Undefined means legacy/unknown freshness; false forces consumers to treat
|
||||||
|
|||||||
@ -752,10 +752,19 @@ export async function runCronIsolatedAgentTurn(params: {
|
|||||||
lookupContextTokens(modelUsed, { allowAsyncLoad: false }) ??
|
lookupContextTokens(modelUsed, { allowAsyncLoad: false }) ??
|
||||||
DEFAULT_CONTEXT_TOKENS;
|
DEFAULT_CONTEXT_TOKENS;
|
||||||
|
|
||||||
|
const modelChanged =
|
||||||
|
(cronSession.sessionEntry.model !== undefined &&
|
||||||
|
cronSession.sessionEntry.model !== modelUsed) ||
|
||||||
|
(cronSession.sessionEntry.modelProvider !== undefined &&
|
||||||
|
cronSession.sessionEntry.modelProvider !== providerUsed);
|
||||||
setSessionRuntimeModel(cronSession.sessionEntry, {
|
setSessionRuntimeModel(cronSession.sessionEntry, {
|
||||||
provider: providerUsed,
|
provider: providerUsed,
|
||||||
model: modelUsed,
|
model: modelUsed,
|
||||||
});
|
});
|
||||||
|
if (modelChanged) {
|
||||||
|
cronSession.sessionEntry.totalTokens = undefined;
|
||||||
|
cronSession.sessionEntry.totalTokensFresh = false;
|
||||||
|
}
|
||||||
cronSession.sessionEntry.contextTokens = contextTokens;
|
cronSession.sessionEntry.contextTokens = contextTokens;
|
||||||
if (isCliProvider(providerUsed, cfgWithAgentDefaults)) {
|
if (isCliProvider(providerUsed, cfgWithAgentDefaults)) {
|
||||||
const cliSessionId = finalRunResult.meta?.agentMeta?.sessionId?.trim();
|
const cliSessionId = finalRunResult.meta?.agentMeta?.sessionId?.trim();
|
||||||
@ -790,10 +799,14 @@ export async function runCronIsolatedAgentTurn(params: {
|
|||||||
if (typeof totalTokens === "number" && Number.isFinite(totalTokens) && totalTokens > 0) {
|
if (typeof totalTokens === "number" && Number.isFinite(totalTokens) && totalTokens > 0) {
|
||||||
cronSession.sessionEntry.totalTokens = totalTokens;
|
cronSession.sessionEntry.totalTokens = totalTokens;
|
||||||
cronSession.sessionEntry.totalTokensFresh = true;
|
cronSession.sessionEntry.totalTokensFresh = true;
|
||||||
|
cronSession.sessionEntry.totalTokensEstimate = totalTokens;
|
||||||
telemetryUsage.total_tokens = totalTokens;
|
telemetryUsage.total_tokens = totalTokens;
|
||||||
} else {
|
} else {
|
||||||
cronSession.sessionEntry.totalTokens = undefined;
|
cronSession.sessionEntry.totalTokens = undefined;
|
||||||
cronSession.sessionEntry.totalTokensFresh = false;
|
cronSession.sessionEntry.totalTokensFresh = false;
|
||||||
|
if (typeof totalTokens === "number" && Number.isFinite(totalTokens)) {
|
||||||
|
cronSession.sessionEntry.totalTokensEstimate = totalTokens;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cronSession.sessionEntry.cacheRead = usage.cacheRead ?? 0;
|
cronSession.sessionEntry.cacheRead = usage.cacheRead ?? 0;
|
||||||
cronSession.sessionEntry.cacheWrite = usage.cacheWrite ?? 0;
|
cronSession.sessionEntry.cacheWrite = usage.cacheWrite ?? 0;
|
||||||
|
|||||||
@ -42,6 +42,7 @@ export function truncateLine(value: string, maxLength: number) {
|
|||||||
|
|
||||||
export type TokenUsageLike = {
|
export type TokenUsageLike = {
|
||||||
totalTokens?: unknown;
|
totalTokens?: unknown;
|
||||||
|
totalTokensFresh?: unknown;
|
||||||
inputTokens?: unknown;
|
inputTokens?: unknown;
|
||||||
outputTokens?: unknown;
|
outputTokens?: unknown;
|
||||||
};
|
};
|
||||||
@ -50,7 +51,11 @@ export function resolveTotalTokens(entry?: TokenUsageLike) {
|
|||||||
if (!entry || typeof entry !== "object") {
|
if (!entry || typeof entry !== "object") {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (typeof entry.totalTokens === "number" && Number.isFinite(entry.totalTokens)) {
|
if (
|
||||||
|
entry.totalTokensFresh !== false &&
|
||||||
|
typeof entry.totalTokens === "number" &&
|
||||||
|
Number.isFinite(entry.totalTokens)
|
||||||
|
) {
|
||||||
return entry.totalTokens;
|
return entry.totalTokens;
|
||||||
}
|
}
|
||||||
const input = typeof entry.inputTokens === "number" ? entry.inputTokens : 0;
|
const input = typeof entry.inputTokens === "number" ? entry.inputTokens : 0;
|
||||||
|
|||||||
@ -48,6 +48,7 @@ export type SessionInfo = {
|
|||||||
inputTokens?: number | null;
|
inputTokens?: number | null;
|
||||||
outputTokens?: number | null;
|
outputTokens?: number | null;
|
||||||
totalTokens?: number | null;
|
totalTokens?: number | null;
|
||||||
|
totalTokensEstimate?: number | null;
|
||||||
responseUsage?: ResponseUsageMode;
|
responseUsage?: ResponseUsageMode;
|
||||||
updatedAt?: number | null;
|
updatedAt?: number | null;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
@ -91,6 +92,7 @@ export type GatewayStatusSummary = {
|
|||||||
age?: number | null;
|
age?: number | null;
|
||||||
model?: string | null;
|
model?: string | null;
|
||||||
totalTokens?: number | null;
|
totalTokens?: number | null;
|
||||||
|
totalTokensEstimate?: number | null;
|
||||||
contextTokens?: number | null;
|
contextTokens?: number | null;
|
||||||
remainingTokens?: number | null;
|
remainingTokens?: number | null;
|
||||||
percentUsed?: number | null;
|
percentUsed?: number | null;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user