mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-04 01:34:06 +00:00
fix(channels): bound thread binding lifecycle durations
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { MAX_DATE_TIMESTAMP_MS } from "../shared/number-coercion.js";
|
||||
import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
import {
|
||||
requiresNativeThreadContextForThreadHere,
|
||||
resolveThreadBindingIdleTimeoutMs,
|
||||
resolveThreadBindingMaxAgeMs,
|
||||
resolveThreadBindingPlacementForCurrentContext,
|
||||
resolveThreadBindingSpawnPolicy,
|
||||
supportsAutomaticThreadBindingSpawn,
|
||||
@@ -80,6 +83,21 @@ describe("thread binding spawn policy helpers", () => {
|
||||
expect(policy.defaultSpawnContext).toBe("fork");
|
||||
});
|
||||
|
||||
it("preserves long lifecycle hour values while capping unsafe conversions", () => {
|
||||
expect(
|
||||
resolveThreadBindingIdleTimeoutMs({
|
||||
channelIdleHoursRaw: 720,
|
||||
sessionIdleHoursRaw: undefined,
|
||||
}),
|
||||
).toBe(2_592_000_000);
|
||||
expect(
|
||||
resolveThreadBindingMaxAgeMs({
|
||||
channelMaxAgeHoursRaw: undefined,
|
||||
sessionMaxAgeHoursRaw: Number.MAX_SAFE_INTEGER,
|
||||
}),
|
||||
).toBe(MAX_DATE_TIMESTAMP_MS);
|
||||
});
|
||||
|
||||
it("uses spawnSessions for both subagent and ACP spawn policy", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
@@ -94,26 +95,34 @@ function normalizeThreadBindingHours(raw: unknown): number | undefined {
|
||||
return raw;
|
||||
}
|
||||
|
||||
function resolveThreadBindingHoursMs(raw: unknown, fallbackHours: number): number {
|
||||
const hours = normalizeThreadBindingHours(raw) ?? fallbackHours;
|
||||
const durationMs = Math.floor(hours * 60 * 60 * 1000);
|
||||
if (!Number.isFinite(durationMs) || durationMs < 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.min(durationMs, MAX_DATE_TIMESTAMP_MS);
|
||||
}
|
||||
|
||||
export function resolveThreadBindingIdleTimeoutMs(params: {
|
||||
channelIdleHoursRaw: unknown;
|
||||
sessionIdleHoursRaw: unknown;
|
||||
}): number {
|
||||
const idleHours =
|
||||
normalizeThreadBindingHours(params.channelIdleHoursRaw) ??
|
||||
normalizeThreadBindingHours(params.sessionIdleHoursRaw) ??
|
||||
DEFAULT_THREAD_BINDING_IDLE_HOURS;
|
||||
return Math.floor(idleHours * 60 * 60 * 1000);
|
||||
return resolveThreadBindingHoursMs(
|
||||
params.channelIdleHoursRaw,
|
||||
normalizeThreadBindingHours(params.sessionIdleHoursRaw) ?? DEFAULT_THREAD_BINDING_IDLE_HOURS,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveThreadBindingMaxAgeMs(params: {
|
||||
channelMaxAgeHoursRaw: unknown;
|
||||
sessionMaxAgeHoursRaw: unknown;
|
||||
}): number {
|
||||
const maxAgeHours =
|
||||
normalizeThreadBindingHours(params.channelMaxAgeHoursRaw) ??
|
||||
return resolveThreadBindingHoursMs(
|
||||
params.channelMaxAgeHoursRaw,
|
||||
normalizeThreadBindingHours(params.sessionMaxAgeHoursRaw) ??
|
||||
DEFAULT_THREAD_BINDING_MAX_AGE_HOURS;
|
||||
return Math.floor(maxAgeHours * 60 * 60 * 1000);
|
||||
DEFAULT_THREAD_BINDING_MAX_AGE_HOURS,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveThreadBindingEffectiveExpiresAt(params: {
|
||||
|
||||
Reference in New Issue
Block a user