@qorejs/qore 1.0.3 → 1.0.5
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 +16 -0
- package/dist/src/core/devtools.d.ts +29 -0
- package/dist/src/core/devtools.d.ts.map +1 -1
- package/dist/src/core/devtools.js +169 -0
- package/dist/src/core/devtools.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/docs/api.md +6 -1
- package/docs/devtools.md +53 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,6 +101,22 @@ See [React Adapter](./docs/react.md) for lifecycle, status, abort, and signal su
|
|
|
101
101
|
|
|
102
102
|
Provider adapters are intended for server-side or trusted runtimes. Do not put `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or any vendor secret in browser code. For browsers, expose your own SSE or NDJSON endpoint and stream that endpoint into Qore.
|
|
103
103
|
|
|
104
|
+
## Inspect Streams
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
import { createStreamInspector, stream } from '@qorejs/qore';
|
|
108
|
+
|
|
109
|
+
const inspector = createStreamInspector({ maxEvents: 200 });
|
|
110
|
+
const answer = stream(provider.chat(prompt), { name: 'answer' });
|
|
111
|
+
const trace = inspector.stream('answer');
|
|
112
|
+
|
|
113
|
+
await answer.ready;
|
|
114
|
+
console.log(trace()?.firstChunkLatencyMs, trace()?.chunksPerSecond);
|
|
115
|
+
inspector.dispose();
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The inspector is zero-dependency and built on the same `__QORE_DEVTOOLS__` hook that custom panels can consume. It reports lifecycle events, terminal state, first-chunk latency, total duration, and chunk throughput.
|
|
119
|
+
|
|
104
120
|
## Documentation
|
|
105
121
|
|
|
106
122
|
- [Concepts](./docs/concepts.md): `stream = signal` and the mental model
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResponseStatus } from './response.js';
|
|
2
|
+
import { type ReadonlySignal } from './signal.js';
|
|
2
3
|
export type QoreDevtoolsStreamPhase = 'create' | 'status' | 'chunk' | 'complete' | 'error' | 'abort';
|
|
3
4
|
export interface QoreDevtoolsStreamEvent<TChunk = unknown, TValue = unknown> {
|
|
4
5
|
kind: 'stream';
|
|
@@ -18,11 +19,39 @@ export interface QoreDevtoolsHook {
|
|
|
18
19
|
events?: QoreDevtoolsEvent[];
|
|
19
20
|
emit?(event: QoreDevtoolsEvent): void;
|
|
20
21
|
}
|
|
22
|
+
export interface QoreInspectedStream<TValue = unknown> {
|
|
23
|
+
id: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
status?: ResponseStatus;
|
|
26
|
+
value?: TValue;
|
|
27
|
+
chunkCount: number;
|
|
28
|
+
createdAt: number;
|
|
29
|
+
updatedAt: number;
|
|
30
|
+
firstChunkAt?: number;
|
|
31
|
+
finishedAt?: number;
|
|
32
|
+
durationMs?: number;
|
|
33
|
+
firstChunkLatencyMs?: number;
|
|
34
|
+
chunksPerSecond?: number;
|
|
35
|
+
terminal: boolean;
|
|
36
|
+
error?: Error | null;
|
|
37
|
+
}
|
|
38
|
+
export interface StreamInspectorOptions {
|
|
39
|
+
maxEvents?: number;
|
|
40
|
+
capturePayloads?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface QoreStreamInspector {
|
|
43
|
+
events: ReadonlySignal<readonly QoreDevtoolsEvent[]>;
|
|
44
|
+
streams: ReadonlySignal<readonly QoreInspectedStream[]>;
|
|
45
|
+
stream(idOrName: string): ReadonlySignal<QoreInspectedStream | undefined>;
|
|
46
|
+
clear(): void;
|
|
47
|
+
dispose(): void;
|
|
48
|
+
}
|
|
21
49
|
type QoreDevtoolsTarget = QoreDevtoolsHook | ((event: QoreDevtoolsEvent) => void) | undefined;
|
|
22
50
|
declare global {
|
|
23
51
|
var __QORE_DEVTOOLS__: QoreDevtoolsTarget;
|
|
24
52
|
}
|
|
25
53
|
export declare function createDevtoolsStreamId(): string;
|
|
26
54
|
export declare function emitQoreDevtoolsEvent(event: QoreDevtoolsEvent): void;
|
|
55
|
+
export declare function createStreamInspector(options?: StreamInspectorOptions): QoreStreamInspector;
|
|
27
56
|
export {};
|
|
28
57
|
//# sourceMappingURL=devtools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.d.ts","sourceRoot":"","sources":["../../../src/core/devtools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"devtools.d.ts","sourceRoot":"","sources":["../../../src/core/devtools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAyC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzF,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAErG,MAAM,WAAW,uBAAuB,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO;IACzE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,uBAAuB,CAAC;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,mBAAmB,CAAC,MAAM,GAAG,OAAO;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC;IACrD,OAAO,EAAE,cAAc,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAAC;IACxD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAAC;IAC1E,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,KAAK,kBAAkB,GAAG,gBAAgB,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;AAE9F,OAAO,CAAC,MAAM,CAAC;IAGb,IAAI,iBAAiB,EAAE,kBAAkB,CAAC;CAC3C;AAID,wBAAgB,sBAAsB,IAAI,MAAM,CAG/C;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAsBpE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,mBAAmB,CAgH/F"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { computed, signal } from './signal.js';
|
|
1
2
|
let nextStreamId = 0;
|
|
2
3
|
export function createDevtoolsStreamId() {
|
|
3
4
|
nextStreamId += 1;
|
|
@@ -23,4 +24,172 @@ export function emitQoreDevtoolsEvent(event) {
|
|
|
23
24
|
// DevTools instrumentation must never affect application control flow.
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
export function createStreamInspector(options = {}) {
|
|
28
|
+
const { maxEvents = 500, capturePayloads = true } = options;
|
|
29
|
+
const previousHook = globalThis.__QORE_DEVTOOLS__;
|
|
30
|
+
const recordedEvents = signal([]);
|
|
31
|
+
const streamSelectors = new Map();
|
|
32
|
+
function record(event) {
|
|
33
|
+
const nextEvent = capturePayloads ? event : withoutPayload(event);
|
|
34
|
+
recordedEvents.update((currentEvents) => {
|
|
35
|
+
const nextEvents = [...currentEvents, nextEvent];
|
|
36
|
+
return nextEvents.length > maxEvents ? nextEvents.slice(nextEvents.length - maxEvents) : nextEvents;
|
|
37
|
+
});
|
|
38
|
+
forwardDevtoolsEvent(previousHook, event);
|
|
39
|
+
}
|
|
40
|
+
globalThis.__QORE_DEVTOOLS__ = record;
|
|
41
|
+
const inspectedStreams = computed(() => {
|
|
42
|
+
const byId = new Map();
|
|
43
|
+
for (const event of recordedEvents()) {
|
|
44
|
+
if (event.kind !== 'stream') {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const previous = byId.get(event.id);
|
|
48
|
+
const createdAt = previous?.createdAt ?? event.timestamp;
|
|
49
|
+
const updatedAt = event.timestamp;
|
|
50
|
+
const chunkCount = event.chunkCount ?? previous?.chunkCount ?? 0;
|
|
51
|
+
const terminal = previous?.terminal === true || isTerminalPhase(event.phase);
|
|
52
|
+
const nextStreamInput = {
|
|
53
|
+
id: event.id,
|
|
54
|
+
chunkCount,
|
|
55
|
+
createdAt,
|
|
56
|
+
updatedAt,
|
|
57
|
+
terminal
|
|
58
|
+
};
|
|
59
|
+
const name = event.name ?? previous?.name;
|
|
60
|
+
const status = event.status ?? previous?.status;
|
|
61
|
+
const value = event.value ?? previous?.value;
|
|
62
|
+
const firstChunkAt = event.phase === 'chunk'
|
|
63
|
+
? previous?.firstChunkAt ?? event.timestamp
|
|
64
|
+
: previous?.firstChunkAt;
|
|
65
|
+
const finishedAt = isTerminalPhase(event.phase) ? event.timestamp : previous?.finishedAt;
|
|
66
|
+
const error = event.error ?? previous?.error;
|
|
67
|
+
if (name !== undefined) {
|
|
68
|
+
nextStreamInput.name = name;
|
|
69
|
+
}
|
|
70
|
+
if (status !== undefined) {
|
|
71
|
+
nextStreamInput.status = status;
|
|
72
|
+
}
|
|
73
|
+
if (value !== undefined) {
|
|
74
|
+
nextStreamInput.value = value;
|
|
75
|
+
}
|
|
76
|
+
if (firstChunkAt !== undefined) {
|
|
77
|
+
nextStreamInput.firstChunkAt = firstChunkAt;
|
|
78
|
+
}
|
|
79
|
+
if (finishedAt !== undefined) {
|
|
80
|
+
nextStreamInput.finishedAt = finishedAt;
|
|
81
|
+
}
|
|
82
|
+
if (error !== undefined) {
|
|
83
|
+
nextStreamInput.error = error;
|
|
84
|
+
}
|
|
85
|
+
const nextStream = createInspectedStream(nextStreamInput);
|
|
86
|
+
byId.set(event.id, nextStream);
|
|
87
|
+
}
|
|
88
|
+
return [...byId.values()];
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
events: recordedEvents,
|
|
92
|
+
streams: inspectedStreams,
|
|
93
|
+
stream(idOrName) {
|
|
94
|
+
const existingSelector = streamSelectors.get(idOrName);
|
|
95
|
+
if (existingSelector) {
|
|
96
|
+
return existingSelector;
|
|
97
|
+
}
|
|
98
|
+
const selector = computed(() => inspectedStreams().find((stream) => stream.id === idOrName || stream.name === idOrName));
|
|
99
|
+
streamSelectors.set(idOrName, selector);
|
|
100
|
+
return selector;
|
|
101
|
+
},
|
|
102
|
+
clear() {
|
|
103
|
+
recordedEvents([]);
|
|
104
|
+
},
|
|
105
|
+
dispose() {
|
|
106
|
+
inspectedStreams.stop();
|
|
107
|
+
for (const selector of streamSelectors.values()) {
|
|
108
|
+
selector.stop();
|
|
109
|
+
}
|
|
110
|
+
streamSelectors.clear();
|
|
111
|
+
if (globalThis.__QORE_DEVTOOLS__ === record) {
|
|
112
|
+
globalThis.__QORE_DEVTOOLS__ = previousHook;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function createInspectedStream(input) {
|
|
118
|
+
const stream = {
|
|
119
|
+
id: input.id,
|
|
120
|
+
chunkCount: input.chunkCount,
|
|
121
|
+
createdAt: input.createdAt,
|
|
122
|
+
updatedAt: input.updatedAt,
|
|
123
|
+
terminal: input.terminal
|
|
124
|
+
};
|
|
125
|
+
if (input.name !== undefined) {
|
|
126
|
+
stream.name = input.name;
|
|
127
|
+
}
|
|
128
|
+
if (input.status !== undefined) {
|
|
129
|
+
stream.status = input.status;
|
|
130
|
+
}
|
|
131
|
+
if (input.value !== undefined) {
|
|
132
|
+
stream.value = input.value;
|
|
133
|
+
}
|
|
134
|
+
if (input.finishedAt !== undefined) {
|
|
135
|
+
stream.finishedAt = input.finishedAt;
|
|
136
|
+
}
|
|
137
|
+
if (input.firstChunkAt !== undefined) {
|
|
138
|
+
stream.firstChunkAt = input.firstChunkAt;
|
|
139
|
+
stream.firstChunkLatencyMs = Math.max(0, input.firstChunkAt - input.createdAt);
|
|
140
|
+
}
|
|
141
|
+
const durationEnd = input.finishedAt ?? input.updatedAt;
|
|
142
|
+
const durationMs = Math.max(0, durationEnd - input.createdAt);
|
|
143
|
+
stream.durationMs = durationMs;
|
|
144
|
+
if (input.chunkCount > 0) {
|
|
145
|
+
stream.chunksPerSecond = input.chunkCount / (Math.max(1, durationMs) / 1000);
|
|
146
|
+
}
|
|
147
|
+
if (input.error !== undefined) {
|
|
148
|
+
stream.error = input.error;
|
|
149
|
+
}
|
|
150
|
+
return stream;
|
|
151
|
+
}
|
|
152
|
+
function withoutPayload(event) {
|
|
153
|
+
const nextEvent = {
|
|
154
|
+
kind: event.kind,
|
|
155
|
+
phase: event.phase,
|
|
156
|
+
id: event.id,
|
|
157
|
+
timestamp: event.timestamp
|
|
158
|
+
};
|
|
159
|
+
if (event.name !== undefined) {
|
|
160
|
+
nextEvent.name = event.name;
|
|
161
|
+
}
|
|
162
|
+
if (event.status !== undefined) {
|
|
163
|
+
nextEvent.status = event.status;
|
|
164
|
+
}
|
|
165
|
+
if (event.chunkCount !== undefined) {
|
|
166
|
+
nextEvent.chunkCount = event.chunkCount;
|
|
167
|
+
}
|
|
168
|
+
if (event.error !== undefined) {
|
|
169
|
+
nextEvent.error = event.error;
|
|
170
|
+
}
|
|
171
|
+
return nextEvent;
|
|
172
|
+
}
|
|
173
|
+
function isTerminalPhase(phase) {
|
|
174
|
+
return phase === 'complete' || phase === 'error' || phase === 'abort';
|
|
175
|
+
}
|
|
176
|
+
function forwardDevtoolsEvent(target, event) {
|
|
177
|
+
if (!target) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
if (typeof target === 'function') {
|
|
182
|
+
target(event);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (target.enabled === false) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
target.events?.push(event);
|
|
189
|
+
target.emit?.(event);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Inspector forwarding must remain best-effort for the same reason as raw hook emission.
|
|
193
|
+
}
|
|
194
|
+
}
|
|
26
195
|
//# sourceMappingURL=devtools.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.js","sourceRoot":"","sources":["../../../src/core/devtools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"devtools.js","sourceRoot":"","sources":["../../../src/core/devtools.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { signal, computed, createRoot, effect, onCleanup, batch, untrack, isSignal } from './core/signal.js';
|
|
2
2
|
export type { ComputedSignal, ReadonlySignal, Signal } from './core/signal.js';
|
|
3
3
|
export type { EffectOptions, EffectScheduler, SubscribeOptions } from './core/signal-types.js';
|
|
4
|
-
export
|
|
4
|
+
export { createStreamInspector } from './core/devtools.js';
|
|
5
|
+
export type { QoreDevtoolsEvent, QoreDevtoolsHook, QoreDevtoolsStreamEvent, QoreDevtoolsStreamPhase, QoreInspectedStream, QoreStreamInspector, StreamInspectorOptions } from './core/devtools.js';
|
|
5
6
|
export { stream, createStream, from, mapStream, scanStream, toAsyncIterable } from './core/stream.js';
|
|
6
7
|
export type { BackpressureOptions, QoreEventStream, QoreStream, RetryBackoff, RetryableStreamOptions, StreamController, StreamEventBase, StreamEventOf, StreamEventOptions, StreamEventType, StreamFactory, StreamInput, StreamOptions, StreamSelectOptions, StreamSetup } from './core/stream.js';
|
|
7
8
|
export { createResponse, response } from './core/response.js';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC7G,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/E,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/F,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Re-export the public runtime surface from a single module entrypoint.
|
|
2
2
|
export { signal, computed, createRoot, effect, onCleanup, batch, untrack, isSignal } from './core/signal.js';
|
|
3
|
+
export { createStreamInspector } from './core/devtools.js';
|
|
3
4
|
export { stream, createStream, from, mapStream, scanStream, toAsyncIterable } from './core/stream.js';
|
|
4
5
|
export { createResponse, response } from './core/response.js';
|
|
5
6
|
export { createApp } from './dom/app.js';
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG7G,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAU3D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAkBtG,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAiB9D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAoB7D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAiD5B,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC"}
|
package/docs/api.md
CHANGED
|
@@ -80,10 +80,15 @@ import { createSSEResponse } from '@qorejs/qore';
|
|
|
80
80
|
## DevTools
|
|
81
81
|
|
|
82
82
|
```js
|
|
83
|
-
|
|
83
|
+
const inspector = createStreamInspector({ maxEvents: 200 });
|
|
84
84
|
const answer = stream(source, { name: 'answer' });
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
- `QoreStream.id`: stable runtime id for inspection.
|
|
88
88
|
- `QoreStream.name`: optional stream name from `StreamOptions.name`.
|
|
89
|
+
- `createStreamInspector(options?)`: install a disposable inspector over the global DevTools hook.
|
|
90
|
+
- `QoreStreamInspector.events()`: recent raw stream lifecycle events.
|
|
91
|
+
- `QoreStreamInspector.streams()`: derived stream summaries for custom panels and tests.
|
|
92
|
+
- `QoreStreamInspector.stream(idOrName)`: subscribe to one stream summary by runtime id or name.
|
|
93
|
+
- `QoreInspectedStream`: includes status, chunk count, terminal state, first-chunk latency, duration, and chunks-per-second metrics.
|
|
89
94
|
- `QoreDevtoolsEvent`: exported TypeScript event type for custom inspectors.
|
package/docs/devtools.md
CHANGED
|
@@ -2,6 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
Qore exposes a lightweight development hook for stream inspection. It is inert by default and does not install any global state unless your app provides one.
|
|
4
4
|
|
|
5
|
+
## Stream Inspector
|
|
6
|
+
|
|
7
|
+
For local dashboards, tests, and playgrounds, use the built-in inspector wrapper:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { createStreamInspector, stream } from '@qorejs/qore';
|
|
11
|
+
|
|
12
|
+
const inspector = createStreamInspector({ maxEvents: 200 });
|
|
13
|
+
|
|
14
|
+
const answer = stream(openai.chat('hello'), { name: 'answer' });
|
|
15
|
+
await answer.ready;
|
|
16
|
+
|
|
17
|
+
console.table(inspector.streams());
|
|
18
|
+
console.log(inspector.events());
|
|
19
|
+
|
|
20
|
+
inspector.dispose();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`inspector.events()` is a readonly signal containing the recent raw DevTools events. `inspector.streams()` is a derived readonly signal summarizing each observed stream by `id`, `name`, `status`, `chunkCount`, timestamps, latest value, and runtime metrics.
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
const answerSummary = inspector.stream('answer');
|
|
27
|
+
|
|
28
|
+
console.log({
|
|
29
|
+
status: answerSummary()?.status,
|
|
30
|
+
firstChunkLatencyMs: answerSummary()?.firstChunkLatencyMs,
|
|
31
|
+
durationMs: answerSummary()?.durationMs,
|
|
32
|
+
chunksPerSecond: answerSummary()?.chunksPerSecond,
|
|
33
|
+
terminal: answerSummary()?.terminal
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The summary includes:
|
|
38
|
+
|
|
39
|
+
- `firstChunkAt`: timestamp for the first observed chunk
|
|
40
|
+
- `firstChunkLatencyMs`: time from stream creation to first chunk
|
|
41
|
+
- `durationMs`: time from stream creation to terminal state, or latest update while active
|
|
42
|
+
- `chunksPerSecond`: observed chunk throughput, using a 1ms minimum window for instant streams
|
|
43
|
+
- `terminal`: whether the stream reached `complete`, `error`, or `abort`
|
|
44
|
+
|
|
45
|
+
Use `capturePayloads: false` when you want lifecycle timing without retaining token payloads:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const inspector = createStreamInspector({
|
|
49
|
+
maxEvents: 500,
|
|
50
|
+
capturePayloads: false
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Always call `dispose()` when a test, story, or custom panel is torn down. Disposal restores the previous global hook instead of leaving instrumentation attached.
|
|
55
|
+
|
|
56
|
+
## Raw Hook
|
|
57
|
+
|
|
5
58
|
```js
|
|
6
59
|
globalThis.__QORE_DEVTOOLS__ = {
|
|
7
60
|
events: [],
|