blun-king-cli 9.1.45 → 9.1.47
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 +1 -1
- package/README.md +1 -1
- package/blun.mjs +200 -31
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
package/README.md
CHANGED
package/blun.mjs
CHANGED
|
@@ -75557,6 +75557,9 @@ var init_full = __esmMin((() => {
|
|
|
75557
75557
|
const estimatedProgressPercent = estimateCompactionProgressPercent(stage, estimatedStageCount);
|
|
75558
75558
|
const windowUsagePercent = estimateCompactionWindowUsagePercent(estimatedCompactionRequestTokens, compactionRequestLimit);
|
|
75559
75559
|
this.agent.log.info("compaction stage request", {
|
|
75560
|
+
requestPurpose: "compaction",
|
|
75561
|
+
toolSuppressionReason: "compaction_summary",
|
|
75562
|
+
selectedToolCount: compactionTools.length,
|
|
75560
75563
|
source: data.source,
|
|
75561
75564
|
stage,
|
|
75562
75565
|
estimatedStageCount,
|
|
@@ -76582,6 +76585,24 @@ var init_jitter = __esmMin((() => {
|
|
|
76582
76585
|
}));
|
|
76583
76586
|
//#endregion
|
|
76584
76587
|
//#region ../../packages/agent-core/src/tools/cron/scheduler.ts
|
|
76588
|
+
function sessionLoopIntervalMs(task) {
|
|
76589
|
+
if (task.owner !== "session-loop" || typeof task.loopInterval !== "string") return null;
|
|
76590
|
+
if (task.loopInterval === "auto") return 15 * 6e4;
|
|
76591
|
+
const match = /^([1-9]\d*)(m|h|d)$/i.exec(task.loopInterval);
|
|
76592
|
+
if (match === null) return null;
|
|
76593
|
+
const amount = Number(match[1]);
|
|
76594
|
+
const unit = match[2]?.toLowerCase();
|
|
76595
|
+
const multiplier = unit === "m" ? 6e4 : unit === "h" ? 36e5 : 864e5;
|
|
76596
|
+
const intervalMs = amount * multiplier;
|
|
76597
|
+
return Number.isSafeInteger(intervalMs) ? intervalMs : null;
|
|
76598
|
+
}
|
|
76599
|
+
function countSessionLoopCoalesced(intervalMs, firstFireMs, nowMs) {
|
|
76600
|
+
const count = Math.max(1, Math.min(MAX_COALESCE_ITERATIONS, Math.floor((nowMs - firstFireMs) / intervalMs) + 1));
|
|
76601
|
+
return {
|
|
76602
|
+
count,
|
|
76603
|
+
lastDueMs: firstFireMs + (count - 1) * intervalMs
|
|
76604
|
+
};
|
|
76605
|
+
}
|
|
76585
76606
|
function createCronScheduler(opts) {
|
|
76586
76607
|
const { clocks, source, onFire, isIdle, isKilled, removeOneShot, onAdvanceCursor, pollIntervalMs } = opts;
|
|
76587
76608
|
const parsedCache = /* @__PURE__ */ new Map();
|
|
@@ -76605,6 +76626,8 @@ function createCronScheduler(opts) {
|
|
|
76605
76626
|
* the search budget (legal-but-never-fires expression).
|
|
76606
76627
|
*/
|
|
76607
76628
|
function computeJitteredNext(task, parsed, baseMs) {
|
|
76629
|
+
const intervalMs = sessionLoopIntervalMs(task);
|
|
76630
|
+
if (intervalMs !== null) return baseMs + intervalMs;
|
|
76608
76631
|
const ideal = computeNextCronRun(parsed, baseMs);
|
|
76609
76632
|
if (ideal === null) return null;
|
|
76610
76633
|
if (task.recurring === false) return oneShotJitteredNextCronRunMs(task, ideal);
|
|
@@ -76668,11 +76691,12 @@ function createCronScheduler(opts) {
|
|
|
76668
76691
|
const nextFireAt = computeJitteredNext(task, parsed, baseFromMs);
|
|
76669
76692
|
if (nextFireAt === null) continue;
|
|
76670
76693
|
if (now < nextFireAt) continue;
|
|
76671
|
-
const
|
|
76694
|
+
const intervalMs = sessionLoopIntervalMs(task);
|
|
76695
|
+
const ideal = intervalMs === null ? computeNextCronRun(parsed, baseFromMs) : nextFireAt;
|
|
76672
76696
|
let coalescedCount = 1;
|
|
76673
76697
|
let lastDueMs = null;
|
|
76674
76698
|
if (task.recurring !== false && ideal !== null) {
|
|
76675
|
-
const result = countCoalesced(task, parsed, ideal, now);
|
|
76699
|
+
const result = intervalMs === null ? countCoalesced(task, parsed, ideal, now) : countSessionLoopCoalesced(intervalMs, ideal, now);
|
|
76676
76700
|
coalescedCount = Math.max(1, result.count);
|
|
76677
76701
|
lastDueMs = result.lastDueMs;
|
|
76678
76702
|
}
|
|
@@ -77632,6 +77656,10 @@ var init_cron_create = __esmMin((() => {
|
|
|
77632
77656
|
//#endregion
|
|
77633
77657
|
//#region ../../packages/agent-core/src/agent/session-loop.ts
|
|
77634
77658
|
function parseLoopInterval(rawInterval) {
|
|
77659
|
+
if (rawInterval.trim().toLowerCase() === "auto") return {
|
|
77660
|
+
interval: "auto",
|
|
77661
|
+
cron: "* * * * *"
|
|
77662
|
+
};
|
|
77635
77663
|
const match = LOOP_INTERVAL_PATTERN.exec(rawInterval.trim());
|
|
77636
77664
|
if (match === null) throw invalidLoopInterval(rawInterval);
|
|
77637
77665
|
const amount = Number(match[1]);
|
|
@@ -77639,25 +77667,13 @@ function parseLoopInterval(rawInterval) {
|
|
|
77639
77667
|
if (!Number.isSafeInteger(amount)) throw invalidLoopInterval(rawInterval);
|
|
77640
77668
|
const totalMinutes = unit === "m" ? amount : unit === "h" ? amount * 60 : amount * 1440;
|
|
77641
77669
|
if (!Number.isSafeInteger(totalMinutes)) throw invalidLoopInterval(rawInterval);
|
|
77642
|
-
|
|
77643
|
-
interval:
|
|
77644
|
-
cron: "
|
|
77645
|
-
};
|
|
77646
|
-
if (totalMinutes < 60 && 60 % totalMinutes === 0) return {
|
|
77647
|
-
interval: `${String(totalMinutes)}m`,
|
|
77648
|
-
cron: totalMinutes === 1 ? "* * * * *" : `*/${String(totalMinutes)} * * * *`
|
|
77670
|
+
return {
|
|
77671
|
+
interval: `${String(amount)}${unit}`,
|
|
77672
|
+
cron: "* * * * *"
|
|
77649
77673
|
};
|
|
77650
|
-
if (totalMinutes < 1440 && totalMinutes % 60 === 0) {
|
|
77651
|
-
const hours = totalMinutes / 60;
|
|
77652
|
-
if (24 % hours === 0) return {
|
|
77653
|
-
interval: `${String(hours)}h`,
|
|
77654
|
-
cron: hours === 1 ? "0 * * * *" : `0 */${String(hours)} * * *`
|
|
77655
|
-
};
|
|
77656
|
-
}
|
|
77657
|
-
throw invalidLoopInterval(rawInterval);
|
|
77658
77674
|
}
|
|
77659
77675
|
function invalidLoopInterval(rawInterval) {
|
|
77660
|
-
return new BlunError(ErrorCodes.LOOP_INTERVAL_INVALID, `Invalid loop interval ${JSON.stringify(rawInterval)}
|
|
77676
|
+
return new BlunError(ErrorCodes.LOOP_INTERVAL_INVALID, `Invalid loop interval ${JSON.stringify(rawInterval)}`);
|
|
77661
77677
|
}
|
|
77662
77678
|
var MAX_LOOP_PROMPT_BYTES, LOOP_INTERVAL_PATTERN, SessionLoopMode;
|
|
77663
77679
|
var init_session_loop = __esmMin((() => {
|
|
@@ -259739,6 +259755,12 @@ function blunSelectTurnTools(tools, maxContextTokens) {
|
|
|
259739
259755
|
const lean = tools.filter((tool) => BLUN_LEAN_TOOL_NAMES.has(tool.name) || BLUN_LEAN_KEEP_RE.test(tool.name));
|
|
259740
259756
|
return lean.length > 0 ? lean : tools;
|
|
259741
259757
|
}
|
|
259758
|
+
function blunToolSuppressionReason(turnNeedsTools, eligibleTools, selectedTools) {
|
|
259759
|
+
if (!turnNeedsTools) return "greeting_optimization";
|
|
259760
|
+
if (eligibleTools.length === 0) return "no_eligible_tools";
|
|
259761
|
+
if (selectedTools.length < eligibleTools.length) return "context_budget_lean_set";
|
|
259762
|
+
return "none";
|
|
259763
|
+
}
|
|
259742
259764
|
function isGoalOutcomeReminderOrigin(origin) {
|
|
259743
259765
|
return origin?.kind === "system_trigger" && (origin.name === "goal_completion" || origin.name === "goal_blocked");
|
|
259744
259766
|
}
|
|
@@ -260553,6 +260575,13 @@ var init_turn = __esmMin((() => {
|
|
|
260553
260575
|
try {
|
|
260554
260576
|
const eligibleTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools), origin);
|
|
260555
260577
|
const selectedTools = turnNeedsTools ? blunSelectTurnTools(eligibleTools, this.agent.config.modelCapabilities?.max_context_tokens) : [];
|
|
260578
|
+
const toolSuppressionReason = blunToolSuppressionReason(turnNeedsTools, eligibleTools, selectedTools);
|
|
260579
|
+
this.agent.log.info("turn request tools", {
|
|
260580
|
+
requestPurpose: "conversation",
|
|
260581
|
+
toolSuppressionReason,
|
|
260582
|
+
eligibleToolCount: eligibleTools.length,
|
|
260583
|
+
selectedToolCount: selectedTools.length
|
|
260584
|
+
});
|
|
260556
260585
|
return (await runTurn({
|
|
260557
260586
|
turnId: String(turnId),
|
|
260558
260587
|
signal,
|
|
@@ -401109,7 +401138,8 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
|
|
|
401109
401138
|
aliases: [],
|
|
401110
401139
|
descriptionKey: "command.loop.description",
|
|
401111
401140
|
priority: 80,
|
|
401112
|
-
argumentHint: "
|
|
401141
|
+
argumentHint: "<natürlicher Auftrag>",
|
|
401142
|
+
liveArgumentHint: loopInputHint,
|
|
401113
401143
|
availability: (args) => {
|
|
401114
401144
|
const trimmed = args.trim();
|
|
401115
401145
|
if (trimmed === "") return "always";
|
|
@@ -420058,7 +420088,8 @@ function isBusy(host) {
|
|
|
420058
420088
|
}
|
|
420059
420089
|
//#endregion
|
|
420060
420090
|
//#region src/tui/commands/loop.ts
|
|
420061
|
-
const LOOP_ARGUMENT_HINT = "/loop
|
|
420091
|
+
const LOOP_ARGUMENT_HINT = "/loop <natürlicher Auftrag> · Zeitangaben dürfen überall stehen";
|
|
420092
|
+
const DEFAULT_LOOP_INTERVAL = "auto";
|
|
420062
420093
|
const LOOP_CREATE_FILLERS = new Set([
|
|
420063
420094
|
"mit",
|
|
420064
420095
|
"alle",
|
|
@@ -420068,6 +420099,77 @@ const LOOP_CREATE_FILLERS = new Set([
|
|
|
420068
420099
|
"each"
|
|
420069
420100
|
]);
|
|
420070
420101
|
const LOOP_INTERVAL_TOKEN = /^\d+(?:m|h|d)$/i;
|
|
420102
|
+
const LOOP_NATURAL_INTERVAL = /\b(?:alle|jede(?:n|r|s)?|every|each)\s+(\d+)\s*(min(?:ute)?n?|minutes?|stunden?|hours?|tage?|days?)\b/iu;
|
|
420103
|
+
const LOOP_NATURAL_HALF_HOUR = /\b(?:alle|jede(?:n|r|s)?|every|each)\s+(?:halbe|half(?:\s+an)?)\s+(?:stunde|hour)\b/iu;
|
|
420104
|
+
const LOOP_NATURAL_SINGLE_INTERVAL = /\b(?:jede(?:n|r|s)?|every|each)\s+(minute|stunde|hour|tag|day)\b/iu;
|
|
420105
|
+
const LOOP_NATURAL_ADVERB_INTERVAL = /\b(stündlich|stuendlich|hourly|täglich|taeglich|daily)\b/iu;
|
|
420106
|
+
const LOOP_SELF_CONTROLLED = /\b(?:selbst\s+entscheiden|selbstgesteuert)\b/iu;
|
|
420107
|
+
function naturalLoopIntervalMatch(args) {
|
|
420108
|
+
const numeric = LOOP_NATURAL_INTERVAL.exec(args);
|
|
420109
|
+
if (numeric !== null) {
|
|
420110
|
+
const amount = numeric[1];
|
|
420111
|
+
const unit = numeric[2]?.toLowerCase() ?? "";
|
|
420112
|
+
const suffix = unit.startsWith("stund") || unit.startsWith("hour") ? "h" : unit.startsWith("tag") || unit.startsWith("day") ? "d" : "m";
|
|
420113
|
+
return {
|
|
420114
|
+
match: numeric,
|
|
420115
|
+
interval: `${amount}${suffix}`
|
|
420116
|
+
};
|
|
420117
|
+
}
|
|
420118
|
+
const halfHour = LOOP_NATURAL_HALF_HOUR.exec(args);
|
|
420119
|
+
if (halfHour !== null) return {
|
|
420120
|
+
match: halfHour,
|
|
420121
|
+
interval: "30m"
|
|
420122
|
+
};
|
|
420123
|
+
const single = LOOP_NATURAL_SINGLE_INTERVAL.exec(args);
|
|
420124
|
+
if (single !== null) {
|
|
420125
|
+
const unit = single[1]?.toLowerCase() ?? "";
|
|
420126
|
+
return {
|
|
420127
|
+
match: single,
|
|
420128
|
+
interval: unit === "minute" ? "1m" : unit === "tag" || unit === "day" ? "1d" : "1h"
|
|
420129
|
+
};
|
|
420130
|
+
}
|
|
420131
|
+
const adverb = LOOP_NATURAL_ADVERB_INTERVAL.exec(args);
|
|
420132
|
+
if (adverb !== null) {
|
|
420133
|
+
const unit = adverb[1]?.toLowerCase() ?? "";
|
|
420134
|
+
return {
|
|
420135
|
+
match: adverb,
|
|
420136
|
+
interval: unit === "täglich" || unit === "taeglich" || unit === "daily" ? "1d" : "1h"
|
|
420137
|
+
};
|
|
420138
|
+
}
|
|
420139
|
+
return null;
|
|
420140
|
+
}
|
|
420141
|
+
function parseNaturalLoopInterval(args) {
|
|
420142
|
+
const parsed = naturalLoopIntervalMatch(args);
|
|
420143
|
+
if (parsed === null) return null;
|
|
420144
|
+
const { match, interval } = parsed;
|
|
420145
|
+
const prompt = `${args.slice(0, match.index)} ${args.slice(match.index + match[0].length)}`.replace(/\s+/gu, " ").trim();
|
|
420146
|
+
if (prompt.length === 0) return { kind: "error" };
|
|
420147
|
+
return {
|
|
420148
|
+
kind: "create",
|
|
420149
|
+
interval,
|
|
420150
|
+
prompt
|
|
420151
|
+
};
|
|
420152
|
+
}
|
|
420153
|
+
function naturalLoopIntervalText(interval) {
|
|
420154
|
+
if (interval === "auto") return "Selbstgesteuert";
|
|
420155
|
+
const match = /^([1-9]\d*)(m|h|d)$/i.exec(interval);
|
|
420156
|
+
if (match === null) return "";
|
|
420157
|
+
const amount = Number(match[1]);
|
|
420158
|
+
const unit = match[2]?.toLowerCase();
|
|
420159
|
+
if (unit === "m") return `Erkannt: alle ${String(amount)} ${amount === 1 ? "Minute" : "Minuten"}`;
|
|
420160
|
+
if (unit === "h") return `Erkannt: alle ${String(amount)} ${amount === 1 ? "Stunde" : "Stunden"}`;
|
|
420161
|
+
return `Erkannt: alle ${String(amount)} ${amount === 1 ? "Tag" : "Tage"}`;
|
|
420162
|
+
}
|
|
420163
|
+
function loopInputHint(rawArgs) {
|
|
420164
|
+
const args = rawArgs.trim();
|
|
420165
|
+
if (args.length === 0) return "Natürlichen Auftrag eingeben; Zeitangaben dürfen überall stehen";
|
|
420166
|
+
if (/^(?:status|pause|paused|resume|stop)$/i.test(args)) return "";
|
|
420167
|
+
const natural = naturalLoopIntervalMatch(args);
|
|
420168
|
+
if (natural !== null) return naturalLoopIntervalText(natural.interval);
|
|
420169
|
+
const explicit = /^(?:start\s+)?([1-9]\d*(?:m|h|d))\b/i.exec(args);
|
|
420170
|
+
if (explicit?.[1] !== void 0) return naturalLoopIntervalText(explicit[1].toLowerCase());
|
|
420171
|
+
return "Selbstgesteuert";
|
|
420172
|
+
}
|
|
420071
420173
|
function parseLoopCommand(rawArgs) {
|
|
420072
420174
|
const args = rawArgs.trim();
|
|
420073
420175
|
if (args.length === 0 || args.toLowerCase() === "status") return { kind: "status" };
|
|
@@ -420079,13 +420181,35 @@ function parseLoopCommand(rawArgs) {
|
|
|
420079
420181
|
if (action === "stop") return { kind: "stop" };
|
|
420080
420182
|
}
|
|
420081
420183
|
let startIndex = action === "start" ? 1 : 0;
|
|
420184
|
+
const createArgs = tokens.slice(startIndex).join(" ");
|
|
420185
|
+
const natural = parseNaturalLoopInterval(createArgs);
|
|
420186
|
+
if (natural !== null) return natural;
|
|
420187
|
+
const selfControlled = LOOP_SELF_CONTROLLED.exec(createArgs);
|
|
420188
|
+
if (selfControlled !== null) {
|
|
420189
|
+
const prompt = `${createArgs.slice(0, selfControlled.index)} ${createArgs.slice(selfControlled.index + selfControlled[0].length)}`.replace(/\s+/gu, " ").trim();
|
|
420190
|
+
if (prompt.length === 0) return { kind: "error" };
|
|
420191
|
+
return {
|
|
420192
|
+
kind: "create",
|
|
420193
|
+
interval: "auto",
|
|
420194
|
+
prompt
|
|
420195
|
+
};
|
|
420196
|
+
}
|
|
420082
420197
|
if (LOOP_CREATE_FILLERS.has(tokens[startIndex]?.toLowerCase() ?? "")) startIndex += 1;
|
|
420083
420198
|
const interval = tokens[startIndex];
|
|
420084
|
-
|
|
420085
|
-
|
|
420199
|
+
if (interval !== void 0 && LOOP_INTERVAL_TOKEN.test(interval)) {
|
|
420200
|
+
const prompt = tokens.slice(startIndex + 1).join(" ").trim();
|
|
420201
|
+
if (prompt.length === 0) return { kind: "error" };
|
|
420202
|
+
return {
|
|
420203
|
+
kind: "create",
|
|
420204
|
+
interval,
|
|
420205
|
+
prompt
|
|
420206
|
+
};
|
|
420207
|
+
}
|
|
420208
|
+
const prompt = tokens.slice(startIndex).join(" ").trim();
|
|
420209
|
+
if (prompt.length === 0) return { kind: "error" };
|
|
420086
420210
|
return {
|
|
420087
420211
|
kind: "create",
|
|
420088
|
-
interval,
|
|
420212
|
+
interval: DEFAULT_LOOP_INTERVAL,
|
|
420089
420213
|
prompt
|
|
420090
420214
|
};
|
|
420091
420215
|
}
|
|
@@ -501930,6 +502054,9 @@ var PersonalMemoryController = class {
|
|
|
501930
502054
|
};
|
|
501931
502055
|
//#endregion
|
|
501932
502056
|
//#region src/tui/constant/scrollback.ts
|
|
502057
|
+
function shouldEnableScrollbackMouseTracking(buffer) {
|
|
502058
|
+
return buffer !== void 0 && buffer.isActive();
|
|
502059
|
+
}
|
|
501933
502060
|
const ENABLE_SCROLLBACK_MOUSE_TRACKING = "\x1B[?1000h\x1B[?1006h";
|
|
501934
502061
|
const DISABLE_SCROLLBACK_MOUSE_TRACKING = "\x1B[?1000l\x1B[?1006l";
|
|
501935
502062
|
//#endregion
|
|
@@ -502286,7 +502413,7 @@ var BottomPinnedTUI = class extends TUI {
|
|
|
502286
502413
|
}
|
|
502287
502414
|
const buffer = this.scrollbackBuffer;
|
|
502288
502415
|
buffer?.updateSnapshot(clipped, scrollViewportRows);
|
|
502289
|
-
this.setMouseTracking(buffer
|
|
502416
|
+
this.setMouseTracking(shouldEnableScrollbackMouseTracking(buffer));
|
|
502290
502417
|
if (buffer !== void 0 && buffer.isActive() && terminalRows > 0) {
|
|
502291
502418
|
const pinnedLines = [];
|
|
502292
502419
|
for (let i = chromeAt; i < blocks.length; i++) {
|
|
@@ -510056,8 +510183,10 @@ var CustomEditor = class extends Editor {
|
|
|
510056
510183
|
consumingPaste = false;
|
|
510057
510184
|
consumeBuffer = "";
|
|
510058
510185
|
argumentHints = /* @__PURE__ */ new Map();
|
|
510059
|
-
|
|
510186
|
+
argumentHintResolvers = /* @__PURE__ */ new Map();
|
|
510187
|
+
setArgumentHints(hints, resolvers = /* @__PURE__ */ new Map()) {
|
|
510060
510188
|
this.argumentHints = hints;
|
|
510189
|
+
this.argumentHintResolvers = resolvers;
|
|
510061
510190
|
}
|
|
510062
510191
|
constructor(tui, options = {}) {
|
|
510063
510192
|
const theme = createEditorTheme();
|
|
@@ -510151,12 +510280,18 @@ var CustomEditor = class extends Editor {
|
|
|
510151
510280
|
computeArgumentHint() {
|
|
510152
510281
|
if (this.inputMode === "bash") return void 0;
|
|
510153
510282
|
const text = this.getText();
|
|
510154
|
-
const match = /^\/(\S+)(
|
|
510283
|
+
const match = /^\/(\S+)(?:\s+([\s\S]*))?$/.exec(text);
|
|
510155
510284
|
if (match === null) return void 0;
|
|
510156
510285
|
const cmd = match[1];
|
|
510157
|
-
const
|
|
510286
|
+
const args = match[2] ?? "";
|
|
510287
|
+
const trailingSpace = text.endsWith(" ") ? " " : "";
|
|
510158
510288
|
if (cmd === void 0) return void 0;
|
|
510159
510289
|
if (this.hasAutocompleteActivity() && trailingSpace.length === 0) return void 0;
|
|
510290
|
+
const resolver = this.argumentHintResolvers.get(cmd);
|
|
510291
|
+
if (resolver !== void 0) {
|
|
510292
|
+
const resolved = resolver(args);
|
|
510293
|
+
if (resolved.length > 0) return args.length > 0 ? ` · ${resolved}` : ` ${resolved}`;
|
|
510294
|
+
}
|
|
510160
510295
|
const hint = this.argumentHints.get(cmd);
|
|
510161
510296
|
if (hint === void 0) return void 0;
|
|
510162
510297
|
const { line, col } = this.getCursor();
|
|
@@ -512061,20 +512196,26 @@ var BlunTUI = class {
|
|
|
512061
512196
|
aliases: cmd.aliases,
|
|
512062
512197
|
description: cmd.description,
|
|
512063
512198
|
...cmd.argumentHint !== void 0 ? { argumentHint: cmd.argumentHint } : {},
|
|
512199
|
+
...cmd.liveArgumentHint !== void 0 ? { liveArgumentHint: cmd.liveArgumentHint } : {},
|
|
512064
512200
|
...completer !== void 0 ? { getArgumentCompletions: (prefix) => completer(prefix) } : {}
|
|
512065
512201
|
};
|
|
512066
512202
|
});
|
|
512067
512203
|
const provider = new FileMentionProvider(slashCommands, this.state.appState.workDir, this.fdPath, this.state.appState.additionalDirs, () => this.state.appState.inputMode, this.mentionFileSearch);
|
|
512068
512204
|
this.state.editor.setAutocompleteProvider(provider);
|
|
512069
512205
|
const argumentHints = /* @__PURE__ */ new Map();
|
|
512206
|
+
const argumentHintResolvers = /* @__PURE__ */ new Map();
|
|
512070
512207
|
for (const cmd of slashCommands) {
|
|
512071
512208
|
if (cmd.argumentHint === void 0) continue;
|
|
512072
512209
|
const visibleHint = cmd.description?.trim();
|
|
512073
512210
|
if (visibleHint === void 0 || visibleHint.length === 0) continue;
|
|
512074
512211
|
argumentHints.set(cmd.name, visibleHint);
|
|
512075
512212
|
for (const alias of cmd.aliases ?? []) argumentHints.set(alias, visibleHint);
|
|
512213
|
+
if (cmd.liveArgumentHint !== void 0) {
|
|
512214
|
+
argumentHintResolvers.set(cmd.name, cmd.liveArgumentHint);
|
|
512215
|
+
for (const alias of cmd.aliases ?? []) argumentHintResolvers.set(alias, cmd.liveArgumentHint);
|
|
512216
|
+
}
|
|
512076
512217
|
}
|
|
512077
|
-
this.state.editor.setArgumentHints(argumentHints);
|
|
512218
|
+
this.state.editor.setArgumentHints(argumentHints, argumentHintResolvers);
|
|
512078
512219
|
}
|
|
512079
512220
|
refreshSlashCommandAutocomplete() {
|
|
512080
512221
|
this.setupAutocomplete();
|
|
@@ -514681,16 +514822,44 @@ function readTelegramUpdateRecipients(stateDir = defaultTelegramStateDir()) {
|
|
|
514681
514822
|
return [];
|
|
514682
514823
|
}
|
|
514683
514824
|
}
|
|
514825
|
+
function claimTelegramUpdateNotice(version, chatId, receiptDir = join(homedir(), ".blun", "updates", "telegram-notices")) {
|
|
514826
|
+
const safeVersion = version.trim().replace(/[^0-9A-Za-z._-]/gu, "_").slice(0, 64);
|
|
514827
|
+
if (safeVersion.length === 0 || !TELEGRAM_DM_ID.test(chatId)) return null;
|
|
514828
|
+
const receiptPath = join(receiptDir, `${safeVersion}-${chatId}.sent`);
|
|
514829
|
+
try {
|
|
514830
|
+
mkdirSync(receiptDir, {
|
|
514831
|
+
recursive: true,
|
|
514832
|
+
mode: 448
|
|
514833
|
+
});
|
|
514834
|
+
writeFileSync(receiptPath, `${(/* @__PURE__ */ new Date()).toISOString()}\n`, {
|
|
514835
|
+
encoding: "utf8",
|
|
514836
|
+
flag: "wx",
|
|
514837
|
+
mode: 384
|
|
514838
|
+
});
|
|
514839
|
+
return receiptPath;
|
|
514840
|
+
} catch {
|
|
514841
|
+
return null;
|
|
514842
|
+
}
|
|
514843
|
+
}
|
|
514684
514844
|
async function sendTelegramUpdateNotice(text, options = {}) {
|
|
514685
514845
|
const stateDir = options.stateDir ?? defaultTelegramStateDir();
|
|
514686
514846
|
const configured = hasConfiguredToken(stateDir);
|
|
514687
514847
|
const recipients = configured ? readTelegramUpdateRecipients(stateDir) : [];
|
|
514688
514848
|
const send = options.send ?? ((chatId, message) => sendReplyFallback(chatId, message));
|
|
514689
514849
|
let sent = 0;
|
|
514690
|
-
|
|
514850
|
+
let attempted = 0;
|
|
514851
|
+
for (const chatId of recipients) {
|
|
514852
|
+
const receiptPath = options.version === void 0 ? void 0 : claimTelegramUpdateNotice(options.version, chatId, options.receiptDir);
|
|
514853
|
+
if (options.version !== void 0 && receiptPath === null) continue;
|
|
514854
|
+
attempted += 1;
|
|
514855
|
+
if (await send(chatId, text).catch(() => false)) sent += 1;
|
|
514856
|
+
else if (receiptPath !== void 0) try {
|
|
514857
|
+
unlinkSync(receiptPath);
|
|
514858
|
+
} catch {}
|
|
514859
|
+
}
|
|
514691
514860
|
return {
|
|
514692
514861
|
configured,
|
|
514693
|
-
attempted
|
|
514862
|
+
attempted,
|
|
514694
514863
|
sent
|
|
514695
514864
|
};
|
|
514696
514865
|
}
|
|
@@ -514843,7 +515012,7 @@ async function runShell(opts, version, updateStartupNotice) {
|
|
|
514843
515012
|
workDir,
|
|
514844
515013
|
startupNotice: configWarning,
|
|
514845
515014
|
onStartupNoticeShown: updateStartupNotice === void 0 || updateNoticeText === void 0 ? void 0 : async () => {
|
|
514846
|
-
const delivery = await sendTelegramUpdateNotice(updateNoticeText);
|
|
515015
|
+
const delivery = await sendTelegramUpdateNotice(updateNoticeText, { version: updateStartupNotice.details.version });
|
|
514847
515016
|
if (!delivery.configured || delivery.attempted === 0 || delivery.sent === delivery.attempted) await updateStartupNotice.acknowledge();
|
|
514848
515017
|
}
|
|
514849
515018
|
});
|