Commit graph

29 commits

Author SHA1 Message Date
Johannes du Plessis
209132d355
refactor: durable interrupt dispatch + completion webhook (#1621)
* wip(rebuild): core reliability spine

- remove PR-babysitting (ci_autofix + ci_monitor graph + webhook wiring)
- dispatch core: agent/dispatch.py with multitask_strategy=interrupt +
  durability=sync + completion webhook; reroute all webhook + plan triggers;
  drop the racy in-process lock + is_thread_active busy-check
- completion webhook: agent/completion.py + /webhooks/run-complete loopback
  route for failure/timeout replies (idempotent)

Co-authored-by: open-swe[bot]

* feat(rebuild): async tools, reconcile, shared http timeouts, assembly tuning

Parallel batch on top of the reliability spine:
- async-ify all 24 tools (drop asyncio.run; requests->httpx); re-implement the
  http_request/fetch_url SSRF + DNS-rebinding defense httpx-natively and harden
  the IP check to 'not is_global' (+ IPv4-mapped unwrap)
- reconcile.py: stale pending-run sweep (threads.search -> per-thread runs.list
  -> cancel_many), wired into the scheduler graph via task='reconcile'
- shared DEFAULT_HTTP_TIMEOUT (agent/utils/http.py) on every bare
  httpx.AsyncClient() across utils/dashboard/webapp/middleware
- run budget: MODEL_CALL_RECURSION_LIMIT 5000->250
- fix stale OpenAI->Anthropic fallback id (claude-opus-4-5 -> 4-8)
- drop redundant custom repair middleware (deepagents auto-adds PatchToolCalls)
- confirm tool-result eviction + summarization auto-wired via backend
- slim system prompt ~8% (full harness-profile rewrite deferred)

Co-authored-by: open-swe[bot]

* feat(rebuild): harness-profile prompt + split webhooks out of webapp

- prompt.py: own the system prompt via a registered harness profile
  (OPEN_SWE_SHARED_BASE, kept neutral so the read-only reviewer/analyzer that
  share it stay safe), registered across all 4 providers; per-thread values
  stay in construct_system_prompt. Assembled main-agent prompt ~6.8k -> ~3.1k
  tokens (~55% smaller); de-duped PR/commit/suite/force-push guidance; dropped
  ALL-CAPS markers.
- webapp.py 3325 -> 1890 LOC: moved 14 per-source handlers into
  agent/webhooks/{linear,slack,github}.py; webapp re-exports them for the
  routes + tests; moved handlers reach shared helpers via the webapp namespace
  to preserve the test suite's monkeypatch targets.

Full suite: 1168 passing, lint clean.

Co-authored-by: open-swe[bot]

* Restore MODEL_CALL_RECURSION_LIMIT to 5000 for long-running tasks

Reverts the 250 cap from the run-budget change — long-running tasks legitimately
need many model calls. The notify_step_limit_reached safety net still fires if a
run does hit the cap, so runs end with a signal either way.

Co-authored-by: open-swe[bot]

* fix: address PR review (auth, SSRF, interrupted status, redirect headers)

- completion.py: drop `interrupted` from failure statuses — with
  multitask_strategy=interrupt a follow-up ends the prior run as interrupted,
  which is healthy, not a failure to report. [open-swe]
- /webhooks/run-complete: shared-secret auth — dispatch appends ?token= when
  RUN_COMPLETE_WEBHOOK_SECRET is set; route verifies via hmac.compare_digest.
  [corridor-security]
- SSRF: extract the URL validator to agent/utils/url_safety.py and apply it
  before server-side image fetches in multimodal.fetch_image_block.
  [corridor-security]
- http_request: preserve caller headers/extensions across redirect hops instead
  of dropping them on the first hop. [open-swe]

Co-authored-by: open-swe[bot]

* chore: remove REBUILD_PLAN.md (planning doc, not needed in the repo)

Co-authored-by: open-swe[bot]

* fix: fail closed on run-complete webhook auth when secret unset

Corridor follow-up: verify_run_complete_token returns False (not True) when
RUN_COMPLETE_WEBHOOK_SECRET is unset, so the public route is never
unauthenticated. Logs a startup warning when the secret is absent, and dispatch
skips registering the webhook when there's no secret (no rejected callbacks).

Co-authored-by: open-swe[bot]

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-26 13:48:38 -07:00
Johannes du Plessis
98b824bd54
feat: add size caps for PR diff, fetch_url, Slack threads, pagination, message queue [closes OPE-51] (#1567)
* feat: add size caps for PR diff, fetch_url, Slack threads, pagination, message queue

Per-source byte/token caps with explicit truncation markers to prevent
unbounded payloads from blowing up LLM context/memory.

- reviewer_diff.py: cap PR diff at 200K chars with head+tail truncation
- fetch_url.py: cap markdownify output at 100K chars
- slack.py: cap thread message fetch at 500 messages
- github_comments.py: cap _fetch_paginated at 50 pages
- thread_ops.py: cap queued messages at 100 (drop oldest)

Closes OPE-51

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* fix: compute diff line set from full diff, keep most recent Slack messages

Address PR review comments:

1. Truncated diffs rejected valid findings: fetch_pr_diff now returns the
   full diff; truncate_diff is called separately in reviewer.py so the
   line set used for add_finding/publish_review validation is computed
   from the complete diff, not the truncated prompt text.

2. Slack cap dropped recent thread context: fetch_slack_thread_messages
   now keeps the most recent SLACK_THREAD_MAX_MESSAGES messages (was
   keeping the oldest). The tool surfaces a truncation marker in the
   formatted output so the LLM knows the thread was truncated.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-17 15:40:59 -07:00
Johannes du Plessis
194e9cd60e
feat: link Slack thread/Linear ticket in PRs and append ticket to title (#1504)
* feat: link Slack thread/Linear ticket in PRs and append ticket to title

When opening PRs, include any referenced Slack thread or Linear ticket
in the description and append the resolvable ticket number to the title.
Adds a Slack permalink to the webhook prompt so the agent has a
ready-to-link thread URL.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* fix: use [closes <TICKET>] format in PR title suffix

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* feat: deterministically append source refs to private-repo PRs only

Move the Slack/Linear source-reference linking out of the prompt and into
open_pull_request, gated to private repos so private Slack thread URLs and
Linear identifiers are never published to a public PR. Reverts the prompt
instruction and webhook permalink injection in favor of this server-side append.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-11 15:52:40 -07:00
Mason Daugherty
ab2e0d1da3
feat: resolve Slack repo from channel topic/purpose (#1453)
Add conversations.info fetch so a repo:owner/name (or GitHub URL) token
in a Slack channel's topic/purpose pins the channel to a repo, slotting
in just below thread metadata in get_slack_repo_config.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-08 13:53:16 -07:00
Ramon Nogueira
d2268871eb
feat: surface dashboard UI link on PR reviews [INF-0000] (#1440)
* feat(reviewer): surface dashboard UI link on PR reviews [INF-0000]

Post a transient "review in progress" comment (with an "Open in Web"
dashboard link) when a reviewer run starts, then delete it once the
review lands. The published review body now carries the same
"Open in Web" link, so the link persists on the review itself.

The transient comment's id is tracked in reviewer thread metadata
(status_comment_id) so it can be deleted on completion.

* refactor(reviewer): inline dashboard URL helper, drop redundant future import [INF-0000]
2026-06-07 05:17:09 +00:00
Johannes du Plessis
c1e46b938e
feat: add Slack Block Kit reply options (#1407)
* feat: add Slack Block Kit reply options

Co-authored-by: open-swe[bot] <215916821+open-swe[bot]@users.noreply.github.com>

* docs: document Slack interactivity setup

Co-authored-by: open-swe[bot] <215916821+open-swe[bot]@users.noreply.github.com>

---------

Co-authored-by: open-swe[bot] <215916821+open-swe[bot]@users.noreply.github.com>
2026-06-04 10:26:09 -07:00
Johannes du Plessis
8913926dba
fix: remove manual review trigger surfaces (#1396)
Open SWE Review now runs from automated PR triggers, so drop the old Slack/GitHub review keyword entrypoints and keep PR comments on the regular agent path.
2026-06-03 12:33:22 -07:00
Mukil Loganathan
f4b27c0fee
feat: add Slack Open in Web link (#1392)
* feat: add Slack Open in Web link

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* fix: skip web link for Slack reviewer runs

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* test: accept include_dashboard_link kwarg in Slack reviewer test double

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
Co-authored-by: open-swe[bot] <johannes@langchain.dev>
2026-06-03 11:50:37 -07:00
open-swe[bot]
eb92947806
fix: propagate Slack reply errors (#1358)
* fix: propagate Slack reply errors

Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>

* fix: classify Slack 429 as rate_limited with retry-after

Slack chat.postMessage rate limiting returns HTTP 429, which raise_for_status
turned into a generic http_error and told the agent to retry immediately,
ignoring Slack's retry window. Special-case 429 (threading Retry-After) and
normalize the ratelimited body code before the generic HTTP path so the
existing rate_limited hint actually fires.

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
2026-05-28 23:11:42 +00:00
open-swe[bot]
dd4ca9181e
fix: route PR review requests through agent tool (#1340)
* fix: route PR review requests through agent tool

Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>

* fix: align public repo gate test with agent routing

Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>

* fix: allow app-token PR review requests

Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
2026-05-27 10:29:43 -07:00
open-swe[bot]
e347aed851
feat: make PR creation policy opt-in (#1334)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
2026-05-26 13:30:18 -07:00
open-swe[bot]
d2c62e5fc6
chore: remove slack assistants api feature flag (#1295)
The SLACK_ASSISTANTS_API_ENABLED env flag and its gating function
are removed. set_slack_assistant_status now always proceeds when a
bot token and channel/thread are provided.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
2026-05-12 00:41:51 +00:00
open-swe[bot]
6a984d86c4
feat: add 10 more tips to the trace-reply rotation (#1283)
* feat: add 10 more tips to the trace-reply rotation

The TRACE_REPLY_TIPS pool only had 9 tips, so users mostly saw the same
ones. Added 10 more grounded in actual features (review command, image
attachments, GitHub-issue triggers, persistent sandboxes, OAuth fallback,
etc.) so the rotation surfaces more of what open-swe can actually do.

Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>

* swap out 3 tips per review feedback

Replaced the suggestion-blocks, sandbox-auto-recovery, and OAuth-fallback
tips with three more practically useful ones: cross-posted Slack message
resolution, the web_search tool, and the Linear ticket-management tools.

Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
2026-05-08 22:52:29 +00:00
Johannes du Plessis
51bdde93b9
slack: move feedback-reaction ask out of every reply, into the tip rotation (#1279)
Appending "Please react with 👍 or 👎..." to every Slack completion
message ended up being repetitive noise. Drop the prompt-side instruction
and add the same ask as one of the rotating tips on the trace reply, so
users still see it occasionally without it cluttering each final summary.
2026-05-08 21:59:14 +00:00
Johannes du Plessis
b541f6d08a
slack: slim down the trace reply (drop greeting, suppress unfurl) (#1278)
Now that assistant.threads.setStatus carries the "is thinking…"
indicator, the per-run greeting phrase + auto-unfurl on the LangSmith
link are just visual noise stacking on top of it. The trace reply now
posts only `<url|View trace>` + a tip, with link unfurling off so the
smith.langchain.com card no longer appears.

Adds an `unfurl_links`/`unfurl_media` knob to post_slack_thread_reply_with_ts
(default-on to preserve behaviour for every other caller).
2026-05-08 14:51:28 -07:00
Johannes du Plessis
3f9dbb6597
feat: add Slack reaction feedback to LangSmith (#1231)
* feat: add Slack reaction feedback to LangSmith

Record Slack reaction feedback against explicitly mapped LangGraph runs so user ratings are idempotent and tied to the message they reacted to.

* Address review feedback on Slack reaction → LangSmith feedback

- langsmith.py: drop lru_cache on _build_langsmith_feedback_clients so
  rotated keys / late env hydration are picked up; dedupe by (key, url)
  tuple instead of key alone so the same key pointing at different
  endpoints (cloud + self-hosted) builds both clients.
- langsmith.py: treat LangSmithNotFoundError on delete_feedback as
  success — out-of-order or redelivered reaction_removed events would
  otherwise loop forever on Slack's retry policy.
- slack_feedback.py: include channel_id in _feedback_key so the same
  message_ts in two channels can't collide on the same feedback id.
- slack_feedback.py: treat conflicting +/- reactions from one user as
  ambiguous (clear feedback) instead of averaging to a misleading 0.5.
- slack_feedback.py + slack.py + webapp.py: gate reaction handling to
  the user who triggered the run (stored in the slack_run_map mapping
  alongside run_id). Prevents bystanders in shared channels from
  polluting eval feedback.
2026-05-08 14:24:12 -07:00
Johannes du Plessis
d151a118ae
Use Claude Code style spinner vocab for Slack loading messages (#1276) 2026-05-08 14:23:21 -07:00
Johannes du Plessis
d38f17ffe8
fix Slack assistant status endpoint (#1272) 2026-05-08 13:07:32 -07:00
open-swe[bot]
96f97710ad
feat: add optional Slack Assistants API typing status indicator (#1269)
* feat: add optional Slack Assistants API typing status indicator

Mirrors OpenClaw's pragmatic approach: instead of rebuilding around
assistant_thread_started events, just opt into assistants.threads.setStatus
to show 'is thinking…' while the agent is working, and clear it when
post_slack_thread_reply lands. Gated behind SLACK_ASSISTANTS_API_ENABLED so
it can be toggled without touching code.

* fix(slack): drop redundant clear, add status heartbeat across model calls

- Slack auto-clears the typing indicator on bot post; remove the explicit
  assistants.threads.setStatus("") call from post_slack_thread_reply.
- The indicator expires after ~2 minutes; add a before_model middleware
  that refreshes it on every model tick so it stays visible across long
  agent runs. Reuses the existing slack_thread.{channel_id,thread_ts}
  configurable already plumbed for notify_step_limit.
- chat:write is sufficient on the bot token (assistant:write is on the
  way out per Slack docs); no scope or app-config change required.

* feat(slack): contextual status text + rotating loading_messages

- set_slack_assistant_status now accepts an optional loading_messages list
  (capped at 10 per Slack's API), surfaced via the assistants.threads.setStatus
  payload so Slack rotates through them client-side.
- The heartbeat middleware derives a contextual status from the last
  assistant message's tool calls (e.g. "searching the codebase…" after
  grep, "running commands…" after execute), falling back to the default
  "is thinking…" when no tool calls or unknown tool name.
- Adds a curated DEFAULT_LOADING_MESSAGES list passed alongside the
  contextual status on each refresh.

* fix slack assistant status lifecycle

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
2026-05-08 10:21:55 -07:00
open-swe[bot]
5a845ba99f
feat: add Tip section to Slack trace-reply initial message (#1268)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-05-08 09:25:06 -07:00
open-swe[bot]
2fb719822f
feat: add "Running to the roar!" trace reply phrase (#1252)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-05-07 13:18:54 -07:00
open-swe[bot]
5a01aff1c7
feat: only post Slack 'Working on it!' on first thread mention (#1250)
* feat: only post Slack 'Working on it!' on first thread mention

* feat: randomize Slack trace reply phrase

Pick from a small list of friendly phrases instead of always saying
'Working on it!' so the bot feels less robotic. Explicit messages (e.g.
'Taking a look...' from PR review path) are unaffected.

* adjust phrases

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
2026-05-07 12:37:46 -07:00
Johannes du Plessis
1319347dd9
feat: route Slack PR review requests (#1245)
* feat: route Slack PR review requests

Add a lightweight Slack review command path that starts the reviewer graph directly and gives the core agent a handoff tool when review requests are misrouted.

* fix: harden Slack PR review routing

* fix: validate Slack PR review URLs

* fix: preserve malformed GitHub review routing
2026-05-06 17:14:43 -07:00
Aran Yogesh
b6ea229a46
feat: give agent ability to read cross-posted Slack message links [closes OPE-37] (#1200)
* feat: give agent ability to read cross-posted Slack message links [close OPE-37]

* refactor: clean up Slack link resolution code

* linting

* refactor: address PR review feedback for Slack link resolution

* linting

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-04-29 17:42:27 -07:00
Aran Yogesh
fc3e492083
fix: use thread-level LangSmith URLs instead of run-level URLs to fix broken trace links (#1217)
* fix: use thread-level LangSmith URLs instead of run-level URLs to fix broken trace links

* linting
2026-04-23 13:46:28 -07:00
Brace Sproul
e1de58c584
fix: convert @Name(USER_ID) mentions to Slack's <@USER_ID> format in thread replies (#1126)
The agent sees users formatted as @Name(USER_ID) in conversation context and
reproduces that pattern in replies, but Slack requires <@USER_ID> for real
mentions. This adds automatic conversion and updates prompt instructions.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-03-25 11:51:11 -07:00
Aran Yogesh
b64d871913
feat: send LangSmith trace URL on run trigger from Slack and Linear (#1057)
* feat: send LangSmith trace URL on run trigger from Slack and Linear

* fix: check LANGSMITH_PROJECT before LANGSMITH_PROJECT_PROD for project name lookup

* fix: pass LangSmith API key explicitly to Client and remove global variable

* Update agent/utils/langsmith.py

Co-authored-by: Brace Sproul <braceasproul@gmail.com>

* refactor: move trace notification helpers out of webapp and use env vars for LangSmith URL base

* docs: add LangSmith tenant and project ID env vars to installation guide

* fix: remove unused comment_on_linear_issue import from webapp

* nit: remove lru_cache, make get_langsmith_trace_url sync, and move langsmith import to top level

* Update INSTALLATION.md

Co-authored-by: Brace Sproul <braceasproul@gmail.com>

* Update INSTALLATION.md

Co-authored-by: Brace Sproul <braceasproul@gmail.com>

* Update INSTALLATION.md

Co-authored-by: Brace Sproul <braceasproul@gmail.com>

---------

Co-authored-by: Brace Sproul <braceasproul@gmail.com>
2026-03-18 12:17:45 -07:00
Brace Sproul
3e73447920
fix: better docs, github auth (#1055)
* fix: Update github auth methods

* cr
2026-03-11 22:57:56 -08:00
Brace Sproul
bd52e5e09d
chore: Drop monorepo (#1029)
* chore: Drop monorepo

* cr
2026-03-06 16:10:34 -08:00
Renamed from apps/agent/agent/utils/slack.py (Browse further)