@x-code-cli/core 0.1.3 → 0.1.5
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/LICENSE +21 -0
- package/README.en.md +15 -0
- package/README.md +15 -0
- package/dist/agent/api-errors.d.ts +11 -0
- package/dist/agent/api-errors.d.ts.map +1 -0
- package/dist/agent/api-errors.js +134 -0
- package/dist/agent/api-errors.js.map +1 -0
- package/dist/agent/context-window.d.ts +26 -0
- package/dist/agent/context-window.d.ts.map +1 -0
- package/dist/agent/context-window.js +126 -0
- package/dist/agent/context-window.js.map +1 -0
- package/dist/agent/loop-state.d.ts +14 -0
- package/dist/agent/loop-state.d.ts.map +1 -0
- package/dist/agent/loop-state.js +12 -0
- package/dist/agent/loop-state.js.map +1 -0
- package/dist/agent/loop.d.ts +11 -15
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +213 -381
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/messages.d.ts +0 -2
- package/dist/agent/messages.d.ts.map +1 -1
- package/dist/agent/messages.js +0 -32
- package/dist/agent/messages.js.map +1 -1
- package/dist/agent/provider-compat.d.ts +17 -0
- package/dist/agent/provider-compat.d.ts.map +1 -0
- package/dist/agent/provider-compat.js +31 -0
- package/dist/agent/provider-compat.js.map +1 -0
- package/dist/agent/stream-utils.d.ts +33 -0
- package/dist/agent/stream-utils.d.ts.map +1 -0
- package/dist/agent/stream-utils.js +14 -0
- package/dist/agent/stream-utils.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +1 -3
- package/dist/agent/system-prompt.d.ts.map +1 -1
- package/dist/agent/system-prompt.js +34 -23
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/agent/tool-execution.d.ts +11 -0
- package/dist/agent/tool-execution.d.ts.map +1 -0
- package/dist/agent/tool-execution.js +171 -0
- package/dist/agent/tool-execution.js.map +1 -0
- package/dist/config/index.d.ts +19 -8
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +66 -32
- package/dist/config/index.js.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/knowledge/auto-memory.d.ts +1 -1
- package/dist/knowledge/auto-memory.d.ts.map +1 -1
- package/dist/knowledge/auto-memory.js +55 -16
- package/dist/knowledge/auto-memory.js.map +1 -1
- package/dist/knowledge/init.d.ts +1 -2
- package/dist/knowledge/init.d.ts.map +1 -1
- package/dist/knowledge/init.js +83 -69
- package/dist/knowledge/init.js.map +1 -1
- package/dist/knowledge/loader.d.ts +0 -9
- package/dist/knowledge/loader.d.ts.map +1 -1
- package/dist/knowledge/loader.js +54 -99
- package/dist/knowledge/loader.js.map +1 -1
- package/dist/knowledge/session.d.ts +1 -1
- package/dist/knowledge/session.d.ts.map +1 -1
- package/dist/knowledge/session.js +2 -1
- package/dist/knowledge/session.js.map +1 -1
- package/dist/permissions/index.d.ts +2 -0
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +35 -14
- package/dist/permissions/index.js.map +1 -1
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +3 -1
- package/dist/tools/glob.js.map +1 -1
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +7 -2
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/index.d.ts +3 -7
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list-dir.d.ts.map +1 -1
- package/dist/tools/list-dir.js +3 -1
- package/dist/tools/list-dir.js.map +1 -1
- package/dist/tools/progress.d.ts +6 -0
- package/dist/tools/progress.d.ts.map +1 -0
- package/dist/tools/progress.js +14 -0
- package/dist/tools/progress.js.map +1 -0
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +3 -1
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/save-knowledge.d.ts +2 -2
- package/dist/tools/save-knowledge.d.ts.map +1 -1
- package/dist/tools/save-knowledge.js +31 -6
- package/dist/tools/save-knowledge.js.map +1 -1
- package/dist/tools/shell-utils.d.ts.map +1 -1
- package/dist/tools/shell-utils.js +7 -0
- package/dist/tools/shell-utils.js.map +1 -1
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +88 -19
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +85 -12
- package/dist/tools/web-search.js.map +1 -1
- package/dist/types/index.d.ts +60 -21
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +64 -6
- package/dist/types/index.js.map +1 -1
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +32 -0
- package/dist/utils.js.map +1 -1
- package/package.json +6 -6
- package/dist/agent/plan-mode.d.ts +0 -11
- package/dist/agent/plan-mode.d.ts.map +0 -1
- package/dist/agent/plan-mode.js +0 -37
- package/dist/agent/plan-mode.js.map +0 -1
- package/dist/agent/pricing.d.ts +0 -9
- package/dist/agent/pricing.d.ts.map +0 -1
- package/dist/agent/pricing.js +0 -47
- package/dist/agent/pricing.js.map +0 -1
- package/dist/knowledge/hooks.d.ts +0 -3
- package/dist/knowledge/hooks.d.ts.map +0 -1
- package/dist/knowledge/hooks.js +0 -59
- package/dist/knowledge/hooks.js.map +0 -1
- package/dist/tools/enter-plan-mode.d.ts +0 -2
- package/dist/tools/enter-plan-mode.d.ts.map +0 -1
- package/dist/tools/enter-plan-mode.js +0 -11
- package/dist/tools/enter-plan-mode.js.map +0 -1
- package/dist/tools/exit-plan-mode.d.ts +0 -2
- package/dist/tools/exit-plan-mode.d.ts.map +0 -1
- package/dist/tools/exit-plan-mode.js +0 -9
- package/dist/tools/exit-plan-mode.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Guangzhi Tan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @x-code-cli/core
|
|
2
|
+
|
|
3
|
+
[简体中文](./README.md) · [English](./README.en.md)
|
|
4
|
+
|
|
5
|
+
Core AI engine powering [X-Code CLI](https://github.com/woai3c/x-code-cli).
|
|
6
|
+
|
|
7
|
+
This package is the headless runtime consumed by `@x-code-cli/cli` — agent loop, tools, provider registry, and permission system. It has **no UI dependencies** and can in principle be embedded in other tools.
|
|
8
|
+
|
|
9
|
+
> ⚠️ The public API is not yet stable — breaking changes may happen between minor versions. If you just want the CLI, install [`@x-code-cli/cli`](https://www.npmjs.com/package/@x-code-cli/cli) directly.
|
|
10
|
+
|
|
11
|
+
For full installation, API key setup, and usage, see the [main repo README](https://github.com/woai3c/x-code-cli).
|
|
12
|
+
|
|
13
|
+
## License
|
|
14
|
+
|
|
15
|
+
[MIT](https://github.com/woai3c/x-code-cli/blob/main/LICENSE)
|
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @x-code-cli/core
|
|
2
|
+
|
|
3
|
+
[简体中文](./README.md) · [English](./README.en.md)
|
|
4
|
+
|
|
5
|
+
[X-Code CLI](https://github.com/woai3c/x-code-cli) 的核心 AI 引擎。
|
|
6
|
+
|
|
7
|
+
本包是 `@x-code-cli/cli` 使用的无头(headless)运行时,包含 Agent 循环、工具、模型厂商适配、权限系统等逻辑,**不依赖任何 UI 框架**,理论上可以嵌入到其他工具中使用。
|
|
8
|
+
|
|
9
|
+
> ⚠️ 公共 API 尚未稳定,小版本之间可能会有破坏性变更。如果你只是想使用 CLI,请直接安装 [`@x-code-cli/cli`](https://www.npmjs.com/package/@x-code-cli/cli)。
|
|
10
|
+
|
|
11
|
+
完整的安装说明、API Key 配置、使用方式请看 [主仓库 README](https://github.com/woai3c/x-code-cli)。
|
|
12
|
+
|
|
13
|
+
## License
|
|
14
|
+
|
|
15
|
+
[MIT](https://github.com/woai3c/x-code-cli/blob/main/LICENSE)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Extract HTTP status from "status code 400", "(400)", or "400 ..." */
|
|
2
|
+
export declare function extractHttpStatus(msg: string): number;
|
|
3
|
+
/** True when an error message indicates the request exceeded the context window. */
|
|
4
|
+
export declare function isContextTooLongError(err: unknown): boolean;
|
|
5
|
+
export interface ClassifiedError {
|
|
6
|
+
message: string;
|
|
7
|
+
retryable: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Classify API error and return a user-friendly recovery message. */
|
|
10
|
+
export declare function classifyApiError(err: unknown): ClassifiedError;
|
|
11
|
+
//# sourceMappingURL=api-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-errors.d.ts","sourceRoot":"","sources":["../../src/agent/api-errors.ts"],"names":[],"mappings":"AAaA,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAM3D;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,OAAO,CAAA;CACnB;AAwBD,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAgG9D"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// @x-code-cli/core — API error classification & pattern detection
|
|
2
|
+
/** Substrings that signal the request exceeded the model's context window. */
|
|
3
|
+
const CONTEXT_TOO_LONG_PATTERNS = [
|
|
4
|
+
'maximum context length',
|
|
5
|
+
'context_length_exceeded',
|
|
6
|
+
'token limit',
|
|
7
|
+
'prompt is too long',
|
|
8
|
+
'prompt_too_long',
|
|
9
|
+
'input tokens',
|
|
10
|
+
'context window',
|
|
11
|
+
];
|
|
12
|
+
/** Extract HTTP status from "status code 400", "(400)", or "400 ..." */
|
|
13
|
+
export function extractHttpStatus(msg) {
|
|
14
|
+
const match = msg.match(/\bstatus(?:\s+code)?\s+(\d{3})\b/i) ?? msg.match(/\((\d{3})\)/) ?? msg.match(/^(\d{3})\s/);
|
|
15
|
+
return match ? Number(match[1]) : 0;
|
|
16
|
+
}
|
|
17
|
+
/** True when an error message indicates the request exceeded the context window. */
|
|
18
|
+
export function isContextTooLongError(err) {
|
|
19
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20
|
+
for (const pattern of CONTEXT_TOO_LONG_PATTERNS) {
|
|
21
|
+
if (msg.includes(pattern))
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Extract a meaningful error message from AI SDK errors. TypeValidationError
|
|
28
|
+
* (thrown when a provider returns non-standard JSON — e.g. Alibaba returning
|
|
29
|
+
* an error object instead of an SSE stream) embeds the real provider message
|
|
30
|
+
* inside its `.value` property. We dig it out so classifyApiError can pattern-
|
|
31
|
+
* match on the actual provider error, not the Zod validation wrapper.
|
|
32
|
+
*/
|
|
33
|
+
function extractErrorMessage(err) {
|
|
34
|
+
if (!(err instanceof Error))
|
|
35
|
+
return String(err);
|
|
36
|
+
const msg = err.message;
|
|
37
|
+
// AI SDK TypeValidationError: the real provider error lives in `.value`
|
|
38
|
+
const val = err.value;
|
|
39
|
+
if (val && typeof val === 'object') {
|
|
40
|
+
const inner = val.error;
|
|
41
|
+
if (inner && typeof inner === 'object') {
|
|
42
|
+
const innerMsg = inner.message;
|
|
43
|
+
if (typeof innerMsg === 'string')
|
|
44
|
+
return innerMsg;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return msg;
|
|
48
|
+
}
|
|
49
|
+
/** Classify API error and return a user-friendly recovery message. */
|
|
50
|
+
export function classifyApiError(err) {
|
|
51
|
+
const msg = extractErrorMessage(err);
|
|
52
|
+
const status = extractHttpStatus(msg);
|
|
53
|
+
if (isContextTooLongError(err)) {
|
|
54
|
+
return {
|
|
55
|
+
message: "Context too long — the conversation exceeded the model's token limit. Try /compact to compress context, or /clear to start fresh.",
|
|
56
|
+
retryable: false,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (msg.includes('Missing `reasoning_content`') || msg.includes('reasoning_content')) {
|
|
60
|
+
return {
|
|
61
|
+
message: 'DeepSeek Reasoner requires reasoning_content in assistant messages during tool-call chains. This is usually an SDK compatibility issue — please report it.',
|
|
62
|
+
retryable: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (msg.includes('API key is missing') || msg.includes('API_KEY')) {
|
|
66
|
+
const providerMatch = msg.match(/^(\w+)\s+API key/i);
|
|
67
|
+
const provider = providerMatch ? providerMatch[1] : 'Provider';
|
|
68
|
+
return {
|
|
69
|
+
message: `${provider} API key is not set. Please set the corresponding environment variable (e.g. ${provider.toUpperCase()}_API_KEY).`,
|
|
70
|
+
retryable: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (status === 401 || msg.includes('Unauthorized') || msg.includes('Invalid API Key')) {
|
|
74
|
+
return {
|
|
75
|
+
message: 'API authentication failed (401). Please check your API key with /model or reconfigure with `xc init`.',
|
|
76
|
+
retryable: false,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (status === 402 ||
|
|
80
|
+
msg.includes('Insufficient Balance') ||
|
|
81
|
+
msg.includes('insufficient_balance') ||
|
|
82
|
+
msg.includes('insufficient_quota') ||
|
|
83
|
+
msg.includes('exceeded your current quota')) {
|
|
84
|
+
return {
|
|
85
|
+
message: 'API account balance insufficient (402). Top up your provider account, or switch to a different provider with /model.',
|
|
86
|
+
retryable: false,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (status === 403 || msg.includes('Forbidden')) {
|
|
90
|
+
return {
|
|
91
|
+
message: 'API access forbidden (403). Your API key may not have permission for this model.',
|
|
92
|
+
retryable: false,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (msg.includes('Invalid max_tokens') ||
|
|
96
|
+
msg.includes('Range of max_tokens') ||
|
|
97
|
+
msg.includes('InvalidParameter') ||
|
|
98
|
+
(msg.includes('max_tokens') && (msg.includes('invalid') || msg.includes('Invalid') || msg.includes('range') || msg.includes('Range')))) {
|
|
99
|
+
return {
|
|
100
|
+
message: 'The configured max_tokens exceeds this model\'s limit. Try switching to a different model with /model, or report this issue so we can add the correct ceiling.',
|
|
101
|
+
retryable: false,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (status === 503 || msg.includes('Service Unavailable') || msg.includes('overloaded')) {
|
|
105
|
+
return {
|
|
106
|
+
message: 'Model service unavailable (503). Try switching to a different model with /model.',
|
|
107
|
+
retryable: false,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (status === 429 || msg.includes('rate limit') || msg.includes('Rate limit')) {
|
|
111
|
+
return {
|
|
112
|
+
message: 'Rate limited (429). Waiting for retry... (AI SDK handles exponential backoff automatically with maxRetries: 3)',
|
|
113
|
+
retryable: true,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (msg.includes('timeout') || msg.includes('ETIMEDOUT') || msg.includes('ECONNRESET')) {
|
|
117
|
+
return {
|
|
118
|
+
message: `Network error: ${msg}. Retrying...`,
|
|
119
|
+
retryable: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// AI SDK TypeValidationError — provider returned a non-standard response
|
|
123
|
+
// (e.g. an error JSON body instead of a valid SSE stream). Surface the
|
|
124
|
+
// provider's error message rather than the raw Zod validation dump.
|
|
125
|
+
if ((err instanceof Error && err.constructor.name === 'AI_TypeValidationError') ||
|
|
126
|
+
msg.includes('Type validation failed')) {
|
|
127
|
+
return {
|
|
128
|
+
message: `Provider returned an error: ${msg}. Try a different model with /model.`,
|
|
129
|
+
retryable: false,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { message: msg, retryable: false };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=api-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-errors.js","sourceRoot":"","sources":["../../src/agent/api-errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ModelMessage } from 'ai';
|
|
2
|
+
/**
|
|
3
|
+
* Compress context when usage exceeds this fraction of the model's context
|
|
4
|
+
* window. Two checks use this:
|
|
5
|
+
* 1. After each turn — based on the **real** input-token count reported by
|
|
6
|
+
* the API, which is the most reliable signal.
|
|
7
|
+
* 2. Before each API call — based on a **character-based estimate** as a
|
|
8
|
+
* safety net. Estimates drift (tool output, non-ASCII), so we use a
|
|
9
|
+
* conservative multiplier. The estimate catches cases where a single
|
|
10
|
+
* turn (e.g. reading a huge file) pushes context past the limit before
|
|
11
|
+
* the real count is available.
|
|
12
|
+
*/
|
|
13
|
+
export declare const COMPRESSION_TRIGGER_RATIO = 0.8;
|
|
14
|
+
/** Resolve context window (tokens) for a model id like `provider:model`. */
|
|
15
|
+
export declare function getContextWindow(modelId: string): number;
|
|
16
|
+
/** Token threshold above which we trigger compression for a given model. */
|
|
17
|
+
export declare function getCompressionThreshold(modelId: string): number;
|
|
18
|
+
/** Resolve the max_tokens ceiling we send to the provider. */
|
|
19
|
+
export declare function getMaxOutputTokens(modelId: string): number;
|
|
20
|
+
/**
|
|
21
|
+
* Estimate total token count from messages using character length.
|
|
22
|
+
* This is intentionally conservative (over-counting) to serve as a safety net
|
|
23
|
+
* that fires before the real API limit is hit.
|
|
24
|
+
*/
|
|
25
|
+
export declare function estimateTokenCount(messages: ModelMessage[]): number;
|
|
26
|
+
//# sourceMappingURL=context-window.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-window.d.ts","sourceRoot":"","sources":["../../src/agent/context-window.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAEtC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AA4D5C,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AA0BD,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAYnE"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compress context when usage exceeds this fraction of the model's context
|
|
3
|
+
* window. Two checks use this:
|
|
4
|
+
* 1. After each turn — based on the **real** input-token count reported by
|
|
5
|
+
* the API, which is the most reliable signal.
|
|
6
|
+
* 2. Before each API call — based on a **character-based estimate** as a
|
|
7
|
+
* safety net. Estimates drift (tool output, non-ASCII), so we use a
|
|
8
|
+
* conservative multiplier. The estimate catches cases where a single
|
|
9
|
+
* turn (e.g. reading a huge file) pushes context past the limit before
|
|
10
|
+
* the real count is available.
|
|
11
|
+
*/
|
|
12
|
+
export const COMPRESSION_TRIGGER_RATIO = 0.8;
|
|
13
|
+
/**
|
|
14
|
+
* Rough chars-per-token ratio for pre-call estimation. Most English text is
|
|
15
|
+
* ~4 chars/token; CJK and code can be lower. We use 3.0 (aggressive) so the
|
|
16
|
+
* estimate over-counts slightly, making the safety net trigger earlier.
|
|
17
|
+
*/
|
|
18
|
+
const CHARS_PER_TOKEN_ESTIMATE = 3.0;
|
|
19
|
+
/** Default context window when both model- and provider-level lookups miss. */
|
|
20
|
+
const DEFAULT_CONTEXT_WINDOW = 128000;
|
|
21
|
+
/** Context window sizes per model (tokens). */
|
|
22
|
+
const MODEL_CONTEXT_WINDOWS = new Map([
|
|
23
|
+
// Anthropic
|
|
24
|
+
['anthropic:claude-opus-4-7', 1000000],
|
|
25
|
+
['anthropic:claude-sonnet-4-6', 1000000],
|
|
26
|
+
['anthropic:claude-haiku-4-5', 200000],
|
|
27
|
+
// OpenAI
|
|
28
|
+
['openai:gpt-4.1', 1047576],
|
|
29
|
+
['openai:gpt-4.1-mini', 1047576],
|
|
30
|
+
['openai:gpt-4.1-nano', 1047576],
|
|
31
|
+
['openai:o3', 200000],
|
|
32
|
+
['openai:o4-mini', 200000],
|
|
33
|
+
// Google
|
|
34
|
+
['google:gemini-2.5-pro', 1000000],
|
|
35
|
+
['google:gemini-2.5-flash', 1000000],
|
|
36
|
+
// DeepSeek
|
|
37
|
+
['deepseek:deepseek-v4-flash', 1000000],
|
|
38
|
+
['deepseek:deepseek-v4-pro', 1000000],
|
|
39
|
+
// Alibaba — per DashScope docs: qwen-turbo and qwen3-coder-plus extend to 1M;
|
|
40
|
+
// qwen-max still caps at 32k (use qwen3-max for 256k). Values verified against
|
|
41
|
+
// https://help.aliyun.com/zh/model-studio/models.
|
|
42
|
+
['alibaba:qwen-turbo', 1000000],
|
|
43
|
+
['alibaba:qwen-plus', 131072],
|
|
44
|
+
['alibaba:qwen-max', 32768],
|
|
45
|
+
['alibaba:qwen3-max', 262144],
|
|
46
|
+
['alibaba:qwen3-coder-plus', 1000000],
|
|
47
|
+
['alibaba:qwq-plus', 131072],
|
|
48
|
+
// xAI
|
|
49
|
+
['xai:grok-3', 131072],
|
|
50
|
+
['xai:grok-3-mini', 131072],
|
|
51
|
+
// Zhipu
|
|
52
|
+
['zhipu:glm-4-plus', 128000],
|
|
53
|
+
// Moonshot
|
|
54
|
+
['moonshotai:kimi-k2.5', 131072],
|
|
55
|
+
]);
|
|
56
|
+
/** Provider-level fallback context windows. */
|
|
57
|
+
const PROVIDER_CONTEXT_WINDOWS = new Map([
|
|
58
|
+
['anthropic', 1000000],
|
|
59
|
+
['openai', 128000],
|
|
60
|
+
['google', 1000000],
|
|
61
|
+
['deepseek', 1000000],
|
|
62
|
+
['alibaba', 128000],
|
|
63
|
+
['xai', 128000],
|
|
64
|
+
['zhipu', 128000],
|
|
65
|
+
['moonshotai', 128000],
|
|
66
|
+
]);
|
|
67
|
+
/** Resolve context window (tokens) for a model id like `provider:model`. */
|
|
68
|
+
export function getContextWindow(modelId) {
|
|
69
|
+
const exact = MODEL_CONTEXT_WINDOWS.get(modelId);
|
|
70
|
+
if (exact !== undefined)
|
|
71
|
+
return exact;
|
|
72
|
+
const provider = modelId.split(':')[0];
|
|
73
|
+
return PROVIDER_CONTEXT_WINDOWS.get(provider) ?? DEFAULT_CONTEXT_WINDOW;
|
|
74
|
+
}
|
|
75
|
+
/** Token threshold above which we trigger compression for a given model. */
|
|
76
|
+
export function getCompressionThreshold(modelId) {
|
|
77
|
+
return Math.floor(getContextWindow(modelId) * COMPRESSION_TRIGGER_RATIO);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Per-model cap on max_tokens (reply size). Some providers reject requests
|
|
81
|
+
* that exceed their ceiling rather than clamping silently.
|
|
82
|
+
* For models without an explicit entry, we fall back to a high default that
|
|
83
|
+
* the AI SDK will clamp for known providers.
|
|
84
|
+
*/
|
|
85
|
+
const DEFAULT_MAX_OUTPUT_TOKENS = 16384;
|
|
86
|
+
const MODEL_MAX_OUTPUT_TOKENS = new Map([
|
|
87
|
+
// DeepSeek V4: both flash and pro advertise up to 384K output tokens.
|
|
88
|
+
// We cap at a generous but conservative 131072 to avoid edge-case 400s.
|
|
89
|
+
['deepseek:deepseek-v4-flash', 131072],
|
|
90
|
+
['deepseek:deepseek-v4-pro', 131072],
|
|
91
|
+
// Alibaba — qwen-turbo rejects anything above 16384; other Qwen3 models
|
|
92
|
+
// support 32768 (non-thinking) / 81920 (thinking mode). We cap at the
|
|
93
|
+
// non-thinking ceiling so the request always succeeds. qwen-max only has a
|
|
94
|
+
// 32k context window, so we keep its output ceiling well below that.
|
|
95
|
+
['alibaba:qwen-turbo', 16384],
|
|
96
|
+
['alibaba:qwen-plus', 32000],
|
|
97
|
+
['alibaba:qwen-max', 8192],
|
|
98
|
+
['alibaba:qwen3-max', 32000],
|
|
99
|
+
['alibaba:qwen3-coder-plus', 32000],
|
|
100
|
+
['alibaba:qwq-plus', 32000],
|
|
101
|
+
]);
|
|
102
|
+
/** Resolve the max_tokens ceiling we send to the provider. */
|
|
103
|
+
export function getMaxOutputTokens(modelId) {
|
|
104
|
+
return MODEL_MAX_OUTPUT_TOKENS.get(modelId) ?? DEFAULT_MAX_OUTPUT_TOKENS;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Estimate total token count from messages using character length.
|
|
108
|
+
* This is intentionally conservative (over-counting) to serve as a safety net
|
|
109
|
+
* that fires before the real API limit is hit.
|
|
110
|
+
*/
|
|
111
|
+
export function estimateTokenCount(messages) {
|
|
112
|
+
let chars = 0;
|
|
113
|
+
for (const msg of messages) {
|
|
114
|
+
if (typeof msg.content === 'string') {
|
|
115
|
+
chars += msg.content.length;
|
|
116
|
+
}
|
|
117
|
+
else if (Array.isArray(msg.content)) {
|
|
118
|
+
for (const part of msg.content) {
|
|
119
|
+
if (typeof part.text === 'string')
|
|
120
|
+
chars += part.text.length;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return Math.ceil(chars / CHARS_PER_TOKEN_ESTIMATE);
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=context-window.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-window.js","sourceRoot":"","sources":["../../src/agent/context-window.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ModelMessage } from 'ai';
|
|
2
|
+
import type { TokenUsage } from '../types/index.js';
|
|
3
|
+
export interface LoopState {
|
|
4
|
+
messages: ModelMessage[];
|
|
5
|
+
tokenUsage: TokenUsage;
|
|
6
|
+
/** Real input-token count from the most recent API response, used to trigger compression. */
|
|
7
|
+
lastInputTokens: number;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
startedAt: string;
|
|
10
|
+
filesModified: Set<string>;
|
|
11
|
+
turnCount: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function createLoopState(): LoopState;
|
|
14
|
+
//# sourceMappingURL=loop-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop-state.d.ts","sourceRoot":"","sources":["../../src/agent/loop-state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,6FAA6F;IAC7F,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,eAAe,IAAI,SAAS,CAU3C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function createLoopState() {
|
|
2
|
+
return {
|
|
3
|
+
messages: [],
|
|
4
|
+
tokenUsage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
5
|
+
lastInputTokens: 0,
|
|
6
|
+
sessionId: Date.now().toString(36),
|
|
7
|
+
startedAt: new Date().toISOString(),
|
|
8
|
+
filesModified: new Set(),
|
|
9
|
+
turnCount: 0,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=loop-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop-state.js","sourceRoot":"","sources":["../../src/agent/loop-state.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE;QAC/D,eAAe,EAAE,CAAC;QAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,aAAa,EAAE,IAAI,GAAG,EAAE;QACxB,SAAS,EAAE,CAAC;KACb,CAAA;AACH,CAAC"}
|
package/dist/agent/loop.d.ts
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import type { LanguageModel, ModelMessage } from 'ai';
|
|
2
|
-
import type { AgentCallbacks, AgentOptions
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
planMode: boolean;
|
|
7
|
-
planId: string | null;
|
|
8
|
-
sessionId: string;
|
|
9
|
-
startedAt: string;
|
|
10
|
-
filesModified: Set<string>;
|
|
11
|
-
turnCount: number;
|
|
12
|
-
}
|
|
13
|
-
/** Compress old messages into a summary */
|
|
2
|
+
import type { AgentCallbacks, AgentOptions } from '../types/index.js';
|
|
3
|
+
import type { LoopState } from './loop-state.js';
|
|
4
|
+
export type { LoopState } from './loop-state.js';
|
|
5
|
+
/** Compress old messages into a summary. */
|
|
14
6
|
export declare function compressMessages(messages: ModelMessage[], model: LanguageModel): Promise<ModelMessage[]>;
|
|
15
|
-
/** Main agent loop */
|
|
7
|
+
/** Main agent loop. */
|
|
16
8
|
export declare function agentLoop(userMessage: string, model: LanguageModel, options: AgentOptions, callbacks: AgentCallbacks, existingState?: LoopState): Promise<LoopState>;
|
|
17
|
-
/** Save session on exit
|
|
18
|
-
|
|
9
|
+
/** Save session on exit. Summary generation makes an LLM call that can be
|
|
10
|
+
* slow, so we bound it with a 2s timeout — on Ctrl+C we want to return
|
|
11
|
+
* to the shell promptly, not wait for a roundtrip. If the timeout fires
|
|
12
|
+
* or the call fails, we silently skip (session summaries are nice-to-have,
|
|
13
|
+
* not critical for exit). */
|
|
14
|
+
export declare function saveSession(state: LoopState, model: LanguageModel, timeoutMs?: number): Promise<void>;
|
|
19
15
|
//# sourceMappingURL=loop.d.ts.map
|
package/dist/agent/loop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAMrD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAKrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAOhD,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAKhD,4CAA4C;AAC5C,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAc9G;AAmLD,uBAAuB;AACvB,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,cAAc,EACzB,aAAa,CAAC,EAAE,SAAS,GACxB,OAAO,CAAC,SAAS,CAAC,CAkGpB;AAED;;;;8BAI8B;AAC9B,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzG"}
|