gyoshu 0.4.16 → 0.4.18
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/package.json +1 -1
- package/src/gyoshu-manifest.json +2 -2
- package/src/index.ts +33 -19
- package/src/plugin/gyoshu-hooks.ts +28 -56
package/package.json
CHANGED
package/src/gyoshu-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gyoshu",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.18",
|
|
4
4
|
"description": "Scientific research agent extension for OpenCode",
|
|
5
5
|
"files": {
|
|
6
6
|
"agent": [
|
|
@@ -59,6 +59,6 @@
|
|
|
59
59
|
"bridge": [
|
|
60
60
|
"gyoshu_bridge.py"
|
|
61
61
|
],
|
|
62
|
-
"plugin": []
|
|
62
|
+
"plugin": ["gyoshu-hooks.ts"]
|
|
63
63
|
}
|
|
64
64
|
}
|
package/src/index.ts
CHANGED
|
@@ -867,32 +867,46 @@ function autoInstall(): InstallResult {
|
|
|
867
867
|
}
|
|
868
868
|
|
|
869
869
|
export const GyoshuPlugin: Plugin = async (ctx) => {
|
|
870
|
-
|
|
870
|
+
// Always return a valid Hooks object, even on error
|
|
871
|
+
const emptyHooks = {};
|
|
872
|
+
|
|
873
|
+
try {
|
|
874
|
+
const installResult = autoInstall();
|
|
871
875
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
+
if (installResult.fatal) {
|
|
877
|
+
console.error(`❌ Gyoshu: Fatal installation error`);
|
|
878
|
+
for (const error of installResult.errors) {
|
|
879
|
+
console.error(` - ${error}`);
|
|
880
|
+
}
|
|
876
881
|
}
|
|
877
|
-
return GyoshuHooks(ctx);
|
|
878
|
-
}
|
|
879
882
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
+
if (installResult.installed > 0) {
|
|
884
|
+
console.log(`🎓 Gyoshu: Installed ${installResult.installed} files to ~/.config/opencode/`);
|
|
885
|
+
}
|
|
883
886
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
+
if (installResult.updated > 0) {
|
|
888
|
+
console.log(`🎓 Gyoshu: Updated ${installResult.updated} files`);
|
|
889
|
+
}
|
|
887
890
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
891
|
+
if (installResult.errors.length > 0) {
|
|
892
|
+
console.warn(`⚠️ Gyoshu: Some issues occurred:`);
|
|
893
|
+
for (const error of installResult.errors) {
|
|
894
|
+
console.warn(` - ${error}`);
|
|
895
|
+
}
|
|
892
896
|
}
|
|
893
|
-
}
|
|
894
897
|
|
|
895
|
-
|
|
898
|
+
// Try to initialize hooks, return empty hooks on failure
|
|
899
|
+
try {
|
|
900
|
+
const hooks = await GyoshuHooks(ctx);
|
|
901
|
+
return hooks || emptyHooks;
|
|
902
|
+
} catch (hooksError) {
|
|
903
|
+
console.error(`❌ Gyoshu: Failed to initialize hooks: ${hooksError instanceof Error ? hooksError.message : String(hooksError)}`);
|
|
904
|
+
return emptyHooks;
|
|
905
|
+
}
|
|
906
|
+
} catch (err) {
|
|
907
|
+
console.error(`❌ Gyoshu: Plugin initialization failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
908
|
+
return emptyHooks;
|
|
909
|
+
}
|
|
896
910
|
};
|
|
897
911
|
|
|
898
912
|
export default GyoshuPlugin;
|
|
@@ -473,8 +473,14 @@ export const GyoshuPlugin: Plugin = async ({ client }) => {
|
|
|
473
473
|
idleCheckInterval = setInterval(killIdleBridges, IDLE_CHECK_INTERVAL_MS);
|
|
474
474
|
|
|
475
475
|
return {
|
|
476
|
+
// NOTE: tool.execute.after receives:
|
|
477
|
+
// input: { tool: string; sessionID: string; callID: string; }
|
|
478
|
+
// output: { title: string; output: string; metadata: any; }
|
|
479
|
+
// The original tool args are in output.metadata (if the tool stored them there)
|
|
476
480
|
"tool.execute.after": async (input, output) => {
|
|
477
|
-
|
|
481
|
+
// Extract args from output.metadata (where tools may store their call args)
|
|
482
|
+
const metadata = output?.metadata as Record<string, unknown> | undefined;
|
|
483
|
+
const args = metadata?.args as Record<string, unknown> | undefined;
|
|
478
484
|
|
|
479
485
|
const toolReportTitle = extractReportTitleFromArgs(args);
|
|
480
486
|
if (toolReportTitle && activeAutoLoops.has(toolReportTitle)) {
|
|
@@ -504,7 +510,7 @@ export const GyoshuPlugin: Plugin = async ({ client }) => {
|
|
|
504
510
|
|
|
505
511
|
if (input.tool === "gyoshu-completion") {
|
|
506
512
|
const reportTitle = args?.reportTitle as string | undefined;
|
|
507
|
-
const outputText = typeof output === "string" ? output : JSON.stringify(output);
|
|
513
|
+
const outputText = typeof output?.output === "string" ? output.output : JSON.stringify(output);
|
|
508
514
|
if (reportTitle) {
|
|
509
515
|
recentOutputBuffer.set(reportTitle, outputText);
|
|
510
516
|
}
|
|
@@ -519,49 +525,27 @@ export const GyoshuPlugin: Plugin = async ({ client }) => {
|
|
|
519
525
|
}
|
|
520
526
|
},
|
|
521
527
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const matchedReportTitles = findReportTitlesInOutput(outputText);
|
|
529
|
-
if (matchedReportTitles.length > 0) {
|
|
530
|
-
for (const reportTitle of matchedReportTitles) {
|
|
531
|
-
await deactivateAutoLoop(reportTitle);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
for (const [reportTitle] of activeAutoLoops) {
|
|
539
|
-
const bufferedOutput = recentOutputBuffer.get(reportTitle) || "";
|
|
540
|
-
const combinedOutput = bufferedOutput + outputText;
|
|
541
|
-
|
|
542
|
-
const result = await checkAutoLoopContinuation(reportTitle, combinedOutput, client);
|
|
543
|
-
|
|
544
|
-
if (result.budgetExhaustedMessage) {
|
|
545
|
-
const sent = await trySendContinuationPrompt(client, result.budgetExhaustedMessage);
|
|
546
|
-
if (sent) {
|
|
547
|
-
await onSuccessfulContinuationSend(reportTitle);
|
|
548
|
-
}
|
|
549
|
-
} else if (result.prompt) {
|
|
550
|
-
const sent = await trySendContinuationPrompt(client, result.prompt);
|
|
551
|
-
if (sent) {
|
|
552
|
-
await onSuccessfulContinuationSend(reportTitle);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
recentOutputBuffer.delete(reportTitle);
|
|
557
|
-
}
|
|
558
|
-
},
|
|
528
|
+
// NOTE: OpenCode does not have an "agent.after" hook.
|
|
529
|
+
// Auto-loop continuation logic that was here has been disabled.
|
|
530
|
+
// When/if OpenCode adds an agent completion hook, the following would need to be restored:
|
|
531
|
+
// - Detect terminal promise tags (GYOSHU_AUTO_COMPLETE, GYOSHU_AUTO_BLOCKED, GYOSHU_AUTO_BUDGET_EXHAUSTED)
|
|
532
|
+
// - Call checkAutoLoopContinuation() and trySendContinuationPrompt() for active auto-loops
|
|
533
|
+
// The auto-loop state management code is preserved for when this becomes available.
|
|
559
534
|
|
|
560
535
|
event: async ({ event }) => {
|
|
561
536
|
const eventType = event.type as string;
|
|
562
537
|
|
|
538
|
+
// Handle session cleanup (merged from removed 'cleanup' hook)
|
|
563
539
|
if (eventType === "session.end" || eventType === "session.disposed") {
|
|
540
|
+
// Stop idle check interval
|
|
541
|
+
if (idleCheckInterval) {
|
|
542
|
+
clearInterval(idleCheckInterval);
|
|
543
|
+
idleCheckInterval = null;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Clean up all bridges and session state
|
|
564
547
|
cleanupAllBridges();
|
|
548
|
+
activeSessions.clear();
|
|
565
549
|
activeAutoLoops.clear();
|
|
566
550
|
recentOutputBuffer.clear();
|
|
567
551
|
injectionInFlight.clear();
|
|
@@ -572,6 +556,9 @@ export const GyoshuPlugin: Plugin = async ({ client }) => {
|
|
|
572
556
|
saveDebounceTimers.clear();
|
|
573
557
|
}
|
|
574
558
|
|
|
559
|
+
// Auto-loop continuation on idle/message events
|
|
560
|
+
// NOTE: This is a partial replacement for the removed "agent.after" hook.
|
|
561
|
+
// It only triggers on explicit idle/message events, not on every agent turn completion.
|
|
575
562
|
if (eventType === "agent.idle" || eventType === "message.completed") {
|
|
576
563
|
for (const [reportTitle] of activeAutoLoops) {
|
|
577
564
|
const bufferedOutput = recentOutputBuffer.get(reportTitle) || "";
|
|
@@ -593,23 +580,8 @@ export const GyoshuPlugin: Plugin = async ({ client }) => {
|
|
|
593
580
|
}
|
|
594
581
|
},
|
|
595
582
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
clearInterval(idleCheckInterval);
|
|
599
|
-
idleCheckInterval = null;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
cleanupAllBridges();
|
|
603
|
-
activeSessions.clear();
|
|
604
|
-
activeAutoLoops.clear();
|
|
605
|
-
recentOutputBuffer.clear();
|
|
606
|
-
injectionInFlight.clear();
|
|
607
|
-
lastProcessedOutputHash.clear();
|
|
608
|
-
for (const timer of saveDebounceTimers.values()) {
|
|
609
|
-
clearTimeout(timer);
|
|
610
|
-
}
|
|
611
|
-
saveDebounceTimers.clear();
|
|
612
|
-
},
|
|
583
|
+
// NOTE: OpenCode does not have a 'cleanup' hook.
|
|
584
|
+
// Cleanup logic has been moved to the 'event' hook, listening for 'session.end' and 'session.disposed'.
|
|
613
585
|
};
|
|
614
586
|
};
|
|
615
587
|
|