blun-king-cli 9.1.421 → 9.1.422
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/LIESMICH.txt +2 -0
- package/README.md +2 -0
- package/bin/cognitive-goal-autostart-policy.cjs +39 -10
- package/bin/cognitive-goal-time-trigger-controller.cjs +146 -0
- package/blun.mjs +56 -16
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
|
@@ -106,6 +106,8 @@ ausdrücklichen Trigger-Beleg. Andere Trigger-Arten dürfen kein `dueAt`
|
|
|
106
106
|
enthalten. Ein Laufzeit-Wecker für eine durchgehend geöffnete Sitzung ist in
|
|
107
107
|
diesem Release noch nicht enthalten.
|
|
108
108
|
|
|
109
|
+
Ab BLUN King 9.1.422 überwacht auch eine durchgehend geöffnete, untätige Sitzung ihren gespeicherten Zeit-Trigger. Sobald `dueAt` erreicht oder überschritten ist, fügt der Auto- oder God-Modus genau eine verborgene Fortsetzung in dieselbe Sitzung ein. Wird der Zeitpunkt während einer laufenden Antwort, Verdichtung, wartenden Nachricht, eines Befehls oder Dialogs fällig, wartet die Fortsetzung bis zum Leerlauf. Unmittelbar vor dem Start liest King Ziel, Checkpoint-Revision, Fälligkeit, Berechtigungsmodus und Sitzung erneut; ein geänderter oder veralteter Trigger kann deshalb nicht auslösen. Stoppen, Notausgang, Entladen und Wechseln der Sitzung entsorgen den Timer. Im manuellen Modus erfolgt kein selbstständiger Start.
|
|
110
|
+
|
|
109
111
|
Zuverlässiger King-Start
|
|
110
112
|
-----------------------
|
|
111
113
|
Bei einer ausdrücklich als wiederholbar gekennzeichneten Serverüberlastung
|
package/README.md
CHANGED
|
@@ -125,6 +125,8 @@ ausdrücklichen Trigger-Beleg. Andere Trigger-Arten dürfen kein `dueAt`
|
|
|
125
125
|
enthalten. Ein Laufzeit-Wecker für eine durchgehend geöffnete Sitzung ist in
|
|
126
126
|
diesem Release noch nicht enthalten.
|
|
127
127
|
|
|
128
|
+
Ab BLUN King 9.1.422 überwacht auch eine durchgehend geöffnete, untätige Sitzung ihren gespeicherten Zeit-Trigger. Sobald `dueAt` erreicht oder überschritten ist, fügt der Auto- oder God-Modus genau eine verborgene Fortsetzung in dieselbe Sitzung ein. Wird der Zeitpunkt während einer laufenden Antwort, Verdichtung, wartenden Nachricht, eines Befehls oder Dialogs fällig, wartet die Fortsetzung bis zum Leerlauf. Unmittelbar vor dem Start liest King Ziel, Checkpoint-Revision, Fälligkeit, Berechtigungsmodus und Sitzung erneut; ein geänderter oder veralteter Trigger kann deshalb nicht auslösen. Stoppen, Notausgang, Entladen und Wechseln der Sitzung entsorgen den Timer. Im manuellen Modus erfolgt kein selbstständiger Start.
|
|
129
|
+
|
|
128
130
|
## Zuverlässiger King-Start
|
|
129
131
|
|
|
130
132
|
Bei einer vom Server ausdrücklich als wiederholbar gekennzeichneten
|
|
@@ -7,6 +7,40 @@ const START = Object.freeze({ kind: 'start', trigger: 'immediate' });
|
|
|
7
7
|
const WAIT = Object.freeze({ kind: 'wait' });
|
|
8
8
|
const CONTINUE = Object.freeze({ kind: 'continue' });
|
|
9
9
|
const YIELD = Object.freeze({ kind: 'yield' });
|
|
10
|
+
const IGNORE = Object.freeze({ kind: 'ignore' });
|
|
11
|
+
|
|
12
|
+
function goalTimeTriggerDecision({ goal, permissionMode, now = new Date() } = {}) {
|
|
13
|
+
if (!goal || typeof goal !== 'object' || Array.isArray(goal)) return IGNORE;
|
|
14
|
+
if (goal.status !== 'active' || !AUTONOMOUS_PERMISSION_MODES.has(permissionMode)) return IGNORE;
|
|
15
|
+
if (typeof goal.goalId !== 'string' || goal.goalId.trim().length === 0) return IGNORE;
|
|
16
|
+
|
|
17
|
+
const checkpoint = goal.actionCheckpoint;
|
|
18
|
+
if (!checkpoint || typeof checkpoint !== 'object' || Array.isArray(checkpoint)) return IGNORE;
|
|
19
|
+
if (!Number.isInteger(checkpoint.revision) || checkpoint.revision < 1) return IGNORE;
|
|
20
|
+
if (checkpoint.phase !== 'wait') return IGNORE;
|
|
21
|
+
const trigger = checkpoint.nextTrigger;
|
|
22
|
+
if (!trigger || typeof trigger !== 'object' || Array.isArray(trigger)) return IGNORE;
|
|
23
|
+
if (trigger.kind !== 'time' || typeof trigger.condition !== 'string' || trigger.condition.trim().length === 0) return IGNORE;
|
|
24
|
+
|
|
25
|
+
const dueAt = String(trigger.dueAt ?? '');
|
|
26
|
+
if (!ISO_TIMESTAMP_RE.test(dueAt)) return IGNORE;
|
|
27
|
+
const dueAtMs = new Date(dueAt).getTime();
|
|
28
|
+
const nowMs = new Date(now).getTime();
|
|
29
|
+
if (!Number.isFinite(dueAtMs) || !Number.isFinite(nowMs)) return IGNORE;
|
|
30
|
+
const key = `${goal.goalId}:${checkpoint.revision}:${dueAt}`;
|
|
31
|
+
if (dueAtMs > nowMs) return Object.freeze({
|
|
32
|
+
kind: 'schedule',
|
|
33
|
+
key,
|
|
34
|
+
dueAt,
|
|
35
|
+
delayMs: dueAtMs - nowMs,
|
|
36
|
+
});
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
kind: 'due',
|
|
39
|
+
key,
|
|
40
|
+
dueAt,
|
|
41
|
+
observation: `The checkpointed time trigger became due at ${dueAt}.`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
10
44
|
|
|
11
45
|
function goalAutostartDecision({ goal, permissionMode, now = new Date() } = {}) {
|
|
12
46
|
if (!goal || typeof goal !== 'object' || Array.isArray(goal)) return WAIT;
|
|
@@ -18,18 +52,13 @@ function goalAutostartDecision({ goal, permissionMode, now = new Date() } = {})
|
|
|
18
52
|
if (!trigger || typeof trigger !== 'object' || Array.isArray(trigger)) return WAIT;
|
|
19
53
|
if (typeof trigger.condition !== 'string' || trigger.condition.trim().length === 0) return WAIT;
|
|
20
54
|
if (ACTIVE_PHASES.has(checkpoint.phase) && trigger.kind === 'immediate') return START;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const dueAt = String(trigger.dueAt ?? '');
|
|
24
|
-
if (!ISO_TIMESTAMP_RE.test(dueAt)) return WAIT;
|
|
25
|
-
const dueAtMs = new Date(dueAt).getTime();
|
|
26
|
-
const nowMs = new Date(now).getTime();
|
|
27
|
-
if (!Number.isFinite(dueAtMs) || !Number.isFinite(nowMs) || dueAtMs > nowMs) return WAIT;
|
|
55
|
+
const timed = goalTimeTriggerDecision({ goal, permissionMode, now });
|
|
56
|
+
if (timed.kind !== 'due') return WAIT;
|
|
28
57
|
return Object.freeze({
|
|
29
58
|
kind: 'start',
|
|
30
59
|
trigger: 'time',
|
|
31
|
-
dueAt,
|
|
32
|
-
observation:
|
|
60
|
+
dueAt: timed.dueAt,
|
|
61
|
+
observation: timed.observation,
|
|
33
62
|
});
|
|
34
63
|
}
|
|
35
64
|
|
|
@@ -40,4 +69,4 @@ function goalContinuationDecision({ goal } = {}) {
|
|
|
40
69
|
return checkpoint.phase === 'wait' ? YIELD : CONTINUE;
|
|
41
70
|
}
|
|
42
71
|
|
|
43
|
-
module.exports = { goalAutostartDecision, goalContinuationDecision };
|
|
72
|
+
module.exports = { goalAutostartDecision, goalContinuationDecision, goalTimeTriggerDecision };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { goalTimeTriggerDecision } = require('./cognitive-goal-autostart-policy.cjs');
|
|
4
|
+
|
|
5
|
+
const MAX_TIMER_DELAY_MS = 2_147_483_647;
|
|
6
|
+
|
|
7
|
+
class GoalTimeTriggerController {
|
|
8
|
+
#readState;
|
|
9
|
+
#start;
|
|
10
|
+
#now;
|
|
11
|
+
#setTimer;
|
|
12
|
+
#clearTimer;
|
|
13
|
+
#onError;
|
|
14
|
+
#retryDelayMs;
|
|
15
|
+
#timer;
|
|
16
|
+
#timerKey;
|
|
17
|
+
#inFlightKey;
|
|
18
|
+
#startedKey;
|
|
19
|
+
#generation = 0;
|
|
20
|
+
#disposed = false;
|
|
21
|
+
|
|
22
|
+
constructor({
|
|
23
|
+
readState,
|
|
24
|
+
start,
|
|
25
|
+
now = () => new Date(),
|
|
26
|
+
setTimer = setTimeout,
|
|
27
|
+
clearTimer = clearTimeout,
|
|
28
|
+
onError = () => {},
|
|
29
|
+
retryDelayMs = 1_000,
|
|
30
|
+
} = {}) {
|
|
31
|
+
if (typeof readState !== 'function') throw new TypeError('readState must be a function');
|
|
32
|
+
if (typeof start !== 'function') throw new TypeError('start must be a function');
|
|
33
|
+
this.#readState = readState;
|
|
34
|
+
this.#start = start;
|
|
35
|
+
this.#now = now;
|
|
36
|
+
this.#setTimer = setTimer;
|
|
37
|
+
this.#clearTimer = clearTimer;
|
|
38
|
+
this.#onError = onError;
|
|
39
|
+
this.#retryDelayMs = retryDelayMs;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
sync() {
|
|
43
|
+
if (this.#disposed) return undefined;
|
|
44
|
+
const state = this.#readState() ?? {};
|
|
45
|
+
const decision = goalTimeTriggerDecision({
|
|
46
|
+
goal: state.goal,
|
|
47
|
+
permissionMode: state.permissionMode,
|
|
48
|
+
now: this.#now(),
|
|
49
|
+
});
|
|
50
|
+
if (decision.kind === 'ignore' || typeof state.sessionId !== 'string' || state.sessionId.length === 0) {
|
|
51
|
+
this.#clearScheduledTimer();
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const key = `${state.sessionId}:${decision.key}`;
|
|
56
|
+
if (this.#startedKey === key || this.#inFlightKey === key) {
|
|
57
|
+
this.#clearScheduledTimer();
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
if (decision.kind === 'schedule') {
|
|
61
|
+
this.#schedule(key, Math.min(MAX_TIMER_DELAY_MS, Math.max(0, decision.delayMs)));
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.#clearScheduledTimer();
|
|
66
|
+
if (state.idle !== true) return undefined;
|
|
67
|
+
return this.#startDueTrigger(key, decision);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
reset() {
|
|
71
|
+
this.#generation += 1;
|
|
72
|
+
this.#clearScheduledTimer();
|
|
73
|
+
this.#inFlightKey = undefined;
|
|
74
|
+
this.#startedKey = undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
dispose() {
|
|
78
|
+
this.reset();
|
|
79
|
+
this.#disposed = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#schedule(key, delayMs) {
|
|
83
|
+
if (this.#timer !== undefined && this.#timerKey === key) return;
|
|
84
|
+
this.#clearScheduledTimer();
|
|
85
|
+
this.#timerKey = key;
|
|
86
|
+
this.#timer = this.#setTimer(() => {
|
|
87
|
+
this.#timer = undefined;
|
|
88
|
+
this.#timerKey = undefined;
|
|
89
|
+
void this.sync();
|
|
90
|
+
}, delayMs);
|
|
91
|
+
this.#timer?.unref?.();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#startDueTrigger(key, decision) {
|
|
95
|
+
const generation = this.#generation;
|
|
96
|
+
this.#inFlightKey = key;
|
|
97
|
+
const trigger = {
|
|
98
|
+
key,
|
|
99
|
+
trigger: 'time',
|
|
100
|
+
dueAt: decision.dueAt,
|
|
101
|
+
observation: decision.observation,
|
|
102
|
+
};
|
|
103
|
+
let result;
|
|
104
|
+
try {
|
|
105
|
+
result = this.#start(trigger);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
result = Promise.reject(error);
|
|
108
|
+
}
|
|
109
|
+
return Promise.resolve(result).then((accepted) => {
|
|
110
|
+
if (this.#disposed || generation !== this.#generation || this.#inFlightKey !== key) return false;
|
|
111
|
+
this.#inFlightKey = undefined;
|
|
112
|
+
if (accepted === true) {
|
|
113
|
+
this.#startedKey = key;
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
this.#scheduleRetry(key);
|
|
117
|
+
return false;
|
|
118
|
+
}, (error) => {
|
|
119
|
+
if (!this.#disposed && generation === this.#generation && this.#inFlightKey === key) {
|
|
120
|
+
this.#inFlightKey = undefined;
|
|
121
|
+
this.#onError(error);
|
|
122
|
+
this.#scheduleRetry(key);
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#scheduleRetry(key) {
|
|
129
|
+
const state = this.#readState() ?? {};
|
|
130
|
+
const decision = goalTimeTriggerDecision({
|
|
131
|
+
goal: state.goal,
|
|
132
|
+
permissionMode: state.permissionMode,
|
|
133
|
+
now: this.#now(),
|
|
134
|
+
});
|
|
135
|
+
if (decision.kind !== 'due' || `${state.sessionId}:${decision.key}` !== key) return;
|
|
136
|
+
this.#schedule(key, this.#retryDelayMs);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#clearScheduledTimer() {
|
|
140
|
+
if (this.#timer !== undefined) this.#clearTimer(this.#timer);
|
|
141
|
+
this.#timer = undefined;
|
|
142
|
+
this.#timerKey = undefined;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = { GoalTimeTriggerController, MAX_TIMER_DELAY_MS };
|
package/blun.mjs
CHANGED
|
@@ -7,6 +7,7 @@ const __dirname = __cjsShimDirname(__filename);
|
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import telegramConsoleStatusPolicy from "./bin/telegram-console-status-policy.cjs";
|
|
9
9
|
import cognitiveGoalAutostartPolicy from "./bin/cognitive-goal-autostart-policy.cjs";
|
|
10
|
+
import cognitiveGoalTimeTriggerController from "./bin/cognitive-goal-time-trigger-controller.cjs";
|
|
10
11
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
11
12
|
import * as fs$16 from "node:fs";
|
|
12
13
|
import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
@@ -38,6 +39,7 @@ import { createServer } from "node:http";
|
|
|
38
39
|
import { pipeline as pipeline$1 } from "node:stream/promises";
|
|
39
40
|
const { writeTelegramConsoleStatus } = telegramConsoleStatusPolicy;
|
|
40
41
|
const { goalAutostartDecision, goalContinuationDecision } = cognitiveGoalAutostartPolicy;
|
|
42
|
+
const { GoalTimeTriggerController } = cognitiveGoalTimeTriggerController;
|
|
41
43
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
42
44
|
import { StringDecoder } from "node:string_decoder";
|
|
43
45
|
import co from "node:assert";
|
|
@@ -507786,6 +507788,7 @@ var SessionEventHandler = class {
|
|
|
507786
507788
|
this.handleEvent(event, sendQueued);
|
|
507787
507789
|
});
|
|
507788
507790
|
this.syncMcpServerStatusSnapshot(session);
|
|
507791
|
+
this.host.syncGoalTimeTrigger();
|
|
507789
507792
|
}
|
|
507790
507793
|
async syncMcpServerStatusSnapshot(session) {
|
|
507791
507794
|
const { host } = this;
|
|
@@ -508289,6 +508292,7 @@ var SessionEventHandler = class {
|
|
|
508289
508292
|
}
|
|
508290
508293
|
handleGoalUpdated(event) {
|
|
508291
508294
|
this.host.setAppState({ goal: event.snapshot });
|
|
508295
|
+
this.host.syncGoalTimeTrigger();
|
|
508292
508296
|
if (event.snapshot === null && this.goalCompletionAwaitingClear) {
|
|
508293
508297
|
this.goalCompletionAwaitingClear = false;
|
|
508294
508298
|
this.queuedGoalPromotionPending = true;
|
|
@@ -516160,6 +516164,7 @@ var BlunTUI = class {
|
|
|
516160
516164
|
personalMemoryController;
|
|
516161
516165
|
customerMistakeController;
|
|
516162
516166
|
managedQuotaWarningController;
|
|
516167
|
+
goalTimeTriggerController;
|
|
516163
516168
|
managedQuotaWarningPersistence = Promise.resolve();
|
|
516164
516169
|
footerMounted = false;
|
|
516165
516170
|
/** Timer that auto-clears the one-shot "moved to background" footer hint. */
|
|
@@ -516263,6 +516268,13 @@ var BlunTUI = class {
|
|
|
516263
516268
|
}
|
|
516264
516269
|
}));
|
|
516265
516270
|
this.streamingUI = new StreamingUIController(this);
|
|
516271
|
+
this.goalTimeTriggerController = new GoalTimeTriggerController({
|
|
516272
|
+
readState: () => this.readGoalTimeTriggerState(),
|
|
516273
|
+
start: (trigger) => this.startAutonomousGoalContinuation(trigger),
|
|
516274
|
+
onError: (error) => {
|
|
516275
|
+
this.track("goal_time_trigger_failed", { error_type: error?.code ?? error?.name ?? "Error" });
|
|
516276
|
+
}
|
|
516277
|
+
});
|
|
516266
516278
|
this.authFlow = new AuthFlowController(this);
|
|
516267
516279
|
this.personalMemoryController = new PersonalMemoryController(this);
|
|
516268
516280
|
this.customerMistakeController = new CustomerMistakeHostController();
|
|
@@ -516685,6 +516697,41 @@ var BlunTUI = class {
|
|
|
516685
516697
|
});
|
|
516686
516698
|
return result.kind === "selected" ? result.path : void 0;
|
|
516687
516699
|
}
|
|
516700
|
+
readGoalTimeTriggerState() {
|
|
516701
|
+
return {
|
|
516702
|
+
sessionId: this.session?.id ?? "",
|
|
516703
|
+
goal: this.state.appState.goal,
|
|
516704
|
+
permissionMode: this.state.appState.permissionMode,
|
|
516705
|
+
idle: this.session !== void 0 && !this.isShuttingDown && !this.aborted && !this.queueCommandRunning && this.queueSteerInFlight === void 0 && !this.editorReplacementActive && !this.deferUserMessages && !this.streamingUI.hasActiveTurn() && this.state.appState.streamingPhase === "idle" && !this.state.appState.isCompacting && this.state.queuedMessages.length === 0
|
|
516706
|
+
};
|
|
516707
|
+
}
|
|
516708
|
+
syncGoalTimeTrigger() {
|
|
516709
|
+
if (this.isShuttingDown) return;
|
|
516710
|
+
void this.goalTimeTriggerController?.sync();
|
|
516711
|
+
}
|
|
516712
|
+
async startAutonomousGoalContinuation(autostart) {
|
|
516713
|
+
const session = this.session;
|
|
516714
|
+
if (session === void 0) return false;
|
|
516715
|
+
const sessionId = session.id;
|
|
516716
|
+
const autostartPrompt = autostart.observation === void 0 ? GOAL_CONTINUATION_PROMPT : `${GOAL_CONTINUATION_PROMPT}\n\n${autostart.observation}`;
|
|
516717
|
+
this.beginSessionRequest();
|
|
516718
|
+
this.setAppState({
|
|
516719
|
+
model: BLUN_KING_MODEL_ALIAS,
|
|
516720
|
+
modelFallbackAllowed: false
|
|
516721
|
+
});
|
|
516722
|
+
try {
|
|
516723
|
+
const result = await session.promptAccepted(autostartPrompt);
|
|
516724
|
+
if (!result.accepted && this.session?.id === sessionId) {
|
|
516725
|
+
this.setAppState({ streamingPhase: "idle" });
|
|
516726
|
+
this.resetLivePane();
|
|
516727
|
+
this.track("goal_autostart", { outcome: "not_accepted" });
|
|
516728
|
+
}
|
|
516729
|
+
return result.accepted === true;
|
|
516730
|
+
} catch (error) {
|
|
516731
|
+
if (this.session?.id === sessionId) this.failSessionRequest(uiText("blunTui.session.sendFailed", { error: formatErrorMessage$2(error) }));
|
|
516732
|
+
return false;
|
|
516733
|
+
}
|
|
516734
|
+
}
|
|
516688
516735
|
async promptStartupResumeGoalIfNeeded() {
|
|
516689
516736
|
const session = this.session;
|
|
516690
516737
|
const goal = this.state.appState.goal;
|
|
@@ -516696,25 +516743,12 @@ var BlunTUI = class {
|
|
|
516696
516743
|
now: new Date()
|
|
516697
516744
|
});
|
|
516698
516745
|
if (autostart.kind === "start") {
|
|
516699
|
-
const autostartPrompt = autostart.observation === void 0 ? GOAL_CONTINUATION_PROMPT : `${GOAL_CONTINUATION_PROMPT}\n\n${autostart.observation}`;
|
|
516700
516746
|
this.startupGoalPromptedSessionId = sessionId;
|
|
516701
|
-
this.
|
|
516702
|
-
this.
|
|
516703
|
-
model: BLUN_KING_MODEL_ALIAS,
|
|
516704
|
-
modelFallbackAllowed: false
|
|
516705
|
-
});
|
|
516706
|
-
try {
|
|
516707
|
-
const result = await session.promptAccepted(autostartPrompt);
|
|
516708
|
-
if (!result.accepted && this.session?.id === sessionId) {
|
|
516709
|
-
this.setAppState({ streamingPhase: "idle" });
|
|
516710
|
-
this.resetLivePane();
|
|
516711
|
-
this.track("goal_autostart", { outcome: "not_accepted" });
|
|
516712
|
-
}
|
|
516713
|
-
} catch (error) {
|
|
516714
|
-
if (this.session?.id === sessionId) this.failSessionRequest(uiText("blunTui.session.sendFailed", { error: formatErrorMessage$2(error) }));
|
|
516715
|
-
}
|
|
516747
|
+
if (autostart.trigger === "time") await this.goalTimeTriggerController.sync();
|
|
516748
|
+
else await this.startAutonomousGoalContinuation(autostart);
|
|
516716
516749
|
return;
|
|
516717
516750
|
}
|
|
516751
|
+
this.syncGoalTimeTrigger();
|
|
516718
516752
|
if (goal.status !== "paused" && goal.status !== "blocked") return;
|
|
516719
516753
|
this.startupGoalPromptedSessionId = sessionId;
|
|
516720
516754
|
const choice = await promptStartupResumeGoal(this, goal.objective, startupResumeGoalPromptCopy());
|
|
@@ -516728,6 +516762,7 @@ var BlunTUI = class {
|
|
|
516728
516762
|
async stop(exitCode) {
|
|
516729
516763
|
if (this.isShuttingDown) return;
|
|
516730
516764
|
this.isShuttingDown = true;
|
|
516765
|
+
this.goalTimeTriggerController.dispose();
|
|
516731
516766
|
await this.flushInputDraft();
|
|
516732
516767
|
this.unregisterSignalHandlers();
|
|
516733
516768
|
this.aborted = true;
|
|
@@ -516807,6 +516842,7 @@ var BlunTUI = class {
|
|
|
516807
516842
|
}
|
|
516808
516843
|
emergencyTerminalExit(exitCode = 129) {
|
|
516809
516844
|
this.isShuttingDown = true;
|
|
516845
|
+
this.goalTimeTriggerController.dispose();
|
|
516810
516846
|
this.unregisterSignalHandlers();
|
|
516811
516847
|
this.channelQueueDeadline?.dispose();
|
|
516812
516848
|
this.directFocusController?.dispose();
|
|
@@ -518154,6 +518190,7 @@ var BlunTUI = class {
|
|
|
518154
518190
|
if (!hasPatchChanges(this.state.appState, effectivePatch)) return;
|
|
518155
518191
|
const additionalDirsChanged = "additionalDirs" in effectivePatch && !sameStringArrays(this.state.appState.additionalDirs, effectivePatch.additionalDirs ?? []);
|
|
518156
518192
|
const busyChanged = "streamingPhase" in effectivePatch || "isCompacting" in effectivePatch;
|
|
518193
|
+
const goalTimeTriggerChanged = busyChanged || "permissionMode" in effectivePatch;
|
|
518157
518194
|
Object.assign(this.state.appState, effectivePatch);
|
|
518158
518195
|
if ("planMode" in effectivePatch) this.updateEditorBorderHighlight();
|
|
518159
518196
|
this.state.loopIndicator.setState(this.state.appState);
|
|
@@ -518165,6 +518202,7 @@ var BlunTUI = class {
|
|
|
518165
518202
|
this.updateQueueDisplay();
|
|
518166
518203
|
this.sessionEventHandler.retryQueuedGoalPromotion();
|
|
518167
518204
|
}
|
|
518205
|
+
if (goalTimeTriggerChanged) queueMicrotask(() => this.syncGoalTimeTrigger());
|
|
518168
518206
|
if (additionalDirsChanged) this.setupAutocomplete();
|
|
518169
518207
|
this.state.ui.requestRender();
|
|
518170
518208
|
}
|
|
@@ -518303,6 +518341,7 @@ var BlunTUI = class {
|
|
|
518303
518341
|
}
|
|
518304
518342
|
unloadCurrentSession(reason) {
|
|
518305
518343
|
const previous = this.session;
|
|
518344
|
+
this.goalTimeTriggerController.reset();
|
|
518306
518345
|
this.managedQuotaWarningController.dismiss();
|
|
518307
518346
|
this.sessionEventUnsubscribe?.();
|
|
518308
518347
|
this.sessionEventUnsubscribe = void 0;
|
|
@@ -518355,6 +518394,7 @@ var BlunTUI = class {
|
|
|
518355
518394
|
}
|
|
518356
518395
|
resetSessionRuntime() {
|
|
518357
518396
|
this.aborted = false;
|
|
518397
|
+
this.goalTimeTriggerController.reset();
|
|
518358
518398
|
this.managedQuotaWarningController.dismiss();
|
|
518359
518399
|
this.streamingUI.discardPending();
|
|
518360
518400
|
this.streamingUI.disposeActiveCompactionBlock();
|