[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
import type { ModelMessage } from 'ai';
import type { TokenEstimatorKind } from './types';
const CHARS_PER_TOKEN_FALLBACK = 4;
function estimateChars(value: unknown): number {
if (value == null) return 0;
if (typeof value === 'string') return value.length;
if (Array.isArray(value)) {
return value.reduce((sum, item) => sum + estimateChars(item), 0);
}
if (typeof value === 'object') {
try {
return JSON.stringify(value).length;
} catch {
return String(value).length;
}
}
return String(value).length;
}
export function resolveEstimatorKind(providerId?: string | null): TokenEstimatorKind {
const id = (providerId ?? '').toLowerCase();
if (id.includes('openai') || id.includes('gpt')) return 'openai-heuristic';
if (id.includes('anthropic') || id.includes('claude')) return 'anthropic-heuristic';
if (id.includes('google') || id.includes('gemini')) return 'google-heuristic';
return 'chars-div-4';
}
function applyHeuristicMultiplier(chars: number, kind: TokenEstimatorKind): number {
switch (kind) {
case 'openai-heuristic':
return Math.ceil(chars / 3.5);
case 'anthropic-heuristic':
return Math.ceil(chars / 3.2);
case 'google-heuristic':
return Math.ceil(chars / 3.8);
default:
return Math.ceil(chars / CHARS_PER_TOKEN_FALLBACK);
}
}
export function estimateTextTokens(text: string, providerId?: string | null): number {
const kind = resolveEstimatorKind(providerId);
return applyHeuristicMultiplier(text.length, kind);
}
export function estimateUnknownTokens(value: unknown, providerId?: string | null): number {
const kind = resolveEstimatorKind(providerId);
return applyHeuristicMultiplier(estimateChars(value), kind);
}
export interface EstimateModelMessagesTokensInput {
messages: ModelMessage[];
providerId?: string | null;
}
export interface EstimateModelMessagesTokensResult {
tokens: number;
estimatorKind: TokenEstimatorKind;
}
export function estimateModelMessagesTokensWithKind(
input: EstimateModelMessagesTokensInput,
): EstimateModelMessagesTokensResult {
const estimatorKind = resolveEstimatorKind(input.providerId);
const chars = input.messages.reduce((total, message) => {
return total + estimateChars(message.role) + estimateChars(message.content);
}, 0);
return {
tokens: applyHeuristicMultiplier(chars, estimatorKind),
estimatorKind,
};
}
export function estimateModelMessagesTokens(
messages: ModelMessage[],
providerId?: string | null,
): number {
return estimateModelMessagesTokensWithKind({ messages, providerId }).tokens;
}