@dexto/tui 1.14.1 → 1.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -371,6 +371,16 @@ async function processStream(iterator, setters, options) {
|
|
|
371
371
|
}
|
|
372
372
|
break;
|
|
373
373
|
}
|
|
374
|
+
case "llm:retrying": {
|
|
375
|
+
if (event.reason !== "empty_response") break;
|
|
376
|
+
state.nonStreamingAccumulatedReasoning = "";
|
|
377
|
+
if (state.messageId && !state.content && !state.reasoningFinalized) {
|
|
378
|
+
removeFromPending(state.messageId);
|
|
379
|
+
state.messageId = null;
|
|
380
|
+
}
|
|
381
|
+
if (!state.messageId) state.reasoning = "";
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
374
384
|
case "llm:response": {
|
|
375
385
|
if (!useStreaming) {
|
|
376
386
|
setUi((prev) => ({ ...prev, isThinking: false }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processStream.d.ts","sourceRoot":"","sources":["../../src/services/processStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,aAAa,CAAC;AAGvE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAc,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAoEvE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,oFAAoF;IACpF,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,iFAAiF;IACjF,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,kEAAkE;IAClE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC;IAC3F,4CAA4C;IAC5C,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC9F,2CAA2C;IAC3C,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC/F,4DAA4D;IAC5D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,uDAAuD;IACvD,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;CAC7E;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2FAA2F;IAC3F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2FAA2F;IAC3F,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,wFAAwF;IACxF,oBAAoB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,yDAAyD;IACzD,QAAQ,EAAE,IAAI,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC5D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,+BAA+B,EAAE,wBAAwB,CAAC;IAChF,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;CAC3F;AAgDD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAC/B,QAAQ,EAAE,qBAAqB,CAAC,cAAc,CAAC,EAC/C,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,oBAAoB,GAC9B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"processStream.d.ts","sourceRoot":"","sources":["../../src/services/processStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,aAAa,CAAC;AAGvE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAc,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAoEvE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,oFAAoF;IACpF,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,iFAAiF;IACjF,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,kEAAkE;IAClE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC;IAC3F,4CAA4C;IAC5C,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC9F,2CAA2C;IAC3C,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC/F,4DAA4D;IAC5D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,uDAAuD;IACvD,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;CAC7E;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2FAA2F;IAC3F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2FAA2F;IAC3F,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,wFAAwF;IACxF,oBAAoB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,yDAAyD;IACzD,QAAQ,EAAE,IAAI,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC5D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,+BAA+B,EAAE,wBAAwB,CAAC;IAChF,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;CAC3F;AAgDD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAC/B,QAAQ,EAAE,qBAAqB,CAAC,cAAc,CAAC,EAC/C,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,oBAAoB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuvCf"}
|
|
@@ -338,6 +338,16 @@ async function processStream(iterator, setters, options) {
|
|
|
338
338
|
}
|
|
339
339
|
break;
|
|
340
340
|
}
|
|
341
|
+
case "llm:retrying": {
|
|
342
|
+
if (event.reason !== "empty_response") break;
|
|
343
|
+
state.nonStreamingAccumulatedReasoning = "";
|
|
344
|
+
if (state.messageId && !state.content && !state.reasoningFinalized) {
|
|
345
|
+
removeFromPending(state.messageId);
|
|
346
|
+
state.messageId = null;
|
|
347
|
+
}
|
|
348
|
+
if (!state.messageId) state.reasoning = "";
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
341
351
|
case "llm:response": {
|
|
342
352
|
if (!useStreaming) {
|
|
343
353
|
setUi((prev) => ({ ...prev, isThinking: false }));
|
|
@@ -335,6 +335,66 @@ function createSetters({
|
|
|
335
335
|
(0, import_vitest.expect)(messagesWithReasoning).toHaveLength(1);
|
|
336
336
|
(0, import_vitest.expect)(messagesWithReasoning[0]?.reasoning).toBe("R");
|
|
337
337
|
});
|
|
338
|
+
import_vitest.it.each([true, false])(
|
|
339
|
+
"drops reasoning from an empty reply that is retried (streaming: %s)",
|
|
340
|
+
async (useStreaming) => {
|
|
341
|
+
const { getMessages, getPendingMessages, setters } = createSetters();
|
|
342
|
+
const events = [
|
|
343
|
+
{ name: "llm:thinking", sessionId: "test-session" },
|
|
344
|
+
{
|
|
345
|
+
name: "llm:chunk",
|
|
346
|
+
sessionId: "test-session",
|
|
347
|
+
chunkType: "reasoning",
|
|
348
|
+
content: "FIRST"
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
name: "llm:retrying",
|
|
352
|
+
sessionId: "test-session",
|
|
353
|
+
error: new Error("The model ended its reply without answering. Try again."),
|
|
354
|
+
context: "TurnExecutor.runModelStep",
|
|
355
|
+
attempt: 1,
|
|
356
|
+
maxRetries: 1,
|
|
357
|
+
provider: "openai",
|
|
358
|
+
model: "gpt-4",
|
|
359
|
+
reason: "empty_response"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
name: "llm:chunk",
|
|
363
|
+
sessionId: "test-session",
|
|
364
|
+
chunkType: "reasoning",
|
|
365
|
+
content: "SECOND"
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
name: "llm:chunk",
|
|
369
|
+
sessionId: "test-session",
|
|
370
|
+
chunkType: "text",
|
|
371
|
+
content: "Hello"
|
|
372
|
+
},
|
|
373
|
+
llmResponse({
|
|
374
|
+
content: "Hello",
|
|
375
|
+
reasoning: "SECOND"
|
|
376
|
+
}),
|
|
377
|
+
{
|
|
378
|
+
name: "run:complete",
|
|
379
|
+
sessionId: "test-session",
|
|
380
|
+
finishReason: "stop",
|
|
381
|
+
stepCount: 1,
|
|
382
|
+
durationMs: 1
|
|
383
|
+
}
|
|
384
|
+
];
|
|
385
|
+
await (0, import_processStream.processStream)(eventStream(events), setters, {
|
|
386
|
+
useStreaming,
|
|
387
|
+
autoApproveEditsRef: { current: false },
|
|
388
|
+
bypassPermissionsRef: { current: false },
|
|
389
|
+
eventBus: { emit: import_vitest.vi.fn() }
|
|
390
|
+
});
|
|
391
|
+
(0, import_vitest.expect)(getPendingMessages()).toEqual([]);
|
|
392
|
+
const assistantMessages = getMessages().filter((m) => m.role === "assistant");
|
|
393
|
+
(0, import_vitest.expect)(assistantMessages).toHaveLength(1);
|
|
394
|
+
(0, import_vitest.expect)(assistantMessages[0]?.content).toBe("Hello");
|
|
395
|
+
(0, import_vitest.expect)(assistantMessages[0]?.reasoning).toBe("SECOND");
|
|
396
|
+
}
|
|
397
|
+
);
|
|
338
398
|
(0, import_vitest.it)("includes reasoning in non-streaming mode (accumulated from chunks)", async () => {
|
|
339
399
|
const { getMessages, setters } = createSetters();
|
|
340
400
|
const events = [
|
|
@@ -334,6 +334,66 @@ describe("processStream (reasoning)", () => {
|
|
|
334
334
|
expect(messagesWithReasoning).toHaveLength(1);
|
|
335
335
|
expect(messagesWithReasoning[0]?.reasoning).toBe("R");
|
|
336
336
|
});
|
|
337
|
+
it.each([true, false])(
|
|
338
|
+
"drops reasoning from an empty reply that is retried (streaming: %s)",
|
|
339
|
+
async (useStreaming) => {
|
|
340
|
+
const { getMessages, getPendingMessages, setters } = createSetters();
|
|
341
|
+
const events = [
|
|
342
|
+
{ name: "llm:thinking", sessionId: "test-session" },
|
|
343
|
+
{
|
|
344
|
+
name: "llm:chunk",
|
|
345
|
+
sessionId: "test-session",
|
|
346
|
+
chunkType: "reasoning",
|
|
347
|
+
content: "FIRST"
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
name: "llm:retrying",
|
|
351
|
+
sessionId: "test-session",
|
|
352
|
+
error: new Error("The model ended its reply without answering. Try again."),
|
|
353
|
+
context: "TurnExecutor.runModelStep",
|
|
354
|
+
attempt: 1,
|
|
355
|
+
maxRetries: 1,
|
|
356
|
+
provider: "openai",
|
|
357
|
+
model: "gpt-4",
|
|
358
|
+
reason: "empty_response"
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
name: "llm:chunk",
|
|
362
|
+
sessionId: "test-session",
|
|
363
|
+
chunkType: "reasoning",
|
|
364
|
+
content: "SECOND"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: "llm:chunk",
|
|
368
|
+
sessionId: "test-session",
|
|
369
|
+
chunkType: "text",
|
|
370
|
+
content: "Hello"
|
|
371
|
+
},
|
|
372
|
+
llmResponse({
|
|
373
|
+
content: "Hello",
|
|
374
|
+
reasoning: "SECOND"
|
|
375
|
+
}),
|
|
376
|
+
{
|
|
377
|
+
name: "run:complete",
|
|
378
|
+
sessionId: "test-session",
|
|
379
|
+
finishReason: "stop",
|
|
380
|
+
stepCount: 1,
|
|
381
|
+
durationMs: 1
|
|
382
|
+
}
|
|
383
|
+
];
|
|
384
|
+
await processStream(eventStream(events), setters, {
|
|
385
|
+
useStreaming,
|
|
386
|
+
autoApproveEditsRef: { current: false },
|
|
387
|
+
bypassPermissionsRef: { current: false },
|
|
388
|
+
eventBus: { emit: vi.fn() }
|
|
389
|
+
});
|
|
390
|
+
expect(getPendingMessages()).toEqual([]);
|
|
391
|
+
const assistantMessages = getMessages().filter((m) => m.role === "assistant");
|
|
392
|
+
expect(assistantMessages).toHaveLength(1);
|
|
393
|
+
expect(assistantMessages[0]?.content).toBe("Hello");
|
|
394
|
+
expect(assistantMessages[0]?.reasoning).toBe("SECOND");
|
|
395
|
+
}
|
|
396
|
+
);
|
|
337
397
|
it("includes reasoning in non-streaming mode (accumulated from chunks)", async () => {
|
|
338
398
|
const { getMessages, setters } = createSetters();
|
|
339
399
|
const events = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dexto/tui",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.3",
|
|
4
4
|
"description": "Interactive terminal UI for Dexto CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
"string-width": "^8.1.0",
|
|
29
29
|
"strip-ansi": "^7.1.2",
|
|
30
30
|
"wrap-ansi": "^9.0.2",
|
|
31
|
-
"@dexto/
|
|
32
|
-
"@dexto/
|
|
33
|
-
"@dexto/
|
|
34
|
-
"@dexto/
|
|
31
|
+
"@dexto/core": "1.14.3",
|
|
32
|
+
"@dexto/registry": "1.14.3",
|
|
33
|
+
"@dexto/agent-management": "1.14.3",
|
|
34
|
+
"@dexto/llm": "1.14.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/react": "^19.0.0",
|
|
38
38
|
"tsup": "^8.0.0",
|
|
39
39
|
"typescript": "^5.3.3",
|
|
40
|
-
"vitest": "^
|
|
40
|
+
"vitest": "^4.1.12"
|
|
41
41
|
},
|
|
42
42
|
"license": "Elastic-2.0",
|
|
43
43
|
"scripts": {
|