Skip to content

Commit 0506393

Browse files
committed
# Conflicts: # tests/bot/routers/command-router.test.ts
2 parents 2527a21 + a12582e commit 0506393

119 files changed

Lines changed: 961 additions & 508 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/app/formatters/scheduled-task-display-formatter.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ function parseCronParts(cron: string): CronParts | null {
127127
}
128128

129129
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
130+
if (!minute || !hour || !dayOfMonth || !month || !dayOfWeek) {
131+
return null;
132+
}
130133
return {
131134
minute,
132135
hour,
@@ -156,7 +159,11 @@ function parseEveryStep(field: string, minStep: number, maxStep: number): number
156159
return null;
157160
}
158161

159-
const step = Number.parseInt(match[1], 10);
162+
const stepText = match[1];
163+
if (!stepText) {
164+
return null;
165+
}
166+
const step = Number.parseInt(stepText, 10);
160167
if (!Number.isInteger(step) || step < minStep || step > maxStep) {
161168
return null;
162169
}
@@ -176,8 +183,9 @@ function normalizeWeekdayValue(token: string): number | null {
176183
sat: 6,
177184
};
178185

179-
if (normalized in aliases) {
180-
return aliases[normalized];
186+
const aliasValue = aliases[normalized];
187+
if (aliasValue !== undefined) {
188+
return aliasValue;
181189
}
182190

183191
const numericValue = parseExactNumber(normalized, 0, 7);
@@ -199,6 +207,9 @@ function parseWeekdaySet(field: string): Set<number> | null {
199207

200208
if (trimmedToken.includes("-")) {
201209
const [startRaw, endRaw] = trimmedToken.split("-");
210+
if (startRaw === undefined || endRaw === undefined) {
211+
return null;
212+
}
202213
const start = normalizeWeekdayValue(startRaw);
203214
const end = normalizeWeekdayValue(endRaw);
204215
if (start === null || end === null || start > end) {
@@ -299,7 +310,11 @@ function formatCronTaskBadge(cron: string): string {
299310

300311
if (weekdayValues.size === 1) {
301312
const [weekday] = weekdayValues;
302-
return `${WEEKDAY_LABELS[weekday]} ${formatTime(hour, minute)}`;
313+
const weekdayLabel = weekday === undefined ? undefined : WEEKDAY_LABELS[weekday];
314+
if (!weekdayLabel) {
315+
return "cron";
316+
}
317+
return `${weekdayLabel} ${formatTime(hour, minute)}`;
303318
}
304319
}
305320

src/app/formatters/subagent-formatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function formatToolStep(subagent: SubagentInfo): string {
5656
state: {
5757
status: "running",
5858
input: subagent.currentToolInput ?? {},
59-
title: toolTitle,
59+
...(toolTitle !== undefined ? { title: toolTitle } : {}),
6060
metadata: {},
6161
time: { start: subagent.updatedAt },
6262
},

src/app/formatters/summary-formatter.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ function formatTodos(todos: Array<{ content: string; status: string }>): string
140140

141141
for (let i = 0; i < Math.min(todos.length, MAX_TODOS); i++) {
142142
const todo = todos[i];
143+
if (!todo) {
144+
continue;
145+
}
143146
const marker = statusToMarker[todo.status] ?? "🔲";
144147
formattedTodos.push(`${marker} ${todo.content}`);
145148
}
@@ -153,7 +156,10 @@ function formatTodos(todos: Array<{ content: string; status: string }>): string
153156
return result;
154157
}
155158

156-
function formatDiffLineInfo(filediff: { additions?: number; deletions?: number }): string {
159+
function formatDiffLineInfo(filediff: {
160+
additions?: number | undefined;
161+
deletions?: number | undefined;
162+
}): string {
157163
const parts = [];
158164
if (filediff.additions && filediff.additions > 0) parts.push(`+${filediff.additions}`);
159165
if (filediff.deletions && filediff.deletions > 0) parts.push(`-${filediff.deletions}`);
@@ -181,7 +187,8 @@ function countDiffChangesFromText(text: string): { additions: number; deletions:
181187
function extractFirstUpdatedFileFromTitle(title: string): string {
182188
for (const rawLine of title.split("\n")) {
183189
const line = rawLine.trim();
184-
if (line.length >= 3 && line[1] === " " && /[AMDURC]/.test(line[0])) {
190+
const status = line[0];
191+
if (line.length >= 3 && line[1] === " " && status !== undefined && /[AMDURC]/.test(status)) {
185192
return line.slice(2).trim();
186193
}
187194
}

src/app/managers/assistant-run-state-manager.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ import { logger } from "../../utils/logger.js";
22

33
export interface AssistantRunStartInfo {
44
startedAt: number;
5-
configuredAgent?: string;
6-
configuredProviderID?: string;
7-
configuredModelID?: string;
5+
configuredAgent?: string | undefined;
6+
configuredProviderID?: string | undefined;
7+
configuredModelID?: string | undefined;
88
}
99

1010
export interface AssistantRunResolvedInfo {
11-
agent?: string;
12-
providerID?: string;
13-
modelID?: string;
11+
agent?: string | undefined;
12+
providerID?: string | undefined;
13+
modelID?: string | undefined;
1414
}
1515

1616
export interface AssistantRunInfo extends AssistantRunStartInfo {
1717
sessionId: string;
18-
actualAgent?: string;
19-
actualProviderID?: string;
20-
actualModelID?: string;
18+
actualAgent?: string | undefined;
19+
actualProviderID?: string | undefined;
20+
actualModelID?: string | undefined;
2121
hasCompletedResponse: boolean;
2222
}
2323

src/app/managers/background-session-manager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ export type BackgroundSessionNotificationKind =
1010
export interface BackgroundSessionNotification {
1111
kind: BackgroundSessionNotificationKind;
1212
sessionId: string;
13-
sessionTitle?: string;
14-
requestId?: string;
15-
messageId?: string;
13+
sessionTitle?: string | undefined;
14+
requestId?: string | undefined;
15+
messageId?: string | undefined;
1616
}
1717

1818
type NotificationCallback = (notification: BackgroundSessionNotification) => void | Promise<void>;

src/app/managers/interaction-manager.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ function normalizeCommand(command: string): string | null {
2626

2727
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
2828
const withoutMention = withSlash.split("@")[0];
29-
30-
if (withoutMention.length <= 1) {
29+
if (!withoutMention || withoutMention.length <= 1) {
3130
return null;
3231
}
3332

src/app/managers/permission-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class PermissionManager {
161161
return null;
162162
}
163163

164-
return messageIds[messageIds.length - 1];
164+
return messageIds[messageIds.length - 1] ?? null;
165165
}
166166

167167
/**

src/app/managers/prompt-queue-manager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class PromptQueueManager {
4040
}
4141

4242
const [removed] = this.items.splice(index, 1);
43+
if (!removed) {
44+
return null;
45+
}
4346
logger.debug(
4447
`[PromptQueue] Prompt removed: id=${removed.id}, position=${index + 1}, size=${this.items.length}`,
4548
);

src/app/managers/question-manager.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ class QuestionManager {
4646
}
4747

4848
getCurrentQuestion(): Question | null {
49-
if (this.state.currentIndex >= this.state.questions.length) {
50-
return null;
51-
}
52-
return this.state.questions[this.state.currentIndex];
49+
return this.state.questions[this.state.currentIndex] ?? null;
5350
}
5451

5552
selectOption(questionIndex: number, optionIndex: number): void {
@@ -93,10 +90,10 @@ class QuestionManager {
9390
}
9491

9592
const selected = this.state.selectedOptions.get(questionIndex) || new Set();
96-
const options = Array.from(selected)
97-
.map((idx) => question.options[idx])
98-
.filter((opt) => opt)
99-
.map((opt) => `* ${opt.label}: ${opt.description}`);
93+
const options = Array.from(selected).flatMap((idx) => {
94+
const opt = question.options[idx];
95+
return opt ? [`* ${opt.label}: ${opt.description}`] : [];
96+
});
10097

10198
return options.join("\n");
10299
}
@@ -211,6 +208,9 @@ class QuestionManager {
211208

212209
for (let i = 0; i < this.state.questions.length; i++) {
213210
const question = this.state.questions[i];
211+
if (!question) {
212+
continue;
213+
}
214214
const selectedAnswer = this.getSelectedAnswer(i);
215215
const customAnswer = this.getCustomAnswer(i);
216216

src/app/managers/summary-aggregation-manager.ts

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ export interface SummaryInfo {
1818
}
1919

2020
export interface MessageCompletionInfo {
21-
agent?: string;
22-
providerID?: string;
23-
modelID?: string;
24-
createdAt?: number;
25-
completedAt?: number;
21+
agent?: string | undefined;
22+
providerID?: string | undefined;
23+
modelID?: string | undefined;
24+
createdAt?: number | undefined;
25+
completedAt?: number | undefined;
2626
}
2727

2828
type MessageCompleteCallback = (
@@ -36,7 +36,7 @@ type MessagePartialCallback = (sessionId: string, messageId: string, messageText
3636

3737
export interface ThinkingSection {
3838
id: string;
39-
title?: string;
39+
title?: string | undefined;
4040
text: string;
4141
}
4242

@@ -82,10 +82,10 @@ export interface ToolInfo {
8282
callId: string;
8383
tool: string;
8484
state: ToolState;
85-
input?: { [key: string]: unknown };
86-
title?: string;
87-
metadata?: { [key: string]: unknown };
88-
hasFileAttachment?: boolean;
85+
input?: { [key: string]: unknown } | undefined;
86+
title?: string | undefined;
87+
metadata?: { [key: string]: unknown } | undefined;
88+
hasFileAttachment?: boolean | undefined;
8989
}
9090

9191
export interface ToolFileInfo extends ToolInfo {
@@ -128,20 +128,20 @@ export interface SubagentInfo {
128128
agent: string;
129129
description: string;
130130
prompt: string;
131-
command?: string;
131+
command?: string | undefined;
132132
status: SubagentStatus;
133-
providerID?: string;
134-
modelID?: string;
133+
providerID?: string | undefined;
134+
modelID?: string | undefined;
135135
tokens: TokensInfo;
136136
cost: number;
137-
currentTool?: string;
138-
currentToolInput?: { [key: string]: unknown };
139-
currentToolTitle?: string;
140-
currentToolCallId?: string;
141-
currentToolStartedAt?: number;
142-
terminalMessage?: string;
137+
currentTool?: string | undefined;
138+
currentToolInput?: { [key: string]: unknown } | undefined;
139+
currentToolTitle?: string | undefined;
140+
currentToolCallId?: string | undefined;
141+
currentToolStartedAt?: number | undefined;
142+
terminalMessage?: string | undefined;
143143
createdAt: number;
144-
finishedAt?: number;
144+
finishedAt?: number | undefined;
145145
updatedAt: number;
146146
}
147147

@@ -239,7 +239,8 @@ function isUpstreamEmptyResponseText(text: string, isFinal: boolean): boolean {
239239
function extractFirstUpdatedFileFromTitle(title: string): string {
240240
for (const rawLine of title.split("\n")) {
241241
const line = rawLine.trim();
242-
if (line.length >= 3 && line[1] === " " && /[AMDURC]/.test(line[0])) {
242+
const status = line[0];
243+
if (line.length >= 3 && line[1] === " " && status !== undefined && /[AMDURC]/.test(status)) {
243244
return line.slice(2).trim();
244245
}
245246
}
@@ -286,7 +287,6 @@ class SummaryAggregator {
286287
private thinkingMessageStates: Map<string, ThinkingMessageState> = new Map();
287288
private messages: Map<string, { role: string }> = new Map();
288289
private messageCount = 0;
289-
private lastUpdated = 0;
290290
private onCompleteCallback: MessageCompleteCallback | null = null;
291291
private onPartialCallback: MessagePartialCallback | null = null;
292292
private onExternalUserInputCallback: ExternalUserInputCallback | null = null;
@@ -570,7 +570,6 @@ class SummaryAggregator {
570570
this.lastSubagentSnapshot = "";
571571
this.permissionQueue = Promise.resolve();
572572
this.messageCount = 0;
573-
this.lastUpdated = 0;
574573

575574
if (this.onClearedCallback) {
576575
try {
@@ -741,7 +740,12 @@ class SummaryAggregator {
741740

742741
private enrichSubagentFromSubtask(
743742
state: SubagentState,
744-
details: { agent: string; description: string; prompt: string; command?: string },
743+
details: {
744+
agent: string;
745+
description: string;
746+
prompt: string;
747+
command?: string | undefined;
748+
},
745749
): void {
746750
state.agent = details.agent || state.agent;
747751
state.description = details.description || details.prompt || state.description;
@@ -754,10 +758,10 @@ class SummaryAggregator {
754758
private enrichSubagentFromTaskTool(
755759
state: SubagentState,
756760
details: {
757-
agent?: string;
758-
description?: string;
759-
prompt?: string;
760-
command?: string;
761+
agent?: string | undefined;
762+
description?: string | undefined;
763+
prompt?: string | undefined;
764+
command?: string | undefined;
761765
},
762766
): void {
763767
const nextDescription = details.description?.trim() || details.prompt?.trim();
@@ -1226,7 +1230,6 @@ class SummaryAggregator {
12261230
);
12271231
}
12281232

1229-
this.lastUpdated = Date.now();
12301233
}
12311234
}
12321235

@@ -1261,7 +1264,6 @@ class SummaryAggregator {
12611264
part.prompt,
12621265
part.command,
12631266
);
1264-
this.lastUpdated = Date.now();
12651267
return;
12661268
}
12671269

@@ -1281,7 +1283,6 @@ class SummaryAggregator {
12811283
this.updateSubagentStepFinish(part.sessionID, part.tokens, part.cost, part.snapshot);
12821284
}
12831285

1284-
this.lastUpdated = Date.now();
12851286
return;
12861287
}
12871288

@@ -1293,7 +1294,6 @@ class SummaryAggregator {
12931294
// for the user - rendering them would echo a whole attached file back into the chat.
12941295
if (part.type === "text" && "synthetic" in part && part.synthetic === true) {
12951296
this.registerSyntheticPart(messageID, part.id);
1296-
this.lastUpdated = Date.now();
12971297
return;
12981298
}
12991299

@@ -1318,7 +1318,6 @@ class SummaryAggregator {
13181318
) {
13191319
this.emitThinkingFinishedOnce(part.sessionID, messageID);
13201320
this.applyTextDelta(part.sessionID, messageID, part.id, deltaFromUpdated, part.text);
1321-
this.lastUpdated = Date.now();
13221321
return;
13231322
}
13241323

@@ -1336,7 +1335,6 @@ class SummaryAggregator {
13361335
partText,
13371336
this.extractReasoningTitle(part),
13381337
);
1339-
this.lastUpdated = Date.now();
13401338
return;
13411339
}
13421340

@@ -1488,8 +1486,6 @@ class SummaryAggregator {
14881486
}
14891487
}
14901488
}
1491-
1492-
this.lastUpdated = Date.now();
14931489
}
14941490

14951491
private handleMessagePartDelta(event: MessagePartDeltaEventRaw): void {

0 commit comments

Comments
 (0)