@prbe.ai/electron-sdk 0.1.18 → 0.1.19

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
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.1.18";
2
+ var version = "0.1.19";
3
3
 
4
4
  // src/agent.ts
5
5
  import * as fs2 from "fs";
@@ -25,6 +25,9 @@ var WSMessageType = /* @__PURE__ */ ((WSMessageType2) => {
25
25
  WSMessageType2["COMPLETE"] = "complete";
26
26
  WSMessageType2["ERROR"] = "error";
27
27
  WSMessageType2["PING"] = "ping";
28
+ WSMessageType2["PRIVACY_SANITIZING"] = "privacy_sanitizing";
29
+ WSMessageType2["PRIVACY_REVIEW"] = "privacy_review";
30
+ WSMessageType2["PRIVACY_REVIEW_RESPONSE"] = "privacy_review_response";
28
31
  return WSMessageType2;
29
32
  })(WSMessageType || {});
30
33
  var ConversationRole = /* @__PURE__ */ ((ConversationRole3) => {
@@ -82,6 +85,7 @@ var PRBEAgentStatusType = /* @__PURE__ */ ((PRBEAgentStatusType2) => {
82
85
  PRBEAgentStatusType2["COMPLETED"] = "completed";
83
86
  PRBEAgentStatusType2["ERROR"] = "error";
84
87
  PRBEAgentStatusType2["AWAITING_INTERACTION"] = "awaiting_interaction";
88
+ PRBEAgentStatusType2["PRIVACY_SANITIZING"] = "privacy_sanitizing";
85
89
  return PRBEAgentStatusType2;
86
90
  })(PRBEAgentStatusType || {});
87
91
  var PRBEAgentErrorType = /* @__PURE__ */ ((PRBEAgentErrorType2) => {
@@ -147,10 +151,14 @@ var InvestigationConnection = class {
147
151
  return false;
148
152
  }
149
153
  }
150
- sendConversationMessage(content) {
154
+ sendConversationMessage(content, role, label) {
155
+ const metadata = {};
156
+ if (role) metadata["role"] = role;
157
+ if (label) metadata["label"] = label;
151
158
  this.send({
152
159
  type: "conversation_message" /* CONVERSATION_MESSAGE */,
153
- content
160
+ content,
161
+ ...Object.keys(metadata).length > 0 ? { metadata } : {}
154
162
  });
155
163
  }
156
164
  sendToolResult(callId, toolName, result, metadata) {
@@ -213,6 +221,7 @@ var PRBEAgentState = class extends EventEmitter {
213
221
  resolvedInteractions = [];
214
222
  agentMessage;
215
223
  conversationHistory = [];
224
+ isPrivacySanitizing = false;
216
225
  // Completed user investigations (history)
217
226
  completedInvestigations = [];
218
227
  // Background investigations (context requests, external requests, etc.)
@@ -310,6 +319,7 @@ var PRBEAgentState = class extends EventEmitter {
310
319
  });
311
320
  this.report = report;
312
321
  this.isInvestigating = false;
322
+ this.isPrivacySanitizing = false;
313
323
  this.emit("complete" /* COMPLETE */, { report });
314
324
  this.emit("status" /* STATUS */);
315
325
  }
@@ -317,9 +327,14 @@ var PRBEAgentState = class extends EventEmitter {
317
327
  this.appendEvent(`Error: ${message}`);
318
328
  this.investigationError = message;
319
329
  this.isInvestigating = false;
330
+ this.isPrivacySanitizing = false;
320
331
  this.emit("error" /* ERROR */, { message });
321
332
  this.emit("status" /* STATUS */);
322
333
  }
334
+ setPrivacySanitizing(value) {
335
+ this.isPrivacySanitizing = value;
336
+ this.emit("status" /* STATUS */);
337
+ }
323
338
  // ---------- Interaction state mutations ----------
324
339
  setPendingInteraction(payload) {
325
340
  this.pendingInteraction = payload;
@@ -500,6 +515,7 @@ var InteractionType = /* @__PURE__ */ ((InteractionType2) => {
500
515
  InteractionType2["ASK_QUESTION"] = "ask_question";
501
516
  InteractionType2["REQUEST_PERMISSION"] = "request_permission";
502
517
  InteractionType2["REQUEST_PATH_ACCESS"] = "request_path_access";
518
+ InteractionType2["REVIEW_SANITIZED_OUTPUT"] = "review_sanitized_output";
503
519
  return InteractionType2;
504
520
  })(InteractionType || {});
505
521
  var InvestigationSource = /* @__PURE__ */ ((InvestigationSource2) => {
@@ -1413,7 +1429,8 @@ var AskUserTool = class {
1413
1429
  const response = await this.requester.requestUserInteraction({
1414
1430
  type: "ask_question" /* ASK_QUESTION */,
1415
1431
  interactionId: randomUUID3(),
1416
- question: reason
1432
+ question,
1433
+ context: reason
1417
1434
  });
1418
1435
  const askResponse = response;
1419
1436
  return askResponse.answer;
@@ -1623,6 +1640,10 @@ var BashExecuteTool = class {
1623
1640
  return `Error: working directory '${cwdArg}' is outside auto-approved directories`;
1624
1641
  }
1625
1642
  cwd = resolved;
1643
+ } else if (this.autoApprovedDirs.length > 0) {
1644
+ cwd = this.autoApprovedDirs[0];
1645
+ } else {
1646
+ return "Error: no approved directories configured and no working directory specified";
1626
1647
  }
1627
1648
  const isSafe = this.isCommandSafe(command);
1628
1649
  if (!isSafe) {
@@ -1886,8 +1907,8 @@ var PRBEAgent = class _PRBEAgent {
1886
1907
  get investigationSource() {
1887
1908
  return this.currentInvestigationSource;
1888
1909
  }
1889
- sendConversationMessage(content) {
1890
- this.activeConnection?.sendConversationMessage(content);
1910
+ sendConversationMessage(content, role, label) {
1911
+ this.activeConnection?.sendConversationMessage(content, role, label);
1891
1912
  }
1892
1913
  async requestUserInteraction(payload) {
1893
1914
  if (!this.interactionHandler) {
@@ -1896,6 +1917,22 @@ var PRBEAgent = class _PRBEAgent {
1896
1917
  "No interaction handler configured"
1897
1918
  );
1898
1919
  }
1920
+ if (payload.type === "request_permission" /* REQUEST_PERMISSION */) {
1921
+ const p = payload;
1922
+ const content = p.reason ? `${p.command}
1923
+
1924
+ ${p.reason}` : p.command;
1925
+ this.sendConversationMessage(content, "agent" /* Agent */, p.action);
1926
+ } else if (payload.type === "request_path_access" /* REQUEST_PATH_ACCESS */) {
1927
+ const p = payload;
1928
+ const content = p.reason ? `${p.path}
1929
+
1930
+ ${p.reason}` : p.path;
1931
+ this.sendConversationMessage(content, "agent" /* Agent */, "Request path access");
1932
+ } else if (payload.type === "ask_question" /* ASK_QUESTION */) {
1933
+ const p = payload;
1934
+ this.sendConversationMessage(p.question, "agent" /* Agent */);
1935
+ }
1899
1936
  if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
1900
1937
  this.state.setBackgroundPendingInteraction(this.currentBackgroundId, payload);
1901
1938
  } else {
@@ -2041,6 +2078,14 @@ var PRBEAgent = class _PRBEAgent {
2041
2078
  this.state.failInvestigation(status.message);
2042
2079
  }
2043
2080
  break;
2081
+ case "privacy_sanitizing" /* PRIVACY_SANITIZING */:
2082
+ if (isBackground && opts.sourceId) {
2083
+ this.state.appendBackgroundEvent(opts.sourceId, "Sanitizing data for privacy review...");
2084
+ } else {
2085
+ this.state.appendEvent("Sanitizing data for privacy review...");
2086
+ }
2087
+ this.state.setPrivacySanitizing(true);
2088
+ break;
2044
2089
  }
2045
2090
  };
2046
2091
  const result = await this.connectToProxy(
@@ -2133,6 +2178,30 @@ var PRBEAgent = class _PRBEAgent {
2133
2178
  return null;
2134
2179
  }
2135
2180
  }
2181
+ async fetchSanitizedFile(url) {
2182
+ const res = await fetch(url, {
2183
+ headers: { "X-API-Key": this.config.apiKey }
2184
+ });
2185
+ if (!res.ok) throw new Error(`Failed to fetch sanitized file: ${res.status}`);
2186
+ const buffer = Buffer.from(await res.arrayBuffer());
2187
+ if (!_PRBEAgent.isTextContent(buffer)) {
2188
+ return { isText: false, url };
2189
+ }
2190
+ return { isText: true, content: buffer.toString("utf-8"), url };
2191
+ }
2192
+ /**
2193
+ * Detect whether a buffer contains text by checking for null bytes
2194
+ * and verifying the content is valid UTF-8.
2195
+ */
2196
+ static isTextContent(buffer) {
2197
+ const checkLength = Math.min(buffer.length, 8192);
2198
+ for (let i = 0; i < checkLength; i++) {
2199
+ if (buffer[i] === 0) return false;
2200
+ }
2201
+ const decoded = buffer.toString("utf-8");
2202
+ const reEncoded = Buffer.from(decoded, "utf-8");
2203
+ return buffer.length === reEncoded.length;
2204
+ }
2136
2205
  stopPolling() {
2137
2206
  if (this.pollingTimer !== null) {
2138
2207
  clearInterval(this.pollingTimer);
@@ -2222,8 +2291,8 @@ var PRBEAgent = class _PRBEAgent {
2222
2291
  uploadBaseUrl = url;
2223
2292
  }),
2224
2293
  (message) => {
2225
- if (!isCancelled()) emit({ type: "error" /* ERROR */, message });
2226
- finish(null);
2294
+ if (!resolved && !isCancelled()) emit({ type: "error" /* ERROR */, message });
2295
+ if (!resolved) finish(null);
2227
2296
  },
2228
2297
  () => {
2229
2298
  if (!resolved) {
@@ -2366,6 +2435,41 @@ var PRBEAgent = class _PRBEAgent {
2366
2435
  }
2367
2436
  break;
2368
2437
  }
2438
+ case "privacy_sanitizing" /* PRIVACY_SANITIZING */: {
2439
+ emit({ type: "privacy_sanitizing" /* PRIVACY_SANITIZING */ });
2440
+ break;
2441
+ }
2442
+ case "privacy_review" /* PRIVACY_REVIEW */: {
2443
+ const sanitizedText = msg.content ?? "";
2444
+ const issues = msg.metadata?.issues ?? [];
2445
+ const files = msg.metadata?.files ?? [];
2446
+ const summary = msg.metadata?.summary ?? "";
2447
+ const payload = {
2448
+ type: "review_sanitized_output" /* REVIEW_SANITIZED_OUTPUT */,
2449
+ interactionId: randomUUID5(),
2450
+ sanitizedAnalysis: sanitizedText,
2451
+ files,
2452
+ summary,
2453
+ issues
2454
+ };
2455
+ try {
2456
+ const response = await this.requestUserInteraction(payload);
2457
+ const reviewResponse = response;
2458
+ conn.send({
2459
+ type: "privacy_review_response" /* PRIVACY_REVIEW_RESPONSE */,
2460
+ metadata: {
2461
+ approved: reviewResponse.approved,
2462
+ ...reviewResponse.editedText ? { editedText: reviewResponse.editedText } : {}
2463
+ }
2464
+ });
2465
+ } catch {
2466
+ conn.send({
2467
+ type: "privacy_review_response" /* PRIVACY_REVIEW_RESPONSE */,
2468
+ metadata: { approved: false }
2469
+ });
2470
+ }
2471
+ break;
2472
+ }
2369
2473
  case "ping" /* PING */:
2370
2474
  conn.sendPong();
2371
2475
  break;
@@ -2468,6 +2572,7 @@ var PRBEAgent = class _PRBEAgent {
2468
2572
  // src/serialization.ts
2469
2573
  var DEFAULT_PRBE_STATE = {
2470
2574
  isInvestigating: false,
2575
+ isPrivacySanitizing: false,
2471
2576
  events: [],
2472
2577
  report: "",
2473
2578
  summary: "",
@@ -2506,6 +2611,7 @@ function serializeBackgroundInvestigation(bg) {
2506
2611
  function serializePRBEState(state) {
2507
2612
  return {
2508
2613
  isInvestigating: state.isInvestigating,
2614
+ isPrivacySanitizing: state.isPrivacySanitizing,
2509
2615
  events: state.events,
2510
2616
  report: state.report,
2511
2617
  summary: state.summary,