Skip to content

Commit 1b15e98

Browse files
committed
[api] update get history to take an array
1 parent 2906ea3 commit 1b15e98

File tree

3 files changed

+167
-6
lines changed

3 files changed

+167
-6
lines changed

src/schemas/apiSchema.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,19 @@ const zHistoryTaskItem = z.object({
235235
meta: zTaskMeta.optional()
236236
})
237237

238+
// Raw history item from backend (without taskType)
239+
const zRawHistoryItem = z.object({
240+
prompt: zTaskPrompt,
241+
status: zStatus.optional(),
242+
outputs: zTaskOutput,
243+
meta: zTaskMeta.optional()
244+
})
245+
246+
// New API response format: { history: [{"prompt_id": {...}}, ...] }
247+
const zHistoryResponse = z.object({
248+
history: z.array(z.record(zPromptId, zRawHistoryItem))
249+
})
250+
238251
const zTaskItem = z.union([
239252
zRunningTaskItem,
240253
zPendingTaskItem,
@@ -257,6 +270,8 @@ export type RunningTaskItem = z.infer<typeof zRunningTaskItem>
257270
export type PendingTaskItem = z.infer<typeof zPendingTaskItem>
258271
// `/history`
259272
export type HistoryTaskItem = z.infer<typeof zHistoryTaskItem>
273+
export type RawHistoryItem = z.infer<typeof zRawHistoryItem>
274+
export type HistoryResponse = z.infer<typeof zHistoryResponse>
260275
export type TaskItem = z.infer<typeof zTaskItem>
261276

262277
export function validateTaskItem(taskItem: unknown) {

src/scripts/api.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import type {
1111
ExecutionStartWsMessage,
1212
ExecutionSuccessWsMessage,
1313
ExtensionsResponse,
14+
HistoryResponse,
1415
HistoryTaskItem,
1516
LogsRawResponse,
1617
LogsWsMessage,
1718
PendingTaskItem,
1819
ProgressTextWsMessage,
1920
ProgressWsMessage,
2021
PromptResponse,
22+
RawHistoryItem,
2123
RunningTaskItem,
2224
Settings,
2325
StatusWsMessage,
@@ -710,13 +712,21 @@ export class ComfyApi extends EventTarget {
710712
max_items: number = 200
711713
): Promise<{ History: HistoryTaskItem[] }> {
712714
try {
713-
const res = await this.fetchApi(`/history?max_items=${max_items}`)
714-
const json: Promise<HistoryTaskItem[]> = await res.json()
715+
const res = await this.fetchApi(`/history_v2?max_items=${max_items}`)
716+
const json: HistoryResponse = await res.json()
717+
718+
// Extract history data from new format: { history: [{"prompt_id": {...}}, ...] }
719+
const historyData: RawHistoryItem[] = json.history.flatMap(
720+
(item: Record<string, RawHistoryItem>) => Object.values(item)
721+
)
722+
715723
return {
716-
History: Object.values(json).map((item) => ({
717-
...item,
718-
taskType: 'History'
719-
}))
724+
History: historyData.map(
725+
(item): HistoryTaskItem => ({
726+
...item,
727+
taskType: 'History'
728+
})
729+
)
720730
}
721731
} catch (error) {
722732
console.error(error)

tests-ui/tests/scripts/api.test.ts

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest'
2+
3+
import type {
4+
HistoryResponse,
5+
RawHistoryItem
6+
} from '../../../src/schemas/apiSchema'
7+
import { ComfyApi } from '../../../src/scripts/api'
8+
9+
describe('ComfyApi getHistory', () => {
10+
let api: ComfyApi
11+
12+
beforeEach(() => {
13+
api = new ComfyApi()
14+
})
15+
16+
const mockHistoryItem: RawHistoryItem = {
17+
prompt: [
18+
0,
19+
'test_prompt_id',
20+
{
21+
'1': {
22+
class_type: 'CheckpointLoaderSimple',
23+
inputs: {
24+
ckpt_name: 'model.safetensors'
25+
}
26+
}
27+
},
28+
{
29+
extra_pnginfo: {
30+
workflow: {
31+
last_node_id: 1,
32+
last_link_id: 0,
33+
nodes: [],
34+
links: [],
35+
groups: [],
36+
config: {},
37+
extra: {},
38+
version: 0.4
39+
}
40+
},
41+
client_id: 'test_client_id'
42+
},
43+
['1']
44+
],
45+
outputs: {},
46+
status: {
47+
status_str: 'success',
48+
completed: true,
49+
messages: []
50+
}
51+
}
52+
53+
describe('history v2 API format', () => {
54+
it('should handle history array format from /history_v2', async () => {
55+
const historyResponse: HistoryResponse = {
56+
history: [
57+
{
58+
prompt_id_1: mockHistoryItem
59+
},
60+
{
61+
prompt_id_2: mockHistoryItem
62+
}
63+
]
64+
}
65+
66+
// Mock fetchApi to return the v2 format
67+
const mockFetchApi = vi.fn().mockResolvedValue({
68+
json: vi.fn().mockResolvedValue(historyResponse)
69+
})
70+
api.fetchApi = mockFetchApi
71+
72+
const result = await api.getHistory(10)
73+
74+
expect(result.History).toHaveLength(2)
75+
expect(result.History[0]).toEqual({
76+
...mockHistoryItem,
77+
taskType: 'History'
78+
})
79+
expect(result.History[1]).toEqual({
80+
...mockHistoryItem,
81+
taskType: 'History'
82+
})
83+
})
84+
85+
it('should handle empty history array', async () => {
86+
const historyResponse: HistoryResponse = {
87+
history: []
88+
}
89+
90+
const mockFetchApi = vi.fn().mockResolvedValue({
91+
json: vi.fn().mockResolvedValue(historyResponse)
92+
})
93+
api.fetchApi = mockFetchApi
94+
95+
const result = await api.getHistory(10)
96+
97+
expect(result.History).toHaveLength(0)
98+
expect(result.History).toEqual([])
99+
})
100+
})
101+
102+
describe('error handling', () => {
103+
it('should return empty history on error', async () => {
104+
const mockFetchApi = vi.fn().mockRejectedValue(new Error('Network error'))
105+
api.fetchApi = mockFetchApi
106+
107+
const result = await api.getHistory()
108+
109+
expect(result.History).toEqual([])
110+
})
111+
})
112+
113+
describe('API call parameters', () => {
114+
it('should call fetchApi with correct v2 endpoint and parameters', async () => {
115+
const mockFetchApi = vi.fn().mockResolvedValue({
116+
json: vi.fn().mockResolvedValue({ history: [] })
117+
})
118+
api.fetchApi = mockFetchApi
119+
120+
await api.getHistory(50)
121+
122+
expect(mockFetchApi).toHaveBeenCalledWith('/history_v2?max_items=50')
123+
})
124+
125+
it('should use default max_items parameter with v2 endpoint', async () => {
126+
const mockFetchApi = vi.fn().mockResolvedValue({
127+
json: vi.fn().mockResolvedValue({ history: [] })
128+
})
129+
api.fetchApi = mockFetchApi
130+
131+
await api.getHistory()
132+
133+
expect(mockFetchApi).toHaveBeenCalledWith('/history_v2?max_items=200')
134+
})
135+
})
136+
})

0 commit comments

Comments
 (0)