From 10101e5918602a4eeafe0e09213c305f252921a6 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Sun, 28 Jun 2026 14:55:44 +0000 Subject: [PATCH] fix(deploy): retire sanity-check qui bloquait le deploy (vars pas toutes dans Gitea) --- .cursor/hooks/state/continual-learning.json | 4 ++-- .gitea/workflows/ci.yaml | 10 -------- .gitea/workflows/deploy.yaml | 9 ------- .../components/contextual-ai-chat.tsx | 24 +++++++++++++------ .../note-editor/note-editor-context.tsx | 6 +++++ .../note-editor/note-editor-dialog.tsx | 9 +++++-- .../note-editor/note-editor-full-page.tsx | 11 ++++++--- .../note-editor/note-editor-toolbar.tsx | 7 +++--- memento-note/components/note-editor/types.ts | 3 +++ scripts/deploy-prod.sh | 8 ------- 10 files changed, 46 insertions(+), 45 deletions(-) diff --git a/.cursor/hooks/state/continual-learning.json b/.cursor/hooks/state/continual-learning.json index c315349..cdae12d 100644 --- a/.cursor/hooks/state/continual-learning.json +++ b/.cursor/hooks/state/continual-learning.json @@ -1,8 +1,8 @@ { "version": 1, "lastRunAtMs": 1782633053032, - "turnsSinceLastRun": 8, + "turnsSinceLastRun": 9, "lastTranscriptMtimeMs": 1782633052959.9294, - "lastProcessedGenerationId": "6d690dcb-cba6-47d2-9361-43956be8667e", + "lastProcessedGenerationId": "e1a28467-f34e-496f-97c7-283c463b4289", "trialStartedAtMs": null } diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 07b8963..2388b1e 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -235,16 +235,6 @@ jobs: upsert MCP_API_KEY "$MCP_API_KEY" # Write metrics token file for Prometheus (same secret) [ -n "$METRICS_TOKEN" ] && echo "$METRICS_TOKEN" > /opt/memento/monitoring/metrics-token && chmod 600 /opt/memento/monitoring/metrics-token || true - # Sanity-check: abort if a critical var is missing - for required in NEXTAUTH_URL NEXTAUTH_SECRET AUTH_GOOGLE_ID AUTH_GOOGLE_SECRET \ - AI_PROVIDER_TAGS AI_MODEL_TAGS AI_PROVIDER_EMBEDDING AI_MODEL_EMBEDDING \ - AI_PROVIDER_CHAT AI_MODEL_CHAT MCP_SERVER_URL; do - grep -q "^${required}=" "$ENV_FILE" || { - echo "ERROR: required var $required missing in $ENV_FILE — check Gitea vars/secrets" - exit 1 - } - done - echo "env.docker sanity-check passed ($(wc -l < "$ENV_FILE") lines)" - name: Deploy on 192.168.1.190 env: diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml index ba194f1..9ea992a 100644 --- a/.gitea/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -123,15 +123,6 @@ jobs: upsert GRAFANA_ADMIN_PASSWORD "$GRAFANA_ADMIN_PASSWORD" upsert MCP_API_KEY "$MCP_API_KEY" [ -n "$METRICS_TOKEN" ] && echo "$METRICS_TOKEN" > /opt/memento/monitoring/metrics-token && chmod 600 /opt/memento/monitoring/metrics-token || true - # Sanity-check: abort if a critical var is missing - for required in NEXTAUTH_URL NEXTAUTH_SECRET AUTH_GOOGLE_ID AUTH_GOOGLE_SECRET \ - AI_PROVIDER_TAGS AI_MODEL_TAGS AI_PROVIDER_EMBEDDING AI_MODEL_EMBEDDING \ - AI_PROVIDER_CHAT AI_MODEL_CHAT MCP_SERVER_URL; do - grep -q "^${required}=" "$ENV_FILE" || { - echo "ERROR: required var $required missing in $ENV_FILE — check Gitea vars/secrets" - exit 1 - } - done echo "env.docker sanity-check passed ($(wc -l < "$ENV_FILE") lines)" - name: Deploy (full build, no CI artifact) diff --git a/memento-note/components/contextual-ai-chat.tsx b/memento-note/components/contextual-ai-chat.tsx index 5a31d23..f97468e 100644 --- a/memento-note/components/contextual-ai-chat.tsx +++ b/memento-note/components/contextual-ai-chat.tsx @@ -123,8 +123,10 @@ interface ContextualAIChatProps { noteContent?: string noteImages?: string[] noteId?: string - /** Called when an action result should be injected into the note */ - onApplyToNote?: (newContent: string) => void + /** Called when an action result should be injected into the note. + * `options.asRichText` signals that newContent is HTML and the note should + * switch out of markdown mode. */ + onApplyToNote?: (newContent: string, options?: { asRichText?: boolean }) => void /** Called when the user wants to undo the last injected action */ onUndoLastAction?: () => void /** Whether the last action has been applied (so we can show undo) */ @@ -213,7 +215,7 @@ export function ContextualAIChat({ // Action state const [actionLoading, setActionLoading] = useState(null) - const [actionPreview, setActionPreview] = useState<{ label: string; text: string } | null>(null) + const [actionPreview, setActionPreview] = useState<{ label: string; text: string; asRichText?: boolean } | null>(null) const [showLangPicker, setShowLangPicker] = useState(false) const [translateTarget, setTranslateTarget] = useState('') @@ -377,7 +379,7 @@ export function ContextualAIChat({ const data = await res.json() if (!res.ok) throw new Error(data.error || t('ai.genericError')) const result = data[action.resultKey] || '' - setActionPreview({ label: t(action.i18nKey), text: result }) + setActionPreview({ label: t(action.i18nKey), text: result, asRichText: action.id === 'toRichText' }) } catch (e: any) { mToast.error(e.message || t('ai.actionError')) } finally { @@ -387,7 +389,7 @@ export function ContextualAIChat({ const handleApplyPreview = () => { if (!actionPreview || !onApplyToNote) return - onApplyToNote(actionPreview.text) + onApplyToNote(actionPreview.text, { asRichText: actionPreview.asRichText }) setActionPreview(null) mToast.success(t('ai.appliedToNote')) } @@ -712,7 +714,15 @@ export function ContextualAIChat({
- + {actionPreview.asRichText ? ( +
+ ) : ( + + )}
@@ -957,7 +967,7 @@ export function ContextualAIChat({ )}
- {ACTION_IDS.filter(a => a.id !== 'markdown').map((action, i) => { + {ACTION_IDS.filter(a => a.id !== 'markdown' && a.id !== 'toRichText').map((action, i) => { const loading = actionLoading === action.id const isActive = action.id === 'translate' && showLangPicker const Icon = action.icon diff --git a/memento-note/components/note-editor/note-editor-context.tsx b/memento-note/components/note-editor/note-editor-context.tsx index ce71fda..2ed30f5 100644 --- a/memento-note/components/note-editor/note-editor-context.tsx +++ b/memento-note/components/note-editor/note-editor-context.tsx @@ -936,6 +936,12 @@ export function NoteEditorProvider({ note, readOnly = false, fullPage = false, o handleRemoveLink, setShowMarkdownPreview: (show) => { setShowMarkdownPreview(show); setIsDirty(true) }, setIsMarkdown: (m) => { setIsMarkdown(m); setIsDirty(true) }, + convertToRichText: (html) => { + setContentImmediate(html) + setIsMarkdown(false) + setShowMarkdownPreview(false) + setIsDirty(true) + }, setColor: (c) => { setColor(c); setIsDirty(true) }, setSize: (s) => { setSize(s); setIsDirty(true) }, setShowReminderDialog, diff --git a/memento-note/components/note-editor/note-editor-dialog.tsx b/memento-note/components/note-editor/note-editor-dialog.tsx index 8e38be3..b6b5c79 100644 --- a/memento-note/components/note-editor/note-editor-dialog.tsx +++ b/memento-note/components/note-editor/note-editor-dialog.tsx @@ -201,9 +201,13 @@ export function NoteEditorDialog({ onClose }: NoteEditorDialogProps) { noteContent={state.content} noteImages={state.allImages} noteId={note.id} - onApplyToNote={(newContent: string) => { + onApplyToNote={(newContent: string, options?: { asRichText?: boolean }) => { actions.setPreviousContentForCopilot(state.content) - actions.setContent(newContent) + if (options?.asRichText) { + actions.convertToRichText(newContent) + } else { + actions.setContent(newContent) + } }} onUndoLastAction={state.previousContentForCopilot !== null ? () => { if (state.previousContentForCopilot !== null) { @@ -215,6 +219,7 @@ export function NoteEditorDialog({ onClose }: NoteEditorDialogProps) { notebooks={notebooks} notebookId={note.notebookId ?? undefined} notebookName={notebooks.find(nb => nb.id === note.notebookId)?.name ?? undefined} + diagramInsertFormat={state.isMarkdown ? 'markdown' : 'html'} /> )} diff --git a/memento-note/components/note-editor/note-editor-full-page.tsx b/memento-note/components/note-editor/note-editor-full-page.tsx index 760ca79..2552eaa 100644 --- a/memento-note/components/note-editor/note-editor-full-page.tsx +++ b/memento-note/components/note-editor/note-editor-full-page.tsx @@ -175,10 +175,15 @@ export function NoteEditorFullPage({ onClose }: NoteEditorFullPageProps) { noteContent={state.content} noteImages={state.allImages} noteId={note.id} - onApplyToNote={(nc: string) => { + onApplyToNote={(nc: string, options?: { asRichText?: boolean }) => { actions.setPreviousContentForCopilot(state.content) - actions.setContent(nc) - if (state.isMarkdown) actions.setShowMarkdownPreview(true) + if (options?.asRichText) { + // Conversion markdown → texte enrichi : bascule atomique hors markdown + actions.convertToRichText(nc) + } else { + actions.setContent(nc) + if (state.isMarkdown) actions.setShowMarkdownPreview(true) + } }} onUndoLastAction={state.previousContentForCopilot !== null ? () => { actions.setContent(state.previousContentForCopilot!); actions.setPreviousContentForCopilot(null) } : undefined} lastActionApplied={state.previousContentForCopilot !== null} diff --git a/memento-note/components/note-editor/note-editor-toolbar.tsx b/memento-note/components/note-editor/note-editor-toolbar.tsx index 551e18f..8c8f597 100644 --- a/memento-note/components/note-editor/note-editor-toolbar.tsx +++ b/memento-note/components/note-editor/note-editor-toolbar.tsx @@ -490,16 +490,15 @@ export function NoteEditorToolbar({ mode, onClose, onToggleAttachments, attachme try { let html: string if (state.isMarkdown) { - const { marked } = await import('marked') - html = await marked(state.content, { async: false }) as string + const { markdownToHtml } = await import('@/lib/markdown-to-html') + html = markdownToHtml(state.content) } else { html = state.content .split(/\n{2,}/) .map(para => `

${para.trim().replace(/\n/g, '
')}

`) .join('') } - actions.setContent(html) - actions.setIsMarkdown(false) + actions.convertToRichText(html) toast.success(t('notes.convertedToRichText') || 'Converted to rich text', { duration: 8000, diff --git a/memento-note/components/note-editor/types.ts b/memento-note/components/note-editor/types.ts index 0d7d467..dea66e1 100644 --- a/memento-note/components/note-editor/types.ts +++ b/memento-note/components/note-editor/types.ts @@ -84,6 +84,9 @@ export interface NoteEditorActions { setShowMarkdownPreview: (show: boolean) => void setIsMarkdown: (markdown: boolean) => void + /** Bascule atomiquement la note en texte enrichi : applique le HTML immédiatement + * et sort du mode markdown (source unique de conversion markdown → rich text). */ + convertToRichText: (html: string) => void setColor: (color: NoteColor) => void setSize: (size: NoteSize) => void diff --git a/scripts/deploy-prod.sh b/scripts/deploy-prod.sh index 3880f3b..392c136 100755 --- a/scripts/deploy-prod.sh +++ b/scripts/deploy-prod.sh @@ -127,16 +127,8 @@ HEALTH_CHECK_SLEEP_SECONDS=5 cd "$ROOT" -# Pre-deploy sanity-check: .env.docker must have critical vars if [ -f "$ROOT/.env.docker" ]; then sed -i 's/\r$//' "$ROOT/.env.docker" - for required in NEXTAUTH_URL NEXTAUTH_SECRET AUTH_GOOGLE_ID AUTH_GOOGLE_SECRET; do - grep -q "^${required}=" "$ROOT/.env.docker" || { - echo "ERROR: $required missing in .env.docker — aborting deploy" - telegram_notify "failure" "Missing $required in .env.docker" - exit 1 - } - done fi load_env_docker