@agent-native/toolkit 0.16.0 → 0.16.2
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 +29 -19
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts +4 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +2 -2
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +12 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +249 -162
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.spec.js +33 -1
- package/dist/composer/TiptapComposer.spec.js.map +1 -1
- package/dist/composer/index.d.ts +1 -0
- package/dist/composer/index.d.ts.map +1 -1
- package/dist/composer/index.js +1 -0
- package/dist/composer/index.js.map +1 -1
- package/dist/composer/model-selection.d.ts +12 -0
- package/dist/composer/model-selection.d.ts.map +1 -0
- package/dist/composer/model-selection.js +31 -0
- package/dist/composer/model-selection.js.map +1 -0
- package/dist/composer/model-selection.spec.d.ts +2 -0
- package/dist/composer/model-selection.spec.d.ts.map +1 -0
- package/dist/composer/model-selection.spec.js +38 -0
- package/dist/composer/model-selection.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/composer/ComposerPlusMenu.tsx +122 -65
- package/src/composer/PromptComposer.tsx +8 -0
- package/src/composer/TiptapComposer.spec.ts +46 -0
- package/src/composer/TiptapComposer.tsx +678 -412
- package/src/composer/index.ts +6 -0
- package/src/composer/model-selection.spec.ts +45 -0
- package/src/composer/model-selection.ts +51 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function isClaudeCodeAgentId(agentId) {
|
|
2
|
+
return agentId === "claude-code" || agentId === "claude-cli";
|
|
3
|
+
}
|
|
4
|
+
export function isLunaModel(model) {
|
|
5
|
+
return model.toLowerCase().includes("luna");
|
|
6
|
+
}
|
|
7
|
+
export function resolvePreferredAgentModel(agentId, groups) {
|
|
8
|
+
const candidates = groups.flatMap((group) => group.models
|
|
9
|
+
.filter((model) => model !== "auto")
|
|
10
|
+
.map((model) => ({
|
|
11
|
+
model,
|
|
12
|
+
engine: group.engine,
|
|
13
|
+
configured: group.configured !== false,
|
|
14
|
+
})));
|
|
15
|
+
const orderedCandidates = [
|
|
16
|
+
...candidates.filter((candidate) => candidate.configured),
|
|
17
|
+
...candidates.filter((candidate) => !candidate.configured),
|
|
18
|
+
];
|
|
19
|
+
if (isClaudeCodeAgentId(agentId)) {
|
|
20
|
+
const preferred = orderedCandidates.find((candidate) => candidate.model.toLowerCase().includes("sonnet") &&
|
|
21
|
+
!isLunaModel(candidate.model)) ?? orderedCandidates.find((candidate) => !isLunaModel(candidate.model));
|
|
22
|
+
return preferred
|
|
23
|
+
? { model: preferred.model, engine: preferred.engine }
|
|
24
|
+
: undefined;
|
|
25
|
+
}
|
|
26
|
+
const preferred = orderedCandidates.find((candidate) => isLunaModel(candidate.model));
|
|
27
|
+
return preferred
|
|
28
|
+
? { model: preferred.model, engine: preferred.engine }
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=model-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selection.js","sourceRoot":"","sources":["../../src/composer/model-selection.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,mBAAmB,CAAC,OAA2B;IAC7D,OAAO,OAAO,KAAK,aAAa,IAAI,OAAO,KAAK,YAAY,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,OAA2B,EAC3B,MAAyC;IAEzC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAC1C,KAAK,CAAC,MAAM;SACT,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC;SACnC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,KAAK;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU,KAAK,KAAK;KACvC,CAAC,CAAC,CACN,CAAC;IACF,MAAM,iBAAiB,GAAG;QACxB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC;QACzD,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC;KAC3D,CAAC;IAEF,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,MAAM,SAAS,GACb,iBAAiB,CAAC,IAAI,CACpB,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAChD,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAChC,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5E,OAAO,SAAS;YACd,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE;YACtD,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CACrD,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAC7B,CAAC;IACF,OAAO,SAAS;QACd,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE;QACtD,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selection.spec.d.ts","sourceRoot":"","sources":["../../src/composer/model-selection.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { isClaudeCodeAgentId, isLunaModel, resolvePreferredAgentModel, } from "./model-selection.js";
|
|
3
|
+
describe("composer agent model defaults", () => {
|
|
4
|
+
const groups = [
|
|
5
|
+
{
|
|
6
|
+
engine: "builder",
|
|
7
|
+
models: ["gpt-5-6-luna"],
|
|
8
|
+
configured: true,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
engine: "builder",
|
|
12
|
+
models: ["claude-sonnet-5"],
|
|
13
|
+
configured: true,
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
it("identifies Claude Code and Luna model ids", () => {
|
|
17
|
+
expect(isClaudeCodeAgentId("claude-code")).toBe(true);
|
|
18
|
+
expect(isClaudeCodeAgentId("claude-cli")).toBe(true);
|
|
19
|
+
expect(isClaudeCodeAgentId("codex")).toBe(false);
|
|
20
|
+
expect(isLunaModel("gpt-5.6-luna")).toBe(true);
|
|
21
|
+
expect(isLunaModel("openai/gpt-5.6-sol")).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
it("defaults Claude Code to Sonnet and other agents to Luna", () => {
|
|
24
|
+
expect(resolvePreferredAgentModel("claude-code", groups)).toEqual({
|
|
25
|
+
engine: "builder",
|
|
26
|
+
model: "claude-sonnet-5",
|
|
27
|
+
});
|
|
28
|
+
expect(resolvePreferredAgentModel("codex", groups)).toEqual({
|
|
29
|
+
engine: "builder",
|
|
30
|
+
model: "gpt-5-6-luna",
|
|
31
|
+
});
|
|
32
|
+
expect(resolvePreferredAgentModel(undefined, groups)).toEqual({
|
|
33
|
+
engine: "builder",
|
|
34
|
+
model: "gpt-5-6-luna",
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=model-selection.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selection.spec.js","sourceRoot":"","sources":["../../src/composer/model-selection.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,0BAA0B,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,MAAM,MAAM,GAAG;QACb;YACE,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,CAAC,cAAc,CAAC;YACxB,UAAU,EAAE,IAAI;SACjB;QACD;YACE,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,CAAC,iBAAiB,CAAC;YAC3B,UAAU,EAAE,IAAI;SACjB;KACF,CAAC;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,0BAA0B,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAChE,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,iBAAiB;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1D,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,cAAc;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,0BAA0B,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5D,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,cAAc;SACtB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
IconLoader2,
|
|
12
12
|
IconArrowLeft,
|
|
13
13
|
IconX,
|
|
14
|
+
IconHelpCircle,
|
|
14
15
|
} from "@tabler/icons-react";
|
|
15
16
|
import React, {
|
|
16
17
|
useState,
|
|
@@ -196,6 +197,39 @@ function formatAttachmentError(error: unknown, fallback: string): string {
|
|
|
196
197
|
return error instanceof Error ? error.message : fallback;
|
|
197
198
|
}
|
|
198
199
|
|
|
200
|
+
function MenuItemHelp({
|
|
201
|
+
label,
|
|
202
|
+
description,
|
|
203
|
+
}: {
|
|
204
|
+
label: string;
|
|
205
|
+
description?: string;
|
|
206
|
+
}) {
|
|
207
|
+
const normalizedDescription = description?.trim();
|
|
208
|
+
if (!normalizedDescription) return null;
|
|
209
|
+
return (
|
|
210
|
+
<Tooltip>
|
|
211
|
+
<TooltipTrigger asChild>
|
|
212
|
+
<span
|
|
213
|
+
role="img"
|
|
214
|
+
tabIndex={0}
|
|
215
|
+
aria-label={`${label}: ${normalizedDescription}`}
|
|
216
|
+
onClick={(event) => event.stopPropagation()}
|
|
217
|
+
className="flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
218
|
+
>
|
|
219
|
+
<IconHelpCircle
|
|
220
|
+
aria-hidden="true"
|
|
221
|
+
className="size-3"
|
|
222
|
+
strokeWidth={1.8}
|
|
223
|
+
/>
|
|
224
|
+
</span>
|
|
225
|
+
</TooltipTrigger>
|
|
226
|
+
<TooltipContent side="right" className="max-w-xs">
|
|
227
|
+
{normalizedDescription}
|
|
228
|
+
</TooltipContent>
|
|
229
|
+
</Tooltip>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
199
233
|
function UploadOnlyAttachButton({
|
|
200
234
|
onAttachmentError,
|
|
201
235
|
}: Pick<ComposerPlusMenuProps, "onAttachmentError">) {
|
|
@@ -612,7 +646,11 @@ function ComposerPlusMenuFull({
|
|
|
612
646
|
return (
|
|
613
647
|
<div
|
|
614
648
|
key={item.label}
|
|
615
|
-
className={cn(
|
|
649
|
+
className={cn(
|
|
650
|
+
"relative flex items-center hover:bg-accent/50",
|
|
651
|
+
isSkill && "group/skill",
|
|
652
|
+
isSkill && skillFlyoutOpen && "bg-accent/50",
|
|
653
|
+
)}
|
|
616
654
|
onMouseEnter={(e) => {
|
|
617
655
|
if (isSkill) {
|
|
618
656
|
openSkillFlyout(e.currentTarget);
|
|
@@ -640,25 +678,25 @@ function ComposerPlusMenuFull({
|
|
|
640
678
|
type="button"
|
|
641
679
|
onClick={item.action}
|
|
642
680
|
className={cn(
|
|
643
|
-
"flex w-
|
|
644
|
-
isSkill && skillFlyoutOpen && "bg-accent/50",
|
|
681
|
+
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-2 text-start",
|
|
645
682
|
)}
|
|
646
683
|
>
|
|
647
684
|
<span className="text-muted-foreground">{item.icon}</span>
|
|
648
|
-
<
|
|
649
|
-
<
|
|
685
|
+
<span className="flex min-w-0 items-center gap-0.5">
|
|
686
|
+
<span className="min-w-0 truncate text-[12px] font-medium text-foreground">
|
|
650
687
|
{item.label}
|
|
651
|
-
</div>
|
|
652
|
-
<div className="mt-0.5 text-[10px] text-muted-foreground/60">
|
|
653
|
-
{item.desc}
|
|
654
|
-
</div>
|
|
655
|
-
</div>
|
|
656
|
-
{isSkill && (
|
|
657
|
-
<span className="ms-auto text-muted-foreground/60">
|
|
658
|
-
›
|
|
659
688
|
</span>
|
|
660
|
-
|
|
689
|
+
<MenuItemHelp
|
|
690
|
+
label={item.label}
|
|
691
|
+
description={item.desc}
|
|
692
|
+
/>
|
|
693
|
+
</span>
|
|
661
694
|
</button>
|
|
695
|
+
{isSkill && (
|
|
696
|
+
<span className="me-3 ms-auto text-muted-foreground/60">
|
|
697
|
+
›
|
|
698
|
+
</span>
|
|
699
|
+
)}
|
|
662
700
|
{isSkill && skillFlyoutOpen && (
|
|
663
701
|
<div
|
|
664
702
|
role="menu"
|
|
@@ -671,57 +709,76 @@ function ComposerPlusMenuFull({
|
|
|
671
709
|
: "right-full mr-1",
|
|
672
710
|
)}
|
|
673
711
|
>
|
|
674
|
-
<
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
<
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
<
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
"
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
>
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
<
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
712
|
+
<div className="flex items-center hover:bg-accent/50">
|
|
713
|
+
<button
|
|
714
|
+
type="button"
|
|
715
|
+
onClick={() => {
|
|
716
|
+
onSelectMode?.("skill");
|
|
717
|
+
setSkillFlyoutOpen(false);
|
|
718
|
+
setOpen(false);
|
|
719
|
+
}}
|
|
720
|
+
className="flex min-w-0 flex-1 items-center gap-2.5 px-3 py-2 text-start"
|
|
721
|
+
>
|
|
722
|
+
<span className="text-muted-foreground">
|
|
723
|
+
<IconBulb className="h-3.5 w-3.5" />
|
|
724
|
+
</span>
|
|
725
|
+
<span className="flex min-w-0 items-center gap-0.5">
|
|
726
|
+
<span className="min-w-0 truncate text-[12px] font-medium text-foreground">
|
|
727
|
+
{t("agentChat.composer.skill.createNew", {
|
|
728
|
+
defaultValue: "Create new skill",
|
|
729
|
+
})}
|
|
730
|
+
</span>
|
|
731
|
+
<MenuItemHelp
|
|
732
|
+
label={t("agentChat.composer.skill.createNew", {
|
|
733
|
+
defaultValue: "Create new skill",
|
|
734
|
+
})}
|
|
735
|
+
description={t(
|
|
736
|
+
"agentChat.composer.skill.createDescription",
|
|
737
|
+
{
|
|
738
|
+
defaultValue:
|
|
739
|
+
"Describe a skill and let the agent draft it",
|
|
740
|
+
},
|
|
741
|
+
)}
|
|
742
|
+
/>
|
|
743
|
+
</span>
|
|
744
|
+
</button>
|
|
745
|
+
</div>
|
|
746
|
+
<div className="flex items-center hover:bg-accent/50">
|
|
747
|
+
<button
|
|
748
|
+
type="button"
|
|
749
|
+
onClick={() => {
|
|
750
|
+
setSkillFlyoutOpen(false);
|
|
751
|
+
skillFileInputRef.current?.click();
|
|
752
|
+
}}
|
|
753
|
+
className="flex min-w-0 flex-1 items-center gap-2.5 px-3 py-2 text-start"
|
|
754
|
+
>
|
|
755
|
+
<span className="text-muted-foreground">
|
|
756
|
+
<IconUpload className="h-3.5 w-3.5" />
|
|
757
|
+
</span>
|
|
758
|
+
<span className="flex min-w-0 items-center gap-0.5">
|
|
759
|
+
<span className="min-w-0 truncate text-[12px] font-medium text-foreground">
|
|
760
|
+
{t("agentChat.composer.skill.uploadFile", {
|
|
761
|
+
defaultValue: "Upload skill file",
|
|
762
|
+
})}
|
|
763
|
+
</span>
|
|
764
|
+
<MenuItemHelp
|
|
765
|
+
label={t(
|
|
766
|
+
"agentChat.composer.skill.uploadFile",
|
|
767
|
+
{
|
|
768
|
+
defaultValue: "Upload skill file",
|
|
769
|
+
},
|
|
770
|
+
)}
|
|
771
|
+
description={t(
|
|
772
|
+
"agentChat.composer.skill.uploadDescription",
|
|
773
|
+
{
|
|
774
|
+
defaultValue:
|
|
775
|
+
"Import an existing SKILL.md file",
|
|
776
|
+
},
|
|
777
|
+
)}
|
|
778
|
+
/>
|
|
779
|
+
</span>
|
|
780
|
+
</button>
|
|
781
|
+
</div>
|
|
725
782
|
</div>
|
|
726
783
|
)}
|
|
727
784
|
</div>
|
|
@@ -100,6 +100,8 @@ export interface PromptComposerProps {
|
|
|
100
100
|
preserveDraftOnSubmit?: boolean;
|
|
101
101
|
/** Show the model selector (default: true). */
|
|
102
102
|
showModelSelector?: boolean;
|
|
103
|
+
/** Controlled open state for hosts that resize around the model picker. */
|
|
104
|
+
modelSelectorOpen?: boolean;
|
|
103
105
|
/** Show the legacy provider-level Auto model option (default: true). */
|
|
104
106
|
showAutoModelOption?: boolean;
|
|
105
107
|
/** Show the voice dictation button. Defaults to DEFAULT_VOICE_DICTATION_ENABLED. */
|
|
@@ -156,6 +158,8 @@ export interface PromptComposerProps {
|
|
|
156
158
|
selectedAgent?: string;
|
|
157
159
|
/** Callback when the user picks an agent runtime. */
|
|
158
160
|
onAgentChange?: (agent: string) => void;
|
|
161
|
+
/** Called when the shared model picker opens or closes. */
|
|
162
|
+
onModelSelectorOpenChange?: (open: boolean) => void;
|
|
159
163
|
/**
|
|
160
164
|
* Enable server-backed model/provider status checks. Defaults off when the
|
|
161
165
|
* host supplies model state and callbacks, otherwise on.
|
|
@@ -497,6 +501,7 @@ function PromptComposerInner({
|
|
|
497
501
|
draftScope,
|
|
498
502
|
preserveDraftOnSubmit = false,
|
|
499
503
|
showModelSelector = true,
|
|
504
|
+
modelSelectorOpen,
|
|
500
505
|
showAutoModelOption = true,
|
|
501
506
|
voiceEnabled = DEFAULT_VOICE_DICTATION_ENABLED,
|
|
502
507
|
attachmentsEnabled = true,
|
|
@@ -525,6 +530,7 @@ function PromptComposerInner({
|
|
|
525
530
|
availableAgents,
|
|
526
531
|
selectedAgent,
|
|
527
532
|
onAgentChange,
|
|
533
|
+
onModelSelectorOpenChange,
|
|
528
534
|
modelStatusChecksEnabled,
|
|
529
535
|
onTextChange,
|
|
530
536
|
onConnectProvider,
|
|
@@ -697,6 +703,7 @@ function PromptComposerInner({
|
|
|
697
703
|
onTextChange={onTextChange}
|
|
698
704
|
draftScope={draftScope}
|
|
699
705
|
selectedModel={composerModel}
|
|
706
|
+
modelSelectorOpen={modelSelectorOpen}
|
|
700
707
|
selectedEffort={composerEffort}
|
|
701
708
|
availableModels={composerModelGroups}
|
|
702
709
|
availableAgents={availableAgents}
|
|
@@ -706,6 +713,7 @@ function PromptComposerInner({
|
|
|
706
713
|
onModelChange={handleModelChange}
|
|
707
714
|
onEffortChange={handleEffortChange}
|
|
708
715
|
onAgentChange={onAgentChange}
|
|
716
|
+
onModelSelectorOpenChange={onModelSelectorOpenChange}
|
|
709
717
|
providerConnectStatusEnabled={resolvedModelStatusChecksEnabled}
|
|
710
718
|
onConnectProvider={onConnectProvider}
|
|
711
719
|
onConnectLocalRuntime={onConnectLocalRuntime}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
getOversizedDocumentAttachmentError,
|
|
19
19
|
handleComposerFileDrop,
|
|
20
20
|
insertComposerHardBreakAndScrollIntoView,
|
|
21
|
+
isOpenAiModelProviderGroup,
|
|
21
22
|
isComposerEditorUsable,
|
|
22
23
|
formatVoiceTranscriptForComposer,
|
|
23
24
|
MODEL_SELECTOR_POPOVER_STYLE,
|
|
@@ -106,6 +107,51 @@ describe("createTiptapComposerExtensions", () => {
|
|
|
106
107
|
);
|
|
107
108
|
});
|
|
108
109
|
|
|
110
|
+
it("limits Codex to OpenAI model providers", () => {
|
|
111
|
+
expect(
|
|
112
|
+
isOpenAiModelProviderGroup({
|
|
113
|
+
engine: "builder",
|
|
114
|
+
label: "OpenAI",
|
|
115
|
+
models: ["gpt-5.6-luna"],
|
|
116
|
+
}),
|
|
117
|
+
).toBe(true);
|
|
118
|
+
expect(
|
|
119
|
+
isOpenAiModelProviderGroup({
|
|
120
|
+
engine: "ai-sdk:google",
|
|
121
|
+
label: "Gemini",
|
|
122
|
+
models: ["gemini-3.5-flash"],
|
|
123
|
+
}),
|
|
124
|
+
).toBe(false);
|
|
125
|
+
expect(
|
|
126
|
+
isOpenAiModelProviderGroup({
|
|
127
|
+
engine: "custom-gateway",
|
|
128
|
+
label: "Custom",
|
|
129
|
+
models: ["gpt-5.6-luna"],
|
|
130
|
+
}),
|
|
131
|
+
).toBe(true);
|
|
132
|
+
expect(
|
|
133
|
+
isOpenAiModelProviderGroup({
|
|
134
|
+
engine: "ai-sdk:openrouter",
|
|
135
|
+
label: "OpenRouter",
|
|
136
|
+
models: ["openai/gpt-5.6-luna"],
|
|
137
|
+
}),
|
|
138
|
+
).toBe(true);
|
|
139
|
+
expect(
|
|
140
|
+
isOpenAiModelProviderGroup({
|
|
141
|
+
engine: "codex-cli",
|
|
142
|
+
label: "OpenAI",
|
|
143
|
+
models: ["gpt-5.6-luna"],
|
|
144
|
+
}),
|
|
145
|
+
).toBe(true);
|
|
146
|
+
expect(
|
|
147
|
+
isOpenAiModelProviderGroup({
|
|
148
|
+
engine: "codex-cli",
|
|
149
|
+
label: "OpenAI",
|
|
150
|
+
models: ["codex-cli"],
|
|
151
|
+
}),
|
|
152
|
+
).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
|
|
109
155
|
it("keeps the prompt composer schema minimal and restores legacy draft HTML", () => {
|
|
110
156
|
const editor = new Editor({
|
|
111
157
|
element: document.createElement("div"),
|