@theia/ai-copilot 1.76.0-next.7 → 1.76.0
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 -1
- package/lib/browser/copilot-auth-dialog.d.ts.map +1 -1
- package/lib/browser/copilot-auth-dialog.js +7 -7
- package/lib/browser/copilot-auth-dialog.js.map +1 -1
- package/lib/browser/copilot-frontend-application-contribution.d.ts +6 -0
- package/lib/browser/copilot-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/copilot-frontend-application-contribution.js +77 -2
- package/lib/browser/copilot-frontend-application-contribution.js.map +1 -1
- package/lib/common/copilot-language-models-manager.d.ts +5 -3
- package/lib/common/copilot-language-models-manager.d.ts.map +1 -1
- package/lib/common/copilot-language-models-manager.js.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.d.ts +24 -2
- package/lib/node/copilot-language-models-manager-impl.d.ts.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.js +79 -4
- package/lib/node/copilot-language-models-manager-impl.js.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.spec.js +47 -4
- package/lib/node/copilot-language-models-manager-impl.spec.js.map +1 -1
- package/lib/node/copilot-sdk-language-model.d.ts +2 -2
- package/lib/node/copilot-sdk-language-model.d.ts.map +1 -1
- package/lib/node/copilot-sdk-language-model.js +4 -4
- package/lib/node/copilot-sdk-language-model.js.map +1 -1
- package/lib/node/copilot-sdk-language-model.spec.js +14 -1
- package/lib/node/copilot-sdk-language-model.spec.js.map +1 -1
- package/lib/node/copilot-sdk-mappers.d.ts +11 -6
- package/lib/node/copilot-sdk-mappers.d.ts.map +1 -1
- package/lib/node/copilot-sdk-mappers.js +28 -17
- package/lib/node/copilot-sdk-mappers.js.map +1 -1
- package/lib/node/copilot-sdk-mappers.spec.js +37 -2
- package/lib/node/copilot-sdk-mappers.spec.js.map +1 -1
- package/lib/node/copilot-sdk-types.d.ts +13 -3
- package/lib/node/copilot-sdk-types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/browser/copilot-auth-dialog.tsx +8 -8
- package/src/browser/copilot-frontend-application-contribution.ts +82 -2
- package/src/common/copilot-language-models-manager.ts +5 -3
- package/src/node/copilot-language-models-manager-impl.spec.ts +55 -4
- package/src/node/copilot-language-models-manager-impl.ts +86 -5
- package/src/node/copilot-sdk-language-model.spec.ts +17 -3
- package/src/node/copilot-sdk-language-model.ts +5 -4
- package/src/node/copilot-sdk-mappers.spec.ts +41 -2
- package/src/node/copilot-sdk-mappers.ts +31 -20
- package/src/node/copilot-sdk-types.ts +16 -2
|
@@ -14,14 +14,8 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { LanguageModelMessage } from '@theia/ai-core';
|
|
18
|
-
import type { ModelInfo, SystemMessageConfig } from './copilot-sdk-types';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Recognizes an id that names a dated release of another model, such as
|
|
22
|
-
* `gpt-4o-2024-11-20` or `claude-sonnet-5-20260514` for `gpt-4o` and `claude-sonnet-5`.
|
|
23
|
-
*/
|
|
24
|
-
const DATED_MODEL_ID = /^(.+?)-(\d{4}-\d{2}-\d{2}|\d{8})$/;
|
|
17
|
+
import { Base64ImageContent, ImageContent, ImageMessage, LanguageModelMessage } from '@theia/ai-core';
|
|
18
|
+
import type { BlobMessageAttachment, ModelInfo, SystemMessageConfig } from './copilot-sdk-types';
|
|
25
19
|
|
|
26
20
|
/**
|
|
27
21
|
* Selects the model IDs that should be surfaced to Theia from the list returned
|
|
@@ -30,12 +24,12 @@ const DATED_MODEL_ID = /^(.+?)-(\d{4}-\d{2}-\d{2}|\d{8})$/;
|
|
|
30
24
|
* Models whose policy is explicitly `disabled` are filtered out; `enabled` and
|
|
31
25
|
* `unconfigured` models are kept. Order is preserved and duplicates are removed.
|
|
32
26
|
*
|
|
33
|
-
* The list can name the same model both by its family and by its dated releases
|
|
34
|
-
*
|
|
35
|
-
*
|
|
27
|
+
* The list can name the same model both by its family and by its dated releases, and both are kept:
|
|
28
|
+
* the family is what the model pickers offer, while a dated release stays selectable for anyone who
|
|
29
|
+
* wants to pin one. This mirrors the other providers, where discovery reports every release and only
|
|
30
|
+
* the undated ids are featured.
|
|
36
31
|
*/
|
|
37
32
|
export function selectSdkModelIds(models: ModelInfo[]): string[] {
|
|
38
|
-
const available = new Set(models.filter(model => model.id && model.policy?.state !== 'disabled').map(model => model.id));
|
|
39
33
|
const result: string[] = [];
|
|
40
34
|
const seen = new Set<string>();
|
|
41
35
|
for (const model of models) {
|
|
@@ -45,10 +39,6 @@ export function selectSdkModelIds(models: ModelInfo[]): string[] {
|
|
|
45
39
|
if (model.policy && model.policy.state === 'disabled') {
|
|
46
40
|
continue;
|
|
47
41
|
}
|
|
48
|
-
const family = model.id.match(DATED_MODEL_ID)?.[1];
|
|
49
|
-
if (family && available.has(family)) {
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
42
|
seen.add(model.id);
|
|
53
43
|
result.push(model.id);
|
|
54
44
|
}
|
|
@@ -64,6 +54,8 @@ export interface SdkPrompt {
|
|
|
64
54
|
systemText: string;
|
|
65
55
|
/** The user-facing prompt body derived from the non-system messages. */
|
|
66
56
|
prompt: string;
|
|
57
|
+
/** Base64-encoded images pulled out of the user's messages, sent alongside the prompt. */
|
|
58
|
+
attachments?: BlobMessageAttachment[];
|
|
67
59
|
}
|
|
68
60
|
|
|
69
61
|
function roleLabel(message: LanguageModelMessage): string {
|
|
@@ -77,6 +69,17 @@ function roleLabel(message: LanguageModelMessage): string {
|
|
|
77
69
|
}
|
|
78
70
|
}
|
|
79
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Whether a message is a user image the SDK can be sent as a blob attachment.
|
|
74
|
+
*
|
|
75
|
+
* URL images are not covered: the SDK's attachments carry inline data, not a remote reference,
|
|
76
|
+
* and fetching the URL on the backend to inline it would add a server-side-request-forgery
|
|
77
|
+
* surface for what is, today, not a use case Theia exercises.
|
|
78
|
+
*/
|
|
79
|
+
function isAttachableImageMessage(message: LanguageModelMessage): message is ImageMessage & { image: Base64ImageContent } {
|
|
80
|
+
return LanguageModelMessage.isImageMessage(message) && message.actor === 'user' && ImageContent.isBase64(message.image);
|
|
81
|
+
}
|
|
82
|
+
|
|
80
83
|
function messageToText(message: LanguageModelMessage): string {
|
|
81
84
|
if (LanguageModelMessage.isTextMessage(message)) {
|
|
82
85
|
return message.text;
|
|
@@ -91,6 +94,7 @@ function messageToText(message: LanguageModelMessage): string {
|
|
|
91
94
|
return `[tool result: ${content}]`;
|
|
92
95
|
}
|
|
93
96
|
if (LanguageModelMessage.isImageMessage(message)) {
|
|
97
|
+
// Reached for URL images and non-user image messages; base64 user images are attachments instead, see buildSdkPrompt.
|
|
94
98
|
return '[image omitted]';
|
|
95
99
|
}
|
|
96
100
|
return '';
|
|
@@ -105,16 +109,23 @@ function messageToText(message: LanguageModelMessage): string {
|
|
|
105
109
|
* see {@link buildSdkSystemMessage}. A lone user turn is forwarded verbatim;
|
|
106
110
|
* richer histories are rendered as a role-labelled transcript.
|
|
107
111
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
112
|
+
* Base64 user images are pulled out of the history and sent as blob attachments instead of
|
|
113
|
+
* being flattened into the prompt text, see {@link isAttachableImageMessage}. This is otherwise
|
|
114
|
+
* a lossy mapping by design, see the limitations documented in the package README, and is
|
|
115
|
+
* intended for single-turn requests.
|
|
110
116
|
*/
|
|
111
117
|
export function buildSdkPrompt(messages: LanguageModelMessage[]): SdkPrompt {
|
|
112
118
|
const systemParts: string[] = [];
|
|
113
119
|
const conversation: LanguageModelMessage[] = [];
|
|
120
|
+
const attachments: BlobMessageAttachment[] = [];
|
|
114
121
|
for (const message of messages) {
|
|
115
122
|
if (message.actor === 'system' && LanguageModelMessage.isTextMessage(message)) {
|
|
116
123
|
systemParts.push(message.text);
|
|
117
|
-
} else if (message.type
|
|
124
|
+
} else if (message.type === 'thinking') {
|
|
125
|
+
continue;
|
|
126
|
+
} else if (isAttachableImageMessage(message)) {
|
|
127
|
+
attachments.push({ type: 'blob', data: message.image.base64data, mimeType: message.image.mimeType });
|
|
128
|
+
} else {
|
|
118
129
|
conversation.push(message);
|
|
119
130
|
}
|
|
120
131
|
}
|
|
@@ -131,7 +142,7 @@ export function buildSdkPrompt(messages: LanguageModelMessage[]): SdkPrompt {
|
|
|
131
142
|
.trim();
|
|
132
143
|
}
|
|
133
144
|
|
|
134
|
-
return { systemText, prompt };
|
|
145
|
+
return { systemText, prompt, attachments: attachments.length > 0 ? attachments : undefined };
|
|
135
146
|
}
|
|
136
147
|
|
|
137
148
|
/**
|
|
@@ -191,9 +191,23 @@ export interface CopilotSessionEvents {
|
|
|
191
191
|
export type CopilotSessionEventType = keyof CopilotSessionEvents;
|
|
192
192
|
|
|
193
193
|
// ============================================================================
|
|
194
|
-
// Session, from `dist/session.d.ts`
|
|
194
|
+
// Session, from `dist/session.d.ts` and `dist/types.d.ts`
|
|
195
195
|
// ============================================================================
|
|
196
196
|
|
|
197
|
+
/** The one attachment kind this integration produces: an inline image, from `MessageOptions['attachments']`. */
|
|
198
|
+
export interface BlobMessageAttachment {
|
|
199
|
+
type: 'blob';
|
|
200
|
+
data: string;
|
|
201
|
+
mimeType: string;
|
|
202
|
+
displayName?: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** The options this integration passes to {@link CopilotSession.send}. */
|
|
206
|
+
export interface MessageOptions {
|
|
207
|
+
prompt: string;
|
|
208
|
+
attachments?: BlobMessageAttachment[];
|
|
209
|
+
}
|
|
210
|
+
|
|
197
211
|
/** A conversation with the runtime, upstream a class with resume, fork and sharing on top. */
|
|
198
212
|
export interface CopilotSession {
|
|
199
213
|
readonly sessionId: string;
|
|
@@ -202,7 +216,7 @@ export interface CopilotSession {
|
|
|
202
216
|
*/
|
|
203
217
|
on<K extends CopilotSessionEventType>(eventType: K, handler: (event: CopilotSessionEvents[K]) => void): () => void;
|
|
204
218
|
/** Sends a turn and resolves with the id of the message it created. */
|
|
205
|
-
send(options:
|
|
219
|
+
send(options: MessageOptions): Promise<string>;
|
|
206
220
|
/** Stops the turn in flight. */
|
|
207
221
|
abort(): Promise<void>;
|
|
208
222
|
/** Releases the session in memory, leaving what it persisted in place. */
|