theorum 1.0.0 → 1.1.3
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 +81 -25
- package/esm/mod.d.ts +48 -29
- package/esm/mod.js +37 -24
- package/esm/src/cli/commands/bench.js +13 -16
- package/esm/src/cli/commands/fuzz-canary.js +25 -29
- package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
- package/esm/src/cli/commands/guardrails-eval.js +15 -0
- package/esm/src/cli/commands/profile.js +12 -3
- package/esm/src/cli/commands/run.js +8 -9
- package/esm/src/cli/commands/test.js +8 -8
- package/esm/src/cli/event-log.d.ts +1 -1
- package/esm/src/cli/index.js +12 -0
- package/esm/src/cli/matrix/synthesizer.d.ts +6 -6
- package/esm/src/cli/matrix/synthesizer.js +23 -22
- package/esm/src/guardrails/canary-gate.d.ts +2 -1
- package/esm/src/guardrails/canary-gate.js +2 -1
- package/esm/src/guardrails/canary.d.ts +9 -1
- package/esm/src/guardrails/canary.js +21 -10
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +1 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +12 -15
- package/esm/src/guardrails/corpus/inbound-payloads.js +1 -0
- package/esm/src/guardrails/corpus/live-attacks.js +0 -1
- package/esm/src/guardrails/corpus/mod.d.ts +1 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +1 -0
- package/esm/src/guardrails/corpus/secrets.js +1 -0
- package/esm/src/guardrails/corpus/strings.d.ts +1 -0
- package/esm/src/guardrails/corpus/strings.js +1 -0
- package/esm/src/guardrails/corpus/types.d.ts +1 -0
- package/esm/src/guardrails/egress.d.ts +26 -3
- package/esm/src/guardrails/egress.js +69 -18
- package/esm/src/guardrails/error.d.ts +14 -23
- package/esm/src/guardrails/error.js +86 -77
- package/esm/src/guardrails/eval/corpus.d.ts +108 -0
- package/esm/src/guardrails/eval/corpus.js +978 -0
- package/esm/src/guardrails/eval/mod.d.ts +51 -0
- package/esm/src/guardrails/eval/mod.js +133 -0
- package/esm/src/guardrails/eval/score.d.ts +66 -0
- package/esm/src/guardrails/eval/score.js +114 -0
- package/esm/src/guardrails/events.d.ts +25 -0
- package/esm/src/guardrails/events.js +56 -0
- package/esm/src/guardrails/hits.d.ts +24 -0
- package/esm/src/guardrails/hits.js +45 -0
- package/esm/src/guardrails/lexicon.d.ts +39 -0
- package/esm/src/guardrails/lexicon.js +200 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +15 -13
- package/esm/src/guardrails/live-outbound-gate.js +131 -89
- package/esm/src/guardrails/mod.d.ts +19 -4
- package/esm/src/guardrails/mod.js +12 -3
- package/esm/src/guardrails/network.d.ts +19 -0
- package/esm/src/guardrails/network.js +234 -0
- package/esm/src/guardrails/policy.d.ts +35 -0
- package/esm/src/guardrails/policy.js +50 -0
- package/esm/src/guardrails/progressive-yield.d.ts +51 -0
- package/esm/src/guardrails/progressive-yield.js +98 -0
- package/esm/src/guardrails/quota.d.ts +17 -3
- package/esm/src/guardrails/quota.js +18 -4
- package/esm/src/guardrails/sanitize.d.ts +36 -6
- package/esm/src/guardrails/sanitize.js +152 -60
- package/esm/src/guardrails/serialize.d.ts +35 -0
- package/esm/src/guardrails/serialize.js +58 -0
- package/esm/src/guardrails/testing.d.ts +7 -0
- package/esm/src/guardrails/testing.js +4 -0
- package/esm/src/guardrails/theorum-error.d.ts +12 -0
- package/esm/src/guardrails/theorum-error.js +15 -0
- package/esm/src/guardrails/tool-directives.d.ts +48 -0
- package/esm/src/guardrails/tool-directives.js +124 -0
- package/esm/src/guardrails/tool-result.d.ts +93 -0
- package/esm/src/guardrails/tool-result.js +276 -0
- package/esm/src/guardrails/types.d.ts +291 -0
- package/esm/src/guardrails/types.js +72 -0
- package/esm/src/host/client-turn.js +4 -0
- package/esm/src/host/mint-trace.d.ts +1 -1
- package/esm/src/kernel/auth/crypto.d.ts +42 -0
- package/esm/src/kernel/auth/crypto.js +106 -0
- package/esm/src/kernel/auth/mod.d.ts +11 -0
- package/esm/src/kernel/auth/mod.js +11 -0
- package/esm/src/kernel/auth/oauth.d.ts +47 -0
- package/esm/src/kernel/auth/oauth.js +278 -0
- package/esm/src/kernel/auth/types.d.ts +133 -0
- package/esm/src/kernel/auth/types.js +13 -0
- package/esm/src/kernel/engine/delta.js +43 -2
- package/esm/src/kernel/engine/live-inbound.d.ts +15 -3
- package/esm/src/kernel/engine/live-inbound.js +22 -8
- package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
- package/esm/src/kernel/engine/live-ingress.js +47 -0
- package/esm/src/kernel/engine/repair.js +13 -12
- package/esm/src/kernel/engine/runner/gates.js +127 -40
- package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
- package/esm/src/kernel/engine/runner/mod.js +182 -43
- package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
- package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
- package/esm/src/kernel/engine/runner/stages.js +89 -0
- package/esm/src/kernel/engine/runner/state.d.ts +24 -0
- package/esm/src/kernel/engine/runner/steps.js +128 -61
- package/esm/src/kernel/engine/runner/stream.d.ts +9 -2
- package/esm/src/kernel/engine/runner/stream.js +114 -55
- package/esm/src/kernel/engine/session/mod.d.ts +3 -1
- package/esm/src/kernel/engine/session/mod.js +386 -34
- package/esm/src/kernel/interaction-parts.d.ts +14 -0
- package/esm/src/kernel/interaction-parts.js +23 -0
- package/esm/src/kernel/mod.d.ts +19 -7
- package/esm/src/kernel/mod.js +10 -5
- package/esm/src/kernel/profile-graph.d.ts +159 -0
- package/esm/src/kernel/profile-graph.js +156 -0
- package/esm/src/kernel/registry/attachments.d.ts +10 -10
- package/esm/src/kernel/registry/attachments.js +29 -26
- package/esm/src/kernel/registry/catalog.d.ts +25 -11
- package/esm/src/kernel/registry/catalog.js +59 -24
- package/esm/src/kernel/registry/ingress.js +34 -22
- package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
- package/esm/src/kernel/registry/profile-outputs.js +8 -0
- package/esm/src/kernel/registry/profiles.d.ts +34 -14
- package/esm/src/kernel/registry/profiles.js +306 -59
- package/esm/src/kernel/registry/provider-request.js +2 -0
- package/esm/src/kernel/registry/resolve.d.ts +7 -6
- package/esm/src/kernel/registry/resolve.js +102 -117
- package/esm/src/kernel/registry/schemas.js +1 -1
- package/esm/src/kernel/registry/sole-model.d.ts +8 -0
- package/esm/src/kernel/registry/sole-model.js +10 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
- package/esm/src/kernel/registry/system-prompt.js +40 -0
- package/esm/src/kernel/registry/system-role.d.ts +8 -0
- package/esm/src/kernel/registry/system-role.js +14 -0
- package/esm/src/kernel/registry/vault.d.ts +2 -2
- package/esm/src/kernel/registry/vault.js +4 -4
- package/esm/src/kernel/schema.d.ts +97 -11
- package/esm/src/kernel/schema.js +256 -111
- package/esm/src/kernel/stages.d.ts +175 -0
- package/esm/src/kernel/stages.js +476 -0
- package/esm/src/kernel/stop.d.ts +65 -11
- package/esm/src/kernel/stop.js +46 -11
- package/esm/src/kernel/tools/events.d.ts +41 -0
- package/esm/src/kernel/tools/events.js +71 -0
- package/esm/src/kernel/tools/execute.d.ts +63 -24
- package/esm/src/kernel/tools/execute.js +475 -224
- package/esm/src/kernel/tools/harness.js +16 -14
- package/esm/src/kernel/tools/invoke.js +26 -8
- package/esm/src/kernel/tools/mod.d.ts +3 -1
- package/esm/src/kernel/tools/mod.js +2 -1
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +47 -0
- package/esm/src/kernel/tools/project.js +5 -3
- package/esm/src/kernel/tools/registry.js +20 -10
- package/esm/src/kernel/tools/remote.d.ts +94 -0
- package/esm/src/kernel/tools/remote.js +577 -0
- package/esm/src/kernel/tools/resolve.d.ts +17 -7
- package/esm/src/kernel/tools/resolve.js +38 -17
- package/esm/src/kernel/tools/schema.d.ts +2 -0
- package/esm/src/kernel/tools/schema.js +23 -6
- package/esm/src/kernel/tools/stage-run.d.ts +105 -0
- package/esm/src/kernel/tools/stage-run.js +155 -0
- package/esm/src/kernel/tools/types.d.ts +198 -20
- package/esm/src/kernel/types.d.ts +253 -114
- package/esm/src/kernel/util/find-last.d.ts +2 -0
- package/esm/src/kernel/util/find-last.js +10 -0
- package/esm/src/observability/destinations.d.ts +31 -0
- package/esm/src/observability/destinations.js +67 -0
- package/esm/src/observability/mod.d.ts +10 -3
- package/esm/src/observability/mod.js +6 -2
- package/esm/src/observability/policy.d.ts +27 -0
- package/esm/src/observability/policy.js +80 -0
- package/esm/src/observability/resolve-policy.d.ts +16 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/trace-attach.d.ts +3 -1
- package/esm/src/observability/trace-attach.js +17 -10
- package/esm/src/observability/trace-record.d.ts +12 -4
- package/esm/src/observability/trace-record.js +63 -19
- package/esm/src/observability/trace-sink.d.ts +19 -0
- package/esm/src/observability/trace-sink.js +10 -0
- package/esm/src/observability/trace.d.ts +14 -11
- package/esm/src/observability/trace.js +23 -14
- package/esm/src/observability/types.d.ts +113 -0
- package/esm/src/observability/types.js +11 -0
- package/esm/src/providers/create-provider.d.ts +7 -4
- package/esm/src/providers/create-provider.js +21 -7
- package/esm/src/providers/google/interactions/framing.d.ts +8 -0
- package/esm/src/providers/google/interactions/framing.js +74 -13
- package/esm/src/providers/google/live/framing.d.ts +5 -2
- package/esm/src/providers/google/live/framing.js +49 -12
- package/esm/src/providers/google/live/openapi-schema.js +3 -2
- package/esm/src/providers/google/live/stream.d.ts +9 -0
- package/esm/src/providers/google/live/stream.js +16 -3
- package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
- package/esm/src/providers/openrouter/cache-control.js +23 -0
- package/esm/src/providers/openrouter/chat.d.ts +21 -1
- package/esm/src/providers/openrouter/chat.js +51 -6
- package/esm/src/providers/openrouter/image.js +8 -19
- package/esm/src/providers/openrouter/openai/chat-payload.js +23 -1
- package/esm/src/providers/openrouter/openai/compat.d.ts +7 -1
- package/esm/src/providers/openrouter/openai/compat.js +23 -4
- package/esm/src/providers/openrouter/openai/image-payload.js +8 -2
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +1 -1
- package/esm/src/providers/openrouter/openai/sdk-messages.js +32 -5
- package/package.json +1 -1
- package/esm/src/interface/blocks.d.ts +0 -20
- package/esm/src/interface/blocks.js +0 -180
- package/esm/src/interface/from-profile.d.ts +0 -14
- package/esm/src/interface/from-profile.js +0 -104
- package/esm/src/interface/inputs.d.ts +0 -8
- package/esm/src/interface/inputs.js +0 -127
- package/esm/src/interface/mod.d.ts +0 -10
- package/esm/src/interface/mod.js +0 -9
- package/esm/src/interface/types.d.ts +0 -153
- package/esm/src/interface/types.js +0 -13
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-registered trace destinations for profile `observability.writeTo` ids.
|
|
3
|
+
*
|
|
4
|
+
* THEORUM does not invent filesystem roots. Hosts register a named destination
|
|
5
|
+
* once per process; profiles reference it by id.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { TheorumError } from '../guardrails/error.js';
|
|
10
|
+
const destinations = new Map();
|
|
11
|
+
/** Build a JSONL destination descriptor for `registerTraceDestination`. */
|
|
12
|
+
function jsonlDestination(dir) {
|
|
13
|
+
const trimmed = dir.trim();
|
|
14
|
+
if (!trimmed) {
|
|
15
|
+
throw new TheorumError('jsonlDestination requires a non-empty directory');
|
|
16
|
+
}
|
|
17
|
+
return { kind: 'jsonl', dir: trimmed };
|
|
18
|
+
}
|
|
19
|
+
function isJsonlTraceDestination(value) {
|
|
20
|
+
return (typeof value === 'object' &&
|
|
21
|
+
value !== null &&
|
|
22
|
+
'kind' in value &&
|
|
23
|
+
value.kind === 'jsonl' &&
|
|
24
|
+
typeof value.dir === 'string');
|
|
25
|
+
}
|
|
26
|
+
function isTraceSink(value) {
|
|
27
|
+
return (typeof value === 'object' && value !== null && typeof value.write === 'function');
|
|
28
|
+
}
|
|
29
|
+
/** Register a named destination for profile `observability.writeTo`. */
|
|
30
|
+
function registerTraceDestination(id, destination) {
|
|
31
|
+
const key = id.trim();
|
|
32
|
+
if (!key) {
|
|
33
|
+
throw new TheorumError('registerTraceDestination requires a non-empty id');
|
|
34
|
+
}
|
|
35
|
+
if (isJsonlTraceDestination(destination)) {
|
|
36
|
+
if (!destination.dir.trim()) {
|
|
37
|
+
throw new TheorumError(`Trace destination '${key}' jsonl dir must be non-empty`);
|
|
38
|
+
}
|
|
39
|
+
destinations.set(key, { kind: 'jsonl', dir: destination.dir.trim() });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!isTraceSink(destination)) {
|
|
43
|
+
throw new TheorumError(`Trace destination '${key}' must be a TraceSink or jsonl destination`);
|
|
44
|
+
}
|
|
45
|
+
destinations.set(key, destination);
|
|
46
|
+
}
|
|
47
|
+
/** Look up a registered destination; undefined when missing. */
|
|
48
|
+
function getTraceDestination(id) {
|
|
49
|
+
return destinations.get(id);
|
|
50
|
+
}
|
|
51
|
+
/** Require a registered destination or throw. */
|
|
52
|
+
function requireTraceDestination(id) {
|
|
53
|
+
const found = getTraceDestination(id);
|
|
54
|
+
if (!found) {
|
|
55
|
+
throw new TheorumError(`Trace destination '${id}' is not registered`);
|
|
56
|
+
}
|
|
57
|
+
return found;
|
|
58
|
+
}
|
|
59
|
+
/** List registered destination ids (stable sort). */
|
|
60
|
+
function listTraceDestinationIds() {
|
|
61
|
+
return [...destinations.keys()].sort();
|
|
62
|
+
}
|
|
63
|
+
/** Clear the destination registry (tests). */
|
|
64
|
+
function clearTraceDestinations() {
|
|
65
|
+
destinations.clear();
|
|
66
|
+
}
|
|
67
|
+
export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, };
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Trace sinks
|
|
2
|
+
* Trace sinks, destination registry, and profile observability policy.
|
|
3
3
|
*
|
|
4
4
|
* THEORUM does not own a database or environment variable. Host applications
|
|
5
|
-
*
|
|
5
|
+
* register named destinations, declare `profile.observability`, and/or pass a
|
|
6
|
+
* sink into `runTurn`.
|
|
6
7
|
*
|
|
7
8
|
* @module
|
|
8
9
|
*/
|
|
9
10
|
import "../../_dnt.polyfills.js";
|
|
10
|
-
export type {
|
|
11
|
+
export type { JsonlTraceDestination, TraceDestination, } from './destinations.js';
|
|
12
|
+
export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, } from './destinations.js';
|
|
13
|
+
export { resolveTraceWriter } from './policy.js';
|
|
14
|
+
export { resolveObservabilityPolicy } from './resolve-policy.js';
|
|
15
|
+
export type { JsonlSinkOptions } from './trace.js';
|
|
11
16
|
export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './trace.js';
|
|
12
17
|
export type { TraceRecord } from './trace-record.js';
|
|
18
|
+
export type { TraceSink } from './trace-sink.js';
|
|
19
|
+
export type { ProfileObservabilitySpec, ResolvedObservabilityPolicy, ResolvedTraceInclude, ResolvedTraceScrub, TraceIncludeSpec, TraceScrubSpec, } from './types.js';
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Trace sinks
|
|
2
|
+
* Trace sinks, destination registry, and profile observability policy.
|
|
3
3
|
*
|
|
4
4
|
* THEORUM does not own a database or environment variable. Host applications
|
|
5
|
-
*
|
|
5
|
+
* register named destinations, declare `profile.observability`, and/or pass a
|
|
6
|
+
* sink into `runTurn`.
|
|
6
7
|
*
|
|
7
8
|
* @module
|
|
8
9
|
*/
|
|
9
10
|
import "../../_dnt.polyfills.js";
|
|
11
|
+
export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, listTraceDestinationIds, registerTraceDestination, requireTraceDestination, } from './destinations.js';
|
|
12
|
+
export { resolveTraceWriter } from './policy.js';
|
|
13
|
+
export { resolveObservabilityPolicy } from './resolve-policy.js';
|
|
10
14
|
export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './trace.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace writer resolution — a resolved observability policy becomes a sink.
|
|
3
|
+
*
|
|
4
|
+
* Policy defaults live in `resolve-policy.ts` (pure); this module owns the
|
|
5
|
+
* writer precedence and needs the sink implementations.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { TraceSink } from './trace-sink.js';
|
|
10
|
+
import type { ProfileObservabilitySpec, ResolvedObservabilityPolicy } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the TraceSink for one turn.
|
|
13
|
+
*
|
|
14
|
+
* Precedence: explicit `override` (runTurn third arg) → profile `writeTo` → noop.
|
|
15
|
+
* An explicit override always records (sampleRate does not apply) so tests and
|
|
16
|
+
* one-off capture are deterministic.
|
|
17
|
+
*/
|
|
18
|
+
declare function resolveTraceWriter(args: {
|
|
19
|
+
override?: TraceSink;
|
|
20
|
+
observability?: ProfileObservabilitySpec;
|
|
21
|
+
/** Injectable for deterministic sampleRate tests. */
|
|
22
|
+
random?: () => number;
|
|
23
|
+
}): {
|
|
24
|
+
sink: TraceSink;
|
|
25
|
+
policy: ResolvedObservabilityPolicy;
|
|
26
|
+
};
|
|
27
|
+
export { resolveTraceWriter };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace writer resolution — a resolved observability policy becomes a sink.
|
|
3
|
+
*
|
|
4
|
+
* Policy defaults live in `resolve-policy.ts` (pure); this module owns the
|
|
5
|
+
* writer precedence and needs the sink implementations.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { TheorumError } from '../guardrails/error.js';
|
|
10
|
+
import { isJsonlTraceDestination, isTraceSink, requireTraceDestination } from './destinations.js';
|
|
11
|
+
import { resolveObservabilityPolicy } from './resolve-policy.js';
|
|
12
|
+
import { jsonlSink, noopSink } from './trace.js';
|
|
13
|
+
function bindOnWriteError(sink, onWriteError) {
|
|
14
|
+
if (!onWriteError && !sink.onError) {
|
|
15
|
+
return sink;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
write: (record) => sink.write(record),
|
|
19
|
+
onError: sink.onError ?? onWriteError,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function withSampleRate(sink, sampleRate, random) {
|
|
23
|
+
if (sampleRate >= 1) {
|
|
24
|
+
return sink;
|
|
25
|
+
}
|
|
26
|
+
if (sampleRate <= 0) {
|
|
27
|
+
return noopSink();
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
write: async (record) => {
|
|
31
|
+
if (random() < sampleRate) {
|
|
32
|
+
await sink.write(record);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
onError: sink.onError,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function sinkFromWriteTo(writeTo, policy) {
|
|
39
|
+
if (writeTo === undefined || writeTo === false) {
|
|
40
|
+
return noopSink();
|
|
41
|
+
}
|
|
42
|
+
if (typeof writeTo !== 'string') {
|
|
43
|
+
return bindOnWriteError(writeTo, policy.onWriteError);
|
|
44
|
+
}
|
|
45
|
+
const destination = requireTraceDestination(writeTo);
|
|
46
|
+
if (isJsonlTraceDestination(destination)) {
|
|
47
|
+
return bindOnWriteError(jsonlSink(destination.dir, {
|
|
48
|
+
retainForDays: policy.retainForDays,
|
|
49
|
+
rotateAfterMiB: policy.rotateAfterMiB,
|
|
50
|
+
}), policy.onWriteError);
|
|
51
|
+
}
|
|
52
|
+
if (!isTraceSink(destination)) {
|
|
53
|
+
throw new TheorumError(`Trace destination '${writeTo}' is not a usable writer`);
|
|
54
|
+
}
|
|
55
|
+
return bindOnWriteError(destination, policy.onWriteError);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the TraceSink for one turn.
|
|
59
|
+
*
|
|
60
|
+
* Precedence: explicit `override` (runTurn third arg) → profile `writeTo` → noop.
|
|
61
|
+
* An explicit override always records (sampleRate does not apply) so tests and
|
|
62
|
+
* one-off capture are deterministic.
|
|
63
|
+
*/
|
|
64
|
+
function resolveTraceWriter(args) {
|
|
65
|
+
const policy = resolveObservabilityPolicy(args.observability);
|
|
66
|
+
if (args.override) {
|
|
67
|
+
return {
|
|
68
|
+
policy,
|
|
69
|
+
sink: bindOnWriteError(args.override, policy.onWriteError),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (!policy.record) {
|
|
73
|
+
return { policy, sink: noopSink() };
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
policy,
|
|
77
|
+
sink: withSampleRate(sinkFromWriteTo(policy.writeTo, policy), policy.sampleRate, args.random ?? Math.random),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export { resolveTraceWriter };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability policy resolution — profile switches become resolved defaults.
|
|
3
|
+
*
|
|
4
|
+
* Pure: no sinks, no file system. `policy.ts` builds the writer on top of this
|
|
5
|
+
* so type consumers of the kernel never pull the JSONL sink into their graph.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { ProfileObservabilitySpec, ResolvedObservabilityPolicy } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Apply defaults to a profile's observability block.
|
|
12
|
+
*
|
|
13
|
+
* Omitted block → record false (noop). Explicit `writeTo: false` → record false.
|
|
14
|
+
* A writeTo target with sampleRate 0 still resolves record false at write time.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveObservabilityPolicy(spec: ProfileObservabilitySpec | undefined): ResolvedObservabilityPolicy;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability policy resolution — profile switches become resolved defaults.
|
|
3
|
+
*
|
|
4
|
+
* Pure: no sinks, no file system. `policy.ts` builds the writer on top of this
|
|
5
|
+
* so type consumers of the kernel never pull the JSONL sink into their graph.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { TheorumError } from '../guardrails/error.js';
|
|
10
|
+
const DEFAULT_RETAIN_DAYS = 14;
|
|
11
|
+
const DEFAULT_ROTATE_MIB = 32;
|
|
12
|
+
function resolveInclude(spec) {
|
|
13
|
+
// When no observability block is authored, preserve historical buildRecord
|
|
14
|
+
// behavior (wire + evidence included). Authored blocks default those off.
|
|
15
|
+
const authored = spec !== undefined;
|
|
16
|
+
return {
|
|
17
|
+
upstreamLog: spec?.include?.upstreamLog ?? true,
|
|
18
|
+
outboundWire: spec?.include?.outboundWire ?? !authored,
|
|
19
|
+
evidenceRaw: spec?.include?.evidenceRaw ?? !authored,
|
|
20
|
+
usage: spec?.include?.usage ?? true,
|
|
21
|
+
guardrailDecisions: spec?.include?.guardrailDecisions ?? true,
|
|
22
|
+
guardrailMatchPreview: spec?.include?.guardrailMatchPreview ?? false,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function resolveScrub(spec) {
|
|
26
|
+
return {
|
|
27
|
+
sensitive: spec?.scrub?.sensitive ?? true,
|
|
28
|
+
injection: spec?.scrub?.injection ?? true,
|
|
29
|
+
canary: spec?.scrub?.canary ?? true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function clampSampleRate(value) {
|
|
33
|
+
if (value === undefined) {
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
if (!Number.isFinite(value)) {
|
|
37
|
+
throw new TheorumError('observability.sampleRate must be a finite number');
|
|
38
|
+
}
|
|
39
|
+
if (value < 0 || value > 1) {
|
|
40
|
+
throw new TheorumError('observability.sampleRate must be between 0 and 1 inclusive');
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Apply defaults to a profile's observability block.
|
|
46
|
+
*
|
|
47
|
+
* Omitted block → record false (noop). Explicit `writeTo: false` → record false.
|
|
48
|
+
* A writeTo target with sampleRate 0 still resolves record false at write time.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveObservabilityPolicy(spec) {
|
|
51
|
+
const writeTo = spec?.writeTo;
|
|
52
|
+
const sampleRate = clampSampleRate(spec?.sampleRate);
|
|
53
|
+
const record = spec !== undefined && writeTo !== false && writeTo !== undefined;
|
|
54
|
+
return {
|
|
55
|
+
record,
|
|
56
|
+
writeTo,
|
|
57
|
+
sampleRate,
|
|
58
|
+
include: resolveInclude(spec),
|
|
59
|
+
scrub: resolveScrub(spec),
|
|
60
|
+
retainForDays: spec?.retainForDays ?? DEFAULT_RETAIN_DAYS,
|
|
61
|
+
rotateAfterMiB: spec?.rotateAfterMiB ?? DEFAULT_ROTATE_MIB,
|
|
62
|
+
onWriteError: spec?.onWriteError,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Protocol } from '../kernel/schema.js';
|
|
2
2
|
import type { ResolvedGeneration, TurnEvent, TurnRequest } from '../kernel/types.js';
|
|
3
3
|
import type { TraceRecord } from './trace-record.js';
|
|
4
|
+
import type { ResolvedTraceInclude } from './types.js';
|
|
4
5
|
declare function attachResolved(record: TraceRecord, args: {
|
|
5
6
|
safe: TurnRequest;
|
|
6
7
|
model?: string;
|
|
@@ -13,6 +14,7 @@ declare function attachTape(record: TraceRecord, args: {
|
|
|
13
14
|
system?: string;
|
|
14
15
|
generation?: ResolvedGeneration;
|
|
15
16
|
protocol?: Protocol;
|
|
17
|
+
include: ResolvedTraceInclude;
|
|
16
18
|
}): Promise<void>;
|
|
17
|
-
declare function attachUsage(record: TraceRecord, upstream: unknown, done: Record<string, unknown> | undefined, events
|
|
19
|
+
declare function attachUsage(record: TraceRecord, upstream: unknown, done: Record<string, unknown> | undefined, events: TurnEvent[] | undefined, include: ResolvedTraceInclude): void;
|
|
18
20
|
export { attachResolved, attachTape, attachUsage };
|
|
@@ -6,11 +6,11 @@ function attachResolved(record, args) {
|
|
|
6
6
|
if (safe.projectId) {
|
|
7
7
|
record.projectId = safe.projectId;
|
|
8
8
|
}
|
|
9
|
-
if (safe.
|
|
10
|
-
record.
|
|
9
|
+
if (safe.model) {
|
|
10
|
+
record.modelSelect = safe.model;
|
|
11
11
|
}
|
|
12
|
-
if (safe.
|
|
13
|
-
record.
|
|
12
|
+
if (safe.effort) {
|
|
13
|
+
record.effort = safe.effort;
|
|
14
14
|
}
|
|
15
15
|
if (safe.metadata) {
|
|
16
16
|
record.metadata = safe.metadata;
|
|
@@ -39,11 +39,14 @@ function attachResolved(record, args) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
async function attachTape(record, args) {
|
|
42
|
-
const { upstream, canary, system, generation, protocol } = args;
|
|
43
|
-
if (upstream !== undefined) {
|
|
42
|
+
const { upstream, canary, system, generation, protocol, include } = args;
|
|
43
|
+
if (include.upstreamLog && upstream !== undefined) {
|
|
44
44
|
record.upstreamLog = await tapeUpstream(upstream, canary ?? '');
|
|
45
45
|
}
|
|
46
|
-
if (
|
|
46
|
+
if (include.outboundWire &&
|
|
47
|
+
generation &&
|
|
48
|
+
system !== undefined &&
|
|
49
|
+
protocol === 'geminiInteractions') {
|
|
47
50
|
const { toInteractionsBody } = await import('../providers/google/interactions/framing.js');
|
|
48
51
|
record.wire = await tapeUpstream(toInteractionsBody(providerCompleteRequest(generation, system)), canary ?? '');
|
|
49
52
|
}
|
|
@@ -74,8 +77,12 @@ function attachUpstreamSummary(record, upstream, done) {
|
|
|
74
77
|
serviceTier: done?.service_tier ?? done?.serviceTier,
|
|
75
78
|
};
|
|
76
79
|
}
|
|
77
|
-
function attachUsage(record, upstream, done, events) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
function attachUsage(record, upstream, done, events, include) {
|
|
81
|
+
if (include.usage) {
|
|
82
|
+
attachUsageTokens(record, done, events);
|
|
83
|
+
}
|
|
84
|
+
if (include.upstreamLog) {
|
|
85
|
+
attachUpstreamSummary(record, upstream, done);
|
|
86
|
+
}
|
|
80
87
|
}
|
|
81
88
|
export { attachResolved, attachTape, attachUsage };
|
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Protocol } from '../kernel/schema.js';
|
|
10
10
|
import type { ResolvedGeneration, TurnEvent, TurnRequest } from '../kernel/types.js';
|
|
11
|
+
import type { ProfileObservabilitySpec, ResolvedObservabilityPolicy } from './types.js';
|
|
11
12
|
/** Hash-only image reference stored in trace records. */
|
|
12
13
|
export interface TraceImage {
|
|
13
14
|
mimeType: string;
|
|
14
|
-
|
|
15
|
+
/** Content hash for inline bytes; absent for a provider file reference. */
|
|
16
|
+
sha256?: string;
|
|
17
|
+
/** Provider file reference when the attachment was supplied by uri. */
|
|
18
|
+
uri?: string;
|
|
15
19
|
}
|
|
16
20
|
/** Trace-safe copy of a public turn event. */
|
|
17
21
|
export interface TraceEvent {
|
|
@@ -30,6 +34,8 @@ export interface TraceEvent {
|
|
|
30
34
|
media?: TraceImage;
|
|
31
35
|
grounding?: TurnEvent['grounding'];
|
|
32
36
|
evidence?: TurnEvent['evidence'];
|
|
37
|
+
/** Guardrail decision — rule identity and offsets, never matched content. */
|
|
38
|
+
guardrail?: TurnEvent['guardrail'];
|
|
33
39
|
error?: string;
|
|
34
40
|
errorInternal?: string;
|
|
35
41
|
}
|
|
@@ -46,8 +52,8 @@ interface TraceRecord {
|
|
|
46
52
|
profile: string;
|
|
47
53
|
title?: string;
|
|
48
54
|
projectId?: string;
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
modelSelect?: string;
|
|
56
|
+
effort?: string;
|
|
51
57
|
metadata?: Record<string, unknown>;
|
|
52
58
|
model?: {
|
|
53
59
|
id: string;
|
|
@@ -55,7 +61,7 @@ interface TraceRecord {
|
|
|
55
61
|
};
|
|
56
62
|
keySlot?: string;
|
|
57
63
|
generation?: {
|
|
58
|
-
thinking
|
|
64
|
+
thinking?: string;
|
|
59
65
|
summaries?: string;
|
|
60
66
|
temperature?: number;
|
|
61
67
|
maxOutputTokens?: number;
|
|
@@ -111,6 +117,8 @@ declare function buildRecord(args: {
|
|
|
111
117
|
generation?: ResolvedGeneration;
|
|
112
118
|
protocol?: Protocol;
|
|
113
119
|
sanitizedReq?: TurnRequest;
|
|
120
|
+
/** Profile observability — omit for defaults (safe scrub, standard include). */
|
|
121
|
+
observability?: ProfileObservabilitySpec | ResolvedObservabilityPolicy;
|
|
114
122
|
}): Promise<TraceRecord>;
|
|
115
123
|
export type { TraceRecord };
|
|
116
124
|
export { buildRecord };
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { OMIT_CANARY } from '../guardrails/canary.js';
|
|
10
10
|
import { isAbortError, publicError } from '../guardrails/error.js';
|
|
11
|
+
import { projectGuardrailEvent } from '../guardrails/hits.js';
|
|
11
12
|
import { redactSensitiveOnly, sanitizeText, sanitizeTurnRequestForTrace, } from '../guardrails/sanitize.js';
|
|
12
13
|
import { sha256 } from '../kernel/engine/hash.js';
|
|
14
|
+
import { resolveObservabilityPolicy } from './resolve-policy.js';
|
|
13
15
|
import { attachResolved, attachTape, attachUsage } from './trace-attach.js';
|
|
14
16
|
import { completedInteraction, stopKindFromEvents } from './trace-usage.js';
|
|
15
17
|
const TRACE_VERSION = 2;
|
|
@@ -18,21 +20,32 @@ function hashBlobs(blobs) {
|
|
|
18
20
|
if (!blobs) {
|
|
19
21
|
return Promise.resolve([]);
|
|
20
22
|
}
|
|
21
|
-
return Promise.all(blobs.map(async (blob) =>
|
|
22
|
-
mimeType: blob.mimeType,
|
|
23
|
-
sha256: await sha256(blob.data)
|
|
24
|
-
})));
|
|
23
|
+
return Promise.all(blobs.map(async (blob) => 'uri' in blob
|
|
24
|
+
? { mimeType: blob.mimeType, uri: blob.uri }
|
|
25
|
+
: { mimeType: blob.mimeType, sha256: await sha256(blob.data) }));
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
function scrubStoredText(text, scrub) {
|
|
28
|
+
if (scrub.sensitive && scrub.injection) {
|
|
29
|
+
return sanitizeText(text);
|
|
30
|
+
}
|
|
31
|
+
if (scrub.sensitive) {
|
|
32
|
+
return redactSensitiveOnly(text);
|
|
33
|
+
}
|
|
34
|
+
if (scrub.injection) {
|
|
35
|
+
return sanitizeText(text, { sanitizeInput: true, redactSensitive: false });
|
|
36
|
+
}
|
|
37
|
+
return text;
|
|
38
|
+
}
|
|
39
|
+
async function snapshotEvent(event, include, scrub) {
|
|
27
40
|
const row = { type: event.type };
|
|
28
41
|
if (event.text) {
|
|
29
|
-
row.text =
|
|
42
|
+
row.text = scrubStoredText(event.text, scrub);
|
|
30
43
|
}
|
|
31
44
|
if (event.error) {
|
|
32
45
|
row.error = event.error;
|
|
33
46
|
}
|
|
34
47
|
if (event.errorInternal) {
|
|
35
|
-
row.errorInternal =
|
|
48
|
+
row.errorInternal = scrubStoredText(event.errorInternal, scrub);
|
|
36
49
|
}
|
|
37
50
|
if (event.structured !== undefined) {
|
|
38
51
|
row.structured = event.structured;
|
|
@@ -66,9 +79,12 @@ async function snapshotEvent(event) {
|
|
|
66
79
|
if (event.grounding) {
|
|
67
80
|
row.grounding = event.grounding;
|
|
68
81
|
}
|
|
69
|
-
if (event.evidence) {
|
|
82
|
+
if (include.evidenceRaw && event.evidence) {
|
|
70
83
|
row.evidence = event.evidence;
|
|
71
84
|
}
|
|
85
|
+
if (event.guardrail) {
|
|
86
|
+
row.guardrail = projectGuardrailEvent(event.guardrail, include.guardrailMatchPreview);
|
|
87
|
+
}
|
|
72
88
|
return row;
|
|
73
89
|
}
|
|
74
90
|
function requestForTrace(req) {
|
|
@@ -93,25 +109,43 @@ function titleFrom(text) {
|
|
|
93
109
|
}
|
|
94
110
|
return trimmed.slice(0, TITLE_MAX);
|
|
95
111
|
}
|
|
96
|
-
function attachFailure(record, thrown, lastErr, canary) {
|
|
112
|
+
function attachFailure(record, thrown, lastErr, canary, scrub) {
|
|
97
113
|
if (!record.ok) {
|
|
98
114
|
record.error = publicError(thrown ?? lastErr?.error);
|
|
99
115
|
const inside = internalError(thrown) ?? lastErr?.errorInternal ?? lastErr?.error;
|
|
100
116
|
if (inside) {
|
|
101
|
-
record.errorInternal = inside;
|
|
117
|
+
record.errorInternal = scrubStoredText(inside, scrub);
|
|
102
118
|
}
|
|
103
119
|
}
|
|
104
|
-
if (canary && JSON.stringify(record).includes(canary)) {
|
|
120
|
+
if (scrub.canary && canary && JSON.stringify(record).includes(canary)) {
|
|
105
121
|
record.errorInternal = OMIT_CANARY;
|
|
106
122
|
}
|
|
107
123
|
}
|
|
124
|
+
function eventsForTrace(events, include) {
|
|
125
|
+
if (include.guardrailDecisions) {
|
|
126
|
+
return events;
|
|
127
|
+
}
|
|
128
|
+
return events.filter((event) => event.type !== 'guardrail');
|
|
129
|
+
}
|
|
130
|
+
function asResolvedPolicy(value) {
|
|
131
|
+
if (value &&
|
|
132
|
+
typeof value === 'object' &&
|
|
133
|
+
'record' in value &&
|
|
134
|
+
typeof value.record === 'boolean') {
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
return resolveObservabilityPolicy(value);
|
|
138
|
+
}
|
|
108
139
|
async function buildRecord(args) {
|
|
109
140
|
const { req, events, started, model, keySlot, thrown, upstreamLog, canary, system, generation } = args;
|
|
110
141
|
const protocol = args.protocol;
|
|
142
|
+
const policy = asResolvedPolicy(args.observability);
|
|
143
|
+
const { include, scrub } = policy;
|
|
111
144
|
const traced = args.sanitizedReq ? { request: args.sanitizedReq } : requestForTrace(req);
|
|
112
145
|
const safe = traced.request;
|
|
113
146
|
const input = safe.input ?? {};
|
|
114
|
-
const
|
|
147
|
+
const traceEvents = eventsForTrace(events, include);
|
|
148
|
+
const snapped = await Promise.all(traceEvents.map((event) => snapshotEvent(event, include, scrub)));
|
|
115
149
|
const lastErr = [...snapped].reverse().find((row) => row.type === 'error');
|
|
116
150
|
const aborted = isAbortError(thrown);
|
|
117
151
|
const stopKind = stopKindFromEvents(events);
|
|
@@ -132,25 +166,35 @@ async function buildRecord(args) {
|
|
|
132
166
|
store: safe.store ?? null,
|
|
133
167
|
profile: safe.profile,
|
|
134
168
|
input: {
|
|
135
|
-
text: input.text,
|
|
169
|
+
text: input.text !== undefined ? scrubStoredText(input.text, scrub) : undefined,
|
|
136
170
|
role: input.role,
|
|
137
|
-
slots: input.slots
|
|
171
|
+
slots: input.slots
|
|
172
|
+
? Object.fromEntries(Object.entries(input.slots).map(([key, value]) => [key, scrubStoredText(value, scrub)]))
|
|
173
|
+
: undefined,
|
|
138
174
|
attachments: await hashBlobs(input.attachments),
|
|
139
175
|
voice: await hashBlobs(input.voice),
|
|
140
176
|
},
|
|
141
177
|
events: snapped,
|
|
142
178
|
ok,
|
|
143
179
|
};
|
|
144
|
-
const title = titleFrom(input.text);
|
|
180
|
+
const title = titleFrom(record.input.text);
|
|
145
181
|
if (title) {
|
|
146
182
|
record.title = title;
|
|
147
183
|
}
|
|
148
|
-
|
|
149
|
-
|
|
184
|
+
const tapeCanary = scrub.canary ? canary : undefined;
|
|
185
|
+
await attachTape(record, {
|
|
186
|
+
upstream: upstreamLog,
|
|
187
|
+
canary: tapeCanary,
|
|
188
|
+
system,
|
|
189
|
+
generation,
|
|
190
|
+
protocol,
|
|
191
|
+
include,
|
|
192
|
+
});
|
|
193
|
+
attachUsage(record, upstreamLog, done, events, include);
|
|
150
194
|
attachResolved(record, { safe, model, keySlot, generation });
|
|
151
|
-
attachFailure(record, thrown, lastErr, canary);
|
|
195
|
+
attachFailure(record, thrown, lastErr, canary, scrub);
|
|
152
196
|
if (traced.sanitizeError && !record.errorInternal) {
|
|
153
|
-
record.errorInternal =
|
|
197
|
+
record.errorInternal = scrubStoredText(`request sanitize for trace failed: ${traced.sanitizeError}`, scrub);
|
|
154
198
|
}
|
|
155
199
|
return record;
|
|
156
200
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace sink contract.
|
|
3
|
+
*
|
|
4
|
+
* Type-only so hosts that consume kernel types under a non-Deno TypeScript
|
|
5
|
+
* program (browser bundles, Workers) never pull the JSONL file sink and its
|
|
6
|
+
* `Deno` calls into their type graph. Implementations live in `trace.ts`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type { TraceRecord } from './trace-record.js';
|
|
11
|
+
/** Minimal async destination for completed turn trace records. */
|
|
12
|
+
export interface TraceSink {
|
|
13
|
+
write: (record: TraceRecord) => Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Optional host hook when `writeTrace` catches record-build or write failures.
|
|
16
|
+
* Must not throw; tracing never fails the turn.
|
|
17
|
+
*/
|
|
18
|
+
onError?: (err: unknown) => void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace sink contract.
|
|
3
|
+
*
|
|
4
|
+
* Type-only so hosts that consume kernel types under a non-Deno TypeScript
|
|
5
|
+
* program (browser bundles, Workers) never pull the JSONL file sink and its
|
|
6
|
+
* `Deno` calls into their type graph. Implementations live in `trace.ts`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { TraceRecord } from './trace-record.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
onError?: (err: unknown) => void;
|
|
2
|
+
import type { TraceSink } from './trace-sink.js';
|
|
3
|
+
/** Options for daily rotating JSONL sinks. */
|
|
4
|
+
interface JsonlSinkOptions {
|
|
5
|
+
retainForDays?: number;
|
|
6
|
+
rotateAfterMiB?: number;
|
|
7
|
+
now?: () => number;
|
|
10
8
|
}
|
|
11
9
|
/**
|
|
12
10
|
* Write a trace record without allowing trace failures to fail the turn.
|
|
@@ -17,8 +15,13 @@ declare function writeTrace(sink: TraceSink, record: Promise<TraceRecord>): Prom
|
|
|
17
15
|
declare function noopSink(): TraceSink;
|
|
18
16
|
/** Trace sink that appends records to a caller-owned array. */
|
|
19
17
|
declare function memorySink(into: TraceRecord[]): TraceSink;
|
|
20
|
-
/**
|
|
21
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Trace sink that writes daily rotating JSONL files under a host-selected directory.
|
|
20
|
+
*
|
|
21
|
+
* @param dir - Absolute host-chosen directory
|
|
22
|
+
* @param optionsOrNow - Retention/rotate options, or a `now` clock (legacy)
|
|
23
|
+
*/
|
|
24
|
+
declare function jsonlSink(dir: string, optionsOrNow?: JsonlSinkOptions | (() => number)): TraceSink;
|
|
22
25
|
/** Resolve a trace directory while refusing relative paths or paths inside the clone. */
|
|
23
26
|
declare function resolveTraceDir(args: {
|
|
24
27
|
dir?: string;
|
|
@@ -27,5 +30,5 @@ declare function resolveTraceDir(args: {
|
|
|
27
30
|
}): string | undefined;
|
|
28
31
|
/** Build a JSONL sink from a host-supplied directory or return a noop sink. */
|
|
29
32
|
declare function sinkFromDir(dir?: string, fallbackDir?: string): TraceSink;
|
|
30
|
-
export type {
|
|
33
|
+
export type { JsonlSinkOptions };
|
|
31
34
|
export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace };
|