@prbe.ai/electron-sdk 0.1.6 → 0.1.8
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 +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +222 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +222 -22
- package/dist/index.mjs.map +1 -1
- package/dist/{types-DHT-JxMT.d.mts → types-CwYRJCG0.d.mts} +11 -2
- package/dist/{types-DHT-JxMT.d.ts → types-CwYRJCG0.d.ts} +11 -2
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/agent.ts
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
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,
|
|
@@ -395,8 +399,13 @@ var PRBEToolRegistry = class {
|
|
|
395
399
|
var PRBEClosureTool = class {
|
|
396
400
|
declaration;
|
|
397
401
|
handler;
|
|
398
|
-
constructor(name, description, parameters, handler) {
|
|
399
|
-
this.declaration = {
|
|
402
|
+
constructor(name, description, parameters, handler, options) {
|
|
403
|
+
this.declaration = {
|
|
404
|
+
name,
|
|
405
|
+
description,
|
|
406
|
+
parameters,
|
|
407
|
+
...options?.interactive ? { interactive: true } : {}
|
|
408
|
+
};
|
|
400
409
|
this.handler = handler;
|
|
401
410
|
}
|
|
402
411
|
async execute(args) {
|
|
@@ -1499,20 +1508,196 @@ var BashExecuteTool = class {
|
|
|
1499
1508
|
}
|
|
1500
1509
|
};
|
|
1501
1510
|
|
|
1502
|
-
// src/
|
|
1503
|
-
|
|
1511
|
+
// src/history.ts
|
|
1512
|
+
import * as fs2 from "fs";
|
|
1513
|
+
import * as path4 from "path";
|
|
1514
|
+
import * as os from "os";
|
|
1515
|
+
import * as crypto from "crypto";
|
|
1516
|
+
var HKDF_SALT = Buffer.from("prbe-history-encryption-salt", "utf-8");
|
|
1517
|
+
var HKDF_INFO = Buffer.from("prbe-history-v1", "utf-8");
|
|
1518
|
+
function getAppDataDir() {
|
|
1504
1519
|
const appData = process.env["APPDATA"] || (process.platform === "darwin" ? path4.join(os.homedir(), "Library", "Application Support") : path4.join(os.homedir(), ".local", "share"));
|
|
1505
|
-
|
|
1520
|
+
return path4.join(appData, "prbe-agent");
|
|
1521
|
+
}
|
|
1522
|
+
function getHistoryDir() {
|
|
1523
|
+
const dir = path4.join(getAppDataDir(), "history" /* HISTORY_DIR */);
|
|
1506
1524
|
if (!fs2.existsSync(dir)) {
|
|
1507
1525
|
fs2.mkdirSync(dir, { recursive: true });
|
|
1508
1526
|
}
|
|
1509
|
-
return
|
|
1527
|
+
return dir;
|
|
1528
|
+
}
|
|
1529
|
+
function deriveKey(apiKey) {
|
|
1530
|
+
return Buffer.from(
|
|
1531
|
+
crypto.hkdfSync(
|
|
1532
|
+
"sha256",
|
|
1533
|
+
Buffer.from(apiKey, "utf-8"),
|
|
1534
|
+
HKDF_SALT,
|
|
1535
|
+
HKDF_INFO,
|
|
1536
|
+
32 /* KEY_LENGTH */
|
|
1537
|
+
)
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
function encrypt(plaintext, key) {
|
|
1541
|
+
const iv = crypto.randomBytes(12 /* IV_LENGTH */);
|
|
1542
|
+
const cipher = crypto.createCipheriv(
|
|
1543
|
+
"aes-256-gcm" /* ALGORITHM */,
|
|
1544
|
+
key,
|
|
1545
|
+
iv,
|
|
1546
|
+
{ authTagLength: 16 /* AUTH_TAG_LENGTH */ }
|
|
1547
|
+
);
|
|
1548
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, "utf-8"), cipher.final()]);
|
|
1549
|
+
const authTag = cipher.getAuthTag();
|
|
1550
|
+
return Buffer.concat([iv, authTag, encrypted]);
|
|
1551
|
+
}
|
|
1552
|
+
function decrypt(data, key) {
|
|
1553
|
+
const iv = data.subarray(0, 12 /* IV_LENGTH */);
|
|
1554
|
+
const authTag = data.subarray(
|
|
1555
|
+
12 /* IV_LENGTH */,
|
|
1556
|
+
12 /* IV_LENGTH */ + 16 /* AUTH_TAG_LENGTH */
|
|
1557
|
+
);
|
|
1558
|
+
const ciphertext = data.subarray(
|
|
1559
|
+
12 /* IV_LENGTH */ + 16 /* AUTH_TAG_LENGTH */
|
|
1560
|
+
);
|
|
1561
|
+
const decipher = crypto.createDecipheriv(
|
|
1562
|
+
"aes-256-gcm" /* ALGORITHM */,
|
|
1563
|
+
key,
|
|
1564
|
+
iv,
|
|
1565
|
+
{ authTagLength: 16 /* AUTH_TAG_LENGTH */ }
|
|
1566
|
+
);
|
|
1567
|
+
decipher.setAuthTag(authTag);
|
|
1568
|
+
return decipher.update(ciphertext) + decipher.final("utf-8");
|
|
1569
|
+
}
|
|
1570
|
+
var HistoryStore = class {
|
|
1571
|
+
key;
|
|
1572
|
+
constructor(apiKey) {
|
|
1573
|
+
this.key = deriveKey(apiKey);
|
|
1574
|
+
}
|
|
1575
|
+
load() {
|
|
1576
|
+
const investigations = [];
|
|
1577
|
+
const crs = [];
|
|
1578
|
+
try {
|
|
1579
|
+
const dir = getHistoryDir();
|
|
1580
|
+
let files;
|
|
1581
|
+
try {
|
|
1582
|
+
files = fs2.readdirSync(dir);
|
|
1583
|
+
} catch {
|
|
1584
|
+
return { investigations, crs };
|
|
1585
|
+
}
|
|
1586
|
+
for (const filename of files) {
|
|
1587
|
+
try {
|
|
1588
|
+
const filePath = path4.join(dir, filename);
|
|
1589
|
+
const raw = fs2.readFileSync(filePath);
|
|
1590
|
+
const json = decrypt(raw, this.key);
|
|
1591
|
+
if (filename.startsWith("inv-") && filename.endsWith(".json")) {
|
|
1592
|
+
const item = JSON.parse(json);
|
|
1593
|
+
investigations.push({
|
|
1594
|
+
...item,
|
|
1595
|
+
completedAt: new Date(item.completedAt)
|
|
1596
|
+
});
|
|
1597
|
+
} else if (filename.startsWith("cr-") && filename.endsWith(".json")) {
|
|
1598
|
+
const item = JSON.parse(json);
|
|
1599
|
+
crs.push({
|
|
1600
|
+
...item,
|
|
1601
|
+
startedAt: new Date(item.startedAt),
|
|
1602
|
+
resolvedInteractions: item.resolvedInteractions ?? []
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
} catch {
|
|
1606
|
+
console.warn(`[PRBEAgent] Skipping unreadable history file: ${filename}`);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
} catch {
|
|
1610
|
+
}
|
|
1611
|
+
investigations.sort(
|
|
1612
|
+
(a, b) => b.completedAt.getTime() - a.completedAt.getTime()
|
|
1613
|
+
);
|
|
1614
|
+
crs.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());
|
|
1615
|
+
return { investigations, crs };
|
|
1616
|
+
}
|
|
1617
|
+
save(investigations, crs) {
|
|
1618
|
+
try {
|
|
1619
|
+
const dir = getHistoryDir();
|
|
1620
|
+
const desiredFiles = /* @__PURE__ */ new Set();
|
|
1621
|
+
for (const inv of investigations) {
|
|
1622
|
+
const filename = `inv-${inv.id}.json`;
|
|
1623
|
+
desiredFiles.add(filename);
|
|
1624
|
+
const data = {
|
|
1625
|
+
id: inv.id,
|
|
1626
|
+
query: inv.query,
|
|
1627
|
+
report: inv.report,
|
|
1628
|
+
summary: inv.summary,
|
|
1629
|
+
ticketId: inv.ticketId,
|
|
1630
|
+
events: inv.events,
|
|
1631
|
+
resolvedInteractions: inv.resolvedInteractions,
|
|
1632
|
+
completedAt: inv.completedAt.toISOString()
|
|
1633
|
+
};
|
|
1634
|
+
fs2.writeFileSync(
|
|
1635
|
+
path4.join(dir, filename),
|
|
1636
|
+
encrypt(JSON.stringify(data), this.key)
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
for (const cr of crs) {
|
|
1640
|
+
const filename = `cr-${cr.id}.json`;
|
|
1641
|
+
desiredFiles.add(filename);
|
|
1642
|
+
const data = {
|
|
1643
|
+
id: cr.id,
|
|
1644
|
+
query: cr.query,
|
|
1645
|
+
slug: cr.slug,
|
|
1646
|
+
ticketId: cr.ticketId,
|
|
1647
|
+
events: cr.events,
|
|
1648
|
+
isRunning: cr.isRunning,
|
|
1649
|
+
isCompleted: cr.isCompleted,
|
|
1650
|
+
isFailed: cr.isFailed,
|
|
1651
|
+
report: cr.report,
|
|
1652
|
+
summary: cr.summary,
|
|
1653
|
+
errorMessage: cr.errorMessage,
|
|
1654
|
+
startedAt: cr.startedAt.toISOString(),
|
|
1655
|
+
pendingInteraction: cr.pendingInteraction,
|
|
1656
|
+
resolvedInteractions: cr.resolvedInteractions ?? []
|
|
1657
|
+
};
|
|
1658
|
+
fs2.writeFileSync(
|
|
1659
|
+
path4.join(dir, filename),
|
|
1660
|
+
encrypt(JSON.stringify(data), this.key)
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
try {
|
|
1664
|
+
const existing = fs2.readdirSync(dir);
|
|
1665
|
+
for (const filename of existing) {
|
|
1666
|
+
if (!desiredFiles.has(filename)) {
|
|
1667
|
+
fs2.unlinkSync(path4.join(dir, filename));
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
} catch {
|
|
1671
|
+
}
|
|
1672
|
+
} catch {
|
|
1673
|
+
console.error("[PRBEAgent] Failed to save investigation history");
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
static clear() {
|
|
1677
|
+
try {
|
|
1678
|
+
const dir = path4.join(getAppDataDir(), "history" /* HISTORY_DIR */);
|
|
1679
|
+
if (fs2.existsSync(dir)) {
|
|
1680
|
+
fs2.rmSync(dir, { recursive: true, force: true });
|
|
1681
|
+
}
|
|
1682
|
+
} catch {
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
// src/agent.ts
|
|
1688
|
+
function getPersistencePath() {
|
|
1689
|
+
const appData = process.env["APPDATA"] || (process.platform === "darwin" ? path5.join(os2.homedir(), "Library", "Application Support") : path5.join(os2.homedir(), ".local", "share"));
|
|
1690
|
+
const dir = path5.join(appData, "prbe-agent");
|
|
1691
|
+
if (!fs3.existsSync(dir)) {
|
|
1692
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
1693
|
+
}
|
|
1694
|
+
return path5.join(dir, "agent-state.json");
|
|
1510
1695
|
}
|
|
1511
1696
|
function loadPersistedData() {
|
|
1512
1697
|
try {
|
|
1513
1698
|
const filePath = getPersistencePath();
|
|
1514
|
-
if (
|
|
1515
|
-
const raw =
|
|
1699
|
+
if (fs3.existsSync(filePath)) {
|
|
1700
|
+
const raw = fs3.readFileSync(filePath, "utf-8");
|
|
1516
1701
|
return JSON.parse(raw);
|
|
1517
1702
|
}
|
|
1518
1703
|
} catch {
|
|
@@ -1522,7 +1707,7 @@ function loadPersistedData() {
|
|
|
1522
1707
|
function savePersistedData(data) {
|
|
1523
1708
|
try {
|
|
1524
1709
|
const filePath = getPersistencePath();
|
|
1525
|
-
|
|
1710
|
+
fs3.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
1526
1711
|
} catch {
|
|
1527
1712
|
console.error("[PRBEAgent] Failed to save persisted data");
|
|
1528
1713
|
}
|
|
@@ -1542,6 +1727,7 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1542
1727
|
fetchAbortController = null;
|
|
1543
1728
|
currentInvestigationSource = "user" /* USER */;
|
|
1544
1729
|
currentCRId = null;
|
|
1730
|
+
historyStore;
|
|
1545
1731
|
/** Files flagged during the current tool call — uploaded immediately after the tool returns. */
|
|
1546
1732
|
pendingFlaggedFiles = [];
|
|
1547
1733
|
// ---------- Persistence ----------
|
|
@@ -1603,6 +1789,10 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1603
1789
|
this.state = new PRBEAgentState();
|
|
1604
1790
|
this.logCapture = new PRBELogCapture(this.config.maxLogEntries);
|
|
1605
1791
|
this.persistedData = loadPersistedData();
|
|
1792
|
+
this.historyStore = new HistoryStore(this.config.apiKey);
|
|
1793
|
+
const history = this.historyStore.load();
|
|
1794
|
+
this.state.completedInvestigations = history.investigations;
|
|
1795
|
+
this.state.completedCRs = history.crs;
|
|
1606
1796
|
const roots = this.config.autoApprovedDirs;
|
|
1607
1797
|
const requester = this.interactionHandler ? this : void 0;
|
|
1608
1798
|
const grantedPaths = this.grantedPaths;
|
|
@@ -1723,9 +1913,9 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1723
1913
|
/**
|
|
1724
1914
|
* Register a custom tool that the middleware can invoke during investigations.
|
|
1725
1915
|
*/
|
|
1726
|
-
registerTool(name, description, parameters, handler) {
|
|
1916
|
+
registerTool(name, description, parameters, handler, options) {
|
|
1727
1917
|
this.registry.register(
|
|
1728
|
-
new PRBEClosureTool(name, description, parameters, handler)
|
|
1918
|
+
new PRBEClosureTool(name, description, parameters, handler, options)
|
|
1729
1919
|
);
|
|
1730
1920
|
}
|
|
1731
1921
|
/**
|
|
@@ -1753,7 +1943,8 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1753
1943
|
this.state.appendEvent("Thinking", status.text);
|
|
1754
1944
|
break;
|
|
1755
1945
|
case "completed" /* COMPLETED */:
|
|
1756
|
-
this.state.completeInvestigation(status.report, status.userSummary);
|
|
1946
|
+
this.state.completeInvestigation(status.report, status.userSummary, status.ticketId);
|
|
1947
|
+
this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
|
|
1757
1948
|
break;
|
|
1758
1949
|
case "error" /* ERROR */:
|
|
1759
1950
|
this.state.failInvestigation(status.message);
|
|
@@ -1895,6 +2086,7 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1895
2086
|
this.stopPolling();
|
|
1896
2087
|
this.persistedData = {};
|
|
1897
2088
|
savePersistedData(this.persistedData);
|
|
2089
|
+
HistoryStore.clear();
|
|
1898
2090
|
this.state.resetInvestigation();
|
|
1899
2091
|
this.state.completedInvestigations = [];
|
|
1900
2092
|
this.state.activeCRs.clear();
|
|
@@ -1909,9 +2101,10 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1909
2101
|
static clearPersistedData() {
|
|
1910
2102
|
try {
|
|
1911
2103
|
const filePath = getPersistencePath();
|
|
1912
|
-
if (
|
|
1913
|
-
|
|
2104
|
+
if (fs3.existsSync(filePath)) {
|
|
2105
|
+
fs3.unlinkSync(filePath);
|
|
1914
2106
|
}
|
|
2107
|
+
HistoryStore.clear();
|
|
1915
2108
|
} catch {
|
|
1916
2109
|
}
|
|
1917
2110
|
}
|
|
@@ -1920,7 +2113,7 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1920
2113
|
const crID = cr.id;
|
|
1921
2114
|
this.currentInvestigationSource = "context_request" /* CONTEXT_REQUEST */;
|
|
1922
2115
|
this.currentCRId = crID;
|
|
1923
|
-
this.state.beginCR(crID, cr.query, cr.slug ?? void 0);
|
|
2116
|
+
this.state.beginCR(crID, cr.query, cr.slug ?? void 0, ticketId);
|
|
1924
2117
|
const emitter = (status) => {
|
|
1925
2118
|
switch (status.type) {
|
|
1926
2119
|
case "started" /* STARTED */:
|
|
@@ -1939,9 +2132,11 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
1939
2132
|
break;
|
|
1940
2133
|
case "completed" /* COMPLETED */:
|
|
1941
2134
|
this.state.completeCR(crID, status.report, status.userSummary);
|
|
2135
|
+
this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
|
|
1942
2136
|
break;
|
|
1943
2137
|
case "error" /* ERROR */:
|
|
1944
2138
|
this.state.failCR(crID, status.message);
|
|
2139
|
+
this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);
|
|
1945
2140
|
break;
|
|
1946
2141
|
}
|
|
1947
2142
|
};
|
|
@@ -2080,7 +2275,7 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
2080
2275
|
const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);
|
|
2081
2276
|
const uploadedRefs = [];
|
|
2082
2277
|
for (const file of this.pendingFlaggedFiles) {
|
|
2083
|
-
const filename =
|
|
2278
|
+
const filename = path5.basename(file.originalPath);
|
|
2084
2279
|
const safeName = encodeURIComponent(filename);
|
|
2085
2280
|
const storagePath = `${uploadPrefix}/${safeName}`;
|
|
2086
2281
|
uploadedRefs.push({
|
|
@@ -2136,7 +2331,8 @@ var PRBEAgent = class _PRBEAgent {
|
|
|
2136
2331
|
emit({
|
|
2137
2332
|
type: "completed" /* COMPLETED */,
|
|
2138
2333
|
report,
|
|
2139
|
-
userSummary
|
|
2334
|
+
userSummary,
|
|
2335
|
+
ticketId: ticketId2
|
|
2140
2336
|
});
|
|
2141
2337
|
ws.close(1e3, "Complete");
|
|
2142
2338
|
finish({ report, userSummary, ticketId: ticketId2 });
|
|
@@ -2319,6 +2515,7 @@ function serializeCR(cr) {
|
|
|
2319
2515
|
id: cr.id,
|
|
2320
2516
|
query: cr.query,
|
|
2321
2517
|
slug: cr.slug,
|
|
2518
|
+
ticketId: cr.ticketId,
|
|
2322
2519
|
events: cr.events,
|
|
2323
2520
|
isRunning: cr.isRunning,
|
|
2324
2521
|
isCompleted: cr.isCompleted,
|
|
@@ -2346,6 +2543,9 @@ function serializePRBEState(state) {
|
|
|
2346
2543
|
query: inv.query,
|
|
2347
2544
|
report: inv.report,
|
|
2348
2545
|
summary: inv.summary,
|
|
2546
|
+
ticketId: inv.ticketId,
|
|
2547
|
+
events: inv.events,
|
|
2548
|
+
resolvedInteractions: inv.resolvedInteractions,
|
|
2349
2549
|
completedAt: inv.completedAt.toISOString()
|
|
2350
2550
|
})),
|
|
2351
2551
|
activeCRs: Array.from(state.activeCRs.values()).map(serializeCR),
|