@prbe.ai/electron-sdk 0.1.13 → 0.1.14

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/index.js CHANGED
@@ -34,6 +34,7 @@ __export(src_exports, {
34
34
  AskUserTool: () => AskUserTool,
35
35
  BashExecuteTool: () => BashExecuteTool,
36
36
  ClearAppLogsTool: () => ClearAppLogsTool,
37
+ ConversationRole: () => ConversationRole,
37
38
  DEFAULT_PRBE_STATE: () => DEFAULT_PRBE_STATE,
38
39
  FindFilesTool: () => FindFilesTool,
39
40
  FlagAppLogsTool: () => FlagAppLogsTool,
@@ -79,6 +80,7 @@ var WSMessageType = /* @__PURE__ */ ((WSMessageType2) => {
79
80
  WSMessageType2["START"] = "start";
80
81
  WSMessageType2["TOOL_RESULT"] = "tool_result";
81
82
  WSMessageType2["UPLOAD_REQUEST"] = "upload_request";
83
+ WSMessageType2["CONVERSATION_MESSAGE"] = "conversation_message";
82
84
  WSMessageType2["CANCEL"] = "cancel";
83
85
  WSMessageType2["PONG"] = "pong";
84
86
  WSMessageType2["THOUGHT"] = "thought";
@@ -87,11 +89,17 @@ var WSMessageType = /* @__PURE__ */ ((WSMessageType2) => {
87
89
  WSMessageType2["SERVER_OBSERVATION"] = "server_observation";
88
90
  WSMessageType2["UPLOAD_URL"] = "upload_url";
89
91
  WSMessageType2["SESSION_CONFIG"] = "session_config";
92
+ WSMessageType2["CONVERSATION_UPDATE"] = "conversation_update";
90
93
  WSMessageType2["COMPLETE"] = "complete";
91
94
  WSMessageType2["ERROR"] = "error";
92
95
  WSMessageType2["PING"] = "ping";
93
96
  return WSMessageType2;
94
97
  })(WSMessageType || {});
98
+ var ConversationRole = /* @__PURE__ */ ((ConversationRole3) => {
99
+ ConversationRole3["User"] = "user";
100
+ ConversationRole3["Agent"] = "agent";
101
+ return ConversationRole3;
102
+ })(ConversationRole || {});
95
103
  var ToolParamType = /* @__PURE__ */ ((ToolParamType2) => {
96
104
  ToolParamType2["STRING"] = "STRING";
97
105
  ToolParamType2["BOOLEAN"] = "BOOLEAN";
@@ -161,6 +169,83 @@ function redactPII(text) {
161
169
  var API_URL = "https://api.prbe.ai";
162
170
  var MIDDLEWARE_URL = "wss://middleware.prbe.ai";
163
171
 
172
+ // src/connection.ts
173
+ var InvestigationConnection = class {
174
+ constructor(url, apiKey, onMessage, onError, onClose) {
175
+ this.onMessage = onMessage;
176
+ this.onError = onError;
177
+ this.onClose = onClose;
178
+ this.ws = new WebSocket(url, {
179
+ headers: { "X-API-Key": apiKey }
180
+ });
181
+ this.ws.onmessage = (event) => {
182
+ const raw = typeof event.data === "string" ? event.data : event.data instanceof Buffer ? event.data.toString("utf-8") : null;
183
+ if (!raw) return;
184
+ try {
185
+ const msg = JSON.parse(raw);
186
+ this.onMessage(msg);
187
+ } catch {
188
+ }
189
+ };
190
+ this.ws.onerror = (event) => {
191
+ const errorEvent = event;
192
+ this.onError(errorEvent.message || "WebSocket connection error");
193
+ };
194
+ this.ws.onclose = () => {
195
+ this.onClose();
196
+ };
197
+ }
198
+ ws;
199
+ closed = false;
200
+ get isOpen() {
201
+ return !this.closed && this.ws.readyState === WebSocket.OPEN;
202
+ }
203
+ send(msg) {
204
+ if (!this.isOpen) return false;
205
+ try {
206
+ this.ws.send(JSON.stringify(msg));
207
+ return true;
208
+ } catch {
209
+ return false;
210
+ }
211
+ }
212
+ sendConversationMessage(content) {
213
+ this.send({
214
+ type: "conversation_message" /* CONVERSATION_MESSAGE */,
215
+ content
216
+ });
217
+ }
218
+ sendToolResult(callId, toolName, result, metadata) {
219
+ this.send({
220
+ type: "tool_result" /* TOOL_RESULT */,
221
+ id: callId,
222
+ name: toolName,
223
+ content: result,
224
+ metadata
225
+ });
226
+ }
227
+ sendCancel() {
228
+ this.send({ type: "cancel" /* CANCEL */ });
229
+ }
230
+ sendPong() {
231
+ this.send({ type: "pong" /* PONG */ });
232
+ }
233
+ close(code = 1e3, reason) {
234
+ if (this.closed) return;
235
+ this.closed = true;
236
+ try {
237
+ this.ws.close(code, reason);
238
+ } catch {
239
+ }
240
+ }
241
+ /**
242
+ * Set the onopen handler. Called when the connection is ready to send messages.
243
+ */
244
+ set onopen(handler) {
245
+ this.ws.onopen = handler;
246
+ }
247
+ };
248
+
164
249
  // src/state.ts
165
250
  var import_events = require("events");
166
251
  var import_crypto = require("crypto");
@@ -189,6 +274,7 @@ var PRBEAgentState = class extends import_events.EventEmitter {
189
274
  pendingInteraction;
190
275
  resolvedInteractions = [];
191
276
  agentMessage;
277
+ conversationHistory = [];
192
278
  // Completed user investigations (history)
193
279
  completedInvestigations = [];
194
280
  // Background context requests
@@ -212,6 +298,7 @@ var PRBEAgentState = class extends import_events.EventEmitter {
212
298
  this.isInvestigating = true;
213
299
  this.events = [];
214
300
  this.resolvedInteractions = [];
301
+ this.conversationHistory = [];
215
302
  this.report = "";
216
303
  this.summary = "";
217
304
  this.currentQuery = query;
@@ -219,10 +306,15 @@ var PRBEAgentState = class extends import_events.EventEmitter {
219
306
  this.agentMessage = void 0;
220
307
  this.emit("status" /* STATUS */);
221
308
  }
309
+ appendConversation(entry) {
310
+ this.conversationHistory.push(entry);
311
+ this.emit("status" /* STATUS */);
312
+ }
222
313
  resetInvestigation() {
223
314
  this.isInvestigating = false;
224
315
  this.events = [];
225
316
  this.resolvedInteractions = [];
317
+ this.conversationHistory = [];
226
318
  this.report = "";
227
319
  this.summary = "";
228
320
  this.currentQuery = "";
@@ -255,7 +347,7 @@ var PRBEAgentState = class extends import_events.EventEmitter {
255
347
  this.emit("status" /* STATUS */);
256
348
  }
257
349
  }
258
- completeInvestigation(report, summary, ticketId) {
350
+ completeInvestigation(report, ticketId) {
259
351
  if (this.events.length > 0) {
260
352
  this.events[this.events.length - 1].isCompleted = true;
261
353
  }
@@ -264,16 +356,15 @@ var PRBEAgentState = class extends import_events.EventEmitter {
264
356
  id: (0, import_crypto.randomUUID)(),
265
357
  query: this.currentQuery,
266
358
  report,
267
- summary,
268
359
  ticketId,
269
360
  events: [...this.events],
270
361
  resolvedInteractions: [...this.resolvedInteractions],
362
+ conversationHistory: [...this.conversationHistory],
271
363
  completedAt: /* @__PURE__ */ new Date()
272
364
  });
273
365
  this.report = report;
274
- this.summary = summary;
275
366
  this.isInvestigating = false;
276
- this.emit("complete" /* COMPLETE */, { report, summary });
367
+ this.emit("complete" /* COMPLETE */, { report });
277
368
  this.emit("status" /* STATUS */);
278
369
  }
279
370
  failInvestigation(message) {
@@ -398,7 +489,7 @@ var PRBEAgentState = class extends import_events.EventEmitter {
398
489
  cr.events[cr.events.length - 1].detail = text;
399
490
  this.emit("status" /* STATUS */);
400
491
  }
401
- completeCR(id, report, summary) {
492
+ completeCR(id, report) {
402
493
  const cr = this.activeCRs.get(id);
403
494
  if (!cr) return;
404
495
  this.activeCRs.delete(id);
@@ -414,7 +505,6 @@ var PRBEAgentState = class extends import_events.EventEmitter {
414
505
  cr.isRunning = false;
415
506
  cr.isCompleted = true;
416
507
  cr.report = report;
417
- cr.summary = summary;
418
508
  this.completedCRs.unshift(cr);
419
509
  this.emit("cr-complete" /* CR_COMPLETE */, cr);
420
510
  this.emit("status" /* STATUS */);
@@ -1351,9 +1441,9 @@ var AskUserTool = class {
1351
1441
  required: true
1352
1442
  },
1353
1443
  {
1354
- name: "context",
1444
+ name: "reason",
1355
1445
  type: "STRING" /* STRING */,
1356
- description: "Optional context explaining why you need this information",
1446
+ description: "Short reason displayed alongside the input prompt explaining why you need this information",
1357
1447
  required: false
1358
1448
  }
1359
1449
  ]
@@ -1365,12 +1455,11 @@ var AskUserTool = class {
1365
1455
  if (this.requester.investigationSource !== "user" /* USER */) {
1366
1456
  return "This is a context request investigation \u2014 you cannot ask the user questions. Use the available tools to answer the query autonomously.";
1367
1457
  }
1368
- const context = args["context"];
1458
+ const reason = args["reason"] ?? "Waiting for your response";
1369
1459
  const response = await this.requester.requestUserInteraction({
1370
1460
  type: "ask_question" /* ASK_QUESTION */,
1371
1461
  interactionId: (0, import_crypto3.randomUUID)(),
1372
- question,
1373
- context
1462
+ question: reason
1374
1463
  });
1375
1464
  const askResponse = response;
1376
1465
  return askResponse.answer;
@@ -1791,6 +1880,7 @@ var HistoryStore = class {
1791
1880
  ticketId: inv.ticketId,
1792
1881
  events: inv.events,
1793
1882
  resolvedInteractions: inv.resolvedInteractions,
1883
+ conversationHistory: inv.conversationHistory,
1794
1884
  completedAt: inv.completedAt.toISOString()
1795
1885
  };
1796
1886
  fs2.writeFileSync(
@@ -1883,7 +1973,7 @@ var PRBEAgent = class _PRBEAgent {
1883
1973
  registry = new PRBEToolRegistry();
1884
1974
  grantedPaths = /* @__PURE__ */ new Set();
1885
1975
  userCancelled = false;
1886
- activeWS = null;
1976
+ activeConnection = null;
1887
1977
  pollingTimer = null;
1888
1978
  persistedData;
1889
1979
  fetchAbortController = null;
@@ -2043,6 +2133,9 @@ var PRBEAgent = class _PRBEAgent {
2043
2133
  get investigationSource() {
2044
2134
  return this.currentInvestigationSource;
2045
2135
  }
2136
+ sendConversationMessage(content) {
2137
+ this.activeConnection?.sendConversationMessage(content);
2138
+ }
2046
2139
  async requestUserInteraction(payload) {
2047
2140
  if (!this.interactionHandler) {
2048
2141
  throw new PRBEAgentError(
@@ -2062,6 +2155,13 @@ var PRBEAgent = class _PRBEAgent {
2062
2155
  } else {
2063
2156
  this.state.resolveInteraction(response);
2064
2157
  }
2158
+ if (response.type === "request_permission" /* REQUEST_PERMISSION */) {
2159
+ const approved = response.approved;
2160
+ this.sendConversationMessage(approved ? "Approved" : "Denied");
2161
+ } else if (response.type === "request_path_access" /* REQUEST_PATH_ACCESS */) {
2162
+ const granted = response.granted;
2163
+ this.sendConversationMessage(granted ? "Allowed" : "Denied");
2164
+ }
2065
2165
  return response;
2066
2166
  } catch (err) {
2067
2167
  if (this.currentInvestigationSource === "context_request" /* CONTEXT_REQUEST */ && this.currentCRId) {
@@ -2114,7 +2214,7 @@ var PRBEAgent = class _PRBEAgent {
2114
2214
  this.state.appendEvent("Thinking", status.text);
2115
2215
  break;
2116
2216
  case "completed" /* COMPLETED */:
2117
- this.state.completeInvestigation(status.report, status.userSummary, status.ticketId);
2217
+ this.state.completeInvestigation(status.report, status.ticketId);
2118
2218
  this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2119
2219
  break;
2120
2220
  case "error" /* ERROR */:
@@ -2144,9 +2244,9 @@ var PRBEAgent = class _PRBEAgent {
2144
2244
  */
2145
2245
  cancelInvestigation() {
2146
2246
  this.userCancelled = true;
2147
- if (this.activeWS) {
2148
- this.activeWS.close(1e3, "User cancelled");
2149
- this.activeWS = null;
2247
+ if (this.activeConnection) {
2248
+ this.activeConnection.close(1e3, "User cancelled");
2249
+ this.activeConnection = null;
2150
2250
  }
2151
2251
  }
2152
2252
  /**
@@ -2154,9 +2254,9 @@ var PRBEAgent = class _PRBEAgent {
2154
2254
  */
2155
2255
  cancel() {
2156
2256
  this.userCancelled = true;
2157
- if (this.activeWS) {
2158
- this.activeWS.close(1e3, "User cancelled");
2159
- this.activeWS = null;
2257
+ if (this.activeConnection) {
2258
+ this.activeConnection.close(1e3, "User cancelled");
2259
+ this.activeConnection = null;
2160
2260
  }
2161
2261
  this.abortInFlightRequests();
2162
2262
  this.stopPolling();
@@ -2295,7 +2395,7 @@ var PRBEAgent = class _PRBEAgent {
2295
2395
  this.state.appendCREvent(crID, "Thinking", status.text);
2296
2396
  break;
2297
2397
  case "completed" /* COMPLETED */:
2298
- this.state.completeCR(crID, status.report, status.userSummary);
2398
+ this.state.completeCR(crID, status.report);
2299
2399
  this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2300
2400
  break;
2301
2401
  case "error" /* ERROR */:
@@ -2322,31 +2422,44 @@ var PRBEAgent = class _PRBEAgent {
2322
2422
  connectToProxy(query, contextRequestID, emit, isCancelled, ticketId) {
2323
2423
  return new Promise((resolve2) => {
2324
2424
  const wsUrl = `${MIDDLEWARE_URL}/api/agent/client/ws`;
2325
- let ws;
2326
- try {
2327
- ws = new WebSocket(wsUrl, {
2328
- headers: {
2329
- "X-API-Key": this.config.apiKey
2330
- }
2331
- });
2332
- } catch (err) {
2333
- emit({
2334
- type: "error" /* ERROR */,
2335
- message: `Failed to create WebSocket: ${err}`
2336
- });
2337
- resolve2(null);
2338
- return;
2339
- }
2340
- this.activeWS = ws;
2341
2425
  let uploadBaseUrl;
2342
2426
  let resolved = false;
2343
2427
  const finish = (result) => {
2344
2428
  if (resolved) return;
2345
2429
  resolved = true;
2346
- this.activeWS = null;
2430
+ this.activeConnection = null;
2347
2431
  resolve2(result);
2348
2432
  };
2349
- ws.onopen = () => {
2433
+ let conn;
2434
+ try {
2435
+ conn = new InvestigationConnection(
2436
+ wsUrl,
2437
+ this.config.apiKey,
2438
+ (msg) => this.handleMessage(msg, conn, emit, isCancelled, finish, () => uploadBaseUrl, (url) => {
2439
+ uploadBaseUrl = url;
2440
+ }),
2441
+ (message) => {
2442
+ if (!isCancelled()) emit({ type: "error" /* ERROR */, message });
2443
+ finish(null);
2444
+ },
2445
+ () => {
2446
+ if (!resolved) {
2447
+ if (isCancelled()) {
2448
+ finish(null);
2449
+ } else {
2450
+ emit({ type: "error" /* ERROR */, message: "WebSocket connection closed unexpectedly" });
2451
+ finish(null);
2452
+ }
2453
+ }
2454
+ }
2455
+ );
2456
+ } catch (err) {
2457
+ emit({ type: "error" /* ERROR */, message: `Failed to create WebSocket: ${err}` });
2458
+ resolve2(null);
2459
+ return;
2460
+ }
2461
+ this.activeConnection = conn;
2462
+ conn.onopen = () => {
2350
2463
  const toolDeclarations = this.registry.allDeclarations().map((decl) => ({
2351
2464
  name: decl.name,
2352
2465
  description: decl.description,
@@ -2365,206 +2478,99 @@ var PRBEAgent = class _PRBEAgent {
2365
2478
  os_version: os2.release(),
2366
2479
  arch: os2.arch()
2367
2480
  };
2368
- if (contextRequestID) {
2369
- startMetadata["context_request_id"] = contextRequestID;
2370
- }
2371
- if (ticketId) {
2372
- startMetadata["ticket_id"] = ticketId;
2373
- }
2374
- if (this.appDataPath) {
2375
- startMetadata["app_data_path"] = this.appDataPath;
2376
- }
2377
- const startMsg = {
2378
- type: "start" /* START */,
2379
- content: query,
2380
- metadata: startMetadata
2381
- };
2382
- try {
2383
- ws.send(JSON.stringify(startMsg));
2384
- } catch (err) {
2385
- emit({
2386
- type: "error" /* ERROR */,
2387
- message: `Failed to send start message: ${err}`
2388
- });
2481
+ if (contextRequestID) startMetadata["context_request_id"] = contextRequestID;
2482
+ if (ticketId) startMetadata["ticket_id"] = ticketId;
2483
+ if (this.appDataPath) startMetadata["app_data_path"] = this.appDataPath;
2484
+ if (!conn.send({ type: "start" /* START */, content: query, metadata: startMetadata })) {
2485
+ emit({ type: "error" /* ERROR */, message: "Failed to send start message" });
2389
2486
  finish(null);
2390
2487
  return;
2391
2488
  }
2392
2489
  emit({ type: "started" /* STARTED */ });
2393
2490
  this.pendingFlaggedFiles = [];
2394
2491
  };
2395
- ws.onmessage = async (event) => {
2396
- if (isCancelled()) {
2397
- this.sendCancel(ws);
2398
- ws.close(1e3, "Cancelled");
2399
- finish(null);
2400
- return;
2401
- }
2402
- let raw;
2403
- if (typeof event.data === "string") {
2404
- raw = event.data;
2405
- } else if (event.data instanceof Buffer) {
2406
- raw = event.data.toString("utf-8");
2407
- } else {
2408
- return;
2409
- }
2410
- let msg;
2411
- try {
2412
- msg = JSON.parse(raw);
2413
- } catch {
2414
- return;
2415
- }
2416
- switch (msg.type) {
2417
- case "thought" /* THOUGHT */:
2418
- emit({
2419
- type: "thought" /* THOUGHT */,
2420
- text: msg.content ?? ""
2421
- });
2422
- break;
2423
- case "tool_call" /* TOOL_CALL */: {
2424
- const toolName = msg.name ?? "";
2425
- const callId = msg.id ?? "";
2426
- const args = this.extractArgs(msg.metadata);
2427
- emit({
2428
- type: "tool_call" /* TOOL_CALL */,
2429
- name: toolName,
2430
- label: msg.content ?? `Running ${toolName}`
2431
- });
2432
- this.pendingFlaggedFiles = [];
2433
- const toolResult = redactPII(
2434
- await this.registry.execute(toolName, args)
2435
- );
2436
- emit({
2437
- type: "observation" /* OBSERVATION */,
2438
- text: toolResult.substring(0, 200)
2439
- });
2440
- let resultMetadata;
2441
- if (this.pendingFlaggedFiles.length > 0 && uploadBaseUrl) {
2442
- const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
2443
- const uploadedRefs = [];
2444
- for (const file of this.pendingFlaggedFiles) {
2445
- const filename = path5.basename(file.originalPath);
2446
- const safeName = encodeURIComponent(filename);
2447
- const storagePath = `${uploadPrefix}/${safeName}`;
2448
- uploadedRefs.push({
2449
- original_path: file.originalPath,
2450
- reason: file.reason ?? "",
2451
- storage_path: storagePath,
2452
- file_size_bytes: file.data.length
2453
- });
2454
- const uploadUrl = `${uploadBaseUrl}/${safeName}`;
2455
- const fileData = file.data;
2456
- const contentType = file.isText ? "text/plain" : "application/octet-stream";
2457
- void _PRBEAgent.backgroundUpload(
2458
- fileData,
2459
- uploadUrl,
2460
- this.config.apiKey,
2461
- contentType,
2462
- this.getFetchSignal()
2463
- );
2464
- }
2465
- resultMetadata = { flagged_files: uploadedRefs };
2466
- this.pendingFlaggedFiles = [];
2467
- }
2468
- const resultMsg = {
2469
- type: "tool_result" /* TOOL_RESULT */,
2470
- id: callId,
2471
- name: toolName,
2472
- content: toolResult,
2473
- metadata: resultMetadata
2474
- };
2475
- try {
2476
- ws.send(JSON.stringify(resultMsg));
2477
- } catch {
2478
- }
2479
- break;
2480
- }
2481
- case "server_tool_call" /* SERVER_TOOL_CALL */:
2482
- emit({
2483
- type: "tool_call" /* TOOL_CALL */,
2484
- name: msg.name ?? "",
2485
- label: msg.content ?? ""
2486
- });
2487
- break;
2488
- case "server_observation" /* SERVER_OBSERVATION */:
2489
- emit({
2490
- type: "observation" /* OBSERVATION */,
2491
- text: (msg.content ?? "").substring(0, 200)
2492
- });
2493
- break;
2494
- case "complete" /* COMPLETE */: {
2495
- const report = msg.content ?? "";
2496
- const userSummary = msg.metadata?.["user_summary"] ?? "";
2497
- const ticketId2 = msg.metadata?.["ticket_id"];
2498
- const sessionId = msg.metadata?.["session_id"];
2499
- emit({
2500
- type: "completed" /* COMPLETED */,
2501
- report,
2502
- userSummary,
2503
- ticketId: ticketId2
2504
- });
2505
- ws.close(1e3, "Complete");
2506
- finish({ report, userSummary, ticketId: ticketId2, sessionId });
2507
- break;
2508
- }
2509
- case "error" /* ERROR */:
2510
- emit({
2511
- type: "error" /* ERROR */,
2512
- message: msg.content || "Unknown error"
2492
+ });
2493
+ }
2494
+ async handleMessage(msg, conn, emit, isCancelled, finish, getUploadBaseUrl, setUploadBaseUrl) {
2495
+ if (isCancelled()) {
2496
+ conn.sendCancel();
2497
+ conn.close(1e3, "Cancelled");
2498
+ finish(null);
2499
+ return;
2500
+ }
2501
+ switch (msg.type) {
2502
+ case "thought" /* THOUGHT */:
2503
+ emit({ type: "thought" /* THOUGHT */, text: msg.content ?? "" });
2504
+ break;
2505
+ case "tool_call" /* TOOL_CALL */: {
2506
+ const toolName = msg.name ?? "";
2507
+ const callId = msg.id ?? "";
2508
+ const args = this.extractArgs(msg.metadata);
2509
+ emit({ type: "tool_call" /* TOOL_CALL */, name: toolName, label: msg.content ?? `Running ${toolName}` });
2510
+ this.pendingFlaggedFiles = [];
2511
+ const toolResult = redactPII(await this.registry.execute(toolName, args));
2512
+ emit({ type: "observation" /* OBSERVATION */, text: toolResult.substring(0, 200) });
2513
+ let resultMetadata;
2514
+ const uploadBaseUrl = getUploadBaseUrl();
2515
+ if (this.pendingFlaggedFiles.length > 0 && uploadBaseUrl) {
2516
+ const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
2517
+ const uploadedRefs = [];
2518
+ for (const file of this.pendingFlaggedFiles) {
2519
+ const filename = path5.basename(file.originalPath);
2520
+ const safeName = encodeURIComponent(filename);
2521
+ const storagePath = `${uploadPrefix}/${safeName}`;
2522
+ uploadedRefs.push({
2523
+ original_path: file.originalPath,
2524
+ reason: file.reason ?? "",
2525
+ storage_path: storagePath,
2526
+ file_size_bytes: file.data.length
2513
2527
  });
2514
- ws.close(1e3, "Error received");
2515
- finish(null);
2516
- break;
2517
- case "session_config" /* SESSION_CONFIG */:
2518
- uploadBaseUrl = msg.metadata?.["upload_url"];
2519
- break;
2520
- case "ping" /* PING */: {
2521
- const pongMsg = { type: "pong" /* PONG */ };
2522
- try {
2523
- ws.send(JSON.stringify(pongMsg));
2524
- } catch {
2525
- }
2526
- break;
2528
+ const uploadUrl = `${uploadBaseUrl}/${safeName}`;
2529
+ const contentType = file.isText ? "text/plain" : "application/octet-stream";
2530
+ void _PRBEAgent.backgroundUpload(file.data, uploadUrl, this.config.apiKey, contentType, this.getFetchSignal());
2527
2531
  }
2528
- // SDK-originated types and upload_url — ignore
2529
- case "start" /* START */:
2530
- case "tool_result" /* TOOL_RESULT */:
2531
- case "upload_request" /* UPLOAD_REQUEST */:
2532
- case "cancel" /* CANCEL */:
2533
- case "pong" /* PONG */:
2534
- case "upload_url" /* UPLOAD_URL */:
2535
- break;
2532
+ resultMetadata = { flagged_files: uploadedRefs };
2533
+ this.pendingFlaggedFiles = [];
2536
2534
  }
2537
- };
2538
- ws.onerror = (event) => {
2539
- if (isCancelled()) {
2540
- finish(null);
2541
- return;
2542
- }
2543
- const errorEvent = event;
2544
- const message = errorEvent.message || "WebSocket connection error";
2545
- emit({ type: "error" /* ERROR */, message });
2535
+ conn.sendToolResult(callId, toolName, toolResult, resultMetadata);
2536
+ break;
2537
+ }
2538
+ case "server_tool_call" /* SERVER_TOOL_CALL */:
2539
+ emit({ type: "tool_call" /* TOOL_CALL */, name: msg.name ?? "", label: msg.content ?? "" });
2540
+ break;
2541
+ case "server_observation" /* SERVER_OBSERVATION */:
2542
+ emit({ type: "observation" /* OBSERVATION */, text: (msg.content ?? "").substring(0, 200) });
2543
+ break;
2544
+ case "complete" /* COMPLETE */: {
2545
+ const report = msg.content ?? "";
2546
+ const completedTicketId = msg.metadata?.["ticket_id"];
2547
+ const sessionId = msg.metadata?.["session_id"];
2548
+ emit({ type: "completed" /* COMPLETED */, report, ticketId: completedTicketId });
2549
+ conn.close(1e3, "Complete");
2550
+ finish({ report, ticketId: completedTicketId, sessionId });
2551
+ break;
2552
+ }
2553
+ case "error" /* ERROR */:
2554
+ emit({ type: "error" /* ERROR */, message: msg.content || "Unknown error" });
2555
+ conn.close(1e3, "Error received");
2546
2556
  finish(null);
2547
- };
2548
- ws.onclose = (_event) => {
2549
- if (!resolved) {
2550
- if (isCancelled()) {
2551
- finish(null);
2552
- } else {
2553
- emit({
2554
- type: "error" /* ERROR */,
2555
- message: "WebSocket connection closed unexpectedly"
2556
- });
2557
- finish(null);
2558
- }
2557
+ break;
2558
+ case "session_config" /* SESSION_CONFIG */:
2559
+ setUploadBaseUrl(msg.metadata?.["upload_url"]);
2560
+ break;
2561
+ case "conversation_update" /* CONVERSATION_UPDATE */: {
2562
+ try {
2563
+ const entry = JSON.parse(msg.content ?? "{}");
2564
+ this.state.appendConversation(entry);
2565
+ } catch {
2559
2566
  }
2560
- };
2561
- });
2562
- }
2563
- sendCancel(ws) {
2564
- try {
2565
- const cancelMsg = { type: "cancel" /* CANCEL */ };
2566
- ws.send(JSON.stringify(cancelMsg));
2567
- } catch {
2567
+ break;
2568
+ }
2569
+ case "ping" /* PING */:
2570
+ conn.sendPong();
2571
+ break;
2572
+ default:
2573
+ break;
2568
2574
  }
2569
2575
  }
2570
2576
  extractArgs(metadata) {
@@ -2682,6 +2688,7 @@ var DEFAULT_PRBE_STATE = {
2682
2688
  summary: "",
2683
2689
  currentQuery: "",
2684
2690
  resolvedInteractions: [],
2691
+ conversationHistory: [],
2685
2692
  completedInvestigations: [],
2686
2693
  activeCRs: [],
2687
2694
  completedCRs: [],
@@ -2719,6 +2726,7 @@ function serializePRBEState(state) {
2719
2726
  pendingInteraction: state.pendingInteraction,
2720
2727
  resolvedInteractions: state.resolvedInteractions,
2721
2728
  agentMessage: state.agentMessage,
2729
+ conversationHistory: state.conversationHistory,
2722
2730
  completedInvestigations: state.completedInvestigations.map((inv) => ({
2723
2731
  id: inv.id,
2724
2732
  query: inv.query,
@@ -2727,6 +2735,7 @@ function serializePRBEState(state) {
2727
2735
  ticketId: inv.ticketId,
2728
2736
  events: inv.events,
2729
2737
  resolvedInteractions: inv.resolvedInteractions,
2738
+ conversationHistory: inv.conversationHistory,
2730
2739
  completedAt: inv.completedAt.toISOString()
2731
2740
  })),
2732
2741
  activeCRs: Array.from(state.activeCRs.values()).map(serializeCR),
@@ -2749,6 +2758,7 @@ var PROBE_MARK_SVG = `<svg width="256" height="256" viewBox="0 0 256 256" fill="
2749
2758
  AskUserTool,
2750
2759
  BashExecuteTool,
2751
2760
  ClearAppLogsTool,
2761
+ ConversationRole,
2752
2762
  DEFAULT_PRBE_STATE,
2753
2763
  FindFilesTool,
2754
2764
  FlagAppLogsTool,