@prbe.ai/electron-sdk 0.1.16 → 0.1.18

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
@@ -61,6 +61,7 @@ __export(src_exports, {
61
61
  SearchContentTool: () => SearchContentTool,
62
62
  ToolName: () => ToolName,
63
63
  ToolParamType: () => ToolParamType,
64
+ UserIdentifierType: () => UserIdentifierType,
64
65
  WSMessageType: () => WSMessageType,
65
66
  humanReadableSize: () => humanReadableSize,
66
67
  redactPII: () => redactPII,
@@ -71,12 +72,12 @@ __export(src_exports, {
71
72
  module.exports = __toCommonJS(src_exports);
72
73
 
73
74
  // package.json
74
- var version = "0.1.16";
75
+ var version = "0.1.18";
75
76
 
76
77
  // src/agent.ts
77
- var fs3 = __toESM(require("fs"));
78
- var path5 = __toESM(require("path"));
79
- var os2 = __toESM(require("os"));
78
+ var fs2 = __toESM(require("fs"));
79
+ var path4 = __toESM(require("path"));
80
+ var os = __toESM(require("os"));
80
81
  var import_crypto5 = require("crypto");
81
82
 
82
83
  // src/models.ts
@@ -125,6 +126,11 @@ var ToolName = /* @__PURE__ */ ((ToolName2) => {
125
126
  ToolName2["CLIENT_MESSAGE_USER"] = "client_message_user";
126
127
  return ToolName2;
127
128
  })(ToolName || {});
129
+ var UserIdentifierType = /* @__PURE__ */ ((UserIdentifierType2) => {
130
+ UserIdentifierType2["EMAIL"] = "email";
131
+ UserIdentifierType2["ID"] = "id";
132
+ return UserIdentifierType2;
133
+ })(UserIdentifierType || {});
128
134
  var PRBEAgentConfigKey = /* @__PURE__ */ ((PRBEAgentConfigKey3) => {
129
135
  PRBEAgentConfigKey3["API_KEY"] = "apiKey";
130
136
  PRBEAgentConfigKey3["AUTO_APPROVED_DIRS"] = "autoApprovedDirs";
@@ -259,8 +265,8 @@ var PRBEStateEvent = /* @__PURE__ */ ((PRBEStateEvent2) => {
259
265
  PRBEStateEvent2["EVENT"] = "event";
260
266
  PRBEStateEvent2["COMPLETE"] = "complete";
261
267
  PRBEStateEvent2["ERROR"] = "error";
262
- PRBEStateEvent2["CR_START"] = "cr-start";
263
- PRBEStateEvent2["CR_COMPLETE"] = "cr-complete";
268
+ PRBEStateEvent2["BACKGROUND_START"] = "background-start";
269
+ PRBEStateEvent2["BACKGROUND_COMPLETE"] = "background-complete";
264
270
  PRBEStateEvent2["TICKETS_CHANGED"] = "tickets-changed";
265
271
  PRBEStateEvent2["TICKET_INFO"] = "ticket-info";
266
272
  PRBEStateEvent2["INTERACTION_REQUESTED"] = "interaction-requested";
@@ -282,18 +288,20 @@ var PRBEAgentState = class extends import_events.EventEmitter {
282
288
  conversationHistory = [];
283
289
  // Completed user investigations (history)
284
290
  completedInvestigations = [];
285
- // Background context requests
286
- activeCRs = /* @__PURE__ */ new Map();
287
- completedCRs = [];
291
+ // Background investigations (context requests, external requests, etc.)
292
+ activeBackgroundInvestigations = /* @__PURE__ */ new Map();
293
+ completedBackgroundInvestigations = [];
288
294
  // Tracked tickets
289
295
  trackedSessionIDs = [];
290
296
  ticketInfo = [];
297
+ // Agent history
298
+ agentHistory = [];
291
299
  // Computed
292
300
  get hasActiveWork() {
293
- return this.isInvestigating || this.activeCRs.size > 0;
301
+ return this.isInvestigating || this.activeBackgroundInvestigations.size > 0;
294
302
  }
295
- get activeCRCount() {
296
- return this.activeCRs.size;
303
+ get activeBackgroundCount() {
304
+ return this.activeBackgroundInvestigations.size;
297
305
  }
298
306
  get isActive() {
299
307
  return this.isInvestigating || this.report.length > 0 || this.investigationError != null;
@@ -315,6 +323,12 @@ var PRBEAgentState = class extends import_events.EventEmitter {
315
323
  this.conversationHistory.push(entry);
316
324
  this.emit("status" /* STATUS */);
317
325
  }
326
+ appendBackgroundConversation(backgroundId, entry) {
327
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
328
+ if (!bg) return;
329
+ bg.conversationHistory.push(entry);
330
+ this.emit("status" /* STATUS */);
331
+ }
318
332
  resetInvestigation() {
319
333
  this.isInvestigating = false;
320
334
  this.events = [];
@@ -390,17 +404,17 @@ var PRBEAgentState = class extends import_events.EventEmitter {
390
404
  this.emit("interaction-resolved" /* INTERACTION_RESOLVED */);
391
405
  this.emit("status" /* STATUS */);
392
406
  }
393
- setCRPendingInteraction(crID, payload) {
394
- const cr = this.activeCRs.get(crID);
395
- if (!cr) return;
396
- cr.pendingInteraction = payload;
407
+ setBackgroundPendingInteraction(backgroundId, payload) {
408
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
409
+ if (!bg) return;
410
+ bg.pendingInteraction = payload;
397
411
  this.emit("interaction-requested" /* INTERACTION_REQUESTED */, payload);
398
412
  this.emit("status" /* STATUS */);
399
413
  }
400
- clearCRPendingInteraction(crID) {
401
- const cr = this.activeCRs.get(crID);
402
- if (!cr) return;
403
- cr.pendingInteraction = void 0;
414
+ clearBackgroundPendingInteraction(backgroundId) {
415
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
416
+ if (!bg) return;
417
+ bg.pendingInteraction = void 0;
404
418
  this.emit("interaction-resolved" /* INTERACTION_RESOLVED */);
405
419
  this.emit("status" /* STATUS */);
406
420
  }
@@ -416,18 +430,18 @@ var PRBEAgentState = class extends import_events.EventEmitter {
416
430
  this.emit("interaction-resolved" /* INTERACTION_RESOLVED */);
417
431
  this.emit("status" /* STATUS */);
418
432
  }
419
- resolveCRInteraction(crID, response) {
420
- const cr = this.activeCRs.get(crID);
421
- if (!cr || !cr.pendingInteraction) return;
422
- const resolved = cr.resolvedInteractions ?? [];
433
+ resolveBackgroundInteraction(backgroundId, response) {
434
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
435
+ if (!bg || !bg.pendingInteraction) return;
436
+ const resolved = bg.resolvedInteractions ?? [];
423
437
  resolved.push({
424
- interactionId: cr.pendingInteraction.interactionId,
425
- payload: cr.pendingInteraction,
438
+ interactionId: bg.pendingInteraction.interactionId,
439
+ payload: bg.pendingInteraction,
426
440
  response,
427
- eventIndex: cr.events.length
441
+ eventIndex: bg.events.length
428
442
  });
429
- cr.resolvedInteractions = resolved;
430
- cr.pendingInteraction = void 0;
443
+ bg.resolvedInteractions = resolved;
444
+ bg.pendingInteraction = void 0;
431
445
  this.emit("interaction-resolved" /* INTERACTION_RESOLVED */);
432
446
  this.emit("status" /* STATUS */);
433
447
  }
@@ -436,10 +450,10 @@ var PRBEAgentState = class extends import_events.EventEmitter {
436
450
  this.emit("agent-message" /* AGENT_MESSAGE */, { message });
437
451
  this.emit("status" /* STATUS */);
438
452
  }
439
- setCRAgentMessage(crID, message) {
440
- const cr = this.activeCRs.get(crID);
441
- if (!cr) return;
442
- cr.agentMessage = message;
453
+ setBackgroundAgentMessage(backgroundId, message) {
454
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
455
+ if (!bg) return;
456
+ bg.agentMessage = message;
443
457
  this.emit("agent-message" /* AGENT_MESSAGE */, { message });
444
458
  this.emit("status" /* STATUS */);
445
459
  }
@@ -450,14 +464,17 @@ var PRBEAgentState = class extends import_events.EventEmitter {
450
464
  this.emit("status" /* STATUS */);
451
465
  }
452
466
  }
453
- // ---------- CR state mutations ----------
454
- beginCR(id, query, slug, ticketId) {
455
- const cr = {
467
+ // ---------- Background investigation state mutations ----------
468
+ beginBackgroundInvestigation(id, query, slug, ticketId, source, sourceDetail) {
469
+ const bg = {
456
470
  id,
457
471
  query,
458
472
  slug,
459
473
  ticketId,
474
+ source,
475
+ sourceDetail,
460
476
  events: [],
477
+ conversationHistory: [],
461
478
  resolvedInteractions: [],
462
479
  isRunning: true,
463
480
  isCompleted: false,
@@ -466,20 +483,20 @@ var PRBEAgentState = class extends import_events.EventEmitter {
466
483
  summary: "",
467
484
  startedAt: /* @__PURE__ */ new Date()
468
485
  };
469
- this.activeCRs.set(id, cr);
470
- this.emit("cr-start" /* CR_START */, cr);
486
+ this.activeBackgroundInvestigations.set(id, bg);
487
+ this.emit("background-start" /* BACKGROUND_START */, bg);
471
488
  this.emit("status" /* STATUS */);
472
489
  }
473
- appendCREvent(crID, label, detail, completed = false) {
474
- const cr = this.activeCRs.get(crID);
475
- if (!cr) return;
476
- if (cr.events.length > 0) {
477
- const last = cr.events[cr.events.length - 1];
490
+ appendBackgroundEvent(backgroundId, label, detail, completed = false) {
491
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
492
+ if (!bg) return;
493
+ if (bg.events.length > 0) {
494
+ const last = bg.events[bg.events.length - 1];
478
495
  if (!last.isCompleted && !completed) {
479
496
  last.isCompleted = true;
480
497
  }
481
498
  }
482
- cr.events.push({
499
+ bg.events.push({
483
500
  id: (0, import_crypto.randomUUID)(),
484
501
  label,
485
502
  detail,
@@ -488,47 +505,47 @@ var PRBEAgentState = class extends import_events.EventEmitter {
488
505
  });
489
506
  this.emit("status" /* STATUS */);
490
507
  }
491
- attachCRObservation(crID, text) {
492
- const cr = this.activeCRs.get(crID);
493
- if (!cr || cr.events.length === 0) return;
494
- cr.events[cr.events.length - 1].detail = text;
508
+ attachBackgroundObservation(backgroundId, text) {
509
+ const bg = this.activeBackgroundInvestigations.get(backgroundId);
510
+ if (!bg || bg.events.length === 0) return;
511
+ bg.events[bg.events.length - 1].detail = text;
495
512
  this.emit("status" /* STATUS */);
496
513
  }
497
- completeCR(id, report) {
498
- const cr = this.activeCRs.get(id);
499
- if (!cr) return;
500
- this.activeCRs.delete(id);
501
- if (cr.events.length > 0) {
502
- cr.events[cr.events.length - 1].isCompleted = true;
514
+ completeBackgroundInvestigation(id, report) {
515
+ const bg = this.activeBackgroundInvestigations.get(id);
516
+ if (!bg) return;
517
+ this.activeBackgroundInvestigations.delete(id);
518
+ if (bg.events.length > 0) {
519
+ bg.events[bg.events.length - 1].isCompleted = true;
503
520
  }
504
- cr.events.push({
521
+ bg.events.push({
505
522
  id: (0, import_crypto.randomUUID)(),
506
523
  label: "Done",
507
524
  isCompleted: true,
508
525
  isExpanded: false
509
526
  });
510
- cr.isRunning = false;
511
- cr.isCompleted = true;
512
- cr.report = report;
513
- this.completedCRs.unshift(cr);
514
- this.emit("cr-complete" /* CR_COMPLETE */, cr);
527
+ bg.isRunning = false;
528
+ bg.isCompleted = true;
529
+ bg.report = report;
530
+ this.completedBackgroundInvestigations.unshift(bg);
531
+ this.emit("background-complete" /* BACKGROUND_COMPLETE */, bg);
515
532
  this.emit("status" /* STATUS */);
516
533
  }
517
- failCR(id, message) {
518
- const cr = this.activeCRs.get(id);
519
- if (!cr) return;
520
- this.activeCRs.delete(id);
521
- cr.events.push({
534
+ failBackgroundInvestigation(id, message) {
535
+ const bg = this.activeBackgroundInvestigations.get(id);
536
+ if (!bg) return;
537
+ this.activeBackgroundInvestigations.delete(id);
538
+ bg.events.push({
522
539
  id: (0, import_crypto.randomUUID)(),
523
540
  label: `Error: ${message}`,
524
541
  isCompleted: false,
525
542
  isExpanded: false
526
543
  });
527
- cr.isRunning = false;
528
- cr.isFailed = true;
529
- cr.errorMessage = message;
530
- this.completedCRs.unshift(cr);
531
- this.emit("cr-complete" /* CR_COMPLETE */, cr);
544
+ bg.isRunning = false;
545
+ bg.isFailed = true;
546
+ bg.errorMessage = message;
547
+ this.completedBackgroundInvestigations.unshift(bg);
548
+ this.emit("background-complete" /* BACKGROUND_COMPLETE */, bg);
532
549
  this.emit("status" /* STATUS */);
533
550
  }
534
551
  // ---------- Tickets ----------
@@ -542,6 +559,10 @@ var PRBEAgentState = class extends import_events.EventEmitter {
542
559
  this.emit("ticket-info" /* TICKET_INFO */, info);
543
560
  this.emit("status" /* STATUS */);
544
561
  }
562
+ updateAgentHistory(tickets) {
563
+ this.agentHistory = tickets;
564
+ this.emit("status" /* STATUS */);
565
+ }
545
566
  };
546
567
 
547
568
  // src/tools/index.ts
@@ -557,6 +578,7 @@ var InteractionType = /* @__PURE__ */ ((InteractionType2) => {
557
578
  var InvestigationSource = /* @__PURE__ */ ((InvestigationSource2) => {
558
579
  InvestigationSource2["USER"] = "user";
559
580
  InvestigationSource2["CONTEXT_REQUEST"] = "context_request";
581
+ InvestigationSource2["EXTERNAL_REQUEST"] = "external_request";
560
582
  return InvestigationSource2;
561
583
  })(InvestigationSource || {});
562
584
 
@@ -1764,197 +1786,20 @@ var BashExecuteTool = class {
1764
1786
  }
1765
1787
  };
1766
1788
 
1767
- // src/history.ts
1768
- var fs2 = __toESM(require("fs"));
1769
- var path4 = __toESM(require("path"));
1770
- var os = __toESM(require("os"));
1771
- var crypto = __toESM(require("crypto"));
1772
- var HKDF_SALT = Buffer.from("prbe-history-encryption-salt", "utf-8");
1773
- var HKDF_INFO = Buffer.from("prbe-history-v1", "utf-8");
1774
- function getAppDataDir() {
1789
+ // src/agent.ts
1790
+ function getPersistencePath() {
1775
1791
  const appData = process.env["APPDATA"] || (process.platform === "darwin" ? path4.join(os.homedir(), "Library", "Application Support") : path4.join(os.homedir(), ".local", "share"));
1776
- return path4.join(appData, "prbe-agent");
1777
- }
1778
- function getHistoryDir() {
1779
- const dir = path4.join(getAppDataDir(), "history" /* HISTORY_DIR */);
1792
+ const dir = path4.join(appData, "prbe-agent");
1780
1793
  if (!fs2.existsSync(dir)) {
1781
1794
  fs2.mkdirSync(dir, { recursive: true });
1782
1795
  }
1783
- return dir;
1784
- }
1785
- function deriveKey(apiKey) {
1786
- return Buffer.from(
1787
- crypto.hkdfSync(
1788
- "sha256",
1789
- Buffer.from(apiKey, "utf-8"),
1790
- HKDF_SALT,
1791
- HKDF_INFO,
1792
- 32 /* KEY_LENGTH */
1793
- )
1794
- );
1795
- }
1796
- function encrypt(plaintext, key) {
1797
- const iv = crypto.randomBytes(12 /* IV_LENGTH */);
1798
- const cipher = crypto.createCipheriv(
1799
- "aes-256-gcm" /* ALGORITHM */,
1800
- key,
1801
- iv,
1802
- { authTagLength: 16 /* AUTH_TAG_LENGTH */ }
1803
- );
1804
- const encrypted = Buffer.concat([cipher.update(plaintext, "utf-8"), cipher.final()]);
1805
- const authTag = cipher.getAuthTag();
1806
- return Buffer.concat([iv, authTag, encrypted]);
1807
- }
1808
- function decrypt(data, key) {
1809
- const iv = data.subarray(0, 12 /* IV_LENGTH */);
1810
- const authTag = data.subarray(
1811
- 12 /* IV_LENGTH */,
1812
- 12 /* IV_LENGTH */ + 16 /* AUTH_TAG_LENGTH */
1813
- );
1814
- const ciphertext = data.subarray(
1815
- 12 /* IV_LENGTH */ + 16 /* AUTH_TAG_LENGTH */
1816
- );
1817
- const decipher = crypto.createDecipheriv(
1818
- "aes-256-gcm" /* ALGORITHM */,
1819
- key,
1820
- iv,
1821
- { authTagLength: 16 /* AUTH_TAG_LENGTH */ }
1822
- );
1823
- decipher.setAuthTag(authTag);
1824
- return decipher.update(ciphertext) + decipher.final("utf-8");
1825
- }
1826
- var HistoryStore = class {
1827
- key;
1828
- constructor(apiKey) {
1829
- this.key = deriveKey(apiKey);
1830
- }
1831
- load() {
1832
- const investigations = [];
1833
- const crs = [];
1834
- try {
1835
- const dir = getHistoryDir();
1836
- let files;
1837
- try {
1838
- files = fs2.readdirSync(dir);
1839
- } catch {
1840
- return { investigations, crs };
1841
- }
1842
- for (const filename of files) {
1843
- try {
1844
- const filePath = path4.join(dir, filename);
1845
- const raw = fs2.readFileSync(filePath);
1846
- const json = decrypt(raw, this.key);
1847
- if (filename.startsWith("inv-") && filename.endsWith(".json")) {
1848
- const item = JSON.parse(json);
1849
- investigations.push({
1850
- ...item,
1851
- completedAt: new Date(item.completedAt)
1852
- });
1853
- } else if (filename.startsWith("cr-") && filename.endsWith(".json")) {
1854
- const item = JSON.parse(json);
1855
- crs.push({
1856
- ...item,
1857
- startedAt: new Date(item.startedAt),
1858
- resolvedInteractions: item.resolvedInteractions ?? []
1859
- });
1860
- }
1861
- } catch {
1862
- console.warn(`[PRBEAgent] Skipping unreadable history file: ${filename}`);
1863
- }
1864
- }
1865
- } catch {
1866
- }
1867
- investigations.sort(
1868
- (a, b) => b.completedAt.getTime() - a.completedAt.getTime()
1869
- );
1870
- crs.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());
1871
- return { investigations, crs };
1872
- }
1873
- save(investigations, crs) {
1874
- try {
1875
- const dir = getHistoryDir();
1876
- const desiredFiles = /* @__PURE__ */ new Set();
1877
- for (const inv of investigations) {
1878
- const filename = `inv-${inv.id}.json`;
1879
- desiredFiles.add(filename);
1880
- const data = {
1881
- id: inv.id,
1882
- query: inv.query,
1883
- report: inv.report,
1884
- summary: inv.summary,
1885
- ticketId: inv.ticketId,
1886
- events: inv.events,
1887
- resolvedInteractions: inv.resolvedInteractions,
1888
- conversationHistory: inv.conversationHistory,
1889
- completedAt: inv.completedAt.toISOString()
1890
- };
1891
- fs2.writeFileSync(
1892
- path4.join(dir, filename),
1893
- encrypt(JSON.stringify(data), this.key)
1894
- );
1895
- }
1896
- for (const cr of crs) {
1897
- const filename = `cr-${cr.id}.json`;
1898
- desiredFiles.add(filename);
1899
- const data = {
1900
- id: cr.id,
1901
- query: cr.query,
1902
- slug: cr.slug,
1903
- ticketId: cr.ticketId,
1904
- events: cr.events,
1905
- isRunning: cr.isRunning,
1906
- isCompleted: cr.isCompleted,
1907
- isFailed: cr.isFailed,
1908
- report: cr.report,
1909
- summary: cr.summary,
1910
- errorMessage: cr.errorMessage,
1911
- startedAt: cr.startedAt.toISOString(),
1912
- pendingInteraction: cr.pendingInteraction,
1913
- resolvedInteractions: cr.resolvedInteractions ?? []
1914
- };
1915
- fs2.writeFileSync(
1916
- path4.join(dir, filename),
1917
- encrypt(JSON.stringify(data), this.key)
1918
- );
1919
- }
1920
- try {
1921
- const existing = fs2.readdirSync(dir);
1922
- for (const filename of existing) {
1923
- if (!desiredFiles.has(filename)) {
1924
- fs2.unlinkSync(path4.join(dir, filename));
1925
- }
1926
- }
1927
- } catch {
1928
- }
1929
- } catch {
1930
- console.error("[PRBEAgent] Failed to save investigation history");
1931
- }
1932
- }
1933
- static clear() {
1934
- try {
1935
- const dir = path4.join(getAppDataDir(), "history" /* HISTORY_DIR */);
1936
- if (fs2.existsSync(dir)) {
1937
- fs2.rmSync(dir, { recursive: true, force: true });
1938
- }
1939
- } catch {
1940
- }
1941
- }
1942
- };
1943
-
1944
- // src/agent.ts
1945
- function getPersistencePath() {
1946
- const appData = process.env["APPDATA"] || (process.platform === "darwin" ? path5.join(os2.homedir(), "Library", "Application Support") : path5.join(os2.homedir(), ".local", "share"));
1947
- const dir = path5.join(appData, "prbe-agent");
1948
- if (!fs3.existsSync(dir)) {
1949
- fs3.mkdirSync(dir, { recursive: true });
1950
- }
1951
- return path5.join(dir, "agent-state.json");
1796
+ return path4.join(dir, "agent-state.json");
1952
1797
  }
1953
1798
  function loadPersistedData() {
1954
1799
  try {
1955
1800
  const filePath = getPersistencePath();
1956
- if (fs3.existsSync(filePath)) {
1957
- const raw = fs3.readFileSync(filePath, "utf-8");
1801
+ if (fs2.existsSync(filePath)) {
1802
+ const raw = fs2.readFileSync(filePath, "utf-8");
1958
1803
  return JSON.parse(raw);
1959
1804
  }
1960
1805
  } catch {
@@ -1964,7 +1809,7 @@ function loadPersistedData() {
1964
1809
  function savePersistedData(data) {
1965
1810
  try {
1966
1811
  const filePath = getPersistencePath();
1967
- fs3.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
1812
+ fs2.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
1968
1813
  } catch {
1969
1814
  console.error("[PRBEAgent] Failed to save persisted data");
1970
1815
  }
@@ -1984,10 +1829,12 @@ var PRBEAgent = class _PRBEAgent {
1984
1829
  persistedData;
1985
1830
  fetchAbortController = null;
1986
1831
  currentInvestigationSource = "user" /* USER */;
1987
- currentCRId = null;
1988
- historyStore;
1832
+ currentBackgroundId = null;
1989
1833
  /** Files flagged during the current tool call — uploaded immediately after the tool returns. */
1990
1834
  pendingFlaggedFiles = [];
1835
+ // ---------- User Identifier ----------
1836
+ userEmail;
1837
+ userId;
1991
1838
  // ---------- Persistence ----------
1992
1839
  get agentID() {
1993
1840
  if (this.persistedData.agentId) {
@@ -1998,30 +1845,6 @@ var PRBEAgent = class _PRBEAgent {
1998
1845
  savePersistedData(this.persistedData);
1999
1846
  return newID;
2000
1847
  }
2001
- get trackedSessionIDs() {
2002
- return this.persistedData.sessionIds ?? [];
2003
- }
2004
- set trackedSessionIDs(ids) {
2005
- this.persistedData.sessionIds = ids;
2006
- savePersistedData(this.persistedData);
2007
- this.state.updateTrackedSessionIDs(ids);
2008
- this.syncPolling(ids.length > 0);
2009
- }
2010
- syncPolling(hasSessions) {
2011
- if (this.config.backgroundPolling && hasSessions) {
2012
- if (this.pollingTimer === null) {
2013
- this.startPolling();
2014
- }
2015
- } else if (!hasSessions) {
2016
- this.stopPolling();
2017
- }
2018
- }
2019
- addTrackedSession(id) {
2020
- const ids = this.trackedSessionIDs;
2021
- if (!ids.includes(id)) {
2022
- this.trackedSessionIDs = [...ids, id];
2023
- }
2024
- }
2025
1848
  // ---------- Constructor ----------
2026
1849
  constructor(config) {
2027
1850
  this.config = {
@@ -2041,10 +1864,7 @@ var PRBEAgent = class _PRBEAgent {
2041
1864
  this.state = new PRBEAgentState();
2042
1865
  this.logCapture = new PRBELogCapture(this.config.maxLogEntries);
2043
1866
  this.persistedData = loadPersistedData();
2044
- this.historyStore = new HistoryStore(this.config.apiKey);
2045
- const history = this.historyStore.load();
2046
- this.state.completedInvestigations = history.investigations;
2047
- this.state.completedCRs = history.crs;
1867
+ void this.agentID;
2048
1868
  const roots = this.config.autoApprovedDirs;
2049
1869
  const requester = this.interactionHandler ? this : void 0;
2050
1870
  const grantedPaths = this.grantedPaths;
@@ -2076,8 +1896,8 @@ var PRBEAgent = class _PRBEAgent {
2076
1896
  [{ name: "message", type: "STRING" /* STRING */, description: "Message for the user", required: true }],
2077
1897
  async (args) => {
2078
1898
  const message = args["message"] ?? "";
2079
- if (this.currentInvestigationSource === "context_request" /* CONTEXT_REQUEST */ && this.currentCRId) {
2080
- this.state.setCRAgentMessage(this.currentCRId, message);
1899
+ if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
1900
+ this.state.setBackgroundAgentMessage(this.currentBackgroundId, message);
2081
1901
  } else {
2082
1902
  this.state.setAgentMessage(message);
2083
1903
  }
@@ -2094,9 +1914,8 @@ var PRBEAgent = class _PRBEAgent {
2094
1914
  if (config.ipcMain) {
2095
1915
  this.hookRendererLogs(config.ipcMain, config.rendererLogChannel ?? "prbe-renderer-log");
2096
1916
  }
2097
- const existingSessions = this.trackedSessionIDs;
2098
- if (existingSessions.length > 0) {
2099
- this.trackedSessionIDs = existingSessions;
1917
+ if (this.config.backgroundPolling) {
1918
+ this.startPolling();
2100
1919
  }
2101
1920
  }
2102
1921
  // ---------- Log integration ----------
@@ -2150,15 +1969,15 @@ var PRBEAgent = class _PRBEAgent {
2150
1969
  "No interaction handler configured"
2151
1970
  );
2152
1971
  }
2153
- if (this.currentInvestigationSource === "context_request" /* CONTEXT_REQUEST */ && this.currentCRId) {
2154
- this.state.setCRPendingInteraction(this.currentCRId, payload);
1972
+ if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
1973
+ this.state.setBackgroundPendingInteraction(this.currentBackgroundId, payload);
2155
1974
  } else {
2156
1975
  this.state.setPendingInteraction(payload);
2157
1976
  }
2158
1977
  try {
2159
1978
  const response = await this.interactionHandler.handleInteraction(payload);
2160
- if (this.currentInvestigationSource === "context_request" /* CONTEXT_REQUEST */ && this.currentCRId) {
2161
- this.state.resolveCRInteraction(this.currentCRId, response);
1979
+ if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
1980
+ this.state.resolveBackgroundInteraction(this.currentBackgroundId, response);
2162
1981
  } else {
2163
1982
  this.state.resolveInteraction(response);
2164
1983
  }
@@ -2171,8 +1990,8 @@ var PRBEAgent = class _PRBEAgent {
2171
1990
  }
2172
1991
  return response;
2173
1992
  } catch (err) {
2174
- if (this.currentInvestigationSource === "context_request" /* CONTEXT_REQUEST */ && this.currentCRId) {
2175
- this.state.clearCRPendingInteraction(this.currentCRId);
1993
+ if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
1994
+ this.state.clearBackgroundPendingInteraction(this.currentBackgroundId);
2176
1995
  } else {
2177
1996
  this.state.clearPendingInteraction();
2178
1997
  }
@@ -2195,6 +2014,47 @@ var PRBEAgent = class _PRBEAgent {
2195
2014
  updateSessionMetadata(metadata) {
2196
2015
  this.sessionMetadata = { ...this.sessionMetadata, ...metadata };
2197
2016
  }
2017
+ /**
2018
+ * Set a user identifier for this agent. Persists to the backend agents table.
2019
+ * Can be called multiple times with different types to set both email and ID.
2020
+ * Also auto-injects user_email and/or user_id into session metadata for investigations.
2021
+ */
2022
+ setUserIdentifier(type, value) {
2023
+ if (type === "email" /* EMAIL */) {
2024
+ this.userEmail = value;
2025
+ } else {
2026
+ this.userId = value;
2027
+ }
2028
+ this.syncUserIdentifierToBackend(type, value);
2029
+ }
2030
+ /**
2031
+ * Clear user identifier(s) for this agent.
2032
+ * Pass a specific type to clear only that identifier, or omit to clear both email and ID.
2033
+ */
2034
+ clearUserIdentifier(type) {
2035
+ if (type) {
2036
+ if (type === "email" /* EMAIL */) {
2037
+ this.userEmail = void 0;
2038
+ } else {
2039
+ this.userId = void 0;
2040
+ }
2041
+ this.syncUserIdentifierToBackend(type, null);
2042
+ } else {
2043
+ this.userEmail = void 0;
2044
+ this.userId = void 0;
2045
+ this.syncUserIdentifierToBackend("email" /* EMAIL */, null);
2046
+ this.syncUserIdentifierToBackend("id" /* ID */, null);
2047
+ }
2048
+ }
2049
+ syncUserIdentifierToBackend(type, value) {
2050
+ void this.post("/api/agent/update-user", {
2051
+ agent_id: this.agentID,
2052
+ identifier_type: type,
2053
+ identifier_value: value
2054
+ }).catch((err) => {
2055
+ console.error(`[PRBEAgent] Failed to sync user identifier: ${err}`);
2056
+ });
2057
+ }
2198
2058
  /**
2199
2059
  * Register a custom tool that the middleware can invoke during investigations.
2200
2060
  */
@@ -2203,58 +2063,92 @@ var PRBEAgent = class _PRBEAgent {
2203
2063
  new PRBEClosureTool(name, description, parameters, handler, options)
2204
2064
  );
2205
2065
  }
2206
- /**
2207
- * User-initiated investigation. Updates `state` events/report directly.
2208
- */
2209
- async investigate(query, contextRequestID) {
2210
- this.userCancelled = false;
2211
- this.currentInvestigationSource = "user" /* USER */;
2212
- this.currentCRId = null;
2213
- this.state.beginInvestigation(query);
2066
+ // ---------- Unified Investigation ----------
2067
+ async runInvestigation(opts) {
2068
+ this.currentInvestigationSource = opts.source;
2069
+ this.currentBackgroundId = opts.sourceId ?? null;
2070
+ const isBackground = opts.source !== "user" /* USER */;
2214
2071
  const emitter = (status) => {
2215
2072
  switch (status.type) {
2216
2073
  case "started" /* STARTED */:
2217
- this.state.appendEvent("Starting investigation...");
2074
+ if (isBackground && opts.sourceId) {
2075
+ this.state.appendBackgroundEvent(opts.sourceId, "Starting investigation...");
2076
+ } else {
2077
+ this.state.appendEvent("Starting investigation...");
2078
+ }
2218
2079
  break;
2219
2080
  case "thinking" /* THINKING */:
2220
2081
  break;
2221
2082
  case "tool_call" /* TOOL_CALL */:
2222
- this.state.appendEvent(status.label);
2083
+ if (isBackground && opts.sourceId) {
2084
+ this.state.appendBackgroundEvent(opts.sourceId, status.label);
2085
+ } else {
2086
+ this.state.appendEvent(status.label);
2087
+ }
2223
2088
  break;
2224
2089
  case "observation" /* OBSERVATION */:
2225
- this.state.attachObservation(status.text);
2090
+ if (isBackground && opts.sourceId) {
2091
+ this.state.attachBackgroundObservation(opts.sourceId, status.text);
2092
+ } else {
2093
+ this.state.attachObservation(status.text);
2094
+ }
2226
2095
  break;
2227
2096
  case "thought" /* THOUGHT */:
2228
- this.state.appendEvent("Thinking", status.text);
2097
+ if (isBackground && opts.sourceId) {
2098
+ this.state.appendBackgroundEvent(opts.sourceId, "Thinking", status.text);
2099
+ } else {
2100
+ this.state.appendEvent("Thinking", status.text);
2101
+ }
2229
2102
  break;
2230
2103
  case "completed" /* COMPLETED */:
2231
- this.state.completeInvestigation(status.report, status.ticketId);
2232
- this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2104
+ if (isBackground && opts.sourceId) {
2105
+ this.state.completeBackgroundInvestigation(opts.sourceId, status.report);
2106
+ } else {
2107
+ this.state.completeInvestigation(status.report, status.ticketId);
2108
+ }
2233
2109
  break;
2234
2110
  case "error" /* ERROR */:
2235
- this.state.failInvestigation(status.message);
2111
+ if (isBackground && opts.sourceId) {
2112
+ this.state.failBackgroundInvestigation(opts.sourceId, status.message);
2113
+ } else {
2114
+ this.state.failInvestigation(status.message);
2115
+ }
2236
2116
  break;
2237
2117
  }
2238
2118
  };
2239
2119
  const result = await this.connectToProxy(
2240
- query,
2241
- contextRequestID,
2120
+ opts.query,
2121
+ opts.contextRequestId,
2122
+ opts.externalRequestId,
2123
+ opts.externalRequestSource,
2124
+ opts.externalRequestSourceDetail,
2242
2125
  emitter,
2243
- () => this.userCancelled
2126
+ opts.cancellable ? () => this.userCancelled : () => false,
2127
+ opts.ticketId
2244
2128
  );
2245
2129
  this.currentInvestigationSource = "user" /* USER */;
2246
- this.currentCRId = null;
2247
- if (result?.sessionId) {
2248
- this.addTrackedSession(result.sessionId);
2249
- } else if (!result) {
2250
- if (this.state.isInvestigating) {
2251
- const message = this.userCancelled ? "Investigation cancelled" : "Investigation ended unexpectedly";
2252
- this.state.failInvestigation(message);
2253
- }
2130
+ this.currentBackgroundId = null;
2131
+ return result;
2132
+ }
2133
+ /**
2134
+ * User-initiated investigation. Updates `state` events/report directly.
2135
+ */
2136
+ async investigate(query, contextRequestID) {
2137
+ this.userCancelled = false;
2138
+ this.state.beginInvestigation(query);
2139
+ const result = await this.runInvestigation({
2140
+ query,
2141
+ source: "user" /* USER */,
2142
+ contextRequestId: contextRequestID,
2143
+ cancellable: true
2144
+ });
2145
+ if (!result && this.state.isInvestigating) {
2146
+ const message = this.userCancelled ? "Investigation cancelled" : "Investigation ended unexpectedly";
2147
+ this.state.failInvestigation(message);
2254
2148
  }
2255
2149
  }
2256
2150
  /**
2257
- * Cancel user-initiated investigation only (does not cancel background CRs).
2151
+ * Cancel user-initiated investigation only (does not cancel background investigations).
2258
2152
  */
2259
2153
  cancelInvestigation() {
2260
2154
  this.userCancelled = true;
@@ -2276,41 +2170,21 @@ var PRBEAgent = class _PRBEAgent {
2276
2170
  this.stopPolling();
2277
2171
  }
2278
2172
  /**
2279
- * Poll the backend for context requests on tracked tickets.
2280
- * Resolves session IDs → ticket IDs first, then polls with ticket IDs.
2173
+ * Poll the backend for context requests and external requests.
2281
2174
  */
2282
2175
  async poll() {
2283
- const sessionIDs = this.trackedSessionIDs;
2284
- if (sessionIDs.length === 0) return null;
2285
2176
  try {
2286
- const resolved = await this.resolveSessions(sessionIDs);
2287
- const returnedSessionIDs = new Set(
2288
- resolved.tickets.flatMap((t) => t.session_ids)
2289
- );
2290
- const resolvedSessionIDs = new Set(
2291
- resolved.tickets.filter((t) => t.status === "resolved").flatMap((t) => t.session_ids)
2292
- );
2293
- const survivingSessions = sessionIDs.filter(
2294
- (id) => returnedSessionIDs.has(id) && !resolvedSessionIDs.has(id)
2295
- );
2296
- if (survivingSessions.length !== sessionIDs.length) {
2297
- this.trackedSessionIDs = survivingSessions;
2177
+ const request = { agent_id: this.agentID };
2178
+ const response = await this.post("/api/agent/poll", request);
2179
+ for (const cr of response.context_requests) {
2180
+ if (!cr.is_active) continue;
2181
+ if (this.state.activeBackgroundInvestigations.has(cr.id)) continue;
2182
+ await this.investigateForCR(cr, cr.ticket_id);
2298
2183
  }
2299
- const ticketIDs = resolved.tickets.filter((t) => t.status !== "resolved").map((t) => t.ticket_id);
2300
- if (ticketIDs.length === 0) return { tickets: [] };
2301
- const request = {
2302
- agent_id: this.agentID,
2303
- ticket_ids: ticketIDs
2304
- };
2305
- const response = await this.post(
2306
- "/api/agent/poll",
2307
- request
2308
- );
2309
- for (const ticket of response.tickets) {
2310
- for (const cr of ticket.context_requests) {
2311
- if (!cr.is_active) continue;
2312
- await this.investigateForCR(cr, ticket.ticket_id);
2313
- }
2184
+ for (const er of response.external_requests) {
2185
+ if (!er.is_active) continue;
2186
+ if (this.state.activeBackgroundInvestigations.has(er.id)) continue;
2187
+ await this.investigateForER(er);
2314
2188
  }
2315
2189
  return response;
2316
2190
  } catch {
@@ -2318,25 +2192,18 @@ var PRBEAgent = class _PRBEAgent {
2318
2192
  }
2319
2193
  }
2320
2194
  /**
2321
- * Fetch ticket display info for all tracked sessions.
2322
- * Resolves session IDs → ticket IDs first, then fetches ticket info.
2195
+ * Fetch agent history (tickets + sessions) from the backend.
2323
2196
  */
2324
- async fetchTicketInfo() {
2325
- const sessionIDs = this.trackedSessionIDs;
2326
- if (sessionIDs.length === 0) return [];
2197
+ async fetchHistory() {
2327
2198
  try {
2328
- const resolved = await this.resolveSessions(sessionIDs);
2329
- const ticketIDs = resolved.tickets.map((t) => t.ticket_id);
2330
- if (ticketIDs.length === 0) return [];
2331
- const request = { ticket_ids: ticketIDs };
2332
2199
  const response = await this.post(
2333
- "/api/agent/tickets",
2334
- request
2200
+ "/api/agent/history",
2201
+ { agent_id: this.agentID }
2335
2202
  );
2336
- this.state.updateTicketInfo(response.tickets);
2337
- return response.tickets;
2203
+ this.state.updateAgentHistory(response.tickets);
2204
+ return response;
2338
2205
  } catch {
2339
- return [];
2206
+ return null;
2340
2207
  }
2341
2208
  }
2342
2209
  stopPolling() {
@@ -2346,7 +2213,7 @@ var PRBEAgent = class _PRBEAgent {
2346
2213
  }
2347
2214
  }
2348
2215
  resumePolling() {
2349
- if (this.trackedSessionIDs.length === 0) return;
2216
+ if (!this.config.backgroundPolling) return;
2350
2217
  this.startPolling();
2351
2218
  }
2352
2219
  /**
@@ -2364,13 +2231,11 @@ var PRBEAgent = class _PRBEAgent {
2364
2231
  this.stopPolling();
2365
2232
  this.persistedData = {};
2366
2233
  savePersistedData(this.persistedData);
2367
- HistoryStore.clear();
2368
2234
  this.state.resetInvestigation();
2369
2235
  this.state.completedInvestigations = [];
2370
- this.state.activeCRs.clear();
2371
- this.state.completedCRs = [];
2372
- this.state.trackedSessionIDs = [];
2373
- this.state.ticketInfo = [];
2236
+ this.state.activeBackgroundInvestigations.clear();
2237
+ this.state.completedBackgroundInvestigations = [];
2238
+ this.state.agentHistory = [];
2374
2239
  this.state.emit("status" /* STATUS */);
2375
2240
  }
2376
2241
  /**
@@ -2379,61 +2244,38 @@ var PRBEAgent = class _PRBEAgent {
2379
2244
  static clearPersistedData() {
2380
2245
  try {
2381
2246
  const filePath = getPersistencePath();
2382
- if (fs3.existsSync(filePath)) {
2383
- fs3.unlinkSync(filePath);
2247
+ if (fs2.existsSync(filePath)) {
2248
+ fs2.unlinkSync(filePath);
2384
2249
  }
2385
- HistoryStore.clear();
2386
2250
  } catch {
2387
2251
  }
2388
2252
  }
2389
- // ---------- CR Investigation ----------
2253
+ // ---------- Background Investigation ----------
2390
2254
  async investigateForCR(cr, ticketId) {
2391
- const crID = cr.id;
2392
- this.currentInvestigationSource = "context_request" /* CONTEXT_REQUEST */;
2393
- this.currentCRId = crID;
2394
- this.state.beginCR(crID, cr.query, cr.slug ?? void 0, ticketId);
2395
- const emitter = (status) => {
2396
- switch (status.type) {
2397
- case "started" /* STARTED */:
2398
- this.state.appendCREvent(crID, "Starting investigation...");
2399
- break;
2400
- case "thinking" /* THINKING */:
2401
- break;
2402
- case "tool_call" /* TOOL_CALL */:
2403
- this.state.appendCREvent(crID, status.label);
2404
- break;
2405
- case "observation" /* OBSERVATION */:
2406
- this.state.attachCRObservation(crID, status.text);
2407
- break;
2408
- case "thought" /* THOUGHT */:
2409
- this.state.appendCREvent(crID, "Thinking", status.text);
2410
- break;
2411
- case "completed" /* COMPLETED */:
2412
- this.state.completeCR(crID, status.report);
2413
- this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2414
- break;
2415
- case "error" /* ERROR */:
2416
- this.state.failCR(crID, status.message);
2417
- this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
2418
- break;
2419
- }
2420
- };
2421
- const result = await this.connectToProxy(
2422
- cr.query,
2423
- crID,
2424
- emitter,
2425
- () => false,
2426
- // CRs are not user-cancellable
2427
- ticketId
2428
- );
2429
- this.currentInvestigationSource = "user" /* USER */;
2430
- this.currentCRId = null;
2431
- if (result?.sessionId) {
2432
- this.addTrackedSession(result.sessionId);
2433
- }
2255
+ this.state.beginBackgroundInvestigation(cr.id, cr.query, cr.slug ?? void 0, ticketId);
2256
+ await this.runInvestigation({
2257
+ query: cr.query,
2258
+ source: "context_request" /* CONTEXT_REQUEST */,
2259
+ sourceId: cr.id,
2260
+ contextRequestId: cr.id,
2261
+ ticketId,
2262
+ cancellable: false
2263
+ });
2264
+ }
2265
+ async investigateForER(er) {
2266
+ this.state.beginBackgroundInvestigation(er.id, er.query, void 0, void 0, er.source, er.source_detail);
2267
+ await this.runInvestigation({
2268
+ query: er.query,
2269
+ source: "external_request" /* EXTERNAL_REQUEST */,
2270
+ sourceId: er.id,
2271
+ externalRequestId: er.id,
2272
+ externalRequestSource: er.source,
2273
+ externalRequestSourceDetail: er.source_detail,
2274
+ cancellable: false
2275
+ });
2434
2276
  }
2435
2277
  // ---------- WebSocket Investigation ----------
2436
- connectToProxy(query, contextRequestID, emit, isCancelled, ticketId) {
2278
+ connectToProxy(query, contextRequestID, externalRequestId, externalRequestSource, externalRequestSourceDetail, emit, isCancelled, ticketId) {
2437
2279
  return new Promise((resolve2) => {
2438
2280
  const wsUrl = `${MIDDLEWARE_URL}/api/agent/client/ws`;
2439
2281
  let uploadBaseUrl;
@@ -2488,15 +2330,25 @@ var PRBEAgent = class _PRBEAgent {
2488
2330
  const startMetadata = {
2489
2331
  agent_id: this.agentID,
2490
2332
  custom_tools: toolDeclarations,
2491
- platform: os2.platform(),
2492
- os_version: os2.release(),
2493
- arch: os2.arch()
2333
+ platform: os.platform(),
2334
+ os_version: os.release(),
2335
+ arch: os.arch()
2494
2336
  };
2495
2337
  if (contextRequestID) startMetadata["context_request_id"] = contextRequestID;
2338
+ if (externalRequestId) startMetadata["external_request_id"] = externalRequestId;
2339
+ if (externalRequestSource) startMetadata["external_request_source"] = externalRequestSource;
2340
+ if (externalRequestSourceDetail) startMetadata["external_request_source_detail"] = externalRequestSourceDetail;
2496
2341
  if (ticketId) startMetadata["ticket_id"] = ticketId;
2497
2342
  if (this.appDataPath) startMetadata["app_data_path"] = this.appDataPath;
2498
- if (Object.keys(this.sessionMetadata).length > 0) {
2499
- startMetadata["session_metadata"] = this.sessionMetadata;
2343
+ const enrichedMetadata = { ...this.sessionMetadata };
2344
+ if (this.userEmail) {
2345
+ enrichedMetadata["user_email"] = this.userEmail;
2346
+ }
2347
+ if (this.userId) {
2348
+ enrichedMetadata["user_id"] = this.userId;
2349
+ }
2350
+ if (Object.keys(enrichedMetadata).length > 0) {
2351
+ startMetadata["session_metadata"] = enrichedMetadata;
2500
2352
  }
2501
2353
  if (!conn.send({ type: "start" /* START */, content: query, metadata: startMetadata })) {
2502
2354
  emit({ type: "error" /* ERROR */, message: "Failed to send start message" });
@@ -2533,7 +2385,7 @@ var PRBEAgent = class _PRBEAgent {
2533
2385
  const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
2534
2386
  const uploadedRefs = [];
2535
2387
  for (const file of this.pendingFlaggedFiles) {
2536
- const filename = path5.basename(file.originalPath);
2388
+ const filename = path4.basename(file.originalPath);
2537
2389
  const safeName = encodeURIComponent(filename);
2538
2390
  const storagePath = `${uploadPrefix}/${safeName}`;
2539
2391
  uploadedRefs.push({
@@ -2578,7 +2430,11 @@ var PRBEAgent = class _PRBEAgent {
2578
2430
  case "conversation_update" /* CONVERSATION_UPDATE */: {
2579
2431
  try {
2580
2432
  const entry = JSON.parse(msg.content ?? "{}");
2581
- this.state.appendConversation(entry);
2433
+ if (this.currentInvestigationSource !== "user" /* USER */ && this.currentBackgroundId) {
2434
+ this.state.appendBackgroundConversation(this.currentBackgroundId, entry);
2435
+ } else {
2436
+ this.state.appendConversation(entry);
2437
+ }
2582
2438
  } catch {
2583
2439
  }
2584
2440
  break;
@@ -2636,24 +2492,9 @@ var PRBEAgent = class _PRBEAgent {
2636
2492
  startPolling() {
2637
2493
  this.stopPolling();
2638
2494
  this.pollingTimer = setInterval(() => {
2639
- void this.poll().then(() => {
2640
- if (this.trackedSessionIDs.length === 0) {
2641
- this.stopPolling();
2642
- }
2643
- });
2495
+ void this.poll();
2644
2496
  }, this.config.pollingInterval);
2645
2497
  }
2646
- // ---------- Session Resolution ----------
2647
- async resolveSessions(sessionIDs) {
2648
- const request = {
2649
- agent_id: this.agentID,
2650
- session_ids: sessionIDs
2651
- };
2652
- return this.post(
2653
- "/api/agent/resolve-sessions",
2654
- request
2655
- );
2656
- }
2657
2498
  // ---------- Networking ----------
2658
2499
  /**
2659
2500
  * Abort all in-flight fetch requests to prevent orphaned DNS lookups
@@ -2707,29 +2548,32 @@ var DEFAULT_PRBE_STATE = {
2707
2548
  resolvedInteractions: [],
2708
2549
  conversationHistory: [],
2709
2550
  completedInvestigations: [],
2710
- activeCRs: [],
2711
- completedCRs: [],
2712
- trackedSessionIDs: [],
2551
+ activeBackgroundInvestigations: [],
2552
+ completedBackgroundInvestigations: [],
2713
2553
  ticketInfo: [],
2554
+ agentHistory: [],
2714
2555
  hasActiveWork: false
2715
2556
  };
2716
- function serializeCR(cr) {
2557
+ function serializeBackgroundInvestigation(bg) {
2717
2558
  return {
2718
- id: cr.id,
2719
- query: cr.query,
2720
- slug: cr.slug,
2721
- ticketId: cr.ticketId,
2722
- events: cr.events,
2723
- isRunning: cr.isRunning,
2724
- isCompleted: cr.isCompleted,
2725
- isFailed: cr.isFailed,
2726
- report: cr.report,
2727
- summary: cr.summary,
2728
- errorMessage: cr.errorMessage,
2729
- agentMessage: cr.agentMessage,
2730
- startedAt: cr.startedAt.toISOString(),
2731
- pendingInteraction: cr.pendingInteraction,
2732
- resolvedInteractions: cr.resolvedInteractions ?? []
2559
+ id: bg.id,
2560
+ query: bg.query,
2561
+ slug: bg.slug,
2562
+ ticketId: bg.ticketId,
2563
+ source: bg.source,
2564
+ sourceDetail: bg.sourceDetail,
2565
+ events: bg.events,
2566
+ isRunning: bg.isRunning,
2567
+ isCompleted: bg.isCompleted,
2568
+ isFailed: bg.isFailed,
2569
+ report: bg.report,
2570
+ summary: bg.summary,
2571
+ errorMessage: bg.errorMessage,
2572
+ agentMessage: bg.agentMessage,
2573
+ startedAt: bg.startedAt.toISOString(),
2574
+ pendingInteraction: bg.pendingInteraction,
2575
+ resolvedInteractions: bg.resolvedInteractions ?? [],
2576
+ conversationHistory: bg.conversationHistory ?? []
2733
2577
  };
2734
2578
  }
2735
2579
  function serializePRBEState(state) {
@@ -2755,10 +2599,10 @@ function serializePRBEState(state) {
2755
2599
  conversationHistory: inv.conversationHistory,
2756
2600
  completedAt: inv.completedAt.toISOString()
2757
2601
  })),
2758
- activeCRs: Array.from(state.activeCRs.values()).map(serializeCR),
2759
- completedCRs: state.completedCRs.map(serializeCR),
2760
- trackedSessionIDs: state.trackedSessionIDs,
2602
+ activeBackgroundInvestigations: Array.from(state.activeBackgroundInvestigations.values()).map(serializeBackgroundInvestigation),
2603
+ completedBackgroundInvestigations: state.completedBackgroundInvestigations.map(serializeBackgroundInvestigation),
2761
2604
  ticketInfo: state.ticketInfo,
2605
+ agentHistory: state.agentHistory,
2762
2606
  hasActiveWork: state.hasActiveWork
2763
2607
  };
2764
2608
  }
@@ -2802,6 +2646,7 @@ var PROBE_MARK_SVG = `<svg width="256" height="256" viewBox="0 0 256 256" fill="
2802
2646
  SearchContentTool,
2803
2647
  ToolName,
2804
2648
  ToolParamType,
2649
+ UserIdentifierType,
2805
2650
  WSMessageType,
2806
2651
  humanReadableSize,
2807
2652
  redactPII,