fix: Handling with build - #2
Closed
drobnikj wants to merge 1 commit into
Closed
Conversation
matyascimbulka
pushed a commit
that referenced
this pull request
Sep 5, 2025
* Component batch #2 * pnpm
drobnikj
pushed a commit
that referenced
this pull request
Sep 3, 2026
…HQ#21493) * feat(slack_v2): eval-driven fixes for the MCP tool surface Iterated against the MCP eval suite (pd-connect-eval-monster/evals/slack_v2). Suite went 23/35 -> 33/35 on Sonnet 5 (pass^2); every change below is tied to a specific red-to-green flip or a measured payload reduction. - list-channels: evals #2/#10/#11/#16/#19/PipedreamHQ#35 all failed the same way — the action returned every field of every channel with numPages defaulting to 1, so a 62-channel workspace produced ~55k chars, blew the 25k-token MCP ceiling, and the model was handed a file path instead of data (#2 burned all 20 turns re-calling it). Added an additive `fields` projection, a `cursor` prop, and `has_more`/`next_cursor` so truncation is visible instead of silent. Payload 55k -> 5.9k chars; all six evals pass. [minor] - slack_v2.app.mjs: `assistantSearch` called `sdk().apiCall()` directly — the one path in the app that bypassed `_withRetries` — while the client is built with `rejectRateLimitedCalls: true`, so every 429 rejected instantly. 8 of 12 search calls errored in one run (#24/#26/#27). Routed through `_withRetries`. Also adds `resolveUserId` (id / email / display name) for the invite fix below. - delete-message: eval #20 ("post a note then take it back") failed every run with cant_delete_message — post-message sends no `as_user` so it posts as the USER, while this action defaulted `as_user: false`, which routes to the BOT token. A message just posted could never be deleted. Now retries with the other identity on cant_delete_message; the default is unchanged, so existing workflows are unaffected. Description also gained confirmation guidance for the destructive path (PipedreamHQ#33). [minor] - invite-user-to-channel: eval #10 failed with user_not_found — the agent passed the email from the prompt. Now resolves user id / email / display name, and the channel by name. [minor] - get-channel-details, list-members-in-channel, set-channel-topic: every AI-optimized action in this app resolves channel NAMES server-side and these did not, so agents that read "#seinfeld-general" from a prompt got channel_not_found (#19, #22) or a bare internal_error (#10). All three now use resolveChannelId. [minor] - get-channel-history, get-thread-replies: outputs measured at 17k chars average (worst 49k) and 25k average respectively — every call burned that much of the agent's context. Added the same additive `fields` projection. [minor] - get-user-details, get-current-user: two tools answer "who am I" and the agent chose the legacy one in 10/10 trials (#1). Descriptions now differentiate them. NOTE: this did NOT change routing — the agent still picks get-current-user. The actual fix is removing one of the two from the /v3 component allowlist; these edits only make the intended split legible. [patch] App package.json bumped 0.6.1 -> 0.7.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(slack_v2): satisfy CI — lint formatting, dependent version bumps, UI-centric copy - Lint Code Base: 9 errors, all in the files this branch touches and all formatting. Broke the `.split().map().filter()` chains across lines (newline-per-chained-call), split the `has_more` spread ternary and its object literal (multiline-ternary, object-curly-newline), and expanded the `users.list` destructure in resolveUserId (object-curly-newline). - Ensure component commits modify component versions: this branch edits slack_v2.app.mjs, so every component importing it needs a version bump. Patch-bumped the 48 actions/sources that were not already versioned in the previous commit. - Removed UI-centric wording from two descriptions, which read oddly for an agent calling the tool over MCP and contradicted the resolution behaviour added in the previous commit: - get-channel-details: "by selecting it or providing an ID" -> "specified by ID or by name" (it had claimed both "selecting it" and "Accepts a channel ID or NAME" in the same sentence). - set-channel-topic: "a selected channel" -> "a channel, specified by ID or by name". Verified locally with ESLint 9 against the repo's own rule options for the three failing rules: 0 violations across components/slack_v2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(slack_v2): restore comma-separated users on invite, fix delete identity fallback invite-user-to-channel: conversations.invite documents `users` as comma-separated and the prop is a plain string, so "U01ABCDEF,U02GHIJKL" was a working input. The new resolveUserId() matches neither the ID regex (no comma) nor the email regex, then falls through to an exhaustive paged users.list scan that cannot match, and throws. Adds resolveUserIds() (plural), which splits on commas — or accepts an array — resolves each token independently, and rejoins. An all-IDs input still makes zero extra API calls, so the common path is unchanged in cost as well as result. delete-message: makeRequest() routes to the bot token only on `as_user === false`, so `!this.as_user` made the retry a no-op whenever as_user arrived nullish — undefined and true both route to the user token, so it retried as the identity that had just been refused. Changed to `this.as_user === false`. Attempt 1 still passes the configured value verbatim. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(slack_v2): reattach resolveChannelId's JSDoc to its function resolveUserId/resolveUserIds were inserted between resolveChannelId's doc comment and resolveChannelId itself, leaving two stacked doc blocks above resolveUserId and no doc on resolveChannelId. Comment move only; no code change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(slack_v2): move the fields projection into common/utils.mjs Addresses review feedback on PipedreamHQ#21493: `pickFields` was copy-pasted identically into get-channel-history, get-thread-replies and list-channels. Moved to components/slack_v2/common/utils.mjs, alongside the CSV-or-array `fields` normalizer that was duplicated in the same three places — both halves of one feature, so splitting them across files would just invite the next divergence. `projectFields(records, fields)` composes the two and keeps the additive contract: with no `fields`, it returns the ORIGINAL array, so a caller that omits the prop gets exactly what these actions have always returned. Behavior-identical to the three removed copies, verified against them across undefined / empty array / empty string / array / CSV / CSV-with-spaces / unknown field / all-unknown inputs, including array identity on the no-fields path. No version bumps: all three components are already ahead of master on this branch, so the PR diff still shows a version change for each. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(slack_v2): address review feedback on delete-message, resolveUserId, invite-user-to-channel - delete-message: only retry with the other identity when a bot token exists, since otherwise both attempts hit the same token and just repeat the error. - resolveUserId: scan all users.list pages and require an exact, unambiguous name match; throw ConfigurationError instead of silently picking the first. - invite-user-to-channel: treat already_in_channel as success only for a single user; bulk invites are now sent per-user with individual results so failures aren't hidden behind a successful summary. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(slack_v2): guard invite-user-to-channel against empty resolved user list resolveUserIds() returns "" when every comma-separated token is blank, and "".split(",") yields [""] rather than [], which slipped through the single-user path and sent an empty users value to Slack. Filter empty tokens and throw ConfigurationError when none remain. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(slack_v2): resolve channel name in delete-message, treat self-invite as no-op - delete-message now calls resolveChannelId() before deleting, like every other AI-optimized action in this app. Previously it passed `conversation` straight through, so a channel NAME (rather than ID) failed with channel_not_found. - invite-user-to-channel: Slack refuses to let an identity invite itself (cant_invite_self) before it would ever reach an already_in_channel check. Treat that the same way — a no-op, not an error — since to the caller it means the same thing: the user has no further action needed on that channel. Found via eval-driven regression testing on PR PipedreamHQ#21493. * chore(slack_v2): revert version bumps on delete-message, invite-user-to-channel Keep at 0.2.0/0.1.0 rather than bumping per fix. --------- Co-authored-by: Dylan Sather <Dylan Sather> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Michelle Bergeron <michelle.bergeron@workday.com> Co-authored-by: michelle0927 <michelle0927@users.noreply.github.com>
drobnikj
pushed a commit
that referenced
this pull request
Sep 3, 2026
…1826) * feat(dappier): AI-optimized Dappier action set for MCP (real-time search, recommendations, analytics) Initial AI-optimized Dappier components for the MCP tool surface, covering issue PipedreamHQ#21660 (real-time web search, AI content recommendations, data-model querying) plus the four Analytics API endpoints. Iterated against the MCP eval suite (evals/dappier) — 9/10 green on Sonnet 5 (trials: 1); the one failure is an upstream HTTP 500 on POST /app/v2/search, not a component defect. agent-audit: 100/100. - search-real-time-data (new, 0.0.1): real-time web/data search via a Dappier AI model (am_ id); returns a synthesized answer. Eval #9 passes. - get-ai-recommendations (new, 0.0.1): AI-ranked content recommendations for a data model (dm_ id); optional additive `fields` projection trims large article payloads. Eval #10 blocked by an upstream 500 (server-side). - get-ask-ai-analytics (new, 0.0.1): aggregate Ask AI widget analytics. Evals #1/#4/#5 pass. - get-ask-ai-logs (new, 0.0.1): raw Ask AI conversation logs with page/limit pagination + paging guidance. Evals #2/#6 pass. - get-sponsored-conversations-analytics (new, 0.0.1): sponsored-conversation (ad campaign) analytics. Eval #7 passes. - get-session-intelligence (new, 0.0.1): session intent/topic breakdowns. Evals #3/#8 pass. - dappier.app.mjs: shared analytics prop definitions + GET request methods. - common/utils.mjs: validateDateRange (365-day cap) + pluckFields projection helper. - common/constants.mjs: analytics interaction types, range + page-size bounds. App package.json bumped 0.0.1 -> 0.1.0 (minor -- new actions). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(dappier): add trailing newline to package.json (eol-last) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(dappier): address review — numArticlesRef max, own-prop projection, date default wording - get-ai-recommendations: numArticlesRef description said max 1000 but schema is max 100; corrected the doc. - common/utils.mjs: pluckFields now uses Object.hasOwn so a requested field name that collides with an inherited prop (e.g. toString) is not copied; own result fields still are. - dappier.app.mjs: reworded startDate default from the brittle/off-by-one '7 days before today' to 'the last 7 days (UTC), i.e. today and the six prior days', matching observed API behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(dappier): resolve one-sided analytics date windows before sending Verified against the live API: omitting either start_date or end_date makes Dappier reset BOTH bounds to its default trailing-7-day window, silently discarding the bound the caller supplied — so a one-sided range returned the wrong period. resolveDateRange() now fills the missing bound (missing end -> today UTC; missing start -> 6 days before the end) and always sends both, so a supplied bound is honored; both-omitted still defers to the API default. All four analytics actions use it; start/end prop docs updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(dappier): match analytics date-range cap to the API (inclusive days) Probed the live API: it accepts a 364-day start/end difference (365 inclusive days) and returns 400 at a 365-day difference (366 inclusive days). validateDateRange used '> 365 days difference', so a 365-day-difference window slipped past the fail-fast and hit a raw API 400. Now counts inclusive days (difference + 1) and caps at 365, matching the API exactly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(dappier): note session_intelligence wrapper in get-session-intelligence description The API nests all six breakdowns under a single top-level `session_intelligence` object (verified live). The description listed them as if they were root keys, so an agent would look for them at the root and miss the `session_intelligence.` prefix. Description-only; no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(dappier): use camelCase widgetId in session-intelligence example The example told the agent to pass `widget_id`, but the input prop is `widgetId` (run() maps it to the `widget_id` query param). Match the example to the prop the agent actually sets. Description-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(dappier): use camelCase prop names in remaining action examples Same fix as get-session-intelligence, applied to the sibling descriptions: the agent-facing 'Example:' hints used API param names (start_date, end_date, campaign_id, data_model_id) instead of the camelCase input props (startDate, endDate, campaignId, dataModelId). API-mapping mentions stay snake_case. Description-only; no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(dappier): camelCase input-guidance for model-id props The 'Provide a ...' input guidance used API param names — get-ai-recommendations said 'Provide a data_model_id' (prop is dataModelId) and search-real-time-data said 'Provide an ai_model_id' (prop is aiModelId). Use the camelCase input keys; snake_case is retained only where describing the API request mapping (query param / path template). Description-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Adding missing dependencies field --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: GTFalcao <gtfalcao96@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WHY