Skip to content

Conversation

@marcus-daily
Copy link
Contributor

No description provided.

}
}

if (handler == null) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per the other discussion, i do not believe this is an if/else situation.

Separately, I don't understand Kotlin. How does the registered functionCallHandler pass back the resultData used in the resultHandler?

Also note that in client-js/ios, I don't believe we are providing built-in support for sending back a result for the generic onLLMFunctionCall callback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll update this.

How does the registered functionCallHandler pass back the resultData used in the resultHandler?

We give the function call handler two arguments, the functionCallData, and onResult, the latter of which is a function (defined as the lambda resultHandler above). The function call handler invokes onResult(value) with the value once it's done.

Also note that in client-js/ios, I don't believe we are providing built-in support for sending back a result for the generic onLLMFunctionCall callback.

This would make sense (to avoid two responses), however I think currently the iOS client does currently accept a result in the callback (tagging @filipi87):

func onLLMFunctionCall(functionCallData: LLMFunctionCallData, onResult: ((Value) async -> Void)) async

else -> {
Log.w(TAG, "Unexpected message type '${msg.type}'")

callbacks.onGenericMessage(msg)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did away with the onGenericMessage handler in 1.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Will remove.

TransportState.Connected,
TransportState.Ready -> return@runOnThreadReturningFuture resolvedPromiseErr(
thread,
PipecatError.InvalidState(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might be right that a better name for this type of error is a PipecatError, but if we want to be consistent, they are RTVIErrors in the client-js API.

I'm starting to feel like a lesson-learned from this is for all platforms to update simultaneously so we work out these oddities and overlooked corners before we're stuck with them simply because "it's the way i did it 🤷‍♀️ "

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my defense, I think it's because we have one Error type and I think my hands were tied because i needed to define the Error type as part of the RTVI portion of the library due to dependencies in the RTVIEvents

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂 Okay, I'll rename this back to RTVIError for consistency.

thread = thread,
url = startBotParams.endpoint,
body = JSON_INSTANCE.encodeToString(startBotParams.requestData)
.toRequestBody("application/json".toMediaType()),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is "application/json" not part of the headers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is just a quirk of the OkHTTP API and the headers get set as a result of this.

/**
* Initiate an RTVI session, connecting to the backend.
*/
fun connect(transportParams: Value): Future<Unit, PipecatError> =
Copy link

@mattieruth mattieruth Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: transportConnectionParams or connectParams

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah -- I copied this from the iOS API which uses transportParams. Happy to change if we can settle on a name, maybe connectParams? Because Swift and Kotlin use named params this is an API break if we update iOS retroactively. Tagging @filipi87.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not worth breaking on a nit. the js signature is:

public async connect(connectParams?: TransportConnectionParams): Promise<BotReadyData>

which is where i conjured up those names, but probably better to prioritize android being consistent with ios vs. js

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, will leave as transportParams in that case.

* Initiate an RTVI session, connecting to the backend.
*/
fun connect(transportParams: Value): Future<Unit, PipecatError> =
thread.runOnThreadReturningFuture {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should also throw an error if the state is already authorizing/authorized/connecting/connected

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nm. maybe the logic below actually does that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it's currently relying on the existence of the connection object which seems cleaner imo than checking if we're in one of the 4 of 9 acceptable states.

)
}

Log.w(TAG, "No connect endpoint specified, skipping auth request")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accidental leave-over log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, well spotted.


Log.w(TAG, "No connect endpoint specified, skipping auth request")
connection = Connection()
return@runOnThreadReturningFuture transport.connect(transportParams)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where are devices initialized on connect()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do this inside the transport (to avoid the outer client needing to keep track of whether it was already done)

val arguments: List<Option>
data class ClientAbout(
val library: String,
@SerialName("library_version")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, what does this resolve to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm setting this in the transports (not pushed yet), to the version of the transport library ("1.0.0" in this case).

)

@Serializable
data class BotLLMSearchResponseData(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our type here is very different. i'm trying to understand if they should be? something tells me yours is more accurate, but then again, i know i've tested this and it worked on client-js 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's weird. I based these on the types in the iOS client here:

https://github.com/pipecat-ai/pipecat-client-ios/pull/25/files#diff-5ee5b746fe28d28b1782f80bdcedc284af281591c322a004339f63028a7ade61

Which differ dramatically from the web version:

https://github.com/pipecat-ai/pipecat-client-web/blob/c81f41aa35a05ad2b1b1f82693509871d991ef6e/client-js/rtvi/messages.ts#L143

Since you've tested these I'm happy to change the Android ones to match. It would be good to understand how the difference arose though (maybe the iOS ones are left over historically?)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but i also see these fields in the pipecat GoogleLLMService code. so don't delete yet. i'll see if i can dig.

@marcus-daily marcus-daily merged commit dbb4831 into main Aug 29, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants