@loutrejs/loutre 0.9.2 → 0.10.0

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.
Files changed (145) hide show
  1. package/dist/adapters/aws-lambda.d.ts +1 -1
  2. package/dist/adapters/aws-lambda.js +8 -2
  3. package/dist/adapters/bun.d.ts +3 -2
  4. package/dist/adapters/bun.js +12 -6
  5. package/dist/adapters/cloudflare-workers.d.ts +1 -1
  6. package/dist/adapters/cloudflare-workers.js +2 -1
  7. package/dist/adapters/electron.d.ts +1 -1
  8. package/dist/adapters/electron.js +8 -51
  9. package/dist/adapters/server-transports.js +2 -2
  10. package/dist/adapters/websocket-native.js +4 -1
  11. package/dist/application/definition.d.ts +4 -7
  12. package/dist/application/definition.js +3 -1
  13. package/dist/application/kernel.d.ts +0 -2
  14. package/dist/application/kernel.js +1 -3
  15. package/dist/core/args.d.ts +1 -0
  16. package/dist/core/args.js +2 -1
  17. package/dist/core/env.d.ts +1 -0
  18. package/dist/core/env.js +2 -1
  19. package/dist/core/extension.d.ts +23 -13
  20. package/dist/core/extension.js +3 -1
  21. package/dist/core/generic-layer.d.ts +9 -2
  22. package/dist/core/generic-layer.js +2 -1
  23. package/dist/core/identity.d.ts +18 -0
  24. package/dist/core/identity.js +5 -0
  25. package/dist/core/index.d.ts +13 -5
  26. package/dist/core/index.js +7 -1
  27. package/dist/core/injection.d.ts +2 -1
  28. package/dist/core/instrumentation.d.ts +7 -5
  29. package/dist/core/lifecycle.d.ts +4 -0
  30. package/dist/core/logger-identity.d.ts +4 -0
  31. package/dist/core/logger-identity.js +9 -0
  32. package/dist/core/logger-internal.d.ts +5 -0
  33. package/dist/core/logger-internal.js +27 -0
  34. package/dist/core/logger-module.d.ts +5 -0
  35. package/dist/core/logger-module.js +8 -0
  36. package/dist/core/logger.d.ts +42 -0
  37. package/dist/core/logger.js +221 -0
  38. package/dist/core/model/context.d.ts +6 -3
  39. package/dist/core/model/context.js +17 -17
  40. package/dist/core/model/identity.d.ts +19 -0
  41. package/dist/core/model/identity.js +8 -0
  42. package/dist/core/model/lifecycle.d.ts +3 -2
  43. package/dist/core/model/lifecycle.js +7 -3
  44. package/dist/core/model/logger.d.ts +3 -0
  45. package/dist/core/model/logger.js +59 -0
  46. package/dist/core/model/modules.d.ts +4 -1
  47. package/dist/core/model/modules.js +6 -4
  48. package/dist/core/model/providers.d.ts +1 -1
  49. package/dist/core/model/providers.js +8 -8
  50. package/dist/core/model/types.d.ts +25 -18
  51. package/dist/core/model/validation.js +3 -2
  52. package/dist/core/model/visibility.js +7 -2
  53. package/dist/core/model.js +15 -7
  54. package/dist/core/module.d.ts +7 -7
  55. package/dist/core/module.js +0 -3
  56. package/dist/core/runtime-input.d.ts +2 -1
  57. package/dist/core/source-location.d.ts +14 -2
  58. package/dist/core/source-location.js +8 -3
  59. package/dist/core/token-internal.js +3 -1
  60. package/dist/core/token.d.ts +4 -2
  61. package/dist/core/token.js +3 -0
  62. package/dist/core/units.d.ts +22 -0
  63. package/dist/core/units.js +14 -0
  64. package/dist/devtools/capsule.d.ts +17 -13
  65. package/dist/devtools/capsule.js +14 -10
  66. package/dist/devtools/decoder.d.ts +15 -0
  67. package/dist/devtools/decoder.js +179 -0
  68. package/dist/devtools/identity-internal.d.ts +6 -0
  69. package/dist/devtools/identity-internal.js +5 -0
  70. package/dist/devtools/identity.d.ts +21 -0
  71. package/dist/devtools/identity.js +7 -0
  72. package/dist/devtools/index.d.ts +3 -0
  73. package/dist/devtools/index.js +2 -0
  74. package/dist/devtools/inspector.d.ts +18 -16
  75. package/dist/devtools/observer.d.ts +32 -28
  76. package/dist/devtools/runtime.js +34 -30
  77. package/dist/devtools/values.js +3 -5
  78. package/dist/generated/version.d.ts +1 -1
  79. package/dist/generated/version.js +1 -1
  80. package/dist/graph/model.d.ts +25 -14
  81. package/dist/http/auth.d.ts +4 -2
  82. package/dist/http/client.d.ts +6 -3
  83. package/dist/http/client.js +8 -9
  84. package/dist/http/cors-internal.d.ts +7 -5
  85. package/dist/http/cors-internal.js +8 -6
  86. package/dist/http/extension.d.ts +60 -21
  87. package/dist/http/extension.js +91 -20
  88. package/dist/http/identity.d.ts +20 -0
  89. package/dist/http/identity.js +10 -0
  90. package/dist/http/index.d.ts +6 -2
  91. package/dist/http/index.js +3 -1
  92. package/dist/http/openapi-identity.d.ts +9 -0
  93. package/dist/http/openapi-identity.js +4 -0
  94. package/dist/http/openapi.d.ts +1 -1
  95. package/dist/http/openapi.js +10 -7
  96. package/dist/http/path.d.ts +8 -5
  97. package/dist/http/route-validation.js +2 -1
  98. package/dist/http/runtime/request.d.ts +3 -2
  99. package/dist/http/runtime/request.js +1 -4
  100. package/dist/http/websocket-upgrade.d.ts +2 -0
  101. package/dist/http/websocket-upgrade.js +4 -0
  102. package/dist/internal/brand.d.ts +8 -0
  103. package/dist/internal/brand.js +1 -0
  104. package/dist/message-port/extension.d.ts +4 -2
  105. package/dist/message-port/extension.js +15 -8
  106. package/dist/message-port/identity.d.ts +9 -0
  107. package/dist/message-port/identity.js +16 -0
  108. package/dist/message-port/index.d.ts +2 -0
  109. package/dist/message-port/index.js +1 -0
  110. package/dist/message-port/transport.d.ts +4 -2
  111. package/dist/message-port/transport.js +6 -1
  112. package/dist/runtime/async-iterator-lifecycle.d.ts +2 -1
  113. package/dist/runtime/async-iterator-lifecycle.js +2 -1
  114. package/dist/runtime/capability.d.ts +6 -2
  115. package/dist/runtime/capability.js +3 -1
  116. package/dist/runtime/di.d.ts +1 -3
  117. package/dist/runtime/di.js +62 -35
  118. package/dist/runtime/error.d.ts +3 -1
  119. package/dist/runtime/index.d.ts +6 -2
  120. package/dist/runtime/index.js +3 -1
  121. package/dist/runtime/kernel.d.ts +0 -2
  122. package/dist/runtime/kernel.js +68 -30
  123. package/dist/runtime/logger-source.d.ts +4 -0
  124. package/dist/runtime/logger-source.js +47 -0
  125. package/dist/runtime/logger.d.ts +2 -38
  126. package/dist/runtime/logger.js +1 -209
  127. package/dist/runtime/node-capabilities.d.ts +1 -1
  128. package/dist/runtime/node-capabilities.js +2 -1
  129. package/dist/runtime/server-port.d.ts +5 -1
  130. package/dist/runtime/server-port.js +2 -1
  131. package/dist/runtime/shutdown-hooks.d.ts +1 -1
  132. package/dist/runtime/shutdown-hooks.js +5 -4
  133. package/dist/tasks/extension.d.ts +18 -16
  134. package/dist/tasks/extension.js +28 -23
  135. package/dist/tasks/identity.d.ts +9 -0
  136. package/dist/tasks/identity.js +4 -0
  137. package/dist/tasks/index.d.ts +1 -0
  138. package/dist/tasks/runtime/cron.d.ts +6 -2
  139. package/dist/tasks/runtime/cron.js +9 -0
  140. package/dist/websocket/extension.d.ts +19 -9
  141. package/dist/websocket/extension.js +103 -30
  142. package/dist/websocket/identity.d.ts +9 -0
  143. package/dist/websocket/identity.js +4 -0
  144. package/dist/websocket/index.d.ts +1 -0
  145. package/package.json +1 -1
@@ -0,0 +1,179 @@
1
+ import { runtimeExecutionId } from '../core/identity.js';
2
+ import { epochMilliseconds, milliseconds } from '../core/units.js';
3
+ import { parseCapsuleId, parseRunId, parseSpanId, eventSequence, parseInspectorRequestId, parseTraceId, } from './identity.js';
4
+ import { parseModelNodeId, parseProviderNodeId, } from '../core/model/identity.js';
5
+ export const isDevtoolsRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
6
+ function optional(value, names, check) {
7
+ return names.every((name) => value[name] === undefined || check(value[name]));
8
+ }
9
+ function jsonValue(value, ancestors = new Set()) {
10
+ if (value === null || ['string', 'boolean', 'number'].includes(typeof value))
11
+ return true;
12
+ if (typeof value !== 'object' || ancestors.has(value))
13
+ return false;
14
+ if (!Array.isArray(value) &&
15
+ Object.getPrototypeOf(value) !== Object.prototype &&
16
+ Object.getPrototypeOf(value) !== null)
17
+ return false;
18
+ const next = new Set(ancestors).add(value);
19
+ return Object.values(value).every((child) => jsonValue(child, next));
20
+ }
21
+ function preview(value) {
22
+ return (isDevtoolsRecord(value) &&
23
+ typeof value.preview === 'string' &&
24
+ optional(value, ['truncated', 'redacted'], (item) => typeof item === 'boolean') &&
25
+ optional(value, ['type'], (item) => typeof item === 'string') &&
26
+ (value.value === undefined || jsonValue(value.value)));
27
+ }
28
+ function serializedError(value) {
29
+ return (isDevtoolsRecord(value) &&
30
+ typeof value.message === 'string' &&
31
+ optional(value, ['name', 'stack'], (item) => typeof item === 'string'));
32
+ }
33
+ function replayModes(value) {
34
+ return (Array.isArray(value) &&
35
+ value.every((mode) => mode === 'direct' || mode === 'transport'));
36
+ }
37
+ export function decodeRuntimeEvent(value) {
38
+ if (!isDevtoolsRecord(value) ||
39
+ typeof value.runId !== 'string' ||
40
+ typeof value.seq !== 'number' ||
41
+ typeof value.timestamp !== 'number' ||
42
+ typeof value.traceId !== 'string' ||
43
+ typeof value.spanId !== 'string')
44
+ return undefined;
45
+ if (!optional(value, [
46
+ 'parentSpanId',
47
+ 'graphNodeId',
48
+ 'capsuleId',
49
+ 'replayedFromTraceId',
50
+ 'replayedFromCapsuleId',
51
+ ], (item) => typeof item === 'string') ||
52
+ !optional(value, ['replayable'], (item) => typeof item === 'boolean') ||
53
+ !optional(value, ['attributes'], isDevtoolsRecord) ||
54
+ !optional(value, ['input', 'result'], preview) ||
55
+ !optional(value, ['error'], serializedError) ||
56
+ !optional(value, ['replayModes'], replayModes))
57
+ return undefined;
58
+ const base = {
59
+ runId: parseRunId(value.runId),
60
+ seq: eventSequence(value.seq),
61
+ timestamp: epochMilliseconds(value.timestamp),
62
+ traceId: parseTraceId(value.traceId),
63
+ spanId: parseSpanId(value.spanId),
64
+ ...(typeof value.parentSpanId === 'string'
65
+ ? { parentSpanId: parseSpanId(value.parentSpanId) }
66
+ : {}),
67
+ ...(typeof value.graphNodeId === 'string'
68
+ ? { graphNodeId: parseModelNodeId(value.graphNodeId) }
69
+ : {}),
70
+ ...(typeof value.capsuleId === 'string'
71
+ ? { capsuleId: parseCapsuleId(value.capsuleId) }
72
+ : {}),
73
+ ...(typeof value.replayedFromTraceId === 'string'
74
+ ? { replayedFromTraceId: parseTraceId(value.replayedFromTraceId) }
75
+ : {}),
76
+ ...(typeof value.replayedFromCapsuleId === 'string'
77
+ ? { replayedFromCapsuleId: parseCapsuleId(value.replayedFromCapsuleId) }
78
+ : {}),
79
+ ...(typeof value.replayable === 'boolean'
80
+ ? { replayable: value.replayable }
81
+ : {}),
82
+ ...(isDevtoolsRecord(value.attributes)
83
+ ? { attributes: value.attributes }
84
+ : {}),
85
+ ...(preview(value.input) ? { input: value.input } : {}),
86
+ ...(preview(value.result) ? { result: value.result } : {}),
87
+ ...(serializedError(value.error) ? { error: value.error } : {}),
88
+ ...(replayModes(value.replayModes)
89
+ ? { replayModes: value.replayModes }
90
+ : {}),
91
+ };
92
+ switch (value.type) {
93
+ case 'execution.started':
94
+ if (typeof value.executionId !== 'string' ||
95
+ typeof value.executionKind !== 'string' ||
96
+ typeof value.name !== 'string')
97
+ return undefined;
98
+ return {
99
+ ...base,
100
+ type: value.type,
101
+ executionId: runtimeExecutionId(value.executionId),
102
+ executionKind: value.executionKind,
103
+ name: value.name,
104
+ };
105
+ case 'span.started':
106
+ if (typeof value.name !== 'string' || typeof value.kind !== 'string')
107
+ return undefined;
108
+ return { ...base, type: value.type, kind: value.kind, name: value.name };
109
+ case 'execution.ended':
110
+ if (typeof value.executionId !== 'string')
111
+ return undefined;
112
+ if (typeof value.durationMs !== 'number' ||
113
+ (value.status !== 'ok' &&
114
+ value.status !== 'error' &&
115
+ value.status !== 'cancelled'))
116
+ return undefined;
117
+ return {
118
+ ...base,
119
+ type: value.type,
120
+ executionId: runtimeExecutionId(value.executionId),
121
+ durationMs: milliseconds(value.durationMs),
122
+ status: value.status,
123
+ };
124
+ case 'span.ended':
125
+ if (typeof value.durationMs !== 'number' ||
126
+ (value.status !== 'ok' &&
127
+ value.status !== 'error' &&
128
+ value.status !== 'cancelled'))
129
+ return undefined;
130
+ return {
131
+ ...base,
132
+ type: value.type,
133
+ durationMs: milliseconds(value.durationMs),
134
+ status: value.status,
135
+ };
136
+ default:
137
+ return undefined;
138
+ }
139
+ }
140
+ export function decodeInspectorCommand(value) {
141
+ if (!isDevtoolsRecord(value) || !isDevtoolsRecord(value.request))
142
+ return undefined;
143
+ const body = value.request;
144
+ const requestId = parseInspectorRequestId(body.requestId);
145
+ if (requestId === undefined)
146
+ return undefined;
147
+ if (value.type === 'command.replay-capsule') {
148
+ const capsuleId = parseCapsuleId(body.capsuleId);
149
+ if (capsuleId === undefined ||
150
+ !optional(body, ['parentTraceId'], (item) => typeof item === 'string'))
151
+ return undefined;
152
+ return {
153
+ type: value.type,
154
+ request: {
155
+ requestId,
156
+ capsuleId,
157
+ ...('inputOverride' in body
158
+ ? { inputOverride: body.inputOverride }
159
+ : {}),
160
+ ...(body.parentTraceId === undefined
161
+ ? {}
162
+ : { parentTraceId: parseTraceId(body.parentTraceId) }),
163
+ },
164
+ };
165
+ }
166
+ const graphNodeId = parseProviderNodeId(body.graphNodeId);
167
+ if (graphNodeId === undefined)
168
+ return undefined;
169
+ if (value.type === 'command.provider-playground')
170
+ return { type: value.type, request: { requestId, graphNodeId } };
171
+ if (value.type === 'command.invoke-provider-method' &&
172
+ typeof body.method === 'string' &&
173
+ Array.isArray(body.args))
174
+ return {
175
+ type: value.type,
176
+ request: { requestId, graphNodeId, method: body.method, args: body.args },
177
+ };
178
+ return undefined;
179
+ }
@@ -0,0 +1,6 @@
1
+ import type { RunId, TraceId, SpanId, CapsuleId, CaptureHandleId } from './identity.js';
2
+ export declare const createRunId: () => RunId;
3
+ export declare const createTraceId: () => TraceId;
4
+ export declare const createSpanId: () => SpanId;
5
+ export declare const createCapsuleId: () => CapsuleId;
6
+ export declare const createCaptureHandleId: () => CaptureHandleId;
@@ -0,0 +1,5 @@
1
+ export const createRunId = () => `run_${crypto.randomUUID()}`;
2
+ export const createTraceId = () => `trace_${crypto.randomUUID()}`;
3
+ export const createSpanId = () => `span_${crypto.randomUUID()}`;
4
+ export const createCapsuleId = () => `capsule_${crypto.randomUUID()}`;
5
+ export const createCaptureHandleId = () => `ref_${crypto.randomUUID()}`;
@@ -0,0 +1,21 @@
1
+ type DevtoolsId<Kind extends string> = string & {
2
+ readonly '~loutre.devtools-id': Kind;
3
+ };
4
+ export type RunId = DevtoolsId<'run'>;
5
+ export type TraceId = DevtoolsId<'trace'>;
6
+ export type SpanId = DevtoolsId<'span'>;
7
+ export type CapsuleId = DevtoolsId<'capsule'>;
8
+ export type InspectorRequestId = DevtoolsId<'inspector-request'>;
9
+ export type ControlRequestId = DevtoolsId<'control-request'>;
10
+ export type CaptureHandleId = DevtoolsId<'capture-handle'>;
11
+ export type EventSequence = number & {
12
+ readonly '~loutre.devtools-sequence': true;
13
+ };
14
+ export declare const parseRunId: (value: unknown) => RunId | undefined;
15
+ export declare const parseTraceId: (value: unknown) => TraceId | undefined;
16
+ export declare const parseSpanId: (value: unknown) => SpanId | undefined;
17
+ export declare const parseCapsuleId: (value: unknown) => CapsuleId | undefined;
18
+ export declare const parseInspectorRequestId: (value: unknown) => InspectorRequestId | undefined;
19
+ export declare const parseControlRequestId: (value: unknown) => ControlRequestId | undefined;
20
+ export declare const eventSequence: (value: number) => EventSequence;
21
+ export {};
@@ -0,0 +1,7 @@
1
+ export const parseRunId = (value) => typeof value === 'string' ? value : undefined;
2
+ export const parseTraceId = (value) => typeof value === 'string' ? value : undefined;
3
+ export const parseSpanId = (value) => typeof value === 'string' ? value : undefined;
4
+ export const parseCapsuleId = (value) => typeof value === 'string' ? value : undefined;
5
+ export const parseInspectorRequestId = (value) => typeof value === 'string' ? value : undefined;
6
+ export const parseControlRequestId = (value) => typeof value === 'string' ? value : undefined;
7
+ export const eventSequence = (value) => value;
@@ -9,3 +9,6 @@ export type { ExecutionEndedEvent, ExecutionStartedEvent, RuntimeEvent, RuntimeE
9
9
  export { serializeDevtoolsError } from './observer.js';
10
10
  export type { DevtoolsValue, DevtoolsValuePreview, DevtoolsValuePreviewOptions, } from './values.js';
11
11
  export { previewDevtoolsValue } from './values.js';
12
+ export * from './identity.js';
13
+ export { decodeRuntimeEvent, decodeInspectorCommand } from './decoder.js';
14
+ export type { InspectorCommand } from './decoder.js';
@@ -4,3 +4,5 @@ export { ReplayCapsuleStore, } from './capsule.js';
4
4
  export { RuntimeDevtoolsInstrumentation } from './runtime.js';
5
5
  export { serializeDevtoolsError } from './observer.js';
6
6
  export { previewDevtoolsValue } from './values.js';
7
+ export * from './identity.js';
8
+ export { decodeRuntimeEvent, decodeInspectorCommand } from './decoder.js';
@@ -1,23 +1,25 @@
1
+ import type { TraceId, SpanId, CapsuleId, InspectorRequestId } from './identity.js';
2
+ import type { ProviderNodeId } from '../core/model/identity.js';
1
3
  import type { SerializedDevtoolsError } from './observer.js';
2
4
  import type { DevtoolsValuePreview } from './values.js';
3
5
  export interface ReplayExecutionContext {
4
- readonly sourceTraceId: string;
5
- readonly sourceCapsuleId: string;
6
- readonly parentTraceId?: string;
6
+ readonly sourceTraceId: TraceId;
7
+ readonly sourceCapsuleId: CapsuleId;
8
+ readonly parentTraceId?: TraceId;
7
9
  }
8
10
  export interface ReplayCapsuleRequest {
9
- readonly requestId: string;
10
- readonly capsuleId: string;
11
+ readonly requestId: InspectorRequestId;
12
+ readonly capsuleId: CapsuleId;
11
13
  readonly inputOverride?: unknown;
12
- readonly parentTraceId?: string;
14
+ readonly parentTraceId?: TraceId;
13
15
  }
14
16
  export interface ProviderPlaygroundRequest {
15
- readonly requestId: string;
16
- readonly graphNodeId: string;
17
+ readonly requestId: InspectorRequestId;
18
+ readonly graphNodeId: ProviderNodeId;
17
19
  }
18
20
  export interface ProviderMethodInvocationRequest {
19
- readonly requestId: string;
20
- readonly graphNodeId: string;
21
+ readonly requestId: InspectorRequestId;
22
+ readonly graphNodeId: ProviderNodeId;
21
23
  readonly method: string;
22
24
  readonly args: readonly unknown[];
23
25
  }
@@ -26,15 +28,15 @@ export interface ProviderPlaygroundMethod {
26
28
  readonly arity: number;
27
29
  }
28
30
  export interface ProviderPlaygroundDescriptor {
29
- readonly requestId: string;
30
- readonly graphNodeId: string;
31
+ readonly requestId: InspectorRequestId;
32
+ readonly graphNodeId: ProviderNodeId;
31
33
  readonly providerName: string;
32
34
  readonly methods: readonly ProviderPlaygroundMethod[];
33
35
  }
34
36
  export interface RuntimeInvocationResult {
35
- readonly requestId: string;
37
+ readonly requestId: InspectorRequestId;
36
38
  readonly status: 'ok' | 'error';
37
- readonly traceId?: string;
39
+ readonly traceId?: TraceId;
38
40
  readonly result?: DevtoolsValuePreview;
39
41
  readonly error?: SerializedDevtoolsError;
40
42
  }
@@ -44,8 +46,8 @@ export interface RuntimeInspector {
44
46
  invokeProviderMethod(request: ProviderMethodInvocationRequest): Promise<RuntimeInvocationResult>;
45
47
  }
46
48
  export interface RuntimeTraceContext {
47
- readonly traceId: string;
48
- readonly spanId: string;
49
+ readonly traceId: TraceId;
50
+ readonly spanId: SpanId;
49
51
  }
50
52
  export interface RuntimeDevtoolsContext {
51
53
  readonly trace?: RuntimeTraceContext;
@@ -1,40 +1,44 @@
1
- import type { RuntimeExecutionMetadata } from '../core/instrumentation.js';
1
+ import type { RunId, TraceId, SpanId, CapsuleId, EventSequence } from './identity.js';
2
+ import type { ModelNodeId } from '../core/model/identity.js';
3
+ import type { RuntimeExecutionId } from '../core/identity.js';
4
+ import type { EpochMs, DurationMs } from '../core/units.js';
5
+ import type { RuntimeExecutionMetadata, RuntimeOperationMetadata } from '../core/instrumentation.js';
2
6
  import type { DevtoolsValuePreview } from './values.js';
3
- export type RuntimeSpanKind = 'execution' | 'http.request' | 'http.middleware' | 'http.handler' | 'task.handler' | 'message-port.handler' | 'websocket.handler' | 'di.resolve' | 'provider.construct' | 'provider.method' | 'response' | 'dependency' | 'custom';
7
+ export type RuntimeSpanKind = RuntimeOperationMetadata['kind'];
4
8
  export interface SerializedDevtoolsError {
5
9
  readonly name?: string;
6
10
  readonly message: string;
7
11
  readonly stack?: string;
8
12
  }
9
13
  export interface RuntimeEventBase {
10
- readonly runId: string;
11
- readonly seq: number;
12
- readonly timestamp: number;
13
- readonly traceId?: string;
14
- readonly spanId?: string;
15
- readonly parentSpanId?: string;
16
- readonly graphNodeId?: string;
14
+ readonly runId: RunId;
15
+ readonly seq: EventSequence;
16
+ readonly timestamp: EpochMs;
17
+ readonly traceId?: TraceId;
18
+ readonly spanId?: SpanId;
19
+ readonly parentSpanId?: SpanId;
20
+ readonly graphNodeId?: ModelNodeId;
17
21
  }
18
22
  export interface ExecutionStartedEvent extends RuntimeEventBase {
19
23
  readonly type: 'execution.started';
20
- readonly traceId: string;
21
- readonly spanId: string;
22
- readonly executionId: string;
24
+ readonly traceId: TraceId;
25
+ readonly spanId: SpanId;
26
+ readonly executionId: RuntimeExecutionId;
23
27
  readonly executionKind: string;
24
28
  readonly name: string;
25
29
  readonly input?: DevtoolsValuePreview;
26
- readonly capsuleId?: string;
30
+ readonly capsuleId?: CapsuleId;
27
31
  readonly replayable?: boolean;
28
32
  readonly replayModes?: readonly ('direct' | 'transport')[];
29
- readonly replayedFromTraceId?: string;
30
- readonly replayedFromCapsuleId?: string;
33
+ readonly replayedFromTraceId?: TraceId;
34
+ readonly replayedFromCapsuleId?: CapsuleId;
31
35
  }
32
36
  export interface ExecutionEndedEvent extends RuntimeEventBase {
33
37
  readonly type: 'execution.ended';
34
- readonly traceId: string;
35
- readonly spanId: string;
36
- readonly executionId: string;
37
- readonly durationMs: number;
38
+ readonly traceId: TraceId;
39
+ readonly spanId: SpanId;
40
+ readonly executionId: RuntimeExecutionId;
41
+ readonly durationMs: DurationMs;
38
42
  readonly status: 'ok' | 'error' | 'cancelled';
39
43
  readonly attributes?: Readonly<Record<string, unknown>>;
40
44
  readonly result?: DevtoolsValuePreview;
@@ -42,21 +46,21 @@ export interface ExecutionEndedEvent extends RuntimeEventBase {
42
46
  }
43
47
  export interface SpanStartedEvent extends RuntimeEventBase {
44
48
  readonly type: 'span.started';
45
- readonly spanId: string;
46
- readonly traceId: string;
49
+ readonly spanId: SpanId;
50
+ readonly traceId: TraceId;
47
51
  readonly kind: RuntimeSpanKind;
48
52
  readonly name: string;
49
53
  readonly attributes?: Readonly<Record<string, unknown>>;
50
54
  readonly input?: DevtoolsValuePreview;
51
- readonly capsuleId?: string;
55
+ readonly capsuleId?: CapsuleId;
52
56
  readonly replayable?: boolean;
53
57
  readonly replayModes?: readonly ('direct' | 'transport')[];
54
58
  }
55
59
  export interface SpanEndedEvent extends RuntimeEventBase {
56
60
  readonly type: 'span.ended';
57
- readonly spanId: string;
58
- readonly traceId: string;
59
- readonly durationMs: number;
61
+ readonly spanId: SpanId;
62
+ readonly traceId: TraceId;
63
+ readonly durationMs: DurationMs;
60
64
  readonly status: 'ok' | 'error' | 'cancelled';
61
65
  readonly attributes?: Readonly<Record<string, unknown>>;
62
66
  readonly result?: DevtoolsValuePreview;
@@ -64,14 +68,14 @@ export interface SpanEndedEvent extends RuntimeEventBase {
64
68
  }
65
69
  export type RuntimeEvent = ExecutionStartedEvent | ExecutionEndedEvent | SpanStartedEvent | SpanEndedEvent;
66
70
  export interface RuntimeObserver {
67
- readonly runId?: string;
71
+ readonly runId?: RunId;
68
72
  executionStarted?(event: ExecutionStartedEvent): void;
69
73
  executionEnded?(event: ExecutionEndedEvent): void;
70
74
  spanStarted?(event: SpanStartedEvent): void;
71
75
  spanEnded?(event: SpanEndedEvent): void;
72
76
  }
73
77
  export interface RuntimeExecutionContext extends RuntimeExecutionMetadata {
74
- readonly traceId: string;
75
- readonly spanId: string;
78
+ readonly traceId: TraceId;
79
+ readonly spanId: SpanId;
76
80
  }
77
81
  export declare function serializeDevtoolsError(error: unknown): SerializedDevtoolsError;
@@ -1,5 +1,9 @@
1
+ import { syntheticExecutionId } from '../core/identity.js';
2
+ import { createRunId, createTraceId, createSpanId, } from './identity-internal.js';
3
+ import { eventSequence } from './identity.js';
4
+ import { monotonicNow, epochFromMonotonic, elapsed, } from '../core/units.js';
1
5
  import { ReplayCapsuleStore } from './capsule.js';
2
- import { serializeDevtoolsError, } from './observer.js';
6
+ import { serializeDevtoolsError } from './observer.js';
3
7
  import { discoverProviderMethods, instrumentProviderMethods, } from './provider-instrumentation.js';
4
8
  import { previewDevtoolsValue } from './values.js';
5
9
  export class RuntimeDevtoolsInstrumentation {
@@ -27,7 +31,7 @@ export class RuntimeDevtoolsInstrumentation {
27
31
  const captureResults = options.options.capture?.results;
28
32
  this.#captureResults =
29
33
  captureResults !== false && captureResults !== 'errors';
30
- this.#runId = options.observer.runId ?? `run_${crypto.randomUUID()}`;
34
+ this.#runId = options.observer.runId ?? createRunId();
31
35
  const replay = options.options.replay;
32
36
  this.#capsules =
33
37
  replay?.enabled === false
@@ -48,10 +52,10 @@ export class RuntimeDevtoolsInstrumentation {
48
52
  });
49
53
  }
50
54
  beginExecution(metadata, invocation) {
51
- const traceId = `trace_${crypto.randomUUID()}`;
52
- const spanId = `span_${crypto.randomUUID()}`;
53
- const startedAt = performance.now();
54
- const startedTimestamp = performance.timeOrigin + startedAt;
55
+ const traceId = createTraceId();
56
+ const spanId = createSpanId();
57
+ const startedAt = monotonicNow();
58
+ const startedTimestamp = epochFromMonotonic(startedAt);
55
59
  const name = metadata.name ?? metadata.executionId;
56
60
  const replaySource = this.#context.current()?.replay;
57
61
  const capsule = invocation && this.#capsules
@@ -117,12 +121,12 @@ export class RuntimeDevtoolsInstrumentation {
117
121
  const result = resultValues.length === 0
118
122
  ? undefined
119
123
  : this.#previewResult(resultValues[0]);
120
- const endedAt = performance.now();
121
- const timestamp = performance.timeOrigin + endedAt;
124
+ const endedAt = monotonicNow();
125
+ const timestamp = epochFromMonotonic(endedAt);
122
126
  this.#notify('spanEnded', {
123
127
  type: 'span.ended',
124
128
  ...this.#identity(timestamp, traceId, spanId, metadata.graphNodeId),
125
- durationMs: endedAt - startedAt,
129
+ durationMs: elapsed(startedAt, endedAt),
126
130
  status,
127
131
  ...(Object.keys(attributes).length === 0 ? {} : { attributes }),
128
132
  ...(result === undefined ? {} : { result }),
@@ -132,7 +136,7 @@ export class RuntimeDevtoolsInstrumentation {
132
136
  type: 'execution.ended',
133
137
  ...this.#identity(timestamp, traceId, spanId, metadata.graphNodeId),
134
138
  executionId: metadata.executionId,
135
- durationMs: endedAt - startedAt,
139
+ durationMs: elapsed(startedAt, endedAt),
136
140
  status,
137
141
  ...(Object.keys(attributes).length === 0 ? {} : { attributes }),
138
142
  ...(result === undefined ? {} : { result }),
@@ -145,11 +149,11 @@ export class RuntimeDevtoolsInstrumentation {
145
149
  const current = this.#context.current();
146
150
  if (!current?.trace)
147
151
  return undefined;
148
- const spanId = `span_${crypto.randomUUID()}`;
149
- const startedAt = performance.now();
152
+ const spanId = createSpanId();
153
+ const startedAt = monotonicNow();
150
154
  const capsule = invocation && this.#capsules
151
155
  ? this.#capsules.createExecution(current.trace.traceId, spanId, {
152
- executionId: `span:${metadata.name}`,
156
+ executionId: syntheticExecutionId(`span:${metadata.name}`),
153
157
  executionKind: metadata.kind,
154
158
  name: metadata.name,
155
159
  ...(metadata.graphNodeId === undefined
@@ -167,8 +171,8 @@ export class RuntimeDevtoolsInstrumentation {
167
171
  this.#notify('spanStarted', {
168
172
  type: 'span.started',
169
173
  runId: this.#runId,
170
- seq: ++this.#seq,
171
- timestamp: performance.timeOrigin + startedAt,
174
+ seq: eventSequence(++this.#seq),
175
+ timestamp: epochFromMonotonic(startedAt),
172
176
  traceId: current.trace.traceId,
173
177
  spanId,
174
178
  parentSpanId: current.trace.spanId,
@@ -206,19 +210,19 @@ export class RuntimeDevtoolsInstrumentation {
206
210
  ? undefined
207
211
  : this.#previewResult(resultValues[0]);
208
212
  const error = failed ? serializeDevtoolsError(failureReason) : undefined;
209
- const endedAt = performance.now();
213
+ const endedAt = monotonicNow();
210
214
  this.#notify('spanEnded', {
211
215
  type: 'span.ended',
212
216
  runId: this.#runId,
213
- seq: ++this.#seq,
214
- timestamp: performance.timeOrigin + endedAt,
217
+ seq: eventSequence(++this.#seq),
218
+ timestamp: epochFromMonotonic(endedAt),
215
219
  traceId: current.trace.traceId,
216
220
  spanId,
217
221
  parentSpanId: current.trace.spanId,
218
222
  ...(metadata.graphNodeId === undefined
219
223
  ? {}
220
224
  : { graphNodeId: metadata.graphNodeId }),
221
- durationMs: endedAt - startedAt,
225
+ durationMs: elapsed(startedAt, endedAt),
222
226
  status: failed ? 'error' : 'ok',
223
227
  ...(Object.keys(attributes).length === 0 ? {} : { attributes }),
224
228
  ...(result === undefined ? {} : { result }),
@@ -356,13 +360,13 @@ export class RuntimeDevtoolsInstrumentation {
356
360
  if (!current?.trace) {
357
361
  return Reflect.apply(invocation.original, invocation.receiver, invocation.args);
358
362
  }
359
- const spanId = `span_${crypto.randomUUID()}`;
360
- const startedAt = performance.now();
363
+ const spanId = createSpanId();
364
+ const startedAt = monotonicNow();
361
365
  const name = `${metadata.name}.${invocation.name}`;
362
366
  const capsule = metadata.scope === 'transient'
363
367
  ? undefined
364
368
  : this.#capsules?.createExecution(current.trace.traceId, spanId, {
365
- executionId: `${metadata.providerId}.${invocation.name}`,
369
+ executionId: syntheticExecutionId(`${metadata.providerId}.${invocation.name}`),
366
370
  executionKind: 'provider.method',
367
371
  graphNodeId: metadata.graphNodeId,
368
372
  name,
@@ -394,8 +398,8 @@ export class RuntimeDevtoolsInstrumentation {
394
398
  this.#notify('spanStarted', {
395
399
  type: 'span.started',
396
400
  runId: this.#runId,
397
- seq: ++this.#seq,
398
- timestamp: performance.timeOrigin + startedAt,
401
+ seq: eventSequence(++this.#seq),
402
+ timestamp: epochFromMonotonic(startedAt),
399
403
  traceId: parent.traceId,
400
404
  spanId,
401
405
  parentSpanId: parent.spanId,
@@ -411,18 +415,18 @@ export class RuntimeDevtoolsInstrumentation {
411
415
  replayModes: capsule.replayModes,
412
416
  }),
413
417
  });
414
- const endedAt = performance.now();
418
+ const endedAt = monotonicNow();
415
419
  const result = outcome.status === 'ok' ? this.#previewResult(outcome.result) : undefined;
416
420
  this.#notify('spanEnded', {
417
421
  type: 'span.ended',
418
422
  runId: this.#runId,
419
- seq: ++this.#seq,
420
- timestamp: performance.timeOrigin + endedAt,
423
+ seq: eventSequence(++this.#seq),
424
+ timestamp: epochFromMonotonic(endedAt),
421
425
  traceId: parent.traceId,
422
426
  spanId,
423
427
  parentSpanId: parent.spanId,
424
428
  graphNodeId: metadata.graphNodeId,
425
- durationMs: endedAt - startedAt,
429
+ durationMs: elapsed(startedAt, endedAt),
426
430
  status: outcome.status,
427
431
  ...(result === undefined ? {} : { result }),
428
432
  ...(outcome.status === 'error'
@@ -438,7 +442,7 @@ export class RuntimeDevtoolsInstrumentation {
438
442
  throw new TypeError('LUTRE_DEVTOOLS_PROVIDER_ARGS_REQUIRED');
439
443
  }
440
444
  const scope = this.beginExecution({
441
- executionId: `${metadata.providerId}.${method}`,
445
+ executionId: syntheticExecutionId(`${metadata.providerId}.${method}`),
442
446
  executionKind: 'provider.method',
443
447
  graphNodeId: metadata.graphNodeId,
444
448
  name: `${metadata.name}.${method}`,
@@ -500,7 +504,7 @@ export class RuntimeDevtoolsInstrumentation {
500
504
  #identity(timestamp, traceId, spanId, graphNodeId) {
501
505
  return {
502
506
  runId: this.#runId,
503
- seq: ++this.#seq,
507
+ seq: eventSequence(++this.#seq),
504
508
  timestamp,
505
509
  traceId,
506
510
  spanId,
@@ -1,9 +1,10 @@
1
+ import { byteLimit, captureDepthLimit, utf8ByteLength } from '../core/units.js';
1
2
  import { match } from 'ts-pattern';
2
3
  const defaultMaxValueBytes = 64 * 1024;
3
4
  const defaultMaxDepth = 8;
4
5
  export function previewDevtoolsValue(value, options = {}) {
5
- const maxValueBytes = options.maxValueBytes ?? defaultMaxValueBytes;
6
- const maxDepth = options.maxDepth ?? defaultMaxDepth;
6
+ const maxValueBytes = byteLimit(options.maxValueBytes ?? defaultMaxValueBytes);
7
+ const maxDepth = captureDepthLimit(options.maxDepth ?? defaultMaxDepth);
7
8
  const redactions = new Set((options.redact ?? []).map((entry) => entry.trim().toLowerCase()));
8
9
  let redacted = false;
9
10
  let truncated = false;
@@ -158,9 +159,6 @@ function safeValueType(value) {
158
159
  return typeof value;
159
160
  }
160
161
  }
161
- function utf8ByteLength(value) {
162
- return new TextEncoder().encode(value).byteLength;
163
- }
164
162
  function bytesToBase64(value) {
165
163
  let binary = '';
166
164
  for (const byte of value)
@@ -1 +1 @@
1
- export declare const LOUTRE_VERSION = "0.9.2";
1
+ export declare const LOUTRE_VERSION = "0.10.0";
@@ -1,2 +1,2 @@
1
1
  // package manifestとのずれを避けるため、scripts/generate-version.mjsがbuild前に更新する。
2
- export const LOUTRE_VERSION = '0.9.2';
2
+ export const LOUTRE_VERSION = '0.10.0';