@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.d.mts +25 -17
- package/dist/index.d.ts +25 -17
- package/dist/index.js +311 -466
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +310 -466
- package/dist/index.mjs.map +1 -1
- package/dist/{types-Cyfgy1uD.d.mts → types-BeZ2nQ9x.d.mts} +66 -46
- package/dist/{types-Cyfgy1uD.d.ts → types-BeZ2nQ9x.d.ts} +66 -46
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +5 -5
- package/dist/types.js.map +1 -1
- package/dist/types.mjs +5 -5
- package/dist/types.mjs.map +1 -1
- package/package.json +1 -1
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.
|
|
75
|
+
var version = "0.1.18";
|
|
75
76
|
|
|
76
77
|
// src/agent.ts
|
|
77
|
-
var
|
|
78
|
-
var
|
|
79
|
-
var
|
|
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["
|
|
263
|
-
PRBEStateEvent2["
|
|
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
|
-
|
|
287
|
-
|
|
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.
|
|
301
|
+
return this.isInvestigating || this.activeBackgroundInvestigations.size > 0;
|
|
294
302
|
}
|
|
295
|
-
get
|
|
296
|
-
return this.
|
|
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
|
-
|
|
394
|
-
const
|
|
395
|
-
if (!
|
|
396
|
-
|
|
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
|
-
|
|
401
|
-
const
|
|
402
|
-
if (!
|
|
403
|
-
|
|
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
|
-
|
|
420
|
-
const
|
|
421
|
-
if (!
|
|
422
|
-
const resolved =
|
|
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:
|
|
425
|
-
payload:
|
|
438
|
+
interactionId: bg.pendingInteraction.interactionId,
|
|
439
|
+
payload: bg.pendingInteraction,
|
|
426
440
|
response,
|
|
427
|
-
eventIndex:
|
|
441
|
+
eventIndex: bg.events.length
|
|
428
442
|
});
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
440
|
-
const
|
|
441
|
-
if (!
|
|
442
|
-
|
|
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
|
-
// ----------
|
|
454
|
-
|
|
455
|
-
const
|
|
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.
|
|
470
|
-
this.emit("
|
|
486
|
+
this.activeBackgroundInvestigations.set(id, bg);
|
|
487
|
+
this.emit("background-start" /* BACKGROUND_START */, bg);
|
|
471
488
|
this.emit("status" /* STATUS */);
|
|
472
489
|
}
|
|
473
|
-
|
|
474
|
-
const
|
|
475
|
-
if (!
|
|
476
|
-
if (
|
|
477
|
-
const last =
|
|
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
|
-
|
|
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
|
-
|
|
492
|
-
const
|
|
493
|
-
if (!
|
|
494
|
-
|
|
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
|
-
|
|
498
|
-
const
|
|
499
|
-
if (!
|
|
500
|
-
this.
|
|
501
|
-
if (
|
|
502
|
-
|
|
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
|
-
|
|
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
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
this.
|
|
514
|
-
this.emit("
|
|
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
|
-
|
|
518
|
-
const
|
|
519
|
-
if (!
|
|
520
|
-
this.
|
|
521
|
-
|
|
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
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
this.
|
|
531
|
-
this.emit("
|
|
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/
|
|
1768
|
-
|
|
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
|
-
|
|
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 (
|
|
1957
|
-
const raw =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2080
|
-
this.state.
|
|
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
|
-
|
|
2098
|
-
|
|
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
|
|
2154
|
-
this.state.
|
|
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
|
|
2161
|
-
this.state.
|
|
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
|
|
2175
|
-
this.state.
|
|
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
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
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
|
|
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
|
|
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
|
|
2287
|
-
const
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
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
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
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
|
|
2322
|
-
* Resolves session IDs → ticket IDs first, then fetches ticket info.
|
|
2195
|
+
* Fetch agent history (tickets + sessions) from the backend.
|
|
2323
2196
|
*/
|
|
2324
|
-
async
|
|
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/
|
|
2334
|
-
|
|
2200
|
+
"/api/agent/history",
|
|
2201
|
+
{ agent_id: this.agentID }
|
|
2335
2202
|
);
|
|
2336
|
-
this.state.
|
|
2337
|
-
return response
|
|
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.
|
|
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.
|
|
2371
|
-
this.state.
|
|
2372
|
-
this.state.
|
|
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 (
|
|
2383
|
-
|
|
2247
|
+
if (fs2.existsSync(filePath)) {
|
|
2248
|
+
fs2.unlinkSync(filePath);
|
|
2384
2249
|
}
|
|
2385
|
-
HistoryStore.clear();
|
|
2386
2250
|
} catch {
|
|
2387
2251
|
}
|
|
2388
2252
|
}
|
|
2389
|
-
// ----------
|
|
2253
|
+
// ---------- Background Investigation ----------
|
|
2390
2254
|
async investigateForCR(cr, ticketId) {
|
|
2391
|
-
|
|
2392
|
-
this.
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
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:
|
|
2492
|
-
os_version:
|
|
2493
|
-
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
|
-
|
|
2499
|
-
|
|
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 =
|
|
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.
|
|
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()
|
|
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
|
-
|
|
2711
|
-
|
|
2712
|
-
trackedSessionIDs: [],
|
|
2551
|
+
activeBackgroundInvestigations: [],
|
|
2552
|
+
completedBackgroundInvestigations: [],
|
|
2713
2553
|
ticketInfo: [],
|
|
2554
|
+
agentHistory: [],
|
|
2714
2555
|
hasActiveWork: false
|
|
2715
2556
|
};
|
|
2716
|
-
function
|
|
2557
|
+
function serializeBackgroundInvestigation(bg) {
|
|
2717
2558
|
return {
|
|
2718
|
-
id:
|
|
2719
|
-
query:
|
|
2720
|
-
slug:
|
|
2721
|
-
ticketId:
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
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
|
-
|
|
2759
|
-
|
|
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,
|