boxsh.js 1.0.0 → 2.0.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/client.mjs +42 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boxsh.js",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Node.js SDK for boxsh — sandboxed shell execution with overlay copy-on-write and JSON-line RPC",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
package/src/client.mjs CHANGED
@@ -74,7 +74,12 @@ export class BoxshClient {
74
74
  const entry = this.#pending.get(id);
75
75
  if (!entry) return;
76
76
  this.#pending.delete(id);
77
- entry.resolve(resp);
77
+ // JSON-RPC 2.0: unwrap result or reject with error.
78
+ if (resp.error) {
79
+ entry.reject(new Error(resp.error.message || 'unknown error'));
80
+ } else {
81
+ entry.resolve(resp.result);
82
+ }
78
83
  });
79
84
 
80
85
  this.#proc.on('error', (err) => this.#failAll(err));
@@ -107,7 +112,13 @@ export class BoxshClient {
107
112
  }
108
113
  const id = this.#nextId();
109
114
  this.#pending.set(id, { resolve, reject });
110
- this.#proc.stdin.write(JSON.stringify({ ...req, id }) + '\n');
115
+ // JSON-RPC 2.0 envelope.
116
+ this.#proc.stdin.write(JSON.stringify({
117
+ jsonrpc: '2.0',
118
+ id,
119
+ method: req.method,
120
+ params: req.params,
121
+ }) + '\n');
111
122
  });
112
123
  }
113
124
 
@@ -121,14 +132,18 @@ export class BoxshClient {
121
132
  */
122
133
  async exec(cmd, cwd, timeout) {
123
134
  const command = cwd ? `(cd ${shellQuote(cwd)} && ${cmd})` : cmd;
124
- const req = { cmd: command };
125
- if (timeout !== undefined && timeout > 0) req.timeout = timeout;
135
+ const args = { command };
136
+ if (timeout !== undefined && timeout > 0) args.timeout = timeout;
126
137
 
127
- const resp = await this.#send(req);
138
+ const result = await this.#send({
139
+ method: 'tools/call',
140
+ params: { name: 'bash', arguments: args },
141
+ });
142
+ const sc = result.structuredContent ?? {};
128
143
  return {
129
- exitCode: typeof resp.exit_code === 'number' ? resp.exit_code : null,
130
- stdout: typeof resp.stdout === 'string' ? resp.stdout : '',
131
- stderr: typeof resp.stderr === 'string' ? resp.stderr : '',
144
+ exitCode: typeof sc.exit_code === 'number' ? sc.exit_code : null,
145
+ stdout: typeof sc.stdout === 'string' ? sc.stdout : '',
146
+ stderr: typeof sc.stderr === 'string' ? sc.stderr : '',
132
147
  };
133
148
  }
134
149
 
@@ -141,13 +156,15 @@ export class BoxshClient {
141
156
  * @returns {Promise<string>}
142
157
  */
143
158
  async read(filePath, offset, limit) {
144
- const req = { tool: 'read', path: filePath };
145
- if (offset !== undefined) req.offset = offset;
146
- if (limit !== undefined) req.limit = limit;
159
+ const args = { path: filePath };
160
+ if (offset !== undefined) args.offset = offset;
161
+ if (limit !== undefined) args.limit = limit;
147
162
 
148
- const resp = await this.#send(req);
149
- if (resp.error) throw new Error(String(resp.error));
150
- return resp.content[0].text;
163
+ const result = await this.#send({
164
+ method: 'tools/call',
165
+ params: { name: 'read', arguments: args },
166
+ });
167
+ return result.content[0].text;
151
168
  }
152
169
 
153
170
  /**
@@ -157,8 +174,10 @@ export class BoxshClient {
157
174
  * @param {string} content Full file content to write
158
175
  */
159
176
  async write(filePath, content) {
160
- const resp = await this.#send({ tool: 'write', path: filePath, content });
161
- if (resp.error) throw new Error(String(resp.error));
177
+ await this.#send({
178
+ method: 'tools/call',
179
+ params: { name: 'write', arguments: { path: filePath, content } },
180
+ });
162
181
  }
163
182
 
164
183
  /**
@@ -172,11 +191,14 @@ export class BoxshClient {
172
191
  * @returns {Promise<{ diff: string, firstChangedLine: number }>}
173
192
  */
174
193
  async edit(filePath, edits) {
175
- const resp = await this.#send({ tool: 'edit', path: filePath, edits });
176
- if (resp.error) throw new Error(String(resp.error));
194
+ const result = await this.#send({
195
+ method: 'tools/call',
196
+ params: { name: 'edit', arguments: { path: filePath, edits } },
197
+ });
198
+ const sc = result.structuredContent ?? {};
177
199
  return {
178
- diff: resp.details?.diff ?? '',
179
- firstChangedLine: resp.details?.firstChangedLine ?? 0,
200
+ diff: sc.diff ?? '',
201
+ firstChangedLine: sc.firstChangedLine ?? 0,
180
202
  };
181
203
  }
182
204