@react-grab/opencode 0.0.82 → 0.0.84
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/README.md +6 -6
- package/dist/cli.cjs +6596 -58
- package/dist/cli.js +6589 -57
- package/dist/client.cjs +57 -26
- package/dist/client.global.js +4 -3
- package/dist/client.js +57 -26
- package/dist/server.cjs +20 -14
- package/dist/server.js +20 -14
- package/package.json +5 -5
package/dist/client.cjs
CHANGED
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
var DEFAULT_PORT = 6567;
|
|
3
|
+
// ../utils/dist/client.js
|
|
5
4
|
var CONNECTION_CHECK_TTL_MS = 5e3;
|
|
6
|
-
|
|
7
|
-
// src/client.ts
|
|
8
|
-
var DEFAULT_SERVER_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
9
5
|
var STORAGE_KEY = "react-grab:agent-sessions";
|
|
10
|
-
var
|
|
6
|
+
var parseSSEEvent = (eventBlock) => {
|
|
11
7
|
let eventType = "";
|
|
12
8
|
let data = "";
|
|
13
|
-
for (const line of
|
|
9
|
+
for (const line of eventBlock.split("\n")) {
|
|
14
10
|
if (line.startsWith("event:")) eventType = line.slice(6).trim();
|
|
15
11
|
else if (line.startsWith("data:")) data = line.slice(5).trim();
|
|
16
12
|
}
|
|
17
13
|
return { eventType, data };
|
|
18
14
|
};
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
let
|
|
15
|
+
async function* streamSSE(stream, signal) {
|
|
16
|
+
const reader = stream.getReader();
|
|
17
|
+
const decoder = new TextDecoder();
|
|
18
|
+
let buffer = "";
|
|
23
19
|
let aborted = false;
|
|
24
20
|
const onAbort = () => {
|
|
25
21
|
aborted = true;
|
|
26
|
-
|
|
22
|
+
reader.cancel().catch(() => {
|
|
27
23
|
});
|
|
28
24
|
};
|
|
29
25
|
signal.addEventListener("abort", onAbort);
|
|
@@ -32,18 +28,16 @@ var streamSSE = async function* (stream, signal) {
|
|
|
32
28
|
throw new DOMException("Aborted", "AbortError");
|
|
33
29
|
}
|
|
34
30
|
while (true) {
|
|
35
|
-
const result = await
|
|
31
|
+
const result = await reader.read();
|
|
36
32
|
if (aborted || signal.aborted) {
|
|
37
33
|
throw new DOMException("Aborted", "AbortError");
|
|
38
34
|
}
|
|
39
35
|
const { done, value } = result;
|
|
40
|
-
if (value)
|
|
41
|
-
let
|
|
42
|
-
while ((
|
|
43
|
-
const { eventType, data } =
|
|
44
|
-
|
|
45
|
-
);
|
|
46
|
-
textBuffer = textBuffer.slice(boundaryIndex + 2);
|
|
36
|
+
if (value) buffer += decoder.decode(value, { stream: true });
|
|
37
|
+
let boundary;
|
|
38
|
+
while ((boundary = buffer.indexOf("\n\n")) !== -1) {
|
|
39
|
+
const { eventType, data } = parseSSEEvent(buffer.slice(0, boundary));
|
|
40
|
+
buffer = buffer.slice(boundary + 2);
|
|
47
41
|
if (eventType === "done") return;
|
|
48
42
|
if (eventType === "error") throw new Error(data || "Agent error");
|
|
49
43
|
if (data) yield data;
|
|
@@ -53,12 +47,19 @@ var streamSSE = async function* (stream, signal) {
|
|
|
53
47
|
} finally {
|
|
54
48
|
signal.removeEventListener("abort", onAbort);
|
|
55
49
|
try {
|
|
56
|
-
|
|
50
|
+
reader.releaseLock();
|
|
57
51
|
} catch {
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
|
-
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/constants.ts
|
|
57
|
+
var DEFAULT_PORT = 6567;
|
|
58
|
+
|
|
59
|
+
// src/client.ts
|
|
60
|
+
var DEFAULT_SERVER_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
61
61
|
var streamFromServer = async function* (serverUrl, context, signal) {
|
|
62
|
+
const startTime = Date.now();
|
|
62
63
|
const sessionId = context.sessionId;
|
|
63
64
|
const handleAbort = () => {
|
|
64
65
|
if (sessionId) {
|
|
@@ -82,12 +83,42 @@ var streamFromServer = async function* (serverUrl, context, signal) {
|
|
|
82
83
|
if (!response.body) {
|
|
83
84
|
throw new Error("No response body");
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
+
const iterator = streamSSE(response.body, signal)[Symbol.asyncIterator]();
|
|
87
|
+
let done = false;
|
|
88
|
+
let pendingNext = iterator.next();
|
|
89
|
+
while (!done) {
|
|
90
|
+
const result = await Promise.race([
|
|
91
|
+
pendingNext.then((iteratorResult) => ({
|
|
92
|
+
type: "status",
|
|
93
|
+
iteratorResult
|
|
94
|
+
})),
|
|
95
|
+
new Promise(
|
|
96
|
+
(resolve) => setTimeout(() => resolve({ type: "timeout" }), 100)
|
|
97
|
+
)
|
|
98
|
+
]);
|
|
99
|
+
if (result.type === "timeout") {
|
|
100
|
+
const elapsedSeconds = (Date.now() - startTime) / 1e3;
|
|
101
|
+
yield `Working\u2026 ${elapsedSeconds.toFixed(1)}s`;
|
|
102
|
+
} else {
|
|
103
|
+
const iteratorResult = result.iteratorResult;
|
|
104
|
+
done = iteratorResult.done ?? false;
|
|
105
|
+
if (!done && iteratorResult.value) {
|
|
106
|
+
const status = iteratorResult.value;
|
|
107
|
+
if (status === "Completed successfully") {
|
|
108
|
+
const totalSeconds = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
109
|
+
yield `Completed in ${totalSeconds}s`;
|
|
110
|
+
} else {
|
|
111
|
+
yield status;
|
|
112
|
+
}
|
|
113
|
+
pendingNext = iterator.next();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
86
117
|
} finally {
|
|
87
118
|
signal.removeEventListener("abort", handleAbort);
|
|
88
119
|
}
|
|
89
120
|
};
|
|
90
|
-
var
|
|
121
|
+
var createOpenCodeAgentProvider = (options = {}) => {
|
|
91
122
|
const { serverUrl = DEFAULT_SERVER_URL, getOptions } = options;
|
|
92
123
|
let connectionCache = null;
|
|
93
124
|
const mergeOptions = (contextOptions) => ({
|
|
@@ -147,7 +178,7 @@ var createOpencodeAgentProvider = (options = {}) => {
|
|
|
147
178
|
};
|
|
148
179
|
var attachAgent = async () => {
|
|
149
180
|
if (typeof window === "undefined") return;
|
|
150
|
-
const provider =
|
|
181
|
+
const provider = createOpenCodeAgentProvider();
|
|
151
182
|
const attach = (api2) => {
|
|
152
183
|
api2.setAgent({ provider, storage: sessionStorage });
|
|
153
184
|
};
|
|
@@ -172,4 +203,4 @@ var attachAgent = async () => {
|
|
|
172
203
|
attachAgent();
|
|
173
204
|
|
|
174
205
|
exports.attachAgent = attachAgent;
|
|
175
|
-
exports.
|
|
206
|
+
exports.createOpenCodeAgentProvider = createOpenCodeAgentProvider;
|
package/dist/client.global.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
var
|
|
2
|
-
`))
|
|
1
|
+
var ReactGrabOpenCode=(function(exports){'use strict';var f=5e3,m="react-grab:agent-sessions",y=c=>{let e="",n="";for(let t of c.split(`
|
|
2
|
+
`))t.startsWith("event:")?e=t.slice(6).trim():t.startsWith("data:")&&(n=t.slice(5).trim());return {eventType:e,data:n}};async function*g(c,e){let n=c.getReader(),t=new TextDecoder,r="",o=false,i=()=>{o=true,n.cancel().catch(()=>{});};e.addEventListener("abort",i);try{if(e.aborted)throw new DOMException("Aborted","AbortError");for(;;){let a=await n.read();if(o||e.aborted)throw new DOMException("Aborted","AbortError");let{done:p,value:u}=a;u&&(r+=t.decode(u,{stream:!0}));let d;for(;(d=r.indexOf(`
|
|
3
3
|
|
|
4
|
-
`))!==-1;){let{eventType:
|
|
4
|
+
`))!==-1;){let{eventType:s,data:l}=y(r.slice(0,d));if(r=r.slice(d+2),s==="done")return;if(s==="error")throw new Error(l||"Agent error");l&&(yield l);}if(p)break}}finally{e.removeEventListener("abort",i);try{n.releaseLock();}catch{}}}var C=`http://localhost:${6567}`,A=async function*(c,e,n){let t=Date.now(),r=e.sessionId,o=()=>{r&&fetch(`${c}/abort/${r}`,{method:"POST"}).catch(()=>{});};n.addEventListener("abort",o);try{let i=await fetch(`${c}/agent`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:n});if(!i.ok)throw new Error(`Server error: ${i.status}`);if(!i.body)throw new Error("No response body");let a=g(i.body,n)[Symbol.asyncIterator](),p=!1,u=a.next();for(;!p;){let d=await Promise.race([u.then(s=>({type:"status",iteratorResult:s})),new Promise(s=>setTimeout(()=>s({type:"timeout"}),100))]);if(d.type==="timeout")yield `Working\u2026 ${((Date.now()-t)/1e3).toFixed(1)}s`;else {let s=d.iteratorResult;if(p=s.done??!1,!p&&s.value){let l=s.value;l==="Completed successfully"?yield `Completed in ${((Date.now()-t)/1e3).toFixed(1)}s`:yield l,u=a.next();}}}}finally{n.removeEventListener("abort",o);}},E=(c={})=>{let{serverUrl:e=C,getOptions:n}=c,t=null,r=o=>({...n?.()??{},...o??{}});return {send:async function*(o,i){let a={...o,options:r(o.options)};yield*A(e,a,i);},resume:async function*(o,i,a){let p=a.getItem(m);if(!p)throw new Error("No sessions to resume");let d=JSON.parse(p)[o];if(!d)throw new Error(`Session ${o} not found`);let s=d.context,l={...s,options:r(s.options)};yield "Resuming...",yield*A(e,l,i);},supportsResume:true,supportsFollowUp:true,checkConnection:async()=>{let o=Date.now();if(t&&o-t.timestamp<f)return t.result;try{let a=(await fetch(`${e}/health`,{method:"GET"})).ok;return t={result:a,timestamp:o},a}catch{return t={result:false,timestamp:o},false}},undo:async()=>{try{await fetch(`${e}/undo`,{method:"POST"});}catch{}}}},O=async()=>{if(typeof window>"u")return;let c=E(),e=r=>{r.setAgent({provider:c,storage:sessionStorage});},n=window.__REACT_GRAB__;if(n){e(n);return}window.addEventListener("react-grab:init",r=>{e(r.detail);},{once:true});let t=window.__REACT_GRAB__;t&&e(t);};O();
|
|
5
|
+
exports.attachAgent=O;exports.createOpenCodeAgentProvider=E;return exports;})({});
|
package/dist/client.js
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
//
|
|
2
|
-
var DEFAULT_PORT = 6567;
|
|
1
|
+
// ../utils/dist/client.js
|
|
3
2
|
var CONNECTION_CHECK_TTL_MS = 5e3;
|
|
4
|
-
|
|
5
|
-
// src/client.ts
|
|
6
|
-
var DEFAULT_SERVER_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
7
3
|
var STORAGE_KEY = "react-grab:agent-sessions";
|
|
8
|
-
var
|
|
4
|
+
var parseSSEEvent = (eventBlock) => {
|
|
9
5
|
let eventType = "";
|
|
10
6
|
let data = "";
|
|
11
|
-
for (const line of
|
|
7
|
+
for (const line of eventBlock.split("\n")) {
|
|
12
8
|
if (line.startsWith("event:")) eventType = line.slice(6).trim();
|
|
13
9
|
else if (line.startsWith("data:")) data = line.slice(5).trim();
|
|
14
10
|
}
|
|
15
11
|
return { eventType, data };
|
|
16
12
|
};
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
let
|
|
13
|
+
async function* streamSSE(stream, signal) {
|
|
14
|
+
const reader = stream.getReader();
|
|
15
|
+
const decoder = new TextDecoder();
|
|
16
|
+
let buffer = "";
|
|
21
17
|
let aborted = false;
|
|
22
18
|
const onAbort = () => {
|
|
23
19
|
aborted = true;
|
|
24
|
-
|
|
20
|
+
reader.cancel().catch(() => {
|
|
25
21
|
});
|
|
26
22
|
};
|
|
27
23
|
signal.addEventListener("abort", onAbort);
|
|
@@ -30,18 +26,16 @@ var streamSSE = async function* (stream, signal) {
|
|
|
30
26
|
throw new DOMException("Aborted", "AbortError");
|
|
31
27
|
}
|
|
32
28
|
while (true) {
|
|
33
|
-
const result = await
|
|
29
|
+
const result = await reader.read();
|
|
34
30
|
if (aborted || signal.aborted) {
|
|
35
31
|
throw new DOMException("Aborted", "AbortError");
|
|
36
32
|
}
|
|
37
33
|
const { done, value } = result;
|
|
38
|
-
if (value)
|
|
39
|
-
let
|
|
40
|
-
while ((
|
|
41
|
-
const { eventType, data } =
|
|
42
|
-
|
|
43
|
-
);
|
|
44
|
-
textBuffer = textBuffer.slice(boundaryIndex + 2);
|
|
34
|
+
if (value) buffer += decoder.decode(value, { stream: true });
|
|
35
|
+
let boundary;
|
|
36
|
+
while ((boundary = buffer.indexOf("\n\n")) !== -1) {
|
|
37
|
+
const { eventType, data } = parseSSEEvent(buffer.slice(0, boundary));
|
|
38
|
+
buffer = buffer.slice(boundary + 2);
|
|
45
39
|
if (eventType === "done") return;
|
|
46
40
|
if (eventType === "error") throw new Error(data || "Agent error");
|
|
47
41
|
if (data) yield data;
|
|
@@ -51,12 +45,19 @@ var streamSSE = async function* (stream, signal) {
|
|
|
51
45
|
} finally {
|
|
52
46
|
signal.removeEventListener("abort", onAbort);
|
|
53
47
|
try {
|
|
54
|
-
|
|
48
|
+
reader.releaseLock();
|
|
55
49
|
} catch {
|
|
56
50
|
}
|
|
57
51
|
}
|
|
58
|
-
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/constants.ts
|
|
55
|
+
var DEFAULT_PORT = 6567;
|
|
56
|
+
|
|
57
|
+
// src/client.ts
|
|
58
|
+
var DEFAULT_SERVER_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
59
59
|
var streamFromServer = async function* (serverUrl, context, signal) {
|
|
60
|
+
const startTime = Date.now();
|
|
60
61
|
const sessionId = context.sessionId;
|
|
61
62
|
const handleAbort = () => {
|
|
62
63
|
if (sessionId) {
|
|
@@ -80,12 +81,42 @@ var streamFromServer = async function* (serverUrl, context, signal) {
|
|
|
80
81
|
if (!response.body) {
|
|
81
82
|
throw new Error("No response body");
|
|
82
83
|
}
|
|
83
|
-
|
|
84
|
+
const iterator = streamSSE(response.body, signal)[Symbol.asyncIterator]();
|
|
85
|
+
let done = false;
|
|
86
|
+
let pendingNext = iterator.next();
|
|
87
|
+
while (!done) {
|
|
88
|
+
const result = await Promise.race([
|
|
89
|
+
pendingNext.then((iteratorResult) => ({
|
|
90
|
+
type: "status",
|
|
91
|
+
iteratorResult
|
|
92
|
+
})),
|
|
93
|
+
new Promise(
|
|
94
|
+
(resolve) => setTimeout(() => resolve({ type: "timeout" }), 100)
|
|
95
|
+
)
|
|
96
|
+
]);
|
|
97
|
+
if (result.type === "timeout") {
|
|
98
|
+
const elapsedSeconds = (Date.now() - startTime) / 1e3;
|
|
99
|
+
yield `Working\u2026 ${elapsedSeconds.toFixed(1)}s`;
|
|
100
|
+
} else {
|
|
101
|
+
const iteratorResult = result.iteratorResult;
|
|
102
|
+
done = iteratorResult.done ?? false;
|
|
103
|
+
if (!done && iteratorResult.value) {
|
|
104
|
+
const status = iteratorResult.value;
|
|
105
|
+
if (status === "Completed successfully") {
|
|
106
|
+
const totalSeconds = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
107
|
+
yield `Completed in ${totalSeconds}s`;
|
|
108
|
+
} else {
|
|
109
|
+
yield status;
|
|
110
|
+
}
|
|
111
|
+
pendingNext = iterator.next();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
84
115
|
} finally {
|
|
85
116
|
signal.removeEventListener("abort", handleAbort);
|
|
86
117
|
}
|
|
87
118
|
};
|
|
88
|
-
var
|
|
119
|
+
var createOpenCodeAgentProvider = (options = {}) => {
|
|
89
120
|
const { serverUrl = DEFAULT_SERVER_URL, getOptions } = options;
|
|
90
121
|
let connectionCache = null;
|
|
91
122
|
const mergeOptions = (contextOptions) => ({
|
|
@@ -145,7 +176,7 @@ var createOpencodeAgentProvider = (options = {}) => {
|
|
|
145
176
|
};
|
|
146
177
|
var attachAgent = async () => {
|
|
147
178
|
if (typeof window === "undefined") return;
|
|
148
|
-
const provider =
|
|
179
|
+
const provider = createOpenCodeAgentProvider();
|
|
149
180
|
const attach = (api2) => {
|
|
150
181
|
api2.setAgent({ provider, storage: sessionStorage });
|
|
151
182
|
};
|
|
@@ -169,4 +200,4 @@ var attachAgent = async () => {
|
|
|
169
200
|
};
|
|
170
201
|
attachAgent();
|
|
171
202
|
|
|
172
|
-
export { attachAgent,
|
|
203
|
+
export { attachAgent, createOpenCodeAgentProvider };
|
package/dist/server.cjs
CHANGED
|
@@ -7339,17 +7339,21 @@ var import_picocolors = __toESM(require_picocolors());
|
|
|
7339
7339
|
|
|
7340
7340
|
// src/constants.ts
|
|
7341
7341
|
var DEFAULT_PORT = 6567;
|
|
7342
|
-
|
|
7343
|
-
|
|
7342
|
+
|
|
7343
|
+
// ../utils/dist/server.js
|
|
7344
7344
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7345
|
+
var VERSION = "0.0.84";
|
|
7346
|
+
var OPENCODE_SDK_PORT = 4096;
|
|
7345
7347
|
var opencodeInstance = null;
|
|
7346
7348
|
var sessionMap = /* @__PURE__ */ new Map();
|
|
7347
7349
|
var abortedSessions = /* @__PURE__ */ new Set();
|
|
7348
|
-
var
|
|
7349
|
-
var
|
|
7350
|
+
var lastOpenCodeSessionId;
|
|
7351
|
+
var getOpenCodeClient = async () => {
|
|
7350
7352
|
if (!opencodeInstance) {
|
|
7351
|
-
await fkill(`:${OPENCODE_SDK_PORT}`, { force: true, silent: true }).catch(
|
|
7352
|
-
|
|
7353
|
+
await fkill(`:${OPENCODE_SDK_PORT}`, { force: true, silent: true }).catch(
|
|
7354
|
+
() => {
|
|
7355
|
+
}
|
|
7356
|
+
);
|
|
7353
7357
|
await sleep(100);
|
|
7354
7358
|
const instance = await createOpencode({
|
|
7355
7359
|
hostname: "127.0.0.1",
|
|
@@ -7359,8 +7363,8 @@ var getOpencodeClient = async () => {
|
|
|
7359
7363
|
}
|
|
7360
7364
|
return opencodeInstance.client;
|
|
7361
7365
|
};
|
|
7362
|
-
var
|
|
7363
|
-
const client2 = await
|
|
7366
|
+
var executeOpenCodePrompt = async (prompt, options, onStatus, reactGrabSessionId) => {
|
|
7367
|
+
const client2 = await getOpenCodeClient();
|
|
7364
7368
|
onStatus?.("Thinking...");
|
|
7365
7369
|
let opencodeSessionId;
|
|
7366
7370
|
if (reactGrabSessionId && sessionMap.has(reactGrabSessionId)) {
|
|
@@ -7377,7 +7381,7 @@ var executeOpencodePrompt = async (prompt, options, onStatus, reactGrabSessionId
|
|
|
7377
7381
|
sessionMap.set(reactGrabSessionId, opencodeSessionId);
|
|
7378
7382
|
}
|
|
7379
7383
|
}
|
|
7380
|
-
|
|
7384
|
+
lastOpenCodeSessionId = opencodeSessionId;
|
|
7381
7385
|
const modelConfig = options?.model ? {
|
|
7382
7386
|
providerID: options.model.split("/")[0],
|
|
7383
7387
|
modelID: options.model.split("/")[1] || options.model
|
|
@@ -7414,7 +7418,7 @@ ${content}
|
|
|
7414
7418
|
return streamSSE(context, async (stream2) => {
|
|
7415
7419
|
const isAborted = () => sessionId && abortedSessions.has(sessionId);
|
|
7416
7420
|
try {
|
|
7417
|
-
await
|
|
7421
|
+
await executeOpenCodePrompt(
|
|
7418
7422
|
formattedPrompt,
|
|
7419
7423
|
options,
|
|
7420
7424
|
(text) => {
|
|
@@ -7461,13 +7465,13 @@ ${stderr.trim()}` : errorMessage;
|
|
|
7461
7465
|
return context.json({ status: "ok" });
|
|
7462
7466
|
});
|
|
7463
7467
|
honoApplication.post("/undo", async (context) => {
|
|
7464
|
-
if (!
|
|
7468
|
+
if (!lastOpenCodeSessionId) {
|
|
7465
7469
|
return context.json({ status: "error", message: "No session to undo" });
|
|
7466
7470
|
}
|
|
7467
7471
|
try {
|
|
7468
|
-
const client2 = await
|
|
7472
|
+
const client2 = await getOpenCodeClient();
|
|
7469
7473
|
await client2.session.prompt({
|
|
7470
|
-
path: { id:
|
|
7474
|
+
path: { id: lastOpenCodeSessionId },
|
|
7471
7475
|
body: {
|
|
7472
7476
|
parts: [{ type: "text", text: "/undo" }]
|
|
7473
7477
|
}
|
|
@@ -7489,7 +7493,9 @@ var startServer = async (port = DEFAULT_PORT) => {
|
|
|
7489
7493
|
await sleep(100);
|
|
7490
7494
|
const honoApplication = createServer();
|
|
7491
7495
|
serve({ fetch: honoApplication.fetch, port });
|
|
7492
|
-
console.log(
|
|
7496
|
+
console.log(
|
|
7497
|
+
`${import_picocolors.default.magenta("\u269B")} ${import_picocolors.default.bold("React Grab")} ${import_picocolors.default.gray(VERSION)} ${import_picocolors.default.dim("(OpenCode)")}`
|
|
7498
|
+
);
|
|
7493
7499
|
console.log(`- Local: ${import_picocolors.default.cyan(`http://localhost:${port}`)}`);
|
|
7494
7500
|
};
|
|
7495
7501
|
if ((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('server.cjs', document.baseURI).href)) === url.pathToFileURL(process.argv[1]).href) {
|
package/dist/server.js
CHANGED
|
@@ -7328,17 +7328,21 @@ var import_picocolors = __toESM(require_picocolors());
|
|
|
7328
7328
|
|
|
7329
7329
|
// src/constants.ts
|
|
7330
7330
|
var DEFAULT_PORT = 6567;
|
|
7331
|
-
|
|
7332
|
-
|
|
7331
|
+
|
|
7332
|
+
// ../utils/dist/server.js
|
|
7333
7333
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7334
|
+
var VERSION = "0.0.84";
|
|
7335
|
+
var OPENCODE_SDK_PORT = 4096;
|
|
7334
7336
|
var opencodeInstance = null;
|
|
7335
7337
|
var sessionMap = /* @__PURE__ */ new Map();
|
|
7336
7338
|
var abortedSessions = /* @__PURE__ */ new Set();
|
|
7337
|
-
var
|
|
7338
|
-
var
|
|
7339
|
+
var lastOpenCodeSessionId;
|
|
7340
|
+
var getOpenCodeClient = async () => {
|
|
7339
7341
|
if (!opencodeInstance) {
|
|
7340
|
-
await fkill(`:${OPENCODE_SDK_PORT}`, { force: true, silent: true }).catch(
|
|
7341
|
-
|
|
7342
|
+
await fkill(`:${OPENCODE_SDK_PORT}`, { force: true, silent: true }).catch(
|
|
7343
|
+
() => {
|
|
7344
|
+
}
|
|
7345
|
+
);
|
|
7342
7346
|
await sleep(100);
|
|
7343
7347
|
const instance = await createOpencode({
|
|
7344
7348
|
hostname: "127.0.0.1",
|
|
@@ -7348,8 +7352,8 @@ var getOpencodeClient = async () => {
|
|
|
7348
7352
|
}
|
|
7349
7353
|
return opencodeInstance.client;
|
|
7350
7354
|
};
|
|
7351
|
-
var
|
|
7352
|
-
const client2 = await
|
|
7355
|
+
var executeOpenCodePrompt = async (prompt, options, onStatus, reactGrabSessionId) => {
|
|
7356
|
+
const client2 = await getOpenCodeClient();
|
|
7353
7357
|
onStatus?.("Thinking...");
|
|
7354
7358
|
let opencodeSessionId;
|
|
7355
7359
|
if (reactGrabSessionId && sessionMap.has(reactGrabSessionId)) {
|
|
@@ -7366,7 +7370,7 @@ var executeOpencodePrompt = async (prompt, options, onStatus, reactGrabSessionId
|
|
|
7366
7370
|
sessionMap.set(reactGrabSessionId, opencodeSessionId);
|
|
7367
7371
|
}
|
|
7368
7372
|
}
|
|
7369
|
-
|
|
7373
|
+
lastOpenCodeSessionId = opencodeSessionId;
|
|
7370
7374
|
const modelConfig = options?.model ? {
|
|
7371
7375
|
providerID: options.model.split("/")[0],
|
|
7372
7376
|
modelID: options.model.split("/")[1] || options.model
|
|
@@ -7403,7 +7407,7 @@ ${content}
|
|
|
7403
7407
|
return streamSSE(context, async (stream2) => {
|
|
7404
7408
|
const isAborted = () => sessionId && abortedSessions.has(sessionId);
|
|
7405
7409
|
try {
|
|
7406
|
-
await
|
|
7410
|
+
await executeOpenCodePrompt(
|
|
7407
7411
|
formattedPrompt,
|
|
7408
7412
|
options,
|
|
7409
7413
|
(text) => {
|
|
@@ -7450,13 +7454,13 @@ ${stderr.trim()}` : errorMessage;
|
|
|
7450
7454
|
return context.json({ status: "ok" });
|
|
7451
7455
|
});
|
|
7452
7456
|
honoApplication.post("/undo", async (context) => {
|
|
7453
|
-
if (!
|
|
7457
|
+
if (!lastOpenCodeSessionId) {
|
|
7454
7458
|
return context.json({ status: "error", message: "No session to undo" });
|
|
7455
7459
|
}
|
|
7456
7460
|
try {
|
|
7457
|
-
const client2 = await
|
|
7461
|
+
const client2 = await getOpenCodeClient();
|
|
7458
7462
|
await client2.session.prompt({
|
|
7459
|
-
path: { id:
|
|
7463
|
+
path: { id: lastOpenCodeSessionId },
|
|
7460
7464
|
body: {
|
|
7461
7465
|
parts: [{ type: "text", text: "/undo" }]
|
|
7462
7466
|
}
|
|
@@ -7478,7 +7482,9 @@ var startServer = async (port = DEFAULT_PORT) => {
|
|
|
7478
7482
|
await sleep(100);
|
|
7479
7483
|
const honoApplication = createServer();
|
|
7480
7484
|
serve({ fetch: honoApplication.fetch, port });
|
|
7481
|
-
console.log(
|
|
7485
|
+
console.log(
|
|
7486
|
+
`${import_picocolors.default.magenta("\u269B")} ${import_picocolors.default.bold("React Grab")} ${import_picocolors.default.gray(VERSION)} ${import_picocolors.default.dim("(OpenCode)")}`
|
|
7487
|
+
);
|
|
7482
7488
|
console.log(`- Local: ${import_picocolors.default.cyan(`http://localhost:${port}`)}`);
|
|
7483
7489
|
};
|
|
7484
7490
|
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-grab/opencode",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.84",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"react-grab-opencode": "./dist/cli.cjs"
|
|
@@ -24,17 +24,17 @@
|
|
|
24
24
|
"dist"
|
|
25
25
|
],
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
27
|
+
"tsup": "^8.4.0",
|
|
28
|
+
"@react-grab/utils": "0.0.84"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@hono/node-server": "^1.19.6",
|
|
32
32
|
"@opencode-ai/sdk": "^1.0.0",
|
|
33
|
-
"
|
|
33
|
+
"execa": "^9.6.0",
|
|
34
34
|
"fkill": "^9.0.0",
|
|
35
35
|
"hono": "^4.0.0",
|
|
36
36
|
"picocolors": "^1.1.1",
|
|
37
|
-
"react-grab": "0.0.
|
|
37
|
+
"react-grab": "0.0.84"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"dev": "tsup --watch",
|