@agent-native/toolkit 0.14.3 → 0.15.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/agent-native.eject.json +19 -1
- package/dist/chat-history.css +3 -1
- 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 +289 -79
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.spec.js +57 -0
- 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/dist/design-system/default-adapter.d.ts.map +1 -1
- package/dist/design-system/default-adapter.js +4 -1
- package/dist/design-system/default-adapter.js.map +1 -1
- package/dist/design-system/default-adapter.spec.js +12 -0
- package/dist/design-system/default-adapter.spec.js.map +1 -1
- package/dist/design-system/types.d.ts +2 -0
- package/dist/design-system/types.d.ts.map +1 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +5 -2
- package/dist/provider.js.map +1 -1
- package/dist/sharing/SharePrimitives.d.ts +31 -0
- package/dist/sharing/SharePrimitives.d.ts.map +1 -0
- package/dist/sharing/SharePrimitives.js +45 -0
- package/dist/sharing/SharePrimitives.js.map +1 -0
- package/dist/sharing/index.d.ts +1 -0
- package/dist/sharing/index.d.ts.map +1 -1
- package/dist/sharing/index.js +1 -0
- package/dist/sharing/index.js.map +1 -1
- package/package.json +2 -2
- package/src/chat-history.css +3 -1
- 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 +85 -0
- package/src/composer/TiptapComposer.tsx +338 -81
- 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
- package/src/design-system/default-adapter.spec.tsx +15 -0
- package/src/design-system/default-adapter.tsx +5 -1
- package/src/design-system/types.ts +2 -0
- package/src/provider.tsx +9 -1
- package/src/sharing/SharePrimitives.tsx +185 -0
- package/src/sharing/index.ts +8 -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,7 +1048,10 @@ 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];
|
|
@@ -938,16 +1060,62 @@ export function compactComposerModelName(model: string): string {
|
|
|
938
1060
|
gpt56Variant[0].toUpperCase() + gpt56Variant.slice(1).toLowerCase();
|
|
939
1061
|
return `GPT-5.6 ${variant}`;
|
|
940
1062
|
}
|
|
941
|
-
return friendlyModelName(model);
|
|
1063
|
+
return friendlyModelName(model, t);
|
|
942
1064
|
}
|
|
943
1065
|
|
|
944
1066
|
export function compactComposerReasoningEffortLabel(
|
|
945
1067
|
effort: ReasoningEffort,
|
|
1068
|
+
t?: ComposerTranslate,
|
|
946
1069
|
): string {
|
|
947
|
-
if (effort === "medium" || effort === "auto")
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
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
|
+
}
|
|
951
1119
|
}
|
|
952
1120
|
|
|
953
1121
|
/**
|
|
@@ -999,16 +1167,21 @@ const MODEL_COST_TIERS: ReadonlyArray<readonly [string, 1 | 2 | 3]> = [
|
|
|
999
1167
|
["pro", 3],
|
|
1000
1168
|
];
|
|
1001
1169
|
|
|
1002
|
-
const COST_TIER_LABELS = { 1: "Lower", 2: "Medium", 3: "Higher" } as const;
|
|
1003
|
-
|
|
1004
1170
|
export function composerModelCostTier(model: string): 1 | 2 | 3 | undefined {
|
|
1005
1171
|
const normalized = model.toLowerCase();
|
|
1006
1172
|
return MODEL_COST_TIERS.find(([token]) => normalized.includes(token))?.[1];
|
|
1007
1173
|
}
|
|
1008
1174
|
|
|
1009
1175
|
function ModelCostTier({ model }: { model: string }) {
|
|
1176
|
+
const t = useComposerRuntimeAdapters().translate!;
|
|
1010
1177
|
const tier = composerModelCostTier(model);
|
|
1011
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" });
|
|
1012
1185
|
return (
|
|
1013
1186
|
<>
|
|
1014
1187
|
<span
|
|
@@ -1017,7 +1190,7 @@ function ModelCostTier({ model }: { model: string }) {
|
|
|
1017
1190
|
>
|
|
1018
1191
|
{"$".repeat(tier)}
|
|
1019
1192
|
</span>
|
|
1020
|
-
<span className="sr-only">{
|
|
1193
|
+
<span className="sr-only">{costLabel}</span>
|
|
1021
1194
|
</>
|
|
1022
1195
|
);
|
|
1023
1196
|
}
|
|
@@ -1104,7 +1277,15 @@ function ModelSelector({
|
|
|
1104
1277
|
const selectedEffort =
|
|
1105
1278
|
reasoning?.resolve?.(model, effort) ??
|
|
1106
1279
|
resolveReasoningEffortSelection(model, effort ?? defaultEffort);
|
|
1107
|
-
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
|
+
);
|
|
1108
1289
|
|
|
1109
1290
|
// Collapse non-selected families by default. The family containing the
|
|
1110
1291
|
// currently-selected model stays expanded so the user sees their pick at
|
|
@@ -1202,19 +1383,23 @@ function ModelSelector({
|
|
|
1202
1383
|
<button
|
|
1203
1384
|
type="button"
|
|
1204
1385
|
data-agent-composer-slot="model-button"
|
|
1205
|
-
aria-label={
|
|
1386
|
+
aria-label={`${t("agentChat.composer.model", {
|
|
1387
|
+
defaultValue: "Model",
|
|
1388
|
+
})}: ${friendlyModelName(model, t)}${
|
|
1206
1389
|
effortOptions.length > 0
|
|
1207
|
-
? `.
|
|
1390
|
+
? `. ${t("agentChat.composer.reasoning", {
|
|
1391
|
+
defaultValue: "Reasoning",
|
|
1392
|
+
})}: ${effortLabel(selectedEffort)}`
|
|
1208
1393
|
: ""
|
|
1209
1394
|
}`}
|
|
1210
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"
|
|
1211
1396
|
>
|
|
1212
1397
|
<span className="min-w-0 truncate">
|
|
1213
|
-
{compactComposerModelName(model)}
|
|
1398
|
+
{compactComposerModelName(model, t)}
|
|
1214
1399
|
</span>
|
|
1215
1400
|
{effortOptions.length > 0 && (
|
|
1216
1401
|
<span className="agent-composer-model-effort min-w-0 shrink truncate text-muted-foreground/70">
|
|
1217
|
-
· {compactComposerReasoningEffortLabel(selectedEffort)}
|
|
1402
|
+
· {compactComposerReasoningEffortLabel(selectedEffort, t)}
|
|
1218
1403
|
</span>
|
|
1219
1404
|
)}
|
|
1220
1405
|
<IconChevronDown className="h-3 w-3 shrink-0 opacity-60" />
|
|
@@ -1308,7 +1493,10 @@ function ModelSelector({
|
|
|
1308
1493
|
<IconChevronRight className="h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" />
|
|
1309
1494
|
)}
|
|
1310
1495
|
<span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0">
|
|
1311
|
-
{imageModel.label ??
|
|
1496
|
+
{imageModel.label ??
|
|
1497
|
+
t("agentChat.composer.imageModel", {
|
|
1498
|
+
defaultValue: "Image model",
|
|
1499
|
+
})}
|
|
1312
1500
|
</span>
|
|
1313
1501
|
{!imageExpanded && imageModelLabel && (
|
|
1314
1502
|
<span className="text-[11px] text-muted-foreground/80 truncate">
|
|
@@ -1350,7 +1538,7 @@ function ModelSelector({
|
|
|
1350
1538
|
className="flex w-full items-center gap-3 px-3 py-1.5 text-start hover:bg-accent/50"
|
|
1351
1539
|
>
|
|
1352
1540
|
<span className="flex-1 min-w-0 text-[13px] text-foreground truncate">
|
|
1353
|
-
Auto
|
|
1541
|
+
{t("agentChat.composer.auto", { defaultValue: "Auto" })}
|
|
1354
1542
|
</span>
|
|
1355
1543
|
{model === "auto" && (
|
|
1356
1544
|
<IconCheck className="h-3.5 w-3.5 shrink-0 text-blue-500" />
|
|
@@ -1376,8 +1564,10 @@ function ModelSelector({
|
|
|
1376
1564
|
group.statusLabel ??
|
|
1377
1565
|
(!group.configured
|
|
1378
1566
|
? canConnectLocalRuntime
|
|
1379
|
-
? "
|
|
1380
|
-
: "
|
|
1567
|
+
? t("agentChat.auth.logIn", { defaultValue: "Sign in" })
|
|
1568
|
+
: t("agentChat.composer.needsApiKey", {
|
|
1569
|
+
defaultValue: "needs API key",
|
|
1570
|
+
})
|
|
1381
1571
|
: undefined);
|
|
1382
1572
|
return (
|
|
1383
1573
|
<div key={groupKey}>
|
|
@@ -1394,7 +1584,7 @@ function ModelSelector({
|
|
|
1394
1584
|
</span>
|
|
1395
1585
|
{!isExpanded && groupKey === selectedGroupKey && (
|
|
1396
1586
|
<span className="text-[11px] text-muted-foreground/80 truncate">
|
|
1397
|
-
{friendlyModelName(model)}
|
|
1587
|
+
{friendlyModelName(model, t)}
|
|
1398
1588
|
</span>
|
|
1399
1589
|
)}
|
|
1400
1590
|
</button>
|
|
@@ -1449,7 +1639,7 @@ function ModelSelector({
|
|
|
1449
1639
|
}`}
|
|
1450
1640
|
>
|
|
1451
1641
|
<span className="flex-1 min-w-0 text-[13px] text-foreground truncate">
|
|
1452
|
-
{friendlyModelName(m)}
|
|
1642
|
+
{friendlyModelName(m, t)}
|
|
1453
1643
|
</span>
|
|
1454
1644
|
<ModelCostTier model={m} />
|
|
1455
1645
|
{m === model && group.configured && (
|
|
@@ -1478,7 +1668,9 @@ function ModelSelector({
|
|
|
1478
1668
|
<IconChevronRight className="h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" />
|
|
1479
1669
|
)}
|
|
1480
1670
|
<span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0">
|
|
1481
|
-
|
|
1671
|
+
{t("agentChat.composer.reasoning", {
|
|
1672
|
+
defaultValue: "Reasoning",
|
|
1673
|
+
})}
|
|
1482
1674
|
</span>
|
|
1483
1675
|
{!effortExpanded && (
|
|
1484
1676
|
<span className="text-[11px] text-muted-foreground/80 truncate">
|
|
@@ -1511,13 +1703,20 @@ function ModelSelector({
|
|
|
1511
1703
|
}
|
|
1512
1704
|
|
|
1513
1705
|
function ModelSelectorSkeleton() {
|
|
1706
|
+
const t = useComposerRuntimeAdapters().translate!;
|
|
1514
1707
|
return (
|
|
1515
1708
|
<div
|
|
1516
1709
|
className="space-y-1 px-2 py-2"
|
|
1517
1710
|
role="status"
|
|
1518
|
-
aria-label="
|
|
1711
|
+
aria-label={t("agentChat.composer.loadingModels", {
|
|
1712
|
+
defaultValue: "Loading models",
|
|
1713
|
+
})}
|
|
1519
1714
|
>
|
|
1520
|
-
<span className="sr-only">
|
|
1715
|
+
<span className="sr-only">
|
|
1716
|
+
{t("agentChat.composer.loadingModelsProgress", {
|
|
1717
|
+
defaultValue: "Loading models…",
|
|
1718
|
+
})}
|
|
1719
|
+
</span>
|
|
1521
1720
|
{["w-24", "w-32", "w-20", "w-28"].map((width, index) => (
|
|
1522
1721
|
<div key={index} className="flex items-center gap-1.5 px-1 py-1.5">
|
|
1523
1722
|
<Skeleton className="size-3 rounded-sm" />
|
|
@@ -1536,7 +1735,7 @@ type PopoverState = {
|
|
|
1536
1735
|
} | null;
|
|
1537
1736
|
|
|
1538
1737
|
export function TiptapComposer({
|
|
1539
|
-
placeholder
|
|
1738
|
+
placeholder,
|
|
1540
1739
|
disabled = false,
|
|
1541
1740
|
maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES,
|
|
1542
1741
|
documentAttachmentLimitLabel = "PDFs",
|
|
@@ -1651,10 +1850,10 @@ export function TiptapComposer({
|
|
|
1651
1850
|
const allSlashCommands = useMemo(
|
|
1652
1851
|
() =>
|
|
1653
1852
|
mergeSlashCommands([
|
|
1654
|
-
...(includeDefaultSlashCommands ?
|
|
1853
|
+
...(includeDefaultSlashCommands ? builtInCommands(t) : []),
|
|
1655
1854
|
...slashCommands,
|
|
1656
1855
|
]),
|
|
1657
|
-
[includeDefaultSlashCommands, slashCommands],
|
|
1856
|
+
[includeDefaultSlashCommands, slashCommands, t],
|
|
1658
1857
|
);
|
|
1659
1858
|
|
|
1660
1859
|
const allSlashSkills = useMemo(
|
|
@@ -1736,12 +1935,14 @@ export function TiptapComposer({
|
|
|
1736
1935
|
}, [composerRuntime]);
|
|
1737
1936
|
// Tiptap reads extension config once at init; ref keeps runtime prop
|
|
1738
1937
|
// changes visible to Placeholder's function form.
|
|
1739
|
-
const
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
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;
|
|
1745
1946
|
|
|
1746
1947
|
const editor = useEditor({
|
|
1747
1948
|
extensions: createTiptapComposerExtensions(() => placeholderRef.current),
|
|
@@ -1830,7 +2031,10 @@ export function TiptapComposer({
|
|
|
1830
2031
|
const msg =
|
|
1831
2032
|
error instanceof Error
|
|
1832
2033
|
? error.message
|
|
1833
|
-
: "
|
|
2034
|
+
: t("agentChat.composer.pastedImageError", {
|
|
2035
|
+
defaultValue:
|
|
2036
|
+
"Could not attach the pasted image. Try a different format.",
|
|
2037
|
+
});
|
|
1834
2038
|
onAttachmentErrorRef.current?.(msg);
|
|
1835
2039
|
});
|
|
1836
2040
|
return true;
|
|
@@ -1851,7 +2055,9 @@ export function TiptapComposer({
|
|
|
1851
2055
|
const msg =
|
|
1852
2056
|
error instanceof Error
|
|
1853
2057
|
? error.message
|
|
1854
|
-
: "
|
|
2058
|
+
: t("agentChat.composer.pastedTextError", {
|
|
2059
|
+
defaultValue: "Could not attach the pasted text.",
|
|
2060
|
+
});
|
|
1855
2061
|
onAttachmentErrorRef.current?.(msg);
|
|
1856
2062
|
});
|
|
1857
2063
|
return true;
|
|
@@ -1870,7 +2076,10 @@ export function TiptapComposer({
|
|
|
1870
2076
|
const msg =
|
|
1871
2077
|
error instanceof Error
|
|
1872
2078
|
? error.message
|
|
1873
|
-
: "
|
|
2079
|
+
: t("agentChat.composer.droppedFileError", {
|
|
2080
|
+
defaultValue:
|
|
2081
|
+
"Could not attach the dropped file. Try a different format.",
|
|
2082
|
+
});
|
|
1874
2083
|
onAttachmentErrorRef.current?.(msg);
|
|
1875
2084
|
},
|
|
1876
2085
|
});
|
|
@@ -2049,6 +2258,13 @@ export function TiptapComposer({
|
|
|
2049
2258
|
},
|
|
2050
2259
|
});
|
|
2051
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
|
+
|
|
2052
2268
|
// A tab can stay mounted while becoming the active composer later. Publish
|
|
2053
2269
|
// its existing draft when the host starts observing it so contextual UI is
|
|
2054
2270
|
// correct immediately after a tab switch, not only after the next keystroke.
|
|
@@ -2289,7 +2505,12 @@ export function TiptapComposer({
|
|
|
2289
2505
|
3200,
|
|
2290
2506
|
);
|
|
2291
2507
|
if (activeContext) {
|
|
2292
|
-
snippets.push({
|
|
2508
|
+
snippets.push({
|
|
2509
|
+
label: t("agentChat.composer.activeAppContext", {
|
|
2510
|
+
defaultValue: "Active app context",
|
|
2511
|
+
}),
|
|
2512
|
+
value: activeContext,
|
|
2513
|
+
});
|
|
2293
2514
|
}
|
|
2294
2515
|
|
|
2295
2516
|
const selectedReferences = trimVoiceContextValue(
|
|
@@ -2298,7 +2519,9 @@ export function TiptapComposer({
|
|
|
2298
2519
|
);
|
|
2299
2520
|
if (selectedReferences) {
|
|
2300
2521
|
snippets.push({
|
|
2301
|
-
label: "
|
|
2522
|
+
label: t("agentChat.composer.selectedReferences", {
|
|
2523
|
+
defaultValue: "Selected references",
|
|
2524
|
+
}),
|
|
2302
2525
|
value: selectedReferences,
|
|
2303
2526
|
});
|
|
2304
2527
|
}
|
|
@@ -2306,16 +2529,35 @@ export function TiptapComposer({
|
|
|
2306
2529
|
const draft = isComposerEditorUsable(editor)
|
|
2307
2530
|
? trimVoiceContextValue(editor.state.doc.textContent, 1200)
|
|
2308
2531
|
: null;
|
|
2309
|
-
if (draft)
|
|
2532
|
+
if (draft) {
|
|
2533
|
+
snippets.push({
|
|
2534
|
+
label: t("agentChat.composer.currentDraft", {
|
|
2535
|
+
defaultValue: "Current draft",
|
|
2536
|
+
}),
|
|
2537
|
+
value: draft,
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2310
2540
|
|
|
2311
2541
|
if (typeof document !== "undefined") {
|
|
2312
2542
|
const title = trimVoiceContextValue(document.title, 160);
|
|
2313
|
-
if (title)
|
|
2543
|
+
if (title) {
|
|
2544
|
+
snippets.push({
|
|
2545
|
+
label: t("agentChat.composer.pageTitle", {
|
|
2546
|
+
defaultValue: "Page title",
|
|
2547
|
+
}),
|
|
2548
|
+
value: title,
|
|
2549
|
+
});
|
|
2550
|
+
}
|
|
2314
2551
|
}
|
|
2315
2552
|
|
|
2316
2553
|
if (typeof window !== "undefined") {
|
|
2317
2554
|
const route = trimVoiceContextValue(window.location.pathname, 240);
|
|
2318
|
-
if (route)
|
|
2555
|
+
if (route) {
|
|
2556
|
+
snippets.push({
|
|
2557
|
+
label: t("agentChat.composer.route", { defaultValue: "Route" }),
|
|
2558
|
+
value: route,
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2319
2561
|
}
|
|
2320
2562
|
|
|
2321
2563
|
if (snippets.length === 0) return undefined;
|
|
@@ -2324,7 +2566,7 @@ export function TiptapComposer({
|
|
|
2324
2566
|
mode: "dictation",
|
|
2325
2567
|
snippets,
|
|
2326
2568
|
};
|
|
2327
|
-
}, [adapters, contextItems, editor, slotReferences]);
|
|
2569
|
+
}, [adapters, contextItems, editor, slotReferences, t]);
|
|
2328
2570
|
|
|
2329
2571
|
const voice = useVoiceDictation({
|
|
2330
2572
|
onTranscript: insertTranscript,
|
|
@@ -2554,6 +2796,7 @@ export function TiptapComposer({
|
|
|
2554
2796
|
{
|
|
2555
2797
|
maxBytes: maxDocumentAttachmentBytes,
|
|
2556
2798
|
label: documentAttachmentLimitLabel,
|
|
2799
|
+
translate: t,
|
|
2557
2800
|
},
|
|
2558
2801
|
);
|
|
2559
2802
|
if (oversizedDocumentError) {
|
|
@@ -2611,16 +2854,23 @@ export function TiptapComposer({
|
|
|
2611
2854
|
|
|
2612
2855
|
// Composer mode: send with context via agent chat bridge
|
|
2613
2856
|
if (composerMode) {
|
|
2614
|
-
const config =
|
|
2857
|
+
const config = localizedComposerModeConfig(composerMode, t);
|
|
2615
2858
|
config.beforeSend?.();
|
|
2616
2859
|
const message = displayableComposerModeMessage({
|
|
2617
2860
|
messagePrefix: config.messagePrefix,
|
|
2618
2861
|
trimmedText: trimmed,
|
|
2619
2862
|
attachmentCount: attachments.length,
|
|
2863
|
+
attachedContextFallback: t("agentChat.composer.useAttachedContext", {
|
|
2864
|
+
defaultValue: "Use the attached context.",
|
|
2865
|
+
}),
|
|
2620
2866
|
});
|
|
2621
2867
|
const modePrompt =
|
|
2622
2868
|
trimmed ||
|
|
2623
|
-
(attachments.length > 0
|
|
2869
|
+
(attachments.length > 0
|
|
2870
|
+
? t("agentChat.composer.useAttachedContext", {
|
|
2871
|
+
defaultValue: "Use the attached context.",
|
|
2872
|
+
})
|
|
2873
|
+
: "");
|
|
2624
2874
|
if (attachments.length > 0) {
|
|
2625
2875
|
composerRuntime.setText(
|
|
2626
2876
|
`${message}\n\n<context>\n${config.getContext(modePrompt)}\n</context>`,
|
|
@@ -2695,6 +2945,7 @@ export function TiptapComposer({
|
|
|
2695
2945
|
syncComposerState,
|
|
2696
2946
|
voice,
|
|
2697
2947
|
allSlashCommands,
|
|
2948
|
+
t,
|
|
2698
2949
|
],
|
|
2699
2950
|
);
|
|
2700
2951
|
|
|
@@ -2946,7 +3197,10 @@ export function TiptapComposer({
|
|
|
2946
3197
|
editor.commands.focus("end");
|
|
2947
3198
|
}
|
|
2948
3199
|
}}
|
|
2949
|
-
aria-label={
|
|
3200
|
+
aria-label={t("agentChat.composer.removeReference", {
|
|
3201
|
+
defaultValue: "Remove {{name}} reference",
|
|
3202
|
+
name: slotReferenceTitle(ref),
|
|
3203
|
+
})}
|
|
2950
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"
|
|
2951
3205
|
>
|
|
2952
3206
|
<IconX className="h-3 w-3" />
|
|
@@ -2974,7 +3228,10 @@ export function TiptapComposer({
|
|
|
2974
3228
|
setSelectedContextItemKey(null);
|
|
2975
3229
|
onRemoveContextItem?.(item.key);
|
|
2976
3230
|
}}
|
|
2977
|
-
aria-label={
|
|
3231
|
+
aria-label={t("agentChat.composer.removeContext", {
|
|
3232
|
+
defaultValue: "Remove {{name}} context",
|
|
3233
|
+
name: item.title,
|
|
3234
|
+
})}
|
|
2978
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"
|
|
2979
3236
|
>
|
|
2980
3237
|
<IconX className="h-3 w-3" />
|