feat: show session ID in dashboard status display
Add session label (last 8 chars) next to each group status. Export buildStatusContent and DashboardOptions for testing.
This commit is contained in:
@@ -20,9 +20,11 @@ export const ASSISTANT_HAS_OWN_NUMBER =
|
||||
(process.env.ASSISTANT_HAS_OWN_NUMBER ||
|
||||
envConfig.ASSISTANT_HAS_OWN_NUMBER) === 'true';
|
||||
export const SESSION_COMMAND_USER_IDS = new Set(
|
||||
(process.env.SESSION_COMMAND_USER_IDS ||
|
||||
(
|
||||
process.env.SESSION_COMMAND_USER_IDS ||
|
||||
envConfig.SESSION_COMMAND_USER_IDS ||
|
||||
'')
|
||||
''
|
||||
)
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter(Boolean),
|
||||
|
||||
49
src/dashboard.test.ts
Normal file
49
src/dashboard.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { buildStatusContent, type DashboardOptions } from './dashboard.js';
|
||||
|
||||
function makeOptions(sessionId?: string): DashboardOptions {
|
||||
const sessions: Record<string, string> = sessionId
|
||||
? { 'group-folder': sessionId }
|
||||
: {};
|
||||
|
||||
return {
|
||||
assistantName: 'Test',
|
||||
channels: [],
|
||||
getSessions: () => sessions,
|
||||
queue: {
|
||||
getStatuses: () => [
|
||||
{
|
||||
jid: 'dc:123',
|
||||
status: 'inactive',
|
||||
elapsedMs: null,
|
||||
pendingMessages: false,
|
||||
pendingTasks: 0,
|
||||
},
|
||||
],
|
||||
} as unknown as DashboardOptions['queue'],
|
||||
registeredGroups: () => ({
|
||||
'dc:123': {
|
||||
name: 'clone-test',
|
||||
folder: 'group-folder',
|
||||
trigger: '@bot',
|
||||
added_at: '2026-03-16T00:00:00.000Z',
|
||||
},
|
||||
}),
|
||||
statusChannelId: 'status',
|
||||
statusUpdateInterval: 60000,
|
||||
usageUpdateInterval: 60000,
|
||||
};
|
||||
}
|
||||
|
||||
describe('buildStatusContent', () => {
|
||||
it('shows cleared sessions as empty', () => {
|
||||
const content = buildStatusContent(makeOptions());
|
||||
expect(content).toContain('세션 없음');
|
||||
});
|
||||
|
||||
it('shows a shortened session id when a session exists', () => {
|
||||
const content = buildStatusContent(makeOptions('session-1234567890'));
|
||||
expect(content).toContain('세션 34567890');
|
||||
});
|
||||
});
|
||||
@@ -8,9 +8,10 @@ import { GroupQueue, GroupStatus } from './group-queue.js';
|
||||
import { logger } from './logger.js';
|
||||
import { Channel, ChannelMeta, RegisteredGroup } from './types.js';
|
||||
|
||||
interface DashboardOptions {
|
||||
export interface DashboardOptions {
|
||||
assistantName: string;
|
||||
channels: Channel[];
|
||||
getSessions: () => Record<string, string>;
|
||||
queue: GroupQueue;
|
||||
registeredGroups: () => Record<string, RegisteredGroup>;
|
||||
statusChannelId: string;
|
||||
@@ -114,8 +115,16 @@ function getStatusLabel(status: GroupStatus): string {
|
||||
return '비활성';
|
||||
}
|
||||
|
||||
function buildStatusContent(opts: DashboardOptions): string {
|
||||
function getSessionLabel(sessionId: string | undefined): string {
|
||||
if (!sessionId) return '세션 없음';
|
||||
const shortId = sessionId.length > 8 ? sessionId.slice(-8) : sessionId;
|
||||
return `세션 ${shortId}`;
|
||||
}
|
||||
|
||||
/** @internal - exported for testing */
|
||||
export function buildStatusContent(opts: DashboardOptions): string {
|
||||
const registeredGroups = opts.registeredGroups();
|
||||
const sessions = opts.getSessions();
|
||||
const jids = Object.keys(registeredGroups);
|
||||
const statuses = opts.queue.getStatuses(jids);
|
||||
|
||||
@@ -153,8 +162,9 @@ function buildStatusContent(opts: DashboardOptions): string {
|
||||
const lines = categoryEntries.map((entry) => {
|
||||
const icon = STATUS_ICONS[entry.status.status] || '⚪';
|
||||
const label = getStatusLabel(entry.status);
|
||||
const sessionLabel = getSessionLabel(sessions[entry.group.folder]);
|
||||
const name = entry.meta?.name ? `#${entry.meta.name}` : entry.group.name;
|
||||
return ` ${icon} **${name}** — ${label}`;
|
||||
return ` ${icon} **${name}** — ${label} · ${sessionLabel}`;
|
||||
});
|
||||
|
||||
if (channelMetaCache.size > 0 && categoryName !== '기타') {
|
||||
|
||||
@@ -256,6 +256,7 @@ async function main(): Promise<void> {
|
||||
const dashboardOpts = {
|
||||
assistantName: ASSISTANT_NAME,
|
||||
channels,
|
||||
getSessions: () => sessions,
|
||||
queue,
|
||||
registeredGroups: () => registeredGroups,
|
||||
statusChannelId: STATUS_CHANNEL_ID,
|
||||
|
||||
@@ -238,7 +238,9 @@ describe('handleSessionCommand', () => {
|
||||
isAdminSender: vi.fn().mockReturnValue(true),
|
||||
});
|
||||
const result = await handleSessionCommand({
|
||||
missedMessages: [makeMsg('/clear', { is_from_me: false, sender: 'discord-user-1' })],
|
||||
missedMessages: [
|
||||
makeMsg('/clear', { is_from_me: false, sender: 'discord-user-1' }),
|
||||
],
|
||||
isMainGroup: false,
|
||||
groupName: 'test',
|
||||
triggerPattern: trigger,
|
||||
|
||||
Reference in New Issue
Block a user