What should the agent do?
{context.clientConfig.billingMode === "stripe" &&
workspace?.accountId &&
hasAccountPermission(context.accessContext, workspace.accountId, "billing:manage") ? (
<>
>
) : null}
{launchSkillCapabilityId ? (
This installed Skill will be frozen onto this session only. Other workspace sessions
will not receive it.
) : null}
{creditGap ? (
setCreateCreditRefusal(null) } : {})}
/>
) : modelUsesCredits(selectedPolicyRow?.catalog) &&
hasAccountPermission(
context.accessContext,
workspace?.accountId ?? "",
"billing:read",
) ? (
) : null}
void connectionAccounts.refresh(),
disabled: busy || newSessionDraft.loading,
},
}}
menuSide="bottom"
agentCapabilities={{
...composerAgentCapabilities,
disabled: busy || newSessionDraft.loading,
}}
draftChatSettings={{
workspaceId,
scope:
createVisibility === "private" || personalWorkspace
? "personal"
: "workspace",
value: draft.agentLearning ?? {},
onChange: (agentLearning) =>
setDraft((current) => ({ ...current, agentLearning })),
}}
workspaceId={workspaceId}
disabled={busy || newSessionDraft.loading}
fileUploadsEnabled={context.clientConfig.fileUploads.enabled === true}
servers={context.toolMcpServers}
firstPartyTools={firstPartyToolOptions}
selection={{
mcpServerIds: context.selectedCapabilityToolIds,
firstPartyToolIds: draft.firstPartyMcpTools,
}}
toolsDisabled={busy || newSessionDraft.loading}
connectorCustomizing={connectorCustomizing}
onConnectorCustomizingChange={(next) => {
if (next) setConnectorCustomizing(true);
else followWorkspaceConnectors();
}}
onToolSelectionChange={(selection) => {
changeConnectorSelection(selection);
}}
{...(hasRunsOnChoices(runsOnChoices)
? {
runsOn: {
summary: runsOnSummary(runsOnChoices),
disabled: busy || newSessionDraft.loading,
panel: (
void fleet.refresh()}
/>
),
},
}
: {})}
{...(hasVisibilityChoice({
personalWorkspace,
canCreatePrivate: tenancyCapabilities?.canCreatePrivate === true,
})
? {
visibility: {
summary: visibilitySummary(draft.visibility),
disabled: busy || newSessionDraft.loading,
panel: (
{
visibilityChosenRef.current = true;
setDraft((current) => ({
...current,
visibility,
}));
}}
/>
),
},
}
: {})}
{...(usageLimitCapability === "enabled"
? {
usageLimit: {
summary: sessionUsageLimitDraftSummary(usageLimitDraft),
disabled: busy || newSessionDraft.loading,
panel: (
),
},
}
: {})}
{...(draft.compute.kind === "sandbox"
? {
repositories: {
selectedCount:
context.selectedRepoIds.size +
context.selectedPersonalGitHubRepoIds.size +
context.manualRepos.filter((repo) => repo.url.trim().length > 0).length,
disabled: busy || newSessionDraft.loading,
panel: (
),
},
}
: {})}
{...(draftSecretsOn && canListSecrets
? {
secrets: {
summary: sessionSecretsSummary(draftVaultPolicy, draftVaultRows),
disabled: busy || newSessionDraft.loading,
panel: (
void draftVaults.refresh()}
onPolicyChange={(policy) =>
setDraft((current) => {
const { vaultPolicy: _previous, ...rest } = current;
return policy.mode === "all"
? rest
: { ...rest, vaultPolicy: policy };
})
}
onManage={() =>
void navigate({
to: "/workspaces/$workspaceId/secrets",
params: { workspaceId },
})
}
/>
),
},
}
: {})}
/>
{composerAgentCapabilities.customized ? (
setCapabilitiesOpenRequest((current) => ({
panel: "capabilities",
nonce: (current?.nonce ?? 0) + 1,
}))
}
/>
) : null}
>
}
controls={
file.status !== "failed" && file.contentType.startsWith("image/"),
)}
modelCatalog={modelCatalog}
policyError={newSessionPolicyError}
disabled={busy || newSessionDraft.loading}
workspaceId={workspaceId}
onPolicyChosen={() => setModelProvided(true)}
/>
}
actions={
<>
await submitNewSession(model)}
/>
>
}
header={
setProjectDialogOpen(true)}
/>
}
/>
{personalWorkspace ? : null}
{newSessionDraft.conflict ? : null}
{/* A deploy or restart makes Opengeni unreachable for a few seconds.
Reads retry quietly first; if it lasts longer, this one calm line
replaces every error, the message stays in the composer, and the
hooks reconnect on their own so Send works again. */}
{newSessionDraft.unavailable || connectionAccounts.unavailable ? (
{OPENGENI_UPDATING_NOTICE(t)}
) : null}
{/* Accounts load quietly with the composer: only a problem shows here,
never a loading line behind an open menu. */}
{accountsFailure || connectionAccounts.accountChoiceMessage ? (
void connectionAccounts.refresh()}
>
Retry
) : undefined
}
>
{accountsFailure
? connectionAccounts.accessDenied
? connectionAccounts.error
: "Couldn't send your message. Try again."
: connectionAccounts.accountChoiceMessage}
) : null}
void refreshPersonalResourceCatalogs(),
}}
selectedChannelId={selectedChannelId}
selectionHistory={selectionHistory}
/>
{starters ? (
{
setMessage(prompt);
composerRegionRef.current?.querySelector("textarea")?.focus({ preventScroll: true });
}}
/>
) : null}