@agent-native/toolkit 0.14.2 → 0.15.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/dist/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/composer/ComposerPlusMenu.js +131 -35
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +40 -5
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/PastedTextChip.d.ts.map +1 -1
- package/dist/composer/PastedTextChip.js +26 -2
- package/dist/composer/PastedTextChip.js.map +1 -1
- package/dist/composer/PastedTextChip.spec.d.ts +2 -0
- package/dist/composer/PastedTextChip.spec.d.ts.map +1 -0
- package/dist/composer/PastedTextChip.spec.js +42 -0
- package/dist/composer/PastedTextChip.spec.js.map +1 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +26 -5
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +5 -3
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +291 -80
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.spec.js +60 -3
- package/dist/composer/TiptapComposer.spec.js.map +1 -1
- package/dist/composer/VoiceButton.d.ts.map +1 -1
- package/dist/composer/VoiceButton.js +24 -5
- package/dist/composer/VoiceButton.js.map +1 -1
- package/dist/composer/runtime-adapters.d.ts +1 -0
- package/dist/composer/runtime-adapters.d.ts.map +1 -1
- package/dist/composer/runtime-adapters.js +8 -1
- package/dist/composer/runtime-adapters.js.map +1 -1
- package/dist/composer/runtime-adapters.spec.js +15 -0
- package/dist/composer/runtime-adapters.spec.js.map +1 -1
- package/dist/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/composer/useRealtimeVoiceMode.js +204 -68
- package/dist/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/composer/useRealtimeVoiceMode.spec.js +27 -1
- package/dist/composer/useRealtimeVoiceMode.spec.js.map +1 -1
- package/dist/context-ui/ContextMeter.d.ts +3 -2
- package/dist/context-ui/ContextMeter.d.ts.map +1 -1
- package/dist/context-ui/ContextMeter.js +23 -3
- package/dist/context-ui/ContextMeter.js.map +1 -1
- package/dist/context-ui/ContextMeter.spec.d.ts +2 -0
- package/dist/context-ui/ContextMeter.spec.d.ts.map +1 -0
- package/dist/context-ui/ContextMeter.spec.js +52 -0
- package/dist/context-ui/ContextMeter.spec.js.map +1 -0
- package/dist/context-ui/ContextSegmentRow.d.ts +5 -3
- package/dist/context-ui/ContextSegmentRow.d.ts.map +1 -1
- package/dist/context-ui/ContextSegmentRow.js +74 -7
- package/dist/context-ui/ContextSegmentRow.js.map +1 -1
- package/dist/context-ui/ContextTreemap.d.ts +3 -2
- package/dist/context-ui/ContextTreemap.d.ts.map +1 -1
- package/dist/context-ui/ContextTreemap.js +5 -2
- package/dist/context-ui/ContextTreemap.js.map +1 -1
- package/dist/context-ui/ContextXRayPanel.d.ts +3 -2
- package/dist/context-ui/ContextXRayPanel.d.ts.map +1 -1
- package/dist/context-ui/ContextXRayPanel.js +112 -23
- package/dist/context-ui/ContextXRayPanel.js.map +1 -1
- package/dist/context-ui/types.d.ts +2 -0
- package/dist/context-ui/types.d.ts.map +1 -1
- package/dist/context-ui/types.js +7 -1
- package/dist/context-ui/types.js.map +1 -1
- package/package.json +2 -2
- package/src/composer/ComposerPlusMenu.tsx +170 -52
- package/src/composer/MentionPopover.tsx +43 -7
- package/src/composer/PastedTextChip.spec.tsx +58 -0
- package/src/composer/PastedTextChip.tsx +35 -7
- package/src/composer/PromptComposer.tsx +28 -7
- package/src/composer/TiptapComposer.spec.ts +90 -3
- package/src/composer/TiptapComposer.tsx +341 -82
- package/src/composer/VoiceButton.tsx +36 -11
- package/src/composer/runtime-adapters.spec.tsx +19 -0
- package/src/composer/runtime-adapters.tsx +12 -2
- package/src/composer/useRealtimeVoiceMode.spec.ts +34 -0
- package/src/composer/useRealtimeVoiceMode.tsx +219 -69
- package/src/context-ui/ContextMeter.spec.tsx +73 -0
- package/src/context-ui/ContextMeter.tsx +34 -4
- package/src/context-ui/ContextSegmentRow.tsx +111 -22
- package/src/context-ui/ContextTreemap.tsx +7 -1
- package/src/context-ui/ContextXRayPanel.tsx +138 -24
- package/src/context-ui/types.ts +14 -0
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
type AgentChatContextItem,
|
|
53
53
|
type AgentComposerReference,
|
|
54
54
|
type AgentComposerReferenceInsertPayload,
|
|
55
|
+
type ComposerTranslate,
|
|
55
56
|
type ReasoningEffort,
|
|
56
57
|
type VoiceContextPack,
|
|
57
58
|
useComposerRuntimeAdapters,
|
|
@@ -289,10 +290,12 @@ export function getOversizedDocumentAttachmentError(
|
|
|
289
290
|
options: {
|
|
290
291
|
maxBytes?: number;
|
|
291
292
|
label?: string;
|
|
293
|
+
translate?: ComposerTranslate;
|
|
292
294
|
} = {},
|
|
293
295
|
): string | null {
|
|
294
296
|
const maxBytes = options.maxBytes ?? MAX_DOCUMENT_ATTACHMENT_BYTES;
|
|
295
297
|
const label = options.label ?? "PDFs";
|
|
298
|
+
const t = options.translate;
|
|
296
299
|
for (const attachment of attachments) {
|
|
297
300
|
if (!attachment || typeof attachment !== "object") continue;
|
|
298
301
|
const candidate = attachment as Record<string, unknown>;
|
|
@@ -306,7 +309,17 @@ export function getOversizedDocumentAttachmentError(
|
|
|
306
309
|
: file.name;
|
|
307
310
|
const mb = (file.size / 1024 / 1024).toFixed(1);
|
|
308
311
|
const maxMb = (maxBytes / 1024 / 1024).toFixed(0);
|
|
309
|
-
return
|
|
312
|
+
return (
|
|
313
|
+
t?.("agentChat.composer.documentTooLarge", {
|
|
314
|
+
defaultValue:
|
|
315
|
+
'"{{name}}" is {{size}} MB. {{label}} are capped at {{maxSize}} MB to stay within message limits. Please reduce the file size or split it into smaller parts.',
|
|
316
|
+
name,
|
|
317
|
+
size: mb,
|
|
318
|
+
label,
|
|
319
|
+
maxSize: maxMb,
|
|
320
|
+
}) ??
|
|
321
|
+
`"${name}" is ${mb} MB. ${label} are capped at ${maxMb} MB to stay within message limits. Please reduce the file size or split it into smaller parts.`
|
|
322
|
+
);
|
|
310
323
|
}
|
|
311
324
|
return null;
|
|
312
325
|
}
|
|
@@ -356,10 +369,13 @@ export function displayableComposerModeMessage(options: {
|
|
|
356
369
|
messagePrefix: string;
|
|
357
370
|
trimmedText: string;
|
|
358
371
|
attachmentCount: number;
|
|
372
|
+
attachedContextFallback?: string;
|
|
359
373
|
}): string {
|
|
360
374
|
const modePrompt =
|
|
361
375
|
options.trimmedText ||
|
|
362
|
-
(options.attachmentCount > 0
|
|
376
|
+
(options.attachmentCount > 0
|
|
377
|
+
? (options.attachedContextFallback ?? "Use the attached context.")
|
|
378
|
+
: "");
|
|
363
379
|
return `${options.messagePrefix}${modePrompt}`;
|
|
364
380
|
}
|
|
365
381
|
|
|
@@ -408,14 +424,52 @@ export function handleComposerFileDrop(options: {
|
|
|
408
424
|
return true;
|
|
409
425
|
}
|
|
410
426
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
427
|
+
function builtInCommands(t: ComposerTranslate): SlashCommand[] {
|
|
428
|
+
return [
|
|
429
|
+
{
|
|
430
|
+
name: "clear",
|
|
431
|
+
description: t("agentChat.commands.clearShort", {
|
|
432
|
+
defaultValue: "Start a new chat",
|
|
433
|
+
}),
|
|
434
|
+
icon: "clear",
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
name: "new",
|
|
438
|
+
description: t("agentChat.commands.newShort", {
|
|
439
|
+
defaultValue: "Start a new chat",
|
|
440
|
+
}),
|
|
441
|
+
icon: "new",
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
name: "history",
|
|
445
|
+
description: t("agentChat.commands.history", {
|
|
446
|
+
defaultValue: "Browse all chats",
|
|
447
|
+
}),
|
|
448
|
+
icon: "history",
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
name: "plan",
|
|
452
|
+
description: t("agentChat.commands.plan", {
|
|
453
|
+
defaultValue: "Switch to read-only planning",
|
|
454
|
+
}),
|
|
455
|
+
icon: "plan",
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: "act",
|
|
459
|
+
description: t("agentChat.commands.act", {
|
|
460
|
+
defaultValue: "Switch back to acting",
|
|
461
|
+
}),
|
|
462
|
+
icon: "act",
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: "help",
|
|
466
|
+
description: t("agentChat.commands.help", {
|
|
467
|
+
defaultValue: "Show available commands",
|
|
468
|
+
}),
|
|
469
|
+
icon: "help",
|
|
470
|
+
},
|
|
471
|
+
];
|
|
472
|
+
}
|
|
419
473
|
|
|
420
474
|
function normalizeSlashCommandName(name: string): string {
|
|
421
475
|
return name.replace(/^\/+/, "").trim().toLowerCase();
|
|
@@ -448,19 +502,13 @@ function mergeSlashSkills(skills: SkillResult[]): SkillResult[] {
|
|
|
448
502
|
const COMPOSER_MODE_CONFIGS: Record<
|
|
449
503
|
ComposerMode,
|
|
450
504
|
{
|
|
451
|
-
label: string;
|
|
452
505
|
icon: React.ComponentType<{ className?: string }>;
|
|
453
|
-
placeholder: string;
|
|
454
|
-
messagePrefix: string;
|
|
455
506
|
getContext: (prompt: string) => string;
|
|
456
507
|
beforeSend?: () => void;
|
|
457
508
|
}
|
|
458
509
|
> = {
|
|
459
510
|
skill: {
|
|
460
|
-
label: "Create Skill",
|
|
461
511
|
icon: IconBulb,
|
|
462
|
-
placeholder: "Describe the skill you want to create...",
|
|
463
|
-
messagePrefix: "Create a skill: ",
|
|
464
512
|
getContext: (prompt) =>
|
|
465
513
|
`The user wants to create an agent skill. Their description: "${prompt}"
|
|
466
514
|
|
|
@@ -482,10 +530,7 @@ After creating, update the shared AGENTS.md resource to reference the new skill
|
|
|
482
530
|
Keep the skill concise (under 500 lines) and actionable.`,
|
|
483
531
|
},
|
|
484
532
|
job: {
|
|
485
|
-
label: "Schedule Task",
|
|
486
533
|
icon: IconClock,
|
|
487
|
-
placeholder: "Describe what should happen and when...",
|
|
488
|
-
messagePrefix: "Create a recurring job: ",
|
|
489
534
|
getContext: (prompt) =>
|
|
490
535
|
`The user wants to create a recurring job. Their description: "${prompt}"
|
|
491
536
|
|
|
@@ -498,10 +543,7 @@ Use the manage-jobs tool with action "create" to create this. You need to:
|
|
|
498
543
|
The job will run automatically on the schedule. Make the instructions specific — include which actions to call and what to do with results.`,
|
|
499
544
|
},
|
|
500
545
|
automation: {
|
|
501
|
-
label: "Create Automation",
|
|
502
546
|
icon: IconBolt,
|
|
503
|
-
placeholder: "Describe what you want to automate...",
|
|
504
|
-
messagePrefix: "Create an automation: ",
|
|
505
547
|
beforeSend: () => {
|
|
506
548
|
window.dispatchEvent(
|
|
507
549
|
new CustomEvent("agent-panel:set-mode", {
|
|
@@ -515,10 +557,7 @@ The job will run automatically on the schedule. Make the instructions specific
|
|
|
515
557
|
Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`,
|
|
516
558
|
},
|
|
517
559
|
extension: {
|
|
518
|
-
label: "Create Extension",
|
|
519
560
|
icon: IconTool,
|
|
520
|
-
placeholder: "Describe the interactive extension you want to build...",
|
|
521
|
-
messagePrefix: "Create an extension: ",
|
|
522
561
|
getContext: (prompt) =>
|
|
523
562
|
`The user wants to create an interactive extension (sandboxed mini-app). Their description: "${prompt}"
|
|
524
563
|
|
|
@@ -532,6 +571,60 @@ Prefer appAction()/appFetch() for app data. Some actions return JSON strings for
|
|
|
532
571
|
},
|
|
533
572
|
};
|
|
534
573
|
|
|
574
|
+
function localizedComposerModeConfig(mode: ComposerMode, t: ComposerTranslate) {
|
|
575
|
+
const config = COMPOSER_MODE_CONFIGS[mode];
|
|
576
|
+
const copies: Record<
|
|
577
|
+
ComposerMode,
|
|
578
|
+
{ label: string; placeholder: string; messagePrefix: string }
|
|
579
|
+
> = {
|
|
580
|
+
skill: {
|
|
581
|
+
label: t("agentChat.composer.createSkill", {
|
|
582
|
+
defaultValue: "Create Skill",
|
|
583
|
+
}),
|
|
584
|
+
placeholder: t("agentChat.composer.describeSkill", {
|
|
585
|
+
defaultValue: "Describe the skill you want to create...",
|
|
586
|
+
}),
|
|
587
|
+
messagePrefix: t("agentChat.composer.createSkillPrefix", {
|
|
588
|
+
defaultValue: "Create a skill: ",
|
|
589
|
+
}),
|
|
590
|
+
},
|
|
591
|
+
job: {
|
|
592
|
+
label: t("agentChat.composer.scheduleTask", {
|
|
593
|
+
defaultValue: "Schedule Task",
|
|
594
|
+
}),
|
|
595
|
+
placeholder: t("agentChat.composer.describeSchedule", {
|
|
596
|
+
defaultValue: "Describe what should happen and when...",
|
|
597
|
+
}),
|
|
598
|
+
messagePrefix: t("agentChat.composer.scheduleTaskPrefix", {
|
|
599
|
+
defaultValue: "Create a recurring job: ",
|
|
600
|
+
}),
|
|
601
|
+
},
|
|
602
|
+
automation: {
|
|
603
|
+
label: t("agentChat.composer.createAutomation", {
|
|
604
|
+
defaultValue: "Create Automation",
|
|
605
|
+
}),
|
|
606
|
+
placeholder: t("agentChat.composer.describeAutomation", {
|
|
607
|
+
defaultValue: "Describe what you want to automate...",
|
|
608
|
+
}),
|
|
609
|
+
messagePrefix: t("agentChat.composer.createAutomationPrefix", {
|
|
610
|
+
defaultValue: "Create an automation: ",
|
|
611
|
+
}),
|
|
612
|
+
},
|
|
613
|
+
extension: {
|
|
614
|
+
label: t("agentChat.composer.createExtension", {
|
|
615
|
+
defaultValue: "Create Extension",
|
|
616
|
+
}),
|
|
617
|
+
placeholder: t("agentChat.composer.describeExtension", {
|
|
618
|
+
defaultValue: "Describe the interactive extension you want to build...",
|
|
619
|
+
}),
|
|
620
|
+
messagePrefix: t("agentChat.composer.createExtensionPrefix", {
|
|
621
|
+
defaultValue: "Create an extension: ",
|
|
622
|
+
}),
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
return { ...config, ...copies[mode] };
|
|
626
|
+
}
|
|
627
|
+
|
|
535
628
|
function ComposerModeChip({
|
|
536
629
|
mode,
|
|
537
630
|
onRemove,
|
|
@@ -539,7 +632,8 @@ function ComposerModeChip({
|
|
|
539
632
|
mode: ComposerMode;
|
|
540
633
|
onRemove: () => void;
|
|
541
634
|
}) {
|
|
542
|
-
const
|
|
635
|
+
const t = useComposerRuntimeAdapters().translate!;
|
|
636
|
+
const config = localizedComposerModeConfig(mode, t);
|
|
543
637
|
const Icon = config.icon;
|
|
544
638
|
return (
|
|
545
639
|
<span className="inline-flex items-center gap-1 rounded-md border border-border bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground">
|
|
@@ -761,25 +855,37 @@ function ModeSelector({
|
|
|
761
855
|
mode,
|
|
762
856
|
onChange,
|
|
763
857
|
planModeDisabled = false,
|
|
764
|
-
planModeDisabledReason
|
|
858
|
+
planModeDisabledReason,
|
|
765
859
|
}: {
|
|
766
860
|
mode: ExecMode;
|
|
767
861
|
onChange: (mode: ExecMode) => void;
|
|
768
862
|
planModeDisabled?: boolean;
|
|
769
863
|
planModeDisabledReason?: string;
|
|
770
864
|
}) {
|
|
865
|
+
const t = useComposerRuntimeAdapters().translate!;
|
|
771
866
|
const [open, setOpen] = useState(false);
|
|
867
|
+
const resolvedPlanModeDisabledReason =
|
|
868
|
+
planModeDisabledReason ??
|
|
869
|
+
t("agentChat.composer.planDesktopRequired", {
|
|
870
|
+
defaultValue: "Open Agent Native Desktop to use Plan mode.",
|
|
871
|
+
});
|
|
772
872
|
|
|
773
873
|
return (
|
|
774
874
|
<Popover open={open} onOpenChange={setOpen}>
|
|
775
875
|
<PopoverTrigger asChild>
|
|
776
876
|
<button
|
|
777
877
|
type="button"
|
|
778
|
-
aria-label={
|
|
878
|
+
aria-label={
|
|
879
|
+
mode === "build"
|
|
880
|
+
? t("agentChat.composer.actMode", { defaultValue: "Act mode" })
|
|
881
|
+
: t("agentChat.plan.mode", { defaultValue: "Plan mode" })
|
|
882
|
+
}
|
|
779
883
|
data-agent-composer-slot="mode-button"
|
|
780
884
|
className="agent-composer-mode-button shrink-0 flex items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
781
885
|
>
|
|
782
|
-
{mode === "build"
|
|
886
|
+
{mode === "build"
|
|
887
|
+
? t("agentChat.plan.act", { defaultValue: "Act" })
|
|
888
|
+
: t("agentChat.composer.plan", { defaultValue: "Plan" })}
|
|
783
889
|
<IconChevronDown className="h-3 w-3 opacity-60" />
|
|
784
890
|
</button>
|
|
785
891
|
</PopoverTrigger>
|
|
@@ -802,9 +908,13 @@ function ModeSelector({
|
|
|
802
908
|
>
|
|
803
909
|
<IconPencil className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
804
910
|
<div className="flex-1 min-w-0">
|
|
805
|
-
<span className="font-medium text-foreground text-[13px]">
|
|
911
|
+
<span className="font-medium text-foreground text-[13px]">
|
|
912
|
+
{t("agentChat.plan.act", { defaultValue: "Act" })}
|
|
913
|
+
</span>
|
|
806
914
|
<p className="text-[11px] text-muted-foreground mt-0.5">
|
|
807
|
-
|
|
915
|
+
{t("agentChat.composer.actDescription", {
|
|
916
|
+
defaultValue: "Use tools and make approved changes",
|
|
917
|
+
})}
|
|
808
918
|
</p>
|
|
809
919
|
</div>
|
|
810
920
|
{mode === "build" && (
|
|
@@ -814,7 +924,7 @@ function ModeSelector({
|
|
|
814
924
|
<button
|
|
815
925
|
type="button"
|
|
816
926
|
disabled={planModeDisabled}
|
|
817
|
-
title={planModeDisabled ?
|
|
927
|
+
title={planModeDisabled ? resolvedPlanModeDisabledReason : undefined}
|
|
818
928
|
onClick={() => {
|
|
819
929
|
if (planModeDisabled) return;
|
|
820
930
|
onChange("plan");
|
|
@@ -829,12 +939,14 @@ function ModeSelector({
|
|
|
829
939
|
<IconClipboardList className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
830
940
|
<div className="flex-1 min-w-0">
|
|
831
941
|
<span className="font-medium text-foreground text-[13px]">
|
|
832
|
-
Plan
|
|
942
|
+
{t("agentChat.composer.plan", { defaultValue: "Plan" })}
|
|
833
943
|
</span>
|
|
834
944
|
<p className="text-[11px] text-muted-foreground mt-0.5">
|
|
835
945
|
{planModeDisabled
|
|
836
|
-
?
|
|
837
|
-
: "
|
|
946
|
+
? resolvedPlanModeDisabledReason
|
|
947
|
+
: t("agentChat.composer.planDescription", {
|
|
948
|
+
defaultValue: "Read-only research and approval first",
|
|
949
|
+
})}
|
|
838
950
|
</p>
|
|
839
951
|
</div>
|
|
840
952
|
{mode === "plan" && !planModeDisabled && (
|
|
@@ -879,7 +991,14 @@ export function shouldShowOnlyConnectPath(
|
|
|
879
991
|
return showBuilderCta && groups.every((group) => !group.configured);
|
|
880
992
|
}
|
|
881
993
|
|
|
882
|
-
function friendlyModelName(model: string): string {
|
|
994
|
+
function friendlyModelName(model: string, t?: ComposerTranslate): string {
|
|
995
|
+
if (model === "auto") {
|
|
996
|
+
return (
|
|
997
|
+
t?.("agentChat.composer.defaultModel", {
|
|
998
|
+
defaultValue: "Default model",
|
|
999
|
+
}) ?? "Default model"
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
883
1002
|
if (FRIENDLY_MODEL_NAMES[model]) return FRIENDLY_MODEL_NAMES[model];
|
|
884
1003
|
// Claude: claude-{tier}-{major}[-minor][-dateYYYYMMDD] → Tier Major[.Minor]
|
|
885
1004
|
const claude = model.match(
|
|
@@ -929,23 +1048,74 @@ function friendlyModelName(model: string): string {
|
|
|
929
1048
|
return model;
|
|
930
1049
|
}
|
|
931
1050
|
|
|
932
|
-
export function compactComposerModelName(
|
|
1051
|
+
export function compactComposerModelName(
|
|
1052
|
+
model: string,
|
|
1053
|
+
t?: ComposerTranslate,
|
|
1054
|
+
): string {
|
|
933
1055
|
const gpt56Variant = model.match(
|
|
934
1056
|
/^(?:openai\/)?gpt-5[.-]6[.-](sol|terra|luna)$/i,
|
|
935
1057
|
)?.[1];
|
|
936
1058
|
if (gpt56Variant) {
|
|
937
|
-
|
|
1059
|
+
const variant =
|
|
1060
|
+
gpt56Variant[0].toUpperCase() + gpt56Variant.slice(1).toLowerCase();
|
|
1061
|
+
return `GPT-5.6 ${variant}`;
|
|
938
1062
|
}
|
|
939
|
-
return friendlyModelName(model);
|
|
1063
|
+
return friendlyModelName(model, t);
|
|
940
1064
|
}
|
|
941
1065
|
|
|
942
1066
|
export function compactComposerReasoningEffortLabel(
|
|
943
1067
|
effort: ReasoningEffort,
|
|
1068
|
+
t?: ComposerTranslate,
|
|
944
1069
|
): string {
|
|
945
|
-
if (effort === "medium" || effort === "auto")
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1070
|
+
if (effort === "medium" || effort === "auto") {
|
|
1071
|
+
return (
|
|
1072
|
+
t?.("agentChat.composer.reasoningMediumShort", {
|
|
1073
|
+
defaultValue: "Med",
|
|
1074
|
+
}) ?? "Med"
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
if (effort === "minimal") {
|
|
1078
|
+
return (
|
|
1079
|
+
t?.("agentChat.composer.reasoningMinimalShort", {
|
|
1080
|
+
defaultValue: "Min",
|
|
1081
|
+
}) ?? "Min"
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
if (effort === "xhigh") {
|
|
1085
|
+
return (
|
|
1086
|
+
t?.("agentChat.composer.reasoningExtraHighShort", {
|
|
1087
|
+
defaultValue: "XHigh",
|
|
1088
|
+
}) ?? "XHigh"
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
return t
|
|
1092
|
+
? localizedReasoningEffortLabel(t, effort, reasoningEffortLabel(effort))
|
|
1093
|
+
: reasoningEffortLabel(effort);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
function localizedReasoningEffortLabel(
|
|
1097
|
+
t: ComposerTranslate,
|
|
1098
|
+
effort: ReasoningEffort,
|
|
1099
|
+
defaultValue: string,
|
|
1100
|
+
): string {
|
|
1101
|
+
switch (effort) {
|
|
1102
|
+
case "auto":
|
|
1103
|
+
return t("agentChat.composer.reasoningEffort.auto", { defaultValue });
|
|
1104
|
+
case "none":
|
|
1105
|
+
return t("agentChat.composer.reasoningEffort.none", { defaultValue });
|
|
1106
|
+
case "minimal":
|
|
1107
|
+
return t("agentChat.composer.reasoningEffort.minimal", { defaultValue });
|
|
1108
|
+
case "low":
|
|
1109
|
+
return t("agentChat.composer.reasoningEffort.low", { defaultValue });
|
|
1110
|
+
case "medium":
|
|
1111
|
+
return t("agentChat.composer.reasoningEffort.medium", { defaultValue });
|
|
1112
|
+
case "high":
|
|
1113
|
+
return t("agentChat.composer.reasoningEffort.high", { defaultValue });
|
|
1114
|
+
case "xhigh":
|
|
1115
|
+
return t("agentChat.composer.reasoningEffort.xhigh", { defaultValue });
|
|
1116
|
+
case "max":
|
|
1117
|
+
return t("agentChat.composer.reasoningEffort.max", { defaultValue });
|
|
1118
|
+
}
|
|
949
1119
|
}
|
|
950
1120
|
|
|
951
1121
|
/**
|
|
@@ -997,16 +1167,21 @@ const MODEL_COST_TIERS: ReadonlyArray<readonly [string, 1 | 2 | 3]> = [
|
|
|
997
1167
|
["pro", 3],
|
|
998
1168
|
];
|
|
999
1169
|
|
|
1000
|
-
const COST_TIER_LABELS = { 1: "Lower", 2: "Medium", 3: "Higher" } as const;
|
|
1001
|
-
|
|
1002
1170
|
export function composerModelCostTier(model: string): 1 | 2 | 3 | undefined {
|
|
1003
1171
|
const normalized = model.toLowerCase();
|
|
1004
1172
|
return MODEL_COST_TIERS.find(([token]) => normalized.includes(token))?.[1];
|
|
1005
1173
|
}
|
|
1006
1174
|
|
|
1007
1175
|
function ModelCostTier({ model }: { model: string }) {
|
|
1176
|
+
const t = useComposerRuntimeAdapters().translate!;
|
|
1008
1177
|
const tier = composerModelCostTier(model);
|
|
1009
1178
|
if (!tier) return null;
|
|
1179
|
+
const costLabel =
|
|
1180
|
+
tier === 1
|
|
1181
|
+
? t("agentChat.composer.costLower", { defaultValue: "Lower cost" })
|
|
1182
|
+
: tier === 2
|
|
1183
|
+
? t("agentChat.composer.costMedium", { defaultValue: "Medium cost" })
|
|
1184
|
+
: t("agentChat.composer.costHigher", { defaultValue: "Higher cost" });
|
|
1010
1185
|
return (
|
|
1011
1186
|
<>
|
|
1012
1187
|
<span
|
|
@@ -1015,7 +1190,7 @@ function ModelCostTier({ model }: { model: string }) {
|
|
|
1015
1190
|
>
|
|
1016
1191
|
{"$".repeat(tier)}
|
|
1017
1192
|
</span>
|
|
1018
|
-
<span className="sr-only">{
|
|
1193
|
+
<span className="sr-only">{costLabel}</span>
|
|
1019
1194
|
</>
|
|
1020
1195
|
);
|
|
1021
1196
|
}
|
|
@@ -1102,7 +1277,15 @@ function ModelSelector({
|
|
|
1102
1277
|
const selectedEffort =
|
|
1103
1278
|
reasoning?.resolve?.(model, effort) ??
|
|
1104
1279
|
resolveReasoningEffortSelection(model, effort ?? defaultEffort);
|
|
1105
|
-
const effortLabel =
|
|
1280
|
+
const effortLabel = useCallback(
|
|
1281
|
+
(value: ReasoningEffort) =>
|
|
1282
|
+
localizedReasoningEffortLabel(
|
|
1283
|
+
t,
|
|
1284
|
+
value,
|
|
1285
|
+
(reasoning?.label ?? reasoningEffortLabel)(value),
|
|
1286
|
+
),
|
|
1287
|
+
[reasoning?.label, t],
|
|
1288
|
+
);
|
|
1106
1289
|
|
|
1107
1290
|
// Collapse non-selected families by default. The family containing the
|
|
1108
1291
|
// currently-selected model stays expanded so the user sees their pick at
|
|
@@ -1200,19 +1383,23 @@ function ModelSelector({
|
|
|
1200
1383
|
<button
|
|
1201
1384
|
type="button"
|
|
1202
1385
|
data-agent-composer-slot="model-button"
|
|
1203
|
-
aria-label={
|
|
1386
|
+
aria-label={`${t("agentChat.composer.model", {
|
|
1387
|
+
defaultValue: "Model",
|
|
1388
|
+
})}: ${friendlyModelName(model, t)}${
|
|
1204
1389
|
effortOptions.length > 0
|
|
1205
|
-
? `.
|
|
1390
|
+
? `. ${t("agentChat.composer.reasoning", {
|
|
1391
|
+
defaultValue: "Reasoning",
|
|
1392
|
+
})}: ${effortLabel(selectedEffort)}`
|
|
1206
1393
|
: ""
|
|
1207
1394
|
}`}
|
|
1208
1395
|
className="agent-composer-model-button flex min-w-0 max-w-[10.5rem] shrink items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
1209
1396
|
>
|
|
1210
1397
|
<span className="min-w-0 truncate">
|
|
1211
|
-
{compactComposerModelName(model)}
|
|
1398
|
+
{compactComposerModelName(model, t)}
|
|
1212
1399
|
</span>
|
|
1213
1400
|
{effortOptions.length > 0 && (
|
|
1214
1401
|
<span className="agent-composer-model-effort min-w-0 shrink truncate text-muted-foreground/70">
|
|
1215
|
-
· {compactComposerReasoningEffortLabel(selectedEffort)}
|
|
1402
|
+
· {compactComposerReasoningEffortLabel(selectedEffort, t)}
|
|
1216
1403
|
</span>
|
|
1217
1404
|
)}
|
|
1218
1405
|
<IconChevronDown className="h-3 w-3 shrink-0 opacity-60" />
|
|
@@ -1306,7 +1493,10 @@ function ModelSelector({
|
|
|
1306
1493
|
<IconChevronRight className="h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" />
|
|
1307
1494
|
)}
|
|
1308
1495
|
<span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0">
|
|
1309
|
-
{imageModel.label ??
|
|
1496
|
+
{imageModel.label ??
|
|
1497
|
+
t("agentChat.composer.imageModel", {
|
|
1498
|
+
defaultValue: "Image model",
|
|
1499
|
+
})}
|
|
1310
1500
|
</span>
|
|
1311
1501
|
{!imageExpanded && imageModelLabel && (
|
|
1312
1502
|
<span className="text-[11px] text-muted-foreground/80 truncate">
|
|
@@ -1348,7 +1538,7 @@ function ModelSelector({
|
|
|
1348
1538
|
className="flex w-full items-center gap-3 px-3 py-1.5 text-start hover:bg-accent/50"
|
|
1349
1539
|
>
|
|
1350
1540
|
<span className="flex-1 min-w-0 text-[13px] text-foreground truncate">
|
|
1351
|
-
Auto
|
|
1541
|
+
{t("agentChat.composer.auto", { defaultValue: "Auto" })}
|
|
1352
1542
|
</span>
|
|
1353
1543
|
{model === "auto" && (
|
|
1354
1544
|
<IconCheck className="h-3.5 w-3.5 shrink-0 text-blue-500" />
|
|
@@ -1374,8 +1564,10 @@ function ModelSelector({
|
|
|
1374
1564
|
group.statusLabel ??
|
|
1375
1565
|
(!group.configured
|
|
1376
1566
|
? canConnectLocalRuntime
|
|
1377
|
-
? "
|
|
1378
|
-
: "
|
|
1567
|
+
? t("agentChat.auth.logIn", { defaultValue: "Sign in" })
|
|
1568
|
+
: t("agentChat.composer.needsApiKey", {
|
|
1569
|
+
defaultValue: "needs API key",
|
|
1570
|
+
})
|
|
1379
1571
|
: undefined);
|
|
1380
1572
|
return (
|
|
1381
1573
|
<div key={groupKey}>
|
|
@@ -1392,7 +1584,7 @@ function ModelSelector({
|
|
|
1392
1584
|
</span>
|
|
1393
1585
|
{!isExpanded && groupKey === selectedGroupKey && (
|
|
1394
1586
|
<span className="text-[11px] text-muted-foreground/80 truncate">
|
|
1395
|
-
{friendlyModelName(model)}
|
|
1587
|
+
{friendlyModelName(model, t)}
|
|
1396
1588
|
</span>
|
|
1397
1589
|
)}
|
|
1398
1590
|
</button>
|
|
@@ -1447,7 +1639,7 @@ function ModelSelector({
|
|
|
1447
1639
|
}`}
|
|
1448
1640
|
>
|
|
1449
1641
|
<span className="flex-1 min-w-0 text-[13px] text-foreground truncate">
|
|
1450
|
-
{friendlyModelName(m)}
|
|
1642
|
+
{friendlyModelName(m, t)}
|
|
1451
1643
|
</span>
|
|
1452
1644
|
<ModelCostTier model={m} />
|
|
1453
1645
|
{m === model && group.configured && (
|
|
@@ -1476,7 +1668,9 @@ function ModelSelector({
|
|
|
1476
1668
|
<IconChevronRight className="h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" />
|
|
1477
1669
|
)}
|
|
1478
1670
|
<span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0">
|
|
1479
|
-
|
|
1671
|
+
{t("agentChat.composer.reasoning", {
|
|
1672
|
+
defaultValue: "Reasoning",
|
|
1673
|
+
})}
|
|
1480
1674
|
</span>
|
|
1481
1675
|
{!effortExpanded && (
|
|
1482
1676
|
<span className="text-[11px] text-muted-foreground/80 truncate">
|
|
@@ -1509,13 +1703,20 @@ function ModelSelector({
|
|
|
1509
1703
|
}
|
|
1510
1704
|
|
|
1511
1705
|
function ModelSelectorSkeleton() {
|
|
1706
|
+
const t = useComposerRuntimeAdapters().translate!;
|
|
1512
1707
|
return (
|
|
1513
1708
|
<div
|
|
1514
1709
|
className="space-y-1 px-2 py-2"
|
|
1515
1710
|
role="status"
|
|
1516
|
-
aria-label="
|
|
1711
|
+
aria-label={t("agentChat.composer.loadingModels", {
|
|
1712
|
+
defaultValue: "Loading models",
|
|
1713
|
+
})}
|
|
1517
1714
|
>
|
|
1518
|
-
<span className="sr-only">
|
|
1715
|
+
<span className="sr-only">
|
|
1716
|
+
{t("agentChat.composer.loadingModelsProgress", {
|
|
1717
|
+
defaultValue: "Loading models…",
|
|
1718
|
+
})}
|
|
1719
|
+
</span>
|
|
1519
1720
|
{["w-24", "w-32", "w-20", "w-28"].map((width, index) => (
|
|
1520
1721
|
<div key={index} className="flex items-center gap-1.5 px-1 py-1.5">
|
|
1521
1722
|
<Skeleton className="size-3 rounded-sm" />
|
|
@@ -1534,7 +1735,7 @@ type PopoverState = {
|
|
|
1534
1735
|
} | null;
|
|
1535
1736
|
|
|
1536
1737
|
export function TiptapComposer({
|
|
1537
|
-
placeholder
|
|
1738
|
+
placeholder,
|
|
1538
1739
|
disabled = false,
|
|
1539
1740
|
maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES,
|
|
1540
1741
|
documentAttachmentLimitLabel = "PDFs",
|
|
@@ -1649,10 +1850,10 @@ export function TiptapComposer({
|
|
|
1649
1850
|
const allSlashCommands = useMemo(
|
|
1650
1851
|
() =>
|
|
1651
1852
|
mergeSlashCommands([
|
|
1652
|
-
...(includeDefaultSlashCommands ?
|
|
1853
|
+
...(includeDefaultSlashCommands ? builtInCommands(t) : []),
|
|
1653
1854
|
...slashCommands,
|
|
1654
1855
|
]),
|
|
1655
|
-
[includeDefaultSlashCommands, slashCommands],
|
|
1856
|
+
[includeDefaultSlashCommands, slashCommands, t],
|
|
1656
1857
|
);
|
|
1657
1858
|
|
|
1658
1859
|
const allSlashSkills = useMemo(
|
|
@@ -1734,12 +1935,14 @@ export function TiptapComposer({
|
|
|
1734
1935
|
}, [composerRuntime]);
|
|
1735
1936
|
// Tiptap reads extension config once at init; ref keeps runtime prop
|
|
1736
1937
|
// changes visible to Placeholder's function form.
|
|
1737
|
-
const
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1938
|
+
const resolvedPlaceholder = composerMode
|
|
1939
|
+
? localizedComposerModeConfig(composerMode, t).placeholder
|
|
1940
|
+
: (placeholder ??
|
|
1941
|
+
t("agentChat.composer.messageAgent", {
|
|
1942
|
+
defaultValue: "Message agent...",
|
|
1943
|
+
}));
|
|
1944
|
+
const placeholderRef = useRef(resolvedPlaceholder);
|
|
1945
|
+
placeholderRef.current = resolvedPlaceholder;
|
|
1743
1946
|
|
|
1744
1947
|
const editor = useEditor({
|
|
1745
1948
|
extensions: createTiptapComposerExtensions(() => placeholderRef.current),
|
|
@@ -1828,7 +2031,10 @@ export function TiptapComposer({
|
|
|
1828
2031
|
const msg =
|
|
1829
2032
|
error instanceof Error
|
|
1830
2033
|
? error.message
|
|
1831
|
-
: "
|
|
2034
|
+
: t("agentChat.composer.pastedImageError", {
|
|
2035
|
+
defaultValue:
|
|
2036
|
+
"Could not attach the pasted image. Try a different format.",
|
|
2037
|
+
});
|
|
1832
2038
|
onAttachmentErrorRef.current?.(msg);
|
|
1833
2039
|
});
|
|
1834
2040
|
return true;
|
|
@@ -1849,7 +2055,9 @@ export function TiptapComposer({
|
|
|
1849
2055
|
const msg =
|
|
1850
2056
|
error instanceof Error
|
|
1851
2057
|
? error.message
|
|
1852
|
-
: "
|
|
2058
|
+
: t("agentChat.composer.pastedTextError", {
|
|
2059
|
+
defaultValue: "Could not attach the pasted text.",
|
|
2060
|
+
});
|
|
1853
2061
|
onAttachmentErrorRef.current?.(msg);
|
|
1854
2062
|
});
|
|
1855
2063
|
return true;
|
|
@@ -1868,7 +2076,10 @@ export function TiptapComposer({
|
|
|
1868
2076
|
const msg =
|
|
1869
2077
|
error instanceof Error
|
|
1870
2078
|
? error.message
|
|
1871
|
-
: "
|
|
2079
|
+
: t("agentChat.composer.droppedFileError", {
|
|
2080
|
+
defaultValue:
|
|
2081
|
+
"Could not attach the dropped file. Try a different format.",
|
|
2082
|
+
});
|
|
1872
2083
|
onAttachmentErrorRef.current?.(msg);
|
|
1873
2084
|
},
|
|
1874
2085
|
});
|
|
@@ -2047,6 +2258,13 @@ export function TiptapComposer({
|
|
|
2047
2258
|
},
|
|
2048
2259
|
});
|
|
2049
2260
|
|
|
2261
|
+
// Placeholder decorations are computed by ProseMirror. Dispatching an empty
|
|
2262
|
+
// transaction makes a locale or composer-mode change visible immediately.
|
|
2263
|
+
useEffect(() => {
|
|
2264
|
+
if (!isComposerEditorUsable(editor)) return;
|
|
2265
|
+
editor.view.dispatch(editor.state.tr.setSelection(editor.state.selection));
|
|
2266
|
+
}, [editor, resolvedPlaceholder]);
|
|
2267
|
+
|
|
2050
2268
|
// A tab can stay mounted while becoming the active composer later. Publish
|
|
2051
2269
|
// its existing draft when the host starts observing it so contextual UI is
|
|
2052
2270
|
// correct immediately after a tab switch, not only after the next keystroke.
|
|
@@ -2287,7 +2505,12 @@ export function TiptapComposer({
|
|
|
2287
2505
|
3200,
|
|
2288
2506
|
);
|
|
2289
2507
|
if (activeContext) {
|
|
2290
|
-
snippets.push({
|
|
2508
|
+
snippets.push({
|
|
2509
|
+
label: t("agentChat.composer.activeAppContext", {
|
|
2510
|
+
defaultValue: "Active app context",
|
|
2511
|
+
}),
|
|
2512
|
+
value: activeContext,
|
|
2513
|
+
});
|
|
2291
2514
|
}
|
|
2292
2515
|
|
|
2293
2516
|
const selectedReferences = trimVoiceContextValue(
|
|
@@ -2296,7 +2519,9 @@ export function TiptapComposer({
|
|
|
2296
2519
|
);
|
|
2297
2520
|
if (selectedReferences) {
|
|
2298
2521
|
snippets.push({
|
|
2299
|
-
label: "
|
|
2522
|
+
label: t("agentChat.composer.selectedReferences", {
|
|
2523
|
+
defaultValue: "Selected references",
|
|
2524
|
+
}),
|
|
2300
2525
|
value: selectedReferences,
|
|
2301
2526
|
});
|
|
2302
2527
|
}
|
|
@@ -2304,16 +2529,35 @@ export function TiptapComposer({
|
|
|
2304
2529
|
const draft = isComposerEditorUsable(editor)
|
|
2305
2530
|
? trimVoiceContextValue(editor.state.doc.textContent, 1200)
|
|
2306
2531
|
: null;
|
|
2307
|
-
if (draft)
|
|
2532
|
+
if (draft) {
|
|
2533
|
+
snippets.push({
|
|
2534
|
+
label: t("agentChat.composer.currentDraft", {
|
|
2535
|
+
defaultValue: "Current draft",
|
|
2536
|
+
}),
|
|
2537
|
+
value: draft,
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2308
2540
|
|
|
2309
2541
|
if (typeof document !== "undefined") {
|
|
2310
2542
|
const title = trimVoiceContextValue(document.title, 160);
|
|
2311
|
-
if (title)
|
|
2543
|
+
if (title) {
|
|
2544
|
+
snippets.push({
|
|
2545
|
+
label: t("agentChat.composer.pageTitle", {
|
|
2546
|
+
defaultValue: "Page title",
|
|
2547
|
+
}),
|
|
2548
|
+
value: title,
|
|
2549
|
+
});
|
|
2550
|
+
}
|
|
2312
2551
|
}
|
|
2313
2552
|
|
|
2314
2553
|
if (typeof window !== "undefined") {
|
|
2315
2554
|
const route = trimVoiceContextValue(window.location.pathname, 240);
|
|
2316
|
-
if (route)
|
|
2555
|
+
if (route) {
|
|
2556
|
+
snippets.push({
|
|
2557
|
+
label: t("agentChat.composer.route", { defaultValue: "Route" }),
|
|
2558
|
+
value: route,
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2317
2561
|
}
|
|
2318
2562
|
|
|
2319
2563
|
if (snippets.length === 0) return undefined;
|
|
@@ -2322,7 +2566,7 @@ export function TiptapComposer({
|
|
|
2322
2566
|
mode: "dictation",
|
|
2323
2567
|
snippets,
|
|
2324
2568
|
};
|
|
2325
|
-
}, [adapters, contextItems, editor, slotReferences]);
|
|
2569
|
+
}, [adapters, contextItems, editor, slotReferences, t]);
|
|
2326
2570
|
|
|
2327
2571
|
const voice = useVoiceDictation({
|
|
2328
2572
|
onTranscript: insertTranscript,
|
|
@@ -2552,6 +2796,7 @@ export function TiptapComposer({
|
|
|
2552
2796
|
{
|
|
2553
2797
|
maxBytes: maxDocumentAttachmentBytes,
|
|
2554
2798
|
label: documentAttachmentLimitLabel,
|
|
2799
|
+
translate: t,
|
|
2555
2800
|
},
|
|
2556
2801
|
);
|
|
2557
2802
|
if (oversizedDocumentError) {
|
|
@@ -2609,16 +2854,23 @@ export function TiptapComposer({
|
|
|
2609
2854
|
|
|
2610
2855
|
// Composer mode: send with context via agent chat bridge
|
|
2611
2856
|
if (composerMode) {
|
|
2612
|
-
const config =
|
|
2857
|
+
const config = localizedComposerModeConfig(composerMode, t);
|
|
2613
2858
|
config.beforeSend?.();
|
|
2614
2859
|
const message = displayableComposerModeMessage({
|
|
2615
2860
|
messagePrefix: config.messagePrefix,
|
|
2616
2861
|
trimmedText: trimmed,
|
|
2617
2862
|
attachmentCount: attachments.length,
|
|
2863
|
+
attachedContextFallback: t("agentChat.composer.useAttachedContext", {
|
|
2864
|
+
defaultValue: "Use the attached context.",
|
|
2865
|
+
}),
|
|
2618
2866
|
});
|
|
2619
2867
|
const modePrompt =
|
|
2620
2868
|
trimmed ||
|
|
2621
|
-
(attachments.length > 0
|
|
2869
|
+
(attachments.length > 0
|
|
2870
|
+
? t("agentChat.composer.useAttachedContext", {
|
|
2871
|
+
defaultValue: "Use the attached context.",
|
|
2872
|
+
})
|
|
2873
|
+
: "");
|
|
2622
2874
|
if (attachments.length > 0) {
|
|
2623
2875
|
composerRuntime.setText(
|
|
2624
2876
|
`${message}\n\n<context>\n${config.getContext(modePrompt)}\n</context>`,
|
|
@@ -2693,6 +2945,7 @@ export function TiptapComposer({
|
|
|
2693
2945
|
syncComposerState,
|
|
2694
2946
|
voice,
|
|
2695
2947
|
allSlashCommands,
|
|
2948
|
+
t,
|
|
2696
2949
|
],
|
|
2697
2950
|
);
|
|
2698
2951
|
|
|
@@ -2944,7 +3197,10 @@ export function TiptapComposer({
|
|
|
2944
3197
|
editor.commands.focus("end");
|
|
2945
3198
|
}
|
|
2946
3199
|
}}
|
|
2947
|
-
aria-label={
|
|
3200
|
+
aria-label={t("agentChat.composer.removeReference", {
|
|
3201
|
+
defaultValue: "Remove {{name}} reference",
|
|
3202
|
+
name: slotReferenceTitle(ref),
|
|
3203
|
+
})}
|
|
2948
3204
|
className="ms-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
2949
3205
|
>
|
|
2950
3206
|
<IconX className="h-3 w-3" />
|
|
@@ -2972,7 +3228,10 @@ export function TiptapComposer({
|
|
|
2972
3228
|
setSelectedContextItemKey(null);
|
|
2973
3229
|
onRemoveContextItem?.(item.key);
|
|
2974
3230
|
}}
|
|
2975
|
-
aria-label={
|
|
3231
|
+
aria-label={t("agentChat.composer.removeContext", {
|
|
3232
|
+
defaultValue: "Remove {{name}} context",
|
|
3233
|
+
name: item.title,
|
|
3234
|
+
})}
|
|
2976
3235
|
className="ms-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
2977
3236
|
>
|
|
2978
3237
|
<IconX className="h-3 w-3" />
|