@prbe.ai/electron-sdk 0.1.13 → 0.1.15

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.mjs CHANGED
@@ -9,6 +9,7 @@ var WSMessageType = /* @__PURE__ */ ((WSMessageType2) => {
9
9
  WSMessageType2["START"] = "start";
10
10
  WSMessageType2["TOOL_RESULT"] = "tool_result";
11
11
  WSMessageType2["UPLOAD_REQUEST"] = "upload_request";
12
+ WSMessageType2["CONVERSATION_MESSAGE"] = "conversation_message";
12
13
  WSMessageType2["CANCEL"] = "cancel";
13
14
  WSMessageType2["PONG"] = "pong";
14
15
  WSMessageType2["THOUGHT"] = "thought";
@@ -17,11 +18,17 @@ var WSMessageType = /* @__PURE__ */ ((WSMessageType2) => {
17
18
  WSMessageType2["SERVER_OBSERVATION"] = "server_observation";
18
19
  WSMessageType2["UPLOAD_URL"] = "upload_url";
19
20
  WSMessageType2["SESSION_CONFIG"] = "session_config";
21
+ WSMessageType2["CONVERSATION_UPDATE"] = "conversation_update";
20
22
  WSMessageType2["COMPLETE"] = "complete";
21
23
  WSMessageType2["ERROR"] = "error";
22
24
  WSMessageType2["PING"] = "ping";
23
25
  return WSMessageType2;
24
26
  })(WSMessageType || {});
27
+ var ConversationRole = /* @__PURE__ */ ((ConversationRole3) => {
28
+ ConversationRole3["User"] = "user";
29
+ ConversationRole3["Agent"] = "agent";
30
+ return ConversationRole3;
31
+ })(ConversationRole || {});
25
32
  var ToolParamType = /* @__PURE__ */ ((ToolParamType2) => {
26
33
  ToolParamType2["STRING"] = "STRING";
27
34
  ToolParamType2["BOOLEAN"] = "BOOLEAN";
@@ -55,6 +62,7 @@ var PRBEAgentConfigKey = /* @__PURE__ */ ((PRBEAgentConfigKey3) => {
55
62
  PRBEAgentConfigKey3["IPC_MAIN"] = "ipcMain";
56
63
  PRBEAgentConfigKey3["RENDERER_LOG_CHANNEL"] = "rendererLogChannel";
57
64
  PRBEAgentConfigKey3["APP_DATA_PATH"] = "appDataPath";
65
+ PRBEAgentConfigKey3["SESSION_METADATA"] = "sessionMetadata";
58
66
  return PRBEAgentConfigKey3;
59
67
  })(PRBEAgentConfigKey || {});
60
68
  var PRBEAgentStatusType = /* @__PURE__ */ ((PRBEAgentStatusType2) => {
@@ -91,6 +99,83 @@ function redactPII(text) {
91
99
  var API_URL = "https://api.prbe.ai";
92
100
  var MIDDLEWARE_URL = "wss://middleware.prbe.ai";
93
101
 
102
+ // src/connection.ts
103
+ var InvestigationConnection = class {
104
+ constructor(url, apiKey, onMessage, onError, onClose) {
105
+ this.onMessage = onMessage;
106
+ this.onError = onError;
107
+ this.onClose = onClose;
108
+ this.ws = new WebSocket(url, {
109
+ headers: { "X-API-Key": apiKey }
110
+ });
111
+ this.ws.onmessage = (event) => {
112
+ const raw = typeof event.data === "string" ? event.data : event.data instanceof Buffer ? event.data.toString("utf-8") : null;
113
+ if (!raw) return;
114
+ try {
115
+ const msg = JSON.parse(raw);
116
+ this.onMessage(msg);
117
+ } catch {
118
+ }
119
+ };
120
+ this.ws.onerror = (event) => {
121
+ const errorEvent = event;
122
+ this.onError(errorEvent.message || "WebSocket connection error");
123
+ };
124
+ this.ws.onclose = () => {
125
+ this.onClose();
126
+ };
127
+ }
128
+ ws;
129
+ closed = false;
130
+ get isOpen() {
131
+ return !this.closed && this.ws.readyState === WebSocket.OPEN;
132
+ }
133
+ send(msg) {
134
+ if (!this.isOpen) return false;
135
+ try {
136
+ this.ws.send(JSON.stringify(msg));
137
+ return true;
138
+ } catch {
139
+ return false;
140
+ }
141
+ }
142
+ sendConversationMessage(content) {
143
+ this.send({
144
+ type: "conversation_message" /* CONVERSATION_MESSAGE */,
145
+ content
146
+ });
147
+ }
148
+ sendToolResult(callId, toolName, result, metadata) {
149
+ this.send({
150
+ type: "tool_result" /* TOOL_RESULT */,
151
+ id: callId,
152
+ name: toolName,
153
+ content: result,
154
+ metadata
155
+ });
156
+ }
157
+ sendCancel() {
158
+ this.send({ type: "cancel" /* CANCEL */ });
159
+ }
160
+ sendPong() {
161
+ this.send({ type: "pong" /* PONG */ });
162
+ }
163
+ close(code = 1e3, reason) {
164
+ if (this.closed) return;
165
+ this.closed = true;
166
+ try {
167
+ this.ws.close(code, reason);
168
+ } catch {
169
+ }
170
+ }
171
+ /**
172
+ * Set the onopen handler. Called when the connection is ready to send messages.
173
+ */
174
+ set onopen(handler) {
175
+ this.ws.onopen = handler;
176
+ }
177
+ };
178
+
94
179
  // src/state.ts
95
180
  import { EventEmitter } from "events";
96
181
  import { randomUUID } from "crypto";
@@ -119,6 +204,7 @@ var PRBEAgentState = class extends EventEmitter {
119
204
  pendingInteraction;
120
205
  resolvedInteractions = [];
121
206
  agentMessage;
207
+ conversationHistory = [];
122
208
  // Completed user investigations (history)
123
209
  completedInvestigations = [];
124
210
  // Background context requests
@@ -142,6 +228,7 @@ var PRBEAgentState = class extends EventEmitter {
142
228
  this.isInvestigating = true;
143
229
  this.events = [];
144
230
  this.resolvedInteractions = [];
231
+ this.conversationHistory = [];
145
232
  this.report = "";
146
233
  this.summary = "";
147
234
  this.currentQuery = query;
@@ -149,10 +236,15 @@ var PRBEAgentState = class extends EventEmitter {
149
236
  this.agentMessage = void 0;
150
237
  this.emit("status" /* STATUS */);
151
238
  }
239
+ appendConversation(entry) {
240
+ this.conversationHistory.push(entry);
241
+ this.emit("status" /* STATUS */);
242
+ }
152
243
  resetInvestigation() {
153
244
  this.isInvestigating = false;
154
245
  this.events = [];
155
246
  this.resolvedInteractions = [];
247
+ this.conversationHistory = [];
156
248
  this.report = "";
157
249
  this.summary = "";
158
250
  this.currentQuery = "";
@@ -185,7 +277,7 @@ var PRBEAgentState = class extends EventEmitter {
185
277
  this.emit("status" /* STATUS */);
186
278
  }
187
279
  }
188
- completeInvestigation(report, summary, ticketId) {
280
+ completeInvestigation(report, ticketId) {
189
281
  if (this.events.length > 0) {
190
282
  this.events[this.events.length - 1].isCompleted = true;
191
283
  }
@@ -194,16 +286,15 @@ var PRBEAgentState = class extends EventEmitter {
194
286
  id: randomUUID(),
195
287
  query: this.currentQuery,
196
288
  report,
197
- summary,
198
289
  ticketId,
199
290
  events: [...this.events],
200
291
  resolvedInteractions: [...this.resolvedInteractions],
292
+ conversationHistory: [...this.conversationHistory],
201
293
  completedAt: /* @__PURE__ */ new Date()
202
294
  });
203
295
  this.report = report;
204
- this.summary = summary;
205
296
  this.isInvestigating = false;
206
- this.emit("complete" /* COMPLETE */, { report, summary });
297
+ this.emit("complete" /* COMPLETE */, { report });
207
298
  this.emit("status" /* STATUS */);
208
299
  }
209
300
  failInvestigation(message) {
@@ -328,7 +419,7 @@ var PRBEAgentState = class extends EventEmitter {
328
419
  cr.events[cr.events.length - 1].detail = text;
329
420
  this.emit("status" /* STATUS */);
330
421
  }
331
- completeCR(id, report, summary) {
422
+ completeCR(id, report) {
332
423
  const cr = this.activeCRs.get(id);
333
424
  if (!cr) return;
334
425
  this.activeCRs.delete(id);
@@ -344,7 +435,6 @@ var PRBEAgentState = class extends EventEmitter {
344
435
  cr.isRunning = false;
345
436
  cr.isCompleted = true;
346
437
  cr.report = report;
347
- cr.summary = summary;
348
438
  this.completedCRs.unshift(cr);
349
439
  this.emit("cr-complete" /* CR_COMPLETE */, cr);
350
440
  this.emit("status" /* STATUS */);
@@ -1281,9 +1371,9 @@ var AskUserTool = class {
1281
1371
  required: true
1282
1372
  },
1283
1373
  {
1284
- name: "context",
1374
+ name: "reason",
1285
1375
  type: "STRING" /* STRING */,
1286
- description: "Optional context explaining why you need this information",
1376
+ description: "Short reason displayed alongside the input prompt explaining why you need this information",
1287
1377
  required: false
1288
1378
  }
1289
1379
  ]
@@ -1295,12 +1385,11 @@ var AskUserTool = class {
1295
1385
  if (this.requester.investigationSource !== "user" /* USER */) {
1296
1386
  return "This is a context request investigation \u2014 you cannot ask the user questions. Use the available tools to answer the query autonomously.";
1297
1387
  }
1298
- const context = args["context"];
1388
+ const reason = args["reason"] ?? "Waiting for your response";
1299
1389
  const response = await this.requester.requestUserInteraction({
1300
1390
  type: "ask_question" /* ASK_QUESTION */,
1301
1391
  interactionId: randomUUID3(),
1302
- question,
1303
- context
1392
+ question: reason
1304
1393
  });
1305
1394
  const askResponse = response;
1306
1395
  return askResponse.answer;
@@ -1721,6 +1810,7 @@ var HistoryStore = class {
1721
1810
  ticketId: inv.ticketId,
1722
1811
  events: inv.events,
1723
1812
  resolvedInteractions: inv.resolvedInteractions,
1813
+ conversationHistory: inv.conversationHistory,
1724
1814
  completedAt: inv.completedAt.toISOString()
1725
1815
  };
1726
1816
  fs2.writeFileSync(
@@ -1809,11 +1899,12 @@ var PRBEAgent = class _PRBEAgent {
1809
1899
  logCapture;
1810
1900
  config;
1811
1901
  appDataPath;
1902
+ sessionMetadata;
1812
1903
  interactionHandler;
1813
1904
  registry = new PRBEToolRegistry();
1814
1905
  grantedPaths = /* @__PURE__ */ new Set();
1815
1906
  userCancelled = false;
1816
- activeWS = null;
1907
+ activeConnection = null;
1817
1908
  pollingTimer = null;
1818
1909
  persistedData;
1819
1910
  fetchAbortController = null;
@@ -1868,6 +1959,7 @@ var PRBEAgent = class _PRBEAgent {
1868
1959
  };
1869
1960
  this.interactionHandler = config.interactionHandler;
1870
1961
  this.appDataPath = config.appDataPath;
1962
+ this.sessionMetadata = config.sessionMetadata ?? {};
1871
1963
  if (this.appDataPath && !this.config.autoApprovedDirs.includes(this.appDataPath)) {
1872
1964
  this.config.autoApprovedDirs.push(this.appDataPath);
1873
1965
  }
@@ -1973,6 +2065,9 @@ var PRBEAgent = class _PRBEAgent {
1973
2065
  get investigationSource() {
1974
2066
  return this.currentInvestigationSource;
1975
2067
  }
2068
+ sendConversationMessage(content) {
2069
+ this.activeConnection?.sendConversationMessage(content);
2070
+ }
1976
2071
  async requestUserInteraction(payload) {
1977
2072
  if (!this.interactionHandler) {
1978
2073
  throw new PRBEAgentError(
@@ -1992,6 +2087,13 @@ var PRBEAgent = class _PRBEAgent {
1992
2087
  } else {
1993
2088
  this.state.resolveInteraction(response);
1994
2089
  }
2090
+ if (response.type === "request_permission" /* REQUEST_PERMISSION */) {
2091
+ const approved = response.approved;
2092
+ this.sendConversationMessage(approved ? "Approved" : "Denied");
2093
+ } else if (response.type === "request_path_access" /* REQUEST_PATH_ACCESS */) {
2094
+ const granted = response.granted;
2095
+ this.sendConversationMessage(granted ? "Allowed" : "Denied");
2096
+ }
1995
2097
  return response;
1996
2098
  } catch (err) {
1997
2099
  if (this.currentInvestigationSource === "context_request" /* CONTEXT_REQUEST */ && this.currentCRId) {
@@ -2011,6 +2113,13 @@ var PRBEAgent = class _PRBEAgent {
2011
2113
  }
2012
2114
  }
2013
2115
  // ---------- Public API ----------
2116
+ /**
2117
+ * Update session metadata. Merged with existing metadata.
2118
+ * Call this to add user profile data, app version, etc. after async initialization.
2119
+ */
2120
+ updateSessionMetadata(metadata) {
2121
+ this.sessionMetadata = { ...this.sessionMetadata, ...metadata };
2122
+ }
2014
2123
  /**
2015
2124
  * Register a custom tool that the middleware can invoke during investigations.
2016
2125
  */
@@ -2044,7 +2153,7 @@ var PRBEAgent = class _PRBEAgent {
2044
2153
  this.state.appendEvent("Thinking", status.text);
2045
2154
  break;
2046
2155
  case "completed" /* COMPLETED */:
2047
- this.state.completeInvestigation(status.report, status.userSummary, status.ticketId);
2156
+ this.state.completeInvestigation(status.report, status.ticketId);
2048
2157
  this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2049
2158
  break;
2050
2159
  case "error" /* ERROR */:
@@ -2074,9 +2183,9 @@ var PRBEAgent = class _PRBEAgent {
2074
2183
  */
2075
2184
  cancelInvestigation() {
2076
2185
  this.userCancelled = true;
2077
- if (this.activeWS) {
2078
- this.activeWS.close(1e3, "User cancelled");
2079
- this.activeWS = null;
2186
+ if (this.activeConnection) {
2187
+ this.activeConnection.close(1e3, "User cancelled");
2188
+ this.activeConnection = null;
2080
2189
  }
2081
2190
  }
2082
2191
  /**
@@ -2084,9 +2193,9 @@ var PRBEAgent = class _PRBEAgent {
2084
2193
  */
2085
2194
  cancel() {
2086
2195
  this.userCancelled = true;
2087
- if (this.activeWS) {
2088
- this.activeWS.close(1e3, "User cancelled");
2089
- this.activeWS = null;
2196
+ if (this.activeConnection) {
2197
+ this.activeConnection.close(1e3, "User cancelled");
2198
+ this.activeConnection = null;
2090
2199
  }
2091
2200
  this.abortInFlightRequests();
2092
2201
  this.stopPolling();
@@ -2225,7 +2334,7 @@ var PRBEAgent = class _PRBEAgent {
2225
2334
  this.state.appendCREvent(crID, "Thinking", status.text);
2226
2335
  break;
2227
2336
  case "completed" /* COMPLETED */:
2228
- this.state.completeCR(crID, status.report, status.userSummary);
2337
+ this.state.completeCR(crID, status.report);
2229
2338
  this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2230
2339
  break;
2231
2340
  case "error" /* ERROR */:
@@ -2252,31 +2361,44 @@ var PRBEAgent = class _PRBEAgent {
2252
2361
  connectToProxy(query, contextRequestID, emit, isCancelled, ticketId) {
2253
2362
  return new Promise((resolve2) => {
2254
2363
  const wsUrl = `${MIDDLEWARE_URL}/api/agent/client/ws`;
2255
- let ws;
2256
- try {
2257
- ws = new WebSocket(wsUrl, {
2258
- headers: {
2259
- "X-API-Key": this.config.apiKey
2260
- }
2261
- });
2262
- } catch (err) {
2263
- emit({
2264
- type: "error" /* ERROR */,
2265
- message: `Failed to create WebSocket: ${err}`
2266
- });
2267
- resolve2(null);
2268
- return;
2269
- }
2270
- this.activeWS = ws;
2271
2364
  let uploadBaseUrl;
2272
2365
  let resolved = false;
2273
2366
  const finish = (result) => {
2274
2367
  if (resolved) return;
2275
2368
  resolved = true;
2276
- this.activeWS = null;
2369
+ this.activeConnection = null;
2277
2370
  resolve2(result);
2278
2371
  };
2279
- ws.onopen = () => {
2372
+ let conn;
2373
+ try {
2374
+ conn = new InvestigationConnection(
2375
+ wsUrl,
2376
+ this.config.apiKey,
2377
+ (msg) => this.handleMessage(msg, conn, emit, isCancelled, finish, () => uploadBaseUrl, (url) => {
2378
+ uploadBaseUrl = url;
2379
+ }),
2380
+ (message) => {
2381
+ if (!isCancelled()) emit({ type: "error" /* ERROR */, message });
2382
+ finish(null);
2383
+ },
2384
+ () => {
2385
+ if (!resolved) {
2386
+ if (isCancelled()) {
2387
+ finish(null);
2388
+ } else {
2389
+ emit({ type: "error" /* ERROR */, message: "WebSocket connection closed unexpectedly" });
2390
+ finish(null);
2391
+ }
2392
+ }
2393
+ }
2394
+ );
2395
+ } catch (err) {
2396
+ emit({ type: "error" /* ERROR */, message: `Failed to create WebSocket: ${err}` });
2397
+ resolve2(null);
2398
+ return;
2399
+ }
2400
+ this.activeConnection = conn;
2401
+ conn.onopen = () => {
2280
2402
  const toolDeclarations = this.registry.allDeclarations().map((decl) => ({
2281
2403
  name: decl.name,
2282
2404
  description: decl.description,
@@ -2295,206 +2417,102 @@ var PRBEAgent = class _PRBEAgent {
2295
2417
  os_version: os2.release(),
2296
2418
  arch: os2.arch()
2297
2419
  };
2298
- if (contextRequestID) {
2299
- startMetadata["context_request_id"] = contextRequestID;
2300
- }
2301
- if (ticketId) {
2302
- startMetadata["ticket_id"] = ticketId;
2420
+ if (contextRequestID) startMetadata["context_request_id"] = contextRequestID;
2421
+ if (ticketId) startMetadata["ticket_id"] = ticketId;
2422
+ if (this.appDataPath) startMetadata["app_data_path"] = this.appDataPath;
2423
+ if (Object.keys(this.sessionMetadata).length > 0) {
2424
+ startMetadata["session_metadata"] = this.sessionMetadata;
2303
2425
  }
2304
- if (this.appDataPath) {
2305
- startMetadata["app_data_path"] = this.appDataPath;
2306
- }
2307
- const startMsg = {
2308
- type: "start" /* START */,
2309
- content: query,
2310
- metadata: startMetadata
2311
- };
2312
- try {
2313
- ws.send(JSON.stringify(startMsg));
2314
- } catch (err) {
2315
- emit({
2316
- type: "error" /* ERROR */,
2317
- message: `Failed to send start message: ${err}`
2318
- });
2426
+ if (!conn.send({ type: "start" /* START */, content: query, metadata: startMetadata })) {
2427
+ emit({ type: "error" /* ERROR */, message: "Failed to send start message" });
2319
2428
  finish(null);
2320
2429
  return;
2321
2430
  }
2322
2431
  emit({ type: "started" /* STARTED */ });
2323
2432
  this.pendingFlaggedFiles = [];
2324
2433
  };
2325
- ws.onmessage = async (event) => {
2326
- if (isCancelled()) {
2327
- this.sendCancel(ws);
2328
- ws.close(1e3, "Cancelled");
2329
- finish(null);
2330
- return;
2331
- }
2332
- let raw;
2333
- if (typeof event.data === "string") {
2334
- raw = event.data;
2335
- } else if (event.data instanceof Buffer) {
2336
- raw = event.data.toString("utf-8");
2337
- } else {
2338
- return;
2339
- }
2340
- let msg;
2341
- try {
2342
- msg = JSON.parse(raw);
2343
- } catch {
2344
- return;
2345
- }
2346
- switch (msg.type) {
2347
- case "thought" /* THOUGHT */:
2348
- emit({
2349
- type: "thought" /* THOUGHT */,
2350
- text: msg.content ?? ""
2351
- });
2352
- break;
2353
- case "tool_call" /* TOOL_CALL */: {
2354
- const toolName = msg.name ?? "";
2355
- const callId = msg.id ?? "";
2356
- const args = this.extractArgs(msg.metadata);
2357
- emit({
2358
- type: "tool_call" /* TOOL_CALL */,
2359
- name: toolName,
2360
- label: msg.content ?? `Running ${toolName}`
2361
- });
2362
- this.pendingFlaggedFiles = [];
2363
- const toolResult = redactPII(
2364
- await this.registry.execute(toolName, args)
2365
- );
2366
- emit({
2367
- type: "observation" /* OBSERVATION */,
2368
- text: toolResult.substring(0, 200)
2369
- });
2370
- let resultMetadata;
2371
- if (this.pendingFlaggedFiles.length > 0 && uploadBaseUrl) {
2372
- const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
2373
- const uploadedRefs = [];
2374
- for (const file of this.pendingFlaggedFiles) {
2375
- const filename = path5.basename(file.originalPath);
2376
- const safeName = encodeURIComponent(filename);
2377
- const storagePath = `${uploadPrefix}/${safeName}`;
2378
- uploadedRefs.push({
2379
- original_path: file.originalPath,
2380
- reason: file.reason ?? "",
2381
- storage_path: storagePath,
2382
- file_size_bytes: file.data.length
2383
- });
2384
- const uploadUrl = `${uploadBaseUrl}/${safeName}`;
2385
- const fileData = file.data;
2386
- const contentType = file.isText ? "text/plain" : "application/octet-stream";
2387
- void _PRBEAgent.backgroundUpload(
2388
- fileData,
2389
- uploadUrl,
2390
- this.config.apiKey,
2391
- contentType,
2392
- this.getFetchSignal()
2393
- );
2394
- }
2395
- resultMetadata = { flagged_files: uploadedRefs };
2396
- this.pendingFlaggedFiles = [];
2397
- }
2398
- const resultMsg = {
2399
- type: "tool_result" /* TOOL_RESULT */,
2400
- id: callId,
2401
- name: toolName,
2402
- content: toolResult,
2403
- metadata: resultMetadata
2404
- };
2405
- try {
2406
- ws.send(JSON.stringify(resultMsg));
2407
- } catch {
2408
- }
2409
- break;
2410
- }
2411
- case "server_tool_call" /* SERVER_TOOL_CALL */:
2412
- emit({
2413
- type: "tool_call" /* TOOL_CALL */,
2414
- name: msg.name ?? "",
2415
- label: msg.content ?? ""
2416
- });
2417
- break;
2418
- case "server_observation" /* SERVER_OBSERVATION */:
2419
- emit({
2420
- type: "observation" /* OBSERVATION */,
2421
- text: (msg.content ?? "").substring(0, 200)
2422
- });
2423
- break;
2424
- case "complete" /* COMPLETE */: {
2425
- const report = msg.content ?? "";
2426
- const userSummary = msg.metadata?.["user_summary"] ?? "";
2427
- const ticketId2 = msg.metadata?.["ticket_id"];
2428
- const sessionId = msg.metadata?.["session_id"];
2429
- emit({
2430
- type: "completed" /* COMPLETED */,
2431
- report,
2432
- userSummary,
2433
- ticketId: ticketId2
2434
- });
2435
- ws.close(1e3, "Complete");
2436
- finish({ report, userSummary, ticketId: ticketId2, sessionId });
2437
- break;
2438
- }
2439
- case "error" /* ERROR */:
2440
- emit({
2441
- type: "error" /* ERROR */,
2442
- message: msg.content || "Unknown error"
2434
+ });
2435
+ }
2436
+ async handleMessage(msg, conn, emit, isCancelled, finish, getUploadBaseUrl, setUploadBaseUrl) {
2437
+ if (isCancelled()) {
2438
+ conn.sendCancel();
2439
+ conn.close(1e3, "Cancelled");
2440
+ finish(null);
2441
+ return;
2442
+ }
2443
+ switch (msg.type) {
2444
+ case "thought" /* THOUGHT */:
2445
+ emit({ type: "thought" /* THOUGHT */, text: msg.content ?? "" });
2446
+ break;
2447
+ case "tool_call" /* TOOL_CALL */: {
2448
+ const toolName = msg.name ?? "";
2449
+ const callId = msg.id ?? "";
2450
+ const args = this.extractArgs(msg.metadata);
2451
+ emit({ type: "tool_call" /* TOOL_CALL */, name: toolName, label: msg.content ?? `Running ${toolName}` });
2452
+ this.pendingFlaggedFiles = [];
2453
+ const toolResult = redactPII(await this.registry.execute(toolName, args));
2454
+ emit({ type: "observation" /* OBSERVATION */, text: toolResult.substring(0, 200) });
2455
+ let resultMetadata;
2456
+ const uploadBaseUrl = getUploadBaseUrl();
2457
+ if (this.pendingFlaggedFiles.length > 0 && uploadBaseUrl) {
2458
+ const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
2459
+ const uploadedRefs = [];
2460
+ for (const file of this.pendingFlaggedFiles) {
2461
+ const filename = path5.basename(file.originalPath);
2462
+ const safeName = encodeURIComponent(filename);
2463
+ const storagePath = `${uploadPrefix}/${safeName}`;
2464
+ uploadedRefs.push({
2465
+ original_path: file.originalPath,
2466
+ reason: file.reason ?? "",
2467
+ storage_path: storagePath,
2468
+ file_size_bytes: file.data.length
2443
2469
  });
2444
- ws.close(1e3, "Error received");
2445
- finish(null);
2446
- break;
2447
- case "session_config" /* SESSION_CONFIG */:
2448
- uploadBaseUrl = msg.metadata?.["upload_url"];
2449
- break;
2450
- case "ping" /* PING */: {
2451
- const pongMsg = { type: "pong" /* PONG */ };
2452
- try {
2453
- ws.send(JSON.stringify(pongMsg));
2454
- } catch {
2455
- }
2456
- break;
2470
+ const uploadUrl = `${uploadBaseUrl}/${safeName}`;
2471
+ const contentType = file.isText ? "text/plain" : "application/octet-stream";
2472
+ void _PRBEAgent.backgroundUpload(file.data, uploadUrl, this.config.apiKey, contentType, this.getFetchSignal());
2457
2473
  }
2458
- // SDK-originated types and upload_url — ignore
2459
- case "start" /* START */:
2460
- case "tool_result" /* TOOL_RESULT */:
2461
- case "upload_request" /* UPLOAD_REQUEST */:
2462
- case "cancel" /* CANCEL */:
2463
- case "pong" /* PONG */:
2464
- case "upload_url" /* UPLOAD_URL */:
2465
- break;
2474
+ resultMetadata = { flagged_files: uploadedRefs };
2475
+ this.pendingFlaggedFiles = [];
2466
2476
  }
2467
- };
2468
- ws.onerror = (event) => {
2469
- if (isCancelled()) {
2470
- finish(null);
2471
- return;
2472
- }
2473
- const errorEvent = event;
2474
- const message = errorEvent.message || "WebSocket connection error";
2475
- emit({ type: "error" /* ERROR */, message });
2477
+ conn.sendToolResult(callId, toolName, toolResult, resultMetadata);
2478
+ break;
2479
+ }
2480
+ case "server_tool_call" /* SERVER_TOOL_CALL */:
2481
+ emit({ type: "tool_call" /* TOOL_CALL */, name: msg.name ?? "", label: msg.content ?? "" });
2482
+ break;
2483
+ case "server_observation" /* SERVER_OBSERVATION */:
2484
+ emit({ type: "observation" /* OBSERVATION */, text: (msg.content ?? "").substring(0, 200) });
2485
+ break;
2486
+ case "complete" /* COMPLETE */: {
2487
+ const report = msg.content ?? "";
2488
+ const completedTicketId = msg.metadata?.["ticket_id"];
2489
+ const sessionId = msg.metadata?.["session_id"];
2490
+ emit({ type: "completed" /* COMPLETED */, report, ticketId: completedTicketId });
2491
+ conn.close(1e3, "Complete");
2492
+ finish({ report, ticketId: completedTicketId, sessionId });
2493
+ break;
2494
+ }
2495
+ case "error" /* ERROR */:
2496
+ emit({ type: "error" /* ERROR */, message: msg.content || "Unknown error" });
2497
+ conn.close(1e3, "Error received");
2476
2498
  finish(null);
2477
- };
2478
- ws.onclose = (_event) => {
2479
- if (!resolved) {
2480
- if (isCancelled()) {
2481
- finish(null);
2482
- } else {
2483
- emit({
2484
- type: "error" /* ERROR */,
2485
- message: "WebSocket connection closed unexpectedly"
2486
- });
2487
- finish(null);
2488
- }
2499
+ break;
2500
+ case "session_config" /* SESSION_CONFIG */:
2501
+ setUploadBaseUrl(msg.metadata?.["upload_url"]);
2502
+ break;
2503
+ case "conversation_update" /* CONVERSATION_UPDATE */: {
2504
+ try {
2505
+ const entry = JSON.parse(msg.content ?? "{}");
2506
+ this.state.appendConversation(entry);
2507
+ } catch {
2489
2508
  }
2490
- };
2491
- });
2492
- }
2493
- sendCancel(ws) {
2494
- try {
2495
- const cancelMsg = { type: "cancel" /* CANCEL */ };
2496
- ws.send(JSON.stringify(cancelMsg));
2497
- } catch {
2509
+ break;
2510
+ }
2511
+ case "ping" /* PING */:
2512
+ conn.sendPong();
2513
+ break;
2514
+ default:
2515
+ break;
2498
2516
  }
2499
2517
  }
2500
2518
  extractArgs(metadata) {
@@ -2612,6 +2630,7 @@ var DEFAULT_PRBE_STATE = {
2612
2630
  summary: "",
2613
2631
  currentQuery: "",
2614
2632
  resolvedInteractions: [],
2633
+ conversationHistory: [],
2615
2634
  completedInvestigations: [],
2616
2635
  activeCRs: [],
2617
2636
  completedCRs: [],
@@ -2649,6 +2668,7 @@ function serializePRBEState(state) {
2649
2668
  pendingInteraction: state.pendingInteraction,
2650
2669
  resolvedInteractions: state.resolvedInteractions,
2651
2670
  agentMessage: state.agentMessage,
2671
+ conversationHistory: state.conversationHistory,
2652
2672
  completedInvestigations: state.completedInvestigations.map((inv) => ({
2653
2673
  id: inv.id,
2654
2674
  query: inv.query,
@@ -2657,6 +2677,7 @@ function serializePRBEState(state) {
2657
2677
  ticketId: inv.ticketId,
2658
2678
  events: inv.events,
2659
2679
  resolvedInteractions: inv.resolvedInteractions,
2680
+ conversationHistory: inv.conversationHistory,
2660
2681
  completedAt: inv.completedAt.toISOString()
2661
2682
  })),
2662
2683
  activeCRs: Array.from(state.activeCRs.values()).map(serializeCR),
@@ -2678,6 +2699,7 @@ export {
2678
2699
  AskUserTool,
2679
2700
  BashExecuteTool,
2680
2701
  ClearAppLogsTool,
2702
+ ConversationRole,
2681
2703
  DEFAULT_PRBE_STATE,
2682
2704
  FindFilesTool,
2683
2705
  FlagAppLogsTool,