@kkeve/suite 0.0.1 → 0.0.2
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 +53 -0
- package/dist/bin/keve.d.ts +13 -0
- package/dist/bin/keve.js +164 -0
- package/dist/commands/auth-update.d.ts +16 -0
- package/dist/commands/auth-update.js +88 -0
- package/dist/commands/clean.d.ts +10 -0
- package/dist/commands/clean.js +78 -0
- package/dist/commands/config.d.ts +17 -0
- package/dist/commands/config.js +99 -0
- package/dist/commands/init.d.ts +15 -0
- package/dist/commands/init.js +292 -0
- package/dist/commands/report.d.ts +12 -0
- package/dist/commands/report.js +159 -0
- package/dist/commands/run.d.ts +29 -0
- package/dist/commands/run.js +417 -0
- package/dist/commands/test.d.ts +12 -0
- package/dist/commands/test.js +102 -0
- package/dist/commands/vitest.d.ts +14 -0
- package/dist/commands/vitest.js +166 -0
- package/dist/config.d.ts +109 -0
- package/dist/config.js +291 -0
- package/dist/core/action-log-writer.d.ts +47 -0
- package/dist/{tools/write-file.js → core/action-log-writer.js} +42 -26
- package/dist/core/auth.d.ts +17 -0
- package/dist/core/auth.js +224 -0
- package/dist/core/cdp-resolver.d.ts +5 -0
- package/dist/core/cdp-resolver.js +93 -0
- package/dist/core/generateReport/report.d.ts +19 -0
- package/dist/core/generateReport/report.js +91 -0
- package/dist/core/generateReport/reportData.d.ts +215 -0
- package/dist/core/generateReport/reportData.js +735 -0
- package/dist/core/global-setup.d.ts +6 -0
- package/dist/core/global-setup.js +113 -0
- package/dist/core/keve-aspect.d.ts +54 -0
- package/dist/core/keve-aspect.js +52 -0
- package/dist/core/keve-decorators.d.ts +51 -0
- package/dist/core/keve-decorators.js +95 -0
- package/dist/core/keve-registry.d.ts +38 -0
- package/dist/core/keve-registry.js +25 -0
- package/dist/core/keve-report.d.ts +27 -0
- package/dist/core/keve-report.js +357 -0
- package/dist/core/keve-test.d.ts +36 -0
- package/dist/core/keve-test.js +364 -0
- package/dist/core/learned-actions.d.ts +24 -0
- package/dist/core/learned-actions.js +65 -0
- package/dist/core/pw-config.d.ts +19 -0
- package/dist/core/pw-config.js +180 -0
- package/dist/index.d.ts +8 -23
- package/dist/index.js +36 -43
- package/dist/page-agent/agent.d.ts +129 -0
- package/dist/page-agent/agent.js +585 -0
- package/dist/page-agent/hooks.d.ts +13 -0
- package/dist/page-agent/hooks.js +218 -0
- package/dist/page-agent/tools.d.ts +29 -0
- package/dist/page-agent/tools.js +297 -0
- package/doc/README.md +124 -0
- package/doc/agents/keve-dev-test-agent.md +140 -0
- package/doc/agents/keve-test-agent.md +178 -0
- package/doc/asserts//346/265/213/350/257/225/345/220/204/351/230/266/346/256/265/350/257/264/346/230/216.png +0 -0
- package/doc/keve-agent-demo.html +370 -0
- package/doc/skills/keve-bddcase-gen/SKILL.md +332 -0
- package/doc/skills/keve-bddcase-gen/references/test-case-rules.md +91 -0
- package/doc/skills/keve-bddcase-gen/references/test-cases-example.md +103 -0
- package/doc/skills/keve-component-gen/SKILL.md +255 -0
- package/doc/skills/keve-component-gen/references/component-mock-strategy.md +74 -0
- package/doc/skills/keve-component-gen/references/component-model-template.md +98 -0
- package/doc/skills/keve-component-gen/references/component-test-template.md +100 -0
- package/doc/skills/keve-component-gen/references/vue-test-utils-guide.md +91 -0
- package/doc/skills/keve-e2e-gen/SKILL.md +179 -0
- package/doc/skills/keve-e2e-gen/references/code-analysis-guide.md +208 -0
- package/doc/skills/keve-e2e-gen/references/decisions.md +36 -0
- package/doc/skills/keve-e2e-gen/references/pom-generation-guide.md +140 -0
- package/doc/skills/keve-e2e-gen/references/script-generation-guide.md +236 -0
- package/doc/skills/keve-e2e-gen/references/test-auditor-guide.md +189 -0
- package/doc/skills/keve-e2e-gen/scripts/extract-components.sh +85 -0
- package/doc/skills/keve-e2e-gen/scripts/inject-testids.sh +95 -0
- package/doc/skills/keve-static-analysis/SKILL.md +362 -0
- package/doc/skills/keve-static-analysis/references/codegraph-analysis-guide.md +108 -0
- package/doc/skills/keve-static-analysis/references/git-impact-analysis.md +81 -0
- package/doc/skills/keve-static-analysis/references/lint-fix-guide.md +69 -0
- package/doc/skills/keve-static-analysis/references/runtime-risk-patterns.md +92 -0
- package/doc/skills/keve-static-analysis/references/security-scan-guide.md +32 -0
- package/doc/skills/keve-static-analysis/references/ts-error-patterns.md +98 -0
- package/doc/skills/keve-static-analysis/references/vue-security-guide.md +72 -0
- package/doc/skills/keve-test-eval/SKILL.md +78 -0
- package/doc/skills/keve-test-eval/references/common-fix-guide.md +166 -0
- package/doc/skills/keve-test-eval/references/confidence-data-guide.md +78 -0
- package/doc/skills/keve-test-eval/references/fix-loop-guide.md +67 -0
- package/doc/skills/keve-unit-gen/SKILL.md +203 -0
- package/doc/skills/keve-unit-gen/references/boundary-conditions.md +78 -0
- package/doc/skills/keve-unit-gen/references/unit-mock-strategy.md +71 -0
- package/doc/skills/keve-unit-gen/references/unit-test-template.md +105 -0
- package/package.json +47 -25
- package/dist/agent/factory.d.ts +0 -25
- package/dist/agent/factory.js +0 -99
- package/dist/agent/index.d.ts +0 -3
- package/dist/agent/index.js +0 -7
- package/dist/agent/loader.d.ts +0 -22
- package/dist/agent/loader.js +0 -117
- package/dist/agent/types.d.ts +0 -9
- package/dist/agent/types.js +0 -2
- package/dist/agent-loop/complete-task.d.ts +0 -28
- package/dist/agent-loop/complete-task.js +0 -70
- package/dist/agent-loop/index.d.ts +0 -16
- package/dist/agent-loop/index.js +0 -26
- package/dist/agent-loop/loop.d.ts +0 -42
- package/dist/agent-loop/loop.js +0 -282
- package/dist/agent-loop/runtime.d.ts +0 -40
- package/dist/agent-loop/runtime.js +0 -163
- package/dist/agent-loop/types.d.ts +0 -161
- package/dist/agent-loop/types.js +0 -105
- package/dist/context/index.d.ts +0 -8
- package/dist/context/index.js +0 -29
- package/dist/context/tokenCalculation.d.ts +0 -55
- package/dist/context/tokenCalculation.js +0 -95
- package/dist/context/truncation.d.ts +0 -67
- package/dist/context/truncation.js +0 -142
- package/dist/context/types.d.ts +0 -7
- package/dist/context/types.js +0 -27
- package/dist/llm/OpenAIClient.d.ts +0 -31
- package/dist/llm/OpenAIClient.js +0 -455
- package/dist/llm/constants.d.ts +0 -2
- package/dist/llm/constants.js +0 -6
- package/dist/llm/errors.d.ts +0 -25
- package/dist/llm/errors.js +0 -51
- package/dist/llm/index.d.ts +0 -49
- package/dist/llm/index.js +0 -158
- package/dist/llm/types.d.ts +0 -124
- package/dist/llm/types.js +0 -2
- package/dist/llm/utils.d.ts +0 -29
- package/dist/llm/utils.js +0 -284
- package/dist/skill/frontmatter-parser.d.ts +0 -50
- package/dist/skill/frontmatter-parser.js +0 -152
- package/dist/skill/index.d.ts +0 -12
- package/dist/skill/index.js +0 -17
- package/dist/skill/loader.d.ts +0 -96
- package/dist/skill/loader.js +0 -256
- package/dist/tools/ask-user.d.ts +0 -8
- package/dist/tools/ask-user.js +0 -47
- package/dist/tools/bash.d.ts +0 -47
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit-file.d.ts +0 -9
- package/dist/tools/edit-file.js +0 -76
- package/dist/tools/glob.d.ts +0 -8
- package/dist/tools/glob.js +0 -101
- package/dist/tools/grep.d.ts +0 -10
- package/dist/tools/grep.js +0 -76
- package/dist/tools/index.d.ts +0 -24
- package/dist/tools/index.js +0 -47
- package/dist/tools/read-files.d.ts +0 -8
- package/dist/tools/read-files.js +0 -81
- package/dist/tools/write-file.d.ts +0 -8
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* RuntimeEnvironment — runtime environment detection
|
|
4
|
-
*
|
|
5
|
-
* Detects available system binaries (git/codegraph/playwright/node),
|
|
6
|
-
* and provides config paths (env).
|
|
7
|
-
*
|
|
8
|
-
* Tools (core/tools/*) get paths via ToolExecutionContext.runtime,
|
|
9
|
-
* instead of resolving binaries themselves.
|
|
10
|
-
*
|
|
11
|
-
* Design decisions:
|
|
12
|
-
* D02: Layer 1: RuntimeEnvironment provides binary paths
|
|
13
|
-
* Layer 2: Tool execute() gets paths from runtime
|
|
14
|
-
* Layer 3: Skill only ctx.tools.call(), no path awareness
|
|
15
|
-
* D04: Business-specific paths (keveWikiDir/reposBaseDir) removed from core.
|
|
16
|
-
* Agent package can add them in its own runtime extension.
|
|
17
|
-
*/
|
|
18
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
-
if (k2 === undefined) k2 = k;
|
|
20
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
-
}
|
|
24
|
-
Object.defineProperty(o, k2, desc);
|
|
25
|
-
}) : (function(o, m, k, k2) {
|
|
26
|
-
if (k2 === undefined) k2 = k;
|
|
27
|
-
o[k2] = m[k];
|
|
28
|
-
}));
|
|
29
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
-
}) : function(o, v) {
|
|
32
|
-
o["default"] = v;
|
|
33
|
-
});
|
|
34
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
-
var ownKeys = function(o) {
|
|
36
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
-
var ar = [];
|
|
38
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
-
return ar;
|
|
40
|
-
};
|
|
41
|
-
return ownKeys(o);
|
|
42
|
-
};
|
|
43
|
-
return function (mod) {
|
|
44
|
-
if (mod && mod.__esModule) return mod;
|
|
45
|
-
var result = {};
|
|
46
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
-
__setModuleDefault(result, mod);
|
|
48
|
-
return result;
|
|
49
|
-
};
|
|
50
|
-
})();
|
|
51
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
-
exports.detectRuntimeEnvironment = detectRuntimeEnvironment;
|
|
53
|
-
const path = __importStar(require("node:path"));
|
|
54
|
-
const fs = __importStar(require("node:fs"));
|
|
55
|
-
const node_child_process_1 = require("node:child_process");
|
|
56
|
-
// ===== Detection =====
|
|
57
|
-
/**
|
|
58
|
-
* Find a binary on the system PATH.
|
|
59
|
-
* Returns the absolute path or the binary name if not found (will fail at exec time).
|
|
60
|
-
*/
|
|
61
|
-
function findBinary(name) {
|
|
62
|
-
try {
|
|
63
|
-
return (0, node_child_process_1.execSync)(`which ${name} 2>/dev/null`, { encoding: 'utf-8' }).trim();
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return name;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Detect package manager from lockfile
|
|
71
|
-
*/
|
|
72
|
-
function detectPackageManager(projectDir) {
|
|
73
|
-
if (fs.existsSync(path.join(projectDir, 'pnpm-lock.yaml')))
|
|
74
|
-
return 'pnpm';
|
|
75
|
-
if (fs.existsSync(path.join(projectDir, 'yarn.lock')))
|
|
76
|
-
return 'yarn';
|
|
77
|
-
if (fs.existsSync(path.join(projectDir, 'package-lock.json')))
|
|
78
|
-
return 'npm';
|
|
79
|
-
return 'pnpm';
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Load environment variables from .env file (if present)
|
|
83
|
-
*/
|
|
84
|
-
function loadEnvFile(envPath) {
|
|
85
|
-
const env = {};
|
|
86
|
-
if (!fs.existsSync(envPath))
|
|
87
|
-
return env;
|
|
88
|
-
try {
|
|
89
|
-
const content = fs.readFileSync(envPath, 'utf-8');
|
|
90
|
-
for (const line of content.split('\n')) {
|
|
91
|
-
const trimmed = line.trim();
|
|
92
|
-
if (!trimmed || trimmed.startsWith('#'))
|
|
93
|
-
continue;
|
|
94
|
-
const eqIndex = trimmed.indexOf('=');
|
|
95
|
-
if (eqIndex > 0) {
|
|
96
|
-
const key = trimmed.slice(0, eqIndex).trim();
|
|
97
|
-
let value = trimmed.slice(eqIndex + 1).trim();
|
|
98
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
99
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
100
|
-
value = value.slice(1, -1);
|
|
101
|
-
}
|
|
102
|
-
env[key] = value;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// Ignore .env read errors
|
|
108
|
-
}
|
|
109
|
-
return env;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Detect the runtime environment.
|
|
113
|
-
*
|
|
114
|
-
* Scans for binaries, loads env vars.
|
|
115
|
-
* Called once at startup (entry.ts) and passed to Pipeline → SkillContext.
|
|
116
|
-
*
|
|
117
|
-
* @param cwd - Starting directory (defaults to process.cwd())
|
|
118
|
-
* @param agentDir - Agent package directory for finding node_modules binaries
|
|
119
|
-
*/
|
|
120
|
-
function detectRuntimeEnvironment(cwd, agentDir) {
|
|
121
|
-
const startDir = cwd ?? process.cwd();
|
|
122
|
-
const pkgDir = agentDir ?? findPkgDir(startDir);
|
|
123
|
-
// Find playwright binary: prefer agent's node_modules, fallback to global
|
|
124
|
-
const localPlaywright = path.join(pkgDir, 'node_modules', '.bin', 'playwright');
|
|
125
|
-
const playwrightBin = fs.existsSync(localPlaywright)
|
|
126
|
-
? localPlaywright
|
|
127
|
-
: findBinary('playwright');
|
|
128
|
-
// Load .env from agent/pkg dir
|
|
129
|
-
const env = {
|
|
130
|
-
...loadEnvFile(path.join(pkgDir, '.env')),
|
|
131
|
-
};
|
|
132
|
-
// Also inherit relevant process.env
|
|
133
|
-
for (const key of ['GITLAB_TOKEN', 'HOME', 'PATH', 'NODE_ENV']) {
|
|
134
|
-
if (process.env[key])
|
|
135
|
-
env[key] = process.env[key];
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
gitBin: findBinary('git'),
|
|
139
|
-
codegraphBin: findBinary('codegraph'),
|
|
140
|
-
playwrightBin,
|
|
141
|
-
nodeBin: process.execPath,
|
|
142
|
-
packageManager: detectPackageManager(pkgDir),
|
|
143
|
-
env,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Walk up from startDir to find the nearest package directory
|
|
148
|
-
* (contains package.json with node_modules)
|
|
149
|
-
*/
|
|
150
|
-
function findPkgDir(startDir) {
|
|
151
|
-
let dir = startDir;
|
|
152
|
-
for (let i = 0; i < 15; i++) {
|
|
153
|
-
const pkgPath = path.join(dir, 'package.json');
|
|
154
|
-
if (fs.existsSync(pkgPath) && fs.existsSync(path.join(dir, 'node_modules'))) {
|
|
155
|
-
return dir;
|
|
156
|
-
}
|
|
157
|
-
const parent = path.dirname(dir);
|
|
158
|
-
if (parent === dir)
|
|
159
|
-
break;
|
|
160
|
-
dir = parent;
|
|
161
|
-
}
|
|
162
|
-
return startDir;
|
|
163
|
-
}
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Loop Core Types
|
|
3
|
-
*
|
|
4
|
-
* Reference: gemini-cli LocalAgentExecutor + AgentProtocol
|
|
5
|
-
* Adapted for OpenAI-compatible API (internal proxy at xxx)
|
|
6
|
-
*
|
|
7
|
-
* Key differences from gemini-cli:
|
|
8
|
-
* - LLM calls use OpenAIClient instead of GeminiChat
|
|
9
|
-
* - Tool definitions reuse core/llm/types.ts Tool interface
|
|
10
|
-
* - No Gemini-specific Content/Part types — use OpenAI Message format
|
|
11
|
-
* - Simplified timeout (no DeadlineTimer pause/resume — we don't wait for user confirmation)
|
|
12
|
-
*/
|
|
13
|
-
import type { LLMClient, Tool } from '../llm/types';
|
|
14
|
-
import type { RuntimeEnvironment } from './runtime';
|
|
15
|
-
/** Default maximum number of conversational turns for an agent. */
|
|
16
|
-
export declare const DEFAULT_MAX_TURNS = 30;
|
|
17
|
-
/** Default maximum execution time for an agent in minutes. */
|
|
18
|
-
export declare const DEFAULT_MAX_TIME_MINUTES = 10;
|
|
19
|
-
/** Tool name for signaling task completion (reference: gemini-cli CompleteTaskTool) */
|
|
20
|
-
export declare const COMPLETE_TASK_TOOL_NAME = "complete_task";
|
|
21
|
-
/**
|
|
22
|
-
* Definition of an agent to execute via the loop.
|
|
23
|
-
* Reference: gemini-cli LocalAgentDefinition (agents/types.ts L214-285)
|
|
24
|
-
*
|
|
25
|
-
* Simplified from gemini-cli: removed kind, promptConfig, modelConfig, runConfig,
|
|
26
|
-
* workspaceDirectories, memoryInboxAccess, mcpServers, processOutput, onBeforeTurn.
|
|
27
|
-
* These features can be added incrementally as needed.
|
|
28
|
-
*/
|
|
29
|
-
export interface AgentDefinition {
|
|
30
|
-
/** Unique identifier for the agent. */
|
|
31
|
-
name: string;
|
|
32
|
-
/** Human-readable description. */
|
|
33
|
-
description: string;
|
|
34
|
-
/** System prompt injected as the first message. Can include SKILL.md content. */
|
|
35
|
-
systemPrompt?: string;
|
|
36
|
-
/** The initial user query/message. Defaults to 'Get Started!' if not provided. */
|
|
37
|
-
query?: string;
|
|
38
|
-
/** Maximum number of conversational turns. Defaults to DEFAULT_MAX_TURNS (30). */
|
|
39
|
-
maxTurns?: number;
|
|
40
|
-
/** Maximum execution time in minutes. Defaults to DEFAULT_MAX_TIME_MINUTES (10). */
|
|
41
|
-
maxTimeMinutes?: number;
|
|
42
|
-
/** Tool names to restrict to. If omitted, all registered tools are available. */
|
|
43
|
-
toolNames?: string[];
|
|
44
|
-
/** Paths that are read-only — bash tool will block write operations targeting these directories */
|
|
45
|
-
readOnlyPaths?: string[];
|
|
46
|
-
/** Working directory for tool execution. Defaults to process.cwd() */
|
|
47
|
-
cwd?: string;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Execution context for the agent loop.
|
|
51
|
-
* Provides the LLM client, tool registry, and config needed to run an agent.
|
|
52
|
-
*/
|
|
53
|
-
export interface AgentLoopContext {
|
|
54
|
-
/** LLM client for calling the model. Uses core/llm/OpenAIClient. */
|
|
55
|
-
llmClient: LLMClient;
|
|
56
|
-
/** Tool registry for executing tool calls from the model. */
|
|
57
|
-
toolRegistry: ToolRegistry;
|
|
58
|
-
/** Application configuration. */
|
|
59
|
-
config: Record<string, unknown>;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Callback for receiving agent events during execution.
|
|
63
|
-
* Events are emitted at key points: start, tool calls, thoughts, end, errors.
|
|
64
|
-
*/
|
|
65
|
-
export type AgentEventCallback = (event: AgentEvent) => void;
|
|
66
|
-
/**
|
|
67
|
-
* Events emitted during agent execution.
|
|
68
|
-
* Reference: gemini-cli AgentEvents (agent/types.ts L104-131) and SubagentActivityEvent (agents/types.ts L84-89)
|
|
69
|
-
*
|
|
70
|
-
* Simplified from gemini-cli: merged multiple event interfaces into one,
|
|
71
|
-
* removed display-specific fields (DisplayContent, ToolDisplayFormat).
|
|
72
|
-
*/
|
|
73
|
-
export interface AgentEvent {
|
|
74
|
-
type: 'agent_start' | 'tool_call_start' | 'tool_call_end' | 'thought_chunk' | 'agent_end' | 'agent_error';
|
|
75
|
-
/** Stream identifier (typically the agent name). */
|
|
76
|
-
streamId: string;
|
|
77
|
-
/** Event-specific data. */
|
|
78
|
-
data: Record<string, unknown>;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Describes how an agent's execution ended.
|
|
82
|
-
* Reference: gemini-cli AgentTerminateMode (agents/types.ts L24-31)
|
|
83
|
-
*/
|
|
84
|
-
export declare const TM_GOAL = "GOAL";
|
|
85
|
-
export declare const TM_TIMEOUT = "TIMEOUT";
|
|
86
|
-
export declare const TM_MAX_TURNS = "MAX_TURNS";
|
|
87
|
-
export declare const TM_ABORTED = "ABORTED";
|
|
88
|
-
export declare const TM_ERROR = "ERROR";
|
|
89
|
-
export declare const TM_ERROR_NO_COMPLETE_TASK = "ERROR_NO_COMPLETE_TASK";
|
|
90
|
-
export type AgentTerminateMode = typeof TM_GOAL | typeof TM_TIMEOUT | typeof TM_MAX_TURNS | typeof TM_ABORTED | typeof TM_ERROR | typeof TM_ERROR_NO_COMPLETE_TASK;
|
|
91
|
-
/**
|
|
92
|
-
* The final result of an agent's execution.
|
|
93
|
-
* Reference: gemini-cli OutputObject (agents/types.ts L36-41)
|
|
94
|
-
*/
|
|
95
|
-
export interface AgentResult {
|
|
96
|
-
/** Whether the agent completed successfully (GOAL termination). */
|
|
97
|
-
success: boolean;
|
|
98
|
-
/** The final output string from complete_task, if available. */
|
|
99
|
-
output?: string;
|
|
100
|
-
/** How the agent's execution ended. */
|
|
101
|
-
terminateReason: AgentTerminateMode;
|
|
102
|
-
/** Number of conversational turns completed. */
|
|
103
|
-
turnCount: number;
|
|
104
|
-
/** Total execution time in milliseconds. */
|
|
105
|
-
durationMs: number;
|
|
106
|
-
/** Error message if the agent failed. */
|
|
107
|
-
error?: string;
|
|
108
|
-
}
|
|
109
|
-
export interface ToolExecutionContext {
|
|
110
|
-
/** Runtime environment (binary paths, config dirs, env vars) */
|
|
111
|
-
runtime: RuntimeEnvironment;
|
|
112
|
-
/** Working directory for command execution */
|
|
113
|
-
cwd: string;
|
|
114
|
-
/** Timeout in milliseconds */
|
|
115
|
-
timeout?: number;
|
|
116
|
-
/** 🆕 Paths that are read-only — bash tool will block write operations to these directories */
|
|
117
|
-
readOnlyPaths?: string[];
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* A tool definition for the agent loop's registry.
|
|
121
|
-
* Compatible with core/llm/types.ts Tool interface.
|
|
122
|
-
*/
|
|
123
|
-
export interface ToolDefinition {
|
|
124
|
-
/** Tool name (used as the key in OpenAI function_call). */
|
|
125
|
-
name: string;
|
|
126
|
-
/** Human-readable description sent to the LLM. */
|
|
127
|
-
description: string;
|
|
128
|
-
/** Zod schema for input validation and OpenAI parameter generation. */
|
|
129
|
-
inputSchema: z.ZodType<any>;
|
|
130
|
-
/** Execute the tool with validated arguments. */
|
|
131
|
-
execute: (args: any, context?: ToolExecutionContext) => Promise<any>;
|
|
132
|
-
/** Custom JSON Schema for the LLM (overrides zod conversion). */
|
|
133
|
-
customJsonSchema?: Record<string, any>;
|
|
134
|
-
}
|
|
135
|
-
import type * as z from 'zod/v4';
|
|
136
|
-
/**
|
|
137
|
-
* Tool registry for managing and executing tools during agent execution.
|
|
138
|
-
* Reference: gemini-cli ToolRegistry (tools/tool-registry.ts)
|
|
139
|
-
*
|
|
140
|
-
* Simplified: no message bus, no confirmation policy, no sort, no MCP integration.
|
|
141
|
-
* These can be added incrementally.
|
|
142
|
-
*/
|
|
143
|
-
export declare class ToolRegistry {
|
|
144
|
-
private tools;
|
|
145
|
-
/** Register a tool definition. */
|
|
146
|
-
register(tool: ToolDefinition): void;
|
|
147
|
-
/** Unregister a tool by name. */
|
|
148
|
-
unregister(name: string): void;
|
|
149
|
-
/** Get all registered tool names. */
|
|
150
|
-
getAllToolNames(): string[];
|
|
151
|
-
/** Convert registered tools to the core/llm/types.ts Tool map format for LLM calls. */
|
|
152
|
-
getToolsMap(): Record<string, Tool>;
|
|
153
|
-
/** Get a subset of tools by name (for agent's toolNames restriction). */
|
|
154
|
-
getToolsMapSubset(names: string[]): Record<string, Tool>;
|
|
155
|
-
/** Execute a registered tool by name with the given arguments and optional context. */
|
|
156
|
-
execute(name: string, args: any, context?: ToolExecutionContext): Promise<any>;
|
|
157
|
-
/** Check if a tool is registered. */
|
|
158
|
-
has(name: string): boolean;
|
|
159
|
-
/** Get a tool definition by name. */
|
|
160
|
-
get(name: string): ToolDefinition | undefined;
|
|
161
|
-
}
|
package/dist/agent-loop/types.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Agent Loop Core Types
|
|
4
|
-
*
|
|
5
|
-
* Reference: gemini-cli LocalAgentExecutor + AgentProtocol
|
|
6
|
-
* Adapted for OpenAI-compatible API (internal proxy at xxx)
|
|
7
|
-
*
|
|
8
|
-
* Key differences from gemini-cli:
|
|
9
|
-
* - LLM calls use OpenAIClient instead of GeminiChat
|
|
10
|
-
* - Tool definitions reuse core/llm/types.ts Tool interface
|
|
11
|
-
* - No Gemini-specific Content/Part types — use OpenAI Message format
|
|
12
|
-
* - Simplified timeout (no DeadlineTimer pause/resume — we don't wait for user confirmation)
|
|
13
|
-
*/
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.ToolRegistry = exports.TM_ERROR_NO_COMPLETE_TASK = exports.TM_ERROR = exports.TM_ABORTED = exports.TM_MAX_TURNS = exports.TM_TIMEOUT = exports.TM_GOAL = exports.COMPLETE_TASK_TOOL_NAME = exports.DEFAULT_MAX_TIME_MINUTES = exports.DEFAULT_MAX_TURNS = void 0;
|
|
16
|
-
// ===== Constants (reference: gemini-cli DEFAULT_MAX_TURNS/DEFAULT_MAX_TIME_MINUTES) =====
|
|
17
|
-
/** Default maximum number of conversational turns for an agent. */
|
|
18
|
-
exports.DEFAULT_MAX_TURNS = 30;
|
|
19
|
-
/** Default maximum execution time for an agent in minutes. */
|
|
20
|
-
exports.DEFAULT_MAX_TIME_MINUTES = 10;
|
|
21
|
-
/** Tool name for signaling task completion (reference: gemini-cli CompleteTaskTool) */
|
|
22
|
-
exports.COMPLETE_TASK_TOOL_NAME = 'complete_task';
|
|
23
|
-
// ===== Termination Modes =====
|
|
24
|
-
/**
|
|
25
|
-
* Describes how an agent's execution ended.
|
|
26
|
-
* Reference: gemini-cli AgentTerminateMode (agents/types.ts L24-31)
|
|
27
|
-
*/
|
|
28
|
-
// Inline termination mode constants (vite tree-shaking removes cross-module const objects)
|
|
29
|
-
exports.TM_GOAL = 'GOAL';
|
|
30
|
-
exports.TM_TIMEOUT = 'TIMEOUT';
|
|
31
|
-
exports.TM_MAX_TURNS = 'MAX_TURNS';
|
|
32
|
-
exports.TM_ABORTED = 'ABORTED';
|
|
33
|
-
exports.TM_ERROR = 'ERROR';
|
|
34
|
-
exports.TM_ERROR_NO_COMPLETE_TASK = 'ERROR_NO_COMPLETE_TASK';
|
|
35
|
-
/**
|
|
36
|
-
* Tool registry for managing and executing tools during agent execution.
|
|
37
|
-
* Reference: gemini-cli ToolRegistry (tools/tool-registry.ts)
|
|
38
|
-
*
|
|
39
|
-
* Simplified: no message bus, no confirmation policy, no sort, no MCP integration.
|
|
40
|
-
* These can be added incrementally.
|
|
41
|
-
*/
|
|
42
|
-
class ToolRegistry {
|
|
43
|
-
tools = new Map();
|
|
44
|
-
/** Register a tool definition. */
|
|
45
|
-
register(tool) {
|
|
46
|
-
this.tools.set(tool.name, tool);
|
|
47
|
-
}
|
|
48
|
-
/** Unregister a tool by name. */
|
|
49
|
-
unregister(name) {
|
|
50
|
-
this.tools.delete(name);
|
|
51
|
-
}
|
|
52
|
-
/** Get all registered tool names. */
|
|
53
|
-
getAllToolNames() {
|
|
54
|
-
return Array.from(this.tools.keys());
|
|
55
|
-
}
|
|
56
|
-
/** Convert registered tools to the core/llm/types.ts Tool map format for LLM calls. */
|
|
57
|
-
getToolsMap() {
|
|
58
|
-
const result = {};
|
|
59
|
-
for (const [name, def] of this.tools) {
|
|
60
|
-
result[name] = {
|
|
61
|
-
description: def.description,
|
|
62
|
-
inputSchema: def.inputSchema,
|
|
63
|
-
execute: def.execute,
|
|
64
|
-
customJsonSchema: def.customJsonSchema,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
return result;
|
|
68
|
-
}
|
|
69
|
-
/** Get a subset of tools by name (for agent's toolNames restriction). */
|
|
70
|
-
getToolsMapSubset(names) {
|
|
71
|
-
const result = {};
|
|
72
|
-
for (const name of names) {
|
|
73
|
-
const def = this.tools.get(name);
|
|
74
|
-
if (def) {
|
|
75
|
-
result[name] = {
|
|
76
|
-
description: def.description,
|
|
77
|
-
inputSchema: def.inputSchema,
|
|
78
|
-
execute: def.execute,
|
|
79
|
-
customJsonSchema: def.customJsonSchema,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
/** Execute a registered tool by name with the given arguments and optional context. */
|
|
86
|
-
async execute(name, args, context) {
|
|
87
|
-
const tool = this.tools.get(name);
|
|
88
|
-
if (!tool) {
|
|
89
|
-
throw new Error(`Tool not found: ${name}`);
|
|
90
|
-
}
|
|
91
|
-
// Validate args with zod schema
|
|
92
|
-
const validation = tool.inputSchema.safeParse(args);
|
|
93
|
-
const validatedArgs = validation.success ? validation.data : args;
|
|
94
|
-
return tool.execute(validatedArgs, context);
|
|
95
|
-
}
|
|
96
|
-
/** Check if a tool is registered. */
|
|
97
|
-
has(name) {
|
|
98
|
-
return this.tools.has(name);
|
|
99
|
-
}
|
|
100
|
-
/** Get a tool definition by name. */
|
|
101
|
-
get(name) {
|
|
102
|
-
return this.tools.get(name);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
exports.ToolRegistry = ToolRegistry;
|
package/dist/context/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @ks-data/agent-core — context module entry point.
|
|
3
|
-
*
|
|
4
|
-
* Provides truncation and token estimation utilities for managing
|
|
5
|
-
* LLM input size within token budgets.
|
|
6
|
-
*/
|
|
7
|
-
export { ASCII_TOKENS_PER_CHAR, NON_ASCII_TOKENS_PER_CHAR, MSG_OVERHEAD_TOKENS, DEFAULT_CHARS_PER_TOKEN, estimateTextTokens, estimateTokenCountSync, estimateTokenCountForText, calculateTokenCount, type TokenEstimationPart, } from './tokenCalculation';
|
|
8
|
-
export { MIN_TARGET_TOKENS, MIN_CHARS_FOR_TRUNCATION, TEXT_TRUNCATION_PREFIX, TOOL_TRUNCATION_PREFIX, estimateCharsFromTokens, truncateProportionally, normalizeFunctionResponse, truncateToTokenBudget, } from './truncation';
|
package/dist/context/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @ks-data/agent-core — context module entry point.
|
|
4
|
-
*
|
|
5
|
-
* Provides truncation and token estimation utilities for managing
|
|
6
|
-
* LLM input size within token budgets.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.truncateToTokenBudget = exports.normalizeFunctionResponse = exports.truncateProportionally = exports.estimateCharsFromTokens = exports.TOOL_TRUNCATION_PREFIX = exports.TEXT_TRUNCATION_PREFIX = exports.MIN_CHARS_FOR_TRUNCATION = exports.MIN_TARGET_TOKENS = exports.calculateTokenCount = exports.estimateTokenCountForText = exports.estimateTokenCountSync = exports.estimateTextTokens = exports.DEFAULT_CHARS_PER_TOKEN = exports.MSG_OVERHEAD_TOKENS = exports.NON_ASCII_TOKENS_PER_CHAR = exports.ASCII_TOKENS_PER_CHAR = void 0;
|
|
10
|
-
var tokenCalculation_1 = require("./tokenCalculation");
|
|
11
|
-
// Token calculation
|
|
12
|
-
Object.defineProperty(exports, "ASCII_TOKENS_PER_CHAR", { enumerable: true, get: function () { return tokenCalculation_1.ASCII_TOKENS_PER_CHAR; } });
|
|
13
|
-
Object.defineProperty(exports, "NON_ASCII_TOKENS_PER_CHAR", { enumerable: true, get: function () { return tokenCalculation_1.NON_ASCII_TOKENS_PER_CHAR; } });
|
|
14
|
-
Object.defineProperty(exports, "MSG_OVERHEAD_TOKENS", { enumerable: true, get: function () { return tokenCalculation_1.MSG_OVERHEAD_TOKENS; } });
|
|
15
|
-
Object.defineProperty(exports, "DEFAULT_CHARS_PER_TOKEN", { enumerable: true, get: function () { return tokenCalculation_1.DEFAULT_CHARS_PER_TOKEN; } });
|
|
16
|
-
Object.defineProperty(exports, "estimateTextTokens", { enumerable: true, get: function () { return tokenCalculation_1.estimateTextTokens; } });
|
|
17
|
-
Object.defineProperty(exports, "estimateTokenCountSync", { enumerable: true, get: function () { return tokenCalculation_1.estimateTokenCountSync; } });
|
|
18
|
-
Object.defineProperty(exports, "estimateTokenCountForText", { enumerable: true, get: function () { return tokenCalculation_1.estimateTokenCountForText; } });
|
|
19
|
-
Object.defineProperty(exports, "calculateTokenCount", { enumerable: true, get: function () { return tokenCalculation_1.calculateTokenCount; } });
|
|
20
|
-
var truncation_1 = require("./truncation");
|
|
21
|
-
// Truncation
|
|
22
|
-
Object.defineProperty(exports, "MIN_TARGET_TOKENS", { enumerable: true, get: function () { return truncation_1.MIN_TARGET_TOKENS; } });
|
|
23
|
-
Object.defineProperty(exports, "MIN_CHARS_FOR_TRUNCATION", { enumerable: true, get: function () { return truncation_1.MIN_CHARS_FOR_TRUNCATION; } });
|
|
24
|
-
Object.defineProperty(exports, "TEXT_TRUNCATION_PREFIX", { enumerable: true, get: function () { return truncation_1.TEXT_TRUNCATION_PREFIX; } });
|
|
25
|
-
Object.defineProperty(exports, "TOOL_TRUNCATION_PREFIX", { enumerable: true, get: function () { return truncation_1.TOOL_TRUNCATION_PREFIX; } });
|
|
26
|
-
Object.defineProperty(exports, "estimateCharsFromTokens", { enumerable: true, get: function () { return truncation_1.estimateCharsFromTokens; } });
|
|
27
|
-
Object.defineProperty(exports, "truncateProportionally", { enumerable: true, get: function () { return truncation_1.truncateProportionally; } });
|
|
28
|
-
Object.defineProperty(exports, "normalizeFunctionResponse", { enumerable: true, get: function () { return truncation_1.normalizeFunctionResponse; } });
|
|
29
|
-
Object.defineProperty(exports, "truncateToTokenBudget", { enumerable: true, get: function () { return truncation_1.truncateToTokenBudget; } });
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token estimation constants — ported from gemini-cli (Apache-2.0).
|
|
3
|
-
*
|
|
4
|
-
* ASCII characters (0-127) are roughly 3-4 chars per token.
|
|
5
|
-
* We use 0.33 (~3 chars/token) as a conservative baseline for mixed text and code.
|
|
6
|
-
*/
|
|
7
|
-
export declare const ASCII_TOKENS_PER_CHAR = 0.33;
|
|
8
|
-
/**
|
|
9
|
-
* Non-ASCII characters (including CJK) are often 1-2 tokens per char.
|
|
10
|
-
* We use 1.5 as a conservative estimate to avoid underestimation.
|
|
11
|
-
*/
|
|
12
|
-
export declare const NON_ASCII_TOKENS_PER_CHAR = 1.5;
|
|
13
|
-
/** Structural overhead per message turn (role prefixes, separators). */
|
|
14
|
-
export declare const MSG_OVERHEAD_TOKENS = 5;
|
|
15
|
-
/** Default chars-per-token ratio used as fallback. */
|
|
16
|
-
export declare const DEFAULT_CHARS_PER_TOKEN = 4;
|
|
17
|
-
/**
|
|
18
|
-
* Heuristic estimation of tokens for a text string.
|
|
19
|
-
* Uses char-by-char scan for strings ≤ 100K chars, length/charsPerToken for larger strings.
|
|
20
|
-
*/
|
|
21
|
-
export declare function estimateTextTokens(text: string, charsPerToken?: number): number;
|
|
22
|
-
/**
|
|
23
|
-
* Synchronous token-count estimation for an array of message-like parts.
|
|
24
|
-
* Adapted from gemini-cli's `estimateTokenCountSync`, but uses our own
|
|
25
|
-
* message-part representation instead of Gemini's `Part` type.
|
|
26
|
-
*
|
|
27
|
-
* Each "part" can be:
|
|
28
|
-
* - `{ text: string }` → text token estimation
|
|
29
|
-
* - `{ functionResponse: ... }` → tool response estimation
|
|
30
|
-
* - other objects → JSON string length / charsPerToken fallback
|
|
31
|
-
*/
|
|
32
|
-
export interface TokenEstimationPart {
|
|
33
|
-
text?: string;
|
|
34
|
-
functionResponse?: {
|
|
35
|
-
name?: string;
|
|
36
|
-
response?: unknown;
|
|
37
|
-
};
|
|
38
|
-
[key: string]: unknown;
|
|
39
|
-
}
|
|
40
|
-
export declare function estimateTokenCountSync(parts: TokenEstimationPart[], charsPerToken?: number): number;
|
|
41
|
-
/**
|
|
42
|
-
* Asynchronous token count calculation for a text string or message array.
|
|
43
|
-
* For text-only content, this simply delegates to `estimateTokenCountSync`.
|
|
44
|
-
* For content with media references (future: image/PDF), we would call
|
|
45
|
-
* an external tokenizer — but for now, everything is text-only estimation.
|
|
46
|
-
*
|
|
47
|
-
* This replaces gemini-cli's `calculateRequestTokenCount` which uses
|
|
48
|
-
* the Gemini `countTokens` API. We don't have an equivalent API for
|
|
49
|
-
* our internal OpenAI-compatible proxy, so we rely on heuristic estimation.
|
|
50
|
-
*/
|
|
51
|
-
export declare function calculateTokenCount(content: string | TokenEstimationPart[], charsPerToken?: number): Promise<number>;
|
|
52
|
-
/**
|
|
53
|
-
* Convenience: estimate token count for a single text string.
|
|
54
|
-
*/
|
|
55
|
-
export declare function estimateTokenCountForText(text: string, charsPerToken?: number): number;
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_CHARS_PER_TOKEN = exports.MSG_OVERHEAD_TOKENS = exports.NON_ASCII_TOKENS_PER_CHAR = exports.ASCII_TOKENS_PER_CHAR = void 0;
|
|
4
|
-
exports.estimateTextTokens = estimateTextTokens;
|
|
5
|
-
exports.estimateTokenCountSync = estimateTokenCountSync;
|
|
6
|
-
exports.calculateTokenCount = calculateTokenCount;
|
|
7
|
-
exports.estimateTokenCountForText = estimateTokenCountForText;
|
|
8
|
-
/**
|
|
9
|
-
* Token estimation constants — ported from gemini-cli (Apache-2.0).
|
|
10
|
-
*
|
|
11
|
-
* ASCII characters (0-127) are roughly 3-4 chars per token.
|
|
12
|
-
* We use 0.33 (~3 chars/token) as a conservative baseline for mixed text and code.
|
|
13
|
-
*/
|
|
14
|
-
exports.ASCII_TOKENS_PER_CHAR = 0.33;
|
|
15
|
-
/**
|
|
16
|
-
* Non-ASCII characters (including CJK) are often 1-2 tokens per char.
|
|
17
|
-
* We use 1.5 as a conservative estimate to avoid underestimation.
|
|
18
|
-
*/
|
|
19
|
-
exports.NON_ASCII_TOKENS_PER_CHAR = 1.5;
|
|
20
|
-
/** Structural overhead per message turn (role prefixes, separators). */
|
|
21
|
-
exports.MSG_OVERHEAD_TOKENS = 5;
|
|
22
|
-
/** Default chars-per-token ratio used as fallback. */
|
|
23
|
-
exports.DEFAULT_CHARS_PER_TOKEN = 4;
|
|
24
|
-
/**
|
|
25
|
-
* Maximum number of characters to process with the full character-by-character heuristic.
|
|
26
|
-
* Above this, we use a faster approximation to avoid performance bottlenecks.
|
|
27
|
-
*/
|
|
28
|
-
const MAX_CHARS_FOR_FULL_HEURISTIC = 100_000;
|
|
29
|
-
/**
|
|
30
|
-
* Heuristic estimation of tokens for a text string.
|
|
31
|
-
* Uses char-by-char scan for strings ≤ 100K chars, length/charsPerToken for larger strings.
|
|
32
|
-
*/
|
|
33
|
-
function estimateTextTokens(text, charsPerToken = exports.DEFAULT_CHARS_PER_TOKEN) {
|
|
34
|
-
if (text.length > MAX_CHARS_FOR_FULL_HEURISTIC) {
|
|
35
|
-
return text.length / charsPerToken;
|
|
36
|
-
}
|
|
37
|
-
let tokens = 0;
|
|
38
|
-
const asciiTokensPerChar = 1 / charsPerToken;
|
|
39
|
-
for (let i = 0; i < text.length; i++) {
|
|
40
|
-
if (text.charCodeAt(i) <= 127) {
|
|
41
|
-
tokens += asciiTokensPerChar;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
tokens += exports.NON_ASCII_TOKENS_PER_CHAR;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return tokens;
|
|
48
|
-
}
|
|
49
|
-
function estimateTokenCountSync(parts, charsPerToken = exports.DEFAULT_CHARS_PER_TOKEN) {
|
|
50
|
-
let totalTokens = 0;
|
|
51
|
-
for (const part of parts) {
|
|
52
|
-
if (typeof part.text === 'string') {
|
|
53
|
-
totalTokens += estimateTextTokens(part.text, charsPerToken);
|
|
54
|
-
}
|
|
55
|
-
else if (part.functionResponse) {
|
|
56
|
-
const fr = part.functionResponse;
|
|
57
|
-
let frTokens = (fr.name?.length ?? 0) / charsPerToken;
|
|
58
|
-
const response = fr.response;
|
|
59
|
-
if (typeof response === 'string') {
|
|
60
|
-
frTokens += response.length / charsPerToken;
|
|
61
|
-
}
|
|
62
|
-
else if (response !== undefined && response !== null) {
|
|
63
|
-
frTokens += JSON.stringify(response).length / charsPerToken;
|
|
64
|
-
}
|
|
65
|
-
totalTokens += frTokens;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
// Fallback: JSON-serialize the whole part and estimate by length.
|
|
69
|
-
totalTokens += JSON.stringify(part).length / charsPerToken;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return Math.floor(totalTokens);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Asynchronous token count calculation for a text string or message array.
|
|
76
|
-
* For text-only content, this simply delegates to `estimateTokenCountSync`.
|
|
77
|
-
* For content with media references (future: image/PDF), we would call
|
|
78
|
-
* an external tokenizer — but for now, everything is text-only estimation.
|
|
79
|
-
*
|
|
80
|
-
* This replaces gemini-cli's `calculateRequestTokenCount` which uses
|
|
81
|
-
* the Gemini `countTokens` API. We don't have an equivalent API for
|
|
82
|
-
* our internal OpenAI-compatible proxy, so we rely on heuristic estimation.
|
|
83
|
-
*/
|
|
84
|
-
async function calculateTokenCount(content, charsPerToken = exports.DEFAULT_CHARS_PER_TOKEN) {
|
|
85
|
-
if (typeof content === 'string') {
|
|
86
|
-
return estimateTokenCountSync([{ text: content }], charsPerToken);
|
|
87
|
-
}
|
|
88
|
-
return estimateTokenCountSync(content, charsPerToken);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Convenience: estimate token count for a single text string.
|
|
92
|
-
*/
|
|
93
|
-
function estimateTokenCountForText(text, charsPerToken = exports.DEFAULT_CHARS_PER_TOKEN) {
|
|
94
|
-
return Math.floor(estimateTextTokens(text, charsPerToken));
|
|
95
|
-
}
|