blun-king-cli 9.1.224 → 9.1.226

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.
@@ -103,6 +103,16 @@ function refreshedSystemPromptContext(previousFingerprint, context) {
103
103
  return { fingerprint, reminder };
104
104
  }
105
105
 
106
+ function resolveStableSystemPromptTimestamp(value, fallback = new Date()) {
107
+ const candidate = value instanceof Date ? value : new Date(value);
108
+ if (Number.isFinite(candidate.getTime())) return new Date(candidate.getTime());
109
+
110
+ const fallbackDate = fallback instanceof Date ? fallback : new Date(fallback);
111
+ return Number.isFinite(fallbackDate.getTime())
112
+ ? new Date(fallbackDate.getTime())
113
+ : new Date();
114
+ }
115
+
106
116
  module.exports = {
107
117
  SYSTEM_PROMPT_DIRECTORY_MAX_CHARS,
108
118
  SYSTEM_PROMPT_DIRECTORY_TRUNCATED_MARKER,
@@ -110,4 +120,5 @@ module.exports = {
110
120
  compactRepeatedConductSections,
111
121
  fingerprintSystemPromptContext,
112
122
  refreshedSystemPromptContext,
123
+ resolveStableSystemPromptTimestamp,
113
124
  };
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const CANDIDATE_ID = /^vl-[a-f0-9]{32}$/iu;
4
+ const COMMAND_HASH = /^[a-f0-9]{64}$/iu;
5
+ const TOOL_NAME = /^[a-z0-9._ -]{1,64}$/iu;
6
+
7
+ function safeLatestCandidate(candidate) {
8
+ const id = typeof candidate?.id === 'string' && CANDIDATE_ID.test(candidate.id)
9
+ ? candidate.id
10
+ : 'unknown';
11
+ const toolName = typeof candidate?.verification?.toolName === 'string'
12
+ && TOOL_NAME.test(candidate.verification.toolName)
13
+ ? candidate.verification.toolName
14
+ : 'unknown';
15
+ const commandHash = typeof candidate?.verification?.commandHash === 'string'
16
+ && COMMAND_HASH.test(candidate.verification.commandHash)
17
+ ? candidate.verification.commandHash.slice(0, 12)
18
+ : 'unknown';
19
+ return { id, toolName, commandHash };
20
+ }
21
+
22
+ function buildValidatedLearningInsight(candidates) {
23
+ const insight = {
24
+ pending: 0,
25
+ recorded: 0,
26
+ expired: 0,
27
+ latestPending: null,
28
+ };
29
+ let latestCandidate = null;
30
+ let latestTime = Number.NEGATIVE_INFINITY;
31
+
32
+ for (const candidate of Array.isArray(candidates) ? candidates : []) {
33
+ if (!candidate || typeof candidate !== 'object') continue;
34
+ if (candidate.status === 'recorded') {
35
+ insight.recorded += 1;
36
+ continue;
37
+ }
38
+ if (candidate.status === 'expired') {
39
+ insight.expired += 1;
40
+ continue;
41
+ }
42
+ if (candidate.status !== 'pending') continue;
43
+
44
+ insight.pending += 1;
45
+ const candidateTime = Date.parse(candidate.createdAt);
46
+ if (latestCandidate === null || (Number.isFinite(candidateTime) && candidateTime >= latestTime)) {
47
+ latestCandidate = candidate;
48
+ latestTime = Number.isFinite(candidateTime) ? candidateTime : latestTime;
49
+ }
50
+ }
51
+
52
+ if (latestCandidate !== null) insight.latestPending = safeLatestCandidate(latestCandidate);
53
+ return insight;
54
+ }
55
+
56
+ module.exports = {
57
+ buildValidatedLearningInsight,
58
+ };
package/blun.mjs CHANGED
@@ -21437,7 +21437,7 @@ var init_list_directory = __esmMin((() => {
21437
21437
  }));
21438
21438
  //#endregion
21439
21439
  //#region ../../packages/agent-core/src/profile/context.ts
21440
- var { boundSystemPromptDirectoryListing, compactRepeatedConductSections, fingerprintSystemPromptContext, refreshedSystemPromptContext } = createRequire(import.meta.url)("./bin/system-prompt-context-policy.cjs");
21440
+ var { boundSystemPromptDirectoryListing, compactRepeatedConductSections, fingerprintSystemPromptContext, refreshedSystemPromptContext, resolveStableSystemPromptTimestamp } = createRequire(import.meta.url)("./bin/system-prompt-context-policy.cjs");
21441
21441
  async function prepareSystemPromptContext(kaos, brandHome, options) {
21442
21442
  const additionalDirs = normalizeAdditionalDirs(options?.additionalDirs ?? []);
21443
21443
  const [cwdListing, agentsMdResult, additionalDirsInfo] = await Promise.all([
@@ -264973,6 +264973,9 @@ var init_agent = __esmMin((() => {
264973
264973
  setRuntimeSystemPromptAppend(value) {
264974
264974
  this.runtimeSystemPromptAppend = normalizeRuntimeSystemPromptAppend(value);
264975
264975
  }
264976
+ setSystemPromptTimestamp(value) {
264977
+ this.systemPromptTimestamp = resolveStableSystemPromptTimestamp(value, this.systemPromptTimestamp);
264978
+ }
264976
264979
  setActiveResponderModel(modelAlias) {
264977
264980
  if (this._activeResponderModel === modelAlias) return;
264978
264981
  this._activeResponderModel = modelAlias;
@@ -297363,6 +297366,7 @@ var init_session$1 = __esmMin((() => {
297363
297366
  additionalDirs: parentAgent?.getAdditionalDirs() ?? this.additionalDirs,
297364
297367
  systemPromptContextProvider: () => prepareSystemPromptContext(this.systemContextKaos(agent.kaos.getcwd()), this.options.blunHomeDir, { additionalDirs: agent.getAdditionalDirs() })
297365
297368
  });
297369
+ agent.setSystemPromptTimestamp(this.metadata.createdAt);
297366
297370
  agent.setRuntimeSystemPromptAppend(this.accountMemoryContext);
297367
297371
  return agent;
297368
297372
  }
@@ -340806,7 +340810,13 @@ registerUiCatalogFragment({
340806
340810
  en: {
340807
340811
  "command.update.description": "Configure updates",
340808
340812
  "command.premortem.description": "Stress-test a plan before execution",
340813
+ "command.improve.description": "Show validated learning status",
340809
340814
  "premortem.usage": "Usage: /premortem <plan or decision>",
340815
+ "learning.panel.title": "Validated learning",
340816
+ "learning.counts": "Pending: {pending} · Recorded: {recorded} · Expired: {expired}",
340817
+ "learning.latest": "Latest candidate",
340818
+ "learning.verification": "Verification",
340819
+ "learning.empty": "No validated learning candidates yet.",
340810
340820
  "update.title": "Update behavior",
340811
340821
  "update.hint": "↑↓ navigate · Enter select · Esc cancel",
340812
340822
  "update.manual.label": "Manual updates",
@@ -340823,7 +340833,13 @@ registerUiCatalogFragment({
340823
340833
  de: {
340824
340834
  "command.update.description": "Updates konfigurieren",
340825
340835
  "command.premortem.description": "Einen Plan vor der Umsetzung auf Schwachstellen prüfen",
340836
+ "command.improve.description": "Status des validierten Lernens anzeigen",
340826
340837
  "premortem.usage": "Verwendung: /premortem <Plan oder Entscheidung>",
340838
+ "learning.panel.title": "Validiertes Lernen",
340839
+ "learning.counts": "Offen: {pending} · Übernommen: {recorded} · Abgelaufen: {expired}",
340840
+ "learning.latest": "Neuester Kandidat",
340841
+ "learning.verification": "Prüfung",
340842
+ "learning.empty": "Noch keine validierten Lernkandidaten vorhanden.",
340827
340843
  "update.title": "Update-Verhalten",
340828
340844
  "update.hint": "↑↓ navigieren · Enter auswählen · Esc abbrechen",
340829
340845
  "update.manual.label": "Updates von Hand",
@@ -340840,7 +340856,13 @@ registerUiCatalogFragment({
340840
340856
  es: {
340841
340857
  "command.update.description": "Configurar actualizaciones",
340842
340858
  "command.premortem.description": "Someter un plan a una prueba de estrés antes de ejecutarlo",
340859
+ "command.improve.description": "Mostrar el estado del aprendizaje validado",
340843
340860
  "premortem.usage": "Uso: /premortem <plan o decisión>",
340861
+ "learning.panel.title": "Aprendizaje validado",
340862
+ "learning.counts": "Pendientes: {pending} · Registrados: {recorded} · Caducados: {expired}",
340863
+ "learning.latest": "Candidato más reciente",
340864
+ "learning.verification": "Verificación",
340865
+ "learning.empty": "Todavía no hay candidatos de aprendizaje validados.",
340844
340866
  "update.title": "Comportamiento de las actualizaciones",
340845
340867
  "update.hint": "↑↓ navegar · Enter seleccionar · Esc cancelar",
340846
340868
  "update.manual.label": "Actualizaciones manuales",
@@ -340857,7 +340879,13 @@ registerUiCatalogFragment({
340857
340879
  fr: {
340858
340880
  "command.update.description": "Configurer les mises à jour",
340859
340881
  "command.premortem.description": "Mettre un plan à l’épreuve avant son exécution",
340882
+ "command.improve.description": "Afficher l’état de l’apprentissage validé",
340860
340883
  "premortem.usage": "Utilisation : /premortem <plan ou décision>",
340884
+ "learning.panel.title": "Apprentissage validé",
340885
+ "learning.counts": "En attente : {pending} · Enregistrés : {recorded} · Expirés : {expired}",
340886
+ "learning.latest": "Candidat le plus récent",
340887
+ "learning.verification": "Vérification",
340888
+ "learning.empty": "Aucun candidat d’apprentissage validé pour le moment.",
340861
340889
  "update.title": "Comportement des mises à jour",
340862
340890
  "update.hint": "↑↓ naviguer · Entrée sélectionner · Échap annuler",
340863
340891
  "update.manual.label": "Mises à jour manuelles",
@@ -340874,7 +340902,13 @@ registerUiCatalogFragment({
340874
340902
  sv: {
340875
340903
  "command.update.description": "Konfigurera uppdateringar",
340876
340904
  "command.premortem.description": "Stresstesta en plan före genomförandet",
340905
+ "command.improve.description": "Visa status för validerat lärande",
340877
340906
  "premortem.usage": "Användning: /premortem <plan eller beslut>",
340907
+ "learning.panel.title": "Validerat lärande",
340908
+ "learning.counts": "Väntande: {pending} · Registrerade: {recorded} · Utgångna: {expired}",
340909
+ "learning.latest": "Senaste kandidaten",
340910
+ "learning.verification": "Verifiering",
340911
+ "learning.empty": "Det finns inga validerade inlärningskandidater ännu.",
340878
340912
  "update.title": "Uppdateringsbeteende",
340879
340913
  "update.hint": "↑↓ navigera · Enter välj · Esc avbryt",
340880
340914
  "update.manual.label": "Manuella uppdateringar",
@@ -340891,7 +340925,13 @@ registerUiCatalogFragment({
340891
340925
  cs: {
340892
340926
  "command.update.description": "Nastavit aktualizace",
340893
340927
  "command.premortem.description": "Prověřit plán před provedením zátěžovým testem",
340928
+ "command.improve.description": "Zobrazit stav ověřeného učení",
340894
340929
  "premortem.usage": "Použití: /premortem <plán nebo rozhodnutí>",
340930
+ "learning.panel.title": "Ověřené učení",
340931
+ "learning.counts": "Čekající: {pending} · Zaznamenané: {recorded} · Prošlé: {expired}",
340932
+ "learning.latest": "Nejnovější kandidát",
340933
+ "learning.verification": "Ověření",
340934
+ "learning.empty": "Zatím nejsou k dispozici žádní kandidáti ověřeného učení.",
340895
340935
  "update.title": "Chování aktualizací",
340896
340936
  "update.hint": "↑↓ navigace · Enter vybrat · Esc zrušit",
340897
340937
  "update.manual.label": "Ruční aktualizace",
@@ -403158,6 +403198,13 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
403158
403198
  priority: 65,
403159
403199
  availability: "always"
403160
403200
  },
403201
+ {
403202
+ name: "improve",
403203
+ aliases: ["learning"],
403204
+ descriptionKey: "command.improve.description",
403205
+ priority: 64,
403206
+ availability: "always"
403207
+ },
403161
403208
  {
403162
403209
  name: "status",
403163
403210
  aliases: [],
@@ -416897,6 +416944,8 @@ function buildManagedUsageReportLines(options) {
416897
416944
  var { buildApprovalRejectionStop } = createRequire(import.meta.url)("./bin/approval-rejection-stop.cjs");
416898
416945
  var { reconcileContextBudget } = createRequire(import.meta.url)("./bin/context-budget-ledger.cjs");
416899
416946
  var { buildContextInsight } = createRequire(import.meta.url)("./bin/context-insight-policy.cjs");
416947
+ var { buildValidatedLearningInsight } = createRequire(import.meta.url)("./bin/validated-learning-insight-policy.cjs");
416948
+ var { readValidatedLearningCandidates } = createRequire(import.meta.url)("./bin/validated-learning-signal.cjs");
416900
416949
  function buildUsageReportLines(options) {
416901
416950
  const accent = (text) => currentTheme.boldFg("primary", text);
416902
416951
  const value = (text) => currentTheme.fg("text", text);
@@ -417958,6 +418007,29 @@ function buildContextInsightLines(insight) {
417958
418007
  ];
417959
418008
  return lines;
417960
418009
  }
418010
+ function buildValidatedLearningInsightLines(insight) {
418011
+ const value = (text) => currentTheme.fg("text", text);
418012
+ const muted = (text) => currentTheme.fg("textDim", text);
418013
+ const lines = [
418014
+ ` ${value(uiText("learning.counts", insight))}`
418015
+ ];
418016
+ if (insight.latestPending === null) {
418017
+ lines.push(` ${muted(uiText("learning.empty"))}`);
418018
+ return lines;
418019
+ }
418020
+ lines.push(` ${muted(`${uiText("learning.latest")}:`)} ${value(insight.latestPending.id)}`);
418021
+ lines.push(` ${muted(`${uiText("learning.verification")}:`)} ${value(`${insight.latestPending.toolName} · ${insight.latestPending.commandHash}`)}`);
418022
+ return lines;
418023
+ }
418024
+ function showValidatedLearningInsight(host) {
418025
+ const homeDir = process.env["BLUN_SHARED_HOME"] ?? process.env["BLUN_HOME"] ?? "";
418026
+ const profile = process.env["BLUN_PROFILE"] ?? "default";
418027
+ const candidates = readValidatedLearningCandidates({ homeDir, profile });
418028
+ const insight = buildValidatedLearningInsight(candidates);
418029
+ const panel = new UsagePanelComponent(() => buildValidatedLearningInsightLines(insight), "primary", uiText("learning.panel.title"));
418030
+ host.state.transcriptContainer.addChild(panel);
418031
+ host.state.ui.requestRender();
418032
+ }
417961
418033
  async function showContextInsight(host) {
417962
418034
  const insight = buildContextInsight(await host.requireSession().getContext());
417963
418035
  const panel = new UsagePanelComponent(() => buildContextInsightLines(insight), "primary", uiText("usage.context.title"));
@@ -495174,6 +495246,9 @@ async function handleBuiltInSlashCommand(host, name, args) {
495174
495246
  case "premortem":
495175
495247
  await handlePremortemCommand(host, args);
495176
495248
  return;
495249
+ case "improve":
495250
+ showValidatedLearningInsight(host);
495251
+ return;
495177
495252
  case "context":
495178
495253
  await showContextInsight(host);
495179
495254
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.224",
3
+ "version": "9.1.226",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {