kiro-proxy 0.1.17 → 0.1.18

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/README.md CHANGED
@@ -77,14 +77,18 @@ Claude Code 默认使用 Anthropic 官方 model ID,需要通过环境变量映
77
77
  "env": {
78
78
  "ANTHROPIC_AUTH_TOKEN": "any",
79
79
  "ANTHROPIC_BASE_URL": "http://localhost:3456",
80
- "ANTHROPIC_MODEL": "claude-sonnet-4.6",
81
80
  "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4.6",
82
81
  "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4.6",
83
82
  "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4.5"
84
- }
83
+ },
84
+ "model": "sonnet"
85
85
  }
86
86
  ```
87
87
 
88
+ `model` 可选值:`sonnet`、`opus`、`haiku`,添加 `[1m]` 后缀可启用 1M 上下文窗口(如 `"opus[1m]"`)。
89
+
90
+ > 注意:不要设置 `ANTHROPIC_MODEL` 环境变量,它会覆盖 `model` 字段,导致上下文窗口等配置失效。
91
+
88
92
  ## 相关项目
89
93
 
90
94
  - [kiro-web-search](https://github.com/Colin3191/kiro-web-search) — 将 Kiro 内置的联网搜索封装为 MCP server,可在 Claude Code 等客户端中使用
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiro-proxy",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Kiro API proxy with OpenAI and Anthropic compatible endpoints",
5
5
  "type": "module",
6
6
  "bin": {
package/token-counter.js CHANGED
@@ -1,11 +1,131 @@
1
+ const CLAUDE_MULTIPLIERS = {
2
+ word: 1.13,
3
+ number: 1.63,
4
+ cjk: 1.21,
5
+ symbol: 0.4,
6
+ mathSymbol: 4.52,
7
+ urlDelim: 1.26,
8
+ atSign: 2.82,
9
+ emoji: 2.6,
10
+ newline: 0.89,
11
+ space: 0.39,
12
+ };
13
+
14
+ function isCJK(code) {
15
+ return (
16
+ (code >= 0x4e00 && code <= 0x9fff) ||
17
+ (code >= 0x3400 && code <= 0x4dbf) ||
18
+ (code >= 0x20000 && code <= 0x2a6df) ||
19
+ (code >= 0x2a700 && code <= 0x2b73f) ||
20
+ (code >= 0x2b740 && code <= 0x2b81f) ||
21
+ (code >= 0x3040 && code <= 0x30ff) ||
22
+ (code >= 0xac00 && code <= 0xd7a3)
23
+ );
24
+ }
25
+
26
+ function isEmoji(code) {
27
+ return (
28
+ (code >= 0x1f300 && code <= 0x1f9ff) ||
29
+ (code >= 0x2600 && code <= 0x26ff) ||
30
+ (code >= 0x2700 && code <= 0x27bf) ||
31
+ (code >= 0x1f600 && code <= 0x1f64f) ||
32
+ (code >= 0x1f900 && code <= 0x1f9ff) ||
33
+ (code >= 0x1fa00 && code <= 0x1faff)
34
+ );
35
+ }
36
+
37
+ function isMathSymbol(code) {
38
+ if (code >= 0x2200 && code <= 0x22ff) return true;
39
+ if (code >= 0x2a00 && code <= 0x2aff) return true;
40
+ if (code >= 0x1d400 && code <= 0x1d7ff) return true;
41
+ const mathChars =
42
+ '∑∫∂√∞≤≥≠≈±×÷∈∉∋∌⊂⊃⊆⊇∪∩∧∨¬∀∃∄∅∆∇∝∟∠∡∢°′″‴⁺⁻⁼⁽⁾ⁿ₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎²³¹⁴⁵⁶⁷⁸⁹⁰';
43
+ return mathChars.includes(String.fromCodePoint(code));
44
+ }
45
+
46
+ function isURLDelim(code) {
47
+ return '/:?&=;#%'.includes(String.fromCodePoint(code));
48
+ }
49
+
50
+ function isLetterOrDigit(code) {
51
+ return (
52
+ (code >= 0x41 && code <= 0x5a) ||
53
+ (code >= 0x61 && code <= 0x7a) ||
54
+ (code >= 0x30 && code <= 0x39) ||
55
+ (code >= 0xc0 && code <= 0x24f)
56
+ );
57
+ }
58
+
59
+ function isDigit(code) {
60
+ return code >= 0x30 && code <= 0x39;
61
+ }
62
+
63
+ const NONE = 0;
64
+ const LATIN = 1;
65
+ const NUMBER = 2;
66
+
1
67
  function countText(text) {
2
68
  if (!text) return 0;
3
- return Math.round(text.length / 4);
69
+
70
+ const m = CLAUDE_MULTIPLIERS;
71
+ let count = 0;
72
+ let currentWordType = NONE;
73
+
74
+ for (const char of text) {
75
+ const code = char.codePointAt(0);
76
+
77
+ if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
78
+ currentWordType = NONE;
79
+ if (char === '\n' || char === '\t') {
80
+ count += m.newline;
81
+ } else {
82
+ count += m.space;
83
+ }
84
+ continue;
85
+ }
86
+
87
+ if (isCJK(code)) {
88
+ currentWordType = NONE;
89
+ count += m.cjk;
90
+ continue;
91
+ }
92
+
93
+ if (isEmoji(code)) {
94
+ currentWordType = NONE;
95
+ count += m.emoji;
96
+ continue;
97
+ }
98
+
99
+ if (isLetterOrDigit(code)) {
100
+ const isNum = isDigit(code);
101
+ const newType = isNum ? NUMBER : LATIN;
102
+
103
+ if (currentWordType === NONE || currentWordType !== newType) {
104
+ count += isNum ? m.number : m.word;
105
+ currentWordType = newType;
106
+ }
107
+ continue;
108
+ }
109
+
110
+ currentWordType = NONE;
111
+ if (isMathSymbol(code)) {
112
+ count += m.mathSymbol;
113
+ } else if (code === 0x40) {
114
+ count += m.atSign;
115
+ } else if (isURLDelim(code)) {
116
+ count += m.urlDelim;
117
+ } else {
118
+ count += m.symbol;
119
+ }
120
+ }
121
+
122
+ return Math.ceil(count);
4
123
  }
5
124
 
6
125
  export function countMessages(messages, system) {
7
126
  let tokens = 0;
8
- if (system) tokens += countText(typeof system === 'string' ? system : JSON.stringify(system));
127
+ if (system)
128
+ tokens += countText(typeof system === 'string' ? system : JSON.stringify(system));
9
129
  for (const msg of messages || []) {
10
130
  tokens += 4;
11
131
  if (typeof msg.content === 'string') {
@@ -13,7 +133,10 @@ export function countMessages(messages, system) {
13
133
  } else if (Array.isArray(msg.content)) {
14
134
  for (const block of msg.content) {
15
135
  if (block.type === 'text') tokens += countText(block.text);
16
- else if (block.type === 'tool_result') tokens += countText(typeof block.content === 'string' ? block.content : JSON.stringify(block.content));
136
+ else if (block.type === 'tool_result')
137
+ tokens += countText(
138
+ typeof block.content === 'string' ? block.content : JSON.stringify(block.content),
139
+ );
17
140
  else if (block.type === 'tool_use') tokens += countText(JSON.stringify(block.input));
18
141
  }
19
142
  }