@yeaft/webchat-agent 0.1.967 → 0.1.969
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 +29 -8
- package/package.json +1 -1
- package/workbench/transfer.js +28 -5
package/conversation.js
CHANGED
|
@@ -774,18 +774,39 @@ export async function handleUserInput(msg) {
|
|
|
774
774
|
let state = ctx.conversations.get(conversationId);
|
|
775
775
|
|
|
776
776
|
// ★ Non-Claude providers: dispatch to driver and return
|
|
777
|
-
|
|
777
|
+
// fix-copilot-provider-persist: after an agent process restart `state` is
|
|
778
|
+
// gone (ctx.conversations is in-memory only). The server now forwards the
|
|
779
|
+
// persisted `provider` on the execute/transfer_files payload so we can
|
|
780
|
+
// re-resolve it here — otherwise this falls back to claude-code, skips the
|
|
781
|
+
// self-heal `driver.start()` below, and a copilot conversation mis-routes
|
|
782
|
+
// to Claude (the dead-send bug). `isValidProvider` guards a bad value.
|
|
783
|
+
const providerName = state?.providerName
|
|
784
|
+
|| (isValidProvider(msg.provider) ? msg.provider : DEFAULT_PROVIDER);
|
|
778
785
|
if (providerName !== 'claude-code') {
|
|
779
786
|
const driver = getProvider(providerName);
|
|
780
787
|
const effectiveWorkDir = workDir || state?.workDir || ctx.CONFIG.workDir;
|
|
781
788
|
if (!state) {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
+
// Re-spawn the provider's session (e.g. the Copilot ACP child) that
|
|
790
|
+
// died with the previous agent process. If the CLI is unavailable on
|
|
791
|
+
// the restarted machine, surface a visible error frame instead of an
|
|
792
|
+
// unhandled rejection (the send was dispatched un-awaited upstream).
|
|
793
|
+
try {
|
|
794
|
+
state = await driver.start({
|
|
795
|
+
conversationId,
|
|
796
|
+
workDir: effectiveWorkDir,
|
|
797
|
+
resumeSessionId: claudeSessionId || null,
|
|
798
|
+
userId: msg.userId,
|
|
799
|
+
username: msg.username,
|
|
800
|
+
});
|
|
801
|
+
} catch (err) {
|
|
802
|
+
sendOutput(conversationId, {
|
|
803
|
+
type: 'result',
|
|
804
|
+
subtype: 'error',
|
|
805
|
+
is_error: true,
|
|
806
|
+
error: `${providerName} provider failed to start: ${err?.message || err}`,
|
|
807
|
+
});
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
789
810
|
}
|
|
790
811
|
if (workDir) state.workDir = workDir;
|
|
791
812
|
|
package/package.json
CHANGED
package/workbench/transfer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
2
|
import { join, basename, extname } from 'path';
|
|
3
3
|
import ctx from '../context.js';
|
|
4
|
-
import { getProvider, DEFAULT_PROVIDER } from '../providers/index.js';
|
|
4
|
+
import { getProvider, DEFAULT_PROVIDER, isValidProvider } from '../providers/index.js';
|
|
5
5
|
import { sendOutput, sendConversationList } from '../conversation.js';
|
|
6
6
|
|
|
7
7
|
// 临时文件目录名 (不易冲突)
|
|
@@ -64,12 +64,35 @@ export async function handleTransferFiles(msg) {
|
|
|
64
64
|
// image bytes over ACP, so images are handed to the driver as attachments
|
|
65
65
|
// instead of being inlined as disk paths the way the Claude path does.
|
|
66
66
|
//
|
|
67
|
-
// Note:
|
|
68
|
-
// (
|
|
69
|
-
//
|
|
70
|
-
|
|
67
|
+
// Note: after an agent process restart `state` is null even for a copilot
|
|
68
|
+
// conversation (ctx.conversations is in-memory). The server now forwards
|
|
69
|
+
// the persisted `provider` on the transfer_files payload, so we re-resolve
|
|
70
|
+
// it here and re-spawn the driver — without this an attachment send on a
|
|
71
|
+
// restarted copilot conversation would fall through to the Claude path and
|
|
72
|
+
// mis-route. `isValidProvider` guards a bad value.
|
|
73
|
+
const providerName = state?.providerName
|
|
74
|
+
|| (isValidProvider(msg.provider) ? msg.provider : DEFAULT_PROVIDER);
|
|
71
75
|
if (providerName !== 'claude-code') {
|
|
72
76
|
const driver = getProvider(providerName);
|
|
77
|
+
if (!state) {
|
|
78
|
+
try {
|
|
79
|
+
state = await driver.start({
|
|
80
|
+
conversationId,
|
|
81
|
+
workDir: effectiveWorkDir,
|
|
82
|
+
resumeSessionId: claudeSessionId || null,
|
|
83
|
+
userId: msg.userId,
|
|
84
|
+
username: msg.username,
|
|
85
|
+
});
|
|
86
|
+
} catch (err) {
|
|
87
|
+
sendOutput(conversationId, {
|
|
88
|
+
type: 'result',
|
|
89
|
+
subtype: 'error',
|
|
90
|
+
is_error: true,
|
|
91
|
+
error: `${providerName} provider failed to start: ${err?.message || err}`,
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
73
96
|
if (workDir) state.workDir = workDir;
|
|
74
97
|
|
|
75
98
|
// Images go inline as provider attachments ([{type,data,mimeType}] — the
|