feat(public-share): selectable agent-role identity + fix floating-icon overlap
Anonymous public-share AI assistant: - Add a workspace setting `publicShareAssistantRoleId` so an admin can pick which agent role (identity/persona) the anonymous assistant adopts. The role's instructions REPLACE the built-in persona while the immutable safety framework is still always appended; the role's optional model override takes precedence over the cheap publicShareChatModel. Resolved server-authoritatively (workspace-scoped, soft-delete aware; disabled/missing roles fall back to the built-in persona, so the tool scope remains the real security boundary). - Plumb the field through the update DTO, ai-settings service, the workspace.repo ALLOWED whitelist, resolve()/getMasked(), stream-time role resolution and the prompt/model, plus the settings UI: a new "Assistant identity" Select listing enabled roles (and surfacing a saved-but-disabled role explicitly). Public-share branding / floating icon: - Fix the AI assistant FAB overlapping the "Powered by ..." button (both were Affixed bottom-right): stack the FAB above the bottom-right branding. - Rename "Powered by Docmost" -> "Powered by Gitmost" and point the link at the gitmost repo. Tests: extend public-share-chat.spec (role persona replacement still appends the safety framework, resolveShareRole edge cases, model-override precedence). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ export interface UpdateAiSettingsInput {
|
||||
sttApiStyle?: SttApiStyle;
|
||||
sttApiKey?: string;
|
||||
publicShareChatModel?: string;
|
||||
publicShareAssistantRoleId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,6 +136,9 @@ export class AiSettingsService {
|
||||
// Cheap model id for the anonymous public-share assistant; reuses the chat
|
||||
// driver/baseUrl/apiKey. Empty/unset → callers fall back to chatModel.
|
||||
publicShareChatModel: provider.publicShareChatModel,
|
||||
// Agent-role id whose persona the public-share assistant adopts; empty/unset
|
||||
// = built-in locked persona.
|
||||
publicShareAssistantRoleId: provider.publicShareAssistantRoleId,
|
||||
embeddingModel: provider.embeddingModel,
|
||||
sttModel: provider.sttModel,
|
||||
// Plain passthrough, no fallback; the transcribe path defaults unset to
|
||||
@@ -216,6 +220,7 @@ export class AiSettingsService {
|
||||
sttApiStyle: provider.sttApiStyle,
|
||||
systemPrompt: provider.systemPrompt,
|
||||
publicShareChatModel: provider.publicShareChatModel,
|
||||
publicShareAssistantRoleId: provider.publicShareAssistantRoleId,
|
||||
hasApiKey,
|
||||
hasEmbeddingApiKey,
|
||||
hasSttApiKey,
|
||||
@@ -254,6 +259,7 @@ export class AiSettingsService {
|
||||
'sttApiStyle',
|
||||
'systemPrompt',
|
||||
'publicShareChatModel',
|
||||
'publicShareAssistantRoleId',
|
||||
] as const) {
|
||||
if (nonSecret[key] !== undefined) {
|
||||
(providerPatch as Record<string, unknown>)[key] = nonSecret[key];
|
||||
|
||||
@@ -38,6 +38,9 @@ export interface AiProviderSettings {
|
||||
// `chatModel`. The workspace owner pays for anonymous tokens, so a cheaper
|
||||
// model is preferred for read-only Q&A over published documentation.
|
||||
publicShareChatModel?: string;
|
||||
// Agent-role id whose persona the anonymous public-share assistant adopts;
|
||||
// empty/unset = built-in locked persona.
|
||||
publicShareAssistantRoleId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +58,9 @@ export interface ResolvedAiConfig extends Partial<AiProviderSettings> {
|
||||
chatModel?: string;
|
||||
// Cheap model id for the public-share assistant; reuses the chat creds.
|
||||
publicShareChatModel?: string;
|
||||
// Agent-role id whose persona the public-share assistant adopts (empty/unset
|
||||
// = built-in locked persona). Re-declared for parity with the explicit fields.
|
||||
publicShareAssistantRoleId?: string;
|
||||
apiKey?: string;
|
||||
embeddingApiKey?: string;
|
||||
sttApiKey?: string;
|
||||
@@ -76,6 +82,9 @@ export interface MaskedAiSettings {
|
||||
sttApiStyle?: SttApiStyle;
|
||||
systemPrompt?: string;
|
||||
publicShareChatModel?: string;
|
||||
// Agent-role id whose persona the public-share assistant adopts; empty/unset
|
||||
// = built-in locked persona.
|
||||
publicShareAssistantRoleId?: string;
|
||||
hasApiKey: boolean;
|
||||
hasEmbeddingApiKey: boolean;
|
||||
hasSttApiKey: boolean;
|
||||
|
||||
@@ -63,4 +63,10 @@ export class UpdateAiSettingsDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
publicShareChatModel?: string;
|
||||
|
||||
// Agent-role id whose persona the anonymous public-share assistant adopts;
|
||||
// empty/unset = built-in locked persona.
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
publicShareAssistantRoleId?: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user