fix: subagents list uses command session

This commit is contained in:
Peter Steinberger
2026-01-22 05:32:28 +00:00
parent 5ff4ac7fb7
commit 8580b85f0b
5 changed files with 45 additions and 7 deletions

View File

@@ -45,7 +45,7 @@ function formatTimestampWithAge(valueMs?: number) {
} }
function resolveRequesterSessionKey(params: Parameters<CommandHandler>[0]): string | undefined { function resolveRequesterSessionKey(params: Parameters<CommandHandler>[0]): string | undefined {
const raw = params.ctx.CommandTargetSessionKey?.trim() || params.sessionKey; const raw = params.sessionKey?.trim() || params.ctx.CommandTargetSessionKey?.trim();
if (!raw) return undefined; if (!raw) return undefined;
const { mainKey, alias } = resolveMainSessionAlias(params.cfg); const { mainKey, alias } = resolveMainSessionAlias(params.cfg);
return resolveInternalSessionKey({ key: raw, alias, mainKey }); return resolveInternalSessionKey({ key: raw, alias, mainKey });

View File

@@ -215,6 +215,33 @@ describe("handleCommands subagents", () => {
expect(result.reply?.text).toContain("Subagents: none"); expect(result.reply?.text).toContain("Subagents: none");
}); });
it("lists subagents for the current command session over the target session", async () => {
resetSubagentRegistryForTests();
addSubagentRunForTests({
runId: "run-1",
childSessionKey: "agent:main:subagent:abc",
requesterSessionKey: "agent:main:slack:slash:U1",
requesterDisplayKey: "agent:main:slack:slash:U1",
task: "do thing",
cleanup: "keep",
createdAt: 1000,
startedAt: 1000,
});
const cfg = {
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as ClawdbotConfig;
const params = buildParams("/subagents list", cfg, {
CommandSource: "native",
CommandTargetSessionKey: "agent:main:main",
});
params.sessionKey = "agent:main:slack:slash:U1";
const result = await handleCommands(params);
expect(result.shouldContinue).toBe(false);
expect(result.reply?.text).toContain("Subagents (current session)");
expect(result.reply?.text).toContain("agent:main:subagent:abc");
});
it("omits subagent status line when none exist", async () => { it("omits subagent status line when none exist", async () => {
resetSubagentRegistryForTests(); resetSubagentRegistryForTests();
const cfg = { const cfg = {

View File

@@ -89,7 +89,6 @@ vi.mock("grammy", () => ({
const sequentializeMiddleware = vi.fn(); const sequentializeMiddleware = vi.fn();
const sequentializeSpy = vi.fn(() => sequentializeMiddleware); const sequentializeSpy = vi.fn(() => sequentializeMiddleware);
let _sequentializeKey: ((ctx: unknown) => string) | undefined; let _sequentializeKey: ((ctx: unknown) => string) | undefined;
let originalTz: string | undefined;
vi.mock("@grammyjs/runner", () => ({ vi.mock("@grammyjs/runner", () => ({
sequentialize: (keyFn: (ctx: unknown) => string) => { sequentialize: (keyFn: (ctx: unknown) => string) => {
_sequentializeKey = keyFn; _sequentializeKey = keyFn;
@@ -119,9 +118,10 @@ const getOnHandler = (event: string) => {
return handler as (ctx: Record<string, unknown>) => Promise<void>; return handler as (ctx: Record<string, unknown>) => Promise<void>;
}; };
const ORIGINAL_TZ = process.env.TZ;
describe("createTelegramBot", () => { describe("createTelegramBot", () => {
beforeEach(() => { beforeEach(() => {
originalTz = process.env.TZ;
process.env.TZ = "UTC"; process.env.TZ = "UTC";
resetInboundDedupe(); resetInboundDedupe();
loadConfig.mockReturnValue({ loadConfig.mockReturnValue({
@@ -140,9 +140,8 @@ describe("createTelegramBot", () => {
botCtorSpy.mockReset(); botCtorSpy.mockReset();
_sequentializeKey = undefined; _sequentializeKey = undefined;
}); });
afterEach(() => { afterEach(() => {
process.env.TZ = originalTz; process.env.TZ = ORIGINAL_TZ;
}); });
// groupPolicy tests // groupPolicy tests

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js"; import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js";
import { createTelegramBot, getTelegramSequentialKey } from "./bot.js"; import { createTelegramBot, getTelegramSequentialKey } from "./bot.js";
import { resolveTelegramFetch } from "./fetch.js"; import { resolveTelegramFetch } from "./fetch.js";
@@ -121,8 +121,11 @@ const getOnHandler = (event: string) => {
return handler as (ctx: Record<string, unknown>) => Promise<void>; return handler as (ctx: Record<string, unknown>) => Promise<void>;
}; };
const ORIGINAL_TZ = process.env.TZ;
describe("createTelegramBot", () => { describe("createTelegramBot", () => {
beforeEach(() => { beforeEach(() => {
process.env.TZ = "UTC";
resetInboundDedupe(); resetInboundDedupe();
loadConfig.mockReturnValue({ loadConfig.mockReturnValue({
channels: { channels: {
@@ -140,6 +143,9 @@ describe("createTelegramBot", () => {
botCtorSpy.mockReset(); botCtorSpy.mockReset();
sequentializeKey = undefined; sequentializeKey = undefined;
}); });
afterEach(() => {
process.env.TZ = ORIGINAL_TZ;
});
// groupPolicy tests // groupPolicy tests

View File

@@ -1,7 +1,7 @@
import fs from "node:fs"; import fs from "node:fs";
import os from "node:os"; import os from "node:os";
import path from "node:path"; import path from "node:path";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { import {
listNativeCommandSpecs, listNativeCommandSpecs,
listNativeCommandSpecsForConfig, listNativeCommandSpecsForConfig,
@@ -147,8 +147,11 @@ const getOnHandler = (event: string) => {
return handler as (ctx: Record<string, unknown>) => Promise<void>; return handler as (ctx: Record<string, unknown>) => Promise<void>;
}; };
const ORIGINAL_TZ = process.env.TZ;
describe("createTelegramBot", () => { describe("createTelegramBot", () => {
beforeEach(() => { beforeEach(() => {
process.env.TZ = "UTC";
resetInboundDedupe(); resetInboundDedupe();
loadConfig.mockReturnValue({ loadConfig.mockReturnValue({
channels: { channels: {
@@ -167,6 +170,9 @@ describe("createTelegramBot", () => {
botCtorSpy.mockReset(); botCtorSpy.mockReset();
sequentializeKey = undefined; sequentializeKey = undefined;
}); });
afterEach(() => {
process.env.TZ = ORIGINAL_TZ;
});
it("installs grammY throttler", () => { it("installs grammY throttler", () => {
createTelegramBot({ token: "tok" }); createTelegramBot({ token: "tok" });