@prbe.ai/electron-sdk 0.1.18 → 0.1.21

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.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { P as PRBEToolDeclaration, a as PRBEToolParameter, b as PRBEInteractionRequester, F as FlaggedFileIn, c as PRBEAgentState, d as PRBEAgentConfig, I as InvestigationSource, e as InteractionPayload, f as InteractionResponse, U as UserIdentifierType, g as PollResponse, A as AgentHistoryResponse } from './types-BeZ2nQ9x.mjs';
2
- export { h as API_URL, i as AgentHistoryRequest, j as AgentSessionOut, k as AgentTicketOut, l as AskQuestionPayload, m as AskQuestionResponse, C as ContextRequestOut, n as ConversationEntry, o as ConversationRole, D as DEFAULT_PRBE_STATE, E as ExternalRequestOut, p as InteractionType, q as InvestigationResult, M as MIDDLEWARE_URL, r as PRBEAgentConfigKey, s as PRBEAgentError, t as PRBEAgentErrorType, u as PRBEAgentStatus, v as PRBEAgentStatusType, w as PRBEBackgroundInvestigation, x as PRBECompletedInvestigation, y as PRBEInteractionHandler, z as PRBESerializedBackgroundInvestigation, B as PRBESerializedCompletedInvestigation, G as PRBESerializedState, H as PRBESerializedTicket, J as PRBEStateEvent, K as PRBEStatusEvent, L as PollRequest, R as RequestPathAccessPayload, N as RequestPathAccessResponse, O as RequestPermissionPayload, Q as RequestPermissionResponse, S as ResolvedInteraction, T as TicketInfoOut, V as ToolName, W as ToolParamType, X as WSMessage, Y as WSMessageType, Z as redactPII, _ as serializePRBEState } from './types-BeZ2nQ9x.mjs';
1
+ import { P as PRBEToolDeclaration, a as PRBEToolParameter, b as PRBEInteractionRequester, F as FlaggedFileIn, c as PRBEAgentState, d as PRBEAgentConfig, I as InvestigationSource, C as ConversationRole, e as InteractionPayload, f as InteractionResponse, U as UserIdentifierType, g as PollResponse, A as AgentHistoryResponse, S as SanitizedFileResult } from './types-CtT5RMCX.mjs';
2
+ export { h as API_URL, i as AgentHistoryRequest, j as AgentSessionOut, k as AgentTicketOut, l as AskQuestionPayload, m as AskQuestionResponse, n as ContextRequestOut, o as ConversationEntry, D as DEFAULT_PRBE_STATE, E as ExternalRequestOut, p as InteractionType, q as InvestigationResult, M as MIDDLEWARE_URL, r as PRBEAgentConfigKey, s as PRBEAgentError, t as PRBEAgentErrorType, u as PRBEAgentStatus, v as PRBEAgentStatusType, w as PRBEBackgroundInvestigation, x as PRBECompletedInvestigation, y as PRBEInteractionHandler, z as PRBESerializedBackgroundInvestigation, B as PRBESerializedCompletedInvestigation, G as PRBESerializedState, H as PRBESerializedTicket, J as PRBEStateEvent, K as PRBEStatusEvent, L as PollRequest, R as RequestPathAccessPayload, N as RequestPathAccessResponse, O as RequestPermissionPayload, Q as RequestPermissionResponse, T as ResolvedInteraction, V as ReviewSanitizedOutputPayload, W as ReviewSanitizedOutputResponse, X as SanitizationIssue, Y as SanitizedFileRef, Z as TicketInfoOut, _ as ToolName, $ as ToolParamType, a0 as WSMessage, a1 as WSMessageType, a2 as redactPII, a3 as serializePRBEState } from './types-CtT5RMCX.mjs';
3
3
  import 'events';
4
4
 
5
- var version = "0.1.18";
5
+ var version = "0.1.21";
6
6
 
7
7
  /**
8
8
  * tools/index.ts — Tool interface, registry, and closure tool
@@ -159,7 +159,7 @@ declare class PRBEAgent implements PRBEInteractionRequester {
159
159
  private hookRendererLogs;
160
160
  private static mapElectronLogLevel;
161
161
  get investigationSource(): InvestigationSource;
162
- sendConversationMessage(content: string): void;
162
+ sendConversationMessage(content: string, role?: ConversationRole, label?: string): void;
163
163
  requestUserInteraction(payload: InteractionPayload): Promise<InteractionResponse>;
164
164
  /**
165
165
  * Add an additional root directory to the runtime allowed roots.
@@ -209,6 +209,12 @@ declare class PRBEAgent implements PRBEInteractionRequester {
209
209
  * Fetch agent history (tickets + sessions) from the backend.
210
210
  */
211
211
  fetchHistory(): Promise<AgentHistoryResponse | null>;
212
+ fetchSanitizedFile(url: string): Promise<SanitizedFileResult>;
213
+ /**
214
+ * Detect whether a buffer contains text by checking for null bytes
215
+ * and verifying the content is valid UTF-8.
216
+ */
217
+ private static isTextContent;
212
218
  stopPolling(): void;
213
219
  resumePolling(): void;
214
220
  /**
@@ -354,4 +360,4 @@ declare class BashExecuteTool implements PRBETool {
354
360
  */
355
361
  declare const PROBE_MARK_SVG = "<svg width=\"256\" height=\"256\" viewBox=\"0 0 256 256\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M50 112 L114 148 L50 184 Z\" fill=\"#111111\" opacity=\"0.07\"/>\n <path d=\"M70 86 L148 134 L70 182 Z\" fill=\"#111111\" opacity=\"0.18\"/>\n <path d=\"M92 56 L192 118 L92 180 Z\" fill=\"#111111\"/>\n</svg>";
356
362
 
357
- export { AgentHistoryResponse, AskUserTool, BashExecuteTool, ClearAppLogsTool, FindFilesTool, FlagAppLogsTool, FlagFileTool, FlaggedFileIn, InteractionPayload, InteractionResponse, InvestigationSource, ListDirectoryTool, type LogEntry, PRBEAgent, PRBEAgentConfig, PRBEAgentState, PRBEClosureTool, PRBEInteractionRequester, PRBELogCapture, type PRBETool, PRBEToolDeclaration, PRBEToolParameter, PRBEToolRegistry, PROBE_MARK_SVG, PollResponse, ReadAppLogsTool, ReadFileTool, version as SDK_VERSION, SearchAppLogsTool, SearchContentTool, UserIdentifierType, humanReadableSize, resolveAndValidate, resolveWithAccessRequest };
363
+ export { AgentHistoryResponse, AskUserTool, BashExecuteTool, ClearAppLogsTool, ConversationRole, FindFilesTool, FlagAppLogsTool, FlagFileTool, FlaggedFileIn, InteractionPayload, InteractionResponse, InvestigationSource, ListDirectoryTool, type LogEntry, PRBEAgent, PRBEAgentConfig, PRBEAgentState, PRBEClosureTool, PRBEInteractionRequester, PRBELogCapture, type PRBETool, PRBEToolDeclaration, PRBEToolParameter, PRBEToolRegistry, PROBE_MARK_SVG, PollResponse, ReadAppLogsTool, ReadFileTool, version as SDK_VERSION, SanitizedFileResult, SearchAppLogsTool, SearchContentTool, UserIdentifierType, humanReadableSize, resolveAndValidate, resolveWithAccessRequest };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { P as PRBEToolDeclaration, a as PRBEToolParameter, b as PRBEInteractionRequester, F as FlaggedFileIn, c as PRBEAgentState, d as PRBEAgentConfig, I as InvestigationSource, e as InteractionPayload, f as InteractionResponse, U as UserIdentifierType, g as PollResponse, A as AgentHistoryResponse } from './types-BeZ2nQ9x.js';
2
- export { h as API_URL, i as AgentHistoryRequest, j as AgentSessionOut, k as AgentTicketOut, l as AskQuestionPayload, m as AskQuestionResponse, C as ContextRequestOut, n as ConversationEntry, o as ConversationRole, D as DEFAULT_PRBE_STATE, E as ExternalRequestOut, p as InteractionType, q as InvestigationResult, M as MIDDLEWARE_URL, r as PRBEAgentConfigKey, s as PRBEAgentError, t as PRBEAgentErrorType, u as PRBEAgentStatus, v as PRBEAgentStatusType, w as PRBEBackgroundInvestigation, x as PRBECompletedInvestigation, y as PRBEInteractionHandler, z as PRBESerializedBackgroundInvestigation, B as PRBESerializedCompletedInvestigation, G as PRBESerializedState, H as PRBESerializedTicket, J as PRBEStateEvent, K as PRBEStatusEvent, L as PollRequest, R as RequestPathAccessPayload, N as RequestPathAccessResponse, O as RequestPermissionPayload, Q as RequestPermissionResponse, S as ResolvedInteraction, T as TicketInfoOut, V as ToolName, W as ToolParamType, X as WSMessage, Y as WSMessageType, Z as redactPII, _ as serializePRBEState } from './types-BeZ2nQ9x.js';
1
+ import { P as PRBEToolDeclaration, a as PRBEToolParameter, b as PRBEInteractionRequester, F as FlaggedFileIn, c as PRBEAgentState, d as PRBEAgentConfig, I as InvestigationSource, C as ConversationRole, e as InteractionPayload, f as InteractionResponse, U as UserIdentifierType, g as PollResponse, A as AgentHistoryResponse, S as SanitizedFileResult } from './types-CtT5RMCX.js';
2
+ export { h as API_URL, i as AgentHistoryRequest, j as AgentSessionOut, k as AgentTicketOut, l as AskQuestionPayload, m as AskQuestionResponse, n as ContextRequestOut, o as ConversationEntry, D as DEFAULT_PRBE_STATE, E as ExternalRequestOut, p as InteractionType, q as InvestigationResult, M as MIDDLEWARE_URL, r as PRBEAgentConfigKey, s as PRBEAgentError, t as PRBEAgentErrorType, u as PRBEAgentStatus, v as PRBEAgentStatusType, w as PRBEBackgroundInvestigation, x as PRBECompletedInvestigation, y as PRBEInteractionHandler, z as PRBESerializedBackgroundInvestigation, B as PRBESerializedCompletedInvestigation, G as PRBESerializedState, H as PRBESerializedTicket, J as PRBEStateEvent, K as PRBEStatusEvent, L as PollRequest, R as RequestPathAccessPayload, N as RequestPathAccessResponse, O as RequestPermissionPayload, Q as RequestPermissionResponse, T as ResolvedInteraction, V as ReviewSanitizedOutputPayload, W as ReviewSanitizedOutputResponse, X as SanitizationIssue, Y as SanitizedFileRef, Z as TicketInfoOut, _ as ToolName, $ as ToolParamType, a0 as WSMessage, a1 as WSMessageType, a2 as redactPII, a3 as serializePRBEState } from './types-CtT5RMCX.js';
3
3
  import 'events';
4
4
 
5
- var version = "0.1.18";
5
+ var version = "0.1.21";
6
6
 
7
7
  /**
8
8
  * tools/index.ts — Tool interface, registry, and closure tool
@@ -159,7 +159,7 @@ declare class PRBEAgent implements PRBEInteractionRequester {
159
159
  private hookRendererLogs;
160
160
  private static mapElectronLogLevel;
161
161
  get investigationSource(): InvestigationSource;
162
- sendConversationMessage(content: string): void;
162
+ sendConversationMessage(content: string, role?: ConversationRole, label?: string): void;
163
163
  requestUserInteraction(payload: InteractionPayload): Promise<InteractionResponse>;
164
164
  /**
165
165
  * Add an additional root directory to the runtime allowed roots.
@@ -209,6 +209,12 @@ declare class PRBEAgent implements PRBEInteractionRequester {
209
209
  * Fetch agent history (tickets + sessions) from the backend.
210
210
  */
211
211
  fetchHistory(): Promise<AgentHistoryResponse | null>;
212
+ fetchSanitizedFile(url: string): Promise<SanitizedFileResult>;
213
+ /**
214
+ * Detect whether a buffer contains text by checking for null bytes
215
+ * and verifying the content is valid UTF-8.
216
+ */
217
+ private static isTextContent;
212
218
  stopPolling(): void;
213
219
  resumePolling(): void;
214
220
  /**
@@ -354,4 +360,4 @@ declare class BashExecuteTool implements PRBETool {
354
360
  */
355
361
  declare const PROBE_MARK_SVG = "<svg width=\"256\" height=\"256\" viewBox=\"0 0 256 256\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M50 112 L114 148 L50 184 Z\" fill=\"#111111\" opacity=\"0.07\"/>\n <path d=\"M70 86 L148 134 L70 182 Z\" fill=\"#111111\" opacity=\"0.18\"/>\n <path d=\"M92 56 L192 118 L92 180 Z\" fill=\"#111111\"/>\n</svg>";
356
362
 
357
- export { AgentHistoryResponse, AskUserTool, BashExecuteTool, ClearAppLogsTool, FindFilesTool, FlagAppLogsTool, FlagFileTool, FlaggedFileIn, InteractionPayload, InteractionResponse, InvestigationSource, ListDirectoryTool, type LogEntry, PRBEAgent, PRBEAgentConfig, PRBEAgentState, PRBEClosureTool, PRBEInteractionRequester, PRBELogCapture, type PRBETool, PRBEToolDeclaration, PRBEToolParameter, PRBEToolRegistry, PROBE_MARK_SVG, PollResponse, ReadAppLogsTool, ReadFileTool, version as SDK_VERSION, SearchAppLogsTool, SearchContentTool, UserIdentifierType, humanReadableSize, resolveAndValidate, resolveWithAccessRequest };
363
+ export { AgentHistoryResponse, AskUserTool, BashExecuteTool, ClearAppLogsTool, ConversationRole, FindFilesTool, FlagAppLogsTool, FlagFileTool, FlaggedFileIn, InteractionPayload, InteractionResponse, InvestigationSource, ListDirectoryTool, type LogEntry, PRBEAgent, PRBEAgentConfig, PRBEAgentState, PRBEClosureTool, PRBEInteractionRequester, PRBELogCapture, type PRBETool, PRBEToolDeclaration, PRBEToolParameter, PRBEToolRegistry, PROBE_MARK_SVG, PollResponse, ReadAppLogsTool, ReadFileTool, version as SDK_VERSION, SanitizedFileResult, SearchAppLogsTool, SearchContentTool, UserIdentifierType, humanReadableSize, resolveAndValidate, resolveWithAccessRequest };
package/dist/index.js CHANGED
@@ -72,7 +72,7 @@ __export(src_exports, {
72
72
  module.exports = __toCommonJS(src_exports);
73
73
 
74
74
  // package.json
75
- var version = "0.1.18";
75
+ var version = "0.1.21";
76
76
 
77
77
  // src/agent.ts
78
78
  var fs2 = __toESM(require("fs"));
@@ -98,6 +98,9 @@ var WSMessageType = /* @__PURE__ */ ((WSMessageType2) => {
98
98
  WSMessageType2["COMPLETE"] = "complete";
99
99
  WSMessageType2["ERROR"] = "error";
100
100
  WSMessageType2["PING"] = "ping";
101
+ WSMessageType2["PRIVACY_SANITIZING"] = "privacy_sanitizing";
102
+ WSMessageType2["PRIVACY_REVIEW"] = "privacy_review";
103
+ WSMessageType2["PRIVACY_REVIEW_RESPONSE"] = "privacy_review_response";
101
104
  return WSMessageType2;
102
105
  })(WSMessageType || {});
103
106
  var ConversationRole = /* @__PURE__ */ ((ConversationRole3) => {
@@ -124,6 +127,8 @@ var ToolName = /* @__PURE__ */ ((ToolName2) => {
124
127
  ToolName2["CLIENT_ASK_USER"] = "client_ask_user";
125
128
  ToolName2["CLIENT_BASH_EXECUTE"] = "client_bash_execute";
126
129
  ToolName2["CLIENT_MESSAGE_USER"] = "client_message_user";
130
+ ToolName2["SDK_MESSAGE_USER"] = "sdk_message_user";
131
+ ToolName2["SDK_ASK_USER"] = "sdk_ask_user";
127
132
  return ToolName2;
128
133
  })(ToolName || {});
129
134
  var UserIdentifierType = /* @__PURE__ */ ((UserIdentifierType2) => {
@@ -155,6 +160,7 @@ var PRBEAgentStatusType = /* @__PURE__ */ ((PRBEAgentStatusType2) => {
155
160
  PRBEAgentStatusType2["COMPLETED"] = "completed";
156
161
  PRBEAgentStatusType2["ERROR"] = "error";
157
162
  PRBEAgentStatusType2["AWAITING_INTERACTION"] = "awaiting_interaction";
163
+ PRBEAgentStatusType2["PRIVACY_SANITIZING"] = "privacy_sanitizing";
158
164
  return PRBEAgentStatusType2;
159
165
  })(PRBEAgentStatusType || {});
160
166
  var PRBEAgentErrorType = /* @__PURE__ */ ((PRBEAgentErrorType2) => {
@@ -194,7 +200,9 @@ var InvestigationConnection = class {
194
200
  if (!raw) return;
195
201
  try {
196
202
  const msg = JSON.parse(raw);
197
- this.onMessage(msg);
203
+ Promise.resolve(this.onMessage(msg)).catch((err) => {
204
+ this.onError(`Message handler error: ${err instanceof Error ? err.message : String(err)}`);
205
+ });
198
206
  } catch {
199
207
  }
200
208
  };
@@ -220,10 +228,14 @@ var InvestigationConnection = class {
220
228
  return false;
221
229
  }
222
230
  }
223
- sendConversationMessage(content) {
231
+ sendConversationMessage(content, role, label) {
232
+ const metadata = {};
233
+ if (role) metadata["role"] = role;
234
+ if (label) metadata["label"] = label;
224
235
  this.send({
225
236
  type: "conversation_message" /* CONVERSATION_MESSAGE */,
226
- content
237
+ content,
238
+ ...Object.keys(metadata).length > 0 ? { metadata } : {}
227
239
  });
228
240
  }
229
241
  sendToolResult(callId, toolName, result, metadata) {
@@ -286,6 +298,7 @@ var PRBEAgentState = class extends import_events.EventEmitter {
286
298
  resolvedInteractions = [];
287
299
  agentMessage;
288
300
  conversationHistory = [];
301
+ isPrivacySanitizing = false;
289
302
  // Completed user investigations (history)
290
303
  completedInvestigations = [];
291
304
  // Background investigations (context requests, external requests, etc.)
@@ -383,6 +396,7 @@ var PRBEAgentState = class extends import_events.EventEmitter {
383
396
  });
384
397
  this.report = report;
385
398
  this.isInvestigating = false;
399
+ this.isPrivacySanitizing = false;
386
400
  this.emit("complete" /* COMPLETE */, { report });
387
401
  this.emit("status" /* STATUS */);
388
402
  }
@@ -390,9 +404,14 @@ var PRBEAgentState = class extends import_events.EventEmitter {
390
404
  this.appendEvent(`Error: ${message}`);
391
405
  this.investigationError = message;
392
406
  this.isInvestigating = false;
407
+ this.isPrivacySanitizing = false;
393
408
  this.emit("error" /* ERROR */, { message });
394
409
  this.emit("status" /* STATUS */);
395
410
  }
411
+ setPrivacySanitizing(value) {
412
+ this.isPrivacySanitizing = value;
413
+ this.emit("status" /* STATUS */);
414
+ }
396
415
  // ---------- Interaction state mutations ----------
397
416
  setPendingInteraction(payload) {
398
417
  this.pendingInteraction = payload;
@@ -573,6 +592,7 @@ var InteractionType = /* @__PURE__ */ ((InteractionType2) => {
573
592
  InteractionType2["ASK_QUESTION"] = "ask_question";
574
593
  InteractionType2["REQUEST_PERMISSION"] = "request_permission";
575
594
  InteractionType2["REQUEST_PATH_ACCESS"] = "request_path_access";
595
+ InteractionType2["REVIEW_SANITIZED_OUTPUT"] = "review_sanitized_output";
576
596
  return InteractionType2;
577
597
  })(InteractionType || {});
578
598
  var InvestigationSource = /* @__PURE__ */ ((InvestigationSource2) => {
@@ -1457,7 +1477,7 @@ var AskUserTool = class {
1457
1477
  }
1458
1478
  get declaration() {
1459
1479
  return {
1460
- name: "client_ask_user" /* CLIENT_ASK_USER */,
1480
+ name: "sdk_ask_user" /* SDK_ASK_USER */,
1461
1481
  description: "Ask the user a question and wait for their response. Use this when you need clarification or additional information from the user to continue the investigation.",
1462
1482
  interactive: true,
1463
1483
  parameters: [
@@ -1486,7 +1506,8 @@ var AskUserTool = class {
1486
1506
  const response = await this.requester.requestUserInteraction({
1487
1507
  type: "ask_question" /* ASK_QUESTION */,
1488
1508
  interactionId: (0, import_crypto3.randomUUID)(),
1489
- question: reason
1509
+ question,
1510
+ context: reason
1490
1511
  });
1491
1512
  const askResponse = response;
1492
1513
  return askResponse.answer;
@@ -1696,6 +1717,10 @@ var BashExecuteTool = class {
1696
1717
  return `Error: working directory '${cwdArg}' is outside auto-approved directories`;
1697
1718
  }
1698
1719
  cwd = resolved;
1720
+ } else if (this.autoApprovedDirs.length > 0) {
1721
+ cwd = this.autoApprovedDirs[0];
1722
+ } else {
1723
+ return "Error: no approved directories configured and no working directory specified";
1699
1724
  }
1700
1725
  const isSafe = this.isCommandSafe(command);
1701
1726
  if (!isSafe) {
@@ -1891,7 +1916,7 @@ var PRBEAgent = class _PRBEAgent {
1891
1916
  }
1892
1917
  this.registry.register(
1893
1918
  new PRBEClosureTool(
1894
- "client_message_user",
1919
+ "sdk_message_user" /* SDK_MESSAGE_USER */,
1895
1920
  "Send a message to the user.",
1896
1921
  [{ name: "message", type: "STRING" /* STRING */, description: "Message for the user", required: true }],
1897
1922
  async (args) => {
@@ -1959,8 +1984,8 @@ var PRBEAgent = class _PRBEAgent {
1959
1984
  get investigationSource() {
1960
1985
  return this.currentInvestigationSource;
1961
1986
  }
1962
- sendConversationMessage(content) {
1963
- this.activeConnection?.sendConversationMessage(content);
1987
+ sendConversationMessage(content, role, label) {
1988
+ this.activeConnection?.sendConversationMessage(content, role, label);
1964
1989
  }
1965
1990
  async requestUserInteraction(payload) {
1966
1991
  if (!this.interactionHandler) {
@@ -1969,6 +1994,19 @@ var PRBEAgent = class _PRBEAgent {
1969
1994
  "No interaction handler configured"
1970
1995
  );
1971
1996
  }
1997
+ if (payload.type === "request_permission" /* REQUEST_PERMISSION */) {
1998
+ const p = payload;
1999
+ const content = p.reason ? `${p.command}
2000
+
2001
+ ${p.reason}` : p.command;
2002
+ this.sendConversationMessage(content, "agent" /* Agent */, p.action);
2003
+ } else if (payload.type === "request_path_access" /* REQUEST_PATH_ACCESS */) {
2004
+ const p = payload;
2005
+ const content = p.reason ? `${p.path}
2006
+
2007
+ ${p.reason}` : p.path;
2008
+ this.sendConversationMessage(content, "agent" /* Agent */, "Request path access");
2009
+ }
1972
2010
  if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
1973
2011
  this.state.setBackgroundPendingInteraction(this.currentBackgroundId, payload);
1974
2012
  } else {
@@ -2114,6 +2152,14 @@ var PRBEAgent = class _PRBEAgent {
2114
2152
  this.state.failInvestigation(status.message);
2115
2153
  }
2116
2154
  break;
2155
+ case "privacy_sanitizing" /* PRIVACY_SANITIZING */:
2156
+ if (isBackground && opts.sourceId) {
2157
+ this.state.appendBackgroundEvent(opts.sourceId, "Sanitizing data for privacy review...");
2158
+ } else {
2159
+ this.state.appendEvent("Sanitizing data for privacy review...");
2160
+ }
2161
+ this.state.setPrivacySanitizing(true);
2162
+ break;
2117
2163
  }
2118
2164
  };
2119
2165
  const result = await this.connectToProxy(
@@ -2206,6 +2252,30 @@ var PRBEAgent = class _PRBEAgent {
2206
2252
  return null;
2207
2253
  }
2208
2254
  }
2255
+ async fetchSanitizedFile(url) {
2256
+ const res = await fetch(url, {
2257
+ headers: { "X-API-Key": this.config.apiKey }
2258
+ });
2259
+ if (!res.ok) throw new Error(`Failed to fetch sanitized file: ${res.status}`);
2260
+ const buffer = Buffer.from(await res.arrayBuffer());
2261
+ if (!_PRBEAgent.isTextContent(buffer)) {
2262
+ return { isText: false, url };
2263
+ }
2264
+ return { isText: true, content: buffer.toString("utf-8"), url };
2265
+ }
2266
+ /**
2267
+ * Detect whether a buffer contains text by checking for null bytes
2268
+ * and verifying the content is valid UTF-8.
2269
+ */
2270
+ static isTextContent(buffer) {
2271
+ const checkLength = Math.min(buffer.length, 8192);
2272
+ for (let i = 0; i < checkLength; i++) {
2273
+ if (buffer[i] === 0) return false;
2274
+ }
2275
+ const decoded = buffer.toString("utf-8");
2276
+ const reEncoded = Buffer.from(decoded, "utf-8");
2277
+ return buffer.length === reEncoded.length;
2278
+ }
2209
2279
  stopPolling() {
2210
2280
  if (this.pollingTimer !== null) {
2211
2281
  clearInterval(this.pollingTimer);
@@ -2295,8 +2365,8 @@ var PRBEAgent = class _PRBEAgent {
2295
2365
  uploadBaseUrl = url;
2296
2366
  }),
2297
2367
  (message) => {
2298
- if (!isCancelled()) emit({ type: "error" /* ERROR */, message });
2299
- finish(null);
2368
+ if (!resolved && !isCancelled()) emit({ type: "error" /* ERROR */, message });
2369
+ if (!resolved) finish(null);
2300
2370
  },
2301
2371
  () => {
2302
2372
  if (!resolved) {
@@ -2329,6 +2399,8 @@ var PRBEAgent = class _PRBEAgent {
2329
2399
  }));
2330
2400
  const startMetadata = {
2331
2401
  agent_id: this.agentID,
2402
+ sdk_name: "electron",
2403
+ supports_chat: true,
2332
2404
  custom_tools: toolDeclarations,
2333
2405
  platform: os.platform(),
2334
2406
  os_version: os.release(),
@@ -2377,7 +2449,12 @@ var PRBEAgent = class _PRBEAgent {
2377
2449
  const args = this.extractArgs(msg.metadata);
2378
2450
  emit({ type: "tool_call" /* TOOL_CALL */, name: toolName, label: msg.content ?? `Running ${toolName}` });
2379
2451
  this.pendingFlaggedFiles = [];
2380
- const toolResult = redactPII(await this.registry.execute(toolName, args));
2452
+ let toolResult;
2453
+ try {
2454
+ toolResult = redactPII(await this.registry.execute(toolName, args));
2455
+ } catch (err) {
2456
+ toolResult = `Error: Tool execution failed: ${err instanceof Error ? err.message : String(err)}`;
2457
+ }
2381
2458
  emit({ type: "observation" /* OBSERVATION */, text: toolResult.substring(0, 200) });
2382
2459
  let resultMetadata;
2383
2460
  const uploadBaseUrl = getUploadBaseUrl();
@@ -2439,6 +2516,41 @@ var PRBEAgent = class _PRBEAgent {
2439
2516
  }
2440
2517
  break;
2441
2518
  }
2519
+ case "privacy_sanitizing" /* PRIVACY_SANITIZING */: {
2520
+ emit({ type: "privacy_sanitizing" /* PRIVACY_SANITIZING */ });
2521
+ break;
2522
+ }
2523
+ case "privacy_review" /* PRIVACY_REVIEW */: {
2524
+ const sanitizedText = msg.content ?? "";
2525
+ const issues = msg.metadata?.issues ?? [];
2526
+ const files = msg.metadata?.files ?? [];
2527
+ const summary = msg.metadata?.summary ?? "";
2528
+ const payload = {
2529
+ type: "review_sanitized_output" /* REVIEW_SANITIZED_OUTPUT */,
2530
+ interactionId: (0, import_crypto5.randomUUID)(),
2531
+ sanitizedAnalysis: sanitizedText,
2532
+ files,
2533
+ summary,
2534
+ issues
2535
+ };
2536
+ try {
2537
+ const response = await this.requestUserInteraction(payload);
2538
+ const reviewResponse = response;
2539
+ conn.send({
2540
+ type: "privacy_review_response" /* PRIVACY_REVIEW_RESPONSE */,
2541
+ metadata: {
2542
+ approved: reviewResponse.approved,
2543
+ ...reviewResponse.editedText ? { editedText: reviewResponse.editedText } : {}
2544
+ }
2545
+ });
2546
+ } catch {
2547
+ conn.send({
2548
+ type: "privacy_review_response" /* PRIVACY_REVIEW_RESPONSE */,
2549
+ metadata: { approved: false }
2550
+ });
2551
+ }
2552
+ break;
2553
+ }
2442
2554
  case "ping" /* PING */:
2443
2555
  conn.sendPong();
2444
2556
  break;
@@ -2541,6 +2653,7 @@ var PRBEAgent = class _PRBEAgent {
2541
2653
  // src/serialization.ts
2542
2654
  var DEFAULT_PRBE_STATE = {
2543
2655
  isInvestigating: false,
2656
+ isPrivacySanitizing: false,
2544
2657
  events: [],
2545
2658
  report: "",
2546
2659
  summary: "",
@@ -2579,6 +2692,7 @@ function serializeBackgroundInvestigation(bg) {
2579
2692
  function serializePRBEState(state) {
2580
2693
  return {
2581
2694
  isInvestigating: state.isInvestigating,
2695
+ isPrivacySanitizing: state.isPrivacySanitizing,
2582
2696
  events: state.events,
2583
2697
  report: state.report,
2584
2698
  summary: state.summary,