@yeaft/webchat-agent 1.0.505 → 1.0.507
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/conversation.js +4 -2
- package/local-runtime/server/handlers/agent-conversation.js +11 -9
- package/local-runtime/server/handlers/client-conversation.js +28 -2
- package/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +80 -80
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +1 -1
- package/package.json +1 -1
- package/yeaft/cli.js +3 -0
- package/yeaft/conversation/persist.js +15 -9
- package/yeaft/conversation/search.js +2 -1
- package/yeaft/effort.js +159 -6
- package/yeaft/engine.js +94 -28
- package/yeaft/history-window.js +60 -5
- package/yeaft/llm/adapter.js +3 -2
- package/yeaft/llm/anthropic.js +97 -25
- package/yeaft/llm/openai-responses.js +71 -7
- package/yeaft/llm/provider-state.js +242 -0
- package/yeaft/llm/router.js +14 -2
- package/yeaft/llm/usage-accounting.js +3 -0
- package/yeaft/models.js +4 -1
- package/yeaft/snapshot-filter.js +1 -0
- package/yeaft/sub-agent/output-log.js +4 -0
- package/yeaft/sub-agent/prompt-queue.js +3 -0
- package/yeaft/sub-agent/runner.js +13 -2
- package/yeaft/tools/agent.js +3 -0
- package/yeaft/tools/send-message.js +2 -0
- package/yeaft/web-bridge.js +5 -5
package/conversation.js
CHANGED
|
@@ -423,10 +423,12 @@ export async function resumeConversation(msg) {
|
|
|
423
423
|
console.log(`[Resume] claudeSessionId: ${claudeSessionId}`);
|
|
424
424
|
console.log(`[Resume] workDir: ${effectiveWorkDir} (lazy start)`);
|
|
425
425
|
|
|
426
|
-
//
|
|
426
|
+
// 清理旧条目:CLI session ID 只在当前实例的同 owner/provider 内去重。
|
|
427
427
|
let priorProviderOptions = null;
|
|
428
428
|
for (const [id, conv] of ctx.conversations) {
|
|
429
|
-
if (id === conversationId || (claudeSessionId && conv.claudeSessionId === claudeSessionId
|
|
429
|
+
if (id === conversationId || (claudeSessionId && conv.claudeSessionId === claudeSessionId &&
|
|
430
|
+
(conv.providerName || DEFAULT_PROVIDER) === provider &&
|
|
431
|
+
(conv.userId || null) === (userId || null))) {
|
|
430
432
|
console.log(`[Resume] Cleaning up old conversation: ${id} (claudeSessionId: ${conv.claudeSessionId})`);
|
|
431
433
|
if (conv.providerOptions && !priorProviderOptions) priorProviderOptions = conv.providerOptions;
|
|
432
434
|
let cleanupDriver = null;
|
|
@@ -87,15 +87,6 @@ export async function handleAgentConversation(agentId, agent, msg) {
|
|
|
87
87
|
|
|
88
88
|
case 'conversation_created':
|
|
89
89
|
case 'conversation_resumed': {
|
|
90
|
-
// 清理同 claudeSessionId 的旧条目(避免重复恢复同一个 session 累积)
|
|
91
|
-
if (msg.type === 'conversation_resumed' && msg.claudeSessionId) {
|
|
92
|
-
for (const [id, conv] of agent.conversations) {
|
|
93
|
-
if (id !== msg.conversationId && conv.claudeSessionId === msg.claudeSessionId) {
|
|
94
|
-
agent.conversations.delete(id);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
90
|
// fix-session-dup: if this conv is currently held in another
|
|
100
91
|
// agent's in-memory Map (e.g. user resumed it against a
|
|
101
92
|
// different machine after the original agent went offline),
|
|
@@ -141,6 +132,17 @@ export async function handleAgentConversation(agentId, agent, msg) {
|
|
|
141
132
|
const reportedProvider = (msg.provider && msg.provider !== 'claude-code') ? msg.provider : null;
|
|
142
133
|
const resolvedProvider = reportedProvider || existingConvData?.provider || dbSessionData?.provider || null;
|
|
143
134
|
|
|
135
|
+
// CLI IDs are scoped to this Agent, provider and owner, not globally unique.
|
|
136
|
+
if (msg.type === 'conversation_resumed' && msg.claudeSessionId) {
|
|
137
|
+
for (const [id, conv] of agent.conversations) {
|
|
138
|
+
if (id !== msg.conversationId && conv.claudeSessionId === msg.claudeSessionId &&
|
|
139
|
+
(conv.provider || 'claude-code') === (resolvedProvider || 'claude-code') &&
|
|
140
|
+
(conv.userId || agent.ownerId || null) === trustedUserId) {
|
|
141
|
+
agent.conversations.delete(id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
144
146
|
agent.conversations.set(msg.conversationId, {
|
|
145
147
|
id: msg.conversationId,
|
|
146
148
|
workDir: msg.workDir,
|
|
@@ -509,7 +509,6 @@ export async function handleClientConversation(clientId, client, msg, checkAgent
|
|
|
509
509
|
await sendToWebClient(client, { type: 'error', message: 'Agent is still syncing, please wait...' });
|
|
510
510
|
return;
|
|
511
511
|
}
|
|
512
|
-
client.currentAgent = resumeAgentId;
|
|
513
512
|
// fix-copilot-provider-persist: the web's auto-restore / recovery
|
|
514
513
|
// resume paths (web/stores/helpers/session.js) send no provider, and
|
|
515
514
|
// the agent's resume handler defaults an absent provider to
|
|
@@ -518,7 +517,34 @@ export async function handleClientConversation(clientId, client, msg, checkAgent
|
|
|
518
517
|
// 'claude-code'} and the persist path would CLOBBER the stored
|
|
519
518
|
// 'copilot' binding — reintroducing the bug, permanently. Inject the
|
|
520
519
|
// persisted provider so a provider-less resume keeps the real one.
|
|
521
|
-
const
|
|
520
|
+
const persistedResume = msg.conversationId ? sessionDb.get(msg.conversationId) : null;
|
|
521
|
+
const liveResume = resumeAgent.conversations?.get(msg.conversationId);
|
|
522
|
+
const resumeProvider = msg.provider || persistedResume?.provider || liveResume?.provider || 'claude-code';
|
|
523
|
+
// A supplied Web ID may only be reused within its existing identity.
|
|
524
|
+
// Check both persisted and live rows before forwarding any destructive resume.
|
|
525
|
+
const bindings = [];
|
|
526
|
+
if (persistedResume) bindings.push({
|
|
527
|
+
agentId: persistedResume.agent_id,
|
|
528
|
+
userId: persistedResume.user_id || agents.get(persistedResume.agent_id)?.ownerId,
|
|
529
|
+
provider: persistedResume.provider,
|
|
530
|
+
});
|
|
531
|
+
if (msg.conversationId) {
|
|
532
|
+
for (const [agentId, agent] of agents) {
|
|
533
|
+
const conversation = agent.conversations?.get(msg.conversationId);
|
|
534
|
+
if (conversation) bindings.push({
|
|
535
|
+
agentId,
|
|
536
|
+
userId: conversation.userId || agent.ownerId,
|
|
537
|
+
provider: conversation.provider || persistedResume?.provider,
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
if (bindings.some(binding => binding.agentId !== resumeAgentId ||
|
|
542
|
+
(binding.provider || 'claude-code') !== resumeProvider ||
|
|
543
|
+
(!CONFIG.skipAuth && binding.userId !== client.userId))) {
|
|
544
|
+
await sendToWebClient(client, { type: 'error', message: 'Permission denied' });
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
client.currentAgent = resumeAgentId;
|
|
522
548
|
await forwardToAgent(resumeAgentId, {
|
|
523
549
|
type: 'resume_conversation',
|
|
524
550
|
conversationId: msg.conversationId || randomUUID(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.0.
|
|
1
|
+
{"version":"1.0.507"}
|