@ian2018cs/agenthub 0.1.62 → 0.1.63
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.html
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
<!-- Prevent zoom on iOS -->
|
|
27
27
|
<meta name="format-detection" content="telephone=no" />
|
|
28
|
-
<script type="module" crossorigin src="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-Bih5jXn3.js"></script>
|
|
29
29
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BeVl62c0.js">
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-C_VWDoZS.js">
|
|
31
31
|
<link rel="modulepreload" crossorigin href="/assets/vendor-utils-00TdZexr.js">
|
package/package.json
CHANGED
package/server/claude-sdk.js
CHANGED
|
@@ -232,13 +232,14 @@ function mapCliOptionsToSDK(options = {}) {
|
|
|
232
232
|
* @param {Array<string>} tempImagePaths - Temp image file paths for cleanup
|
|
233
233
|
* @param {string} tempDir - Temp directory for cleanup
|
|
234
234
|
*/
|
|
235
|
-
function addSession(sessionId, queryInstance, tempImagePaths = [], tempDir = null) {
|
|
235
|
+
function addSession(sessionId, queryInstance, tempImagePaths = [], tempDir = null, abortController = null) {
|
|
236
236
|
activeSessions.set(sessionId, {
|
|
237
237
|
instance: queryInstance,
|
|
238
238
|
startTime: Date.now(),
|
|
239
239
|
status: 'active',
|
|
240
240
|
tempImagePaths,
|
|
241
|
-
tempDir
|
|
241
|
+
tempDir,
|
|
242
|
+
abortController
|
|
242
243
|
});
|
|
243
244
|
}
|
|
244
245
|
|
|
@@ -511,6 +512,10 @@ async function queryClaudeSDK(command, options = {}, ws) {
|
|
|
511
512
|
// Map CLI options to SDK format
|
|
512
513
|
const sdkOptions = mapCliOptionsToSDK(options);
|
|
513
514
|
|
|
515
|
+
// Create AbortController for session cancellation
|
|
516
|
+
const abortController = new AbortController();
|
|
517
|
+
sdkOptions.abortController = abortController;
|
|
518
|
+
|
|
514
519
|
// Load MCP configuration
|
|
515
520
|
const mcpServers = await loadMcpConfig(options.cwd, userUuid);
|
|
516
521
|
if (mcpServers) {
|
|
@@ -651,7 +656,7 @@ async function queryClaudeSDK(command, options = {}, ws) {
|
|
|
651
656
|
|
|
652
657
|
// Track the query instance for abort capability
|
|
653
658
|
if (capturedSessionId) {
|
|
654
|
-
addSession(capturedSessionId, queryInstance, tempImagePaths, tempDir);
|
|
659
|
+
addSession(capturedSessionId, queryInstance, tempImagePaths, tempDir, abortController);
|
|
655
660
|
}
|
|
656
661
|
|
|
657
662
|
// Process streaming messages
|
|
@@ -661,7 +666,7 @@ async function queryClaudeSDK(command, options = {}, ws) {
|
|
|
661
666
|
if (message.session_id && !capturedSessionId) {
|
|
662
667
|
|
|
663
668
|
capturedSessionId = message.session_id;
|
|
664
|
-
addSession(capturedSessionId, queryInstance, tempImagePaths, tempDir);
|
|
669
|
+
addSession(capturedSessionId, queryInstance, tempImagePaths, tempDir, abortController);
|
|
665
670
|
|
|
666
671
|
// Set session ID on writer
|
|
667
672
|
if (ws.setSessionId && typeof ws.setSessionId === 'function') {
|
|
@@ -775,17 +780,33 @@ async function queryClaudeSDK(command, options = {}, ws) {
|
|
|
775
780
|
// Clean up temporary image files
|
|
776
781
|
await cleanupTempFiles(tempImagePaths, tempDir);
|
|
777
782
|
|
|
778
|
-
//
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
783
|
+
// Only send completion event if not aborted — when the session is aborted
|
|
784
|
+
// via abortClaudeSDKSession(), that function already sends 'session-aborted'
|
|
785
|
+
// to the frontend, so we must not send a duplicate 'claude-complete'.
|
|
786
|
+
if (!abortController.signal.aborted) {
|
|
787
|
+
console.log('Streaming complete, sending claude-complete event');
|
|
788
|
+
ws.send({
|
|
789
|
+
type: 'claude-complete',
|
|
790
|
+
sessionId: capturedSessionId,
|
|
791
|
+
exitCode: 0,
|
|
792
|
+
isNewSession: !sessionId && !!command
|
|
793
|
+
});
|
|
794
|
+
console.log('claude-complete event sent');
|
|
795
|
+
} else {
|
|
796
|
+
console.log('Session was aborted, skipping claude-complete event');
|
|
797
|
+
}
|
|
787
798
|
|
|
788
799
|
} catch (error) {
|
|
800
|
+
// If the session was aborted, this is expected — do not treat as an error.
|
|
801
|
+
if (abortController.signal.aborted) {
|
|
802
|
+
console.log('Session aborted, ignoring post-abort error:', error.message);
|
|
803
|
+
if (capturedSessionId) {
|
|
804
|
+
removeSession(capturedSessionId);
|
|
805
|
+
}
|
|
806
|
+
await cleanupTempFiles(tempImagePaths, tempDir);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
|
|
789
810
|
console.error('SDK query error:', error);
|
|
790
811
|
|
|
791
812
|
// Clean up session on error
|
|
@@ -822,8 +843,20 @@ async function abortClaudeSDKSession(sessionId) {
|
|
|
822
843
|
try {
|
|
823
844
|
console.log(`Aborting SDK session: ${sessionId}`);
|
|
824
845
|
|
|
825
|
-
//
|
|
826
|
-
|
|
846
|
+
// Signal abort via AbortController (stops SDK internal operations)
|
|
847
|
+
if (session.abortController) {
|
|
848
|
+
session.abortController.abort();
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// Forcefully close the query and terminate the underlying process.
|
|
852
|
+
// close() is the correct method for aborting a running query — it kills the
|
|
853
|
+
// CLI subprocess and cleans up all resources (MCP transports, pending requests).
|
|
854
|
+
// interrupt() only works in streaming-input mode and is not reliable here.
|
|
855
|
+
try {
|
|
856
|
+
session.instance.close();
|
|
857
|
+
} catch (closeError) {
|
|
858
|
+
console.error(`Error closing session ${sessionId}:`, closeError);
|
|
859
|
+
}
|
|
827
860
|
|
|
828
861
|
// Update session status
|
|
829
862
|
session.status = 'aborted';
|
|
@@ -78,6 +78,8 @@ export async function evaluate(toolName, input, { userUuid, cwd }) {
|
|
|
78
78
|
const rewrittenInput = rewriteClaudePaths(toolName, input, claudeDir);
|
|
79
79
|
const effectiveInput = rewrittenInput || input;
|
|
80
80
|
|
|
81
|
+
if (VERBOSE) console.log(`[ToolGuard] INPUT ${toolName}:`, JSON.stringify(effectiveInput));
|
|
82
|
+
|
|
81
83
|
if (rewrittenInput && VERBOSE) {
|
|
82
84
|
console.log(`[ToolGuard] PATH-REWRITE ${toolName}: .claude paths → ${claudeDir}`);
|
|
83
85
|
}
|