Commit Graph

9813 Commits

Author SHA1 Message Date
Artale
643288fda8 fix(cli): route logs to stderr during shell completion output (openclaw#15496) thanks @arosstale
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 19:14:53 -06:00
Owen
87b31acbb5 feat: add GLM-5 model support (#14352) (#15867)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0e3289a594
Co-authored-by: battman21 <2656916+battman21@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 02:13:42 +01:00
Peter Steinberger
4fdfa42619 perf(test): silence config overwrite warnings in vitest 2026-02-14 01:10:45 +00:00
Peter Steinberger
9cb630ca7c docs: fix compaction config note 2026-02-14 02:10:28 +01:00
Artale
0942ecb54f fix(cron): use job config for cleanup instead of hardcoded "keep" (openclaw#15427) thanks @arosstale
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 19:10:17 -06:00
Peter Steinberger
59d2d89fe6 perf(test): collapse docker setup sandbox churn 2026-02-14 01:09:03 +00:00
Peter Steinberger
8796bfaaac perf(test): consolidate browser and canvas hotspot suites 2026-02-14 01:07:23 +00:00
Artale
7f0d6b1fcb fix(heartbeat): exempt wake and hook reasons from empty-heartbeat skip (openclaw#14532) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 19:05:02 -06:00
Peter Steinberger
e18f94a347 refactor(config): simplify env snapshot write context 2026-02-14 02:03:45 +01:00
Peter Steinberger
cc2249a431 refactor(telegram): extract native command menu helpers 2026-02-14 02:02:53 +01:00
Peter Steinberger
2e84ae7019 perf(test): consolidate browser profile CRUD checks 2026-02-14 01:02:14 +00:00
Peter Steinberger
e8377799bb perf(test): reduce vitest logging overhead and media fixture cost 2026-02-14 00:59:53 +00:00
Artale
31d8546afd fix(gateway): hide phantom main agent when agents.list is configured (openclaw#12364) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:56:10 -06:00
AkosCz
a4f4b0636f fix: preserve ${VAR} env var references when writing config back to disk (#11560)
* fix: preserve ${VAR} env var references when writing config back to disk

Fixes #11466

When config is loaded, ${VAR} references are resolved to their plaintext
values. Previously, writeConfigFile would serialize the resolved values,
silently replacing "${ANTHROPIC_API_KEY}" with "sk-ant-api03-..." in the
config file.

Now writeConfigFile reads the current file pre-substitution, and for each
value that matches what a ${VAR} reference would resolve to, restores the
original reference. Values the caller intentionally changed are kept as-is.

This fixes all 50+ writeConfigFile call sites (doctor, configure wizard,
gateway config.set/apply/patch, plugins, hooks, etc.) without requiring
any caller changes.

New files:
- src/config/env-preserve.ts — restoreEnvVarRefs() utility
- src/config/env-preserve.test.ts — 11 unit tests

* fix: remove global config env snapshot race

* docs(changelog): note config env snapshot race fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 01:53:17 +01:00
Owen
11ab1c6937 fix: enforce Telegram 100-command limit with warning (#5787) (#15844)
* fix: enforce Telegram 100-command limit with warning (#5787)

Telegram's setMyCommands API rejects requests with more than 100 commands.
When skills + custom + plugin commands exceed the limit, truncate to 100
and warn the user instead of silently failing on every startup.

* fix: enforce Telegram menu cap + keep hidden commands callable (#15844) (thanks @battman21)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 01:51:00 +01:00
Peter Steinberger
aa6d8b27ac perf(test): merge queue integration coverage and shrink media fixture 2026-02-14 00:50:14 +00:00
Cezar “ikari” Pokorski
d134c854a5 feat(config): expose full pi-ai model compat fields in config schema (openclaw#11063) thanks @ikari-pl
Verified:
- pnpm build
- pnpm check
- pnpm test (full run; transient lobster timeout rerun passed)

Co-authored-by: ikari-pl <811702+ikari-pl@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:47:18 -06:00
AI-Reviewer-QS
28431b84cc fix(gateway): prune expired entries instead of clearing all hook auth failure state (#15848)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 188a40e8a3
Co-authored-by: AI-Reviewer-QS <255312808+AI-Reviewer-QS@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:46:12 +01:00
Artale
67b5c093b5 fix(auto-reply): allow image-only messages to reach the agent (openclaw#12352) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:42:22 -06:00
Peter Steinberger
e7c3c27fd0 perf(test): trim browser and models suite overhead 2026-02-14 00:38:55 +00:00
Artale
fdacfc571c fix(media): classify text/* MIME types as documents (openclaw#12341) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:38:38 -06:00
Spacefish
f9379ecee2 Ignore up to 4 non-word characters when stripping HEARTBEAT_OK token … (#15847)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: dc03ce5005
Co-authored-by: Spacefish <375633+Spacefish@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:36:04 +01:00
Peter Steinberger
6daa4911e7 perf(subagents): speed announce retry polling and trim duplicate e2e coverage 2026-02-14 00:28:20 +00:00
Peter Steinberger
4d1461011d perf(cli): speed up help/config paths and route config get/unset 2026-02-14 00:27:35 +00:00
Shadril Hassan Shifat
386bb0c618 fix: don't auto-create HEARTBEAT.md on workspace init (openclaw#12027) thanks @shadril238
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:24:22 -06:00
Peter Steinberger
0a724127dc perf(test): tighten telegram media e2e flush windows 2026-02-14 00:23:36 +00:00
Peter Steinberger
784e7c1fd5 perf(test): reduce repeated image work in web auto-reply e2e 2026-02-14 00:21:53 +00:00
Shadril Hassan Shifat
1c928e493d fix(hooks): replace console logging with proper subsystem logging in loader (openclaw#11029) thanks @shadril238
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:21:11 -06:00
Peter Steinberger
05524bb5ef perf(test): remove duplicate models list e2e suite 2026-02-14 00:20:47 +00:00
Sunwoo Yu
11702290ff feat(ollama): add native /api/chat provider for streaming + tool calling (#11853)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0a723f98e6
Co-authored-by: BrokenFinger98 <115936166+BrokenFinger98@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:20:42 +01:00
Shadril Hassan Shifat
5378583da1 fix(discord): Apply historyLimit to channel/group sessions to prevent compaction bypass (openclaw#11356) thanks @shadril238
Verified:
- pnpm build
- pnpm check
- pnpm test (ran; one unrelated existing failure in models forward-compat test)
- pnpm vitest src/agents/pi-embedded-runner.history-limit-from-session-key.test.ts

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:18:57 -06:00
Peter Steinberger
ec4da3aca9 perf(test): lighten models list e2e registry mock 2026-02-14 00:17:49 +00:00
Peter Steinberger
212da860a9 perf(test): speed up screenshot normalization e2e fixture 2026-02-14 00:17:49 +00:00
Peter Steinberger
93dc3bb79a perf(test): avoid npm pack in plugin install e2e fixtures 2026-02-14 00:17:49 +00:00
Peter Steinberger
bc3eb98445 fix(cli): avoid runtime import cycle in routed commands 2026-02-14 00:17:29 +00:00
Peter Steinberger
2f49d8858c perf(cli): slim route-first bootstrap with lazy route handlers 2026-02-14 00:12:23 +00:00
Peter Steinberger
fecb3f326e perf(test): trim models/browser suite overhead 2026-02-14 00:08:02 +00:00
Peter Steinberger
cf2524b8b9 refactor(models): share auth helpers and forward-compat list fallbacks 2026-02-14 01:07:35 +01:00
Peter Steinberger
363a56ab87 refactor(telegram): streamline file-ref wrapping and hoist regexes 2026-02-14 01:03:50 +01:00
Peter Steinberger
3a73e2508b perf(gateway): skip idle channel shutdown work 2026-02-13 23:57:03 +00:00
Vincent Koc
a0cbf9002d fix(models): antigravity opus 4.6 availability follow-up (#12845)
* fix(models): antigravity opus 4.6 availability follow-up

* chore(format): apply updated oxfmt config to models files

* fix(models): retain zai glm-5 forward-compat fallback after extraction

* chore(format): apply updated oxfmt config

* fix(models): fail fast on unknown auth login provider

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:54:46 +01:00
Peter Steinberger
23e8f3a20a perf(test): merge block-streaming scenarios into single fixture run 2026-02-13 23:54:28 +00:00
Glucksberg
9bd2ccb017 feat: add pre-prompt context size diagnostic logging (openclaw#8930) thanks @Glucksberg
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 17:54:22 -06:00
Peter Steinberger
79bd82a35b perf(test): statically import gateway reload deps 2026-02-13 23:52:20 +00:00
Divanoli Mydeen Pitchai
1055e71c4b fix(telegram): auto-wrap .md file references in backticks to prevent URL previews (#8649)
* fix(telegram): auto-wrap file references with TLD extensions to prevent URL previews

Telegram's auto-linker aggressively treats filenames like HEARTBEAT.md,
README.md, main.go, script.py as URLs and generates domain registrar previews.

This fix adds comprehensive protection for file extensions that share TLDs:
- High priority: .md, .go, .py, .pl, .ai, .sh
- Medium priority: .io, .tv, .fm, .am, .at, .be, .cc, .co

Implementation:
- Added wrapFileReferencesInHtml() in format.ts
- Runs AFTER markdown→HTML conversion
- Tokenizes HTML to respect tag boundaries
- Skips content inside <code>, <pre>, <a> tags (no nesting issues)
- Applied to all rendering paths: renderTelegramHtmlText, markdownToTelegramHtml,
  markdownToTelegramChunks, and delivery.ts fallback

Addresses review comments:
- P1: Now handles chunked rendering paths correctly
- P2: No longer wraps inside existing code blocks (token-based parsing)
- No lookbehinds used (broad Node compatibility)

Includes comprehensive test suite in format.wrap-md.test.ts

AI-assisted: true

* fix(telegram): prevent URL previews for file refs with TLD extensions

Two layers were causing spurious link previews for file references like
`README.md`, `backup.sh`, `main.go`:

1. **markdown-it linkify** converts `README.md` to
   `<a href="http://README.md">README.md</a>` (.md = Moldova TLD)
2. **Telegram auto-linker** treats remaining bare text as URLs

## Changes

### Primary fix: suppress auto-linkified file refs in buildTelegramLink
- Added `isAutoLinkedFileRef()` helper that detects when linkify auto-
  generated a link from a bare filename (href = "http://" + label)
- Rejects paths with domain-like segments (dots in non-final path parts)
- Modified `buildTelegramLink()` to return null for these, so file refs
  stay as plain text and get wrapped in `<code>` by the wrapper

### Safety-net: de-linkify in wrapFileReferencesInHtml
- Added pre-pass that catches auto-linkified anchors in pre-rendered HTML
- Handles edge cases where HTML is passed directly (textMode: "html")
- Reuses `isAutoLinkedFileRef()` logic — no duplication

### Bug fixes discovered during review
- **Fixed `isClosing` bug (line 169)**: the check `match[1] === "/"`
  was wrong — the regex `(<\/?)}` captures `<` or `</`, so closing
  tags were never detected. Changed to `match[1] === "</"`. This was
  causing `inCode/inPre/inAnchor` to stay stuck at true after any
  opening tag, breaking file ref wrapping after closing tags.
- **Removed double `wrapFileReferencesInHtml` call**: `renderTelegramHtmlText`
  was calling `markdownToTelegramHtml` (which wraps) then wrapping again.

### Test coverage (+12 tests, 26 total)
- `.sh` filenames (original issue #6932 mentioned backup.sh)
- Auto-linkified anchor replacement
- Auto-linkified path anchor replacement
- Explicit link preservation (different label)
- File ref after closing anchor tag (exercises isClosing fix)
- Multiple file types in single message
- Real URL preservation
- Explicit markdown link preservation
- File ref after real URL in same message
- Chunked output file ref wrapping

Closes #6932

* test(telegram): add comprehensive edge case coverage for file ref wrapping

Add 16 edge case tests covering:
- File refs inside bold/italic tags
- Fenced code blocks (no double-wrap)
- Domain-like paths preserved as links (example.com/README.md)
- GitHub URLs with file paths
- wrapFileRefs: false behavior
- All TLD extensions (.ai, .io, .tv, .fm)
- Non-TLD extensions not wrapped (.png, .css, .js)
- File ref position (start, end, multiple in sequence)
- Nested paths without domain segments
- Version-like paths (v1.0/README.md wraps, example.com/v1.0/README.md links)
- Hyphens and underscores in filenames
- Uppercase extensions

* fix(telegram): use regex literal and depth counters for tag tracking

Code review fixes:
1. Replace RegExp constructor with regex literal for autoLinkedAnchor
   - Avoids double-escaping issues with \s
   - Uses backreference \1 to match href=label pattern directly

2. Replace boolean toggles with depth counters for tag nesting
   - codeDepth, preDepth, anchorDepth track nesting levels
   - Correctly handles nested tags like <pre><code>...</code></pre>
   - Prevents wrapping inside any level of protected tags

Add 4 tests for edge cases:
- Nested code tags (depth tracking)
- Multiple anchor tags in sequence
- Auto-linked anchor with backreference match
- Anchor with different href/label (no match)

* fix(telegram): add escapeHtml and escapeRegex for defense in depth

Code review fixes:
1. Escape filename with escapeHtml() before inserting into <code> tags
   - Prevents HTML injection if regex ever matches unsafe chars
   - Defense in depth (current regex already limits to safe chars)

2. Escape extensions with escapeRegex() before joining into pattern
   - Prevents regex breakage if extensions contain metacharacters
   - Future-proofs against extensions like 'c++' or 'd.ts'

Add tests documenting regex safety boundaries:
- Filenames with special chars (&, <, >) don't match
- Only [a-zA-Z0-9_.\-./] chars are captured

* fix(telegram): catch orphaned single-letter TLD patterns

When text like 'R&D.md' doesn't match the main file pattern (because &
breaks the character class), the 'D.md' part can still be auto-linked
by Telegram as a domain (https://d.md/).

Add second pass to catch orphaned TLD patterns like 'D.md', 'R.io', 'X.ai'
that follow non-alphanumeric characters and wrap them in <code> tags.

Pattern: ([^a-zA-Z0-9]|^)([A-Za-z]\.(?:extensions))(?=[^a-zA-Z0-9/]|$)

Tests added:
- 'wraps orphaned TLD pattern after special character' (R&D.md → R&<code>D.md</code>)
- 'wraps orphaned single-letter TLD patterns' (X.ai, R.io)

* refactor(telegram): remove popular domain TLDs from file extension list

Remove .ai, .io, .tv, .fm from FILE_EXTENSIONS_WITH_TLD because:
- These are commonly used as real domains (x.ai, vercel.io, github.io)
- Rarely used as actual file extensions
- Users are more likely referring to websites than files

Keep: md, sh, py, go, pl (common file extensions, rarely intentional domains)
Keep: am, at, be, cc, co (less common as intentional domain references)

Update tests to reflect the change:
- Add test for supported extensions (.am, .at, .be, .cc, .co)
- Add test verifying popular TLDs stay as links

* fix(telegram): prevent orphaned TLD wrapping inside HTML tags

Code review fixes:

1. Orphaned TLD pass now checks if match is inside HTML tag
   - Uses lastIndexOf('<') vs lastIndexOf('>') to detect tag context
   - Skips wrapping when between < and > (inside attributes)
   - Prevents invalid HTML like <a href="...&<code>D.md</code>">

2. textMode: 'html' now trusts caller markup
   - Returns text unchanged instead of wrapping
   - Caller owns HTML structure in this mode

Tests added:
- 'does not wrap orphaned TLD inside href attributes'
- 'does not wrap orphaned TLD inside any HTML attribute'
- 'does not wrap in HTML mode (trusts caller markup)'

* refactor(telegram): use snapshot for orphaned TLD offset clarity

Use explicit snapshot variable when checking tag positions in orphaned
TLD pass. While JavaScript's replace() doesn't mutate during iteration,
this makes intent explicit and adds test coverage for multi-TLD HTML.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(telegram): prevent orphaned TLD wrapping inside code/pre tags

- Add depth tracking for code/pre tags in orphaned TLD pass
- Fix test to expect valid HTML output
- 55 tests now covering nested tag scenarios

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(telegram): clamp depth counters and add anchor tracking to orphaned pass

- Clamp depth counters at 0 for malformed HTML with stray closing tags
- Add anchor depth tracking to orphaned TLD pass to prevent wrapping
  inside link text (e.g., <a href="...">R&D.md</a>)
- 57 tests covering all edge cases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(telegram): keep .co domains linked and wrap punctuated file refs

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:51:47 +01:00
Peter Steinberger
4bef423d83 perf(test): reduce gateway reload waits and trim duplicate invoke coverage 2026-02-13 23:50:08 +00:00
solstead
ab71fdf821 Plugin API: compaction/reset hooks, bootstrap file globs, memory plugin status (#13287)
* feat: add before_compaction and before_reset plugin hooks with session context

- Pass session messages to before_compaction hook
- Add before_reset plugin hook for /new and /reset commands
- Add sessionId to plugin hook agent context

* feat: extraBootstrapFiles config with glob pattern support

Add extraBootstrapFiles to agent defaults config, allowing glob patterns
(e.g. "projects/*/TOOLS.md") to auto-load project-level bootstrap files
into agent context every turn. Missing files silently skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(status): show custom memory plugins as enabled, not unavailable

The status command probes memory availability using the built-in
memory-core manager. Custom memory plugins (e.g. via plugin slot)
can't be probed this way, so they incorrectly showed "unavailable".
Now they show "enabled (plugin X)" without the misleading label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use async fs.glob and capture pre-compaction messages

- Replace globSync (node:fs) with fs.glob (node:fs/promises) to match
  codebase conventions for async file operations
- Capture session.messages BEFORE replaceMessages(limited) so
  before_compaction hook receives the full conversation history,
  not the already-truncated list

* fix: resolve lint errors from CI (oxlint strict mode)

- Add void to fire-and-forget IIFE (no-floating-promises)
- Use String() for unknown catch params in template literals
- Add curly braces to single-statement if (curly rule)

* fix: resolve remaining CI lint errors in workspace.ts

- Remove `| string` from WorkspaceBootstrapFileName union (made all
  typeof members redundant per no-redundant-type-constituents)
- Use type assertion for extra bootstrap file names
- Drop redundant await on fs.glob() AsyncIterable (await-thenable)

* fix: address Greptile review — path traversal guard + fs/promises import

- workspace.ts: use path.resolve() + traversal check in loadExtraBootstrapFiles()
- commands-core.ts: import fs from node:fs/promises, drop fs.promises prefix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve symlinks before workspace boundary check

Greptile correctly identified that symlinks inside the workspace could
point to files outside it, bypassing the path prefix check. Now uses
fs.realpath() to resolve symlinks before verifying the real path stays
within the workspace boundary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address Greptile review — hook reliability and type safety

1. before_compaction: add compactingCount field so plugins know both
   the full pre-compaction message count and the truncated count being
   fed to the compaction LLM. Clarify semantics in comment.

2. loadExtraBootstrapFiles: use path.basename() for the name field
   so "projects/quaid/TOOLS.md" maps to the known "TOOLS.md" type
   instead of an invalid WorkspaceBootstrapFileName cast.

3. before_reset: fire the hook even when no session file exists.
   Previously, short sessions without a persisted file would silently
   skip the hook. Now fires with empty messages array so plugins
   always know a reset occurred.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: validate bootstrap filenames and add compaction hook timeout

- Only load extra bootstrap files whose basename matches a recognized
  workspace filename (AGENTS.md, TOOLS.md, etc.), preventing arbitrary
  files from being injected into agent context.
- Wrap before_compaction hook in a 30-second Promise.race timeout so
  misbehaving plugins cannot stall the compaction pipeline.
- Clarify hook comments: before_compaction is intentionally awaited
  (plugins need messages before they're discarded) but bounded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: make before_compaction non-blocking, add sessionFile to after_compaction

- before_compaction is now true fire-and-forget — no await, no timeout.
  Plugins that need full conversation data should persist it themselves
  and return quickly, or use after_compaction for async processing.
- after_compaction now includes sessionFile path so plugins can read
  the full JSONL transcript asynchronously. All pre-compaction messages
  are preserved on disk, eliminating the need to block compaction.
- Removes Promise.race timeout pattern that didn't actually cancel
  slow hooks (just raced past them while they continued running).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add sessionFile to before_compaction for parallel processing

The session JSONL already has all messages on disk before compaction
starts. By providing sessionFile in before_compaction, plugins can
read and extract data in parallel with the compaction LLM call rather
than waiting for after_compaction. This is the optimal path for memory
plugins that need the full conversation history.

sessionFile is also kept on after_compaction for plugins that only
need to act after compaction completes (analytics, cleanup, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: move bootstrap extras into bundled hook

---------

Co-authored-by: Solomon Steadman <solstead@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Clawdbot <clawdbot@alfie.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:45:45 +01:00
Jessy LANGE
3bda3df729 fix(browser): hot-reload profiles added after gateway start (#4841) (#8816)
* fix(browser): hot-reload profiles added after gateway start (#4841)

* style: format files with oxfmt

* Fix hot-reload stale config fields bug in forProfile

* Fix test order-dependency in hot-reload profiles test

* Fix mock reset order to prevent stale cfgProfiles

* Fix config cache blocking hot-reload by clearing cache before loadConfig

* test: improve hot-reload test to properly exercise config cache

- Add simulated cache behavior in mock
- Prime cache before mutating config
- Verify stale value without clearConfigCache
- Verify fresh value after hot-reload

Addresses review comment about test not exercising cache

* test: add hot-reload tests for browser profiles in server context.

* fix(browser): optimize profile hot-reload to avoid global cache clear

* fix(browser): remove unused loadConfig import

* fix(test): execute resetModules before test setup

* feat: implement browser server context with profile hot-reloading and tab management.

* fix(browser): harden profile hot-reload and shutdown cleanup

* test(browser): use toSorted in known-profile names test

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:44:04 +01:00
Peter Steinberger
d5e25e0ad8 refactor: centralize dispatcher lifecycle ownership 2026-02-14 00:41:37 +01:00
Peter Steinberger
5caf829d28 perf(test): trim duplicate gateway and auto-reply test overhead 2026-02-13 23:40:38 +00:00