All notable changes to the nope-net package. The format follows
Keep a Changelog; versions follow
Semantic Versioning.
Patch release from the 4.0.0 newcomer report. No public signature is changed or removed.
NopeError.body: the response parsed into a dict when it was a JSON object, elseNone.response_bodystays the raw text. Every error now hasdetails({}outsideNopeValidationError), soerr.detailsnever raisesAttributeError.VerifiedWebhook.delivery_id, theX-NOPE-Delivery-IDheader.event_idon that object keeps the same value and is deprecated in favour ofdelivery_id; the payload's own id stayspayload.event_id.WebhookPayloadUnion, the plain union of the four payload models.Webhook.verify()andparse_webhook_payload()return it instead ofAny, andVerifiedWebhook.payloadis typed with it.DetectCountryResponseshowsdetectedin its repr and str.- README paragraphs on client-side errors and
codepresence, the Ocular per-turn contract (0-based turn indices,trajectory_stridedefault 3,signals_by_axiskeys, the two indexings insidetrajectory_shape, no shape on the demo route), third-party risk ontext=input, andSignpostResponse.primary/secondary.
- Client-side validation and demo-mode refusals raise
NopeValidationError(status_codeNone;codeinvalid_requestornot_available_in_demo) instead of a bareValueError. The class now also inherits fromValueError, soexcept ValueErrorkeeps working and the README'sexcept NopeValidationErrorladder catches them. messagesonevaluate(),screen()andocular()is typedOptional[Sequence[Union[Message, Mapping[str, Any]]]], and the Oversightconversationandconversationsparameters accept mappings and sequences.mypy --strictrejectedlist[dict[str, str]],list[Message]and tuples before (listis invariant). Tuples and read-only mappings reach the wire as JSON arrays and objects.mypy src tests/typingis the gate.- Docstrings and the README describe current API behaviour instead of
internal ticket references: the demo evaluate route reads
config.country, database-backed resources carryidon every route,bot_contextreaches the Oversight analysis prompt, and trajectory roles areuserorassistant. Thescreen()docstring names the 2027-01-01 sunset the runtime warning already carried. - Oversight ingest documentation now states the deployed 5 MB body limit.
Analyze documentation distinguishes retained event metadata from the
conversation and full-result records created by ingest. Signpost's
urgentoption is consistently described as a ranking hint. - Package metadata identifies the SDK as beta, matching the service status.
Realigns the SDK with the API at commit 73c477c. Every v1 response model is now
pinned to a sanitized live capture under tests/fixtures/ (the deprecated
/v0/screen models have none), and the two
versions that never reached PyPI (2.3.1, 3.0.0) are folded into this release.
The preceding published version was 2.3.0.
Evaluate
EvaluateResponse.resourcesis a typedEvaluateResources(primary,secondary) ofEvaluateResource(CrisisResourcepluswhy). Attribute access (result.resources.primary.phone) is the supported surface;result.resources["primary"]["phone"]and.get()keep working as a compatibility shim.Risk.subjectisLiteral["self", "other"]. The classifier'sunknownis mapped toselfbefore it reaches the wire.Risk.confidenceandRisk.subject_confidenceare removed (v0 only).rationale,speaker_severity,speaker_imminenceandshow_resourcesare required onEvaluateResponse.ResponseMetadatais renamedEvaluateMetadata;access_levelandis_adminare removed;modelandtry_endpointare added.- Removed from
EvaluateResponse:communication,summary,legal_flags,protective_factors,confidence,agreement,crisis_resources,widget_url,recommended_reply,resource_query,resource_tags,reflection,filter_result. Only/v0/evaluateemits them and no SDK method calls that route. - Removed models:
Summary,CommunicationAssessment,CommunicationStyleAssessment,LegalFlags,IPVFlags,SafeguardingConcernFlags,ThirdPartyThreatFlags,StalkingFlags,ProtectiveFactorsInfo,FilterResult,RecommendedReply,PreliminaryRisk; literalsCommunicationStyle,EvidenceGrade. evaluate()no longer acceptsuser_contextorproposed_response(nothing on/v1/evaluateread them).EvaluateConfigiscountry,include_resources,conversation_id,end_user_id. The keysuser_country,locale,user_age_band,policy_id,return_assistant_reply,assistant_safety_mode,use_multiple_judgesandmodelsare removed. In demo mode the client sendsuser_countrymirroringcountryfor the try route.evaluate()validates messages client-side: non-empty, at most 100, roleuserorassistant.CrisisResource:sourceremoved;resource_kindno longer includesdirectory. Addedid,country_codes,subdivision_codes.
Screen (deprecated, kept)
ScreenResponse.resourcesisScreenCrisisResourceswithprimary: CrisisResourceandsecondary: List[CrisisResource].ScreenCrisisResourcePrimary,ScreenCrisisResourceSecondary,ScreenDisplayTextandScreenDebugInfo.raw_responseare removed.ScreenRisk.subjectkeeps the three-valueScreenRiskSubjectthe v0 route still emits.
Oversight
oversight_analyze(conversation, *, bot_context=None, config=None, behaviors=None).conversationis positional.configisOversightAnalyzeConfig(strategy,mode,include_raw_xml,model);behaviorsisOversightBehaviorFilter(enabled,disabled,min_severity,categories).enabledanddisabledboth non-empty raiseValueError, as does an invalidmin_severity.- In demo mode
oversight_analyzereturnsOversightDemoAnalyzeResponse(mode,result,try_endpoint); authenticated calls returnOversightAnalyzeResponsewithstrategyandstrategy_reasonrequired. The old combined model with optionalmode/strategyis gone. OversightAnalysisResult.summary,pattern_assessmentandmodel_usedare optional (fast mode omits the first two).TruncationWarningis{type, details}(was{type, message}).oversight_ingestaccepts up to 300 conversations (was 100).- Turn numbers are documented as 1-based.
Ocular
- Demo mode routes to
/v1/try/ocularand returnsOcularDemoResponse(addsheadsanddetail). 3.x sent demo clients to/v1/ocularwith no key, which the API rejects. OcularAxis.levelis the five-valueOcularLevelliteral (nonot_applicable).
Signpost
signpost(country, *, config=None, scopes=None, populations=None, subdivisions=None, limit=None, urgent=None):countryis positional, filters are accepted at the top level (the form the README showed and 3.x rejected withTypeError) or underconfig.signpost_smart(country, query, *, config=None)withSignpostSmartConfig(scopes,populations,limit);urgentremoved (never sent).- Response models renamed:
SignpostResponse,SignpostSmartResponse,SignpostByIdResponse,SignpostCountriesResponse,SignpostConfig. TheResources*names remain as aliases of the same classes. SignpostSearchResultis declared explicitly from the search wire (pluralservice_scopes,populations,resource_type,contacts, nullable strings) and no longer subclassesCrisisResource.SignpostSearchTimingfields are required.resources(),resources_smart(),resource_by_id()andresources_countries()take the same arguments as theirsignpost*twins and warn with the 2027-01-01 sunset.
Webhooks
Webhook.verify()returns one ofEvaluateAlertPayload,OversightAlertPayload,OversightIngestionCompletePayload,TestPingPayload(discriminated onevent). The 3.xWebhookPayloadmodel with therisk.elevated/risk.criticalevents is gone; it rejected every event the API sends.WebhookEventTypeisevaluate.alert | oversight.alert | oversight.ingestion.complete | test.ping.WebhookRiskSummary.primary_concernsisstr | List[str].- The dict path of
verify()andsign()serialises with UTF-8 intact (ensure_ascii=False); 3.x failed verification on any non-ASCII byte.
Errors
- Every error carries
code(machine string) andmessage(sentence) separately. In 3.x the machine code replaced the message on 402, 429 and 503. - New classes:
NopeInsufficientBalanceError(402),NopeNotFoundError(404),NopeServiceUnavailableError(503, aNopeServerError). - 413 maps to
NopeValidationError;NopeValidationError.detailscarries the body extras. A 403 carryingupgrade_urlmaps toNopeFeatureErrorwithfeature="paid_plan". NopeServerError.retry_afteris set when the response carries one.- Error constructors take keyword-only extras.
Package
__version__is4.0.0and the User-Agent isnope-python/4.0.0(3.x sentnope-python/0.1.0).pytest-httpxis no longer a dev dependency.
- Automatic retries on 429 and 503 (
max_retries, default 2), honouringRetry-Afterandretry_after_seconds, capped at 30 seconds per wait. Never on timeouts, connection failures or other 5xx. client.last_response_meta:rate_limit(X-RateLimit-*) andbalance(X-Balance-Mills,X-Cost-Mills) from the last response.transport=andsleep=constructor options for dependency injection.client.webhooks:create,list,get,update,delete,regenerate_secret,test,events.client.billing:balance,usage,usage_history,pricing,topup.Webhook.verify_request(body, headers, secret)returningVerifiedWebhook(payload, event, delivery id, webhook id);parse_webhook_payload().- Ocular request fields
per_turn,trajectory_stride,user_id,session_id,agent_id; responsetrajectory[].signals_by_axisandtrajectory_shape. - Oversight result fields
mode_used,filter_applied,windows(WindowAnalysiswithmessage_rangeandconversation_turn_range),concern_progression,peak_concern,final_concern,inflection_points,context_for_next_window,narrative_summary;AggregatedBehavior.recommendation;OversightConversationMetadata.bot_context. - Generated literals
OversightBehaviorCode(91),OversightBehaviorCategory(14),ServiceScope(93),Population(26) with matching tuples, produced byscripts/generate_taxonomy.pyfrom the API source. signpost(..., subdivisions=...);SignpostSmartResponse.messageandtry_endpoint;detect_country(country_hint=...);DetectCountryResponse.subdivision_code,subdivision_nameand the deriveddetected.EvaluateMetadata.model,try_endpoint;CrisisResource.id,country_codes,subdivision_codes.- Offline contract tests over every live fixture, a unit suite on an
injected
httpx.MockTransport, and an opt-in live suite (NOPE_LIVE=1 pytest -m live).
- Demo-mode
evaluatenow reaches the country you asked for: the try route readsconfig.user_country, which the client mirrors fromcountry. - Fast-mode Oversight responses and ingest responses with truncation warnings parse.
- Search results, detect-country misses and empty smart pools parse into typed models.
- Removed
client.steer()and the Steer types; the route was retired.
- Removed statutory compliance claims and serving-implementation copy from docstrings and the README.
- Added
signpost_search()(vector semantic search) and the Steer client. - Ocular response shape synced with the customer wire.
Earlier history is on the GitHub releases page.