next-observer 0.3.27 → 0.3.31
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/README.md +11 -1
- package/dist/agents/cards.js +10 -2
- package/dist/agents/cards.js.map +1 -1
- package/dist/agents/chat.d.ts +2 -0
- package/dist/agents/chat.js +59 -18
- package/dist/agents/chat.js.map +1 -1
- package/dist/agents/investigator.d.ts +4 -0
- package/dist/agents/investigator.js +7 -3
- package/dist/agents/investigator.js.map +1 -1
- package/dist/agents/resilient-llm.js +19 -3
- package/dist/agents/resilient-llm.js.map +1 -1
- package/dist/agents/specialists.js +3 -1
- package/dist/agents/specialists.js.map +1 -1
- package/dist/collector/chat-history.d.ts +35 -0
- package/dist/collector/chat-history.js +44 -0
- package/dist/collector/chat-history.js.map +1 -0
- package/dist/collector/chat.d.ts +25 -1
- package/dist/collector/server.js +71 -6
- package/dist/collector/server.js.map +1 -1
- package/dist/debug/queries.d.ts +23 -1
- package/dist/debug/queries.js +57 -4
- package/dist/debug/queries.js.map +1 -1
- package/dist/ui/assets/index-BfLmeTpK.js +20 -0
- package/dist/ui/assets/index-Clc8emDK.css +2 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-8P-dMmH-.css +0 -2
- package/dist/ui/assets/index-CXUv4-u5.js +0 -20
package/README.md
CHANGED
|
@@ -62,7 +62,8 @@ this call compares with the others of its kind.
|
|
|
62
62
|
|
|
63
63
|
A span can be fast, without an error, and still carry the wrong answer. When the app records its own verdict as a span
|
|
64
64
|
event — `integrity_check` with `ok`, `expected`, `actual` — the observer raises an anomaly on the first `ok: false` and the
|
|
65
|
-
trace says so
|
|
65
|
+
trace says so. The AI agents get those checks counted per deployed version (`compare_versions`), so they can name the
|
|
66
|
+
version that started returning wrong data and how often it happens:
|
|
66
67
|
|
|
67
68
|

|
|
68
69
|
|
|
@@ -126,6 +127,15 @@ One investigation makes 7–12 model calls. A call that hangs is started again o
|
|
|
126
127
|
few requests per minute, so an investigation may pause for that minute; a key without credits, a wrong key or a wrong
|
|
127
128
|
model name is explained in the chat in plain words.
|
|
128
129
|
|
|
130
|
+
The chat keeps a list of investigations — your questions and the ones the observer started on its own — with their
|
|
131
|
+
state; pick one to read it again. The observer keeps them (the last 100, in memory), so a reload or another browser
|
|
132
|
+
shows the same list; a restart of the observer starts clean.
|
|
133
|
+
|
|
134
|
+
An investigation can be stopped — the **Stop** button next to "working…" in the chat, for a question you asked and for
|
|
135
|
+
one the observer started on its own. What was found until then stays on the page. A model behind an API drops the call
|
|
136
|
+
in flight; a CLI model finishes the call it is on and then stops. A stopped (or timed-out) conversation is not continued —
|
|
137
|
+
the next question starts a new one.
|
|
138
|
+
|
|
129
139
|
## Your own AI agents
|
|
130
140
|
|
|
131
141
|
The built-in AI agents are an orchestrator and three specialists (latency, errors, traffic). To change them, put `observe.agents.ts` (or `.mts`, `.js`, `.mjs`) in the app root. A specialist with a built-in name
|
package/dist/agents/cards.js
CHANGED
|
@@ -19,11 +19,17 @@ function describeFilters(args) {
|
|
|
19
19
|
export function cardsFromResult(tool, args, result) {
|
|
20
20
|
switch (tool) {
|
|
21
21
|
case 'compare_versions': {
|
|
22
|
-
const { changes } = result;
|
|
23
|
-
|
|
22
|
+
const { changes, integrity } = result;
|
|
23
|
+
const regressions = changes
|
|
24
24
|
.filter((c) => ((c.p95Ratio ?? 0) >= THRESHOLDS.regressionRatio && c.to.p95Ms - c.from.p95Ms >= THRESHOLDS.regressionMinMs) ||
|
|
25
25
|
(c.errorRateDelta >= THRESHOLDS.regressionErrorDelta && c.errorRateChangeSignificant))
|
|
26
26
|
.map((c) => ({ kind: 'regression', service: c.service, operation: c.operation, from: c.from, to: c.to, p95Ratio: c.p95Ratio, errorRateDelta: c.errorRateDelta }));
|
|
27
|
+
// One wrong answer is worth a card — there is no acceptable share of them. In the version running now, that is:
|
|
28
|
+
// wrong data an earlier version returned and the next one fixed is history, not evidence.
|
|
29
|
+
const wrong = (integrity ?? [])
|
|
30
|
+
.filter((i) => (i.versions.at(-1)?.failed ?? 0) > 0)
|
|
31
|
+
.map((i) => ({ kind: 'wrong-data', service: i.service, operation: i.operation, versions: i.versions }));
|
|
32
|
+
return [...wrong, ...regressions];
|
|
27
33
|
}
|
|
28
34
|
case 'get_errors': {
|
|
29
35
|
const { errors } = result;
|
|
@@ -79,6 +85,8 @@ export function cardKey(card) {
|
|
|
79
85
|
return `${card.kind}:${card.parent}:${card.operation}`;
|
|
80
86
|
case 'hotspot':
|
|
81
87
|
return `${card.kind}:${card.operation}:${card.codeFile}`;
|
|
88
|
+
case 'wrong-data':
|
|
89
|
+
return `${card.kind}:${card.service}:${card.operation}`;
|
|
82
90
|
case 'silent':
|
|
83
91
|
return `${card.kind}:${card.service}`;
|
|
84
92
|
case 'traces':
|
package/dist/agents/cards.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../../src/agents/cards.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,qCAAqC;IACrC,eAAe,EAAE,GAAG;IACpB,0GAA0G;IAC1G,eAAe,EAAE,EAAE;IACnB,oGAAoG;IACpG,oBAAoB,EAAE,GAAG;IACzB,SAAS,EAAE,IAAI;IACf,0DAA0D;IAC1D,YAAY,EAAE,GAAG;IACjB,aAAa,EAAE,GAAG;CACnB,CAAA;AAID,SAAS,eAAe,CAAC,IAA6B;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;SAC9C,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAA;AACxE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAA6B,EAAE,MAAe;IAC1F,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,kBAAkB,EAAE,CAAC;YACxB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../../src/agents/cards.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,qCAAqC;IACrC,eAAe,EAAE,GAAG;IACpB,0GAA0G;IAC1G,eAAe,EAAE,EAAE;IACnB,oGAAoG;IACpG,oBAAoB,EAAE,GAAG;IACzB,SAAS,EAAE,IAAI;IACf,0DAA0D;IAC1D,YAAY,EAAE,GAAG;IACjB,aAAa,EAAE,GAAG;CACnB,CAAA;AAID,SAAS,eAAe,CAAC,IAA6B;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;SAC9C,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAA;AACxE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAA6B,EAAE,MAAe;IAC1F,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,kBAAkB,EAAE,CAAC;YACxB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAmC,CAAA;YAClE,MAAM,WAAW,GAAmB,OAAO;iBACxC,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,eAAe,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,eAAe,CAAC;gBAC5G,CAAC,CAAC,CAAC,cAAc,IAAI,UAAU,CAAC,oBAAoB,IAAI,CAAC,CAAC,0BAA0B,CAAC,CACxF;iBACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;YACnK,gHAAgH;YAChH,0FAA0F;YAC1F,MAAM,KAAK,GAAmB,CAAC,SAAS,IAAI,EAAE,CAAC;iBAC5C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;iBACnD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YACzG,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,WAAW,CAAC,CAAA;QACnC,CAAC;QACD,KAAK,YAAY,EAAE,CAAC;YAClB,MAAM,EAAE,MAAM,EAAE,GAAG,MAA6B,CAAA;YAChD,OAAO,MAAM;iBACV,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC;iBACzD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,cAAc;gBACpD,QAAQ,EAAE,CAAC,CAAC,eAAe;aAC5B,CAAC,CAAC,CAAA;QACP,CAAC;QACD,KAAK,WAAW,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAA4B,CAAA;YAC1C,IAAI,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAA;YAChE,MAAM,KAAK,GAAmB,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACvL,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAA;YACzC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK;iBACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,UAAU,EAAE,CAAC,eAAe,CAAC,KAAK,QAAQ,CAAC;iBACjF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;YACzC,IAAI,OAAO,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,OAAO,IAAI,UAAU,CAAC,YAAY,EAAE,CAAC;gBAClF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,UAAW,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAA;YAC3K,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,KAAK,cAAc,EAAE,CAAC;YACpB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAA+B,CAAA;YACpD,OAAO,QAAQ;iBACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,GAAG,UAAU,CAAC,aAAa,CAAC;iBAC9D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAA;QAChG,CAAC;QACD,KAAK,eAAe,EAAE,CAAC;YACrB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAgC,CAAA;YACnD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAA;YAClC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;QACtL,CAAC;QACD;YACE,OAAO,EAAE,CAAA;IACb,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,OAAO,CAAC,IAAkB;IACxC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,YAAY,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;QACzD,KAAK,YAAY;YACf,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;QACxD,KAAK,SAAS;YACZ,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC1D,KAAK,YAAY;YACf,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAA;QACzD,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAA;QACvC,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAA;IACvC,CAAC;AACH,CAAC"}
|
package/dist/agents/chat.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import type { QueryOptions } from '../debug/queries.js';
|
|
|
5
5
|
import type { SpecialistSpec } from './specialists.js';
|
|
6
6
|
import { type Env } from './model.js';
|
|
7
7
|
export interface ChatHandlerOptions {
|
|
8
|
+
/** How many cut-short conversations are remembered (and their history kept) before the oldest is dropped. Default 1000. */
|
|
9
|
+
maxCutSessions?: number;
|
|
8
10
|
storage: StorageAdapter;
|
|
9
11
|
env?: Env;
|
|
10
12
|
queryOptions?: QueryOptions;
|
package/dist/agents/chat.js
CHANGED
|
@@ -36,9 +36,17 @@ export async function createChatHandler(options) {
|
|
|
36
36
|
const timeoutMs = options.timeoutMs ?? 240_000;
|
|
37
37
|
// One question at a time per conversation: a second one would interleave with the first in the session history.
|
|
38
38
|
const busy = new Set();
|
|
39
|
-
|
|
39
|
+
// Conversations whose last run was cut short (stopped, or timed out). Their history may end in the middle of a step —
|
|
40
|
+
// a tool call without its result — which a provider rejects on the next request; they are not continued.
|
|
41
|
+
const cut = new Set();
|
|
42
|
+
const MAX_CUT_SESSIONS = options.maxCutSessions ?? 1000;
|
|
43
|
+
const handle = async ({ question, sessionId: requested, signal }, emit) => {
|
|
40
44
|
// Reserve synchronously, before any await: two requests for the same session must not both get through.
|
|
41
45
|
if (requested) {
|
|
46
|
+
if (cut.has(requested)) {
|
|
47
|
+
emit({ type: 'error', message: 'this conversation was cut short — ask again in a new chat', closed: true });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
42
50
|
if (busy.has(requested)) {
|
|
43
51
|
emit({ type: 'error', message: 'this chat is still answering the previous question' });
|
|
44
52
|
return;
|
|
@@ -46,8 +54,8 @@ export async function createChatHandler(options) {
|
|
|
46
54
|
busy.add(requested);
|
|
47
55
|
}
|
|
48
56
|
let sessionId = requested;
|
|
49
|
-
let investigation;
|
|
50
57
|
let timedOut = false;
|
|
58
|
+
let stopped = false;
|
|
51
59
|
let finished = false;
|
|
52
60
|
const send = (event) => {
|
|
53
61
|
if (!finished)
|
|
@@ -55,6 +63,20 @@ export async function createChatHandler(options) {
|
|
|
55
63
|
};
|
|
56
64
|
let timer;
|
|
57
65
|
const timeout = new Promise((resolve) => (timer = setTimeout(() => resolve('timeout'), timeoutMs)));
|
|
66
|
+
// One way to cancel the run, for a stop and for the timeout alike.
|
|
67
|
+
const own = new AbortController();
|
|
68
|
+
const cancel = signal ? AbortSignal.any([signal, own.signal]) : own.signal;
|
|
69
|
+
// Resolves when somebody stops the investigation. The run itself is cancelled through the signal above, but a model
|
|
70
|
+
// that cannot be cancelled (a CLI) would keep us waiting — so the turn ends here, at once.
|
|
71
|
+
let onAbort;
|
|
72
|
+
const stop = new Promise((resolve) => {
|
|
73
|
+
if (!signal)
|
|
74
|
+
return;
|
|
75
|
+
if (signal.aborted)
|
|
76
|
+
return resolve('stopped');
|
|
77
|
+
onAbort = () => resolve('stopped');
|
|
78
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
79
|
+
});
|
|
58
80
|
const shown = new Set();
|
|
59
81
|
const onResult = (step, result) => {
|
|
60
82
|
for (const card of cardsFromResult(step.tool, step.args, result)) {
|
|
@@ -69,12 +91,18 @@ export async function createChatHandler(options) {
|
|
|
69
91
|
sessionId = await investigator.startSession(requested);
|
|
70
92
|
busy.add(sessionId);
|
|
71
93
|
emit({ type: 'status', mode, sessionId, text: 'Investigating…' });
|
|
72
|
-
const running = investigator.ask(question, { sessionId, onStep: (s) => send({ type: 'step', ...s }), onResult });
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
94
|
+
const running = investigator.ask(question, { sessionId, onStep: (s) => send({ type: 'step', ...s }), onResult, signal: cancel });
|
|
95
|
+
// A cancelled run rejects or resolves on its own time; nobody is waiting for it any more.
|
|
96
|
+
running.catch(() => { });
|
|
97
|
+
const result = await Promise.race([running, timeout, stop]);
|
|
98
|
+
if (result === 'stopped') {
|
|
99
|
+
stopped = true;
|
|
100
|
+
send({ type: 'stopped', closed: true });
|
|
101
|
+
}
|
|
102
|
+
else if (result === 'timeout') {
|
|
76
103
|
timedOut = true;
|
|
77
|
-
|
|
104
|
+
own.abort();
|
|
105
|
+
send({ type: 'error', message: `investigation took longer than ${Math.round(timeoutMs / 1000)}s — try a narrower question`, closed: true });
|
|
78
106
|
}
|
|
79
107
|
else if (result.error && !result.text) {
|
|
80
108
|
send({ type: 'error', message: result.error });
|
|
@@ -84,21 +112,34 @@ export async function createChatHandler(options) {
|
|
|
84
112
|
}
|
|
85
113
|
}
|
|
86
114
|
catch (error) {
|
|
87
|
-
|
|
115
|
+
// The run was cancelled under us: that is the stop, not a failure.
|
|
116
|
+
if (signal?.aborted) {
|
|
117
|
+
stopped = true;
|
|
118
|
+
send({ type: 'stopped', closed: true });
|
|
119
|
+
}
|
|
120
|
+
else
|
|
121
|
+
send({ type: 'error', message: error instanceof Error ? error.message : String(error) });
|
|
88
122
|
}
|
|
89
123
|
finally {
|
|
90
|
-
// A
|
|
91
|
-
// finished turn
|
|
124
|
+
// A cancelled run may still be winding down (a CLI model finishes the call it is on): its late steps must not
|
|
125
|
+
// leak into this finished turn — and its conversation is closed for good, so nothing has to wait for it.
|
|
92
126
|
finished = true;
|
|
93
127
|
clearTimeout(timer);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
if (onAbort)
|
|
129
|
+
signal?.removeEventListener('abort', onAbort);
|
|
130
|
+
if (sessionId) {
|
|
131
|
+
busy.delete(sessionId);
|
|
132
|
+
if (timedOut || stopped) {
|
|
133
|
+
cut.add(sessionId);
|
|
134
|
+
// The oldest are forgotten, together with their history: an observer that runs for weeks must not keep every
|
|
135
|
+
// stopped turn. Its id then simply starts a clean conversation — the run that used it ended long ago.
|
|
136
|
+
if (cut.size > MAX_CUT_SESSIONS) {
|
|
137
|
+
const oldest = cut.values().next().value;
|
|
138
|
+
cut.delete(oldest);
|
|
139
|
+
void investigator.endSession(oldest).catch(() => { });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
102
143
|
}
|
|
103
144
|
};
|
|
104
145
|
return { mode, handle };
|
package/dist/agents/chat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/agents/chat.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,OAAO,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAA;AAIvD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAY,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/agents/chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,8 @@ export interface InvestigatorOptions {
|
|
|
25
25
|
export declare function isLeakedToolCall(text: string): boolean;
|
|
26
26
|
export declare function createInvestigator(options: InvestigatorOptions): {
|
|
27
27
|
startSession: (sessionId?: string) => Promise<string>;
|
|
28
|
+
/** Forgets a conversation and its history. */
|
|
29
|
+
endSession(sessionId: string): Promise<void>;
|
|
28
30
|
/**
|
|
29
31
|
* Runs one investigation; resolves with the final report and every tool call made on the way.
|
|
30
32
|
* Pass the sessionId from a previous answer to continue that conversation. Safe to call concurrently (per session: one at a time).
|
|
@@ -34,6 +36,8 @@ export declare function createInvestigator(options: InvestigatorOptions): {
|
|
|
34
36
|
/** Called with each data tool's result — the chat builds evidence cards from these. */
|
|
35
37
|
onResult?: (step: InvestigationStep, result: unknown) => void;
|
|
36
38
|
sessionId?: string;
|
|
39
|
+
/** Stops the run: ADK cancels between steps, and a model that supports it drops the call in flight. */
|
|
40
|
+
signal?: AbortSignal;
|
|
37
41
|
}): Promise<{
|
|
38
42
|
text: string;
|
|
39
43
|
sessionId: string;
|
|
@@ -62,9 +62,9 @@ export function createInvestigator(options) {
|
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
const tools = (agent) => ({
|
|
65
|
-
get_services: tool(agent, 'get_services', 'Services,
|
|
65
|
+
get_services: tool(agent, 'get_services', 'Services, every version of them seen so far (in deploy order) and seconds since their last span. `versionLastSpanSecondsAgo` says which versions are still sending: one that has been quiet for minutes was replaced by the next, it is not running alongside it.', z.object({}), () => q.getServices()),
|
|
66
66
|
get_operation_stats: tool(agent, 'get_operation_stats', 'Slowest operations by p95 with p50/p99 and error rate.', z.object({ service, operation, sinceMinutes: since }), (a) => q.getOperationStats(a)),
|
|
67
|
-
compare_versions: tool(agent, 'compare_versions', 'Latest deployed version vs the previous one per operation: p95 ratio and error-rate delta. `errorRateChangeSignificant: false` means the error-rate difference is within random noise for that many requests. Use it to name the deployment that caused a regression.', z.object({ service, operation, sinceMinutes: since }), (a) => q.compareVersions(a)),
|
|
67
|
+
compare_versions: tool(agent, 'compare_versions', 'Latest deployed version vs the previous one per operation: p95 ratio and error-rate delta. `errorRateChangeSignificant: false` means the error-rate difference is within random noise for that many requests. Use it to name the deployment that caused a regression. `integrity` (present when the app checks its own answers) counts those checks per version over the whole history: `failed` > 0 in one version and 0 in the one before names the deployment that started returning wrong data, and failed/checked says how often.', z.object({ service, operation, sinceMinutes: since }), (a) => q.compareVersions(a)),
|
|
68
68
|
get_errors: tool(agent, 'get_errors', 'Failing operations: error rate, top exception messages (each with when it was first seen and in which versions), example trace ids.', z.object({ service, operation, sinceMinutes: since }), (a) => q.getErrors(a)),
|
|
69
69
|
search_traces: tool(agent, 'search_traces', 'Recent traces matching filters, to get example trace ids.', z.object({ service, operation, minDurationMs: z.number().optional(), hasError: z.boolean().optional(), sinceMinutes: since }), (a) => q.searchTraces(a)),
|
|
70
70
|
get_trace: tool(agent, 'get_trace', 'One trace as a tree with self time, errors and code file paths; `repeated` lists ≥3 identical sibling calls (N+1); `nextInternalMs` is time inside Next.js itself (routing, rendering, dev compilation), not the app code; `integrityCheck` on a span means it returned successfully, quickly, and still the wrong data — the span has no error and may not even be slow, so check this field specifically rather than assuming a clean-looking span is fine.', z.object({ traceId: z.string().describe('32-char hex trace id from search_traces, or from an anomaly question') }), (a) => q.getTrace(a)),
|
|
@@ -89,6 +89,10 @@ export function createInvestigator(options) {
|
|
|
89
89
|
}
|
|
90
90
|
return {
|
|
91
91
|
startSession,
|
|
92
|
+
/** Forgets a conversation and its history. */
|
|
93
|
+
async endSession(sessionId) {
|
|
94
|
+
await sessions.deleteSession({ appName: APP_NAME, userId: USER_ID, sessionId });
|
|
95
|
+
},
|
|
92
96
|
/**
|
|
93
97
|
* Runs one investigation; resolves with the final report and every tool call made on the way.
|
|
94
98
|
* Pass the sessionId from a previous answer to continue that conversation. Safe to call concurrently (per session: one at a time).
|
|
@@ -105,7 +109,7 @@ export function createInvestigator(options) {
|
|
|
105
109
|
const transcript = [];
|
|
106
110
|
let text = '';
|
|
107
111
|
let failure;
|
|
108
|
-
for await (const event of runner.runAsync({ userId: USER_ID, sessionId, newMessage: { role: 'user', parts: [{ text: question }] } })) {
|
|
112
|
+
for await (const event of runner.runAsync({ userId: USER_ID, sessionId, newMessage: { role: 'user', parts: [{ text: question }] }, ...(call.signal ? { abortSignal: call.signal } : {}) })) {
|
|
109
113
|
if (event.errorMessage)
|
|
110
114
|
failure = event.errorMessage;
|
|
111
115
|
if (event.author !== 'orchestrator')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"investigator.js","sourceRoot":"","sources":["../../src/agents/investigator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"investigator.js","sourceRoot":"","sources":["../../src/agents/investigator.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,12 +26,16 @@ export class ResilientLlm extends BaseLlm {
|
|
|
26
26
|
this.attempts = Math.max(1, options.attempts ?? 2);
|
|
27
27
|
this.transientAttempts = Math.max(1, options.transientAttempts ?? 3);
|
|
28
28
|
this.maxRetryDelayMs = options.maxRetryDelayMs ?? 60_000;
|
|
29
|
-
|
|
29
|
+
// unref: a wait that a stop has already ended must not keep the process alive until its timer fires.
|
|
30
|
+
this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => void setTimeout(resolve, ms).unref?.()));
|
|
30
31
|
}
|
|
31
32
|
async *generateContentAsync(request, stream = false, abortSignal) {
|
|
32
33
|
// Hangs and provider errors are counted apart: a call may hang once and be rate-limited twice.
|
|
33
34
|
let transientTries = 1;
|
|
34
35
|
for (let attempt = 1;; attempt++) {
|
|
36
|
+
// Stopped while we were waiting out a rate limit (or before we began): no new call goes out — nobody reads it.
|
|
37
|
+
if (abortSignal?.aborted)
|
|
38
|
+
return;
|
|
35
39
|
// Our own signal: a provider that supports cancelling (Gemini) stops the hung request; one that does not (a CLI
|
|
36
40
|
// model) keeps running in the background and its late answer is dropped.
|
|
37
41
|
const controller = new AbortController();
|
|
@@ -48,9 +52,12 @@ export class ResilientLlm extends BaseLlm {
|
|
|
48
52
|
next = await Promise.race([responses.next(), deadline]).finally(() => clearTimeout(timer));
|
|
49
53
|
}
|
|
50
54
|
catch (error) {
|
|
55
|
+
// The caller stopped the investigation and the provider dropped the call: not a model failure to report.
|
|
56
|
+
if (abortSignal?.aborted)
|
|
57
|
+
throw error;
|
|
51
58
|
const failure = parseModelError(error);
|
|
52
59
|
const wait = failure.retryAfterMs ?? backoffMs(transientTries);
|
|
53
|
-
const retry = isTransient(failure) && !answered && transientTries < this.transientAttempts && wait <= this.maxRetryDelayMs
|
|
60
|
+
const retry = isTransient(failure) && !answered && transientTries < this.transientAttempts && wait <= this.maxRetryDelayMs;
|
|
54
61
|
if (!retry) {
|
|
55
62
|
// An error we know how to explain is rethrown in plain words; anything else exactly as it came.
|
|
56
63
|
if (failure.status === undefined) {
|
|
@@ -64,7 +71,16 @@ export class ResilientLlm extends BaseLlm {
|
|
|
64
71
|
transientTries++;
|
|
65
72
|
const what = failure.status === 429 ? 'rate limit reached (429)' : `provider unavailable (${failure.status})`;
|
|
66
73
|
this.options.onRetry?.({ attempt: transientTries, attempts: this.transientAttempts, reason: `${what}, waiting ${Math.ceil(wait / 1000)}s` });
|
|
67
|
-
|
|
74
|
+
// A stop does not wait out the provider's "retry in 50 s".
|
|
75
|
+
await new Promise((resolve) => {
|
|
76
|
+
// Whichever comes first ends the wait and takes the listener off — one is not left behind per retry.
|
|
77
|
+
const done = () => {
|
|
78
|
+
abortSignal?.removeEventListener('abort', done);
|
|
79
|
+
resolve();
|
|
80
|
+
};
|
|
81
|
+
abortSignal?.addEventListener('abort', done, { once: true });
|
|
82
|
+
void this.sleep(wait).then(done);
|
|
83
|
+
});
|
|
68
84
|
// The same attempt again: this was not a hang.
|
|
69
85
|
attempt--;
|
|
70
86
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resilient-llm.js","sourceRoot":"","sources":["../../src/agents/resilient-llm.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,oHAAoH;AACpH,uHAAuH;AACvH,kCAAkC;AAClC,OAAO,EAAE,OAAO,EAA6D,MAAM,aAAa,CAAA;AAChG,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAkCnF,uDAAuD;AACvD,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAA;AAEhE,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAA;AACrC,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAA;AAC7C,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAA;AAEhD,MAAM,OAAO,YAAa,SAAQ,OAAO;IAQpB,KAAK;IACL,OAAO;IART,aAAa,CAAQ;IACrB,QAAQ,CAAQ;IAChB,iBAAiB,CAAQ;IACzB,eAAe,CAAQ;IACvB,KAAK,CAA+B;IAErD,YACmB,KAAc,EACd,OAAO,GAAwB,EAAE;QAElD,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;qBAHZ,KAAK;uBACL,OAAO;QAGxB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAA;QACrE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAA;QAClD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAA;QACpE,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,MAAM,CAAA;QACxD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"resilient-llm.js","sourceRoot":"","sources":["../../src/agents/resilient-llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,7 +42,9 @@ tells whether the error rate changed with the latest deployment (errorRateChange
|
|
|
42
42
|
A trace can look completely clean — no error, not slow — and still be wrong: get_trace's \`integrityCheck\` field on a
|
|
43
43
|
span means that span's response did not match what was requested. get_errors will not find these (their status is not
|
|
44
44
|
"error"); you only see them by opening the trace. Report this as a data-integrity problem, distinct from an exception,
|
|
45
|
-
and name what the mismatched spans share (same operation? same deployment version?).
|
|
45
|
+
and name what the mismatched spans share (same operation? same deployment version?). compare_versions' \`integrity\`
|
|
46
|
+
counts those checks per version: say which version started failing them and how often (failed of checked). Quote the
|
|
47
|
+
expected/actual pairs as they are — two or three pairs are not a pattern, do not read one into them. Max 4 sentences.`,
|
|
46
48
|
tools: ['get_errors', 'compare_versions', 'search_traces', 'get_trace'],
|
|
47
49
|
},
|
|
48
50
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specialists.js","sourceRoot":"","sources":["../../src/agents/specialists.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,2HAA2H;AAE3H,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,cAAc,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,CAAU,CAAA;AAa1I,MAAM,IAAI,GAAG,wBAAwB,CAAA;AAErC,wGAAwG;AACxG,MAAM,UAAU,gBAAgB,CAAC,IAAoB;IACnD,MAAM,KAAK,GAAG,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,YAAY,CAAA;IACzF,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;IAChG,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,0DAA0D,CAAC,CAAA;IAC/I,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,8BAA8B,CAAC,CAAA;IACzF,KAAK,MAAM,KAAK,IAAI,CAAC,aAAa,EAAE,aAAa,CAAU,EAAE,CAAC;QAC5D,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,KAAK,6BAA6B,CAAC,CAAA;IAC9H,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,qCAAqC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChJ,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAE,UAAgC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACxF,IAAI,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC1H,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAA;AACzI,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAqB;IACpD;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,wGAAwG;QACrH,WAAW,EAAE;;;uEAGsD;QACnE,KAAK,EAAE,CAAC,qBAAqB,EAAE,kBAAkB,EAAE,eAAe,EAAE,WAAW,CAAC;KACjF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,qQAAqQ;QAClR,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"specialists.js","sourceRoot":"","sources":["../../src/agents/specialists.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ChatEvent } from './chat.js';
|
|
2
|
+
export interface StoredTurn {
|
|
3
|
+
id: string;
|
|
4
|
+
/** The question asked; absent for a turn the observer started — its first event is the anomaly. */
|
|
5
|
+
question?: string;
|
|
6
|
+
proactive: boolean;
|
|
7
|
+
startedAtMs: number;
|
|
8
|
+
events: ChatEvent[];
|
|
9
|
+
/** False once it ended — with a report, an error, a stop, or simply because nobody was left to answer. */
|
|
10
|
+
running: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ChatHistoryOptions {
|
|
13
|
+
/** Turns kept; the oldest go first. Default 100. */
|
|
14
|
+
maxTurns?: number;
|
|
15
|
+
/** Events kept per turn (steps of a long investigation). Default 500. */
|
|
16
|
+
maxEvents?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class ChatHistory {
|
|
19
|
+
private readonly turns;
|
|
20
|
+
private readonly maxTurns;
|
|
21
|
+
private readonly maxEvents;
|
|
22
|
+
constructor(options?: ChatHistoryOptions);
|
|
23
|
+
/** Begins a turn. An id already known is left as it is: the same question is not recorded twice. */
|
|
24
|
+
start(turn: Pick<StoredTurn, 'id' | 'proactive' | 'startedAtMs'> & {
|
|
25
|
+
question?: string;
|
|
26
|
+
running?: boolean;
|
|
27
|
+
}): void;
|
|
28
|
+
/** Adds an event to a turn; one that ends the turn stops it. An unknown (already dropped) turn is ignored. */
|
|
29
|
+
add(id: string, event: ChatEvent): void;
|
|
30
|
+
/** The turn is over, whatever its last event was (the asker's connection closed, the handler returned). */
|
|
31
|
+
end(id: string): void;
|
|
32
|
+
has(id: string): boolean;
|
|
33
|
+
/** Oldest first. Copies: what the caller does with them does not reach the history. */
|
|
34
|
+
list(): StoredTurn[];
|
|
35
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const isEnd = (event) => event.type === 'report' || event.type === 'error' || event.type === 'stopped';
|
|
2
|
+
export class ChatHistory {
|
|
3
|
+
turns = new Map();
|
|
4
|
+
maxTurns;
|
|
5
|
+
maxEvents;
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.maxTurns = Math.max(1, options.maxTurns ?? 100);
|
|
8
|
+
this.maxEvents = Math.max(1, options.maxEvents ?? 500);
|
|
9
|
+
}
|
|
10
|
+
/** Begins a turn. An id already known is left as it is: the same question is not recorded twice. */
|
|
11
|
+
start(turn) {
|
|
12
|
+
if (this.turns.has(turn.id))
|
|
13
|
+
return;
|
|
14
|
+
this.turns.set(turn.id, { id: turn.id, ...(turn.question === undefined ? {} : { question: turn.question }), proactive: turn.proactive, startedAtMs: turn.startedAtMs, events: [], running: turn.running ?? true });
|
|
15
|
+
while (this.turns.size > this.maxTurns)
|
|
16
|
+
this.turns.delete(this.turns.keys().next().value);
|
|
17
|
+
}
|
|
18
|
+
/** Adds an event to a turn; one that ends the turn stops it. An unknown (already dropped) turn is ignored. */
|
|
19
|
+
add(id, event) {
|
|
20
|
+
const turn = this.turns.get(id);
|
|
21
|
+
if (!turn)
|
|
22
|
+
return;
|
|
23
|
+
// The end of a turn is never the event to drop: a long investigation loses its middle steps, not its report.
|
|
24
|
+
if (turn.events.length >= this.maxEvents && !isEnd(event))
|
|
25
|
+
return;
|
|
26
|
+
turn.events.push(event);
|
|
27
|
+
if (isEnd(event))
|
|
28
|
+
turn.running = false;
|
|
29
|
+
}
|
|
30
|
+
/** The turn is over, whatever its last event was (the asker's connection closed, the handler returned). */
|
|
31
|
+
end(id) {
|
|
32
|
+
const turn = this.turns.get(id);
|
|
33
|
+
if (turn)
|
|
34
|
+
turn.running = false;
|
|
35
|
+
}
|
|
36
|
+
has(id) {
|
|
37
|
+
return this.turns.has(id);
|
|
38
|
+
}
|
|
39
|
+
/** Oldest first. Copies: what the caller does with them does not reach the history. */
|
|
40
|
+
list() {
|
|
41
|
+
return [...this.turns.values()].map((turn) => ({ ...turn, events: [...turn.events] }));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=chat-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-history.js","sourceRoot":"","sources":["../../src/collector/chat-history.ts"],"names":[],"mappings":"AAuBA,MAAM,KAAK,GAAG,CAAC,KAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAA;AAEjH,MAAM,OAAO,WAAW;IACL,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAA;IACrC,QAAQ,CAAQ;IAChB,SAAS,CAAQ;IAElC,YAAY,OAAO,GAAuB,EAAE;QAC1C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAA;QACpD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC,CAAA;IACxD,CAAC;IAED,oGAAoG;IACpG,KAAK,CAAC,IAAqG;QACzG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAM;QACnC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAA;QAClN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAe,CAAC,CAAA;IACrG,CAAC;IAED,8GAA8G;IAC9G,GAAG,CAAC,EAAU,EAAE,KAAgB;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,6GAA6G;QAC7G,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAM;QACjE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,IAAI,KAAK,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACxC,CAAC;IAED,2GAA2G;IAC3G,GAAG,CAAC,EAAU;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC/B,IAAI,IAAI;YAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IAChC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC3B,CAAC;IAED,uFAAuF;IACvF,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;IACxF,CAAC;CACF"}
|
package/dist/collector/chat.d.ts
CHANGED
|
@@ -44,6 +44,17 @@ export type EvidenceCard = {
|
|
|
44
44
|
kind: 'silent';
|
|
45
45
|
service: string;
|
|
46
46
|
lastSpanSecondsAgo: number;
|
|
47
|
+
}
|
|
48
|
+
/** The app's own checks of its answers, per deployed version: where wrong data started and how often it happens. */
|
|
49
|
+
| {
|
|
50
|
+
kind: 'wrong-data';
|
|
51
|
+
service: string;
|
|
52
|
+
operation: string;
|
|
53
|
+
versions: {
|
|
54
|
+
version: string;
|
|
55
|
+
checked: number;
|
|
56
|
+
failed: number;
|
|
57
|
+
}[];
|
|
47
58
|
} | {
|
|
48
59
|
kind: 'traces';
|
|
49
60
|
label: string;
|
|
@@ -73,14 +84,27 @@ export type ChatEvent = {
|
|
|
73
84
|
} | {
|
|
74
85
|
type: 'report';
|
|
75
86
|
text: string;
|
|
76
|
-
}
|
|
87
|
+
}
|
|
88
|
+
/** Somebody stopped the investigation; what was found until then stays on the page. */
|
|
89
|
+
| {
|
|
90
|
+
type: 'stopped';
|
|
91
|
+
closed?: true;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* `closed`: this conversation cannot be continued (it was stopped or timed out, so its history ends in the middle of
|
|
95
|
+
* a step) — the next question has to start a new one. The observer says so; the client does not have to guess.
|
|
96
|
+
*/
|
|
97
|
+
| {
|
|
77
98
|
type: 'error';
|
|
78
99
|
message: string;
|
|
100
|
+
closed?: true;
|
|
79
101
|
};
|
|
80
102
|
export interface ChatRequest {
|
|
81
103
|
question: string;
|
|
82
104
|
/** From a previous `status` event: continue that conversation. Omitted → a new conversation. */
|
|
83
105
|
sessionId?: string;
|
|
106
|
+
/** Aborted when somebody stops the investigation (the Stop button, or the asker went away). */
|
|
107
|
+
signal?: AbortSignal;
|
|
84
108
|
}
|
|
85
109
|
/** Runs one chat turn, emitting events as it goes. Resolves when the turn is over. */
|
|
86
110
|
export type ChatHandler = (request: ChatRequest, emit: (event: ChatEvent) => void) => Promise<void>;
|