Skip to content

refactor(slack): reuse fetchAgentsForProject in lookupAgentName#2283

Merged
amikofalvy merged 1 commit intomainfrom
refactor/dedup-agent-name-lookup
Feb 24, 2026
Merged

refactor(slack): reuse fetchAgentsForProject in lookupAgentName#2283
amikofalvy merged 1 commit intomainfrom
refactor/dedup-agent-name-lookup

Conversation

@amikofalvy
Copy link
Copy Markdown
Collaborator

Summary

  • Refactors lookupAgentName in agent-resolution.ts to delegate to the existing fetchAgentsForProject utility from events/utils.ts instead of duplicating the internal API call logic (token generation, fetch, error handling)
  • Removes unused imports (generateInternalServiceToken, getInProcessFetch, InternalServices, env)
  • Adds mock for fetchAgentsForProject in agent-resolution.test.ts to fix tests after the import change

Test plan

  • All 10 existing agent-resolution.test.ts tests pass
  • Typecheck passes
  • Pre-commit hooks pass (lint, format)

🤖 Generated with Claude Code

Remove duplicated API call logic from lookupAgentName and delegate to the
existing fetchAgentsForProject utility, reducing maintenance surface.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 24, 2026

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

Project Deployment Actions Updated (UTC)
agents-api Ready Ready Preview, Comment Feb 24, 2026 3:18am
agents-docs Ready Ready Preview, Comment Feb 24, 2026 3:18am
agents-manage-ui Ready Ready Preview, Comment Feb 24, 2026 3:18am

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 24, 2026

🦋 Changeset detected

Latest commit: ece5d8f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@inkeep/agents-work-apps Patch
@inkeep/agents-api Patch
@inkeep/agents-manage-ui Patch
@inkeep/agents-cli Patch
@inkeep/agents-core Patch
@inkeep/agents-mcp Patch
@inkeep/agents-sdk Patch
@inkeep/ai-sdk-provider Patch
@inkeep/create-agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

PR Review Summary

(0) Total Issues | Risk: Low

This is a clean deduplication refactor that consolidates ~70 lines of duplicated internal API call logic into a reuse of the existing fetchAgentsForProject utility. The behavioral semantics are preserved, error handling is correctly delegated, and the test mock updates are appropriate.

💭 Consider (1) 💭

💭 1) agent-resolution.ts Timeout increased from 5s to 10s

Issue: The original lookupAgentName used a 5-second timeout, while fetchAgentsForProject uses 10 seconds.

Why: This is a minor behavioral difference—agent name lookups will now wait longer before timing out. This is likely acceptable (more lenient for slow networks) but worth being aware of for observability/debugging purposes.

Fix: No action needed unless you want to preserve the original 5-second timeout. If so, consider adding an optional timeout parameter to fetchAgentsForProject.

Refs: Original timeout in diff · INTERNAL_FETCH_TIMEOUT_MS

🧹 While You're Here (1) 🧹

🧹 1) agent-resolution.test.ts Enrichment code path has no test coverage

Issue: The lookupAgentName enrichment logic (triggered when agentName is missing or equals agentId) is not tested. All existing tests provide agentName in their mocks, bypassing this code path.

Why: This is pre-existing (not introduced by this PR), but since you're refactoring lookupAgentName, it's a good opportunity to add coverage. A regression here would show agent IDs instead of human-readable names in Slack responses.

Fix: Optional—add a test case that exercises the enrichment path:

it('should enrich agentName from manage API when agentName equals agentId', async () => {
  const { findWorkAppSlackChannelAgentConfig } = await import('@inkeep/agents-core');
  const { fetchAgentsForProject } = await import('../../slack/services/events/utils');

  vi.mocked(findWorkAppSlackChannelAgentConfig).mockReturnValue(
    vi.fn().mockResolvedValue({
      agentId: 'agent-123',
      projectId: 'proj-1',
      agentName: 'agent-123', // Name equals ID, triggers enrichment
      enabled: true,
      grantAccessToMembers: true,
    })
  );
  vi.mocked(fetchAgentsForProject).mockResolvedValue([
    { id: 'agent-123', name: 'My Friendly Agent', projectId: 'proj-1', projectName: 'Project' },
  ]);

  const { resolveEffectiveAgent } = await import('../../slack/services/agent-resolution');
  const result = await resolveEffectiveAgent({ tenantId: 't1', teamId: 'T1', channelId: 'C1' });

  expect(result?.agentName).toBe('My Friendly Agent');
  expect(fetchAgentsForProject).toHaveBeenCalledWith('t1', 'proj-1');
});

Refs: agent-resolution.ts:137-146


✅ APPROVE

Summary: Clean refactor that eliminates code duplication without changing behavior. The consolidation improves maintainability by centralizing internal API call logic in one place. Ship it! 🚀

Discarded (1)
Location Issue Reason Discarded
agent-resolution.ts Error handling delegation no longer explicitly tested Intentional design—the refactor correctly delegates error handling to the shared utility, which already has its own error handling. Not a problem.
Reviewers (3)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-standards 0 0 0 0 0 0 0
pr-review-consistency 0 0 0 0 0 0 0
pr-review-tests 2 0 0 1 0 0 1
Total 2 0 1 1 0 0 1

Note: Standards and consistency reviewers found no issues—this is a well-executed refactor that follows existing patterns.

@github-actions github-actions Bot deleted a comment from claude Bot Feb 24, 2026
@itoqa
Copy link
Copy Markdown

itoqa Bot commented Feb 24, 2026

Ito Test Report ✅

14 test cases ran. 14 passed.

This test run verified the backend refactor in PR #2283 that moves lookupAgentName to delegate to the existing fetchAgentsForProject utility. All tests confirmed that the refactor maintains correct behavior: the Manage UI Slack dashboard loads without errors, the agents list API returns the expected format, unit tests pass with the new mock setup, and edge cases (empty names, empty agent lists, cache eviction, timeout handling, agent not found) are handled gracefully. Code inspection verified proper error handling for malformed JSON, 401/403 responses, network timeouts, race conditions, and the 50-agent limit parameter.

✅ Passed (14)
Test Case Summary Timestamp Screenshot
ROUTE-1 Manage UI loaded successfully at /default/projects via auto-login. Work Apps page rendered correctly. Navigated to Slack dashboard which displayed 'Slack Integration Admin' with empty state. No JavaScript errors or failed API calls. 10:38 ROUTE-1_10-38.png
ROUTE-2 Created project test-project via Manage UI. Called GET /manage/tenants/default/projects/test-project/agents?limit=50 with Bearer auth. Received HTTP 200 with valid JSON format: data array + pagination metadata. 13:11 ROUTE-2_13-11.png
LOGIC-1 Verified via targeted unit test that lookupAgentName correctly enriches agent name from fetchAgentsForProject when agentName equals agentId. All 4 targeted enrichment tests and all 10 existing agent-resolution tests passed. 16:19 LOGIC-1_16-19.png
LOGIC-2 All 10 unit tests in agent-resolution.test.ts passed. TypeScript typecheck (tsc --noEmit) completed with no errors, confirming removed imports cause no regressions. 17:29 LOGIC-2_17-29.png
EDGE-1 Verified via targeted unit test that when fetchAgentsForProject returns an agent with empty name, the name-or-id fallback pattern maps it to agent ID. lookupAgentName returns undefined for empty names, preserving original agentId. 16:20 EDGE-1_16-20.png
EDGE-2 Verified via targeted unit test that when fetchAgentsForProject returns an empty array, lookupAgentName does not crash - agents.find returns undefined, function returns undefined, preserving original agentName. 16:21 EDGE-2_16-21.png
EDGE-3 Code inspection confirms AGENT_NAME_CACHE_MAX_SIZE=500. Cache eviction uses two-phase strategy: first removes expired entries, then if still over limit, removes oldest excess entries. 18:10 EDGE-3_18-10.png
EDGE-4 Code inspection confirms INTERNAL_FETCH_TIMEOUT_MS=10_000 (10s). fetchAgentsForProject uses AbortController with setTimeout for abort, clearTimeout in finally block. Error handling catches exceptions and returns empty array. 18:27 EDGE-4_18-27.png
EDGE-5 Verified via targeted unit test that when fetchAgentsForProject returns agents but the target agent ID is not in the list, lookupAgentName returns undefined gracefully. No crash or error. 16:22 EDGE-5_16-22.png
ADV-1 Code inspection confirms fetchAgentsForProject wraps the entire fetch+json parse in try-catch. If response.json() throws (malformed JSON), the catch block logs via logger.error and returns empty array []. 18:46 ADV-1_18-46.png
ADV-2 Code inspection confirms fetchAgentsForProject checks response.ok; for 401/403 responses, it reads error body, logs warning with logger.warn including status, then returns empty array []. classifyError utility maps 401/403 to AUTH_ERROR. 19:01 ADV-2_19-01.png
ADV-3 Code inspection confirms fetchAgentsForProject creates AbortController with setTimeout at INTERNAL_FETCH_TIMEOUT_MS (10_000ms). On timeout, controller.abort() fires, fetch throws AbortError caught by try-catch which returns []. 19:11 ADV-3_19-11.png
ADV-4 Code inspection confirms lookupAgentName is safe for concurrent calls. JavaScript's single-threaded event loop ensures Map operations are atomic. Concurrent calls with empty cache both call fetchAgentsForProject, but cache writes are idempotent. 19:21 ADV-4_19-21.png
ADV-5 Code inspection confirms fetchAgentsForProject sends ?limit=50 to the agents API endpoint. If the target agent is beyond the 50-agent limit, agents.find returns undefined and lookupAgentName returns undefined - graceful degradation. 19:32 ADV-5_19-32.png
📋 View Recording

Screen Recording

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant