@sunub/obsidian-mcp-server 0.2.0 → 0.3.1
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/README.md +217 -25
- package/build/cli/AppContainer.d.ts +1 -0
- package/build/cli/AppContainer.js +197 -0
- package/build/cli/AppContainer.js.map +1 -0
- package/build/cli/config/SettingContext.d.ts +1 -0
- package/build/cli/config/SettingContext.js +2 -0
- package/build/cli/config/SettingContext.js.map +1 -0
- package/build/cli/config/mcpServersConfig.d.ts +18 -0
- package/build/cli/config/mcpServersConfig.js +119 -0
- package/build/cli/config/mcpServersConfig.js.map +1 -0
- package/build/cli/config/settingSchema.d.ts +180 -0
- package/build/cli/config/settingSchema.js +128 -0
- package/build/cli/config/settingSchema.js.map +1 -0
- package/build/cli/context/InputContext.d.ts +12 -0
- package/build/cli/context/InputContext.js +10 -0
- package/build/cli/context/InputContext.js.map +1 -0
- package/build/cli/context/KeypressContext.d.ts +30 -0
- package/build/cli/context/KeypressContext.js +200 -0
- package/build/cli/context/KeypressContext.js.map +1 -0
- package/build/cli/context/KeypressContext.util.d.ts +7 -0
- package/build/cli/context/KeypressContext.util.js +474 -0
- package/build/cli/context/KeypressContext.util.js.map +1 -0
- package/build/cli/hooks/useAtCompletion.d.ts +12 -0
- package/build/cli/hooks/useAtCompletion.js +5 -0
- package/build/cli/hooks/useAtCompletion.js.map +1 -0
- package/build/cli/hooks/useCommandCompletion.d.ts +59 -0
- package/build/cli/hooks/useCommandCompletion.js +344 -0
- package/build/cli/hooks/useCommandCompletion.js.map +1 -0
- package/build/cli/hooks/useCompletion.d.ts +22 -0
- package/build/cli/hooks/useCompletion.js +84 -0
- package/build/cli/hooks/useCompletion.js.map +1 -0
- package/build/cli/hooks/useDispatcher.d.ts +6 -0
- package/build/cli/hooks/useDispatcher.js +286 -0
- package/build/cli/hooks/useDispatcher.js.map +1 -0
- package/build/cli/hooks/useFocus.d.ts +2 -0
- package/build/cli/hooks/useFocus.js +3 -0
- package/build/cli/hooks/useFocus.js.map +1 -0
- package/build/cli/hooks/useInputHistory.d.ts +24 -0
- package/build/cli/hooks/useInputHistory.js +159 -0
- package/build/cli/hooks/useInputHistory.js.map +1 -0
- package/build/cli/hooks/useKeyMatchers.d.ts +17 -0
- package/build/cli/hooks/useKeyMatchers.js +13 -0
- package/build/cli/hooks/useKeyMatchers.js.map +1 -0
- package/build/cli/hooks/useKeypress.d.ts +19 -0
- package/build/cli/hooks/useKeypress.js +28 -0
- package/build/cli/hooks/useKeypress.js.map +1 -0
- package/build/cli/hooks/useLlmStream.d.ts +12 -0
- package/build/cli/hooks/useLlmStream.js +365 -0
- package/build/cli/hooks/useLlmStream.js.map +1 -0
- package/build/cli/hooks/useMcpClient.d.ts +10 -0
- package/build/cli/hooks/useMcpClient.js +100 -0
- package/build/cli/hooks/useMcpClient.js.map +1 -0
- package/build/cli/hooks/useMcpManager.d.ts +22 -0
- package/build/cli/hooks/useMcpManager.js +86 -0
- package/build/cli/hooks/useMcpManager.js.map +1 -0
- package/build/cli/hooks/usePromptCompletion.d.ts +19 -0
- package/build/cli/hooks/usePromptCompletion.js +13 -0
- package/build/cli/hooks/usePromptCompletion.js.map +1 -0
- package/build/cli/hooks/useRagContext.d.ts +6 -0
- package/build/cli/hooks/useRagContext.js +83 -0
- package/build/cli/hooks/useRagContext.js.map +1 -0
- package/build/cli/hooks/useShellCompletion.d.ts +18 -0
- package/build/cli/hooks/useShellCompletion.js +10 -0
- package/build/cli/hooks/useShellCompletion.js.map +1 -0
- package/build/cli/hooks/useSlashCompletion.d.ts +21 -0
- package/build/cli/hooks/useSlashCompletion.js +11 -0
- package/build/cli/hooks/useSlashCompletion.js.map +1 -0
- package/build/cli/hooks/useTerminalSize.d.ts +9 -0
- package/build/cli/hooks/useTerminalSize.js +26 -0
- package/build/cli/hooks/useTerminalSize.js.map +1 -0
- package/build/cli/index.js +27 -0
- package/build/cli/index.js.map +1 -0
- package/build/cli/key/keyBindings.d.ts +152 -0
- package/build/cli/key/keyBindings.js +630 -0
- package/build/cli/key/keyBindings.js.map +1 -0
- package/build/cli/key/keyMatchers.d.ts +27 -0
- package/build/cli/key/keyMatchers.js +33 -0
- package/build/cli/key/keyMatchers.js.map +1 -0
- package/build/cli/key/text-buffer.js +918 -0
- package/build/cli/key/text-buffer.js.map +1 -0
- package/build/cli/reference/HistoryItemDisplay.d.ts +23 -0
- package/build/cli/reference/HistoryItemDisplay.js +63 -0
- package/build/cli/reference/HistoryItemDisplay.js.map +1 -0
- package/build/cli/reference/InputContext.d.ts +17 -0
- package/build/cli/reference/InputContext.js +16 -0
- package/build/cli/reference/InputContext.js.map +1 -0
- package/build/cli/reference/KerypressContext.d.ts +37 -0
- package/build/cli/reference/KerypressContext.js +791 -0
- package/build/cli/reference/KerypressContext.js.map +1 -0
- package/build/cli/reference/MainContent.d.ts +6 -0
- package/build/cli/reference/MainContent.js +207 -0
- package/build/cli/reference/MainContent.js.map +1 -0
- package/build/cli/reference/UIStateContext.d.ts +188 -0
- package/build/cli/reference/UIStateContext.js +16 -0
- package/build/cli/reference/UIStateContext.js.map +1 -0
- package/build/cli/reference/useGeminiStream.d.ts +42 -0
- package/build/cli/reference/useGeminiStream.js +1404 -0
- package/build/cli/reference/useGeminiStream.js.map +1 -0
- package/build/cli/services/McpClientService.d.ts +32 -0
- package/build/cli/services/McpClientService.js +123 -0
- package/build/cli/services/McpClientService.js.map +1 -0
- package/build/cli/services/McpManager.d.ts +28 -0
- package/build/cli/services/McpManager.js +146 -0
- package/build/cli/services/McpManager.js.map +1 -0
- package/build/cli/tmp.js +27 -0
- package/build/cli/tmp.js.map +1 -0
- package/build/cli/ui/ConnectionStatus.d.ts +13 -0
- package/build/cli/ui/ConnectionStatus.js +24 -0
- package/build/cli/ui/ConnectionStatus.js.map +1 -0
- package/build/cli/ui/HelpCommands.d.ts +5 -0
- package/build/cli/ui/HelpCommands.js +11 -0
- package/build/cli/ui/HelpCommands.js.map +1 -0
- package/build/cli/ui/HistoryItemDisplay.d.ts +9 -0
- package/build/cli/ui/HistoryItemDisplay.js +38 -0
- package/build/cli/ui/HistoryItemDisplay.js.map +1 -0
- package/build/cli/ui/InputPrompt-bestcase.d.ts +63 -0
- package/build/cli/ui/InputPrompt-bestcase.js +1301 -0
- package/build/cli/ui/InputPrompt-bestcase.js.map +1 -0
- package/build/cli/ui/InputPrompt.d.ts +12 -0
- package/build/cli/ui/InputPrompt.js +145 -0
- package/build/cli/ui/InputPrompt.js.map +1 -0
- package/build/cli/ui/InputPrompt.tmp.d.ts +7 -0
- package/build/cli/ui/InputPrompt.tmp.js +215 -0
- package/build/cli/ui/InputPrompt.tmp.js.map +1 -0
- package/build/cli/ui/MainContent.d.ts +10 -0
- package/build/cli/ui/MainContent.js +24 -0
- package/build/cli/ui/MainContent.js.map +1 -0
- package/build/cli/ui/MouseContext.d.ts +1 -0
- package/build/cli/ui/MouseContext.js +2 -0
- package/build/cli/ui/MouseContext.js.map +1 -0
- package/build/cli/ui/SuggestionsDisplay.d.ts +25 -0
- package/build/cli/ui/SuggestionsDisplay.js +45 -0
- package/build/cli/ui/SuggestionsDisplay.js.map +1 -0
- package/build/cli/ui/ThinkingIndicator.d.ts +2 -0
- package/build/cli/ui/ThinkingIndicator.js +16 -0
- package/build/cli/ui/ThinkingIndicator.js.map +1 -0
- package/build/cli/ui/layout/DefaultAppLayout.d.ts +2 -0
- package/build/cli/ui/layout/DefaultAppLayout.js +6 -0
- package/build/cli/ui/layout/DefaultAppLayout.js.map +1 -0
- package/build/cli/ui/shared/ExpandableText.d.ts +14 -0
- package/build/cli/ui/shared/ExpandableText.js +19 -0
- package/build/cli/ui/shared/ExpandableText.js.map +1 -0
- package/build/cli/utils/commandUtils.d.ts +11 -0
- package/build/cli/utils/commandUtils.js +16 -0
- package/build/cli/utils/commandUtils.js.map +1 -0
- package/build/cli/utils/debugLogger.d.ts +12 -0
- package/build/cli/utils/debugLogger.js +52 -0
- package/build/cli/utils/debugLogger.js.map +1 -0
- package/build/cli/utils/historyStorage.d.ts +13 -0
- package/build/cli/utils/historyStorage.js +64 -0
- package/build/cli/utils/historyStorage.js.map +1 -0
- package/build/cli/utils/textUtil.d.ts +68 -0
- package/build/cli/utils/textUtil.js +236 -0
- package/build/cli/utils/textUtil.js.map +1 -0
- package/build/db.js +55 -0
- package/build/db.js.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/tools/create_document_with_properties/index.d.ts +60 -0
- package/build/tools/create_document_with_properties/index.js +7 -1
- package/build/tools/create_document_with_properties/index.js.map +1 -0
- package/build/tools/create_document_with_properties/params.d.ts +66 -0
- package/build/tools/generate_property/index.js +6 -0
- package/build/tools/generate_property/index.js.map +1 -0
- package/build/tools/index.d.ts +184 -0
- package/build/tools/organize_attachments/index.js +7 -1
- package/build/tools/organize_attachments/index.js.map +1 -0
- package/build/tools/organize_attachments/params.d.ts +122 -0
- package/build/tools/vault/index.js +17 -3
- package/build/tools/vault/index.js.map +1 -0
- package/build/tools/vault/params.d.ts +115 -0
- package/build/tools/vault/types/collect_context.d.ts +1340 -0
- package/build/tools/vault/types/list_all.d.ts +387 -0
- package/build/tools/vault/types/read_specific.d.ts +297 -0
- package/build/tools/vault/types/search.d.ts +598 -0
- package/build/tools/vault/utils/actions/collect_context.js +26 -1
- package/build/tools/vault/utils/actions/collect_context.js.map +1 -0
- package/build/tools/vault/utils/actions/index_rag.js +27 -0
- package/build/tools/vault/utils/actions/index_rag.js.map +1 -0
- package/build/tools/vault/utils/actions/list_all.js +1 -0
- package/build/tools/vault/utils/actions/list_all.js.map +1 -0
- package/build/tools/vault/utils/actions/load_memory.js +23 -13
- package/build/tools/vault/utils/actions/load_memory.js.map +1 -0
- package/build/tools/vault/utils/actions/read.js +2 -1
- package/build/tools/vault/utils/actions/read.js.map +1 -0
- package/build/tools/vault/utils/actions/search.js +2 -1
- package/build/tools/vault/utils/actions/search.js.map +1 -0
- package/build/tools/vault/utils/actions/search_semantic.js +54 -0
- package/build/tools/vault/utils/actions/search_semantic.js.map +1 -0
- package/build/tools/vault/utils/actions/stats.js +1 -0
- package/build/tools/vault/utils/actions/stats.js.map +1 -0
- package/build/tools/vault/utils/document.js +1 -0
- package/build/tools/vault/utils/document.js.map +1 -0
- package/build/tools/write_property/index.d.ts +58 -0
- package/build/tools/write_property/index.js +7 -1
- package/build/tools/write_property/index.js.map +1 -0
- package/build/utils/DirectoryWalker.d.ts +6 -0
- package/build/utils/DirectoryWalker.js +7 -0
- package/build/utils/DirectoryWalker.js.map +1 -0
- package/build/utils/Indexer.d.ts +18 -0
- package/build/utils/Indexer.js +5 -9
- package/build/utils/Indexer.js.map +1 -0
- package/build/utils/LLMClient.d.ts +37 -0
- package/build/utils/LLMClient.js +82 -0
- package/build/utils/LLMClient.js.map +1 -0
- package/build/utils/RAGIndexer.d.ts +22 -0
- package/build/utils/RAGIndexer.js +206 -0
- package/build/utils/RAGIndexer.js.map +1 -0
- package/build/utils/RerankerClient.d.ts +27 -0
- package/build/utils/RerankerClient.js +69 -0
- package/build/utils/RerankerClient.js.map +1 -0
- package/build/utils/VaultManger/VaultManager.d.ts +34 -0
- package/build/utils/VaultManger/VaultManager.js +1 -0
- package/build/utils/VaultManger/VaultManager.js.map +1 -0
- package/build/utils/VaultManger/VaultPathError.d.ts +6 -0
- package/build/utils/VaultManger/VaultPathError.js +1 -0
- package/build/utils/VaultManger/VaultPathError.js.map +1 -0
- package/build/utils/VaultManger/index.d.ts +3 -0
- package/build/utils/VaultManger/index.js +1 -0
- package/build/utils/VaultManger/index.js.map +1 -0
- package/build/utils/VaultManger/types.d.ts +16 -0
- package/build/utils/VaultManger/types.js +1 -0
- package/build/utils/VaultManger/types.js.map +1 -0
- package/build/utils/VaultWatcher.d.ts +8 -0
- package/build/utils/VaultWatcher.js +96 -0
- package/build/utils/VaultWatcher.js.map +1 -0
- package/build/utils/VectorDB.d.ts +53 -0
- package/build/utils/VectorDB.js +243 -0
- package/build/utils/VectorDB.js.map +1 -0
- package/build/utils/createToolError.d.ts +2 -0
- package/build/utils/createToolError.js +1 -0
- package/build/utils/createToolError.js.map +1 -0
- package/build/utils/getVaultManager.d.ts +2 -0
- package/build/utils/getVaultManager.js +2 -1
- package/build/utils/getVaultManager.js.map +1 -0
- package/build/utils/processor/LinkExtractor.d.ts +2 -0
- package/build/utils/processor/LinkExtractor.js +1 -0
- package/build/utils/processor/LinkExtractor.js.map +1 -0
- package/build/utils/processor/MatterParser.d.ts +2 -0
- package/build/utils/processor/MatterParser.js +12 -3
- package/build/utils/processor/MatterParser.js.map +1 -0
- package/build/utils/processor/types.d.ts +100 -0
- package/package.json +29 -3
- package/build/config.js +0 -55
- package/build/server.js +0 -32
- package/build/tools/create_document_with_properties/params.js +0 -32
- package/build/tools/generate_property/params.js +0 -54
- package/build/tools/index.js +0 -12
- package/build/tools/organize_attachments/params.js +0 -60
- package/build/tools/organize_attachments/utils.js +0 -65
- package/build/tools/vault/metrics.js +0 -126
- package/build/tools/vault/params.js +0 -141
- package/build/tools/vault/types/collect_context.js +0 -102
- package/build/tools/vault/types/list_all.js +0 -52
- package/build/tools/vault/types/read_specific.js +0 -40
- package/build/tools/vault/types/search.js +0 -58
- package/build/tools/vault/utils/constants.js +0 -2
- package/build/tools/vault/utils/shared.js +0 -74
- package/build/tools/vault/utils.js +0 -6
- package/build/tools/write_property/params.js +0 -51
- package/build/utils/processor/types.js +0 -27
- package/build/utils/semaphore.js +0 -25
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { HELP_COMMAND_MARKER } from "../constants.js";
|
|
3
|
+
import { debugLogger } from "../utils/debugLogger.js";
|
|
4
|
+
function extractText(result) {
|
|
5
|
+
return result.content
|
|
6
|
+
.filter((c) => c.type === "text" && c.text)
|
|
7
|
+
.map((c) => c.text ?? "")
|
|
8
|
+
.join("\n");
|
|
9
|
+
}
|
|
10
|
+
function extractFilenameFromArgs(args) {
|
|
11
|
+
const quoted = args.match(/[\u201C"]([^\u201D"]+)[\u201D"]/) ??
|
|
12
|
+
args.match(/"([^"]+)"/) ??
|
|
13
|
+
args.match(/\u300C([^\u300D]+)\u300D/);
|
|
14
|
+
if (quoted?.[1]) {
|
|
15
|
+
return quoted[1].trim();
|
|
16
|
+
}
|
|
17
|
+
return args;
|
|
18
|
+
}
|
|
19
|
+
function parseKeyValueArgs(args) {
|
|
20
|
+
const result = {};
|
|
21
|
+
const regex = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))/g;
|
|
22
|
+
for (const match of args.matchAll(regex)) {
|
|
23
|
+
const key = match[1];
|
|
24
|
+
const value = match[2] ?? match[3] ?? match[4];
|
|
25
|
+
if (value === "true")
|
|
26
|
+
result[key] = true;
|
|
27
|
+
else if (value === "false")
|
|
28
|
+
result[key] = false;
|
|
29
|
+
else if (/^\d+$/.test(value))
|
|
30
|
+
result[key] = Number(value);
|
|
31
|
+
else
|
|
32
|
+
result[key] = value;
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
const COMMAND_MAP = {
|
|
37
|
+
"/search": {
|
|
38
|
+
tool: "vault",
|
|
39
|
+
requiresArgs: true,
|
|
40
|
+
noArgsMessage: "사용법: /search <검색어>",
|
|
41
|
+
buildArgs: (args) => ({
|
|
42
|
+
action: "search",
|
|
43
|
+
keyword: args,
|
|
44
|
+
limit: 10,
|
|
45
|
+
includeContent: true,
|
|
46
|
+
compressionMode: "balanced",
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
"/read": {
|
|
50
|
+
tool: "vault",
|
|
51
|
+
requiresArgs: true,
|
|
52
|
+
noArgsMessage: '사용법: /read <파일명>\n예: /read "브라우저의 교차 출처 리소스 공유(CORS).md"',
|
|
53
|
+
buildArgs: (args) => ({
|
|
54
|
+
action: "read",
|
|
55
|
+
filename: extractFilenameFromArgs(args),
|
|
56
|
+
}),
|
|
57
|
+
},
|
|
58
|
+
"/semantic": {
|
|
59
|
+
tool: "vault",
|
|
60
|
+
requiresArgs: true,
|
|
61
|
+
noArgsMessage: "사용법: /semantic <검색 쿼리>",
|
|
62
|
+
buildArgs: (args) => ({
|
|
63
|
+
action: "search_vault_by_semantic",
|
|
64
|
+
query: args,
|
|
65
|
+
limit: 5,
|
|
66
|
+
}),
|
|
67
|
+
},
|
|
68
|
+
"/stats": {
|
|
69
|
+
tool: "vault",
|
|
70
|
+
buildArgs: () => ({ action: "stats" }),
|
|
71
|
+
},
|
|
72
|
+
"/index": {
|
|
73
|
+
tool: "vault",
|
|
74
|
+
buildArgs: () => ({ action: "index_vault_to_vectordb" }),
|
|
75
|
+
},
|
|
76
|
+
"/context": {
|
|
77
|
+
tool: "vault",
|
|
78
|
+
requiresArgs: true,
|
|
79
|
+
noArgsMessage: "사용법: /context <토픽>",
|
|
80
|
+
buildArgs: (args) => ({
|
|
81
|
+
action: "collect_context",
|
|
82
|
+
topic: args,
|
|
83
|
+
scope: "topic",
|
|
84
|
+
maxDocs: 10,
|
|
85
|
+
memoryMode: "response_only",
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
"/organize": {
|
|
89
|
+
tool: "organize_attachments",
|
|
90
|
+
requiresArgs: true,
|
|
91
|
+
noArgsMessage: "사용법: /organize <검색키워드>",
|
|
92
|
+
buildArgs: (args) => ({ keyword: args }),
|
|
93
|
+
},
|
|
94
|
+
"/genprop": {
|
|
95
|
+
tool: "generate_property",
|
|
96
|
+
requiresArgs: true,
|
|
97
|
+
noArgsMessage: '사용법: /genprop <파일명>\n예: /genprop "my-post.md"',
|
|
98
|
+
buildArgs: (args) => ({
|
|
99
|
+
filename: extractFilenameFromArgs(args),
|
|
100
|
+
}),
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
async function handleReadFallback(args, callTool) {
|
|
104
|
+
const filename = extractFilenameFromArgs(args);
|
|
105
|
+
debugLogger.debug(`[Dispatcher] Read failed, trying search fallback for: "${filename}"`);
|
|
106
|
+
try {
|
|
107
|
+
const searchResult = await callTool("vault", {
|
|
108
|
+
action: "search",
|
|
109
|
+
keyword: filename,
|
|
110
|
+
limit: 5,
|
|
111
|
+
includeContent: false,
|
|
112
|
+
compressionMode: "aggressive",
|
|
113
|
+
});
|
|
114
|
+
if (!searchResult.isError) {
|
|
115
|
+
const searchText = extractText(searchResult);
|
|
116
|
+
if (searchText && !searchText.includes("No results")) {
|
|
117
|
+
return {
|
|
118
|
+
type: "tool_result",
|
|
119
|
+
content: `"${filename}" 파일을 찾지 못했습니다.\n\n유사한 문서:\n${searchText}\n\n💡 정확한 파일명으로 다시 시도하세요: /read "파일명.md"`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch { }
|
|
125
|
+
return {
|
|
126
|
+
type: "tool_result",
|
|
127
|
+
content: `"${filename}" 파일을 찾지 못했습니다.\n💡 /search ${filename} 으로 먼저 검색해보세요.`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function isToolAvailable(toolName, availableTools) {
|
|
131
|
+
return availableTools.some((t) => t.name === toolName);
|
|
132
|
+
}
|
|
133
|
+
function buildAvailableToolsHint(availableTools) {
|
|
134
|
+
if (availableTools.length === 0)
|
|
135
|
+
return "등록된 도구가 없습니다.";
|
|
136
|
+
return availableTools.map((t) => ` • ${t.name}`).join("\n");
|
|
137
|
+
}
|
|
138
|
+
function tryMatchDynamicTool(command, availableTools) {
|
|
139
|
+
const toolName = command.slice(1);
|
|
140
|
+
return availableTools.find((t) => t.name === toolName);
|
|
141
|
+
}
|
|
142
|
+
function buildDynamicArgs(rawArgs, tool) {
|
|
143
|
+
if (!rawArgs)
|
|
144
|
+
return {};
|
|
145
|
+
const kvArgs = parseKeyValueArgs(rawArgs);
|
|
146
|
+
if (Object.keys(kvArgs).length > 0)
|
|
147
|
+
return kvArgs;
|
|
148
|
+
if (rawArgs.startsWith("{")) {
|
|
149
|
+
try {
|
|
150
|
+
return JSON.parse(rawArgs);
|
|
151
|
+
}
|
|
152
|
+
catch { }
|
|
153
|
+
}
|
|
154
|
+
const extractedIdentifier = extractFilenameFromArgs(rawArgs);
|
|
155
|
+
const isExtracted = extractedIdentifier !== rawArgs &&
|
|
156
|
+
extractedIdentifier.length < rawArgs.length;
|
|
157
|
+
const schema = tool.inputSchema;
|
|
158
|
+
if (schema?.required?.length && schema.properties) {
|
|
159
|
+
for (const paramName of schema.required) {
|
|
160
|
+
const prop = schema.properties[paramName];
|
|
161
|
+
if (prop?.type === "string") {
|
|
162
|
+
const value = isExtracted ? extractedIdentifier : rawArgs;
|
|
163
|
+
debugLogger.debug(`[Dispatcher] Schema-based arg mapping: "${paramName}" ← ${isExtracted ? `extracted "${value}"` : "raw text"}`);
|
|
164
|
+
return { [paramName]: value };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const commonParamNames = [
|
|
169
|
+
"filename",
|
|
170
|
+
"keyword",
|
|
171
|
+
"query",
|
|
172
|
+
"sourcePath",
|
|
173
|
+
"filePath",
|
|
174
|
+
"name",
|
|
175
|
+
"input",
|
|
176
|
+
"text",
|
|
177
|
+
];
|
|
178
|
+
if (schema?.properties) {
|
|
179
|
+
for (const name of commonParamNames) {
|
|
180
|
+
if (name in schema.properties) {
|
|
181
|
+
const value = isExtracted ? extractedIdentifier : rawArgs;
|
|
182
|
+
return { [name]: value };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return { input: isExtracted ? extractedIdentifier : rawArgs };
|
|
187
|
+
}
|
|
188
|
+
export function useDispatcher(availableTools = []) {
|
|
189
|
+
const handleDispatch = useCallback(async (text, callTool) => {
|
|
190
|
+
const trimmed = text.trim();
|
|
191
|
+
const [command, ...argParts] = trimmed.split(/\s+/);
|
|
192
|
+
const args = argParts.join(" ").trim();
|
|
193
|
+
debugLogger.debug(`[Dispatcher] Command: ${command}, Args: "${args}"`);
|
|
194
|
+
switch (command) {
|
|
195
|
+
case "/help":
|
|
196
|
+
return { type: "local_action", content: HELP_COMMAND_MARKER };
|
|
197
|
+
case "/clear":
|
|
198
|
+
return { type: "local_action", content: "__CLEAR_HISTORY__" };
|
|
199
|
+
case "/tools":
|
|
200
|
+
return { type: "local_action", content: "__LIST_TOOLS__" };
|
|
201
|
+
}
|
|
202
|
+
const mapping = COMMAND_MAP[command];
|
|
203
|
+
if (mapping) {
|
|
204
|
+
if (availableTools.length > 0 &&
|
|
205
|
+
!isToolAvailable(mapping.tool, availableTools)) {
|
|
206
|
+
return {
|
|
207
|
+
type: "tool_result",
|
|
208
|
+
content: `도구 "${mapping.tool}"이(가) 현재 연결된 MCP 서버에 등록되어 있지 않습니다.\n\n` +
|
|
209
|
+
`사용 가능한 도구:\n${buildAvailableToolsHint(availableTools)}`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (mapping.requiresArgs && !args) {
|
|
213
|
+
return {
|
|
214
|
+
type: "tool_result",
|
|
215
|
+
content: mapping.noArgsMessage ?? "인자가 필요합니다.",
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const toolArgs = mapping.buildArgs(args);
|
|
219
|
+
return executeToolCall(command, mapping.tool, toolArgs, args, callTool, text);
|
|
220
|
+
}
|
|
221
|
+
const dynamicTool = tryMatchDynamicTool(command, availableTools);
|
|
222
|
+
if (dynamicTool) {
|
|
223
|
+
const toolArgs = buildDynamicArgs(args, dynamicTool);
|
|
224
|
+
debugLogger.debug(`[Dispatcher] Dynamic tool dispatch: ${dynamicTool.name}`, JSON.stringify(toolArgs).slice(0, 200));
|
|
225
|
+
return executeToolCall(command, dynamicTool.name, toolArgs, args, callTool, text);
|
|
226
|
+
}
|
|
227
|
+
const hint = availableTools.length > 0
|
|
228
|
+
? `\n\n사용 가능한 도구 (/<tool_name> 형태로 직접 호출 가능):\n${buildAvailableToolsHint(availableTools)}`
|
|
229
|
+
: "";
|
|
230
|
+
return {
|
|
231
|
+
type: "unknown_command",
|
|
232
|
+
content: `알 수 없는 커맨드: ${command}\n/help 를 입력하여 사용 가능한 커맨드를 확인하세요.${hint}`,
|
|
233
|
+
};
|
|
234
|
+
}, [availableTools]);
|
|
235
|
+
return { handleDispatch };
|
|
236
|
+
}
|
|
237
|
+
async function executeToolCall(command, toolName, toolArgs, rawArgs, callTool, userIntent) {
|
|
238
|
+
try {
|
|
239
|
+
const result = await callTool(toolName, toolArgs);
|
|
240
|
+
if (result.isError) {
|
|
241
|
+
if (command === "/read") {
|
|
242
|
+
return handleReadFallback(rawArgs, callTool);
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
type: "tool_result",
|
|
246
|
+
content: `실행 실패: ${extractText(result)}`,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
const text = extractText(result);
|
|
250
|
+
if (isLlmInstructionPayload(text)) {
|
|
251
|
+
debugLogger.info(`[Dispatcher] Tool "${toolName}" returned LLM instruction payload — routing to LLM`);
|
|
252
|
+
return {
|
|
253
|
+
type: "llm_required",
|
|
254
|
+
content: text,
|
|
255
|
+
userIntent: userIntent ?? rawArgs,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
type: "tool_result",
|
|
260
|
+
content: text || "결과가 없습니다.",
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
265
|
+
debugLogger.error(`[Dispatcher] Tool call failed:`, msg);
|
|
266
|
+
return {
|
|
267
|
+
type: "tool_result",
|
|
268
|
+
content: `도구 호출 오류: ${msg}`,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function isLlmInstructionPayload(text) {
|
|
273
|
+
try {
|
|
274
|
+
const parsed = JSON.parse(text);
|
|
275
|
+
return (parsed !== null &&
|
|
276
|
+
typeof parsed === "object" &&
|
|
277
|
+
"instructions" in parsed &&
|
|
278
|
+
typeof parsed.instructions === "object" &&
|
|
279
|
+
parsed.instructions !== null &&
|
|
280
|
+
("purpose" in parsed.instructions || "usage" in parsed.instructions));
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=useDispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDispatcher.js","sourceRoot":"","sources":["../../../src/cli/hooks/useDispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFocus.js","sourceRoot":"","sources":["../../../src/cli/hooks/useFocus.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,SAAS,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface Logger {
|
|
2
|
+
getPreviousUserMessages(): Promise<string[]>;
|
|
3
|
+
}
|
|
4
|
+
export interface UseInputHistoryStoreReturn {
|
|
5
|
+
inputHistory: string[];
|
|
6
|
+
addInput: (input: string) => void;
|
|
7
|
+
initializeFromLogger: (logger: Logger | null) => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
interface UseInputHistoryProps {
|
|
10
|
+
userMessages: readonly string[];
|
|
11
|
+
onSubmit: (value: string) => void;
|
|
12
|
+
isActive: boolean;
|
|
13
|
+
currentQuery: string;
|
|
14
|
+
currentCursorOffset: number;
|
|
15
|
+
onChange: (value: string, cursorPosition?: "start" | "end" | number) => void;
|
|
16
|
+
}
|
|
17
|
+
export interface UseInputHistoryReturn {
|
|
18
|
+
handleSubmit: (value: string) => void;
|
|
19
|
+
navigateUp: () => boolean;
|
|
20
|
+
navigateDown: () => boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function useInputHistory({ userMessages, onSubmit, isActive, currentQuery, currentCursorOffset, onChange, }: UseInputHistoryProps): UseInputHistoryReturn;
|
|
23
|
+
export declare function useInputHistoryStore(): UseInputHistoryStoreReturn;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
import { debugLogger } from "../utils/debugLogger.js";
|
|
3
|
+
import { cpLen } from "../utils/textUtil.js";
|
|
4
|
+
export function useInputHistory({ userMessages, onSubmit, isActive, currentQuery, currentCursorOffset, onChange, }) {
|
|
5
|
+
const [historyIndex, setHistoryIndex] = useState(-1);
|
|
6
|
+
// previousHistoryIndexRef tracks the index we occupied *immediately before* the current historyIndex.
|
|
7
|
+
// This allows us to detect when we are "returning" to a level we just left.
|
|
8
|
+
const previousHistoryIndexRef = useRef(undefined);
|
|
9
|
+
// Cache stores text and cursor offset for each history index level.
|
|
10
|
+
// Level -1 is the current unsubmitted prompt.
|
|
11
|
+
const historyCacheRef = useRef({});
|
|
12
|
+
const resetHistoryNav = useCallback(() => {
|
|
13
|
+
setHistoryIndex(-1);
|
|
14
|
+
previousHistoryIndexRef.current = undefined;
|
|
15
|
+
historyCacheRef.current = {};
|
|
16
|
+
}, []);
|
|
17
|
+
const handleSubmit = useCallback((value) => {
|
|
18
|
+
const trimmedValue = value.trim();
|
|
19
|
+
if (trimmedValue) {
|
|
20
|
+
onSubmit(trimmedValue); // Parent handles clearing the query
|
|
21
|
+
}
|
|
22
|
+
resetHistoryNav();
|
|
23
|
+
}, [onSubmit, resetHistoryNav]);
|
|
24
|
+
const navigateTo = useCallback((nextIndex, defaultCursor) => {
|
|
25
|
+
const prevIndexBeforeMove = historyIndex;
|
|
26
|
+
// 1. Save current state to cache before moving
|
|
27
|
+
historyCacheRef.current[prevIndexBeforeMove] = {
|
|
28
|
+
text: currentQuery,
|
|
29
|
+
offset: currentCursorOffset,
|
|
30
|
+
};
|
|
31
|
+
// 2. Update index
|
|
32
|
+
setHistoryIndex(nextIndex);
|
|
33
|
+
// 3. Restore next state
|
|
34
|
+
const saved = historyCacheRef.current[nextIndex];
|
|
35
|
+
// We robustly restore the cursor position IF:
|
|
36
|
+
// 1. We are returning to the compose prompt (-1)
|
|
37
|
+
// 2. OR we are returning to the level we occupied *just before* the current one.
|
|
38
|
+
// AND in both cases, the cursor was not at the very first or last character.
|
|
39
|
+
const isReturningToPrevious = nextIndex === -1 || nextIndex === previousHistoryIndexRef.current;
|
|
40
|
+
if (isReturningToPrevious &&
|
|
41
|
+
saved &&
|
|
42
|
+
saved.offset > 0 &&
|
|
43
|
+
saved.offset < cpLen(saved.text)) {
|
|
44
|
+
onChange(saved.text, saved.offset);
|
|
45
|
+
}
|
|
46
|
+
else if (nextIndex === -1) {
|
|
47
|
+
onChange(saved ? saved.text : "", defaultCursor);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// For regular history browsing, use default cursor position.
|
|
51
|
+
if (saved) {
|
|
52
|
+
onChange(saved.text, defaultCursor);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const newValue = userMessages[userMessages.length - 1 - nextIndex];
|
|
56
|
+
onChange(newValue, defaultCursor);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Record the level we just came from for the next navigation
|
|
60
|
+
previousHistoryIndexRef.current = prevIndexBeforeMove;
|
|
61
|
+
}, [historyIndex, currentQuery, currentCursorOffset, userMessages, onChange]);
|
|
62
|
+
const navigateUp = useCallback(() => {
|
|
63
|
+
if (!isActive)
|
|
64
|
+
return false;
|
|
65
|
+
if (userMessages.length === 0)
|
|
66
|
+
return false;
|
|
67
|
+
if (historyIndex < userMessages.length - 1) {
|
|
68
|
+
navigateTo(historyIndex + 1, "start");
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}, [historyIndex, userMessages, isActive, navigateTo]);
|
|
73
|
+
const navigateDown = useCallback(() => {
|
|
74
|
+
if (!isActive)
|
|
75
|
+
return false;
|
|
76
|
+
if (historyIndex === -1)
|
|
77
|
+
return false; // Not currently navigating history
|
|
78
|
+
navigateTo(historyIndex - 1, "end");
|
|
79
|
+
return true;
|
|
80
|
+
}, [historyIndex, isActive, navigateTo]);
|
|
81
|
+
return {
|
|
82
|
+
handleSubmit,
|
|
83
|
+
navigateUp,
|
|
84
|
+
navigateDown,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function useInputHistoryStore() {
|
|
88
|
+
const [inputHistory, setInputHistory] = useState([]);
|
|
89
|
+
const [_pastSessionMessages, setPastSessionMessages] = useState([]);
|
|
90
|
+
const [_currentSessionMessages, setCurrentSessionMessages] = useState([]);
|
|
91
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
92
|
+
/**
|
|
93
|
+
* Recalculate the complete input history from past and current sessions.
|
|
94
|
+
* Applies the same deduplication logic as the previous implementation.
|
|
95
|
+
*/
|
|
96
|
+
const recalculateHistory = useCallback((currentSession, pastSession) => {
|
|
97
|
+
// Combine current session (newest first) + past session (newest first)
|
|
98
|
+
const combinedMessages = [...currentSession, ...pastSession];
|
|
99
|
+
// Deduplicate consecutive identical messages (same algorithm as before)
|
|
100
|
+
const deduplicatedMessages = [];
|
|
101
|
+
if (combinedMessages.length > 0) {
|
|
102
|
+
deduplicatedMessages.push(combinedMessages[0]); // Add the newest one unconditionally
|
|
103
|
+
for (let i = 1; i < combinedMessages.length; i++) {
|
|
104
|
+
if (combinedMessages[i] !== combinedMessages[i - 1]) {
|
|
105
|
+
deduplicatedMessages.push(combinedMessages[i]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Reverse to oldest first for useInputHistory
|
|
110
|
+
setInputHistory(deduplicatedMessages.reverse());
|
|
111
|
+
}, []);
|
|
112
|
+
/**
|
|
113
|
+
* Initialize input history from logger with past session data.
|
|
114
|
+
* Executed only once at app startup.
|
|
115
|
+
*/
|
|
116
|
+
const initializeFromLogger = useCallback(async (logger) => {
|
|
117
|
+
if (isInitialized || !logger)
|
|
118
|
+
return;
|
|
119
|
+
try {
|
|
120
|
+
const pastMessages = (await logger.getPreviousUserMessages()) || [];
|
|
121
|
+
setPastSessionMessages(pastMessages); // Store as newest first
|
|
122
|
+
recalculateHistory([], pastMessages);
|
|
123
|
+
setIsInitialized(true);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
// Start with empty history even if logger initialization fails
|
|
127
|
+
debugLogger.warn("Failed to initialize input history from logger:", error);
|
|
128
|
+
setPastSessionMessages([]);
|
|
129
|
+
recalculateHistory([], []);
|
|
130
|
+
setIsInitialized(true);
|
|
131
|
+
}
|
|
132
|
+
}, [isInitialized, recalculateHistory]);
|
|
133
|
+
/**
|
|
134
|
+
* Add new input to history.
|
|
135
|
+
* Recalculates the entire history with deduplication.
|
|
136
|
+
*/
|
|
137
|
+
const addInput = useCallback((input) => {
|
|
138
|
+
const trimmedInput = input.trim();
|
|
139
|
+
if (!trimmedInput)
|
|
140
|
+
return; // Filter empty/whitespace-only inputs
|
|
141
|
+
setCurrentSessionMessages((prevCurrent) => {
|
|
142
|
+
const newCurrentSession = [...prevCurrent, trimmedInput];
|
|
143
|
+
setPastSessionMessages((prevPast) => {
|
|
144
|
+
recalculateHistory(newCurrentSession
|
|
145
|
+
.slice()
|
|
146
|
+
.reverse(), // Convert to newest first
|
|
147
|
+
prevPast);
|
|
148
|
+
return prevPast; // No change to past messages
|
|
149
|
+
});
|
|
150
|
+
return newCurrentSession;
|
|
151
|
+
});
|
|
152
|
+
}, [recalculateHistory]);
|
|
153
|
+
return {
|
|
154
|
+
inputHistory,
|
|
155
|
+
addInput,
|
|
156
|
+
initializeFromLogger,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=useInputHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInputHistory.js","sourceRoot":"","sources":["../../../src/cli/hooks/useInputHistory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type React from "react";
|
|
7
|
+
import { type KeyMatchers } from "../key/keyMatchers.js";
|
|
8
|
+
export declare const KeyMatchersContext: React.Context<KeyMatchers>;
|
|
9
|
+
export declare const KeyMatchersProvider: ({ children, value, }: {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
value: KeyMatchers;
|
|
12
|
+
}) => React.JSX.Element;
|
|
13
|
+
/**
|
|
14
|
+
* Hook to retrieve the currently active key matchers.
|
|
15
|
+
* Defaults to defaultKeyMatchers if no provider is present, allowing tests to run without explicit wrappers.
|
|
16
|
+
*/
|
|
17
|
+
export declare function useKeyMatchers(): KeyMatchers;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
import { defaultKeyMatchers } from "../key/keyMatchers.js";
|
|
4
|
+
export const KeyMatchersContext = createContext(defaultKeyMatchers);
|
|
5
|
+
export const KeyMatchersProvider = ({ children, value, }) => (_jsx(KeyMatchersContext.Provider, { value: value, children: children }));
|
|
6
|
+
/**
|
|
7
|
+
* Hook to retrieve the currently active key matchers.
|
|
8
|
+
* Defaults to defaultKeyMatchers if no provider is present, allowing tests to run without explicit wrappers.
|
|
9
|
+
*/
|
|
10
|
+
export function useKeyMatchers() {
|
|
11
|
+
return useContext(KeyMatchersContext);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=useKeyMatchers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeyMatchers.js","sourceRoot":"","sources":["../../../src/cli/hooks/useKeyMatchers.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,uBAAuB,CAAC;AAE7E,MAAM,CAAC,MAAM,kBAAkB,GAC9B,aAAa,CAAc,kBAAkB,CAAC,CAAC;AAEhD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EACnC,QAAQ,EACR,KAAK,GAIL,EAAqB,EAAE,CAAC,CACxB,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACvC,QAAQ,GACoB,CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC7B,OAAO,UAAU,CAAC,kBAAkB,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { type Key, type KeypressHandler, type KeypressPriority } from "../context/KeypressContext.js";
|
|
7
|
+
export type { Key };
|
|
8
|
+
/**
|
|
9
|
+
* A hook that listens for keypress events from stdin.
|
|
10
|
+
*
|
|
11
|
+
* @param onKeypress - The callback function to execute on each keypress.
|
|
12
|
+
* @param options - Options to control the hook's behavior.
|
|
13
|
+
* @param options.isActive - Whether the hook should be actively listening for input.
|
|
14
|
+
* @param options.priority - Priority level (integer or KeypressPriority enum) or boolean for backward compatibility.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useKeypress(onKeypress: KeypressHandler, { isActive, priority, }: {
|
|
17
|
+
isActive: boolean;
|
|
18
|
+
priority?: KeypressPriority | boolean;
|
|
19
|
+
}): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { useEffect } from "react";
|
|
7
|
+
import { useKeypressContext, } from "../context/KeypressContext.js";
|
|
8
|
+
/**
|
|
9
|
+
* A hook that listens for keypress events from stdin.
|
|
10
|
+
*
|
|
11
|
+
* @param onKeypress - The callback function to execute on each keypress.
|
|
12
|
+
* @param options - Options to control the hook's behavior.
|
|
13
|
+
* @param options.isActive - Whether the hook should be actively listening for input.
|
|
14
|
+
* @param options.priority - Priority level (integer or KeypressPriority enum) or boolean for backward compatibility.
|
|
15
|
+
*/
|
|
16
|
+
export function useKeypress(onKeypress, { isActive, priority, }) {
|
|
17
|
+
const { subscribe, unsubscribe } = useKeypressContext();
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!isActive) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
subscribe(onKeypress, priority);
|
|
23
|
+
return () => {
|
|
24
|
+
unsubscribe(onKeypress);
|
|
25
|
+
};
|
|
26
|
+
}, [isActive, onKeypress, subscribe, unsubscribe, priority]);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=useKeypress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeypress.js","sourceRoot":"","sources":["../../../src/cli/hooks/useKeypress.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAIN,kBAAkB,GAClB,MAAM,+BAA+B,CAAC;AAIvC;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAC1B,UAA2B,EAC3B,EACC,QAAQ,EACR,QAAQ,GACsD;IAE/D,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAExD,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,OAAO;QACR,CAAC;QAED,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO,GAAG,EAAE;YACX,WAAW,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpToolInfo } from "../services/McpClientService.js";
|
|
2
|
+
import type { CallToolFn, PendingItem, StreamingState } from "../types.js";
|
|
3
|
+
export interface LlmStreamState {
|
|
4
|
+
pendingItem: PendingItem | null;
|
|
5
|
+
streamingState: StreamingState;
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
sendMessage: (text: string, ragContext?: string | null) => Promise<void>;
|
|
9
|
+
reset: () => void;
|
|
10
|
+
clearHistory: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const useLlmStream: (callTool?: CallToolFn, availableTools?: McpToolInfo[]) => LlmStreamState;
|