@stigmer/react 3.12.4 → 3.12.6
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/AgentDetailView.js +2 -2
- package/agent/AgentDetailView.js.map +1 -1
- package/agent/index.d.ts +0 -1
- package/agent/index.d.ts.map +1 -1
- package/agent/index.js +0 -1
- package/agent/index.js.map +1 -1
- package/agent/useUpdateAgent.d.ts +3 -3
- package/agent/useUpdateAgent.js +3 -3
- package/agent-instance/AgentInstanceDetailPanel.d.ts.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.js +5 -7
- package/agent-instance/AgentInstanceDetailPanel.js.map +1 -1
- package/agent-instance/useUpdateAgentInstance.d.ts +1 -1
- package/agent-instance/useUpdateAgentInstance.js +1 -1
- package/attachment/AttachmentChipList.js +16 -6
- package/attachment/AttachmentChipList.js.map +1 -1
- package/attachment/index.d.ts +1 -1
- package/attachment/index.d.ts.map +1 -1
- package/attachment/index.js.map +1 -1
- package/attachment/useAttachments.d.ts +51 -8
- package/attachment/useAttachments.d.ts.map +1 -1
- package/attachment/useAttachments.js +74 -3
- package/attachment/useAttachments.js.map +1 -1
- package/channel/AgentChannelsPanel.d.ts.map +1 -1
- package/channel/AgentChannelsPanel.js +10 -5
- package/channel/AgentChannelsPanel.js.map +1 -1
- package/channel/ChannelRunConfigDialog.d.ts +51 -0
- package/channel/ChannelRunConfigDialog.d.ts.map +1 -0
- package/channel/ChannelRunConfigDialog.js +121 -0
- package/channel/ChannelRunConfigDialog.js.map +1 -0
- package/channel/index.d.ts +2 -0
- package/channel/index.d.ts.map +1 -1
- package/channel/index.js +1 -0
- package/channel/index.js.map +1 -1
- package/channel/useSaveAgentChannel.d.ts.map +1 -1
- package/channel/useSaveAgentChannel.js +6 -3
- package/channel/useSaveAgentChannel.js.map +1 -1
- package/channel-app/ChannelAppDetailPanel.js +9 -9
- package/channel-app/ChannelAppDetailPanel.js.map +1 -1
- package/composer/ComposerToolbar.d.ts +6 -1
- package/composer/ComposerToolbar.d.ts.map +1 -1
- package/composer/ComposerToolbar.js +2 -2
- package/composer/ComposerToolbar.js.map +1 -1
- package/composer/SessionComposer.d.ts +9 -0
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +39 -13
- package/composer/SessionComposer.js.map +1 -1
- package/conversation/ConversationComposer.d.ts +19 -3
- package/conversation/ConversationComposer.d.ts.map +1 -1
- package/conversation/ConversationComposer.js +4 -4
- package/conversation/ConversationComposer.js.map +1 -1
- package/conversation/ConversationTemplatePickerDialog.d.ts +63 -0
- package/conversation/ConversationTemplatePickerDialog.d.ts.map +1 -0
- package/conversation/ConversationTemplatePickerDialog.js +151 -0
- package/conversation/ConversationTemplatePickerDialog.js.map +1 -0
- package/conversation/ConversationsWorkbench.d.ts.map +1 -1
- package/conversation/ConversationsWorkbench.js +16 -5
- package/conversation/ConversationsWorkbench.js.map +1 -1
- package/conversation/index.d.ts +3 -1
- package/conversation/index.d.ts.map +1 -1
- package/conversation/index.js +1 -0
- package/conversation/index.js.map +1 -1
- package/conversation/useConversationParticipation.d.ts +41 -4
- package/conversation/useConversationParticipation.d.ts.map +1 -1
- package/conversation/useConversationParticipation.js +13 -2
- package/conversation/useConversationParticipation.js.map +1 -1
- package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -1
- package/cursor-accounts/CursorAccountsConsole.js +12 -3
- package/cursor-accounts/CursorAccountsConsole.js.map +1 -1
- package/cursor-accounts/cursor-account-coverage.d.ts +30 -1
- package/cursor-accounts/cursor-account-coverage.d.ts.map +1 -1
- package/cursor-accounts/cursor-account-coverage.js +21 -0
- package/cursor-accounts/cursor-account-coverage.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +15 -0
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +5 -0
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/identity-account/AccountPreferencesPanel.d.ts +36 -0
- package/identity-account/AccountPreferencesPanel.d.ts.map +1 -0
- package/identity-account/AccountPreferencesPanel.js +202 -0
- package/identity-account/AccountPreferencesPanel.js.map +1 -0
- package/identity-account/index.d.ts +8 -0
- package/identity-account/index.d.ts.map +1 -1
- package/identity-account/index.js +4 -0
- package/identity-account/index.js.map +1 -1
- package/identity-account/useAccountExecutionDefaults.d.ts +36 -0
- package/identity-account/useAccountExecutionDefaults.d.ts.map +1 -0
- package/identity-account/useAccountExecutionDefaults.js +46 -0
- package/identity-account/useAccountExecutionDefaults.js.map +1 -0
- package/identity-account/useMyIdentityAccount.d.ts +55 -0
- package/identity-account/useMyIdentityAccount.d.ts.map +1 -0
- package/identity-account/useMyIdentityAccount.js +37 -0
- package/identity-account/useMyIdentityAccount.js.map +1 -0
- package/identity-account/useUpdateIdentityAccount.d.ts +42 -0
- package/identity-account/useUpdateIdentityAccount.d.ts.map +1 -0
- package/identity-account/useUpdateIdentityAccount.js +53 -0
- package/identity-account/useUpdateIdentityAccount.js.map +1 -0
- package/identity-provider/IdentityProviderDetailPanel.d.ts.map +1 -1
- package/identity-provider/IdentityProviderDetailPanel.js +16 -15
- package/identity-provider/IdentityProviderDetailPanel.js.map +1 -1
- package/index.d.ts +15 -13
- package/index.d.ts.map +1 -1
- package/index.js +11 -8
- package/index.js.map +1 -1
- package/internal/StandingContextField.d.ts +37 -0
- package/internal/StandingContextField.d.ts.map +1 -0
- package/internal/StandingContextField.js +24 -0
- package/internal/StandingContextField.js.map +1 -0
- package/library/InstanceVisibilitySelector.d.ts.map +1 -1
- package/library/InstanceVisibilitySelector.js +9 -2
- package/library/InstanceVisibilitySelector.js.map +1 -1
- package/library/ResourceVisibilityControl.d.ts +13 -3
- package/library/ResourceVisibilityControl.d.ts.map +1 -1
- package/library/ResourceVisibilityControl.js +33 -5
- package/library/ResourceVisibilityControl.js.map +1 -1
- package/library/VisibilityOptionRow.d.ts +6 -0
- package/library/VisibilityOptionRow.d.ts.map +1 -1
- package/library/VisibilityOptionRow.js +11 -1
- package/library/VisibilityOptionRow.js.map +1 -1
- package/library/VisibilitySelector.d.ts.map +1 -1
- package/library/VisibilitySelector.js +14 -2
- package/library/VisibilitySelector.js.map +1 -1
- package/library/index.d.ts +4 -2
- package/library/index.d.ts.map +1 -1
- package/library/index.js +2 -1
- package/library/index.js.map +1 -1
- package/library/useCanSetPublicVisibility.d.ts +30 -0
- package/library/useCanSetPublicVisibility.d.ts.map +1 -0
- package/library/useCanSetPublicVisibility.js +41 -0
- package/library/useCanSetPublicVisibility.js.map +1 -0
- package/library/visibilityLevels.d.ts +32 -1
- package/library/visibilityLevels.d.ts.map +1 -1
- package/library/visibilityLevels.js +34 -14
- package/library/visibilityLevels.js.map +1 -1
- package/mcp-server/McpServerDetailView.js +2 -2
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/index.d.ts +0 -1
- package/mcp-server/index.d.ts.map +1 -1
- package/mcp-server/index.js +0 -1
- package/mcp-server/index.js.map +1 -1
- package/mcp-server/internal/definitionDrift.d.ts +14 -12
- package/mcp-server/internal/definitionDrift.d.ts.map +1 -1
- package/mcp-server/internal/definitionDrift.js +22 -19
- package/mcp-server/internal/definitionDrift.js.map +1 -1
- package/mcp-server/useMcpServerConnect.d.ts +8 -5
- package/mcp-server/useMcpServerConnect.d.ts.map +1 -1
- package/mcp-server/useMcpServerConnect.js +2 -1
- package/mcp-server/useMcpServerConnect.js.map +1 -1
- package/mcp-server/useMcpServerOAuthConnect.d.ts.map +1 -1
- package/mcp-server/useMcpServerOAuthConnect.js +7 -2
- package/mcp-server/useMcpServerOAuthConnect.js.map +1 -1
- package/mcp-server/useUpdateMcpServer.d.ts +3 -3
- package/mcp-server/useUpdateMcpServer.js +3 -3
- package/models/ModelSelector.d.ts +33 -1
- package/models/ModelSelector.d.ts.map +1 -1
- package/models/ModelSelector.js +37 -4
- package/models/ModelSelector.js.map +1 -1
- package/models/index.d.ts +2 -0
- package/models/index.d.ts.map +1 -1
- package/models/index.js +1 -0
- package/models/index.js.map +1 -1
- package/models/registry.d.ts +16 -0
- package/models/registry.d.ts.map +1 -1
- package/models/registry.js +13 -0
- package/models/registry.js.map +1 -1
- package/models/thinking-mode.d.ts +27 -0
- package/models/thinking-mode.d.ts.map +1 -0
- package/models/thinking-mode.js +32 -0
- package/models/thinking-mode.js.map +1 -0
- package/oauth-app/CreateOAuthAppForm.d.ts +2 -2
- package/oauth-app/CreateOAuthAppForm.d.ts.map +1 -1
- package/oauth-app/CreateOAuthAppForm.js +13 -4
- package/oauth-app/CreateOAuthAppForm.js.map +1 -1
- package/oauth-app/OAuthAppDetailPanel.d.ts.map +1 -1
- package/oauth-app/OAuthAppDetailPanel.js +50 -22
- package/oauth-app/OAuthAppDetailPanel.js.map +1 -1
- package/organization/OrgPreferencesPanel.d.ts +32 -0
- package/organization/OrgPreferencesPanel.d.ts.map +1 -0
- package/organization/OrgPreferencesPanel.js +90 -0
- package/organization/OrgPreferencesPanel.js.map +1 -0
- package/organization/OrgProfilePanel.d.ts.map +1 -1
- package/organization/OrgProfilePanel.js +5 -4
- package/organization/OrgProfilePanel.js.map +1 -1
- package/organization/index.d.ts +2 -0
- package/organization/index.d.ts.map +1 -1
- package/organization/index.js +1 -0
- package/organization/index.js.map +1 -1
- package/package.json +4 -4
- package/platform-client/PlatformClientDetailPanel.d.ts.map +1 -1
- package/platform-client/PlatformClientDetailPanel.js +12 -13
- package/platform-client/PlatformClientDetailPanel.js.map +1 -1
- package/schedule/ScheduleDetailView.d.ts.map +1 -1
- package/schedule/ScheduleDetailView.js +21 -10
- package/schedule/ScheduleDetailView.js.map +1 -1
- package/schedule/ScheduleForm.d.ts.map +1 -1
- package/schedule/ScheduleForm.js +13 -3
- package/schedule/ScheduleForm.js.map +1 -1
- package/session/NewSessionViewer.d.ts +10 -1
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +2 -1
- package/session/NewSessionViewer.js.map +1 -1
- package/session/run-config.d.ts +9 -0
- package/session/run-config.d.ts.map +1 -1
- package/session/run-config.js +5 -0
- package/session/run-config.js.map +1 -1
- package/session/useNewSessionFlow.d.ts +27 -1
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +51 -8
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useSessionConversation.d.ts +12 -1
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +15 -24
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +14 -10
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useUpdateSession.d.ts +18 -24
- package/session/useUpdateSession.d.ts.map +1 -1
- package/session/useUpdateSession.js +18 -24
- package/session/useUpdateSession.js.map +1 -1
- package/settings/AccountPreferencesSection.d.ts +3 -0
- package/settings/AccountPreferencesSection.d.ts.map +1 -0
- package/settings/AccountPreferencesSection.js +10 -0
- package/settings/AccountPreferencesSection.js.map +1 -0
- package/settings/OrgPreferencesSection.d.ts +3 -0
- package/settings/OrgPreferencesSection.d.ts.map +1 -0
- package/settings/OrgPreferencesSection.js +13 -0
- package/settings/OrgPreferencesSection.js.map +1 -0
- package/settings/index.d.ts +2 -0
- package/settings/index.d.ts.map +1 -1
- package/settings/index.js +2 -0
- package/settings/index.js.map +1 -1
- package/settings/settings-nav.d.ts.map +1 -1
- package/settings/settings-nav.js +17 -1
- package/settings/settings-nav.js.map +1 -1
- package/src/agent/AgentDetailView.tsx +2 -2
- package/src/agent/index.ts +0 -2
- package/src/agent/useUpdateAgent.ts +3 -3
- package/src/agent-instance/AgentInstanceDetailPanel.tsx +5 -7
- package/src/agent-instance/__tests__/AgentInstanceDetailPanel.test.tsx +75 -0
- package/src/agent-instance/useUpdateAgentInstance.ts +1 -1
- package/src/attachment/AttachmentChipList.tsx +19 -8
- package/src/attachment/__tests__/AttachmentChipList.test.tsx +12 -0
- package/src/attachment/__tests__/useAttachments.test.ts +293 -0
- package/src/attachment/index.ts +1 -0
- package/src/attachment/useAttachments.ts +143 -11
- package/src/channel/AgentChannelsPanel.tsx +26 -1
- package/src/channel/ChannelRunConfigDialog.tsx +351 -0
- package/src/channel/__tests__/ChannelRunConfigDialog.test.tsx +210 -0
- package/src/channel/index.ts +2 -0
- package/src/channel/useSaveAgentChannel.ts +6 -3
- package/src/channel-app/ChannelAppDetailPanel.tsx +9 -9
- package/src/channel-app/__tests__/channelAppWhatsApp.test.tsx +2 -0
- package/src/channel-app/__tests__/channelAppWipeSafety.test.tsx +87 -0
- package/src/composer/ComposerToolbar.tsx +9 -0
- package/src/composer/SessionComposer.tsx +59 -16
- package/src/composer/__tests__/SessionComposer-thinkingMode.test.tsx +176 -0
- package/src/conversation/ConversationComposer.tsx +38 -4
- package/src/conversation/ConversationTemplatePickerDialog.tsx +441 -0
- package/src/conversation/ConversationsWorkbench.tsx +40 -4
- package/src/conversation/__tests__/ConversationComposer.test.tsx +56 -1
- package/src/conversation/__tests__/ConversationTemplatePickerDialog.test.tsx +224 -0
- package/src/conversation/__tests__/useConversationParticipation.test.tsx +45 -4
- package/src/conversation/index.ts +4 -0
- package/src/conversation/useConversationParticipation.ts +58 -6
- package/src/cursor-accounts/CursorAccountsConsole.tsx +40 -5
- package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +32 -0
- package/src/cursor-accounts/__tests__/cursor-account-coverage.test.ts +58 -1
- package/src/cursor-accounts/cursor-account-coverage.ts +55 -0
- package/src/execution/useCreateAgentExecution.ts +19 -0
- package/src/identity-account/AccountPreferencesPanel.tsx +532 -0
- package/src/identity-account/__tests__/AccountPreferencesPanel.test.tsx +267 -0
- package/src/identity-account/__tests__/useAccountExecutionDefaults.test.tsx +116 -0
- package/src/identity-account/__tests__/useMyIdentityAccount.test.tsx +121 -0
- package/src/identity-account/index.ts +11 -0
- package/src/identity-account/useAccountExecutionDefaults.ts +63 -0
- package/src/identity-account/useMyIdentityAccount.ts +75 -0
- package/src/identity-account/useUpdateIdentityAccount.ts +73 -0
- package/src/identity-provider/IdentityProviderDetailPanel.tsx +18 -15
- package/src/identity-provider/__tests__/IdentityProviderDetailPanel.test.tsx +80 -0
- package/src/index.ts +26 -4
- package/src/internal/StandingContextField.tsx +92 -0
- package/src/library/InstanceVisibilitySelector.tsx +9 -2
- package/src/library/ResourceVisibilityControl.tsx +46 -13
- package/src/library/VisibilityOptionRow.tsx +28 -6
- package/src/library/VisibilitySelector.tsx +14 -2
- package/src/library/__tests__/VisibilitySelector.test.tsx +48 -1
- package/src/library/__tests__/visibilityLevels.test.ts +67 -1
- package/src/library/index.ts +6 -1
- package/src/library/useCanSetPublicVisibility.ts +56 -0
- package/src/library/visibilityLevels.ts +65 -14
- package/src/mcp-server/McpServerDetailView.tsx +2 -2
- package/src/mcp-server/__tests__/useMcpServerConnect.asyncLane.test.tsx +117 -0
- package/src/mcp-server/index.ts +0 -2
- package/src/mcp-server/internal/definitionDrift.ts +22 -20
- package/src/mcp-server/useMcpServerConnect.ts +9 -6
- package/src/mcp-server/useMcpServerOAuthConnect.ts +7 -2
- package/src/mcp-server/useUpdateMcpServer.ts +3 -3
- package/src/models/ModelSelector.tsx +94 -1
- package/src/models/index.ts +2 -0
- package/src/models/registry.ts +29 -0
- package/src/models/thinking-mode.ts +48 -0
- package/src/oauth-app/CreateOAuthAppForm.tsx +58 -3
- package/src/oauth-app/OAuthAppDetailPanel.tsx +103 -20
- package/src/oauth-app/__tests__/OAuthAppDetailPanel.test.tsx +94 -0
- package/src/organization/OrgPreferencesPanel.tsx +221 -0
- package/src/organization/OrgProfilePanel.tsx +5 -4
- package/src/organization/__tests__/OrgPreferencesPanel.test.tsx +145 -0
- package/src/organization/__tests__/OrgProfilePanel.test.tsx +108 -0
- package/src/organization/index.ts +2 -0
- package/src/platform-client/PlatformClientDetailPanel.tsx +14 -13
- package/src/platform-client/__tests__/PlatformClientDetailPanel.test.tsx +82 -0
- package/src/schedule/ScheduleDetailView.tsx +29 -4
- package/src/schedule/ScheduleForm.tsx +14 -1
- package/src/session/NewSessionViewer.tsx +12 -0
- package/src/session/__tests__/useNewSessionFlow.test.tsx +151 -0
- package/src/session/run-config.ts +16 -0
- package/src/session/useNewSessionFlow.ts +82 -9
- package/src/session/useSessionConversation.ts +32 -40
- package/src/session/useSessionPageFlow.ts +14 -11
- package/src/session/useUpdateSession.ts +18 -24
- package/src/settings/AccountPreferencesSection.tsx +25 -0
- package/src/settings/OrgPreferencesSection.tsx +35 -0
- package/src/settings/__tests__/settings-nav.test.ts +27 -0
- package/src/settings/index.ts +2 -0
- package/src/settings/settings-nav.ts +18 -0
- package/src/workflow/ApprovalFormBuilder.tsx +20 -27
- package/src/workflow/WorkflowDetailView.tsx +2 -2
- package/src/workflow/__tests__/WorkflowInstanceDetailPanel.test.tsx +83 -0
- package/src/workflow/index.ts +0 -2
- package/src/workflow/instance/WorkflowInstanceDetailPanel.tsx +6 -7
- package/src/workflow/useUpdateWorkflow.ts +3 -3
- package/styles.css +1 -1
- package/workflow/ApprovalFormBuilder.d.ts.map +1 -1
- package/workflow/ApprovalFormBuilder.js +10 -5
- package/workflow/ApprovalFormBuilder.js.map +1 -1
- package/workflow/WorkflowDetailView.js +2 -2
- package/workflow/WorkflowDetailView.js.map +1 -1
- package/workflow/index.d.ts +0 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +0 -1
- package/workflow/index.js.map +1 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.d.ts.map +1 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.js +6 -7
- package/workflow/instance/WorkflowInstanceDetailPanel.js.map +1 -1
- package/workflow/useUpdateWorkflow.d.ts +3 -3
- package/workflow/useUpdateWorkflow.js +3 -3
- package/agent/internal/agentToInput.d.ts +0 -15
- package/agent/internal/agentToInput.d.ts.map +0 -1
- package/agent/internal/agentToInput.js +0 -84
- package/agent/internal/agentToInput.js.map +0 -1
- package/mcp-server/internal/mcpServerToInput.d.ts +0 -12
- package/mcp-server/internal/mcpServerToInput.d.ts.map +0 -1
- package/mcp-server/internal/mcpServerToInput.js +0 -84
- package/mcp-server/internal/mcpServerToInput.js.map +0 -1
- package/session/session-spec-converters.d.ts +0 -24
- package/session/session-spec-converters.d.ts.map +0 -1
- package/session/session-spec-converters.js +0 -72
- package/session/session-spec-converters.js.map +0 -1
- package/src/agent/internal/__tests__/agentToInput.test.ts +0 -145
- package/src/agent/internal/agentToInput.ts +0 -102
- package/src/mcp-server/__tests__/mcpServerToInput.test.ts +0 -201
- package/src/mcp-server/internal/mcpServerToInput.ts +0 -98
- package/src/session/__tests__/session-spec-converters.test.ts +0 -183
- package/src/session/session-spec-converters.ts +0 -86
- package/src/workflow/internal/workflowToInput.ts +0 -96
- package/workflow/internal/workflowToInput.d.ts +0 -12
- package/workflow/internal/workflowToInput.d.ts.map +0 -1
- package/workflow/internal/workflowToInput.js +0 -73
- package/workflow/internal/workflowToInput.js.map +0 -1
|
@@ -14,6 +14,7 @@ import { useStigmer } from "../hooks.js";
|
|
|
14
14
|
import { toError } from "../internal/toError.js";
|
|
15
15
|
import { toProtoInteractionMode } from "../composer/interaction-mode.js";
|
|
16
16
|
import { toProtoServiceTier, type ServiceTierOption } from "../models/service-tier.js";
|
|
17
|
+
import { toProtoThinkingMode, type ThinkingModeOption } from "../models/thinking-mode.js";
|
|
17
18
|
import { toProtoHarness, type HarnessOption } from "../models/harness.js";
|
|
18
19
|
import {
|
|
19
20
|
toProtoExecutionTarget,
|
|
@@ -138,6 +139,20 @@ export interface SharedAgentExecutionFields {
|
|
|
138
139
|
* Maps to `ExecutionConfig.service_tier` in the proto.
|
|
139
140
|
*/
|
|
140
141
|
readonly serviceTier?: ServiceTierOption;
|
|
142
|
+
/**
|
|
143
|
+
* Thinking mode for this execution's model calls (stigmer/stigmer#772).
|
|
144
|
+
*
|
|
145
|
+
* - `"disabled"` (default): the model's base variant, pinned explicitly —
|
|
146
|
+
* never the provider account default.
|
|
147
|
+
* - `"enabled"`: the model's extended-reasoning variant, billed at base
|
|
148
|
+
* per-token rates (reasoning tokens bill as output). Valid only for
|
|
149
|
+
* cursor-harness models whose registry entry declares the thinking
|
|
150
|
+
* capability — the backend refuses the create otherwise, so gate the
|
|
151
|
+
* option on `ModelInfo.thinkingCapable`.
|
|
152
|
+
*
|
|
153
|
+
* Maps to `ExecutionConfig.thinking_mode` in the proto.
|
|
154
|
+
*/
|
|
155
|
+
readonly thinkingMode?: ThinkingModeOption;
|
|
141
156
|
/**
|
|
142
157
|
* Marks this execution as a Build-from-plan turn: the user approved a
|
|
143
158
|
* plan from a prior Plan-mode execution and asked the agent to implement
|
|
@@ -318,6 +333,7 @@ export function useCreateAgentExecution(): UseCreateAgentExecutionReturn {
|
|
|
318
333
|
input.modelName ||
|
|
319
334
|
input.interactionMode ||
|
|
320
335
|
input.serviceTier ||
|
|
336
|
+
input.thinkingMode ||
|
|
321
337
|
input.structuredOutputSchema ||
|
|
322
338
|
input.buildFromPlan;
|
|
323
339
|
const executionConfig = hasConfig
|
|
@@ -329,6 +345,9 @@ export function useCreateAgentExecution(): UseCreateAgentExecutionReturn {
|
|
|
329
345
|
...(input.serviceTier
|
|
330
346
|
? { serviceTier: toProtoServiceTier(input.serviceTier) }
|
|
331
347
|
: {}),
|
|
348
|
+
...(input.thinkingMode
|
|
349
|
+
? { thinkingMode: toProtoThinkingMode(input.thinkingMode) }
|
|
350
|
+
: {}),
|
|
332
351
|
...(input.structuredOutputSchema
|
|
333
352
|
? { structuredOutputSchema: input.structuredOutputSchema }
|
|
334
353
|
: {}),
|
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type FormEvent,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
useCallback,
|
|
7
|
+
useEffect,
|
|
8
|
+
useId,
|
|
9
|
+
useMemo,
|
|
10
|
+
useState,
|
|
11
|
+
} from "react";
|
|
12
|
+
import { cn } from "@stigmer/theme";
|
|
13
|
+
import { getUserMessage, toIdentityAccountUpdateInput } from "@stigmer/sdk";
|
|
14
|
+
import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
15
|
+
import { useMyIdentityAccount } from "./useMyIdentityAccount.js";
|
|
16
|
+
import { useUpdateIdentityAccount } from "./useUpdateIdentityAccount.js";
|
|
17
|
+
import { useResourceAvailable, ApiResourceKind } from "../deployment-mode.js";
|
|
18
|
+
import { useModelRegistry } from "../models/index.js";
|
|
19
|
+
import { HARNESS_META, type HarnessOption } from "../models/harness.js";
|
|
20
|
+
import { CloudFeatureNotice } from "../internal/CloudFeatureNotice.js";
|
|
21
|
+
import { StandingContextField } from "../internal/StandingContextField.js";
|
|
22
|
+
import { SpinnerIcon } from "../internal/SpinnerIcon.js";
|
|
23
|
+
|
|
24
|
+
/** Props for {@link AccountPreferencesPanel}. */
|
|
25
|
+
export interface AccountPreferencesPanelProps {
|
|
26
|
+
/** Fired with the updated resource after a successful save. */
|
|
27
|
+
readonly onUpdated?: (account: IdentityAccount) => void;
|
|
28
|
+
/** Additional CSS class names for the root container. */
|
|
29
|
+
readonly className?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Self-contained editor for the current user's declared preferences
|
|
34
|
+
* (`IdentityAccountSpec.preferences`): standing context plus the
|
|
35
|
+
* execution defaults (default harness and per-harness default models).
|
|
36
|
+
*
|
|
37
|
+
* The declared text is snapshotted into the user's own eligible agent
|
|
38
|
+
* executions and delivered to the agent as background context.
|
|
39
|
+
* Self-service: the account is resolved via `whoAmI()` and updated
|
|
40
|
+
* through the caller's self-ownership permission — no explicit
|
|
41
|
+
* permission check is needed. On save, calls `identityAccount.update()`
|
|
42
|
+
* with the complete mapped input (full-spec-replace safety) and fires
|
|
43
|
+
* `onUpdated`.
|
|
44
|
+
*
|
|
45
|
+
* Cloud-only: the OSS local server has no IdentityAccount (local mode
|
|
46
|
+
* is single-user, so the organization's preferences cover it). In local
|
|
47
|
+
* mode the panel renders a {@link CloudFeatureNotice} instead.
|
|
48
|
+
*
|
|
49
|
+
* All visual properties flow through `--stgm-*` design tokens. Zero
|
|
50
|
+
* dependencies on Console routing, auth context, or layout — platform
|
|
51
|
+
* builders can embed it directly:
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <AccountPreferencesPanel />
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function AccountPreferencesPanel({
|
|
59
|
+
onUpdated,
|
|
60
|
+
className,
|
|
61
|
+
}: AccountPreferencesPanelProps) {
|
|
62
|
+
const baseId = useId();
|
|
63
|
+
const available = useResourceAvailable(ApiResourceKind.identity_account);
|
|
64
|
+
|
|
65
|
+
if (!available) {
|
|
66
|
+
return (
|
|
67
|
+
<CloudFeatureNotice className={className}>
|
|
68
|
+
Personal preferences require Stigmer Cloud. Local mode is
|
|
69
|
+
single-user, so the organization's preferences apply to every
|
|
70
|
+
execution — set standing context there instead.
|
|
71
|
+
</CloudFeatureNotice>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<AccountPreferencesForm
|
|
77
|
+
baseId={baseId}
|
|
78
|
+
onUpdated={onUpdated}
|
|
79
|
+
className={className}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Inner form, mounted only when IdentityAccount is available — keeps the
|
|
86
|
+
* data hooks from issuing doomed RPCs against a local server.
|
|
87
|
+
*/
|
|
88
|
+
function AccountPreferencesForm({
|
|
89
|
+
baseId,
|
|
90
|
+
onUpdated,
|
|
91
|
+
className,
|
|
92
|
+
}: {
|
|
93
|
+
readonly baseId: string;
|
|
94
|
+
readonly onUpdated?: (account: IdentityAccount) => void;
|
|
95
|
+
readonly className?: string;
|
|
96
|
+
}) {
|
|
97
|
+
const {
|
|
98
|
+
account,
|
|
99
|
+
isLoading: isFetching,
|
|
100
|
+
error: fetchError,
|
|
101
|
+
refetch,
|
|
102
|
+
} = useMyIdentityAccount();
|
|
103
|
+
|
|
104
|
+
const {
|
|
105
|
+
update,
|
|
106
|
+
isUpdating,
|
|
107
|
+
error: updateError,
|
|
108
|
+
clearError,
|
|
109
|
+
} = useUpdateIdentityAccount();
|
|
110
|
+
|
|
111
|
+
const [standingContext, setStandingContext] = useState("");
|
|
112
|
+
const [defaultHarness, setDefaultHarness] = useState("");
|
|
113
|
+
const [defaultNativeModel, setDefaultNativeModel] = useState("");
|
|
114
|
+
const [defaultCursorModel, setDefaultCursorModel] = useState("");
|
|
115
|
+
|
|
116
|
+
const serverPreferences = account?.spec?.preferences;
|
|
117
|
+
const serverStandingContext = serverPreferences?.standingContext ?? "";
|
|
118
|
+
const serverDefaultHarness = serverPreferences?.defaultHarness ?? "";
|
|
119
|
+
const serverDefaultNativeModel = serverPreferences?.defaultNativeModel ?? "";
|
|
120
|
+
const serverDefaultCursorModel = serverPreferences?.defaultCursorModel ?? "";
|
|
121
|
+
|
|
122
|
+
// Sync the form fields when server data changes.
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
if (!account) return;
|
|
125
|
+
const prefs = account.spec?.preferences;
|
|
126
|
+
setStandingContext(prefs?.standingContext ?? "");
|
|
127
|
+
setDefaultHarness(prefs?.defaultHarness ?? "");
|
|
128
|
+
setDefaultNativeModel(prefs?.defaultNativeModel ?? "");
|
|
129
|
+
setDefaultCursorModel(prefs?.defaultCursorModel ?? "");
|
|
130
|
+
}, [account]);
|
|
131
|
+
|
|
132
|
+
const hasChanges = useMemo(
|
|
133
|
+
() =>
|
|
134
|
+
standingContext.trim() !== serverStandingContext ||
|
|
135
|
+
defaultHarness !== serverDefaultHarness ||
|
|
136
|
+
defaultNativeModel !== serverDefaultNativeModel ||
|
|
137
|
+
defaultCursorModel !== serverDefaultCursorModel,
|
|
138
|
+
[
|
|
139
|
+
standingContext,
|
|
140
|
+
defaultHarness,
|
|
141
|
+
defaultNativeModel,
|
|
142
|
+
defaultCursorModel,
|
|
143
|
+
serverStandingContext,
|
|
144
|
+
serverDefaultHarness,
|
|
145
|
+
serverDefaultNativeModel,
|
|
146
|
+
serverDefaultCursorModel,
|
|
147
|
+
],
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const canSubmit = hasChanges && !isUpdating;
|
|
151
|
+
|
|
152
|
+
const handleDiscard = useCallback(() => {
|
|
153
|
+
setStandingContext(serverStandingContext);
|
|
154
|
+
setDefaultHarness(serverDefaultHarness);
|
|
155
|
+
setDefaultNativeModel(serverDefaultNativeModel);
|
|
156
|
+
setDefaultCursorModel(serverDefaultCursorModel);
|
|
157
|
+
clearError();
|
|
158
|
+
}, [
|
|
159
|
+
serverStandingContext,
|
|
160
|
+
serverDefaultHarness,
|
|
161
|
+
serverDefaultNativeModel,
|
|
162
|
+
serverDefaultCursorModel,
|
|
163
|
+
clearError,
|
|
164
|
+
]);
|
|
165
|
+
|
|
166
|
+
const handleSubmit = useCallback(
|
|
167
|
+
async (e: FormEvent) => {
|
|
168
|
+
e.preventDefault();
|
|
169
|
+
if (!canSubmit || !account) return;
|
|
170
|
+
|
|
171
|
+
clearError();
|
|
172
|
+
try {
|
|
173
|
+
// update() is a full-spec replace: spread the complete mapped input
|
|
174
|
+
// so unedited spec fields survive. `preferences` is a nested message,
|
|
175
|
+
// so the override spreads the mapper's COMPLETE preferences too —
|
|
176
|
+
// fields this form does not own (added by later phases) survive.
|
|
177
|
+
const mapped = toIdentityAccountUpdateInput(account);
|
|
178
|
+
const updated = await update({
|
|
179
|
+
...mapped,
|
|
180
|
+
preferences: {
|
|
181
|
+
...mapped.preferences,
|
|
182
|
+
standingContext: standingContext.trim() || undefined,
|
|
183
|
+
defaultHarness: defaultHarness || undefined,
|
|
184
|
+
defaultNativeModel: defaultNativeModel || undefined,
|
|
185
|
+
defaultCursorModel: defaultCursorModel || undefined,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
refetch();
|
|
189
|
+
onUpdated?.(updated);
|
|
190
|
+
} catch {
|
|
191
|
+
// error state is managed by useUpdateIdentityAccount
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
[
|
|
195
|
+
canSubmit,
|
|
196
|
+
account,
|
|
197
|
+
standingContext,
|
|
198
|
+
defaultHarness,
|
|
199
|
+
defaultNativeModel,
|
|
200
|
+
defaultCursorModel,
|
|
201
|
+
update,
|
|
202
|
+
clearError,
|
|
203
|
+
refetch,
|
|
204
|
+
onUpdated,
|
|
205
|
+
],
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// -----------------------------------------------------------------------
|
|
209
|
+
// Loading state
|
|
210
|
+
// -----------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
if (isFetching && !account) {
|
|
213
|
+
return (
|
|
214
|
+
<div
|
|
215
|
+
className={cn("stg:space-y-4", className)}
|
|
216
|
+
aria-busy="true"
|
|
217
|
+
aria-label="Loading account preferences"
|
|
218
|
+
>
|
|
219
|
+
<div className="stg:bg-muted-subtle stg:h-28 stg:animate-pulse stg:rounded" />
|
|
220
|
+
<div className="stg:bg-muted-subtle stg:h-8 stg:w-32 stg:animate-pulse stg:rounded" />
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// -----------------------------------------------------------------------
|
|
226
|
+
// Fetch error
|
|
227
|
+
// -----------------------------------------------------------------------
|
|
228
|
+
|
|
229
|
+
if (fetchError) {
|
|
230
|
+
return (
|
|
231
|
+
<div className={cn("stg:space-y-3", className)} role="alert">
|
|
232
|
+
<p className="stg:text-destructive stg:text-sm">
|
|
233
|
+
{getUserMessage(fetchError)}
|
|
234
|
+
</p>
|
|
235
|
+
<button
|
|
236
|
+
type="button"
|
|
237
|
+
onClick={refetch}
|
|
238
|
+
className={cn(
|
|
239
|
+
"stg:rounded-md stg:px-3 stg:py-1.5 stg:text-xs stg:font-medium",
|
|
240
|
+
"stg:bg-primary stg:text-primary-foreground stg:hover:bg-primary-hover",
|
|
241
|
+
)}
|
|
242
|
+
>
|
|
243
|
+
Retry
|
|
244
|
+
</button>
|
|
245
|
+
</div>
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!account) return null;
|
|
250
|
+
|
|
251
|
+
// -----------------------------------------------------------------------
|
|
252
|
+
// Render
|
|
253
|
+
// -----------------------------------------------------------------------
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<form onSubmit={handleSubmit} className={cn("stg:space-y-4", className)}>
|
|
257
|
+
<StandingContextField
|
|
258
|
+
id={`${baseId}-standing-context`}
|
|
259
|
+
value={standingContext}
|
|
260
|
+
onChange={setStandingContext}
|
|
261
|
+
disabled={isUpdating}
|
|
262
|
+
placeholder={
|
|
263
|
+
"e.g. Keep answers terse. I prefer TypeScript examples. My timezone is IST."
|
|
264
|
+
}
|
|
265
|
+
helperText="Shared with agents as background context — not instructions. Applies only to executions you start and is visible on those execution records."
|
|
266
|
+
/>
|
|
267
|
+
|
|
268
|
+
<div className="stg:space-y-3">
|
|
269
|
+
<div>
|
|
270
|
+
<h3 className="stg:text-xs stg:font-medium stg:text-foreground">
|
|
271
|
+
Execution defaults
|
|
272
|
+
</h3>
|
|
273
|
+
<p className="stg:text-[0.65rem] stg:text-muted-foreground">
|
|
274
|
+
Seed new sessions across your devices and the CLI. An explicit
|
|
275
|
+
pick in the composer always wins for that device.
|
|
276
|
+
</p>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<fieldset className="stg:space-y-2" disabled={isUpdating}>
|
|
280
|
+
<legend className="stg:text-xs stg:font-medium stg:text-foreground stg:mb-1">
|
|
281
|
+
Default harness
|
|
282
|
+
</legend>
|
|
283
|
+
<HarnessOptionRow
|
|
284
|
+
radioName={`${baseId}-default-harness`}
|
|
285
|
+
value=""
|
|
286
|
+
label="Platform default"
|
|
287
|
+
description="Stigmer picks the harness for new sessions."
|
|
288
|
+
checked={defaultHarness === ""}
|
|
289
|
+
onSelect={setDefaultHarness}
|
|
290
|
+
disabled={isUpdating}
|
|
291
|
+
/>
|
|
292
|
+
<HarnessOptionRow
|
|
293
|
+
radioName={`${baseId}-default-harness`}
|
|
294
|
+
value="native"
|
|
295
|
+
label={HARNESS_META.native.label}
|
|
296
|
+
description={HARNESS_META.native.description}
|
|
297
|
+
checked={defaultHarness === "native"}
|
|
298
|
+
onSelect={setDefaultHarness}
|
|
299
|
+
disabled={isUpdating}
|
|
300
|
+
>
|
|
301
|
+
<DefaultModelSelect
|
|
302
|
+
id={`${baseId}-default-native-model`}
|
|
303
|
+
harness="native"
|
|
304
|
+
label="Default model"
|
|
305
|
+
value={defaultNativeModel}
|
|
306
|
+
onChange={setDefaultNativeModel}
|
|
307
|
+
disabled={isUpdating}
|
|
308
|
+
/>
|
|
309
|
+
</HarnessOptionRow>
|
|
310
|
+
<HarnessOptionRow
|
|
311
|
+
radioName={`${baseId}-default-harness`}
|
|
312
|
+
value="cursor"
|
|
313
|
+
label={HARNESS_META.cursor.label}
|
|
314
|
+
description={HARNESS_META.cursor.description}
|
|
315
|
+
checked={defaultHarness === "cursor"}
|
|
316
|
+
onSelect={setDefaultHarness}
|
|
317
|
+
disabled={isUpdating}
|
|
318
|
+
>
|
|
319
|
+
<DefaultModelSelect
|
|
320
|
+
id={`${baseId}-default-cursor-model`}
|
|
321
|
+
harness="cursor"
|
|
322
|
+
label="Default model"
|
|
323
|
+
value={defaultCursorModel}
|
|
324
|
+
onChange={setDefaultCursorModel}
|
|
325
|
+
disabled={isUpdating}
|
|
326
|
+
/>
|
|
327
|
+
</HarnessOptionRow>
|
|
328
|
+
<p className="stg:text-[0.65rem] stg:text-muted-foreground">
|
|
329
|
+
Each harness's default model applies whenever a session runs
|
|
330
|
+
on that harness — even when it isn't your default.
|
|
331
|
+
</p>
|
|
332
|
+
</fieldset>
|
|
333
|
+
</div>
|
|
334
|
+
|
|
335
|
+
{updateError && (
|
|
336
|
+
<p className="stg:text-destructive stg:text-[0.65rem]" role="alert">
|
|
337
|
+
{getUserMessage(updateError)}
|
|
338
|
+
</p>
|
|
339
|
+
)}
|
|
340
|
+
|
|
341
|
+
<div className="stg:flex stg:items-center stg:gap-2">
|
|
342
|
+
<button
|
|
343
|
+
type="submit"
|
|
344
|
+
disabled={!canSubmit}
|
|
345
|
+
className={cn(
|
|
346
|
+
"stg:inline-flex stg:items-center stg:gap-1.5 stg:rounded-md stg:px-3 stg:py-1.5 stg:text-xs stg:font-medium",
|
|
347
|
+
"stg:bg-primary stg:text-primary-foreground stg:hover:bg-primary-hover",
|
|
348
|
+
"stg:disabled:pointer-events-none stg:disabled:opacity-40",
|
|
349
|
+
)}
|
|
350
|
+
>
|
|
351
|
+
{isUpdating && <SpinnerIcon size={12} />}
|
|
352
|
+
Save changes
|
|
353
|
+
</button>
|
|
354
|
+
|
|
355
|
+
{hasChanges && !isUpdating && (
|
|
356
|
+
<button
|
|
357
|
+
type="button"
|
|
358
|
+
onClick={handleDiscard}
|
|
359
|
+
className={cn(
|
|
360
|
+
"stg:rounded-md stg:px-3 stg:py-1.5 stg:text-xs",
|
|
361
|
+
"stg:text-muted-foreground stg:hover:text-foreground stg:hover:bg-accent-hover",
|
|
362
|
+
)}
|
|
363
|
+
>
|
|
364
|
+
Discard
|
|
365
|
+
</button>
|
|
366
|
+
)}
|
|
367
|
+
</div>
|
|
368
|
+
</form>
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* One selectable default-harness choice, presented as a bordered row
|
|
374
|
+
* (the `VisibilityOptionRow` presentation shape): radio + label +
|
|
375
|
+
* one-line description, with the harness's own controls nested below.
|
|
376
|
+
*
|
|
377
|
+
* The rows for shipped harnesses embed that harness's default-model
|
|
378
|
+
* select as `children` — the pairing IS the information architecture:
|
|
379
|
+
* a harness and its model default belong to each other, and each model
|
|
380
|
+
* default applies whenever a session runs on that harness, independent
|
|
381
|
+
* of which harness is the default. The non-selected harness's select
|
|
382
|
+
* therefore stays interactive (visually secondary, never disabled).
|
|
383
|
+
*
|
|
384
|
+
* The nested controls live OUTSIDE the radio's `<label>` on purpose:
|
|
385
|
+
* a `<select>` inside the label would toggle the radio on every
|
|
386
|
+
* interaction with it.
|
|
387
|
+
*
|
|
388
|
+
* The shipped-harness rows must stay in lockstep with the proto's
|
|
389
|
+
* `default_harness` in-list validation (`["native", "cursor"]`) — each
|
|
390
|
+
* shipped harness binds to its own proto model field, so a new harness
|
|
391
|
+
* adds a field, a row, and a validation entry together.
|
|
392
|
+
*/
|
|
393
|
+
function HarnessOptionRow({
|
|
394
|
+
radioName,
|
|
395
|
+
value,
|
|
396
|
+
label,
|
|
397
|
+
description,
|
|
398
|
+
checked,
|
|
399
|
+
onSelect,
|
|
400
|
+
disabled,
|
|
401
|
+
children,
|
|
402
|
+
}: {
|
|
403
|
+
readonly radioName: string;
|
|
404
|
+
readonly value: string;
|
|
405
|
+
readonly label: string;
|
|
406
|
+
readonly description: string;
|
|
407
|
+
readonly checked: boolean;
|
|
408
|
+
readonly onSelect: (value: string) => void;
|
|
409
|
+
readonly disabled: boolean;
|
|
410
|
+
readonly children?: ReactNode;
|
|
411
|
+
}) {
|
|
412
|
+
// The radio's accessible name is the title alone (aria-labelledby), with
|
|
413
|
+
// the description attached as aria-describedby — the wrapping label keeps
|
|
414
|
+
// the whole text block clickable without bloating the announced name.
|
|
415
|
+
const titleId = `${radioName}-${value || "platform"}-title`;
|
|
416
|
+
const descriptionId = `${radioName}-${value || "platform"}-description`;
|
|
417
|
+
|
|
418
|
+
return (
|
|
419
|
+
<div
|
|
420
|
+
className={cn(
|
|
421
|
+
"stg:rounded-md stg:border stg:px-3 stg:py-2.5 stg:transition-colors",
|
|
422
|
+
checked
|
|
423
|
+
? "stg:border-primary stg:bg-accent"
|
|
424
|
+
: "stg:border-input stg:hover:bg-accent-hover",
|
|
425
|
+
disabled && "stg:opacity-50",
|
|
426
|
+
)}
|
|
427
|
+
>
|
|
428
|
+
<label
|
|
429
|
+
className={cn(
|
|
430
|
+
"stg:flex stg:cursor-pointer stg:items-start stg:gap-2",
|
|
431
|
+
disabled && "stg:cursor-default",
|
|
432
|
+
)}
|
|
433
|
+
>
|
|
434
|
+
<input
|
|
435
|
+
type="radio"
|
|
436
|
+
name={radioName}
|
|
437
|
+
value={value}
|
|
438
|
+
checked={checked}
|
|
439
|
+
onChange={() => onSelect(value)}
|
|
440
|
+
disabled={disabled}
|
|
441
|
+
aria-labelledby={titleId}
|
|
442
|
+
aria-describedby={descriptionId}
|
|
443
|
+
className="stg:mt-0.5 stg:accent-primary stg:focus-visible:outline-none stg:focus-visible:ring-1 stg:focus-visible:ring-ring"
|
|
444
|
+
/>
|
|
445
|
+
<span className="stg:min-w-0 stg:flex-1">
|
|
446
|
+
<span
|
|
447
|
+
id={titleId}
|
|
448
|
+
className="stg:block stg:text-xs stg:font-medium stg:text-foreground"
|
|
449
|
+
>
|
|
450
|
+
{label}
|
|
451
|
+
</span>
|
|
452
|
+
<span
|
|
453
|
+
id={descriptionId}
|
|
454
|
+
className="stg:block stg:text-[0.65rem] stg:leading-snug stg:text-muted-foreground"
|
|
455
|
+
>
|
|
456
|
+
{description}
|
|
457
|
+
</span>
|
|
458
|
+
</span>
|
|
459
|
+
</label>
|
|
460
|
+
{children && (
|
|
461
|
+
<div
|
|
462
|
+
className={cn(
|
|
463
|
+
"stg:mt-2 stg:pl-6 stg:transition-opacity",
|
|
464
|
+
!checked && "stg:opacity-70",
|
|
465
|
+
)}
|
|
466
|
+
>
|
|
467
|
+
{children}
|
|
468
|
+
</div>
|
|
469
|
+
)}
|
|
470
|
+
</div>
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Per-harness default model select, fed by the harness-filtered registry.
|
|
476
|
+
*
|
|
477
|
+
* A saved model that the registry no longer lists is rendered as its own
|
|
478
|
+
* "(unavailable)" option so the select never lies about the stored value;
|
|
479
|
+
* composers self-heal such a preference to the platform default on read.
|
|
480
|
+
*/
|
|
481
|
+
function DefaultModelSelect({
|
|
482
|
+
id,
|
|
483
|
+
harness,
|
|
484
|
+
label,
|
|
485
|
+
value,
|
|
486
|
+
onChange,
|
|
487
|
+
disabled,
|
|
488
|
+
}: {
|
|
489
|
+
readonly id: string;
|
|
490
|
+
readonly harness: HarnessOption;
|
|
491
|
+
readonly label: string;
|
|
492
|
+
readonly value: string;
|
|
493
|
+
readonly onChange: (value: string) => void;
|
|
494
|
+
readonly disabled: boolean;
|
|
495
|
+
}) {
|
|
496
|
+
const { models, isLoading } = useModelRegistry({ harness });
|
|
497
|
+
const isStale = value !== "" && !isLoading && !models.some((m) => m.modelId === value);
|
|
498
|
+
|
|
499
|
+
return (
|
|
500
|
+
<div className="stg:space-y-1">
|
|
501
|
+
<label
|
|
502
|
+
htmlFor={id}
|
|
503
|
+
className="stg:text-xs stg:font-medium stg:text-foreground"
|
|
504
|
+
>
|
|
505
|
+
{label}
|
|
506
|
+
</label>
|
|
507
|
+
<select
|
|
508
|
+
id={id}
|
|
509
|
+
value={value}
|
|
510
|
+
onChange={(e) => onChange(e.target.value)}
|
|
511
|
+
// Both harness rows show the same visible label; the accessible
|
|
512
|
+
// name stays unique per control by qualifying it with the harness
|
|
513
|
+
// (WCAG label-in-name: the visible text remains a prefix).
|
|
514
|
+
aria-label={`${label} — ${HARNESS_META[harness].label}`}
|
|
515
|
+
disabled={disabled || isLoading}
|
|
516
|
+
className={cn(
|
|
517
|
+
"stg:w-full stg:rounded-md stg:border stg:border-input stg:bg-background stg:px-2.5 stg:py-1.5 stg:text-xs stg:text-foreground",
|
|
518
|
+
"stg:focus-visible:outline-none stg:focus-visible:ring-1 stg:focus-visible:ring-ring",
|
|
519
|
+
"stg:disabled:pointer-events-none stg:disabled:opacity-50",
|
|
520
|
+
)}
|
|
521
|
+
>
|
|
522
|
+
<option value="">Platform default</option>
|
|
523
|
+
{isStale && <option value={value}>{value} (unavailable)</option>}
|
|
524
|
+
{models.map((model) => (
|
|
525
|
+
<option key={model.modelId} value={model.modelId}>
|
|
526
|
+
{model.displayName || model.modelId}
|
|
527
|
+
</option>
|
|
528
|
+
))}
|
|
529
|
+
</select>
|
|
530
|
+
</div>
|
|
531
|
+
);
|
|
532
|
+
}
|