@nomad-e/bluma-cli 0.1.80 → 0.1.82

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.
@@ -285,7 +285,7 @@ in every commit and PR generated by BluMa, with no exceptions.
285
285
 
286
286
  ## Available Scripts
287
287
 
288
- - validate_commits.py: Validates that all commits in a range follow Conventional Commits format
288
+ - validate_commits.py: Validates that all commits in a range follow Conventional Commits format. Accepts a branch name (`main`) or a full range (`main..HEAD`).
289
289
 
290
290
  ## Next Steps
291
291
 
@@ -4,10 +4,11 @@ Validate that commits in a given range follow Conventional Commits format
4
4
  and include the BluMa watermark trailer.
5
5
 
6
6
  Usage:
7
- python validate_commits.py [base_branch]
7
+ python validate_commits.py [base_branch_or_range]
8
8
 
9
9
  Arguments:
10
- base_branch Target branch to compare against (default: main)
10
+ base_branch_or_range Target branch (e.g. "main") or full range
11
+ (e.g. "main..HEAD"). Default: main
11
12
 
12
13
  Exit codes:
13
14
  0 All commits are valid
@@ -28,8 +29,15 @@ WATERMARK = "Generated-by: BluMa"
28
29
 
29
30
 
30
31
  def get_commits(base: str) -> list[dict]:
32
+ # Accept either a bare branch name ("main") or a full range ("main..HEAD").
33
+ # If the argument already contains "..", use it as-is to avoid duplication.
34
+ if ".." not in base:
35
+ range_arg = f"{base}..HEAD"
36
+ else:
37
+ range_arg = base
38
+
31
39
  result = subprocess.run(
32
- ["git", "log", f"{base}..HEAD", "--format=%H|||%s|||%b%n---END---"],
40
+ ["git", "log", range_arg, "--format=%H|||%s|||%b%n---END---"],
33
41
  capture_output=True, text=True
34
42
  )
35
43
  if result.returncode != 0:
package/dist/main.js CHANGED
@@ -14801,13 +14801,38 @@ function partitionConversationIntoTurnSlices(conversationHistory) {
14801
14801
  }
14802
14802
  return turns;
14803
14803
  }
14804
- var CONTEXT_TOKEN_BUDGET = 24e4;
14805
- var COMPRESS_THRESHOLD = 0.7;
14804
+ var CONTEXT_TOKEN_BUDGET = 131072;
14805
+ var COMPRESS_THRESHOLD = 0.85;
14806
14806
  var KEEP_RECENT_TURNS = 10;
14807
14807
  function buildContextMessages(systemMessages, anchor, pendingRaw, recentFlat) {
14808
14808
  const anchorMsg = anchor ? [anchorToSystemMessage(anchor)] : [];
14809
14809
  return [...systemMessages, ...anchorMsg, ...pendingRaw, ...recentFlat];
14810
14810
  }
14811
+ function enforceHardContextTokenCap(params) {
14812
+ let { systemMessages, anchor, pendingSlices, recentSlices, tokenBudget } = params;
14813
+ let pendingFlat = pendingSlices.flat();
14814
+ let recentFlat = recentSlices.flat();
14815
+ let messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
14816
+ let tokens = countTokens(messages, true);
14817
+ while (tokens > tokenBudget && pendingSlices.length > 0) {
14818
+ pendingSlices = pendingSlices.slice(1);
14819
+ pendingFlat = pendingSlices.flat();
14820
+ messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
14821
+ tokens = countTokens(messages, true);
14822
+ }
14823
+ while (tokens > tokenBudget && recentSlices.length > 1) {
14824
+ recentSlices = recentSlices.slice(1);
14825
+ recentFlat = recentSlices.flat();
14826
+ messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
14827
+ tokens = countTokens(messages, true);
14828
+ }
14829
+ while (tokens > tokenBudget && recentFlat.length > 1) {
14830
+ recentFlat = recentFlat.slice(1);
14831
+ messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
14832
+ tokens = countTokens(messages, true);
14833
+ }
14834
+ return { messages, pendingSlices, recentSlices };
14835
+ }
14811
14836
  async function createApiContextWindow(fullHistory, currentAnchor, compressedTurnSliceCount, llmService, userContext, options) {
14812
14837
  if (!fullHistory.length) {
14813
14838
  return {
@@ -14862,6 +14887,20 @@ async function createApiContextWindow(fullHistory, currentAnchor, compressedTurn
14862
14887
  messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
14863
14888
  tokens = countTokens(messages, true);
14864
14889
  }
14890
+ if (tokens > tokenBudget) {
14891
+ clearTokenCountCache();
14892
+ const capped = enforceHardContextTokenCap({
14893
+ systemMessages,
14894
+ anchor,
14895
+ pendingSlices,
14896
+ recentSlices,
14897
+ tokenBudget
14898
+ });
14899
+ pendingSlices = capped.pendingSlices;
14900
+ pendingFlat = pendingSlices.flat();
14901
+ messages = capped.messages;
14902
+ tokens = countTokens(messages, true);
14903
+ }
14865
14904
  return {
14866
14905
  messages,
14867
14906
  newAnchor: anchor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomad-e/bluma-cli",
3
- "version": "0.1.80",
3
+ "version": "0.1.82",
4
4
  "description": "BluMa independent agent for automation and advanced software engineering.",
5
5
  "author": "Alex Fonseca",
6
6
  "license": "Apache-2.0",