@theia/ai-chat 1.60.1 → 1.61.0-next.8

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.
Files changed (34) hide show
  1. package/lib/common/chat-agents.d.ts.map +1 -1
  2. package/lib/common/chat-agents.js +27 -20
  3. package/lib/common/chat-agents.js.map +1 -1
  4. package/lib/common/chat-model.d.ts +18 -0
  5. package/lib/common/chat-model.d.ts.map +1 -1
  6. package/lib/common/chat-model.js +46 -1
  7. package/lib/common/chat-model.js.map +1 -1
  8. package/lib/common/chat-session-naming-service.d.ts.map +1 -1
  9. package/lib/common/chat-session-naming-service.js +7 -9
  10. package/lib/common/chat-session-naming-service.js.map +1 -1
  11. package/lib/common/parse-contents-with-incomplete-parts.spec.d.ts +2 -0
  12. package/lib/common/parse-contents-with-incomplete-parts.spec.d.ts.map +1 -0
  13. package/lib/common/parse-contents-with-incomplete-parts.spec.js +103 -0
  14. package/lib/common/parse-contents-with-incomplete-parts.spec.js.map +1 -0
  15. package/lib/common/parse-contents.d.ts +1 -0
  16. package/lib/common/parse-contents.d.ts.map +1 -1
  17. package/lib/common/parse-contents.js +45 -5
  18. package/lib/common/parse-contents.js.map +1 -1
  19. package/lib/common/parse-contents.spec.d.ts +1 -0
  20. package/lib/common/parse-contents.spec.d.ts.map +1 -1
  21. package/lib/common/parse-contents.spec.js +25 -13
  22. package/lib/common/parse-contents.spec.js.map +1 -1
  23. package/lib/common/response-content-matcher.d.ts +6 -0
  24. package/lib/common/response-content-matcher.d.ts.map +1 -1
  25. package/lib/common/response-content-matcher.js +14 -3
  26. package/lib/common/response-content-matcher.js.map +1 -1
  27. package/package.json +11 -11
  28. package/src/common/chat-agents.ts +32 -21
  29. package/src/common/chat-model.ts +60 -0
  30. package/src/common/chat-session-naming-service.ts +10 -13
  31. package/src/common/parse-contents-with-incomplete-parts.spec.ts +114 -0
  32. package/src/common/parse-contents.spec.ts +24 -12
  33. package/src/common/parse-contents.ts +52 -6
  34. package/src/common/response-content-matcher.ts +21 -3
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2025 EclipseSource GmbH.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const chai_1 = require("chai");
19
+ const chat_model_1 = require("./chat-model");
20
+ const parse_contents_1 = require("./parse-contents");
21
+ const fakeRequest = {};
22
+ // Custom matchers with incompleteContentFactory for testing
23
+ const TestCodeContentMatcher = {
24
+ start: /^```.*?$/m,
25
+ end: /^```$/m,
26
+ contentFactory: (content) => {
27
+ var _a;
28
+ const language = ((_a = content.match(/^```(\w+)/)) === null || _a === void 0 ? void 0 : _a[1]) || '';
29
+ const code = content.replace(/^```(\w+)\n|```$/g, '');
30
+ return new chat_model_1.CodeChatResponseContentImpl(code.trim(), language);
31
+ },
32
+ incompleteContentFactory: (content) => {
33
+ var _a;
34
+ const language = ((_a = content.match(/^```(\w+)/)) === null || _a === void 0 ? void 0 : _a[1]) || '';
35
+ // Remove only the start delimiter, since we don't have an end delimiter yet
36
+ const code = content.replace(/^```(\w+)\n?/g, '');
37
+ return new chat_model_1.CodeChatResponseContentImpl(code.trim(), language);
38
+ }
39
+ };
40
+ describe('parseContents with incomplete parts', () => {
41
+ it('should handle incomplete code blocks with incompleteContentFactory', () => {
42
+ // Only the start of a code block without an end
43
+ const text = '```typescript\nconsole.log("Hello World");';
44
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [TestCodeContentMatcher]);
45
+ (0, chai_1.expect)(result.length).to.equal(1);
46
+ (0, chai_1.expect)(result[0]).to.be.instanceOf(chat_model_1.CodeChatResponseContentImpl);
47
+ const codeContent = result[0];
48
+ (0, chai_1.expect)(codeContent.code).to.equal('console.log("Hello World");');
49
+ (0, chai_1.expect)(codeContent.language).to.equal('typescript');
50
+ });
51
+ it('should handle complete code blocks with contentFactory', () => {
52
+ const text = '```typescript\nconsole.log("Hello World");\n```';
53
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [TestCodeContentMatcher]);
54
+ (0, chai_1.expect)(result.length).to.equal(1);
55
+ (0, chai_1.expect)(result[0]).to.be.instanceOf(chat_model_1.CodeChatResponseContentImpl);
56
+ const codeContent = result[0];
57
+ (0, chai_1.expect)(codeContent.code).to.equal('console.log("Hello World");');
58
+ (0, chai_1.expect)(codeContent.language).to.equal('typescript');
59
+ });
60
+ it('should handle mixed content with incomplete and complete blocks', () => {
61
+ const text = 'Some text\n```typescript\nconsole.log("Hello");\n```\nMore text\n```python\nprint("World")';
62
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [TestCodeContentMatcher]);
63
+ (0, chai_1.expect)(result.length).to.equal(4);
64
+ (0, chai_1.expect)(result[0]).to.be.instanceOf(chat_model_1.MarkdownChatResponseContentImpl);
65
+ (0, chai_1.expect)(result[1]).to.be.instanceOf(chat_model_1.CodeChatResponseContentImpl);
66
+ const completeContent = result[1];
67
+ (0, chai_1.expect)(completeContent.language).to.equal('typescript');
68
+ (0, chai_1.expect)(result[2]).to.be.instanceOf(chat_model_1.MarkdownChatResponseContentImpl);
69
+ (0, chai_1.expect)(result[3]).to.be.instanceOf(chat_model_1.CodeChatResponseContentImpl);
70
+ const incompleteContent = result[3];
71
+ (0, chai_1.expect)(incompleteContent.language).to.equal('python');
72
+ });
73
+ it('should use default content factory if no incompleteContentFactory provided', () => {
74
+ // Create a matcher without incompleteContentFactory
75
+ const matcherWithoutIncomplete = {
76
+ start: /^<test>$/m,
77
+ end: /^<\/test>$/m,
78
+ contentFactory: (content) => new chat_model_1.MarkdownChatResponseContentImpl('complete: ' + content)
79
+ };
80
+ // Text with only the start delimiter
81
+ const text = '<test>\ntest content';
82
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [matcherWithoutIncomplete]);
83
+ (0, chai_1.expect)(result.length).to.equal(1);
84
+ (0, chai_1.expect)(result[0]).to.be.instanceOf(chat_model_1.MarkdownChatResponseContentImpl);
85
+ (0, chai_1.expect)(result[0].content.value).to.equal('<test>\ntest content');
86
+ });
87
+ it('should prefer complete matches over incomplete ones', () => {
88
+ // Text with both a complete and incomplete match at same position
89
+ const text = '```typescript\nconsole.log();\n```\n<test>\ntest content';
90
+ const matcherWithoutIncomplete = {
91
+ start: /^<test>$/m,
92
+ end: /^<\/test>$/m,
93
+ contentFactory: (content) => new chat_model_1.MarkdownChatResponseContentImpl('complete: ' + content)
94
+ };
95
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [TestCodeContentMatcher, matcherWithoutIncomplete]);
96
+ (0, chai_1.expect)(result.length).to.equal(2);
97
+ (0, chai_1.expect)(result[0]).to.be.instanceOf(chat_model_1.CodeChatResponseContentImpl);
98
+ (0, chai_1.expect)(result[0].language).to.equal('typescript');
99
+ (0, chai_1.expect)(result[1]).to.be.instanceOf(chat_model_1.MarkdownChatResponseContentImpl);
100
+ (0, chai_1.expect)(result[1].content.value).to.contain('test content');
101
+ });
102
+ });
103
+ //# sourceMappingURL=parse-contents-with-incomplete-parts.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-contents-with-incomplete-parts.spec.js","sourceRoot":"","sources":["../../src/common/parse-contents-with-incomplete-parts.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAEhF,+BAA8B;AAC9B,6CAAqH;AACrH,qDAAiD;AAGjD,MAAM,WAAW,GAAG,EAA6B,CAAC;AAElD,4DAA4D;AAC5D,MAAM,sBAAsB,GAA2B;IACnD,KAAK,EAAE,WAAW;IAClB,GAAG,EAAE,QAAQ;IACb,cAAc,EAAE,CAAC,OAAe,EAAE,EAAE;;QAChC,MAAM,QAAQ,GAAG,CAAA,MAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,0CAAG,CAAC,CAAC,KAAI,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,wCAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;IACD,wBAAwB,EAAE,CAAC,OAAe,EAAE,EAAE;;QAC1C,MAAM,QAAQ,GAAG,CAAA,MAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,0CAAG,CAAC,CAAC,KAAI,EAAE,CAAC;QACvD,4EAA4E;QAC5E,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QAClD,OAAO,IAAI,wCAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;CACJ,CAAC;AAEF,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC1E,gDAAgD;QAChD,MAAM,IAAI,GAAG,4CAA4C,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAE1E,IAAA,aAAM,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,wCAA2B,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAgC,CAAC;QAC7D,IAAA,aAAM,EAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjE,IAAA,aAAM,EAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,MAAM,IAAI,GAAG,iDAAiD,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAE1E,IAAA,aAAM,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,wCAA2B,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAgC,CAAC;QAC7D,IAAA,aAAM,EAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjE,IAAA,aAAM,EAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACvE,MAAM,IAAI,GAAG,4FAA4F,CAAC;QAC1G,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAE1E,IAAA,aAAM,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,4CAA+B,CAAC,CAAC;QACpE,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,wCAA2B,CAAC,CAAC;QAChE,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAgC,CAAC;QACjE,IAAA,aAAM,EAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxD,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,4CAA+B,CAAC,CAAC;QACpE,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,wCAA2B,CAAC,CAAC;QAChE,MAAM,iBAAiB,GAAG,MAAM,CAAC,CAAC,CAAgC,CAAC;QACnE,IAAA,aAAM,EAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QAClF,oDAAoD;QACpD,MAAM,wBAAwB,GAA2B;YACrD,KAAK,EAAE,WAAW;YAClB,GAAG,EAAE,aAAa;YAClB,cAAc,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,4CAA+B,CAAC,YAAY,GAAG,OAAO,CAAC;SACnG,CAAC;QAEF,qCAAqC;QACrC,MAAM,IAAI,GAAG,sBAAsB,CAAC;QACpC,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAE5E,IAAA,aAAM,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,4CAA+B,CAAC,CAAC;QACpE,IAAA,aAAM,EAAE,MAAM,CAAC,CAAC,CAAqC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC3D,kEAAkE;QAClE,MAAM,IAAI,GAAG,0DAA0D,CAAC;QACxE,MAAM,wBAAwB,GAA2B;YACrD,KAAK,EAAE,WAAW;YAClB,GAAG,EAAE,aAAa;YAClB,cAAc,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,4CAA+B,CAAC,YAAY,GAAG,OAAO,CAAC;SACnG,CAAC;QAEF,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,sBAAsB,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAEpG,IAAA,aAAM,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,wCAA2B,CAAC,CAAC;QAChE,IAAA,aAAM,EAAE,MAAM,CAAC,CAAC,CAAiC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACnF,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,4CAA+B,CAAC,CAAC;QACpE,IAAA,aAAM,EAAE,MAAM,CAAC,CAAC,CAAqC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACpG,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -4,6 +4,7 @@ interface Match {
4
4
  matcher: ResponseContentMatcher;
5
5
  index: number;
6
6
  content: string;
7
+ isComplete: boolean;
7
8
  }
8
9
  export declare function parseContents(text: string, request: MutableChatRequestModel, contentMatchers?: ResponseContentMatcher[], defaultContentFactory?: ResponseContentFactory): ChatResponseContent[];
9
10
  export declare function findFirstMatch(contentMatchers: ResponseContentMatcher[], text: string): Match | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"parse-contents.d.ts","sourceRoot":"","sources":["../../src/common/parse-contents.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,EAA8C,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAExI,UAAU,KAAK;IACX,OAAO,EAAE,sBAAsB,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,aAAa,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,uBAAuB,EAChC,eAAe,GAAE,sBAAsB,EAAyB,EAChE,qBAAqB,GAAE,sBAA+C,GACvE,mBAAmB,EAAE,CA8BvB;AAED,wBAAgB,cAAc,CAAC,eAAe,EAAE,sBAAsB,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CA8BzG"}
1
+ {"version":3,"file":"parse-contents.d.ts","sourceRoot":"","sources":["../../src/common/parse-contents.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,EAA8C,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAExI,UAAU,KAAK;IACX,OAAO,EAAE,sBAAsB,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,aAAa,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,uBAAuB,EAChC,eAAe,GAAE,sBAAsB,EAAyB,EAChE,qBAAqB,GAAE,sBAA+C,GACvE,mBAAmB,EAAE,CAuCvB;AAED,wBAAgB,cAAc,CAAC,eAAe,EAAE,sBAAsB,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAkEzG"}
@@ -24,7 +24,18 @@ function parseContents(text, request, contentMatchers = [response_content_matche
24
24
  }
25
25
  }
26
26
  // 2. Add the matched content object
27
- result.push(match.matcher.contentFactory(match.content, request));
27
+ if (match.isComplete) {
28
+ // Complete match, use regular content factory
29
+ result.push(match.matcher.contentFactory(match.content, request));
30
+ }
31
+ else if (match.matcher.incompleteContentFactory) {
32
+ // Incomplete match with an incomplete content factory available
33
+ result.push(match.matcher.incompleteContentFactory(match.content, request));
34
+ }
35
+ else {
36
+ // Incomplete match but no incomplete content factory available, use default
37
+ result.push(defaultContentFactory(match.content, request));
38
+ }
28
39
  // Update currentIndex to the end of the end of the match
29
40
  // And continue with the search after the end of the match
30
41
  currentIndex += match.index + match.content.length;
@@ -34,6 +45,7 @@ function parseContents(text, request, contentMatchers = [response_content_matche
34
45
  exports.parseContents = parseContents;
35
46
  function findFirstMatch(contentMatchers, text) {
36
47
  let firstMatch;
48
+ let firstIncompleteMatch;
37
49
  for (const matcher of contentMatchers) {
38
50
  const startMatch = matcher.start.exec(text);
39
51
  if (!startMatch) {
@@ -43,13 +55,35 @@ function findFirstMatch(contentMatchers, text) {
43
55
  const endOfStartMatch = startMatch.index + startMatch[0].length;
44
56
  if (endOfStartMatch >= text.length) {
45
57
  // There is no text after the start match.
46
- // No need to search for the end match yet, try next matcher.
58
+ // This is an incomplete match if the matcher has an incompleteContentFactory
59
+ if (matcher.incompleteContentFactory) {
60
+ const incompleteMatch = {
61
+ matcher,
62
+ index: startMatch.index,
63
+ content: text.substring(startMatch.index),
64
+ isComplete: false
65
+ };
66
+ if (!firstIncompleteMatch || incompleteMatch.index < firstIncompleteMatch.index) {
67
+ firstIncompleteMatch = incompleteMatch;
68
+ }
69
+ }
47
70
  continue;
48
71
  }
49
72
  const remainingTextAfterStartMatch = text.substring(endOfStartMatch);
50
73
  const endMatch = matcher.end.exec(remainingTextAfterStartMatch);
51
74
  if (!endMatch) {
52
- // No end match found, try next matcher.
75
+ // No end match found, this is an incomplete match
76
+ if (matcher.incompleteContentFactory) {
77
+ const incompleteMatch = {
78
+ matcher,
79
+ index: startMatch.index,
80
+ content: text.substring(startMatch.index),
81
+ isComplete: false
82
+ };
83
+ if (!firstIncompleteMatch || incompleteMatch.index < firstIncompleteMatch.index) {
84
+ firstIncompleteMatch = incompleteMatch;
85
+ }
86
+ }
53
87
  continue;
54
88
  }
55
89
  // Found start and end match.
@@ -57,11 +91,17 @@ function findFirstMatch(contentMatchers, text) {
57
91
  const index = startMatch.index;
58
92
  const contentEnd = index + startMatch[0].length + endMatch.index + endMatch[0].length;
59
93
  const content = text.substring(index, contentEnd);
94
+ const completeMatch = { matcher, index, content, isComplete: true };
60
95
  if (!firstMatch || index < firstMatch.index) {
61
- firstMatch = { matcher, index, content };
96
+ firstMatch = completeMatch;
62
97
  }
63
98
  }
64
- return firstMatch;
99
+ // If we found a complete match, return it
100
+ if (firstMatch) {
101
+ return firstMatch;
102
+ }
103
+ // Otherwise, return the first incomplete match if one exists
104
+ return firstIncompleteMatch;
65
105
  }
66
106
  exports.findFirstMatch = findFirstMatch;
67
107
  //# sourceMappingURL=parse-contents.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-contents.js","sourceRoot":"","sources":["../../src/common/parse-contents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse-contents.js","sourceRoot":"","sources":["../../src/common/parse-contents.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { ChatResponseContent } from './chat-model';
2
2
  import { ResponseContentMatcher } from './response-content-matcher';
3
+ export declare const TestCodeContentMatcher: ResponseContentMatcher;
3
4
  export declare class CommandChatResponseContentImpl implements ChatResponseContent {
4
5
  readonly command: string;
5
6
  constructor(command: string);
@@ -1 +1 @@
1
- {"version":3,"file":"parse-contents.spec.d.ts","sourceRoot":"","sources":["../../src/common/parse-contents.spec.ts"],"names":[],"mappings":"AAiBA,OAAO,EAA2B,mBAAmB,EAAgE,MAAM,cAAc,CAAC;AAE1I,OAAO,EAAsB,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAExF,qBAAa,8BAA+B,YAAW,mBAAmB;aAC1C,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;IAC3C,IAAI,SAAa;CACpB;AAED,eAAO,MAAM,qBAAqB,EAAE,sBAOnC,CAAC"}
1
+ {"version":3,"file":"parse-contents.spec.d.ts","sourceRoot":"","sources":["../../src/common/parse-contents.spec.ts"],"names":[],"mappings":"AAiBA,OAAO,EAA2B,mBAAmB,EAAgE,MAAM,cAAc,CAAC;AAE1I,OAAO,EAAsB,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAExF,eAAO,MAAM,sBAAsB,EAAE,sBAQpC,CAAC;AAEF,qBAAa,8BAA+B,YAAW,mBAAmB;aAC1C,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;IAC3C,IAAI,SAAa;CACpB;AAED,eAAO,MAAM,qBAAqB,EAAE,sBAOnC,CAAC"}
@@ -15,11 +15,21 @@
15
15
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
16
  // *****************************************************************************
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.CommandContentMatcher = exports.CommandChatResponseContentImpl = void 0;
18
+ exports.CommandContentMatcher = exports.CommandChatResponseContentImpl = exports.TestCodeContentMatcher = void 0;
19
19
  const chai_1 = require("chai");
20
20
  const chat_model_1 = require("./chat-model");
21
21
  const parse_contents_1 = require("./parse-contents");
22
22
  const response_content_matcher_1 = require("./response-content-matcher");
23
+ exports.TestCodeContentMatcher = {
24
+ start: /^```.*?$/m,
25
+ end: /^```$/m,
26
+ contentFactory: (content) => {
27
+ var _a;
28
+ const language = ((_a = content.match(/^```(\w+)/)) === null || _a === void 0 ? void 0 : _a[1]) || '';
29
+ const code = content.replace(/^```(\w+)\n|```$/g, '');
30
+ return new chat_model_1.CodeChatResponseContentImpl(code.trim(), language);
31
+ }
32
+ };
23
33
  class CommandChatResponseContentImpl {
24
34
  constructor(command) {
25
35
  this.command = command;
@@ -39,17 +49,17 @@ const fakeRequest = {};
39
49
  describe('parseContents', () => {
40
50
  it('should parse code content', () => {
41
51
  const text = '```typescript\nconsole.log("Hello World");\n```';
42
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
52
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
43
53
  (0, chai_1.expect)(result).to.deep.equal([new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript')]);
44
54
  });
45
55
  it('should parse markdown content', () => {
46
56
  const text = 'Hello **World**';
47
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
57
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
48
58
  (0, chai_1.expect)(result).to.deep.equal([new chat_model_1.MarkdownChatResponseContentImpl('Hello **World**')]);
49
59
  });
50
60
  it('should parse multiple content blocks', () => {
51
61
  const text = '```typescript\nconsole.log("Hello World");\n```\nHello **World**';
52
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
62
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
53
63
  (0, chai_1.expect)(result).to.deep.equal([
54
64
  new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'),
55
65
  new chat_model_1.MarkdownChatResponseContentImpl('\nHello **World**')
@@ -57,7 +67,7 @@ describe('parseContents', () => {
57
67
  });
58
68
  it('should parse multiple content blocks with different languages', () => {
59
69
  const text = '```typescript\nconsole.log("Hello World");\n```\n```python\nprint("Hello World")\n```';
60
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
70
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
61
71
  (0, chai_1.expect)(result).to.deep.equal([
62
72
  new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'),
63
73
  new chat_model_1.CodeChatResponseContentImpl('print("Hello World")', 'python')
@@ -65,7 +75,7 @@ describe('parseContents', () => {
65
75
  });
66
76
  it('should parse multiple content blocks with different languages and markdown', () => {
67
77
  const text = '```typescript\nconsole.log("Hello World");\n```\nHello **World**\n```python\nprint("Hello World")\n```';
68
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
78
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
69
79
  (0, chai_1.expect)(result).to.deep.equal([
70
80
  new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'),
71
81
  new chat_model_1.MarkdownChatResponseContentImpl('\nHello **World**\n'),
@@ -74,7 +84,7 @@ describe('parseContents', () => {
74
84
  });
75
85
  it('should parse content blocks with empty content', () => {
76
86
  const text = '```typescript\n```\nHello **World**\n```python\nprint("Hello World")\n```';
77
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
87
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
78
88
  (0, chai_1.expect)(result).to.deep.equal([
79
89
  new chat_model_1.CodeChatResponseContentImpl('', 'typescript'),
80
90
  new chat_model_1.MarkdownChatResponseContentImpl('\nHello **World**\n'),
@@ -83,7 +93,7 @@ describe('parseContents', () => {
83
93
  });
84
94
  it('should parse content with markdown, code, and markdown', () => {
85
95
  const text = 'Hello **World**\n```typescript\nconsole.log("Hello World");\n```\nGoodbye **World**';
86
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
96
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
87
97
  (0, chai_1.expect)(result).to.deep.equal([
88
98
  new chat_model_1.MarkdownChatResponseContentImpl('Hello **World**\n'),
89
99
  new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'),
@@ -92,30 +102,32 @@ describe('parseContents', () => {
92
102
  });
93
103
  it('should handle text with no special content', () => {
94
104
  const text = 'Just some plain text.';
95
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
105
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
96
106
  (0, chai_1.expect)(result).to.deep.equal([new chat_model_1.MarkdownChatResponseContentImpl('Just some plain text.')]);
97
107
  });
98
108
  it('should handle text with only start code block', () => {
99
109
  const text = '```typescript\nconsole.log("Hello World");';
110
+ // We're using the standard CodeContentMatcher which has incompleteContentFactory
100
111
  const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
101
- (0, chai_1.expect)(result).to.deep.equal([new chat_model_1.MarkdownChatResponseContentImpl('```typescript\nconsole.log("Hello World");')]);
112
+ (0, chai_1.expect)(result).to.deep.equal([new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript')]);
102
113
  });
103
114
  it('should handle text with only end code block', () => {
104
115
  const text = 'console.log("Hello World");\n```';
105
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
116
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
106
117
  (0, chai_1.expect)(result).to.deep.equal([new chat_model_1.MarkdownChatResponseContentImpl('console.log("Hello World");\n```')]);
107
118
  });
108
119
  it('should handle text with unmatched code block', () => {
109
120
  const text = '```typescript\nconsole.log("Hello World");\n```\n```python\nprint("Hello World")';
121
+ // We're using the standard CodeContentMatcher which has incompleteContentFactory
110
122
  const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
111
123
  (0, chai_1.expect)(result).to.deep.equal([
112
124
  new chat_model_1.CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'),
113
- new chat_model_1.MarkdownChatResponseContentImpl('\n```python\nprint("Hello World")')
125
+ new chat_model_1.CodeChatResponseContentImpl('print("Hello World")', 'python')
114
126
  ]);
115
127
  });
116
128
  it('should parse code block without newline after language', () => {
117
129
  const text = '```typescript console.log("Hello World");```';
118
- const result = (0, parse_contents_1.parseContents)(text, fakeRequest);
130
+ const result = (0, parse_contents_1.parseContents)(text, fakeRequest, [exports.TestCodeContentMatcher]);
119
131
  (0, chai_1.expect)(result).to.deep.equal([
120
132
  new chat_model_1.MarkdownChatResponseContentImpl('```typescript console.log("Hello World");```')
121
133
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"parse-contents.spec.js","sourceRoot":"","sources":["../../src/common/parse-contents.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse-contents.spec.js","sourceRoot":"","sources":["../../src/common/parse-contents.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;AAEhF,+BAA8B;AAC9B,6CAA0I;AAC1I,qDAAiD;AACjD,yEAAwF;AAE3E,QAAA,sBAAsB,GAA2B;IAC1D,KAAK,EAAE,WAAW;IAClB,GAAG,EAAE,QAAQ;IACb,cAAc,EAAE,CAAC,OAAe,EAAE,EAAE;;QAChC,MAAM,QAAQ,GAAG,CAAA,MAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,0CAAG,CAAC,CAAC,KAAI,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,wCAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;CACJ,CAAC;AAEF,MAAa,8BAA8B;IACvC,YAA4B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QAC3C,SAAI,GAAG,SAAS,CAAC;IAD8B,CAAC;CAEnD;AAHD,wEAGC;AAEY,QAAA,qBAAqB,GAA2B;IACzD,KAAK,EAAE,cAAc;IACrB,GAAG,EAAE,gBAAgB;IACrB,cAAc,EAAE,CAAC,OAAe,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO,IAAI,8BAA8B,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;CACJ,CAAC;AAEF,MAAM,WAAW,GAAG,EAA6B,CAAC;AAElD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACjC,MAAM,IAAI,GAAG,iDAAiD,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,iBAAiB,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,4CAA+B,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC5C,MAAM,IAAI,GAAG,kEAAkE,CAAC;QAChF,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC;YAC5E,IAAI,4CAA+B,CAAC,mBAAmB,CAAC;SAC3D,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,MAAM,IAAI,GAAG,uFAAuF,CAAC;QACrG,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC;YAC5E,IAAI,wCAA2B,CAAC,sBAAsB,EAAE,QAAQ,CAAC;SACpE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QAClF,MAAM,IAAI,GAAG,wGAAwG,CAAC;QACtH,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC;YAC5E,IAAI,4CAA+B,CAAC,qBAAqB,CAAC;YAC1D,IAAI,wCAA2B,CAAC,sBAAsB,EAAE,QAAQ,CAAC;SACpE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACtD,MAAM,IAAI,GAAG,2EAA2E,CAAC;QACzF,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,wCAA2B,CAAC,EAAE,EAAE,YAAY,CAAC;YACjD,IAAI,4CAA+B,CAAC,qBAAqB,CAAC;YAC1D,IAAI,wCAA2B,CAAC,sBAAsB,EAAE,QAAQ,CAAC;SACpE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,MAAM,IAAI,GAAG,qFAAqF,CAAC;QACnG,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,4CAA+B,CAAC,mBAAmB,CAAC;YACxD,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC;YAC5E,IAAI,4CAA+B,CAAC,qBAAqB,CAAC;SAC7D,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,uBAAuB,CAAC;QACrC,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,4CAA+B,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACrD,MAAM,IAAI,GAAG,4CAA4C,CAAC;QAC1D,iFAAiF;QACjF,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAChD,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACnD,MAAM,IAAI,GAAG,kCAAkC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,4CAA+B,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC;IAC5G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG,kFAAkF,CAAC;QAChG,iFAAiF;QACjF,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAChD,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,wCAA2B,CAAC,6BAA6B,EAAE,YAAY,CAAC;YAC5E,IAAI,wCAA2B,CAAC,sBAAsB,EAAE,QAAQ,CAAC;SACpE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,MAAM,IAAI,GAAG,8CAA8C,CAAC;QAC5D,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,8BAAsB,CAAC,CAAC,CAAC;QAC1E,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,4CAA+B,CAAC,8CAA8C,CAAC;SACtF,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC5E,MAAM,IAAI,GAAG,8IAA8I,CAAC;QAC5J,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,IAAI,EAAE,WAAW,EAAE,CAAC,6CAAkB,EAAE,6BAAqB,CAAC,CAAC,CAAC;QAC7F,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,8BAA8B,CAAC,oBAAoB,CAAC;YACxD,IAAI,4CAA+B,CAAC,qBAAqB,CAAC;YAC1D,IAAI,wCAA2B,CAAC,sBAAsB,EAAE,QAAQ,CAAC;YACjE,IAAI,8BAA8B,CAAC,qBAAqB,CAAC;SAC5D,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -24,6 +24,12 @@ export interface ResponseContentMatcher {
24
24
  * from start index to end index of the match (including delimiters).
25
25
  */
26
26
  contentFactory: ResponseContentFactory;
27
+ /**
28
+ * Optional factory for creating a response content when only the start delimiter has been matched,
29
+ * but not yet the end delimiter. Used during streaming to provide better visual feedback.
30
+ * If not provided, the default content factory will be used until the end delimiter is matched.
31
+ */
32
+ incompleteContentFactory?: ResponseContentFactory;
27
33
  }
28
34
  export declare const CodeContentMatcher: ResponseContentMatcher;
29
35
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"response-content-matcher.d.ts","sourceRoot":"","sources":["../../src/common/response-content-matcher.ts"],"names":[],"mappings":"AAeA,OAAO,EACH,uBAAuB,EACvB,mBAAmB,EAGtB,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,KAAK,mBAAmB,CAAC;AAEhH,eAAO,MAAM,sBAAsB,EAAE,sBACW,CAAC;AAEjD;;;;;GAKG;AACH,qBACa,6BAA6B;IACtC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,GAAG,mBAAmB;CAGjF;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACnC,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,cAAc,EAAE,sBAAsB,CAAC;CAC1C;AAED,eAAO,MAAM,kBAAkB,EAAE,sBAQhC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,8BAA8B,eAA2C,CAAC;AACvF,MAAM,WAAW,8BAA8B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;CAC/C;AAED,qBACa,qCAAsC,YAAW,8BAA8B;IACxF,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAwB;CACtE"}
1
+ {"version":3,"file":"response-content-matcher.d.ts","sourceRoot":"","sources":["../../src/common/response-content-matcher.ts"],"names":[],"mappings":"AAeA,OAAO,EACH,uBAAuB,EACvB,mBAAmB,EAGtB,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,KAAK,mBAAmB,CAAC;AAEhH,eAAO,MAAM,sBAAsB,EAAE,sBACW,CAAC;AAEjD;;;;;GAKG;AACH,qBACa,6BAA6B;IACtC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,GAAG,mBAAmB;CAGjF;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACnC,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,cAAc,EAAE,sBAAsB,CAAC;IACvC;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,sBAAsB,CAAC;CACrD;AAED,eAAO,MAAM,kBAAkB,EAAE,sBAoBhC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,8BAA8B,eAA2C,CAAC;AACvF,MAAM,WAAW,8BAA8B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;CAC/C;AAED,qBACa,qCAAsC,YAAW,8BAA8B;IACxF,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAwB;CACtE"}
@@ -19,7 +19,7 @@ const tslib_1 = require("tslib");
19
19
  */
20
20
  const chat_model_1 = require("./chat-model");
21
21
  const inversify_1 = require("@theia/core/shared/inversify");
22
- const MarkdownContentFactory = (content) => new chat_model_1.MarkdownChatResponseContentImpl(content);
22
+ const MarkdownContentFactory = (content, request) => new chat_model_1.MarkdownChatResponseContentImpl(content);
23
23
  exports.MarkdownContentFactory = MarkdownContentFactory;
24
24
  /**
25
25
  * Default response content factory used if no other `ResponseContentMatcher` applies.
@@ -37,13 +37,24 @@ exports.DefaultResponseContentFactory = DefaultResponseContentFactory = tslib_1.
37
37
  (0, inversify_1.injectable)()
38
38
  ], DefaultResponseContentFactory);
39
39
  exports.CodeContentMatcher = {
40
- start: /^```.*?$/m,
40
+ // Only match when we have the complete first line ending with a newline
41
+ // This ensures we have the full language specification before creating the editor
42
+ start: /^```.*\n/m,
41
43
  end: /^```$/m,
42
- contentFactory: (content) => {
44
+ contentFactory: (content, request) => {
43
45
  var _a;
44
46
  const language = ((_a = content.match(/^```(\w+)/)) === null || _a === void 0 ? void 0 : _a[1]) || '';
45
47
  const code = content.replace(/^```(\w+)\n|```$/g, '');
46
48
  return new chat_model_1.CodeChatResponseContentImpl(code.trim(), language);
49
+ },
50
+ incompleteContentFactory: (content, request) => {
51
+ var _a;
52
+ // By this point, we know we have at least the complete first line with ```
53
+ const firstLine = content.split('\n')[0];
54
+ const language = ((_a = firstLine.match(/^```(\w+)/)) === null || _a === void 0 ? void 0 : _a[1]) || '';
55
+ // Remove the first line to get just the code content
56
+ const code = content.substring(content.indexOf('\n') + 1);
57
+ return new chat_model_1.CodeChatResponseContentImpl(code.trim(), language);
47
58
  }
48
59
  };
49
60
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"response-content-matcher.js","sourceRoot":"","sources":["../../src/common/response-content-matcher.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;GAcG;AACH,6CAKsB;AACtB,4DAA0D;AAInD,MAAM,sBAAsB,GAA2B,CAAC,OAAe,EAAE,EAAE,CAC9E,IAAI,4CAA+B,CAAC,OAAO,CAAC,CAAC;AADpC,QAAA,sBAAsB,0BACc;AAEjD;;;;;GAKG;AAEI,IAAM,6BAA6B,GAAnC,MAAM,6BAA6B;IACtC,MAAM,CAAC,OAAe,EAAE,OAAgC;QACpD,OAAO,IAAA,8BAAsB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;CACJ,CAAA;AAJY,sEAA6B;wCAA7B,6BAA6B;IADzC,IAAA,sBAAU,GAAE;GACA,6BAA6B,CAIzC;AAkBY,QAAA,kBAAkB,GAA2B;IACtD,KAAK,EAAE,WAAW;IAClB,GAAG,EAAE,QAAQ;IACb,cAAc,EAAE,CAAC,OAAe,EAAE,EAAE;;QAChC,MAAM,QAAQ,GAAG,CAAA,MAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,0CAAG,CAAC,CAAC,KAAI,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,wCAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;CACJ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACU,QAAA,8BAA8B,GAAG,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAMhF,IAAM,qCAAqC,GAA3C,MAAM,qCAAqC;IAA3C;QACM,aAAQ,GAA6B,CAAC,0BAAkB,CAAC,CAAC;IACvE,CAAC;CAAA,CAAA;AAFY,sFAAqC;gDAArC,qCAAqC;IADjD,IAAA,sBAAU,GAAE;GACA,qCAAqC,CAEjD"}
1
+ {"version":3,"file":"response-content-matcher.js","sourceRoot":"","sources":["../../src/common/response-content-matcher.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;GAcG;AACH,6CAKsB;AACtB,4DAA0D;AAInD,MAAM,sBAAsB,GAA2B,CAAC,OAAe,EAAE,OAAgC,EAAE,EAAE,CAChH,IAAI,4CAA+B,CAAC,OAAO,CAAC,CAAC;AADpC,QAAA,sBAAsB,0BACc;AAEjD;;;;;GAKG;AAEI,IAAM,6BAA6B,GAAnC,MAAM,6BAA6B;IACtC,MAAM,CAAC,OAAe,EAAE,OAAgC;QACpD,OAAO,IAAA,8BAAsB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;CACJ,CAAA;AAJY,sEAA6B;wCAA7B,6BAA6B;IADzC,IAAA,sBAAU,GAAE;GACA,6BAA6B,CAIzC;AAwBY,QAAA,kBAAkB,GAA2B;IACtD,wEAAwE;IACxE,kFAAkF;IAClF,KAAK,EAAE,WAAW;IAClB,GAAG,EAAE,QAAQ;IACb,cAAc,EAAE,CAAC,OAAe,EAAE,OAAgC,EAAE,EAAE;;QAClE,MAAM,QAAQ,GAAG,CAAA,MAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,0CAAG,CAAC,CAAC,KAAI,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,wCAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;IACD,wBAAwB,EAAE,CAAC,OAAe,EAAE,OAAgC,EAAE,EAAE;;QAC5E,2EAA2E;QAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,CAAA,MAAA,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,0CAAG,CAAC,CAAC,KAAI,EAAE,CAAC;QAEzD,qDAAqD;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE1D,OAAO,IAAI,wCAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;CACJ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACU,QAAA,8BAA8B,GAAG,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAMhF,IAAM,qCAAqC,GAA3C,MAAM,qCAAqC;IAA3C;QACM,aAAQ,GAA6B,CAAC,0BAAkB,CAAC,CAAC;IACvE,CAAC;CAAA,CAAA;AAFY,sFAAqC;gDAArC,qCAAqC;IADjD,IAAA,sBAAU,GAAE;GACA,qCAAqC,CAEjD"}
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@theia/ai-chat",
3
- "version": "1.60.1",
3
+ "version": "1.61.0-next.8+436de3c45",
4
4
  "description": "Theia - AI Chat Extension",
5
5
  "dependencies": {
6
- "@theia/ai-core": "1.60.1",
7
- "@theia/ai-history": "1.60.1",
8
- "@theia/core": "1.60.1",
9
- "@theia/editor": "1.60.1",
10
- "@theia/file-search": "1.60.1",
11
- "@theia/filesystem": "1.60.1",
12
- "@theia/monaco": "1.60.1",
6
+ "@theia/ai-core": "1.61.0-next.8+436de3c45",
7
+ "@theia/ai-history": "1.61.0-next.8+436de3c45",
8
+ "@theia/core": "1.61.0-next.8+436de3c45",
9
+ "@theia/editor": "1.61.0-next.8+436de3c45",
10
+ "@theia/file-search": "1.61.0-next.8+436de3c45",
11
+ "@theia/filesystem": "1.61.0-next.8+436de3c45",
12
+ "@theia/monaco": "1.61.0-next.8+436de3c45",
13
13
  "@theia/monaco-editor-core": "1.96.302",
14
- "@theia/workspace": "1.60.1",
14
+ "@theia/workspace": "1.61.0-next.8+436de3c45",
15
15
  "minimatch": "^5.1.0",
16
16
  "tslib": "^2.6.2"
17
17
  },
@@ -49,10 +49,10 @@
49
49
  "watch": "theiaext watch"
50
50
  },
51
51
  "devDependencies": {
52
- "@theia/ext-scripts": "1.60.1"
52
+ "@theia/ext-scripts": "1.60.0"
53
53
  },
54
54
  "nyc": {
55
55
  "extends": "../../configs/nyc.json"
56
56
  },
57
- "gitHead": "23230a4ff18bb6b4c09e08c1a40ae1ebdb20ff69"
57
+ "gitHead": "436de3c4571e0000fdcbbf2e94ddfc992f38ccb2"
58
58
  }
@@ -27,6 +27,7 @@ import {
27
27
  isTextResponsePart,
28
28
  isThinkingResponsePart,
29
29
  isToolCallResponsePart,
30
+ isUsageResponsePart,
30
31
  LanguageModel,
31
32
  LanguageModelMessage,
32
33
  LanguageModelRequirement,
@@ -60,7 +61,7 @@ import {
60
61
  ChatRequestModel,
61
62
  ThinkingChatResponseContentImpl
62
63
  } from './chat-model';
63
- import { findFirstMatch, parseContents } from './parse-contents';
64
+ import { parseContents } from './parse-contents';
64
65
  import { DefaultResponseContentFactory, ResponseContentMatcher, ResponseContentMatcherProvider } from './response-content-matcher';
65
66
  import { ChatToolRequest, ChatToolRequestService } from './chat-tool-request-service';
66
67
 
@@ -389,28 +390,35 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent {
389
390
  }
390
391
 
391
392
  protected async addStreamResponse(languageModelResponse: LanguageModelStreamResponse, request: MutableChatRequestModel): Promise<void> {
392
- for await (const token of languageModelResponse.stream) {
393
- const newContents = this.parse(token, request);
394
- if (isArray(newContents)) {
395
- request.response.response.addContents(newContents);
396
- } else {
397
- request.response.response.addContent(newContents);
398
- }
399
-
400
- const lastContent = request.response.response.content.pop();
401
- if (lastContent === undefined) {
402
- return;
403
- }
404
- const text = lastContent.asString?.();
405
- if (text === undefined) {
406
- return;
407
- }
393
+ let completeTextBuffer = '';
394
+ let startIndex = Math.max(0, request.response.response.content.length - 1);
408
395
 
409
- const result: ChatResponseContent[] = findFirstMatch(this.contentMatchers, text) ? this.parseContents(text, request) : [];
410
- if (result.length > 0) {
411
- request.response.response.addContents(result);
396
+ for await (const token of languageModelResponse.stream) {
397
+ const newContent = this.parse(token, request);
398
+
399
+ if (!(isTextResponsePart(token) && token.content)) {
400
+ // For non-text tokens (like tool calls), add them directly
401
+ if (isArray(newContent)) {
402
+ request.response.response.addContents(newContent);
403
+ } else {
404
+ request.response.response.addContent(newContent);
405
+ }
406
+ // And reset the marker index and the text buffer as we skip matching across non-text tokens
407
+ startIndex = request.response.response.content.length - 1;
408
+ completeTextBuffer = '';
412
409
  } else {
413
- request.response.response.addContent(lastContent);
410
+ // parse the entire text so far (since beginning of the stream or last non-text token)
411
+ // and replace the entire content with the currently parsed content parts
412
+ completeTextBuffer += token.content;
413
+
414
+ const parsedContents = this.parseContents(completeTextBuffer, request);
415
+ const contentBeforeMarker = startIndex > 0
416
+ ? request.response.response.content.slice(0, startIndex)
417
+ : [];
418
+
419
+ request.response.response.clearContent();
420
+ request.response.response.addContents(contentBeforeMarker);
421
+ request.response.response.addContents(parsedContents);
414
422
  }
415
423
  }
416
424
  }
@@ -435,6 +443,9 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent {
435
443
  if (isThinkingResponsePart(token)) {
436
444
  return new ThinkingChatResponseContentImpl(token.thought, token.signature);
437
445
  }
446
+ if (isUsageResponsePart(token)) {
447
+ return [];
448
+ }
438
449
  return this.defaultContentFactory.create('', request);
439
450
  }
440
451