@leanandmean/coding-agent 0.74.1-scramjet.73 → 0.74.1-scramjet.75
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 +4 -0
- package/dist/core/agent-session.d.ts +19 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +293 -68
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +18 -5
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +9 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +123 -17
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +35 -16
- package/dist/modes/print-mode.js.map +1 -1
- package/docs/compaction.md +6 -0
- package/docs/custom-provider.md +3 -1
- package/docs/extensions.md +13 -1
- package/docs/sdk.md +27 -0
- package/docs/settings.md +2 -0
- package/docs/terminal-verification.md +8 -0
- package/package.json +4 -4
|
@@ -11,7 +11,7 @@ import { getProviders, } from "@leanandmean/ai";
|
|
|
11
11
|
import { CombinedAutocompleteProvider, Container, fuzzyFilter, isKeyRelease, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, TUI_KEYBINDINGS, visibleWidth, } from "@leanandmean/tui";
|
|
12
12
|
import { spawn, spawnSync } from "child_process";
|
|
13
13
|
import { APP_NAME, APP_TITLE, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, VERSION } from "../../config.js";
|
|
14
|
-
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
14
|
+
import { parseSkillBlock, } from "../../core/agent-session.js";
|
|
15
15
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
16
16
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
17
17
|
import { KeybindingsManager } from "../../core/keybindings.js";
|
|
@@ -130,6 +130,7 @@ export class InteractiveMode {
|
|
|
130
130
|
version;
|
|
131
131
|
isInitialized = false;
|
|
132
132
|
onInputCallback;
|
|
133
|
+
promptSubmission;
|
|
133
134
|
loadingAnimation = undefined;
|
|
134
135
|
workingMessage = undefined;
|
|
135
136
|
workingVisible = true;
|
|
@@ -877,7 +878,7 @@ export class InteractiveMode {
|
|
|
877
878
|
// Process initial messages
|
|
878
879
|
if (initialMessage) {
|
|
879
880
|
try {
|
|
880
|
-
await this.
|
|
881
|
+
await this.promptInteractive(initialMessage, initialImages);
|
|
881
882
|
}
|
|
882
883
|
catch (error) {
|
|
883
884
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -887,7 +888,7 @@ export class InteractiveMode {
|
|
|
887
888
|
if (initialMessages) {
|
|
888
889
|
for (const message of initialMessages) {
|
|
889
890
|
try {
|
|
890
|
-
await this.
|
|
891
|
+
await this.promptInteractive(message);
|
|
891
892
|
}
|
|
892
893
|
catch (error) {
|
|
893
894
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -899,7 +900,7 @@ export class InteractiveMode {
|
|
|
899
900
|
while (true) {
|
|
900
901
|
const userInput = await this.getUserInput();
|
|
901
902
|
try {
|
|
902
|
-
await this.
|
|
903
|
+
await this.promptInteractive(userInput);
|
|
903
904
|
}
|
|
904
905
|
catch (error) {
|
|
905
906
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -907,6 +908,71 @@ export class InteractiveMode {
|
|
|
907
908
|
}
|
|
908
909
|
}
|
|
909
910
|
}
|
|
911
|
+
// SCRAMJET-DIVERGENCE: native consumers retain invocation identity through recovery.
|
|
912
|
+
async promptInteractive(text, images) {
|
|
913
|
+
const submission = { session: this.session, retried: false };
|
|
914
|
+
this.promptSubmission = submission;
|
|
915
|
+
const draftGeneration = this.clipboardPasteGeneration;
|
|
916
|
+
try {
|
|
917
|
+
await submission.session.prompt(text, {
|
|
918
|
+
images,
|
|
919
|
+
onRunSettlement: (settlement) => {
|
|
920
|
+
submission.settlement = settlement;
|
|
921
|
+
void settlement.catch(() => { });
|
|
922
|
+
},
|
|
923
|
+
});
|
|
924
|
+
const outcome = submission.settlement ? await submission.settlement : undefined;
|
|
925
|
+
if (this.promptSubmission !== submission || this.session !== submission.session)
|
|
926
|
+
return;
|
|
927
|
+
if (outcome?.status === "cancelled") {
|
|
928
|
+
this.showStatus("Execution cancelled. Review interrupted work before submitting a new prompt.");
|
|
929
|
+
}
|
|
930
|
+
else if (outcome?.status === "failed") {
|
|
931
|
+
const retryRecord = submission.session.sessionManager
|
|
932
|
+
.getBranch()
|
|
933
|
+
.reverse()
|
|
934
|
+
.find((entry) => entry.type === "custom" && entry.customType === "coding-agent:auto-retry");
|
|
935
|
+
const exhausted = submission.retryFailure &&
|
|
936
|
+
retryRecord?.type === "custom" &&
|
|
937
|
+
retryRecord.data?.outcome === "exhausted";
|
|
938
|
+
const prefix = exhausted ? "Recovery exhausted" : "Execution failed";
|
|
939
|
+
this.showError(`${prefix}: ${outcome.errorMessage}. Review the failure before trying again.`);
|
|
940
|
+
}
|
|
941
|
+
else if (outcome?.status === "completed" && submission.retried) {
|
|
942
|
+
this.showStatus("Execution recovered and continued.");
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
catch (error) {
|
|
946
|
+
if (this.promptSubmission !== submission || this.session !== submission.session)
|
|
947
|
+
return;
|
|
948
|
+
if (!this.editor.getText() && this.clipboardPasteGeneration === draftGeneration)
|
|
949
|
+
this.editor.setText(text);
|
|
950
|
+
this.showError(`${error instanceof Error ? error.message : String(error)}. Review the failure before trying again.`);
|
|
951
|
+
}
|
|
952
|
+
finally {
|
|
953
|
+
if (this.promptSubmission === submission && this.session === submission.session) {
|
|
954
|
+
this.promptSubmission = undefined;
|
|
955
|
+
this.clearRetryControls();
|
|
956
|
+
this.stopWorkingLoader();
|
|
957
|
+
if (this.settingsManager.getShowTerminalProgress())
|
|
958
|
+
this.ui.terminal.setProgress(false);
|
|
959
|
+
this.ui.requestRender();
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
clearRetryControls() {
|
|
964
|
+
if (this.retryEscapeHandler) {
|
|
965
|
+
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
966
|
+
this.retryEscapeHandler = undefined;
|
|
967
|
+
}
|
|
968
|
+
this.retryCountdown?.dispose();
|
|
969
|
+
this.retryCountdown = undefined;
|
|
970
|
+
if (this.retryLoader) {
|
|
971
|
+
this.statusContainer.removeChild(this.retryLoader);
|
|
972
|
+
this.retryLoader.stop();
|
|
973
|
+
this.retryLoader = undefined;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
910
976
|
async checkForPackageUpdates() {
|
|
911
977
|
// SCRAMJET-DIVERGENCE: prefer SCRAMJET_OFFLINE, fall back to PI_OFFLINE.
|
|
912
978
|
if (process.env.SCRAMJET_OFFLINE || process.env.PI_OFFLINE) {
|
|
@@ -1513,6 +1579,13 @@ export class InteractiveMode {
|
|
|
1513
1579
|
}
|
|
1514
1580
|
}
|
|
1515
1581
|
async rebindCurrentSession() {
|
|
1582
|
+
if (this.promptSubmission && this.promptSubmission.session !== this.session) {
|
|
1583
|
+
this.promptSubmission = undefined;
|
|
1584
|
+
this.clearRetryControls();
|
|
1585
|
+
this.stopWorkingLoader();
|
|
1586
|
+
if (this.settingsManager.getShowTerminalProgress())
|
|
1587
|
+
this.ui.terminal.setProgress(false);
|
|
1588
|
+
}
|
|
1516
1589
|
this.unsubscribe?.();
|
|
1517
1590
|
this.unsubscribe = undefined;
|
|
1518
1591
|
this.applyRuntimeSettings();
|
|
@@ -2366,7 +2439,7 @@ export class InteractiveMode {
|
|
|
2366
2439
|
this.pendingSelectorOpenGeneration = undefined;
|
|
2367
2440
|
return;
|
|
2368
2441
|
}
|
|
2369
|
-
if (this.session.isStreaming) {
|
|
2442
|
+
if (this.promptSubmission?.session === this.session || this.session.isStreaming || this.session.isRetrying) {
|
|
2370
2443
|
this.restoreQueuedMessagesToEditor({ abort: true });
|
|
2371
2444
|
}
|
|
2372
2445
|
else if (this.session.isBashRunning) {
|
|
@@ -2608,11 +2681,16 @@ export class InteractiveMode {
|
|
|
2608
2681
|
if (this.session.isStreaming) {
|
|
2609
2682
|
this.editor.addToHistory?.(text);
|
|
2610
2683
|
this.editor.setText("");
|
|
2611
|
-
await this.
|
|
2684
|
+
await this.submitQueuedPrompt(text, "steer");
|
|
2612
2685
|
this.updatePendingMessagesDisplay();
|
|
2613
2686
|
this.ui.requestRender();
|
|
2614
2687
|
return;
|
|
2615
2688
|
}
|
|
2689
|
+
if (!this.onInputCallback) {
|
|
2690
|
+
this.editor.setText(text);
|
|
2691
|
+
this.showWarning("Execution is still settling or recovering. Wait, or press Esc to cancel before submitting again.");
|
|
2692
|
+
return;
|
|
2693
|
+
}
|
|
2616
2694
|
// Normal message submission
|
|
2617
2695
|
// First, move any pending bash components to chat
|
|
2618
2696
|
this.flushPendingBashComponents();
|
|
@@ -2823,10 +2901,10 @@ export class InteractiveMode {
|
|
|
2823
2901
|
await Promise.all(pendingToolFinalizations);
|
|
2824
2902
|
if (runGeneration !== this.agentRunGeneration || pendingToolFinalizations !== this.pendingToolFinalizations)
|
|
2825
2903
|
break;
|
|
2826
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2904
|
+
if (this.promptSubmission?.session !== this.session && this.settingsManager.getShowTerminalProgress()) {
|
|
2827
2905
|
this.ui.terminal.setProgress(false);
|
|
2828
2906
|
}
|
|
2829
|
-
if (this.loadingAnimation) {
|
|
2907
|
+
if (this.loadingAnimation && this.promptSubmission?.session !== this.session) {
|
|
2830
2908
|
this.loadingAnimation.stop();
|
|
2831
2909
|
this.loadingAnimation = undefined;
|
|
2832
2910
|
this.statusContainer.clear();
|
|
@@ -2853,8 +2931,14 @@ export class InteractiveMode {
|
|
|
2853
2931
|
}
|
|
2854
2932
|
// Keep editor active; submissions are queued during compaction.
|
|
2855
2933
|
this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
|
|
2934
|
+
const compactingSession = this.session;
|
|
2856
2935
|
this.defaultEditor.onEscape = () => {
|
|
2857
|
-
this.session
|
|
2936
|
+
if (this.session !== compactingSession)
|
|
2937
|
+
return;
|
|
2938
|
+
if (this.promptSubmission?.session === compactingSession)
|
|
2939
|
+
compactingSession.abortRetry();
|
|
2940
|
+
else
|
|
2941
|
+
compactingSession.abortCompaction();
|
|
2858
2942
|
};
|
|
2859
2943
|
this.statusContainer.clear();
|
|
2860
2944
|
const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
|
|
@@ -2867,7 +2951,7 @@ export class InteractiveMode {
|
|
|
2867
2951
|
break;
|
|
2868
2952
|
}
|
|
2869
2953
|
case "compaction_end": {
|
|
2870
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2954
|
+
if (this.promptSubmission?.session !== this.session && this.settingsManager.getShowTerminalProgress()) {
|
|
2871
2955
|
this.ui.terminal.setProgress(false);
|
|
2872
2956
|
}
|
|
2873
2957
|
if (this.autoCompactionEscapeHandler) {
|
|
@@ -2908,9 +2992,14 @@ export class InteractiveMode {
|
|
|
2908
2992
|
}
|
|
2909
2993
|
case "auto_retry_start": {
|
|
2910
2994
|
// Set up escape to abort retry
|
|
2995
|
+
if (this.promptSubmission?.session === this.session)
|
|
2996
|
+
this.promptSubmission.retried = true;
|
|
2997
|
+
this.clearRetryControls();
|
|
2911
2998
|
this.retryEscapeHandler = this.defaultEditor.onEscape;
|
|
2999
|
+
const retrySession = this.session;
|
|
2912
3000
|
this.defaultEditor.onEscape = () => {
|
|
2913
|
-
this.session
|
|
3001
|
+
if (this.session === retrySession)
|
|
3002
|
+
this.restoreQueuedMessagesToEditor({ abort: true });
|
|
2914
3003
|
};
|
|
2915
3004
|
// Show retry indicator
|
|
2916
3005
|
this.statusContainer.clear();
|
|
@@ -2949,8 +3038,11 @@ export class InteractiveMode {
|
|
|
2949
3038
|
this.statusContainer.clear();
|
|
2950
3039
|
}
|
|
2951
3040
|
// Show error only on final failure (success shows normal response)
|
|
2952
|
-
if (!event.success) {
|
|
2953
|
-
this.
|
|
3041
|
+
if (!event.success && this.promptSubmission?.session === this.session) {
|
|
3042
|
+
this.promptSubmission.retryFailure = event.finalError;
|
|
3043
|
+
}
|
|
3044
|
+
else if (!event.success) {
|
|
3045
|
+
this.showStatus("Recovery stopped. Review interrupted work before submitting a new prompt.");
|
|
2954
3046
|
}
|
|
2955
3047
|
this.ui.requestRender();
|
|
2956
3048
|
break;
|
|
@@ -3411,6 +3503,20 @@ export class InteractiveMode {
|
|
|
3411
3503
|
throw error;
|
|
3412
3504
|
}
|
|
3413
3505
|
}
|
|
3506
|
+
async submitQueuedPrompt(text, streamingBehavior) {
|
|
3507
|
+
const session = this.session;
|
|
3508
|
+
const generation = this.clipboardPasteGeneration;
|
|
3509
|
+
try {
|
|
3510
|
+
await session.prompt(text, { streamingBehavior });
|
|
3511
|
+
}
|
|
3512
|
+
catch (error) {
|
|
3513
|
+
if (this.session !== session)
|
|
3514
|
+
return;
|
|
3515
|
+
if (!this.editor.getText() && generation === this.clipboardPasteGeneration)
|
|
3516
|
+
this.editor.setText(text);
|
|
3517
|
+
this.showError(`${error instanceof Error ? error.message : String(error)}. Wait or cancel recovery before submitting again.`);
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3414
3520
|
async handleFollowUp() {
|
|
3415
3521
|
const text = (this.editor.getExpandedText?.() ?? this.editor.getText()).trim();
|
|
3416
3522
|
if (!text)
|
|
@@ -3433,14 +3539,14 @@ export class InteractiveMode {
|
|
|
3433
3539
|
if (this.session.isStreaming) {
|
|
3434
3540
|
this.editor.addToHistory?.(text);
|
|
3435
3541
|
this.editor.setText("");
|
|
3436
|
-
await this.
|
|
3542
|
+
await this.submitQueuedPrompt(text, "followUp");
|
|
3437
3543
|
this.updatePendingMessagesDisplay();
|
|
3438
3544
|
this.ui.requestRender();
|
|
3439
3545
|
}
|
|
3440
3546
|
// If not streaming, Alt+Enter acts like regular Enter (trigger onSubmit)
|
|
3441
3547
|
else if (this.editor.onSubmit) {
|
|
3442
3548
|
this.editor.setText("");
|
|
3443
|
-
this.editor.onSubmit(text);
|
|
3549
|
+
await this.editor.onSubmit(text);
|
|
3444
3550
|
}
|
|
3445
3551
|
}
|
|
3446
3552
|
handleDequeue() {
|
|
@@ -3659,7 +3765,7 @@ export class InteractiveMode {
|
|
|
3659
3765
|
if (allQueued.length === 0) {
|
|
3660
3766
|
this.updatePendingMessagesDisplay();
|
|
3661
3767
|
if (options?.abort) {
|
|
3662
|
-
this.
|
|
3768
|
+
this.session.abortRetry();
|
|
3663
3769
|
}
|
|
3664
3770
|
return 0;
|
|
3665
3771
|
}
|
|
@@ -3669,7 +3775,7 @@ export class InteractiveMode {
|
|
|
3669
3775
|
this.editor.setText(combinedText);
|
|
3670
3776
|
this.updatePendingMessagesDisplay();
|
|
3671
3777
|
if (options?.abort) {
|
|
3672
|
-
this.
|
|
3778
|
+
this.session.abortRetry();
|
|
3673
3779
|
}
|
|
3674
3780
|
return allQueued.length;
|
|
3675
3781
|
}
|