Commit Graph

922 Commits

Author SHA1 Message Date
Peter Steinberger 5157340862 fix(browser): avoid colliding extension relay ports (#115592) 2026-07-29 01:40:06 -04:00
Peter Steinberger ad36646ed1 fix(gateway): reconnect nodes after transient socket failures (#115539)
* fix(gateway): reconnect nodes after transient socket failures

* fix(browser): refresh bundled gateway reconnect runtime

* fix(gateway): preserve callback-owned reconnect state
2026-07-29 01:15:26 -04:00
Peter Steinberger 90fca5aadb fix(browser): cancel in-flight status probes (#115534) 2026-07-29 00:35:55 -04:00
Peter Steinberger d239a59d82 fix(ui): make Control UI ownership and permissions reliable (#115364)
* fix(ui): unify connection-owned gateway event dispatch

* fix(qa): keep hosted UI smoke evidence truthful

* fix(ui): make mobile navigation drawer an accessible modal

* refactor(ui): centralize settings search destinations

* fix(ui): own chat media resource lifecycles

* fix(ui): unify sidebar session scope ownership

* refactor(ui): remove obsolete navigation backdrop styles

* refactor(ui): isolate dashboard provider lease capabilities

* fix(ui): centralize gateway operator permissions

* style(ui): format gateway event regressions

* fix(ui): render live dashboard permissions immediately

* fix(ui): enforce approval grant authority

* fix(gateway): fence retired sockets after event gaps

* fix(ui): isolate sidebar gateway fixtures across shared workers

* test(ui): isolate singleton-sensitive browser suites

* fix(ui): retire stale catalog pagination on gateway reconnect

* fix(ui): restore drawer focus after native dialog dismissal

* fix(ui): seed drawer threads and preserve modal focus ownership

* fix(ui): isolate nested native drawer overlay lifecycle

* test(ui): prove isolated dashboard lease authorization

* fix(ui): bound settled managed image resources

* fix(ui): type native modal focus and shared test helper

* fix(ui): correct approval mock types and trim dead export

* fix(ui): keep settings section metadata private

* fix(qa): keep hosted coverage regression within lint limit

* refactor(ui): keep catalog presence in its session data owner

* fix(browser): regenerate bundled copilot runtime

* test(ui): split board lease authorization regressions

* fix(ui): snapshot gateway listener fanout without redundant spread

* fix(ui): bind chat media subscriptions to image lifetime

* fix(ui): extract overlay access lifecycle

* fix(ui): restore guarded media after Lit reconnection

* test(ui): localize board lease fixture title

* fix(ui): reuse system approval fixture labels

* test(ui): narrow managed media lifecycle source

* fix(ui): prevent retired board gateway clients from rolling back leases

* fix(ui): expose pairing to pairing-scoped operators

* fix(ui): preserve legacy device pairing access

* fix(ui): preserve responsive sidebar ownership

* fix(ui): preserve responsive navigation and prove media ownership

* fix(ui): retire revoked catalog and refresh pairing grants

* test(ui): align typed catalog fixtures with main
2026-07-28 16:42:05 -04:00
Peter Steinberger 2b8e6395b9 fix: prevent node gateway hangs and runaway local inference (#115248)
* fix(node): bound gateway wake, cancellation, and local inference

* refactor(gateway): extract bounded node invocation policies
2026-07-28 12:47:30 -04:00
Ayaan Zaidi a54e28e8e9 feat(browser): return inline page state after navigation (#114814)
navigate and act results that changed the page document now include the
loaded page's compact snapshot inline (honoring browser.snapshotDefaults
and standard caps/wrapping), removing the follow-up snapshot round-trip.
Snapshot execution moves to browser-tool.snapshot.ts to keep action
executors under the file size cap.
2026-07-28 20:42:57 +09:00
wahaha1223 4c2d06be2b fix(browser): reject startup when control ports are occupied (#109994)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-28 06:01:02 -04:00
Vincent Koc 9d5bec8487 fix(deps): remediate tar and Hono advisories (#115029) 2026-07-28 16:48:04 +08:00
Peter Steinberger 98b8a18b4c fix(node): harden reconnect and local inference cancellation (#115033)
* fix(node): harden reconnect and local inference cancellation

* fix(browser): refresh bundled gateway client

* fix(gateway): preserve restart after reconnect reset

* fix(node): preserve tracked remote command ownership
2026-07-28 04:18:51 -04:00
Peter Steinberger 0d7fb8eb39 refactor(fs): adopt fs-safe 0.5 core primitives (#113705)
* refactor(fs): unify exclusive file publication

* fix(fs): fence stale lock reclamation

* refactor(fs): bound wiki scans and secret reads

* chore(fs): finalize fs-safe 0.5 compatibility

* fix(fs): preserve publication ownership and legacy mode

* fix(fs): fail closed on unverifiable lock owners

* fix(fs): preserve concurrent backup publications

* refactor(fs): preserve ambiguous backup outputs

* fix(fs): preserve mixed-version lock coordination

* refactor(file-transfer): adopt fs-safe archive extraction

* refactor(fs): add bounded walk and secret seams

* refactor(auth): replace proper-lockfile with fs-safe

* fix(fs): honor Windows mode override casing

* refactor(snapshot): adopt fs-safe publication

* refactor(memory-wiki): adopt prunable root walks

* refactor(fleet): adopt bounded archive restore

* fix(fs): preserve post-publication ownership receipts

* refactor(fs): harvest final fs-safe primitives

* style(fs): clean harvest lint

* chore(plugin-sdk): refresh move helper API baseline

* refactor(snapshot): adopt native Windows ACL facts

* refactor(fs): adopt hardened atomic outputs

* fix(fs): scope lock reentrancy to logical owners

* chore(config): lower env var count budget

* fix(deps): adopt published fs-safe 0.5.0

* fix(ci): align SDK surface ratchets

* fix(ci): regenerate SDK API baseline after rebase

* fix(fs): preserve owner-scoped file lock nesting

* fix(ci): refresh SDK API baseline for file locks

* fix(fs): separate SQLite and file lock reentrancy

* fix(imessage): bound pinned attachment reads

* fix(agents): narrow session-key lock options

* fix(fs): preserve fs-safe 0.5 compatibility contracts

* fix(windows): retain private SQLite directory owner

* refactor(sqlite): centralize exclusive coordinator

* refactor(snapshot): isolate Windows ACL policy

* fix(windows): retain snapshot ACL inspector

* chore(config): realign env budget after rebase

* test(agents): accept canonical sandbox escape error

* docs(changelog): defer fs-safe release note
2026-07-28 03:41:47 -04:00
Peter Steinberger 960b050add refactor(extensions): remove orphaned shadow trial and retired config aliases (#114709)
* refactor(memory-core): remove orphaned shadow trials

* refactor(qqbot): migrate direct voice upload formats

Release note: QQBot configs using voiceDirectUploadFormats now migrate through openclaw doctor --fix to audioFormatPolicy.uploadDirectFormats at root and account scope. Existing nested uploadDirectFormats values win conflicts, and runtime reads only the nested policy.

* refactor(feishu): migrate tools base alias

Release note: Feishu configs using tools.base now migrate through openclaw doctor --fix to tools.bitable at root and account scope. Existing bitable values win conflicts, and runtime accepts only the canonical key.

* refactor(extensions): remove dead runtime state

* chore(config): refresh bundled channel metadata

* refactor(codex): keep realtime fallback type private

* test(ci): align QA compatibility scenario count
2026-07-27 17:12:41 -04:00
Peter Steinberger c54d5aa3e8 test(browser): cover machine output descriptor (#114581) 2026-07-27 08:59:08 -04:00
Peter Steinberger 44bcaa263c fix(browser): bypass managed proxy during CDP handshake (#114546) 2026-07-27 08:32:32 -04:00
Peter Steinberger 3f37731175 docs(agents): surface hidden tool capabilities in model-facing descriptions (#114516) 2026-07-27 07:20:25 -04:00
Peter Steinberger 269bc5c89e fix(cli): preserve machine-readable stdout (#113654)
Co-authored-by: 1052326311 <65798732+1052326311@users.noreply.github.com>
2026-07-27 05:44:16 -04:00
Peter Steinberger bba7e30fcc fix(browser): preserve nested timeouts and cancellation across node actions (#114131) 2026-07-26 12:04:52 -04:00
Peter Steinberger a2c6474377 feat(browser): scoped and structured page extraction (#113938)
* feat(browser): add scoped structured extraction

* fix(browser): keep capture result type module-local and refresh docs map

* fix(browser): keep extract capture helper private
2026-07-25 19:32:44 -07:00
Peter Steinberger 3838d342c2 fix(browser): recover node proxy after failed startup (#113926) 2026-07-25 18:47:11 -07:00
Peter Steinberger d42c11ec24 fix(browser): one unresponsive shared tab no longer hangs every browser tool (#113921)
* fix(browser): keep tab enumeration responsive

Read tab titles from browser-process CDP target metadata and skip bounded target-info reads so one wedged tab cannot block the profile.

Fixes #113787

Co-authored-by: CBruney <CBruney@users.noreply.github.com>

* fix(browser): parallelize tab metadata reads

Resolve page target metadata concurrently so multiple wedged tabs consume one bounded timeout window.

Co-authored-by: CBruney <CBruney@users.noreply.github.com>

---------

Co-authored-by: CBruney <CBruney@users.noreply.github.com>
2026-07-25 18:35:19 -07:00
Peter Steinberger 7c34185ac2 fix(browser): preserve lazy tool output schema (#113925) 2026-07-25 18:26:55 -07:00
Peter Steinberger 4cdd9b8d85 feat(browser): extract action — answer page questions via a bounded sub-model call (#113861)
* feat(browser): add page extract action

* docs(browser): document extract action

* improve(browser): make extract discoverable in tool description

* fix(browser): keep extract dep types module-local
2026-07-25 15:13:32 -07:00
Peter Steinberger 1bce047953 fix(ci): repair plugin prerelease contracts (#113820) 2026-07-25 12:38:31 -07:00
Peter Steinberger 502d1cf56b refactor(browser): split Playwright interaction tools (#113771)
* refactor(browser): split Playwright interactions

* test(browser): track split lint suppressions

* refactor(browser): inline interaction timeout resolver
2026-07-25 12:17:43 -07:00
Peter Steinberger 0e2c60e605 fix(browser): settle page shares when the relay disconnects (#113803)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 12:04:03 -07:00
Peter Steinberger 24d16b39c8 fix(browser): isolate copilot chat events by active turn (#113781)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 11:54:19 -07:00
Peter Steinberger 4dd8a2be76 improve(browser): batch navigation guard, snapshot delta markers, tool output schema, code-mode recipe (#113749)
* feat(browser): guard batches and annotate snapshot deltas

* docs(browser): document reliable automation loops

* test(browser): align batch guard mocks

* fix(browser): reset snapshot deltas after navigation

* fix(browser): detect document navigation without URL equality

* fix(browser): require stable identity for snapshot deltas

* fix(browser): keep snapshot delta helper private
2026-07-25 10:58:03 -07:00
Peter Steinberger fe4972b12b fix(browser): keep shared page text inside producer limits (#113768)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 10:41:06 -07:00
Peter Steinberger dd606796c1 fix(browser): clean up failed guarded navigation routes (#113753)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 09:17:53 -07:00
Peter Steinberger 511d759c50 fix(browser): prevent IME composition from sending copilot messages (#113752)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 09:14:20 -07:00
Peter Steinberger 06548ae57f fix(browser): prevent copilot popup hang when a tab closes (#113744)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 08:39:30 -07:00
Peter Steinberger 332006bc1f test: consolidate OpenClaw test state fixtures (#113576)
* test: consolidate OpenClaw test state fixtures

* test(plugin-sdk): expose isolated test state

Promote the isolated OpenClaw test-state lifecycle through a narrow published Plugin SDK subpath so extension tests no longer import private core helpers. This intentional SDK surface addition is maintainer-approved.

* test: use SDK test-state seam in extensions

Route bundled extension suites through the focused repo-local Plugin SDK test-state entrypoint and remove the Codex projector harness exports made stale by fixture consolidation. Keep the seam out of production builds and published package artifacts while auditing its real consumers in the full-tree deadcode scan.

* test(plugins): map test-state in package boundaries
2026-07-25 05:30:52 -07:00
ooiuuii 591e029095 fix(browser): skip non-executable auto-discovery candidates (#111951)
* fix(browser): skip non-executable candidates

* test(browser): preserve fs constants in mocks

* fix(browser): simplify executable candidate checks

* fix(browser): require regular executable files

* style(browser): format executable candidates

* test(ci): allow sqlite proof on fork runners

* style(test): keep sqlite timeout diff compact

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 04:50:40 -07:00
Peter Steinberger b0603cb443 refactor(fs): adopt shared safe filesystem primitives (#113596)
* refactor(fs): adopt fs-safe helpers

* fix(zalouser): keep stable per-profile QR temp path

* fix(fs): route adoption through owned facades
2026-07-25 03:24:19 -07:00
xingzhou 87b424aca8 fix(browser): control results can contain corrupted text from malformed UTF-8 (#111898)
* fix(browser): reject malformed UTF-8 control responses

* test(browser): cover malformed UTF-8 error responses

* test(browser): strengthen UTF-8 transport coverage

* fix(browser): preserve retry guidance on decode errors

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 02:30:36 -07:00
Peter Steinberger aba0b12014 refactor(browser): split Playwright session manager (#113585) 2026-07-25 01:58:10 -07:00
Peter Steinberger 1e93465a2a refactor(sqlite): enforce one database connection boundary (#113418)
* refactor(sqlite): centralize database opens

* test(sqlite): mock connection owner boundary
2026-07-24 15:15:17 -07:00
Vincent Koc 5ff16901ef refactor(browser): reuse shared error coercion (#113229) 2026-07-24 13:58:29 +08:00
FMLS b88eeddeed feat(browser): add openclaw browser batch CLI subcommand (#111457)
* feat(browser): add `openclaw browser batch` CLI subcommand

Expose the existing `act:batch` runtime through a dedicated CLI subcommand so
users and scripts can run nested act requests in one call without going through
the agent tool.

- `--actions <json>` for inline JSON, `--actions-file <path>` for file input,
  `--actions-file -` for stdin (1MB cap to bound a runaway pipe)
- `--continue` sets `stopOnError=false`; default keeps the runtime fail-fast
  (stop on first error) behavior, matching the existing batch contract
- `--target-id` forwards to the batch body
- Outer request timeout uses `resolveBrowserActExecutionBudgetMs` so the batch
  budget covers nested actions
- Docs (`docs/tools/browser-control.md` + bundled `browser-automation` skill)
  document the batch CLI, ref lifecycle, targetId conflict handling, and error
  summary format

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(browser): fail batch CLI on action errors

* fix(browser): keep batch stdin reader private

* docs(browser): refresh batch heading map

* test(browser): assert batch JSON via runtime mock

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mason Huang <masonxhuang@icloud.com>
Co-authored-by: Mason Huang <masonxhuang@proton.me>
2026-07-24 11:33:45 +08:00
Peter Steinberger 1f051da39d refactor(browser): split Chrome MCP lifecycle (#113114) 2026-07-23 10:45:21 -07:00
Peter Steinberger acd92f6a3d chore(deps): refresh repository dependencies (#112453)
* build(deps): update QA broker dependency

* build(deps): refresh repository dependencies

* build(deps): reconcile rebased shrinkwraps

* test(plugins): remove stale loader test state

* test(deps): stabilize updated dependency coverage

* fix(swift): use caller-isolated TaskLocal overload

* build(deps): regenerate rebased shrinkwraps

* test(msteams): preserve DNS validation in fetch helper

* fix(deps): avoid vulnerable optional image stack

* test(deps): validate generated LRU override

* refactor(ui): extract chat resizable divider

* test(ui): update divider ownership path

* fix(matrix): retain restart-compatible SDK

* style(cron): format update test
2026-07-23 16:17:13 +00:00
Peter Steinberger 525a7f4c96 ci(release): restore full validation after config migrations (#112740)
* fix(browser): preserve scoped CDP authority policy

* test(release): migrate canonical config fixtures

* ci(release): repair acceptance harness drift

* ci(release): extend Anthropic setup budget

* test(release): align remaining CI contracts

* test(release): align Docker and QA contract tests

* docs(release): preserve validation evidence inputs

* test(plugins): align unprepared metadata reads

* ci(release): separate QA live suite filters

* test(release): bind cron MCP cleanup device
2026-07-23 08:46:55 -04:00
LZY3538 954a5089b3 fix(browser): detect Windows browsers when install roots are blank (#111256)
* fix(browser): ignore blank Windows install roots

* fix(browser): complete Windows install root fallbacks

Co-authored-by: LZY3538 <liu.zhenye@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-22 14:54:50 -07:00
Hiroshi Tanaka 52f412bf17 fix(browser): tab creation steals window focus during agent automation (#105356)
* fix(browser): tab creation steals window focus during agent automation

Agent-created tabs inherited CDP's foreground default: direct CDP
Target.createTarget omitted the background flag, and the extension
relay's createTab defaulted to active:true, so every agent tab open
activated the new tab (and, on the extension driver, focused the
window), interrupting whatever the human was doing in that browser.

Direct CDP tab creation now requests background:true (agent tab
ownership/selection is target-id based and never depended on
activation), and the extension relay defaults an omitted background
to true while preserving an explicit background:false, matching the
Codex/Claude-in-Chrome model the extension driver mirrors.

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

* refactor(browser): keep focus fix LOC-neutral

Preserve background tab creation while keeping the oversized CDP and relay modules within the current LOC ratchet.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* fix(browser): honor explicit CDP focus requests

Keep background-by-default automation while treating Target.createTarget focus=true as an explicit foreground request in the extension relay.

Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* fix(browser): preserve explicit CDP focus semantics

Apply the background-by-default automation policy only when focus is omitted, preserving focus=false foreground-tab requests as well as focus=true.

Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* fix(browser): preserve create target window focus

Carry the resolved CDP focus intent through the extension relay and explicitly focus the containing Chrome window when requested.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* style(browser): refresh relay import order

* test(secrets): use secure node exec fixtures

* test(doctor): secure exec secret fixture

* test(doctor): retain narrowed temp path

* test(secrets): secure remaining exec fixtures

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 21:35:40 -07:00
Peter Steinberger edecdbd05e refactor(config): config-surface reduction tranche 3 — product consolidations (review request) (#111527)
* refactor(config): consolidate media model lists

* refactor(config): unify memory configuration

* refactor(config): consolidate TTS ownership

* refactor(config): move typing policy to agents

* refactor(config): retire product-level config surfaces

* refactor(config): share scoped tool policy type

* chore(config): refresh generated baselines

* fix(config): honor agent typing overrides

* fix(config): migrate sibling config consumers

* refactor(infra): keep base64url decoder private

* fix(config): strip invalid legacy TTS values

* chore(config): refresh rebased baseline hash

* fix(doctor): route legacy messages.tts.realtime voice to talk during tts move

* refactor(config): polish final layout names

* refactor(config): freeze retired tuning defaults

* feat(config): add fast mode default symmetry

* refactor(config): key agent entries by id

* docs(config): update final layout reference

* test(config): cover final layout migrations

* chore(config): refresh final layout baselines

* fix(config): align final layout runtime readers

* fix(config): align remaining readers

* fix(config): stabilize final layout migrations

* fix(config): finalize config projection proof

* fix(config): address final layout review

* docs(release): preserve historical config names

* fix(config): complete keyed agent migration

* fix(config): close final migration gaps

* fix(config): finish full-branch review

* fix(config): complete runtime secret detection

* fix(config): close final review findings

* fix(config): finish canonical docs and heartbeat migration

* fix(config): integrate latest main after rebase

* refactor(env): isolate test-only controls

* refactor(env): isolate build and development controls

* refactor(env): collapse process identity indirection

* refactor(env): remove duplicate config and temp aliases

* docs(env): define the operator-facing allowlist

* ci(env): ratchet production variable count

* fix(env): remove stale provider helper import

* fix(env): make ratchet sorting explicit

* test(env): keep test seam in dead-code audit

* test(env): cover ratchet growth and boundary; document surface budgets

* docs(config): document tier-eval consolidations

* docs(config): clarify speech preference ownership

* test(memory): align retired tuning fixtures

* refactor(memory): freeze engine heuristics

* refactor(config): apply tier-eval tranche

* refactor(tts): move persona shaping to providers

* refactor(compaction): move prompt policy to providers

* test(config): align hookified prompt fixtures

* chore(deadcode): classify test-only exports

* chore(github): remove unused spawn helper

* chore(deadcode): classify queue diagnostics

* chore(deadcode): remove unused lane snapshot export

* chore(plugin-sdk): ratchet consolidated surface

* fix(config): integrate latest main after rebase
2026-07-21 20:28:43 -07:00
Peter Steinberger 4541c27f30 fix(browser): regenerate stale copilot runtime bundle (#112379) 2026-07-21 14:28:56 -07:00
Yiğit ERDOĞAN 1096b74ab7 fix(browser): retire durable tab rows whose browser never returns (#111307)
* fix(browser): retire durable tab rows whose browser never returns

Durable cleanup defers whenever ownership cannot be proven, so a browser
that never comes back at the same cdpUrl leaves its rows behind forever:
each sweep re-claims them, fails the identity lookup, warns, and defers
again. Nothing in the subsystem removes a row by age.

The `browser.session-tabs` namespace is opened with a 5000-row cap and
`reject-new`, so once those rows accumulate to the cap, tracking a new tab
throws PLUGIN_STATE_LIMIT_EXCEEDED. That propagates into the compensation
path in browser-tool-session-tabs.ts, which closes the tab the user just
opened and rethrows -- every `browser open` on that profile then opens a
tab, closes it again, and errors, with no self-healing path.

Bound the retry: when a close attempt reports the target unavailable and
the tab has been unused for longer than the retire window, drop the row
instead of deferring again. A browser returning after that long almost
always carries a fresh instance fingerprint, which retires the row through
the ownership-mismatch path anyway.

closeTrackedBrowserTabsForSessions now accepts `now` like the sweep does,
so lifecycle cleanup can be exercised on a coherent clock.

* refactor(browser): split session tab cleanup claim and test harness

check-lint failed on max-lines: session-tab-registry.ts was at 699 of its
700-line budget and the durable registry test at 982 of 1000, so the retire
branch and its regression test pushed both over.

Extract the cleanup claim bookkeeping (claim, ownership match, delete) into
session-tab-cleanup-claim.ts, and the durable registry test shapes into
session-tab-registry.sqlite.test-helpers.ts, matching the existing
*.test-helpers.ts convention in this directory. No behavior change.

* test(browser): protect unreachable retirement races

Co-authored-by: Yigtwxx <yigiterdogan023@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 10:10:28 -07:00
FMLS 25d6f13a1f test(browser): add cross-operation tab reference parity contract (#111375) 2026-07-20 11:56:57 +08:00
mushuiyu886 34978b5a07 fix(browser): report final URL when opening managed Chrome tabs (#111374) 2026-07-19 10:01:42 -07:00
Peter Steinberger 7aedca21b2 test(release): align built-in timing proofs (#111483) 2026-07-19 09:42:16 -07:00
Peter Steinberger 783a5d21cf refactor(config): purge numeric tuning knobs behind built-in defaults (#111382) 2026-07-19 07:35:45 -07:00