nrepl

ericdallo 2025-04-08T14:44:33.420459Z

How can I know which client/editor is using nrepl, is there any middleware I can wrap to know that?

ericdallo 2025-04-08T14:44:45.258519Z

tried checking describe op but found nothing

oyakushev 2025-04-08T15:09:40.567219Z

As in, how to know on the server side what type of client has connected to it?

ericdallo 2025-04-08T15:10:29.764979Z

I'd expect that client send any info in any op to know that, similar to the LSP protocol initialize request

oyakushev 2025-04-08T15:13:47.682659Z

Looking at the docs and the code, I don't see any standard way for clients to identify themselves. There is no init op, a successful socket connection means that the client is active and is allowed to send requests.

ericdallo 2025-04-08T15:14:28.564419Z

yeah, that's what I was afraid πŸ˜”

oyakushev 2025-04-08T15:14:51.739129Z

Do you want to tune responses based on the client?

ericdallo 2025-04-08T15:17:52.101409Z

nope, I'm building a middleware that will export multiple metrics about the REPL usage, since JVM startup to evaluated things and errors. One of the metrics I want to export is the client used

ericdallo 2025-04-08T15:21:53.214929Z

I just found that I think I can wrap describe middleware and access the :aux , so maybe infer something from there:

{:id "3",
 :session "98b13ffd-efc3-4450-8a52-25b16af0a61e",
 :aux
 {:cider-version
  {:major 0,
   :minor 52,
   :incremental 0,
   :qualifier nil,
   :version-string "0.52.0"},
  :current-ns "user"},
 :ops
 {...},
 :versions
 {:nrepl {:major 1, :minor 3, :incremental 1, :version-string "1.3.1"},
  :clojure
  {:major 1, :minor 12, :incremental 0, :version-string "1.12.0"},
  :java {:major 17, :version-string "17.0.13"}},
 :status #{:done}}

ericdallo 2025-04-08T15:22:14.718059Z

hum, although that cider is related to cider-nrepl and not cider from emacs I guess

oyakushev 2025-04-08T15:22:36.459799Z

Yeah, 0.52.0 is a cider-nrepl version (the middleware library)

ericdallo 2025-04-08T15:23:02.406949Z

that's a pity there is no info like that on any op request or response

oyakushev 2025-04-08T15:24:02.696189Z

Yeah, seems like that

ericdallo 2025-04-08T15:27:39.946689Z

does it sounds like a crazy idea to add to a describe op something like :client-name "my-plugin", :client-version "..." to cider, calva, and clojure-repl-intellij? I believe only cursive is not easy to add, but most of main editors yes, if maintainers agree. Not sure there is a better idea

oyakushev 2025-04-08T15:28:32.364859Z

The client is not required to call describe, that's the thing

ericdallo 2025-04-08T15:29:03.412969Z

yeah I know, but I think all of the main editors do that

oyakushev 2025-04-08T15:30:22.867979Z

Looking at CIDER, it indeed invokes describe at the beginning to get server capabilities.

ericdallo 2025-04-08T15:30:37.486789Z

it's just really weird to me I can't know what client initialized the nrepl process

ericdallo 2025-04-08T15:30:49.882409Z

feels like nrepl should have a built-in op or something to help with that

oyakushev 2025-04-08T15:32:09.619729Z

Again, it's not about having op, but about obliging the clients to call it. That is a change in the protocol.

oyakushev 2025-04-08T15:32:31.097999Z

I don't mind sending client identification in describe, although it feels a bit hacky

ericdallo 2025-04-08T15:32:43.219849Z

yeah, I agree we cant obligate that, but more like a good practice

ericdallo 2025-04-08T15:32:53.933889Z

> although it feels a bit hacky agree

oyakushev 2025-04-08T15:33:14.836419Z

@bozhidar can probably tell better if it's a viable approach

πŸ‘ 1
bozhidar 2025-04-09T08:02:48.793169Z

> does it sounds like a crazy idea to add to a describe op something like :client-name "my-plugin", :client-version "..." to cider, calva, and clojure-repl-intellij? I believe only cursive is not easy to add, but most of main editors yes, if maintainers agree. Any op can contribute to the describe - this was part of the idea, so we can get richer information about the server's environment. I'm not sure if that's the best course of action for you, but it's one option for you. Alternatively we can modify clone to accept some additional data I guess. So far there was never need to track the clients.

oyakushev 2025-04-09T08:14:57.916049Z

It's slightly different – it is not about describe op returning more data about the server, but about it accepting more data from the client (client details). Then there's the question what to do with that data coming in. Should nREPL save it somewhere?

☝️ 1
bozhidar 2025-04-09T08:51:40.248959Z

Yeah, I get the point, that's why I thought it's best to add such info at session creation time (`clone`) instead of when the session gets described.

ericdallo 2025-04-09T11:41:55.163009Z

Interesting, so in your idea, client would send more data to clone which we could have a middleware that wraps clone and add such info in the session or as other fields?

bozhidar 2025-04-09T11:42:49.150959Z

Yeah, this seems like the most natural approach to me if you want to attach more info a session.

ericdallo 2025-04-09T11:46:32.357099Z

Ok, I'm open to open Prs in Calva, cider and Intellij that I know the codebase to add that info to clone, but I think we would need to open a new one to nrepl, adding that middleware, is that right?

ericdallo 2025-04-09T12:51:07.053099Z

something like that makes sense?

(defun nrepl-sync-request:clone (connection &optional tooling)
  (nrepl-send-sync-request `("op" "clone"
                             "client-name" "CIDER"
                             "client-version" ,cider-version)
                           connection
                           nil tooling))

ericdallo 2025-04-09T12:52:34.538529Z

on a second thought, I think only changing clients to include that info is enough for me, not sure we need that change on nrepl, just my middleware will use that wrapping that op

ericdallo 2025-04-09T12:53:56.839519Z

well we will need to change nrepl docs to include these optional client- fields, but I think only that?

bozhidar 2025-04-09T12:59:18.104379Z

Sounds good to me.

πŸ‘ 1
ericdallo 2025-04-09T13:15:15.503909Z

reviewplease https://github.com/clojure-emacs/cider/pull/3806

ericdallo 2025-04-09T13:15:38.425229Z

working on nrepl PR

ericdallo 2025-04-09T13:41:01.380649Z

reviewplease https://github.com/nrepl/nrepl/pull/370

2025-04-09T13:46:15.499399Z

maybe this can be called user-agent which is an already known mechanism from browsers/http-servers?

ericdallo 2025-04-09T13:47:00.342279Z

both work for me

oyakushev 2025-04-09T13:47:07.048639Z

But why? We never use the term agent anywhere

ericdallo 2025-04-09T13:47:46.608939Z

yeah, the nREPL client term is used usually to identify editors, I think so

2025-04-09T13:48:26.035399Z

yeah, I mean, on one side it is easy to infer for most people what it is about. On the downside maybe a user-agent is a string with some constrained format, I don't remember

ericdallo 2025-04-09T14:02:48.015759Z

https://github.com/BetterThanTomorrow/calva/pull/2774 waiting for nrepl PR

ericdallo 2025-04-09T14:11:42.444139Z

https://github.com/afucher/clojure-repl-intellij/pull/152 waiting for nrepl PR

ericdallo 2025-04-09T14:28:05.403959Z

https://github.com/Olical/conjure/pull/659 waiting for nrepl PR

ericdallo 2025-04-09T14:29:11.317349Z

I think only cursive missing from plugins of main editors, I can talk with colin later after those others are merged

2025-04-09T16:17:23.490469Z

you stole my thunder with that conjure pr lmao. i asked in the discord about finding the version earlier.

πŸ˜… 1
pez 2025-04-09T16:52:05.621179Z

Other nrepl params use kebab-case, is there a point with keeping it like that also for these infos? (The PR uses camelCase, so that’s why I am asking.)

pez 2025-04-09T16:55:02.743889Z

Also wondering is sending along editor, os, and cpu architecture may make sense.

ericdallo 2025-04-09T16:57:42.473329Z

@pez I thought calva would convert camelCase to kebab πŸ˜… , so maybe we need to make that on calva side as all nrepl params are kebab, right?

ericdallo 2025-04-09T16:58:44.692439Z

About the other data, the server can access that via properties, only editor that not, but we can discuss if it makes sense to send the editor, because indeed Calva is not enough to know if it's being used in VSCode or Cursor, for example

pez 2025-04-09T17:05:50.733199Z

Yeah, lot’s of forks ! πŸ˜ƒ

pez 2025-04-09T17:06:29.245759Z

There is no auto-conversion of camel to kebab happening.

πŸ‘ 1
ericdallo 2025-04-09T17:08:50.475079Z

Just fixed the calva PR!

πŸ™ 1