hdsp-jupyter-extension 2.0.8__py3-none-any.whl → 2.0.10__py3-none-any.whl
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.
- agent_server/core/rag_manager.py +12 -3
- agent_server/core/retriever.py +2 -1
- agent_server/core/vllm_embedding_service.py +8 -5
- agent_server/langchain/ARCHITECTURE.md +7 -51
- agent_server/langchain/agent.py +31 -20
- agent_server/langchain/custom_middleware.py +148 -31
- agent_server/langchain/hitl_config.py +0 -8
- agent_server/langchain/llm_factory.py +85 -1
- agent_server/langchain/logging_utils.py +7 -7
- agent_server/langchain/prompts.py +45 -36
- agent_server/langchain/tools/__init__.py +1 -10
- agent_server/langchain/tools/file_tools.py +9 -61
- agent_server/langchain/tools/jupyter_tools.py +0 -1
- agent_server/langchain/tools/lsp_tools.py +8 -8
- agent_server/langchain/tools/resource_tools.py +12 -12
- agent_server/langchain/tools/search_tools.py +3 -158
- agent_server/routers/langchain_agent.py +122 -113
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/build_log.json +1 -1
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/package.json +2 -2
- hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.8740a527757068814573.js → hdsp_jupyter_extension-2.0.10.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.2d9fb488c82498c45c2d.js +93 -4
- hdsp_jupyter_extension-2.0.10.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.2d9fb488c82498c45c2d.js.map +1 -0
- hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.e4ff4b5779b5e049f84c.js → hdsp_jupyter_extension-2.0.10.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.dc6434bee96ab03a0539.js +90 -71
- hdsp_jupyter_extension-2.0.10.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.dc6434bee96ab03a0539.js.map +1 -0
- hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.020cdb0b864cfaa4e41e.js → hdsp_jupyter_extension-2.0.10.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.4a252df3ade74efee8d6.js +6 -6
- hdsp_jupyter_extension-2.0.10.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.4a252df3ade74efee8d6.js.map +1 -0
- {hdsp_jupyter_extension-2.0.8.dist-info → hdsp_jupyter_extension-2.0.10.dist-info}/METADATA +1 -3
- {hdsp_jupyter_extension-2.0.8.dist-info → hdsp_jupyter_extension-2.0.10.dist-info}/RECORD +57 -57
- jupyter_ext/_version.py +1 -1
- jupyter_ext/labextension/build_log.json +1 -1
- jupyter_ext/labextension/package.json +2 -2
- jupyter_ext/labextension/static/{frontend_styles_index_js.8740a527757068814573.js → frontend_styles_index_js.2d9fb488c82498c45c2d.js} +93 -4
- jupyter_ext/labextension/static/frontend_styles_index_js.2d9fb488c82498c45c2d.js.map +1 -0
- jupyter_ext/labextension/static/{lib_index_js.e4ff4b5779b5e049f84c.js → lib_index_js.dc6434bee96ab03a0539.js} +90 -71
- jupyter_ext/labextension/static/lib_index_js.dc6434bee96ab03a0539.js.map +1 -0
- jupyter_ext/labextension/static/{remoteEntry.020cdb0b864cfaa4e41e.js → remoteEntry.4a252df3ade74efee8d6.js} +6 -6
- jupyter_ext/labextension/static/remoteEntry.4a252df3ade74efee8d6.js.map +1 -0
- hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/frontend_styles_index_js.8740a527757068814573.js.map +0 -1
- hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/lib_index_js.e4ff4b5779b5e049f84c.js.map +0 -1
- hdsp_jupyter_extension-2.0.8.data/data/share/jupyter/labextensions/hdsp-agent/static/remoteEntry.020cdb0b864cfaa4e41e.js.map +0 -1
- jupyter_ext/labextension/static/frontend_styles_index_js.8740a527757068814573.js.map +0 -1
- jupyter_ext/labextension/static/lib_index_js.e4ff4b5779b5e049f84c.js.map +0 -1
- jupyter_ext/labextension/static/remoteEntry.020cdb0b864cfaa4e41e.js.map +0 -1
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/etc/jupyter/jupyter_server_config.d/hdsp_jupyter_extension.json +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/install.json +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b80.c095373419d05e6f141a.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/node_modules_emotion_use-insertion-effect-with-fallbacks_dist_emotion-use-insertion-effect-wi-3ba6b81.61e75fb98ecff46cf836.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/style.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_babel_runtime_helpers_esm_extends_js-node_modules_emotion_serialize_dist-051195.e2553aab0c3963b83dd7.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_cache_dist_emotion-cache_browser_development_esm_js.24edcc52a1c014a8a5f0.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_react_dist_emotion-react_browser_development_esm_js.19ecf6babe00caff6b8a.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_emotion_styled_dist_emotion-styled_browser_development_esm_js.661fb5836f4978a7c6e1.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_index_js.985697e0162d8d088ca2.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js +0 -0
- {hdsp_jupyter_extension-2.0.8.data → hdsp_jupyter_extension-2.0.10.data}/data/share/jupyter/labextensions/hdsp-agent/static/vendors-node_modules_mui_material_utils_createSvgIcon_js.1f5038488cdfd8b3a85d.js.map +0 -0
- {hdsp_jupyter_extension-2.0.8.dist-info → hdsp_jupyter_extension-2.0.10.dist-info}/WHEEL +0 -0
- {hdsp_jupyter_extension-2.0.8.dist-info → hdsp_jupyter_extension-2.0.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -1157,10 +1157,8 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
1157
1157
|
console.log('[AgentPanel] Captured agentThreadId from interrupt:', interrupt.threadId);
|
|
1158
1158
|
}
|
|
1159
1159
|
// Auto-approve search/file/resource tools - execute immediately without user interaction
|
|
1160
|
-
if (interrupt.action === '
|
|
1161
|
-
|| interrupt.action === 'search_notebook_cells_tool'
|
|
1160
|
+
if (interrupt.action === 'search_notebook_cells_tool'
|
|
1162
1161
|
|| interrupt.action === 'check_resource_tool'
|
|
1163
|
-
|| interrupt.action === 'list_files_tool'
|
|
1164
1162
|
|| interrupt.action === 'read_file_tool') {
|
|
1165
1163
|
void handleAutoToolInterrupt(interrupt);
|
|
1166
1164
|
return;
|
|
@@ -2212,8 +2210,12 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2212
2210
|
if (!pathCheck.valid) {
|
|
2213
2211
|
return { success: false, error: pathCheck.error };
|
|
2214
2212
|
}
|
|
2215
|
-
|
|
2216
|
-
const
|
|
2213
|
+
// Support both old (maxLines) and new (offset/limit) parameters
|
|
2214
|
+
const offset = typeof params.offset === 'number' ? Math.max(0, params.offset) : 0;
|
|
2215
|
+
const limit = typeof params.limit === 'number'
|
|
2216
|
+
? params.limit
|
|
2217
|
+
: (typeof params.maxLines === 'number' ? params.maxLines : 500);
|
|
2218
|
+
const safeLimit = Math.max(0, limit);
|
|
2217
2219
|
const contentsResult = await fetchContentsModel(params.path, { content: true, format: 'text' });
|
|
2218
2220
|
if (!contentsResult.success) {
|
|
2219
2221
|
return { success: false, error: contentsResult.error };
|
|
@@ -2233,13 +2235,18 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2233
2235
|
content = JSON.stringify(content, null, 2);
|
|
2234
2236
|
}
|
|
2235
2237
|
const lines = content.split('\n');
|
|
2236
|
-
const
|
|
2238
|
+
const totalLines = lines.length;
|
|
2239
|
+
// Apply offset and limit
|
|
2240
|
+
const sliced = lines.slice(offset, offset + safeLimit);
|
|
2237
2241
|
return {
|
|
2238
2242
|
success: true,
|
|
2239
2243
|
output: sliced.join('\n'),
|
|
2240
2244
|
metadata: {
|
|
2241
2245
|
lineCount: sliced.length,
|
|
2242
|
-
|
|
2246
|
+
totalLines,
|
|
2247
|
+
offset,
|
|
2248
|
+
limit: safeLimit,
|
|
2249
|
+
truncated: totalLines > offset + safeLimit
|
|
2243
2250
|
}
|
|
2244
2251
|
};
|
|
2245
2252
|
};
|
|
@@ -2249,18 +2256,7 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2249
2256
|
console.log('[AgentPanel] Auto-approving tool:', action, args);
|
|
2250
2257
|
try {
|
|
2251
2258
|
let executionResult;
|
|
2252
|
-
if (action === '
|
|
2253
|
-
setDebugStatus(`🔍 검색 실행 중: ${args?.pattern || ''}`);
|
|
2254
|
-
executionResult = await apiService.searchWorkspace({
|
|
2255
|
-
pattern: args?.pattern || '',
|
|
2256
|
-
file_types: args?.file_types || ['*.py', '*.ipynb'],
|
|
2257
|
-
path: args?.path || '.',
|
|
2258
|
-
max_results: args?.max_results || 50,
|
|
2259
|
-
case_sensitive: args?.case_sensitive || false
|
|
2260
|
-
});
|
|
2261
|
-
console.log('[AgentPanel] search_workspace result:', executionResult);
|
|
2262
|
-
}
|
|
2263
|
-
else if (action === 'search_notebook_cells_tool') {
|
|
2259
|
+
if (action === 'search_notebook_cells_tool') {
|
|
2264
2260
|
setDebugStatus(`🔍 노트북 검색 실행 중: ${args?.pattern || ''}`);
|
|
2265
2261
|
executionResult = await apiService.searchNotebookCells({
|
|
2266
2262
|
pattern: args?.pattern || '',
|
|
@@ -2282,22 +2278,13 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2282
2278
|
});
|
|
2283
2279
|
console.log('[AgentPanel] check_resource result:', executionResult);
|
|
2284
2280
|
}
|
|
2285
|
-
else if (action === 'list_files_tool') {
|
|
2286
|
-
setDebugStatus('📂 파일 목록 조회 중...');
|
|
2287
|
-
const listParams = {
|
|
2288
|
-
path: typeof args?.path === 'string' ? args.path : '.',
|
|
2289
|
-
recursive: args?.recursive ?? false,
|
|
2290
|
-
pattern: args?.pattern ?? undefined
|
|
2291
|
-
};
|
|
2292
|
-
executionResult = await executeListFilesTool(listParams);
|
|
2293
|
-
console.log('[AgentPanel] list_files result:', executionResult);
|
|
2294
|
-
}
|
|
2295
2281
|
else if (action === 'read_file_tool') {
|
|
2296
2282
|
setDebugStatus('📄 파일 읽는 중...');
|
|
2297
2283
|
const readParams = {
|
|
2298
2284
|
path: typeof args?.path === 'string' ? args.path : '',
|
|
2299
2285
|
encoding: typeof args?.encoding === 'string' ? args.encoding : undefined,
|
|
2300
|
-
|
|
2286
|
+
offset: typeof args?.offset === 'number' ? args.offset : 0,
|
|
2287
|
+
limit: typeof args?.limit === 'number' ? args.limit : (args?.max_lines ?? args?.maxLines ?? 500)
|
|
2301
2288
|
};
|
|
2302
2289
|
executionResult = await executeReadFileTool(readParams);
|
|
2303
2290
|
console.log('[AgentPanel] read_file result:', executionResult);
|
|
@@ -2341,10 +2328,8 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2341
2328
|
approvalPendingRef.current = true;
|
|
2342
2329
|
const autoApproveEnabled = getAutoApproveEnabled(llmConfig || (0,_services_ApiKeyManager__WEBPACK_IMPORTED_MODULE_4__.getLLMConfig)() || (0,_services_ApiKeyManager__WEBPACK_IMPORTED_MODULE_4__.getDefaultLLMConfig)());
|
|
2343
2330
|
// Handle next interrupt (could be another search or code execution)
|
|
2344
|
-
if (nextInterrupt.action === '
|
|
2345
|
-
|| nextInterrupt.action === 'search_notebook_cells_tool'
|
|
2331
|
+
if (nextInterrupt.action === 'search_notebook_cells_tool'
|
|
2346
2332
|
|| nextInterrupt.action === 'check_resource_tool'
|
|
2347
|
-
|| nextInterrupt.action === 'list_files_tool'
|
|
2348
2333
|
|| nextInterrupt.action === 'read_file_tool') {
|
|
2349
2334
|
void handleAutoToolInterrupt(nextInterrupt);
|
|
2350
2335
|
return;
|
|
@@ -2673,7 +2658,7 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2673
2658
|
};
|
|
2674
2659
|
}
|
|
2675
2660
|
else {
|
|
2676
|
-
// LSP not available - suggest using
|
|
2661
|
+
// LSP not available - suggest using execute_command_tool with grep
|
|
2677
2662
|
console.log('[AgentPanel] LSP not available for references, suggesting grep fallback');
|
|
2678
2663
|
resumeDecision = 'approve';
|
|
2679
2664
|
resumeArgs = {
|
|
@@ -2839,10 +2824,8 @@ const ChatPanel = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ apiServic
|
|
|
2839
2824
|
approvalPendingRef.current = true;
|
|
2840
2825
|
const autoApproveEnabled = getAutoApproveEnabled(llmConfig || (0,_services_ApiKeyManager__WEBPACK_IMPORTED_MODULE_4__.getLLMConfig)() || (0,_services_ApiKeyManager__WEBPACK_IMPORTED_MODULE_4__.getDefaultLLMConfig)());
|
|
2841
2826
|
// Auto-approve search/file/resource tools
|
|
2842
|
-
if (nextInterrupt.action === '
|
|
2843
|
-
|| nextInterrupt.action === 'search_notebook_cells_tool'
|
|
2827
|
+
if (nextInterrupt.action === 'search_notebook_cells_tool'
|
|
2844
2828
|
|| nextInterrupt.action === 'check_resource_tool'
|
|
2845
|
-
|| nextInterrupt.action === 'list_files_tool'
|
|
2846
2829
|
|| nextInterrupt.action === 'read_file_tool') {
|
|
2847
2830
|
void handleAutoToolInterrupt(nextInterrupt);
|
|
2848
2831
|
return;
|
|
@@ -5699,10 +5682,10 @@ class IdleMonitorService {
|
|
|
5699
5682
|
console.log('[IdleMonitor] Idle timeout reached. Triggering shutdown...');
|
|
5700
5683
|
// Hide countdown
|
|
5701
5684
|
this.hideCountdown();
|
|
5702
|
-
//
|
|
5685
|
+
// Call shutdown API FIRST (non-blocking) - shutdown starts immediately
|
|
5686
|
+
this.callShutdownApi().catch(e => console.error('[IdleMonitor] Shutdown API error:', e));
|
|
5687
|
+
// Show notification popup (for user info only - shutdown already initiated)
|
|
5703
5688
|
alert(`${this.idleTimeoutMinutes}분 동안 활동이 없어 세션이 종료됩니다.`);
|
|
5704
|
-
// Call shutdown API
|
|
5705
|
-
await this.callShutdownApi();
|
|
5706
5689
|
}
|
|
5707
5690
|
/**
|
|
5708
5691
|
* Call HDSP shutdown API via Jupyter server endpoint
|
|
@@ -6059,7 +6042,7 @@ class LSPBridgeService {
|
|
|
6059
6042
|
};
|
|
6060
6043
|
}
|
|
6061
6044
|
// TODO: jupyterlab-lsp 연결 시 구현
|
|
6062
|
-
// 현재는 빈 결과 반환 (Agent가
|
|
6045
|
+
// 현재는 빈 결과 반환 (Agent가 execute_command_tool with grep 사용하도록)
|
|
6063
6046
|
return {
|
|
6064
6047
|
success: false,
|
|
6065
6048
|
locations: []
|
|
@@ -9062,20 +9045,15 @@ Avoid unnecessary introductions or conclusions.
|
|
|
9062
9045
|
## Task Management
|
|
9063
9046
|
Use write_todos for complex multi-step tasks (3+ steps). Mark tasks in_progress before starting, completed immediately after finishing.
|
|
9064
9047
|
For simple 1-2 step tasks, just do them directly without todos.
|
|
9048
|
+
When creating a todo list, ALWAYS include "작업 요약 및 다음단계 제시" as the LAST todo item.
|
|
9065
9049
|
|
|
9066
9050
|
You MUST ALWAYS call a tool in every response. After any tool result, you MUST:
|
|
9067
9051
|
1. Check your todo list - are there pending or in_progress items?
|
|
9068
9052
|
2. If YES → call the next appropriate tool (jupyter_cell_tool, markdown_tool, etc.)
|
|
9069
|
-
3. When
|
|
9070
|
-
{
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
"subject": "<subject for next step>",
|
|
9074
|
-
"description": "<detailed description for the next step>"
|
|
9075
|
-
}, ...
|
|
9076
|
-
]
|
|
9077
|
-
}
|
|
9078
|
-
4. If ALL todos are completed → call final_answer_tool with a summary
|
|
9053
|
+
3. When executing "작업 요약 및 다음단계 제시" (final todo):
|
|
9054
|
+
- Output this JSON as text content: {"summary": "실행된 작업 요약", "next_items": [{"subject": "제목", "description": "설명"}]}
|
|
9055
|
+
- AND call write_todos to mark all as 'completed' IN THE SAME RESPONSE
|
|
9056
|
+
- Both content AND tool call must be in ONE response
|
|
9079
9057
|
|
|
9080
9058
|
## 🔴 MANDATORY: Resource Check Before Data Hanlding
|
|
9081
9059
|
**ALWAYS call check_resource_tool FIRST** when the task involves:
|
|
@@ -9086,16 +9064,26 @@ You MUST ALWAYS call a tool in every response. After any tool result, you MUST:
|
|
|
9086
9064
|
## Mandatory Workflow
|
|
9087
9065
|
1. After EVERY tool result, immediately call the next tool
|
|
9088
9066
|
2. Continue until ALL todos show status: "completed"
|
|
9089
|
-
3.
|
|
9067
|
+
3. When all todos are completed, the session ends automatically
|
|
9090
9068
|
4. Only use jupyter_cell_tool for Python code or when the user explicitly asks to run in a notebook cell
|
|
9091
9069
|
5. For plots and charts, use English text only.
|
|
9092
9070
|
|
|
9093
9071
|
## ❌ FORBIDDEN (will break the workflow)
|
|
9094
9072
|
- Producing an empty response (no tool call, no content)
|
|
9095
9073
|
- Stopping after any tool without calling the next tool
|
|
9096
|
-
- Ending without calling final_answer_tool
|
|
9097
9074
|
- Leaving todos in "in_progress" or "pending" state without continuing
|
|
9098
9075
|
|
|
9076
|
+
## 📂 File Search Best Practices
|
|
9077
|
+
**CRITICAL**: Use \`execute_command_tool\` with find/grep commands for file searching.
|
|
9078
|
+
|
|
9079
|
+
**To find files by NAME** (e.g., find titanic.csv):
|
|
9080
|
+
- \`execute_command_tool(command="find . -iname '*titanic*.csv' 2>/dev/null")\`
|
|
9081
|
+
- \`execute_command_tool(command="find . -name '*.csv' 2>/dev/null")\` - find all CSV files
|
|
9082
|
+
|
|
9083
|
+
**To search file CONTENTS** (e.g., find code containing "import pandas"):
|
|
9084
|
+
- \`execute_command_tool(command="grep -rn 'import pandas' --include='*.py' .")\`
|
|
9085
|
+
- \`execute_command_tool(command="grep -rn 'def train_model' --include='*.py' --include='*.ipynb' .")\`
|
|
9086
|
+
|
|
9099
9087
|
## 📖 File Reading Best Practices
|
|
9100
9088
|
**CRITICAL**: When exploring codebases or reading files, use pagination to prevent context overflow.
|
|
9101
9089
|
|
|
@@ -12183,7 +12171,7 @@ class ToolExecutor {
|
|
|
12183
12171
|
return { text, truncated: lines.length > maxLines };
|
|
12184
12172
|
}
|
|
12185
12173
|
/**
|
|
12186
|
-
* read_file 도구: 파일 읽기
|
|
12174
|
+
* read_file 도구: 파일 읽기 (offset/limit 지원)
|
|
12187
12175
|
*/
|
|
12188
12176
|
async executeReadFile(params) {
|
|
12189
12177
|
console.log('[ToolExecutor] executeReadFile:', params);
|
|
@@ -12193,15 +12181,29 @@ class ToolExecutor {
|
|
|
12193
12181
|
return { success: false, error: pathCheck.error };
|
|
12194
12182
|
}
|
|
12195
12183
|
const encoding = params.encoding || 'utf-8';
|
|
12196
|
-
|
|
12197
|
-
|
|
12184
|
+
// Support both old (maxLines) and new (offset/limit) parameters
|
|
12185
|
+
const offset = typeof params.offset === 'number' ? Math.max(0, params.offset) : 0;
|
|
12186
|
+
const limit = typeof params.limit === 'number'
|
|
12187
|
+
? params.limit
|
|
12188
|
+
: (typeof params.maxLines === 'number' ? params.maxLines : 500);
|
|
12189
|
+
// Python 코드로 파일 읽기 (커널에서 실행) - offset/limit 적용
|
|
12198
12190
|
const pythonCode = `
|
|
12199
12191
|
import json
|
|
12200
12192
|
try:
|
|
12201
12193
|
with open(${JSON.stringify(params.path)}, 'r', encoding=${JSON.stringify(encoding)}) as f:
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12194
|
+
all_lines = f.readlines()
|
|
12195
|
+
total_lines = len(all_lines)
|
|
12196
|
+
sliced_lines = all_lines[${offset}:${offset + limit}]
|
|
12197
|
+
content = ''.join(sliced_lines)
|
|
12198
|
+
result = {
|
|
12199
|
+
'success': True,
|
|
12200
|
+
'content': content,
|
|
12201
|
+
'lineCount': len(sliced_lines),
|
|
12202
|
+
'totalLines': total_lines,
|
|
12203
|
+
'offset': ${offset},
|
|
12204
|
+
'limit': ${limit},
|
|
12205
|
+
'truncated': total_lines > ${offset + limit}
|
|
12206
|
+
}
|
|
12205
12207
|
except FileNotFoundError:
|
|
12206
12208
|
result = {'success': False, 'error': f'File not found: ${params.path}'}
|
|
12207
12209
|
except PermissionError:
|
|
@@ -15068,19 +15070,19 @@ function extractNextItemsBlock(text) {
|
|
|
15068
15070
|
if (lang && lang !== 'json' && !content.includes('"next_items"')) {
|
|
15069
15071
|
continue;
|
|
15070
15072
|
}
|
|
15071
|
-
const
|
|
15072
|
-
if (
|
|
15073
|
+
const parsed = parseNextItemsPayload(content);
|
|
15074
|
+
if (parsed) {
|
|
15073
15075
|
const placeholder = `__NEXT_ITEMS_${Math.random().toString(36).slice(2, 11)}__`;
|
|
15074
15076
|
const updated = text.slice(0, match.index) + placeholder + text.slice(match.index + match[0].length);
|
|
15075
|
-
return { items, placeholder, text: updated };
|
|
15077
|
+
return { items: parsed.items, summary: parsed.summary, placeholder, text: updated };
|
|
15076
15078
|
}
|
|
15077
15079
|
}
|
|
15078
15080
|
const range = findNextItemsJsonRange(text);
|
|
15079
15081
|
if (!range)
|
|
15080
15082
|
return null;
|
|
15081
15083
|
const candidate = text.slice(range.start, range.end + 1);
|
|
15082
|
-
const
|
|
15083
|
-
if (!
|
|
15084
|
+
const parsed = parseNextItemsPayload(candidate);
|
|
15085
|
+
if (!parsed)
|
|
15084
15086
|
return null;
|
|
15085
15087
|
let replacementStart = range.start;
|
|
15086
15088
|
const lineStart = text.lastIndexOf('\n', range.start - 1) + 1;
|
|
@@ -15091,7 +15093,7 @@ function extractNextItemsBlock(text) {
|
|
|
15091
15093
|
}
|
|
15092
15094
|
const placeholder = `__NEXT_ITEMS_${Math.random().toString(36).slice(2, 11)}__`;
|
|
15093
15095
|
const updated = text.slice(0, replacementStart) + placeholder + text.slice(range.end + 1);
|
|
15094
|
-
return { items, placeholder, text: updated };
|
|
15096
|
+
return { items: parsed.items, summary: parsed.summary, placeholder, text: updated };
|
|
15095
15097
|
}
|
|
15096
15098
|
function findNextItemsJsonRange(text) {
|
|
15097
15099
|
const key = '"next_items"';
|
|
@@ -15169,17 +15171,25 @@ function parseNextItemsPayload(payload) {
|
|
|
15169
15171
|
return { subject, description };
|
|
15170
15172
|
})
|
|
15171
15173
|
.filter((item) => Boolean(item));
|
|
15172
|
-
|
|
15174
|
+
// Extract summary field if present
|
|
15175
|
+
const summaryRaw = parsed.summary;
|
|
15176
|
+
const summary = typeof summaryRaw === 'string' && summaryRaw.trim() ? summaryRaw.trim() : null;
|
|
15177
|
+
return items.length > 0 ? { items, summary } : null;
|
|
15173
15178
|
}
|
|
15174
15179
|
catch {
|
|
15175
15180
|
return null;
|
|
15176
15181
|
}
|
|
15177
15182
|
}
|
|
15178
|
-
function renderNextItemsList(items) {
|
|
15179
|
-
// Simple arrow icon
|
|
15183
|
+
function renderNextItemsList(items, summary) {
|
|
15184
|
+
// Simple arrow icon for next items
|
|
15180
15185
|
const arrowSvg = `
|
|
15181
15186
|
<svg class="jp-next-items-icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
15182
15187
|
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"/>
|
|
15188
|
+
</svg>`;
|
|
15189
|
+
// Checkmark icon for summary
|
|
15190
|
+
const checkSvg = `
|
|
15191
|
+
<svg class="jp-summary-icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
15192
|
+
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
|
|
15183
15193
|
</svg>`;
|
|
15184
15194
|
const listItems = items.map((item) => {
|
|
15185
15195
|
const subject = escapeHtml(item.subject);
|
|
@@ -15195,7 +15205,16 @@ function renderNextItemsList(items) {
|
|
|
15195
15205
|
${arrowSvg}
|
|
15196
15206
|
</li>`;
|
|
15197
15207
|
}).join('');
|
|
15198
|
-
|
|
15208
|
+
// Render summary as separate block above next items
|
|
15209
|
+
const summaryHtml = summary ? `
|
|
15210
|
+
<div class="jp-summary-block">
|
|
15211
|
+
<div class="jp-summary-header">작업 요약</div>
|
|
15212
|
+
<div class="jp-summary-body">
|
|
15213
|
+
${checkSvg}
|
|
15214
|
+
<div class="jp-summary-content">${escapeHtml(summary)}</div>
|
|
15215
|
+
</div>
|
|
15216
|
+
</div>` : '';
|
|
15217
|
+
return `${summaryHtml}
|
|
15199
15218
|
<div class="jp-next-items" data-next-items="true">
|
|
15200
15219
|
<div class="jp-next-items-header">다음 단계 제안</div>
|
|
15201
15220
|
<ul class="jp-next-items-list" role="list">
|
|
@@ -15821,7 +15840,7 @@ function formatMarkdownToHtml(text) {
|
|
|
15821
15840
|
});
|
|
15822
15841
|
// Step 8.5: Restore next items list placeholders
|
|
15823
15842
|
if (nextItemsBlock) {
|
|
15824
|
-
html = html.split(nextItemsBlock.placeholder).join(renderNextItemsList(nextItemsBlock.items));
|
|
15843
|
+
html = html.split(nextItemsBlock.placeholder).join(renderNextItemsList(nextItemsBlock.items, nextItemsBlock.summary));
|
|
15825
15844
|
}
|
|
15826
15845
|
return html;
|
|
15827
15846
|
}
|
|
@@ -15984,4 +16003,4 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
15984
16003
|
/***/ }
|
|
15985
16004
|
|
|
15986
16005
|
}]);
|
|
15987
|
-
//# sourceMappingURL=lib_index_js.
|
|
16006
|
+
//# sourceMappingURL=lib_index_js.dc6434bee96ab03a0539.js.map
|