Skip to content

✨ feat(agent-signal): add execAgent plumbing for self-iteration migration#15187

Merged
arvinxx merged 1 commit into
canaryfrom
feat/agent-signal-execagent-plumbing
May 25, 2026
Merged

✨ feat(agent-signal): add execAgent plumbing for self-iteration migration#15187
arvinxx merged 1 commit into
canaryfrom
feat/agent-signal-execagent-plumbing

Conversation

@arvinxx

@arvinxx arvinxx commented May 25, 2026

Copy link
Copy Markdown
Member

💻 Change Type

  • ✨ feat
  • ✅ test

🔗 Related Issue

Part of LOBE-9434 (parent).
Relates to #15116 — this is Phase 1 (dormant plumbing) of the staged split for that PR.

🔀 Description of Change

Phase 1 of LOBE-9434: introduce dormant infrastructure for converging
agent execution onto execAgent. Every piece in this PR is a no-op for every
existing caller — later phases will start using these primitives.

The goal of splitting Phase 1 out is to let the high-risk pieces of #15116
(switching userMemory to async execAgent, deleting executeSync,
migrating executeSelfIteration) land in much smaller, individually
revertable PRs once this foundation has baked.

Contents:

Item What Active today?
A ExecAgentAppContext.suppressSignal flag + sourceMessageId; shouldSuppressSignal helper; gate the agent.user.message re-emission inside AiAgentService.execAgent No caller passes suppressSignal: true and no caller passes the self-iteration slug yet — current behaviour identical.
B Register self-iteration builtin agent + SELF_ITERATION_AGENT_SLUGS set Not referenced by any router/UI; only consumed by shouldSuppressSignal.
C finalStateExtractor (extractFromFinalState / extractMutations / extractArtifacts) Pure helper, no callers yet.
D completionPolicy registered on agent.execution.completed, onSelfIterationCompleted callback is undefined by default Registered as a no-op listener; callback wiring deferred.

Differences vs. the original #15116:

  • Helper shouldSuppressSignal is actually wired into AiAgentService.execAgent (the original PR added the helper but never called it).
  • Did not delete incidental comments in packages/builtin-agents/src/types.ts or packages/builtin-agents/src/index.ts.
  • Kept the existing log(…) debug logger in aiAgent/index.ts for the enqueue catch handler (original PR switched to console.error).
  • The completionPolicy short-circuits before the try { … } block when no callback is provided, instead of always entering it.
  • Added 17 unit tests across the three new modules.

🧪 How to Test

  • Tested locally — bun run type-check clean for everything Phase 1 touches (remaining errors are pre-existing cloud-business issues unrelated to this PR)
  • Added tests:
    • src/server/services/agentSignal/__tests__/suppressSignal.test.ts (5 tests)
    • src/server/services/agentSignal/services/selfIteration/__test__/finalStateExtractor.test.ts (6 tests)
    • src/server/services/agentSignal/policies/completionPolicy.test.ts (6 tests)
  • Re-ran nearby existing suites — packages/builtin-agents, policies/, and services/selfIteration/: 300 tests pass.
bunx vitest run --silent='passed-only' \
  'finalStateExtractor.test.ts' 'completionPolicy.test.ts' 'suppressSignal.test.ts'

📝 Additional Information

No behaviour change. Safe to merge first; subsequent phases:

  • Phase 2 — add executeViaExecAgent (still not wired into any caller)
  • Phase 3 — migrate userMemory.ts (the high-risk piece), then migrate executeSelfIteration callers one at a time
  • Phase 4 — implement onSelfIterationCompleted callback and clean up legacy execute.ts

Cloud impact: none — aiAgent/index.ts is an open-source path; the suppress check is gated by appContext?.suppressSignal === true or membership in SELF_ITERATION_AGENT_SLUGS, neither of which is reachable by any current cloud caller.

…tion

Phase 1 of LOBE-9434: introduces dormant plumbing for converging
agent execution onto execAgent. No behavior changes for any existing
caller — every piece is a no-op until later phases wire it up.

- Add `ExecAgentAppContext.suppressSignal` flag and `sourceMessageId`
- Add `shouldSuppressSignal` helper; gate the `agent.user.message`
  re-emission in `aiAgent.execAgent` so future builtin/background runs
  cannot recurse into the analyzeIntent pipeline
- Register `self-iteration` builtin agent + `SELF_ITERATION_AGENT_SLUGS`
- Add `finalStateExtractor` (`extractFromFinalState` /
  `extractMutations` / `extractArtifacts`) for reading tool-result kind
  partitions off a persisted AgentState snapshot
- Register a no-op `completionPolicy` listener on
  `agent.execution.completed` with an optional
  `onSelfIterationCompleted` callback (undefined by default)

Tests: 17 new unit tests across suppressSignal, finalStateExtractor,
and completionPolicy.
@vercel

vercel Bot commented May 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lobehub Ready Ready Preview, Comment May 25, 2026 3:35am

Request Review

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label May 25, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @arvinxx, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@dosubot dosubot Bot added the feature:agent Assistant/Agent configuration and behavior label May 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5d483c4f9b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


results.push({
apiName: typeof message.apiName === 'string' ? message.apiName : undefined,
data: contentRecord ?? content,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve pluginState payload for extracted tool results

When kind is discovered via pluginState.kind (because message.content is plain text/non-JSON), extractFromFinalState still sets data to contentRecord ?? content, which drops the structured pluginState fields (e.g., IDs needed for mutation/artifact projection). In that scenario downstream self-iteration completion handlers will receive only a string message instead of the actual tool result object, making final-state reconstruction incomplete.

Useful? React with 👍 / 👎.

@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.92473% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 70.93%. Comparing base (f3d5d03) to head (5d483c4).
⚠️ Report is 1 commits behind head on canary.

Additional details and impacted files
@@            Coverage Diff            @@
##           canary   #15187     +/-   ##
=========================================
  Coverage   70.92%   70.93%             
=========================================
  Files        3149     3152      +3     
  Lines      313896   313971     +75     
  Branches    33311    28558   -4753     
=========================================
+ Hits       222628   222705     +77     
+ Misses      91100    91098      -2     
  Partials      168      168             
Flag Coverage Δ
app 61.79% <98.92%> (+0.01%) ⬆️
database 92.20% <ø> (ø)
packages/agent-runtime 80.48% <ø> (ø)
packages/builtin-tool-lobe-agent 19.87% <ø> (ø)
packages/context-engine 84.13% <ø> (ø)
packages/conversation-flow 91.28% <ø> (ø)
packages/file-loaders 87.89% <ø> (ø)
packages/memory-user-memory 74.99% <ø> (ø)
packages/model-bank 99.99% <ø> (ø)
packages/model-runtime 83.88% <ø> (ø)
packages/prompts 72.54% <ø> (ø)
packages/python-interpreter 92.90% <ø> (ø)
packages/ssrf-safe-fetch 0.00% <ø> (ø)
packages/types 35.09% <ø> (ø)
packages/utils 88.47% <ø> (ø)
packages/web-crawler 88.08% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Store 68.01% <ø> (ø)
Services 54.68% <ø> (ø)
Server 72.20% <98.92%> (+0.02%) ⬆️
Libs 56.77% <ø> (ø)
Utils 85.96% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@arvinxx arvinxx changed the title ✨ feat(agent-signal): add execAgent plumbing for self-iteration migration [LOBE-9434 Phase 1] ✨ feat(agent-signal): add execAgent plumbing for self-iteration migration May 25, 2026
@arvinxx arvinxx merged commit 8d4c487 into canary May 25, 2026
52 checks passed
@arvinxx arvinxx deleted the feat/agent-signal-execagent-plumbing branch May 25, 2026 03:40
hardy-one pushed a commit to hardy-one/lobehub that referenced this pull request May 27, 2026
…tion (lobehub#15187)

Phase 1 of LOBE-9434: introduces dormant plumbing for converging
agent execution onto execAgent. No behavior changes for any existing
caller — every piece is a no-op until later phases wire it up.

- Add `ExecAgentAppContext.suppressSignal` flag and `sourceMessageId`
- Add `shouldSuppressSignal` helper; gate the `agent.user.message`
  re-emission in `aiAgent.execAgent` so future builtin/background runs
  cannot recurse into the analyzeIntent pipeline
- Register `self-iteration` builtin agent + `SELF_ITERATION_AGENT_SLUGS`
- Add `finalStateExtractor` (`extractFromFinalState` /
  `extractMutations` / `extractArtifacts`) for reading tool-result kind
  partitions off a persisted AgentState snapshot
- Register a no-op `completionPolicy` listener on
  `agent.execution.completed` with an optional
  `onSelfIterationCompleted` callback (undefined by default)

Tests: 17 new unit tests across suppressSignal, finalStateExtractor,
and completionPolicy.
arvinxx added a commit that referenced this pull request Jun 1, 2026
…nt slugs (#15202)

The Phase 1 consolidation into a single `self-iteration` slug (PR #15187,
inheriting commit 627f899 from the closed #15116) conflated three
distinct background flows that have:

- Independent receipt tables and idempotency Redis namespaces
- Different preflight / brief projection paths
- Different audit pipelines

`one identifier = one behavior` is a load-bearing contract once these
agents are routed through the standard execAgent plugin lookup. Restore
the 3 mode-specific slugs so each agent declares its own tool surface:

| slug                    | future plugin identifier        |
| ----------------------- | ------------------------------- |
| `nightly-review`        | `agent-signal-review`           |
| `self-reflection`       | `agent-signal-reflection`       |
| `self-feedback-intent`  | `agent-signal-feedback-intent`  |

`SELF_ITERATION_AGENT_SLUGS` now contains all three; `completionPolicy`
dispatches on slug membership rather than equality; callback receives
the resolved `agentId` so mode-specific bookkeeping can route from it.

Plugin arrays reference the future identifiers but the tool packages
are not yet registered — invoking any of these agents today runs the
LLM with no tools (dormant by design). Tool-package registration
follows in a separate PR.

No behavior change for existing callers (none invoke these slugs yet).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature:agent Assistant/Agent configuration and behavior size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant