@agent-link/agent 0.1.235 → 0.1.237
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/dist/backends/index.js +2 -0
- package/dist/backends/index.js.map +1 -1
- package/dist/backends/types.d.ts +7 -1
- package/dist/backends/types.js +62 -1
- package/dist/backends/types.js.map +1 -1
- package/dist/connection.js +197 -15
- package/dist/connection.js.map +1 -1
- package/dist/copilot.d.ts +69 -0
- package/dist/copilot.js +676 -0
- package/dist/copilot.js.map +1 -0
- package/dist/providers.d.ts +7 -0
- package/dist/providers.js +30 -0
- package/dist/providers.js.map +1 -1
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.js +13 -0
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
package/dist/backends/index.js
CHANGED
|
@@ -42,6 +42,8 @@ export function createBackend(type, _opts) {
|
|
|
42
42
|
return new ClaudeBackend(_opts);
|
|
43
43
|
case 'codex':
|
|
44
44
|
throw new BackendNotImplementedError('codex');
|
|
45
|
+
case 'copilot':
|
|
46
|
+
throw new BackendNotImplementedError('copilot'); // CopilotBackend uses copilot.ts directly, not through AgentBackend
|
|
45
47
|
default: {
|
|
46
48
|
// exhaustiveness guard
|
|
47
49
|
const _exhaustive = type;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAuD,MAAM,YAAY,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,IAAY;QACtB,KAAK,CACH,0BAA0B,IAAI,mBAAmB,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACnF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAY,IAAiB;QAC3B,KAAK,CACH,YAAY,IAAI,0DAA0D,CAC3E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,IAAI,CAAE,mBAAyC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAiB;IAC3D,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,OAAO;YACV,MAAM,IAAI,0BAA0B,CAAC,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,CAAC,CAAC;YACR,uBAAuB;YACvB,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAuD,MAAM,YAAY,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,IAAY;QACtB,KAAK,CACH,0BAA0B,IAAI,mBAAmB,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACnF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAY,IAAiB;QAC3B,KAAK,CACH,YAAY,IAAI,0DAA0D,CAC3E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,IAAI,CAAE,mBAAyC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAiB;IAC3D,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,OAAO;YACV,MAAM,IAAI,0BAA0B,CAAC,OAAO,CAAC,CAAC;QAChD,KAAK,SAAS;YACZ,MAAM,IAAI,0BAA0B,CAAC,SAAS,CAAC,CAAC,CAAC,oEAAoE;QACvH,OAAO,CAAC,CAAC,CAAC;YACR,uBAAuB;YACvB,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/backends/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Stage 1: defines the interface only. ClaudeBackend implementation lives in
|
|
5
5
|
* agent/src/claude.ts (refactor to backends/claude/* is a follow-up PR).
|
|
6
6
|
*/
|
|
7
|
-
export type BackendType = 'claude' | 'codex';
|
|
7
|
+
export type BackendType = 'claude' | 'codex' | 'copilot';
|
|
8
8
|
export declare const KNOWN_BACKEND_TYPES: readonly BackendType[];
|
|
9
9
|
/**
|
|
10
10
|
* Backend-neutral file attachment for `UserTurnInput.files`.
|
|
@@ -319,3 +319,9 @@ export declare function emptyCapabilities(): BackendCapabilities;
|
|
|
319
319
|
* yet, so both are reported as unsupported.
|
|
320
320
|
*/
|
|
321
321
|
export declare function claudeCapabilities(): BackendCapabilities;
|
|
322
|
+
/**
|
|
323
|
+
* Capabilities declared by the CopilotBackend adapter.
|
|
324
|
+
* Copilot CLI uses `--output-format json` JSONL, per-turn process spawning,
|
|
325
|
+
* and `~/.copilot/session-state/` for session persistence.
|
|
326
|
+
*/
|
|
327
|
+
export declare function copilotCapabilities(): BackendCapabilities;
|
package/dist/backends/types.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Stage 1: defines the interface only. ClaudeBackend implementation lives in
|
|
5
5
|
* agent/src/claude.ts (refactor to backends/claude/* is a follow-up PR).
|
|
6
6
|
*/
|
|
7
|
-
export const KNOWN_BACKEND_TYPES = ['claude', 'codex'];
|
|
7
|
+
export const KNOWN_BACKEND_TYPES = ['claude', 'codex', 'copilot'];
|
|
8
8
|
/** Helper: minimal capabilities object for a stub/unknown backend. */
|
|
9
9
|
export function emptyCapabilities() {
|
|
10
10
|
const cap = () => ({ supported: false });
|
|
@@ -101,4 +101,65 @@ export function claudeCapabilities() {
|
|
|
101
101
|
sandboxModes: ['unrestricted'], // Claude runs with bypassPermissions
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Capabilities declared by the CopilotBackend adapter.
|
|
106
|
+
* Copilot CLI uses `--output-format json` JSONL, per-turn process spawning,
|
|
107
|
+
* and `~/.copilot/session-state/` for session persistence.
|
|
108
|
+
*/
|
|
109
|
+
export function copilotCapabilities() {
|
|
110
|
+
const yes = (details) => ({ supported: true, details });
|
|
111
|
+
const no = () => ({ supported: false });
|
|
112
|
+
return {
|
|
113
|
+
lifecycle: {
|
|
114
|
+
persistentProcess: false, // each turn = new process
|
|
115
|
+
resumableSessions: true, // --resume=<sessionId>
|
|
116
|
+
concurrentTurns: false,
|
|
117
|
+
backgroundTurns: false,
|
|
118
|
+
fork: no(),
|
|
119
|
+
compaction: no(), // /compact is interactive-only
|
|
120
|
+
},
|
|
121
|
+
approvals: {
|
|
122
|
+
command: no(), // --allow-all-tools bypasses
|
|
123
|
+
fileChange: no(),
|
|
124
|
+
permissions: no(),
|
|
125
|
+
genericTool: no(),
|
|
126
|
+
userInput: no(), // no stdin protocol for ask_user in -p mode
|
|
127
|
+
},
|
|
128
|
+
streaming: {
|
|
129
|
+
text: true, // assistant.message_delta
|
|
130
|
+
reasoning: yes(), // assistant.reasoning_delta
|
|
131
|
+
plan: no(),
|
|
132
|
+
usage: { supported: true, details: { incremental: false } },
|
|
133
|
+
processOutput: no(),
|
|
134
|
+
fsWatch: no(),
|
|
135
|
+
remoteControl: { supported: false },
|
|
136
|
+
},
|
|
137
|
+
history: {
|
|
138
|
+
list: true, // read workspace.yaml files
|
|
139
|
+
read: true, // parse events.jsonl
|
|
140
|
+
rename: true, // edit workspace.yaml name field
|
|
141
|
+
delete: true, // filesystem delete
|
|
142
|
+
search: false,
|
|
143
|
+
},
|
|
144
|
+
models: {
|
|
145
|
+
list: no(), // /model is interactive-only
|
|
146
|
+
switchPerSession: true, // --model flag
|
|
147
|
+
switchPerTurn: true, // new process per turn
|
|
148
|
+
},
|
|
149
|
+
tools: {
|
|
150
|
+
itemTypes: ['powershell', 'bash', 'create', 'edit', 'read', 'grep', 'glob'],
|
|
151
|
+
fallbackRenderer: true,
|
|
152
|
+
specializedRenderers: [],
|
|
153
|
+
},
|
|
154
|
+
integrations: {
|
|
155
|
+
accountInfo: no(),
|
|
156
|
+
codeReview: no(),
|
|
157
|
+
mcpManagement: no(),
|
|
158
|
+
hooks: no(),
|
|
159
|
+
personalitySwitch: no(),
|
|
160
|
+
skills: no(),
|
|
161
|
+
},
|
|
162
|
+
sandboxModes: ['unrestricted'], // --allow-all-tools
|
|
163
|
+
};
|
|
164
|
+
}
|
|
104
165
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backends/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,MAAM,CAAC,MAAM,mBAAmB,GAA2B,CAAC,QAAQ,EAAE,OAAO,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backends/types.ts"],"names":[],"mappings":"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"}
|
package/dist/connection.js
CHANGED
|
@@ -16,7 +16,7 @@ import { listDevops, getDevopsDetail } from './devops.js';
|
|
|
16
16
|
import { listProjects, getProjectDetail } from './project.js';
|
|
17
17
|
import { brainSearch, getSearchIndexStats } from './search.js';
|
|
18
18
|
import { listBrainSessions, loadBrainChatEntries, sendBrainChatMessage, getBrainSessionStatus, deleteBrainSession } from './brain-chat.js';
|
|
19
|
-
import { listProviders, saveProvider, deleteProvider, getDefaultProviderId, setDefaultProviderId } from './providers.js';
|
|
19
|
+
import { listProviders, saveProvider, deleteProvider, getDefaultProviderId, setDefaultProviderId, getBackendTypeForProvider } from './providers.js';
|
|
20
20
|
import { createTunnelHandler } from './tunnel.js';
|
|
21
21
|
import { createTerminalManager } from './terminal.js';
|
|
22
22
|
import { mkdirSync } from 'fs';
|
|
@@ -24,7 +24,7 @@ const require = createRequire(import.meta.url);
|
|
|
24
24
|
const pkg = require('../package.json');
|
|
25
25
|
const TEAM_SESSIONS_DIR = path.join(CONFIG_DIR, 'team-sessions');
|
|
26
26
|
const LOOP_SESSIONS_DIR = path.join(CONFIG_DIR, 'loop-sessions');
|
|
27
|
-
import { handleChat as claudeHandleChat, addSendFn, abort as abortClaude, abortAll as abortAllClaude, cancelExecution as claudeCancelExecution, handleUserAnswer, handleToolPermissionResponse, handleBtwQuestion, getConversation, getConversations, getIsCompacting, clearSessionId, evictByClaudeSessionId, rebindConversation, addOutputObserver, removeOutputObserver, addCloseObserver, removeCloseObserver, setOutputObserver, clearOutputObserver, setCloseObserver, clearCloseObserver, restartConversation, createPlaceholderConversation, getPendingQuestions, getPendingToolPermissions, setModel, addOnSessionStarted } from './runtime.js';
|
|
27
|
+
import { handleChat as claudeHandleChat, addSendFn, abort as abortClaude, abortAll as abortAllClaude, cancelExecution as claudeCancelExecution, handleUserAnswer, handleToolPermissionResponse, handleBtwQuestion, getConversation, getConversations, getIsCompacting, clearSessionId, evictByClaudeSessionId, rebindConversation, addOutputObserver, removeOutputObserver, addCloseObserver, removeCloseObserver, setOutputObserver, clearOutputObserver, setCloseObserver, clearCloseObserver, restartConversation, createPlaceholderConversation, getPendingQuestions, getPendingToolPermissions, setModel, addOnSessionStarted, getBackendType, setBackendType, isCopilotBackend, addCopilotSendFn, handleCopilotChat, cancelCopilotExecution, listCopilotSessions, listAllCopilotSessions, readCopilotSessionMessages, deleteCopilotSession, renameCopilotSession, getCopilotConversation, createCopilotPlaceholder, restartCopilotConversation, rebindCopilotConversation, copilotCapabilities } from './runtime.js';
|
|
28
28
|
import { listSessions, readSessionMessages, deleteSession, renameSession, listAllRecentSessions, getSessionCacheStats } from './history.js';
|
|
29
29
|
import { searchSessions } from './search-sessions.js';
|
|
30
30
|
import { listMemoryFiles, updateMemoryFile, deleteMemoryFile } from './memory.js';
|
|
@@ -52,6 +52,7 @@ const state = {
|
|
|
52
52
|
entraToken: null,
|
|
53
53
|
};
|
|
54
54
|
let unsubscribeSend = null;
|
|
55
|
+
let unsubscribeCopilotSend = null;
|
|
55
56
|
let unsubscribeSessionStarted = null;
|
|
56
57
|
let heartbeatInterval = null;
|
|
57
58
|
let heartbeatTimeout = null;
|
|
@@ -95,6 +96,14 @@ export function connect(config) {
|
|
|
95
96
|
catch { /* ignore */ }
|
|
96
97
|
}
|
|
97
98
|
unsubscribeSend = addSendFn(send);
|
|
99
|
+
// Also wire up copilot module to send through same WebSocket
|
|
100
|
+
if (unsubscribeCopilotSend) {
|
|
101
|
+
try {
|
|
102
|
+
unsubscribeCopilotSend();
|
|
103
|
+
}
|
|
104
|
+
catch { /* ignore */ }
|
|
105
|
+
}
|
|
106
|
+
unsubscribeCopilotSend = addCopilotSendFn(send);
|
|
98
107
|
// Wire up action item session linkage
|
|
99
108
|
if (unsubscribeSessionStarted) {
|
|
100
109
|
try {
|
|
@@ -567,24 +576,71 @@ function handleServerMessage(msg) {
|
|
|
567
576
|
if (actionItemId && chatConvId) {
|
|
568
577
|
pendingActionItems.set(chatConvId, actionItemId);
|
|
569
578
|
}
|
|
570
|
-
|
|
579
|
+
// Auto-switch backend if chat message's providerId requires a different backend
|
|
580
|
+
if (effectiveProviderId) {
|
|
581
|
+
const requiredBt = getBackendTypeForProvider(effectiveProviderId);
|
|
582
|
+
if (requiredBt !== getBackendType()) {
|
|
583
|
+
setBackendType(requiredBt);
|
|
584
|
+
console.log(`[AgentLink] Backend auto-switched to ${requiredBt} (chat providerId=${effectiveProviderId})`);
|
|
585
|
+
const caps = requiredBt === 'copilot' ? copilotCapabilities() : undefined;
|
|
586
|
+
send({
|
|
587
|
+
type: 'backend_info',
|
|
588
|
+
backend: requiredBt,
|
|
589
|
+
...(caps ? { capabilities: caps } : {}),
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
// Route to copilot or claude based on current backend
|
|
594
|
+
if (isCopilotBackend()) {
|
|
595
|
+
handleCopilotChat(chatConvId || '', msg.prompt, chatDir, { resumeSessionId: chatOptions.resumeSessionId });
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
claudeHandleChat(chatConvId, msg.prompt, chatDir, chatOptions, msg.files);
|
|
599
|
+
}
|
|
571
600
|
break;
|
|
572
601
|
}
|
|
573
602
|
case 'cancel_execution':
|
|
574
|
-
|
|
603
|
+
if (isCopilotBackend()) {
|
|
604
|
+
cancelCopilotExecution(msg.conversationId || '');
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
claudeCancelExecution(msg.conversationId);
|
|
608
|
+
}
|
|
575
609
|
break;
|
|
576
610
|
case 'list_sessions': {
|
|
577
611
|
const m = msg;
|
|
578
612
|
const dir = m.workDir?.trim() ? path.resolve(m.workDir) : state.workDir;
|
|
579
|
-
|
|
613
|
+
// Use providerId from message to determine backend, falling back to global state
|
|
614
|
+
const sessionBackend = m.providerId
|
|
615
|
+
? getBackendTypeForProvider(m.providerId)
|
|
616
|
+
: getBackendType();
|
|
617
|
+
if (sessionBackend === 'copilot') {
|
|
618
|
+
handleListCopilotSessionsFn(dir);
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
handleListSessions(dir);
|
|
622
|
+
}
|
|
580
623
|
break;
|
|
581
624
|
}
|
|
582
625
|
case 'list_brain_sessions':
|
|
583
626
|
handleListBrainSessions();
|
|
584
627
|
break;
|
|
585
|
-
case 'list_recent_sessions':
|
|
586
|
-
|
|
628
|
+
case 'list_recent_sessions': {
|
|
629
|
+
const m = msg;
|
|
630
|
+
const recentBackend = m.providerId
|
|
631
|
+
? getBackendTypeForProvider(m.providerId)
|
|
632
|
+
: getBackendType();
|
|
633
|
+
if (recentBackend === 'copilot') {
|
|
634
|
+
const limit = m.limit && m.limit > 0 ? m.limit : 500;
|
|
635
|
+
const sessions = listAllCopilotSessions(limit);
|
|
636
|
+
console.log(`[AgentLink] → recent_sessions_list (${sessions.length} copilot sessions)`);
|
|
637
|
+
send({ type: 'recent_sessions_list', sessions });
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
handleListRecentSessions(msg);
|
|
641
|
+
}
|
|
587
642
|
break;
|
|
643
|
+
}
|
|
588
644
|
case 'search_sessions': {
|
|
589
645
|
const m = msg;
|
|
590
646
|
const dir = m.workDir?.trim() ? path.resolve(m.workDir) : state.workDir;
|
|
@@ -677,6 +733,45 @@ function handleServerMessage(msg) {
|
|
|
677
733
|
const convId = m.conversationId;
|
|
678
734
|
// Explicit workDir from frontend (e.g. action-item resume) — normalize to absolute path
|
|
679
735
|
const explicitWorkDir = m.workDir?.trim() ? path.resolve(m.workDir) : undefined;
|
|
736
|
+
// Determine backend: use providerId from message, fall back to global state
|
|
737
|
+
const resumeBackend = m.providerId
|
|
738
|
+
? getBackendTypeForProvider(m.providerId)
|
|
739
|
+
: getBackendType();
|
|
740
|
+
// Route to copilot backend
|
|
741
|
+
if (resumeBackend === 'copilot') {
|
|
742
|
+
// Rebind running copilot process to new conversationId (handles page refresh)
|
|
743
|
+
if (convId) {
|
|
744
|
+
rebindCopilotConversation(m.claudeSessionId, convId);
|
|
745
|
+
}
|
|
746
|
+
// Create a copilot placeholder so follow-up chats auto-resume
|
|
747
|
+
if (convId) {
|
|
748
|
+
createCopilotPlaceholder(convId, { providerId: 'copilot' });
|
|
749
|
+
const placeholder = getCopilotConversation(convId);
|
|
750
|
+
if (placeholder) {
|
|
751
|
+
placeholder.copilotSessionId = m.claudeSessionId;
|
|
752
|
+
placeholder.workDir = explicitWorkDir || state.workDir;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const resolvedWorkDir = explicitWorkDir || state.workDir;
|
|
756
|
+
const history = readCopilotSessionMessages(resolvedWorkDir, m.claudeSessionId);
|
|
757
|
+
// Check if this session has an active copilot process running
|
|
758
|
+
const copilotState = getCopilotConversation(convId || '');
|
|
759
|
+
const isCopilotProcessing = !!(copilotState?.turnActive && copilotState?.child);
|
|
760
|
+
console.log(`[AgentLink] → conversation_resumed (${history.length} copilot messages, session ${m.claudeSessionId.slice(0, 8)})`);
|
|
761
|
+
send({
|
|
762
|
+
type: 'conversation_resumed',
|
|
763
|
+
conversationId: convId,
|
|
764
|
+
claudeSessionId: m.claudeSessionId,
|
|
765
|
+
history,
|
|
766
|
+
isCompacting: false,
|
|
767
|
+
isProcessing: isCopilotProcessing,
|
|
768
|
+
planMode: false,
|
|
769
|
+
permissionMode: 'normal',
|
|
770
|
+
...(typeof m.scrollToMessageIdx === 'number' ? { scrollToMessageIdx: m.scrollToMessageIdx } : {}),
|
|
771
|
+
...(m.searchQuery ? { searchQuery: m.searchQuery } : {}),
|
|
772
|
+
});
|
|
773
|
+
break;
|
|
774
|
+
}
|
|
680
775
|
if (!convId) {
|
|
681
776
|
// Backward compat: single-session mode
|
|
682
777
|
const conv = getConversation();
|
|
@@ -803,13 +898,27 @@ function handleServerMessage(msg) {
|
|
|
803
898
|
case 'delete_session': {
|
|
804
899
|
const m = msg;
|
|
805
900
|
const dir = m.workDir?.trim() ? path.resolve(m.workDir) : state.workDir;
|
|
806
|
-
|
|
901
|
+
if (isCopilotBackend()) {
|
|
902
|
+
const ok = deleteCopilotSession(dir, m.sessionId);
|
|
903
|
+
console.log(`[AgentLink] delete copilot session ${m.sessionId}: ${ok}`);
|
|
904
|
+
handleListCopilotSessionsFn(dir);
|
|
905
|
+
}
|
|
906
|
+
else {
|
|
907
|
+
handleDeleteSession(m.sessionId, dir);
|
|
908
|
+
}
|
|
807
909
|
break;
|
|
808
910
|
}
|
|
809
911
|
case 'rename_session': {
|
|
810
912
|
const m = msg;
|
|
811
913
|
const dir = m.workDir?.trim() ? path.resolve(m.workDir) : state.workDir;
|
|
812
|
-
|
|
914
|
+
if (isCopilotBackend()) {
|
|
915
|
+
const ok = renameCopilotSession(dir, m.sessionId, m.newTitle);
|
|
916
|
+
console.log(`[AgentLink] rename copilot session ${m.sessionId}: ${ok}`);
|
|
917
|
+
handleListCopilotSessionsFn(dir);
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
handleRenameSession(m.sessionId, m.newTitle, dir);
|
|
921
|
+
}
|
|
813
922
|
break;
|
|
814
923
|
}
|
|
815
924
|
case 'query_active_conversations': {
|
|
@@ -1076,23 +1185,85 @@ function handleServerMessage(msg) {
|
|
|
1076
1185
|
case 'set_provider': {
|
|
1077
1186
|
const { providerId, conversationId } = msg;
|
|
1078
1187
|
console.log(`[AgentLink] set_provider: providerId=${providerId}, conversationId=${conversationId}`);
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1188
|
+
// Detect backend type change
|
|
1189
|
+
const newBackendType = getBackendTypeForProvider(providerId);
|
|
1190
|
+
const oldBackendType = getBackendType();
|
|
1191
|
+
const backendChanged = newBackendType !== oldBackendType;
|
|
1192
|
+
if (backendChanged) {
|
|
1193
|
+
// Cancel any in-flight work on the old backend
|
|
1194
|
+
if (oldBackendType === 'copilot' && conversationId) {
|
|
1195
|
+
cancelCopilotExecution(conversationId);
|
|
1196
|
+
}
|
|
1197
|
+
else if (conversationId) {
|
|
1198
|
+
const conv = getConversation(conversationId);
|
|
1199
|
+
if (conv) {
|
|
1200
|
+
const result = restartConversation(conversationId, { providerId });
|
|
1201
|
+
if (result.wasTurnActive) {
|
|
1202
|
+
send({ type: 'execution_cancelled', conversationId });
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
setBackendType(newBackendType);
|
|
1207
|
+
console.log(`[AgentLink] Backend switched: ${oldBackendType} → ${newBackendType}`);
|
|
1208
|
+
}
|
|
1209
|
+
else if (oldBackendType === 'copilot') {
|
|
1210
|
+
// Same backend (copilot), restart conversation
|
|
1211
|
+
if (conversationId && getCopilotConversation(conversationId)) {
|
|
1212
|
+
const result = restartCopilotConversation(conversationId, { providerId });
|
|
1213
|
+
if (result.wasTurnActive) {
|
|
1214
|
+
send({ type: 'execution_cancelled', conversationId });
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
else if (conversationId) {
|
|
1218
|
+
createCopilotPlaceholder(conversationId, { providerId });
|
|
1084
1219
|
}
|
|
1085
1220
|
}
|
|
1086
1221
|
else {
|
|
1087
|
-
|
|
1222
|
+
// Same backend (claude), existing logic
|
|
1223
|
+
const conv = getConversation(conversationId);
|
|
1224
|
+
if (conv) {
|
|
1225
|
+
const result = restartConversation(conversationId, { providerId });
|
|
1226
|
+
if (result.wasTurnActive) {
|
|
1227
|
+
send({ type: 'execution_cancelled', conversationId });
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
else {
|
|
1231
|
+
createPlaceholderConversation(conversationId, { providerId });
|
|
1232
|
+
}
|
|
1088
1233
|
}
|
|
1089
1234
|
send({ type: 'provider_changed', providerId, conversationId });
|
|
1235
|
+
// Send backend_info when backend type changed
|
|
1236
|
+
if (backendChanged) {
|
|
1237
|
+
const caps = newBackendType === 'copilot'
|
|
1238
|
+
? copilotCapabilities()
|
|
1239
|
+
: undefined; // Claude doesn't send capabilities yet (Phase 2)
|
|
1240
|
+
send({
|
|
1241
|
+
type: 'backend_info',
|
|
1242
|
+
backend: newBackendType,
|
|
1243
|
+
...(caps ? { capabilities: caps } : {}),
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1090
1246
|
break;
|
|
1091
1247
|
}
|
|
1092
1248
|
case 'list_providers': {
|
|
1093
1249
|
const providers = listProviders();
|
|
1094
1250
|
const defaultId = getDefaultProviderId();
|
|
1095
1251
|
send({ type: 'providers_list', providers, default: defaultId });
|
|
1252
|
+
// On initial connect, sync backend type to match the default provider.
|
|
1253
|
+
// This handles agent restart: currentBackendType resets to 'claude' but
|
|
1254
|
+
// the user's saved default provider may be 'copilot'.
|
|
1255
|
+
const expectedBt = getBackendTypeForProvider(defaultId);
|
|
1256
|
+
if (expectedBt !== getBackendType()) {
|
|
1257
|
+
setBackendType(expectedBt);
|
|
1258
|
+
console.log(`[AgentLink] Backend synced to default provider: ${expectedBt}`);
|
|
1259
|
+
}
|
|
1260
|
+
if (getBackendType() === 'copilot') {
|
|
1261
|
+
send({
|
|
1262
|
+
type: 'backend_info',
|
|
1263
|
+
backend: 'copilot',
|
|
1264
|
+
capabilities: copilotCapabilities(),
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1096
1267
|
break;
|
|
1097
1268
|
}
|
|
1098
1269
|
case 'save_provider': {
|
|
@@ -1570,6 +1741,17 @@ function handleListSessions(dir) {
|
|
|
1570
1741
|
send({ type: 'sessions_list', sessions: [], workDir: dir });
|
|
1571
1742
|
}
|
|
1572
1743
|
}
|
|
1744
|
+
function handleListCopilotSessionsFn(dir) {
|
|
1745
|
+
try {
|
|
1746
|
+
const sessions = listCopilotSessions(dir);
|
|
1747
|
+
console.log(`[AgentLink] → sessions_list (${sessions.length} copilot sessions for ${dir})`);
|
|
1748
|
+
send({ type: 'sessions_list', sessions, workDir: dir });
|
|
1749
|
+
}
|
|
1750
|
+
catch (err) {
|
|
1751
|
+
console.error(`[AgentLink] listCopilotSessions failed:`, err);
|
|
1752
|
+
send({ type: 'sessions_list', sessions: [], workDir: dir });
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1573
1755
|
function handleListBrainSessions() {
|
|
1574
1756
|
try {
|
|
1575
1757
|
const sessions = listSessions(BRAIN_DATA_DIR);
|