adhdev 0.1.37 → 0.1.39
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/index.js +325 -39
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -696,6 +696,16 @@ var init_chunk_BFUPGBW2 = __esm({
|
|
|
696
696
|
}
|
|
697
697
|
});
|
|
698
698
|
|
|
699
|
+
// ../core/dist/chunk-SVQNBQ2O.js
|
|
700
|
+
var DEFAULT_DAEMON_PORT, DAEMON_WS_PATH;
|
|
701
|
+
var init_chunk_SVQNBQ2O = __esm({
|
|
702
|
+
"../core/dist/chunk-SVQNBQ2O.js"() {
|
|
703
|
+
"use strict";
|
|
704
|
+
DEFAULT_DAEMON_PORT = 19222;
|
|
705
|
+
DAEMON_WS_PATH = "/ipc";
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
|
|
699
709
|
// ../core/dist/index.js
|
|
700
710
|
var dist_exports = {};
|
|
701
711
|
__export(dist_exports, {
|
|
@@ -711,15 +721,13 @@ __export(dist_exports, {
|
|
|
711
721
|
getInstalledIDEs: () => getInstalledIDEs,
|
|
712
722
|
isIdeInstalled: () => isIdeInstalled
|
|
713
723
|
});
|
|
714
|
-
var DEFAULT_DAEMON_PORT, DAEMON_WS_PATH;
|
|
715
724
|
var init_dist = __esm({
|
|
716
725
|
"../core/dist/index.js"() {
|
|
717
726
|
"use strict";
|
|
718
727
|
init_chunk_PP6RFM75();
|
|
719
728
|
init_chunk_ZZGGFYGY();
|
|
720
729
|
init_chunk_BFUPGBW2();
|
|
721
|
-
|
|
722
|
-
DAEMON_WS_PATH = "/ipc";
|
|
730
|
+
init_chunk_SVQNBQ2O();
|
|
723
731
|
}
|
|
724
732
|
});
|
|
725
733
|
|
|
@@ -786,6 +794,22 @@ function isSetupComplete() {
|
|
|
786
794
|
function resetConfig() {
|
|
787
795
|
saveConfig({ ...DEFAULT_CONFIG });
|
|
788
796
|
}
|
|
797
|
+
function addCliHistory(entry) {
|
|
798
|
+
const config = loadConfig();
|
|
799
|
+
const history = config.cliHistory || [];
|
|
800
|
+
const argsKey = (entry.cliArgs || []).join(" ");
|
|
801
|
+
const filtered = history.filter((h) => {
|
|
802
|
+
const hArgsKey = (h.cliArgs || []).join(" ");
|
|
803
|
+
return !(h.cliType === entry.cliType && h.dir === entry.dir && hArgsKey === argsKey);
|
|
804
|
+
});
|
|
805
|
+
filtered.unshift({
|
|
806
|
+
...entry,
|
|
807
|
+
timestamp: Date.now(),
|
|
808
|
+
label: entry.label || `${entry.cliType} \xB7 ${entry.dir.split("/").filter(Boolean).pop() || "root"}${argsKey ? ` (${argsKey})` : ""}`
|
|
809
|
+
});
|
|
810
|
+
config.cliHistory = filtered.slice(0, 20);
|
|
811
|
+
saveConfig(config);
|
|
812
|
+
}
|
|
789
813
|
var import_os2, import_path, import_fs2, DEFAULT_CONFIG;
|
|
790
814
|
var init_config = __esm({
|
|
791
815
|
"src/config.ts"() {
|
|
@@ -808,7 +832,9 @@ var init_config = __esm({
|
|
|
808
832
|
setupDate: null,
|
|
809
833
|
configuredCLIs: [],
|
|
810
834
|
enabledIdes: [],
|
|
811
|
-
recentCliWorkspaces: []
|
|
835
|
+
recentCliWorkspaces: [],
|
|
836
|
+
machineNickname: null,
|
|
837
|
+
cliHistory: []
|
|
812
838
|
};
|
|
813
839
|
}
|
|
814
840
|
});
|
|
@@ -1466,7 +1492,7 @@ function findGeminiBinary() {
|
|
|
1466
1492
|
return isWin ? "gemini.cmd" : "gemini";
|
|
1467
1493
|
}
|
|
1468
1494
|
}
|
|
1469
|
-
var os3, import_child_process5, pty, PROMPT_PATTERNS, STARTUP_DIALOG_PATTERNS, GeminiCliAdapter;
|
|
1495
|
+
var os3, import_child_process5, pty, PROMPT_PATTERNS, STARTUP_DIALOG_PATTERNS, GENERATING_PATTERNS, APPROVAL_PATTERNS, GeminiCliAdapter;
|
|
1470
1496
|
var init_gemini_cli = __esm({
|
|
1471
1497
|
"src/cli-adapters/gemini-cli.ts"() {
|
|
1472
1498
|
"use strict";
|
|
@@ -1490,6 +1516,24 @@ var init_gemini_cli = __esm({
|
|
|
1490
1516
|
/● 1\. Yes/,
|
|
1491
1517
|
/2\. No/
|
|
1492
1518
|
];
|
|
1519
|
+
GENERATING_PATTERNS = [
|
|
1520
|
+
/esc\s+to\s+interrupt/i,
|
|
1521
|
+
/⎋\s*to\s+interrupt/i,
|
|
1522
|
+
/press\s+esc\s+to\s+interrupt/i,
|
|
1523
|
+
/accept\s+edits\s+on/i,
|
|
1524
|
+
// ⏵⏵ accept edits on (shift+tab to cycle) · esc to interrupt
|
|
1525
|
+
/shift\+tab\s+to\s+cycle/i,
|
|
1526
|
+
/ctrl\+c\s+to\s+(cancel|interrupt|stop)/i
|
|
1527
|
+
];
|
|
1528
|
+
APPROVAL_PATTERNS = [
|
|
1529
|
+
/allow\s+once/i,
|
|
1530
|
+
/always\s+allow/i,
|
|
1531
|
+
/\(y\)es\s*\/\s*\(n\)o/i,
|
|
1532
|
+
/\[y\/n\/a\]/i,
|
|
1533
|
+
/do\s+you\s+want\s+to\s+(run|proceed|allow|execute)/i,
|
|
1534
|
+
/do\s+you\s+want\s+to\s+proceed/i,
|
|
1535
|
+
/proceed\?/i
|
|
1536
|
+
];
|
|
1493
1537
|
GeminiCliAdapter = class {
|
|
1494
1538
|
cliType = "gemini-cli";
|
|
1495
1539
|
cliName = "Gemini CLI";
|
|
@@ -1500,7 +1544,10 @@ var init_gemini_cli = __esm({
|
|
|
1500
1544
|
onStatusChange = null;
|
|
1501
1545
|
// 응답 버퍼링
|
|
1502
1546
|
responseBuffer = "";
|
|
1547
|
+
recentOutputBuffer = "";
|
|
1548
|
+
// 최근 ~1000자 rolling buffer (청크 경계 패턴 감지용)
|
|
1503
1549
|
isWaitingForResponse = false;
|
|
1550
|
+
activeModal = null;
|
|
1504
1551
|
responseTimeout = null;
|
|
1505
1552
|
idleTimeout = null;
|
|
1506
1553
|
ready = false;
|
|
@@ -1569,6 +1616,7 @@ var init_gemini_cli = __esm({
|
|
|
1569
1616
|
}
|
|
1570
1617
|
handleOutput(rawData) {
|
|
1571
1618
|
const cleanData = stripAnsi(rawData);
|
|
1619
|
+
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
1572
1620
|
if (!this.ready) {
|
|
1573
1621
|
this.startupBuffer += cleanData;
|
|
1574
1622
|
const preview = cleanData.trim().slice(0, 100);
|
|
@@ -1593,9 +1641,45 @@ var init_gemini_cli = __esm({
|
|
|
1593
1641
|
}
|
|
1594
1642
|
return;
|
|
1595
1643
|
}
|
|
1644
|
+
const hasApprovalSignal = APPROVAL_PATTERNS.some((p) => p.test(this.recentOutputBuffer));
|
|
1645
|
+
if (hasApprovalSignal && this.currentStatus !== "waiting_approval") {
|
|
1646
|
+
console.log("[GeminiAdapter] \u23F3 Approval required");
|
|
1647
|
+
this.isWaitingForResponse = true;
|
|
1648
|
+
this.currentStatus = "waiting_approval";
|
|
1649
|
+
const ctxLines = cleanData.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
|
|
1650
|
+
const ctxMsg = ctxLines.slice(-5).join(" ").slice(0, 200);
|
|
1651
|
+
this.activeModal = { message: ctxMsg || "Approval required", buttons: ["Yes", "No"] };
|
|
1652
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
1653
|
+
this.onStatusChange?.();
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
if (this.currentStatus === "waiting_approval") {
|
|
1657
|
+
const hasGeneratingResume = GENERATING_PATTERNS.some((p) => p.test(cleanData));
|
|
1658
|
+
const hasPromptResume = PROMPT_PATTERNS.some((p) => p.test(cleanData));
|
|
1659
|
+
if (hasGeneratingResume) {
|
|
1660
|
+
console.log("[GeminiAdapter] \u2705 Approval granted, generating resumed");
|
|
1661
|
+
this.currentStatus = "generating";
|
|
1662
|
+
this.activeModal = null;
|
|
1663
|
+
this.onStatusChange?.();
|
|
1664
|
+
} else if (hasPromptResume) {
|
|
1665
|
+
console.log("[GeminiAdapter] \u{1F6AB} Approval denied or skipped");
|
|
1666
|
+
this.activeModal = null;
|
|
1667
|
+
this.finishResponse();
|
|
1668
|
+
}
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1596
1671
|
if (this.isWaitingForResponse) {
|
|
1597
1672
|
this.responseBuffer += cleanData;
|
|
1598
1673
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
1674
|
+
const stillGenerating = GENERATING_PATTERNS.some((p) => p.test(cleanData));
|
|
1675
|
+
if (stillGenerating) {
|
|
1676
|
+
this.currentStatus = "generating";
|
|
1677
|
+
this.idleTimeout = setTimeout(() => {
|
|
1678
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
1679
|
+
}, 4e3);
|
|
1680
|
+
this.onStatusChange?.();
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1599
1683
|
const hasPrompt = PROMPT_PATTERNS.some((p) => p.test(this.responseBuffer));
|
|
1600
1684
|
if (hasPrompt) {
|
|
1601
1685
|
this.finishResponse();
|
|
@@ -1649,6 +1733,7 @@ var init_gemini_cli = __esm({
|
|
|
1649
1733
|
}
|
|
1650
1734
|
this.responseBuffer = "";
|
|
1651
1735
|
this.isWaitingForResponse = false;
|
|
1736
|
+
this.activeModal = null;
|
|
1652
1737
|
this.currentStatus = "idle";
|
|
1653
1738
|
this.onStatusChange?.();
|
|
1654
1739
|
}
|
|
@@ -1657,7 +1742,7 @@ var init_gemini_cli = __esm({
|
|
|
1657
1742
|
status: this.currentStatus,
|
|
1658
1743
|
messages: [...this.messages],
|
|
1659
1744
|
workingDir: this.workingDir,
|
|
1660
|
-
activeModal:
|
|
1745
|
+
activeModal: this.activeModal
|
|
1661
1746
|
};
|
|
1662
1747
|
}
|
|
1663
1748
|
/**
|
|
@@ -1793,13 +1878,17 @@ var init_claude_cli = __esm({
|
|
|
1793
1878
|
workingDir;
|
|
1794
1879
|
onStatusChange = null;
|
|
1795
1880
|
responseBuffer = "";
|
|
1881
|
+
recentOutputBuffer = "";
|
|
1882
|
+
// 최근 ~1000자 rolling buffer (청크 경계 패턴 감지용)
|
|
1796
1883
|
isWaitingForResponse = false;
|
|
1884
|
+
activeModal = null;
|
|
1797
1885
|
idleTimeout = null;
|
|
1798
1886
|
ready = false;
|
|
1799
1887
|
startupBuffer = "";
|
|
1800
1888
|
bridge = null;
|
|
1801
1889
|
logBuffer = [];
|
|
1802
1890
|
onPtyDataCallback = null;
|
|
1891
|
+
extraArgs = [];
|
|
1803
1892
|
// Patterns for Claude Code
|
|
1804
1893
|
PROMPT_PATTERNS = [
|
|
1805
1894
|
/❯\s*$/,
|
|
@@ -1808,14 +1897,40 @@ var init_claude_cli = __esm({
|
|
|
1808
1897
|
/➜\s+.*\s*$/,
|
|
1809
1898
|
/\s+✗\s*$/
|
|
1810
1899
|
];
|
|
1900
|
+
// "Esc to interrupt" 표시 → Claude Code가 자율적으로 생성 중임을 감지
|
|
1901
|
+
GENERATING_PATTERNS = [
|
|
1902
|
+
/esc\s+to\s+interrupt/i,
|
|
1903
|
+
/⎋\s*to\s+interrupt/i,
|
|
1904
|
+
/press\s+esc\s+to\s+interrupt/i,
|
|
1905
|
+
/accept\s+edits\s+on/i,
|
|
1906
|
+
// ⏵⏵ accept edits on (shift+tab to cycle) · esc to interrupt
|
|
1907
|
+
/shift\+tab\s+to\s+cycle/i
|
|
1908
|
+
];
|
|
1909
|
+
// Approval 요청 패턴 — Claude Code가 툴 실행 전 사용자 허가를 요청할 때
|
|
1910
|
+
APPROVAL_PATTERNS = [
|
|
1911
|
+
/allow\s+once/i,
|
|
1912
|
+
/always\s+allow/i,
|
|
1913
|
+
/\(y\)es\s*\/\s*\(n\)o/i,
|
|
1914
|
+
/\[y\/n\/a\]/i,
|
|
1915
|
+
/do\s+you\s+want\s+to\s+(run|proceed|allow|execute|make|create|delete|write|edit)/i,
|
|
1916
|
+
/do\s+you\s+want\s+to\s+proceed/i,
|
|
1917
|
+
/proceed\?/i,
|
|
1918
|
+
/esc\s+to\s+cancel/i,
|
|
1919
|
+
// Claude Code 파일 편집 승인 UI
|
|
1920
|
+
/tab\s+to\s+amend/i,
|
|
1921
|
+
// Claude Code 파일 편집 승인 UI
|
|
1922
|
+
/yes,\s+allow\s+all\s+edits/i
|
|
1923
|
+
// "Yes, allow all edits during this session"
|
|
1924
|
+
];
|
|
1811
1925
|
DIALOG_PATTERNS = [
|
|
1812
1926
|
/Do you trust the files in this folder/i,
|
|
1813
1927
|
/Please log in to Anthropic/i,
|
|
1814
1928
|
/Your one-time login code is/i,
|
|
1815
1929
|
/Wait for login to complete/i
|
|
1816
1930
|
];
|
|
1817
|
-
constructor(workingDir) {
|
|
1931
|
+
constructor(workingDir, cliArgs = []) {
|
|
1818
1932
|
this.workingDir = workingDir;
|
|
1933
|
+
this.extraArgs = cliArgs;
|
|
1819
1934
|
}
|
|
1820
1935
|
setBridge(bridge) {
|
|
1821
1936
|
this.bridge = bridge;
|
|
@@ -1834,8 +1949,8 @@ var init_claude_cli = __esm({
|
|
|
1834
1949
|
if (this.ptyProcess) return;
|
|
1835
1950
|
if (!pty2) throw new Error("node-pty is not installed");
|
|
1836
1951
|
const claudeBin = findClaudeBinary();
|
|
1837
|
-
console.log(`[ClaudeAdapter] Spawning Claude Code in ${this.workingDir}`);
|
|
1838
|
-
this.ptyProcess = pty2.spawn(claudeBin,
|
|
1952
|
+
console.log(`[ClaudeAdapter] Spawning Claude Code in ${this.workingDir}${this.extraArgs.length ? ` with args: ${this.extraArgs.join(" ")}` : ""}`);
|
|
1953
|
+
this.ptyProcess = pty2.spawn(claudeBin, this.extraArgs, {
|
|
1839
1954
|
name: "xterm-256color",
|
|
1840
1955
|
cols: 120,
|
|
1841
1956
|
rows: 40,
|
|
@@ -1868,6 +1983,7 @@ var init_claude_cli = __esm({
|
|
|
1868
1983
|
this.logBuffer.push({ message: cleanData.trim(), level: "info" });
|
|
1869
1984
|
}
|
|
1870
1985
|
}
|
|
1986
|
+
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
1871
1987
|
if (!this.ready) {
|
|
1872
1988
|
this.startupBuffer += cleanData;
|
|
1873
1989
|
const hasDialog = this.DIALOG_PATTERNS.some((p) => p.test(this.startupBuffer));
|
|
@@ -1889,9 +2005,55 @@ var init_claude_cli = __esm({
|
|
|
1889
2005
|
}
|
|
1890
2006
|
return;
|
|
1891
2007
|
}
|
|
2008
|
+
const hasApprovalSignal = this.APPROVAL_PATTERNS.some((p) => p.test(this.recentOutputBuffer));
|
|
2009
|
+
if (hasApprovalSignal && this.currentStatus !== "waiting_approval") {
|
|
2010
|
+
console.log('[ClaudeAdapter] \u23F3 Approval required ("Allow once" / y/n detected)');
|
|
2011
|
+
this.isWaitingForResponse = true;
|
|
2012
|
+
this.currentStatus = "waiting_approval";
|
|
2013
|
+
const ctxLines = cleanData.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
|
|
2014
|
+
const ctxMsg = ctxLines.slice(-5).join(" ").slice(0, 200);
|
|
2015
|
+
this.activeModal = { message: ctxMsg || "Approval required", buttons: ["Allow once", "Always allow", "Deny"] };
|
|
2016
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
2017
|
+
this.onStatusChange?.();
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
if (this.currentStatus === "waiting_approval") {
|
|
2021
|
+
const hasGeneratingResume = this.GENERATING_PATTERNS.some((p) => p.test(cleanData));
|
|
2022
|
+
const hasPromptResume = this.PROMPT_PATTERNS.some((p) => p.test(cleanData));
|
|
2023
|
+
if (hasGeneratingResume) {
|
|
2024
|
+
console.log("[ClaudeAdapter] \u2705 Approval granted, generating resumed");
|
|
2025
|
+
this.currentStatus = "generating";
|
|
2026
|
+
this.activeModal = null;
|
|
2027
|
+
this.onStatusChange?.();
|
|
2028
|
+
} else if (hasPromptResume) {
|
|
2029
|
+
console.log("[ClaudeAdapter] \u{1F6AB} Approval denied or skipped, returning to idle");
|
|
2030
|
+
this.activeModal = null;
|
|
2031
|
+
this.finishResponse();
|
|
2032
|
+
}
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
if (!this.isWaitingForResponse) {
|
|
2036
|
+
const hasGeneratingSignal = this.GENERATING_PATTERNS.some((p) => p.test(cleanData));
|
|
2037
|
+
if (hasGeneratingSignal) {
|
|
2038
|
+
console.log('[ClaudeAdapter] \u26A1 Autonomous generating detected ("Esc to interrupt")');
|
|
2039
|
+
this.isWaitingForResponse = true;
|
|
2040
|
+
this.responseBuffer = "";
|
|
2041
|
+
this.currentStatus = "generating";
|
|
2042
|
+
this.onStatusChange?.();
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
1892
2045
|
if (this.isWaitingForResponse) {
|
|
1893
2046
|
this.responseBuffer += cleanData;
|
|
1894
2047
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
2048
|
+
const stillGenerating = this.GENERATING_PATTERNS.some((p) => p.test(cleanData));
|
|
2049
|
+
if (stillGenerating) {
|
|
2050
|
+
this.currentStatus = "generating";
|
|
2051
|
+
this.idleTimeout = setTimeout(() => {
|
|
2052
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
2053
|
+
}, 4e3);
|
|
2054
|
+
this.onStatusChange?.();
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
1895
2057
|
const hasPrompt = this.PROMPT_PATTERNS.some((p) => p.test(this.responseBuffer));
|
|
1896
2058
|
if (hasPrompt) {
|
|
1897
2059
|
this.finishResponse();
|
|
@@ -1917,6 +2079,7 @@ var init_claude_cli = __esm({
|
|
|
1917
2079
|
}
|
|
1918
2080
|
this.responseBuffer = "";
|
|
1919
2081
|
this.isWaitingForResponse = false;
|
|
2082
|
+
this.activeModal = null;
|
|
1920
2083
|
this.currentStatus = "idle";
|
|
1921
2084
|
this.onStatusChange?.();
|
|
1922
2085
|
}
|
|
@@ -1925,7 +2088,7 @@ var init_claude_cli = __esm({
|
|
|
1925
2088
|
status: this.currentStatus,
|
|
1926
2089
|
messages: [...this.messages],
|
|
1927
2090
|
workingDir: this.workingDir,
|
|
1928
|
-
activeModal:
|
|
2091
|
+
activeModal: this.activeModal
|
|
1929
2092
|
};
|
|
1930
2093
|
}
|
|
1931
2094
|
async sendMessage(text) {
|
|
@@ -4461,9 +4624,71 @@ var init_daemon_commands = __esm({
|
|
|
4461
4624
|
const script = loader.getCapabilityWithParams("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
|
|
4462
4625
|
if (!script) return { success: false, error: "switch_session script not available" };
|
|
4463
4626
|
try {
|
|
4464
|
-
const
|
|
4465
|
-
console.log(`[switch_chat] result:`,
|
|
4466
|
-
|
|
4627
|
+
const raw = await cdp2.evaluate(script, 15e3);
|
|
4628
|
+
console.log(`[switch_chat] result:`, raw);
|
|
4629
|
+
let parsed = null;
|
|
4630
|
+
try {
|
|
4631
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
4632
|
+
} catch {
|
|
4633
|
+
}
|
|
4634
|
+
if (parsed?.action === "click" && parsed.clickX && parsed.clickY) {
|
|
4635
|
+
const x = Math.round(parsed.clickX);
|
|
4636
|
+
const y = Math.round(parsed.clickY);
|
|
4637
|
+
console.log(`[switch_chat] CDP click at (${x}, ${y}) for "${parsed.title}"`);
|
|
4638
|
+
await cdp2.send("Input.dispatchMouseEvent", {
|
|
4639
|
+
type: "mousePressed",
|
|
4640
|
+
x,
|
|
4641
|
+
y,
|
|
4642
|
+
button: "left",
|
|
4643
|
+
clickCount: 1
|
|
4644
|
+
});
|
|
4645
|
+
await cdp2.send("Input.dispatchMouseEvent", {
|
|
4646
|
+
type: "mouseReleased",
|
|
4647
|
+
x,
|
|
4648
|
+
y,
|
|
4649
|
+
button: "left",
|
|
4650
|
+
clickCount: 1
|
|
4651
|
+
});
|
|
4652
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
4653
|
+
const wsResult = await cdp2.evaluate(`
|
|
4654
|
+
(() => {
|
|
4655
|
+
const inp = Array.from(document.querySelectorAll('input[type="text"]'))
|
|
4656
|
+
.find(i => i.offsetWidth > 0 && (i.placeholder || '').includes('Select where'));
|
|
4657
|
+
if (!inp) return null;
|
|
4658
|
+
const rows = inp.closest('[class*="quickInput"]')?.querySelectorAll('[class*="cursor-pointer"]');
|
|
4659
|
+
if (rows && rows.length > 0) {
|
|
4660
|
+
const r = rows[0].getBoundingClientRect();
|
|
4661
|
+
return JSON.stringify({ x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) });
|
|
4662
|
+
}
|
|
4663
|
+
return null;
|
|
4664
|
+
})()
|
|
4665
|
+
`, 5e3);
|
|
4666
|
+
if (wsResult) {
|
|
4667
|
+
try {
|
|
4668
|
+
const ws = JSON.parse(wsResult);
|
|
4669
|
+
await cdp2.send("Input.dispatchMouseEvent", {
|
|
4670
|
+
type: "mousePressed",
|
|
4671
|
+
x: ws.x,
|
|
4672
|
+
y: ws.y,
|
|
4673
|
+
button: "left",
|
|
4674
|
+
clickCount: 1
|
|
4675
|
+
});
|
|
4676
|
+
await cdp2.send("Input.dispatchMouseEvent", {
|
|
4677
|
+
type: "mouseReleased",
|
|
4678
|
+
x: ws.x,
|
|
4679
|
+
y: ws.y,
|
|
4680
|
+
button: "left",
|
|
4681
|
+
clickCount: 1
|
|
4682
|
+
});
|
|
4683
|
+
} catch {
|
|
4684
|
+
}
|
|
4685
|
+
}
|
|
4686
|
+
return { success: true, result: "switched" };
|
|
4687
|
+
}
|
|
4688
|
+
if (parsed?.error) {
|
|
4689
|
+
return { success: false, error: parsed.error };
|
|
4690
|
+
}
|
|
4691
|
+
return { success: true, result: raw };
|
|
4467
4692
|
} catch (e) {
|
|
4468
4693
|
console.error(`[switch_chat] error:`, e.message);
|
|
4469
4694
|
return { success: false, error: e.message };
|
|
@@ -5990,9 +6215,12 @@ var init_adhdev_daemon = __esm({
|
|
|
5990
6215
|
this.commandHandler.setAgentStreamManager(this.agentStreamManager);
|
|
5991
6216
|
this.startAgentStreamPolling();
|
|
5992
6217
|
if (options.cliType) {
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
6218
|
+
const cliTypes = Array.isArray(options.cliType) ? options.cliType : options.cliType.split(",").map((s) => s.trim()).filter(Boolean);
|
|
6219
|
+
for (const ct of cliTypes) {
|
|
6220
|
+
await this.startCliSession(ct, workingDir, options.cliArgs).catch((e) => {
|
|
6221
|
+
console.log(import_chalk2.default.yellow(` \u26A0 Failed to start CLI ${ct}: ${e.message}`));
|
|
6222
|
+
});
|
|
6223
|
+
}
|
|
5996
6224
|
}
|
|
5997
6225
|
const machineId = os9.hostname().replace(/[^a-zA-Z0-9]/g, "_");
|
|
5998
6226
|
const machineHash = crypto2.createHash("md5").update(os9.hostname() + os9.homedir()).digest("hex").slice(0, 8);
|
|
@@ -6029,17 +6257,27 @@ var init_adhdev_daemon = __esm({
|
|
|
6029
6257
|
return { id: req.id, success: result.success, entries: result.files, error: result.error };
|
|
6030
6258
|
}
|
|
6031
6259
|
});
|
|
6032
|
-
this.p2p.onPtyInput((
|
|
6260
|
+
this.p2p.onPtyInput((cliId, data) => {
|
|
6261
|
+
const directAdapter = this.adapters.get(cliId);
|
|
6262
|
+
if (directAdapter && typeof directAdapter.writeRaw === "function") {
|
|
6263
|
+
directAdapter.writeRaw(data);
|
|
6264
|
+
return;
|
|
6265
|
+
}
|
|
6033
6266
|
for (const [, adapter] of this.adapters) {
|
|
6034
|
-
if (adapter.cliType ===
|
|
6267
|
+
if (adapter.cliType === cliId && typeof adapter.writeRaw === "function") {
|
|
6035
6268
|
adapter.writeRaw(data);
|
|
6036
6269
|
return;
|
|
6037
6270
|
}
|
|
6038
6271
|
}
|
|
6039
6272
|
});
|
|
6040
|
-
this.p2p.onPtyResize((
|
|
6273
|
+
this.p2p.onPtyResize((cliId, cols, rows) => {
|
|
6274
|
+
const directAdapter = this.adapters.get(cliId);
|
|
6275
|
+
if (directAdapter && typeof directAdapter.resize === "function") {
|
|
6276
|
+
directAdapter.resize(cols, rows);
|
|
6277
|
+
return;
|
|
6278
|
+
}
|
|
6041
6279
|
for (const [, adapter] of this.adapters) {
|
|
6042
|
-
if (adapter.cliType ===
|
|
6280
|
+
if (adapter.cliType === cliId && typeof adapter.resize === "function") {
|
|
6043
6281
|
adapter.resize(cols, rows);
|
|
6044
6282
|
return;
|
|
6045
6283
|
}
|
|
@@ -6206,7 +6444,7 @@ var init_adhdev_daemon = __esm({
|
|
|
6206
6444
|
if (!cliType) throw new Error("cliType required");
|
|
6207
6445
|
const key = this.getCliKey(cliType, dir);
|
|
6208
6446
|
if (!this.adapters.has(key)) {
|
|
6209
|
-
await this.startCliSession(cliType, dir);
|
|
6447
|
+
await this.startCliSession(cliType, dir, args?.cliArgs);
|
|
6210
6448
|
try {
|
|
6211
6449
|
const config = loadConfig();
|
|
6212
6450
|
console.log(import_chalk2.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
|
|
@@ -6416,14 +6654,17 @@ var init_adhdev_daemon = __esm({
|
|
|
6416
6654
|
case "stop_cli": {
|
|
6417
6655
|
const cliType = data.cliType || "gemini-cli";
|
|
6418
6656
|
const dir = data.dir || "";
|
|
6419
|
-
const key =
|
|
6657
|
+
const key = this.getCliKey(cliType, dir);
|
|
6420
6658
|
const adapter = this.adapters.get(key);
|
|
6421
6659
|
if (adapter) {
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6660
|
+
await this.stopCliSession(key);
|
|
6661
|
+
} else {
|
|
6662
|
+
for (const [k, a] of this.adapters) {
|
|
6663
|
+
if (a.cliType === cliType) {
|
|
6664
|
+
await this.stopCliSession(k);
|
|
6665
|
+
break;
|
|
6666
|
+
}
|
|
6425
6667
|
}
|
|
6426
|
-
this.adapters.delete(key);
|
|
6427
6668
|
}
|
|
6428
6669
|
return { success: true, stopped: true };
|
|
6429
6670
|
}
|
|
@@ -6442,6 +6683,34 @@ var init_adhdev_daemon = __esm({
|
|
|
6442
6683
|
await this.startCliSession(cliType, dir);
|
|
6443
6684
|
return { success: true, restarted: true };
|
|
6444
6685
|
}
|
|
6686
|
+
// ─── P2P/Local only: 민감 데이터 (서버 경유 X) ─────
|
|
6687
|
+
case "get_cli_history": {
|
|
6688
|
+
const config = loadConfig();
|
|
6689
|
+
return { success: true, history: config.cliHistory || [] };
|
|
6690
|
+
}
|
|
6691
|
+
case "set_machine_nickname": {
|
|
6692
|
+
const nickname = data.nickname?.trim() || null;
|
|
6693
|
+
const config = loadConfig();
|
|
6694
|
+
config.machineNickname = nickname;
|
|
6695
|
+
saveConfig(config);
|
|
6696
|
+
return { success: true, nickname };
|
|
6697
|
+
}
|
|
6698
|
+
case "get_daemon_logs": {
|
|
6699
|
+
const lines = parseInt(data.lines) || 100;
|
|
6700
|
+
try {
|
|
6701
|
+
const logPath = require("path").join(require("os").tmpdir(), "adhdev-daemon.log");
|
|
6702
|
+
const fs6 = require("fs");
|
|
6703
|
+
if (fs6.existsSync(logPath)) {
|
|
6704
|
+
const content = fs6.readFileSync(logPath, "utf-8");
|
|
6705
|
+
const allLines = content.split("\n");
|
|
6706
|
+
const recent = allLines.slice(-lines).join("\n");
|
|
6707
|
+
return { success: true, logs: recent, totalLines: allLines.length };
|
|
6708
|
+
}
|
|
6709
|
+
return { success: true, logs: "", totalLines: 0 };
|
|
6710
|
+
} catch (e) {
|
|
6711
|
+
return { success: false, error: e.message };
|
|
6712
|
+
}
|
|
6713
|
+
}
|
|
6445
6714
|
}
|
|
6446
6715
|
if (this.commandHandler) {
|
|
6447
6716
|
return this.commandHandler.handle(cmdType, data);
|
|
@@ -6452,17 +6721,18 @@ var init_adhdev_daemon = __esm({
|
|
|
6452
6721
|
}
|
|
6453
6722
|
}
|
|
6454
6723
|
// ─── CLI 세션 관리 ──────────────────────────────
|
|
6455
|
-
createAdapter(cliType, workingDir) {
|
|
6724
|
+
createAdapter(cliType, workingDir, cliArgs) {
|
|
6456
6725
|
if (cliType === "claude-cli" || cliType === "claude-code") {
|
|
6457
|
-
return new ClaudeCliAdapter(workingDir);
|
|
6726
|
+
return new ClaudeCliAdapter(workingDir, cliArgs);
|
|
6458
6727
|
} else if (cliType === "codex-cli" || cliType === "codex") {
|
|
6459
6728
|
return new CodexCliAdapter(workingDir);
|
|
6460
6729
|
} else {
|
|
6461
6730
|
return new GeminiCliAdapter(workingDir);
|
|
6462
6731
|
}
|
|
6463
6732
|
}
|
|
6464
|
-
async startCliSession(cliType, workingDir) {
|
|
6465
|
-
const
|
|
6733
|
+
async startCliSession(cliType, workingDir, cliArgs) {
|
|
6734
|
+
const trimmed = (workingDir || process.cwd()).trim();
|
|
6735
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os9.homedir()) : require("path").resolve(trimmed);
|
|
6466
6736
|
const cliInfo = await detectCLI(cliType);
|
|
6467
6737
|
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
6468
6738
|
const key = this.getCliKey(cliType, resolvedDir);
|
|
@@ -6471,7 +6741,7 @@ var init_adhdev_daemon = __esm({
|
|
|
6471
6741
|
return;
|
|
6472
6742
|
}
|
|
6473
6743
|
console.log(import_chalk2.default.yellow(` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
6474
|
-
const adapter = this.createAdapter(cliType, resolvedDir);
|
|
6744
|
+
const adapter = this.createAdapter(cliType, resolvedDir, cliArgs);
|
|
6475
6745
|
await adapter.spawn();
|
|
6476
6746
|
if (this.bridge && typeof adapter.setBridge === "function") {
|
|
6477
6747
|
adapter.setBridge(this.bridge);
|
|
@@ -6479,10 +6749,11 @@ var init_adhdev_daemon = __esm({
|
|
|
6479
6749
|
adapter.setOnStatusChange(() => this.sendUnifiedStatusReport());
|
|
6480
6750
|
if (typeof adapter.setOnPtyData === "function") {
|
|
6481
6751
|
adapter.setOnPtyData((data) => {
|
|
6482
|
-
const sentViaP2P = this.p2p?.broadcastPtyOutput(
|
|
6752
|
+
const sentViaP2P = this.p2p?.broadcastPtyOutput(key, data);
|
|
6483
6753
|
if (!sentViaP2P && this.bridge) {
|
|
6484
6754
|
this.bridge.sendMessage("pty_output", {
|
|
6485
|
-
cliType:
|
|
6755
|
+
cliType: key,
|
|
6756
|
+
// adapter key (cliType_hash)
|
|
6486
6757
|
data
|
|
6487
6758
|
});
|
|
6488
6759
|
}
|
|
@@ -6491,6 +6762,10 @@ var init_adhdev_daemon = __esm({
|
|
|
6491
6762
|
this.adapters.set(key, adapter);
|
|
6492
6763
|
this.lastAgentStatus.set(key, "idle");
|
|
6493
6764
|
console.log(import_chalk2.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6765
|
+
try {
|
|
6766
|
+
addCliHistory({ cliType, dir: resolvedDir, cliArgs });
|
|
6767
|
+
} catch {
|
|
6768
|
+
}
|
|
6494
6769
|
this.sendUnifiedStatusReport();
|
|
6495
6770
|
}
|
|
6496
6771
|
async stopCliSession(key) {
|
|
@@ -6594,9 +6869,12 @@ var init_adhdev_daemon = __esm({
|
|
|
6594
6869
|
console.log(`[StatusReport] ${ideType} inline fallback: ${inlineResult?.messages?.length || 0} msgs`);
|
|
6595
6870
|
if (inlineResult?.messages?.length > 0) {
|
|
6596
6871
|
this._cachedActiveChatMap.set(ideType, { ...inlineResult, activeModal });
|
|
6872
|
+
} else {
|
|
6873
|
+
this._cachedActiveChatMap.set(ideType, { ...raw, messages: [], activeModal });
|
|
6597
6874
|
}
|
|
6598
6875
|
} catch (e2) {
|
|
6599
6876
|
console.log(`[StatusReport] ${ideType} inline error: ${e2.message}`);
|
|
6877
|
+
this._cachedActiveChatMap.set(ideType, { ...raw, messages: [], activeModal });
|
|
6600
6878
|
}
|
|
6601
6879
|
}
|
|
6602
6880
|
} else {
|
|
@@ -6683,19 +6961,28 @@ var init_adhdev_daemon = __esm({
|
|
|
6683
6961
|
const cliStatus = adapterStatus.status;
|
|
6684
6962
|
let lastStatus = this.lastAgentStatus.get(key) || "idle";
|
|
6685
6963
|
if (cliStatus !== lastStatus) {
|
|
6964
|
+
const chatTitle = `${adapter.cliName} \xB7 ${adapter.workingDir.split("/").filter(Boolean).pop() || "session"}`;
|
|
6686
6965
|
if (lastStatus === "idle" && cliStatus === "generating") {
|
|
6687
6966
|
this.generatingStartedAt.set(key, now);
|
|
6688
6967
|
this.bridge?.sendMessage("status_event", {
|
|
6689
6968
|
event: "agent:generating_started",
|
|
6690
|
-
chatTitle
|
|
6969
|
+
chatTitle,
|
|
6970
|
+
timestamp: now
|
|
6971
|
+
});
|
|
6972
|
+
} else if (cliStatus === "waiting_approval") {
|
|
6973
|
+
if (!this.generatingStartedAt.has(key)) this.generatingStartedAt.set(key, now);
|
|
6974
|
+
this.bridge?.sendMessage("status_event", {
|
|
6975
|
+
event: "agent:approval_requested",
|
|
6976
|
+
chatTitle,
|
|
6691
6977
|
timestamp: now
|
|
6692
6978
|
});
|
|
6693
|
-
} else if (lastStatus === "
|
|
6979
|
+
} else if (lastStatus === "waiting_approval" && cliStatus === "generating") {
|
|
6980
|
+
} else if (cliStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval")) {
|
|
6694
6981
|
const startedAt = this.generatingStartedAt.get(key);
|
|
6695
6982
|
const duration = startedAt ? Math.round((now - startedAt) / 1e3) : 0;
|
|
6696
6983
|
this.bridge?.sendMessage("status_event", {
|
|
6697
6984
|
event: "agent:generating_completed",
|
|
6698
|
-
chatTitle
|
|
6985
|
+
chatTitle,
|
|
6699
6986
|
duration,
|
|
6700
6987
|
timestamp: now
|
|
6701
6988
|
});
|
|
@@ -6734,6 +7021,7 @@ var init_adhdev_daemon = __esm({
|
|
|
6734
7021
|
const payload = {
|
|
6735
7022
|
// Machine 정보
|
|
6736
7023
|
daemonMode: true,
|
|
7024
|
+
machineNickname: loadConfig().machineNickname || null,
|
|
6737
7025
|
machine: {
|
|
6738
7026
|
hostname: os9.hostname(),
|
|
6739
7027
|
platform: os9.platform(),
|
|
@@ -8550,13 +8838,11 @@ program.command("reset").description("Reset ADHDev configuration").action(async
|
|
|
8550
8838
|
console.log(import_chalk4.default.gray(" Run `adhdev setup` to reconfigure.\n"));
|
|
8551
8839
|
}
|
|
8552
8840
|
});
|
|
8553
|
-
program.command("daemon").description("Start ADHDev Daemon \u2014 unified local hub for Extensions, CLIs, and IDEs").option("-p, --port <port>", "Local WS server port", "19222").option("--
|
|
8841
|
+
program.command("daemon").description("Start ADHDev Daemon \u2014 unified local hub for Extensions, CLIs, and IDEs").option("-p, --port <port>", "Local WS server port", "19222").option("--server <url>", "Override server URL for testing").action(async (options) => {
|
|
8554
8842
|
const { AdhdevDaemon: AdhdevDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
|
|
8555
8843
|
const daemon = new AdhdevDaemon2();
|
|
8556
8844
|
await daemon.start({
|
|
8557
8845
|
localPort: parseInt(options.port) || 19222,
|
|
8558
|
-
cliType: options.cli,
|
|
8559
|
-
workingDir: options.dir,
|
|
8560
8846
|
serverUrl: options.server,
|
|
8561
8847
|
foreground: true
|
|
8562
8848
|
});
|