Commit Graph

39 Commits

Author SHA1 Message Date
can1357 8f18464cd7 feat(config): reorganized settings into 8 focused categories with 15+ new customization options
- Reorganized settings tabs from 12 to 8 focused categories (appearance, model, interaction, context, editing, tools, tasks, providers) with consolidated status line settings.
- Added 15+ new settings for status line customization, sampling parameters, speech-to-text, web search, and edit mode configuration.
- Changed default agent model from `default` to `pi/task` for independent subtask configuration and updated model resolution to support single-pattern inheritance fallback.
- Updated system prompt to use ISO 8601 date format (YYYY-MM-DD) and renamed 25+ UI labels for consistency across settings interface.
- Updated tab icon symbols across unicode, nerd, and ASCII presets to reflect new tab organization.
- Simplified settings definitions and removed unused imports to reduce code complexity.
2026-03-14 13:44:20 +01:00
lederniermagicien 486fd4c753 refactor(theme): replace CoreFoundation FFI with OSC 11 for machine-agnostic dark/light detection (#347)
* refactor(theme): replace CoreFoundation FFI + Mode 2031 with OSC 11 for dark/light detection

Replace the 415-line Rust CoreFoundation FFI module and Mode 2031-only
detection with OSC 11 background color queries — the machine-agnostic
method used by Neovim, fish, bat, and terminal-colorsaurus.

Detection stack:
- OSC 11 query + DA1 sentinel at startup (works over SSH, mobile clients)
- Mode 2031 subscribe: re-queries OSC 11 with 100ms debounce (Neovim
  convention) instead of trusting binary dark/light value directly
- 2s OSC 11 poll for terminals without Mode 2031 (Warp, Alacritty,
  WezTerm, iTerm2); self-disables once Mode 2031 fires
- COLORFGBG env var fallback (free, no I/O)
- macOS defaults read fallback (Zellij edge case)

Deleted:
- crates/pi-natives/src/appearance.rs (414 lines of unsafe FFI)
- packages/natives/src/appearance/ (66 lines of TS bindings)
- macOS appearance observer and SIGWINCH coupling in theme.ts

Net: -424 lines. Rust crate lighter, detection works over SSH.

* fix(theme): ignore bogus zellij osc11 dark reading

* fix(theme): scope macOS fallback to broken terminal paths

* fix(tui): swallow DA1 sentinels for OSC 11 probes

---------

Co-authored-by: can1357 <me@can.ac>
2026-03-11 00:58:17 +01:00
can1357 8e3e0ebf9e feat: introduced Effort enum and ThinkingConfig for model-aware reasoning
- Introduced Effort enum and ThinkingConfig metadata for per-model reasoning capabilities with min/max effort levels.
- Migrated thinking level API from string-based ThinkingLevel to structured Effort enum across agent and AI packages.
- Added model-thinking module with effort mapping, policy application, and semantic versioning utilities for provider-specific thinking modes.
- Removed supportsXhigh() function and replaced effort clamping with model-aware validation using ThinkingConfig metadata.
- Expanded models.json with thinking configuration objects for 50+ models including Claude, Gemini, and OpenAI variants.
- Added Python analysis scripts for edit tool usage patterns and tool invocation stream processing.
2026-03-06 12:35:01 +01:00
can1357 b696842570 feat: added serviceTier option and providerPayload field to OpenAI providers
- Added serviceTier option to OpenAI providers for controlling processing priority and cost across agent, completions, responses, and codex APIs.
- Added providerPayload field to messages for transport-native history reconstruction in OpenAI Responses and Codex APIs.
- Added /fast slash command and serviceTier setting to coding-agent for toggling OpenAI priority mode with fast mode indicator.
- Added remote compaction support with encrypted reasoning preservation for OpenAI models in coding-agent.
- Removed usage caching layer across all providers and refactored UsageFetchContext to eliminate cache and now dependencies.
- Fixed OpenAI Codex streaming service_tier inclusion, provider retry logic with exponential backoff, and email-based credential deduplication.
2026-03-06 12:34:57 +01:00
can1357 e1897ce013 refactor: migrated thinking configuration to centralized pi-ai module
- Extracted thinking module with ThinkingEffort, ThinkingLevel, and ThinkingMode types to centralize reasoning configuration across packages.
- Migrated ThinkingLevel type from pi-agent-core to pi-ai package with new validation functions parseThinkingLevel() and getAvailableThinkingLevel().
- Consolidated thinking level constants and descriptions into reusable exports (ALL_THINKING_LEVELS, THINKING_MODE_DESCRIPTIONS) for consistent UI display.
- Removed local thinking-effort-label utility and replaced formatThinkingEffortLabel() with centralized formatThinking() function from pi-ai.
- Refactored thinking mode handling to distinguish ThinkingSelector (user-facing with 'off' option) from ThinkingEffort (provider-level).
2026-03-05 00:03:40 +01:00
Kevin Loftis 5ee80f3a36 feat: Add PR number segment to status bar (#258)
* Add PR number segment to status bar

Add a new 'pr' status line segment that shows the GitHub PR number
(e.g., #1234) as a clickable OSC 8 hyperlink when the current branch
has an associated pull request.

- Async lookup via 'gh pr view', cached per branch
- Invalidates on branch change via .git/HEAD watcher
- Falls back to hidden segment when no PR exists or gh unavailable
- Supports all theme presets (unicode, nerd font, ascii)
- Added to all preset layouts after the git segment

* Skip PR lookup on default branch, resolve dynamically

* Extract git-utils, add tests for parseGitHubRepo and parseDefaultBranch

* Fix PR lookup race condition, invalidation churn, and dotted repo names

- Guard #cachedPr writes against branch change during in-flight lookup
- Stop clearing PR cache in invalidate() (only .git/HEAD watcher should)
- Allow dots in GitHub repo names in parseGitHubRepo regex

* Simplify PR lookup: use gh pr view, try upstream/HEAD for default branch

- Replace gh pr list --head with gh pr view (requires gh repo set-default)
- Remove manual remote URL resolution — gh handles it
- Default branch detection falls back to upstream/HEAD when origin/HEAD is unset
2026-03-03 03:24:15 +01:00
can1357 1c30f5c972 feat: introduced render_mermaid tool for ASCII diagram output
- Added render_mermaid tool to convert Mermaid diagrams to ASCII output with configurable rendering options.
- Added renderMermaid.enabled setting to control availability of the render_mermaid tool.
- Changed Mermaid rendering from PNG terminal graphics to ASCII text format across theme and TUI components.
- Migrated mermaid utilities from pi-tui to pi-utils package with new ASCII rendering functions.
- Removed PNG-based mermaid rendering APIs (getMermaidImage, renderMermaidToPng) in favor of ASCII alternatives.
2026-03-01 09:40:57 +01:00
Kevin Loftis 32efca8536 fix(theme): prioritize COLORFGBG over macOS system appearance for auto-detection (#221)
COLORFGBG reflects the actual terminal profile colors, while
detectMacOSAppearance() reports the OS-level dark/light setting.
When a user runs a dark terminal on macOS light mode (or vice versa),
COLORFGBG gives the correct answer. The previous ordering caused omp
to load the light theme in dark terminals when macOS was in light mode.

Detection priority is now:
1. Mode 2031 (terminal DSR) - most authoritative
2. COLORFGBG env var - reflects terminal profile
3. macOS system appearance - OS-level fallback
4. Default to dark
2026-02-28 18:38:14 +01:00
lederniermagicien c34a2c01e4 feat(theme): native macOS appearance detection via CoreFoundation FFI (#207)
Move macOS dark/light mode detection from compiled Objective-C helper
+ shell-out to defaults(1) into the Rust pi-natives crate.

Sync detection: CFPreferencesCopyAppValue reads AppleInterfaceStyle
directly — no subprocess, no shell.

Observer: background thread registers with CFDistributedNotificationCenter
for AppleInterfaceThemeChangedNotification. A 2-second CFRunLoopTimer
serves as both run-loop keep-alive and polling fallback (distributed
notifications may not reliably reach background threads on all macOS
versions). Dedup logic prevents double-firing.

Removes: MACOS_OBSERVER_OBJC constant, getOrCompileObserver(), binary
cache at ~/.omp/cache/, defaults read shell-out, readLines stream
parsing, fallback poll timer.

Adds: crates/pi-natives/src/appearance.rs (CoreFoundation FFI),
packages/natives/src/appearance/ (TS bindings).
2026-02-28 12:13:09 +01:00
can1357 faa1dd32b0 chore: trimmed deps
- Replaced external dependencies with native Bun APIs: glob, TOML parsing, and HTML parsing.
- Removed 7 unused dependencies (file-type, glob, ignore, marked, zod, ms, @types/ms) and simplified package.json.
- Migrated mermaid cache key type from string to bigint using Bun.hash.xxHash64() for efficient hashing.
- Deleted ignore-files utility module and removed rootDir/ignoreMatcher parameters from loadFilesFromDir().
- Implemented inline MIME type detection for images, reducing sniff buffer from 4100 to 12 bytes.
2026-02-28 06:23:00 +01:00
lederniermagicien 8664af3a3c feat(theme): implement Mode 2031 for automatic dark/light theme switching (#196)
Add cross-platform terminal dark/light mode detection using the Mode 2031
VT extension (DECSET 2031). On startup, query the terminal's current
appearance with CSI ? 996 n, then subscribe to live appearance change
notifications with CSI ? 2031 h. When the OS or terminal switches between
dark and light mode, the terminal sends a DSR that triggers an automatic
theme re-evaluation.

Previously, detectTerminalBackground() only checked the COLORFGBG
environment variable once at launch — a static value that never updates
when the system appearance changes mid-session. The SIGWINCH listener
only fires on terminal resize, not on appearance changes.

Mode 2031 is supported by Ghostty, Kitty (0.38.1+), Contour (0.4.0+),
VTE/GNOME Terminal (0.82.0+), and tmux (3.6+). Unsupported terminals
silently ignore the escape sequences and fall back to the existing
COLORFGBG heuristic.
2026-02-28 05:26:38 +01:00
can1357 8f78e50f1b Move poimandres themes into builtin defaults 2026-02-26 11:02:17 +01:00
can1357 a83175c94c refactor: migrated imports to unified package root and consolidated skill discovery logic
- Consolidated @oh-my-pi/pi-utils subpath imports into single package root import across 100+ files.
- Moved tryParseJson utility from local web scrapers module to @oh-my-pi/pi-utils package for centralized JSON parsing.
- Renamed loadSkillsFromDir to scanSkillsFromDir and refactored skill discovery to use fs.promises.readdir instead of glob-based approach.
- Replaced custom parseJSON with tryParseJson across discovery modules for consistent error handling.
- Removed emitCustomToolSessionEvent method and cleanupSshResources function, consolidating shutdown logic into dispose method.
- Updated glob pattern construction to use GlobBuilder with literal_separator(true) for improved path handling.
2026-02-23 20:59:17 +01:00
DeprecatedLuke ae2721c4cd fix(coding-agent): cosmetic TUI fixes - spinner icons, bracket styling, status icon placement 2026-02-19 23:46:20 +00:00
can1357 081f1063d9 fix(coding-agent): hardened mermaid prerender failure handling
Fixes #109
2026-02-19 05:31:10 +01:00
can1357 8ff758ed07 feat(coding-agent/modes): fixed theme selector with non-destructive preview and deduplication
- Added new previewTheme() function to enable non-destructive theme preview during settings browsing.
- Implemented asynchronous theme loading with request deduplication to prevent race conditions when rapidly browsing theme options.
- Enhanced theme preview cancellation behavior to restore the previously active theme instead of the current value.
- Fixed theme preview updates being applied out-of-order when rapidly browsing theme options by using request ID tracking.
2026-02-15 14:22:43 +01:00
can1357 f20a964986 feat(coding-agent): added animated microphone icon and skill discovery via symlinks, improved STT feedback
- Added animated microphone icon with color cycling during voice recording and transcription states.
- Added support for discovering skills via symbolic links in the skills directory.
- Changed STT status messages to display via state change callbacks instead of dedicated status line segment.
- Removed dedicated STT status line segment in favor of animated cursor-based feedback.
- Added cursor override feature to TUI editor for customizing end-of-text cursor glyph with ANSI-styled strings.
2026-02-15 13:37:43 +01:00
can1357 a155d98f9f feat(coding-agent): auto-switch dark/light theme via SIGWINCH
Replace single `theme` setting with `theme.dark` and `theme.light`.
Auto-detection is always on — COLORFGBG determines which slot to use.
On SIGWINCH, re-check COLORFGBG and switch themes if background changed.
Old `theme` setting auto-migrated using luminance detection.

Fixes #65
2026-02-15 10:20:11 +01:00
can1357 fcd7ff4f84 refactor(dirs): centralized directory path utilities into @oh-my-pi/pi-utils/dirs module
- Extracted directory path utilities from multiple packages into a centralized '@oh-my-pi/pi-utils/dirs' module.
- Moved 30+ path helper functions (getAgentDir, getConfigRootDir, getPluginsDir, getMCPConfigPath, etc.) from scattered locations into a single shared utility module.
- Consolidated APP_NAME, CONFIG_DIR_NAME, and VERSION constants into the centralized dirs module for reuse across packages.
- Updated 70+ import statements across packages/ai, packages/coding-agent, packages/stats, and packages/tui to use the new centralized module.
- Removed local path construction logic and replaced with utility function calls for improved maintainability and consistency.
- Deleted packages/coding-agent/src/extensibility/plugins/paths.ts as its functions were moved to the centralized dirs module.
2026-02-13 15:06:05 +01:00
can1357 9ef390c09b feat(coding-agent): added inline hints and subcommand support for slash commands
- Added inline hint support for slash commands with getInlineHint() method on SlashCommand and AutocompleteProvider interfaces.
- Added SubcommandDef interface for declarative subcommand definitions with name, description, and usage properties.
- Added subcommands and inlineHint properties to BuiltinSlashCommand interface for enhanced command configuration.
- Added getArgumentCompletions and getInlineHint functions to materialized slash commands for browser and mcp subcommand completion.
- Converted browser command to support subcommands (headless, visible) with inline hints.
- Converted mcp command to support 10 subcommands (add, list, remove, test, reauth, unauth, enable, disable, reload, help) with descriptions and usage hints.
2026-02-10 15:35:06 +01:00
can1357 acf8ab5225 style: stylistic changes 2026-02-10 07:39:39 +01:00
can1357 eb9cb2a0a2 feat(coding-agent): changed Unicode symbols 2026-02-07 08:32:02 +01:00
can1357 5b6f88dd95 fix: fixed #11 schema normalization, #10 version parsing, and variable declarations
- Fixed schema normalization in Google provider to handle array-valued type fields by converting them to single type with nullable flag.
- Refactored version parsing in install script to use bash parameter expansion instead of IFS field splitting.
- Changed variable declarations from let to var in theme module global scope.
2026-02-07 02:43:56 +01:00
can1357 b902723cc9 refactor(coding-agent): converted class properties to TypeScript parameter properties across 51 files
- Converted class properties to TypeScript parameter properties across 51 files to reduce boilerplate code.
- Removed explicit field declarations and manual assignments in constructors by using TypeScript's parameter property syntax with access modifiers.
- Applied consistent pattern of declaring private readonly and public readonly properties directly in constructor parameters.
2026-02-05 06:34:12 +01:00
can1357 89e6479661 refactor: migrated environment variable access from process.env to Bun.env across 71 files
- Migrated all environment variable access from Node.js `process.env` to Bun runtime `Bun.env` API across the entire codebase.
- Updated 71 files including source code, tests, documentation, and configuration to use Bun's native environment variable API.
- Added comprehensive environment variables documentation in `packages/coding-agent/docs/environment-variables.md` covering 100+ environment variables organized by category.
- Updated CHANGELOG entries to reflect migration from `process.env` to `Bun.env` and environment variable prefix changes (PI_* vs OMP_*).
- Maintained identical behavior and logic across all changes - only the environment variable access method was updated.
2026-02-05 04:51:18 +01:00
can1357 73a24048a7 feat(coding-agent): reorganized settings tabs from 8 to 10 with improved categorization and visual icons
- Reorganized settings tabs from 8 to 10 tabs with improved categorization: Display, Agent, Input, Tools, Config, Services, Bash, LSP, TTSR, and Status.
- Moved behavior-related settings (thinking level, steering mode, retry attempts) from Behavior tab to new Agent tab.
- Moved input/interaction settings (escape action, collapse changelog, notifications) to new Input tab.
- Moved tool configuration settings (line numbers, fuzzy matching, patch mode) from Tools tab to new Config tab.
- Moved provider and external service settings (web, image, exa) to new Services tab.
- Removed type guard functions (isBashToolResult, isReadToolResult, isEditToolResult, isWriteToolResult, isGrepToolResult, isFindToolResult, isLsToolResult) from public API exports.
2026-02-02 14:56:53 +01:00
can1357 09225bc491 feat: refactored text truncation API to use string type and hardcoded ellipsis
- Changed TextInput type parameter to string in truncateToWidth(), visibleWidth(), sliceWithWidth(), and extractSegments() functions in native bindings.
- Removed TextInput type export from public API of pi-natives package.
- Removed format.ellipsis symbol from theme configuration, replacing all theme-based ellipsis references with hardcoded Unicode ellipsis character (...).
- Removed ellipsis property from SymbolTheme interface in pi-tui package.
- Removed truncateToWidth, sliceWithWidth, and extractSegments wrapper functions from pi-tui public API, now re-exporting directly from pi-natives.
- Added early return optimizations in truncateToWidth() and sliceWithWidth() native functions to skip native calls when possible.
2026-02-01 10:01:56 +01:00
can1357 a07f38b16e feat(grep): added grep CLI, diff highlighting, FileReader abstraction, and markdown improvements
- Added grep CLI subcommand with support for pattern matching, file globbing, context lines, and multiple output modes (content, files-with-matches, count).
- Added diff syntax highlighting support with distinct colors for inserted and deleted lines in code output.
- Implemented FileReader abstraction for cross-platform file reading with mmap support and 4MB size limit.
- Refactored worker pool initialization to support both compiled and development build environments using resolveWorkerSpecifier utility.
- Enhanced markdown rendering with improved inline style context handling and blockquote formatting with text wrapping.
- Replaced external strip-ansi dependency with Bun's built-in stripANSI method across all packages.
2026-01-31 01:27:36 +01:00
can1357 6665b0dfaa fix(coding-agent): fixed linter issues and reorganized imports for consistency
- Fixed incorrect byte and line limit calculations in file read tool that were applying user limits to total selected content instead of just user-limited content.
- Updated test to use SettingsManager.getGlobalShellConfig() instead of shell.getShellConfig() for consistent shell configuration access.
- Reorganized import statements across multiple files for consistency and alphabetical ordering.
- Changed firstLinePreviewChunks from let to const in read tool since it is only mutated via array methods.
2026-01-29 15:41:35 +01:00
can1357 37d5b69250 feat(highlight): replaced cli-highlight with rust-based syntax highlighting
- Added native syntax highlighting module powered by syntect library with ANSI color output support.
- Implemented highlightCode() function that applies syntax highlighting to code with language detection and customizable color themes.
- Implemented supportsLanguage() function to check if a given programming language is supported for syntax highlighting.
- Implemented getSupportedLanguages() function that returns list of all supported language identifiers.
- Replaced cli-highlight dependency with native syntect-based highlighting in coding-agent theme module.
- Added comprehensive language alias mappings supporting 50+ programming languages including TypeScript, Python, Rust, Go, C/C++, and web languages.
2026-01-29 12:01:11 +01:00
can1357 8ef11355e7 perf(tui,natives): added native text utilities with JS fast path for short strings
- Added native text utilities in pi-natives (visible width, truncation, slicing, segment extraction)
- Wired pi-tui to use native implementations with short-string JS fast path
- Optimized key matching via cached parsed key ids
- Refactored visual truncation to reuse Text instances
- Reduced theme color lookups by switching from Map to plain records
- Regenerated WASM artifacts

Benchmarks (after vs before, lower is better):
- truncateToWidth/ansi: 20.37ms vs 38.13ms (2000 iters)
- sliceWithWidth/ansi: 5.12ms vs 20.39ms
- extractSegments/ansi: 8.92ms vs 27.60ms
- truncateToVisualLines: 3.51ms vs 411.55ms (500 iters)
- visibleWidth/ansi: 0.24ms vs 0.31ms
2026-01-29 10:47:55 +01:00
can1357 79079e6ecd feat(coding-agent): added plan mode with approval workflow and tool gating
- Plan mode provides structured workflow where agents propose plans for user approval before execution.
- Added plan:// internal URL protocol for accessing plan files and injecting plan-mode context into subagent prompts.
- Added plan mode toggle shortcut and paused status indicator in status line.
- Fixed plan reference injection to properly pass workflow state to plan-mode system prompts.
- Improved autocomplete fuzzy matching to support subsequence matching for skill suggestions.
2026-01-25 19:35:26 +01:00
can1357 b9dfcb2890 refactor(coding-agent/modes): consolidated color conversion logic in theme module
- Removed duplicate hexToRgb and rgbToAnsi functions that were only used in foreground color conversion.
- Reused colorToAnsi for background colors by applying ANSI code substitution instead of reimplementing the full logic.
2026-01-25 14:01:45 +01:00
can1357 779ca4872b style(deps): migrated from Prettier to Biome and updated formatting rules
- Removed Prettier configuration files (.prettierignore and .prettierrc) and migrated formatting to Biome.
- Updated Biome configuration from version 2.3.11 to 2.3.12 and changed arrowParentheses rule from 'always' to 'asNeeded'.
- Pinned @biomejs/biome dependency to exact version 2.3.12 in package.json and bun.lock.
- Applied consistent arrow function formatting across 489 files by removing unnecessary parentheses around single parameters.
- Removed blank lines after comment blocks and reorganized imports for consistency across the codebase.
2026-01-24 04:20:19 +01:00
can1357 e22d123009 refactor(fs): migrated remaining sync file operations to async
- Converted readdirSync, readFileSync, and statSync to async readdir, readFile, stat across skills and agent discovery.
- Made scanDirectoryForSkills async and refactored custom directory scanning to use Promise.all for concurrent processing.
- Updated agent discovery to use fs/promises for async file reading and refactored helper patterns.
- Added AgentParsingError exception class for better error handling during agent parsing.
- Added filesystem error type guards (isEnoent, isEacces, isPerm, etc.) to pi-utils for safe error checking.
- Added color manipulation utilities to pi-utils for accessibility features.
- Added color-blind mode setting to settings manager.
- Migrated plugins, settings, and config modules from sync to async file operations.
- Updated error handling to use new pi-utils type guards for type-safe checking.
2026-01-24 03:18:03 +01:00
can1357 f66e5dba9b build(config): refactored build and TypeScript configuration with Bun loaders
- Removed WASM generation script; use Bun `wasm?raw` loader for imports.
- Added bunfig.toml with loaders for `.md`, `.py`, and `.wasm?raw` text imports.
- Added types/assets/index.d.ts for global TypeScript module declarations.
- Unified TypeScript configuration with tsgo-based checking across monorepo.
- Removed build and WASM steps from install and publish pipelines.
2026-01-24 00:03:52 +01:00
can1357 0fe761dc4b build(deps): refactored TypeScript and package configuration across monorepo
- Added tsconfig.publish.json files to all packages with optimized publish-time configuration.
- Updated all package.json scripts with prepublishOnly hooks for correct type checking during publish.
- Added @oh-my-pi/omp-stats path mappings to root tsconfig.json for consistent imports.
- Added WASM generation script for photon module and integrated into install:dev script.
2026-01-23 13:46:06 +01:00
can1357 d672458138 feat(coding-agent): added mermaid rendering and Python kernel session pooling
- Added mermaid rendering with terminal graphics for markdown output in iTerm2 and Kitty terminals.
- Implemented two-level mermaid caching with deduplication by content hash.
- Added background mermaid pre-rendering in assistant messages for responsive display.
- Implemented Python kernel session pooling with MAX_KERNEL_SESSIONS limit and idle cleanup timer.
- Refactored commit agent to remove unused FileObservation type and improve prompts.
- Updated test utilities to use AuthStorage.create() async factory method.
2026-01-23 13:46:06 +01:00
can1357 cb5bbbf382 refactor(coding-agent): flattened directory structure, eliminated core/ folder
- Eliminated core/ directory (252 files, 23 subdirs → distributed)
- Reduced max nesting from 9 levels to 5 levels
- Promoted tool subdirs to top level: exa/, lsp/, patch/, task/, web/
- Merged web-scrapers/ + web-search/ into web/{scrapers,search}/
- Flattened modes/interactive/ to modes/
- Split execution/ into: ipy/ (python), exec/ (bash), ssh/
- Renamed ipy/python-*.ts to ipy/*.ts (executor, kernel, etc.)
- Flattened cursor/exec-bridge.ts to cursor.ts
- Created logical groupings: config/, session/, extensibility/, export/
- Updated all imports across 500+ files
2026-01-23 12:24:47 +01:00