@prbe.ai/electron-sdk 0.1.6 → 0.1.7

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,7 +1,7 @@
1
1
  // src/agent.ts
2
- import * as fs2 from "fs";
3
- import * as path4 from "path";
4
- import * as os from "os";
2
+ import * as fs3 from "fs";
3
+ import * as path5 from "path";
4
+ import * as os2 from "os";
5
5
  import { randomUUID as randomUUID5 } from "crypto";
6
6
 
7
7
  // src/models.ts
@@ -180,7 +180,7 @@ var PRBEAgentState = class extends EventEmitter {
180
180
  this.emit("status" /* STATUS */);
181
181
  }
182
182
  }
183
- completeInvestigation(report, summary) {
183
+ completeInvestigation(report, summary, ticketId) {
184
184
  if (this.events.length > 0) {
185
185
  this.events[this.events.length - 1].isCompleted = true;
186
186
  }
@@ -190,6 +190,9 @@ var PRBEAgentState = class extends EventEmitter {
190
190
  query: this.currentQuery,
191
191
  report,
192
192
  summary,
193
+ ticketId,
194
+ events: [...this.events],
195
+ resolvedInteractions: [...this.resolvedInteractions],
193
196
  completedAt: /* @__PURE__ */ new Date()
194
197
  });
195
198
  this.report = report;
@@ -265,11 +268,12 @@ var PRBEAgentState = class extends EventEmitter {
265
268
  }
266
269
  }
267
270
  // ---------- CR state mutations ----------
268
- beginCR(id, query, slug) {
271
+ beginCR(id, query, slug, ticketId) {
269
272
  const cr = {
270
273
  id,
271
274
  query,
272
275
  slug,
276
+ ticketId,
273
277
  events: [],
274
278
  resolvedInteractions: [],
275
279
  isRunning: true,
@@ -1499,20 +1503,196 @@ var BashExecuteTool = class {
1499
1503
  }
1500
1504
  };
1501
1505
 
1502
- // src/agent.ts
1503
- function getPersistencePath() {
1506
+ // src/history.ts
1507
+ import * as fs2 from "fs";
1508
+ import * as path4 from "path";
1509
+ import * as os from "os";
1510
+ import * as crypto from "crypto";
1511
+ var HKDF_SALT = Buffer.from("prbe-history-encryption-salt", "utf-8");
1512
+ var HKDF_INFO = Buffer.from("prbe-history-v1", "utf-8");
1513
+ function getAppDataDir() {
1504
1514
  const appData = process.env["APPDATA"] || (process.platform === "darwin" ? path4.join(os.homedir(), "Library", "Application Support") : path4.join(os.homedir(), ".local", "share"));
1505
- const dir = path4.join(appData, "prbe-agent");
1515
+ return path4.join(appData, "prbe-agent");
1516
+ }
1517
+ function getHistoryDir() {
1518
+ const dir = path4.join(getAppDataDir(), "history" /* HISTORY_DIR */);
1506
1519
  if (!fs2.existsSync(dir)) {
1507
1520
  fs2.mkdirSync(dir, { recursive: true });
1508
1521
  }
1509
- return path4.join(dir, "agent-state.json");
1522
+ return dir;
1523
+ }
1524
+ function deriveKey(apiKey) {
1525
+ return Buffer.from(
1526
+ crypto.hkdfSync(
1527
+ "sha256",
1528
+ Buffer.from(apiKey, "utf-8"),
1529
+ HKDF_SALT,
1530
+ HKDF_INFO,
1531
+ 32 /* KEY_LENGTH */
1532
+ )
1533
+ );
1534
+ }
1535
+ function encrypt(plaintext, key) {
1536
+ const iv = crypto.randomBytes(12 /* IV_LENGTH */);
1537
+ const cipher = crypto.createCipheriv(
1538
+ "aes-256-gcm" /* ALGORITHM */,
1539
+ key,
1540
+ iv,
1541
+ { authTagLength: 16 /* AUTH_TAG_LENGTH */ }
1542
+ );
1543
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf-8"), cipher.final()]);
1544
+ const authTag = cipher.getAuthTag();
1545
+ return Buffer.concat([iv, authTag, encrypted]);
1546
+ }
1547
+ function decrypt(data, key) {
1548
+ const iv = data.subarray(0, 12 /* IV_LENGTH */);
1549
+ const authTag = data.subarray(
1550
+ 12 /* IV_LENGTH */,
1551
+ 12 /* IV_LENGTH */ + 16 /* AUTH_TAG_LENGTH */
1552
+ );
1553
+ const ciphertext = data.subarray(
1554
+ 12 /* IV_LENGTH */ + 16 /* AUTH_TAG_LENGTH */
1555
+ );
1556
+ const decipher = crypto.createDecipheriv(
1557
+ "aes-256-gcm" /* ALGORITHM */,
1558
+ key,
1559
+ iv,
1560
+ { authTagLength: 16 /* AUTH_TAG_LENGTH */ }
1561
+ );
1562
+ decipher.setAuthTag(authTag);
1563
+ return decipher.update(ciphertext) + decipher.final("utf-8");
1564
+ }
1565
+ var HistoryStore = class {
1566
+ key;
1567
+ constructor(apiKey) {
1568
+ this.key = deriveKey(apiKey);
1569
+ }
1570
+ load() {
1571
+ const investigations = [];
1572
+ const crs = [];
1573
+ try {
1574
+ const dir = getHistoryDir();
1575
+ let files;
1576
+ try {
1577
+ files = fs2.readdirSync(dir);
1578
+ } catch {
1579
+ return { investigations, crs };
1580
+ }
1581
+ for (const filename of files) {
1582
+ try {
1583
+ const filePath = path4.join(dir, filename);
1584
+ const raw = fs2.readFileSync(filePath);
1585
+ const json = decrypt(raw, this.key);
1586
+ if (filename.startsWith("inv-") && filename.endsWith(".json")) {
1587
+ const item = JSON.parse(json);
1588
+ investigations.push({
1589
+ ...item,
1590
+ completedAt: new Date(item.completedAt)
1591
+ });
1592
+ } else if (filename.startsWith("cr-") && filename.endsWith(".json")) {
1593
+ const item = JSON.parse(json);
1594
+ crs.push({
1595
+ ...item,
1596
+ startedAt: new Date(item.startedAt),
1597
+ resolvedInteractions: item.resolvedInteractions ?? []
1598
+ });
1599
+ }
1600
+ } catch {
1601
+ console.warn(`[PRBEAgent] Skipping unreadable history file: ${filename}`);
1602
+ }
1603
+ }
1604
+ } catch {
1605
+ }
1606
+ investigations.sort(
1607
+ (a, b) => b.completedAt.getTime() - a.completedAt.getTime()
1608
+ );
1609
+ crs.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());
1610
+ return { investigations, crs };
1611
+ }
1612
+ save(investigations, crs) {
1613
+ try {
1614
+ const dir = getHistoryDir();
1615
+ const desiredFiles = /* @__PURE__ */ new Set();
1616
+ for (const inv of investigations) {
1617
+ const filename = `inv-${inv.id}.json`;
1618
+ desiredFiles.add(filename);
1619
+ const data = {
1620
+ id: inv.id,
1621
+ query: inv.query,
1622
+ report: inv.report,
1623
+ summary: inv.summary,
1624
+ ticketId: inv.ticketId,
1625
+ events: inv.events,
1626
+ resolvedInteractions: inv.resolvedInteractions,
1627
+ completedAt: inv.completedAt.toISOString()
1628
+ };
1629
+ fs2.writeFileSync(
1630
+ path4.join(dir, filename),
1631
+ encrypt(JSON.stringify(data), this.key)
1632
+ );
1633
+ }
1634
+ for (const cr of crs) {
1635
+ const filename = `cr-${cr.id}.json`;
1636
+ desiredFiles.add(filename);
1637
+ const data = {
1638
+ id: cr.id,
1639
+ query: cr.query,
1640
+ slug: cr.slug,
1641
+ ticketId: cr.ticketId,
1642
+ events: cr.events,
1643
+ isRunning: cr.isRunning,
1644
+ isCompleted: cr.isCompleted,
1645
+ isFailed: cr.isFailed,
1646
+ report: cr.report,
1647
+ summary: cr.summary,
1648
+ errorMessage: cr.errorMessage,
1649
+ startedAt: cr.startedAt.toISOString(),
1650
+ pendingInteraction: cr.pendingInteraction,
1651
+ resolvedInteractions: cr.resolvedInteractions ?? []
1652
+ };
1653
+ fs2.writeFileSync(
1654
+ path4.join(dir, filename),
1655
+ encrypt(JSON.stringify(data), this.key)
1656
+ );
1657
+ }
1658
+ try {
1659
+ const existing = fs2.readdirSync(dir);
1660
+ for (const filename of existing) {
1661
+ if (!desiredFiles.has(filename)) {
1662
+ fs2.unlinkSync(path4.join(dir, filename));
1663
+ }
1664
+ }
1665
+ } catch {
1666
+ }
1667
+ } catch {
1668
+ console.error("[PRBEAgent] Failed to save investigation history");
1669
+ }
1670
+ }
1671
+ static clear() {
1672
+ try {
1673
+ const dir = path4.join(getAppDataDir(), "history" /* HISTORY_DIR */);
1674
+ if (fs2.existsSync(dir)) {
1675
+ fs2.rmSync(dir, { recursive: true, force: true });
1676
+ }
1677
+ } catch {
1678
+ }
1679
+ }
1680
+ };
1681
+
1682
+ // src/agent.ts
1683
+ function getPersistencePath() {
1684
+ const appData = process.env["APPDATA"] || (process.platform === "darwin" ? path5.join(os2.homedir(), "Library", "Application Support") : path5.join(os2.homedir(), ".local", "share"));
1685
+ const dir = path5.join(appData, "prbe-agent");
1686
+ if (!fs3.existsSync(dir)) {
1687
+ fs3.mkdirSync(dir, { recursive: true });
1688
+ }
1689
+ return path5.join(dir, "agent-state.json");
1510
1690
  }
1511
1691
  function loadPersistedData() {
1512
1692
  try {
1513
1693
  const filePath = getPersistencePath();
1514
- if (fs2.existsSync(filePath)) {
1515
- const raw = fs2.readFileSync(filePath, "utf-8");
1694
+ if (fs3.existsSync(filePath)) {
1695
+ const raw = fs3.readFileSync(filePath, "utf-8");
1516
1696
  return JSON.parse(raw);
1517
1697
  }
1518
1698
  } catch {
@@ -1522,7 +1702,7 @@ function loadPersistedData() {
1522
1702
  function savePersistedData(data) {
1523
1703
  try {
1524
1704
  const filePath = getPersistencePath();
1525
- fs2.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
1705
+ fs3.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
1526
1706
  } catch {
1527
1707
  console.error("[PRBEAgent] Failed to save persisted data");
1528
1708
  }
@@ -1542,6 +1722,7 @@ var PRBEAgent = class _PRBEAgent {
1542
1722
  fetchAbortController = null;
1543
1723
  currentInvestigationSource = "user" /* USER */;
1544
1724
  currentCRId = null;
1725
+ historyStore;
1545
1726
  /** Files flagged during the current tool call — uploaded immediately after the tool returns. */
1546
1727
  pendingFlaggedFiles = [];
1547
1728
  // ---------- Persistence ----------
@@ -1603,6 +1784,10 @@ var PRBEAgent = class _PRBEAgent {
1603
1784
  this.state = new PRBEAgentState();
1604
1785
  this.logCapture = new PRBELogCapture(this.config.maxLogEntries);
1605
1786
  this.persistedData = loadPersistedData();
1787
+ this.historyStore = new HistoryStore(this.config.apiKey);
1788
+ const history = this.historyStore.load();
1789
+ this.state.completedInvestigations = history.investigations;
1790
+ this.state.completedCRs = history.crs;
1606
1791
  const roots = this.config.autoApprovedDirs;
1607
1792
  const requester = this.interactionHandler ? this : void 0;
1608
1793
  const grantedPaths = this.grantedPaths;
@@ -1753,7 +1938,8 @@ var PRBEAgent = class _PRBEAgent {
1753
1938
  this.state.appendEvent("Thinking", status.text);
1754
1939
  break;
1755
1940
  case "completed" /* COMPLETED */:
1756
- this.state.completeInvestigation(status.report, status.userSummary);
1941
+ this.state.completeInvestigation(status.report, status.userSummary, status.ticketId);
1942
+ this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
1757
1943
  break;
1758
1944
  case "error" /* ERROR */:
1759
1945
  this.state.failInvestigation(status.message);
@@ -1895,6 +2081,7 @@ var PRBEAgent = class _PRBEAgent {
1895
2081
  this.stopPolling();
1896
2082
  this.persistedData = {};
1897
2083
  savePersistedData(this.persistedData);
2084
+ HistoryStore.clear();
1898
2085
  this.state.resetInvestigation();
1899
2086
  this.state.completedInvestigations = [];
1900
2087
  this.state.activeCRs.clear();
@@ -1909,9 +2096,10 @@ var PRBEAgent = class _PRBEAgent {
1909
2096
  static clearPersistedData() {
1910
2097
  try {
1911
2098
  const filePath = getPersistencePath();
1912
- if (fs2.existsSync(filePath)) {
1913
- fs2.unlinkSync(filePath);
2099
+ if (fs3.existsSync(filePath)) {
2100
+ fs3.unlinkSync(filePath);
1914
2101
  }
2102
+ HistoryStore.clear();
1915
2103
  } catch {
1916
2104
  }
1917
2105
  }
@@ -1920,7 +2108,7 @@ var PRBEAgent = class _PRBEAgent {
1920
2108
  const crID = cr.id;
1921
2109
  this.currentInvestigationSource = "context_request" /* CONTEXT_REQUEST */;
1922
2110
  this.currentCRId = crID;
1923
- this.state.beginCR(crID, cr.query, cr.slug ?? void 0);
2111
+ this.state.beginCR(crID, cr.query, cr.slug ?? void 0, ticketId);
1924
2112
  const emitter = (status) => {
1925
2113
  switch (status.type) {
1926
2114
  case "started" /* STARTED */:
@@ -1939,9 +2127,11 @@ var PRBEAgent = class _PRBEAgent {
1939
2127
  break;
1940
2128
  case "completed" /* COMPLETED */:
1941
2129
  this.state.completeCR(crID, status.report, status.userSummary);
2130
+ this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
1942
2131
  break;
1943
2132
  case "error" /* ERROR */:
1944
2133
  this.state.failCR(crID, status.message);
2134
+ this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
1945
2135
  break;
1946
2136
  }
1947
2137
  };
@@ -2080,7 +2270,7 @@ var PRBEAgent = class _PRBEAgent {
2080
2270
  const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
2081
2271
  const uploadedRefs = [];
2082
2272
  for (const file of this.pendingFlaggedFiles) {
2083
- const filename = path4.basename(file.originalPath);
2273
+ const filename = path5.basename(file.originalPath);
2084
2274
  const safeName = encodeURIComponent(filename);
2085
2275
  const storagePath = `${uploadPrefix}/${safeName}`;
2086
2276
  uploadedRefs.push({
@@ -2136,7 +2326,8 @@ var PRBEAgent = class _PRBEAgent {
2136
2326
  emit({
2137
2327
  type: "completed" /* COMPLETED */,
2138
2328
  report,
2139
- userSummary
2329
+ userSummary,
2330
+ ticketId: ticketId2
2140
2331
  });
2141
2332
  ws.close(1e3, "Complete");
2142
2333
  finish({ report, userSummary, ticketId: ticketId2 });
@@ -2319,6 +2510,7 @@ function serializeCR(cr) {
2319
2510
  id: cr.id,
2320
2511
  query: cr.query,
2321
2512
  slug: cr.slug,
2513
+ ticketId: cr.ticketId,
2322
2514
  events: cr.events,
2323
2515
  isRunning: cr.isRunning,
2324
2516
  isCompleted: cr.isCompleted,
@@ -2346,6 +2538,9 @@ function serializePRBEState(state) {
2346
2538
  query: inv.query,
2347
2539
  report: inv.report,
2348
2540
  summary: inv.summary,
2541
+ ticketId: inv.ticketId,
2542
+ events: inv.events,
2543
+ resolvedInteractions: inv.resolvedInteractions,
2349
2544
  completedAt: inv.completedAt.toISOString()
2350
2545
  })),
2351
2546
  activeCRs: Array.from(state.activeCRs.values()).map(serializeCR),