Conversation
- TextInput becomes a CardChild so a reply can be typed without opening a dialog - report the card's inputs as ActionEvent.values, matching ModalSubmitEvent.values - forward those values on a button's callbackUrl POST, which has no handler to read them - render the label as fallback text wherever a platform cannot draw an input - share one Input.Text mapping between the card and dialog converters - convert emoji placeholders in an input label on the cards subpath, as the adapter does - keep the TextInput builder in its own leaf module so chat/workflow does not bundle the modal builders it never calls - name which adapters show the label and which drop the input, rather than promising a fallback four of them do not implement Signed-off-by: Mohammed Mansoor Ahmed <mansoorahmed.mohammed@gmail.com>
Contributor
|
@mmahmed is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
This branch has not been deployed
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.
Summary
On Teams, collecting a line of text from a user meant opening a dialog. The SDK already had
TextInput, but only as aModalChild— usable behind a Task Module, never on the card itself. So "Approve, and tell me why" cost a second round trip and a whole dialog surface for one sentence.This makes
TextInputaCardChildand plumbs what was typed back to the handler.chat—TextInputjoins theCardChildunion, so it can sit on a card next to the buttons that submit it.ActionEventgainsvalues?: Record<string, string>, the card's own input values keyed by input id, deliberately the same shape asModalSubmitEvent.valuesso a card action and a dialog submit are read the same way. It is optional and absent on platforms with no card inputs, so no existing call site changes. The builder and its types live in a new leaf module,packages/chat/src/text-input.ts, imported by bothcards.tsandmodals.ts— see Bundle below for why.@chat-adapter/teams— renders it as an Adaptive CardInput.Textthrough the sametextInputToAdaptivethe dialog converter uses, so an input looks the same on a card as in a Task Module (modals.tsdropped its private copy). The dependency-free@chat-adapter/teams/cardssubpath emits the same element and gains no dependency (+336 B).callbackUrlPOST now carriesvalues, so a flow driven by webhooks rather than anonActionhandler still receives what was typed.JSON.stringifydrops it when the card had no inputs.Reading the inputs back out
Teams merges the card's input values into the same flat
Action.Submitobject the adapter uses for its own bookkeeping.RESERVED_SUBMIT_KEYS(actionId,value,msteams) names those keys andcardInputValues()reads everything else, keepingstringandnumber(numbers stringified exactly asparseDialogSubmitValuesdoes). All four readers — plain actions, adaptive-card invokes, dialog opens and the auto-submit fan-out — share that one set, because if two of them skipped different keys an input would be reported down one path and silently dropped down another.Consequence worth knowing, now documented on the Teams adapter page: an input whose id is
actionId,valueormsteamsis indistinguishable from the adapter's own key and is dropped.valueis the sharp one — it also overwrites the button's payload, which is where acallbackUrltoken rides, so such a button would stop firing its callback. There is a test pinning this.Behavior change on the auto-submit path
fanOutAutoSubmitpreviously filtered onlyactionIdandmsteams; it now filters the shared reserved set, which addsvalue. An auto-submit input whose id is literallyvalueused to fan out as its own action and no longer does. Deliberate — it is what makes all four readers agree — but it is a narrowing, so calling it out.Platform fallback
A new member on the
CardChildunion needs three separate fallback-text switches updated in this repo, and ~15 converters inherit one of them:cardChildToFallbackText(chat/src/cards.ts),BaseFormatConverter.cardChildToFallbackText(chat/src/markdown.ts) and the plain-object copy inadapter-teams/src/cards-primitives. All three handletext_inputby returning the label, andadapter-shared/src/card-utils.tspicks it up through its delegatingdefault:.That still does not give every platform a fallback, and the docs now say so rather than promising one: Slack, Google Chat, Discord, GitHub and Linear reach the core helper through a
default:arm and show the label; WhatsApp, Messenger, Twilio and X return[]/nulland omit the input entirely. Making those four render the label would mean touching four packages this PR otherwise does not, so it is left to their maintainers and the docs, the API reference and the changeset all name the split.Bundle
Sharing the builder naively — a value import from
cards.tsintomodals.ts— mergedmodals.tsinto the same pre-bundled chunk ascards.ts, so the publishedchat/workflowentry shipped and executed the whole modal builder (Modal,DateInput,Select, …) while using onlyActions,Button,CardandText: +6,757 B raw, ~1.2 KB gzip, +28% of that subpath's closure. Hence the leaf module. The builtchat/workflowchunk now contains zero modal builders, and the mainchatentry is unchanged either way.Semver
CardChildgained a member, shipped asminor, matching the precedent set whenChartElementjoined the same union. Source-breaking only for an out-of-repo adapter that exhausts the union with anevercheck; every in-repo converter reaches it through adefault:. The changeset says so.Test plan
pnpm check,pnpm typecheck(44/44),pnpm knip,pnpm konsistent,pnpm build(27/27): clean.pnpm --filter @chat-adapter/teams test: 402 pass. New coverage for theInput.Textmapping on both subpaths;valueson message actions, adaptive-card invokes and the auto-submit fan-out; reserved-key collision; non-string/number values discarded; and the label fallback.pnpm --filter chat test:TextInputsurvivesCard(), the JSX runtime andfromReactElement, and all three fallback switches are covered.toMatchObject, which passes even when the primitives converter drops a field, and keyed on:tada:— a placeholder neither converter transforms, so it could not have caught drift.Three suites fail on this machine and fail identically on a clean
f034cd27checkout with this branch absent, so they are not from this change:create-chat-sdk—pnpm pack --dry-runexceeds the 5s vitest timeout under Turbo's parallel load; passes standalone in 3s.@chat-adapter/gmail— twoboundary.test.tstimeouts, same cause.@chat-adapter/integration-tests—gmail has a custom OG image(1 of 1531); genuinely red onmain.Excluding those three,
pnpm turbo testis 47/47 green.Checklist
git commit -s)pnpm validatepasses — every stage green except the three suites above, which fail the same way onmainwithout this branch