@codehz/ai 0.2.1 → 0.2.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.
- package/README.md +4 -0
- package/dist/index.mjs +27 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/chat-completions.ts +1 -9
- package/src/core/aggregator.ts +33 -6
package/README.md
CHANGED
|
@@ -107,6 +107,10 @@ console.log(response.replay); // 续接材料
|
|
|
107
107
|
| `warnings` | `string[]` | 非致命警告 |
|
|
108
108
|
| `backend` | `BackendTrace` | 调用链路元数据 |
|
|
109
109
|
|
|
110
|
+
流式 `message.delta` / `reasoning.delta` 保持后端分片粒度;完成态 `output` 中的
|
|
111
|
+
`message` / `reasoning` 会合并相邻 `text` content blocks(直接拼接且不添加分隔符),
|
|
112
|
+
非文本 block 仍保留原有边界。
|
|
113
|
+
|
|
110
114
|
## 后端 Adapter
|
|
111
115
|
|
|
112
116
|
| Adapter | 类 | 说明 |
|
package/dist/index.mjs
CHANGED
|
@@ -483,7 +483,9 @@ function createAggregatorState() {
|
|
|
483
483
|
toolCalls: [],
|
|
484
484
|
started: false,
|
|
485
485
|
completed: false,
|
|
486
|
-
activeItems: /* @__PURE__ */ new Map()
|
|
486
|
+
activeItems: /* @__PURE__ */ new Map(),
|
|
487
|
+
itemOrder: [],
|
|
488
|
+
completedItems: /* @__PURE__ */ new Map()
|
|
487
489
|
};
|
|
488
490
|
}
|
|
489
491
|
function getActiveItem(state, itemId, expectedType) {
|
|
@@ -492,12 +494,21 @@ function getActiveItem(state, itemId, expectedType) {
|
|
|
492
494
|
if (item.type !== expectedType) throw streamProtocolError(`Item ${itemId} started as ${item.type} but received ${expectedType} event`);
|
|
493
495
|
return item;
|
|
494
496
|
}
|
|
497
|
+
function coalesceContentBlocks(blocks) {
|
|
498
|
+
const result = [];
|
|
499
|
+
for (const block of blocks) {
|
|
500
|
+
const previous = result[result.length - 1];
|
|
501
|
+
if (block.type === "text" && previous?.type === "text") previous.text += block.text;
|
|
502
|
+
else result.push({ ...block });
|
|
503
|
+
}
|
|
504
|
+
return result;
|
|
505
|
+
}
|
|
495
506
|
function finalizeMessage(active) {
|
|
496
507
|
return {
|
|
497
508
|
type: "message",
|
|
498
509
|
id: active.id,
|
|
499
510
|
role: active.role,
|
|
500
|
-
content: active.content
|
|
511
|
+
content: coalesceContentBlocks(active.content)
|
|
501
512
|
};
|
|
502
513
|
}
|
|
503
514
|
function finalizeReasoning(active) {
|
|
@@ -505,7 +516,7 @@ function finalizeReasoning(active) {
|
|
|
505
516
|
type: "reasoning",
|
|
506
517
|
id: active.id,
|
|
507
518
|
visibility: active.visibility,
|
|
508
|
-
content: active.content
|
|
519
|
+
content: coalesceContentBlocks(active.content)
|
|
509
520
|
};
|
|
510
521
|
}
|
|
511
522
|
function finalizeToolCall(active) {
|
|
@@ -546,6 +557,7 @@ function handleMessageStarted(state, event) {
|
|
|
546
557
|
role: event.item.role,
|
|
547
558
|
content: []
|
|
548
559
|
});
|
|
560
|
+
state.itemOrder.push(id);
|
|
549
561
|
}
|
|
550
562
|
function handleMessageDelta(state, event) {
|
|
551
563
|
getActiveItem(state, event.itemId, "message").content.push(event.delta);
|
|
@@ -554,7 +566,7 @@ function handleMessageCompleted(state, event) {
|
|
|
554
566
|
const active = getActiveItem(state, event.itemId, "message");
|
|
555
567
|
state.activeItems.delete(event.itemId);
|
|
556
568
|
const item = finalizeMessage(active);
|
|
557
|
-
state.
|
|
569
|
+
state.completedItems.set(event.itemId, item);
|
|
558
570
|
pushMessageText(state, item);
|
|
559
571
|
}
|
|
560
572
|
function handleReasoningStarted(state, event) {
|
|
@@ -566,6 +578,7 @@ function handleReasoningStarted(state, event) {
|
|
|
566
578
|
visibility: event.item.visibility,
|
|
567
579
|
content: []
|
|
568
580
|
});
|
|
581
|
+
state.itemOrder.push(id);
|
|
569
582
|
}
|
|
570
583
|
function handleReasoningDelta(state, event) {
|
|
571
584
|
getActiveItem(state, event.itemId, "reasoning").content.push(event.delta);
|
|
@@ -573,7 +586,7 @@ function handleReasoningDelta(state, event) {
|
|
|
573
586
|
function handleReasoningCompleted(state, event) {
|
|
574
587
|
const active = getActiveItem(state, event.itemId, "reasoning");
|
|
575
588
|
state.activeItems.delete(event.itemId);
|
|
576
|
-
state.
|
|
589
|
+
state.completedItems.set(event.itemId, finalizeReasoning(active));
|
|
577
590
|
}
|
|
578
591
|
function handleToolCallStarted(state, event) {
|
|
579
592
|
const id = event.item.id;
|
|
@@ -584,6 +597,7 @@ function handleToolCallStarted(state, event) {
|
|
|
584
597
|
name: event.item.name,
|
|
585
598
|
argumentsText: ""
|
|
586
599
|
});
|
|
600
|
+
state.itemOrder.push(id);
|
|
587
601
|
}
|
|
588
602
|
function handleToolCallDelta(state, event) {
|
|
589
603
|
const active = getActiveItem(state, event.itemId, "tool_call");
|
|
@@ -593,7 +607,7 @@ function handleToolCallCompleted(state, event) {
|
|
|
593
607
|
const active = getActiveItem(state, event.itemId, "tool_call");
|
|
594
608
|
state.activeItems.delete(event.itemId);
|
|
595
609
|
const item = finalizeToolCall(active);
|
|
596
|
-
state.
|
|
610
|
+
state.completedItems.set(event.itemId, item);
|
|
597
611
|
state.toolCalls.push(item);
|
|
598
612
|
}
|
|
599
613
|
function handleResponseCompleted(state, event) {
|
|
@@ -624,9 +638,14 @@ function buildResponse(state) {
|
|
|
624
638
|
metadataSources: backendFromCompleted?.metadataSources,
|
|
625
639
|
warnings: backendFromCompleted?.warnings
|
|
626
640
|
};
|
|
641
|
+
const orderedOutput = state.itemOrder.map((id) => {
|
|
642
|
+
const item = state.completedItems.get(id);
|
|
643
|
+
if (!item) throw streamProtocolError(`Item ${id} was started but not completed`);
|
|
644
|
+
return item;
|
|
645
|
+
});
|
|
627
646
|
return {
|
|
628
647
|
id: state.responseId,
|
|
629
|
-
output: state.output,
|
|
648
|
+
output: [...orderedOutput, ...state.output],
|
|
630
649
|
replay: state.replayFromAdapter ?? [],
|
|
631
650
|
text: state.textParts.join(""),
|
|
632
651
|
toolCalls: state.toolCalls,
|
|
@@ -2675,7 +2694,7 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
2675
2694
|
if (hasMessageStarted) {
|
|
2676
2695
|
const message = messageItem([textBlock(accumulatedContent)], { id: currentMessageId });
|
|
2677
2696
|
events.push(factory.messageCompleted(currentMessageId));
|
|
2678
|
-
|
|
2697
|
+
output.push(message);
|
|
2679
2698
|
}
|
|
2680
2699
|
for (const pending of finalizedToolCalls) {
|
|
2681
2700
|
const toolCall = toolCallItem(pending.id, pending.name, pending.args);
|
|
@@ -2770,10 +2789,6 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
2770
2789
|
hasMessageStarted = true;
|
|
2771
2790
|
accumulatedContent = "";
|
|
2772
2791
|
};
|
|
2773
|
-
if (delta.role === "assistant" && !hasMessageStarted) {
|
|
2774
|
-
ensureMessageStarted();
|
|
2775
|
-
yield factory.messageStarted(currentMessageId);
|
|
2776
|
-
}
|
|
2777
2792
|
if (reasoningDeltas.length > 0) {
|
|
2778
2793
|
if (!hasReasoningStarted) {
|
|
2779
2794
|
currentReasoningId = `reason-${chunk.id}`;
|