- All
- Python
- JavaScript
- Moss CLI
- Portal
- API
Added
MossInference.taskswraps the gateway’s Tasks API: an agent reaches a goal in a browser within time and dollar limits.createqueues a task fromgoal,environment,output_schema,limits,model,effortandmetadata, and sends only the arguments given, so the gateway picks the defaults.retrieveandcancelreturn theTask, andwaitpolls it everypoll_intervalseconds (2 by default) until it is neitherqueuednorrunning, withintimeout, and returns afailedtask too.runcreates a task and waits for it in one call.tracereturns the agent’s record,files.listaTaskFileList, andfiles.contentaTaskFileContentwith the bytes andcontent_type.Task[T]typesresult.output, andTaskUsage.rawkeeps every field the gateway sends.createsends anIdempotency-Key, a new one per call or the one in that call’sextra_headers, and the same one on every retry, so a retried create never starts a second task. Task calls never sendapi_key, and never retry a 409, which the files routes send until a task ends.Taskhasfiles_expire_at, when the gateway removes the trace and files.InferenceError.task_idnames the task of an error ofwaitorrun, so a task thatruncreated can still be read or cancelled.moss.inference.tasksmakes the same calls on a client built from the environment.MossInferenceSyncmakes thetaskscalls without an event loop. It runs them on an event loop in a daemon thread of its own, whichclose()or the end ofwithstops after cancelling the calls under way.
Added
MossInference.tasks, typed by theTasksinterface, wraps the gateway’s Tasks API: an agent reaches a goal in a browser within time and dollar limits.createqueues a task fromTaskCreateParams(goal,environment,output_schema,limits,model,effort,metadata) and sends only the fields given, so the gateway picks the defaults.retrieveandcancelreturn theTask, andwaitpolls it everypollInterval(2000 ms by default) until it is neitherqueuednorrunning, withtimeoutandsignalinTaskWaitOptions, and resolves onfailedtoo.runcreates a task and waits for it in one call.tracereturns the agent’s record,files.listaTaskFileList, andfiles.contentaTaskFileContentwith the bytes andcontentType.Task<Output>typesresult.output.usage(TaskUsage) keeps every field the gateway sends.createsends anIdempotency-Key, a new one per call or the one in that call’sheaders, and the same one on every retry, so a retried create never starts a second task. Task calls never sendapiKey, and never retry a 409, which the files routes send until a task ends.Taskhasfiles_expire_at, when the gateway removes the trace and files.InferenceError.taskIdnames the task of an error ofwaitorrun, so a task thatruncreated can still be read or cancelled.inference.tasksis thetasksof a client built from the environment. See Browser tasks in the README.
responses.createrejects a body number that JSON cannot carry, such asNaNorInfinity, withinvalid_request_error, where it sentnull.
Added
MossInference.tasks, typed by theTasksinterface, wraps the gateway’s Tasks API: an agent reaches a goal in a browser within time and dollar limits.createqueues a task fromTaskCreateParams(goal,environment,output_schema,limits,model,effort,metadata) and sends only the fields given, so the gateway picks the defaults.retrieveandcancelreturn theTask, andwaitpolls it everypollInterval(2000 ms by default) until it is neitherqueuednorrunning, withtimeoutandsignalinTaskWaitOptions, and resolves onfailedtoo.runcreates a task and waits for it in one call.tracereturns the agent’s record,files.listaTaskFileList, andfiles.contentaTaskFileContentwith the bytes, ready for aBlob, andcontentType.Task<Output>typesresult.output.usage(TaskUsage) keeps every field the gateway sends. Task calls go under thebaseURLpath when there is one, with the client’s credentials, timeouts and retries, but never retry a 409, which the files of an unfinished task answer, and never sendapiKey.files_expire_aton aTaskis when the gateway removes its trace and files, 7 days after it ends, after which they reject with a 410files_expired. Once the task exists, everyInferenceErrorofwaitandrunnames it intaskId. Each create sends anIdempotency-Key, a new one per call or the caller’s in the call’sheaders, never one from the client’s, and the same one on every retry. The gateway answers a repeated key with the same body, within 24 hours, with the task it created, so a retried create never starts a second task. To retry a create yourself, pass your own key. See Browser tasks in the README.
responses.createrejects a body number that JSON cannot carry, such asNaNorInfinity, withinvalid_request_error, where it sentnull.
Added
Moss.Inference.Tasksruns browser tasks: an agent works toward a goal in a browser on Moss, within time and dollar limits.run/3queues a task and returns it once it ends, andcreate/3,retrieve/3,cancel/3,wait/3,trace/3andMoss.Inference.Tasks.Files.list/3andcontent/4do each step. Each returns{:ok, value}or{:error, %Moss.Inference.Error{}}, and uses the client’s credentials,MOSS_INFERENCE_URL, timeouts and retries, but never its:api_key, and no task call goes again after a 409, which the files of an unfinished task return.create/3sends only the fields you give. Each create sends anIdempotency-Key, a new one per call or its:idempotency_keyoption, and the same one on every retry. The gateway answers a repeated key with the same body, within 24 hours, with the task it created, so a retried create never starts a second task. To retry a create yourself, pass your own key.wait/3andrun/3poll every:poll_interval,2_000ms by default, until the task is neitherqueuednorrunning, and return afailedorcancelledtask as{:ok, task}. Their:timeoutlimits the wait, each poll included, and past it they return a"timeout"error while the task goes on. Once the task is queued, every error they return has its id in thetask_idfield ofMoss.Inference.Error.- A task is a
Moss.Inference.Taskstruct withresult,verification,usageanderrorstructs.files_expire_atis when the gateway removes the trace and files, 7 days after the task ends, after which they return a 410files_expirederror.rawholds the task as the gateway sent it, andusage.rawevery usage field, such as"browser_minutes".Moss.Inference.Tasks.Files.content/4returns a file’s bytes andcontent_type, and never writes or opens the file.
Added
client.taskswraps the gateway’s Tasks API: an agent reaches a goal in a browser within time and dollar limits.runcreates a task and waits until it ends.createqueues one fromgoal,environment(.browser(startURL:liveView:)),outputSchema,limits(TaskLimits),model,effortandmetadata, and sends only the fields given, so the gateway picks the defaults.retrieveandcancelreturn theMossTask, andwaitpolls it everypollInterval:seconds, 2 by default, until it is neitherqueuednorrunning.runandwaittake atimeout:for the whole wait and return afailedtask too.tracereturns the agent’s record asJSONValue,files.listaTaskFileList, andfiles.contentaTaskFileContentwith the bytes andcontentType.TaskResult.decodeOutput(_:)decodesoutputas your type.TaskUsagekeeps every field the gateway sends inraw, andMossTask.filesExpireAtis when the gateway removes the trace and files, 7 days after the task ends, after which they throw a 410files_expired. Each create sends anIdempotency-Key, a new one per call oridempotencyKey:, and the same one on every retry. The gateway answers a repeated key with the same body, within 24 hours, with the task it created, so a retried create never starts a second task. To retry a create yourself, pass your own key. Task calls retry asresponsesdoes but never after a 409, which the files of an unfinished task throw, and never send the provider key. Once the task exists, everyInferenceErrorofwaitandrunnames it intaskId. See Browser tasks in the README.
sdkVersion: 0.30.0.Added
- Browser tasks.
MossInference.tasksgives an agent a goal to reach in a browser, within time and dollar limits.runcreates a task and waits until it ends.createreturns itqueued, andwaitpolls it everypollIntervalMs, 2 s by default, within its owntimeoutMs, and returns afailedorcancelledtask too.retrieve,cancel,trace,files.listandfiles.contentread or stop a task.Tasktypes every field of the gateway’s task and keeps the whole JSON inraw, andfilesExpireAtis when the gateway removes its trace and files, 7 days after it ends, after which they throw a 410files_expired. Each create sends anIdempotency-Key, a new one per call oridempotencyKey, and the same one on every retry. The gateway answers a repeated key with the same body, within 24 hours, with the task it created, so a retried create never starts a second task. To retry a create yourself, pass your own key. Task calls retry asresponsesdoes but never after a 409, which the files of an unfinished task throw, and never sendapiKey. Once the task exists, everyInferenceErrorofwaitandrunnames it intaskId.
Added
moss_inference_tasks_create,moss_inference_tasks_run,moss_inference_tasks_retrieve,moss_inference_tasks_cancel,moss_inference_tasks_wait,moss_inference_tasks_trace,moss_inference_tasks_files_listandmoss_inference_tasks_files_contentcall the gateway’s Tasks API, where an agent works toward a goal in a browser within time and dollar limits. Tasks go in and come back as JSON text. A create sends the request as given. Each create sends anIdempotency-Key, a new one per call or theidempotency_keyof the call options, and the same one on every retry. The gateway answers a repeated key with the same body, within 24 hours, with the task it created, so a retried create never starts a second task. To retry a create yourself, pass your own key. Task calls go again asmoss_inference_responses_createdoes, but never after a 409, which the files of an unfinished task return. A task’sfiles_expire_atis when the gateway removes its trace and files, 7 days after it ends, after which they fail with a 410files_expired.moss_inference_tasks_runcreates a task and waits for it. It andmoss_inference_tasks_waitpoll everypoll_interval_ms, 2000 by default, until the task is neitherqueuednorrunning, give each task to aMossInferenceTaskFncallback that can stop them, and fail with the typetimeoutpast theirtimeout_mswithout cancelling the task. Each poll takes the client’stimeout_ms, or the time left in the wait when that is shorter.moss_inference_tasks_files_contentreturns a file’s bytes, freed with the newmoss_free_bytes, and itsContent-Type. No task call sendsapi_key.MOSS_INFERENCE_API_VERSIONis 4.
API
Changed
- Moss Inference searches only the indexes a call names, in
X-Moss-Indexesorindexesin the Moss SDKs. A call that names no index is plain inference, with no search and no retrieval fee. It used to search every index of the project. See Ground answers in your indexes.
Portal
Moss Inference beta
- New Moss Inference page and sidebar card. On the Developer plan, request private beta access, then share your invite link to move up the waitlist; the page shows your place and how many people joined through your link.
- On paid plans, the page and card offer Talk to an engineer, and an invite page shares your link without a waitlist rank.
Changed
- Breaking change:
MossInference.responses.createreplaceschat.completions.create, in the shape of OpenAI’s Responses API, and calls/responsesunder the base URL. It takesinput, a string or a list of items, andinstructionsin place ofmessages, plus typedmax_output_tokens. Function tools are flat. Withoutstream=Trueit returns aResponse, whoseoutputholdsResponseOutputMessage,ResponseFunctionToolCallandMcpCallitems and whoseoutput_textjoins the text. With it, it returns aResponseStreamofResponseStreamEvents, such asresponse.output_text.delta, that ends afterresponse.completedorresponse.incomplete, andget_final_response()returns the whole response. A tool call’s result goes back as afunction_call_outputitem. Usage is aResponseUsagewithinput_tokensandoutput_tokens. Aresponse.failedorerrorevent raisesInferenceError, and once anMcpCallhas arrived every error has the codefailed_after_tool_call.moss.inference.responses.createmakes the same call on a client built from the environment. - Requires
inferedge-moss-core0.36.0. - Every request the native core makes, such as model and index downloads, control-plane calls, authentication, uploads and telemetry, sends a
moss-sdk/<version>User-Agent.
chat.completions.create,ChatCompletionStream.get_final_completion(),ToolStepand the chunk, choice, message, completion and logprob types.
- On Linux, TLS no longer trusts emSign ECC Root CA - G3, which
webpki-roots1.0.10 drops after the private keys of eight eMudhra intermediate CAs were compromised. macOS and Windows use the system trust store.
Changed
- Breaking change:
MossInference.responses.create, typed by theResponsesinterface, replaceschat.completions.create, in the shape of OpenAI’s Responses API, and calls/responsesunder the base URL. It takesinput, a string or a list ofResponseInputItems (anEasyInputMessage, aFunctionCallOutputor an output item), andinstructionsin place ofmessages, plus typedmax_output_tokens,text,reasoningandmetadata. A function tool is flat (FunctionTool), andtool_choicenames a function as{ type: "function", name }. Withoutstream: trueit returns aResponse, theresponseobject of the stream’s last event plusoutput_text, whoseoutputholdsResponseOutputMessage,ResponseFunctionToolCall,McpCallandResponseReasoningItemitems. With it, it returns aResponseStreamofResponseStreamEvents, such asresponse.output_text.delta, that ends afterresponse.completedorresponse.incomplete, andfinalResponse()returns the whole response. Theoutputitems go back intoinputunchanged, followed by onefunction_call_outputitem per function call. Usage is aResponseUsagewithinput_tokensandoutput_tokens. Aresponse.failedorerrorevent throwsInferenceError, and once anmcp_callitem has arrived every error has theerrorCodefailed_after_tool_call.inference.responses.createmakes the same call on a client built from the environment. - Requires
@moss-js/moss-core0.37.0. - Every request the native core makes, such as model and index downloads, control-plane calls, authentication, uploads and telemetry, sends a
moss-sdk/<version>User-Agent.
chat.completions.create, theChatCompletionsnamespace,ChatCompletionStreamand itsfinalChatCompletion(),ToolStepwithmoss_tool_stepandmoss_tool_steps, and the chat types:ChatCompletion,ChatCompletionChoice,ChatCompletionChunk,ChatCompletionChunkChoice,ChatCompletionChunkDelta,ChatCompletionChunkToolCall,ChatCompletionContentPart,ChatCompletionCreateParamswith itsBase,StreamingandNonStreamingforms,ChatCompletionLogprobs,ChatCompletionMessage,ChatCompletionMessageParam,ChatCompletionMessageToolCall,ChatCompletionTokenLogprob,ChatCompletionToolandCompletionUsage.
- On Linux, TLS no longer trusts emSign ECC Root CA - G3, which
webpki-roots1.0.10 drops after the private keys of eight eMudhra intermediate CAs were compromised. macOS and Windows use the system trust store.
Changed
- Breaking change:
MossInference.responses.create, typed by theResponsesinterface, replaceschat.completions.create, in the shape of OpenAI’s Responses API, and calls/responses, under thebaseURLpath when there is one. It takesinput, a string or a list ofResponseInputItems (anEasyInputMessage, aFunctionCallOutputor an output item), andinstructionsin place ofmessages, plus typedmax_output_tokens,text,reasoningandmetadata. A function tool is flat (FunctionTool), andtool_choicenames a function as{ type: "function", name }. Withoutstream: trueit returns aResponse, theresponseobject of the stream’s last event plusoutput_text, whoseoutputholdsResponseOutputMessage,ResponseFunctionToolCall,McpCallandResponseReasoningItemitems. With it, it returns aResponseStreamofResponseStreamEvents, such asresponse.output_text.delta, that ends afterresponse.completedorresponse.incomplete, andfinalResponse()returns the whole response. Theoutputitems go back intoinputunchanged, followed by onefunction_call_outputitem per function call. Usage is aResponseUsagewithinput_tokensandoutput_tokens. Aresponse.failedorerrorevent throwsInferenceError, and once anmcp_callitem has arrived every error has theerrorCodefailed_after_tool_call. The proxy route in the README forwards to/responses.
chat.completions.create, theChatCompletionsnamespace,ChatCompletionStreamand itsfinalChatCompletion(),ToolStepwithmoss_tool_stepandmoss_tool_steps, and the chat types:ChatCompletion,ChatCompletionChoice,ChatCompletionChunk,ChatCompletionChunkChoice,ChatCompletionChunkDelta,ChatCompletionChunkToolCall,ChatCompletionContentPart,ChatCompletionCreateParamswith itsBase,StreamingandNonStreamingforms,ChatCompletionLogprobs,ChatCompletionMessage,ChatCompletionMessageParam,ChatCompletionMessageToolCall,ChatCompletionTokenLogprob,ChatCompletionToolandCompletionUsage.
Changed
- Breaking change:
Moss.Inference.Responses.create(client, params, opts)replacesMoss.Inference.Chat.Completions.create/3, in the shape of OpenAI’s Responses API, and calls/responsesunder the base URL.paramstakeinput, a string or a list of items, andinstructionsin place ofmessages, plusmax_output_tokens. Function tools are flat, and so is atool_choicethat names one. Withoutstream: trueit returns{:ok, response}, the"response"map of the last event, whose"output"holds the"message","function_call"and"mcp_call"items as the model sent them, plus"output_text", the text of its messages joined, and"request_id". With it, it returns{:ok, %Moss.Inference.ResponseStream{}}, anEnumerableof event maps, such asresponse.output_text.delta, that ends afterresponse.completedorresponse.incomplete, andMoss.Inference.ResponseStream.close/1ends one early. A tool call’s result goes back as afunction_call_outputitem, after the output items. Usage hasinput_tokensandoutput_tokens. Aresponse.failedorerrorevent raisesMoss.Inference.Error, and once anmcp_callitem has arrived every error has the code"failed_after_tool_call". A stream that ends, or sends[DONE], before its last event is anincomplete_stream. - Requires the
moss_core0.28.0 NIF. - Every request the native core makes, such as model and index downloads, control-plane calls, authentication, uploads and telemetry, sends a
moss-sdk/<version>User-Agent.
Moss.Inference.Chat.Completions,Moss.Inference.ChatCompletionStream, the joinedchat.completionmap with its choices, tool call joining and logprobs, and the"moss_tool_step"chunks and"moss_tool_steps"list.
- On Linux, TLS no longer trusts emSign ECC Root CA - G3, which
webpki-roots1.0.10 drops after the private keys of eight eMudhra intermediate CAs were compromised. macOS and Windows use the system trust store.
Changed
- Breaking change:
client.responses.createandcreateStreamingreplacechat.completions.createandcreateStreaming, in the shape of OpenAI’s Responses API, and call/responsesunder the base URL. They takeinput, a string or a list ofInputItems, andinstructionsin place ofmessages, plusmaxOutputTokens.Tool.functionis flat, andToolChoice.function(name)sends{"type": "function", "name": ...}.createreturns aResponse, whoseoutputholdsOutputItems (.message,.functionCall,.mcpCallor.other, each with itsrawJSON) and whoseoutputTextjoins the text.createStreamingreturns aResponseStreamofResponseStreamEvents, such asresponse.output_text.delta, that ends afterresponse.completedorresponse.incomplete. An output item goes back intoinputasInputItem(item), and a function call’s result as.functionCallOutput(callId:output:).UsagehasinputTokens,outputTokens,totalTokens,cachedTokensandreasoningTokens. Aresponse.failedorerrorevent throwsInferenceError, and once anmcp_callitem has arrived every error has the codefailed_after_tool_call. - Every request the native core makes, such as model and index downloads, control-plane calls, authentication, uploads and telemetry, sends a
moss-sdk/<version>User-Agent.
chat.completions,ChatMessage,ChatCompletion,ChatCompletionChunk,ChatCompletionStream,ToolStep,CompletionUsagewith its token details, and the logprob typesChoiceLogprobsandChatCompletionTokenLogprob.
sdkVersion: 0.29.0.Changed
- Breaking change:
MossInference.responsesreplaceschat.completions, in the shape of OpenAI’s Responses API, and calls/responsesunder the base URL.createandcreateStreamingtakeinput, a list ofInputItems, in place ofmessages, plusinstructionsandmaxOutputTokens, and come in a new argument order:input,model, the OpenAI arguments, the Moss options,extra, then the limits.createreturns aResponse, whoseoutputholdsOutputItem.Message,OutputItem.FunctionCall,OutputItem.McpCallandOutputItem.Otheritems and whoseoutputTextjoins the text.createStreamingreturns aResponseStreamofResponseStreamEvents, such asresponse.output_text.delta, that ends afterresponse.completedorresponse.incomplete.Tool.functionis flat, andToolChoice.functionsends{"type": "function", "name": ...}.InputItem.of(item)sends an output item back with every field it came with, andInputItem.functionCallOutput(callId, output)answers a call. Usage is aUsagewithinputTokensandoutputTokens. Aresponse.failedorerrorevent throwsInferenceError, and once anOutputItem.McpCallhas arrived every error of the call has the codefailed_after_tool_call. - Every request the native core makes, such as model and index downloads, control-plane calls, authentication, uploads and telemetry, sends a
moss-sdk/<version>User-Agent.
chat.completions,ChatMessage,ChatCompletion,ChatCompletionChunk,ChatCompletionStream,ChatToolCall,ToolStep,ChoiceLogprobs,ChatCompletionTokenLogprob,CompletionUsage,CompletionTokensDetailsandPromptTokensDetails.
- TLS no longer trusts emSign ECC Root CA - G3, which
webpki-roots1.0.10 drops after the private keys of eight eMudhra intermediate CAs were compromised.
Changed
- Breaking change:
moss_inference_responses_createreplacesmoss_inference_chat_completions_create, in the shape of OpenAI’s Responses API, and calls/responsesunder the base URL. The request JSON takesinput, a string or a list of items, andinstructionsin place ofmessages, plusmax_output_tokens, and function tools are flat. The callback, aMossInferenceEventFnin place ofMossInferenceChunkFn, gets each Responses event as JSON, such asresponse.output_text.delta, and the stream ends afterresponse.completedorresponse.incomplete. Without a callback,out_jsongets theresponseof that last event, plusrequest_idwhen the reply has one, and it is NULL when a callback stopped the stream first. A function call’s result goes back ininputas afunction_call_outputitem, after theoutputitems as they came, whosemcp_callitems give the model the earlier tool results. Aresponse.failedorerrorevent fails the call with its message and code, and once anmcp_callitem has arrived every failure has the codefailed_after_tool_call. Moss stores nothing:storeis ignored, andprevious_response_id,background,includeand built-in tools fail with the codeunsupported_parameter. The third argument iscall_options_json, the name its error messages use.MOSS_INFERENCE_API_VERSIONis 3. - Every request the library makes, such as model and index downloads, control-plane calls, authentication, uploads, telemetry and inference, sends a
moss-sdk/<version>User-Agent.
moss_inference_chat_completions_create,MossInferenceChunkFn, the chat completion JSON joined from the chunks with itschoices,logprobsandmoss_tool_steps, and themoss_tool_stepchunks.
- On Linux, TLS no longer trusts emSign ECC Root CA - G3, which
webpki-roots1.0.10 drops after the private keys of eight eMudhra intermediate CAs were compromised. macOS and Windows use the system trust store.
Added
- With no credentials,
moss index,moss docandmoss queryrun in offline mode. They keep one index in~/.moss/offline, built from documents that carry their ownembedding. The index opens only for the OS user and device that created it, in one process at a time, and the CLI does not run it on Kubernetes, AWS Lambda and similar server platforms. --offline(orMOSS_OFFLINE=1) selects offline mode, even with credentials. In CI, missing credentials fail without it.- Offline mode sends anonymous usage counts: a random device id, a session id, the CLI version, and document and query counts. Nothing from the index leaves the device.
moss index push <name>uploads that index to your project, embeddings included.moss query --embeddingtakes the query vector as a JSON array or the path of a file holding one, with or without an account.
- moss-cli carries a native module and ships one wheel per platform: Linux x86_64 and aarch64, macOS arm64 and Windows x86_64, where
mossalready installs. It has no source distribution, and a build from a checkout needs a Rust toolchain.
Changed
- Requires
inferedge-moss-core0.36.0, the core thatmoss1.22.0 requires, so the two install together.
Portal
Credits
- The Billing page has a Credits card in place of Pay-As-You-Go: see your balance, buy credits ($5 minimum), and set auto-reload. Only organization owners can buy credits or redeem promo codes.
- When credits run out, usage pauses and the sidebar says Add credits to continue.
- Credit purchases show on the Invoices page.
- The Usage page shows inference tokens per model and inference retrievals.
Added
createtakestools,tool_choiceandparallel_tool_callsas typed arguments, sent only when given.- Tool calls keep every field the model sends, such as Gemini’s
extra_contentwith its thought signature.rawonChoiceDeltaToolCallandChatCompletionMessageToolCallholds them, and a reply message put back intomessagessends them unchanged. moss.inference.McpServerputs an MCP server intools, and Moss runs its tools during the reply. Neither itsserver_urlnor itsheadersshow in a repr.ChatCompletionChunk.tool_stepandChatCompletion.tool_stepshold each MCP tool call and result as aToolStep.ChatCompletionStream.get_final_completion()returns the whole reply as oneChatCompletion, joined from every chunk of the stream, the ones already read included.- Once a call has streamed a tool step, any error it raises has the code
failed_after_tool_call, since a tool may have changed data. max_retries, 2 by default, onMossInferenceor for one call ofcreate, sends a call again when it fails before its reply starts: a connection failure, or a408,409,429or5xxresponse, unless itsx-should-retryheader says otherwise. The wait is theRetry-Afterin seconds when it is 60 or less, else 0.5 s doubled for each retry up to 8 s, and it counts againsttimeout. A stream that fails after it started is never retried.create(cache=False)always asks the model, never Moss’s reply cache.request_idonChatCompletionStreamandChatCompletionholds theX-Moss-Request-Idof the reply, orNone.logprobson each choice of a chunk and of aChatCompletion, as aChoiceLogprobs. A joined choice’scontentandrefusallists are those of its chunks, in order.CompletionUsagehascompletion_tokens_detailsandprompt_tokens_details.
load_indexesruns up to eight loads at once instead of one after another, so many indexes load in about the time of the slowest few. A name listed twice loads once.load_indexon an index that is already loaded checks the cloud version first. An unchanged copy stays loaded with no download or parse, and a changed one is swapped in without interrupting queries. Either way the call’sauto_refreshand polling options replace the current ones.- Auto-refresh polls a loaded index first at a random point of its first interval, then every interval give or take 10%, so indexes loaded together no longer poll together.
- On Linux with glibc,
unload_index,unload_indexes,close, each refresh or reload that installs a newer version, and aSessionIndexthat swaps in a refreshed version or is deleted hand the freed memory back to the operating system, so a long-running process shrinks when it unloads indexes. glibc used to keep those pages until something calledmalloc_trim, and each refresh left the replaced version resident.
indexes=[]searches no index. Leavingindexesout still searches every index of the project.- Tool call pieces with no
indexno longer merge parallel calls into one. A piece joins the call with itsid. A newidstarts the next call, unless the latest call has no id yet and takes it. A piece with noidjoins the latest call. - A joined reply message always has
content: its text, elseNonewhen it has tool calls and""when it has none. Put back intomessages, it keeps thatcontent.
Added
- Tool calls keep every field the model sends, such as Gemini’s
extra_contentwith the thought signature that Gemini 3 needs back. A non-streaming call joins the pieces of each call with those fields, so pushing the reply message intomessagessends each call back unchanged.tools,tool_choiceandparallel_tool_callsare typed and documented. ChatCompletionStream.finalChatCompletion()joins a stream into one completion, as a call withoutstream: truereturns, so a streamed reply with tool calls can go back intomessages.McpServerentries intoolslet the gateway call an MCP server’s tools during the turn. Each tool step arrives as a chunk’smoss_tool_step(ToolStep), and a non-streaming completion lists them inmoss_tool_steps.InferenceErrorTypenamescapacityandmcp_error. Once a step has arrived, every error of that call has theerrorCodefailed_after_tool_call. See the Inference section of the README.maxRetrieson the client and on each call, 2 by default and0for none. A connection that fails, or a 408, 409, 429 or 5xx response, before the stream starts is sent again after itsRetry-Afterof up to 60 seconds, or else after a backoff of 0.5 s doubling up to 8 s with jitter. A response’sx-should-retryforbids or forces a retry, the waits count againsttimeout, and an abort ends a wait at once. A stream that started is never retried, and after the last attempt the last error throws unchanged.cache: falseamong the parameters sendsX-Moss-Cache: off, so the gateway asks the model instead of answering an identical request from its reply cache.ChatCompletionStream.requestIdand a completion’srequestIdhold the response’sX-Moss-Request-Id. On the completion it is not enumerable, soJSON.stringifygives the wire shape.
loadIndexesruns up to eight loads at once instead of one after another, so many indexes load in about the time of the slowest few. A name listed twice loads once.loadIndexon an index that is already loaded checks the cloud version first. An unchanged copy stays loaded with no download or parse, and a changed one is swapped in without interrupting queries. Either way the call’sautoRefreshand polling options replace the current ones.- Auto-refresh polls a loaded index first at a random point of its first interval, then every interval give or take 10%, so indexes loaded together no longer poll together.
- On Linux with glibc,
unloadIndex,unloadIndexes,close, each refresh or reload that installs a newer version, and aSessionIndexthat swaps in a refreshed version or is freed hand the freed memory back to the operating system, so a long-running process shrinks when it unloads indexes. glibc used to keep those pages until something calledmalloc_trim, and each refresh left the replaced version resident.
indexes: []skips the search, asretrieve: falsedoes, instead of searching every index.- A completion’s choices keep
logprobs, each key holding the tokens of every chunk in order, ornullwhen no chunk had any.ChatCompletionChunkChoicetypeslogprobs, andCompletionUsagetypescompletion_tokens_detailsandprompt_tokens_details, whichusagekeeps as the gateway sent them. - Parallel tool calls whose pieces carry no
indexstay apart. Such a piece joins the call of its choice with the sameid. A piece with a newidstarts a new call, unless the latest call has no id yet and takes it, and a piece with noidjoins the latest call. - A completion’s message always has
content: the text, or with no textnullwhen the model called tools and""otherwise, so the message goes back intomessageswhole.
Added
tools,tool_choiceandparallel_tool_callsare typed, documented parameters ofchat.completions.create. A call withoutstream: truejoins each tool call as the gateway does and keeps fields beyond OpenAI’s, such as Gemini’sextra_content, so pushing the reply message ontomessagessends every call back unchanged. The README’s Tool calls section shows the loop.ChatCompletionStream.finalChatCompletion()joins a stream into one completion, as a call withoutstream: truereturns, so a streamed reply with tool calls can go back ontomessages.- MCP servers: a
toolsentry of typemcp, typedMcpServer, asks the gateway to call that server for the model during the turn. Chunks carry each tool step asmoss_tool_step, typedToolStep, and a completion lists them inmoss_tool_steps. Once a step has arrived, any failure of the call carrieserrorCodefailed_after_tool_call, since a tool may have changed data.InferenceErrorTypenamescapacityandmcp_error. maxRetrieson the client and on each call, 2 by default and0for none. A connection that fails, or a 408, 409, 429 or 5xx response, before the stream starts is sent again after itsRetry-Afterof up to 60 seconds, or else after a backoff of 0.5 s doubling up to 8 s with jitter. A response’sx-should-retryforbids or forces a retry, the waits count againsttimeout, and an abort ends a wait at once. A stream that started is never retried, and after the last attempt the last error throws unchanged.cache: falseamong the parameters sendsX-Moss-Cache: off, so the gateway asks the model instead of answering an identical request from its reply cache.ChatCompletionStream.requestIdand a completion’srequestIdhold the response’sX-Moss-Request-Id. On the completion it is not enumerable, soJSON.stringifygives the wire shape.
indexes: []skips the search, asretrieve: falsedoes, instead of searching every index.- A completion’s choices keep
logprobs, each key holding the tokens of every chunk in order, ornullwhen no chunk had any.ChatCompletionChunkChoicetypeslogprobs, andCompletionUsagetypescompletion_tokens_detailsandprompt_tokens_details, whichusagekeeps as the gateway sent them. - Parallel tool calls whose pieces carry no
indexstay apart. Such a piece joins the call of its choice with the sameid. A piece with a newidstarts a new call, unless the latest call has no id yet and takes it, and a piece with noidjoins the latest call. - A completion’s message always has
content: the text, or with no textnullwhen the model called tools and""otherwise, so the message goes back ontomessageswhole.
Added
Moss.Inference.McpServeris an MCP server fortools: Moss calls its tools during the turn. It encodes to{"type": "mcp", ...}without itsnilfields, andinspect/2leaves outserver_urlandheaders.- A chunk with
"moss_tool_step"reports an MCP call before and after it runs, and a reply withoutstreamlists them in"moss_tool_steps". Any failure after a step has code"failed_after_tool_call", since a tool may have changed data. tools,tool_choiceandparallel_tool_callsare documented int:Moss.Inference.Chat.Completions.params/0.:max_retriesonMoss.Inference.new/3and on each call, default2,0for none. A call whose connection fails before the reply’s headers, or that gets a 408, 409, 429 or 5xx reply, is sent again after the reply’sRetry-Afterseconds when they are 60 or fewer, else after 0.5 s doubled each time up to 8 s, less up to 25%. The waits count against:timeout, a wait that would pass it is not taken, and a reply’sx-should-retryheader offalseforbids a retry andtrueforces one. A stream that started is never sent again. After the last attempt the last error returns unchanged.cache: falseon a call sendsX-Moss-Cache: off, so Moss always asks the model instead of its reply cache.stream.request_idand a joined reply’s"request_id"are the reply’sX-Moss-Request-Idheader, elsenil.
indexes: []searches no index and sendsX-Moss-Retrieve: off. Leaving:indexesout still searches every index.- Each choice of a reply without
streamhas"logprobs":nilwhen no chunk sent any, else"content"and"refusal", each the chunks’ lists joined in order, ornilwhen no chunk sent that key. Its"usage"keeps every field the gateway sent, such as"completion_tokens_details". - A tool call piece without an
"index"joins the call of its choice that has its"id", else the most recent call. A new id starts a new call instead when that call has an id already. Parallel calls sent without an index stay separate, even when their pieces interleave. - The message of a reply without
streamalways has"content": the text, elsenilwhen it has tool calls and""when it has none, so it goes back inmessagesas it is. - A reply without
streamkeeps every field of each tool call the model sent, such as Gemini’sextra_content, joined the way Moss joins them, so a reply’s message appended tomessagessends them back unchanged. A call without an id or a name has""for it, notnil. paramsthat give one key twice at any depth, such as:contentand"content", return aninvalid_request_error, since JSON would send that key twice.- On Linux with glibc,
unload_index/2,unload_indexes/2,close/1, each refresh or reload that installs a newer version, and a session that swaps in a refreshed version or is freed hand the freed memory back to the operating system, so a long-running node shrinks when it unloads indexes. glibc used to keep those pages until something calledmalloc_trim.
Added
- Tool calls.
createandcreateStreamingtaketools,toolChoiceandparallelToolCalls.ChatMessage(message)sends a reply back with every field of its tool calls, and.tool(callId:content:)sends a call’s result.ToolChoice.neversendsnone, and.rawany other object. - MCP servers.
Tool.mcp(McpServer)attaches a server the gateway calls, with its steps inchunk.toolStepandcompletion.toolStepsand codefailed_after_tool_callonce a step arrived. - Retries.
maxRetries(2 by default, on the client and per call) sends a call again after a connection failure or a 408, 409, 429 or 5xx status, before its stream starts. It waits aRetry-Afterof up to 60 seconds, else a backoff of up to 8 seconds. - Logprobs and usage details. Chunk and completion choices carry
logprobs, joined in order bycreate, andCompletionUsagekeeps every field inraw, withcompletionTokensDetailsandpromptTokensDetails. - Request id.
ChatCompletionStream.requestIdandChatCompletion.requestIdhold theX-Moss-Request-Idof a call that succeeded. - Reply cache switch.
cache: falsesendsX-Moss-Cache: off, so the model always answers.
indexes: []skips the search and leavingindexesout searches every index.
- A tool call piece with no
indexjoins the call with itsid, so parallel and interleaved calls stay apart and a call whose id comes late stays one call, increateand in each chunk piece’sindex. - A reply with no text and no tool calls has
content"", so it goes back intomessagesintact.
sdkVersion: 0.28.0.Added
- Tool calls.
createandcreateStreamingtaketools(Tool.function,Tool.mcp,Tool.raw),toolChoice(ToolChoice.rawfor any JSON object) andparallelToolCalls, which win over the same keys inextra.createkeeps every field of a tool call, such as Gemini’sextra_content, soChatMessage.assistant(message)sends the reply back unchanged, andChatMessage.tool(callId, content)answers a call. - MCP servers.
Tool.mcp(McpServer(...))lets the gateway call an MCP server’s tools, andMcpServer.toString()shows neither the URL nor a header.ChatCompletionChunk.toolStepandChatCompletion.toolStepscarry the tool steps, after which everyInferenceErrorof the call has the codefailed_after_tool_call. - Retries.
maxRetrieson the client and on a call, 2 by default and 0 for none, sends a call again after a failed or lost connection or a 408, 409, 429 or 5xx before its stream starts, waiting for aRetry-Afterof up to 60 seconds, else a backoff, withintimeoutMs. A read timeout while waiting for the response headers is not retried.x-should-retryforbids or forces a retry, and an interrupt ends the call with its last error. cache = falsesendsX-Moss-Cache: off, so the model answers instead of the reply cache.ChatCompletionStream.requestIdandChatCompletion.requestIdcarry theX-Moss-Request-Idof a call that succeeded.logprobson each chunk choice and joined choice (ChoiceLogprobs), andcompletionTokensDetailsandpromptTokensDetailsonCompletionUsage.AppStatus.providerTimeMsis the part of an app’stimeMsits provider spent before encoding its reply, so the rest is reaching the app and carrying the reply. It isnullwhen the provider runs 0.27.0 or older.CrossAppOptions.providerHoldMs, off by default, keeps a provider that answersOKconnected that long after its last answer, so a search in that time skips the system’s provider lookup and finds the provider awake, and its process keeps the searching app’s priority until then. Opting in withCrossAppOptions.DEFAULT_PROVIDER_HOLD_MSholds a provider for 5 s, and any other positive value is allowed. Any other outcome disconnects it at once.
cachecomes right afterretrieve, andtools,toolChoiceandparallelToolCallsright afterextra, so a Java caller that passesapiKeyor a later argument by position now passes those first, and Kotlin code built against 0.27.0 that callscreateorcreateStreamingmust be rebuilt.creategives a tool call that arrived without anidor functionnamean empty string there, notnull.indexes = emptyList()skips the search and sends no indexes. Leaveindexesout, nownullby default, to search every index.
createkeeps parallel tool calls that arrive without anindexapart: such a piece joins the call with the sameid. A piece with noidjoins the call of the latest piece, and so does one with a newidwhile that call has none; any other newidstarts a new call.- The joined message always has
content:nullbeside tool calls and""when nothing came, soChatMessage.assistant(message)sends it back whole.
Added
moss_inference_chat_completions_createtakes MCP servers intools, as{"type": "mcp", "server_label", "server_url"}with optionalheaders,allowed_toolsandtransport. The completion lists each chunk’smoss_tool_stepinmoss_tool_steps, and a failure after a step has the codefailed_after_tool_call.libmoss.hdocumentstools,tool_choiceandparallel_tool_calls.max_retriesin the client and call options, 2 unless set. A call goes again after a connection failure or a 408, 409, 429 or 5xx, before any of the reply is read, waiting theRetry-Afterin delta-seconds when it is 60 s or less, else 0.5 s doubled per retry up to 8 s, less up to 25%.x-should-retryfrom the gateway forbids or forces a retry, a wait that would passtimeout_msends the call with that failure, and the last failure is the call’s error. A stream that fails after it started is never retried. 0 turns retries off."cache": falsein the request JSON sendsX-Moss-Cache: off, so the gateway asks the model rather than answering from its reply cache.- The completion JSON has
request_id, the reply’sX-Moss-Request-Id, or null without one.
MOSS_INFERENCE_API_VERSIONis 2, which marks a header whose inference calls keep every tool call field, listmoss_tool_steps, reportfailed_after_tool_call, takemax_retriesandcache, turn retrieval off for an emptyindexesand returnrequest_id.- On Linux with glibc,
moss_client_unload_index,moss_client_unload_indexes,moss_client_release_memory,moss_client_free, each refresh or reload that installs a newer version, and a session that swaps in a refreshed version or is freed hand the freed memory back to the operating system. glibc used to keep those pages until something calledmalloc_trim.
- The completion’s tool calls keep every field the model sent, such as Gemini’s
extra_content, merged as the gateway merges them, so the message JSON sent back inmessagescarries them unchanged. They used to keep onlyid,typeand the function’snameandarguments. A call sent without anidhas an empty one, notnull. "indexes": []turns retrieval off and sends noX-Moss-Indexes. It used to search every index.- Each completion choice has
logprobs: null when no chunk of it had any, elsecontentandrefusal, each the chunks’ arrays joined in order. - A tool call piece without an
indexjoins the call with itsid, else the most recent call, unless the piece and that call both have an id, and then it starts the next call. Parallel calls sent without anindexstay apart, even when their pieces alternate, and a call whoseidcomes on its second piece stays one call. They used to join by their position in each chunk. - The completion message of a reply without text has
contentnull when it has tool calls and""when it has none, so it goes back inmessagesas it is. An empty reply used to havenull.
Changed
- Requires
inferedge-moss-core0.35.0, the core thatmoss1.21.0 requires, so the two install together. 2.0.1 required 0.32.0, which conflicts withmoss1.19.0 and later.
- The README, the LiveKit example and the package docstrings said that indexes loaded in
prewarmare shared by every room a process handles. LiveKit runs each call in its own process by default and runsprewarmonce in each new process, which must finish withininitialize_process_timeout(10 seconds by default), so those indexes serve one call. The README shows how to share oneMossAgentacross calls that run as threads of one process.
Added
MossInference(project_id, project_key)answers chat messages with facts from your Moss indexes.await client.chat.completions.create(...)takes the arguments of OpenAI’schat.completions.createplusindexesandretrieve, and returns aChatCompletionStreamofChatCompletionChunkwithstream=True, else oneChatCompletion, with OpenAI’s field names.modelis"moss"by default.api_key, on the client or for one call ofcreate, is optional: your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini.mossignores it, and a vendor model without one is refused. The client also takestimeoutfor a whole call,idle_timeoutfor each wait for data or a free connection (120 seconds by default or whenNone), anddefault_headers. A timeout of 0 or less is off.createcan change the key and both timeouts for one call, andNonethere keeps the client’s. The client checks its arguments when built, keeps one connection pool, and closes it withclose()orasync with. Failures raisemoss.inference.InferenceErrorwithstatus,typeandmessage, and, once the service has answered, itsrequest_id, errorcodeandretry_afterin seconds. A redirect is one of those failures, so credentials never reach another URL. Calls go tohttps://inference.moss.dev/v1, or to the base URL inMOSS_INFERENCE_URL, which a client reads when built.moss.inference.chat.completions.createmakes the same call on a client built fromMOSS_PROJECT_ID,MOSS_PROJECT_KEYandMOSS_INFERENCE_URL.
- Requires
httpx, whichmoss.inferencestreams replies with, along withh110.16 or later andanyio4.14.2 or later, the first releases of each without published advisories. - Requires
inferedge-moss-core0.34.0. Every native object shares one process-wide async runtime instead of starting its own 18 threads, so a process keeps the same few threads however many clients and sessions it opens.MOSS_TOKIO_WORKER_THREADSsets its worker count, by default the number of CPU cores, at least 2 and at most 4, and a forked child builds its own. The background flush a dropped object starts runs to the end. - A
429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, fails on the first response with the codeUNAUTHORIZEDand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing withNETWORK. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
Added
MossInferenceanswers OpenAI’schat.completions.createthrough the Moss inference gateway, which adds what it finds in theindexesyou pass to the prompt.new MossInference(projectId, projectKey, { apiKey, timeout, idleTimeout, headers })checks its arguments when it is built, andclient.chat.completions.create(params, { apiKey, signal, timeout, idleTimeout, headers })takes OpenAI’s parameters plusindexesandretrieve, withmodelset to"moss"when it is left out. Withstream: trueit returns aChatCompletionStreamofChatCompletionChunks, and otherwise oneChatCompletion.apiKeyis optional: your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini.mossignores it, and a vendor model without one is refused. A call’sapiKeywins over the client’s, and an empty one is an error, as isapiKeyorapi_keyamong the parameters. Neither the client’s nor a call’sheaderscan setHost,Content-LengthorTransfer-Encoding.idleTimeoutlimits the wait for response headers or for more of the body, 120 seconds by default. The client does not follow redirects. A client built withMOSS_INFERENCE_URLset calls that gateway instead of production, and abaseURLorbaseUrloption is an error.inference.chat.completions.createuses a client built fromMOSS_PROJECT_ID,MOSS_PROJECT_KEYandMOSS_INFERENCE_URL. Failures throwInferenceError, which carries a MosscodethatisMossErroraccepts, and the gateway’serrorCode, therequestIdandretryAfterin milliseconds when the response has them. See the Inference section of the README.
- Requires
@moss-js/moss-core0.35.0. A429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, fails on the first response with the codeUNAUTHORIZEDand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing withNETWORK. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
Added
MossInferenceanswers OpenAI’schat.completions.createthrough the Moss inference gateway, which adds what it finds in theindexesyou pass to the prompt.new MossInference(projectId, projectKey, { baseURL, apiKey, timeout, idleTimeout, headers })checks its arguments when it is built, andclient.chat.completions.create(params, { apiKey, signal, timeout, idleTimeout, headers })takes OpenAI’s parameters plusindexesandretrieve, withmodelset to"moss"when it is left out. Withstream: trueit returns aChatCompletionStreamofChatCompletionChunks, and otherwise oneChatCompletion, with the types of@moss-js/moss. The client calls the Moss inference gateway, unlessbaseURLnames a path on the page’s origin, such as/moss/v1; any otherbaseURLthrows. Each call resolves that path against the page’s URL, so a client built during server rendering works in the browser, and a call without an http or https page throwsInferenceError. With such a path,nullfor both credentials sends noAuthorizationheader, for a route on your server that adds it, since a project key in page code is visible to every visitor; the Inference section of the README shows that route, which passesRetry-AfterandX-Moss-Request-Idback to the page.apiKeyis optional: your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini.mossignores it, and a vendor model without one is refused. A call’sapiKeywins over the client’s, and an empty one is an error, as isapiKeyorapi_keyamong the parameters.idleTimeoutlimits the wait for response headers or for more of the body, 120 seconds by default. Failures throwInferenceError, which carries the gateway’serrorCode, therequestIdandretryAfterin milliseconds when the response has them and the page can read them. A redirect is not followed: it throwsInferenceError, with nostatusin a browser, which hides the redirect. A browser reports a stream cut off mid-reply as a network error, so that fails asconnection_errorrather thanincomplete_stream. The package declares"sideEffects": false, so a bundle that imports onlyMossInferenceleaves out the WASM client and ONNX Runtime code, though Vite still copies their.wasmfiles into the build output.
- Requires
@moss-dev/moss-wasm0.18.2. A429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, rejects on the first response with the codeUNAUTHORIZEDand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing withNETWORK. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
Added
Moss.Inferenceis a client for OpenAI’s chat completions call, answered by Moss inference athttps://inference.moss.dev/v1, which searches the indexes named in:indexesand adds what it finds to the prompt. TheMOSS_INFERENCE_URLenvironment variable sets another base URL, read when a client is built.Moss.Inference.new(project_id, project_key, opts)returns a%Moss.Inference{}and raisesMoss.Inference.Errorfor an empty credential or key, a project id with:, a credential or key that is not printable ASCII or starts or ends with a space or tab, a bad timeout, or aMOSS_INFERENCE_URLthat is not anhttporhttpsURL with a host and no user info, query or fragment, in an error that names the variable and never its value. An unknown option raisesArgumentError, which names the option and never its value. It takes:api_key, optional, your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini:mossignores it, and a vendor model without one is refused. It also takes:timeout, milliseconds for a whole call (default:infinity), and:idle_timeout, milliseconds Moss may stay silent before the reply headers or between two parts of the body (default120_000,:infinitydisables it).inspect/2leaves out the keys.Moss.Inference.Chat.Completions.create(client, params, opts)sends the call.paramsis the OpenAI request body, with atom or string keys, and withoutmodelthe call sends"model" => "moss".optstakes:indexes,:retrieve, and:api_key,:timeoutand:idle_timeoutover the client’s.paramsthat hold one of these options, orapiKey, as an atom or string key, return aninvalid_request_errorthat names the option and never its value. A provider key goes in a header, never in the body or an error, and an empty one, or one that starts or ends with a space or tab, is an error. A client that is not a%Moss.Inference{}, params that are not a map or an unknown option raisesArgumentError, which holds no key. Withstream: trueit returns{:ok, %Moss.Inference.ChatCompletionStream{}}, anEnumerableof chunk maps that raisesMoss.Inference.Errorif the reply fails after it starts. Without it, it returns{:ok, completion}, the whole reply as onechat.completionmap with tool call arguments joined. A failure before the reply starts returns{:error, %Moss.Inference.Error{}}withstatus,typeandmessage,code, the gateway’serror.codeas text,request_id, the reply’sX-Moss-Request-Idheader, andretry_after, an error reply’sRetry-Afterheader in milliseconds. A failure after the reply’s headers carries the samerequest_id, and an error event itscode. A redirect is an error with its status, never followed. An error reply that is not JSON has its body, on one line and cut to 300 characters, as the message. A reply that ends before[DONE], or a connection reset mid-reply, is anincomplete_stream, an event or line over 1 MiB aserver_error, and a silent reply atimeout.Moss.Inference.ChatCompletionStream.close/1, from any process, ends a stream without an error.- Inference calls reuse idle connections, from any process, in a pool the
:mossapplication starts. A reply read to its end gives its connection back, and a stream that stops early, fails or times out closes its own, as does a process that dies mid-stream. No call is sent twice: a pooled connection found closed is replaced before the call is written to it. A call never waits for the pool past its:timeout, and one that gets a pooled connection too late gives it back unused. The pool keeps up to 100 idle connections, each for at most 4 seconds. Without the:mossapplication running, each call opens its own connection.
- The SDK depends on
jasondirectly, and onmint1.11 or later, the HTTP client the inference client uses. Earliermintreleases, and thehpaxreleases they allow, have published security advisories. - Requires the
moss_core0.26.0 NIF. A429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, fails on the first response with the code:unauthorizedand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing with:network. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
Added
- Inference.
MossInference(projectId:projectKey:apiKey:timeout:idleTimeout:)is a client for the Moss inference gateway, which searches your indexes and answers in the shape of OpenAI’s chat completions.client.chat.completions.createreturns aChatCompletionandcreateStreamingaChatCompletionStreamofChatCompletionChunk.modeldefaults to"moss". Failures throwInferenceError, which carries the gateway’scode, the call’srequestIdand theretryAfterseconds of aRetry-Afterheader, and the client checks its credentials when created.apiKeyis optional. Your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini.mossignores it, and a vendor model without one is refused. A call’sapiKeyreplaces the client’s.MOSS_INFERENCE_URLsets the base URL it calls, and the client reads it when it is created. A value that is not anhttporhttpsURL with a host and no user info, query or fragment makesinitthrowInferenceErrorwith typeinvalid_request_error.idleTimeout(120 seconds by default) ends a call when the gateway goes silent. An event or a line over 1 MiB fails the stream with aserver_error. A redirect is not followed.
- A
429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, throws on the first response with aMossErrorwhose code isMossError.unauthorizedand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing withMossError.network. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
sdkVersion: 0.27.0.Added
- Inference.
MossInference(projectId, projectKey, apiKey, timeoutMs, idleTimeoutMs)calls the Moss inference gateway with OpenAI’s chat completion shape.chat.completions.createStreamingreturns aChatCompletionStreamofChatCompletionChunks,createjoins them into oneChatCompletion. Both takemessagesfirst, andmodelismossunless a call passes another, socreate(messages)works from Java too. Failures throwInferenceErrorwithstatus,typeandmessage, and with the gateway’scode,requestIdandretryAfterMswhen the response carried them.apiKeyis optional, your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini;mossignores it, and a vendor model without one is refused. A call can pass its ownapiKey, which wins over the client’s.idleTimeoutMs(120 seconds by default) ends a call when the gateway goes silent,timeoutMs(off by default) bounds a whole call, and a call can pass its own of either.MOSS_INFERENCE_URL, read when a client is built, sets the base URL it calls. A redirect is not followed. Built onHttpURLConnection, with no new dependency.
- A
429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, throws on the first response with aMossExceptionwhose code isMossErrorCode.UNAUTHORIZEDand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing withMossErrorCode.NETWORK. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
Added
MossInference, a client of the Moss inference gateway in the shape of OpenAI’s chat completions API.moss_inference_newcreates one from an options JSON withproject_idandproject_key, and optionallyapi_key,timeout_msandidle_timeout_ms, and rejects a bad option before any call.moss_inference_freefrees it. A client calls the gateway athttps://inference.moss.dev/v1, or at the base URL inMOSS_INFERENCE_URL, and refuses a value that is not printable ASCII, or not an absolute http or https URL with a host and no user info, query, fragment or port 0.api_keyis your own OpenAI, Anthropic or Google key, for a vendor model such asgpt-4o-mini;mossignores it, and a vendor model without one is refused. It is sent as theX-Moss-Provider-Keyheader.idle_timeout_ms, 120000 unless set, limits each wait for the reply’s headers or its next bytes, andtimeout_msa whole call; 0 turns either off. One client may serve calls on several threads at once.moss_inference_chat_completions_createcreates a chat completion on aMossInferenceclient, like OpenAI’schat.completions.create. It takes the OpenAI request JSON, whosemodeldefaults tomoss, plusindexesandretrieve, and call options withapi_key,timeout_msandidle_timeout_msthat replace the client’s, and streams each chunk to a callback or returns one completion JSON. Redirects are not followed, and an event or a line over 1 MiB fails the call.moss_last_error_detail()describes a failure with its OpenAI errortype, HTTPstatus, the gateway’s errorcode, theX-Moss-Request-Idasrequest_idand aRetry-Afterin delta-seconds asretry_after_ms.MOSS_INFERENCE_API_VERSION1 marks a header with these functions.
- A
429with the codeUSAGE_LIMIT_EXCEEDED, which Moss sends while a project is paused, returns on the first response withERR_UNAUTHORIZEDand the message “The project’s usage limit has been reached; billing must be updated before it can be used.”, instead of retrying for about 90 seconds and failing withERR_CLOUD. A cold start with a committed snapshot on disk fails the same way rather than serving the snapshot. Any other429still retries.
API
Added
- Moss Inference:
POST https://inference.moss.dev/v1/chat/completionstakes an OpenAI chat completion request withAuthorization: Bearer <project_id>:<project_key>, searches the project’s indexes, adds the hits to the prompt, and answers in OpenAI’s shape, so any OpenAI client works by changing the base URL and the key.modelismoss(the default) or an OpenAI, Anthropic, or Google model name with your own key inX-Moss-Provider-Key. Headers, limits, errors, and billing are on the Chat Completions page.
Added
- The package metadata declares its license, PolyForm Shield 1.0.0, as
LicenseRef-PolyForm-Shield-1.0.0, so PyPI and license scanners show it. - The
inferedge-moss-corewheels carryLICENSE-THIRD-PARTY.txt, the license and copyright notices of the third-party code the extension links: the Rust crates of that target, ONNX Runtime and the components it includes, and the Rust standard library. SessionIndex.save_to_diskandload_from_disktakecache_pathas optional. Without one, or with an empty one, snapshots go insessions/<project id>/under the client’scache_path, else under theMOSS_SESSION_CACHE_PATHenvironment variable, which only session snapshots read, else undermossin the default cache directory:~/.cache/mosson macOS and Linux,%LOCALAPPDATA%\mosson Windows. A directory you pass is used as before.
- Requires
inferedge-moss-core0.33.0. - The custom embeddings section of the README says to L2-normalize the vectors you provide. Thanks @VeshRaazThapa (usemoss/moss#529).
inferedge-moss-core, the native runtime ofmoss, is not supported for direct use, and itsmoss_coremodule no longer exportsIndex. Import every Moss type frommoss. No change to themossAPI.SessionIndex.add_docson a session with a built-in model embeds the documents in batches of at most 512 padded tokens instead of 8,192, and tokenizes each batch on the thread that embeds it. Each model session runs 2 inference threads on a desktop or server host (macOS, Linux or Windows) with 8 or more cores, and 1 on a smaller host, on Android and iOS, and formoss-litelm. Idle threads sleep instead of spinning. Embedding many documents needs less memory, and on a host that runs 2 threads it takes less time. Text queries on other sessions with the same model stay fast while it runs.MOSS_EMBEDDING_INTRA_OP_THREADSstill sets the thread count on every platform.moss-litelmembeds each document in its own batch, so a document’s vector equals the vector of its text embedded alone. Embedded in a batch, its vectors used to differ from that, with a cosine similarity as low as 0.989.
- Deleting a
MossClientorSessionIndexwaits at most 100 ms for a DNS lookup still in progress. It used to hold the GIL until DNS gave up.
Added
- The
licensefield namesLICENSE.txt, the file the package ships, so npm and license scanners find the PolyForm Shield 1.0.0 text. SessionIndex.saveToDisk,loadFromDiskandinspectSnapshottake the directory as optional. Without one, or with an empty one, snapshots go insessions/<project id>/under the client’scachePathoption, else under theMOSS_SESSION_CACHE_PATHenvironment variable, which only session snapshots read, else undermossin the default cache directory:~/.cache/mosson macOS and Linux,%LOCALAPPDATA%\mosson Windows. A directory you pass is used as before.IndexInfo,IndexStatusandModelRefare exported, so code that types the results ofgetIndexandlistIndexesimports them from@moss-js/moss. Import every Moss type from@moss-js/moss:@moss-js/moss-coreis the SDK’s native runtime and is not supported for direct use.IndexStatus,JobStatusandJobPhaseare exported as plain objects with matching string union types, so members such asIndexStatus.Readywork at runtime and type-check underisolatedModulesandverbatimModuleSyntax(Vite, Next.js, tsx). Each member also names its own type, as an enum member did, solet status: JobStatus.Completedstill compiles. The fields that hold them, such asIndexInfo.status, accept the same strings.
- Requires
@moss-js/moss-core0.34.0. @moss-js/moss-coredeclaresIndexStatus,JobStatusandJobPhaseas types only, so code that imported their values from it, such asIndexStatus.Ready, imports them from@moss-js/mossinstead.- The published type declarations no longer include internal members. No runtime change.
- The custom embeddings section of the README says to L2-normalize the vectors you provide. Thanks @VeshRaazThapa (usemoss/moss#529).
dist/index.esm.jsships as plain JavaScript, not minified, so stack traces name the SDK’s own functions. No API change.SessionIndex.addDocson a session with a built-in model embeds the documents in batches of at most 512 padded tokens instead of 8,192, and tokenizes each batch on the thread that embeds it. Each model session runs 2 inference threads on a desktop or server host (macOS, Linux or Windows) with 8 or more cores, and 1 on a smaller host, on Android and iOS, and formoss-litelm. Idle threads sleep instead of spinning. Embedding many documents needs less memory, and on a host that runs 2 threads it takes less time. Text queries on other sessions with the same model stay fast while it runs.MOSS_EMBEDDING_INTRA_OP_THREADSstill sets the thread count on every platform.moss-litelmembeds each document in its own batch, so a document’s vector equals the vector of its text embedded alone. Embedded in a batch, its vectors used to differ from that, with a cosine similarity as low as 0.989.
Changed
- Requires
@moss-dev/moss-wasm0.18.1.
- The
licensefield namesLICENSE.txt, the file the package ships, so npm and license scanners find the PolyForm Shield 1.0.0 text.
Added
- The
moss_corepackage declares its license, PolyForm Shield 1.0.0, asLicenseRef-PolyForm-Shield-1.0.0, and it and each NIF archive carry theLICENSE.txtit names. - Each
moss_coreNIF archive carriesLICENSE-THIRD-PARTY.txt, the license and copyright notices of the third-party code the NIF links: the Rust crates of that target, ONNX Runtime and the components it includes, and the Rust standard library. Moss.Session.save_to_disk/2andMoss.Session.load_from_disk/3take the cache path as optional, andload_from_disk(session, rebuild_legacy: false)also works. Without one, or with an empty one, snapshots go insessions/<project id>/under the client’s:cache_path, else under theMOSS_SESSION_CACHE_PATHenvironment variable, which only session snapshots read, else undermossin the default cache directory:~/.cache/mosson macOS and Linux,%LOCALAPPDATA%\mosson Windows. A path you pass is used as before.Moss.Clientkeeps its:cache_path, andMossCore.Nif.session_save_to_disk/3andsession_load_from_disk/4take the client’s cache path.
- Bumped
moss_coredependency to 0.25.0. Moss.Session.add_docs/3on a session with a built-in model embeds the documents in batches of at most 512 padded tokens instead of 8,192, and tokenizes each batch on the thread that embeds it. Each model session runs 2 inference threads on a desktop or server host (macOS, Linux or Windows) with 8 or more cores, and 1 on a smaller host and formoss-litelm. Idle threads sleep instead of spinning. Embedding many documents needs less memory, and on a host that runs 2 threads it takes less time. Text queries on other sessions with the same model stay fast while it runs.MOSS_EMBEDDING_INTRA_OP_THREADSstill sets the thread count on every platform.moss-litelmembeds each document in its own batch, so a document’s vector equals the vector of its text embedded alone. Embedded in a batch, its vectors used to differ from that, with a cosine similarity as low as 0.989.
Added
- Third-party notices.
Moss.xcframework.zipand the Swift package carryLICENSE-THIRD-PARTY.txt, the license and copyright notices of the third-party codelibmoss.alinks: the Rust crates, ONNX Runtime and the components it includes, and the Rust standard library. - Default session directory.
MossSession.save(toCachePath:)andloadFromDisk(cachePath:)take the path as optional. Without one, snapshots go in the app’sLibrary/Caches/moss/sessions/<project id>/, or insessions/<project id>/under theMOSS_SESSION_CACHE_PATHenvironment variable when it is set. Only session snapshots read that variable.
- Document parsing in the core.
MossClient.createIndexandaddDocsparse documents with the core’s JSON parser. Everything accepted before is accepted with the same result, and parse errors name the document’s index. - Smaller embedding batches.
MossSession.addDocson a session with a built-in model embeds the documents in batches of at most 512 padded tokens instead of 8,192, and tokenizes each batch on the thread that embeds it. Each model session keeps 1 inference thread on every iPhone and iPad.MOSS_EMBEDDING_INTRA_OP_THREADSstill sets the thread count, and with more than 1 thread, idle threads sleep instead of spinning. moss-litelmvectors match single texts.moss-litelmembeds each document in its own batch, so a document’s vector equals the vector of its text embedded alone. Embedded in a batch, its vectors used to differ from that, with a cosine similarity as low as 0.989.
- Close returns promptly.
MossClient.close()andMossSession.close(), also run on deinit, wait at most 100 ms past their 2-second close deadline for a DNS lookup still in progress, instead of until DNS gives up. - A session keeps its client’s authenticator. A
MossSessionopened from a client with anAuthenticatorkeeps that authenticator until the session closes, so a session still open afterMossClient.close()gets its tokens instead of crashing.
sdkVersion: 0.26.0.Added
- Third-party notices. The AAR carries
assets/moss/LICENSE-THIRD-PARTY.txt, the license and copyright notices of the third-party codelibmoss_jni.solinks: the Rust crates, ONNX Runtime and the components it includes, and the Rust standard library. - Android SDK. A Kotlin AAR (
dev.usemoss.moss, arm64-v8a, minSdk 24) over one 16 KB-alignedlibmoss_jni.sothat statically linkslibmossand ONNX Runtime.MossClientloads indexes for on-device query (loadIndex,query,unloadIndex), wraps the cloud index operations, and opens on-device sessions withMossClient.session(moss-litelm + INT8 by default) withsaveToDisk,loadFromDiskandpushIndex. Blocking calls reject the main looper, Application trim-memory callbacks unload indexes off the main thread, andclose()frees the native client on a worker thread. - Default session directory.
saveToDiskandloadFromDiskwithout a path usecacheDir/moss/sessions/<project id>/<name>, the layout of the other SDKs, so two projects with a session of the same name stay apart.MossClient.sessionCacheDir(context, projectId)returns the project folder. - Multi-app search.
MossClient.loadIndexes,queryMultiIndexandunloadIndexessearch several loaded indexes, such as one per app, in one call. The result is the global toptopK(10 without options) across all of them, and eachQueryResult.indexNamenames the index a hit came from.alphakeeps its single-index meaning; keyword ranking merges each index’s BM25 hits by score.loadIndexesis best effort and reports each failure by name inLoadIndexesResult.failedandfailedCodes. - Search other apps. An app exports a
MossSearchProviderto answer searches from its own indexes, andCrossAppSearch.querysearches every provider app it trusts plus its own loaded indexes in one call, under one deadline (1,000 ms by default), and ranks the hits by score.AppPolicysets who may search whom by signing certificate or permission, same signer by default; a refused caller gets no hits. Each app reports OK, TIMEOUT, REFUSED, UNTRUSTED, UNAVAILABLE, FAILED or INCOMPATIBLE, and a cloud copy the host loaded answers for any app that did not answer, unless it refused. A reply holds at most 100 hits, 2,000 characters of text per hit and 64 KB. On API 30 and later the searching app needs a<queries>entry forMossSearchProvider.ACTION. - Typed exceptions. Every failure is a
MossExceptionsubclass for itsMossErrorCode:InvalidArgument,NotFound,Unauthorized,Network,Deserialization,ModelUnavailableandInternal.messageis fixed text for each kind of core failure,detailcarries the core error text for logs and support, andnativeCodekeeps the exactMossResultvalue. Arguments the Kotlin layer checks itself, such as a blank index name or atopKbelow 1, throwIllegalArgumentException.
Added
moss_session_save_to_diskandmoss_session_load_from_diskaccept a NULL or emptycache_path. The snapshot then goes insessions/<project id>/under theMOSS_SESSION_CACHE_PATHenvironment variable, which only session snapshots read, else undermossin the default cache directory:~/.cache/mosson macOS and Linux, the app’sLibrary/Caches/mosson iOS,%LOCALAPPDATA%\mosson Windows. Android has no default, so the call returnsERR_INVALID_ARGthere unlessMOSS_SESSION_CACHE_PATHis set.MOSS_SESSION_DEFAULT_DIR_API_VERSION1 marks a header with this default.- Each archive carries
LICENSE-THIRD-PARTY.txt, the license and copyright notices of the third-party code its library links: the Rust crates of that target, ONNX Runtime and the components it includes, and the Rust standard library.
moss_client_freeandmoss_session_freewait at most 100 ms past their 2-second close deadline for blocking work still running, such as a DNS lookup. They used to wait for it, for as long as DNS took to give up.- The authenticator callback of
moss_client_new_with_authenticatoris never invoked after the client and every session opened from it are freed, souser_dataneeds to stay valid only until then.
- The Linux builds support glibc 2.28 and newer on both x86_64 and aarch64, so they load on RHEL 8 and 9, Amazon Linux 2023, Debian 10 and later, and Ubuntu 20.04 and later. They used to need glibc 2.35 on x86_64 and 2.39 on aarch64.
moss_client_create_index_from_jsonandmoss_client_add_docs_from_jsonaccept JSON Lines as well as a JSON array. Integer ids and number or boolean metadata values become strings,nullmetadata values are dropped, and a non-stringpayloadis stored as its JSON text. Everything accepted before parses the same way. Parse errors name the array index or line.moss_session_add_docson a session with a built-in model embeds the documents in batches of at most 512 padded tokens instead of 8,192, and tokenizes each batch on the thread that embeds it. Each model session runs 2 inference threads on a desktop or server host (macOS, Linux or Windows) with 8 or more cores, and 1 on a smaller host, on Android and iOS, and formoss-litelm. Idle threads sleep instead of spinning. Embedding many documents needs less memory, and on a host that runs 2 threads it takes less time. Text queries on other sessions with the same model stay fast while it runs.MOSS_EMBEDDING_INTRA_OP_THREADSstill sets the thread count on every platform.moss-litelmembeds each document in its own batch, so a document’s vector equals the vector of its text embedded alone. Embedded in a batch, its vectors used to differ from that, with a cosine similarity as low as 0.989.
Added
- The package metadata declares its license, PolyForm Shield 1.0.0, as
LicenseRef-PolyForm-Shield-1.0.0, so PyPI and license scanners show it.
- The README puts the global options
--project-id,--project-keyand--jsonbefore the command, wheremossreads them.
Added
- README: ambient retrieval (STT to Moss), which queries Moss with every final user transcript and gives the results to the LLM with the question. Includes a LiveKit
on_user_turn_completedexample and one for any framework.
A major release: the newer core changes what
score means and how built-in models load, and multi-index queries become hybrid by default. See Breaking changes.Breaking changes- Requires
inferedge-moss-core0.32.0 (1.0.0 required 0.12.0). Behavior that comes with the newer core:- Result
scoreis relevance from 0 to 1 on every query path. In 1.0.0, single-indexscorewas a rank-fusion value (1.0, 0.969, 0.939, …) and multi-indexscorewas raw cosine, so a threshold tuned on 1.0.0 scores needs retuning. - Errors are
MossErrorwith stable.code/.detail; invalid arguments raiseInvalidArgumentError, which is also aValueError. $gt/$gte/$lt/$ltefilters compare plain decimals as numbers and everything else as text.- Loading a built-in embedding model needs the Moss cloud to be reachable.
- Result
- Multi-index queries default to
alpha=0.8(hybrid), as in themossSDK. 1.0.0 ran them embedding-only; passQueryOptions(alpha=1.0)for that. query_multi_indexwith no index names raisesInvalidArgumentErrorbefore any search.top_k=0is passed through on every query method and returns no results, as inmossand core, instead of being replaced by the default 5 (10 for multi-index).
MossAgent.start_call(room_id, *, session_id=None, started_at=None) -> MossCallstarts the call scope for one conversation in any voice framework, andMossCall.end()ends it. Starting a room whose call is active returns a handle to that call.started_atmust be timezone-aware and defaults to now.MossCall.room_idandMossCall.session_id.livekit_room_idandlivekit_session_idstay as aliases.MossAgent.close()ends every active call, sends the final usage telemetry and releases the agent; afterwards every method raisesRuntimeError("MossAgent is closed").MossAgentworks asasync withandwith.MossAgent(..., cache_path=...)sets the default on-disk index cache forload_index/load_indexes; a per-callcache_pathoverrides it.MossAgent.was_served_stale(name)reports whether an index is served from a cached snapshot because the cloud was unreachable at load.QueryOptions.min_scoreandQueryOptions.candidate_depthare honored onMossCall.query*andMossAgent.query*, andalphais honored on multi-index queries.create_indexandadd_docstake documents as dicts, JSON array or JSON Lines text, or.json,.jsonl,.ndjson,.txt,.mdand.markdownfile paths, as well asDocumentInfoobjects, with keyword-onlychunkerandchunking(Chunking) arguments.create_index(..., wait=False)submits the build and returns aJobHandle(job_id,status(),wait()).MossAgent.wait_for_job(job_id, *, poll_interval_seconds=2.0, timeout_seconds=1800.0).create_index_from_files(..., parse_options=ParseOptions(...))withuse_high_resolution,segmentation_method,ocr_mode,merge_tables,chunk_sizeandchunk_overlap.- Web sources on the Moss manage API:
create_web_source,list_web_sources,get_web_source,update_web_source,resync_web_sourceanddelete_web_source, with the same signatures and results as themossSDK.MOSS_CLOUD_API_BASE_URLoverrides the host. Failures raiseManageApiError, and a redirect is refused withManageApiErrorrather than followed, so the project key is never resent to another URL. - Exports
ParseOptions,JobHandle,DocsInput,Chunker,Chunking,ParentGrouping,MossError,InvalidArgumentError,ManageApiError,WebSource,CreateWebSourceResult,UpdateWebSourceResult,ResyncWebSourceResultandDeleteWebSourceResult.
attach(ctx)is built onstart_call. A naiveroom.creation_timeis read as local time, as before.MossAgent.queryandquery_multi_indextakeoptionspositionally too.moss_agent.__version__is read from the installed package metadata.
MossAgent.queryandMossCall.querypass an explicitalpha=0.0(keyword-only search) through instead of replacing it with the default 0.8.
Portal
Founding Agent deal codes
- Redeem a Founding Agent deal, such as the YC deal, from the sign-up link in its email. Checkout opens with the code applied, and the plan activates once you confirm it.
- If a code can’t be used, the Plan page says why.
API
Changed
- Parsed PDF and DOCX files are split into chunks that end at sentence boundaries, and each chunk starts with the document’s title and nearest section heading. Image descriptions are no longer indexed.
parseOptionstakeschunkSize(200 to 2000 characters, default 1200) andchunkOverlap(default 200, at most half ofchunkSize). See Index from Files.- Only files parsed from now on are affected.
Added
MossClient.create_index,MossClient.add_docsandSessionIndex.add_docstake documents as dicts (or anycollections.abc.Mapping), JSON array or JSON Lines text, or.json,.jsonl,.ndjson,.txt,.mdand.markdownfile paths, as well asDocumentInfoobjects. Text and markdown files are chunked natively into documents{path}#{n}with metadataparentId. A word longer thanchunk_size(1200 by default), such as a long URL or a run of text without spaces, is split intochunk_sizepieces, so no text is dropped. Markdown front matter (a first---line through the next---or...line) is not indexed.- A keyword-only
chunkerargument on the same methods splits every document’s text with your own function. Passchunkerorchunking, not both: using both raisesTypeError. Neither can be used withmodel_id="custom". moss.Chunkingand a keyword-onlychunkingargument on the same methods tune the native chunker within the embedding model’s limits, with the names and limits ofParseOptions:chunk_size200 to 2000 characters (default 1200),chunk_overlap0 to half ofchunk_size(default 200, capped at half ofchunk_size),mode"pages"or"sentences", andmarkdown_header_depth1 to 6. Withchunking,DocumentInfo, dict and JSON input is chunked too, not only text and markdown files. Out-of-range values raiseInvalidArgumentErrorwithParseOptions-style messages, such asUnsupported chunk_size 100. Supported: 200 to 2000. Chunks from a userchunkerlonger than 2,000 characters raiseInvalidArgumentError.moss.DocsInput,moss.Chunkerandmoss.Chunkingare new exports.
- Requires
inferedge-moss-core0.32.0, which addsmoss_core.parse_documents_jsonandmoss_core.to_document_infos.
- The type stub declares
MossClient.create_index_from_files,ParseFileInputandParseOptions, and its__all__lists them andParentGrouping. It also declaresSearchResult.model_id,IndexStatus.valueand theJobPhase.CRAWLINGandJobPhase.PARSING_DOCUMENTSphases, typescreate_index(..., wait=flag)for aboolflag, and declares fields that are read-only at runtime, such asMutationResult.job_idandSessionIndex.name, as read-only properties. TheLoadIndexesResultarguments no longer acceptNone, which the core refuses. No runtime change. - The type stub marks the classes of the native core, such as
DocumentInfoandQueryOptions, final, since Python cannot subclass them, and declares their constructors with__new__, as the core defines them. No runtime change.
Added
ParseOptions.chunk_size(200 to 2000 characters, default 1200) andParseOptions.chunk_overlap(0 to half ofchunk_size, default 200 capped at half ofchunk_size) control how the parse pipeline splits extracted text. Out-of-range values raiseInvalidArgumentErrorbefore any upload.
- Requires
inferedge-moss-core0.31.0.
Added
ParseOptions.chunkSize(200 to 2000 characters, default 1200) andParseOptions.chunkOverlap(0 to half ofchunkSize, default 200 capped at half ofchunkSize) control how the parse pipeline splits extracted text. Out-of-range values reject before any upload.
- Requires
@moss-js/moss-core0.33.0.
Added
Moss.Client.create_index_from_files/5takes:chunk_size(200 to 2000 characters, default 1200) and:chunk_overlap(0 to half of:chunk_size, default 200 capped at half of:chunk_size) inparse_optionsto control how the parse pipeline splits extracted text. Out-of-range values return{:error, %Moss.Error{code: :invalid_argument}}before any upload.
- Bumped
moss_coredependency to 0.24.0.
Changed
- Requires
inferedge-moss-core0.30.1.
MossClient.query,query_multi_index,unload_index,unload_indexesandwas_served_stalerelease the GIL while they run, so the event loop keeps running other tasks during a query or while an unload waits for one.
Changed
moss_session_add_docsandmoss_session_delete_docsupdate the keyword index in place instead of rebuilding it, and loads build it in one pass. Scores are unchanged.moss_session_add_docschecks a whole batch before changing the session, so a batch with a vector of another length adds nothing.- A session keeps one copy of each document, and adds and loads move documents into the index instead of copying them.
moss_session_load_indexinto a session that holds documents replaces them instead of keeping stale copies.- The token cache keeps a token until 60 seconds before it expires or for 90% of its life, whichever is later, so short-lived tokens are cached too.
- A 401 drops only the token it rejected from the cache, and a refused telemetry request keeps the token.
- A project key session fetches one token for its requests and its telemetry.
moss_session_load_indexandmoss_session_load_from_diskkeep the session’s loaded model when the index uses the same model, instead of loading it again.
Added
SessionIndex.save_to_disk(cache_path)andSessionIndex.load_from_disk(cache_path, *, rebuild_legacy=True)save a session to disk and restore it.save_to_diskwrites the session under<cache_path>/<name>/, and a failed or interrupted save leaves the last saved snapshot loadable.load_from_diskrestores it into a session with the same name and returns the number of documents loaded, and the session takes the snapshot’s model. A session that already loaded the same model keeps it instead of loading it again. A missing or damaged snapshot raisesMossErrorwith codeDESERIALIZATIONand leaves the session as it was. A snapshot that an older core saved for a built-in model has no model artifact identity: by defaultload_from_diskrebuilds it for a session opened with the same model, re-embedding the stored documents and saving the snapshot back in the same call, which needs the cloud for the model. When the model cannot be loaded it raisesMossErrorwith codeMODEL_UNAVAILABLEand changes nothing.rebuild_legacy=Falseloads such a snapshot as a custom-model session. Code that callsload_from_diskon the privateSessionIndex._innergets no rebuild unless it passesrebuild_legacy=True; the public method rebuilds by default.MossClient.session(name, auto_load_on_init=False)opens the session without loading the cloud index of that name. The session starts empty with the given model, soload_from_diskrestores a saved session with no index download. Apush_indexbefore any load replaces the cloud index with the session’s documents.SessionIndex.model_id, the embedding model the session uses, or"custom". A load moves the session to the loaded model, andadd_docsandqueryread it on every call. Reading it never waits for a call in progress, and it still reads afterclose().
- Requires
inferedge-moss-core0.30.0. SessionIndex.add_docsanddelete_docsupdate the keyword index in place instead of rebuilding it, and loads build it in one pass. Scores are unchanged.- Behavior change:
SessionIndex.add_docschecks every document of a call first, so a call with a vector whose length differs from the session’s vectors raisesInvalidArgumentErrorand adds nothing. SessionIndexkeeps one copy of each document, and adds and loads move documents into the index instead of copying them.- The token cache keeps a token until 60 seconds before it expires or for 90% of its life, whichever is later, so short-lived tokens are cached too.
- A 401 drops only the token it rejected from the cache, and a refused telemetry request keeps the token.
- A project key session fetches one token for its requests and its telemetry.
MossClient.sessionmoves the session to the model of an existing cloud index that has no documents, as it does for one with documents. Withoutmodel_id, a session on an empty custom-model index opens and takes embeddings instead of raisingInvalidArgumentErrorwhile it warms the default model, and an explicitmodel_idthe index does not use raisesValueError.- When
MossClient.sessionraises, it closes the session it opened, so the session’s final telemetry is sent and its native memory freed then, not atMossClient.close.
Added
MossModelincludes"moss-litelm", sosession(name, "moss-litelm")type-checks andSessionIndex.modelIdnames every model the core reports.
- Requires
@moss-js/moss-core0.32.0. @moss-js/moss-coreships its native binary only in the@moss-js/moss-core-<platform>package that npm installs for the host as an optional dependency, so an install is about 60 MB smaller. Keep optional dependencies on: after an install withnpm install --omit=optional,optional=falsein.npmrcorpnpm --no-optional, importing@moss-js/mossthrowsCannot find native bindingwith a hint to reinstall without that option. The same happens onnpm cifrom a lockfile that npm older than 11.3 rebuilt whilenode_modulesexisted, because that lockfile keeps only that machine’s platform package. Before installing on another platform, regenerate it withnode_modulesremoved, or with npm 11.3 or newer. No API change.SessionIndex.addDocsanddeleteDocsupdate the keyword index in place instead of rebuilding it, and loads build it in one pass. Scores are unchanged.- Behavior change:
SessionIndex.addDocschecks every document of a call first, so a call with a vector of another length adds nothing. SessionIndexkeeps one copy of each document, and adds and loads move documents into the index instead of copying them.- A token is cached until 60 seconds before it expires or for 90% of its life, whichever is later, for custom authenticators and project keys.
- With a project key, a 401 drops only the token it rejected, and a refused telemetry request keeps the cached token instead of fetching a new one.
- A project key session fetches one token for its requests and its telemetry.
- A session filled by
loadIndexor restored byloadFromDiskkeeps its loaded model when the index uses the same model, instead of loading it again.
loadIndexinto a session that held documents kept them beside the loaded index, andsaveToDiskthen failed. A load now replaces them.- With a custom authenticator, the retry after a 401 resent the same cached token. It now drops the rejected token and asks the authenticator for a new one.
- A client with a custom authenticator kept Node running after
close(). The process now exits once its work is done. - On Windows, a process that first loaded the native addon from a
worker_threadsworker could crash with an access violation when that worker exited. The addon now stays loaded until the process exits, as on Linux and macOS. SessionIndex.modelIdis the model the native core reports after the last completed call, andaddDocsandquerypick their path by it on every call.loadIndexandloadFromDiskmove the session to the model of the index or snapshot they load, which iscustomfor a custom-model one and for a built-in model one without a model artifact identity (such as a legacy snapshot loaded withrebuildLegacy: false), and auto-refresh can install a custom-model version into a built-in model session. After such a change,addDocstakes the documents’ embeddings instead of rejecting, andquerywithout an embedding rejects with codeINVALID_ARGUMENT.
Changed
- Requires
@moss-dev/moss-wasm0.18.0. - Loading an index builds its keyword index in one pass. Scores are unchanged.
- With a project key, a token is cached until 60 seconds before it expires or for 90% of its life, whichever is later.
- With a project key, a request refused with 401, model requests included, drops only the token it sent before it retries.
- Outside Node, the SDK imports
onnxruntime-web/wasminstead of the package default, and it pinsonnxruntime-webto 1.30.0, the version^1.27.0resolved to. A bundled app ships the plainort-wasm-simd-threaded.wasm(14.2 MB, 3.7 MB gzip) instead of the WebGPU buildort-wasm-simd-threaded.jsep.wasm(28.3 MB, 6.7 MB gzip), and about 330 KB less JavaScript. The SDK only runs the wasm execution provider, so embeddings are unchanged. A directory passed asonnxWasmPathmust serveort-wasm-simd-threaded.wasmandort-wasm-simd-threaded.mjsfrom onnxruntime-web 1.30.0; the.jsepfiles are no longer requested. Under Node, including server rendering, the SDK keeps the package default, whose Node build loads the wasm from disk. The choice is the#ortentry of the package’simportsfield, so a bundler must follow that field, as Vite 4.2+ and webpack 5 do; one that does not fails to resolve#ort. No API change.
Added
Moss.Session.save_to_disk/2andMoss.Session.load_from_disk/3save a session to disk and restore it.save_to_disk/2writes the session under<cache_path>/<name>/and returns:ok; a failed or interrupted save leaves the last saved snapshot loadable.load_from_disk/3restores it into a session with the same name and returns{:ok, doc_count}. A missing or damaged snapshot returns{:error, %Moss.Error{code: :deserialization}}and leaves the session as it was. A snapshot that an older core saved for a built-in model has no model artifact identity: by defaultload_from_disk/3rebuilds it for a session opened with the same model, re-embedding the stored documents and saving the snapshot back in the same call, which needs the cloud for the model. When the model cannot be loaded it returns{:error, %Moss.Error{code: :model_unavailable}}and changes nothing.rebuild_legacy: falseloads such a snapshot as a custom-model session. After a load,add_docs/3andquery/3use the model the session took from the snapshot, so a custom-model snapshot needs embeddings.Moss.Client.session/3takesauto_load_on_init: falseto open the session without loading the cloud index of that name. The session starts empty with:model_id, soMoss.Session.load_from_disk/3restores a saved session with no index download.Moss.Session.push_index/1before any load replaces the cloud index with the session’s documents.Moss.Session.model_id/1returns the embedding model the session uses, or"custom". A load moves the session to the loaded model, andadd_docs/3andquery/3read it from the core on every call.
- Bumped
moss_coredependency to 0.23.0. Moss.Session.add_docs/3anddelete_docs/2update the keyword index in place instead of rebuilding it, and loads build it in one pass. Scores are unchanged.add_docs/3checks every document of a call first, so a call with a vector of another length adds nothing.- A session keeps one copy of each document, and adds and loads move documents into the index instead of copying them.
load_index/2into a session that holds documents replaces them instead of keeping stale copies.- The token cache keeps a token until 60 seconds before it expires or for 90% of its life, whichever is later, so short-lived tokens are cached too.
- A 401 drops only the token it rejected from the cache, and a refused telemetry request keeps the token.
- A project key session fetches one token for its requests and its telemetry.
load_index/2keeps the session’s loaded model when the index uses the same model, instead of loading it again.- The precompiled
moss_coreNIFs link the custom-minimal ONNX Runtime that the C, JavaScript and Python SDKs ship, with only the operators the built-in models use, instead of the full runtime. The x86_64 Linux NIF is built on Ubuntu 22.04 and needs glibc 2.35 or newer instead of 2.38. No API change.
- The
reqdependency, which the SDK does not use, and with itfinch,mintandhpax. Their releases with published security advisories no longer reach an app through the SDK. An app that usedreq, or one of its dependencies, through the SDK must declare it in its ownmix.exs.
Moss.Session.load_index/2moves the session to the model of the index it loads, asload_from_disk/3does, so after a custom-model index, or a built-in model index without a model artifact identity, loads into a built-in model session,add_docs/3takes the documents’ embeddings instead of failing andquery/3without an embedding returns{:error, %Moss.Error{code: :invalid_argument}}. Without:model_id,Moss.Client.session/3resumes such an index, an empty one included, instead of returning an error while it warms the default model. An explicit:model_idthe index does not use returns{:error, %Moss.Error{code: :invalid_argument}}with a message that names both models.
Changed
- Keyword index updated in place.
MossSession.addDocsanddeleteDocsno longer rebuild it, andloadIndexandloadFromDiskbuild it in one pass. Scores are unchanged. - Failed adds change nothing.
addDocswith a vector of another length adds none of its documents. - One copy of each document. Adds and loads move documents into the index.
loadIndexreplaces documents a session already held.- Short-lived tokens are cached until 60 seconds before expiry or for 90% of their life, whichever is later.
- A 401 drops only the rejected token, and a refused telemetry request keeps it.
- One token per session open for a project key session’s requests and telemetry.
loadIndexandloadFromDisk(cachePath:)keep the session’s model when the index uses the same model, instead of loading it again.
sdkVersion: 0.25.0.Added
moss loginlogs in through the browser and saves a CLI token to~/.moss/config.json.moss logoutrevokes the saved token and removes it, andmoss whoamishows the account the token belongs to.moss projects listlists the projects in the workspaces you belong to, with your role in each.moss keys create,listanddeletemanage project keys with the CLI token (--jsonfor agents).createshows the secret once, anddeleteasks first unless--confirm/-yor--jsonis passed.moss login --print-token --name ...prints a separate token for an agent instead of saving it, and keeps your saved login.--token/MOSS_TOKENpasses a CLI token, for agents, and--api-url/MOSS_API_URLpointslogin,whoami,projectsandkeysat another dashboard, such as staging. The saved token is only sent to the dashboard that issued it.
moss initkeeps a token saved bymoss logininstead of overwriting the whole config file.- Requires
typer0.26.8 or later andrich15.0.0 or later.
- The
--cloud/-cflag onmoss query. The cloud query service it targeted has been retired, somoss queryalways downloads the index and queries it on-device (the previous default).
- A failing command prints only its error message, not a Python traceback.
Portal
Founding Agent widget teaser
- A new Widget teaser setting on the agent’s Agent tab shows a short message (up to 80 characters) above the idle widget on your site. Requires
@moss-js/founding-agent2.3.0.
- Agents open on their Agent settings, and the Overview page is removed.
Added
- Teaser: when the agent has one set in the portal, the bubble shows a short message above the idle orb. It is a frosted card with a tail toward the orb that appears after a short pause (no entrance animation under reduced motion). Clicking anywhere on it starts the conversation and its X closes it; either keeps it hidden for the rest of the browser session. It never shows during a call. The text is set in Geist Mono at 15px, loaded from jsDelivr only when a teaser shows and falling back to the system monospace if blocked.
PublicConfig.teasercarries it, normalized on fetch. - New
@moss-js/founding-agent/coreexports fromteaser:normalizeTeaser(fail-closed: only an enabled teaser with 1 to 80 characters of text survives),isTeaserDismissed,dismissTeaser,loadTeaserFont,TEASER_FONT_FAMILYandTEASER_MAX_LENGTH.TeaserConfigis exported from/reacttoo.
Fixed
moss_session_push_indexon a session with a built-in model (moss-minilm,moss-mediumlm,moss-litelm) sends that model’s id, so the service re-embeds the text with it and the pushed index loads and answers text queries like one built withmoss_client_create_index. It used to be stampedcustom, so a pushed session could not be resumed with text queries. A custom-model session still pushes its own embeddings.
Fixed
SessionIndex.push_index()on a session with a built-in model (moss-minilm,moss-mediumlm,moss-litelm) sends that model’s id, so the service re-embeds the text with it and the pushed index loads and answers text queries like one built withcreate_index. It used to be stampedcustom, so a pushed session could not be resumed with text queries. A custom-model session still pushes its own embeddings. Requiresinferedge-moss-core0.28.1.
Fixed
SessionIndex.pushIndex()on a session with a built-in model (moss-minilm,moss-mediumlm,moss-litelm) sends that model’s id, so the service re-embeds the text with it and the pushed index loads and answers text queries like one built withcreateIndex. It used to be stampedcustom, so a pushed session could not be resumed with text queries. A custom-model session still pushes its own embeddings. Requires@moss-js/moss-core0.31.1.
Changed
- Bumped
moss_coredependency to 0.22.1.
Moss.Session.push_index/1on a session with a built-in model (moss-minilm,moss-mediumlm,moss-litelm) sends that model’s id, so the service re-embeds the text with it and the pushed index loads and answers text queries like one built withMoss.Client.create_index/4. It used to be stampedcustom, so a pushed session could not be resumed with text queries. A custom-model session still pushes its own embeddings.
Fixed
MossSession.pushIndex()on a session with a built-in model (moss-minilm,moss-mediumlm,moss-litelm) sends that model’s id, so the service re-embeds the text with it and the pushed index loads and answers text queries like one built withcreateIndex. It used to be stampedcustom, so a pushed session could not be resumed with text queries. A custom-model session still pushes its own embeddings. Native runtimemoss-c0.24.1.
The first C SDK release since
c-sdk-v0.9.0, which it supersedes. Manifest versions 0.9.2 through 0.23.0 were never published as C SDK archives, so 0.9.0 is the only earlier build in use.Changed- Built-in models (
moss-minilm,moss-mediumlm,moss-litelm) download from the Moss cloud in the native model format, and this build no longer reads the model files 0.9.0 downloaded. Loading a built-in model needs the Moss cloud to be reachable; thecustommodel still takes caller embeddings and downloads nothing. libmoss.so,libmoss.dylibandmoss.dllexport exactly themoss_*functions declared inlibmoss.hand nothing else.- Each archive ships
include/libmoss.hand the shared library, plus the import librarylib/moss.dll.libon Windows. The static libraries (libmoss.a,moss.lib) are no longer included. - The macOS dylib has the install name
@rpath/libmoss.dylib: link with an-rpaththat resolves to the archive’slib/, for example-Wl,-rpath,@loader_path/lib. - The Linux builds support glibc 2.35 and newer on x86_64, and glibc 2.39 and newer on aarch64.
Added
MossClient.close()andSessionIndex.close(), and both work aswithandasync withcontext managers.close()sends the final usage telemetry, waiting until it is delivered or 2 seconds pass, and frees the native memory;MossClient.close()also closes the sessions the client opened. Afterwards everyMossClientmethod raisesRuntimeError("MossClient is closed")and everySessionIndexmethod butnameraisesInvalidArgumentError. Requiresinferedge-moss-core0.27.0.moss.MossError, aRuntimeErrorsubclass raised for every failure the native core reports.codeis a stable string to branch on:INVALID_ARGUMENT,NOT_FOUND,UNAUTHORIZED,NETWORK,DESERIALIZATION,MODEL_UNAVAILABLEorINTERNAL.moss.InvalidArgumentErroris theINVALID_ARGUMENTsubclass and is also aValueError.detailholds the core error text in released wheels too: diagnostic text for logs and support, at most 512 bytes, and not a stable contract. Requiresinferedge-moss-core0.27.0.LoadIndexesResult.failed_codesmaps each index thatload_indexescould not load to its code, such as"NOT_FOUND". Requiresinferedge-moss-core0.27.0.
MossError.detailcarries no request URL for a cloud or model download error: a cloud timeout, retry or response parse failure names the operation, such asget_index_info, and a model download names only the host. Cache, repair, snapshot andMOSS_CA_BUNDLEerrors name the file, not its absolute path. Parser text from.mosspayloads and from release and manifest files goes to the debug log, and ONNX Runtime and tokenizer failures give fixed text. A failed response contributes only its HTTP status and the error code its body names, such asHTTP 403 Forbidden: AccessDeniedfrom the object store orHTTP 409 Conflict: INDEX_EXISTSfrom the Moss service, never the rest of the body. A.mosspayload whose JSON does not parse, or whose document count does not match its header, gives the detailindex payload is malformed; header and length errors keep their own short text, such asbinary data truncated. A lock left unusable by an earlier panic raisesMossErrorwith codeINTERNALand the detailinternal state is unavailable after an earlier failure, also when an embedding model load hits it.MossError.detailnames a numbered fault for a damaged on-device vector file or session snapshot, such asfault 1028for a vector count that differs from the snapshot metadata, and no longer describes the file layout or the snapshot files. Build the core with itsdiagnosticsCargo feature to add the description.- Behavior change: error messages from the native core are fixed text per kind of failure, such as
Index not found.orThe Moss service could not be reached., and no longer carry URLs, file paths or index names. Code that matched on message text should branch onMossError.code. A failedload_indexorunload_indexnow raises the core’sMossErrordirectly instead of wrapping it in aRuntimeErrorthat names the index. A text query on an index that cannot embed it (a custom-embedding index, or a foundation index without an artifact identity) raisesInvalidArgumentError, still aValueError, with the core’s message. The reasons inload_indexes().failedare the same fixed messages.queryon an index that is not loaded raisesMossErrorwith codeNOT_FOUND, still aRuntimeError, and its message still names the load call. - Behavior change: only
INVALID_ARGUMENTfailures are still aValueError. These session failures wereValueErrorand are now aMossError(aRuntimeError) with the code shown: a rejected project key when opening a session (UNAUTHORIZED), a service or network failure when opening one (NETWORKor another cloud code), a model that cannot be downloaded or loaded duringadd_docsorquerywith text (MODEL_UNAVAILABLE), and an embedding failure during those calls (INTERNAL). Code that catchesValueErroraround these calls should catchMossErroras well. - Built-in model loads (
moss-minilm,moss-mediumlm,moss-litelm) are faster, most of all on arm64. No API change. Requiresinferedge-moss-core0.27.0. SessionIndex.add_docson a session with a built-in model embeds the documents in batches of at most 8,192 padded tokens, grouped by length, instead of one batch padded to the longest document. Large calls need far less memory and time: on an Apple M2, 5,000 short captions in one call took about 20 s with a 0.6 GB peak instead of about 119 s and 9.1 GB. A query embedding for the same model waits for one batch instead of the whole call. Embeddings come back in input order, with the same values to about 1e-7. Requiresinferedge-moss-core0.27.0.- Behavior change: a malformed
$nearfilter value is rejected with aValueErrornaming the expected"lat,lng,maxDistanceMeters"format instead of matching nothing. - Breaking change:
$gt,$gte,$ltand$ltecompare two plain decimals ("42","-3.5") as numbers and two other values as text, and never match a plain decimal against any other value. Zero padded numbers such as"07"and forms such as"1e3"or"NaN"are text, so"07"no longer matches$gt: "5"and"naming"never matches$gt: "999999". Sortingget_docsby a field (sort_by) and assembling aParentGroupingbyorder_fieldput decimals first in numeric order, zero padded ones included, so"099"sorts before"100", then every other value in text order, forms such as"1e3"or"NaN"included. A condition still never matches a document that lacks the field,$neand$ninincluded. - Filter validation and ordering come from
inferedge-moss-core0.27.0. - Behavior change:
query_multi_index([])andquerywithout an embedding on a custom-model session raiseInvalidArgumentError, still aValueError, with codeINVALID_ARGUMENT. A malformed metadata filter that raised a plainValueErrorraisesInvalidArgumentErrorwith the same text; a filter value of the wrong type still raisesTypeError.InvalidArgumentError.codeis"INVALID_ARGUMENT"on the class too. - A load with a cache path that finds no usable snapshot while the Moss service is unreachable reports
NETWORKinstead ofDESERIALIZATION. An auth URL that answers 404 or 410 reportsINTERNALinstead ofNOT_FOUND. A refused index name keeps the naming rule as its message, and a file with an unsupported content type readsA file has an unsupported content type.A text call on a session whose model cannot embed raisesInvalidArgumentErrorwith the messageThis session's model cannot embed text. Pass embeddings with the documents and the query. IndexManager.querywith an empty query embedding runs keyword-only atalpha0, asquery_multi_indexdoes, and raisesInvalidArgumentErrorat a higheralphaon an index that holds vectors.
- Usage telemetry that fails to upload is retried on the next flush, every event under a stable
eventId, for up to an hour and 20,000 events, instead of being dropped. A client or session garbage collected withoutclose()blocks for at most 500 ms on its final flush instead of without limit. Requiresinferedge-moss-core0.27.0. load_indexwithauto_refresh=TruecomparesupdatedAtas a point in time, so two spellings of one instant are no change, and a tick that finds a new snapshot fetches the index metadata once instead of twice. After aload_indexserved stale fromcache_path, the first auto refresh that reaches the cloud warms the embedding model even when the snapshot is unchanged. Requiresinferedge-moss-core0.27.0.- A query whose stored vectors have another length than the query raises
MossErrorwith codeINTERNALinstead of ranking those documents with score 0.Index.serializeininferedge-moss-coreraisesValueErrorfor a vector it cannot read. Requiresinferedge-moss-core0.27.0.
Added
isMossError(error)and theMossError/MossErrorCodetypes. An error from the native core is anErrorwhosecodeis one ofINVALID_ARGUMENT,NOT_FOUND,UNAUTHORIZED,NETWORK,DESERIALIZATION,MODEL_UNAVAILABLEorINTERNAL; branch oncodeinstead of the message.detailholds the core error text, diagnostic text for logs and support rather than a stable contract. Requires@moss-js/moss-core0.31.0.LoadIndexesResult.failedCodesmaps each index thatloadIndexescould not load to itsMossErrorCode. Requires@moss-js/moss-core0.31.0.
- Behavior change: errors from the native core carry fixed messages per kind of failure, such as
Index not found., with no URLs, file paths or index names. The reasons inloadIndexes().failedare the same fixed messages.queryon an index that is not loaded rejects with codeNOT_FOUND, and its message still names the load call.queryMultiIndexon an index that cannot embed text rejects with the core’s own error (codeINVALID_ARGUMENT, messageThis index cannot embed text queries. Pass a query embedding, or use alpha 0 for keyword-only search.) instead of rewording it. - Built-in model loads (
moss-minilm,moss-mediumlm,moss-litelm) are faster, most of all on arm64. No API change. Requires@moss-js/moss-core0.31.0. SessionIndex.addDocson a session with a built-in model embeds the documents in batches of at most 8,192 padded tokens, grouped by length, instead of one batch padded to the longest document. Large calls need far less memory and time: on an Apple M2, 5,000 short captions in one call took about 20 s with a 0.6 GB peak instead of about 119 s and 9.1 GB. A query embedding for the same model waits for one batch instead of the whole call. Embeddings come back in input order, with the same values to about 1e-7. Requires@moss-js/moss-core0.31.0.- Behavior change: a malformed
$nearfilter value is rejected with an error naming the expected"lat,lng,maxDistanceMeters"format instead of matching nothing. - Breaking change:
$gt,$gte,$ltand$ltecompare two plain decimals ("42","-3.5") as numbers and two other values as text, and never match a plain decimal against any other value. Zero padded numbers such as"07"and forms such as"1e3"or"NaN"are text, so"07"no longer matches$gt: "5"and"naming"never matches$gt: "999999". A number in a filter is compared in its plain decimal form, so0.000001still orders as a number. A condition still never matches a document that lacks the field,$neand$ninincluded. - Behavior change: saving a session keeps vectors that were loaded as INT8 in INT8. It used to widen them to FP32, a file about four times larger with no gain in precision.
- Filter validation and ordering come from
@moss-js/moss-core0.31.0. queryMultiIndex([])andSessionIndex.querywithout an embedding on a custom-model session throw anErrorwith codeINVALID_ARGUMENT, soisMossErroraccepts them.- A load with a cache path that finds no usable snapshot while the Moss service is unreachable reports
NETWORKinstead ofDESERIALIZATION. An auth URL that answers 404 or 410 reportsINTERNALinstead ofNOT_FOUND. A refused index name keeps the naming rule as its message, and a file with an unsupported content type readsA file has an unsupported content type.Requires@moss-js/moss-core0.31.0.
MossClient.close()andSessionIndex.close()resolve once the final usage telemetry is delivered or 2 seconds pass, retrying a failing endpoint in that time, so a process that exits right afterawait client.close()reports its last queries. Telemetry a periodic flush could not deliver is retried on the next flush instead of dropped. Requires@moss-js/moss-core0.31.0.loadIndexwithautoRefreshand session auto refresh compareupdatedAtas a point in time, so two spellings of one instant are no change, and a tick that finds a new snapshot fetches the index metadata once instead of twice. After aloadIndexserved stale fromcachePath, the first auto refresh that reaches the cloud warms the embedding model even when the snapshot is unchanged. Requires@moss-js/moss-core0.31.0.- A query whose stored vectors have another length than the query rejects with code
INTERNALinstead of ranking those documents with score 0. Requires@moss-js/moss-core0.31.0.
Added
- Usage telemetry, always on, as in the native SDKs: it carries the query counts Moss bills, and there is no option to turn it off. The client sends its query count every 3 seconds while there are new queries, on
dispose()and onpagehide, withkeepalivewhen the bodies fit in about 60 KB shared by the page, as anindex.usage.periodic_flushorindex.usage.final_flushbody andindex.queryandindex.query_multievents in JSON arrays of up to 500, the bodies the native SDKs send. The client gets a token before each timer send, and every 30 seconds while there are no new queries, the way its other requests do: a cached token costs no request, and a token that is not cached is agetAuthToken()call. Counts wait until the first token request succeeds. Every event carries adeviceId: a random UUID kept inlocalStorageundermoss-device-id, or an id for the page, worker or process alone where storage is missing or throws. A query costs one counter increment. The README lists the events and fields. Requires@moss-dev/moss-wasm0.17.0; 0.16.0 sends no telemetry. loadIndexesresults carry afailedCodesmap from each failed index name to its stable code, such asNOT_FOUNDorNETWORK, next to the message infailed. A failure without a code, such as one raised by an older@moss-dev/moss-wasm, has no entry.
- Behavior change: failures from the WASM core reject with an
Errorinstead of a plain string. Itscodeis a stable string:INVALID_ARGUMENT,NOT_FOUND,UNAUTHORIZED,NETWORK,DESERIALIZATION,MODEL_UNAVAILABLEorINTERNAL. The message is fixed text per kind of failure, such asIndex not found., with no URLs or index names;@moss-dev/moss-wasmadds the core error text asdetailin release builds too, which names the cloud operation instead of the request URL and keeps only the HTTP status and error code of a failed response.detailis diagnostic text for logs and support, at most 512 bytes, and not a stable contract. The WASMquery,queryWithModelIdentity,queryMultiIndexandqueryMultiIndexWithModelIdentityaccept a missing (nullorundefined) query embedding and reject with a coded error when the query needs one, instead of aTypeErrorfrom the generated glue. Requires@moss-dev/moss-wasm0.17.0. - A
ModelDeliveryErrorfrom a model artifact transfer names the file and host, such as'model.mossml' from models.moss.link, instead of the full artifact URL. - Opening
moss-minilmin Node 24 on an Apple M2 takes about 90 ms instead of about 1.9 s, and a whole model load from memory about 0.3 s instead of about 2.1 s. The model no longer passes through wasm memory, which stays near 9 MB instead of growing past 95 MB. Where Web Crypto is unavailable, as on a plain HTTP page, the SDK opens the model in wasm. Requires@moss-dev/moss-wasm0.17.0; with 0.16.0 the SDK opens the model as before. No API change. - The embedding model is hashed once per page load: with
@moss-dev/moss-wasm0.17.0 the SDK does not hash it again in wasm. Where the SDK opens the model in wasm, openingmoss-minilmin V8 on an Apple M2 takes about 1.6 s instead of about 2.5 s. With 0.16.0 the SDK opens the model as before. No API change. - Where the SDK opens the embedding model in wasm, the load holds one full size copy of it in wasm memory instead of three, which lowers peak wasm memory. Requires
@moss-dev/moss-wasm0.17.0. No API change. - Behavior change: metadata filters validate
$near. The value must be"lat,lng,maxDistanceMeters"; anything else, such as a bare number or a"lat,lng"pair, makes the query fail with an error naming that format instead of matching nothing. The$neartype isstring, so a bare number no longer type checks. - Breaking change:
$gt,$gte,$ltand$ltecompare two plain decimals ("42","-3.5") as numbers and two other values as text, and never match a plain decimal against any other value. Zero padded numbers such as"07"and forms such as"1e3"or"NaN"are text, so"07"no longer matches$gt: "5"and"naming"never matches$gt: "999999". A number in a filter is compared in its plain decimal form, so0.000001still orders as a number. A zip code such as"01234"no longer passes$gt: "1000"or$lt: "1000". The README notes the ordering rule, the$nearformat and the rule that a condition never matches a document lacking the field,$neand$ninincluded. Requires@moss-dev/moss-wasm0.17.0. - A malformed metadata filter or query tuning passed to the WASM query methods rejects with code
INVALID_ARGUMENTand the parser’s reason as the message, such as$and value must be an array. Malformed documents and files keep a fixed message, with the reason indetail. A presigned upload answered with a 4xx other than 401 or 403 rejects with that status’s code, such asINVALID_ARGUMENTfor 413, instead ofNETWORK.queryandqueryWithModelIdentitywith a missing embedding run keyword-only atalpha0, as the multi-index calls do. Requires@moss-dev/moss-wasm0.17.0. - An auth URL that answers 404 or 410 reports
INTERNALinstead ofNOT_FOUND, and a refused index name keeps the naming rule as its message.
autoRefreshtakes effect:loadIndex(name, { autoRefresh: true })refreshes the index everypollingIntervalInSeconds(600 when unset or 0, at least 1) until it is unloaded, loaded again withoutautoRefresh, or the client is disposed. A negative or non-finite interval is rejected before loading. The option used to be accepted and ignored. Requires@moss-dev/moss-wasm0.17.0: an older one would download the whole index on every tick, so with itautoRefreshstays off, the index still loads, and the client logs one warning.onProgresstakes effect:createIndex,createIndexFromFiles,addDocsanddeleteDocscallonProgresswith each job status they poll. An exception thrown by the callback, or a rejected promise it returns, is ignored. With a@moss-dev/moss-wasmthat cannot report progress, passingonProgressthrows before the job starts. A nullonProgresscounts as none. Requires@moss-dev/moss-wasm0.17.0.refreshIndexreports real changes: when the cloud snapshot is no newer than the loaded one and uses the same model,refreshIndexdownloads nothing and returnswasUpdated: false. It used to download the whole index and returnwasUpdated: trueevery time. Requires@moss-dev/moss-wasm0.17.0.- A query whose stored vectors have another length than the query rejects with code
INTERNALinstead of ranking those documents with score 0. Requires@moss-dev/moss-wasm0.17.0.
Added
Moss.Session.close/1,Moss.IndexManager.close/1andMoss.Client.close/1send the final usage telemetry, waiting until it is delivered or 2 seconds pass, and stop the process. Closing a process that already stopped returns:ok.Moss.LoadIndexesResulthasfailed_codes, mapping each name that did not load to the same code atomMoss.Errorcarries. The reasons infailedare the fixed messages, with no URLs, file paths or index names.
- Bumped
moss_coredependency to 0.22.0. - Behavior change:
Moss.SessionandMoss.IndexManagertrap exits, so a supervisor shutdown or the abnormal exit of a linked process runs the same close before the process stops. A process that starts one withstart_link/1closes it when it exits, even normally.Moss.Client.new/3andMoss.Client.session/3start unlinked and then link, so a normal exit of their caller leaves the manager and the session running as before. - Breaking: every
{:error, reason}from this SDK carries a%Moss.Error{}instead of a binary.codeis an atom to match on::invalid_argument,:not_found,:unauthorized,:network,:deserialization,:model_unavailableor:internal.messageis fixed text per kind of failure (for example"Index not found.") with no URLs, file paths or index names, anddetailholds the native error text in release and debug NIF builds alike: diagnostic text for logs and support, at most 512 bytes, and not a stable contract. That text names the operation or host in place of a request URL, and the file in place of an absolute path. A failed response contributes only its HTTP status and the error code its body names, such asHTTP 403 Forbidden: AccessDeniedfrom the object store orHTTP 409 Conflict: INDEX_EXISTSfrom the Moss service, never the rest of the body.Moss.Erroris an exception and implementsString.Chars, soraise reason,Exception.message(reason),inspect(reason)and"#{reason}"keep working; code that treatsreasonas a binary (reason <> ...,reason =~ ...,when is_binary(reason)) must readreason.messageor match onreason.codeinstead. Option errors the NIF raises itself (parse_options, metadata filters, file maps) keep their descriptive text as themessagewith code:invalid_argument. A text query on an index that cannot embed text returns the core’s message,"This index cannot embed text queries. Pass a query embedding, or use alpha 0 for keyword-only search.", instead of a reworded one. The NIF no longer uses RustDebugformatting for error text. - The
detailfor a damaged on-device vector file or session snapshot names a numbered fault, such asfault 1028for a vector count that differs from the snapshot metadata, and no longer describes the file layout or the snapshot files. Build the core with itsdiagnosticsCargo feature to add the description. - Built-in model loads (
moss-minilm,moss-mediumlm,moss-litelm) are faster, most of all on arm64. No API change. Moss.Session.add_docs/3on a session with a built-in model embeds the documents in batches of at most 8,192 padded tokens, grouped by length, instead of one batch padded to the longest document. Large calls need far less memory and time: on an Apple M2, 5,000 short captions in one call took about 20 s with a 0.6 GB peak instead of about 119 s and 9.1 GB. A query embedding for the same model waits for one batch instead of the whole call. Embeddings come back in input order, with the same values to about 1e-7.- Behavior change: a malformed
$nearfilter value is rejected with an error naming the expected"lat,lng,maxDistanceMeters"format instead of matching nothing. - Breaking change:
$gt,$gte,$ltand$ltecompare two plain decimals ("42","-3.5") as numbers and two other values as text, and never match a plain decimal against any other value. Zero padded numbers such as"07"and forms such as"1e3"or"NaN"are text, so"07"no longer matches$gt: "5"and"naming"never matches$gt: "999999". A condition still never matches a document that lacks the field,$neand$ninincluded. - A load with a cache path that finds no usable snapshot while the Moss service is unreachable reports
:networkinstead of:deserialization. An auth URL that answers 404 or 410 reports:internalinstead of:not_found. A refused index name keeps the naming rule as its message, and a file with an unsupported content type readsA file has an unsupported content type.A text call on a session whose model cannot embed returns:invalid_argumentwith the message"This session's model cannot embed text. Pass embeddings with the documents and the query."
- Usage telemetry that fails to upload is retried on the next flush, every event under a stable
eventId, for up to an hour and 20,000 events, instead of being dropped. load_index/3on amoss-minilmormoss-mediumlmindex returns{:ok, info}instead of{:error, reason}when the cloud is unreachable and it serves a:cache_pathsnapshot. The core warms the model inside the load and tolerates a warm that fails offline, so the SDK makes no second warm call after the load. The embedding model cannot be opened until the Moss cloud is reachable, so text queries withalphaabove 0 fail until then. Keyword-only queries (alpha: 0.0) and queries that pass an:embeddingkeep working, and a later refresh or query warms the model once the cloud returns.refresh_index/2downloads nothing and returnswas_updated: falsewhen the cloud snapshot is no newer than the loaded one and uses the same model. It used to download the whole index and returnwas_updated: trueevery time. On an index served stale from its cache, such a refresh still warms the embedding model.- A query whose stored vectors have another length than the query returns
{:error, %Moss.Error{code: :internal}}instead of ranking those documents with score 0.
Added
MossErrorcode constants anddetail.MossError.notFound,.unauthorized,.network,.invalidArgument,.modelUnavailable,.deserialization,.internalErrorand.nullPointername the libmoss result codes, so callers can compareerror.codewithout literals.MossError.detailcarries the core error text when the linked libmoss exportsmoss_last_error_detail, release builds included, or the Foundation error when the model cache directory cannot be created, and isnilotherwise. It is diagnostic text for logs and support, at most 512 bytes, and not a stable contract. It names the operation or host in place of a request URL, and the file in place of an absolute path. A failed response contributes only its HTTP status and error code, such asHTTP 403 Forbidden: AccessDenied. A lock left unusable by a panic readsinternal state is unavailable after an earlier failure.LoadIndexesResult.failedCodes.loadIndexesmaps each index it could not load to itsMossErrorcode, next to the message infailed. The message is the same fixed text a thrownMossErrorcarries. Empty when the linked libmoss does not report codes.
close()delivers the final usage telemetry within 2 seconds.MossClient.close()andMossSession.close(), anddeinit, wait until the final flush is delivered or 2 seconds pass, retrying a failing endpoint in that time, instead of blocking without limit on a slow one. Telemetry a periodic flush could not deliver is retried on the next flush instead of dropped.- Behavior change:
MossError.codefollows the kind of failure instead of the call that failed. A missing index isnotFound(-4), a rejected project key or token isunauthorized(-8, new), an unreachable or unresponsive service isnetwork(-3), and undecodable data isdeserialization(-9, new). A load or query used to report -3 for all of these.messageis fixed text for each kind and carries no URLs, file paths or index names. A call that reports success but hands back no result throwsinternalError(-7) with its own message instead of repeating an earlier call’s error text. MossError.detailnames a numbered fault for a damaged on-device vector file or session snapshot, such asfault 1028for a vector count that differs from the snapshot metadata, and no longer describes the file layout or the snapshot files. A releaseMoss.xcframeworkcarries none of that description.- Faster foundation model loads. On an Apple M2, preparing a downloaded
moss-minilmtakes about 0.14 s instead of about 1.85 s. No API change. MossSession.addDocsembeds large calls in batches. A session with a built-in model embeds the documents in batches of at most 8,192 padded tokens, grouped by length, instead of one batch padded to the longest document. On an Apple M2, 5,000 short captions in one call took about 20 s with a 0.6 GB peak instead of about 119 s and 9.1 GB. A query embedding for the same model waits for one batch instead of the whole call. No API change.- Behavior change: a
Filter.nearwith a non-finite coordinate or a negative distance, or a raw filter with a malformed$nearvalue, is rejected with an error naming the expected"lat,lng,maxDistanceMeters"format instead of matching nothing. - Breaking change:
$gt,$gte,$ltand$ltecompare two plain decimals ("42","-3.5") as numbers and two other values as text, and never match a plain decimal against any other value. Zero padded numbers such as"07"and forms such as"1e3"or"NaN"are text, so"07"no longer matches$gt: "5"and"naming"never matches$gt: "999999". SortinggetDocsby a field (sortBy) and assembling aParentGroupingbyorderFieldput decimals first in numeric order, zero padded ones included, so"099"sorts before"100", then every other value in text order, forms such as"1e3"or"NaN"included. A number in a filter is compared in its plain decimal form, so0.000001still orders as a number. A condition still never matches a document that lacks the field,$neand$ninincluded. - A load with a cache path that finds no usable snapshot while the Moss service is unreachable reports
networkinstead ofdeserialization. An auth URL that answers 404 or 410 reportsinternalErrorinstead ofnotFound. A refused index name keeps the naming rule as its message, and a file with an unsupported content type readsA file has an unsupported content type.
loadIndexwith a cache path checks the cached vector file against the index. A.mossvecthat holds as many vectors of the same size as the index, but other vectors, such as another index’s file copied over it, is left unused and the index answers from memory. The check compares the first, middle and last vector. Requires aMoss.xcframeworkbuilt from the matching libmoss.- A local custom session stays custom when it loads a foundation snapshot. To serve text queries from a restored foundation snapshot, open the session with the index’s foundation
modelId, for exampleSessionOptions(modelId: "moss-minilm", autoLoadOnInit: false). Its constructor confirms the credentials with one token request, so it needs the network when the session opens, andloadFromDiskthen restores the saved model from disk with no download. A session opened withSessionOptions(modelId: "custom", autoLoadOnInit: false)skips that check, and itsloadFromDiskadopts a foundation model named by the snapshot only afterloadIndexhas confirmed the credentials in the same session. Before that the snapshot loads ascustomand text queries need explicit embeddings. Saving such a session before it changes any document keeps the snapshot’s foundation model on disk. CallingloadIndexagain also restores text queries, but it downloads the whole index. MossClient.createIndexandaddDocsrefuse a document id holding U+0000. They check their ids asdeleteDocsdoes and throwMossErrorwith code-2before any native call. The cloud stored such an id intact,deleteDocscould not remove it, andqueryafterloadIndexreturned it as an empty id.refreshIndexreports real changes. When the cloud snapshot is no newer than the loaded one and uses the same model,refreshIndexdownloads nothing and returnswasUpdatedfalse. It used to download the whole index and return true every time. On an index served stale from its cache, such a refresh still warms the embedding model.- Stored vectors the core cannot score fail the query. A query whose stored vectors have another length than the query throws
MossErrorwith codeinternalError(-7). A release build used to rank those documents with score 0, and a debug build crashed. Load and add refuse such vectors, so only a fault inside the SDK reaches this. A v1 vector file that declares INT8 vectors is refused at load.
sdkVersion: 0.24.0.Changed
- Depends on
@moss-js/moss^1.15.0 instead of@inferedge/moss, with no pinnedoverrides, and requires Node 20.4 or newer. There is no musl build, so Alpine is not supported. On Linux, x64 needs glibc 2.35 or newer and arm64 needs glibc 2.39 or newer. querytakes an optionalalphafrom 0 to 1.alpha: 0is keyword only and skips local embedding. At the defaultalpha,queryreturns an error for a custom-model index or an older index without a model artifact identity, andalpha: 0still searches them.- The SDK-backed tools read
MOSS_INDEX_URLandMOSS_AUTH_URLinstead ofMOSS_CLOUD_API_MANAGE_URLandMOSS_CLOUD_QUERY_URL. - On stdin end, SIGINT or SIGTERM the server closes the SDK client, which sends its final telemetry, and exits within 8 seconds. On stdin end it first waits for running tool calls.
Portal
New onboarding
- Sign-up asks what you are building and which stack you use, then opens a ready-made index in your project so you can search it right away. Just exploring? opens the demo directly.
- Ready to use your own data? builds your first index from a website or from PDF and DOCX files without leaving onboarding, or keeps the sample data for now.
- Connect your app shows install, credentials, and a first search for your language against the index you just built. Create key mints a project key in place (shown once), and your app’s first query is detected automatically.
- Every index page has a Connect tab with the install, keys, and first-search guide, replacing Quick Start under Settings.
- The new-agent setup starts with What are you building? (optional), which shapes the drafted greeting, instructions, and suggested questions. The knowledge step lists the pages read from your website and the Q&A or text you added, editable in place.
- New Suggested questions step: about five questions visitors are likely to ask, each with an answer drafted from your website. Accept, edit, delete, or skip each one; accepted ones are saved as Q&A.
- Each agent opens on an Overview with conversations, leads, high-intent conversations, meetings booked, and unanswered questions, plus one suggested next action.
Portal
Changed
- Two-factor codes are entered one digit per box. Pasting a code or letting your phone fill it in still works.
- Switching between the Developer Portal and Founding Agent is faster: the sidebar shows at once and the page loads behind it.
- The Playground shows a score next to each result, and the dashboard no longer downloads the embedding model on every visit. Indexes built with an older SDK that does not record its model cannot be searched in the Playground.
- The Founding Agent install snippet installs
@moss-js/founding-agentwith the packages the widget needs and includes the Tailwind setup its styling depends on.
Portal
Founding Agent Knowledge tab
- Add website crawls a site into the agent’s knowledge, with a page limit, live progress, re-crawl, and remove. Bare domains like
docs.example.comare accepted. - Add files uploads up to 10 PDF or DOCX files (20 MB each, 50 MB total). My files are scanned runs OCR and is available on paid plans.
- The tab is organized into Websites, Uploaded files, and Everything the agent knows. Long pages collapse with Show full page, and Q&A changes show up right away.
Added
MossClient(cache_path=...)sets a client-level defaultcache_pathforload_index/load_indexes, the directory for the on-disk index cache and the.moss-device-idfile. A per-callcache_pathoverrides it. With neither, indexes are not cached on disk and the device id stays in~/.moss. Parity with the JS SDK’sMossClientOptions.cachePath.- Offline-tolerant
load_indexandload_indexes. With acache_pathand a snapshot already on disk, a load whose cloud metadata check cannot reach the cloud, times out, or gets a 408, 429, 500, 502, 503 or 504 (only a 408, 429, 500 or 503 from the auth service) serves the cached snapshot instead of failing, probes the cloud with a few-second budget rather than the full retry window, and starts a refresh poller so the index self-heals when the cloud returns. A 401, 403 or real 404 still fails, so a forbidden or deleted index does not resurrect from cache. A snapshot written by 1.13.0 or earlier is not served until the index is downloaded again, which happens when the cloud copy changes. A snapshot fetched under another project or cloud origin is never served.MossClient.was_served_stale(name)reports whether an index is currently served from such a snapshot. The index loads, but a built-in embedding model cannot be opened until the Moss cloud is reachable, so text queries withalphaabove 0 fail until then. Keyword-only queries (alpha == 0) and queries that pass their ownembeddingkeep working, and a later refresh or query warms the model once the cloud returns. Requiresinferedge-moss-core0.26.0 (was_served_staleonIndexManager). QueryOptions.min_scoredrops results whosescoreis below it; a query returns up totop_kresults that clear it, in hybrid order. It takes a value from 0 to 1; anything else raises an error. Keyword-only queries (alpha == 0) and queries on indexes that hold no vectors have no embedding to score against, somin_scoreon them raises a clear error. Works inqueryandquery_multi_index;SessionIndex.queryignores it.QueryOptions.candidate_depthsets how many hits a hybrid query ranks on each signal (vector and keyword) before fusion. A hit outside both lists is never returned, so a deeper list raises recall and query time. Left unset, a hybrid query looks2 * top_kdeep, as before. A set value must be at least 1 (0 raises an error) and is raised totop_kwhen below it. Keyword-only and vector-only queries (alpha0 or 1) ignore it and ranktop_khits, since a deeper list returns the same results. Works inqueryandquery_multi_index;SessionIndex.queryignores it. Requiresinferedge-moss-core0.26.0.
- Behavior change:
scoreis the result’s relevance to the query from 0 to 1, inquery,query_multi_indexandSessionIndex.queryalike. Results keep their hybrid order, so a lower-ranked result can show a higher score. Scores depend on the embedding model: tunemin_scoreon your own queries. Keyword-only queries (alpha == 0) score every result 0.0. Code that relied on the top result scoring about 1.0, or on multi-indexalpha=1.0scores being raw similarity values, needs updating. - Behavior change: a query
embeddingwhose length differs from the index dimension raises atalpha0 as it does above 0; it used to be ignored at 0. An emptyembedding=[]counts as wrong-size inqueryandSessionIndex.query, so it raises at everyalpha, whilequery_multi_indexreads it as no embedding. Requiresinferedge-moss-core0.26.0. - Behavior change: a blank query (empty or only whitespace) with no
embeddingreturns no results at everyalphawithout running the embedding model. It used to embed the empty text abovealpha0 and rank every document against it. A blank query with anembeddingranks by the embedding. Requiresinferedge-moss-core0.26.0. - Requires
inferedge-moss-core0.26.0 (was 0.25.0). That core adds themin_scorequery parameter and the relevancescore. - Queries no longer send one telemetry request each.
index.query,index.query_multiandsession.queryevents are buffered and sent with the usage flush every 3 seconds and at close, as JSON arrays of up to 500 events, one request per array. Each event keeps the fields it had, including its ownlatencyMs. Up to 10,000 events wait between flushes; events past that are dropped and the count is logged. Usage counts are unchanged. The README lists every telemetry event and its fields. Comes withinferedge-moss-core0.26.0. - Keyword-only and hybrid queries without a
filterthat match many documents in a large index are faster, since keyword search sorts only the top hits instead of every match. Comes withinferedge-moss-core0.26.0.
- Every call that names a cloud index (
create_index,create_index_from_files,create_web_source,get_index,delete_index,add_docs,delete_docs,get_docs,load_index,SessionIndex.push_index) raisesRuntimeErrorfor a name that is blank,"."or"..", contains/or a control character, or is longer than 256 bytes, before any request is sent;load_indexeslists such a name infailed. The message includesValidation error: index name must not be blank, "." or "..", must not contain "/" or control characters, and must be at most 256 bytes, the same text in every SDK. Any other name is percent-encoded, so names with spaces,%,?or#reach their own index. Pass the raw name: a name that is already percent-encoded, for example withurllib.parse.quote, is encoded again and addresses a different index. Requiresinferedge-moss-core0.26.0. get_docspercent-encodes each document id, so an id containing,,&or a space returns that one document. An id with a comma used to arrive as two ids.add_docssendsMutationOptions.upsertto the cloud when set. The service decides how to apply it. Requiresinferedge-moss-core0.26.0.- Malformed index data and tokenizer files raise an ordinary error instead of a
PanicException. An index whose stored vectors differ in length fails to load. Atokenizer.jsonwhose truncation stride is not less than 512 minus its special tokens fails the model load. Deleting from an index stored without vectors works, and adding documents to it raises. Requiresinferedge-moss-core0.26.0. - A vector holding NaN or infinity raises instead of reordering results without an error. Adding documents with one raises for the whole call, naming the document and the position, and stores nothing. A query
embeddingholding one raises at everyalpha, and loading an index that stores one fails. Requiresinferedge-moss-core0.26.0. MossClient.querywithQueryOptions(top_k=0)returns no results, asquery_multi_indexandSessionIndex.querydo. It used to search withtop_k=5.moss.__version__now reads the installed distribution metadata (importlib.metadata.version("moss")) instead of a hardcoded literal, so it always matches the published package version. In a source tree that is not installed as a distribution it reports0.0.0+unknown.load_indexandload_indexeswithauto_refresh=Trueandpolling_interval_in_seconds=0poll at the default interval of 600 seconds. Before, the refresh task panicked as it started, so the index never refreshed while the load reported success. An interval above one year polls once a year. Requiresinferedge-moss-core0.26.0.- Keyword-only and hybrid queries order documents with equal keyword scores by their position in the index, so the same query returns the same results on every call. That order used to vary from call to call. Requires
inferedge-moss-core0.26.0. - When the auth service answers 500, 503, 429 or 408, the error names the HTTP status without the service’s response body. A 403 from it raises the same invalid-credentials error as a 401. Requires
inferedge-moss-core0.26.0.
Added
QueryOptions.minScoredrops hits whosescoreis below the threshold, from 0 to 1; a query returns up totopKhits that clear it, in hybrid order. A value outside 0 to 1 is rejected, and so is setting it on a keyword-only query (alpha === 0) or when no queried index holds vectors.queryandqueryMultiIndexforward it to all four native query methods; session queries ignore it.QueryOptions.candidateDepthsets how many hits a hybrid query ranks on each signal (vector and keyword) before fusion. A hit outside both lists is never returned, so a deeper list raises recall and query time. Left unset, a hybrid query looks2 * topKdeep, as before. A set value must be at least 1 (0 is rejected) and is raised totopKwhen below it. Keyword-only and vector-only queries (alpha0 or 1) ignore it and ranktopKhits, since a deeper list returns the same results.queryandqueryMultiIndexforward it to all four native query methods; session queries ignore it. Requires@moss-js/moss-core0.30.0.loadIndexandloadIndexeswith acachePathserve the snapshot saved there when the cloud is unreachable, instead of failing. When a snapshot is on disk, the cloud check makes one attempt within 5 seconds. A transport error (unreachable network, timeout) or an HTTP 408, 429, 500, 502, 503 or 504 (only a 408, 429, 500 or 503 from the auth service) loads the snapshot and starts a refresh poller, even withoutautoRefresh, so the index catches up when the cloud returns. A 404 still fails, as does a 401 or 403, so a deleted or forbidden index does not come back from cache. A snapshot saved by an SDK before 1.15.0, or under another project or cloud origin, is not served, and the load fails after that one attempt. A load that finds the cloud copy unchanged keeps the old snapshot, so a snapshot saved before 1.15.0 is served only after the index is downloaded again, which happens when the cloud copy changes. After a load from the snapshot, text queries withalphaabove 0 fail until the Moss cloud is reachable, since a built-in embedding model cannot open offline, unless the same model is already open in this process. Keyword-only queries (alpha: 0) and queries that pass their own embedding keep working. Requires@moss-js/moss-core0.30.0.
- Behavior change:
scoreis the relevance of the hit to the query, from 0 to 1, inquery,queryMultiIndexandSessionIndex.queryalike. Results stay in hybrid order, so a lower-ranked result can show a higher score. Scores depend on the embedding model: tuneminScoreon your own queries. A keyword-only query (alpha === 0) scores every hit 0. - Requires
@moss-js/moss-core0.30.0, which adds theminScorequery parameter and the relevancescore. - Behavior change: a query
embeddingwhose length differs from the index dimension rejects atalpha0 as it does above 0; it used to be ignored at 0. An emptyembedding: []counts as wrong-size inqueryandSessionIndex.query, so it rejects at everyalpha, whilequeryMultiIndexreads it as no embedding. Requires@moss-js/moss-core0.30.0. - Behavior change: a blank query (empty or only whitespace) with no
embeddingreturns no results at everyalphawithout running the embedding model. It used to embed the empty text abovealpha0 and rank every document against it. A blank query with anembeddingranks by the embedding. Requires@moss-js/moss-core0.30.0. - Queries no longer send one telemetry request each.
index.query,index.query_multiandsession.queryevents are buffered and sent with the usage flush every 3 seconds and at close, as JSON arrays of up to 500 events, one request per array. Each event keeps the fields it had, including its ownlatencyMs. Up to 10,000 events wait between flushes; events past that are dropped and the count is logged. Usage counts are unchanged. The README lists every telemetry event and its fields. Requires@moss-js/moss-core0.30.0. MossClient.close()andSessionIndex.close()resolve after the final telemetry flush is sent, so a process that exits right afterawait close()keeps its buffered query events. A flush waits at most 5 seconds for authentication, once for all its events, and 3 seconds per request. Requires@moss-js/moss-core0.30.0.- Keyword-only and hybrid queries without a
filterthat match many documents in a large index are faster, since keyword search sorts only the top hits instead of every match. Keyword scores are the same. Requires@moss-js/moss-core0.30.0.
- Malformed index data and tokenizer files reject with an ordinary error instead of a native panic. An index whose stored vectors differ in length fails to load. A
tokenizer.jsonwhose truncation stride is not less than 512 minus its special tokens fails the model load. Deleting from an index stored without vectors works, and adding documents to it rejects. Requires@moss-js/moss-core0.30.0. - A vector holding NaN or infinity rejects instead of reordering results without an error.
SessionIndex.addDocswith one rejects the whole call, naming the document and the position, and stores nothing. A queryembeddingholding one rejects at everyalpha, and loading an index that stores one fails. Requires@moss-js/moss-core0.30.0. - Every call that names a cloud index (
createIndex,createIndexFromFiles,createWebSource,getIndex,deleteIndex,addDocs,deleteDocs,getDocs,loadIndex,SessionIndex.loadIndex,SessionIndex.pushIndex) rejects a name that is blank,"."or"..", contains/or a control character, or is longer than 256 bytes, before any request is sent;loadIndexeslists such a name infailed. The error message includesValidation error: index name must not be blank, "." or "..", must not contain "/" or control characters, and must be at most 256 bytes, the same text in every SDK. Any other name is percent-encoded, so names with spaces,%,?or#reach their own index. Pass the raw name: a name that is already percent-encoded, for example withencodeURIComponent, is encoded again and addresses a different index. Requires@moss-js/moss-core0.30.0. getDocspercent-encodes each document id, so an id containing,,&or a space returns that one document. An id with a comma used to arrive as two ids. Requires@moss-js/moss-core0.30.0.addDocssendsMutationOptions.upsertto the cloud when set. The service decides how to apply it. Requires@moss-js/moss-core0.30.0.loadIndexandloadIndexeswithautoRefresh: trueandpollingIntervalInSeconds: 0poll at the default interval of 600 seconds. Before, the refresh task panicked as it started, so the index never refreshed while the load reported success. An interval above one year polls once a year. Requires@moss-js/moss-core0.30.0.- Keyword-only and hybrid queries order documents with equal keyword scores by their position in the index, so the same query returns the same results on every call. That order used to vary from call to call. Requires
@moss-js/moss-core0.30.0. - With a project key, when the auth service answers 408, 429, 500 or 503, the error names the HTTP status without the service’s response body. A 403 from it rejects with the same invalid-credentials error as a 401. Web source methods and
getAuthTokenare not affected. Requires@moss-js/moss-core0.30.0.
Added
MossClientOptions.onProgressreports the embedding model download that the first text query waits on. It receives{ modelId, loadedBytes, totalBytes, fromCache }after each chunk, and once withfromCache: truewhen the model comes from the Cache API. An error thrown from the callback is ignored. Its argument type,ModelDownloadProgress, is exported.QueryOptions.candidateDepthsets how many hits a hybrid query ranks on each signal (vector and keyword) before fusion. A hit outside both lists is never returned, so a deeper list raises recall and query time. Left unset, a hybrid query looks2 * topKdeep, as before. A set value must be at least 1 (0 is rejected) and is raised totopKwhen below it. Keyword-only and vector-only queries (alpha0 or 1) ignore it and ranktopKhits, since a deeper list returns the same results. All four query methods forward it to the runtime in a trailing{ candidateDepth }object. Requires@moss-dev/moss-wasm0.16.0; an older runtime ignores it.
- A model artifact request aborts when its response or its next chunk takes more than 30 seconds. A stall, a dropped connection, a body shorter than the manifest size, a 408, a 429 or a 5xx is retried once; other errors are not. The model request fails with a
ModelDeliveryErrorwhen the Moss service does not answer within 30 seconds. A response larger than the size in the release manifest is cut off as it arrives. - A verified model is kept in the browser Cache API (
moss-model-artifacts-v1), keyed by the release manifest digest, so a later page load skips the model download when the HTTP cache is cold. The release manifest is fetched and verified on every load. A cached model is checked against its SHA-256 again before use, and one that does not match is dropped and downloaded again. Caching a release drops the other cached releases of that model. Where the Cache API is unavailable, such as on a plain HTTP page, the model downloads on each page load. Loading the model still needs the Moss service on every page load. - Behavior change:
scoreis the relevance of the hit to the query, from 0 to 1, on single-index and multi-index queries alike. Results stay in hybrid order, so a lower-ranked result can show a higher score. Scores depend on the embedding model. A keyword-only query (alpha0) scores every hit 0. A relevance floor (minScore) is not available in this SDK. Requires@moss-dev/moss-wasm0.16.0. - A custom authenticator’s token is cached until 60 seconds before it expires, or for 90% of its life when that is later, so a token that lasts a minute or less is cached too. An
expiresInthat is not a positive finite number, such as0,NaN,Infinityor a missing value, is not cached. - With a project key, a 403 from the auth service rejects with an error that includes
Authentication failed: invalid credentials, as a 401 does. A 500, 503, 429 or 408 from it rejects with one that includesAuthentication service temporarily unavailable (HTTP <status>)and no response body. A 401, 403 or 404 from the Moss index API rejects without the response body in the error, except ondeleteIndex. Requires@moss-dev/moss-wasm0.16.0.
IAuthenticator.getAuthHeader()is optional and deprecated. The client never calls it. It sendsAuthorization: Bearer <token>built fromgetAuthToken(). UnderstrictNullChecks, calling it through theIAuthenticatortype is a type error unless the code first checks that it is defined.
- Behavior change:
metadataon query results andgetDocsrows is a plain object. It was aMap, so property access,Object.keysandJSON.stringifysaw no keys. Code that reads it withMapmethods, such asmetadata.get(key), must readmetadata[key]instead. Requires@moss-dev/moss-wasm0.16.0. - Malformed data rejects with an error instead of trapping the WebAssembly module.
loadIndexrejects an index whose stored vectors differ in length, or whose header declares a section length close to 4 GiB. Atokenizer.jsonwhose truncation stride is not less than 512 minus its special tokens fails the model load. Requires@moss-dev/moss-wasm0.16.0. - A vector holding NaN or infinity rejects instead of reordering results without an error.
loadIndexrejects an index that stores one, naming the document and the position. A query embedding holding one, or one whose length differs from the index dimension, rejects at everyalpha; a wrong length used to be ignored atalpha0. Requires@moss-dev/moss-wasm0.16.0. - Behavior change:
queryandqueryMultiIndexwith a blank query (empty or only whitespace) return no results at everyalphawithout running the embedding model. They used to embed the empty text and rank every document against it abovealpha0. createIndex,createIndexFromFiles,getIndex,deleteIndex,addDocs,deleteDocs,getDocsandloadIndexreject an index name that is blank,"."or"..", contains/or a control character, or is longer than 256 bytes, before any request is sent, with an error that includesValidation error: index name must not be blank, "." or "..", must not contain "/" or control characters, and must be at most 256 bytes.loadIndexeslists such a name infailed. Any other name is percent-encoded, andgetDocspercent-encodes each document id, so an id containing,,&or a space returns that one document. Pass the raw name: a name that is already percent-encoded, for example withencodeURIComponent, is encoded again and addresses a different index. Requires@moss-dev/moss-wasm0.16.0.addDocssendsMutationOptions.upsertto the cloud when set. The service decides how to apply it. Requires@moss-dev/moss-wasm0.16.0.
Added
- With a
:cache_pathand a snapshot of the index already on disk,load_index/3makes one metadata request with a 5 second budget instead of retrying. When that request fails on a transport error, or the auth service answers 500, 503, 429 or 408, the load serves the snapshot and starts the refresh poller, even withoutauto_refresh: true. A 404, 401 or 403 still returns{:error, reason}. Only a snapshot saved bymoss_core0.21.0 or later under the same project and cloud origin is served. For an index onmoss-minilmormoss-mediumlm,load_index/3also opens the embedding model, which needs the cloud, so the load can still return{:error, reason}while the cloud is unreachable, though the index stays loaded.
- Bumped
moss_coredependency to 0.21.0. - Behavior change:
Moss.QueryResultDoc.scoreis the relevance of the hit to the query, from 0 to 1, inquery/4,query_multi_index/4andMoss.Session.query/3alike. Results stay in hybrid order, so a lower-ranked result can show a higher score. Scores depend on the embedding model. A keyword-only query (alpha: 0.0) scores every hit 0.0. Code that relied on the top result scoring about 1.0, or onquery_multi_index/4scores atalpha: 1.0being raw similarity, needs updating. A relevance floor (:min_score) is not available in this SDK. - Behavior change: a query
:embeddingwhose length differs from the index dimension returns{:error, reason}atalpha: 0.0as it does above 0; it used to be ignored at 0. An emptyembedding: []counts as wrong-size inquery/4andMoss.Session.query/3, so it returns{:error, reason}at everyalpha, whilequery_multi_index/4reads it as no embedding. An:embeddingof all zeros returns{:error, reason}whenalphais above 0. A blank query (empty or only whitespace) with no:embeddingreturns no hits at everyalphawithout running the embedding model (a"custom"session still requires:embedding), and with an:embeddingranks by it whenalphais above 0. - Queries no longer send one telemetry request each.
index.query,index.query_multiandsession.queryevents are buffered and sent with the usage flush every 3 seconds and when the client or session process stops, as JSON arrays of up to 500 events, one request per array. Each event keeps the fields it had, including its ownlatencyMs. Up to 10,000 events wait between flushes; events past that are dropped and the count is logged. Usage counts are unchanged. - Broad keyword-only and hybrid queries on large indexes are faster.
- A vector holding NaN or infinity returns
{:error, reason}instead of reordering results without an error. Adding documents with one fails the whole call, naming the document and the position, and stores nothing. A query:embeddingholding one fails at everyalpha, and loading an index that stores one fails. - Malformed index data and tokenizer files return
{:error, reason}instead of raising from the NIF. An index whose stored vectors differ in length fails to load. Atokenizer.jsonwhose truncation stride is not less than 512 minus its special tokens fails the model load. Deleting from an index stored without vectors works, and adding documents to it returns{:error, reason}. load_index/3andload_indexes/3withauto_refresh: trueandpolling_interval: 0poll at the default interval of 600 seconds. Before, the refresh task panicked as it started, so the index never refreshed while the load reported success. An interval above one year polls once a year.Moss.Clientcalls that name a cloud index (create_index,create_index_from_files,get_index,delete_index,add_docs,delete_docs,get_docs,load_index),Moss.Session.load_index/2andMoss.Session.push_index/1return an error for a name that is blank,"."or"..", contains/or a control character, or is longer than 256 bytes, before any request is sent, with a message that includesValidation error: index name must not be blank, "." or "..", must not contain "/" or control characters, and must be at most 256 bytes.load_indexeslists such a name infailed. Any other name is percent-encoded, andget_docspercent-encodes each document id, so an id containing,,&or a space returns that one document. Pass the raw name: a name that is already percent-encoded is encoded again and addresses a different index.Moss.Client.add_docs/4sends the:upsertoption to the cloud when set. The service decides how to apply it.- Keyword-only and hybrid queries order documents with equal keyword scores by their position in the index, so the same query returns the same results on every call. That order used to vary from call to call.
- When the auth service answers 500, 503, 429 or 408, the error includes
Authentication service temporarily unavailable (HTTP N)and no response body. A 403 from the auth service returnsAuthentication failed: invalid credentials, as a 401 does.
Changed
- Batched query telemetry. Queries no longer send one telemetry request each.
index.query,index.query_multiandsession.queryevents are buffered and sent with the usage flush every 3 seconds and at close, as JSON arrays of up to 500 events, one request per array. Each event keeps the fields it had, including its ownlatencyMs. Up to 10,000 events wait between flushes; events past that are dropped and the count is logged. Usage counts are unchanged. - Faster keyword and hybrid queries on large indexes. Keyword search sorts only the top hits instead of every matching document, so broad queries with
alphabelow 1 return sooner. Results are unchanged.
- A bad tokenizer file or an index stored without vectors no longer ends the app. A
tokenizer.jsonwhose truncation stride is not less than 512 minus its special tokens fails the model load with aMossError. Deleting from an index stored without vectors works,MossSession.pushIndexon it no longer ends the app, and adding documents to it throws. MossClient.addDocssendsupsertto the Moss cloud. It istruewhen the argument is left out, and the service decides how to apply it.- A vector holding NaN or infinity throws instead of reordering results. Adding documents to a
MossSessionwith one throws aMossErrornaming the document and the position, and stores nothing. A query embedding holding one throws at everyalpha, andloadIndexfails on a cloud index that stores one. - Query boundaries behave the same at every
alpha. A query embedding whose length differs from the index dimension throws atalpha0 as it does above 0; it used to be ignored at 0. A blank query (empty or only whitespace) with no embedding returns no hits at everyalphawithout running the embedding model, and with an embedding andalphaabove 0 ranks by it.topK0 keeps meaning the default (5, or 10 forqueryMultiIndex), where the JavaScript and Python SDKs return no hits for it. - An auto-refresh interval of 0 no longer aborts the app.
MossClient.loadIndexandloadIndexeswithautoRefresh: trueandpollingIntervalSeconds: 0poll at the default interval of 600 seconds. An interval above one year is capped at one year. - Index names are checked before any request.
deleteIndex,getIndex,getDocs,loadIndexand the other calls that name a cloud index throwMossErrorwith code-3for a name that is blank,"."or"..", contains/or a control character, or is longer than 256 bytes.loadIndexeslists such a name infailed. Any other name is percent-encoded, andgetDocsencodes each document id, so an id containing,,&or a space returns that one document. Pass the raw name: a name that is already percent-encoded is encoded again and addresses a different index. - An index name or document id holding U+0000 throws. libmoss reads strings up to their first NUL, so such a name or id would reach a different index or document.
MossClientcalls that take an index name,MossSession.loadIndex, and the id arguments ofMossClient.deleteDocsand ofMossSession.addDocs,deleteDocsandgetDocsthrowMossErrorwith code-2, the code for other argument errors, before any native call.
sdkVersion: 0.23.0.Portal
Added
- A product switcher under the Moss logo moves between the Developer Portal and Founding Agent from any page. It replaces Back to Dashboard in the Founding Agent account menu.
A SwiftPM checkout that resolved
v0.6.3 before 2026-09-25 22:06 UTC may refuse the new fingerprint. Delete ~/Library/org.swift.swiftpm/security/fingerprints/moss-*.json or resolve once with -packageFingerprintPolicy warn.AddedloadIndexesandunloadIndexes. Load or unload several indexes in one call.loadIndexesis best effort: it returns aLoadIndexesResultwhoseloadednames are retained even when others fail, with per-name reasons infailed.unloadIndexesis idempotent and ignores names that are not loaded.queryMultiIndexacross indexes that share an embedding model.options.topKcaps the merged result (10 when unset, where single-indexquerydefaults to 5) andoptions.alphakeeps its single-index meaning: 1.0 embedding-only, 0.0 keyword-only (no embedding is computed), anything between fuses the two with reciprocal rank fusion.QueryResult.indexNamereports the source index for each hit and staysnilfor single-indexqueryresults.- Multi-index requires native runtime
0.22.0or later. OlderMoss.xcframeworkbuilds fail closed: every multi-index call throwsMossError(code: -7), andMossClient.multiIndexAPIAvailablereports support up front.
- Behavior change:
QueryResult.scoreis the relevance of the hit to the query, from 0 to 1, inqueryandqueryMultiIndexalike. Results stay in hybrid order, so a lower-ranked result can show a higher score. Scores depend on the embedding model. A keyword-only query (alpha0) scores every hit 0. A relevance floor (minScore) is not available in this SDK yet. moss-minilmandmoss-mediumlmnow run on iOS, and the default session model ismoss-minilm.SessionOptions.modelId == nilused to resolve tomoss-litelm, which requires an organization entitlement; it now resolves tomoss-minilm.moss-mediumlmis opt-in.- Foundation models download in the native model format.
moss-minilm,moss-mediumlm, andmoss-litelmresume interrupted downloads. A session on a model the project has no access to opens withdocCount == 0, and its firstaddDocsorqueryfails. No API change.
- An index whose stored vectors differ in length fails to load. The
MossErrornames the vector and both lengths. Such an index used to load, and an embedding query on it could abort the process. - A cached vector file of the wrong dimension is ignored instead of being read past its end. Loading with a cache path keeps the vectors in memory when the cached
.mossvecfile’s dimension differs from the index, so queries return correct results.
MOSS_MODEL_ARTIFACT_TOKEN. The variable is ignored.
sdkVersion: 0.22.0.Portal
Founding Agent redesign
- New navigation. The sidebar groups Agents (with New agent), Monitor (Live, Leads, Analytics), Configure (Integration), and Settings. Inside an agent, a switcher moves between agents, and its pages are grouped under Configure (Agent, Appearance, Knowledge Base, Q&A, Demo Booking, Security, Sandbox) and Monitor (Live, Leads, Analytics). Handoffs are now part of Live.
- The Config tab is split into Agent, Demo Booking, and Security, which now holds the agent’s API keys. Each card saves on its own.
- New Appearance tab for the widget’s shape, colors, texture, and theme.
- Agents can be published, unpublished, and deleted from the portal. Publishing and unpublishing need an org owner or admin and an active plan.
- The create wizard is full screen, and the agent is created at the Knowledge step.
- Refreshed styling across the portal and sign-in screens.
- Your profile has a single Display Name instead of first and last name.
- New Settings > Payment page. The pay-as-you-go card shows your Current balance with a Buy more button.
- Voice minutes are now Session minutes on the Usage page, in Analytics, and in the overage banner. The meter is unchanged.
Portal
Added
- Website sources. A new Sources tab on the index page lists the websites crawled into the index, with status, page count, and last crawl, and lets you Add website, Re-crawl, Edit, Remove, and View pages. Each crawl takes a website URL, max pages (default 500, up to 5,000), a re-crawl schedule (only when you ask, every day, or every week), and include and exclude path patterns (regular expressions, up to 50). Removing a source needs an org owner or admin. Crawled documents link back to their source page.
- Create index from a website or files. Create index has two new sources: From Website crawls a site into a new index, and Files builds one from up to 20 PDF or DOCX files of up to 50 MB each, with optional Run OCR on every page. Neither is available for custom-model indexes, and Files creates a new index only.
- On graduated pricing, the overage banner shows your current rate and the next tier once usage passes the first tier. Monthly active devices are shown per device.
- Committed voice plans with rollover count rolled-over minutes in the voice limit, shown as “incl. N rolled over”.
- Cancelling under Settings > Billing first checks the free plan limits (1 project, 3 indexes per project) and lists what to remove; nothing is deleted for you. It then asks why you are leaving.
- While a cancellation is scheduled, new projects and indexes are held to the free limits. Existing ones keep working until the period ends, and undoing the cancellation restores the paid limits.
Added
SessionIndex.loadFromDiskrebuilds a snapshot that an SDK older than 1.8 saved for a built-in model. Those snapshots carry no model provenance, so textaddDocsandqueryon them failed with “requires explicit embeddings”. The stored documents are re-embedded with the current model and the upgraded snapshot is saved back in one operation, so the rebuild runs once per device (about a minute for 10k chunks, off the main thread, with the Moss cloud reachable). It only runs for a session opened with the same built-in model; pass{ rebuildLegacy: false }to opt out. If the model cannot be loaded,loadFromDiskrejects with a message starting “Legacy snapshot rebuild needs the embedding model” and changes nothing, so retry later instead of discarding the snapshot.SessionIndex.inspectSnapshot(cachePath)describes a snapshot without loading it.SnapshotInfoandLoadFromDiskOptionsare exported.
- Every
SessionIndexoperation (addDocs,deleteDocs,getDocs,query,saveToDisk,loadFromDisk) and the model warm-up insideMossClient.session()run their native work on a worker thread instead of the Node main thread, so the event loop keeps serving while a large batch is embedded or a session is saved. Operations on oneSessionIndexstill run in call order, one at a time.docCountstays synchronous and reports the count as of the last completed operation. No API change. - Requires
@moss-js/moss-core0.29.0.
Added
- Custom authenticator:
new MossClient(projectId, authenticator)andMossClient.create(projectId, authenticator)accept anIAuthenticatorin place of theprojectKey, so frontend code never ships the key.IAuthenticatorandAuthTokenare exported, andgetAuthToken()returns the cached token. Requires@moss-dev/moss-wasm0.15.0. - Multi-index search:
queryMultiIndex(names, queryText, options?)andqueryMultiIndexWithEmbedding(names, queryText, embedding, options?)search several loaded indexes in one call and return the global top-k, each document tagged with theindexNameit came from.topKcaps the merged result (default 10), andalphaworks as inquery(default 0.8). loadIndexes(names, options?)returns{ loaded, failed }and keeps the indexes that did load;unloadIndexes(names)ignores names that are not loaded.
- Loading a built-in model requires the Moss service to be reachable, and a refused model request fails with
ModelDeliveryErrorinstead of falling back to the public model files. MossClientOptions.modelArtifactOriginoverrides the model origin (https://models.moss.link);httpis accepted only for loopback hosts.
- Queries on
moss-mediumlmindexes no longer fail: the SDK expected 1024 dimensions from a model that emits 512.
Changed
- Loading a built-in model (
moss-minilm,moss-mediumlm,moss-litelm) now requires the Moss cloud to be reachable and rejects with an error otherwise. No API change. Requires@moss-js/moss-core0.27.0.
Changed
- Loading a built-in model (
moss-minilm,moss-mediumlm,moss-litelm) now requires the Moss cloud to be reachable and raises an error otherwise. No API change. Requiresinferedge-moss-core0.25.0.
Changed
- Loading a built-in model (
moss-minilm,moss-mediumlm,moss-litelm) now requires the Moss cloud to be reachable and fails with an error otherwise. No API change. - Bumped
moss_coredependency to 0.20.0.
Portal
Added
- Two-factor authentication by SMS, required for every portal account, including GitHub and Google sign-ins. The next time you sign in, add a phone number and enter the 6-digit code sent to it. After that, each sign-in asks for a code. New accounts set it up before onboarding.
- Change your number or add another one under Settings > Profile > Two-factor authentication. You get an email whenever a phone is added or removed. Two-factor authentication cannot be turned off, and there are no backup codes: if you lose your phone, contact Moss support to reset it.
- API keys and the SDKs are not affected.
- Signing out ends the session in the current browser only, instead of on every device.
Portal
Founding Agent demo booking
- Google Calendar booking. Connect Google Calendar and pick the calendar to book on; only calendars that can create Google Meet links can be selected. Set the meeting length (15 to 240 minutes), time zone, bookable days and hours (default Monday to Friday, 9:00 to 17:00), buffer between meetings (up to 120 minutes), and minimum notice (default 4 hours, up to 7 days). Visitors get a calendar invite with a Meet link, and busy times are never offered.
- Connect Calendly with OAuth instead of pasting a token, then choose a Calendly event type. Requires a paid Calendly plan (Standard or above). Event types that ask the visitor for a phone number or address, or that offer several locations, cannot be selected.
Fixed
- Closing the booking modal no longer discards the session’s booking nonce. Asking to book again in the same session now reopens the slot picker instead of “Booking unavailable”, and the intake form’s nonce gate is unaffected by a dismissed booking. The nonce is cleared only when the session ends (
reset()).
Changed
- The per-device id is now sourced by the native core (
@moss-js/moss-core0.26.0);@moss-js/moss-coreusers get it without the wrapper. Same file (~/.moss/.moss-device-id), same id.MossClientOptions.cachePathstill uses<cachePath>/.moss-device-id(adopting an existing id, or creating one when the file is missing), andidentity.deviceIdstill overrides the billable id. - Sessions opened through
client.session()carry the client’s resolved identity, including an id adopted byloadIndex(name, { cachePath }). The first id resolved on a client stays on every surface, and a per-callloadIndex(name, { cachePath })still creates<cachePath>/.moss-device-idwhen it is missing.
Changed
- The per-device id is now sourced by the native core (
inferedge-moss-core0.24.0);moss_coreusers get it without the wrapper. Same file (~/.moss/.moss-device-id), same id.moss_coreset_device_id(None)andset_identity(None, ...)keep the current id. - Sessions created by a client now inherit that client’s resolved device identity, and
load_index/load_indexescreate<cache_path>/.moss-device-idwhen it is missing. A client that passescache_pathis one Monthly Active Device across its index and session events instead of two.moss_core.IndexManagergainsset_identityanddevice_identity,moss_core.SessionIndexgainsset_identity.
Added
Moss.Client.query_multi_index/4: search several loaded indexes in one call and get the global top-k, each result tagged with its sourceindex_nameonMoss.QueryResultDoc.:alphaworks as inquery/4(default 0.8):1.0embedding-only,0.0keyword-only, in between hybrid via Reciprocal Rank Fusion; keyword scoring runs each index’s own BM25 and merges hits by score before fusion.:top_k(default 10) caps the merged result. Local-only: every name must be loaded and share one embedding model.Moss.Client.load_indexes/3: best-effort bulk load returning%Moss.LoadIndexesResult{loaded, failed};Moss.Client.unload_indexes/2releases loaded indexes idempotently.- Requires a
moss_coreNIF release withmanager_load_indexes,manager_unload_indexes,manager_query_multi_index, andmanager_query_multi_index_text.
- The per-device id is now sourced by the native core;
Moss.DeviceIdis removed. Same file (~/.moss/.moss-device-id), same id.Moss.Client.new/3’s:cache_pathis forwarded to the core’sload_index, which adopts<cache_path>/.moss-device-id(created when missing, as before) and also caches loaded indexes on disk under that directory; a blank:cache_pathis treated as unset, and the$XDG_CACHE_HOME/mosslocation is no longer consulted.Moss.Client.session/3copies the client manager’s resolved identity onto the session.MossCore.Nif.manager_set_device_id/2andsession_set_device_id/2keep the current id when givennil;manager_device_identity/1andsession_set_identity/4are new. - Improved on-device model loading for foundation models (
moss-minilm,moss-mediumlm,moss-litelm). No API change.
MOSS_MODEL_ARTIFACT_TOKENis no longer used and is ignored.
Added
load_indexandload_indexesacceptcache_path. The downloaded index is persisted under that directory and reused on later loads while the cloud copy is unchanged, so restarts skip the download; auto-refresh writes through to the same cache. Parity with the JS SDK’scachePath. Each load still contacts the cloud to check for a newer version.
Added
- Web source methods on
MossClient:createWebSource,listWebSources,getWebSource,updateWebSource,resyncWebSource, anddeleteWebSource, typed wrappers over the/v1/manageweb source actions.createWebSource,resyncWebSource, andupdateWebSourcewithresync: truereturn ajobIdto poll withgetJobStatus;deleteWebSourcereturnspurgeJobIdwhile the source’s pages are removed. - Types
WebSource,CreateWebSourceOptions,CreateWebSourceResult,UpdateWebSourceOptions,UpdateWebSourceResult,ResyncWebSourceResult,DeleteWebSourceResult, andManageApiError(carries the HTTPstatus). MOSS_CLOUD_API_BASE_URLoverrides the host used by the web source methods.
Added
- Web source methods on
MossClient:create_web_source,list_web_sources,get_web_source,update_web_source,resync_web_source, anddelete_web_source, typed wrappers over the/v1/manageweb source actions.create_web_source,resync_web_source, andupdate_web_sourcewithresync=Truereturn ajob_idto poll withget_job_status;delete_web_sourcereturnspurge_job_idwhile the source’s pages are removed. - Types
WebSource,CreateWebSourceResult,UpdateWebSourceResult,ResyncWebSourceResult,DeleteWebSourceResult, andManageApiError(carries the HTTPstatus). MOSS_CLOUD_API_BASE_URLoverrides the host used by the web source methods.
API
- Several web sources per index:
createWebSourcenow adds a site to an existing index instead of refusing it (up to 20 per index, each root URL once). Each source’s pages are tracked separately: a crawl replaces only its own pages, anddeleteWebSourceremoves the source’s pages through a purge job (purgeJobIdin the response) while the index and its other content stay. updateWebSourceaccepts every crawl setting (rootUrl,maxPages,maxDocuments,maxDepth,includePaths,excludePaths,respectRobots,parseDocuments) as well asrefreshCadence, plusresync: trueto crawl right after saving.listWebSourcesaccepts an optionalindexNamefilter.- A crawl requested while another crawl or build runs on the same index is queued (
getJobStatusreportsqueued) instead of failing with409. - Unchanged pages are no longer re-embedded on refresh, and page boilerplate (navigation, footers, cookie banners, skip links) is stripped before indexing.
Portal
Added
- The Usage page shows Crawled URLs and Parsed document pages against your plan allowance, with the charge, once either is above zero. Counts cover the whole org, even with a project filter on. The overage banner includes both, with per-page rates shown to three decimals.
- JSON uploads in Create Index > Custom Upload are no longer capped at about 4.5 MB. A failed upload releases the index name, so you can retry right away. Add Documents on an existing index still has the 4.5 MB limit.
- The voice minutes chart in Analytics splits a call that crosses midnight UTC across both days, and loads faster for large orgs.
Portal
- Several API keys per project. The project’s API Keys page now creates, lists, and deletes keys, so you can rotate with overlap: create a new key, move your clients to it, then delete the old one. New projects start with no key.
- A key is shown once, at creation. Existing keys keep working but can no longer be viewed in the portal.
- Deleting a key blocks new tokens right away. Tokens already issued with it stop working within about 20 seconds.
- Any org member can see the list of keys. Org owners, admins, and the project owner can create and delete them.
- Reliability improvements to on-device model loading. No API changes. Requires
@moss-js/moss-core0.25.0.
- Reliability improvements to on-device model loading. No API changes. Requires
inferedge-moss-core0.23.0.
Published as
@moss-js/founding-agent. Install with npm install @moss-js/founding-agent. @moss-tools/founding-agent stays at 2.1.0 and receives no further releases.Added- Typed chat panel in the bubble: a toggle opens a text input so visitors can type instead of talk. Typed messages are merged into the transcript with the voice turns, without duplicates, and the panel closes when the call ends.
- Intake form: a config-driven modal that opens after the agent’s configured number of answers. The mic pauses while the form is open and resumes on submit or dismiss; dismissing it keeps it closed for the rest of the session. Submissions post to the intake endpoint and publish an
intake_completedevent. - New
@moss-js/founding-agent/coreexports for custom UIs: the intake types,normalizeIntakeForm,validateIntakeValues,postIntake, andmergeTranscript.
- Your token route must return the whole session object from
createFoundingAgentSession. Returning onlytokenandserverUrlsilently disables the booking and intake forms. See Server token route.
Changed
- Published as
@moss-js/moss, depending on@moss-js/moss-core0.24.0. Install withnpm install @moss-js/moss.@moss-dev/mossstays at 1.7.1 and receives no further releases. - Improved on-device model loading for foundation models (
moss-minilm,moss-mediumlm,moss-litelm). No API change.
- The cloud query fallback.
queryon an index that is not loaded now rejects with an error telling you to callloadIndexfirst. TheMOSS_QUERY_URLoverride is gone. MOSS_MODEL_ARTIFACT_TOKENis no longer used and is ignored.
MossClient.queryMultiIndex(indexNames, query, options): search several loaded indexes in one call and get the global top-k, each result tagged with its sourceindexName.options.alphaworks as inquery(default 0.8):1.0embedding-only,0.0keyword-only, in between hybrid via Reciprocal Rank Fusion.MossClient.loadIndexes(indexNames, options): best-effort bulk load returningLoadIndexesResult { loaded, failed };MossClient.unloadIndex(indexName)andMossClient.unloadIndexes(indexNames)release loaded indexes.QueryResultDocumentInfo.indexName(set on multi-index results) and theLoadIndexesResulttype.
Removed
- The cloud query fallback.
query()on an index that is not loaded now raisesRuntimeErrortelling you to callload_indexfirst.MossClientno longer depends onhttpx, and theMOSS_QUERY_URLoverride is gone. MOSS_MODEL_ARTIFACT_TOKENis no longer used and is ignored.
- Keyword and hybrid multi-index search:
query_multi_indexhonorsQueryOptions.alphaexactly likequery.1.0is embedding-only,0.0is keyword-only, and values in between fuse both signals with Reciprocal Rank Fusion, merging each index’s own BM25 hits by score before fusion.
- Improved on-device model loading for foundation models (
moss-minilm,moss-mediumlm,moss-litelm). No API change. query_multi_indexdefaultsalphato0.8to matchquery. PassQueryOptions(alpha=1.0)for the previous embedding-only behavior. Requiresinferedge-moss-core0.22.0.
QueryOptions(alpha=0.0)is forwarded as given instead of being treated as unset, so keyword-only search works on loaded indexes.- Keyword-only text queries no longer embed the query first, so they no longer load an embedding model and work on custom-model and identity-less indexes.
- Non-finite
alpha(NaN, infinities) is rejected with a clear error instead of producing NaN scores.
API
- Web sources: crawl a website into an index via new
/v1/manageactions (createWebSource,listWebSources,getWebSource,resyncWebSource,updateWebSource,deleteWebSource), with optional daily or weekly refresh schedules and linked PDF/DOCX parsing. See Create Web Source.
Added
create_index_from_filesacceptsparse_options(ParseOptions):use_high_resolution,segmentation_method(“smart_layout_detection” or “page_by_page”),ocr_mode(“auto_ocr” or “full_ocr”), andmerge_tables.session()acceptsartifact_versionandmanifest_sha256keyword arguments to pin a foundation model’s immutable publisher release.
- Supported
content_typevalues areapplication/pdfand the DOCX MIME, matching the parse service’s admission check. JobPhaseincludes the crawl and parse pipeline phases.- Requires
inferedge-moss-core0.21.3 (parse options support and the moss-mediumlm 512 dimension fix).
- Local text queries on foundation indexes without an exact model artifact identity keep the core’s actionable error instead of a misleading “custom embeddings” message.
Fixed
createIndexFromFileswith in-memorydata(Uint8Array, ArrayBuffer, Blob, or File) failed at the native boundary with “Failed to get Array length on JsParseFileInput.data”; bytes are now marshalled in the representation the binding accepts. Thepathflow was unaffected.
- New
CreateIndexFromFilesOptions.parseOptions(ParseOptions, now exported): control server-side extraction withuseHighResolution,segmentationMethod(smart_layout_detectionorpage_by_page),ocrMode(auto_ocrorfull_ocr, the latter for scanned documents with no text layer), andmergeTables. Requires@moss-dev/moss-core0.23.0. ParseFileInput.contentTypesupportsapplication/pdfand the DOCX MIME, matching the parse service’s admission check; unsupported types fail fast locally with a clear error.JobProgress.currentPhaseincludes the crawl and parse pipeline phases (queued,crawling,parsing_documents,parsing,waiting_for_parser,parsing_complete).- Local text queries on server-built foundation indexes without an exact model artifact identity are refused with an actionable error instead of embedding against a guessed artifact; explicit query embeddings and cloud queries are unaffected.
Added
Client.create_index_from_files/5accepts aparse_optionsmap controlling server-side extraction::use_high_resolution,:segmentation_method(“smart_layout_detection” or “page_by_page”),:ocr_mode(“auto_ocr” or “full_ocr”), and:merge_tables. Atom or string keys are accepted; unknown keys and wrong value types raise a clear error.
- Supported parse content types are
application/pdfand the DOCX MIME, matching the parse service’s admission check. Docs now state that:name,:content_type, and:pathare all required per file. - Job status
current_phaseincludes the crawl and parse phases (“crawling”, “parsing_documents”, and the parser phases). - Bumped
moss_coredependency to 0.18.0.
Client.session/3with invalid credentials returns{:error, reason}instead of exiting the calling process; sessions start unlinked and link on success.
- Device-id contract for usage tracking (#312):
Moss.Client.new/3resolves a stable per-device id once and applies it to both manager and session telemetry, so a device counts once toward Monthly Active Devices across the whole client.
- New
MossClientOptions.identity(MossIdentity): pass a stable caller-manageddeviceIdand optionaluserIdat construction. The caller’sdeviceIdis emitted as the billable telemetrydeviceId(Monthly Active Device key); Moss’s stable UUID is always emitted alongside asmossDeviceIdfor correlation;userIdis never billable. Values must be 1-256 UTF-8 bytes with no surrounding whitespace, control or format characters, lone surrogates, or replacement characters; invalid values throw at construction. Without a configured identity,deviceIdandmossDeviceIdboth carry Moss’s UUID, so existing billing behavior is unchanged. Requires@moss-dev/moss-core0.22.0; constructing with an identity on an older core fails fast with an actionable error.
Added
MossSessionManager.last_time_taken_ms- the engine-measured retrieval time (ms) from the most recentquery_contextcall (SearchResult.time_taken_ms);Nonebefore the first query or on error.
- First public release to PyPI (
pip install ten-moss).
Dependencies
- Bump
inferedge-moss-coreto0.21.0. The core now publishes an abi3 wheel (cp310-abi3, installs on Python 3.10-3.14) and a glibc ≥ 2.35 x86_64 wheel, somossinstalls in common older-runtime environments - notably the TEN Framework dev container (Ubuntu 22.04 / Python 3.10), where the previouscp312+/manylinux_2_38wheels did not resolve. No API changes.
Added
MossSessionManager- session-scoped Moss grounding for TEN extensions, built on the Moss Sessions API:open,query_context,add_docs,get_docs,delete_docs,push_index,from_config,doc_count.MossSessionConfig- standardizedmoss_*properties for TEN extensions. The project key is a maskedSecretStr;moss_top_k/moss_alpha/moss_max_context_charsare range-validated; unsetmoss_model_idadopts the stored index’s model;moss_max_context_charscaps the injected grounding block.examples/create_index.py- create and populate a demo index.
Changed
- Bumped
pipecat-aiminimum from>=1.1.0to>=1.5.0.
- New: SessionIndex.close() and MossClient.close(), both idempotent, plus Symbol.asyncDispose support so
await usingworks on Node 24. Closing releases the native index, pollers, and the session’s reference to the shared embedding model (the service is dropped when the last session using it closes; the allocator retains and reuses those pages for the next load, so footprint stays bounded at one model per model id). Threads are no longer per-session. Concurrent close() callers share one completion promise and all settle when disposal finishes. - Published type declarations no longer force consumers to enable the ESNext.Disposable lib (the bundle carries the reference itself); consumers need TypeScript 5.2 or newer.
- README and samples now demonstrate the close() / await using lifecycle.
- MossClient.close() now also closes every live session created by that client (tracked via weak references); sessions can still be closed individually first.
- close() fails loudly when the installed @moss-dev/moss-core predates the lifecycle API instead of silently leaking; this release requires @moss-dev/moss-core 0.20.0.
- Declared engines: node >= 20.4 (first Node release where Symbol.asyncDispose exists).
Added
- Semantic code search sidebar with live debounced queries
- Manual Create Index / Rebuild Index workflow
- Local index persistence (
saveToDisk/loadFromDisk) - Moss Cloud sync via
pushIndex()with restore on new machines - Sidebar gear settings for API credentials and cloud sync toggle
- Sync to Cloud button and command
- Hard exclusions for
node_modules, build output, and common dependency folders - Moss native runtime isolated in a worker process
- Marketplace packaging with cross-platform native binaries
Added
- Verbatim payload round-trip (
DocumentInfo.payload): store an opaque structured payload (e.g. a JSON string) verbatim alongside a document and get it back as-is on query/get - never embedded or searched. - Stable per-device id for usage tracking: the SDK now sources a persisted device id (
~/.moss/.moss-device-id) and hands it to the core, making per-device usage attribution stable across restarts. - Non-blocking
create_index.create_index(..., wait=False)returns aJobHandleas soon as the build is submitted, instead of blocking until it completes:handle.job_idis available immediately.handle.status()gives a live progress readout (phase + percent) as aJobStatusResponse.handle.wait()blocks until the build finishes and returns the terminalJobStatusResponse. It polls asynchronously, so it parks no threads and never holds the GIL.- New
MossClient.wait_for_job(job_id)blocks byjob_idalone - submit, tear down the machine, then reconnect in a fresh process to wait on or poll the build. - The build runs server-side, so a submitted job completes regardless of the client.
waitdefaults toTrueand is keyword-only, so existing blocking callers are unaffected.
- Requires
inferedge-moss-core==0.20.1.
Changed
- Picks up
@moss-dev/moss-core0.19.2(dependency currency; native-bindingDocumentInfo.payloadround-trip fix). No SDK API changes. (Prior1.3.1release re-run failed because the version was not bumped; this restores a publishable version.)
Changed
- LiveKit stack bumped atomically 1.5.7 -> 1.6.4 (
livekit-agents+ alllivekit-plugins-*); live Deepgram -> Gemini -> Cartesia round-trip verified. transformersconstrained to turn-detector’s validated line:>=4.47.1,!=4.57.2,!=4.57.3,<5.0.0(the previous>=5.0.0floor was unintentional).google-genai>=1.67,<2.0.0;livekit-api>=1.0.7.
- First cut of non-blocking
create_index. Use 1.7.1 instead, which finalized the API (waitis keyword-only;JobHandle.wait()andMossClient.wait_for_job()returnJobStatusResponse) and fixed a GIL hold that could freeze the event loop while a build was submitted or awaited.
AddedDependencies
- Exact / graph retrieval on
SessionIndex, at parity with the iOS SDK.get_docsnow accepts a deterministic-fetchGetDocumentsOptions- fetch bydoc_ids, by a metadatafilter(same dict shape as query filters; no query vector, no ranking), withsort_by/ascendingordering, andgroup_byparent grouping. NewParentGrouping(parent_field, order_field)collapses sibling chunks into one result per unit.QueryOptions.group_byapplies the same grouping to semantic queries.
- Bumped
inferedge-moss-coreto0.19.0(adds the graph-retrieval surface).
Added
- Verbatim document
payload.DocumentInfonow carries an optionalpayloadstring - an opaque structured value (e.g. JSON) stored and returned unchanged, never embedded or searched. Set it when building/adding documents and read it back fromget_docs/ query results. Useful for keeping the full structured record alongside the embeddabletext. Requires the new core and a current Moss backend.
- Managed (cloud) query results now surface
payload(previously dropped when mapping the response).
- Bumped
inferedge-moss-coreto0.18.0(adds payload support through the upload/build pipeline).
Fixed
- Parent grouping on
queryno longer under-assembles units. The engine truncated totopKbefore sibling collapse, so siblings ranked below the cutoff were dropped.query(…, groupByParent:)now over-fetches candidates and returnstopKunits assembled from a wider window. For guaranteed-complete units, prefergetDocs(where:…, groupByParent:), which collapses over its full fetch. - Deterministic sibling order under grouping. Parent grouping breaks
orderFieldties by document id, so equal/missing order values yield a stable within-unit order.
sdkVersion: 0.21.2.Fixed
- Restored
SessionOptions.autoLoadOnInit. It shipped in 0.5.0 but was absent from 0.6.0 (the graph-retrieval branch predated the feature and never picked it up), so code usingSessionOptions(autoLoadOnInit:)failed to compile against 0.6.0. 0.6.1 carries both graph/exact retrieval andautoLoadOnInit. Upgrade straight from 0.5.0 or 0.6.0 to 0.6.1.
sdkVersion: 0.21.1.Added
- Deterministic / exact (“graph”) retrieval on a session.
getDocs(ids:)now returns documents in the order requested; newgetDocs(where:sortBy:ascending:)fetches by a metadata predicate with no query vector and no similarity ranking. - Typed metadata filter. A
FilterDSL (.equals/.and/.greaterThanOrEqual/.isIn/.near/ …) with literal-expressibleFilterValue, usable in bothgetDocs(where:)andQueryOptions.filter- no hand-written filter JSON. - Parent-unit grouping.
ParentGrouping(parentField:orderField:)ongetDocs/querycollapses sibling documents that share a parent id into a single result, assembled inorderFieldorder. - Verbatim structured payload.
DocumentInfo.payload(andQueryResult.payload) stores and returns an opaque value unchanged - not embedded or searched. Codable sugar:init(…, structured:)anddecodedPayload(_:). Indexes saved without a payload load withpayload = nil.
sdkVersion: 0.21.0.Added
SessionOptions.autoLoadOnInit. Defaults totrue(auto-load the named index from the cloud at session creation). Setfalsefor a local-only, disk-first session: creation returns immediately and you populate it yourself (loadFromDisk, falling back toloadIndexonly on a cache miss).
sdkVersion: 0.20.0.Fixed
- Fixed a native crash when re-saving an on-disk session. Calling
saveToDiskon a session previously restored withloadFromDiskcould crash the process while writing the on-disk index, because the index file was rewritten in place while the loaded session was still reading from it.saveToDiskstill persists immediately, but now writes to a temporary file and atomically renames it into place, so the file the live session is reading from is never rewritten underneath it. Requires@moss-dev/moss-core0.19.1.
Added
- Sessions work with a custom
IAuthenticator.MossClient.session()now works when the client is constructed with a custom authenticator (short-lived tokens / delegated auth), not just a static project key - it previously threw. The session authenticates (credential validation,pushIndex,loadIndex) and reports usage through the same auth bridge asloadIndex. Requires@moss-dev/moss-core0.19.0(adds theSessionIndex.withAuthenticatornapi factory).
Added
- Client-level
cachePath.new MossClient(projectId, key, { cachePath })(and theIAuthenticatoroverload) sets one location for the per-device telemetry id, honored by every operation that emits telemetry -loadIndex,session, and so on. Set it once instead of per call.
- Session telemetry now carries the per-device id.
MossClient.session()now attaches the anonymousdeviceIdtosession.*telemetry events, matchingloadIndex. Previously only theloadIndexpath attached adeviceId, so usage from session-only clients was reported without one. - The per-device id is now resolved once and shared across
loadIndexandsession()within a client, so a client that uses both surfaces reports a single, consistent id.
- The per-device id location is now resolved with this precedence: the client-level
cachePath, then thecachePathpassed toloadIndex(back-compat), then a per-user fallback,<home>/.moss/.moss-device-id. Previously the id was only written whenloadIndexwas given acachePath.
Added
- Usage telemetry on the custom-authenticator path. Automatic, privacy-light usage telemetry now works when the client is constructed with a custom
IAuthenticator(e.g. short-lived tokens), not just a plain project key - previously it was silently disabled on that path. This enables device-level usage reporting for client-side / delegated-auth deployments. - A stable, anonymous per-device id is generated once and persisted at
<cachePath>/.moss-device-id(thecachePathyou already pass toloadIndex), then attached to telemetry asdeviceId. It is a random UUID - no hardware identifier, no PII. - Bumped
@moss-dev/moss-coreto0.18.0(adds thesetDeviceIdnapi binding and auth-provider telemetry).
Fixed
- Loading
moss-litelmindexes could fail withDeserialization error: unsupported version: 3. These indexes use the v3 index format, which requiresinferedge-moss-core0.17.0; installingmossnow brings in that core version automatically, somoss-litelmindexes load out of the box with no manual dependency steps. (moss-minilm/moss-mediumlmindexes are unaffected.)
- Pinned
inferedge-moss-core==0.17.0.
Added
MossClient.session(name, modelId?)- local-first session index. Construct a session, add/delete/get documents and run queries entirely in-process (no cloud round-trip per operation), thenpushIndex()to persist to the cloud. AlsoloadIndex(indexName, { autoRefresh, pollingIntervalInSeconds })to pull an existing cloud index into the session.- New top-level exports:
SessionIndex,PushIndexResult,LoadSessionOptions. - Bumped
@moss-dev/moss-coreto0.17.0(adds theSessionIndexnapi binding).
- Clean re-release of the v0.4.0 fixes. The v0.4.0 tag was force-moved, which SwiftPM caches as a pin mismatch; v0.4.1 ships the same xcframework as v0.4.0 with the synced 4-argument Swift wrapper. Consume with
from: "0.4.0"(resolves up) orfrom: "0.4.1".
Dependencies
- Bumped
inferedge-moss-coreto0.17.0.
Moss.xcframeworkrelease with iOS device (arm64) and iOS simulator (arm64) slices, consumed via.package(url: "https://github.com/usemoss/moss", from: "0.4.0").
- First tagged SwiftPM release of the Moss iOS SDK: binary
Moss.xcframeworkwith iOS device (arm64) and iOS simulator (arm64) slices, consumed via.package(url: "https://github.com/usemoss/moss", from: "0.3.0").
Added
- Local-first session indexing (merged from the separate
moss-sessionpackage):MossClient.session(index_name, model_id?)- creates aSessionIndex; auto-loads from cloud if an index with that name already exists, otherwise starts empty.SessionIndex.add_docs(docs, options?)/delete_docs(doc_ids)/get_docs(options?)- local in-memory mutations and reads.SessionIndex.query(query, options?)- semantic search over the local session index (~1-10ms, no network). Supports the same filter syntax asMossClient.query().SessionIndex.push_index()- uploads the session index to cloud, creating or replacing the index with the same name. Documents are pushed with their locally-computed embeddings; no server-side re-embedding.- New exports from
moss:SessionIndex,PushIndexResult.
model_id="custom"is supported for sessions - bring your own embeddings viaDocumentInfo.embeddingandQueryOptions.embedding; no local model is loaded.
Changed
pip install mossis now ~64% smaller.
- Built-in model downloads (
moss-minilm,moss-mediumlm) survive slow networks: resume after an interrupted connection instead of restarting, with automatic retries and exponential backoff on transient failures. (Also in 1.1.1.)
- Bumped
inferedge-moss-coreto0.14.0.
Fixed
- Built-in model downloads (
moss-minilm,moss-mediumlm) survive slow networks: resume after an interrupted connection instead of restarting, with automatic retries and exponential backoff on transient failures. - Bumped
inferedge-moss-coreto0.12.1.
First stable release of
moss-agent.AddedMossAgent- process-wide Moss runtime. Holds a hot index cache shared across every room (voice) or every request (text).- Voice path -
MossAgent.attach(ctx) -> MossCallbinds a Moss call scope to a LiveKitJobContext. Idempotent onctx.room.name.MossCall.queryandMossCall.query_multi_indexroute through the call scope. - Text path -
MossAgent.query(name, query, options=None)andMossAgent.query_multi_index(names, query, options=None)for HTTP / chat / non-LiveKit callers. - Full index CRUD (
create_index,add_docs,delete_docs,delete_index,list_indexes,get_index,get_docs,get_job_status) and cache lifecycle (load_index,load_indexes,unload_index,unload_indexes) onMossAgent. - Re-exports of
DocumentInfo,IndexInfo,QueryOptions,SearchResult, etc. frommoss_core.
inferedge-moss-core == 0.12.0- introduces themoss_core.Agentandmoss_core.CallScopePyO3 bindings this package wraps.
Breaking: top-level React component replaced.
- Replaced
MossFoundingAgentCardwithMossFoundingAgentBubble, a compact click-to-talk FAB that morphs into a pill with mute, elapsed-time, and end-call controls while live. Supportsposition="fixed"(default, bottom-right with safe-area insets) orposition="inline". Keyboard: Esc = end, M = mute. - Added a curated 6-color palette (
violet,cobalt,teal,emerald,coral,amber) exported asBUBBLE_COLORS. The bubble’scolorprop accepts a preset name. - Added
examples/bubble-playground/, a local Vite playground for previewing the bubble across all presets.
Added
query_multi_index(names, query, options): search across multiple loaded indexes; returns the global top-K with each doc tagged by sourceindex_name. Embedding-only;options.alphais ignored.load_indexes(names, ...)/unload_indexes(names): bulk lifecycle.load_indexesis best-effort and returnsLoadIndexesResult { loaded, failed }.index_namefield onQueryResultDocumentInfo(set on multi-index results).- Bumped
inferedge-moss-coreto0.11.0.
Changed
- Bumped
@moss-dev/moss-coredependency from0.9.1to0.10.0, which adds prebuilt binaries forx86_64-apple-darwin(Intel Macs) and realigns the npm package version with the underlying Rust core.
Changed
- Updated
requires-pythonfrom>=3.10to>=3.11to matchpipecat-ai 1.1.0requirements.
Changed
- Swapped runtime browser SDK from
@inferedge/mossto@moss-dev/moss-web
Initial release.
MossFoundingAgentserver class andcreateFoundingAgentSessionhelper for minting voice sessions from a Node backend (Next.js, Express, anywhere withfetch).<MossFoundingAgent />React component (exported from@moss-tools/founding-agent/react) that renders a voice UI - idle state, start button, visualizer, end-call - and connects to LiveKit via a company-supplied token endpoint.
Initial release of @moss-dev/moss-web - browser SDK for in-browser semantic search.Added
- In-browser semantic search: Full query pipeline runs entirely in the browser via WebAssembly
- Full CRUD operations:
createIndex,addDocs,deleteDocs,deleteIndex,listIndexes,getIndex,getDocs,getJobStatus - File-based index creation:
createIndexFromFilesacceptsUint8Arraydata (no filesystem paths in browser) - Local index operations:
loadIndex,query,refreshIndex,unloadIndex,hasIndex,getIndexInfo - Lazy initialization: WASM + model download happens automatically on first operation
- Metadata filtering: Same filter syntax as Node SDK (
$eq,$ne,$gt,$gte,$lt,$lte,$in,$nin,$near,$and,$or) - Embedding models:
moss-minilm(default),moss-mediumlm - API shape aligned with
@moss-dev/moss(Node SDK)
Added
- Custom authenticator for browser-safe authentication: new
MossClient.withAuthenticator()andIndexManager.withAuthenticator()factory methods accept a JS-side token callback, backed byJsAuthBridgein@moss-dev/moss-core(#226).
CLOUD_API_MANAGE_URLreplaced by granular constants:CLOUD_API_IDENTITY_URL,CLOUD_API_AUTH_URL, etc. (#226).
Added
submit_session_report(ctx, room_name)method onMossAgentSessionfor submitting LiveKit session reports (transcripts) to the Moss backend. Call from youron_session_endcallback to enable transcript download via the CLI.
- Precompiled
libmossbinaries for macOS ARM64, Linux x86_64, Linux ARM64, and Windows x86_64. Each archive shipsinclude/libmoss.hplus shared and static libraries. See C SDK.
Changed
- Bumped
moss_coredependency to 0.9.0. - Session authentication now uses short-lived JWT tokens (enterprise plan required).
- Removed
validate_credentialscall fromClient.session/3; credential exchange happens inside the Rust core during session init. - Updated package metadata and README.
Portal
- Refreshed dashboard aesthetic and added multi-org support with team management.
Architecture
- Rust-native core: The SDK now delegates all index management, querying, and embedding generation to
@moss-dev/moss-core(Rust via NAPI-RS), replacing the previous pure-JavaScript implementations - Node-only: Dropped browser/WASM support; the SDK targets Node.js 20+ exclusively
- Query embeddings are now generated in Rust (
queryText/loadQueryModel), matching the Python SDK architecture
- Package renamed from
@inferedge/mossto@moss-dev/moss - NAPI binding renamed from
moss-coreto@moss-dev/moss-core(v0.8.7, tracking Rust core version) query()uses Rust-nativequeryText()for local queries (no JS embedding pipeline)query()withembeddingoption uses Rustquery()directlyquery()falls back to cloud HTTP when index is not loaded locally
Changed
- Renamed package from
moss_sessiontomoss. - Published as a public Hex package (no longer requires
organization: "moss"). - Bumped version to 1.0.0 stable.
Changed
- The README, which is the package description on PyPI, has no emojis. The code is the same as in 0.1.0.
Added
- Filesystem Index Caching:
loadIndex()now accepts an optionalcachePathinLoadIndexOptionsto cache index binaries and documents to disk (Node.js/Bun only)- Cache is automatically invalidated when the cloud index is updated
- Auto-refresh also persists refreshed data to the cache
- Atomic writes prevent cache corruption from partial/interrupted writes
- Path traversal protection on index names
- Graceful fallback to re-download if cached data is corrupted
- Metadata Filtering:
query()now accepts an optionalfilterinQueryOptionsto narrow results by document metadata on locally loaded indexes- Comparison operators:
$eq,$ne,$gt,$gte,$lt,$lte - Set operators:
$in,$nin - Composable with
$and/$orfor complex predicates (supports arbitrary nesting) - Numeric coercion: number filter values are automatically stringified for consistent matching
- Comparison operators:
- Geo-distance filtering: new
$nearoperator filters documents by haversine distance from a"lat,lng,radiusMeters"value - New exported types:
FilterCondition,MetadataFilter
Added
- Initial release of
elevenlabs-mossintegration. MossClientToolfor registering Moss semantic search as an ElevenLabs client tool.- Example
moss-elevenlabs-demo.pydemonstrating tool registration.
First stable release of the
moss Python SDK (previously published as inferedge-moss).Import path changed: from moss import MossClient (was from inferedge_moss import ...)Features- Semantic search with built-in on-device models (
moss-minilm,moss-mediumlm); embedding computation runs in Rust for speed; custom embeddings supported viaQueryOptions.embedding - Hybrid search with keyword + semantic search and configurable alpha blending
- Metadata filtering on locally loaded indexes with rich operators (
$eq,$ne,$gt,$gte,$lt,$lte,$in,$nin,$and,$or,$nearfor geo-distance) - Cloud query fallback:
query()automatically falls back to the cloud API when the index is not loaded locally - Hot reload & auto-refresh:
load_index()supportsauto_refreshwith configurable polling interval to detect and reload updated indexes - Async bulk index pipeline: binary upload, server-side build, poll until completion
- Index mutations:
create_index,add_docs,delete_docsreturnMutationResultwithjob_id,index_name,doc_count - Multi-index support for isolated search spaces
- Python 3.10 to 3.14 supported
- Initial release - CLI wrapper for the Moss Python SDK (v1.0.0)
- Index management:
moss index create,list,get,delete - Document management:
moss doc add,delete,get - Semantic search:
moss querywith--cloud,--filter,--alpha,--top-k - Job tracking:
moss job statuswith--waitfor live progress - Interactive credential setup:
moss init - Three-tier auth resolution: CLI flags > env vars > config file
- JSON and CSV document input, stdin piping with
--file - --jsonflag on all commands for machine-readable output- Rich terminal output: tables, progress spinners, colored status
- Updated
inferedge-moss-coredependency to0.8.7 - Telemetry improvements
- Embedding computation for built-in models (
moss-minilm,moss-mediumlm) now runs in Rust; custom embeddings continue to be supported viaQueryOptions.embedding - Fixed
list_indexes()failing when the cloud API returnsnullfor certainIndexInfofields on indexes created by older SDK versions
Added
- Supports latest version of moss
Changed
- Bumped
moss_coredependency to 0.8.7, which fixes the precompiled NIF tarball for macOS - the file inside the archive is now named with the versioned filename so RustlerPrecompiled places it correctly inpriv/native.
Changed
- Bumped
moss_coredependency to 0.8.6, which fixes precompiled NIF packaging for macOS - the binary is now correctly distributed as.so(required by RustlerPrecompiled) instead of.dylib.
Changed
- Bumped
moss_coredependency to 0.8.5.
- Telemetry improvements
Initial release of the
moss_session Elixir SDK (later renamed to moss in 1.0.0) with local-first session indexing.AddedMoss.Client- single entry point for all operationsnew/3- creates a client; starts an internal local index managersession/3- auto-loads from cloud if the named index exists; starts empty otherwise; pre-warms built-in models ("moss-minilm"/"moss-mediumlm") to eliminate cold-start delay on first query- Cloud CRUD:
create_index/4(model_id optional, defaults to"moss-minilm"),add_docs/4,delete_docs/3,get_job_status/2,get_index/2,list_indexes/1,delete_index/2,get_docs/3 - Local index ops:
load_index/3,unload_index/2,has_index/2,query/4,refresh_index/2,get_index_info/2 - Generates a per-client UUID (
client_id) propagated to all sessions and managers for telemetry correlation
Moss.SessionGenServer - local in-session index backed by Rust coreadd_docs/3- built-in models embed automatically;model_id: "custom"reads.embeddingfrom eachDocumentInfo; returns{added, updated}delete_docs/2- remove documents by IDget_docs/2- retrieve documents (optionally filtered by ID list)query/3- semantic search; built-in models embed automatically;model_id: "custom"requiresembedding:opt; accepts metadata filtersload_index/2- load an existing cloud index into the sessionpush_index/1- push local index to cloud (create or replace); flushes telemetry
Moss.Models- Elixir structs:DocumentInfo,SearchResult,QueryResultDoc,IndexInfo,PushIndexResult,RefreshResult,SerializedIndex,MutationResult,JobStatusResponse,CredentialsInfo,ModelRef- Metadata filtering - all query functions accept
:filtermap with full operator support- Field conditions:
$eq,$ne,$gt,$gte,$lt,$lte,$in,$nin,$near - Logical combinators:
$and,$or(fully nestable)
- Field conditions:
- Background telemetry - aggregated telemetry handled by the Rust core
- Built-in models -
"moss-minilm"(fast) and"moss-mediumlm"(higher quality); embedding computation runs entirely in the Rust core via ONNX Runtime model_id: "custom"- bring your own pre-computed embeddings; no local model required
Fixed
- OpenAI TTS models (
tts-*/*-tts) are no longer cached at worker startup. The TTS instance is created per-session instead.
Added
- Support for passing Moss credentials (
project_id,project_key,voice_agent_id) directly into theMossAgentSessionconstructor andMossAgentSession.prewarm(), falling back toMOSS_*environment variables when not provided. - TTS configuration via the
optionsparameter onMossAgentSession, usingSessionOptions(tts=TTSOptions(...)). SupportedTTSOptionsfields:model,voice,language(Cartesia),emotion(Cartesia),instructions(OpenAIgpt-4o-mini-ttsonly). All fields override the platform-configured defaults and are forwarded directly to the underlying provider. SessionOptionsandTTSOptionsexported frommoss_voice_agent_managerfor IDE autocompletion support.- OpenAI TTS support: routes any model matching
tts-*prefix or*-ttssuffix (e.g.tts-1,gpt-4o-mini-tts) to the OpenAI plugin (optional dependency:pip install 'moss-voice-agent-manager[openai]').
Added
- Initial beta release of the Moss semantic search plugin for VitePress
MossPluginVitePress plugin with automatic markdown indexing via@moss-tools/md-indexerSearch.vuecomponent - full search modal with keyboard navigationSearchButton.vuecomponent - trigger button for the search modal- TypeScript types exported via
./types - Support for both ESM and CJS consumers
- Configurable
apiKey,indexId,placeholder, andmaxResultsoptions
Added
AgentServerre-exported frommoss_voice_agent_managerAgentSessionre-exported frommoss_voice_agent_managerinferencemodule re-exported frommoss_voice_agent_managerroom_iomodule re-exported frommoss_voice_agent_manager(includesRoomOptions,AudioInputOptions)MultilingualModelre-exported frommoss_voice_agent_manager(turn detection)livekit-plugins-turn-detector==1.3.11added as a dependencyvoice_agent_namefield added toMossConfig- populated from the platform credentials API, eliminating the need for a separatehttpxcall in agent code
Fixed
MossAgentSession.prewarm()no longer crashes with “no running event loop”.
Added
MossAgentSession.prewarm()static method for use asprewarm_fncinWorkerOptions- initializes providers once at worker startup instead of per sessionctxparameter onMossAgentSession.__init__()- when provided, reuses prewarmed providers from the worker process instead of creating new onesJobProcessre-exported frommoss_voice_agent_manager
- Reduced agent session startup latency by supporting the LiveKit prewarm pattern
Added
- Metadata Filtering:
query()now accepts an optionalfilterdict to narrow results by document metadata on locally loaded indexes- Comparison operators:
$eq,$ne,$gt,$gte,$lt,$lte - Set operators:
$in,$nin - Composable with
$and/$orfor complex predicates (supports arbitrary nesting) - Numeric coercion: int and float filter values are automatically converted to strings for consistent matching
- Comparison operators:
- Geo-distance filtering: new
$nearoperator filters documents by haversine distance from a"lat,lng,radiusMeters"value - When
filteris passed toquery()but the index is not loaded locally, a warning is logged and the filter is skipped (cloud query API does not yet support filtering) - Updated
inferedge-moss-coredependency to0.6.0
Portal
- Billing UI updates.
- Bumped
inferedge-moss-coredependency to0.5.0to support session index telemetry andpush_indeximprovements
Portal
- Self-service password and profile updates from account settings.
Changed
- Only set room agent configuration when
agentNameis explicitly provided tocreateParticipantToken() - Removed automatic fallback to
voice_agent_namefrom credentials, allowing dispatch rules to handle agent joining
Fixed
- Updated API endpoint from
/api/voice-agent-deploy/get-voice-agentto/api/voice-agent/get-voice-agentto match backend API changes
Changed (Complete Rewrite)Complete architectural rewrite. The SDK is now a runtime agent library instead of a deployment client.Old SDK: Deployment client that uploads code to backend
New SDK: Drop-in replacement for LiveKit AgentSession with Moss platform integrationAddedAfter (v1.0.0-beta.4 - Runtime SDK):
MossAgentSession- Drop-in replacement for LiveKit AgentSession- Dynamic configuration fetching from Moss platform API
- Runtime config API endpoint (
/api/voice-agent/get-runtime-config) - Voice agent credentials API endpoint (
/api/voice-agent/get-voice-agent) - Automatic provider configuration (STT, LLM, TTS)
- Built-in metrics tracking (LLM, TTS, STT, VAD, EOU)
- Diagnostics reporting with performance metrics
- Model/provider name masking for proprietary information
- Auto-initialization of VAD (Voice Activity Detection)
py.typedmarker for IDE IntelliSense support
MOSS_PROJECT_ID- Project identifierMOSS_PROJECT_KEY- Project authentication keyMOSS_VOICE_AGENT_ID- Voice agent identifier
MOSS_PLATFORM_API_URL- Platform API URL (defaults to production)
- No fallbacks - Fails hard if configuration/credentials missing
- Dynamic models - Model selection fetched from backend at runtime
- Secure credentials - LiveKit credentials fetched from Supabase via API
- No hardcoded secrets - All secrets from environment or API
MossVoiceClientclass (replaced withMossAgentSession)deploy()method (now runtime library, not deployment tool)- Custom tool source extraction
- Static configuration files
Added
- Async job-based mutations (
createIndex,addDocs,deleteDocs) with built-in polling andonProgresscallbacks - Large index support - up to 100k documents via presigned upload + server-side build
- New binary index format with smaller payloads and faster deserialization; existing indexes using the previous format are still supported
- Internal maintenance
- All index mutations and reads now go through the Rust ManageClient, replacing the Python HTTP layer
- Index creation uses an async bulk pipeline: binary upload → server-side build → poll until completion
load_indexsupports both V1 and V2 binary formats, with cloud query fallback when index isn’t loaded locally- New return type
MutationResult(withjob_id,index_name,doc_count) forcreate_index,add_docs,delete_docs get_docstakesdoc_idsdirectly instead of wrapping inGetDocumentsOptions
Changed (Breaking)After:
- Removed
agent_idparameter fromdeploy()method voice_agent_idis now used internally as the agent identifier- Reordered parameters:
voice_agent_idnow comes beforepromptindeploy() project_nameparameter now defaults tovoice_agent_id(previously defaulted toagent_id)
Initial beta release.Added
MossVoiceClientfor deploying voice agents to LiveKitdeploy()method with custom Python function tools support- Automatic source code extraction for custom tools
- Project-based authentication (X-Project-Id, X-Project-Key)
- Zero external dependencies (uses Python standard library)
Initial beta release.Added
MossVoiceServerclass for managing voice agent connectionsMossVoiceServer.create()- Fetch and initialize credentials from Moss APIvoiceServer.getServerUrl()- Get voice agent server URLvoiceServer.createParticipantToken()- Generate participant tokensvoiceServer.getAgentName()- Get configured agent name- Automatic credential caching
- Full TypeScript support with JSDoc
- Query latency reduced from ~2,300ms to ~10ms for 100K vectors
- Optimized search pipeline reducing memory allocations
- Significantly reduced memory overhead for large indexes (100K+ documents) in the context of hybrid search (keyword + semantic)
- Enhanced performance across all index sizes
- Fixed ESM related conflicts
Added
- Hot Reload & Auto-Refresh: Indexes can now automatically detect and reload when updated in the cloud.
load_index()now accepts optionalauto_refreshandpolling_interval_in_secondsparameters- When
auto_refreshis enabled, the SDK polls for updates at the configured interval (default: 600 seconds) - To stop auto-refresh, call
load_index()again without theauto_refreshoption
load_index()now allows reloading an already-loaded index (previously threw an error)- Index management now uses Rust core for improved performance and reliability
Added
- Hot Reload & Auto-Refresh: Indexes can now automatically detect and reload when updated in the cloud.
loadIndex()now accepts optionalLoadIndexOptionswithautoRefreshandpollingIntervalInSecondsparameters- When
autoRefreshis enabled, the SDK polls for updates at the configured interval (default: 600 seconds) - To stop auto-refresh, call
loadIndex()again without theautoRefreshoption
loadIndex()now allows reloading an already-loaded index (previously threw an error)
- Adds partial support for Python 3.14 by disabling local embedding service functionality. Full support coming soon.
- Adds support for user-supplied embeddings.
query()now automatically falls back to the cloud API when the index is not loaded locally, enabling queries without requiringload_index()first.- Adds better scoring evaluation for search results
Added
- Query optimizations for custom-embedding workflow
Fixed
- Fixed
ReferenceError: process is not definedcrash in browser environments. The SDK now works seamlessly across all JavaScript runtimes including browsers, Node.js, Deno, and Bun.
- Removes the ‘<2’ upper bound on numpy dependency.
Added
- Support for user-supplied document embeddings during ingestion. The SDK supports optional
embeddingarrays inDocumentInfopayloads without using the native embedding service from moss. - Query overloads now accept
QueryOptionsso users can provide a custom embedding alongside query text. - Relaxed
modelIdrequirement when creating indexes. The SDK aligns with the service default ofmoss-minilmwhen no explicit model is provided. query()now automatically falls back to the cloud API when the index is not loaded locally, enabling queries without requiringloadIndex()first.
- New service endpoint with significant infrastructure upgrades. Management operations are now ~3× faster across most real-world use cases, providing faster index operations while also supporting larger payloads.
Added
- Support for Pipecat v0.0.99.
- Support for LLMContext and LLMContextAggregatorPair
- removed deprecated OpenAILLMContext and OpenAILLMContextAggregatorPair
- Drops support for Python 3.9 and below.
- Bug fix: Keyword search now functions correctly after
load_index(). - New service endpoint with significant infrastructure upgrades. Management operations are now ~3× faster across most real-world use cases, providing faster index operations while also supporting larger payloads.
- function-based API for programmatic usage
- Exported
sync()function for building and uploading in one call - Exported
buildJsonDocs()function for building search index programmatically - Exported
uploadDocuments()function for uploading documents programmatically - Exported
createIndex()function for uploading an existing index file - Functions can be imported and called directly in code
- Support for passing credentials via function options or environment variables
- Functions return structured data (e.g.,
{ success: boolean, count: number })
- Exported
Added
- Initial release of
pipecat-mossintegration. MossRetrievalServicefor augmenting Pipecat LLM contexts with retrieved documents- Example
moss-retrieval-demo.pydemonstrating a full voice pipeline with retrieval. moss-create-index-demo.pyfor creating and populating a Moss index.
- Updates
inferedge-moss-coredependency to version 0.2.3 for new ARM64 wheel support.
Adds IntelliSense support in all the IDEs
Fixed
- Fixed ESM (ES Module) import compatibility issue. The package now correctly exports as an ES module and can be imported using standard ESM syntax.
- Migrate from CommonJS (
require) to ES Module syntax (import).
Adds support for keyword search and alpha blending between keyword and semantic search.
Removes Pipecat integration and MossContextRetriever from the SDK. Will be offered as a pipecat extension instead soon.
Performance improvements for query() calls.
New Features
- MossContextRetriever: Added Pipecat integration for real-time voice AI applications
- Automatically enhances LLM conversations with semantic search results from Moss indexes
- Seamless integration with OpenAI LLM context frames
Initial release of @moss-dev/moss with core features:
- Semantic search using transformer-based embeddings
- Lightweight embedding models for edge computing; supports proprietary “moss-minilm” and “moss-mediumlm” models
- Multi-index support for isolated search spaces
- Add, update, and remove documents across indexes
- Blazing fast querying support after loading indexes
- TypeScript support with full type definitions
Initial release of inferedge-moss with core features:
- Semantic search using transformer-based embeddings
- Lightweight embedding models for edge computing; supports proprietary “moss-minilm” model
- API key validation with secure host access
- Cloudflare CDN support for fast model loading
- Multi-index support for isolated search spaces
- Add, update, and remove items across indexes
- Query interface with configurable result count
- Performance metrics tracking