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.
- package/SKILL.md +1 -0
- package/dist/chrome/connection.js +2 -2
- package/dist/chrome/connection.js.map +1 -1
- package/dist/cli.js +51 -0
- package/dist/cli.js.map +1 -1
- package/dist/cljs/compiler.d.ts.map +1 -1
- package/dist/cljs/compiler.js +1 -0
- package/dist/cljs/compiler.js.map +1 -1
- package/dist/commands/install-nvim.d.ts +21 -0
- package/dist/commands/install-nvim.d.ts.map +1 -0
- package/dist/commands/install-nvim.js +127 -0
- package/dist/commands/install-nvim.js.map +1 -0
- package/dist/commands/serve.d.ts +16 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +22 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/repl/repl.d.ts +8 -8
- package/dist/repl/repl.d.ts.map +1 -1
- package/dist/repl/repl.js +45 -131
- package/dist/repl/repl.js.map +1 -1
- package/dist/session/jsonrpc-protocol.d.ts +18 -0
- package/dist/session/jsonrpc-protocol.d.ts.map +1 -0
- package/dist/session/jsonrpc-protocol.js +59 -0
- package/dist/session/jsonrpc-protocol.js.map +1 -0
- package/dist/session/protocol.d.ts +47 -0
- package/dist/session/protocol.d.ts.map +1 -0
- package/dist/session/protocol.js +10 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/repl-protocol.d.ts +16 -0
- package/dist/session/repl-protocol.d.ts.map +1 -0
- package/dist/session/repl-protocol.js +101 -0
- package/dist/session/repl-protocol.js.map +1 -0
- package/dist/session/session.d.ts +44 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +195 -0
- package/dist/session/session.js.map +1 -0
- package/editor/nvim/README.md +134 -0
- package/editor/nvim/lua/cjig/init.lua +226 -0
- package/editor/nvim/lua/cjig/rpc.lua +177 -0
- package/editor/nvim/lua/cjig/ui.lua +88 -0
- 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.
|
|
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
|
],
|