mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
fix(gateway): reuse subagent registry snapshot in session listing (#75019)
Summary: - The branch reuses a request-scoped subagent registry read index across Gateway `sessions.list` `spawnedBy` filtering and row enrichment, with focused regression tests and a changelog entry. - Reproducibility: yes. On current main, `spawnedBy` filtering still calls registry read helpers independently ... ce inspection gives a high-confidence reproduction path for snapshot drift during active registry mutation. ClawSweeper fixups: - Included follow-up commit: fix(gateway): reuse subagent registry snapshot in session listing Validation: - ClawSweeper review passed for head23ae624374. - Required merge gates passed before the squash merge. Prepared head SHA:23ae624374Review: https://github.com/openclaw/openclaw/pull/75019#issuecomment-4351613760 Co-authored-by: anyech <anyech@gmail.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
This commit is contained in:
@@ -549,6 +549,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Active Memory: clarify the deprecated `modelFallbackPolicy` warning and config help so `modelFallback` is described as a chain-resolution last resort, not runtime failover. (#74602) Thanks @jeffrey701.
|
||||
- Channels/Discord: keep read-only allowlist/default-target accessors from resolving SecretRef-backed bot tokens, so status and channel summaries no longer fail when tokens are only available in gateway runtime. (#74737) Thanks @eusine.
|
||||
- Gateway/sessions: align session abort wait semantics across `chat`, `agent`, and `sessions` server methods so abort RPCs return after the targeted sessions actually halt instead of resolving early while runs are still draining. (#74751) Thanks @BunsDev.
|
||||
- Gateway/sessions: reuse one subagent registry read index for `sessions.list` `spawnedBy` filtering and row enrichment so subagent ownership stays consistent without repeated registry reloads. Carries forward #75013. Thanks @anyech.
|
||||
- Agents/output: drop copied inbound metadata-only assistant replay turns before provider replay instead of synthesizing a placeholder, so Telegram and other channels cannot receive `[assistant copied inbound metadata omitted]` as model output. Fixes #74745. Thanks @adamwdear and @Marvae.
|
||||
- Doctor/memory: suppress skipped embedding-readiness warnings for key-optional providers such as Ollama and LM Studio while preserving timeout and not-ready diagnostics. Fixes #74608 and #73882. Thanks @hclsys.
|
||||
- Channels/groups: preserve observe-only turn suppression for prepared dispatch paths and restore deprecated channel turn runtime aliases, so passive observer/group flows stay silent while older plugins keep compiling. Thanks @vincentkoc.
|
||||
|
||||
234
src/agents/subagent-registry-read-context.test.ts
Normal file
234
src/agents/subagent-registry-read-context.test.ts
Normal file
@@ -0,0 +1,234 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildSubagentRunReadIndexFromRuns,
|
||||
countActiveDescendantRunsFromRuns,
|
||||
getSubagentRunByChildSessionKeyFromRuns,
|
||||
listRunsForControllerFromRuns,
|
||||
type SubagentRunReadIndex,
|
||||
} from "./subagent-registry-queries.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
|
||||
function makeRun(overrides: Partial<SubagentRunRecord>): SubagentRunRecord {
|
||||
const runId = overrides.runId ?? "run-default";
|
||||
const childSessionKey = overrides.childSessionKey ?? `agent:main:subagent:${runId}`;
|
||||
const requesterSessionKey = overrides.requesterSessionKey ?? "agent:main:main";
|
||||
return {
|
||||
runId,
|
||||
childSessionKey,
|
||||
controllerSessionKey: overrides.controllerSessionKey,
|
||||
requesterSessionKey,
|
||||
requesterDisplayKey: requesterSessionKey,
|
||||
task: "test task",
|
||||
cleanup: "keep",
|
||||
createdAt: overrides.createdAt ?? Date.now(),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function toRunMap(runs: SubagentRunRecord[]): Map<string, SubagentRunRecord> {
|
||||
return new Map(runs.map((run) => [run.runId, run]));
|
||||
}
|
||||
|
||||
function listRunsForController(
|
||||
index: SubagentRunReadIndex,
|
||||
controllerSessionKey: string,
|
||||
): readonly SubagentRunRecord[] {
|
||||
return index.runsByControllerSessionKey.get(controllerSessionKey.trim()) ?? [];
|
||||
}
|
||||
|
||||
describe("subagent registry read index", () => {
|
||||
it("matches existing query helpers while reusing one indexed snapshot", () => {
|
||||
const now = Date.now();
|
||||
const root = "agent:main:main";
|
||||
const parent = "agent:main:subagent:parent";
|
||||
const liveChild = "agent:main:subagent:parent:subagent:live-child";
|
||||
const movedChild = "agent:main:subagent:moved-child";
|
||||
const runs = toRunMap([
|
||||
makeRun({
|
||||
runId: "run-parent",
|
||||
childSessionKey: parent,
|
||||
controllerSessionKey: root,
|
||||
requesterSessionKey: root,
|
||||
createdAt: now - 5_000,
|
||||
startedAt: now - 4_500,
|
||||
endedAt: now - 2_500,
|
||||
}),
|
||||
makeRun({
|
||||
runId: "run-live-child",
|
||||
childSessionKey: liveChild,
|
||||
controllerSessionKey: parent,
|
||||
requesterSessionKey: parent,
|
||||
createdAt: now - 2_000,
|
||||
startedAt: now - 1_500,
|
||||
}),
|
||||
makeRun({
|
||||
runId: "run-moved-old",
|
||||
childSessionKey: movedChild,
|
||||
controllerSessionKey: root,
|
||||
requesterSessionKey: root,
|
||||
createdAt: now - 4_000,
|
||||
startedAt: now - 3_500,
|
||||
}),
|
||||
makeRun({
|
||||
runId: "run-moved-new",
|
||||
childSessionKey: movedChild,
|
||||
controllerSessionKey: "agent:main:other-controller",
|
||||
requesterSessionKey: "agent:main:other-controller",
|
||||
createdAt: now - 1_000,
|
||||
startedAt: now - 900,
|
||||
}),
|
||||
]);
|
||||
|
||||
const index = buildSubagentRunReadIndexFromRuns({ runs, now });
|
||||
|
||||
expect(listRunsForController(index, root)).toEqual(listRunsForControllerFromRuns(runs, root));
|
||||
expect(index.getDisplaySubagentRun(parent)).toEqual(
|
||||
getSubagentRunByChildSessionKeyFromRuns(runs, parent),
|
||||
);
|
||||
expect(index.countActiveDescendantRuns(root)).toBe(
|
||||
countActiveDescendantRunsFromRuns(runs, root),
|
||||
);
|
||||
expect(index.countActiveDescendantRuns(root)).toBe(1);
|
||||
});
|
||||
|
||||
it("handles empty registry snapshots", () => {
|
||||
const runs = new Map<string, SubagentRunRecord>();
|
||||
const index = buildSubagentRunReadIndexFromRuns({ runs });
|
||||
|
||||
expect(listRunsForController(index, "agent:main:main")).toEqual([]);
|
||||
expect(index.getDisplaySubagentRun("agent:main:subagent:missing")).toBeNull();
|
||||
expect(index.countActiveDescendantRuns("agent:main:main")).toBe(0);
|
||||
});
|
||||
|
||||
it("uses requesterSessionKey when controllerSessionKey is missing", () => {
|
||||
const root = "agent:main:main";
|
||||
const run = makeRun({
|
||||
runId: "run-controller-fallback",
|
||||
childSessionKey: "agent:main:subagent:fallback-child",
|
||||
requesterSessionKey: root,
|
||||
controllerSessionKey: undefined,
|
||||
});
|
||||
const runs = toRunMap([run]);
|
||||
const index = buildSubagentRunReadIndexFromRuns({ runs });
|
||||
|
||||
expect(listRunsForController(index, root)).toEqual(listRunsForControllerFromRuns(runs, root));
|
||||
expect(listRunsForController(index, root)).toEqual([run]);
|
||||
});
|
||||
|
||||
it("keeps moved middle descendants under the latest requester", () => {
|
||||
const now = Date.now();
|
||||
const root = "agent:main:root";
|
||||
const otherRoot = "agent:main:other-root";
|
||||
const middle = "agent:main:subagent:middle";
|
||||
const grandchild = "agent:main:subagent:grandchild";
|
||||
const runs = toRunMap([
|
||||
makeRun({
|
||||
runId: "run-middle-old",
|
||||
childSessionKey: middle,
|
||||
controllerSessionKey: root,
|
||||
requesterSessionKey: root,
|
||||
createdAt: now - 3_000,
|
||||
startedAt: now - 2_900,
|
||||
}),
|
||||
makeRun({
|
||||
runId: "run-grandchild",
|
||||
childSessionKey: grandchild,
|
||||
controllerSessionKey: middle,
|
||||
requesterSessionKey: middle,
|
||||
createdAt: now - 2_000,
|
||||
startedAt: now - 1_900,
|
||||
}),
|
||||
makeRun({
|
||||
runId: "run-middle-moved",
|
||||
childSessionKey: middle,
|
||||
controllerSessionKey: otherRoot,
|
||||
requesterSessionKey: otherRoot,
|
||||
createdAt: now - 1_000,
|
||||
startedAt: now - 900,
|
||||
}),
|
||||
]);
|
||||
const index = buildSubagentRunReadIndexFromRuns({ runs, now });
|
||||
|
||||
expect(index.countActiveDescendantRuns(root)).toBe(
|
||||
countActiveDescendantRunsFromRuns(runs, root),
|
||||
);
|
||||
expect(index.countActiveDescendantRuns(root)).toBe(0);
|
||||
expect(index.countActiveDescendantRuns(otherRoot)).toBe(
|
||||
countActiveDescendantRunsFromRuns(runs, otherRoot),
|
||||
);
|
||||
expect(index.countActiveDescendantRuns(otherRoot)).toBe(2);
|
||||
});
|
||||
|
||||
it("keeps one snapshot stable for the lifetime of the context", () => {
|
||||
const root = "agent:main:main";
|
||||
const runs = toRunMap([
|
||||
makeRun({
|
||||
runId: "run-original",
|
||||
childSessionKey: "agent:main:subagent:original",
|
||||
requesterSessionKey: root,
|
||||
controllerSessionKey: root,
|
||||
}),
|
||||
]);
|
||||
const index = buildSubagentRunReadIndexFromRuns({ runs });
|
||||
|
||||
runs.set(
|
||||
"run-added-after-context",
|
||||
makeRun({
|
||||
runId: "run-added-after-context",
|
||||
childSessionKey: "agent:main:subagent:added",
|
||||
requesterSessionKey: root,
|
||||
controllerSessionKey: root,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(listRunsForController(index, root).map((run) => run.runId)).toEqual(["run-original"]);
|
||||
expect(
|
||||
listRunsForController(buildSubagentRunReadIndexFromRuns({ runs }), root).map(
|
||||
(run) => run.runId,
|
||||
),
|
||||
).toEqual(["run-original", "run-added-after-context"]);
|
||||
});
|
||||
|
||||
it("normalizes display lookup keys for whitespace-padded child session keys", () => {
|
||||
const normalizedChildSessionKey = "agent:main:subagent:whitespace-child";
|
||||
const run = makeRun({
|
||||
runId: "run-whitespace-child",
|
||||
childSessionKey: ` ${normalizedChildSessionKey} `,
|
||||
requesterSessionKey: "agent:main:main",
|
||||
});
|
||||
const runs = toRunMap([run]);
|
||||
const index = buildSubagentRunReadIndexFromRuns({ runs });
|
||||
|
||||
expect(index.getDisplaySubagentRun(normalizedChildSessionKey)).toBe(run);
|
||||
});
|
||||
|
||||
it("keeps the display-row preference for in-memory records over persisted snapshots", () => {
|
||||
const childSessionKey = "agent:main:subagent:display-child";
|
||||
const persistedRuns = toRunMap([
|
||||
makeRun({
|
||||
runId: "run-persisted-newer",
|
||||
childSessionKey,
|
||||
requesterSessionKey: "agent:main:main",
|
||||
createdAt: 200,
|
||||
startedAt: 200,
|
||||
}),
|
||||
]);
|
||||
const inMemoryRuns = toRunMap([
|
||||
makeRun({
|
||||
runId: "run-memory-older-ended",
|
||||
childSessionKey,
|
||||
requesterSessionKey: "agent:main:main",
|
||||
createdAt: 100,
|
||||
startedAt: 100,
|
||||
endedAt: 150,
|
||||
}),
|
||||
]);
|
||||
|
||||
const index = buildSubagentRunReadIndexFromRuns({
|
||||
runs: persistedRuns,
|
||||
inMemoryRuns: inMemoryRuns.values(),
|
||||
});
|
||||
|
||||
expect(index.getDisplaySubagentRun(childSessionKey)?.runId).toBe("run-memory-older-ended");
|
||||
});
|
||||
});
|
||||
@@ -787,6 +787,134 @@ describe("listSessionsFromStore subagent metadata", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("reuses one subagent registry disk snapshot across sessions.list filtering and row enrichment", () => {
|
||||
const tempRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), "openclaw-session-utils-subagent-cache-"),
|
||||
);
|
||||
const stateDir = path.join(tempRoot, "state");
|
||||
const registryPath = path.join(stateDir, "subagents", "runs.json");
|
||||
fs.mkdirSync(path.dirname(registryPath), { recursive: true });
|
||||
const now = Date.now();
|
||||
const controllerSessionKey = "agent:main:main";
|
||||
const childKeys = [
|
||||
"agent:main:subagent:cache-child-a",
|
||||
"agent:main:subagent:cache-child-b",
|
||||
"agent:main:subagent:cache-child-c",
|
||||
];
|
||||
fs.writeFileSync(
|
||||
registryPath,
|
||||
JSON.stringify(
|
||||
{
|
||||
version: 2,
|
||||
runs: Object.fromEntries(
|
||||
childKeys.map((childSessionKey, index) => [
|
||||
`run-cache-child-${index}`,
|
||||
{
|
||||
runId: `run-cache-child-${index}`,
|
||||
childSessionKey,
|
||||
controllerSessionKey,
|
||||
requesterSessionKey: controllerSessionKey,
|
||||
requesterDisplayKey: "main",
|
||||
task: "cache test child",
|
||||
cleanup: "keep",
|
||||
createdAt: now - 5_000 + index,
|
||||
startedAt: now - 4_000 + index,
|
||||
},
|
||||
]),
|
||||
),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const store: Record<string, SessionEntry> = {
|
||||
[controllerSessionKey]: {
|
||||
updatedAt: now,
|
||||
} as SessionEntry,
|
||||
[childKeys[0]]: {
|
||||
updatedAt: now - 1_000,
|
||||
spawnedBy: controllerSessionKey,
|
||||
} as SessionEntry,
|
||||
[childKeys[1]]: {
|
||||
updatedAt: now - 2_000,
|
||||
spawnedBy: controllerSessionKey,
|
||||
} as SessionEntry,
|
||||
[childKeys[2]]: {
|
||||
updatedAt: now - 3_000,
|
||||
spawnedBy: controllerSessionKey,
|
||||
} as SessionEntry,
|
||||
};
|
||||
|
||||
const statSpy = vi.spyOn(fs, "statSync");
|
||||
try {
|
||||
const result = withEnv(
|
||||
{
|
||||
OPENCLAW_STATE_DIR: stateDir,
|
||||
OPENCLAW_TEST_READ_SUBAGENT_RUNS_FROM_DISK: "1",
|
||||
},
|
||||
() =>
|
||||
listSessionsFromStore({
|
||||
cfg,
|
||||
storePath: "/tmp/sessions.json",
|
||||
store,
|
||||
opts: { spawnedBy: controllerSessionKey },
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.sessions.map((session) => session.key)).toEqual(childKeys);
|
||||
const registryStatCount = statSpy.mock.calls.filter(
|
||||
([pathname]) => path.normalize(String(pathname)) === path.normalize(registryPath),
|
||||
).length;
|
||||
expect(registryStatCount).toBe(1);
|
||||
} finally {
|
||||
statSpy.mockRestore();
|
||||
fs.rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("does not read the subagent registry when raw filters drop every session", () => {
|
||||
const tempRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), "openclaw-session-utils-subagent-cache-empty-"),
|
||||
);
|
||||
const stateDir = path.join(tempRoot, "state");
|
||||
const registryPath = path.join(stateDir, "subagents", "runs.json");
|
||||
fs.mkdirSync(path.dirname(registryPath), { recursive: true });
|
||||
fs.writeFileSync(registryPath, JSON.stringify({ version: 2, runs: {} }, null, 2), "utf-8");
|
||||
|
||||
const statSpy = vi.spyOn(fs, "statSync");
|
||||
try {
|
||||
const result = withEnv(
|
||||
{
|
||||
OPENCLAW_STATE_DIR: stateDir,
|
||||
OPENCLAW_TEST_READ_SUBAGENT_RUNS_FROM_DISK: "1",
|
||||
},
|
||||
() =>
|
||||
listSessionsFromStore({
|
||||
cfg,
|
||||
storePath: "/tmp/sessions.json",
|
||||
store: {
|
||||
"agent:main:filtered-out": {
|
||||
label: "keep-me-out",
|
||||
updatedAt: Date.now(),
|
||||
} as SessionEntry,
|
||||
},
|
||||
opts: { label: "wanted-label" },
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.sessions).toEqual([]);
|
||||
const registryStatCount = statSpy.mock.calls.filter(
|
||||
([pathname]) => path.normalize(String(pathname)) === path.normalize(registryPath),
|
||||
).length;
|
||||
expect(registryStatCount).toBe(0);
|
||||
} finally {
|
||||
statSpy.mockRestore();
|
||||
fs.rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("includes explicit parentSessionKey relationships for dashboard child sessions", () => {
|
||||
resetSubagentRegistryForTests({ persist: false });
|
||||
const now = Date.now();
|
||||
|
||||
@@ -381,9 +381,9 @@ function resolveRuntimeChildSessionKeys(
|
||||
): string[] | undefined {
|
||||
const childSessionKeys = new Set<string>();
|
||||
const controllerKey = controllerSessionKey.trim();
|
||||
const runs =
|
||||
subagentRuns?.runsByControllerSessionKey.get(controllerKey) ??
|
||||
listSubagentRunsForController(controllerSessionKey);
|
||||
const runs = subagentRuns
|
||||
? (subagentRuns.runsByControllerSessionKey.get(controllerKey) ?? [])
|
||||
: listSubagentRunsForController(controllerSessionKey);
|
||||
for (const entry of runs) {
|
||||
const childSessionKey = normalizeOptionalString(entry.childSessionKey);
|
||||
if (!childSessionKey) {
|
||||
@@ -1811,8 +1811,10 @@ export function filterAndSortSessionEntries(params: {
|
||||
store: Record<string, SessionEntry>;
|
||||
opts: import("./protocol/index.js").SessionsListParams;
|
||||
now: number;
|
||||
rowContext?: SessionListRowContext;
|
||||
}): [string, SessionEntry][] {
|
||||
const { store, opts, now } = params;
|
||||
const rowContext = params.rowContext;
|
||||
const includeGlobal = opts.includeGlobal === true;
|
||||
const includeUnknown = opts.includeUnknown === true;
|
||||
const spawnedBy = typeof opts.spawnedBy === "string" ? opts.spawnedBy : "";
|
||||
@@ -1854,7 +1856,9 @@ export function filterAndSortSessionEntries(params: {
|
||||
if (key === "unknown" || key === "global") {
|
||||
return false;
|
||||
}
|
||||
const latest = getSessionDisplaySubagentRunByChildSessionKey(key);
|
||||
const latest = rowContext
|
||||
? rowContext.subagentRuns.getDisplaySubagentRun(key)
|
||||
: getSessionDisplaySubagentRunByChildSessionKey(key);
|
||||
if (latest) {
|
||||
const latestControllerSessionKey =
|
||||
normalizeOptionalString(latest.controllerSessionKey) ||
|
||||
@@ -1862,7 +1866,9 @@ export function filterAndSortSessionEntries(params: {
|
||||
return (
|
||||
latestControllerSessionKey === spawnedBy &&
|
||||
shouldKeepSubagentRunChildLink(latest, {
|
||||
activeDescendants: countActiveDescendantRuns(key),
|
||||
activeDescendants: rowContext
|
||||
? rowContext.subagentRuns.countActiveDescendantRuns(key)
|
||||
: countActiveDescendantRuns(key),
|
||||
now,
|
||||
})
|
||||
);
|
||||
@@ -1913,11 +1919,21 @@ export function listSessionsFromStore(params: {
|
||||
const now = Date.now();
|
||||
const sessionListTranscriptUsageMaxBytes = 64 * 1024;
|
||||
const sessionListTranscriptFieldRows = 100;
|
||||
const rowContext = buildSessionListRowContext({ store, now });
|
||||
let rowContext: SessionListRowContext | undefined;
|
||||
const getRowContext = () => {
|
||||
rowContext ??= buildSessionListRowContext({ store, now });
|
||||
return rowContext;
|
||||
};
|
||||
const includeDerivedTitles = opts.includeDerivedTitles === true;
|
||||
const includeLastMessage = opts.includeLastMessage === true;
|
||||
const hasSpawnedByFilter = typeof opts.spawnedBy === "string" && opts.spawnedBy.length > 0;
|
||||
|
||||
const entries = filterAndSortSessionEntries({ store, opts, now });
|
||||
const entries = filterAndSortSessionEntries({
|
||||
store,
|
||||
opts,
|
||||
now,
|
||||
rowContext: hasSpawnedByFilter ? getRowContext() : undefined,
|
||||
});
|
||||
|
||||
const sessions = entries.map(([key, entry], index) => {
|
||||
const includeTranscriptFields = index < sessionListTranscriptFieldRows;
|
||||
@@ -1932,8 +1948,8 @@ export function listSessionsFromStore(params: {
|
||||
includeDerivedTitles: includeTranscriptFields && includeDerivedTitles,
|
||||
includeLastMessage: includeTranscriptFields && includeLastMessage,
|
||||
transcriptUsageMaxBytes: sessionListTranscriptUsageMaxBytes,
|
||||
storeChildSessionsByKey: rowContext.storeChildSessionsByKey,
|
||||
rowContext,
|
||||
storeChildSessionsByKey: getRowContext().storeChildSessionsByKey,
|
||||
rowContext: getRowContext(),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1967,11 +1983,21 @@ export async function listSessionsFromStoreAsync(params: {
|
||||
const now = Date.now();
|
||||
const sessionListTranscriptUsageMaxBytes = 64 * 1024;
|
||||
const sessionListTranscriptFieldRows = 100;
|
||||
const rowContext = buildSessionListRowContext({ store, now });
|
||||
let rowContext: SessionListRowContext | undefined;
|
||||
const getRowContext = () => {
|
||||
rowContext ??= buildSessionListRowContext({ store, now });
|
||||
return rowContext;
|
||||
};
|
||||
const includeDerivedTitles = opts.includeDerivedTitles === true;
|
||||
const includeLastMessage = opts.includeLastMessage === true;
|
||||
const hasSpawnedByFilter = typeof opts.spawnedBy === "string" && opts.spawnedBy.length > 0;
|
||||
|
||||
const entries = filterAndSortSessionEntries({ store, opts, now });
|
||||
const entries = filterAndSortSessionEntries({
|
||||
store,
|
||||
opts,
|
||||
now,
|
||||
rowContext: hasSpawnedByFilter ? getRowContext() : undefined,
|
||||
});
|
||||
|
||||
const sessions: GatewaySessionRow[] = [];
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
@@ -1988,8 +2014,8 @@ export async function listSessionsFromStoreAsync(params: {
|
||||
includeDerivedTitles: false,
|
||||
includeLastMessage: false,
|
||||
transcriptUsageMaxBytes: sessionListTranscriptUsageMaxBytes,
|
||||
storeChildSessionsByKey: rowContext.storeChildSessionsByKey,
|
||||
rowContext,
|
||||
storeChildSessionsByKey: getRowContext().storeChildSessionsByKey,
|
||||
rowContext: getRowContext(),
|
||||
});
|
||||
if (
|
||||
entry?.sessionId &&
|
||||
|
||||
Reference in New Issue
Block a user