fix(status): keep empty status path lightweight

This commit is contained in:
Peter Steinberger
2026-04-04 10:01:34 +09:00
parent f8a3840a42
commit 37ee19521f
6 changed files with 62 additions and 9 deletions

View File

@@ -103,6 +103,7 @@ import { getDmHistoryLimitFromSessionKey, limitHistoryTurns } from "./history.js
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
import { log } from "./logger.js";
import { buildEmbeddedMessageActionDiscoveryInput } from "./message-action-discovery-input.js";
import { readPiModelContextTokens } from "./model-context-tokens.js";
import { buildModelAliasLines, resolveModelAsync } from "./model.js";
import { sanitizeSessionHistory, validateReplayTurns } from "./replay-history.js";
import { buildEmbeddedSandboxInfo } from "./sandbox-info.js";
@@ -443,7 +444,7 @@ export async function compactEmbeddedPiSessionDirect(
cfg: params.config,
provider,
modelId,
modelContextTokens: runtimeModelWithContext.contextTokens,
modelContextTokens: readPiModelContextTokens(runtimeModel),
modelContextWindow: runtimeModelWithContext.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});
@@ -1035,7 +1036,7 @@ export async function compactEmbeddedPiSession(
cfg: params.config,
provider: ceProvider,
modelId: ceModelId,
modelContextTokens: ceRuntimeModel?.contextTokens,
modelContextTokens: readPiModelContextTokens(ceModel),
modelContextWindow: ceRuntimeModel?.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});

View File

@@ -0,0 +1,10 @@
import type { Api, Model } from "@mariozechner/pi-ai";
type PiModelWithOptionalContextTokens = Model<Api> & {
contextTokens?: number;
};
export function readPiModelContextTokens(model: Model<Api> | null | undefined): number | undefined {
const value = (model as PiModelWithOptionalContextTokens | null | undefined)?.contextTokens;
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
}

View File

@@ -12,6 +12,7 @@ import {
import { DEFAULT_CONTEXT_TOKENS } from "../../defaults.js";
import { FailoverError } from "../../failover-error.js";
import { log } from "../logger.js";
import { readPiModelContextTokens } from "../model-context-tokens.js";
type HookContext = {
agentId?: string;
@@ -107,7 +108,7 @@ export function resolveEffectiveRuntimeModel(params: {
cfg: params.cfg,
provider: params.provider,
modelId: params.modelId,
modelContextTokens: params.runtimeModel.contextTokens,
modelContextTokens: readPiModelContextTokens(params.runtimeModel),
modelContextWindow: params.runtimeModel.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});

View File

@@ -56,4 +56,19 @@ describe("config presence", () => {
expectedConfigured: false,
});
});
it("detects env-only channel config", () => {
const stateDir = makeTempStateDir();
const env = {
OPENCLAW_STATE_DIR: stateDir,
MATRIX_ACCESS_TOKEN: "token",
} as NodeJS.ProcessEnv;
expectPotentialConfiguredChannelCase({
cfg: {},
env,
expectedIds: ["matrix"],
expectedConfigured: true,
});
});
});

View File

@@ -1,4 +1,8 @@
import fs from "node:fs";
import os from "node:os";
import type { OpenClawConfig } from "../config/config.js";
import { resolveStateDir } from "../config/paths.js";
import { listBundledChannelPluginIds } from "./plugins/bundled-ids.js";
import { listBundledChannelPlugins } from "./plugins/bundled.js";
const IGNORED_CHANNEL_CONFIG_KEYS = new Set(["defaults", "modelByChannel"]);
@@ -19,12 +23,16 @@ export function hasMeaningfulChannelConfig(value: unknown): boolean {
}
function listConfiguredChannelEnvPrefixes(): Array<[prefix: string, channelId: string]> {
return listBundledChannelPlugins().map((plugin) => [
`${plugin.id.replace(/[^a-z0-9]+/gi, "_").toUpperCase()}_`,
plugin.id,
return listBundledChannelPluginIds().map((channelId) => [
`${channelId.replace(/[^a-z0-9]+/gi, "_").toUpperCase()}_`,
channelId,
]);
}
function hasPersistedChannelState(env: NodeJS.ProcessEnv): boolean {
return fs.existsSync(resolveStateDir(env, os.homedir));
}
export function listPotentialConfiguredChannelIds(
cfg: OpenClawConfig,
env: NodeJS.ProcessEnv = process.env,
@@ -53,9 +61,11 @@ export function listPotentialConfiguredChannelIds(
}
}
}
for (const plugin of listBundledChannelPlugins()) {
if (plugin.config?.hasPersistedAuthState?.({ cfg, env })) {
configuredChannelIds.add(plugin.id);
if (hasPersistedChannelState(env)) {
for (const plugin of listBundledChannelPlugins()) {
if (plugin.config?.hasPersistedAuthState?.({ cfg, env })) {
configuredChannelIds.add(plugin.id);
}
}
}
return [...configuredChannelIds];
@@ -71,6 +81,9 @@ function hasEnvConfiguredChannel(cfg: OpenClawConfig, env: NodeJS.ProcessEnv): b
return true;
}
}
if (!hasPersistedChannelState(env)) {
return false;
}
return listBundledChannelPlugins().some((plugin) =>
Boolean(plugin.config?.hasPersistedAuthState?.({ cfg, env })),
);

View File

@@ -0,0 +1,13 @@
import { listBundledPluginMetadata } from "../../plugins/bundled-plugin-metadata.js";
export const BUNDLED_CHANNEL_PLUGIN_IDS = listBundledPluginMetadata({
includeChannelConfigs: false,
includeSyntheticChannelConfigs: false,
})
.filter(({ manifest }) => Array.isArray(manifest.channels) && manifest.channels.length > 0)
.map(({ manifest }) => manifest.id)
.toSorted((left, right) => left.localeCompare(right));
export function listBundledChannelPluginIds(): string[] {
return [...BUNDLED_CHANNEL_PLUGIN_IDS];
}