Merge upstream PR #4604: Hermes-powered T3 Work - #103
Conversation
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…uses, path containment, draft clearing) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…search/inspect/reload) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… Hermes provider directory Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ateway lifecycle guards, cron/skills fail-closed, per-provider skills UI state) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…s_blocked skills error Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…e on factory failure during reconnect Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ing on socket close events Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…e_ids) so turns degrade instead of failing Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…avigation, control overlap, env scoping) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…rect resume for imported Hermes sessions Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…and transport cleanup Imported Hermes sessions now rehydrate structured history into native T3 turn items: tool calls paired with results by call id, categorized into command_execution/file_change/web_search/dynamic_tool presentations, reasoning restored as activity, unmatched calls kept as cancelled, output bounded with an explicit truncation marker, and malformed arguments parsed safely. Transport framing on inherited user rows (sender prefixes, mirror delivery, channel backfill, attachment envelopes) is cleaned up and gateway-forged delegation/watch notifications are suppressed. A new inherited_message_count boundary on the import ledger scopes all of this to the inherited history only. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…e message dedup Imported settled threads now settle with the upstream started_at (optional settledAt on thread.settle) so sidebar rows stop labeling as "now". Thread snapshots skip history rows whose content is already represented by a live-streamed message, preventing duplicated assistant text when Hermes history omits message ids. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- retry import hydration and log at error level so a transient gateway failure cannot silently leave a completed import without a transcript - leave the inherited boundary unrecorded while history reads empty so a later full history still receives import normalization and rehydration - resolve MEDIA output protocol inside rehydrated tool activities into durable attachment markers instead of leaving raw MEDIA: text - historical settles stamp updatedAt from settledAt so imported threads keep sorting by when the work actually ended Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- close() rejects sent in-flight mutations with HermesGatewayMutationIndeterminateError instead of a connection error - reconcileMutation only touches the local fence when the queried mutation id belongs to the fenced operation - HermesCron reuses one shared gateway client per provider connection so operationId fences survive across cron calls; duplicate operation ids map to invalid_input and blocked writes map to indeterminate - projectProvider projects success:false cron list responses as a provider error instead of a ready empty inventory - HermesProviderDirectory applies assessHermesConnectionSecurity, so remote wss endpoints no longer receive the broad local gateway token, and an empty endpoint resolves to the default loopback endpoint Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- EffectWorker: verify lease ownership before projecting permanent failures and keep effects retryable when the terminal projection fails - HermesHistoryNormalization: stop unquoted MEDIA paths from swallowing a second MEDIA directive on the same line - HermesServeAdapterV2: bound oversized tool property names and redact standard Authorization schemes plus OAuth parameters - HermesSessionCatalog: route discovery through the serve runtime's ensureReady so managed local Hermes instances are started first - HermesServeRuntime: relaunch an owned unhealthy process instead of reporting endpoint_in_use for T3's own listener - ThreadLaunchService: still generate thread titles when workspace preparation is skipped - HermesDriver: resolve default-model capabilities from the active provider on duplicate model slugs Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- SidebarV2: stay put instead of landing on the Code composer when the Work composer cannot open after a workspace switch - SidebarV2: only blur the pin toggle on pointer activation so keyboard focus survives Enter/Space - mobile: exclude Hermes threads from the Code workspace, matching web sidebar classification Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…tion in skills settings
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ture Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- EffectWorker: never re-execute permanently failed effects; persist a pending-terminalization marker so reclaims retry only the terminal projection - HermesCron: close and evict stale gateway clients when a provider's connection identity (endpoint/token) changes - HermesCron: only report duplicate-operation-id for actual duplicates via HermesGatewayDuplicateOperationIdError; map other configuration errors to a gateway diagnostic - HermesDriver: omit the session catalog for disabled instances - HermesServeRuntime: stop any lingering owned process before launching a replacement, even when the endpoint is unreachable - sanitizeHermesToolValue: short-circuit object/array iteration when the size budget is exhausted Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… message snapshots, and route drafts on workspace switch Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…keep the index draft off the T3 Work backing project Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ort hydrate ledger, probe warnings, draft classification) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…classify Hermes Code threads Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…response placeholder with attachments Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… dedup by id and time proximity Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…amps are synthetic) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…nto committed entries Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Resolves 54 conflicted files, keeping both the fork's features (provider handoffs, queued turns, lifecycle timeline, diffstat-first tool rows, MCP liveness windows) and the PR's Hermes/T3 Work additions. Hermes migrations renumbered 45-50 to avoid colliding with the fork's 044. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add generateHandoffSummary stubs to Hermes/HermesAcp/OpenClaw drivers - Widen HermesAcp/OpenClaw driver envs with BackgroundPolicy and ServerSettingsService required by the fork's ACP adapter - Add Hermes RPC scope entries to RPC_REQUIRED_SCOPES - Add fork-added fields to PR test fixtures (searchThreads, lastVisitedAt) - Drop duplicated blocks left by the conflict resolution Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedToo many files! This PR contains 236 files, which is 86 over the limit of 150. To get a review, narrow the scope: Upgrade to Pro+ to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (236)
You can disable this status message by setting the Comment |
Server/Hermes: close browser-artifact file handles, derive asset MIME type, bound the gateway mutations map, fix resetHistory ordering, recognize IPv6 and 127.0.0.0/8 loopback endpoints, guard empty unsettled-create intents, refresh driver checkedAt, trim skill reload operation ids. Orchestration: keep imported thread timestamps off wall-clock, include titleRevision/titleOrigin/pinned fields in threadShellFromProjection, fix failure-item ordinal scale, reject prepareWorkspace:false with worktree strategy, clamp future settledAt to now (with regression test). Web/contracts: extract T3 Work backing-project creation, tighten attachment and Hermes session schemas, per-skill reload state, playsInline video. Docs: move hermes-conformance to docs/internals, fix command examples, kill the spawned child on Windows cleanup. Also fixes stale upstream migration bounds in Hermes tests (Hermes migrations are 045-050 on this branch), which were failing 7 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Tighten IsoDateTime in hermesProactive: require full ISO 8601 date-time grammar and reject impossible calendar dates instead of trusting Date.parse, which accepts date-only and non-ISO values. - Make a failed T3 Work backing-project preparation recoverable: the failure toast now offers 'Try again', which clears the guard and re-runs preparation instead of requiring a reload. - Restore the 'Tool call completed' accessible label on the (visually empty) indicator slot, keeping the fork's diffstat-first row design while preserving screen-reader parity. - Update the coming-soon provider test for the now provider-agnostic copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Bound ISO timezone offsets in the pattern (rejecting +99:99) and reject second 60 outright rather than implying leap-second support these gateway event timestamps do not have. - Give the completed tool-call indicator role=img so its accessible name is actually exposed; ARIA ignores aria-label on role-less elements. - Add contract tests covering ten timestamp forms Date.parse accepts but the contract must reject, plus valid offset/leap-day round-trips. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Critical: - Fence the proactive outbox lease before writing projections: an expired or reclaimed lease could double-deliver a notification. Delivery now commits via a conditional UPDATE and bails when no row matches. - Route Hermes media attachments to the ChatAttachment type implied by their MIME instead of hard-coding 'file', which produced rows the contract rejects at persistence (e.g. .svg as image/svg+xml). Gateway/runtime: bound the sessionSequences map, send connection (not indeterminate) errors for unsent mutations, decouple fast-config reads from the models.inventory capability, and stop late probe socket errors from surfacing as uncaught exceptions. Cron: fail mutations the gateway reports unsuccessful instead of reporting them applied, prune and close cached clients on shutdown and provider removal, and stop the durable-cursor diagnostic firing with no executions. History/proactive: order media by source offset across both MEDIA passes, expand ~/ on Windows, decode stored capability JSON through the error channel, and give the test helper isolated profile keys. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Return lease_not_held instead of unsettled_prompt when a binding lease was lost: the zero-row insert is ambiguous, so re-check the fence. - Stop resetHistory skipping threads moved by provider.switch. The history id query is already scoped to provider instance, profile and project, so the extra providerInstanceId equality added no isolation while orphaning ledger rows the scoped clear still deleted. - Replace the per-session import lookup in discover with one scoped listSessionImports query (was up to 10k queries per discovery). - Report negotiated 'unsupported' protocol reasons instead of an empty missing-capability list, and distinguish sessions filtered out by transport/age from ids the profile never returned. - Reject non-positive started_at epochs so imports cannot backdate to 1970. - Isolate the binding test database per case and scan SQLite sidecars in the private-prompt assertion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- failPermanently ignored the committed flag from writeIfRunCurrent, so a guarded write rejected as stale reported success and the worker never retried. It now fails, which routes into the fork's pending- terminalization requeue path rather than silently completing. - Drop the superseded liveSessionId mapping when a binding resumes with a fresh Hermes session id; late events were routing to a discarded state. - Stop handleToolOutputRisk mutating tool.output: repeated risk events nested wrappers and a later tool.complete discarded the annotation. Risk details now live in dedicated ActiveHermesTool fields. - Clear or finalize the active turn on every startTurn failure, not only when the provider turn was never created. - Allow pinned + workInboxRole 'main' against a settled or snoozed thread: the same command unsettles it, so the guard rejected a combination the client dispatches as one command. - Skip hydration for archived or deleted threads before opening a provider session, matching startNextQueuedRun. - Suppress empty assistant_message projections, and pass mutationOptions so attachment mutations carry wire-level mutation ids. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CodeRabbit review loop — 7 roundsMerged latest 97 findings triaged — 74 fixed, 23 disproved as stale or wrong.
Reviews of the fixes converged to zero twice, while each new directory sweep kept finding real issues in the PR's own code — the full-branch review timed out server-side, so directory-scoped sweeps were used to reach the code it never examined. Most significant fixes
Notable rejectionsSeveral findings were disproved rather than applied — applying them would have caused regressions:
Verification
Outstanding
🤖 Generated with Claude Code |
- Revoke optimistic message preview URLs and clear the handoff map when a Hermes timeline is cleared, on both the draft and server-clear paths; blob URLs leaked and stale optimistic bubbles could re-render. - Derive isHermesConversation from the active thread's runtime provider rather than the composer selection, so opening the handoff or model picker no longer flips Hermes-only behaviour before the handoff runs. - Only intercept bare /new and /reset: the previous pattern accepted trailing text and silently discarded it. - Report every attachment rejection including capacity, instead of stopping at the first, and only preventDefault on paste when at least one clipboard file is accepted so text still lands in the composer. - Reject '.' and '..' as attachment names. - Download cross-origin images through an object URL so the chat document cannot navigate away, and give the image-preview backdrop an accessible name distinct from the close button. - Wrap disabled sidebar tooltip triggers so their tooltips can open in exactly the disabled states they explain. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merges pingdotgg/t3code#4604 (Hermes provider + T3 Work workspace, stacked on upstream #4400) into the fork while preserving all fork features.
Conflict resolution (54 files)
Policy: keep both feature sets — fork features (provider handoffs, queued turns, lifecycle timeline, diffstat-first tool rows, MCP liveness windows) plus the PR's Hermes/T3 Work additions.
Notable decisions:
RPC_REQUIRED_SCOPES(reads → orchestration-read, mutations → orchestration-operate).generateHandoffSummarystubs and widened driver envs for the fork's ACP adapter requirements.routeTree.gen.tsmerged by hand — consider regenerating with the TanStack route generator.reconcileShellscovers it and fork tests forbid clobbering post-import renames).Verification
pnpm -r typecheckclean across the repoWorth a manual pass: work-workspace sidebar visuals, Hermes tool status indicators (running/stopped/failed only — no completed checkmark), work-mode composer labels.
🤖 Generated with Claude Code