blun-king-cli 9.1.354 → 9.1.356

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.
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ function createLlmConfigChangeDetector(options = {}) {
4
+ const serializeParameters = options.serializeParameters ?? JSON.stringify;
5
+ if (typeof serializeParameters !== 'function') {
6
+ throw new TypeError('serializeParameters must be a function');
7
+ }
8
+
9
+ let previous;
10
+
11
+ return function shouldLogConfig(input) {
12
+ const tools = Array.isArray(input.tools) ? input.tools : [];
13
+ const sameScalars = previous !== undefined
14
+ && previous.provider === input.provider
15
+ && previous.model === input.model
16
+ && previous.modelAlias === input.modelAlias
17
+ && previous.thinkingEffort === input.thinkingEffort
18
+ && previous.systemPrompt === input.systemPrompt;
19
+
20
+ if (sameScalars && previous.tools.length === tools.length) {
21
+ let exactToolMatch = true;
22
+ for (let index = 0; index < tools.length; index += 1) {
23
+ const tool = tools[index];
24
+ const prior = previous.tools[index];
25
+ if (
26
+ prior.tool !== tool
27
+ || prior.name !== tool.name
28
+ || prior.description !== tool.description
29
+ || prior.parameters !== tool.parameters
30
+ ) {
31
+ exactToolMatch = false;
32
+ break;
33
+ }
34
+ }
35
+ if (exactToolMatch) return false;
36
+ }
37
+
38
+ let toolsChanged = previous === undefined || previous.tools.length !== tools.length;
39
+ const toolSnapshot = tools.map((tool, index) => {
40
+ const prior = previous?.tools[index];
41
+ const parametersJson = prior?.parameters === tool.parameters
42
+ ? prior.parametersJson
43
+ : serializeParameters(tool.parameters);
44
+ if (
45
+ prior === undefined
46
+ || prior.name !== tool.name
47
+ || prior.description !== tool.description
48
+ || prior.parametersJson !== parametersJson
49
+ ) {
50
+ toolsChanged = true;
51
+ }
52
+ return {
53
+ tool,
54
+ name: tool.name,
55
+ description: tool.description,
56
+ parameters: tool.parameters,
57
+ parametersJson,
58
+ };
59
+ });
60
+
61
+ const changed = !sameScalars || toolsChanged;
62
+ previous = {
63
+ provider: input.provider,
64
+ model: input.model,
65
+ modelAlias: input.modelAlias,
66
+ thinkingEffort: input.thinkingEffort,
67
+ systemPrompt: input.systemPrompt,
68
+ tools: toolSnapshot,
69
+ };
70
+ return changed;
71
+ };
72
+ }
73
+
74
+ module.exports = {
75
+ createLlmConfigChangeDetector,
76
+ };
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ const DEFAULT_MAX_ENTRIES = 4;
4
+ const DEFAULT_MAX_PROMPT_CHARS = 500_000;
5
+ const DEFAULT_MAX_TOTAL_CHARS = 1_000_000;
6
+
7
+ function positiveInteger(value, fallback, name) {
8
+ const resolved = value === undefined ? fallback : value;
9
+ if (!Number.isSafeInteger(resolved) || resolved < 1) {
10
+ throw new TypeError(`${name} must be a positive integer`);
11
+ }
12
+ return resolved;
13
+ }
14
+
15
+ function createSystemPromptTokenEstimator(estimateTextTokens, options = {}) {
16
+ if (typeof estimateTextTokens !== 'function') {
17
+ throw new TypeError('estimateTextTokens must be a function');
18
+ }
19
+
20
+ const maxEntries = positiveInteger(options.maxEntries, DEFAULT_MAX_ENTRIES, 'maxEntries');
21
+ const maxPromptChars = positiveInteger(
22
+ options.maxPromptChars,
23
+ DEFAULT_MAX_PROMPT_CHARS,
24
+ 'maxPromptChars',
25
+ );
26
+ const maxTotalChars = positiveInteger(
27
+ options.maxTotalChars,
28
+ DEFAULT_MAX_TOTAL_CHARS,
29
+ 'maxTotalChars',
30
+ );
31
+ const cache = new Map();
32
+ let cachedChars = 0;
33
+
34
+ return function estimateSystemPrompt(prompt) {
35
+ const cached = cache.get(prompt);
36
+ if (cached !== undefined) {
37
+ cache.delete(prompt);
38
+ cache.set(prompt, cached);
39
+ return cached;
40
+ }
41
+
42
+ const tokens = estimateTextTokens(prompt);
43
+ if (prompt.length > maxPromptChars || prompt.length > maxTotalChars) return tokens;
44
+
45
+ while (cache.size >= maxEntries || cachedChars + prompt.length > maxTotalChars) {
46
+ const oldestPrompt = cache.keys().next().value;
47
+ if (oldestPrompt === undefined) break;
48
+ cachedChars -= oldestPrompt.length;
49
+ cache.delete(oldestPrompt);
50
+ }
51
+
52
+ cache.set(prompt, tokens);
53
+ cachedChars += prompt.length;
54
+ return tokens;
55
+ };
56
+ }
57
+
58
+ module.exports = {
59
+ createSystemPromptTokenEstimator,
60
+ };
package/blun.mjs CHANGED
@@ -31019,11 +31019,13 @@ function estimateTokensForContentPart(part) {
31019
31019
  default: return 0;
31020
31020
  }
31021
31021
  }
31022
- var createToolSchemaTokenEstimator, estimateTokensForTools, messageTokenEstimateCache, MEDIA_TOKEN_ESTIMATE, MAX_IMAGE_HEADER_BYTES;
31022
+ var createToolSchemaTokenEstimator, createSystemPromptTokenEstimator, estimateTokensForTools, estimateSystemPromptTokens, messageTokenEstimateCache, MEDIA_TOKEN_ESTIMATE, MAX_IMAGE_HEADER_BYTES;
31023
31023
  var init_tokens = __esmMin((() => {
31024
31024
  init_file_type$1();
31025
31025
  ({ createToolSchemaTokenEstimator } = createRequire(import.meta.url)("./bin/tool-schema-token-cache-policy.cjs"));
31026
+ ({ createSystemPromptTokenEstimator } = createRequire(import.meta.url)("./bin/system-prompt-token-cache-policy.cjs"));
31026
31027
  estimateTokensForTools = createToolSchemaTokenEstimator(estimateTokens$1);
31028
+ estimateSystemPromptTokens = createSystemPromptTokenEstimator(estimateTokens$1);
31027
31029
  messageTokenEstimateCache = /* @__PURE__ */ new WeakMap();
31028
31030
  MEDIA_TOKEN_ESTIMATE = 2e3;
31029
31031
  MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
@@ -74736,7 +74738,7 @@ var init_kosong_llm = __esmMin((() => {
74736
74738
  const outgoingMessages = downgradeUnsupportedMedia(enrichedMessages, this.capability, (dropped) => {
74737
74739
  this.notifyMediaDropped(dropped);
74738
74740
  });
74739
- const outgoingRequestTokens = estimateTokens$1(this.systemPrompt) + estimateTokensForTools(tools) + estimateTokensForMessages(outgoingMessages);
74741
+ const outgoingRequestTokens = estimateSystemPromptTokens(this.systemPrompt) + estimateTokensForTools(tools) + estimateTokensForMessages(outgoingMessages);
74740
74742
  const reportedContextTokens = this.reportedContextTokens?.() ?? 0;
74741
74743
  const usedContextTokens = Math.max(outgoingRequestTokens, reportedContextTokens);
74742
74744
  completionBudget = applyCompletionBudgetWithDetails({
@@ -75454,7 +75456,7 @@ var init_full = __esmMin((() => {
75454
75456
  return this.agent.context.tokenCountWithPending;
75455
75457
  }
75456
75458
  estimateRequestTokens(messages, systemPrompt = this.agent.effectiveSystemPrompt, tools = this.agent.tools.loopTools) {
75457
- return estimateTokens$1(systemPrompt) + estimateTokensForTools(tools) + estimateTokensForMessages(messages);
75459
+ return estimateSystemPromptTokens(systemPrompt) + estimateTokensForTools(tools) + estimateTokensForMessages(messages);
75458
75460
  }
75459
75461
  resetForTurn() {
75460
75462
  this.compactionCountInTurn = 0;
@@ -264953,23 +264955,15 @@ function splitGenerateOptions(options) {
264953
264955
  generateOptions
264954
264956
  };
264955
264957
  }
264956
- function toolSignature(tools) {
264957
- return tools.map(({ name, description, parameters }) => ({
264958
- name,
264959
- description,
264960
- parameters
264961
- }));
264962
- }
264963
- function fingerprint(content) {
264964
- return createHash("sha256").update(content).digest("hex");
264965
- }
264966
- var LlmRequestLogger;
264958
+ var createLlmConfigChangeDetector, LlmRequestLogger;
264967
264959
  var init_llm_request_logger = __esmMin((() => {
264960
+ createLlmConfigChangeDetector = createRequire(import.meta.url)("./bin/llm-config-log-dedup-policy.cjs").createLlmConfigChangeDetector;
264968
264961
  LlmRequestLogger = class {
264969
264962
  log;
264970
- lastConfigLogSignature;
264963
+ shouldLogConfig;
264971
264964
  constructor(log) {
264972
264965
  this.log = log;
264966
+ this.shouldLogConfig = createLlmConfigChangeDetector();
264973
264967
  }
264974
264968
  logRequest(input) {
264975
264969
  const { provider, modelAlias, systemPrompt, tools, messages, fields } = input;
@@ -264982,13 +264976,11 @@ var init_llm_request_logger = __esmMin((() => {
264982
264976
  systemPromptChars: systemPrompt.length,
264983
264977
  toolCount: tools.length
264984
264978
  };
264985
- const signature = JSON.stringify({
264979
+ if (this.shouldLogConfig({
264986
264980
  ...config,
264987
- systemPromptHash: fingerprint(systemPrompt),
264988
- toolsHash: fingerprint(JSON.stringify(toolSignature(tools)))
264989
- });
264990
- if (signature !== this.lastConfigLogSignature) {
264991
- this.lastConfigLogSignature = signature;
264981
+ systemPrompt,
264982
+ tools
264983
+ })) {
264992
264984
  this.log.info("llm config", {
264993
264985
  ...requestLogFields,
264994
264986
  ...config
@@ -265531,7 +265523,7 @@ var init_agent = __esmMin((() => {
265531
265523
  projectedTokenCount: this.fullCompaction.estimateCurrentRequestTokens(),
265532
265524
  effectiveMaxContextTokens: this.fullCompaction.getEffectiveMaxContextTokens(),
265533
265525
  compactionBudgetTokens: this.fullCompaction.getCompactionBudgetTokens(),
265534
- systemPromptTokens: estimateTokens$1(systemPrompt),
265526
+ systemPromptTokens: estimateSystemPromptTokens(systemPrompt),
265535
265527
  personalityPromptTokens,
265536
265528
  socialPromptTokens,
265537
265529
  skillPromptTokens: includedTokens(skillPrompt),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.354",
3
+ "version": "9.1.356",
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": {