@theia/ai-core 1.74.0-next.9 → 1.74.1
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/lib/browser/ai-configuration-service-impl.d.ts +32 -0
- package/lib/browser/ai-configuration-service-impl.d.ts.map +1 -0
- package/lib/browser/ai-configuration-service-impl.js +120 -0
- package/lib/browser/ai-configuration-service-impl.js.map +1 -0
- package/lib/browser/ai-configuration-service-impl.spec.d.ts +2 -0
- package/lib/browser/ai-configuration-service-impl.spec.d.ts.map +1 -0
- package/lib/browser/ai-configuration-service-impl.spec.js +214 -0
- package/lib/browser/ai-configuration-service-impl.spec.js.map +1 -0
- package/lib/browser/ai-core-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-core-frontend-module.js +4 -0
- package/lib/browser/ai-core-frontend-module.js.map +1 -1
- package/lib/browser/ai-settings-service.d.ts +2 -5
- package/lib/browser/ai-settings-service.d.ts.map +1 -1
- package/lib/browser/ai-settings-service.js +8 -15
- package/lib/browser/ai-settings-service.js.map +1 -1
- package/lib/browser/frontend-language-model-alias-registry.d.ts +2 -4
- package/lib/browser/frontend-language-model-alias-registry.d.ts.map +1 -1
- package/lib/browser/frontend-language-model-alias-registry.js +21 -26
- package/lib/browser/frontend-language-model-alias-registry.js.map +1 -1
- package/lib/browser/frontend-language-model-service.d.ts +2 -3
- package/lib/browser/frontend-language-model-service.d.ts.map +1 -1
- package/lib/browser/frontend-language-model-service.js +6 -6
- package/lib/browser/frontend-language-model-service.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/prompt-variable-contribution.d.ts.map +1 -1
- package/lib/browser/prompt-variable-contribution.js +13 -16
- package/lib/browser/prompt-variable-contribution.js.map +1 -1
- package/lib/browser/prompt-variable-contribution.spec.js +64 -2
- package/lib/browser/prompt-variable-contribution.spec.js.map +1 -1
- package/lib/browser/trust-aware-preference-reader.d.ts +13 -1
- package/lib/browser/trust-aware-preference-reader.d.ts.map +1 -1
- package/lib/browser/trust-aware-preference-reader.js +21 -2
- package/lib/browser/trust-aware-preference-reader.js.map +1 -1
- package/lib/browser/trust-aware-preference-reader.spec.js +26 -0
- package/lib/browser/trust-aware-preference-reader.spec.js.map +1 -1
- package/lib/common/ai-configuration-service.d.ts +104 -0
- package/lib/common/ai-configuration-service.d.ts.map +1 -0
- package/lib/common/ai-configuration-service.js +20 -0
- package/lib/common/ai-configuration-service.js.map +1 -0
- package/lib/common/ai-core-preferences.d.ts +4 -0
- package/lib/common/ai-core-preferences.d.ts.map +1 -1
- package/lib/common/ai-core-preferences.js +20 -1
- package/lib/common/ai-core-preferences.js.map +1 -1
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +1 -0
- package/lib/common/index.js.map +1 -1
- package/lib/common/language-model.d.ts +56 -2
- package/lib/common/language-model.d.ts.map +1 -1
- package/lib/common/language-model.js +53 -3
- package/lib/common/language-model.js.map +1 -1
- package/lib/common/language-model.spec.js +75 -0
- package/lib/common/language-model.spec.js.map +1 -1
- package/lib/common/prompt-service.d.ts +13 -0
- package/lib/common/prompt-service.d.ts.map +1 -1
- package/lib/common/prompt-service.js +8 -0
- package/lib/common/prompt-service.js.map +1 -1
- package/lib/common/prompt-service.spec.js +46 -0
- package/lib/common/prompt-service.spec.js.map +1 -1
- package/lib/node/backend-language-model-registry.d.ts.map +1 -1
- package/lib/node/backend-language-model-registry.js +1 -0
- package/lib/node/backend-language-model-registry.js.map +1 -1
- package/package.json +12 -12
- package/src/browser/ai-configuration-service-impl.spec.ts +254 -0
- package/src/browser/ai-configuration-service-impl.ts +120 -0
- package/src/browser/ai-core-frontend-module.ts +7 -1
- package/src/browser/ai-settings-service.ts +8 -16
- package/src/browser/frontend-language-model-alias-registry.ts +22 -26
- package/src/browser/frontend-language-model-service.ts +5 -6
- package/src/browser/index.ts +1 -0
- package/src/browser/prompt-variable-contribution.spec.ts +88 -2
- package/src/browser/prompt-variable-contribution.ts +13 -16
- package/src/browser/trust-aware-preference-reader.spec.ts +29 -0
- package/src/browser/trust-aware-preference-reader.ts +23 -3
- package/src/common/ai-configuration-service.ts +128 -0
- package/src/common/ai-core-preferences.ts +23 -1
- package/src/common/index.ts +1 -0
- package/src/common/language-model.spec.ts +98 -1
- package/src/common/language-model.ts +107 -4
- package/src/common/prompt-service.spec.ts +56 -0
- package/src/common/prompt-service.ts +22 -0
- package/src/node/backend-language-model-registry.ts +1 -0
|
@@ -42,7 +42,8 @@ export interface ReasoningSupport {
|
|
|
42
42
|
readonly defaultLevel?: ReasoningLevel;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export type LanguageModelMessage =
|
|
45
|
+
export type LanguageModelMessage =
|
|
46
|
+
TextMessage | ThinkingMessage | ToolUseMessage | ToolResultMessage | ServerToolUseMessage | ImageMessage | CompactionMessage;
|
|
46
47
|
export namespace LanguageModelMessage {
|
|
47
48
|
|
|
48
49
|
export function isTextMessage(obj: LanguageModelMessage): obj is TextMessage {
|
|
@@ -63,6 +64,9 @@ export namespace LanguageModelMessage {
|
|
|
63
64
|
export function isImageMessage(obj: LanguageModelMessage): obj is ImageMessage {
|
|
64
65
|
return obj.type === 'image';
|
|
65
66
|
}
|
|
67
|
+
export function isCompactionMessage(obj: LanguageModelMessage): obj is CompactionMessage {
|
|
68
|
+
return obj.type === 'compaction';
|
|
69
|
+
}
|
|
66
70
|
}
|
|
67
71
|
export interface TextMessage {
|
|
68
72
|
actor: MessageActor;
|
|
@@ -127,6 +131,17 @@ export interface ImageMessage {
|
|
|
127
131
|
image: ImageContent;
|
|
128
132
|
}
|
|
129
133
|
|
|
134
|
+
export interface CompactionMessage {
|
|
135
|
+
actor: 'ai';
|
|
136
|
+
type: 'compaction';
|
|
137
|
+
/** Originating provider tag; a backend replays the payload only when this matches its own provider. */
|
|
138
|
+
provider: string;
|
|
139
|
+
/** Opaque provider payload to replay. */
|
|
140
|
+
data: unknown;
|
|
141
|
+
/** Human-readable summary, when the provider exposes one. */
|
|
142
|
+
summary?: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
130
145
|
export const isLanguageModelRequestMessage = (obj: unknown): obj is LanguageModelMessage =>
|
|
131
146
|
!!(obj && typeof obj === 'object' &&
|
|
132
147
|
'type' in obj &&
|
|
@@ -304,6 +319,69 @@ export namespace ToolRequest {
|
|
|
304
319
|
(!('required' in obj) || (Array.isArray(obj.required) && obj.required.every(prop => typeof prop === 'string')));
|
|
305
320
|
}
|
|
306
321
|
}
|
|
322
|
+
// Anthropic requires at least 50,000 tokens, so use one conservative minimum for all compaction settings.
|
|
323
|
+
export const SERVER_SIDE_COMPACTION_TOKEN_THRESHOLD_MINIMUM = 50_000;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Per-session/per-request server-side compaction settings, carried verbatim from the chat
|
|
327
|
+
* session's common settings to the request. Kept as an object so further parameters can be
|
|
328
|
+
* added later.
|
|
329
|
+
*/
|
|
330
|
+
export interface CompactionSettings {
|
|
331
|
+
/** Explicit enablement for this session; when set it wins over the model's default. `undefined` means "no explicit choice". */
|
|
332
|
+
enabled?: boolean;
|
|
333
|
+
/** Input-token threshold for this session; when set it wins over the model's default. `undefined` preserves the provider default. */
|
|
334
|
+
tokenThreshold?: number;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Per-provider override for server-side compaction; combined with the global preference by {@link resolveCompactionDefault}. */
|
|
338
|
+
export type ServerSideCompactionSetting = 'default' | 'enabled' | 'disabled';
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Resolves a model's default server-side compaction enablement from the global preference and
|
|
342
|
+
* the per-provider override. `'enabled'`/`'disabled'` force the result; `'default'` defers to
|
|
343
|
+
* the global preference. Intended to be called where the preferences are read (the provider's
|
|
344
|
+
* frontend contribution) and stored on the model.
|
|
345
|
+
*/
|
|
346
|
+
export function resolveCompactionDefault(globalEnabled: boolean, perProviderOverride: ServerSideCompactionSetting): boolean {
|
|
347
|
+
if (perProviderOverride === 'enabled') {
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
if (perProviderOverride === 'disabled') {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
return globalEnabled;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export function resolveCompactionTokenThresholdDefault(
|
|
357
|
+
globalThreshold: number | undefined,
|
|
358
|
+
perProviderThreshold: number | undefined
|
|
359
|
+
): number | undefined {
|
|
360
|
+
return perProviderThreshold ?? globalThreshold;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function resolveCompactionTokenThreshold(
|
|
364
|
+
thresholdByDefault: number | undefined,
|
|
365
|
+
compaction: CompactionSettings | undefined
|
|
366
|
+
): number | undefined {
|
|
367
|
+
return compaction?.tokenThreshold ?? thresholdByDefault;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Resolves whether server-side compaction is effective for a request: the model must support it
|
|
372
|
+
* (capability), then an explicit per-session setting wins, otherwise the model's resolved default applies.
|
|
373
|
+
*/
|
|
374
|
+
export function resolveServerSideCompaction(
|
|
375
|
+
capability: boolean | undefined,
|
|
376
|
+
enabledByDefault: boolean,
|
|
377
|
+
compaction: CompactionSettings | undefined
|
|
378
|
+
): boolean {
|
|
379
|
+
if (!capability) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
return compaction?.enabled ?? enabledByDefault;
|
|
383
|
+
}
|
|
384
|
+
|
|
307
385
|
export interface LanguageModelRequest {
|
|
308
386
|
messages: LanguageModelMessage[],
|
|
309
387
|
tools?: ToolRequest[];
|
|
@@ -323,6 +401,8 @@ export interface LanguageModelRequest {
|
|
|
323
401
|
clientSettings?: { keepToolCalls: boolean; keepThinking: boolean };
|
|
324
402
|
/** Provider-agnostic reasoning configuration; providers translate it to their native API. */
|
|
325
403
|
reasoning?: ReasoningSettings;
|
|
404
|
+
/** Provider-agnostic server-side compaction settings, copied verbatim from the chat session. Resolved against the model's capability and default in the backend. */
|
|
405
|
+
compaction?: CompactionSettings;
|
|
326
406
|
}
|
|
327
407
|
export interface ResponseFormatJsonSchema {
|
|
328
408
|
type: 'json_schema';
|
|
@@ -378,10 +458,12 @@ export interface LanguageModelTextResponse {
|
|
|
378
458
|
export const isLanguageModelTextResponse = (obj: unknown): obj is LanguageModelTextResponse =>
|
|
379
459
|
!!(obj && typeof obj === 'object' && 'text' in obj && typeof (obj as { text: unknown }).text === 'string');
|
|
380
460
|
|
|
381
|
-
export type LanguageModelStreamResponsePart =
|
|
461
|
+
export type LanguageModelStreamResponsePart =
|
|
462
|
+
TextResponsePart | ToolCallResponsePart | ServerToolCallResponsePart | ThinkingResponsePart | UsageResponsePart | CompactionResponsePart;
|
|
382
463
|
|
|
383
464
|
export const isLanguageModelStreamResponsePart = (part: unknown): part is LanguageModelStreamResponsePart =>
|
|
384
|
-
isUsageResponsePart(part) || isTextResponsePart(part) || isThinkingResponsePart(part) ||
|
|
465
|
+
isUsageResponsePart(part) || isTextResponsePart(part) || isThinkingResponsePart(part) ||
|
|
466
|
+
isToolCallResponsePart(part) || isServerToolCallResponsePart(part) || isCompactionResponsePart(part);
|
|
385
467
|
|
|
386
468
|
export interface UsageResponsePart {
|
|
387
469
|
input_tokens: number;
|
|
@@ -432,6 +514,23 @@ export interface ThinkingResponsePart {
|
|
|
432
514
|
export const isThinkingResponsePart = (part: unknown): part is ThinkingResponsePart =>
|
|
433
515
|
!!(part && typeof part === 'object' && 'thought' in part && typeof part.thought === 'string');
|
|
434
516
|
|
|
517
|
+
export interface CompactionResponsePart {
|
|
518
|
+
compaction: {
|
|
519
|
+
/** Originating provider tag, e.g. 'anthropic' or 'openai-responses'. */
|
|
520
|
+
provider: string;
|
|
521
|
+
/** Opaque provider payload (Anthropic compaction block(s) / OpenAI compaction item). Never interpreted outside the originating backend. */
|
|
522
|
+
data: unknown;
|
|
523
|
+
/** Human-readable summary, when the provider exposes one. */
|
|
524
|
+
summary?: string;
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
export const isCompactionResponsePart = (part: unknown): part is CompactionResponsePart =>
|
|
528
|
+
!!(part && typeof part === 'object' && 'compaction' in part &&
|
|
529
|
+
typeof (part as CompactionResponsePart).compaction === 'object' &&
|
|
530
|
+
(part as CompactionResponsePart).compaction &&
|
|
531
|
+
'provider' in (part as CompactionResponsePart).compaction &&
|
|
532
|
+
typeof (part as CompactionResponsePart).compaction.provider === 'string');
|
|
533
|
+
|
|
435
534
|
export interface ToolCallTextResult { type: 'text', text: string; };
|
|
436
535
|
export interface ToolCallImageResult extends Base64ImageContent { type: 'image' };
|
|
437
536
|
export interface ToolCallAudioResult { type: 'audio', data: string; mimeType: string };
|
|
@@ -530,6 +629,8 @@ export interface LanguageModelMetaData {
|
|
|
530
629
|
* **Note:** If you provide these, you must also provide `vendor` because server tools are vendor-specific.
|
|
531
630
|
*/
|
|
532
631
|
readonly serverTools?: ServerToolDescriptor[];
|
|
632
|
+
/** Whether this model supports provider-native server-side compaction (capability, distinct from whether it is activated). */
|
|
633
|
+
readonly serverSideCompactionSupport?: boolean;
|
|
533
634
|
}
|
|
534
635
|
|
|
535
636
|
export namespace LanguageModelMetaData {
|
|
@@ -644,7 +745,9 @@ export class DefaultLanguageModelRegistryImpl implements LanguageModelRegistry {
|
|
|
644
745
|
|
|
645
746
|
async getLanguageModels(): Promise<LanguageModel[]> {
|
|
646
747
|
await this.initialized;
|
|
647
|
-
|
|
748
|
+
// Return a fresh array (not the internal, mutated-in-place list) so consumers relying on
|
|
749
|
+
// reference equality - e.g. React memoization in the chat model selector - detect changes.
|
|
750
|
+
return [...this.languageModels];
|
|
648
751
|
}
|
|
649
752
|
|
|
650
753
|
async getLanguageModel(id: string): Promise<LanguageModel | undefined> {
|
|
@@ -562,6 +562,62 @@ describe('PromptService', () => {
|
|
|
562
562
|
expect(fragment).to.be.undefined;
|
|
563
563
|
});
|
|
564
564
|
});
|
|
565
|
+
|
|
566
|
+
describe('isKnownCommand', () => {
|
|
567
|
+
it('accepts a registered command name', () => {
|
|
568
|
+
promptService.addBuiltInPromptFragment({
|
|
569
|
+
id: 'sample-debug',
|
|
570
|
+
template: 'Help debug: $ARGUMENTS',
|
|
571
|
+
isCommand: true,
|
|
572
|
+
commandName: 'debug'
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
expect(promptService.isKnownCommand('debug')).to.be.true;
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
it('accepts a command fragment referenced by its id', () => {
|
|
579
|
+
promptService.addBuiltInPromptFragment({
|
|
580
|
+
id: 'sample-debug',
|
|
581
|
+
template: 'Help debug: $ARGUMENTS',
|
|
582
|
+
isCommand: true,
|
|
583
|
+
commandName: 'debug'
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
expect(promptService.isKnownCommand('sample-debug')).to.be.true;
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
it('accepts the id of a fragment that is not marked as a command', () => {
|
|
590
|
+
// The `prompt` variable falls back to a plain fragment lookup, so `/normal-fragment`
|
|
591
|
+
// resolves and must therefore be recognized here as well.
|
|
592
|
+
promptService.addBuiltInPromptFragment({
|
|
593
|
+
id: 'normal-fragment',
|
|
594
|
+
template: 'Not a command'
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
expect(promptService.isKnownCommand('normal-fragment')).to.be.true;
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it('rejects unknown names', () => {
|
|
601
|
+
promptService.addBuiltInPromptFragment({
|
|
602
|
+
id: 'sample-debug',
|
|
603
|
+
template: 'Help debug: $ARGUMENTS',
|
|
604
|
+
isCommand: true,
|
|
605
|
+
commandName: 'debug'
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
expect(promptService.isKnownCommand('home')).to.be.false;
|
|
609
|
+
expect(promptService.isKnownCommand('usr')).to.be.false;
|
|
610
|
+
expect(promptService.isKnownCommand('debugger')).to.be.false;
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('rejects the empty name', () => {
|
|
614
|
+
expect(promptService.isKnownCommand('')).to.be.false;
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
it('rejects names when nothing is registered', () => {
|
|
618
|
+
expect(promptService.isKnownCommand('anything')).to.be.false;
|
|
619
|
+
});
|
|
620
|
+
});
|
|
565
621
|
});
|
|
566
622
|
|
|
567
623
|
describe('CustomAgentDescription', () => {
|
|
@@ -467,6 +467,19 @@ export interface PromptService {
|
|
|
467
467
|
*/
|
|
468
468
|
getPromptFragmentByCommandName(commandName: string): PromptFragment | undefined;
|
|
469
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Checks whether `/name` can be resolved as a slash command.
|
|
472
|
+
*
|
|
473
|
+
* This mirrors the lookup performed when resolving the `prompt` variable: the name may either be
|
|
474
|
+
* the command name of a fragment marked as a command, or the id of any existing prompt fragment.
|
|
475
|
+
* Use this before interpreting a `/name` token as a command, so that unrelated text such as Unix
|
|
476
|
+
* paths is not mistaken for a command.
|
|
477
|
+
*
|
|
478
|
+
* @param name The command name or prompt fragment id
|
|
479
|
+
* @returns `true` if a matching command or prompt fragment exists
|
|
480
|
+
*/
|
|
481
|
+
isKnownCommand(name: string): boolean;
|
|
482
|
+
|
|
470
483
|
/**
|
|
471
484
|
* Resolves a prompt fragment by replacing variables and function references
|
|
472
485
|
* @param fragmentId The prompt fragment ID
|
|
@@ -758,6 +771,15 @@ export class PromptServiceImpl implements PromptService {
|
|
|
758
771
|
);
|
|
759
772
|
}
|
|
760
773
|
|
|
774
|
+
isKnownCommand(name: string): boolean {
|
|
775
|
+
if (!name) {
|
|
776
|
+
return false;
|
|
777
|
+
}
|
|
778
|
+
// Both lookups are needed because the `prompt` variable resolves a command either by its
|
|
779
|
+
// command name or, as a fallback, by prompt fragment id.
|
|
780
|
+
return this.getPromptFragmentByCommandName(name) !== undefined || this.getRawPromptFragment(name) !== undefined;
|
|
781
|
+
}
|
|
782
|
+
|
|
761
783
|
/**
|
|
762
784
|
* Strips comments from a template string
|
|
763
785
|
* @param templateText The template text to process
|
|
@@ -64,6 +64,7 @@ export class BackendLanguageModelRegistryImpl extends DefaultLanguageModelRegist
|
|
|
64
64
|
maxOutputTokens: model.maxOutputTokens,
|
|
65
65
|
reasoningSupport: model.reasoningSupport,
|
|
66
66
|
serverTools: model.serverTools,
|
|
67
|
+
serverSideCompactionSupport: model.serverSideCompactionSupport,
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
}
|