File size: 2,383 Bytes
ca51841
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { describe, expect, it } from 'vitest';
import { formatCompactTokenCount } from '../src/api.js';
import {
  DEFAULT_CONTEXT_LIMIT_TOKENS,
  DEFAULT_CONTEXT_RESET_THRESHOLD_PERCENT,
  resolveContextConfig,
  estimateThreadTokens,
} from '../src/context.js';

describe('context helpers – resolveContextConfig', () => {
  it('falls back to the default context window when nothing is configured', () => {
    const config = resolveContextConfig({}, '');
    expect(config.maxTokens).toBe(DEFAULT_CONTEXT_LIMIT_TOKENS);
    expect(config.resetPercent).toBe(DEFAULT_CONTEXT_RESET_THRESHOLD_PERCENT);
    expect(config.source).toBe('default');
  });

  it('prefers a manually configured context window', () => {
    const config = resolveContextConfig({ contextLimitTokens: 65536 }, 'qwen-32k');
    expect(config.maxTokens).toBe(65536);
    expect(config.source).toBe('manual');
  });

  it('does not infer context length from model ids anymore', () => {
    const config = resolveContextConfig({ contextLimitTokens: null }, 'qwen-128k');
    expect(config.maxTokens).toBe(DEFAULT_CONTEXT_LIMIT_TOKENS);
    expect(config.source).toBe('default');
  });

  it('respects thresholds below the default warning band', () => {
    const config = resolveContextConfig({
      contextLimitTokens: 4096,
      contextResetThresholdPercent: 70,
    }, '');

    expect(config.resetTokens).toBe(Math.floor(4096 * 0.7));
    expect(config.warnTokens).toBe(config.resetTokens);
  });

  it('keeps resetTokens below the hard window when threshold percent is too aggressive', () => {
    const config = resolveContextConfig({
      contextLimitTokens: 32768,
      contextResetThresholdPercent: 95,
    }, '');

    expect(config.warnTokens).toBe(Math.floor(32768 * 0.8));
    expect(config.resetTokens).toBe(30720);
  });
});

describe('context helpers – estimateThreadTokens', () => {
  it('includes pending messages in the projected estimate', () => {
    const messages = [{ role: 'user', content: 'hello world' }];
    const pending = { role: 'assistant', content: 'reply' };

    expect(estimateThreadTokens(messages, pending)).toBeGreaterThan(estimateThreadTokens(messages));
  });
});

describe('api helpers – formatCompactTokenCount', () => {
  it('keeps 4k-class windows readable without rounding them up', () => {
    expect(formatCompactTokenCount(4096)).toBe('4.1k');
  });
});