happy-imou-cloud 2.0.13 → 2.0.16
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/BaseReasoningProcessor-BqMAZlIw.cjs +323 -0
- package/dist/BaseReasoningProcessor-C04_LHjN.mjs +320 -0
- package/dist/ProviderSelectionHandler-CO9NkAt6.cjs +265 -0
- package/dist/ProviderSelectionHandler-DDWyn9Lo.mjs +261 -0
- package/dist/{api-DH5-IqeM.cjs → api-Db1SQcP_.cjs} +2 -2
- package/dist/{api-D1meoL-9.mjs → api-sRF6xXi-.mjs} +2 -2
- package/dist/{command-CMvWClny.mjs → command-WcgGTRnG.mjs} +4 -3
- package/dist/{command-Ch8Dgidj.cjs → command-eRjSBm2C.cjs} +4 -3
- package/dist/{index-CryJfCh5.cjs → index-B6ID1zDR.cjs} +1106 -50
- package/dist/{index-Cxrx9m5D.mjs → index-DpWeKfvS.mjs} +1102 -50
- package/dist/index.cjs +5 -4
- package/dist/index.mjs +5 -4
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{persistence-9Iu0wGNM.mjs → persistence-B89V4xY5.mjs} +1 -1
- package/dist/{persistence-Bl3FYvwd.cjs → persistence-Btu2VPXI.cjs} +1 -1
- package/dist/{registerKillSessionHandler-BElGmD1E.mjs → registerKillSessionHandler-CwmYlUfS.mjs} +541 -5
- package/dist/{registerKillSessionHandler-BjkY-oUn.cjs → registerKillSessionHandler-eZ2TsHqx.cjs} +549 -4
- package/dist/{runClaude-CDZxAF3l.cjs → runClaude-C9-ylbQh.cjs} +599 -747
- package/dist/{runClaude-D7dF4RDM.mjs → runClaude-kRPXCaBj.mjs} +591 -738
- package/dist/{runCodex-DnGz1XES.mjs → runCodex-B1xN0wAU.mjs} +9 -215
- package/dist/{runCodex-Cik8VzFs.cjs → runCodex-CRNBxY5f.cjs} +20 -226
- package/dist/{runGemini-BM2BQ4I7.cjs → runGemini-BZ5hqJyl.cjs} +16 -15
- package/dist/{runGemini-B8tXMHeL.mjs → runGemini-Xn2VwS88.mjs} +8 -7
- package/package.json +1 -1
- package/scripts/release-smoke.mjs +6 -5
- package/dist/ConversationHistory-V3VLmjJf.cjs +0 -868
- package/dist/ConversationHistory-_ciJNIgH.mjs +0 -856
- package/dist/createKeepAliveController-C5cQlDRr.mjs +0 -51
- package/dist/createKeepAliveController-DO8H6d5E.cjs +0 -54
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var node_crypto = require('node:crypto');
|
|
4
|
-
var api = require('./api-
|
|
4
|
+
var api = require('./api-Db1SQcP_.cjs');
|
|
5
5
|
require('cross-spawn');
|
|
6
6
|
require('@agentclientprotocol/sdk');
|
|
7
|
-
var index = require('./index-
|
|
7
|
+
var index = require('./index-B6ID1zDR.cjs');
|
|
8
8
|
require('ps-list');
|
|
9
9
|
require('fs');
|
|
10
10
|
require('path');
|
|
@@ -13,11 +13,12 @@ require('child_process');
|
|
|
13
13
|
var fs$1 = require('node:fs');
|
|
14
14
|
var path = require('node:path');
|
|
15
15
|
var os = require('node:os');
|
|
16
|
-
require('
|
|
16
|
+
var node_child_process = require('node:child_process');
|
|
17
|
+
require('node:readline');
|
|
18
|
+
require('./persistence-Btu2VPXI.cjs');
|
|
17
19
|
var promises = require('node:fs/promises');
|
|
18
20
|
var fs = require('fs/promises');
|
|
19
21
|
require('crypto');
|
|
20
|
-
var node_child_process = require('node:child_process');
|
|
21
22
|
require('chalk');
|
|
22
23
|
require('node:events');
|
|
23
24
|
require('axios');
|
|
@@ -25,11 +26,9 @@ require('tweetnacl');
|
|
|
25
26
|
require('open');
|
|
26
27
|
var React = require('react');
|
|
27
28
|
var ink = require('ink');
|
|
28
|
-
var
|
|
29
|
+
var ProviderSelectionHandler = require('./ProviderSelectionHandler-CO9NkAt6.cjs');
|
|
29
30
|
var types = require('./types-DVk3crez.cjs');
|
|
30
|
-
var registerKillSessionHandler = require('./registerKillSessionHandler-
|
|
31
|
-
var node_readline = require('node:readline');
|
|
32
|
-
var node_url = require('node:url');
|
|
31
|
+
var registerKillSessionHandler = require('./registerKillSessionHandler-eZ2TsHqx.cjs');
|
|
33
32
|
require('socket.io-client');
|
|
34
33
|
require('expo-server-sdk');
|
|
35
34
|
var node_util = require('node:util');
|
|
@@ -43,8 +42,8 @@ require('fastify');
|
|
|
43
42
|
require('fastify-type-provider-zod');
|
|
44
43
|
require('http');
|
|
45
44
|
require('util');
|
|
45
|
+
require('node:url');
|
|
46
46
|
|
|
47
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
48
47
|
class Session {
|
|
49
48
|
path;
|
|
50
49
|
logPath;
|
|
@@ -82,7 +81,7 @@ class Session {
|
|
|
82
81
|
this._onModeChange = opts.onModeChange;
|
|
83
82
|
this.hookSettingsPath = opts.hookSettingsPath;
|
|
84
83
|
this.jsRuntime = opts.jsRuntime ?? "node";
|
|
85
|
-
this.keepAliveController =
|
|
84
|
+
this.keepAliveController = ProviderSelectionHandler.createKeepAliveController({
|
|
86
85
|
initialMode: this.mode,
|
|
87
86
|
initialThinking: this.thinking,
|
|
88
87
|
send: (thinking, mode) => {
|
|
@@ -204,27 +203,6 @@ class Session {
|
|
|
204
203
|
};
|
|
205
204
|
}
|
|
206
205
|
|
|
207
|
-
class Future {
|
|
208
|
-
_resolve;
|
|
209
|
-
_reject;
|
|
210
|
-
_promise;
|
|
211
|
-
constructor() {
|
|
212
|
-
this._promise = new Promise((resolve, reject) => {
|
|
213
|
-
this._resolve = resolve;
|
|
214
|
-
this._reject = reject;
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
resolve(value) {
|
|
218
|
-
this._resolve(value);
|
|
219
|
-
}
|
|
220
|
-
reject(reason) {
|
|
221
|
-
this._reject(reason);
|
|
222
|
-
}
|
|
223
|
-
get promise() {
|
|
224
|
-
return this._promise;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
206
|
class InvalidateSync {
|
|
229
207
|
_invalidated = false;
|
|
230
208
|
_invalidatedDouble = false;
|
|
@@ -633,7 +611,7 @@ async function claudeLocalLauncher(session) {
|
|
|
633
611
|
session.addSessionFoundCallback(scannerSessionCallback);
|
|
634
612
|
let exitReason = null;
|
|
635
613
|
const processAbortController = new AbortController();
|
|
636
|
-
let exutFuture = new Future();
|
|
614
|
+
let exutFuture = new index.Future();
|
|
637
615
|
try {
|
|
638
616
|
async function abort() {
|
|
639
617
|
if (!processAbortController.signal.aborted) {
|
|
@@ -718,6 +696,50 @@ async function claudeLocalLauncher(session) {
|
|
|
718
696
|
return exitReason || { type: "exit", code: 0 };
|
|
719
697
|
}
|
|
720
698
|
|
|
699
|
+
function parseCompact(message) {
|
|
700
|
+
const trimmed = message.trim();
|
|
701
|
+
if (trimmed === "/compact") {
|
|
702
|
+
return {
|
|
703
|
+
isCompact: true,
|
|
704
|
+
originalMessage: trimmed
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
if (trimmed.startsWith("/compact ")) {
|
|
708
|
+
return {
|
|
709
|
+
isCompact: true,
|
|
710
|
+
originalMessage: trimmed
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
return {
|
|
714
|
+
isCompact: false,
|
|
715
|
+
originalMessage: message
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
function parseClear(message) {
|
|
719
|
+
const trimmed = message.trim();
|
|
720
|
+
return {
|
|
721
|
+
isClear: trimmed === "/clear"
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
function parseSpecialCommand(message) {
|
|
725
|
+
const compactResult = parseCompact(message);
|
|
726
|
+
if (compactResult.isCompact) {
|
|
727
|
+
return {
|
|
728
|
+
type: "compact",
|
|
729
|
+
originalMessage: compactResult.originalMessage
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
const clearResult = parseClear(message);
|
|
733
|
+
if (clearResult.isClear) {
|
|
734
|
+
return {
|
|
735
|
+
type: "clear"
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
return {
|
|
739
|
+
type: null
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
|
|
721
743
|
const RemoteModeDisplay = ({ messageBuffer, logPath, onExit, onSwitchToLocal }) => {
|
|
722
744
|
const [messages, setMessages] = React.useState([]);
|
|
723
745
|
const [confirmationMode, setConfirmationMode] = React.useState(null);
|
|
@@ -843,699 +865,593 @@ const RemoteModeDisplay = ({ messageBuffer, logPath, onExit, onSwitchToLocal })
|
|
|
843
865
|
));
|
|
844
866
|
};
|
|
845
867
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}
|
|
850
|
-
queue = [];
|
|
851
|
-
readResolve;
|
|
852
|
-
readReject;
|
|
853
|
-
isDone = false;
|
|
854
|
-
hasError;
|
|
855
|
-
started = false;
|
|
856
|
-
/**
|
|
857
|
-
* Implements async iterable protocol
|
|
858
|
-
*/
|
|
859
|
-
[Symbol.asyncIterator]() {
|
|
860
|
-
if (this.started) {
|
|
861
|
-
throw new Error("Stream can only be iterated once");
|
|
862
|
-
}
|
|
863
|
-
this.started = true;
|
|
864
|
-
return this;
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* Gets the next value from the stream
|
|
868
|
-
*/
|
|
869
|
-
async next() {
|
|
870
|
-
if (this.queue.length > 0) {
|
|
871
|
-
return Promise.resolve({
|
|
872
|
-
done: false,
|
|
873
|
-
value: this.queue.shift()
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
if (this.isDone) {
|
|
877
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
878
|
-
}
|
|
879
|
-
if (this.hasError) {
|
|
880
|
-
return Promise.reject(this.hasError);
|
|
881
|
-
}
|
|
882
|
-
return new Promise((resolve, reject) => {
|
|
883
|
-
this.readResolve = resolve;
|
|
884
|
-
this.readReject = reject;
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
/**
|
|
888
|
-
* Adds a value to the stream
|
|
889
|
-
*/
|
|
890
|
-
enqueue(value) {
|
|
891
|
-
if (this.readResolve) {
|
|
892
|
-
const resolve = this.readResolve;
|
|
893
|
-
this.readResolve = void 0;
|
|
894
|
-
this.readReject = void 0;
|
|
895
|
-
resolve({ done: false, value });
|
|
896
|
-
} else {
|
|
897
|
-
this.queue.push(value);
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
/**
|
|
901
|
-
* Marks the stream as complete
|
|
902
|
-
*/
|
|
903
|
-
done() {
|
|
904
|
-
this.isDone = true;
|
|
905
|
-
if (this.readResolve) {
|
|
906
|
-
const resolve = this.readResolve;
|
|
907
|
-
this.readResolve = void 0;
|
|
908
|
-
this.readReject = void 0;
|
|
909
|
-
resolve({ done: true, value: void 0 });
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
/**
|
|
913
|
-
* Propagates an error through the stream
|
|
914
|
-
*/
|
|
915
|
-
error(error) {
|
|
916
|
-
this.hasError = error;
|
|
917
|
-
if (this.readReject) {
|
|
918
|
-
const reject = this.readReject;
|
|
919
|
-
this.readResolve = void 0;
|
|
920
|
-
this.readReject = void 0;
|
|
921
|
-
reject(error);
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
/**
|
|
925
|
-
* Implements async iterator cleanup
|
|
926
|
-
*/
|
|
927
|
-
async return() {
|
|
928
|
-
this.isDone = true;
|
|
929
|
-
if (this.returned) {
|
|
930
|
-
this.returned();
|
|
931
|
-
}
|
|
932
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
class AbortError extends Error {
|
|
937
|
-
constructor(message) {
|
|
938
|
-
super(message);
|
|
939
|
-
this.name = "AbortError";
|
|
940
|
-
}
|
|
868
|
+
function getClaudeSettingsPath() {
|
|
869
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".claude");
|
|
870
|
+
return path.join(claudeConfigDir, "settings.json");
|
|
941
871
|
}
|
|
942
|
-
|
|
943
|
-
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runClaude-CDZxAF3l.cjs', document.baseURI).href)));
|
|
944
|
-
const __dirname$1 = path.join(__filename$1, "..");
|
|
945
|
-
function getGlobalClaudeVersion() {
|
|
872
|
+
function readClaudeSettings() {
|
|
946
873
|
try {
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
api.logger.debug(`[
|
|
956
|
-
return
|
|
957
|
-
} catch {
|
|
874
|
+
const settingsPath = getClaudeSettingsPath();
|
|
875
|
+
if (!fs$1.existsSync(settingsPath)) {
|
|
876
|
+
api.logger.debug(`[ClaudeSettings] No Claude settings file found at ${settingsPath}`);
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
const settingsContent = fs$1.readFileSync(settingsPath, "utf-8");
|
|
880
|
+
const settings = JSON.parse(settingsContent);
|
|
881
|
+
api.logger.debug(`[ClaudeSettings] Successfully read Claude settings from ${settingsPath}`);
|
|
882
|
+
api.logger.debug(`[ClaudeSettings] includeCoAuthoredBy: ${settings.includeCoAuthoredBy}`);
|
|
883
|
+
return settings;
|
|
884
|
+
} catch (error) {
|
|
885
|
+
api.logger.debug(`[ClaudeSettings] Error reading Claude settings: ${error}`);
|
|
958
886
|
return null;
|
|
959
887
|
}
|
|
960
888
|
}
|
|
961
|
-
function
|
|
962
|
-
const
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
const pathKey = process.platform === "win32" ? "Path" : "PATH";
|
|
966
|
-
const actualPathKey = Object.keys(env).find((k) => k.toLowerCase() === "path") || pathKey;
|
|
967
|
-
if (env[actualPathKey]) {
|
|
968
|
-
const cleanPath = env[actualPathKey].split(pathSep).filter((p) => {
|
|
969
|
-
const normalizedP = p.replace(/\\/g, "/").toLowerCase();
|
|
970
|
-
const normalizedCwd = cwd.replace(/\\/g, "/").toLowerCase();
|
|
971
|
-
return !normalizedP.startsWith(normalizedCwd);
|
|
972
|
-
}).join(pathSep);
|
|
973
|
-
env[actualPathKey] = cleanPath;
|
|
974
|
-
api.logger.debug(`[Claude SDK] Cleaned PATH, removed local paths from: ${cwd}`);
|
|
975
|
-
}
|
|
976
|
-
if (index.isBun()) {
|
|
977
|
-
Object.keys(env).forEach((key) => {
|
|
978
|
-
if (key.startsWith("BUN_")) {
|
|
979
|
-
delete env[key];
|
|
980
|
-
}
|
|
981
|
-
});
|
|
982
|
-
api.logger.debug("[Claude SDK] Removed Bun-specific environment variables for Node.js compatibility");
|
|
889
|
+
function shouldIncludeCoAuthoredBy() {
|
|
890
|
+
const settings = readClaudeSettings();
|
|
891
|
+
if (!settings || settings.includeCoAuthoredBy === void 0) {
|
|
892
|
+
return true;
|
|
983
893
|
}
|
|
984
|
-
return
|
|
894
|
+
return settings.includeCoAuthoredBy;
|
|
985
895
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}).trim();
|
|
1008
|
-
if (result && fs$1.existsSync(result)) {
|
|
1009
|
-
api.logger.debug(`[Claude SDK] Found global claude path via which: ${result}`);
|
|
1010
|
-
return result;
|
|
1011
|
-
}
|
|
1012
|
-
} catch {
|
|
1013
|
-
}
|
|
896
|
+
|
|
897
|
+
const BASE_SYSTEM_PROMPT = (() => index.trimIdent(`
|
|
898
|
+
Help human.
|
|
899
|
+
`))();
|
|
900
|
+
const CO_AUTHORED_CREDITS = (() => index.trimIdent(`
|
|
901
|
+
When making commit messages, instead of just giving co-credit to Claude, also give credit to Happy like so:
|
|
902
|
+
|
|
903
|
+
<main commit message>
|
|
904
|
+
|
|
905
|
+
Generated with [Claude Code](https://claude.ai/code)
|
|
906
|
+
via [Happy](https://happy.engineering)
|
|
907
|
+
|
|
908
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
909
|
+
Co-Authored-By: Happy <yesreply@happy.engineering>
|
|
910
|
+
`))();
|
|
911
|
+
const systemPrompt = (() => {
|
|
912
|
+
const includeCoAuthored = shouldIncludeCoAuthoredBy();
|
|
913
|
+
if (includeCoAuthored) {
|
|
914
|
+
return BASE_SYSTEM_PROMPT + "\n\n" + CO_AUTHORED_CREDITS;
|
|
915
|
+
} else {
|
|
916
|
+
return BASE_SYSTEM_PROMPT;
|
|
1014
917
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
function
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
api.logger.debug(`[Claude SDK] Using HAPPY_CLAUDE_PATH: ${process.env.HAPPY_CLAUDE_PATH}`);
|
|
1021
|
-
return process.env.HAPPY_CLAUDE_PATH;
|
|
1022
|
-
}
|
|
1023
|
-
if (process.env.HAPPY_USE_BUNDLED_CLAUDE === "1") {
|
|
1024
|
-
api.logger.debug(`[Claude SDK] Forced bundled version: ${nodeModulesPath}`);
|
|
1025
|
-
return nodeModulesPath;
|
|
1026
|
-
}
|
|
1027
|
-
const globalPath = findGlobalClaudePath();
|
|
1028
|
-
if (!globalPath) {
|
|
1029
|
-
api.logger.debug(`[Claude SDK] No global claude found, using bundled: ${nodeModulesPath}`);
|
|
1030
|
-
return nodeModulesPath;
|
|
1031
|
-
}
|
|
1032
|
-
const globalVersion = getGlobalClaudeVersion();
|
|
1033
|
-
api.logger.debug(`[Claude SDK] Global version: ${globalVersion || "unknown"}`);
|
|
1034
|
-
if (!globalVersion) {
|
|
1035
|
-
api.logger.debug(`[Claude SDK] Cannot compare versions, using global: ${globalPath}`);
|
|
1036
|
-
return globalPath;
|
|
1037
|
-
}
|
|
1038
|
-
return globalPath;
|
|
1039
|
-
}
|
|
1040
|
-
function logDebug(message) {
|
|
1041
|
-
if (process.env.DEBUG) {
|
|
1042
|
-
api.logger.debug(message);
|
|
1043
|
-
console.log(message);
|
|
918
|
+
})();
|
|
919
|
+
|
|
920
|
+
function getToolDescriptor(toolName) {
|
|
921
|
+
if (toolName === "exit_plan_mode" || toolName === "ExitPlanMode") {
|
|
922
|
+
return { edit: false, exitPlan: true };
|
|
1044
923
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
for await (const message of stream) {
|
|
1048
|
-
if (abort?.aborted) break;
|
|
1049
|
-
stdin.write(JSON.stringify(message) + "\n");
|
|
924
|
+
if (toolName === "Edit" || toolName === "MultiEdit" || toolName === "Write" || toolName === "NotebookEdit") {
|
|
925
|
+
return { edit: true, exitPlan: false };
|
|
1050
926
|
}
|
|
1051
|
-
|
|
927
|
+
return { edit: false, exitPlan: false };
|
|
1052
928
|
}
|
|
1053
929
|
|
|
1054
|
-
class
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
this.processExitPromise = processExitPromise;
|
|
1059
|
-
this.canCallTool = canCallTool;
|
|
1060
|
-
this.readMessages();
|
|
1061
|
-
this.sdkMessages = this.readSdkMessages();
|
|
1062
|
-
}
|
|
1063
|
-
pendingControlResponses = /* @__PURE__ */ new Map();
|
|
1064
|
-
cancelControllers = /* @__PURE__ */ new Map();
|
|
1065
|
-
sdkMessages;
|
|
1066
|
-
inputStream = new Stream();
|
|
1067
|
-
canCallTool;
|
|
1068
|
-
/**
|
|
1069
|
-
* Set an error on the stream
|
|
1070
|
-
*/
|
|
1071
|
-
setError(error) {
|
|
1072
|
-
this.inputStream.error(error);
|
|
930
|
+
class ClaudeAcpPermissionHandler extends registerKillSessionHandler.BasePermissionHandler {
|
|
931
|
+
currentPermissionMode = "default";
|
|
932
|
+
constructor(session) {
|
|
933
|
+
super(session);
|
|
1073
934
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
*/
|
|
1077
|
-
next(...args) {
|
|
1078
|
-
return this.sdkMessages.next(...args);
|
|
935
|
+
getLogPrefix() {
|
|
936
|
+
return "[ClaudeACP]";
|
|
1079
937
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
}
|
|
1084
|
-
return Promise.resolve({ done: true, value: void 0 });
|
|
938
|
+
setPermissionMode(mode) {
|
|
939
|
+
this.currentPermissionMode = mode;
|
|
940
|
+
api.logger.debug(`${this.getLogPrefix()} Permission mode set to: ${mode}`);
|
|
1085
941
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
942
|
+
shouldAutoApprove(toolName) {
|
|
943
|
+
const descriptor = getToolDescriptor(toolName);
|
|
944
|
+
switch (this.currentPermissionMode) {
|
|
945
|
+
case "bypassPermissions":
|
|
946
|
+
case "yolo":
|
|
947
|
+
return true;
|
|
948
|
+
case "acceptEdits":
|
|
949
|
+
return descriptor.edit;
|
|
950
|
+
default:
|
|
951
|
+
return false;
|
|
1089
952
|
}
|
|
1090
|
-
return Promise.reject(e);
|
|
1091
953
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
const controlResponse = message;
|
|
1107
|
-
const handler = this.pendingControlResponses.get(controlResponse.response.request_id);
|
|
1108
|
-
if (handler) {
|
|
1109
|
-
handler(controlResponse.response);
|
|
1110
|
-
}
|
|
1111
|
-
continue;
|
|
1112
|
-
} else if (message.type === "control_request") {
|
|
1113
|
-
await this.handleControlRequest(message);
|
|
1114
|
-
continue;
|
|
1115
|
-
} else if (message.type === "control_cancel_request") {
|
|
1116
|
-
this.handleControlCancelRequest(message);
|
|
1117
|
-
continue;
|
|
1118
|
-
}
|
|
1119
|
-
this.inputStream.enqueue(message);
|
|
1120
|
-
} catch (e) {
|
|
1121
|
-
api.logger.debug(line);
|
|
954
|
+
async handleToolCall(toolCallId, toolName, input) {
|
|
955
|
+
if (this.shouldAutoApprove(toolName)) {
|
|
956
|
+
const decision = this.currentPermissionMode === "bypassPermissions" || this.currentPermissionMode === "yolo" ? "approved_for_session" : "approved";
|
|
957
|
+
this.session.updateAgentState((currentState) => ({
|
|
958
|
+
...currentState,
|
|
959
|
+
completedRequests: {
|
|
960
|
+
...currentState.completedRequests,
|
|
961
|
+
[toolCallId]: {
|
|
962
|
+
tool: toolName,
|
|
963
|
+
arguments: input,
|
|
964
|
+
createdAt: Date.now(),
|
|
965
|
+
completedAt: Date.now(),
|
|
966
|
+
status: "approved",
|
|
967
|
+
decision
|
|
1122
968
|
}
|
|
1123
969
|
}
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
this.inputStream.error(error);
|
|
1128
|
-
} finally {
|
|
1129
|
-
this.inputStream.done();
|
|
1130
|
-
this.cleanupControllers();
|
|
1131
|
-
rl.close();
|
|
970
|
+
}));
|
|
971
|
+
api.logger.debug(`${this.getLogPrefix()} Auto-approved tool ${toolName} (${toolCallId}) in ${this.currentPermissionMode} mode`);
|
|
972
|
+
return { decision };
|
|
1132
973
|
}
|
|
974
|
+
return this.registerPendingRequest(
|
|
975
|
+
toolCallId,
|
|
976
|
+
toolName,
|
|
977
|
+
input,
|
|
978
|
+
` in ${this.currentPermissionMode} mode`
|
|
979
|
+
);
|
|
1133
980
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function normalizeClaudeBackendError(error) {
|
|
984
|
+
const record = typeof error === "object" && error !== null ? error : null;
|
|
985
|
+
const text = index.formatDisplayMessage(error).trim();
|
|
986
|
+
const stderrText = record ? index.formatDisplayMessage(record.stderr).trim() : "";
|
|
987
|
+
const detailText = record ? index.formatDisplayMessage(record.detail).trim() : "";
|
|
988
|
+
const searchable = [text, stderrText, detailText].filter(Boolean).join("\n").trim();
|
|
989
|
+
return searchable || "Claude ACP backend exited unexpectedly";
|
|
990
|
+
}
|
|
991
|
+
const CLAUDE_ACP_LEGACY_FINAL_MESSAGE_SHADOW = "claude-acp-final-message-shadow";
|
|
992
|
+
async function claudeAcpRemoteLauncher(session) {
|
|
993
|
+
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
994
|
+
const messageBuffer = new registerKillSessionHandler.MessageBuffer({ enabled: hasTTY });
|
|
995
|
+
let inkInstance = null;
|
|
996
|
+
let shouldExit = false;
|
|
997
|
+
let abortController = new AbortController();
|
|
998
|
+
let runtimeHandle = null;
|
|
999
|
+
let unsubscribeRuntimeMessages = null;
|
|
1000
|
+
let currentModeHash = null;
|
|
1001
|
+
let pending = null;
|
|
1002
|
+
let accumulatedResponse = "";
|
|
1003
|
+
let isResponseInProgress = false;
|
|
1004
|
+
let taskStartedSent = false;
|
|
1005
|
+
let currentAssistantMessageId = null;
|
|
1006
|
+
let currentThinkingMessageId = null;
|
|
1007
|
+
let shouldInjectHistoryOnNextSession = false;
|
|
1008
|
+
let readyAlreadySent = false;
|
|
1009
|
+
const permissionHandler = new ClaudeAcpPermissionHandler(session.client);
|
|
1010
|
+
const selectionHandler = new ProviderSelectionHandler.ProviderSelectionHandler(session.client, "Claude");
|
|
1011
|
+
const conversationHistory = new registerKillSessionHandler.ConversationHistory({
|
|
1012
|
+
maxMessages: 20,
|
|
1013
|
+
maxCharacters: 5e4
|
|
1014
|
+
});
|
|
1015
|
+
const rotateAbortController = () => {
|
|
1016
|
+
const activeController = abortController;
|
|
1017
|
+
abortController = new AbortController();
|
|
1018
|
+
return activeController;
|
|
1019
|
+
};
|
|
1020
|
+
const sendReady = () => {
|
|
1021
|
+
session.client.sendSessionEvent({ type: "ready" });
|
|
1022
|
+
try {
|
|
1023
|
+
session.api.push().sendToAllDevices(
|
|
1024
|
+
"It's ready!",
|
|
1025
|
+
"Claude is waiting for your command",
|
|
1026
|
+
{ sessionId: session.client.sessionId }
|
|
1027
|
+
);
|
|
1028
|
+
} catch (pushError) {
|
|
1029
|
+
api.logger.debug("[ClaudeACP] Failed to send ready push", pushError);
|
|
1140
1030
|
}
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1031
|
+
};
|
|
1032
|
+
const emitStatusMessage = (message) => {
|
|
1033
|
+
messageBuffer.addMessage(message, "status");
|
|
1034
|
+
session.client.sendSessionEvent({ type: "message", message });
|
|
1035
|
+
};
|
|
1036
|
+
const emitUserVisibleErrorMessage = (message) => {
|
|
1037
|
+
emitStatusMessage(message);
|
|
1038
|
+
session.client.sendAgentMessage("claude", {
|
|
1039
|
+
type: "message",
|
|
1040
|
+
message
|
|
1041
|
+
});
|
|
1042
|
+
};
|
|
1043
|
+
const resetTurnState = () => {
|
|
1044
|
+
accumulatedResponse = "";
|
|
1045
|
+
isResponseInProgress = false;
|
|
1046
|
+
taskStartedSent = false;
|
|
1047
|
+
currentAssistantMessageId = null;
|
|
1048
|
+
currentThinkingMessageId = null;
|
|
1049
|
+
session.onThinkingChange(false);
|
|
1050
|
+
};
|
|
1051
|
+
const emitFinalAssistantMessage = () => {
|
|
1052
|
+
const finalMessage = accumulatedResponse.trim();
|
|
1053
|
+
if (!finalMessage) {
|
|
1054
|
+
accumulatedResponse = "";
|
|
1055
|
+
isResponseInProgress = false;
|
|
1056
|
+
return;
|
|
1148
1057
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
/**
|
|
1154
|
-
* Send control request to Claude process
|
|
1155
|
-
*/
|
|
1156
|
-
request(request, childStdin) {
|
|
1157
|
-
const requestId = Math.random().toString(36).substring(2, 15);
|
|
1158
|
-
const sdkRequest = {
|
|
1159
|
-
request_id: requestId,
|
|
1160
|
-
type: "control_request",
|
|
1161
|
-
request
|
|
1162
|
-
};
|
|
1163
|
-
return new Promise((resolve, reject) => {
|
|
1164
|
-
this.pendingControlResponses.set(requestId, (response) => {
|
|
1165
|
-
if (response.subtype === "success") {
|
|
1166
|
-
resolve(response);
|
|
1167
|
-
} else {
|
|
1168
|
-
reject(new Error(response.error));
|
|
1169
|
-
}
|
|
1170
|
-
});
|
|
1171
|
-
childStdin.write(JSON.stringify(sdkRequest) + "\n");
|
|
1058
|
+
conversationHistory.addAssistantMessage(finalMessage);
|
|
1059
|
+
session.client.sendAgentMessage("claude", {
|
|
1060
|
+
type: "message",
|
|
1061
|
+
message: finalMessage
|
|
1172
1062
|
});
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1063
|
+
session.client.sendClaudeSessionMessage({
|
|
1064
|
+
type: "assistant",
|
|
1065
|
+
uuid: node_crypto.randomUUID(),
|
|
1066
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1067
|
+
sessionId: session.sessionId ?? void 0,
|
|
1068
|
+
happyCompatibilityShadow: CLAUDE_ACP_LEGACY_FINAL_MESSAGE_SHADOW,
|
|
1069
|
+
message: {
|
|
1070
|
+
role: "assistant",
|
|
1071
|
+
content: [{
|
|
1072
|
+
type: "text",
|
|
1073
|
+
text: finalMessage,
|
|
1074
|
+
happyCompatibilityShadow: CLAUDE_ACP_LEGACY_FINAL_MESSAGE_SHADOW
|
|
1075
|
+
}]
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
accumulatedResponse = "";
|
|
1079
|
+
isResponseInProgress = false;
|
|
1080
|
+
};
|
|
1081
|
+
const disposeRuntimeHandle = async () => {
|
|
1082
|
+
if (!runtimeHandle) {
|
|
1181
1083
|
return;
|
|
1182
1084
|
}
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1085
|
+
const activeHandle = runtimeHandle;
|
|
1086
|
+
runtimeHandle = null;
|
|
1087
|
+
unsubscribeRuntimeMessages?.();
|
|
1088
|
+
unsubscribeRuntimeMessages = null;
|
|
1185
1089
|
try {
|
|
1186
|
-
|
|
1187
|
-
const controlResponse = {
|
|
1188
|
-
type: "control_response",
|
|
1189
|
-
response: {
|
|
1190
|
-
subtype: "success",
|
|
1191
|
-
request_id: request.request_id,
|
|
1192
|
-
response
|
|
1193
|
-
}
|
|
1194
|
-
};
|
|
1195
|
-
this.childStdin.write(JSON.stringify(controlResponse) + "\n");
|
|
1090
|
+
await activeHandle.dispose();
|
|
1196
1091
|
} catch (error) {
|
|
1197
|
-
|
|
1198
|
-
type: "control_response",
|
|
1199
|
-
response: {
|
|
1200
|
-
subtype: "error",
|
|
1201
|
-
request_id: request.request_id,
|
|
1202
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1203
|
-
}
|
|
1204
|
-
};
|
|
1205
|
-
this.childStdin.write(JSON.stringify(controlErrorResponse) + "\n");
|
|
1206
|
-
} finally {
|
|
1207
|
-
this.cancelControllers.delete(request.request_id);
|
|
1092
|
+
api.logger.debug("[ClaudeACP] Error disposing runtime handle:", error);
|
|
1208
1093
|
}
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
this.cancelControllers.delete(request.request_id);
|
|
1094
|
+
};
|
|
1095
|
+
const queueHistoryInjectionForRestart = (reason) => {
|
|
1096
|
+
messageBuffer.addMessage("\u2550".repeat(40), "status");
|
|
1097
|
+
if (conversationHistory.hasHistory()) {
|
|
1098
|
+
shouldInjectHistoryOnNextSession = true;
|
|
1099
|
+
const message = `${reason} Preserving ${conversationHistory.size()} earlier messages of context.`;
|
|
1100
|
+
emitStatusMessage(message);
|
|
1101
|
+
api.logger.debug(`[ClaudeACP] Will inject conversation history after restart: ${conversationHistory.getSummary()}`);
|
|
1102
|
+
return;
|
|
1219
1103
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
if (!this.canCallTool) {
|
|
1228
|
-
throw new Error("canCallTool callback is not provided.");
|
|
1229
|
-
}
|
|
1230
|
-
return this.canCallTool(request.request.tool_name, request.request.input, {
|
|
1231
|
-
signal
|
|
1104
|
+
emitStatusMessage(reason);
|
|
1105
|
+
};
|
|
1106
|
+
const setupRuntimeMessageHandler = (activeRuntimeHandle) => {
|
|
1107
|
+
const forwardAgentMessage = (agentMessage) => {
|
|
1108
|
+
registerKillSessionHandler.forwardAgentMessageToProviderSession(agentMessage, {
|
|
1109
|
+
provider: "claude",
|
|
1110
|
+
send: (body) => session.client.sendAgentMessage("claude", body)
|
|
1232
1111
|
});
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1112
|
+
};
|
|
1113
|
+
unsubscribeRuntimeMessages?.();
|
|
1114
|
+
unsubscribeRuntimeMessages = activeRuntimeHandle.onMessage((msg) => {
|
|
1115
|
+
switch (msg.type) {
|
|
1116
|
+
case "model-output": {
|
|
1117
|
+
const text = msg.textDelta ?? msg.fullText ?? "";
|
|
1118
|
+
if (!text) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
if (!isResponseInProgress) {
|
|
1122
|
+
if (currentThinkingMessageId) {
|
|
1123
|
+
messageBuffer.removeMessage(currentThinkingMessageId);
|
|
1124
|
+
currentThinkingMessageId = null;
|
|
1125
|
+
}
|
|
1126
|
+
currentAssistantMessageId = messageBuffer.addMessage(text, "assistant");
|
|
1127
|
+
isResponseInProgress = true;
|
|
1128
|
+
} else if (currentAssistantMessageId) {
|
|
1129
|
+
const updated = messageBuffer.updateMessage(currentAssistantMessageId, text);
|
|
1130
|
+
if (!updated) {
|
|
1131
|
+
currentAssistantMessageId = messageBuffer.addMessage(text, "assistant");
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
accumulatedResponse += text;
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
case "status": {
|
|
1138
|
+
if (msg.status === "running") {
|
|
1139
|
+
session.onThinkingChange(true);
|
|
1140
|
+
if (!taskStartedSent) {
|
|
1141
|
+
session.client.sendAgentMessage("claude", {
|
|
1142
|
+
type: "task_started",
|
|
1143
|
+
id: node_crypto.randomUUID()
|
|
1144
|
+
});
|
|
1145
|
+
taskStartedSent = true;
|
|
1146
|
+
}
|
|
1147
|
+
if (!isResponseInProgress && !currentThinkingMessageId) {
|
|
1148
|
+
currentThinkingMessageId = messageBuffer.addMessage("Thinking...", "system");
|
|
1149
|
+
}
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
if (msg.status === "idle" || msg.status === "stopped") {
|
|
1153
|
+
session.onThinkingChange(false);
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
if (msg.status === "error") {
|
|
1157
|
+
messageBuffer.addMessage(`Error: ${normalizeClaudeBackendError(msg.detail)}`, "status");
|
|
1158
|
+
}
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
case "tool-call": {
|
|
1162
|
+
const toolArgs = index.truncateDisplayMessage(msg.args, 100);
|
|
1163
|
+
messageBuffer.addMessage(
|
|
1164
|
+
`Executing: ${msg.toolName}${toolArgs ? ` ${toolArgs}` : ""}`,
|
|
1165
|
+
"tool"
|
|
1166
|
+
);
|
|
1167
|
+
forwardAgentMessage(msg);
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
case "tool-result": {
|
|
1171
|
+
const resultText = index.truncateDisplayMessage(msg.result, 200);
|
|
1172
|
+
messageBuffer.addMessage(resultText ? `Result: ${resultText}` : "Tool completed", "result");
|
|
1173
|
+
forwardAgentMessage(msg);
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
case "fs-edit": {
|
|
1177
|
+
messageBuffer.addMessage(`File edit: ${msg.description}`, "tool");
|
|
1178
|
+
forwardAgentMessage(msg);
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
case "terminal-output": {
|
|
1182
|
+
const output = index.formatDisplayMessage(msg.data);
|
|
1183
|
+
messageBuffer.addMessage(output, "result");
|
|
1184
|
+
forwardAgentMessage({
|
|
1185
|
+
...msg,
|
|
1186
|
+
data: output
|
|
1187
|
+
});
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
case "permission-request": {
|
|
1191
|
+
forwardAgentMessage(msg);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
case "token-count": {
|
|
1195
|
+
forwardAgentMessage(msg);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
case "exec-approval-request":
|
|
1199
|
+
case "patch-apply-begin":
|
|
1200
|
+
case "patch-apply-end": {
|
|
1201
|
+
forwardAgentMessage(msg);
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
case "event": {
|
|
1205
|
+
if (msg.name === "thinking") {
|
|
1206
|
+
const payload = msg.payload;
|
|
1207
|
+
const thinkingText = typeof payload?.text === "string" ? payload.text : "";
|
|
1208
|
+
if (thinkingText) {
|
|
1209
|
+
session.client.sendAgentMessage("claude", {
|
|
1210
|
+
type: "thinking",
|
|
1211
|
+
text: thinkingText
|
|
1212
|
+
});
|
|
1213
|
+
if (!isResponseInProgress) {
|
|
1214
|
+
const preview = `[Thinking] ${thinkingText.substring(0, 100)}...`;
|
|
1215
|
+
if (currentThinkingMessageId) {
|
|
1216
|
+
messageBuffer.updateMessage(currentThinkingMessageId, preview, { mode: "replace" });
|
|
1217
|
+
} else {
|
|
1218
|
+
currentThinkingMessageId = messageBuffer.addMessage(preview, "system");
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
default:
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1332
1228
|
});
|
|
1333
|
-
}
|
|
1334
|
-
const cleanup = () => {
|
|
1335
|
-
if (!child.killed) {
|
|
1336
|
-
child.kill("SIGTERM");
|
|
1337
|
-
}
|
|
1338
1229
|
};
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1230
|
+
const createRuntimeHandle = async (mode) => {
|
|
1231
|
+
const { session: nextRuntimeHandle, factoryResult } = await registerKillSessionHandler.launchRuntimeHandleWithFactoryResult({
|
|
1232
|
+
provider: "claude",
|
|
1233
|
+
cwd: session.path,
|
|
1234
|
+
createBackendResult: (opts) => index.createClaudeBackend({
|
|
1235
|
+
...opts,
|
|
1236
|
+
baseArgs: session.claudeArgs,
|
|
1237
|
+
mcpServers: session.mcpServers,
|
|
1238
|
+
permissionHandler,
|
|
1239
|
+
permissionMode: mode.permissionMode,
|
|
1240
|
+
model: mode.model,
|
|
1241
|
+
fallbackModel: mode.fallbackModel,
|
|
1242
|
+
customSystemPrompt: mode.customSystemPrompt ? `${mode.customSystemPrompt}
|
|
1243
|
+
|
|
1244
|
+
${systemPrompt}` : void 0,
|
|
1245
|
+
appendSystemPrompt: mode.appendSystemPrompt ? `${mode.appendSystemPrompt}
|
|
1246
|
+
|
|
1247
|
+
${systemPrompt}` : systemPrompt,
|
|
1248
|
+
allowedTools: mode.allowedTools ? mode.allowedTools.concat(session.allowedTools ?? []) : session.allowedTools,
|
|
1249
|
+
disallowedTools: mode.disallowedTools,
|
|
1250
|
+
settingsPath: session.hookSettingsPath
|
|
1251
|
+
})
|
|
1351
1252
|
});
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1253
|
+
api.logger.debug("[ClaudeACP] Started Claude ACP backend", {
|
|
1254
|
+
command: factoryResult.command,
|
|
1255
|
+
args: factoryResult.args
|
|
1256
|
+
});
|
|
1257
|
+
runtimeHandle = nextRuntimeHandle;
|
|
1258
|
+
setupRuntimeMessageHandler(nextRuntimeHandle);
|
|
1259
|
+
session.consumeOneTimeFlags();
|
|
1260
|
+
return nextRuntimeHandle;
|
|
1261
|
+
};
|
|
1262
|
+
const abortActiveTurn = async () => {
|
|
1263
|
+
const activeController = rotateAbortController();
|
|
1264
|
+
activeController.abort();
|
|
1265
|
+
session.onThinkingChange(false);
|
|
1266
|
+
if (runtimeHandle) {
|
|
1267
|
+
await runtimeHandle.cancel().catch((error) => {
|
|
1268
|
+
api.logger.debug("[ClaudeACP] Error cancelling runtime handle:", error);
|
|
1269
|
+
});
|
|
1366
1270
|
}
|
|
1367
|
-
});
|
|
1368
|
-
return query2;
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
function parseCompact(message) {
|
|
1372
|
-
const trimmed = message.trim();
|
|
1373
|
-
if (trimmed === "/compact") {
|
|
1374
|
-
return {
|
|
1375
|
-
isCompact: true,
|
|
1376
|
-
originalMessage: trimmed
|
|
1377
|
-
};
|
|
1378
|
-
}
|
|
1379
|
-
if (trimmed.startsWith("/compact ")) {
|
|
1380
|
-
return {
|
|
1381
|
-
isCompact: true,
|
|
1382
|
-
originalMessage: trimmed
|
|
1383
|
-
};
|
|
1384
|
-
}
|
|
1385
|
-
return {
|
|
1386
|
-
isCompact: false,
|
|
1387
|
-
originalMessage: message
|
|
1388
1271
|
};
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1272
|
+
const completeSyntheticTurn = () => {
|
|
1273
|
+
session.client.sendAgentMessage("claude", {
|
|
1274
|
+
type: "task_complete",
|
|
1275
|
+
id: node_crypto.randomUUID()
|
|
1276
|
+
});
|
|
1394
1277
|
};
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
type: "clear"
|
|
1408
|
-
};
|
|
1409
|
-
}
|
|
1410
|
-
return {
|
|
1411
|
-
type: null
|
|
1278
|
+
const handleClearCommand = async () => {
|
|
1279
|
+
api.logger.debug("[ClaudeACP] /clear command received - resetting runtime and local history");
|
|
1280
|
+
conversationHistory.clear();
|
|
1281
|
+
shouldInjectHistoryOnNextSession = false;
|
|
1282
|
+
await disposeRuntimeHandle();
|
|
1283
|
+
session.clearSessionId();
|
|
1284
|
+
currentModeHash = null;
|
|
1285
|
+
permissionHandler.reset();
|
|
1286
|
+
selectionHandler.reset();
|
|
1287
|
+
resetTurnState();
|
|
1288
|
+
emitStatusMessage("Context was reset");
|
|
1289
|
+
completeSyntheticTurn();
|
|
1412
1290
|
};
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
/**
|
|
1441
|
-
* Mark the iterable as complete
|
|
1442
|
-
*/
|
|
1443
|
-
end() {
|
|
1444
|
-
if (this.isDone) {
|
|
1445
|
-
return;
|
|
1446
|
-
}
|
|
1447
|
-
this.isDone = true;
|
|
1448
|
-
this.cleanup();
|
|
1291
|
+
const handleSwitchToLocal = async () => {
|
|
1292
|
+
const message = "Daemon-spawned Claude ACP sessions stay in remote mode.";
|
|
1293
|
+
api.logger.debug("[ClaudeACP] Ignoring switch request because daemon sessions are remote-only");
|
|
1294
|
+
emitStatusMessage(message);
|
|
1295
|
+
};
|
|
1296
|
+
const handleAbort = async () => {
|
|
1297
|
+
api.logger.debug("[ClaudeACP] Abort requested - stopping current task");
|
|
1298
|
+
await abortActiveTurn();
|
|
1299
|
+
};
|
|
1300
|
+
if (hasTTY) {
|
|
1301
|
+
console.clear();
|
|
1302
|
+
inkInstance = ink.render(React.createElement(RemoteModeDisplay, {
|
|
1303
|
+
messageBuffer,
|
|
1304
|
+
logPath: process.env.DEBUG ? session.logPath : void 0,
|
|
1305
|
+
onExit: async () => {
|
|
1306
|
+
shouldExit = true;
|
|
1307
|
+
await handleAbort();
|
|
1308
|
+
},
|
|
1309
|
+
onSwitchToLocal: () => {
|
|
1310
|
+
void handleSwitchToLocal();
|
|
1311
|
+
}
|
|
1312
|
+
}), {
|
|
1313
|
+
exitOnCtrlC: false,
|
|
1314
|
+
patchConsole: false
|
|
1315
|
+
});
|
|
1449
1316
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
if (this.isDone) {
|
|
1455
|
-
return;
|
|
1317
|
+
if (hasTTY) {
|
|
1318
|
+
process.stdin.resume();
|
|
1319
|
+
if (process.stdin.isTTY) {
|
|
1320
|
+
process.stdin.setRawMode(true);
|
|
1456
1321
|
}
|
|
1457
|
-
|
|
1458
|
-
this.isDone = true;
|
|
1459
|
-
this.cleanup();
|
|
1322
|
+
process.stdin.setEncoding("utf8");
|
|
1460
1323
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
if (
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1324
|
+
session.client.rpcHandlerManager.registerHandler("abort", handleAbort);
|
|
1325
|
+
session.client.rpcHandlerManager.registerHandler("switch", handleSwitchToLocal);
|
|
1326
|
+
try {
|
|
1327
|
+
while (!shouldExit) {
|
|
1328
|
+
let message = pending;
|
|
1329
|
+
pending = null;
|
|
1330
|
+
if (!message) {
|
|
1331
|
+
const waitSignal = abortController.signal;
|
|
1332
|
+
const batch = await session.queue.waitForMessagesAndGetAsString(waitSignal);
|
|
1333
|
+
if (!batch) {
|
|
1334
|
+
if (waitSignal.aborted && !shouldExit) {
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
1337
|
+
break;
|
|
1338
|
+
}
|
|
1339
|
+
message = batch;
|
|
1340
|
+
}
|
|
1341
|
+
if (!message) {
|
|
1342
|
+
break;
|
|
1343
|
+
}
|
|
1344
|
+
if (runtimeHandle && currentModeHash && message.hash !== currentModeHash) {
|
|
1345
|
+
queueHistoryInjectionForRestart("Starting new Claude ACP session (execution settings changed)...");
|
|
1346
|
+
await disposeRuntimeHandle();
|
|
1347
|
+
session.clearSessionId();
|
|
1348
|
+
currentModeHash = null;
|
|
1349
|
+
pending = message;
|
|
1350
|
+
permissionHandler.reset();
|
|
1351
|
+
selectionHandler.reset();
|
|
1352
|
+
resetTurnState();
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
currentModeHash = message.hash;
|
|
1356
|
+
readyAlreadySent = false;
|
|
1357
|
+
const specialCommand = parseSpecialCommand(message.message);
|
|
1358
|
+
if (specialCommand.type === "clear") {
|
|
1359
|
+
await handleClearCommand();
|
|
1360
|
+
if (!shouldExit && !pending && session.queue.size() === 0 && !readyAlreadySent) {
|
|
1361
|
+
sendReady();
|
|
1362
|
+
readyAlreadySent = true;
|
|
1363
|
+
}
|
|
1364
|
+
continue;
|
|
1365
|
+
}
|
|
1366
|
+
permissionHandler.setPermissionMode(message.mode.permissionMode);
|
|
1367
|
+
messageBuffer.addMessage(message.message, "user");
|
|
1368
|
+
let shouldClearHistoryAfterTurn = false;
|
|
1369
|
+
try {
|
|
1370
|
+
const activeRuntimeHandle = runtimeHandle ?? await createRuntimeHandle(message.mode);
|
|
1371
|
+
let promptToSend = message.message;
|
|
1372
|
+
if (shouldInjectHistoryOnNextSession && conversationHistory.hasHistory()) {
|
|
1373
|
+
const historyContext = conversationHistory.getContextForNewSession(
|
|
1374
|
+
"Continue from the prior Claude ACP session using the conversation below as context."
|
|
1375
|
+
);
|
|
1376
|
+
promptToSend = historyContext + promptToSend;
|
|
1377
|
+
api.logger.debug(`[ClaudeACP] Injected conversation history context (${historyContext.length} chars)`);
|
|
1378
|
+
}
|
|
1379
|
+
if (specialCommand.type === "compact") {
|
|
1380
|
+
emitStatusMessage("Compaction started");
|
|
1381
|
+
}
|
|
1382
|
+
conversationHistory.addUserMessage(message.message);
|
|
1383
|
+
await activeRuntimeHandle.sendPrompt(promptToSend);
|
|
1384
|
+
await registerKillSessionHandler.waitForResponseCompleteWithAbort(activeRuntimeHandle.backend, abortController.signal);
|
|
1385
|
+
shouldInjectHistoryOnNextSession = false;
|
|
1386
|
+
shouldClearHistoryAfterTurn = specialCommand.type === "compact";
|
|
1387
|
+
} catch (error) {
|
|
1388
|
+
api.logger.warn("[ClaudeACP] Error in Claude ACP session:", error);
|
|
1389
|
+
const isAbortError = error instanceof Error && error.name === "AbortError";
|
|
1390
|
+
const isExpectedInterruption = isAbortError || abortController.signal.aborted || shouldExit;
|
|
1391
|
+
if (isExpectedInterruption) {
|
|
1392
|
+
session.client.sendAgentMessage("claude", {
|
|
1393
|
+
type: "turn_aborted",
|
|
1394
|
+
id: node_crypto.randomUUID()
|
|
1395
|
+
});
|
|
1396
|
+
emitStatusMessage("Aborted by user");
|
|
1397
|
+
} else {
|
|
1398
|
+
const errorMessage = normalizeClaudeBackendError(error);
|
|
1399
|
+
emitUserVisibleErrorMessage(errorMessage);
|
|
1400
|
+
if (conversationHistory.hasHistory()) {
|
|
1401
|
+
shouldInjectHistoryOnNextSession = true;
|
|
1402
|
+
}
|
|
1403
|
+
await disposeRuntimeHandle();
|
|
1404
|
+
session.clearSessionId();
|
|
1405
|
+
currentModeHash = null;
|
|
1406
|
+
}
|
|
1407
|
+
} finally {
|
|
1408
|
+
emitFinalAssistantMessage();
|
|
1409
|
+
if (shouldClearHistoryAfterTurn) {
|
|
1410
|
+
conversationHistory.clear();
|
|
1411
|
+
emitStatusMessage("Compaction completed");
|
|
1412
|
+
}
|
|
1413
|
+
if (!shouldExit) {
|
|
1414
|
+
session.client.sendAgentMessage("claude", {
|
|
1415
|
+
type: "task_complete",
|
|
1416
|
+
id: node_crypto.randomUUID()
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
permissionHandler.reset();
|
|
1420
|
+
selectionHandler.reset();
|
|
1421
|
+
resetTurnState();
|
|
1422
|
+
if (!shouldExit && !pending && session.queue.size() === 0 && !readyAlreadySent) {
|
|
1423
|
+
sendReady();
|
|
1424
|
+
readyAlreadySent = true;
|
|
1425
|
+
}
|
|
1471
1426
|
}
|
|
1472
1427
|
}
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1428
|
+
} finally {
|
|
1429
|
+
await disposeRuntimeHandle();
|
|
1430
|
+
permissionHandler.reset();
|
|
1431
|
+
selectionHandler.reset();
|
|
1432
|
+
if (process.stdin.isTTY) {
|
|
1433
|
+
try {
|
|
1434
|
+
process.stdin.setRawMode(false);
|
|
1435
|
+
} catch {
|
|
1436
|
+
}
|
|
1480
1437
|
}
|
|
1481
|
-
if (
|
|
1482
|
-
|
|
1483
|
-
|
|
1438
|
+
if (hasTTY) {
|
|
1439
|
+
try {
|
|
1440
|
+
process.stdin.pause();
|
|
1441
|
+
} catch {
|
|
1484
1442
|
}
|
|
1485
|
-
return { done: true, value: void 0 };
|
|
1486
1443
|
}
|
|
1487
|
-
|
|
1488
|
-
this.waiters.push({ resolve, reject });
|
|
1444
|
+
session.client.rpcHandlerManager.registerHandler("abort", async () => {
|
|
1489
1445
|
});
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
async return(_value) {
|
|
1495
|
-
this.end();
|
|
1496
|
-
return { done: true, value: void 0 };
|
|
1497
|
-
}
|
|
1498
|
-
/**
|
|
1499
|
-
* AsyncIterableIterator throw implementation
|
|
1500
|
-
*/
|
|
1501
|
-
async throw(e) {
|
|
1502
|
-
this.setError(e instanceof Error ? e : new Error(String(e)));
|
|
1503
|
-
throw this.error;
|
|
1504
|
-
}
|
|
1505
|
-
/**
|
|
1506
|
-
* Make this iterable
|
|
1507
|
-
*/
|
|
1508
|
-
[Symbol.asyncIterator]() {
|
|
1509
|
-
if (this.started) {
|
|
1510
|
-
throw new Error("PushableAsyncIterable can only be iterated once");
|
|
1446
|
+
session.client.rpcHandlerManager.registerHandler("switch", async () => {
|
|
1447
|
+
});
|
|
1448
|
+
if (inkInstance) {
|
|
1449
|
+
inkInstance.unmount();
|
|
1511
1450
|
}
|
|
1512
|
-
|
|
1513
|
-
return this;
|
|
1514
|
-
}
|
|
1515
|
-
/**
|
|
1516
|
-
* Check if the iterable is done
|
|
1517
|
-
*/
|
|
1518
|
-
get done() {
|
|
1519
|
-
return this.isDone;
|
|
1520
|
-
}
|
|
1521
|
-
/**
|
|
1522
|
-
* Check if the iterable has an error
|
|
1523
|
-
*/
|
|
1524
|
-
get hasError() {
|
|
1525
|
-
return this.error !== null;
|
|
1526
|
-
}
|
|
1527
|
-
/**
|
|
1528
|
-
* Get the current queue size
|
|
1529
|
-
*/
|
|
1530
|
-
get queueSize() {
|
|
1531
|
-
return this.queue.length;
|
|
1532
|
-
}
|
|
1533
|
-
/**
|
|
1534
|
-
* Get the number of waiting consumers
|
|
1535
|
-
*/
|
|
1536
|
-
get waiterCount() {
|
|
1537
|
-
return this.waiters.length;
|
|
1451
|
+
messageBuffer.clear();
|
|
1538
1452
|
}
|
|
1453
|
+
api.logger.debug("[ClaudeACP] Remote launcher returning: exit");
|
|
1454
|
+
return "exit";
|
|
1539
1455
|
}
|
|
1540
1456
|
|
|
1541
1457
|
async function awaitFileExist(file, timeout = 1e4) {
|
|
@@ -1551,58 +1467,6 @@ async function awaitFileExist(file, timeout = 1e4) {
|
|
|
1551
1467
|
return false;
|
|
1552
1468
|
}
|
|
1553
1469
|
|
|
1554
|
-
function getClaudeSettingsPath() {
|
|
1555
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".claude");
|
|
1556
|
-
return path.join(claudeConfigDir, "settings.json");
|
|
1557
|
-
}
|
|
1558
|
-
function readClaudeSettings() {
|
|
1559
|
-
try {
|
|
1560
|
-
const settingsPath = getClaudeSettingsPath();
|
|
1561
|
-
if (!fs$1.existsSync(settingsPath)) {
|
|
1562
|
-
api.logger.debug(`[ClaudeSettings] No Claude settings file found at ${settingsPath}`);
|
|
1563
|
-
return null;
|
|
1564
|
-
}
|
|
1565
|
-
const settingsContent = fs$1.readFileSync(settingsPath, "utf-8");
|
|
1566
|
-
const settings = JSON.parse(settingsContent);
|
|
1567
|
-
api.logger.debug(`[ClaudeSettings] Successfully read Claude settings from ${settingsPath}`);
|
|
1568
|
-
api.logger.debug(`[ClaudeSettings] includeCoAuthoredBy: ${settings.includeCoAuthoredBy}`);
|
|
1569
|
-
return settings;
|
|
1570
|
-
} catch (error) {
|
|
1571
|
-
api.logger.debug(`[ClaudeSettings] Error reading Claude settings: ${error}`);
|
|
1572
|
-
return null;
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
function shouldIncludeCoAuthoredBy() {
|
|
1576
|
-
const settings = readClaudeSettings();
|
|
1577
|
-
if (!settings || settings.includeCoAuthoredBy === void 0) {
|
|
1578
|
-
return true;
|
|
1579
|
-
}
|
|
1580
|
-
return settings.includeCoAuthoredBy;
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
const BASE_SYSTEM_PROMPT = (() => index.trimIdent(`
|
|
1584
|
-
Help human.
|
|
1585
|
-
`))();
|
|
1586
|
-
const CO_AUTHORED_CREDITS = (() => index.trimIdent(`
|
|
1587
|
-
When making commit messages, instead of just giving co-credit to Claude, also give credit to Happy like so:
|
|
1588
|
-
|
|
1589
|
-
<main commit message>
|
|
1590
|
-
|
|
1591
|
-
Generated with [Claude Code](https://claude.ai/code)
|
|
1592
|
-
via [Happy](https://happy.engineering)
|
|
1593
|
-
|
|
1594
|
-
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
1595
|
-
Co-Authored-By: Happy <yesreply@happy.engineering>
|
|
1596
|
-
`))();
|
|
1597
|
-
const systemPrompt = (() => {
|
|
1598
|
-
const includeCoAuthored = shouldIncludeCoAuthoredBy();
|
|
1599
|
-
if (includeCoAuthored) {
|
|
1600
|
-
return BASE_SYSTEM_PROMPT + "\n\n" + CO_AUTHORED_CREDITS;
|
|
1601
|
-
} else {
|
|
1602
|
-
return BASE_SYSTEM_PROMPT;
|
|
1603
|
-
}
|
|
1604
|
-
})();
|
|
1605
|
-
|
|
1606
1470
|
async function claudeRemote(opts) {
|
|
1607
1471
|
let startFrom = opts.sessionId;
|
|
1608
1472
|
if (opts.sessionId && !index.claudeCheckSession(opts.sessionId, opts.path, opts.transcriptPath)) {
|
|
@@ -1685,7 +1549,7 @@ async function claudeRemote(opts) {
|
|
|
1685
1549
|
}
|
|
1686
1550
|
}
|
|
1687
1551
|
};
|
|
1688
|
-
let messages = new PushableAsyncIterable();
|
|
1552
|
+
let messages = new index.PushableAsyncIterable();
|
|
1689
1553
|
messages.push({
|
|
1690
1554
|
type: "user",
|
|
1691
1555
|
message: {
|
|
@@ -1693,7 +1557,7 @@ async function claudeRemote(opts) {
|
|
|
1693
1557
|
content: initial.message
|
|
1694
1558
|
}
|
|
1695
1559
|
});
|
|
1696
|
-
const response = query({
|
|
1560
|
+
const response = index.query({
|
|
1697
1561
|
prompt: messages,
|
|
1698
1562
|
options: sdkOptions
|
|
1699
1563
|
});
|
|
@@ -1749,7 +1613,7 @@ async function claudeRemote(opts) {
|
|
|
1749
1613
|
}
|
|
1750
1614
|
}
|
|
1751
1615
|
} catch (e) {
|
|
1752
|
-
if (e instanceof AbortError) {
|
|
1616
|
+
if (e instanceof index.AbortError) {
|
|
1753
1617
|
api.logger.debug(`[claudeRemote] Aborted`);
|
|
1754
1618
|
} else {
|
|
1755
1619
|
throw e;
|
|
@@ -1806,16 +1670,6 @@ function getToolName(toolName) {
|
|
|
1806
1670
|
return toTitleCase(toolName);
|
|
1807
1671
|
}
|
|
1808
1672
|
|
|
1809
|
-
function getToolDescriptor(toolName) {
|
|
1810
|
-
if (toolName === "exit_plan_mode" || toolName === "ExitPlanMode") {
|
|
1811
|
-
return { edit: false, exitPlan: true };
|
|
1812
|
-
}
|
|
1813
|
-
if (toolName === "Edit" || toolName === "MultiEdit" || toolName === "Write" || toolName === "NotebookEdit") {
|
|
1814
|
-
return { edit: true, exitPlan: false };
|
|
1815
|
-
}
|
|
1816
|
-
return { edit: false, exitPlan: false };
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
1673
|
class PermissionHandler {
|
|
1820
1674
|
toolCalls = [];
|
|
1821
1675
|
responses = /* @__PURE__ */ new Map();
|
|
@@ -2832,7 +2686,7 @@ async function claudeRemoteLauncher(session, options = {}) {
|
|
|
2832
2686
|
previousSessionId = session.sessionId;
|
|
2833
2687
|
const controller = new AbortController();
|
|
2834
2688
|
abortController = controller;
|
|
2835
|
-
abortFuture = new Future();
|
|
2689
|
+
abortFuture = new index.Future();
|
|
2836
2690
|
let modeHash = null;
|
|
2837
2691
|
let mode = null;
|
|
2838
2692
|
try {
|
|
@@ -2968,7 +2822,7 @@ async function loop(opts) {
|
|
|
2968
2822
|
jsRuntime: opts.jsRuntime
|
|
2969
2823
|
});
|
|
2970
2824
|
opts.onSessionReady?.(session);
|
|
2971
|
-
return await
|
|
2825
|
+
return await ProviderSelectionHandler.runModeLoop({
|
|
2972
2826
|
startingMode: opts.startingMode ?? "local",
|
|
2973
2827
|
onIteration: (mode) => {
|
|
2974
2828
|
api.logger.debug(`[loop] Iteration with mode: ${mode}`);
|
|
@@ -2985,9 +2839,7 @@ async function loop(opts) {
|
|
|
2985
2839
|
return { type: "exit", value: result.code };
|
|
2986
2840
|
},
|
|
2987
2841
|
remote: async () => {
|
|
2988
|
-
const reason = await claudeRemoteLauncher(session
|
|
2989
|
-
allowSwitchToLocal: opts.startedBy !== "daemon"
|
|
2990
|
-
});
|
|
2842
|
+
const reason = opts.startedBy === "daemon" ? await claudeAcpRemoteLauncher(session) : await claudeRemoteLauncher(session);
|
|
2991
2843
|
if (reason === "switch") {
|
|
2992
2844
|
return { type: "switch", mode: "local" };
|
|
2993
2845
|
}
|
|
@@ -3001,7 +2853,7 @@ async function extractSDKMetadata() {
|
|
|
3001
2853
|
const abortController = new AbortController();
|
|
3002
2854
|
try {
|
|
3003
2855
|
api.logger.debug("[metadataExtractor] Starting SDK metadata extraction");
|
|
3004
|
-
const sdkQuery = query({
|
|
2856
|
+
const sdkQuery = index.query({
|
|
3005
2857
|
prompt: "hello",
|
|
3006
2858
|
options: {
|
|
3007
2859
|
allowedTools: ["Bash(echo)"],
|