Commit Graph
2633 Commits
Author SHA1 Message Date
Saket Aryan cbf97c6077 fix(plugins): bound the exit flush, and stop openclaw deleting a legacy account
Second review round. The first two are regressions from the first round.

The forced exit flush added fifteen seconds to host shutdown. Node re-emits
beforeExit whenever the handler schedules async work, so an unconditional
flush(true) looped until the five-attempt budget was spent, and against the real
3s delivery timeout that is 15s added to the shutdown of whatever editor or CLI
is hosting this. The backoff used to end that loop after one attempt; removing it
for the forced path removed the only thing bounding it. Measured at 15008ms, now
6001ms with a one-shot latch, and 12ms when delivery is healthy, which is the
only case most people ever see.

openclaw deleted a legacy account before it had anything to replace it with. An
install predating keyFingerprint has an email and no fingerprint, so the
comparison failed and clearResolvedAccount() ran immediately; if the re-resolve
then failed because the user was offline the email was gone from disk for good,
and the per-key latch was already set so nothing retried. Now cleared only when a
real fingerprint disagrees, which is the same trade the Python core makes and
documents: verify, and keep what you have until the verification succeeds. The
latch is released on a failed lookup so the next capture tries again.

The overflow test did not exercise the path it is named for: with only two
events captured the re-queue had an empty queue to merge into, so the slice on
the failure path never ran, and that is the half deciding which end gets dropped.
It now fills past the cap before flushing and asserts the exact surviving order.

core 36, openclaw 432, opencode 35, deepseek 47. Wire e2e 9 of 9 and identity
e2e 7 of 7 still pass against a real local server.

Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb
2026-09-17 19:43:25 +05:30
Saket Aryan 44c6a07ddf fix(plugins): flush on exit regardless of backoff, and prefer the backlog over new events
Findings from an independent review of this branch.

The exit-time flush was gated by its own cooldown. beforeExit called the same
flush() that opens with a retryNotBefore check, so after any failed delivery a
process exiting inside the 2s to 60s window sent nothing and the queue died with
it. That is precisely the loss this branch exists to stop, and timer.unref makes
beforeExit often the only remaining chance. flush(force) now skips the cooldown
and beforeExit passes it.

Overflow kept the newest and evicted the batch being retried, which threw away
exactly the events the retry exists to save. Both the failure path and capture()
now keep the backlog and drop the new event instead, matching Python's record(),
which refuses new events once the spool is full.

That change needs a bound, so delivery now gives up after five attempts, as the
Python core does. Without one a payload the server will never accept would be
retried for the whole session and, with the backlog now preferred, would hold the
queue against everything behind it.

Events carry a capture-time timestamp. They now sit through backoff and across
an entire outage, so without one PostHog records them at whatever moment delivery
happened to succeed. It also matters for the uuid dedupe, whose key includes the
event date.

openclaw wiped a resolved account on any capture without an apiKey: the
fingerprint comparison was `undefined === ""`, so a keyless call looked like a key
change. Guarded on a real key being present. Masked today because every call site
supplies one, which is why only a test found it.

Two smaller ones. opencode's PostHog source was "plugin", which named no
particular plugin and matched no vocabulary; it is now OPENCODE_PLUGIN like every
other surface, and a saved insight filtering source = "plugin" needs repointing.
And an em dash in opencode's published description had been rewritten to a —
escape by my own json.dumps when adding the test script; restored.

One openclaw test asserted only not.toThrow() under a name claiming it checked
the identity, and under the fingerprint gate the path it exercised no longer uses
the email at all. It now pins the real condition.

core 35, openclaw 432, opencode 35, pi-agent 89, deepseek 47. The wire e2e still
passes 9 of 9 against a real local server, and the identity e2e 7 of 7.

Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb
2026-09-17 19:30:59 +05:30
Saket Aryan 6f207d2e28 fix(plugins): treat an HTTP error response as a failed delivery
Found by driving the core against a real local server rather than an injected
delivery stub, which is exactly where it could hide: fetch only rejects on a
network-level failure, so a 500, a 503 or a 429 resolved normally and the batch
was counted as delivered and dropped. The unit tests could not catch it because
their stub throws, and real fetch does not.

That is the likelier outage than a refused connection, so the retry added in the
previous commit was covering the rarer half of the problem.

Any non-2xx now throws and takes the retry path. Matching the Python core, which
retries every HTTP error rather than classifying them: the backoff and the queue
bound contain a payload that will never be accepted, because the re-queued batch
sits at the front and is the first thing evicted.

Two tests against the real default delivery path, stubbing fetch rather than the
delivery hook, so a 503 keeps the batch and a 200 clears it.

End to end against a local server, real fetch and real retry timing: events
arrive and carry a uuid, a 503 keeps the batch, an immediate retry is suppressed
by the backoff, the retained event is delivered on recovery with its original
uuid and no duplicate, and a refused connection behaves the same way. Nine of
nine.

Identity checked on the same path: opencode's project_hash is salted, differs per
account, is stable within one, and no raw project id appears in the payload.
openclaw emits two distinct identities across a key change, which is the defect
this branch fixes, observed on the wire rather than through a mock.

agent-plugin-core/ts 32, openclaw 431, opencode 35, pi-agent 89, deepseek 47,
Python core 242 unaffected.

Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb
2026-09-17 19:02:51 +05:30
Saket Aryan c05556f3cf fix(plugins): stop the TypeScript telemetry losing events and misattributing accounts
The Python plugin telemetry was hardened across #7322 to #7326. The TypeScript
side has the same defect classes and was not touched, because the two share no
code: agent-plugin-core/python generates into six bundles, agent-plugin-core/
typescript is a separate core each plugin wraps. Fixing one surfaced nothing
about the other, which is how this survived.

Three fixes, all confirmed by running the code rather than reading it.

A failed delivery deleted the batch. The core detached the queue before the
await and swallowed the error, so one blip destroyed the events with nothing
recording that it happened. Probed: two events in, delivery throws, queue goes to
zero, no retry ever. The batch is now put back, bounded by maxQueueSize and
biased to the newest so a long outage costs the oldest events rather than
unbounded memory, and repeated failures back off to a ceiling instead of retrying
every flush against a host that is blocking us. Every event now carries a uuid
stamped at capture, which is what makes the retry safe: PostHog collapses
anything it already accepted.

Deliberately no disk spool, and that is written into the code so it reads as a
decision. Python spools because its hooks are per-tool-call processes that exit
immediately. These plugins live inside a host for a whole session, so
re-queueing covers the same transient failures without the claim and lease
machinery that took three review rounds to get right on the Python side. What it
leaves uncovered is narrow: a session that both starts and ends offline.

openclaw used a cached email forever. The refresh was guarded by !hasEmail, so
after an API key change every event kept reporting under the previous account.
The email is now bound to a fingerprint of the key it was resolved for and only
used while those agree; a mismatch forgets the account and re-resolves. The
resolution latch is per key rather than once per process, so a key changed
mid-session is actually looked up. A row with an email and no fingerprint, which
is what an upgrade from the current version looks like, is verified rather than
adopted, matching the decision reached on #7325.

opencode hashed the project id unsalted, which is reversible for anyone who can
enumerate project ids. Salted with the API key rather than a stored per-install
value: it is already in play, it is high entropy, and it needs no new file and so
no write race to get wrong. Per account rather than per machine, which also keeps
joins working across machines, and it resets on key rotation consistently with
distinctId, which already did.

Also wired opencode's tests into CI. They existed and nothing ran them, so the
regression test asked for on #7322 would not have gated anything.

Verified: agent-plugin-core/ts 30, openclaw 431, opencode 35, pi-agent 89,
deepseek 47. The new tests were each checked against the unfixed code first; the
core ones fail 3 of 3 and the openclaw one fails without the fingerprint gate.

Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb
2026-09-17 18:43:27 +05:30
Paurush MittalandGitHub 0df3e4b87d fix(docs): correct rendered titles and remaining SEO links (#7344) 2026-09-16 17:14:33 +05:30
PowderXuandGitHub b51f7692f0 docs(upstash): correct the default collection namespace (#7287) 2026-09-15 19:41:46 +05:30
jianyx1andGitHub dc7f88363f docs: fix Hermes integration page to match the current plugin (#7244) 2026-09-15 19:23:17 +05:30
c7ee362aff fix(security): resolve 12 Vanta/Dependabot vulnerabilities across 6 pnpm workspaces + poetry.lock (#7280)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-09-11 16:07:57 +05:30
KartikandGitHub d873892dad feat(plugins)!: make Sidekick exclusive to Claude Code (#7278) 2026-09-10 20:51:50 +05:30
KartikandGitHub 02f7a9b2c4 docs: align agent plugin guides with shared runtime behavior (#7269) opencode-v0.3.0 deepseek-plugin-v0.3.0 openclaw-v1.1.0 pi-agent-v0.3.0 2026-09-09 01:03:26 +05:30
KartikandGitHub 73e7b8763a refactor(integrations): shared agent plugin runtimes and native adapters (#7203) 2026-09-08 23:32:25 +05:30
KartikandGitHub dae67f74f5 fix(docs): SEO improvements for page titles, internal links, and URL structure (#7224) 2026-09-04 20:32:23 +05:30
KartikandGitHub 9a7924befd chore(release): bump Python and TypeScript SDK patch versions (#7210) v2.0.20 ts-v3.1.8 2026-09-02 18:44:55 +05:30
KartikandGitHub 3cf41878ea fix: replace PostHog evaluate_flags with static config for OSS notices (#7185) 2026-09-02 18:00:01 +05:30
Elif Sema BalciogluandGitHub c33ca27f5e docs: fix Oracle vector store setup and search examples (#7111) 2026-09-01 19:19:48 +05:30
KartikandGitHub 71fba8d464 feat(claude-code-plugin): move the Claude Code plugin to its own integration and ship it as 0.3.0 (#7106) 2026-09-01 02:34:45 +05:30
KartikandGitHub 19cb89aff4 docs: add 301 redirects for 49 legacy 404 pages (#7161) 2026-08-28 17:44:10 +05:30
fdfb763d6e docs(api-reference): add Dream (memory synthesis) endpoints (#7109)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-27 22:12:04 +05:30
KartikandGitHub 0070e08e01 feat(deepseek-plugin,mem0-strands): add usage telemetry (#7110) mem0-strands-v0.1.1 deepseek-plugin-v0.1.1 2026-08-27 13:48:30 +05:30
HimanshuandGitHub 39bc023305 docs(integrations): add Vercel Marketplace (managed) integration page (#7100) mem0-strands-v0.1.0 2026-08-24 22:22:04 +05:30
krishna soniandGitHub b1342a3408 refactor: replace custom validator with Pydantic extra="forbid" config (#7089) 2026-08-24 21:17:57 +05:30
KartikandGitHub b717e38785 refactor(integrations): rename dsh-mem0 to deepseek-plugin, strands-mem0 to mem0-strands (#7098) deepseek-plugin-v0.1.0 2026-08-24 19:21:23 +05:30
Indian-boultandGitHub dc82354e14 docs(skills): fix dead links in skills READMEs (#7092) n8n-nodes-mem0-v0.1.4 cli-node-v0.2.13 cli-v0.2.12 v2.0.19 ts-v3.1.7 openclaw-v1.0.16 pi-agent-v0.1.5 vercel-ai-v3.0.2 2026-08-24 18:25:33 +05:30
KartikandGitHub 4ddee9c51d chore(release): bump SDK, CLI, and plugin versions; add Strands, DeepSeek Harness, and Kimi changelogs (#7097) 2026-08-24 18:10:44 +05:30
7e09615571 feat(integrations): dsh-mem0 — Mem0 as a native DeepSeek Harness plugin (#7027)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
2026-08-24 14:03:50 +05:30
KartikandGitHub d18e751dec docs: redirect five dead api-reference paths to their real pages (#7094) 2026-08-24 13:53:04 +05:30
HimanshuandGitHub 8d5b7865bd feat(integrations): strands-mem0 | Mem0 as a native Strands MemoryStore (#7021) 2026-08-22 19:04:24 +05:30
Abhinav SinghandGitHub 9b565da8e3 docs(embedders): document api_key on the Hugging Face Python config table (#7045) 2026-08-22 13:51:50 +05:30
Yiheng ZhaoandGitHub 48d0d0cd9c fix(docs): balance code fences in cookbook_template.mdx (#7054) 2026-08-22 13:50:49 +05:30
KartikandGitHub feb12852c0 fix(docs): redirect the eight 404 paths and repair dead wildcard rules (#7053) 2026-08-21 19:31:37 +05:30
Harsh Vardhan GuptaandGitHub 5af797834c fix(security): resolve 17 Vanta/Dependabot HIGH+CRITICAL vulnerabilities across 5 pnpm workspaces (#7032) 2026-08-21 17:41:41 +05:30
KartikandGitHub 4fa4839077 fix(ci): make the vouch check speak, unblock list updates, widen the docs exemption (#6974) 2026-08-20 23:13:42 +05:30
KartikandGitHub 3599aa75ed docs: document the real search filter grammar (#6906) 2026-08-20 21:33:21 +05:30
HimanshuandGitHub 1de6499b8a fix(integrations/zapier): address Zapier publishing review (#6985) 2026-08-20 18:53:06 +05:30
KartikandGitHub ed38ddf873 fix(python): huggingface TEI auth, procedural-memory content handling, and proxy pip auto-install (#6947) 2026-08-20 15:56:55 +05:30
KartikandGitHub 530d802b55 fix(plugins): bug-bash fixes for Cursor, Codex, Antigravity, and a Claude.ai docs page (#6948) 2026-08-20 15:56:17 +05:30
KartikandGitHub d3334fa5f1 docs: ground the platform/OSS comparison and memory-type status in reality (#6908) 2026-08-20 15:26:22 +05:30
KartikandGitHub 52b02c7cc1 docs: fix Claude Desktop MCP setup, CrewAI guide, and missing contributor docs (#6945) 2026-08-20 15:24:05 +05:30
mintlify[bot]GitHubmintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
001c235229 Fix broken links: remove duplicate reranking redirect (#6975)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-08-14 12:47:17 +00:00
KartikandGitHub bf2d591b27 docs: remove Controlling Memory Ingestion cookbook, redirect to Custom Instructions (#6955) 2026-08-14 18:16:36 +05:30
KartikandGitHub b4c50550bf docs: correct client call shape and stale v1 response examples (#6901) 2026-08-14 18:13:37 +05:30
KartikandGitHub 290de24bb8 feat(ci): gate pull requests on an accepted issue (#6894) 2026-08-14 17:05:27 +05:30
Ratish jainandGitHub ef6f51d977 fix(tests): check for RediSearch module availability in Redis tests (#6687) 2026-08-14 17:00:56 +05:30
KartikandGitHub a10c0cd030 fix(mem0-plugin): stop search errors from looking like empty results (#6898) 2026-08-14 16:57:01 +05:30
KartikandGitHub 956bf4f88e fix(ts-oss): return snake_case entity ids from the redis and valkey stores (#6902) 2026-08-14 16:56:27 +05:30
KartikandGitHub 0f172c2890 fix(ts-oss): stop prototype keys from short-circuiting embedding lookup (#6903) 2026-08-14 16:56:03 +05:30
KartikandGitHub 696455fd62 docs: contrast the advanced retrieval modes with distinct examples (#6904) 2026-08-14 16:55:44 +05:30
KartikandGitHub 9e99eaadbc docs: correct memory decay claims that contradict the SDK (#6905) 2026-08-14 16:55:26 +05:30
KartikandGitHub 02ff6c5595 feat(cli): add a version subcommand and document the --filter JSON shape (#6907) 2026-08-14 16:55:12 +05:30
KartikandGitHub a0329f047b docs(cookbooks): repair dead references and label OSS vs Platform support (#6909) 2026-08-14 16:50:46 +05:30