@yeaft/webchat-agent 1.0.37 → 1.0.38
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/package.json +1 -1
- package/yeaft/router/continuity.js +7 -6
- package/yeaft/web-bridge.js +60 -11
package/package.json
CHANGED
|
@@ -85,10 +85,10 @@ export function extractPriorPlan(messages, vpId) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* Return a copy of the messages array with
|
|
89
|
-
* message. The serialisers (anthropic/openai-responses) read this;
|
|
90
|
-
* NEVER part of the wire payload. Cheap because we only
|
|
91
|
-
* messages that actually have
|
|
88
|
+
* Return a copy of the messages array with engine-private metadata stripped
|
|
89
|
+
* from every message. The serialisers (anthropic/openai-responses) read this;
|
|
90
|
+
* these fields are NEVER part of the wire payload. Cheap because we only
|
|
91
|
+
* shallow-clone the messages that actually have private fields.
|
|
92
92
|
*
|
|
93
93
|
* @param {object[]} messages
|
|
94
94
|
* @returns {object[]}
|
|
@@ -97,9 +97,10 @@ export function stripMetaForWire(messages) {
|
|
|
97
97
|
if (!Array.isArray(messages)) return messages;
|
|
98
98
|
let mutated = false;
|
|
99
99
|
const out = messages.map(m => {
|
|
100
|
-
if (m && typeof m === 'object'
|
|
100
|
+
if (m && typeof m === 'object'
|
|
101
|
+
&& ('_meta' in m || '_runtimeTurnId' in m || '_partialTurn' in m)) {
|
|
101
102
|
mutated = true;
|
|
102
|
-
const { _meta, ...rest } = m;
|
|
103
|
+
const { _meta, _runtimeTurnId, _partialTurn, ...rest } = m;
|
|
103
104
|
return rest;
|
|
104
105
|
}
|
|
105
106
|
return m;
|
package/yeaft/web-bridge.js
CHANGED
|
@@ -2577,6 +2577,23 @@ function handleEngineEvent(event, hctx) {
|
|
|
2577
2577
|
isError: !!event.isError,
|
|
2578
2578
|
});
|
|
2579
2579
|
}
|
|
2580
|
+
if (hctx.sessionId && hctx.turnId && !hctx.skipPartialHistory) {
|
|
2581
|
+
const appendedPrompts = Array.isArray(hctx.appendedUserPrompts) ? hctx.appendedUserPrompts : [];
|
|
2582
|
+
const prompts = hctx.includeInitialPrompt && typeof hctx.prompt === 'string'
|
|
2583
|
+
? [hctx.prompt, ...appendedPrompts]
|
|
2584
|
+
: appendedPrompts;
|
|
2585
|
+
appendTurnToSessionHistory(
|
|
2586
|
+
hctx.sessionId,
|
|
2587
|
+
hctx.threadId || event.threadId || 'main',
|
|
2588
|
+
hctx.vpId,
|
|
2589
|
+
prompts,
|
|
2590
|
+
hctx.assistantTextParts || [],
|
|
2591
|
+
hctx.toolCallsAccum || [],
|
|
2592
|
+
hctx.toolResultsAccum || [],
|
|
2593
|
+
hctx.thinkingBlocksAccum || [],
|
|
2594
|
+
{ turnId: hctx.turnId, partial: true },
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2580
2597
|
sendSessionOutputFrame({
|
|
2581
2598
|
type: 'user',
|
|
2582
2599
|
tool_use_result: [{
|
|
@@ -3598,6 +3615,9 @@ async function runVpTurn({ prompt, promptParts = null, sessionId, vpId, threadId
|
|
|
3598
3615
|
vpEngine = getOrCreateVpEngine(sessionId, vpId, threadId);
|
|
3599
3616
|
if (thread) thread.engine = vpEngine;
|
|
3600
3617
|
|
|
3618
|
+
const inboundInjectedBy = inboundEnvelope?.msg?.meta?.injectedBy;
|
|
3619
|
+
const inboundIsInternal = inboundInjectedBy === 'route_forward' || inboundInjectedBy === 'task_result';
|
|
3620
|
+
|
|
3601
3621
|
handlerCtx = {
|
|
3602
3622
|
assistantTextParts,
|
|
3603
3623
|
toolCallsAccum,
|
|
@@ -3610,6 +3630,9 @@ async function runVpTurn({ prompt, promptParts = null, sessionId, vpId, threadId
|
|
|
3610
3630
|
threadId,
|
|
3611
3631
|
thread,
|
|
3612
3632
|
appendedUserPrompts,
|
|
3633
|
+
prompt,
|
|
3634
|
+
includeInitialPrompt: !inboundIsInternal,
|
|
3635
|
+
skipPartialHistory: false,
|
|
3613
3636
|
markTurnEnd,
|
|
3614
3637
|
};
|
|
3615
3638
|
// Always trim the snapshot before passing to engine.query. This is
|
|
@@ -3651,10 +3674,8 @@ async function runVpTurn({ prompt, promptParts = null, sessionId, vpId, threadId
|
|
|
3651
3674
|
// the source VP's tool action. Do not append it as a visible prompt for
|
|
3652
3675
|
// the target VP turn; otherwise UI replay can show a trailing handoff
|
|
3653
3676
|
// block after the target response.
|
|
3654
|
-
const inboundInjectedBy = inboundEnvelope?.msg?.meta?.injectedBy;
|
|
3655
|
-
const inboundIsInternal = inboundInjectedBy === 'route_forward' || inboundInjectedBy === 'task_result';
|
|
3656
3677
|
const visiblePrompts = inboundIsInternal ? appendedUserPrompts : [prompt, ...appendedUserPrompts];
|
|
3657
|
-
appendTurnToSessionHistory(sessionId, threadId, vpId, visiblePrompts, assistantTextParts, toolCallsAccum, toolResultsAccum, thinkingBlocksAccum);
|
|
3678
|
+
appendTurnToSessionHistory(sessionId, threadId, vpId, visiblePrompts, assistantTextParts, toolCallsAccum, toolResultsAccum, thinkingBlocksAccum, { turnId });
|
|
3658
3679
|
|
|
3659
3680
|
sendSessionOutputFrame({
|
|
3660
3681
|
type: 'assistant',
|
|
@@ -3766,8 +3787,9 @@ async function runVpTurn({ prompt, promptParts = null, sessionId, vpId, threadId
|
|
|
3766
3787
|
}
|
|
3767
3788
|
|
|
3768
3789
|
/**
|
|
3769
|
-
* Atomically append a completed VP-turn's messages to the GROUP'S
|
|
3770
|
-
* conversation history.
|
|
3790
|
+
* Atomically append a completed or partial VP-turn's messages to the GROUP'S
|
|
3791
|
+
* conversation history. Partial writes are replaced by the final write when
|
|
3792
|
+
* the same runtime turn completes.
|
|
3771
3793
|
*
|
|
3772
3794
|
* Note: this does NOT see the engine's collapsed form — it appends the
|
|
3773
3795
|
* raw user prompt(s) + the per-VP assistant text + tool results. Related
|
|
@@ -3779,15 +3801,20 @@ async function runVpTurn({ prompt, promptParts = null, sessionId, vpId, threadId
|
|
|
3779
3801
|
* a session, this in-memory tape carries the un-collapsed form — which
|
|
3780
3802
|
* is fine because each VP turn's `engine.query` re-collapses on the fly.
|
|
3781
3803
|
*/
|
|
3782
|
-
function
|
|
3783
|
-
|
|
3784
|
-
const
|
|
3804
|
+
function buildTurnHistoryEntries(threadId, vpId, prompts, assistantTextParts, toolCallsAccum, toolResultsAccum, thinkingBlocksAccum, opts = {}) {
|
|
3805
|
+
const entries = [];
|
|
3806
|
+
const runtimeTurnId = typeof opts.turnId === 'string' && opts.turnId ? opts.turnId : null;
|
|
3807
|
+
const markEntry = (entry) => {
|
|
3808
|
+
if (runtimeTurnId) entry._runtimeTurnId = runtimeTurnId;
|
|
3809
|
+
if (opts.partial) entry._partialTurn = true;
|
|
3810
|
+
return entry;
|
|
3811
|
+
};
|
|
3785
3812
|
const promptList = Array.isArray(prompts) ? prompts : [prompts];
|
|
3786
3813
|
for (const prompt of promptList) {
|
|
3787
3814
|
if (typeof prompt === 'string' && prompt.trim()) {
|
|
3788
3815
|
// user rows intentionally carry NO speakerVpId — every VP in the
|
|
3789
3816
|
// session should see the prompt in their history.
|
|
3790
|
-
|
|
3817
|
+
entries.push(markEntry({ role: 'user', content: prompt, threadId: threadId || 'main' }));
|
|
3791
3818
|
}
|
|
3792
3819
|
}
|
|
3793
3820
|
|
|
@@ -3821,7 +3848,7 @@ function appendTurnToSessionHistory(sessionId, threadId, vpId, prompts, assistan
|
|
|
3821
3848
|
: { thinking: tb.thinking, signature: tb.signature }
|
|
3822
3849
|
));
|
|
3823
3850
|
}
|
|
3824
|
-
|
|
3851
|
+
entries.push(markEntry(assistantMsg));
|
|
3825
3852
|
|
|
3826
3853
|
for (const tr of toolResultsAccum) {
|
|
3827
3854
|
const toolMsg = {
|
|
@@ -3832,9 +3859,31 @@ function appendTurnToSessionHistory(sessionId, threadId, vpId, prompts, assistan
|
|
|
3832
3859
|
threadId: threadId || 'main',
|
|
3833
3860
|
};
|
|
3834
3861
|
if (vpId) toolMsg.speakerVpId = vpId;
|
|
3835
|
-
|
|
3862
|
+
entries.push(markEntry(toolMsg));
|
|
3836
3863
|
}
|
|
3837
3864
|
}
|
|
3865
|
+
return entries;
|
|
3866
|
+
}
|
|
3867
|
+
|
|
3868
|
+
function appendTurnToSessionHistory(sessionId, threadId, vpId, prompts, assistantTextParts, toolCallsAccum, toolResultsAccum, thinkingBlocksAccum, opts = {}) {
|
|
3869
|
+
if (!sessionId) return;
|
|
3870
|
+
const history = getOrCreateSessionHistory(sessionId);
|
|
3871
|
+
const nextEntries = buildTurnHistoryEntries(threadId, vpId, prompts, assistantTextParts, toolCallsAccum, toolResultsAccum, thinkingBlocksAccum, opts);
|
|
3872
|
+
if (nextEntries.length === 0) return;
|
|
3873
|
+
const runtimeTurnId = typeof opts.turnId === 'string' && opts.turnId ? opts.turnId : null;
|
|
3874
|
+
if (runtimeTurnId) {
|
|
3875
|
+
let insertAt = history.length;
|
|
3876
|
+
for (let i = history.length - 1; i >= 0; i--) {
|
|
3877
|
+
if (history[i]?._runtimeTurnId === runtimeTurnId) {
|
|
3878
|
+
insertAt = i;
|
|
3879
|
+
history.splice(i, 1);
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
if (insertAt > history.length) insertAt = history.length;
|
|
3883
|
+
history.splice(insertAt, 0, ...nextEntries);
|
|
3884
|
+
} else {
|
|
3885
|
+
history.push(...nextEntries);
|
|
3886
|
+
}
|
|
3838
3887
|
}
|
|
3839
3888
|
|
|
3840
3889
|
/**
|