@vybestack/llxprt-code-core 0.1.23-nightly.250828.9dff311e → 0.1.23-nightly.250902.c3d3686d
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 +0 -15
- 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
package/README.md
CHANGED
@@ -47,21 +47,6 @@ You have two options to install LLxprt Code.
|
|
47
47
|
npx https://github.com/acoliver/llxprt-code
|
48
48
|
```
|
49
49
|
|
50
|
-
### With Homebrew
|
51
|
-
|
52
|
-
1. **Prerequisites:** Ensure you have [Homebrew](https://brew.sh/) installed.
|
53
|
-
2. **Install the CLI:** Execute the following command in your terminal:
|
54
|
-
|
55
|
-
```bash
|
56
|
-
brew install llxprt-code
|
57
|
-
```
|
58
|
-
|
59
|
-
Then, run the CLI from anywhere:
|
60
|
-
|
61
|
-
```bash
|
62
|
-
llxprt
|
63
|
-
```
|
64
|
-
|
65
50
|
### Common Configuration Steps
|
66
51
|
|
67
52
|
3. **Run and configure:**
|
@@ -9,14 +9,25 @@ import { setupUser } from './setup.js';
|
|
9
9
|
import { CodeAssistServer } from './server.js';
|
10
10
|
export async function createCodeAssistContentGenerator(httpOptions, authType, config, baseURL, // Add baseURL parameter
|
11
11
|
_sessionId) {
|
12
|
+
console.log(`createCodeAssistContentGenerator: authType=${authType}, config=${!!config}, baseURL=${baseURL}`);
|
12
13
|
if (authType === AuthType.LOGIN_WITH_GOOGLE ||
|
13
14
|
authType === AuthType.CLOUD_SHELL) {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
try {
|
16
|
+
console.log(`createCodeAssistContentGenerator: calling getOauthClient for authType ${authType}`);
|
17
|
+
const authClient = await getOauthClient(authType, config);
|
18
|
+
console.log(`createCodeAssistContentGenerator: OAuth client created, calling setupUser`);
|
19
|
+
const userData = await setupUser(authClient);
|
20
|
+
console.log(`createCodeAssistContentGenerator: setupUser completed, projectId=${userData.projectId}, userTier=${userData.userTier}`);
|
21
|
+
return new CodeAssistServer(authClient, userData.projectId, httpOptions,
|
22
|
+
// PRIVACY FIX: sessionId removed to prevent transmission to Google servers
|
23
|
+
// sessionId, // removed
|
24
|
+
userData.userTier, baseURL);
|
25
|
+
}
|
26
|
+
catch (error) {
|
27
|
+
console.log(`createCodeAssistContentGenerator: ERROR during OAuth setup: ${error}`);
|
28
|
+
console.log(`createCodeAssistContentGenerator: Error details:`, error);
|
29
|
+
throw error;
|
30
|
+
}
|
20
31
|
}
|
21
32
|
throw new Error(`Unsupported authType: ${authType}`);
|
22
33
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"codeAssist.js","sourceRoot":"","sources":["../../../src/code_assist/codeAssist.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAoB,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAe,MAAM,aAAa,CAAC;AAG5D,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,WAAwB,EACxB,QAAkB,EAClB,MAAc,EACd,OAAgB,EAAE,wBAAwB;AAC1C,UAAmB;IAEnB,IACE,QAAQ,KAAK,QAAQ,CAAC,iBAAiB;QACvC,QAAQ,KAAK,QAAQ,CAAC,WAAW,EACjC,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;
|
1
|
+
{"version":3,"file":"codeAssist.js","sourceRoot":"","sources":["../../../src/code_assist/codeAssist.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAoB,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAe,MAAM,aAAa,CAAC;AAG5D,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,WAAwB,EACxB,QAAkB,EAClB,MAAc,EACd,OAAgB,EAAE,wBAAwB;AAC1C,UAAmB;IAEnB,OAAO,CAAC,GAAG,CACT,8CAA8C,QAAQ,YAAY,CAAC,CAAC,MAAM,aAAa,OAAO,EAAE,CACjG,CAAC;IAEF,IACE,QAAQ,KAAK,QAAQ,CAAC,iBAAiB;QACvC,QAAQ,KAAK,QAAQ,CAAC,WAAW,EACjC,CAAC;QACD,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CACT,yEAAyE,QAAQ,EAAE,CACpF,CAAC;YACF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CACT,2EAA2E,CAC5E,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;YAC7C,OAAO,CAAC,GAAG,CACT,oEAAoE,QAAQ,CAAC,SAAS,cAAc,QAAQ,CAAC,QAAQ,EAAE,CACxH,CAAC;YACF,OAAO,IAAI,gBAAgB,CACzB,UAAU,EACV,QAAQ,CAAC,SAAS,EAClB,WAAW;YACX,2EAA2E;YAC3E,wBAAwB;YACxB,QAAQ,CAAC,QAAQ,EACjB,OAAO,CACR,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CACT,+DAA+D,KAAK,EAAE,CACvE,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,kDAAkD,EAAE,KAAK,CAAC,CAAC;YACvE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;AACvD,CAAC"}
|
@@ -35,10 +35,21 @@ export class CodeAssistServer {
|
|
35
35
|
})();
|
36
36
|
}
|
37
37
|
async generateContent(req, userPromptId) {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
console.log(`CodeAssistServer.generateContent: userPromptId=${userPromptId}, model=${req.model}, projectId=${this.projectId}`);
|
39
|
+
console.log(`CodeAssistServer.generateContent: request contents:`, req.contents);
|
40
|
+
console.log(`CodeAssistServer.generateContent: request config:`, req.config);
|
41
|
+
try {
|
42
|
+
const resp = await this.requestPost('generateContent',
|
43
|
+
// PRIVACY FIX: sessionId removed from request to prevent transmission to Google servers
|
44
|
+
toGenerateContentRequest(req, userPromptId, this.projectId), req.config?.abortSignal);
|
45
|
+
console.log(`CodeAssistServer.generateContent: request successful`);
|
46
|
+
return fromGenerateContentResponse(resp);
|
47
|
+
}
|
48
|
+
catch (error) {
|
49
|
+
console.log(`CodeAssistServer.generateContent: ERROR during request: ${error}`);
|
50
|
+
console.log(`CodeAssistServer.generateContent: Error details:`, error);
|
51
|
+
throw error;
|
52
|
+
}
|
42
53
|
}
|
43
54
|
async onboardUser(req) {
|
44
55
|
return await this.requestPost('onboardUser', req);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/code_assist/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,OAAO,EAGL,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAQxB,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AAC1E,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAC;AAEpD,MAAM,OAAO,gBAAgB;IAEhB;IACA;IACA;IAGA;IACA;IAPX,YACW,MAAoB,EACpB,SAAkB,EAClB,cAA2B,EAAE;IACtC,iFAAiF;IACjF,+BAA+B;IACtB,QAAqB,EACrB,OAAgB;QANhB,WAAM,GAAN,MAAM,CAAc;QACpB,cAAS,GAAT,SAAS,CAAS;QAClB,gBAAW,GAAX,WAAW,CAAkB;QAG7B,aAAQ,GAAR,QAAQ,CAAa;QACrB,YAAO,GAAP,OAAO,CAAS;IACxB,CAAC;IAEJ,KAAK,CAAC,qBAAqB,CACzB,GAA8B,EAC9B,YAAoB;QAEpB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAC3C,uBAAuB;QACvB,wFAAwF;QACxF,wBAAwB,CACtB,GAAG,EACH,YAAY,EACZ,IAAI,CAAC,SAAS,CAEf,EACD,GAAG,CAAC,MAAM,EAAE,WAAW,CACxB,CAAC;QACF,OAAO,CAAC,KAAK,SAAS,CAAC;YACrB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC/B,MAAM,2BAA2B,CAAC,IAAI,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,GAA8B,EAC9B,YAAoB;QAEpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CACjC,iBAAiB;
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/code_assist/server.ts"],"names":[],"mappings":"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"}
|
@@ -16,6 +16,7 @@ export class ProjectIdRequiredError extends Error {
|
|
16
16
|
* @returns the user's actual project id
|
17
17
|
*/
|
18
18
|
export async function setupUser(client) {
|
19
|
+
console.log(`setupUser: starting setup, GOOGLE_CLOUD_PROJECT=${process.env.GOOGLE_CLOUD_PROJECT || 'undefined'}`);
|
19
20
|
const projectId = process.env.GOOGLE_CLOUD_PROJECT || undefined;
|
20
21
|
// PRIVACY FIX: sessionId parameter removed from CodeAssistServer constructor
|
21
22
|
const caServer = new CodeAssistServer(client, projectId, {}, undefined);
|
@@ -24,6 +25,7 @@ export async function setupUser(client) {
|
|
24
25
|
platform: 'PLATFORM_UNSPECIFIED',
|
25
26
|
pluginType: 'GEMINI',
|
26
27
|
};
|
28
|
+
console.log(`setupUser: created CodeAssistServer, calling loadCodeAssist`);
|
27
29
|
const loadRes = await caServer.loadCodeAssist({
|
28
30
|
cloudaicompanionProject: projectId,
|
29
31
|
metadata: {
|
@@ -31,16 +33,21 @@ export async function setupUser(client) {
|
|
31
33
|
duetProject: projectId,
|
32
34
|
},
|
33
35
|
});
|
36
|
+
console.log(`setupUser: loadCodeAssist completed, currentTier=${!!loadRes.currentTier}, cloudaicompanionProject=${loadRes.cloudaicompanionProject}`);
|
34
37
|
if (loadRes.currentTier) {
|
38
|
+
console.log(`setupUser: user has current tier: ${loadRes.currentTier.id}`);
|
35
39
|
if (!loadRes.cloudaicompanionProject) {
|
36
40
|
if (projectId) {
|
41
|
+
console.log(`setupUser: returning with project ID from env: ${projectId}`);
|
37
42
|
return {
|
38
43
|
projectId,
|
39
44
|
userTier: loadRes.currentTier.id,
|
40
45
|
};
|
41
46
|
}
|
47
|
+
console.log(`setupUser: throwing ProjectIdRequiredError - no project ID available`);
|
42
48
|
throw new ProjectIdRequiredError();
|
43
49
|
}
|
50
|
+
console.log(`setupUser: returning with project ID from response: ${loadRes.cloudaicompanionProject}`);
|
44
51
|
return {
|
45
52
|
projectId: loadRes.cloudaicompanionProject,
|
46
53
|
userTier: loadRes.currentTier.id,
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/code_assist/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAKL,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C;QACE,KAAK,CACH,wHAAwH,CACzH,CAAC;IACJ,CAAC;CACF;AAOD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAoB;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,SAAS,CAAC;IAChE,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;IACxE,MAAM,kBAAkB,GAAmB;QACzC,OAAO,EAAE,iBAAiB;QAC1B,QAAQ,EAAE,sBAAsB;QAChC,UAAU,EAAE,QAAQ;KACrB,CAAC;
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/code_assist/setup.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,37 @@
|
|
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 { ContentGenerator } from './contentGenerator.js';
|
17
|
+
import { GenerateContentResponse, GenerateContentParameters, CountTokensResponse, CountTokensParameters, EmbedContentResponse, EmbedContentParameters } from '@google/genai';
|
18
|
+
import { UserTierId } from '../code_assist/types.js';
|
19
|
+
import type { IContent } from '../services/history/IContent.js';
|
20
|
+
/**
|
21
|
+
* Adapter that wraps ContentGenerator to work with IContent[]
|
22
|
+
* This allows GeminiChat to pass IContent[] which gets converted
|
23
|
+
* to Content[] format for providers
|
24
|
+
*/
|
25
|
+
export declare class ContentGeneratorAdapter implements ContentGenerator {
|
26
|
+
private contentGenerator;
|
27
|
+
constructor(contentGenerator: ContentGenerator);
|
28
|
+
generateContent(request: GenerateContentParameters, userPromptId: string): Promise<GenerateContentResponse>;
|
29
|
+
generateContentStream(request: GenerateContentParameters, userPromptId: string): Promise<AsyncGenerator<GenerateContentResponse>>;
|
30
|
+
countTokens(request: CountTokensParameters): Promise<CountTokensResponse>;
|
31
|
+
/**
|
32
|
+
* Helper method to convert IContent[] to Content[] and create request
|
33
|
+
*/
|
34
|
+
static createRequest(iContents: IContent[], model: string, config?: Record<string, unknown>): GenerateContentParameters;
|
35
|
+
embedContent(request: EmbedContentParameters): Promise<EmbedContentResponse>;
|
36
|
+
get userTier(): UserTierId | undefined;
|
37
|
+
}
|
@@ -0,0 +1,58 @@
|
|
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 { ContentConverters } from '../services/history/ContentConverters.js';
|
17
|
+
/**
|
18
|
+
* Adapter that wraps ContentGenerator to work with IContent[]
|
19
|
+
* This allows GeminiChat to pass IContent[] which gets converted
|
20
|
+
* to Content[] format for providers
|
21
|
+
*/
|
22
|
+
export class ContentGeneratorAdapter {
|
23
|
+
contentGenerator;
|
24
|
+
constructor(contentGenerator) {
|
25
|
+
this.contentGenerator = contentGenerator;
|
26
|
+
}
|
27
|
+
async generateContent(request, userPromptId) {
|
28
|
+
// Request should already have the contents set by GeminiChat
|
29
|
+
return this.contentGenerator.generateContent(request, userPromptId);
|
30
|
+
}
|
31
|
+
async generateContentStream(request, userPromptId) {
|
32
|
+
// Request should already have the contents set by GeminiChat
|
33
|
+
return this.contentGenerator.generateContentStream(request, userPromptId);
|
34
|
+
}
|
35
|
+
async countTokens(request) {
|
36
|
+
// Request should already have the contents set by GeminiChat
|
37
|
+
return this.contentGenerator.countTokens(request);
|
38
|
+
}
|
39
|
+
/**
|
40
|
+
* Helper method to convert IContent[] to Content[] and create request
|
41
|
+
*/
|
42
|
+
static createRequest(iContents, model, config) {
|
43
|
+
const contents = ContentConverters.toGeminiContents(iContents);
|
44
|
+
return {
|
45
|
+
model,
|
46
|
+
contents,
|
47
|
+
config,
|
48
|
+
};
|
49
|
+
}
|
50
|
+
async embedContent(request) {
|
51
|
+
// Embedding doesn't use history, so just pass through
|
52
|
+
return this.contentGenerator.embedContent(request);
|
53
|
+
}
|
54
|
+
get userTier() {
|
55
|
+
return this.contentGenerator.userTier;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
//# sourceMappingURL=ContentGeneratorAdapter.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ContentGeneratorAdapter.js","sourceRoot":"","sources":["../../../src/core/ContentGeneratorAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAY7E;;;;GAIG;AACH,MAAM,OAAO,uBAAuB;IACd;IAApB,YAAoB,gBAAkC;QAAlC,qBAAgB,GAAhB,gBAAgB,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,eAAe,CACnB,OAAkC,EAClC,YAAoB;QAEpB,6DAA6D;QAC7D,OAAO,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,qBAAqB,CACzB,OAAkC,EAClC,YAAoB;QAEpB,6DAA6D;QAC7D,OAAO,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,WAAW,CACf,OAA8B;QAE9B,6DAA6D;QAC7D,OAAO,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,aAAa,CAClB,SAAqB,EACrB,KAAa,EACb,MAAgC;QAEhC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC/D,OAAO;YACL,KAAK;YACL,QAAQ;YACR,MAAM;SACP,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,OAA+B;QAE/B,sDAAsD;QACtD,OAAO,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;IACxC,CAAC;CACF"}
|
@@ -8,6 +8,7 @@ import { Turn, ServerGeminiStreamEvent, ChatCompressionInfo } from './turn.js';
|
|
8
8
|
import { Config } from '../config/config.js';
|
9
9
|
import { UserTierId } from '../code_assist/types.js';
|
10
10
|
import { GeminiChat } from './geminiChat.js';
|
11
|
+
import { HistoryService } from '../services/history/HistoryService.js';
|
11
12
|
import { ContentGenerator, ContentGeneratorConfig } from './contentGenerator.js';
|
12
13
|
/**
|
13
14
|
* Returns the index of the content after the fraction of the total characters in the history.
|
@@ -31,8 +32,8 @@ export declare class GeminiClient {
|
|
31
32
|
*/
|
32
33
|
private COMPRESSION_TOKEN_THRESHOLD;
|
33
34
|
/**
|
34
|
-
* The fraction of the latest chat history to keep. A value of 0.
|
35
|
-
* means that only the last
|
35
|
+
* The fraction of the latest chat history to keep. A value of 0.5
|
36
|
+
* means that only the last 50% of the chat history will be kept after compression.
|
36
37
|
*/
|
37
38
|
private readonly COMPRESSION_PRESERVE_THRESHOLD;
|
38
39
|
/**
|
@@ -47,6 +48,7 @@ export declare class GeminiClient {
|
|
47
48
|
private readonly complexitySuggestionCooldown;
|
48
49
|
private lastSentIdeContext;
|
49
50
|
private forceFullIdeContext;
|
51
|
+
private logger;
|
50
52
|
constructor(config: Config);
|
51
53
|
/**
|
52
54
|
* Set the compression threshold and context limit overrides
|
@@ -58,6 +60,11 @@ export declare class GeminiClient {
|
|
58
60
|
getUserTier(): UserTierId | undefined;
|
59
61
|
addHistory(content: Content): Promise<void>;
|
60
62
|
getChat(): GeminiChat;
|
63
|
+
/**
|
64
|
+
* Get the HistoryService from the current chat session
|
65
|
+
* @returns The HistoryService instance, or null if chat is not initialized
|
66
|
+
*/
|
67
|
+
getHistoryService(): HistoryService | null;
|
61
68
|
hasChatInitialized(): boolean;
|
62
69
|
isInitialized(): boolean;
|
63
70
|
getHistory(): Promise<Content[]>;
|
package/dist/src/core/client.js
CHANGED
@@ -9,10 +9,13 @@ import { getCoreSystemPromptAsync, getCompressionPrompt } from './prompts.js';
|
|
9
9
|
import { getResponseText } from '../utils/generateContentResponseUtilities.js';
|
10
10
|
import { reportError } from '../utils/errorReporting.js';
|
11
11
|
import { GeminiChat } from './geminiChat.js';
|
12
|
+
import { HistoryService } from '../services/history/HistoryService.js';
|
13
|
+
import { ContentConverters } from '../services/history/ContentConverters.js';
|
12
14
|
import { retryWithBackoff } from '../utils/retry.js';
|
13
15
|
import { getErrorMessage } from '../utils/errors.js';
|
14
16
|
import { isFunctionResponse } from '../utils/messageInspectors.js';
|
15
17
|
import { tokenLimit } from './tokenLimits.js';
|
18
|
+
import { COMPRESSION_TOKEN_THRESHOLD, COMPRESSION_PRESERVE_THRESHOLD, } from './compression-config.js';
|
16
19
|
import { AuthType, createContentGenerator, } from './contentGenerator.js';
|
17
20
|
import { ProxyAgent, setGlobalDispatcher } from 'undici';
|
18
21
|
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
@@ -20,6 +23,7 @@ import { LoopDetectionService } from '../services/loopDetectionService.js';
|
|
20
23
|
import { ideContext } from '../ide/ideContext.js';
|
21
24
|
import { ComplexityAnalyzer } from '../services/complexity-analyzer.js';
|
22
25
|
import { TodoReminderService } from '../services/todo-reminder-service.js';
|
26
|
+
import { DebugLogger } from '../debug/index.js';
|
23
27
|
function isThinkingSupported(model) {
|
24
28
|
if (model.startsWith('gemini-2.5'))
|
25
29
|
return true;
|
@@ -77,12 +81,12 @@ export class GeminiClient {
|
|
77
81
|
* Threshold for compression token count as a fraction of the model's token limit.
|
78
82
|
* If the chat history exceeds this threshold, it will be compressed.
|
79
83
|
*/
|
80
|
-
COMPRESSION_TOKEN_THRESHOLD =
|
84
|
+
COMPRESSION_TOKEN_THRESHOLD = COMPRESSION_TOKEN_THRESHOLD;
|
81
85
|
/**
|
82
|
-
* The fraction of the latest chat history to keep. A value of 0.
|
83
|
-
* means that only the last
|
86
|
+
* The fraction of the latest chat history to keep. A value of 0.5
|
87
|
+
* means that only the last 50% of the chat history will be kept after compression.
|
84
88
|
*/
|
85
|
-
COMPRESSION_PRESERVE_THRESHOLD =
|
89
|
+
COMPRESSION_PRESERVE_THRESHOLD = COMPRESSION_PRESERVE_THRESHOLD;
|
86
90
|
/**
|
87
91
|
* User-defined context limit override
|
88
92
|
*/
|
@@ -95,8 +99,10 @@ export class GeminiClient {
|
|
95
99
|
complexitySuggestionCooldown;
|
96
100
|
lastSentIdeContext;
|
97
101
|
forceFullIdeContext = true;
|
102
|
+
logger;
|
98
103
|
constructor(config) {
|
99
104
|
this.config = config;
|
105
|
+
this.logger = new DebugLogger('llxprt:core:client');
|
100
106
|
if (config.getProxy()) {
|
101
107
|
setGlobalDispatcher(new ProxyAgent(config.getProxy()));
|
102
108
|
}
|
@@ -148,17 +154,8 @@ export class GeminiClient {
|
|
148
154
|
throw new Error('Content generator config not initialized. Call config.refreshAuth() first.');
|
149
155
|
}
|
150
156
|
this.contentGenerator = await createContentGenerator(contentGenConfig, this.config, this.config.getSessionId());
|
151
|
-
//
|
152
|
-
//
|
153
|
-
if (this._previousHistory && this._previousHistory.length > 0) {
|
154
|
-
// Extract the conversation history after the initial environment setup
|
155
|
-
// The first two messages are always the environment context and acknowledgment
|
156
|
-
const conversationHistory = this._previousHistory.slice(2);
|
157
|
-
this.chat = await this.startChat(conversationHistory);
|
158
|
-
}
|
159
|
-
else {
|
160
|
-
this.chat = await this.startChat();
|
161
|
-
}
|
157
|
+
// Don't create chat here - that causes infinite recursion with startChat()
|
158
|
+
// The chat will be created when needed
|
162
159
|
// Clear pending config after successful initialization
|
163
160
|
// Note: We do NOT clear _previousHistory as it may be needed for the chat context
|
164
161
|
this._pendingConfig = undefined;
|
@@ -185,6 +182,16 @@ export class GeminiClient {
|
|
185
182
|
}
|
186
183
|
return this.chat;
|
187
184
|
}
|
185
|
+
/**
|
186
|
+
* Get the HistoryService from the current chat session
|
187
|
+
* @returns The HistoryService instance, or null if chat is not initialized
|
188
|
+
*/
|
189
|
+
getHistoryService() {
|
190
|
+
if (!this.hasChatInitialized()) {
|
191
|
+
return null;
|
192
|
+
}
|
193
|
+
return this.getChat().getHistoryService();
|
194
|
+
}
|
188
195
|
hasChatInitialized() {
|
189
196
|
return this.chat !== undefined;
|
190
197
|
}
|
@@ -252,7 +259,8 @@ export class GeminiClient {
|
|
252
259
|
this.getChat().setTools(tools);
|
253
260
|
}
|
254
261
|
async resetChat() {
|
255
|
-
|
262
|
+
// Pass the stored history to startChat so it's preserved
|
263
|
+
this.chat = await this.startChat(this._previousHistory);
|
256
264
|
}
|
257
265
|
async addDirectoryContext() {
|
258
266
|
if (!this.chat) {
|
@@ -265,11 +273,21 @@ export class GeminiClient {
|
|
265
273
|
}
|
266
274
|
async startChat(extraHistory) {
|
267
275
|
this.forceFullIdeContext = true;
|
276
|
+
// Ensure content generator is initialized before creating chat
|
277
|
+
await this.lazyInitialize();
|
268
278
|
const envParts = await getEnvironmentContext(this.config);
|
269
279
|
const toolRegistry = this.config.getToolRegistry();
|
270
280
|
const toolDeclarations = toolRegistry.getFunctionDeclarations();
|
271
281
|
const tools = [{ functionDeclarations: toolDeclarations }];
|
272
|
-
|
282
|
+
// Create HistoryService and add initial history
|
283
|
+
const historyService = new HistoryService();
|
284
|
+
// Add extraHistory if provided
|
285
|
+
if (extraHistory && extraHistory.length > 0) {
|
286
|
+
const currentModel = this.config.getModel();
|
287
|
+
for (const content of extraHistory) {
|
288
|
+
historyService.add(ContentConverters.toIContent(content), currentModel);
|
289
|
+
}
|
290
|
+
}
|
273
291
|
try {
|
274
292
|
const userMemory = this.config.getUserMemory();
|
275
293
|
const model = this.config.getModel();
|
@@ -299,10 +317,11 @@ export class GeminiClient {
|
|
299
317
|
systemInstruction,
|
300
318
|
...generateContentConfigWithThinking,
|
301
319
|
tools,
|
302
|
-
}, history
|
320
|
+
}, [], // Empty initial history since we're using HistoryService
|
321
|
+
historyService);
|
303
322
|
}
|
304
323
|
catch (error) {
|
305
|
-
await reportError(error, 'Error initializing chat session.',
|
324
|
+
await reportError(error, 'Error initializing chat session.', extraHistory ?? [], 'startChat');
|
306
325
|
throw new Error(`Failed to initialize chat: ${getErrorMessage(error)}`);
|
307
326
|
}
|
308
327
|
}
|
@@ -453,6 +472,18 @@ export class GeminiClient {
|
|
453
472
|
console.log('DEBUG: GeminiClient.sendMessageStream Array.isArray(request):', Array.isArray(request));
|
454
473
|
}
|
455
474
|
await this.lazyInitialize();
|
475
|
+
// Ensure chat is initialized after lazyInitialize
|
476
|
+
if (!this.chat) {
|
477
|
+
// If we have previous history, restore it when creating the chat
|
478
|
+
if (this._previousHistory && this._previousHistory.length > 0) {
|
479
|
+
// Extract the conversation history after the initial environment setup
|
480
|
+
const conversationHistory = this._previousHistory.slice(2);
|
481
|
+
this.chat = await this.startChat(conversationHistory);
|
482
|
+
}
|
483
|
+
else {
|
484
|
+
this.chat = await this.startChat();
|
485
|
+
}
|
486
|
+
}
|
456
487
|
if (this.lastPromptId !== prompt_id) {
|
457
488
|
this.loopDetector.reset(prompt_id);
|
458
489
|
this.lastPromptId = prompt_id;
|
@@ -705,12 +736,24 @@ export class GeminiClient {
|
|
705
736
|
return null;
|
706
737
|
}
|
707
738
|
const model = this.config.getModel();
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
739
|
+
// Use HistoryService's token count for consistency
|
740
|
+
const historyService = this.getHistoryService();
|
741
|
+
let originalTokenCount = 0;
|
742
|
+
if (historyService) {
|
743
|
+
// Wait for any pending token calculations to complete
|
744
|
+
await historyService.recalculateTokens(model);
|
745
|
+
originalTokenCount = historyService.getTotalTokens();
|
746
|
+
}
|
747
|
+
else {
|
748
|
+
// Fallback to content generator if history service not available
|
749
|
+
const countResult = await this.getContentGenerator().countTokens({
|
750
|
+
model,
|
751
|
+
contents: curatedHistory,
|
752
|
+
});
|
753
|
+
originalTokenCount = countResult.totalTokens || 0;
|
754
|
+
}
|
755
|
+
if (originalTokenCount === 0) {
|
756
|
+
this.logger.log(() => `[Warning] Could not determine token count for model ${model}.`);
|
714
757
|
return null;
|
715
758
|
}
|
716
759
|
const contextPercentageThreshold = this.config.getChatCompression()?.contextPercentageThreshold;
|
@@ -722,8 +765,14 @@ export class GeminiClient {
|
|
722
765
|
return null;
|
723
766
|
}
|
724
767
|
}
|
725
|
-
|
726
|
-
//
|
768
|
+
// Find the split point based on keeping the most recent 50% of messages
|
769
|
+
// Use a simpler approach: keep the last half of the messages
|
770
|
+
let compressBeforeIndex = Math.floor(curatedHistory.length * (1 - this.COMPRESSION_PRESERVE_THRESHOLD));
|
771
|
+
// Ensure we don't compress everything - keep at least the last 2 turns
|
772
|
+
if (compressBeforeIndex >= curatedHistory.length - 4) {
|
773
|
+
compressBeforeIndex = Math.max(0, curatedHistory.length - 4);
|
774
|
+
}
|
775
|
+
// Find the first user message after the index to ensure we don't split mid-turn
|
727
776
|
while (compressBeforeIndex < curatedHistory.length &&
|
728
777
|
(curatedHistory[compressBeforeIndex]?.role === 'model' ||
|
729
778
|
isFunctionResponse(curatedHistory[compressBeforeIndex]))) {
|
@@ -731,8 +780,11 @@ export class GeminiClient {
|
|
731
780
|
}
|
732
781
|
const historyToCompress = curatedHistory.slice(0, compressBeforeIndex);
|
733
782
|
const historyToKeep = curatedHistory.slice(compressBeforeIndex);
|
783
|
+
// Debug logging
|
784
|
+
this.logger.debug(() => `[Compression] Compressing ${historyToCompress.length} messages, keeping ${historyToKeep.length} messages`);
|
785
|
+
this.logger.debug(() => `[Compression] Original token count: ${originalTokenCount}`);
|
734
786
|
this.getChat().setHistory(historyToCompress);
|
735
|
-
const
|
787
|
+
const response = await this.getChat().sendMessage({
|
736
788
|
message: {
|
737
789
|
text: 'First, reason in your scratchpad. Then, generate the <state_snapshot>.',
|
738
790
|
},
|
@@ -740,6 +792,21 @@ export class GeminiClient {
|
|
740
792
|
systemInstruction: { text: getCompressionPrompt() },
|
741
793
|
},
|
742
794
|
}, prompt_id);
|
795
|
+
// Extract text from the response using the utility function
|
796
|
+
const summary = getResponseText(response);
|
797
|
+
// Debug: log the summary length
|
798
|
+
if (summary) {
|
799
|
+
this.logger.debug(() => `[Compression] Summary length: ${summary.length} characters`);
|
800
|
+
this.logger.debug(() => `[Compression] Summary preview: ${summary.substring(0, 200)}...`);
|
801
|
+
// Ensure the summary is meaningful (not just empty XML tags)
|
802
|
+
if (summary.length < 100) {
|
803
|
+
this.logger.log(() => '[Warning] [Compression] Summary appears too short, may be incomplete');
|
804
|
+
}
|
805
|
+
}
|
806
|
+
else {
|
807
|
+
this.logger.log(() => '[Warning] [Compression] No summary generated');
|
808
|
+
return null;
|
809
|
+
}
|
743
810
|
this.chat = await this.startChat([
|
744
811
|
{
|
745
812
|
role: 'user',
|
@@ -752,15 +819,23 @@ export class GeminiClient {
|
|
752
819
|
...historyToKeep,
|
753
820
|
]);
|
754
821
|
this.forceFullIdeContext = true;
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
822
|
+
// Get new token count from the new HistoryService
|
823
|
+
const newHistoryService = this.getHistoryService();
|
824
|
+
let newTokenCount = 0;
|
825
|
+
if (newHistoryService) {
|
826
|
+
// Wait for recalculation to complete
|
827
|
+
await newHistoryService.recalculateTokens(model);
|
828
|
+
newTokenCount = newHistoryService.getTotalTokens();
|
829
|
+
}
|
830
|
+
else {
|
831
|
+
// Fallback
|
832
|
+
const countResult = await this.getContentGenerator().countTokens({
|
833
|
+
model: this.config.getModel(),
|
834
|
+
contents: this.getChat().getHistory(),
|
835
|
+
});
|
836
|
+
newTokenCount = countResult.totalTokens || 0;
|
763
837
|
}
|
838
|
+
this.logger.debug(() => `[Compression] New token count: ${newTokenCount}`);
|
764
839
|
return {
|
765
840
|
originalTokenCount,
|
766
841
|
newTokenCount,
|