Commit Graph

2096 Commits

Author SHA1 Message Date
Peter Steinberger ec866d8abc fix(telegram): clear stale localized command menus (#120885)
* fix(telegram): clear stale localized command menus

* test(telegram): satisfy command menu lint
2026-08-08 22:14:58 -07:00
Peter Steinberger 6192673da4 perf(doctor): delete the heavy doctor barrel and finish slimming enumeration (#120882)
* refactor(plugin-sdk): delete the heavy runtime-doctor barrel

Nothing may pull the state-db/kysely graph through a doctor barrel anymore.
The barrel's remaining heavy exports move to two narrow private-local
subpaths, each with a single purpose:

- doctor-repair-runtime: install-path diagnosis, plugin config removal, and
  state-database schema detect/repair (matrix doctor, voice-call lazy import)
- plugin-state-store-runtime: the sync keyed-store factory. It stays out of
  plugin-state-runtime because hot channel entrypoints import that at module
  load and opening a store pulls the state-database graph.

Doctor closures also stop pulling ssrf-runtime (fetch-guard + gateway net)
for two legacy private-network helpers that live in the lighter ssrf-policy
subpath: mattermost, nextcloud-talk, tlon, matrix.

The closure guard now forbids the two new heavy subpaths instead of the
deleted barrel, so the invariant keeps being enforced where it still applies.

* perf(doctor): keep heavy graphs out of every doctor closure

Doctor enumeration cold-loads each declaring plugin's contract closure, so
one heavy import in a closure is paid by the whole sweep. Four barrels were
still dragging unrelated graphs in for trivial helpers; each is repaired at
the leaf rather than by caching downstream:

- Legacy private-network config migration moves to a config leaf. It only
  reshapes records, but lived beside the SSRF runtime (DNS, proxy, logging),
  costing mattermost ~2.7s. ssrf-policy re-exports it, surface unchanged.
- Streaming config readers move to a leaf. They read two config keys, but
  streaming.ts also formats tool aggregates, pulling tool-display/logging/
  acp-core; that cost slack ~2.3s.
- signal took the channel-secret barrel for isRecord; the canonical plugin
  record guard is string-coerce-runtime (root AGENTS.md).
- llm-task took the provider-model barrel for parseModelRef, now a narrow
  model-ref-parse subpath.

Full doctor enumeration of all 42 declaring plugins, built mode:
legacy config rules 6668ms -> 1265ms, state migrations 184ms -> 127ms.
No plugin remains an outlier; the slowest is now ~380ms against a ~200ms floor.

Public export surfaces of every touched SDK subpath are byte-identical
(verified by diffing built module exports before/after); the API baseline
hashes move only because re-exported declarations emit differently.

The closure guard gains rules for each repaired barrel so the invariant
holds for future closures.

* fix(release): exclude new private-local declarations from the published package

Same pack-path rule as c41da3759f: private-local subpaths ship without d.ts.

* fix(doctor): repair the closure guard violations that break main

The landed guard fails on main: three closures import heavy barrels for one
symbol each. Two more surfaced once the guard learned about the provider-model
barrel. Each gets a narrow subpath at the leaf:

- telegram sent-message-cache + state-migrations took the session-store barrel
  (session accessor + state-db) for resolveStorePath -> session-store-paths
- discord thread-bindings.state took the channel-outbound barrel (reply
  pipeline + channel registry) for one identity write -> outbound-echo-runtime
- discord model-picker took the provider-model barrel for normalizeProviderId,
  which model-ref-parse now exposes beside parseModelRef

The guard also stops walking artifacts of plugins whose manifest declares no
doctor surface. Such a declaration gates the artifact off every enumeration
path exactly as resolvePluginDoctorContracts does, so its closure cost is never
paid; anthropic ("doctorContract": {}) was being held to a cost it cannot
incur. Absent declarations still load eagerly and stay enforced.

Side effect worth naming: discord's built doctor contract now loads again.
On main both discord and telegram fail to require in packaged builds (an
ESM-only transitive dep) and silently lose their repairs; this restores
discord and takes enumerated legacy config rules from 87 to 99. Telegram's
built artifact still pulls execa through dist chunking - a build-level defect
with a different owner, filed as follow-up.
2026-08-08 22:01:44 -07:00
Peter Steinberger e1ec95dcbf refactor(auth): dedupe profile upserts and approval resolvers (#120831)
* refactor(auth): dedupe profile upserts and approval resolvers

* test(auth): mock canonical locked upsert

* test(auth): mock locked upsert during onboarding
2026-08-08 21:14:16 -07:00
clawsweeper[bot] c121788611 fix(telegram): prioritize configured commands under menu pressure (#119717)
* fix(telegram): prioritize configured commands under menu pressure
* fix(telegram): preserve custom commands under localized menu pressure

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: ayeshakhalid192007-dev <ayeshakhalid192007@gmail.com>
2026-08-09 09:07:51 +05:30
Peter Steinberger b7add0b560 fix(telegram): honor polling retry cooldown in watchdog (#120841) 2026-08-08 20:24:05 -07:00
Peter Steinberger 75dbe52e3e refactor: one code path behind doctor legacy-state migrations (#120716)
* refactor(doctor): prefer manifest route-state owners

* refactor(doctor): unify config repair declarations

* refactor(doctor): unify legacy state migrations

* fix(doctor): satisfy migration pipeline guards

* fix(plugin-sdk): keep doctor adapter inside boundary
2026-08-08 18:23:15 -07:00
Peter Steinberger ba7561d25d fix(telegram): acquire polling queue before starting worker (#120800) 2026-08-08 18:20:04 -07:00
Peter Steinberger 8cb53c7b55 perf(doctor): keep bundled doctor contract closures dependency-light (#120698)
* perf(doctor): keep bundled doctor contract closures dependency-light

Doctor contract enumeration cold-loads each plugin's doctor-contract-api
closure via jiti, so a static value import of openclaw/plugin-sdk/runtime-doctor
pulled the state-db/kysely graph (~4.3s per closure) into
listPluginDoctorLegacyConfigRules / listPluginDoctorStateMigrationEntries.

- migrate all light doctor-contract closures (66 files) to the
  dependency-light openclaw/plugin-sdk/runtime-doctor-migrations subpath
- voice-call: load detect/repairOpenClawStateDatabaseSchema* lazily inside
  the migration bodies; keep only a type-only static runtime-doctor import
- matrix: split pure credential record shapes/normalizers into
  credentials-state.ts so the doctor closure no longer imports the sync
  plugin-state store through credentials-read
- guard: doctor-contract-closure-guard.test.ts now forbids static value
  imports of runtime-doctor in closures alongside agent-runtime

* fix(matrix): keep credential revocation record type module-local

Knip production scan flags the export as consumer-less; the type is only
referenced by the exported union and revocation guard signature.
2026-08-08 17:51:31 -07:00
Peter Steinberger 2a7782674e fix(telegram): clean up every failed webhook startup phase (#120788) 2026-08-08 17:27:19 -07:00
Peter Steinberger 4050fb02e0 fix(telegram): prevent session-count routing slowdown (#120774) 2026-08-08 16:54:25 -07:00
Peter Steinberger 6972ef80b7 fix(telegram): classify hosted media size errors consistently (#120757) 2026-08-08 16:44:44 -07:00
Peter Steinberger e4ff0d67f4 fix(telegram): unblock chats after media claim timeout (#120706)
Claim-owned cancellation now stops pre-adoption media hydration, allowing later same-chat messages to proceed. Webhook handling now uses the canonical Telegram adoption stall timeout.

Fixes #120704.
2026-08-08 14:25:38 -07:00
Peter Steinberger da4a656cdb improve: doctor migration checks no longer load every bundled plugin runtime (#120678)
* perf(plugins): declare doctor contract surfaces

* perf(doctor): slim migration import closures

* perf(plugins): narrow doctor declaration record surface and wire owner-test lane

Registry records carry only the doctorContract declaration instead of the whole
parsed manifest, and check:changed now selects the src/plugins-owned declaration
honesty and closure-guard tests for extension module/manifest changes so
cross-lane drift cannot pass PR classification.

* fix(doctor): keep control-plane dist imports require-safe

Keep doctor and channel control-plane chunks off exec-class dependencies, and enforce native require(esm) loading during postbuild.

* chore(plugin-sdk): regenerate API baseline

* chore(plugin-sdk): sync export ordering

* fix(plugins): satisfy doctor contract CI boundaries

* perf(doctor): make qqbot doctor closure dependency-light

qqbot was the last plugin above 5s in doctor state-migration enumeration
(~8s under tsx/jiti). The cost was not the state-key builder (already a
leaf): its doctor closure value-imported the runtime-doctor SDK barrel,
whose plugin-state-store/state-db re-exports pull kysely (~330 modules),
plus security-runtime for one fileExists (~200 modules), all resolved
per-module by jiti during enumeration.

Split the migration-define helpers and light re-exports into a new
private-local plugin-sdk/runtime-doctor-migrations subpath; runtime-doctor
re-exports it so its public surface is byte-identical (API baseline hash
unchanged). qqbot's doctor-contract and state-migrations now import only
the light subpath, swapping fileExists for the equivalent async
legacyStateFileExists already in the closure.

qqbot enumeration: ~8.0s/531 modules -> ~0.25s/18 modules.

* chore(plugin-sdk): drop private-local subpath from API baseline

runtime-doctor-migrations is private-local-only; the baseline tracks public
modules, and the earlier line was generated before the classification.

* fix(plugins): register runtime-doctor-migrations boundary paths

The private-local subpath list feeds the extension package boundary map;
the shared paths config and xai's derived overrides must carry the same
entry or the boundary contract test fails.
2026-08-08 13:29:18 -07:00
Peter Steinberger 725fe96bd7 fix(telegram): avoid credential reads in reply policy
Resolve reply mode through Telegram’s config-only account projection so threading policy never reads token files or SecretRefs.
2026-08-08 06:53:37 -07:00
Peter Steinberger f4f5310355 fix(telegram): restore account-scoped reply mode
Resolve reply mode through the selected Telegram account so account overrides and top-level inheritance reach outbound reply context.

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-08 06:53:37 -07:00
Vincent Koc cdd621eaee test(telegram): use model selection rejection seam 2026-08-08 02:21:34 -07:00
Peter Steinberger 96a75be170 fix(discord): default preview streaming to off (#120376)
Make Discord progress drafts and activity receipts explicit opt-ins while preserving configured streaming modes and legacy explicit progress migrations. Related: #87704.
2026-08-07 17:18:12 -07:00
Josh Avant c691f2e41c fix(progress): preserve callback acceptance results (#120171)
* fix(progress): preserve callback acceptance results

* fix(progress): require transport acknowledgements

* fix(progress): preserve direct acceptance outcomes
2026-08-07 14:40:33 -05:00
Peter Steinberger d448a25a8a refactor(test): compress repetitive fixtures in mega-tests, batch 3 (#120294)
* refactor(test): compress subagent lifecycle fixtures

* refactor(test): compress model resolution fixtures

* refactor(test): compress Telegram bot fixtures

* refactor(test): compress reply-agent e2e fixtures

* refactor(test): compress Matrix SDK fixtures

* refactor(test): compress QMD manager fixtures

* refactor(test): compress gateway chat fixtures

* refactor(test): compress gateway reload fixtures

* fix(test): preserve raw Telegram secret fixture

* fix(test): retain session fixture key type

* fix(test): preserve raw reload secrets fixture

* fix(test): retain gateway fixture parameter types
2026-08-07 11:48:46 -07:00
Peter Steinberger 4188f6892d refactor(test): replace logic-bearing vi.mock factories with boundary fakes, batch 3 (#120291)
* refactor(test): exercise real session rewind policy

* refactor(test): use real Telegram media policy

* refactor(test): exercise real HTTP cancellation lifecycle

* test(gateway): prove mutations clear queued session work
2026-08-07 10:54:58 -07:00
Ayaan Zaidi 5e477aff2a feat(status): render /status as a native rich card and declutter the plain body (#120167)
* feat(status): render /status as native rich tables on channels that support them
* feat(status): tighten rich /status layout into a titled native table card
* feat(status): trim rich /status tail to one clock-and-uptime context line
* feat(status): context meter, hot-window warning, and default-noise trim in rich card
* test(status): satisfy SessionEntry sessionId in meter fixture
* fix(telegram): gate rich table islands off legacy HTML sends and cover payload sends
* test(telegram): split outbound-adapter presentation tests to satisfy max-lines
* fix(outbound): make presentation capability resolution formatting-aware
* fix(telegram): defer presentation canonicalization on rich accounts until send
* feat(status): one fact per line in the plain status body
* feat(status): group the plain status body into blank-line sections
* feat(status): lead the rich status card with the version title

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 20:46:52 +05:30
Vito Cappello 5621979a46 fix(models): preserve session selection across fallback turns (#119325)
* feat(models): add session-only model selection

* fix(models): use trailing session scope option

* test(models): satisfy session scope lint

* fix(models): reject duplicate model options

* fix(models): clarify default and session scope

* fix(models): require complete session option tokens

* fix(models): report configured default dispatch

* fix(models): keep directive handler within lint limit

* fix(models): parse model options in either order

* fix(models): apply session scope to aliases

* fix(models): align alias scope with reply routing

* fix(discord): surface model selection scope in picker

* fix(models): preserve mixed-text model selection

* fix(models): centralize command selection ownership

* fix(models): align session scope lifecycle

* fix(models): preserve command and auth ownership

* fixup! fix(models): preserve command and auth ownership

* fix(auth): preserve scoped CLI provider discovery

* test(models): align result and cron fixtures

* test(models): nest result timing metadata

* fix(discord): narrow silent dispatch results

* fix(transcript): preserve admitted turn identity

* fix(context-engine): fence the admitted transcript turn

* fix(context-engine): stabilize plugin compatibility contract

* chore(plugin-sdk): refresh context engine API baseline

* chore(plugin-sdk): use Linux context engine API baseline

* fix(context-engine): align fallback ownership

* fix(fallback): scope auth skip cache by profile

* fix(context-engine): settle only accepted fallback turns

* refactor(sessions): issue canonical turn admissions

* refactor(context-engine): own logical turn advancement

* fix(context-engine): settle cron fallback winners

* fix(models): align picker and fallback transactions

* fix(delivery): notify block admission after queueing

* fix(sessions): preserve canonical admission receipts

* chore(plugin-sdk): refresh API baseline hash

* fix(context-engine): commit accepted turns durably

* fix(context-engine): validate durable host transitions

* fix(context-engine): preserve fallback turn ownership

* fix(context-engine): preserve queued turn order

* fix(models): preserve fallback retry ownership

* fix(context-engine): enforce durable transcript anchors

* fix(runtime): close fallback persistence gaps

* fix(context-engine): preflight fallback harnesses

* chore(plugin-sdk): use Linux API baseline

* fix(context-engine): drain durable commits before reads

* fix(models): scope harness auth failures by profile

* fix(codex): fence legacy transcript history

* fix(commands): honor suppressed directive interpretation

* chore(runtime): remove unused branch exports

* test(context-engine): derive private outbox payload type

* fix(context-engine): apply durable drain degradation

* fix(context-engine): recover durable turn intents

* fix(context-engine): settle durable turn intents

* refactor(context-engine): satisfy branch quality gates

* fix(context-engine): close durable recovery gaps

* fix(discord): preserve dropped model command outcome

* test(copilot): keep journal fixture types local

* fix(auto-reply): preserve model alias provenance

* fix: close model scope review gaps

* fix(models): close review-found scope leaks

* fix(review): satisfy branch line budgets

* fix(agents): preserve context engine turn facts

* fix(agents): finalize silent context turns

* fix(context-engine): preserve compatibility window

* test(agents): cover both harness preparations

* fix(context-engine): retain blocked turn advancements

* fix(models): parse compact runtime options

* fix(telegram): report runtime resets accurately

* fix(models): isolate automatic auth failure skips

* fix(context-engine): project commit turn host params

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-08-07 16:19:12 +08:00
Peter Steinberger c636060f04 fix(telegram): preserve voice fallback text
Preserve visible text when Telegram rejects a voice note for recipient privacy.

Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-07 08:18:31 +05:30
Peter Steinberger 0b849a316d refactor(plugins): single-source interactive dispatch and its auth downgrade via plugin SDK (#120062) 2026-08-06 16:31:04 -07:00
Peter Steinberger b4a26783f7 refactor(test): consolidate duplicated requireRecord and provider HTTP mock helpers (#119982)
* refactor(test): consolidate duplicated test helpers

* test: remove stale record guard import

* fix(test): remove orphaned record guards

* refactor(test): keep record requirement messages exhaustively typed

* fix(test): keep packages/ai record guard package-local
2026-08-06 14:48:01 -07:00
Peter Steinberger 70f84286c9 fix(telegram): preserve inbound quote attribution
Preserve native Telegram quote attribution in agent-visible input and terminate quotes before following ordinary text.

Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-06 21:11:02 +05:30
Peter Steinberger 913b53ad80 fix(channels): preserve bundled delivery contracts
Preserves pending Telegram replies, Discord webhook preview policy, forwarded Slack file context, and QQBot target recognition.
2026-08-06 18:44:15 +05:30
Peter Steinberger 4d91d44d00 fix(telegram): preserve callback action ownership
Keep Telegram native and typed callback routes under their owning handlers. Expired or malformed typed buttons now clear their controls and return visible unavailable feedback while legacy raw plugin callbacks remain compatible.
2026-08-06 17:23:32 +05:30
Lu Wang 5a8c27ca41 fix(telegram): verify provider topic delivery
Verify Telegram accepted-message topics before follow-up sends, preserving partial-delivery evidence instead of trusting requested routing.

Co-authored-by: Lu Wang <7668944+wangwllu@users.noreply.github.com>
2026-08-06 15:06:39 +05:30
Jerry-Xin b8f6086411 fix(tts): deliver Telegram final speech without text churn
Defer Telegram final-mode text until speech settles, then deliver one captioned voice note or a proven-safe text fallback.

Co-authored-by: Jerry-Xin <jerryxin0@gmail.com>
2026-08-06 10:41:40 +05:30
Peter Steinberger 89014305f1 fix(telegram): reject retired native button input
Prevent stale top-level buttons arguments from silently sending text-only Telegram messages. Point model guidance and docs to typed presentation actions, and reject retired input before delivery.
2026-08-05 21:57:36 +05:30
Val Alexander 4663244170 fix(telegram): bind Mini App auth to dashboard launches
Require a short-lived, owner-bound launch ticket before minting a Control UI bootstrap token.

Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
2026-08-05 20:24:34 +05:30
amittell d85920c03e fix(telegram): preserve truthful empty-content delivery (#88810)
* fix(telegram): skip empty rendered text deliveries
* fix(telegram): preserve empty delivery outcomes

---------

Co-authored-by: amittell <1388680+amittell@users.noreply.github.com>
2026-08-05 18:41:38 +05:30
Peter Lee f68ecec40c fix(telegram): preserve slash-command failure outcomes
Track final delivery outcomes at the Telegram native-command owner so failed finals produce a visible fallback without overriding intentional suppression or partial delivery.
2026-08-05 16:18:50 +05:30
clawSean c02e39345b fix(telegram): route poll answers into agent turns
Route public poll votes through Telegram’s authorized inbound turn path while preserving chat/topic origin and durable ordering. Surface unsupported routing without duplicating sent polls.

Co-authored-by: clawSean <260045960+clawSean@users.noreply.github.com>
2026-08-05 14:42:51 +05:30
qingminlong 76ac472f56 fix(telegram): reject malformed table spans (#109962)
* fix(telegram): reject malformed table spans

* fix(telegram): preserve spaced fallback colspans

* fix(telegram): simplify strict table-span parsing

Preserve the original contributor fix while reusing the existing strict numeric owner, enforcing complete-decimal span attributes on both Telegram paths, and strengthening sibling regressions. Production LOC remains net zero.

Co-authored-by: qingminlong <0668001063@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-04 23:13:46 -07:00
Syu b316c9cacf fix(channels): honor explicit preview streaming settings
Explicit Telegram and Discord preview modes now override inherited block streaming while explicit channel block settings remain authoritative.

Co-authored-by: Syu <zhuqimo@gmail.com>
2026-08-05 09:04:49 +05:30
Peter Steinberger ad37e91fbb refactor(telegram): consolidate outbound contracts and targets (#119438) 2026-08-04 20:33:45 -07:00
Dinesh H Suthar 50c7444edf fix(sessions): preserve compatible auth profiles on model changes (#117550)
* fix(model-picker): preserve compatible auth profiles
* chore(plugin-sdk): refresh API baseline
* fix(model-picker): keep profile policy core-owned
* fix(model-picker): preserve profiles across auth aliases
* chore(plugin-sdk): update public surface budgets
* fix(model-picker): honor explicit profile clearing
* fix: preserve compatible auth profiles on model changes
* perf: reuse prepared auth profile metadata
* docs(plugin-sdk): document direct model persistence fallback
* test: expose auth snapshot in directive mock

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Dinesh Suthar <dineshsld20@gmail.com>
2026-08-05 07:40:00 +05:30
Arthur Lacoste f207e14d92 fix(telegram): keep commands responsive during Codex login
Release Telegram’s chat lane after structured Codex device-code delivery while account-owned authentication completes safely in the background.

Co-authored-by: Arthur Lacoste <arthurlacoste@users.noreply.github.com>
2026-08-05 05:59:13 +05:30
Peter Steinberger 7a0a4c5f2a fix(telegram): correlate deliveries to explicit topics
Use the explicit topic selected by Telegram sends when recording delivery correlation, preventing successful message, poll, and sticker actions from leaving the matching inbound event falsely undelivered.
2026-08-04 22:51:32 +05:30
Guoji-XYDT 47bd1bb194 fix(telegram): report degraded inline controls
Preserve readable fallbacks and tell the model when Telegram drops unencodable controls, including recovery guidance.\n\nCo-authored-by: Guoji-XYDT <li.guoji@xydigit.com>
2026-08-04 21:50:45 +05:30
vovapetry b5876a1086 fix(telegram): route reactions to their originating forum topics
Recover Telegram forum reaction topics from provider-observed message context before authorization, and drop unknown topics instead of routing them to General. Serialize each forum message with its reaction update to avoid cache races. Thanks @vovapetry.
2026-08-04 18:49:57 +05:30
YangManBOBO c6c7d7d9de fix(telegram): retry update offset persistence
Keep accepted and committed Telegram update offsets separate, retry transient state-store failures, and preserve classic plus isolated restart dedupe.

Co-authored-by: 潘晓波0668000512 <pan.xiaobo@xydigit.com>
2026-08-04 17:37:56 +05:30
alfredjbclaw b6a445c393 fix(telegram): preserve later chunks after rejected sends
Prevent Telegram long replies from silently losing their tail after definite per-chunk rejections. Preserve accepted message IDs and explicit partial-delivery state across durable, rich fallback, and streamed replies.

Co-authored-by: alfredjbclaw <alfredjbclaw@users.noreply.github.com>
2026-08-04 14:06:18 +05:30
Galin Iliev 1b58ecb5af fix(telegram): use monotonic polling liveness
Measure Telegram polling deadlines with a monotonic clock so wall-clock corrections cannot trigger false restarts or negative durations. Preserve the worker deadline and continued-stall recovery.

Co-authored-by: Galin Iliev <Galin.Iliev@microsoft.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-04 12:49:13 +05:30
Peter Steinberger 84cfc43684 fix(telegram): keep request deadlines through response bodies
Keep Telegram Bot API deadlines and cancellation active until grammY finishes consuming each response body. Cancel discarded HTTP 421 bodies before retry and cover the stalled group-dispatch boundary with typed socket and live Telegram proof.
2026-08-04 11:40:41 +05:30
tangtaizong666 2ea3b0da98 fix(telegram): record automatic delivery message ids
Record every accepted Telegram automatic delivery in the scoped sent-message ledger, including finalized streaming previews. This restores bot-owned reaction checks and removes the per-send full-ledger expiry scan.
2026-08-04 10:45:00 +05:30
Peter Steinberger f9d9d1225a refactor(channels): own the lifecycle status contract in SDK patch factories (#118795)
* refactor(sdk): add channel lifecycle patch factories

* refactor(channels): adopt lifecycle patches in a-m

* refactor(channels): adopt lifecycle patches in n-z

* refactor(runtime): lifecycle-own ambient registries

* test(slack): assert lifecycle factory fields

* fix(sdk): preserve lifecycle patch extras types

* test(zalouser): widen lifecycle status sink

* test(irc): avoid shadowed status patch

* fix(zalo): reuse account-agnostic media route

* fix(gateway): accept explicit channel ready recovery

* test(qa): assert terminal Slack block fact

* test(qa): restore Slack blocked lifecycle scenario

* test(gateway): lock explicit lifecycle recovery contract
2026-08-03 12:39:48 -07:00
Dinesh H Suthar 430fca67ff fix(reply): preserve streamed Telegram replies on failure
Preserve already-visible Telegram partial replies when a later run failure occurs. Finalize the same draft with the terminal notice while keeping the reply operation in run_failed state.

Co-authored-by: Dinesh Suthar <dineshsld20@gmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-04 01:38:59 +09:00