feat(FN-794): raise auto-summarization threshold from 140 to 200 characters
- Change MIN_DESCRIPTION_LENGTH threshold from 140 to 200 in ai-summarize.ts - Update shouldAutoSummarize logic and tests for new 200-char threshold - Update UI copy in SettingsModal and API/routes references - Update store tests to reflect the new threshold value - Remove obsolete dashboard activity-log mobile layout test files and unused CSS - Add changeset for patch bump
This commit is contained in:
@@ -1718,7 +1718,7 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
const result = await summarizeTitle("a".repeat(200));
|
||||
const result = await summarizeTitle("a".repeat(201));
|
||||
|
||||
expect(result).toBe("Generated Title");
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
@@ -1726,7 +1726,7 @@ describe("summarizeTitle", () => {
|
||||
expect.objectContaining({
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ description: "a".repeat(200), provider: undefined, modelId: undefined }),
|
||||
body: JSON.stringify({ description: "a".repeat(201), provider: undefined, modelId: undefined }),
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -1740,12 +1740,12 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
await summarizeTitle("a".repeat(200), "anthropic", "claude-sonnet-4-5");
|
||||
await summarizeTitle("a".repeat(201), "anthropic", "claude-sonnet-4-5");
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
"/api/ai/summarize-title",
|
||||
expect.objectContaining({
|
||||
body: JSON.stringify({ description: "a".repeat(200), provider: "anthropic", modelId: "claude-sonnet-4-5" }),
|
||||
body: JSON.stringify({ description: "a".repeat(201), provider: "anthropic", modelId: "claude-sonnet-4-5" }),
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -1771,7 +1771,7 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
await expect(summarizeTitle("a".repeat(200))).rejects.toThrow("Rate limit exceeded: Rate limit exceeded");
|
||||
await expect(summarizeTitle("a".repeat(201))).rejects.toThrow("Rate limit exceeded: Rate limit exceeded");
|
||||
});
|
||||
|
||||
it("throws descriptive error on 503 response", async () => {
|
||||
@@ -1783,7 +1783,7 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
await expect(summarizeTitle("a".repeat(200))).rejects.toThrow("AI service temporarily unavailable: AI service unavailable");
|
||||
await expect(summarizeTitle("a".repeat(201))).rejects.toThrow("AI service temporarily unavailable: AI service unavailable");
|
||||
});
|
||||
|
||||
it("throws generic error on other failure responses", async () => {
|
||||
@@ -1795,7 +1795,7 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
await expect(summarizeTitle("a".repeat(200))).rejects.toThrow("Internal server error");
|
||||
await expect(summarizeTitle("a".repeat(201))).rejects.toThrow("Internal server error");
|
||||
});
|
||||
|
||||
it("throws error for non-JSON responses", async () => {
|
||||
@@ -1807,7 +1807,7 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
await expect(summarizeTitle("a".repeat(200))).rejects.toThrow("API returned non-JSON response");
|
||||
await expect(summarizeTitle("a".repeat(201))).rejects.toThrow("API returned non-JSON response");
|
||||
});
|
||||
|
||||
it("throws error when response has no title", async () => {
|
||||
@@ -1819,7 +1819,7 @@ describe("summarizeTitle", () => {
|
||||
});
|
||||
global.fetch = mockFetch;
|
||||
|
||||
await expect(summarizeTitle("a".repeat(200))).rejects.toThrow("API returned empty title");
|
||||
await expect(summarizeTitle("a".repeat(201))).rejects.toThrow("API returned empty title");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1751,7 +1751,7 @@ export interface SummarizeTitleResponse {
|
||||
}
|
||||
|
||||
/** Summarize a task description into a concise title using AI.
|
||||
* @param description - The task description to summarize (must be 141-2000 chars)
|
||||
* @param description - The task description to summarize (must be 201-2000 chars)
|
||||
* @param provider - Optional AI model provider (e.g., "anthropic")
|
||||
* @param modelId - Optional AI model ID (e.g., "claude-sonnet-4-5")
|
||||
* @returns The generated title (guaranteed ≤60 characters)
|
||||
|
||||
@@ -991,7 +991,7 @@ export function SettingsModal({
|
||||
Auto-summarize long descriptions as titles
|
||||
</label>
|
||||
<small>
|
||||
When enabled, tasks created without a title but with descriptions over 140 characters
|
||||
When enabled, tasks created without a title but with descriptions over 200 characters
|
||||
will automatically get an AI-generated title (max 60 characters).
|
||||
</small>
|
||||
</div>
|
||||
|
||||
@@ -5135,7 +5135,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
* Body: { description: string, provider?: string, modelId?: string }
|
||||
* Returns: { title: string }
|
||||
*
|
||||
* Generates a concise title (≤60 characters) from descriptions longer than 140 characters.
|
||||
* Generates a concise title (≤60 characters) from descriptions longer than 200 characters.
|
||||
* Rate limited: 10 requests per hour per IP
|
||||
*/
|
||||
router.post("/ai/summarize-title", async (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user