Commit Graph

65811 Commits

Author SHA1 Message Date
Peter Steinberger c6ddb4bda9 fix: stabilize gateway deletion admission CI fixture (#103486)
* test(gateway): stabilize deletion admission fixture

* test(gateway): delete session through lifecycle owner
2026-07-10 08:12:51 +01:00
Peter Steinberger 0d63f46498 feat(webchat): the lobster remembers - dex memories and a familiarity arc (#103359)
The Lobsterdex upgrades to a v2 object schema (v1 arrays migrate in
place, memories backfill on the next visit): each palette remembers its
first visitor's name and date, shown in the gallery tooltips ('Goldie -
first visited 7/5/2026'). Familiarity counters (visits, shoos) shape
behavior with no UI: fewer than three lifetime visits is shy (shorter
stays, later arrivals), fifteen or more is a friend (longer stays,
sooner returns, and a hello wave on the first arrival of each load),
and shooing it too often makes it wary, stretching the gaps between
visits. All best-effort localStorage; tuning lives in one exported
table.
2026-07-10 08:10:14 +01:00
Peter Steinberger ce47e6ac53 fix(mcp): keep server config private in groups (#103502)
* fix(mcp): keep server config private in groups

* fix(config): redact underscore credential flags

* fix(config): redact plural credential flags
2026-07-10 08:09:48 +01:00
Peter Steinberger a97633a9ad fix(codex): require human approval for app-server commands (#103457)
* fix(codex): require human approval for app-server commands

* docs(exec): clarify Codex approval fallback
2026-07-10 08:07:18 +01:00
SunnyShu a1d03f1cfd fix(gateway): re-check session runtime model against current agent defaults after hot-reload (#102305)
* fix(gateway): re-check session runtime model against current agent defaults after hot-reload

Agent model hot-reload silently did not take effect because session entries
cached modelProvider/model from agent defaults during reset, and the resolver
returned these cached values before checking current config.

Fix (three-pronged):
1. Reset-side: only cache modelProvider/model when the resolved model came
   from a user override — default-derived values are no longer persisted.
2. Resolver-side: when runtime metadata exists without overrides and an
   agentId is available, the values are default-derived and may be stale —
   skip them in the persisted-model fallback so current config defaults win.
3. Inheritance: only inherit runtime model metadata from parent when it
   carries explicit user overrides (align with reset-side contract).

Reset response includes resolvedModel so API and TUI consumers always get
the effective model identity.

Fixes #102269

* fix(gateway): restore truncateUtf16Safe and emoji-boundary title test per ClawSweeper review

* fix(gateway): only skip stale session runtime model metadata when it actually differs from current defaults

The previous change unconditionally skipped cached modelProvider/model when no
user overrides were present and an agentId was available, assuming it was always
stale. This broke sessions that legitimately had non-default models set through
normal session creation (e.g. custom vision models).

Now the resolver resolves the current agent default first and compares: if the
cached runtime metadata matches the current default it is returned directly
(not stale); only when it differs is it treated as stale and re-resolved.

Also updates tests that set modelProvider/model without overrides to configure
their agent defaults so the expected model matches the resolution result.

* fix(session-model-ref): add stale-metadata detection for config hot-reload

* fix(test): remove strict timeoutMs assertion in provider catalog live-runtime test

The remainingTimeoutMs calculation can be off by 1ms depending on timing
(Date.now() - startedAt = 1ms on fast CI runners), causing a flaky failure.
This assertion is not the test's focus — dedicated timeout behavior is already
covered by 'uses one timeout budget across paginated live catalog discovery'.

* fix: restore AVATAR_MAX_BYTES to 2MB (revert accidental merge contamination)

* fix(gateway): resolve session models from current config

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 08:04:55 +01:00
llagy007 56fb460b83 fix(memory): keep batch failure attempts finite (#103117)
* fix(memory): keep batch failure attempts finite

* fix(memory): own batch retry attempt accounting

Co-authored-by: llagy007 <0668001470@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 08:03:23 +01:00
Peter Steinberger e169bfed7c fix: default optional Swift protocol fields (#103493) 2026-07-10 08:02:49 +01:00
Peter Steinberger ed74d8dc7d test(macos): deflake Codex pipe drain (#103478) 2026-07-10 08:02:39 +01:00
Peter Steinberger d7dc6ee845 fix(xai): validate x_search handle filters (#103393) 2026-07-10 08:02:18 +01:00
Peter Steinberger 19111cf29d fix(xai): route provider alias to native endpoint (#103488) 2026-07-10 08:02:08 +01:00
Pavan Kumar Gondhi 0ac5394192 fix: enforce sandbox tool policy for loopback tools [AI] (#103074)
* fix: apply sandbox policy to gateway loopback tools

* test: type gateway sandbox policy helper

* style: format gateway sandbox policy import

* test: exercise sandbox deny on allowed loopback tool
2026-07-10 12:30:51 +05:30
Peter Steinberger 5476930568 improve(ui): mark the default model inline (#103484)
* improve(ui): mark the default model inline

* chore: leave changelog to release workflow

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-09 23:54:43 -07:00
Peter Steinberger 0f3fb9ea58 fix(codex): prefer ChatGPT desktop resources (#103470)
Co-authored-by: Hiroshi Tanaka <solavrc@gmail.com>
2026-07-10 07:44:24 +01:00
wuqxuan 9e74dabad2 fix: parse zero-argument XML tool calls (#103220)
* fix: parse zero-argument XML tool calls

* fix(tool-call-repair): handle empty XML calls safely

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 07:39:23 +01:00
Peter Steinberger 6025aa5f60 fix(macos): tighten the link-browser tab header (#103469)
Drop the 32pt drag-overlay clearance above the sidebar tab strip to a
12pt inset - just enough to clear the window's 12pt drag overlay so
every tab pixel stays clickable - and shrink the header from 98pt to
78pt. Follow-up to #103438 per maintainer feedback.
2026-07-10 07:37:11 +01:00
Peter Steinberger 4a72a6cb2f feat(ui): move app chrome into a topbar and dock the session workspace rail (#103426)
* feat(ui): move app chrome into a topbar and dock the session workspace rail

The desktop shell now uses a slim topbar for brand, primary navigation
(Chat + pinned routes + More menu), command-palette search, pairing,
theme, and Settings; the left column slims down to a sessions-only
panel (Cmd+B hides it entirely — the 78px icon rail is gone). Split
view drops the fixed geometry-mirroring toolbar for in-flow per-pane
headers. The session workspace rail can dock right or bottom inside
its pane — drag its header between edges or use the dock button — and
the collapsed strip's file glyph is now a real button (it used to be a
dead, button-looking span) with a changed-file count badge. The Mac
app's injected chrome CSS slims down accordingly; its drag-region
geometry is unchanged and the topbar brand strip stays passive under
it.

* chore(ui): regenerate locale bundles for topbar and workspace dock strings

* fix(ui): keep the native macOS drawer clear of the titlebar overlay

The narrow-width slide-over drawer sits fixed at the window top, over
the AppKit traffic lights and drag regions. The old Mac-app-injected
CSS padded .sidebar-shell for this; that rule moved web-side for the
desktop topbar, so restore drawer clearance here for both the app
drawer and the in-drawer settings sidebar.

* chore(ui): translate topbar and workspace dock strings; regen docs map
2026-07-10 07:32:57 +01:00
Vincent Koc f11b2493b9 fix(ci): read Codex bindings from SQLite in live harness (#103467)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 23:32:39 -07:00
cxbAsDev 158d646184 fix(signal): retry inbound flushes on reply session init conflict (#103218)
* fix(signal): retry inbound flushes on reply session init conflict

* fix(signal): bind conflict retries to monitor lifecycle

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 07:29:58 +01:00
Peter Steinberger 20bc552590 feat(webchat): pass-through visitors - strangers and the crab (#103352)
Roughly one load in ten, someone else walks across the footer ledge
once and leaves: usually a stranger lobster wearing a palette the
resident pet does not (hover: 'a stranger'), and on rare loads a crab
(hover: 'definitely a lobster') - wide shell, eye stalks, walks
strictly sideways, smug about it. Passers never perch, never react,
and never count for the Lobsterdex. Planned by a pure per-seed
function, gated by the visits setting, skipped under reduced motion,
and their timers reset with the seed and clean up on disconnect.
2026-07-10 07:22:09 +01:00
NIO 514829f0e1 fix(mattermost): cap outbound and monitor caches (#101740)
Co-authored-by: NIO <nocodet@mail.com>
2026-07-10 07:17:34 +01:00
Peter Steinberger 1d20542449 fix(tlon): strip internal tool-trace banners from outbound text (#103450)
Route assistant-visible Tlon output through the shared sanitizer and prove the rendered Urbit poke payload for DMs, groups, and media captions.

Co-authored-by: masatohoshino <g515hoshino@gmail.com>
2026-07-10 07:17:17 +01:00
Peter Steinberger f698703934 fix(sandbox): reap orphaned container processes (#103441)
Co-authored-by: hobo <hobo.l@binance.com>
Co-authored-by: aaajiao <aaajiao@gmail.com>
2026-07-10 07:09:57 +01:00
Peter Steinberger 7f5dce8bbf fix(xai): discover TTS voices dynamically (#103446) 2026-07-10 07:05:45 +01:00
chengzhichao-xydt 5b916cb319 fix(voice-call): add timeout to guardedJsonApiRequest (#102884)
* fix(voice-call): add timeout to guardedJsonApiRequest

* fix(voice-call): bound provider JSON requests

---------

Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 07:05:24 +01:00
Peter Steinberger 54009c15bb improve(qa): verify native Slack chart delivery (#103337)
* test(qa): prove Slack native chart delivery

* test(qa): exercise Slack chart verifier through scenario

* fix(build): bound private QA SDK declarations separately

* fix(qa): normalize Slack chart history whitespace
2026-07-10 06:58:33 +01:00
Ayaan Zaidi 08b6996cd5 fix(mcp): redact secrets from /mcp show in group chats (#103396)
* fix(mcp): redact secrets in /mcp show replies

Prevent owner /mcp show from dumping raw headers/env credentials into
group chats. Mark MCP env values sensitive, restore redaction sentinels
on set so show→set cannot overwrite real secrets.

Fixes #103053

* test(mcp): e2e redaction of /mcp show secrets on live gateway

Spin up an ephemeral gateway process, chat.send /mcp show with live
credential-bearing config, and prove secrets never leave the reply path.
Also prove show→set sentinel restore on disk via chat and CLI.
2026-07-10 11:28:23 +05:30
pick-cat 7eb163d905 fix(synology-chat): strip internal tool-trace banners from outbound text (#102925)
* fix(synology-chat): strip internal tool-trace banners from outbound text

* fix(synology-chat): satisfy eslint curly rule

* fix(synology-chat): add sanitizeText to outbound type contract

* fix(synology-chat): use canonical outbound sanitizer type

---------

Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:56:20 +01:00
Peter Steinberger 7bb3df9b89 feat(webchat): lobster pet sentience - gaze, petting, honest reactions, vigil (#103344)
The pet watches your pointer between acts (facing follows the cursor,
throttled, reduced-motion inert). Press-and-hold now pets it - content
closed eyes and a floating heart - while a quick tap stays a poke.
Run endings are honest: resolveLobsterRunOutcome picks the most recently
ended session (endedAt first, activity stamps as fallback) so successes
cheer, failures earn a sympathetic droop with sagging antennae, and
user-aborted runs just get an acknowledging startle. Runs longer than
ten minutes summon the pet into a settled vigil pose that pauses all
acts until the run ends.
2026-07-10 06:54:29 +01:00
tzy-17 2f7e2aee15 fix(queue): prevent applyQueueDropPolicy from selecting in-flight items as overflow victims (#103284)
* fix(queue): prevent applyQueueDropPolicy from selecting in-flight items as overflow victims

When a burst of inbound messages hits the followup queue cap while the
head item is mid-delivery, applyQueueDropPolicy can select that same
in-flight item as an overflow victim. With the default
dropPolicy: "summarize", the in-flight item ends up recorded in the
overflow summary as dropped even though it is still being delivered,
producing a contradictory record where the same message is both
answered and reported as unanswered-due-to-overflow.

The fix introduces an optional `inFlight` Set parameter to
applyQueueDropPolicy and drainNextQueueItem. The followup queue state
now owns a shared inFlight set that is:
- Populated by drainNextQueueItem during the await run(next) window
- Populated by the collect-merge drain path for activeGroupItems
- Passed to applyQueueDropPolicy in enqueueFollowupRun

The drop policy now computes an effective queue length that excludes
in-flight items, and skips them when selecting splice victims.

Fixes #103246

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(queue): align pending depth with active deliveries

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:53:29 +01:00
Peter Steinberger 477b2860d5 feat(macos): add tabs to the dashboard link browser sidebar (#103438)
Each inline link opens in its own tab (exact-URL dedupe); sidebar
target=_blank links open new tabs. Tab strip on top with click to
activate, close buttons, middle-click close, pointer-drag reorder, and
a per-tab context menu (Open in Default Browser, Copy Link, Reload,
Close Tab, Close Other Tabs). Navigation controls sit below the tabs
and follow the active tab. Closing the last tab collapses the sidebar
with no lingering webviews or history.
2026-07-10 06:51:49 +01:00
Peter Steinberger 120385a88a fix(media-core): detect encoded URL extensions (#103410)
Co-authored-by: VectorPeak <73048950+VectorPeak@users.noreply.github.com>
2026-07-10 06:50:01 +01:00
krissding 1a0dc9b83f fix(opencode-go): remove deprecated mimo-v2-omni and mimo-v2-pro model aliases (#103329)
* fix(opencode-go): remove deprecated mimo-v2-omni and mimo-v2-pro model aliases

These deprecated aliases reject agent requests from the OpenCode Go gateway.
Remove them from the provider catalog and clean up all references in probe
skip lists, CI workflows, and tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(opencode-go): complete deprecated MiMo cleanup

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:49:09 +01:00
Peter Steinberger 461772868d fix(computer): prevent stale, replayed, and post-cancel desktop actions (#103422)
* fix(ai): preserve streamed tool-call identity

* fix(computer): bind actions to current tool authority

* fix(macos): serialize computer control lifecycle

* docs(computer): document hardened control contract

* chore: follow release-owned changelog policy

* test(agents): cover node list cancellation
2026-07-10 06:47:56 +01:00
Pavan Kumar Gondhi c70f3d0dae fix: block unspecified trusted DNS targets (#103075) 2026-07-10 11:16:26 +05:30
Peter Steinberger e1c144a003 fix(xai): preserve Grok thinking through the x-ai alias (#103340)
* fix(xai): honor provider alias runtime policy

* fix(xai): preserve alias billed tool defaults
2026-07-10 06:45:10 +01:00
Peter Steinberger 9d4fb60e90 fix: harden exec auto-review approvals (#103430) 2026-07-10 06:44:03 +01:00
sunlit-deng 8711f6108a fix(config): cap legacy toolsBySender deprecation warning cache with shared dedupe helper (#101696)
* fix(config): use shared dedupe cache for legacy toolsBySender warnings

Replace unbounded Set with createDedupeCache({ ttlMs: 0, maxSize: 4096 })
from src/infra/dedupe.ts. The shared helper provides check() with
touch-on-read and max-size pruning — no custom LRU stack needed.
Tests verify eviction and hot-key retention through the public
resolveToolsBySender API without a testing-only cache export.

* test(config): tighten legacy warning cache proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:43:17 +01:00
lsr911 2cd831a0e3 fix(agents): use Buffer.byteLength for bash output rolling buffer accounting (#103272)
* fix(agents): use Buffer.byteLength for bash output rolling buffer accounting

The outputBytes variable tracks the rolling output buffer size for
bash command execution, but it used string .length (UTF-16 code units)
instead of Buffer.byteLength (UTF-8 bytes). When command output
contains multi-byte UTF-8 characters (emoji, CJK, etc.), the .length
undercount causes the rolling buffer to exceed maxOutputBytes.

Replace .length with Buffer.byteLength() at both increment and
decrement sites to correctly track byte-level buffer size.

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(agents): unify bash output accumulation

* refactor(agents): unify bash output accumulation

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:41:50 +01:00
LZY3538 939d0ef45d fix(ai): cache and case-insensitively match Azure deployment map (#103005)
* fix(ai): cache and case-insensitively match Azure deployment map

resolveAzureDeploymentNameFromMap re-parsed the deployment-map string into
a new Map on every call (a hot path: streams and lifecycle hooks) and
looked model ids up case-sensitively. A request for `GPT-4o` against a
`gpt-4o=deployment-gpt-4o` map therefore fell back to the raw model id and
404'd on Azure ("deployment not found").

Cache the parsed lookup map keyed by the raw deployment-map string (bounded
so memory stays flat) and normalize keys to lowercase so lookups are
case-insensitive. Deployment names (the values) stay verbatim because Azure
requires the exact deployment name, and the fallback still returns the
original-cased model id.

Fixes #102936

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(ai): prefer exact-case match, case-insensitive only as fallback

Addresses review: lowercasing every key regressed configs whose deployment
map distinguishes keys by case (e.g. `GPT-4o=prod-a,gpt-4o=prod-b`), where an
exact `GPT-4o` request previously resolved to `prod-a` but would now collapse
to the last lowercased entry.

Cache an exact-case lookup alongside the lowercased one and resolve exact
first, using the case-insensitive map only as a fallback. Every previously
working exact mapping is preserved; the case-insensitive path only rescues
ids that would otherwise 404. Adds a regression test for exact-case
precedence.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* test(ai): prove Azure deployment map resolves on the real provider path

Adds an integration test that drives the real streamSimpleAzureOpenAIResponses
path against a loopback server (via the AI transport host fetch) and asserts the
deployment name resolved from AZURE_OPENAI_DEPLOYMENT_NAME_MAP is what lands in
the outgoing request `model` field — the value Azure routes on, and the source
of the reported 404 when it fell back to a mixed-case model id.

Covers the mixed-case fix (GPT-4o -> deployment-gpt-4o on the wire) and the
exact-case no-regression case (GPT-4o -> prod-a).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* test(ai): use block-body promise executors to satisfy oxlint

no-promise-executor-return flagged the arrow executors around server
listen/close; use statement bodies so nothing is returned from the executor.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(ai): simplify Azure deployment lookup

* refactor(ai): simplify Azure deployment lookup

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:38:39 +01:00
maweibin f15f2d1092 fix(ui): normalize Unicode line/paragraph separators in markdown rendering (#102169)
* fix(ui): normalize Unicode line/paragraph separators in markdown

LLM outputs can contain U+2028/U+2029 chars that split() ignores,
causing content to render as one unbroken line in the chat UI.

Define LINE_SEP_RE using String.fromCodePoint() and apply it
alongside existing \r\n normalization in all five markdown
processing entry points. Mirrors normalizeDisplayLineBreaks()
in exec-approval-command-display.

* fix(ui): normalize markdown line breaks once

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:38:07 +01:00
Peter Steinberger ffa3d9a336 fix(slack): restore folded IDs at Web API boundaries (#103214)
* fix(slack): preserve delivery target case

Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>

* fix(slack): restore API IDs at Web API boundaries

Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>

---------

Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>
2026-07-10 06:37:57 +01:00
Peter Steinberger fa3eb673cd feat(slack): accept spoken mentions in audio clips (#103416)
* feat(slack): support spoken audio mentions

* chore: keep release notes in PR body
2026-07-09 22:33:26 -07:00
Peter Steinberger e7b652798f fix(xai): remove synthetic batch STT model (#103419) 2026-07-10 06:32:45 +01:00
neilofneils404 dc783bbde8 fix(restart): ignore missing lsof during startup (#76364)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 06:31:50 +01:00
Peter Steinberger c7909ead5c fix(update): prevent build workers surviving timeouts (#103406)
* fix(update): terminate timed-out process trees

* chore: leave changelog to release generation
2026-07-10 06:30:07 +01:00
Peter Steinberger a39a3ee1d0 fix(ui): reserve the pointer cursor for real links across the Control UI (#103411) 2026-07-10 06:29:19 +01:00
saju01 f0534c5b71 fix(github-copilot): honor live prompt token limits (#103275)
* fix(github-copilot): honor live prompt token limits

* fix(github-copilot): align prompt token budgets

* fix(github-copilot): align prompt token budgets

---------

Co-authored-by: saju01 <saju@coderedcorp.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-10 06:27:14 +01:00
Peter Steinberger 0e4c7cd155 feat(ios): render native markdown headings (#103404) 2026-07-10 06:21:46 +01:00
lsr911 a3f9f3567f fix(terminal): strip C1 control characters (0x80-0x9f) in renderTerminalBufferText (#103274)
renderTerminalBufferText filters C0 control characters (0x00-0x1f)
and DEL (0x7f) but did not filter C1 controls (0x80-0x9f). The C1
range includes the CSI (Control Sequence Introducer) at 0x9b, an
alternative ANSI escape prefix that stripAnsiSequences() may miss.

Add the C1 range to CONTROL_BYTES_REGEX to strip all C1 bytes.

Same pattern as the C1 fix in sanitizeForConsole (#103226).

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-10 06:21:29 +01:00
mikasa 541c9f0bf0 fix(cli): bound node camera URL downloads (#103266)
* fix(cli): bound node camera URL downloads

* refactor(cli): enforce camera download policy at guard

* refactor(cli): enforce camera download policy at guard

* refactor(cli): enforce camera download policy at guard

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-10 06:21:01 +01:00