Skip to content

fix: correct git-repo incremental diff and isolate connector ingestion failures#414

Open
Greg Land (bikeusaland) wants to merge 8 commits into
langchain-ai:mainfrom
bikeusaland:fix/git-repo-incremental-diff
Open

fix: correct git-repo incremental diff and isolate connector ingestion failures#414
Greg Land (bikeusaland) wants to merge 8 commits into
langchain-ai:mainfrom
bikeusaland:fix/git-repo-incremental-diff

Conversation

@bikeusaland

Copy link
Copy Markdown
Contributor

Summary

Fixes two correctness bugs in the connector ingestion path.

1. git-repo connector diffed the working tree, not changes since the last run (#409)

GitRepoManifest declared previousHead and connector state already persisted each repo's head in latestIds, but createRepoManifest never read the prior head back. changedFiles was always git diff --name-status HEAD (uncommitted working-tree changes only), so the manifest never described commits landed since the last ingestion — contradicting the recent-changes window the agent is told about.

Now the recorded head is passed in and, when it is still a reachable commit and differs from the current head, the manifest is built from git diff <previousHead> HEAD and git log <previousHead>..HEAD. It falls back to the working-tree diff on the first run, when nothing new was committed, or when the recorded head is unreachable (force-push / rewritten history) — a rev-parse --verify guard ensures a diff against a missing commit can never throw.

2. One connector/stream failure aborted the whole ingestion run (#412)

ingestAllConnectors ran connectors serially with no error handling, so the first connector that threw (e.g. an un-refreshable token) discarded results from every connector that already succeeded. It now runs them concurrently with Promise.allSettled, turning each rejection into a well-formed error result.

The X connector had the same shape internally: any single stream error (e.g. a 429 on one endpoint) threw out of ingest, orphaning already-written dumps and skipping the state write so latestIds never advanced — forcing a full re-fetch next run. Each stream (and each list within list_posts) is now wrapped in try/catch, records a warning, and always writes state at the end, mirroring the resilient pattern already used by the hackernews and git-repo connectors. A run that fetched nothing but hit an error now reports error instead of a benign skipped.

Tests

Three new test files (7 new tests):

  • test/git-repo-connector.test.ts — drives real temp repos across two runs: first run has no previousHead, second run diffs since the recorded head, and an unreachable recorded head falls back safely.
  • test/x-connector-stream-isolation.test.ts — one failing stream keeps the succeeding dump and records a warning; all-failing yields error.
  • test/ingest-all-connectors.test.ts — a throwing connector does not discard a succeeding connector's result.

Full suite green: typecheck, eslint ., prettier --check, and 420 tests pass.

Closes #409
Closes #412

🤖 Generated with Claude Code

Greg Land (bikeusaland) and others added 8 commits July 20, 2026 16:05
The git-repo connector declared previousHead and persisted each repo's head
in state.latestIds, but createRepoManifest never read the prior head back.
changedFiles was always `git diff --name-status HEAD` (uncommitted working-
tree changes only), so the manifest never described commits landed since the
last ingestion run — contradicting the recent-changes window the agent is
told about.

Pass the recorded head into createRepoManifest and, when it is still a
reachable commit and differs from the current head, compute
`git diff <previousHead> HEAD` and `git log <previousHead>..HEAD`. Fall back
to the working-tree diff on the first run, when nothing new was committed, or
when the recorded head is unreachable (force-push / rewritten history), so a
diff against a missing commit can never throw.

Fixes langchain-ai#409

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ingestAllConnectors ran connectors serially with no error handling, so the
first connector that threw (e.g. an un-refreshable token) aborted the whole
"all" run and discarded results from every connector that already succeeded.
Run them concurrently with Promise.allSettled and turn each rejection into a
well-formed `error` result so the agent still sees everything that ran.

The X connector had the same shape internally: any single stream error (e.g. a
429 on one endpoint) threw out of ingest, orphaning already-written dumps and
skipping writeConnectorState so latestIds never advanced — forcing a full
re-fetch next run. Wrap each stream (and each list within list_posts) in
try/catch, record a warning, and always write state at the end, mirroring the
resilient pattern already used by the hackernews and git-repo connectors. A run
that fetched nothing but hit an error now reports `error` instead of a benign
`skipped`.

Fixes langchain-ai#412

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant