chrome-jig 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/SKILL.md +1 -0
  2. package/dist/chrome/connection.js +2 -2
  3. package/dist/chrome/connection.js.map +1 -1
  4. package/dist/cli.js +51 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/cljs/compiler.d.ts.map +1 -1
  7. package/dist/cljs/compiler.js +1 -0
  8. package/dist/cljs/compiler.js.map +1 -1
  9. package/dist/commands/install-nvim.d.ts +21 -0
  10. package/dist/commands/install-nvim.d.ts.map +1 -0
  11. package/dist/commands/install-nvim.js +127 -0
  12. package/dist/commands/install-nvim.js.map +1 -0
  13. package/dist/commands/serve.d.ts +16 -0
  14. package/dist/commands/serve.d.ts.map +1 -0
  15. package/dist/commands/serve.js +22 -0
  16. package/dist/commands/serve.js.map +1 -0
  17. package/dist/index.d.ts +9 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +7 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/repl/repl.d.ts +8 -8
  22. package/dist/repl/repl.d.ts.map +1 -1
  23. package/dist/repl/repl.js +45 -131
  24. package/dist/repl/repl.js.map +1 -1
  25. package/dist/session/jsonrpc-protocol.d.ts +18 -0
  26. package/dist/session/jsonrpc-protocol.d.ts.map +1 -0
  27. package/dist/session/jsonrpc-protocol.js +59 -0
  28. package/dist/session/jsonrpc-protocol.js.map +1 -0
  29. package/dist/session/protocol.d.ts +47 -0
  30. package/dist/session/protocol.d.ts.map +1 -0
  31. package/dist/session/protocol.js +10 -0
  32. package/dist/session/protocol.js.map +1 -0
  33. package/dist/session/repl-protocol.d.ts +16 -0
  34. package/dist/session/repl-protocol.d.ts.map +1 -0
  35. package/dist/session/repl-protocol.js +101 -0
  36. package/dist/session/repl-protocol.js.map +1 -0
  37. package/dist/session/session.d.ts +44 -0
  38. package/dist/session/session.d.ts.map +1 -0
  39. package/dist/session/session.js +195 -0
  40. package/dist/session/session.js.map +1 -0
  41. package/editor/nvim/README.md +134 -0
  42. package/editor/nvim/lua/cjig/init.lua +226 -0
  43. package/editor/nvim/lua/cjig/rpc.lua +177 -0
  44. package/editor/nvim/lua/cjig/ui.lua +88 -0
  45. package/package.json +2 -1
@@ -0,0 +1,177 @@
1
+ --- JSON-RPC 2.0 transport over stdio to `cjig serve`.
2
+ ---
3
+ --- States: disconnected -> connecting -> connected (or error).
4
+ --- Auto-buffers partial lines from stdout.
5
+ --- Detects "Connected to" on stderr to confirm readiness.
6
+
7
+ local M = {}
8
+
9
+ -- State
10
+ local state = "disconnected"
11
+ local job_id = nil
12
+ local next_id = 1
13
+ local pending = {} -- id -> { on_result, on_error }
14
+ local queued = {} -- callbacks waiting for connected state
15
+ local stdout_buf = "" -- partial line buffer
16
+
17
+ --- Send a JSON-RPC 2.0 request.
18
+ --- @param method string
19
+ --- @param params table
20
+ --- @param on_result function(result)
21
+ --- @param on_error function(message)
22
+ function M.request(method, params, on_result, on_error)
23
+ if state ~= "connected" then
24
+ on_error("Not connected")
25
+ return
26
+ end
27
+
28
+ local id = next_id
29
+ next_id = next_id + 1
30
+ pending[id] = { on_result = on_result, on_error = on_error }
31
+
32
+ local payload = vim.json.encode({
33
+ jsonrpc = "2.0",
34
+ id = id,
35
+ method = method,
36
+ params = params or {},
37
+ })
38
+
39
+ vim.fn.chansend(job_id, payload .. "\n")
40
+ end
41
+
42
+ --- Handle stdout data from the cjig process.
43
+ local function on_stdout(_, data, _)
44
+ for i, chunk in ipairs(data) do
45
+ if i == 1 then
46
+ stdout_buf = stdout_buf .. chunk
47
+ else
48
+ -- Previous buffer is a complete line
49
+ local line = stdout_buf
50
+ stdout_buf = chunk
51
+
52
+ if line ~= "" then
53
+ vim.schedule(function()
54
+ local ok, decoded = pcall(vim.json.decode, line)
55
+ if not ok then return end
56
+
57
+ local id = decoded.id
58
+ if id == nil then return end
59
+
60
+ local cb = pending[id]
61
+ if not cb then return end
62
+ pending[id] = nil
63
+
64
+ if decoded.error then
65
+ cb.on_error(decoded.error.message or "Unknown error")
66
+ else
67
+ cb.on_result(decoded.result)
68
+ end
69
+ end)
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ --- Handle stderr data from the cjig process.
76
+ local function on_stderr(_, data, _)
77
+ for _, line in ipairs(data) do
78
+ if line == "" then goto continue end
79
+
80
+ if line:find("Connected to") then
81
+ vim.schedule(function()
82
+ state = "connected"
83
+ vim.notify("cjig: " .. line, vim.log.levels.INFO)
84
+ -- Flush queued callbacks
85
+ local q = queued
86
+ queued = {}
87
+ for _, cb in ipairs(q) do
88
+ cb()
89
+ end
90
+ end)
91
+ else
92
+ vim.schedule(function()
93
+ vim.notify("cjig: " .. line, vim.log.levels.DEBUG)
94
+ end)
95
+ end
96
+
97
+ ::continue::
98
+ end
99
+ end
100
+
101
+ --- Handle process exit.
102
+ local function on_exit(_, exit_code, _)
103
+ vim.schedule(function()
104
+ job_id = nil
105
+ state = "disconnected"
106
+ pending = {}
107
+ stdout_buf = ""
108
+ if exit_code ~= 0 then
109
+ vim.notify("cjig exited with code " .. exit_code, vim.log.levels.WARN)
110
+ end
111
+ -- Reject queued callbacks
112
+ local q = queued
113
+ queued = {}
114
+ for _, cb in ipairs(q) do
115
+ cb() -- they'll see state ~= "connected" if they check
116
+ end
117
+ end)
118
+ end
119
+
120
+ --- Start the cjig serve process.
121
+ function M.connect()
122
+ if state ~= "disconnected" then
123
+ vim.notify("cjig: already " .. state, vim.log.levels.WARN)
124
+ return
125
+ end
126
+
127
+ state = "connecting"
128
+ stdout_buf = ""
129
+
130
+ job_id = vim.fn.jobstart({ "cjig", "serve", "--stdio" }, {
131
+ on_stdout = on_stdout,
132
+ on_stderr = on_stderr,
133
+ on_exit = on_exit,
134
+ stdout_buffered = false,
135
+ stderr_buffered = false,
136
+ })
137
+
138
+ if job_id <= 0 then
139
+ state = "disconnected"
140
+ vim.notify("cjig: failed to start (is cjig installed?)", vim.log.levels.ERROR)
141
+ end
142
+ end
143
+
144
+ --- Stop the cjig serve process.
145
+ function M.disconnect()
146
+ if job_id then
147
+ vim.fn.jobstop(job_id)
148
+ end
149
+ state = "disconnected"
150
+ job_id = nil
151
+ pending = {}
152
+ queued = {}
153
+ stdout_buf = ""
154
+ end
155
+
156
+ --- Auto-connect on first use, then invoke callback when ready.
157
+ --- @param callback function
158
+ function M.ensure_connected(callback)
159
+ if state == "connected" then
160
+ callback()
161
+ return
162
+ end
163
+
164
+ if state == "disconnected" then
165
+ M.connect()
166
+ end
167
+
168
+ -- Queue callback for when "Connected to" arrives
169
+ table.insert(queued, callback)
170
+ end
171
+
172
+ --- @return boolean
173
+ function M.is_connected()
174
+ return state == "connected"
175
+ end
176
+
177
+ return M
@@ -0,0 +1,88 @@
1
+ --- Display layer — floating windows and error reporting.
2
+
3
+ local M = {}
4
+
5
+ local float_win = nil
6
+ local float_buf = nil
7
+
8
+ --- Close any existing float.
9
+ local function close_float()
10
+ if float_win and vim.api.nvim_win_is_valid(float_win) then
11
+ vim.api.nvim_win_close(float_win, true)
12
+ end
13
+ float_win = nil
14
+ float_buf = nil
15
+ end
16
+
17
+ --- Format a result value into display lines.
18
+ --- @param value any
19
+ --- @return string[]
20
+ local function format_lines(value)
21
+ if value == nil or value == vim.NIL then
22
+ return { "nil" }
23
+ end
24
+
25
+ if type(value) == "table" then
26
+ -- Pretty-print with indentation
27
+ local encoded = vim.json.encode(value)
28
+ -- Try to decode and re-encode with indentation
29
+ local ok, decoded = pcall(vim.json.decode, encoded)
30
+ if ok then
31
+ local pretty = vim.inspect(decoded)
32
+ return vim.split(pretty, "\n", { plain = true })
33
+ end
34
+ return { encoded }
35
+ end
36
+
37
+ return vim.split(tostring(value), "\n", { plain = true })
38
+ end
39
+
40
+ --- Show a result in a floating window near the cursor.
41
+ --- @param value any
42
+ function M.show_result(value)
43
+ close_float()
44
+
45
+ local lines = format_lines(value)
46
+ if #lines == 0 then return end
47
+
48
+ -- Compute dimensions
49
+ local max_width = 0
50
+ for _, line in ipairs(lines) do
51
+ max_width = math.max(max_width, #line)
52
+ end
53
+ local width = math.min(max_width + 2, math.floor(vim.o.columns * 0.8))
54
+ local height = math.min(#lines, math.floor(vim.o.lines * 0.4))
55
+
56
+ float_buf = vim.api.nvim_create_buf(false, true)
57
+ vim.api.nvim_buf_set_lines(float_buf, 0, -1, false, lines)
58
+ vim.bo[float_buf].modifiable = false
59
+ vim.bo[float_buf].bufhidden = "wipe"
60
+
61
+ float_win = vim.api.nvim_open_win(float_buf, false, {
62
+ relative = "cursor",
63
+ row = 1,
64
+ col = 0,
65
+ width = width,
66
+ height = height,
67
+ style = "minimal",
68
+ border = "rounded",
69
+ })
70
+
71
+ -- Auto-close on cursor movement
72
+ local group = vim.api.nvim_create_augroup("CjigFloat", { clear = true })
73
+ vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI", "BufLeave" }, {
74
+ group = group,
75
+ once = true,
76
+ callback = function()
77
+ close_float()
78
+ end,
79
+ })
80
+ end
81
+
82
+ --- Show an error via vim.notify.
83
+ --- @param message string
84
+ function M.show_error(message)
85
+ vim.notify("cjig: " .. message, vim.log.levels.ERROR)
86
+ end
87
+
88
+ return M
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-jig",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Chrome debugging REPL with CDP, script injection, and Claude skill support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -35,6 +35,7 @@
35
35
  "files": [
36
36
  "dist",
37
37
  "bin",
38
+ "editor",
38
39
  "SKILL.md",
39
40
  "README.md"
40
41
  ],