@agent-link/agent 0.1.235 → 0.1.236
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 +190 -15
- package/dist/connection.js.map +1 -1
- package/dist/copilot.d.ts +61 -0
- package/dist/copilot.js +634 -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, 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,38 @@ 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
|
+
// Create a copilot placeholder so follow-up chats auto-resume
|
|
743
|
+
if (convId) {
|
|
744
|
+
createCopilotPlaceholder(convId, { providerId: 'copilot' });
|
|
745
|
+
const placeholder = getCopilotConversation(convId);
|
|
746
|
+
if (placeholder) {
|
|
747
|
+
placeholder.copilotSessionId = m.claudeSessionId;
|
|
748
|
+
placeholder.workDir = explicitWorkDir || state.workDir;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
const resolvedWorkDir = explicitWorkDir || state.workDir;
|
|
752
|
+
const history = readCopilotSessionMessages(resolvedWorkDir, m.claudeSessionId);
|
|
753
|
+
console.log(`[AgentLink] → conversation_resumed (${history.length} copilot messages, session ${m.claudeSessionId.slice(0, 8)})`);
|
|
754
|
+
send({
|
|
755
|
+
type: 'conversation_resumed',
|
|
756
|
+
conversationId: convId,
|
|
757
|
+
claudeSessionId: m.claudeSessionId,
|
|
758
|
+
history,
|
|
759
|
+
isCompacting: false,
|
|
760
|
+
isProcessing: false,
|
|
761
|
+
planMode: false,
|
|
762
|
+
permissionMode: 'normal',
|
|
763
|
+
...(typeof m.scrollToMessageIdx === 'number' ? { scrollToMessageIdx: m.scrollToMessageIdx } : {}),
|
|
764
|
+
...(m.searchQuery ? { searchQuery: m.searchQuery } : {}),
|
|
765
|
+
});
|
|
766
|
+
break;
|
|
767
|
+
}
|
|
680
768
|
if (!convId) {
|
|
681
769
|
// Backward compat: single-session mode
|
|
682
770
|
const conv = getConversation();
|
|
@@ -803,13 +891,27 @@ function handleServerMessage(msg) {
|
|
|
803
891
|
case 'delete_session': {
|
|
804
892
|
const m = msg;
|
|
805
893
|
const dir = m.workDir?.trim() ? path.resolve(m.workDir) : state.workDir;
|
|
806
|
-
|
|
894
|
+
if (isCopilotBackend()) {
|
|
895
|
+
const ok = deleteCopilotSession(dir, m.sessionId);
|
|
896
|
+
console.log(`[AgentLink] delete copilot session ${m.sessionId}: ${ok}`);
|
|
897
|
+
handleListCopilotSessionsFn(dir);
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
handleDeleteSession(m.sessionId, dir);
|
|
901
|
+
}
|
|
807
902
|
break;
|
|
808
903
|
}
|
|
809
904
|
case 'rename_session': {
|
|
810
905
|
const m = msg;
|
|
811
906
|
const dir = m.workDir?.trim() ? path.resolve(m.workDir) : state.workDir;
|
|
812
|
-
|
|
907
|
+
if (isCopilotBackend()) {
|
|
908
|
+
const ok = renameCopilotSession(dir, m.sessionId, m.newTitle);
|
|
909
|
+
console.log(`[AgentLink] rename copilot session ${m.sessionId}: ${ok}`);
|
|
910
|
+
handleListCopilotSessionsFn(dir);
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
handleRenameSession(m.sessionId, m.newTitle, dir);
|
|
914
|
+
}
|
|
813
915
|
break;
|
|
814
916
|
}
|
|
815
917
|
case 'query_active_conversations': {
|
|
@@ -1076,23 +1178,85 @@ function handleServerMessage(msg) {
|
|
|
1076
1178
|
case 'set_provider': {
|
|
1077
1179
|
const { providerId, conversationId } = msg;
|
|
1078
1180
|
console.log(`[AgentLink] set_provider: providerId=${providerId}, conversationId=${conversationId}`);
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1181
|
+
// Detect backend type change
|
|
1182
|
+
const newBackendType = getBackendTypeForProvider(providerId);
|
|
1183
|
+
const oldBackendType = getBackendType();
|
|
1184
|
+
const backendChanged = newBackendType !== oldBackendType;
|
|
1185
|
+
if (backendChanged) {
|
|
1186
|
+
// Cancel any in-flight work on the old backend
|
|
1187
|
+
if (oldBackendType === 'copilot' && conversationId) {
|
|
1188
|
+
cancelCopilotExecution(conversationId);
|
|
1189
|
+
}
|
|
1190
|
+
else if (conversationId) {
|
|
1191
|
+
const conv = getConversation(conversationId);
|
|
1192
|
+
if (conv) {
|
|
1193
|
+
const result = restartConversation(conversationId, { providerId });
|
|
1194
|
+
if (result.wasTurnActive) {
|
|
1195
|
+
send({ type: 'execution_cancelled', conversationId });
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
setBackendType(newBackendType);
|
|
1200
|
+
console.log(`[AgentLink] Backend switched: ${oldBackendType} → ${newBackendType}`);
|
|
1201
|
+
}
|
|
1202
|
+
else if (oldBackendType === 'copilot') {
|
|
1203
|
+
// Same backend (copilot), restart conversation
|
|
1204
|
+
if (conversationId && getCopilotConversation(conversationId)) {
|
|
1205
|
+
const result = restartCopilotConversation(conversationId, { providerId });
|
|
1206
|
+
if (result.wasTurnActive) {
|
|
1207
|
+
send({ type: 'execution_cancelled', conversationId });
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
else if (conversationId) {
|
|
1211
|
+
createCopilotPlaceholder(conversationId, { providerId });
|
|
1084
1212
|
}
|
|
1085
1213
|
}
|
|
1086
1214
|
else {
|
|
1087
|
-
|
|
1215
|
+
// Same backend (claude), existing logic
|
|
1216
|
+
const conv = getConversation(conversationId);
|
|
1217
|
+
if (conv) {
|
|
1218
|
+
const result = restartConversation(conversationId, { providerId });
|
|
1219
|
+
if (result.wasTurnActive) {
|
|
1220
|
+
send({ type: 'execution_cancelled', conversationId });
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
else {
|
|
1224
|
+
createPlaceholderConversation(conversationId, { providerId });
|
|
1225
|
+
}
|
|
1088
1226
|
}
|
|
1089
1227
|
send({ type: 'provider_changed', providerId, conversationId });
|
|
1228
|
+
// Send backend_info when backend type changed
|
|
1229
|
+
if (backendChanged) {
|
|
1230
|
+
const caps = newBackendType === 'copilot'
|
|
1231
|
+
? copilotCapabilities()
|
|
1232
|
+
: undefined; // Claude doesn't send capabilities yet (Phase 2)
|
|
1233
|
+
send({
|
|
1234
|
+
type: 'backend_info',
|
|
1235
|
+
backend: newBackendType,
|
|
1236
|
+
...(caps ? { capabilities: caps } : {}),
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1090
1239
|
break;
|
|
1091
1240
|
}
|
|
1092
1241
|
case 'list_providers': {
|
|
1093
1242
|
const providers = listProviders();
|
|
1094
1243
|
const defaultId = getDefaultProviderId();
|
|
1095
1244
|
send({ type: 'providers_list', providers, default: defaultId });
|
|
1245
|
+
// On initial connect, sync backend type to match the default provider.
|
|
1246
|
+
// This handles agent restart: currentBackendType resets to 'claude' but
|
|
1247
|
+
// the user's saved default provider may be 'copilot'.
|
|
1248
|
+
const expectedBt = getBackendTypeForProvider(defaultId);
|
|
1249
|
+
if (expectedBt !== getBackendType()) {
|
|
1250
|
+
setBackendType(expectedBt);
|
|
1251
|
+
console.log(`[AgentLink] Backend synced to default provider: ${expectedBt}`);
|
|
1252
|
+
}
|
|
1253
|
+
if (getBackendType() === 'copilot') {
|
|
1254
|
+
send({
|
|
1255
|
+
type: 'backend_info',
|
|
1256
|
+
backend: 'copilot',
|
|
1257
|
+
capabilities: copilotCapabilities(),
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1096
1260
|
break;
|
|
1097
1261
|
}
|
|
1098
1262
|
case 'save_provider': {
|
|
@@ -1570,6 +1734,17 @@ function handleListSessions(dir) {
|
|
|
1570
1734
|
send({ type: 'sessions_list', sessions: [], workDir: dir });
|
|
1571
1735
|
}
|
|
1572
1736
|
}
|
|
1737
|
+
function handleListCopilotSessionsFn(dir) {
|
|
1738
|
+
try {
|
|
1739
|
+
const sessions = listCopilotSessions(dir);
|
|
1740
|
+
console.log(`[AgentLink] → sessions_list (${sessions.length} copilot sessions for ${dir})`);
|
|
1741
|
+
send({ type: 'sessions_list', sessions, workDir: dir });
|
|
1742
|
+
}
|
|
1743
|
+
catch (err) {
|
|
1744
|
+
console.error(`[AgentLink] listCopilotSessions failed:`, err);
|
|
1745
|
+
send({ type: 'sessions_list', sessions: [], workDir: dir });
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1573
1748
|
function handleListBrainSessions() {
|
|
1574
1749
|
try {
|
|
1575
1750
|
const sessions = listSessions(BRAIN_DATA_DIR);
|