@allternit/gizzi-code 1.0.0 → 1.0.1

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.
Files changed (158) hide show
  1. package/bin/gizzi +4 -0
  2. package/bin/gizzi-ink +5 -0
  3. package/package.json +137 -31
  4. package/src/Tool.ts +26 -0
  5. package/src/bootstrap/state.ts +165 -322
  6. package/src/commands.ts +209 -0
  7. package/src/context/QueuedMessageContext.tsx +63 -0
  8. package/src/context/fpsMetrics.tsx +30 -0
  9. package/src/context/mailbox.tsx +38 -0
  10. package/src/context/modalContext.tsx +58 -0
  11. package/src/context/notifications.tsx +240 -0
  12. package/src/context/overlayContext.tsx +151 -0
  13. package/src/context/promptOverlayContext.tsx +125 -0
  14. package/src/context/stats.tsx +220 -0
  15. package/src/context/voice.tsx +88 -0
  16. package/src/hooks/useCanUseTool.ts +11 -0
  17. package/src/hooks/useExitOnCtrlCD.ts +40 -187
  18. package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +68 -0
  19. package/src/hooks/useKeybinding.ts +68 -209
  20. package/src/hooks/useTerminalSize.ts +31 -99
  21. package/src/hooks.ts +37 -0
  22. package/src/ink.ts +204 -0
  23. package/src/main.ts +7 -0
  24. package/src/types/command.ts +216 -0
  25. package/src/types/connectorText.ts +39 -0
  26. package/src/types/fileSuggestion.ts +15 -0
  27. package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
  28. package/src/types/generated/events_mono/common/v1/auth.ts +100 -0
  29. package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
  30. package/src/types/generated/google/protobuf/timestamp.ts +187 -0
  31. package/src/types/hooks.ts +319 -0
  32. package/src/types/ids.ts +44 -0
  33. package/src/types/logs.ts +331 -0
  34. package/src/types/merged/index.ts +5 -0
  35. package/src/types/merged/message.ts +552 -0
  36. package/src/types/message.ts +927 -186
  37. package/src/types/messageQueueTypes.ts +21 -0
  38. package/src/types/notebook.ts +72 -0
  39. package/src/types/permissions.ts +447 -0
  40. package/src/types/plugin.ts +363 -0
  41. package/src/types/statusLine.ts +15 -0
  42. package/src/types/textInputTypes.ts +387 -0
  43. package/src/types/tools.ts +149 -0
  44. package/src/types/utils.ts +20 -0
  45. package/src/utils/advisor.ts +12 -0
  46. package/src/utils/api.ts +29 -0
  47. package/src/utils/array.ts +7 -0
  48. package/src/utils/attachments.ts +60 -0
  49. package/src/utils/auth.ts +3 -0
  50. package/src/utils/claudeInChrome/chromeNativeHost.ts +15 -0
  51. package/src/utils/claudeInChrome/common.ts +12 -0
  52. package/src/utils/claudeInChrome/mcpServer.ts +15 -0
  53. package/src/utils/computerUse/common.ts +19 -0
  54. package/src/utils/computerUse/mcpServer.ts +15 -0
  55. package/src/utils/config.ts +35 -0
  56. package/src/utils/context.ts +19 -0
  57. package/src/utils/cwd.ts +3 -0
  58. package/src/utils/debug.ts +3 -0
  59. package/src/utils/earlyInput.ts +7 -0
  60. package/src/utils/effort.ts +13 -0
  61. package/src/utils/embeddedTools.ts +12 -0
  62. package/src/utils/envUtils.ts +3 -0
  63. package/src/utils/errors.ts +3 -0
  64. package/src/utils/execFileNoThrow.ts +24 -0
  65. package/src/utils/feature-flags.ts +112 -0
  66. package/src/utils/file.ts +3 -0
  67. package/src/utils/fileHistory.ts +17 -0
  68. package/src/utils/fingerprint.ts +7 -0
  69. package/src/utils/format.ts +75 -305
  70. package/src/utils/frontmatterParser.ts +33 -0
  71. package/src/utils/fsOperations.ts +31 -0
  72. package/src/utils/fullscreen.ts +40 -350
  73. package/src/utils/git.ts +15 -0
  74. package/src/utils/imageResizer.ts +30 -0
  75. package/src/utils/lazySchema.ts +9 -0
  76. package/src/utils/log.ts +3 -0
  77. package/src/utils/markdownConfigLoader.ts +12 -0
  78. package/src/utils/messages.ts +13 -0
  79. package/src/utils/migration.ts +137 -0
  80. package/src/utils/model/providers.ts +15 -0
  81. package/src/utils/path.ts +3 -0
  82. package/src/utils/permissions/PermissionResult.ts +14 -0
  83. package/src/utils/permissions/autoModeState.ts +12 -0
  84. package/src/utils/permissions/filesystem.ts +12 -0
  85. package/src/utils/plugins/loadPluginOutputStyles.ts +12 -0
  86. package/src/utils/plugins/schemas.ts +25 -0
  87. package/src/utils/process.ts +16 -0
  88. package/src/utils/sandbox/sandbox-adapter.ts +19 -0
  89. package/src/utils/sessionStorage.ts +238 -472
  90. package/src/utils/settings/constants.ts +10 -0
  91. package/src/utils/settings/settings.ts +19 -0
  92. package/src/utils/settings/types.ts +18 -0
  93. package/src/utils/shell/shellToolUtils.ts +9 -0
  94. package/src/utils/sinks.ts +11 -0
  95. package/src/utils/sleep.ts +7 -0
  96. package/src/utils/sliceAnsi.ts +7 -0
  97. package/src/utils/slowOperations.ts +3 -0
  98. package/src/utils/startupProfiler.ts +11 -0
  99. package/src/utils/stringUtils.ts +106 -0
  100. package/src/utils/systemPromptType.ts +9 -0
  101. package/src/utils/teleport/api.ts +15 -0
  102. package/src/utils/textHighlighting.ts +16 -0
  103. package/src/utils/theme.ts +17 -0
  104. package/src/utils/thinking.ts +58 -0
  105. package/src/utils/tokens.ts +11 -0
  106. package/src/utils/toolResultStorage.ts +17 -0
  107. package/src/utils/worktreeModeEnabled.ts +7 -0
  108. package/WORKSPACE_INTEGRATION.md +0 -290
  109. package/chat-sessions/sessions-index.json +0 -98
  110. package/package.json.original +0 -31
  111. package/package.json.publish +0 -47
  112. package/src/bootstrap/state.d.ts +0 -169
  113. package/src/bootstrap/state.js +0 -261
  114. package/src/context/pack-builder.d.ts +0 -24
  115. package/src/context/pack-builder.js +0 -281
  116. package/src/hooks/useExitOnCtrlCD.d.ts +0 -86
  117. package/src/hooks/useExitOnCtrlCD.js +0 -130
  118. package/src/hooks/useKeybinding.d.ts +0 -89
  119. package/src/hooks/useKeybinding.js +0 -163
  120. package/src/hooks/useTerminalSize.d.ts +0 -41
  121. package/src/hooks/useTerminalSize.js +0 -90
  122. package/src/index.d.ts +0 -23
  123. package/src/index.js +0 -24
  124. package/src/runtime/brand/brand.d.ts +0 -488
  125. package/src/runtime/brand/brand.js +0 -464
  126. package/src/runtime/brand/brand.ts +0 -667
  127. package/src/runtime/services/tokenEstimation.d.ts +0 -187
  128. package/src/runtime/services/tokenEstimation.js +0 -423
  129. package/src/runtime/services/tokenEstimation.ts +0 -547
  130. package/src/runtime/tools/Tool.d.ts +0 -239
  131. package/src/runtime/tools/Tool.js +0 -285
  132. package/src/runtime/tools/Tool.ts +0 -524
  133. package/src/scheduler/TaskScheduler.d.ts +0 -98
  134. package/src/scheduler/TaskScheduler.js +0 -201
  135. package/src/scheduler/TaskScheduler.ts +0 -259
  136. package/src/state/AppStateStore.d.ts +0 -347
  137. package/src/state/AppStateStore.js +0 -439
  138. package/src/state/AppStateStore.ts +0 -658
  139. package/src/state/WorkspaceStateStore.d.ts +0 -43
  140. package/src/state/WorkspaceStateStore.js +0 -224
  141. package/src/state/WorkspaceStateStore.ts +0 -297
  142. package/src/types/message.d.ts +0 -190
  143. package/src/types/message.js +0 -77
  144. package/src/utils/format.d.ts +0 -126
  145. package/src/utils/format.js +0 -230
  146. package/src/utils/fullscreen.d.ts +0 -161
  147. package/src/utils/fullscreen.js +0 -277
  148. package/src/utils/sessionStorage.d.ts +0 -210
  149. package/src/utils/sessionStorage.js +0 -435
  150. package/src/watcher/WorkspaceWatcher.d.ts +0 -70
  151. package/src/watcher/WorkspaceWatcher.js +0 -191
  152. package/src/watcher/WorkspaceWatcher.ts +0 -251
  153. package/src/workspace/loader.d.ts +0 -30
  154. package/src/workspace/loader.js +0 -117
  155. package/src/workspace/types.d.ts +0 -91
  156. package/src/workspace/types.js +0 -7
  157. package/threads/thread_1775361175022.json +0 -9
  158. package/tsconfig.json +0 -14
@@ -1,187 +0,0 @@
1
- /**
2
- * @fileoverview Token estimation utilities for LLM interactions
3
- * @module runtime/services/tokenEstimation
4
- *
5
- * Provides token counting and estimation functions for various LLM models.
6
- * Supports both accurate encoding (when tiktoken is available) and
7
- * rough estimation based on character counts.
8
- */
9
- import type { Message } from '../../types/message.js';
10
- /**
11
- * Supported LLM models for token estimation
12
- * @typedef {'gpt-4' | 'gpt-4o' | 'gpt-4-turbo' | 'gpt-3.5-turbo' | 'claude-3-opus' | 'claude-3-sonnet' | 'claude-3-haiku' | 'claude-2' | 'gemini-pro' | 'gemini-ultra' | 'default'} SupportedModel
13
- */
14
- export type SupportedModel = 'gpt-4' | 'gpt-4o' | 'gpt-4-turbo' | 'gpt-3.5-turbo' | 'claude-3-opus' | 'claude-3-sonnet' | 'claude-3-haiku' | 'claude-2' | 'gemini-pro' | 'gemini-ultra' | 'default';
15
- /**
16
- * Token estimation configuration options
17
- * @interface TokenEstimationOptions
18
- */
19
- export interface TokenEstimationOptions {
20
- /** Target model for estimation */
21
- readonly model?: SupportedModel;
22
- /** Whether to include formatting overhead in estimate */
23
- readonly includeFormatting?: boolean;
24
- /** Custom tokens per character ratio for rough estimation */
25
- readonly customRatio?: number;
26
- }
27
- /**
28
- * Token estimation result with metadata
29
- * @interface TokenEstimationResult
30
- */
31
- export interface TokenEstimationResult {
32
- /** Estimated token count */
33
- readonly tokens: number;
34
- /** Method used for estimation */
35
- readonly method: 'precise' | 'rough';
36
- /** Model used for estimation */
37
- readonly model: SupportedModel;
38
- /** Confidence level (0-1) based on estimation method */
39
- readonly confidence: number;
40
- }
41
- /**
42
- * Model-specific token estimation ratios (characters per token)
43
- * These are approximate averages and vary by language/content
44
- * @constant {Readonly<Record<SupportedModel, number>>}
45
- */
46
- export declare const MODEL_TOKEN_RATIOS: Readonly<Record<SupportedModel, number>>;
47
- /**
48
- * Message format overhead in tokens (role markers, formatting, etc.)
49
- * @constant {number}
50
- */
51
- export declare const MESSAGE_OVERHEAD_TOKENS = 4;
52
- /**
53
- * Base overhead for a conversation (system prompts, etc.)
54
- * @constant {number}
55
- */
56
- export declare const CONVERSATION_BASE_OVERHEAD = 3;
57
- /**
58
- * Estimate tokens in a single text string
59
- *
60
- * @param {string} text - Text to estimate tokens for
61
- * @param {TokenEstimationOptions} options - Estimation options
62
- * @returns {TokenEstimationResult} Token estimation with metadata
63
- *
64
- * @example
65
- * ```typescript
66
- * const result = estimateTokens('Hello, world!', { model: 'gpt-4' });
67
- * console.log(result.tokens); // ~4 tokens
68
- * ```
69
- */
70
- export declare function estimateTokens(text: string, options?: TokenEstimationOptions): TokenEstimationResult;
71
- /**
72
- * Async version of estimateTokens that attempts to use tiktoken for precision
73
- *
74
- * @param {string} text - Text to estimate tokens for
75
- * @param {TokenEstimationOptions} options - Estimation options
76
- * @returns {Promise<TokenEstimationResult>} Token estimation with metadata
77
- *
78
- * @example
79
- * ```typescript
80
- * const result = await estimateTokensAsync('Hello, world!', { model: 'gpt-4' });
81
- * console.log(result.method); // 'precise' if tiktoken available
82
- * ```
83
- */
84
- export declare function estimateTokensAsync(text: string, options?: TokenEstimationOptions): Promise<TokenEstimationResult>;
85
- /**
86
- * Estimate tokens for an array of messages
87
- *
88
- * @param {readonly Message[]} messages - Messages to estimate tokens for
89
- * @param {TokenEstimationOptions} options - Estimation options
90
- * @returns {TokenEstimationResult} Total token estimation with metadata
91
- *
92
- * @example
93
- * ```typescript
94
- * const messages = [
95
- * { role: 'system', content: 'You are a helpful assistant.' },
96
- * { role: 'user', content: 'Hello!' }
97
- * ];
98
- * const result = estimateTokensForMessages(messages);
99
- * console.log(result.tokens); // Total estimated tokens
100
- * ```
101
- */
102
- export declare function estimateTokensForMessages(messages: readonly Message[], options?: TokenEstimationOptions): TokenEstimationResult;
103
- /**
104
- * Async version of estimateTokensForMessages with tiktoken support
105
- *
106
- * @param {readonly Message[]} messages - Messages to estimate tokens for
107
- * @param {TokenEstimationOptions} options - Estimation options
108
- * @returns {Promise<TokenEstimationResult>} Total token estimation with metadata
109
- */
110
- export declare function estimateTokensForMessagesAsync(messages: readonly Message[], options?: TokenEstimationOptions): Promise<TokenEstimationResult>;
111
- /**
112
- * Rough token count estimation without any dependencies
113
- * Uses a simple characters-per-token heuristic
114
- *
115
- * @param {string | readonly Message[]} input - Text or messages to estimate
116
- * @param {SupportedModel} model - Model for estimation ratios
117
- * @returns {number} Estimated token count
118
- *
119
- * @example
120
- * ```typescript
121
- * // Estimate text
122
- * const textTokens = roughTokenCountEstimation('Hello, world!');
123
- *
124
- * // Estimate messages
125
- * const messageTokens = roughTokenCountEstimation([
126
- * { role: 'user', content: 'Hello!' }
127
- * ]);
128
- * ```
129
- */
130
- export declare function roughTokenCountEstimation(input: string | readonly Message[], model?: SupportedModel): number;
131
- /**
132
- * Check if text would exceed token limit
133
- *
134
- * @param {string} text - Text to check
135
- * @param {number} limit - Token limit
136
- * @param {TokenEstimationOptions} options - Estimation options
137
- * @returns {{ withinLimit: true } | { withinLimit: false; exceededBy: number }} Limit check result
138
- *
139
- * @example
140
- * ```typescript
141
- * const result = checkTokenLimit('Long text...', 100);
142
- * if (!result.withinLimit) {
143
- * console.log(`Exceeded by ${result.exceededBy} tokens`);
144
- * }
145
- * ```
146
- */
147
- export declare function checkTokenLimit(text: string, limit: number, options?: TokenEstimationOptions): {
148
- withinLimit: true;
149
- } | {
150
- withinLimit: false;
151
- exceededBy: number;
152
- };
153
- /**
154
- * Truncate text to fit within token limit
155
- *
156
- * @param {string} text - Text to truncate
157
- * @param {number} maxTokens - Maximum token count
158
- * @param {TokenEstimationOptions} options - Estimation options
159
- * @returns {string} Truncated text
160
- *
161
- * @example
162
- * ```typescript
163
- * const truncated = truncateToTokenLimit(longText, 100);
164
- * ```
165
- */
166
- export declare function truncateToTokenLimit(text: string, maxTokens: number, options?: TokenEstimationOptions): string;
167
- /**
168
- * Get model-specific context window size
169
- *
170
- * @param {SupportedModel} model - Model name
171
- * @returns {number} Context window size in tokens
172
- */
173
- export declare function getModelContextWindow(model: SupportedModel): number;
174
- declare const _default: {
175
- estimateTokens: typeof estimateTokens;
176
- estimateTokensAsync: typeof estimateTokensAsync;
177
- estimateTokensForMessages: typeof estimateTokensForMessages;
178
- estimateTokensForMessagesAsync: typeof estimateTokensForMessagesAsync;
179
- roughTokenCountEstimation: typeof roughTokenCountEstimation;
180
- checkTokenLimit: typeof checkTokenLimit;
181
- truncateToTokenLimit: typeof truncateToTokenLimit;
182
- getModelContextWindow: typeof getModelContextWindow;
183
- MODEL_TOKEN_RATIOS: Readonly<Record<SupportedModel, number>>;
184
- MESSAGE_OVERHEAD_TOKENS: number;
185
- CONVERSATION_BASE_OVERHEAD: number;
186
- };
187
- export default _default;
@@ -1,423 +0,0 @@
1
- /**
2
- * @fileoverview Token estimation utilities for LLM interactions
3
- * @module runtime/services/tokenEstimation
4
- *
5
- * Provides token counting and estimation functions for various LLM models.
6
- * Supports both accurate encoding (when tiktoken is available) and
7
- * rough estimation based on character counts.
8
- */
9
- /**
10
- * Model-specific token estimation ratios (characters per token)
11
- * These are approximate averages and vary by language/content
12
- * @constant {Readonly<Record<SupportedModel, number>>}
13
- */
14
- export const MODEL_TOKEN_RATIOS = {
15
- 'gpt-4': 3.5,
16
- 'gpt-4o': 3.5,
17
- 'gpt-4-turbo': 3.5,
18
- 'gpt-3.5-turbo': 3.5,
19
- 'claude-3-opus': 3.25,
20
- 'claude-3-sonnet': 3.25,
21
- 'claude-3-haiku': 3.25,
22
- 'claude-2': 3.25,
23
- 'gemini-pro': 3.5,
24
- 'gemini-ultra': 3.5,
25
- default: 3.5,
26
- };
27
- /**
28
- * Message format overhead in tokens (role markers, formatting, etc.)
29
- * @constant {number}
30
- */
31
- export const MESSAGE_OVERHEAD_TOKENS = 4;
32
- /**
33
- * Base overhead for a conversation (system prompts, etc.)
34
- * @constant {number}
35
- */
36
- export const CONVERSATION_BASE_OVERHEAD = 3;
37
- /**
38
- * Cache for tiktoken encoder to avoid re-initialization
39
- * @type {unknown | null}
40
- */
41
- let tiktokenEncoder = null;
42
- /**
43
- * Try to load tiktoken for precise token counting
44
- * @returns {Promise<unknown | null>} Tiktoken encoder or null if not available
45
- */
46
- async function getTiktokenEncoder() {
47
- if (tiktokenEncoder) {
48
- return tiktokenEncoder;
49
- }
50
- try {
51
- // Dynamic import to avoid hard dependency
52
- const tiktoken = await import('tiktoken');
53
- // Use cl100k_base encoding (used by GPT-4 and GPT-3.5-turbo)
54
- tiktokenEncoder = tiktoken.get_encoding('cl100k_base');
55
- return tiktokenEncoder;
56
- }
57
- catch {
58
- // tiktoken not available, fall back to rough estimation
59
- return null;
60
- }
61
- }
62
- /**
63
- * Estimate tokens in a single text string
64
- *
65
- * @param {string} text - Text to estimate tokens for
66
- * @param {TokenEstimationOptions} options - Estimation options
67
- * @returns {TokenEstimationResult} Token estimation with metadata
68
- *
69
- * @example
70
- * ```typescript
71
- * const result = estimateTokens('Hello, world!', { model: 'gpt-4' });
72
- * console.log(result.tokens); // ~4 tokens
73
- * ```
74
- */
75
- export function estimateTokens(text, options = {}) {
76
- const { model = 'default', customRatio } = options;
77
- // Handle empty text
78
- if (!text || text.length === 0) {
79
- return {
80
- tokens: 0,
81
- method: 'precise',
82
- model,
83
- confidence: 1,
84
- };
85
- }
86
- // Try synchronous tiktoken if available (pre-loaded)
87
- if (tiktokenEncoder && typeof tiktokenEncoder.encode === 'function') {
88
- try {
89
- const tokens = tiktokenEncoder.encode(text);
90
- return {
91
- tokens: tokens.length,
92
- method: 'precise',
93
- model,
94
- confidence: 0.95,
95
- };
96
- }
97
- catch {
98
- // Fall through to rough estimation
99
- }
100
- }
101
- // Rough estimation based on character count
102
- const ratio = customRatio ?? MODEL_TOKEN_RATIOS[model] ?? MODEL_TOKEN_RATIOS.default;
103
- const estimatedTokens = Math.ceil(text.length / ratio);
104
- return {
105
- tokens: estimatedTokens,
106
- method: 'rough',
107
- model,
108
- confidence: 0.8,
109
- };
110
- }
111
- /**
112
- * Async version of estimateTokens that attempts to use tiktoken for precision
113
- *
114
- * @param {string} text - Text to estimate tokens for
115
- * @param {TokenEstimationOptions} options - Estimation options
116
- * @returns {Promise<TokenEstimationResult>} Token estimation with metadata
117
- *
118
- * @example
119
- * ```typescript
120
- * const result = await estimateTokensAsync('Hello, world!', { model: 'gpt-4' });
121
- * console.log(result.method); // 'precise' if tiktoken available
122
- * ```
123
- */
124
- export async function estimateTokensAsync(text, options = {}) {
125
- const { model = 'default', customRatio } = options;
126
- // Handle empty text
127
- if (!text || text.length === 0) {
128
- return {
129
- tokens: 0,
130
- method: 'precise',
131
- model,
132
- confidence: 1,
133
- };
134
- }
135
- // Try to use tiktoken for precise counting
136
- const encoder = await getTiktokenEncoder();
137
- if (encoder && typeof encoder.encode === 'function') {
138
- try {
139
- const tokens = encoder.encode(text);
140
- return {
141
- tokens: tokens.length,
142
- method: 'precise',
143
- model,
144
- confidence: 0.95,
145
- };
146
- }
147
- catch {
148
- // Fall through to rough estimation
149
- }
150
- }
151
- // Fall back to rough estimation
152
- return estimateTokens(text, options);
153
- }
154
- /**
155
- * Estimate tokens for an array of messages
156
- *
157
- * @param {readonly Message[]} messages - Messages to estimate tokens for
158
- * @param {TokenEstimationOptions} options - Estimation options
159
- * @returns {TokenEstimationResult} Total token estimation with metadata
160
- *
161
- * @example
162
- * ```typescript
163
- * const messages = [
164
- * { role: 'system', content: 'You are a helpful assistant.' },
165
- * { role: 'user', content: 'Hello!' }
166
- * ];
167
- * const result = estimateTokensForMessages(messages);
168
- * console.log(result.tokens); // Total estimated tokens
169
- * ```
170
- */
171
- export function estimateTokensForMessages(messages, options = {}) {
172
- const { model = 'default', includeFormatting = true } = options;
173
- if (!messages || messages.length === 0) {
174
- return {
175
- tokens: 0,
176
- method: 'precise',
177
- model,
178
- confidence: 1,
179
- };
180
- }
181
- let totalTokens = 0;
182
- let preciseCount = 0;
183
- let roughCount = 0;
184
- for (const message of messages) {
185
- // Estimate content tokens
186
- const contentEstimate = estimateTokens(message.content, { model });
187
- totalTokens += contentEstimate.tokens;
188
- if (contentEstimate.method === 'precise') {
189
- preciseCount++;
190
- }
191
- else {
192
- roughCount++;
193
- }
194
- // Add per-message overhead (formatting, role markers, etc.)
195
- if (includeFormatting) {
196
- totalTokens += MESSAGE_OVERHEAD_TOKENS;
197
- // Add tokens for role name
198
- totalTokens += estimateTokens(message.role, { model }).tokens;
199
- }
200
- // Add tokens for attachments if present
201
- if (message.attachments && message.attachments.length > 0) {
202
- for (const attachment of message.attachments) {
203
- // Estimate based on attachment metadata
204
- const attachmentText = `${attachment.name} ${attachment.mimeType} ${attachment.caption ?? ''}`;
205
- totalTokens += estimateTokens(attachmentText, { model }).tokens;
206
- }
207
- }
208
- }
209
- // Add conversation base overhead
210
- if (includeFormatting) {
211
- totalTokens += CONVERSATION_BASE_OVERHEAD;
212
- }
213
- return {
214
- tokens: totalTokens,
215
- method: roughCount > 0 ? 'rough' : 'precise',
216
- model,
217
- confidence: preciseCount > roughCount ? 0.9 : 0.75,
218
- };
219
- }
220
- /**
221
- * Async version of estimateTokensForMessages with tiktoken support
222
- *
223
- * @param {readonly Message[]} messages - Messages to estimate tokens for
224
- * @param {TokenEstimationOptions} options - Estimation options
225
- * @returns {Promise<TokenEstimationResult>} Total token estimation with metadata
226
- */
227
- export async function estimateTokensForMessagesAsync(messages, options = {}) {
228
- const { model = 'default', includeFormatting = true } = options;
229
- if (!messages || messages.length === 0) {
230
- return {
231
- tokens: 0,
232
- method: 'precise',
233
- model,
234
- confidence: 1,
235
- };
236
- }
237
- // Try to initialize tiktoken
238
- const encoder = await getTiktokenEncoder();
239
- const usePrecise = encoder !== null;
240
- let totalTokens = 0;
241
- for (const message of messages) {
242
- // Use precise or rough estimation based on availability
243
- if (usePrecise) {
244
- const contentResult = await estimateTokensAsync(message.content, { model });
245
- totalTokens += contentResult.tokens;
246
- }
247
- else {
248
- const contentResult = estimateTokens(message.content, { model });
249
- totalTokens += contentResult.tokens;
250
- }
251
- // Add per-message overhead
252
- if (includeFormatting) {
253
- totalTokens += MESSAGE_OVERHEAD_TOKENS;
254
- const roleResult = usePrecise
255
- ? await estimateTokensAsync(message.role, { model })
256
- : estimateTokens(message.role, { model });
257
- totalTokens += roleResult.tokens;
258
- }
259
- // Add attachment estimates
260
- if (message.attachments && message.attachments.length > 0) {
261
- for (const attachment of message.attachments) {
262
- const attachmentText = `${attachment.name} ${attachment.mimeType} ${attachment.caption ?? ''}`;
263
- const attachResult = usePrecise
264
- ? await estimateTokensAsync(attachmentText, { model })
265
- : estimateTokens(attachmentText, { model });
266
- totalTokens += attachResult.tokens;
267
- }
268
- }
269
- }
270
- if (includeFormatting) {
271
- totalTokens += CONVERSATION_BASE_OVERHEAD;
272
- }
273
- return {
274
- tokens: totalTokens,
275
- method: usePrecise ? 'precise' : 'rough',
276
- model,
277
- confidence: usePrecise ? 0.95 : 0.75,
278
- };
279
- }
280
- /**
281
- * Rough token count estimation without any dependencies
282
- * Uses a simple characters-per-token heuristic
283
- *
284
- * @param {string | readonly Message[]} input - Text or messages to estimate
285
- * @param {SupportedModel} model - Model for estimation ratios
286
- * @returns {number} Estimated token count
287
- *
288
- * @example
289
- * ```typescript
290
- * // Estimate text
291
- * const textTokens = roughTokenCountEstimation('Hello, world!');
292
- *
293
- * // Estimate messages
294
- * const messageTokens = roughTokenCountEstimation([
295
- * { role: 'user', content: 'Hello!' }
296
- * ]);
297
- * ```
298
- */
299
- export function roughTokenCountEstimation(input, model = 'default') {
300
- const ratio = MODEL_TOKEN_RATIOS[model] ?? MODEL_TOKEN_RATIOS.default;
301
- // Handle string input
302
- if (typeof input === 'string') {
303
- if (!input)
304
- return 0;
305
- return Math.ceil(input.length / ratio);
306
- }
307
- // Handle message array input
308
- if (!Array.isArray(input) || input.length === 0) {
309
- return 0;
310
- }
311
- let totalChars = 0;
312
- for (const message of input) {
313
- // Add content length
314
- if (message.content) {
315
- totalChars += message.content.length;
316
- }
317
- // Add role length
318
- if (message.role) {
319
- totalChars += message.role.length;
320
- }
321
- // Add overhead
322
- totalChars += MESSAGE_OVERHEAD_TOKENS * ratio;
323
- // Add attachment metadata
324
- if (message.attachments) {
325
- for (const attachment of message.attachments) {
326
- totalChars += (attachment.name?.length ?? 0);
327
- totalChars += (attachment.mimeType?.length ?? 0);
328
- totalChars += (attachment.caption?.length ?? 0);
329
- }
330
- }
331
- }
332
- // Add conversation overhead
333
- totalChars += CONVERSATION_BASE_OVERHEAD * ratio;
334
- return Math.ceil(totalChars / ratio);
335
- }
336
- /**
337
- * Check if text would exceed token limit
338
- *
339
- * @param {string} text - Text to check
340
- * @param {number} limit - Token limit
341
- * @param {TokenEstimationOptions} options - Estimation options
342
- * @returns {{ withinLimit: true } | { withinLimit: false; exceededBy: number }} Limit check result
343
- *
344
- * @example
345
- * ```typescript
346
- * const result = checkTokenLimit('Long text...', 100);
347
- * if (!result.withinLimit) {
348
- * console.log(`Exceeded by ${result.exceededBy} tokens`);
349
- * }
350
- * ```
351
- */
352
- export function checkTokenLimit(text, limit, options = {}) {
353
- const estimate = estimateTokens(text, options);
354
- if (estimate.tokens <= limit) {
355
- return { withinLimit: true };
356
- }
357
- return {
358
- withinLimit: false,
359
- exceededBy: estimate.tokens - limit,
360
- };
361
- }
362
- /**
363
- * Truncate text to fit within token limit
364
- *
365
- * @param {string} text - Text to truncate
366
- * @param {number} maxTokens - Maximum token count
367
- * @param {TokenEstimationOptions} options - Estimation options
368
- * @returns {string} Truncated text
369
- *
370
- * @example
371
- * ```typescript
372
- * const truncated = truncateToTokenLimit(longText, 100);
373
- * ```
374
- */
375
- export function truncateToTokenLimit(text, maxTokens, options = {}) {
376
- const estimate = estimateTokens(text, options);
377
- if (estimate.tokens <= maxTokens) {
378
- return text;
379
- }
380
- const ratio = options.customRatio ??
381
- MODEL_TOKEN_RATIOS[options.model ?? 'default'] ??
382
- MODEL_TOKEN_RATIOS.default;
383
- // Calculate approximate character limit
384
- const targetChars = Math.floor(maxTokens * ratio);
385
- // Simple truncation (could be improved to respect word boundaries)
386
- return text.substring(0, targetChars) + '...';
387
- }
388
- /**
389
- * Get model-specific context window size
390
- *
391
- * @param {SupportedModel} model - Model name
392
- * @returns {number} Context window size in tokens
393
- */
394
- export function getModelContextWindow(model) {
395
- const contextWindows = {
396
- 'gpt-4': 8192,
397
- 'gpt-4o': 128000,
398
- 'gpt-4-turbo': 128000,
399
- 'gpt-3.5-turbo': 16385,
400
- 'claude-3-opus': 200000,
401
- 'claude-3-sonnet': 200000,
402
- 'claude-3-haiku': 200000,
403
- 'claude-2': 100000,
404
- 'gemini-pro': 1000000,
405
- 'gemini-ultra': 1000000,
406
- default: 4096,
407
- };
408
- return contextWindows[model] ?? contextWindows.default;
409
- }
410
- // Default export
411
- export default {
412
- estimateTokens,
413
- estimateTokensAsync,
414
- estimateTokensForMessages,
415
- estimateTokensForMessagesAsync,
416
- roughTokenCountEstimation,
417
- checkTokenLimit,
418
- truncateToTokenLimit,
419
- getModelContextWindow,
420
- MODEL_TOKEN_RATIOS,
421
- MESSAGE_OVERHEAD_TOKENS,
422
- CONVERSATION_BASE_OVERHEAD,
423
- };