@react-grab/opencode 0.0.88 → 0.0.90
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/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/dist/client.cjs +103 -59
- package/dist/client.global.js +4 -4
- package/dist/client.js +103 -59
- package/dist/server.cjs +105 -47
- package/dist/server.js +105 -48
- package/package.json +3 -3
package/dist/cli.cjs
CHANGED
|
@@ -7138,7 +7138,7 @@ var import_picocolors = __toESM(require_picocolors());
|
|
|
7138
7138
|
var DEFAULT_PORT = 6567;
|
|
7139
7139
|
|
|
7140
7140
|
// src/cli.ts
|
|
7141
|
-
var VERSION = "0.0.
|
|
7141
|
+
var VERSION = "0.0.90";
|
|
7142
7142
|
var serverPath = path2.join(__dirname, "server.cjs");
|
|
7143
7143
|
execa(process.execPath, [serverPath], {
|
|
7144
7144
|
detached: true,
|
package/dist/cli.js
CHANGED
|
@@ -7130,7 +7130,7 @@ var import_picocolors = __toESM(require_picocolors());
|
|
|
7130
7130
|
var DEFAULT_PORT = 6567;
|
|
7131
7131
|
|
|
7132
7132
|
// src/cli.ts
|
|
7133
|
-
var VERSION = "0.0.
|
|
7133
|
+
var VERSION = "0.0.90";
|
|
7134
7134
|
var serverPath = join(__dirname, "server.cjs");
|
|
7135
7135
|
execa(process.execPath, [serverPath], {
|
|
7136
7136
|
detached: true,
|
package/dist/client.cjs
CHANGED
|
@@ -12,7 +12,7 @@ var parseSSEEvent = (eventBlock) => {
|
|
|
12
12
|
}
|
|
13
13
|
return { eventType, data };
|
|
14
14
|
};
|
|
15
|
-
async function*
|
|
15
|
+
var streamSSE = async function* (stream, signal) {
|
|
16
16
|
const reader = stream.getReader();
|
|
17
17
|
const decoder = new TextDecoder();
|
|
18
18
|
let buffer = "";
|
|
@@ -51,28 +51,54 @@ async function* streamSSE(stream, signal) {
|
|
|
51
51
|
} catch {
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
};
|
|
55
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
56
|
+
var getStoredAgentContext = (storage, sessionId, storageKey = STORAGE_KEY) => {
|
|
57
|
+
const rawSessions = storage.getItem(storageKey);
|
|
58
|
+
if (!rawSessions) throw new Error("No sessions to resume");
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(rawSessions);
|
|
62
|
+
} catch {
|
|
63
|
+
throw new Error("Failed to parse stored sessions");
|
|
64
|
+
}
|
|
65
|
+
if (!isRecord(parsed)) throw new Error("Invalid stored sessions");
|
|
66
|
+
const storedSession = parsed[sessionId];
|
|
67
|
+
if (!isRecord(storedSession)) {
|
|
68
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
69
|
+
}
|
|
70
|
+
const context = storedSession.context;
|
|
71
|
+
if (!isRecord(context)) throw new Error(`Session ${sessionId} is invalid`);
|
|
72
|
+
const content = context.content;
|
|
73
|
+
const prompt = context.prompt;
|
|
74
|
+
if (typeof content !== "string" || typeof prompt !== "string") {
|
|
75
|
+
throw new Error(`Session ${sessionId} is invalid`);
|
|
76
|
+
}
|
|
77
|
+
const options = context.options;
|
|
78
|
+
const storedSessionId = context.sessionId;
|
|
79
|
+
return {
|
|
80
|
+
content,
|
|
81
|
+
prompt,
|
|
82
|
+
options,
|
|
83
|
+
sessionId: typeof storedSessionId === "string" ? storedSessionId : void 0
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
var streamAgentStatusFromServer = async function* (options, context, signal) {
|
|
63
87
|
const startTime = Date.now();
|
|
64
88
|
const sessionId = context.sessionId;
|
|
89
|
+
const pollIntervalMs = options.pollIntervalMs ?? 100;
|
|
90
|
+
const agentUrl = `${options.serverUrl}${options.agentPath ?? "/agent"}`;
|
|
65
91
|
const handleAbort = () => {
|
|
66
|
-
if (sessionId)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
if (!sessionId) return;
|
|
93
|
+
const abortPath = options.abortPath?.(sessionId) ?? `/abort/${sessionId}`;
|
|
94
|
+
fetch(`${options.serverUrl}${abortPath}`, { method: "POST" }).catch(
|
|
95
|
+
() => {
|
|
96
|
+
}
|
|
97
|
+
);
|
|
72
98
|
};
|
|
73
99
|
signal.addEventListener("abort", handleAbort);
|
|
74
100
|
try {
|
|
75
|
-
const response = await fetch(
|
|
101
|
+
const response = await fetch(agentUrl, {
|
|
76
102
|
method: "POST",
|
|
77
103
|
headers: { "Content-Type": "application/json" },
|
|
78
104
|
body: JSON.stringify(context),
|
|
@@ -85,29 +111,29 @@ var streamFromServer = async function* (serverUrl, context, signal) {
|
|
|
85
111
|
throw new Error("No response body");
|
|
86
112
|
}
|
|
87
113
|
const iterator = streamSSE(response.body, signal)[Symbol.asyncIterator]();
|
|
88
|
-
let
|
|
114
|
+
let isDone = false;
|
|
89
115
|
let pendingNext = iterator.next();
|
|
90
116
|
let lastStatus = null;
|
|
91
|
-
while (!
|
|
117
|
+
while (!isDone) {
|
|
92
118
|
const result = await Promise.race([
|
|
93
119
|
pendingNext.then((iteratorResult) => ({
|
|
94
120
|
type: "status",
|
|
95
121
|
iteratorResult
|
|
96
122
|
})),
|
|
97
123
|
new Promise(
|
|
98
|
-
(resolve) => setTimeout(() => resolve({ type: "timeout" }),
|
|
124
|
+
(resolve) => setTimeout(() => resolve({ type: "timeout" }), pollIntervalMs)
|
|
99
125
|
)
|
|
100
126
|
]);
|
|
101
127
|
const elapsedSeconds = (Date.now() - startTime) / 1e3;
|
|
102
128
|
if (result.type === "status") {
|
|
103
129
|
const iteratorResult = result.iteratorResult;
|
|
104
|
-
|
|
105
|
-
if (!
|
|
130
|
+
isDone = iteratorResult.done ?? false;
|
|
131
|
+
if (!isDone && iteratorResult.value) {
|
|
106
132
|
lastStatus = iteratorResult.value;
|
|
107
133
|
pendingNext = iterator.next();
|
|
108
134
|
}
|
|
109
135
|
}
|
|
110
|
-
if (lastStatus ===
|
|
136
|
+
if (lastStatus === options.completedStatus) {
|
|
111
137
|
yield `Completed in ${elapsedSeconds.toFixed(1)}s`;
|
|
112
138
|
} else if (lastStatus) {
|
|
113
139
|
yield `${lastStatus} ${elapsedSeconds.toFixed(1)}s`;
|
|
@@ -119,56 +145,73 @@ var streamFromServer = async function* (serverUrl, context, signal) {
|
|
|
119
145
|
signal.removeEventListener("abort", handleAbort);
|
|
120
146
|
}
|
|
121
147
|
};
|
|
148
|
+
var createCachedConnectionChecker = (checkConnection, ttlMs = CONNECTION_CHECK_TTL_MS) => {
|
|
149
|
+
let cache = null;
|
|
150
|
+
return async () => {
|
|
151
|
+
const now = Date.now();
|
|
152
|
+
if (cache && now - cache.timestamp < ttlMs) return cache.result;
|
|
153
|
+
try {
|
|
154
|
+
const result = await checkConnection();
|
|
155
|
+
cache = { result, timestamp: now };
|
|
156
|
+
return result;
|
|
157
|
+
} catch {
|
|
158
|
+
cache = { result: false, timestamp: now };
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/constants.ts
|
|
165
|
+
var DEFAULT_PORT = 6567;
|
|
166
|
+
var COMPLETED_STATUS = "Completed successfully";
|
|
167
|
+
|
|
168
|
+
// src/client.ts
|
|
169
|
+
var DEFAULT_SERVER_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
170
|
+
var isReactGrabApi = (value) => typeof value === "object" && value !== null && "setAgent" in value;
|
|
122
171
|
var createOpenCodeAgentProvider = (options = {}) => {
|
|
123
172
|
const { serverUrl = DEFAULT_SERVER_URL, getOptions } = options;
|
|
124
|
-
let connectionCache = null;
|
|
125
173
|
const mergeOptions = (contextOptions) => ({
|
|
126
174
|
...getOptions?.() ?? {},
|
|
127
175
|
...contextOptions ?? {}
|
|
128
176
|
});
|
|
177
|
+
const checkConnection = createCachedConnectionChecker(async () => {
|
|
178
|
+
const response = await fetch(`${serverUrl}/health`, { method: "GET" });
|
|
179
|
+
return response.ok;
|
|
180
|
+
}, CONNECTION_CHECK_TTL_MS);
|
|
129
181
|
return {
|
|
130
182
|
send: async function* (context, signal) {
|
|
131
183
|
const combinedContext = {
|
|
132
184
|
...context,
|
|
133
185
|
options: mergeOptions(context.options)
|
|
134
186
|
};
|
|
135
|
-
yield*
|
|
187
|
+
yield* streamAgentStatusFromServer(
|
|
188
|
+
{ serverUrl, completedStatus: COMPLETED_STATUS },
|
|
189
|
+
combinedContext,
|
|
190
|
+
signal
|
|
191
|
+
);
|
|
136
192
|
},
|
|
137
193
|
resume: async function* (sessionId, signal, storage) {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
throw new Error(`Session ${sessionId} not found`);
|
|
146
|
-
}
|
|
147
|
-
const context = session.context;
|
|
194
|
+
const storedContext = getStoredAgentContext(storage, sessionId);
|
|
195
|
+
const context = {
|
|
196
|
+
content: storedContext.content,
|
|
197
|
+
prompt: storedContext.prompt,
|
|
198
|
+
options: storedContext.options,
|
|
199
|
+
sessionId: storedContext.sessionId ?? sessionId
|
|
200
|
+
};
|
|
148
201
|
const combinedContext = {
|
|
149
202
|
...context,
|
|
150
203
|
options: mergeOptions(context.options)
|
|
151
204
|
};
|
|
152
205
|
yield "Resuming...";
|
|
153
|
-
yield*
|
|
206
|
+
yield* streamAgentStatusFromServer(
|
|
207
|
+
{ serverUrl, completedStatus: COMPLETED_STATUS },
|
|
208
|
+
combinedContext,
|
|
209
|
+
signal
|
|
210
|
+
);
|
|
154
211
|
},
|
|
155
212
|
supportsResume: true,
|
|
156
213
|
supportsFollowUp: true,
|
|
157
|
-
checkConnection
|
|
158
|
-
const now = Date.now();
|
|
159
|
-
if (connectionCache && now - connectionCache.timestamp < CONNECTION_CHECK_TTL_MS) {
|
|
160
|
-
return connectionCache.result;
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
const response = await fetch(`${serverUrl}/health`, { method: "GET" });
|
|
164
|
-
const result = response.ok;
|
|
165
|
-
connectionCache = { result, timestamp: now };
|
|
166
|
-
return result;
|
|
167
|
-
} catch {
|
|
168
|
-
connectionCache = { result: false, timestamp: now };
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
},
|
|
214
|
+
checkConnection,
|
|
172
215
|
undo: async () => {
|
|
173
216
|
try {
|
|
174
217
|
await fetch(`${serverUrl}/undo`, { method: "POST" });
|
|
@@ -180,24 +223,25 @@ var createOpenCodeAgentProvider = (options = {}) => {
|
|
|
180
223
|
var attachAgent = async () => {
|
|
181
224
|
if (typeof window === "undefined") return;
|
|
182
225
|
const provider = createOpenCodeAgentProvider();
|
|
183
|
-
const attach = (
|
|
184
|
-
|
|
226
|
+
const attach = (api) => {
|
|
227
|
+
api.setAgent({ provider, storage: sessionStorage });
|
|
185
228
|
};
|
|
186
|
-
const
|
|
187
|
-
if (
|
|
188
|
-
attach(
|
|
229
|
+
const existingApi = window.__REACT_GRAB__;
|
|
230
|
+
if (isReactGrabApi(existingApi)) {
|
|
231
|
+
attach(existingApi);
|
|
189
232
|
return;
|
|
190
233
|
}
|
|
191
234
|
window.addEventListener(
|
|
192
235
|
"react-grab:init",
|
|
193
236
|
(event) => {
|
|
194
|
-
|
|
195
|
-
|
|
237
|
+
if (!(event instanceof CustomEvent)) return;
|
|
238
|
+
if (!isReactGrabApi(event.detail)) return;
|
|
239
|
+
attach(event.detail);
|
|
196
240
|
},
|
|
197
241
|
{ once: true }
|
|
198
242
|
);
|
|
199
243
|
const apiAfterListener = window.__REACT_GRAB__;
|
|
200
|
-
if (apiAfterListener) {
|
|
244
|
+
if (isReactGrabApi(apiAfterListener)) {
|
|
201
245
|
attach(apiAfterListener);
|
|
202
246
|
}
|
|
203
247
|
};
|
package/dist/client.global.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var ReactGrabOpenCode=(function(exports){'use strict';var
|
|
2
|
-
`))
|
|
1
|
+
var ReactGrabOpenCode=(function(exports){'use strict';var A=5e3,O="react-grab:agent-sessions",b=t=>{let e="",o="";for(let r of t.split(`
|
|
2
|
+
`))r.startsWith("event:")?e=r.slice(6).trim():r.startsWith("data:")&&(o=r.slice(5).trim());return {eventType:e,data:o}},v=async function*(t,e){let o=t.getReader(),r=new TextDecoder,n="",s=false,a=()=>{s=true,o.cancel().catch(()=>{});};e.addEventListener("abort",a);try{if(e.aborted)throw new DOMException("Aborted","AbortError");for(;;){let d=await o.read();if(s||e.aborted)throw new DOMException("Aborted","AbortError");let{done:i,value:p}=d;p&&(n+=r.decode(p,{stream:!0}));let c;for(;(c=n.indexOf(`
|
|
3
3
|
|
|
4
|
-
`))!==-1;){let{eventType:
|
|
5
|
-
exports.attachAgent=
|
|
4
|
+
`))!==-1;){let{eventType:f,data:l}=b(n.slice(0,c));if(n=n.slice(c+2),f==="done")return;if(f==="error")throw new Error(l||"Agent error");l&&(yield l);}if(i)break}}finally{e.removeEventListener("abort",a);try{o.releaseLock();}catch{}}},m=t=>typeof t=="object"&&t!==null,S=(t,e,o=O)=>{let r=t.getItem(o);if(!r)throw new Error("No sessions to resume");let n;try{n=JSON.parse(r);}catch{throw new Error("Failed to parse stored sessions")}if(!m(n))throw new Error("Invalid stored sessions");let s=n[e];if(!m(s))throw new Error(`Session ${e} not found`);let a=s.context;if(!m(a))throw new Error(`Session ${e} is invalid`);let d=a.content,i=a.prompt;if(typeof d!="string"||typeof i!="string")throw new Error(`Session ${e} is invalid`);let p=a.options,c=a.sessionId;return {content:d,prompt:i,options:p,sessionId:typeof c=="string"?c:void 0}},y=async function*(t,e,o){let r=Date.now(),n=e.sessionId,s=t.pollIntervalMs??100,a=`${t.serverUrl}${t.agentPath??"/agent"}`,d=()=>{if(!n)return;let i=t.abortPath?.(n)??`/abort/${n}`;fetch(`${t.serverUrl}${i}`,{method:"POST"}).catch(()=>{});};o.addEventListener("abort",d);try{let i=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:o});if(!i.ok)throw new Error(`Server error: ${i.status}`);if(!i.body)throw new Error("No response body");let p=v(i.body,o)[Symbol.asyncIterator](),c=!1,f=p.next(),l=null;for(;!c;){let C=await Promise.race([f.then(u=>({type:"status",iteratorResult:u})),new Promise(u=>setTimeout(()=>u({type:"timeout"}),s))]),g=(Date.now()-r)/1e3;if(C.type==="status"){let u=C.iteratorResult;c=u.done??!1,!c&&u.value&&(l=u.value,f=p.next());}l===t.completedStatus?yield `Completed in ${g.toFixed(1)}s`:l?yield `${l} ${g.toFixed(1)}s`:yield `Working\u2026 ${g.toFixed(1)}s`;}}finally{o.removeEventListener("abort",d);}},E=(t,e=A)=>{let o=null;return async()=>{let r=Date.now();if(o&&r-o.timestamp<e)return o.result;try{let n=await t();return o={result:n,timestamp:r},n}catch{return o={result:false,timestamp:r},false}}};var w="Completed successfully";var x=`http://localhost:${6567}`,h=t=>typeof t=="object"&&t!==null&&"setAgent"in t,_=(t={})=>{let{serverUrl:e=x,getOptions:o}=t,r=s=>({...o?.()??{},...s??{}}),n=E(async()=>(await fetch(`${e}/health`,{method:"GET"})).ok,A);return {send:async function*(s,a){let d={...s,options:r(s.options)};yield*y({serverUrl:e,completedStatus:w},d,a);},resume:async function*(s,a,d){let i=S(d,s),p={content:i.content,prompt:i.prompt,options:i.options,sessionId:i.sessionId??s},c={...p,options:r(p.options)};yield "Resuming...",yield*y({serverUrl:e,completedStatus:w},c,a);},supportsResume:true,supportsFollowUp:true,checkConnection:n,undo:async()=>{try{await fetch(`${e}/undo`,{method:"POST"});}catch{}}}},R=async()=>{if(typeof window>"u")return;let t=_(),e=n=>{n.setAgent({provider:t,storage:sessionStorage});},o=window.__REACT_GRAB__;if(h(o)){e(o);return}window.addEventListener("react-grab:init",n=>{n instanceof CustomEvent&&h(n.detail)&&e(n.detail);},{once:true});let r=window.__REACT_GRAB__;h(r)&&e(r);};R();
|
|
5
|
+
exports.attachAgent=R;exports.createOpenCodeAgentProvider=_;return exports;})({});
|
package/dist/client.js
CHANGED
|
@@ -10,7 +10,7 @@ var parseSSEEvent = (eventBlock) => {
|
|
|
10
10
|
}
|
|
11
11
|
return { eventType, data };
|
|
12
12
|
};
|
|
13
|
-
async function*
|
|
13
|
+
var streamSSE = async function* (stream, signal) {
|
|
14
14
|
const reader = stream.getReader();
|
|
15
15
|
const decoder = new TextDecoder();
|
|
16
16
|
let buffer = "";
|
|
@@ -49,28 +49,54 @@ async function* streamSSE(stream, signal) {
|
|
|
49
49
|
} catch {
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
};
|
|
53
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
54
|
+
var getStoredAgentContext = (storage, sessionId, storageKey = STORAGE_KEY) => {
|
|
55
|
+
const rawSessions = storage.getItem(storageKey);
|
|
56
|
+
if (!rawSessions) throw new Error("No sessions to resume");
|
|
57
|
+
let parsed;
|
|
58
|
+
try {
|
|
59
|
+
parsed = JSON.parse(rawSessions);
|
|
60
|
+
} catch {
|
|
61
|
+
throw new Error("Failed to parse stored sessions");
|
|
62
|
+
}
|
|
63
|
+
if (!isRecord(parsed)) throw new Error("Invalid stored sessions");
|
|
64
|
+
const storedSession = parsed[sessionId];
|
|
65
|
+
if (!isRecord(storedSession)) {
|
|
66
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
67
|
+
}
|
|
68
|
+
const context = storedSession.context;
|
|
69
|
+
if (!isRecord(context)) throw new Error(`Session ${sessionId} is invalid`);
|
|
70
|
+
const content = context.content;
|
|
71
|
+
const prompt = context.prompt;
|
|
72
|
+
if (typeof content !== "string" || typeof prompt !== "string") {
|
|
73
|
+
throw new Error(`Session ${sessionId} is invalid`);
|
|
74
|
+
}
|
|
75
|
+
const options = context.options;
|
|
76
|
+
const storedSessionId = context.sessionId;
|
|
77
|
+
return {
|
|
78
|
+
content,
|
|
79
|
+
prompt,
|
|
80
|
+
options,
|
|
81
|
+
sessionId: typeof storedSessionId === "string" ? storedSessionId : void 0
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
var streamAgentStatusFromServer = async function* (options, context, signal) {
|
|
61
85
|
const startTime = Date.now();
|
|
62
86
|
const sessionId = context.sessionId;
|
|
87
|
+
const pollIntervalMs = options.pollIntervalMs ?? 100;
|
|
88
|
+
const agentUrl = `${options.serverUrl}${options.agentPath ?? "/agent"}`;
|
|
63
89
|
const handleAbort = () => {
|
|
64
|
-
if (sessionId)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
90
|
+
if (!sessionId) return;
|
|
91
|
+
const abortPath = options.abortPath?.(sessionId) ?? `/abort/${sessionId}`;
|
|
92
|
+
fetch(`${options.serverUrl}${abortPath}`, { method: "POST" }).catch(
|
|
93
|
+
() => {
|
|
94
|
+
}
|
|
95
|
+
);
|
|
70
96
|
};
|
|
71
97
|
signal.addEventListener("abort", handleAbort);
|
|
72
98
|
try {
|
|
73
|
-
const response = await fetch(
|
|
99
|
+
const response = await fetch(agentUrl, {
|
|
74
100
|
method: "POST",
|
|
75
101
|
headers: { "Content-Type": "application/json" },
|
|
76
102
|
body: JSON.stringify(context),
|
|
@@ -83,29 +109,29 @@ var streamFromServer = async function* (serverUrl, context, signal) {
|
|
|
83
109
|
throw new Error("No response body");
|
|
84
110
|
}
|
|
85
111
|
const iterator = streamSSE(response.body, signal)[Symbol.asyncIterator]();
|
|
86
|
-
let
|
|
112
|
+
let isDone = false;
|
|
87
113
|
let pendingNext = iterator.next();
|
|
88
114
|
let lastStatus = null;
|
|
89
|
-
while (!
|
|
115
|
+
while (!isDone) {
|
|
90
116
|
const result = await Promise.race([
|
|
91
117
|
pendingNext.then((iteratorResult) => ({
|
|
92
118
|
type: "status",
|
|
93
119
|
iteratorResult
|
|
94
120
|
})),
|
|
95
121
|
new Promise(
|
|
96
|
-
(resolve) => setTimeout(() => resolve({ type: "timeout" }),
|
|
122
|
+
(resolve) => setTimeout(() => resolve({ type: "timeout" }), pollIntervalMs)
|
|
97
123
|
)
|
|
98
124
|
]);
|
|
99
125
|
const elapsedSeconds = (Date.now() - startTime) / 1e3;
|
|
100
126
|
if (result.type === "status") {
|
|
101
127
|
const iteratorResult = result.iteratorResult;
|
|
102
|
-
|
|
103
|
-
if (!
|
|
128
|
+
isDone = iteratorResult.done ?? false;
|
|
129
|
+
if (!isDone && iteratorResult.value) {
|
|
104
130
|
lastStatus = iteratorResult.value;
|
|
105
131
|
pendingNext = iterator.next();
|
|
106
132
|
}
|
|
107
133
|
}
|
|
108
|
-
if (lastStatus ===
|
|
134
|
+
if (lastStatus === options.completedStatus) {
|
|
109
135
|
yield `Completed in ${elapsedSeconds.toFixed(1)}s`;
|
|
110
136
|
} else if (lastStatus) {
|
|
111
137
|
yield `${lastStatus} ${elapsedSeconds.toFixed(1)}s`;
|
|
@@ -117,56 +143,73 @@ var streamFromServer = async function* (serverUrl, context, signal) {
|
|
|
117
143
|
signal.removeEventListener("abort", handleAbort);
|
|
118
144
|
}
|
|
119
145
|
};
|
|
146
|
+
var createCachedConnectionChecker = (checkConnection, ttlMs = CONNECTION_CHECK_TTL_MS) => {
|
|
147
|
+
let cache = null;
|
|
148
|
+
return async () => {
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
if (cache && now - cache.timestamp < ttlMs) return cache.result;
|
|
151
|
+
try {
|
|
152
|
+
const result = await checkConnection();
|
|
153
|
+
cache = { result, timestamp: now };
|
|
154
|
+
return result;
|
|
155
|
+
} catch {
|
|
156
|
+
cache = { result: false, timestamp: now };
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// src/constants.ts
|
|
163
|
+
var DEFAULT_PORT = 6567;
|
|
164
|
+
var COMPLETED_STATUS = "Completed successfully";
|
|
165
|
+
|
|
166
|
+
// src/client.ts
|
|
167
|
+
var DEFAULT_SERVER_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
168
|
+
var isReactGrabApi = (value) => typeof value === "object" && value !== null && "setAgent" in value;
|
|
120
169
|
var createOpenCodeAgentProvider = (options = {}) => {
|
|
121
170
|
const { serverUrl = DEFAULT_SERVER_URL, getOptions } = options;
|
|
122
|
-
let connectionCache = null;
|
|
123
171
|
const mergeOptions = (contextOptions) => ({
|
|
124
172
|
...getOptions?.() ?? {},
|
|
125
173
|
...contextOptions ?? {}
|
|
126
174
|
});
|
|
175
|
+
const checkConnection = createCachedConnectionChecker(async () => {
|
|
176
|
+
const response = await fetch(`${serverUrl}/health`, { method: "GET" });
|
|
177
|
+
return response.ok;
|
|
178
|
+
}, CONNECTION_CHECK_TTL_MS);
|
|
127
179
|
return {
|
|
128
180
|
send: async function* (context, signal) {
|
|
129
181
|
const combinedContext = {
|
|
130
182
|
...context,
|
|
131
183
|
options: mergeOptions(context.options)
|
|
132
184
|
};
|
|
133
|
-
yield*
|
|
185
|
+
yield* streamAgentStatusFromServer(
|
|
186
|
+
{ serverUrl, completedStatus: COMPLETED_STATUS },
|
|
187
|
+
combinedContext,
|
|
188
|
+
signal
|
|
189
|
+
);
|
|
134
190
|
},
|
|
135
191
|
resume: async function* (sessionId, signal, storage) {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
throw new Error(`Session ${sessionId} not found`);
|
|
144
|
-
}
|
|
145
|
-
const context = session.context;
|
|
192
|
+
const storedContext = getStoredAgentContext(storage, sessionId);
|
|
193
|
+
const context = {
|
|
194
|
+
content: storedContext.content,
|
|
195
|
+
prompt: storedContext.prompt,
|
|
196
|
+
options: storedContext.options,
|
|
197
|
+
sessionId: storedContext.sessionId ?? sessionId
|
|
198
|
+
};
|
|
146
199
|
const combinedContext = {
|
|
147
200
|
...context,
|
|
148
201
|
options: mergeOptions(context.options)
|
|
149
202
|
};
|
|
150
203
|
yield "Resuming...";
|
|
151
|
-
yield*
|
|
204
|
+
yield* streamAgentStatusFromServer(
|
|
205
|
+
{ serverUrl, completedStatus: COMPLETED_STATUS },
|
|
206
|
+
combinedContext,
|
|
207
|
+
signal
|
|
208
|
+
);
|
|
152
209
|
},
|
|
153
210
|
supportsResume: true,
|
|
154
211
|
supportsFollowUp: true,
|
|
155
|
-
checkConnection
|
|
156
|
-
const now = Date.now();
|
|
157
|
-
if (connectionCache && now - connectionCache.timestamp < CONNECTION_CHECK_TTL_MS) {
|
|
158
|
-
return connectionCache.result;
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
const response = await fetch(`${serverUrl}/health`, { method: "GET" });
|
|
162
|
-
const result = response.ok;
|
|
163
|
-
connectionCache = { result, timestamp: now };
|
|
164
|
-
return result;
|
|
165
|
-
} catch {
|
|
166
|
-
connectionCache = { result: false, timestamp: now };
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
},
|
|
212
|
+
checkConnection,
|
|
170
213
|
undo: async () => {
|
|
171
214
|
try {
|
|
172
215
|
await fetch(`${serverUrl}/undo`, { method: "POST" });
|
|
@@ -178,24 +221,25 @@ var createOpenCodeAgentProvider = (options = {}) => {
|
|
|
178
221
|
var attachAgent = async () => {
|
|
179
222
|
if (typeof window === "undefined") return;
|
|
180
223
|
const provider = createOpenCodeAgentProvider();
|
|
181
|
-
const attach = (
|
|
182
|
-
|
|
224
|
+
const attach = (api) => {
|
|
225
|
+
api.setAgent({ provider, storage: sessionStorage });
|
|
183
226
|
};
|
|
184
|
-
const
|
|
185
|
-
if (
|
|
186
|
-
attach(
|
|
227
|
+
const existingApi = window.__REACT_GRAB__;
|
|
228
|
+
if (isReactGrabApi(existingApi)) {
|
|
229
|
+
attach(existingApi);
|
|
187
230
|
return;
|
|
188
231
|
}
|
|
189
232
|
window.addEventListener(
|
|
190
233
|
"react-grab:init",
|
|
191
234
|
(event) => {
|
|
192
|
-
|
|
193
|
-
|
|
235
|
+
if (!(event instanceof CustomEvent)) return;
|
|
236
|
+
if (!isReactGrabApi(event.detail)) return;
|
|
237
|
+
attach(event.detail);
|
|
194
238
|
},
|
|
195
239
|
{ once: true }
|
|
196
240
|
);
|
|
197
241
|
const apiAfterListener = window.__REACT_GRAB__;
|
|
198
|
-
if (apiAfterListener) {
|
|
242
|
+
if (isReactGrabApi(apiAfterListener)) {
|
|
199
243
|
attach(apiAfterListener);
|
|
200
244
|
}
|
|
201
245
|
};
|
package/dist/server.cjs
CHANGED
|
@@ -7343,9 +7343,11 @@ var COMPLETED_STATUS = "Completed successfully";
|
|
|
7343
7343
|
|
|
7344
7344
|
// ../utils/dist/server.js
|
|
7345
7345
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7346
|
-
var VERSION = "0.0.
|
|
7346
|
+
var VERSION = "0.0.90";
|
|
7347
7347
|
try {
|
|
7348
|
-
fetch(
|
|
7348
|
+
fetch(
|
|
7349
|
+
`https://www.react-grab.com/api/version?source=opencode&t=${Date.now()}`
|
|
7350
|
+
).catch(() => {
|
|
7349
7351
|
});
|
|
7350
7352
|
} catch {
|
|
7351
7353
|
}
|
|
@@ -7412,7 +7414,10 @@ var executeOpenCodePrompt = async (prompt, options, onStatus, reactGrabSessionId
|
|
|
7412
7414
|
const part = eventData.properties.part;
|
|
7413
7415
|
if (part.sessionID !== opencodeSessionId) continue;
|
|
7414
7416
|
if (part.messageID) {
|
|
7415
|
-
lastMessageInfo = {
|
|
7417
|
+
lastMessageInfo = {
|
|
7418
|
+
sessionId: opencodeSessionId,
|
|
7419
|
+
messageId: part.messageID
|
|
7420
|
+
};
|
|
7416
7421
|
}
|
|
7417
7422
|
if (part.type === "text" && part.text) {
|
|
7418
7423
|
const truncatedText = part.text.length > 100 ? `${part.text.slice(0, 100)}...` : part.text;
|
|
@@ -7425,6 +7430,94 @@ var executeOpenCodePrompt = async (prompt, options, onStatus, reactGrabSessionId
|
|
|
7425
7430
|
}
|
|
7426
7431
|
return opencodeSessionId;
|
|
7427
7432
|
};
|
|
7433
|
+
var runAgent = async function* (prompt, options) {
|
|
7434
|
+
const sessionId = options?.sessionId;
|
|
7435
|
+
const signal = { aborted: false };
|
|
7436
|
+
const isAborted = () => {
|
|
7437
|
+
if (options?.signal?.aborted) {
|
|
7438
|
+
signal.aborted = true;
|
|
7439
|
+
return true;
|
|
7440
|
+
}
|
|
7441
|
+
if (sessionId && abortedSessions.has(sessionId)) {
|
|
7442
|
+
signal.aborted = true;
|
|
7443
|
+
return true;
|
|
7444
|
+
}
|
|
7445
|
+
return false;
|
|
7446
|
+
};
|
|
7447
|
+
const messageQueue = [];
|
|
7448
|
+
let resolveWait = null;
|
|
7449
|
+
const enqueueMessage = (message) => {
|
|
7450
|
+
messageQueue.push(message);
|
|
7451
|
+
if (resolveWait) {
|
|
7452
|
+
resolveWait();
|
|
7453
|
+
resolveWait = null;
|
|
7454
|
+
}
|
|
7455
|
+
};
|
|
7456
|
+
try {
|
|
7457
|
+
const executePromise = executeOpenCodePrompt(
|
|
7458
|
+
prompt,
|
|
7459
|
+
options,
|
|
7460
|
+
(text) => {
|
|
7461
|
+
if (!isAborted()) {
|
|
7462
|
+
enqueueMessage({ type: "status", content: text });
|
|
7463
|
+
}
|
|
7464
|
+
},
|
|
7465
|
+
sessionId,
|
|
7466
|
+
signal
|
|
7467
|
+
);
|
|
7468
|
+
let isDone = false;
|
|
7469
|
+
executePromise.then(() => {
|
|
7470
|
+
if (!isAborted()) {
|
|
7471
|
+
enqueueMessage({ type: "status", content: COMPLETED_STATUS });
|
|
7472
|
+
enqueueMessage({ type: "done", content: "" });
|
|
7473
|
+
}
|
|
7474
|
+
isDone = true;
|
|
7475
|
+
if (resolveWait) {
|
|
7476
|
+
resolveWait();
|
|
7477
|
+
resolveWait = null;
|
|
7478
|
+
}
|
|
7479
|
+
}).catch((error) => {
|
|
7480
|
+
if (!isAborted()) {
|
|
7481
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
7482
|
+
const stderr = error instanceof Error && "stderr" in error ? String(error.stderr) : void 0;
|
|
7483
|
+
const fullError = stderr && stderr.trim() ? `${errorMessage}
|
|
7484
|
+
|
|
7485
|
+
stderr:
|
|
7486
|
+
${stderr.trim()}` : errorMessage;
|
|
7487
|
+
enqueueMessage({ type: "error", content: fullError });
|
|
7488
|
+
enqueueMessage({ type: "done", content: "" });
|
|
7489
|
+
}
|
|
7490
|
+
isDone = true;
|
|
7491
|
+
if (resolveWait) {
|
|
7492
|
+
resolveWait();
|
|
7493
|
+
resolveWait = null;
|
|
7494
|
+
}
|
|
7495
|
+
});
|
|
7496
|
+
while (true) {
|
|
7497
|
+
if (isAborted()) {
|
|
7498
|
+
return;
|
|
7499
|
+
}
|
|
7500
|
+
if (messageQueue.length > 0) {
|
|
7501
|
+
const message = messageQueue.shift();
|
|
7502
|
+
if (message.type === "done") {
|
|
7503
|
+
yield message;
|
|
7504
|
+
return;
|
|
7505
|
+
}
|
|
7506
|
+
yield message;
|
|
7507
|
+
} else if (isDone) {
|
|
7508
|
+
return;
|
|
7509
|
+
} else {
|
|
7510
|
+
await new Promise((resolve) => {
|
|
7511
|
+
resolveWait = resolve;
|
|
7512
|
+
});
|
|
7513
|
+
}
|
|
7514
|
+
}
|
|
7515
|
+
} finally {
|
|
7516
|
+
if (sessionId) {
|
|
7517
|
+
abortedSessions.delete(sessionId);
|
|
7518
|
+
}
|
|
7519
|
+
}
|
|
7520
|
+
};
|
|
7428
7521
|
var createServer = () => {
|
|
7429
7522
|
const honoApplication = new Hono2();
|
|
7430
7523
|
honoApplication.use("*", cors());
|
|
@@ -7439,53 +7532,17 @@ Context:
|
|
|
7439
7532
|
${content}
|
|
7440
7533
|
`;
|
|
7441
7534
|
return streamSSE(context, async (stream2) => {
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
}
|
|
7448
|
-
return false;
|
|
7449
|
-
};
|
|
7450
|
-
try {
|
|
7451
|
-
await executeOpenCodePrompt(
|
|
7452
|
-
formattedPrompt,
|
|
7453
|
-
options,
|
|
7454
|
-
(text) => {
|
|
7455
|
-
if (isAborted()) return;
|
|
7456
|
-
stream2.writeSSE({
|
|
7457
|
-
data: text,
|
|
7458
|
-
event: "status"
|
|
7459
|
-
}).catch(() => {
|
|
7460
|
-
});
|
|
7461
|
-
},
|
|
7462
|
-
sessionId,
|
|
7463
|
-
signal
|
|
7464
|
-
);
|
|
7465
|
-
if (!isAborted()) {
|
|
7535
|
+
for await (const message of runAgent(formattedPrompt, {
|
|
7536
|
+
...options,
|
|
7537
|
+
sessionId
|
|
7538
|
+
})) {
|
|
7539
|
+
if (message.type === "error") {
|
|
7466
7540
|
await stream2.writeSSE({
|
|
7467
|
-
data:
|
|
7468
|
-
event: "status"
|
|
7469
|
-
});
|
|
7470
|
-
await stream2.writeSSE({ data: "", event: "done" });
|
|
7471
|
-
}
|
|
7472
|
-
} catch (error) {
|
|
7473
|
-
if (!isAborted()) {
|
|
7474
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
7475
|
-
const stderr = error instanceof Error && "stderr" in error ? String(error.stderr) : void 0;
|
|
7476
|
-
const fullError = stderr && stderr.trim() ? `${errorMessage}
|
|
7477
|
-
|
|
7478
|
-
stderr:
|
|
7479
|
-
${stderr.trim()}` : errorMessage;
|
|
7480
|
-
await stream2.writeSSE({
|
|
7481
|
-
data: `Error: ${fullError}`,
|
|
7541
|
+
data: `Error: ${message.content}`,
|
|
7482
7542
|
event: "error"
|
|
7483
7543
|
});
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
} finally {
|
|
7487
|
-
if (sessionId) {
|
|
7488
|
-
abortedSessions.delete(sessionId);
|
|
7544
|
+
} else {
|
|
7545
|
+
await stream2.writeSSE({ data: message.content, event: message.type });
|
|
7489
7546
|
}
|
|
7490
7547
|
}
|
|
7491
7548
|
});
|
|
@@ -7532,4 +7589,5 @@ if ((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filen
|
|
|
7532
7589
|
}
|
|
7533
7590
|
|
|
7534
7591
|
exports.createServer = createServer;
|
|
7592
|
+
exports.runAgent = runAgent;
|
|
7535
7593
|
exports.startServer = startServer;
|
package/dist/server.js
CHANGED
|
@@ -7332,9 +7332,11 @@ var COMPLETED_STATUS = "Completed successfully";
|
|
|
7332
7332
|
|
|
7333
7333
|
// ../utils/dist/server.js
|
|
7334
7334
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7335
|
-
var VERSION = "0.0.
|
|
7335
|
+
var VERSION = "0.0.90";
|
|
7336
7336
|
try {
|
|
7337
|
-
fetch(
|
|
7337
|
+
fetch(
|
|
7338
|
+
`https://www.react-grab.com/api/version?source=opencode&t=${Date.now()}`
|
|
7339
|
+
).catch(() => {
|
|
7338
7340
|
});
|
|
7339
7341
|
} catch {
|
|
7340
7342
|
}
|
|
@@ -7401,7 +7403,10 @@ var executeOpenCodePrompt = async (prompt, options, onStatus, reactGrabSessionId
|
|
|
7401
7403
|
const part = eventData.properties.part;
|
|
7402
7404
|
if (part.sessionID !== opencodeSessionId) continue;
|
|
7403
7405
|
if (part.messageID) {
|
|
7404
|
-
lastMessageInfo = {
|
|
7406
|
+
lastMessageInfo = {
|
|
7407
|
+
sessionId: opencodeSessionId,
|
|
7408
|
+
messageId: part.messageID
|
|
7409
|
+
};
|
|
7405
7410
|
}
|
|
7406
7411
|
if (part.type === "text" && part.text) {
|
|
7407
7412
|
const truncatedText = part.text.length > 100 ? `${part.text.slice(0, 100)}...` : part.text;
|
|
@@ -7414,6 +7419,94 @@ var executeOpenCodePrompt = async (prompt, options, onStatus, reactGrabSessionId
|
|
|
7414
7419
|
}
|
|
7415
7420
|
return opencodeSessionId;
|
|
7416
7421
|
};
|
|
7422
|
+
var runAgent = async function* (prompt, options) {
|
|
7423
|
+
const sessionId = options?.sessionId;
|
|
7424
|
+
const signal = { aborted: false };
|
|
7425
|
+
const isAborted = () => {
|
|
7426
|
+
if (options?.signal?.aborted) {
|
|
7427
|
+
signal.aborted = true;
|
|
7428
|
+
return true;
|
|
7429
|
+
}
|
|
7430
|
+
if (sessionId && abortedSessions.has(sessionId)) {
|
|
7431
|
+
signal.aborted = true;
|
|
7432
|
+
return true;
|
|
7433
|
+
}
|
|
7434
|
+
return false;
|
|
7435
|
+
};
|
|
7436
|
+
const messageQueue = [];
|
|
7437
|
+
let resolveWait = null;
|
|
7438
|
+
const enqueueMessage = (message) => {
|
|
7439
|
+
messageQueue.push(message);
|
|
7440
|
+
if (resolveWait) {
|
|
7441
|
+
resolveWait();
|
|
7442
|
+
resolveWait = null;
|
|
7443
|
+
}
|
|
7444
|
+
};
|
|
7445
|
+
try {
|
|
7446
|
+
const executePromise = executeOpenCodePrompt(
|
|
7447
|
+
prompt,
|
|
7448
|
+
options,
|
|
7449
|
+
(text) => {
|
|
7450
|
+
if (!isAborted()) {
|
|
7451
|
+
enqueueMessage({ type: "status", content: text });
|
|
7452
|
+
}
|
|
7453
|
+
},
|
|
7454
|
+
sessionId,
|
|
7455
|
+
signal
|
|
7456
|
+
);
|
|
7457
|
+
let isDone = false;
|
|
7458
|
+
executePromise.then(() => {
|
|
7459
|
+
if (!isAborted()) {
|
|
7460
|
+
enqueueMessage({ type: "status", content: COMPLETED_STATUS });
|
|
7461
|
+
enqueueMessage({ type: "done", content: "" });
|
|
7462
|
+
}
|
|
7463
|
+
isDone = true;
|
|
7464
|
+
if (resolveWait) {
|
|
7465
|
+
resolveWait();
|
|
7466
|
+
resolveWait = null;
|
|
7467
|
+
}
|
|
7468
|
+
}).catch((error) => {
|
|
7469
|
+
if (!isAborted()) {
|
|
7470
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
7471
|
+
const stderr = error instanceof Error && "stderr" in error ? String(error.stderr) : void 0;
|
|
7472
|
+
const fullError = stderr && stderr.trim() ? `${errorMessage}
|
|
7473
|
+
|
|
7474
|
+
stderr:
|
|
7475
|
+
${stderr.trim()}` : errorMessage;
|
|
7476
|
+
enqueueMessage({ type: "error", content: fullError });
|
|
7477
|
+
enqueueMessage({ type: "done", content: "" });
|
|
7478
|
+
}
|
|
7479
|
+
isDone = true;
|
|
7480
|
+
if (resolveWait) {
|
|
7481
|
+
resolveWait();
|
|
7482
|
+
resolveWait = null;
|
|
7483
|
+
}
|
|
7484
|
+
});
|
|
7485
|
+
while (true) {
|
|
7486
|
+
if (isAborted()) {
|
|
7487
|
+
return;
|
|
7488
|
+
}
|
|
7489
|
+
if (messageQueue.length > 0) {
|
|
7490
|
+
const message = messageQueue.shift();
|
|
7491
|
+
if (message.type === "done") {
|
|
7492
|
+
yield message;
|
|
7493
|
+
return;
|
|
7494
|
+
}
|
|
7495
|
+
yield message;
|
|
7496
|
+
} else if (isDone) {
|
|
7497
|
+
return;
|
|
7498
|
+
} else {
|
|
7499
|
+
await new Promise((resolve) => {
|
|
7500
|
+
resolveWait = resolve;
|
|
7501
|
+
});
|
|
7502
|
+
}
|
|
7503
|
+
}
|
|
7504
|
+
} finally {
|
|
7505
|
+
if (sessionId) {
|
|
7506
|
+
abortedSessions.delete(sessionId);
|
|
7507
|
+
}
|
|
7508
|
+
}
|
|
7509
|
+
};
|
|
7417
7510
|
var createServer = () => {
|
|
7418
7511
|
const honoApplication = new Hono2();
|
|
7419
7512
|
honoApplication.use("*", cors());
|
|
@@ -7428,53 +7521,17 @@ Context:
|
|
|
7428
7521
|
${content}
|
|
7429
7522
|
`;
|
|
7430
7523
|
return streamSSE(context, async (stream2) => {
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
}
|
|
7437
|
-
return false;
|
|
7438
|
-
};
|
|
7439
|
-
try {
|
|
7440
|
-
await executeOpenCodePrompt(
|
|
7441
|
-
formattedPrompt,
|
|
7442
|
-
options,
|
|
7443
|
-
(text) => {
|
|
7444
|
-
if (isAborted()) return;
|
|
7445
|
-
stream2.writeSSE({
|
|
7446
|
-
data: text,
|
|
7447
|
-
event: "status"
|
|
7448
|
-
}).catch(() => {
|
|
7449
|
-
});
|
|
7450
|
-
},
|
|
7451
|
-
sessionId,
|
|
7452
|
-
signal
|
|
7453
|
-
);
|
|
7454
|
-
if (!isAborted()) {
|
|
7524
|
+
for await (const message of runAgent(formattedPrompt, {
|
|
7525
|
+
...options,
|
|
7526
|
+
sessionId
|
|
7527
|
+
})) {
|
|
7528
|
+
if (message.type === "error") {
|
|
7455
7529
|
await stream2.writeSSE({
|
|
7456
|
-
data:
|
|
7457
|
-
event: "status"
|
|
7458
|
-
});
|
|
7459
|
-
await stream2.writeSSE({ data: "", event: "done" });
|
|
7460
|
-
}
|
|
7461
|
-
} catch (error) {
|
|
7462
|
-
if (!isAborted()) {
|
|
7463
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
7464
|
-
const stderr = error instanceof Error && "stderr" in error ? String(error.stderr) : void 0;
|
|
7465
|
-
const fullError = stderr && stderr.trim() ? `${errorMessage}
|
|
7466
|
-
|
|
7467
|
-
stderr:
|
|
7468
|
-
${stderr.trim()}` : errorMessage;
|
|
7469
|
-
await stream2.writeSSE({
|
|
7470
|
-
data: `Error: ${fullError}`,
|
|
7530
|
+
data: `Error: ${message.content}`,
|
|
7471
7531
|
event: "error"
|
|
7472
7532
|
});
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
} finally {
|
|
7476
|
-
if (sessionId) {
|
|
7477
|
-
abortedSessions.delete(sessionId);
|
|
7533
|
+
} else {
|
|
7534
|
+
await stream2.writeSSE({ data: message.content, event: message.type });
|
|
7478
7535
|
}
|
|
7479
7536
|
}
|
|
7480
7537
|
});
|
|
@@ -7520,4 +7577,4 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
|
7520
7577
|
startServer(DEFAULT_PORT).catch(console.error);
|
|
7521
7578
|
}
|
|
7522
7579
|
|
|
7523
|
-
export { createServer, startServer };
|
|
7580
|
+
export { createServer, runAgent, startServer };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-grab/opencode",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.90",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"react-grab-opencode": "./dist/cli.cjs"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^22.10.7",
|
|
28
28
|
"tsup": "^8.4.0",
|
|
29
|
-
"@react-grab/utils": "0.0.
|
|
29
|
+
"@react-grab/utils": "0.0.90"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@hono/node-server": "^1.19.6",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"fkill": "^9.0.0",
|
|
36
36
|
"hono": "^4.0.0",
|
|
37
37
|
"picocolors": "^1.1.1",
|
|
38
|
-
"react-grab": "0.0.
|
|
38
|
+
"react-grab": "0.0.90"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"dev": "tsup --watch",
|