feat: add priorMessages and continuationToken support to detectUnsafe - #39
Merged
Merged
Conversation
detectUnsafe never exposed multi-turn support at all -- no context field for submitting prior turns, and no continuationToken/resetConversation params, despite the API (Tuteliq/api#173) already supporting both on /unsafe. detectBullying/detectGrooming had this; detectUnsafe was left behind. Adds context.priorMessages (ContextInput, new PriorMessage type): idiomatic camelCase, matching every other context field. normalizeContext translates it to the wire's prior_messages key -- the API only recognizes snake_case there. Every other endpoint using ContextInput (the fraud/ coercive-control/distress-signals family, grooming, bullying) picks this up automatically through the same shared normalizeContext call; harmless no-op on endpoints that don't read it server-side. Adds continuationToken/resetConversation to DetectUnsafeInput, and continuation_token/continuation_expires_at/state_source/trajectory_risk/ trajectory/severity_series to UnsafeResult -- mirroring BullyingResult's existing shape exactly, since /unsafe's continuation machinery has always returned these, just never had SDK types for them. Verified end-to-end against a local build of this package linked into the MCP server repo (Tuteliq/mcp) before this PR: clean typecheck across both repos, confirming the whole chain (API -> this SDK -> MCP tool schema) is consistent.
safenestdev
added a commit
to Tuteliq/mcp
that referenced
this pull request
Aug 28, 2026
Unblocks this PR's CI: the previous 2.31.0 dependency predates priorMessages/continuationToken on detectUnsafe (Tuteliq/node#39, published as 2.32.0), which this PR's detect_unsafe changes need. Verified: clean typecheck and full build (UI widgets + server) against the real published package, not just the local link used earlier.
safenestdev
added a commit
to Tuteliq/mcp
that referenced
this pull request
Aug 28, 2026
… fleet-wide (#61) * feat: expose detect_unsafe multi-turn support, document priorMessages fleet-wide detect_unsafe's MCP tool never exposed multi-turn support at all -- no continuation_token/reset_conversation params (unlike detect_bullying, which has always had them, even though the API's /unsafe route has supported continuation_token all along), and no way to submit prior turns for a one-shot whole-conversation call either (Tuteliq/api#173 added context.prior_messages server-side). - contextSchema (shared by detect_bullying/detect_unsafe): adds priorMessages, camelCase to match ageGroup and every other context field. Harmlessly ignored by detect_bullying (no multi-turn content field of its own -- use continuation_token there). - detect_unsafe: adds continuation_token/reset_conversation to the input schema and wires them through to the new @tuteliq/sdk fields; renders the "Conversation risk"/"Conversation state" sections via formatTrajectory/formatContinuation, matching detect_bullying's output exactly. Enriched the tool description to explain both multi-turn paths (priorMessages vs continuation_token) and when to use each. - fraudContextSchema (the 10-endpoint fraud/coercive-control/ distress-signals family): adds priorMessages explicitly. It already passed through via .passthrough(), but an undocumented passthrough field isn't real support -- an LLM reading the tool schema had no way to discover it existed. Now it's named and described like every other parameter, with a note appended to all 11 fraud tool descriptions. - resources.ts: fixed the CONTEXT_FIELDS reference doc, which had gone stale on two counts -- still named the old conversation_history field, and described the wrong shape entirely ({sender, content} instead of the real {role, text, timestamp?}). Depends on Tuteliq/node#<priorMessages-continuationToken PR> for the underlying SDK types -- verified together via a local linked build before this PR (clean typecheck across both repos). This repo's package.json still pins the previous published @tuteliq/sdk version; bump it once that SDK PR is published. * chore: bump @tuteliq/sdk to 2.32.0 Unblocks this PR's CI: the previous 2.31.0 dependency predates priorMessages/continuationToken on detectUnsafe (Tuteliq/node#39, published as 2.32.0), which this PR's detect_unsafe changes need. Verified: clean typecheck and full build (UI widgets + server) against the real published package, not just the local link used earlier. --------- Co-authored-by: safenestdev <safenestdev@users.noreply.github.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.
What
`detectUnsafe` never exposed multi-turn support at all — no `context` field for submitting prior turns, and no `continuationToken`/`resetConversation` params, despite the API (Tuteliq/api#173, and `/unsafe`'s pre-existing `continuation_token` machinery) supporting both. `detectBullying`/`detectGrooming` already had this; `detectUnsafe` was left behind.
Changes
ContextInput.priorMessages(new): idiomatic camelCase, matching every other context field (ageGroup,platform, etc).normalizeContexttranslates it to the wire'sprior_messageskey — the API only recognizes snake_case there. Every endpoint usingContextInput(the fraud/coercive-control/distress-signals family, grooming, bullying) picks this up automatically through the same sharednormalizeContextcall; harmless no-op on endpoints that don't read it server-side.DetectUnsafeInput.continuationToken/resetConversation(new): wired through to the request body, matchingdetectBullying's exact pattern.UnsafeResult: addscontinuation_token,continuation_expires_at,state_source,trajectory_risk,trajectory,severity_series— mirroringBullyingResult's existing shape./unsafe's continuation machinery has always returned these; the SDK just never had types for them.Verification
priorMessages→prior_messageswire translation,continuationToken/resetConversationround-trip).Not yet published to npm — this PR is the code change; publishing is a separate, explicit step.