@vybestack/llxprt-code-core 0.1.23-nightly.250829.6bacfcba → 0.1.23-nightly.250903.97906524
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 +2 -2
- package/dist/src/code_assist/codeAssist.js +17 -6
- package/dist/src/code_assist/codeAssist.js.map +1 -1
- package/dist/src/code_assist/server.js +15 -4
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/setup.js +7 -0
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/core/ContentGeneratorAdapter.d.ts +37 -0
- package/dist/src/core/ContentGeneratorAdapter.js +58 -0
- package/dist/src/core/ContentGeneratorAdapter.js.map +1 -0
- package/dist/src/core/client.d.ts +9 -2
- package/dist/src/core/client.js +111 -36
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/compression-config.d.ts +10 -0
- package/dist/src/core/compression-config.js +18 -0
- package/dist/src/core/compression-config.js.map +1 -0
- package/dist/src/core/geminiChat.d.ts +8 -2
- package/dist/src/core/geminiChat.js +148 -32
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/prompts.js +4 -2
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/providers/BaseProvider.d.ts +1 -1
- package/dist/src/providers/BaseProvider.js.map +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.js +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -1
- package/dist/src/providers/gemini/GeminiProvider.js +100 -36
- package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.d.ts +54 -25
- package/dist/src/providers/openai/OpenAIProvider.js +528 -984
- package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
- package/dist/src/providers/openai-responses/OpenAIResponsesProvider.d.ts +91 -0
- package/dist/src/providers/openai-responses/OpenAIResponsesProvider.js +440 -0
- package/dist/src/providers/openai-responses/OpenAIResponsesProvider.js.map +1 -0
- package/dist/src/providers/openai-responses/index.d.ts +1 -0
- package/dist/src/providers/openai-responses/index.js +2 -0
- package/dist/src/providers/openai-responses/index.js.map +1 -0
- package/dist/src/services/history/ContentConverters.d.ts +38 -0
- package/dist/src/services/history/ContentConverters.js +188 -0
- package/dist/src/services/history/ContentConverters.js.map +1 -0
- package/dist/src/services/history/HistoryEvents.d.ts +32 -0
- package/dist/src/services/history/HistoryEvents.js +17 -0
- package/dist/src/services/history/HistoryEvents.js.map +1 -0
- package/dist/src/services/history/HistoryService.d.ts +168 -0
- package/dist/src/services/history/HistoryService.js +521 -0
- package/dist/src/services/history/HistoryService.js.map +1 -0
- package/dist/src/services/history/IContent.d.ts +179 -0
- package/dist/src/services/history/IContent.js +104 -0
- package/dist/src/services/history/IContent.js.map +1 -0
- package/package.json +1 -1
@@ -0,0 +1,188 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2025 Vybestack LLC
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
/**
|
17
|
+
* Converts between Gemini Content format and IContent format
|
18
|
+
*/
|
19
|
+
export class ContentConverters {
|
20
|
+
/**
|
21
|
+
* Convert IContent to Gemini Content format
|
22
|
+
*/
|
23
|
+
static toGeminiContent(iContent) {
|
24
|
+
// Tool responses should have 'user' role in Gemini format
|
25
|
+
let role;
|
26
|
+
if (iContent.speaker === 'tool') {
|
27
|
+
role = 'user';
|
28
|
+
}
|
29
|
+
else if (iContent.speaker === 'human') {
|
30
|
+
role = 'user';
|
31
|
+
}
|
32
|
+
else {
|
33
|
+
role = 'model';
|
34
|
+
}
|
35
|
+
const parts = [];
|
36
|
+
for (const block of iContent.blocks) {
|
37
|
+
switch (block.type) {
|
38
|
+
case 'text': {
|
39
|
+
const textBlock = block;
|
40
|
+
parts.push({ text: textBlock.text });
|
41
|
+
break;
|
42
|
+
}
|
43
|
+
case 'tool_call': {
|
44
|
+
const toolCall = block;
|
45
|
+
parts.push({
|
46
|
+
functionCall: {
|
47
|
+
name: toolCall.name,
|
48
|
+
args: toolCall.parameters,
|
49
|
+
id: toolCall.id,
|
50
|
+
},
|
51
|
+
});
|
52
|
+
break;
|
53
|
+
}
|
54
|
+
case 'tool_response': {
|
55
|
+
const toolResponse = block;
|
56
|
+
parts.push({
|
57
|
+
functionResponse: {
|
58
|
+
name: toolResponse.toolName,
|
59
|
+
response: toolResponse.result,
|
60
|
+
id: toolResponse.callId,
|
61
|
+
},
|
62
|
+
});
|
63
|
+
break;
|
64
|
+
}
|
65
|
+
case 'thinking': {
|
66
|
+
const thinkingBlock = block;
|
67
|
+
parts.push({
|
68
|
+
thought: true,
|
69
|
+
text: thinkingBlock.thought,
|
70
|
+
});
|
71
|
+
break;
|
72
|
+
}
|
73
|
+
case 'media': {
|
74
|
+
// Media blocks can be converted to inline data parts
|
75
|
+
// For now, we'll skip these as GeminiChat doesn't handle them yet
|
76
|
+
break;
|
77
|
+
}
|
78
|
+
case 'code': {
|
79
|
+
// Code blocks are treated as text in Gemini format
|
80
|
+
const codeBlock = block;
|
81
|
+
const codeText = codeBlock.language
|
82
|
+
? `\`\`\`${codeBlock.language}\n${codeBlock.code}\n\`\`\``
|
83
|
+
: codeBlock.code;
|
84
|
+
parts.push({ text: codeText });
|
85
|
+
break;
|
86
|
+
}
|
87
|
+
default:
|
88
|
+
// Ignore unknown block types
|
89
|
+
break;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
// Keep empty parts array for empty model responses
|
93
|
+
// This is valid in Gemini Content format
|
94
|
+
return { role, parts };
|
95
|
+
}
|
96
|
+
/**
|
97
|
+
* Convert Gemini Content to IContent format
|
98
|
+
*/
|
99
|
+
static toIContent(content) {
|
100
|
+
const speaker = content.role === 'user' ? 'human' : 'ai';
|
101
|
+
const blocks = [];
|
102
|
+
// Handle empty parts array explicitly
|
103
|
+
if (!content.parts || content.parts.length === 0) {
|
104
|
+
// Empty content - keep it empty
|
105
|
+
// This represents an empty model response
|
106
|
+
}
|
107
|
+
else if (content.parts) {
|
108
|
+
for (const part of content.parts) {
|
109
|
+
if ('text' in part && part.text !== undefined) {
|
110
|
+
// Check if this is a thinking block
|
111
|
+
if ('thought' in part && part.thought) {
|
112
|
+
blocks.push({
|
113
|
+
type: 'thinking',
|
114
|
+
thought: part.text,
|
115
|
+
isHidden: true,
|
116
|
+
});
|
117
|
+
}
|
118
|
+
else {
|
119
|
+
blocks.push({
|
120
|
+
type: 'text',
|
121
|
+
text: part.text,
|
122
|
+
});
|
123
|
+
}
|
124
|
+
}
|
125
|
+
else if ('functionCall' in part && part.functionCall) {
|
126
|
+
blocks.push({
|
127
|
+
type: 'tool_call',
|
128
|
+
id: part.functionCall.id || generateId(),
|
129
|
+
name: part.functionCall.name || '',
|
130
|
+
parameters: part.functionCall.args || {},
|
131
|
+
});
|
132
|
+
}
|
133
|
+
else if ('functionResponse' in part && part.functionResponse) {
|
134
|
+
blocks.push({
|
135
|
+
type: 'tool_response',
|
136
|
+
callId: part.functionResponse.id || '',
|
137
|
+
toolName: part.functionResponse.name || '',
|
138
|
+
result: part.functionResponse.response || {},
|
139
|
+
});
|
140
|
+
}
|
141
|
+
else if ('inlineData' in part && part.inlineData) {
|
142
|
+
// Handle inline data (media)
|
143
|
+
blocks.push({
|
144
|
+
type: 'media',
|
145
|
+
mimeType: part.inlineData.mimeType || '',
|
146
|
+
data: part.inlineData.data || '',
|
147
|
+
encoding: 'base64',
|
148
|
+
});
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
// Handle tool responses specially - they should have 'tool' speaker
|
153
|
+
// Tool responses come from user role but are tool speaker in IContent
|
154
|
+
if (content.role === 'user' &&
|
155
|
+
blocks.length > 0 &&
|
156
|
+
blocks.every((b) => b.type === 'tool_response')) {
|
157
|
+
return {
|
158
|
+
speaker: 'tool',
|
159
|
+
blocks,
|
160
|
+
metadata: {},
|
161
|
+
};
|
162
|
+
}
|
163
|
+
return {
|
164
|
+
speaker,
|
165
|
+
blocks,
|
166
|
+
metadata: {},
|
167
|
+
};
|
168
|
+
}
|
169
|
+
/**
|
170
|
+
* Convert array of IContent to array of Gemini Content
|
171
|
+
*/
|
172
|
+
static toGeminiContents(iContents) {
|
173
|
+
return iContents.map((ic) => this.toGeminiContent(ic));
|
174
|
+
}
|
175
|
+
/**
|
176
|
+
* Convert array of Gemini Content to array of IContent
|
177
|
+
*/
|
178
|
+
static toIContents(contents) {
|
179
|
+
return contents.map((c) => this.toIContent(c));
|
180
|
+
}
|
181
|
+
}
|
182
|
+
/**
|
183
|
+
* Generate a unique ID for tool calls
|
184
|
+
*/
|
185
|
+
function generateId() {
|
186
|
+
return `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
187
|
+
}
|
188
|
+
//# sourceMappingURL=ContentConverters.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ContentConverters.js","sourceRoot":"","sources":["../../../../src/services/history/ContentConverters.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2025 Vybestack LLC
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
/**
|
17
|
+
* Event data emitted when token count is updated
|
18
|
+
*/
|
19
|
+
export interface TokensUpdatedEvent {
|
20
|
+
/** The new total token count */
|
21
|
+
totalTokens: number;
|
22
|
+
/** Number of tokens added (positive) or removed (negative) */
|
23
|
+
addedTokens: number;
|
24
|
+
/** ID of the content that triggered the update, if applicable */
|
25
|
+
contentId?: string | null;
|
26
|
+
}
|
27
|
+
/**
|
28
|
+
* All possible history service events
|
29
|
+
*/
|
30
|
+
export interface HistoryServiceEvents {
|
31
|
+
tokensUpdated: (event: TokensUpdatedEvent) => void;
|
32
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2025 Vybestack LLC
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
export {};
|
17
|
+
//# sourceMappingURL=HistoryEvents.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"HistoryEvents.js","sourceRoot":"","sources":["../../../../src/services/history/HistoryEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
@@ -0,0 +1,168 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2025 Vybestack LLC
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
import { IContent, ToolCallBlock } from './IContent.js';
|
17
|
+
import { EventEmitter } from 'events';
|
18
|
+
import { TokensUpdatedEvent } from './HistoryEvents.js';
|
19
|
+
/**
|
20
|
+
* Typed EventEmitter for HistoryService events
|
21
|
+
*/
|
22
|
+
interface HistoryServiceEventEmitter {
|
23
|
+
on(event: 'tokensUpdated', listener: (eventData: TokensUpdatedEvent) => void): this;
|
24
|
+
emit(event: 'tokensUpdated', eventData: TokensUpdatedEvent): boolean;
|
25
|
+
off(event: 'tokensUpdated', listener: (eventData: TokensUpdatedEvent) => void): this;
|
26
|
+
}
|
27
|
+
/**
|
28
|
+
* Service for managing conversation history in a provider-agnostic way.
|
29
|
+
* All history is stored as IContent. Providers are responsible for converting
|
30
|
+
* to/from their own formats.
|
31
|
+
*/
|
32
|
+
export declare class HistoryService extends EventEmitter implements HistoryServiceEventEmitter {
|
33
|
+
private history;
|
34
|
+
private totalTokens;
|
35
|
+
private tokenizerCache;
|
36
|
+
private tokenizerLock;
|
37
|
+
/**
|
38
|
+
* Get or create tokenizer for a specific model
|
39
|
+
*/
|
40
|
+
private getTokenizerForModel;
|
41
|
+
/**
|
42
|
+
* Get the current total token count
|
43
|
+
*/
|
44
|
+
getTotalTokens(): number;
|
45
|
+
/**
|
46
|
+
* Add content to the history
|
47
|
+
* Note: We accept all content including empty responses for comprehensive history.
|
48
|
+
* Filtering happens only when getting curated history.
|
49
|
+
*/
|
50
|
+
add(content: IContent, modelName?: string): void;
|
51
|
+
/**
|
52
|
+
* Atomically update token count for new content
|
53
|
+
*/
|
54
|
+
private updateTokenCount;
|
55
|
+
/**
|
56
|
+
* Estimate token count for content using tokenizer
|
57
|
+
*/
|
58
|
+
private estimateContentTokens;
|
59
|
+
/**
|
60
|
+
* Simple token estimation for text
|
61
|
+
*/
|
62
|
+
private simpleTokenEstimateForText;
|
63
|
+
/**
|
64
|
+
* Add multiple contents to the history
|
65
|
+
*/
|
66
|
+
addAll(contents: IContent[], modelName?: string): void;
|
67
|
+
/**
|
68
|
+
* Get all history
|
69
|
+
*/
|
70
|
+
getAll(): IContent[];
|
71
|
+
/**
|
72
|
+
* Clear all history
|
73
|
+
*/
|
74
|
+
clear(): void;
|
75
|
+
/**
|
76
|
+
* Get the last N messages from history
|
77
|
+
*/
|
78
|
+
getRecent(count: number): IContent[];
|
79
|
+
/**
|
80
|
+
* Get curated history (only valid, meaningful content)
|
81
|
+
* Matches the behavior of extractCuratedHistory in geminiChat.ts:
|
82
|
+
* - Always includes user/human messages
|
83
|
+
* - Always includes tool messages
|
84
|
+
* - Only includes AI messages if they are valid (have content)
|
85
|
+
*/
|
86
|
+
getCurated(): IContent[];
|
87
|
+
/**
|
88
|
+
* Get comprehensive history (all content including invalid/empty)
|
89
|
+
*/
|
90
|
+
getComprehensive(): IContent[];
|
91
|
+
/**
|
92
|
+
* Remove the last content if it matches the provided content
|
93
|
+
*/
|
94
|
+
removeLastIfMatches(content: IContent): boolean;
|
95
|
+
/**
|
96
|
+
* Pop the last content from history
|
97
|
+
*/
|
98
|
+
pop(): IContent | undefined;
|
99
|
+
/**
|
100
|
+
* Recalculate total tokens from scratch
|
101
|
+
* Use this when removing content or when token counts might be stale
|
102
|
+
*/
|
103
|
+
recalculateTokens(defaultModel?: string): Promise<void>;
|
104
|
+
/**
|
105
|
+
* Get the last user (human) content
|
106
|
+
*/
|
107
|
+
getLastUserContent(): IContent | undefined;
|
108
|
+
/**
|
109
|
+
* Get the last AI content
|
110
|
+
*/
|
111
|
+
getLastAIContent(): IContent | undefined;
|
112
|
+
/**
|
113
|
+
* Record a complete turn (user input + AI response + optional tool interactions)
|
114
|
+
*/
|
115
|
+
recordTurn(userInput: IContent, aiResponse: IContent, toolInteractions?: IContent[]): void;
|
116
|
+
/**
|
117
|
+
* Get the number of messages in history
|
118
|
+
*/
|
119
|
+
length(): number;
|
120
|
+
/**
|
121
|
+
* Check if history is empty
|
122
|
+
*/
|
123
|
+
isEmpty(): boolean;
|
124
|
+
/**
|
125
|
+
* Clone the history (deep copy)
|
126
|
+
*/
|
127
|
+
clone(): IContent[];
|
128
|
+
/**
|
129
|
+
* Find unmatched tool calls (tool calls without responses)
|
130
|
+
*/
|
131
|
+
findUnmatchedToolCalls(): ToolCallBlock[];
|
132
|
+
/**
|
133
|
+
* Validate and fix the history to ensure proper tool call/response pairing
|
134
|
+
*/
|
135
|
+
validateAndFix(): void;
|
136
|
+
/**
|
137
|
+
* Merge two histories, handling duplicates and conflicts
|
138
|
+
*/
|
139
|
+
merge(other: HistoryService): void;
|
140
|
+
/**
|
141
|
+
* Get history within a token limit (for context window management)
|
142
|
+
*/
|
143
|
+
getWithinTokenLimit(maxTokens: number, countTokensFn: (content: IContent) => number): IContent[];
|
144
|
+
/**
|
145
|
+
* Summarize older history to fit within token limits
|
146
|
+
*/
|
147
|
+
summarizeOldHistory(keepRecentCount: number, summarizeFn: (contents: IContent[]) => Promise<IContent>): Promise<void>;
|
148
|
+
/**
|
149
|
+
* Export history to JSON
|
150
|
+
*/
|
151
|
+
toJSON(): string;
|
152
|
+
/**
|
153
|
+
* Import history from JSON
|
154
|
+
*/
|
155
|
+
static fromJSON(json: string): HistoryService;
|
156
|
+
/**
|
157
|
+
* Get conversation statistics
|
158
|
+
*/
|
159
|
+
getStatistics(): {
|
160
|
+
totalMessages: number;
|
161
|
+
userMessages: number;
|
162
|
+
aiMessages: number;
|
163
|
+
toolCalls: number;
|
164
|
+
toolResponses: number;
|
165
|
+
totalTokens?: number;
|
166
|
+
};
|
167
|
+
}
|
168
|
+
export {};
|