@loutrejs/loutre 0.6.0 → 0.7.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.
@@ -0,0 +1,175 @@
1
+ const defaultMaxValueBytes = 64 * 1024;
2
+ const defaultMaxDepth = 8;
3
+ export function previewDevtoolsValue(value, options = {}) {
4
+ const maxValueBytes = options.maxValueBytes ?? defaultMaxValueBytes;
5
+ const maxDepth = options.maxDepth ?? defaultMaxDepth;
6
+ const redactions = new Set((options.redact ?? []).map((entry) => entry.trim().toLowerCase()));
7
+ let redacted = false;
8
+ let truncated = false;
9
+ const seen = new WeakSet();
10
+ const encode = (current, depth, path) => {
11
+ if (depth > maxDepth) {
12
+ truncated = true;
13
+ return '[Truncated]';
14
+ }
15
+ if (current === null)
16
+ return null;
17
+ switch (typeof current) {
18
+ case 'boolean':
19
+ case 'number':
20
+ case 'string':
21
+ return current;
22
+ case 'undefined':
23
+ return { $type: 'undefined' };
24
+ case 'bigint':
25
+ return { $type: 'bigint', value: current.toString() };
26
+ case 'function':
27
+ case 'symbol':
28
+ truncated = true;
29
+ return `[${typeof current}]`;
30
+ case 'object':
31
+ break;
32
+ }
33
+ if (current instanceof Date) {
34
+ return { $type: 'date', value: current.toISOString() };
35
+ }
36
+ if (current instanceof Uint8Array) {
37
+ return { $type: 'bytes', base64: bytesToBase64(current) };
38
+ }
39
+ if (seen.has(current)) {
40
+ truncated = true;
41
+ return '[Circular]';
42
+ }
43
+ seen.add(current);
44
+ try {
45
+ if (Array.isArray(current)) {
46
+ const output = [];
47
+ const descriptors = Object.getOwnPropertyDescriptors(current);
48
+ for (let index = 0; index < current.length; index += 1) {
49
+ const descriptor = descriptors[String(index)];
50
+ if (!descriptor) {
51
+ output.length = index + 1;
52
+ continue;
53
+ }
54
+ if (!('value' in descriptor)) {
55
+ truncated = true;
56
+ output[index] = '[Accessor]';
57
+ continue;
58
+ }
59
+ output[index] = encode(descriptor.value, depth + 1, [
60
+ ...path,
61
+ String(index),
62
+ ]);
63
+ }
64
+ return output;
65
+ }
66
+ if (current instanceof Map) {
67
+ return {
68
+ $type: 'map',
69
+ entries: [...current.entries()].map(([key, item], index) => [
70
+ encode(key, depth + 1, [...path, String(index), 'key']),
71
+ encode(item, depth + 1, [...path, String(index), 'value']),
72
+ ]),
73
+ };
74
+ }
75
+ if (current instanceof Set) {
76
+ return {
77
+ $type: 'set',
78
+ values: [...current.values()].map((item, index) => encode(item, depth + 1, [...path, String(index)])),
79
+ };
80
+ }
81
+ const output = {};
82
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(current))) {
83
+ if (!descriptor.enumerable)
84
+ continue;
85
+ const nextPath = [...path, key];
86
+ if (shouldRedact(key, nextPath, redactions)) {
87
+ redacted = true;
88
+ output[key] = { $type: 'redacted' };
89
+ continue;
90
+ }
91
+ if (!('value' in descriptor)) {
92
+ truncated = true;
93
+ output[key] = '[Accessor]';
94
+ continue;
95
+ }
96
+ output[key] = encode(descriptor.value, depth + 1, nextPath);
97
+ }
98
+ return output;
99
+ }
100
+ finally {
101
+ seen.delete(current);
102
+ }
103
+ };
104
+ try {
105
+ const encoded = encode(value, 0, []);
106
+ const serialized = JSON.stringify(encoded);
107
+ const bytes = utf8ByteLength(serialized);
108
+ const preview = serialized.length > 512 ? `${serialized.slice(0, 509)}...` : serialized;
109
+ if (bytes > maxValueBytes) {
110
+ return {
111
+ preview,
112
+ truncated: true,
113
+ ...(redacted ? { redacted: true } : {}),
114
+ type: valueType(value),
115
+ };
116
+ }
117
+ return {
118
+ value: encoded,
119
+ preview,
120
+ ...(truncated ? { truncated: true } : {}),
121
+ ...(redacted ? { redacted: true } : {}),
122
+ type: valueType(value),
123
+ };
124
+ }
125
+ catch {
126
+ const type = safeValueType(value);
127
+ return {
128
+ preview: `[${type}]`,
129
+ truncated: true,
130
+ type,
131
+ };
132
+ }
133
+ }
134
+ function shouldRedact(key, path, redactions) {
135
+ if (redactions.size === 0)
136
+ return false;
137
+ const normalizedKey = key.toLowerCase();
138
+ const normalizedPath = path.join('.').toLowerCase();
139
+ return redactions.has(normalizedKey) || redactions.has(normalizedPath);
140
+ }
141
+ function valueType(value) {
142
+ if (value === null)
143
+ return 'null';
144
+ if (Array.isArray(value))
145
+ return 'array';
146
+ if (value instanceof Date)
147
+ return 'date';
148
+ if (value instanceof Uint8Array)
149
+ return 'bytes';
150
+ if (value instanceof Map)
151
+ return 'map';
152
+ if (value instanceof Set)
153
+ return 'set';
154
+ return typeof value === 'object' ? 'object' : typeof value;
155
+ }
156
+ function safeValueType(value) {
157
+ try {
158
+ return valueType(value);
159
+ }
160
+ catch {
161
+ return typeof value;
162
+ }
163
+ }
164
+ function utf8ByteLength(value) {
165
+ return new TextEncoder().encode(value).byteLength;
166
+ }
167
+ function bytesToBase64(value) {
168
+ let binary = '';
169
+ for (const byte of value)
170
+ binary += String.fromCharCode(byte);
171
+ const encoder = globalThis.btoa;
172
+ if (typeof encoder === 'function')
173
+ return encoder(binary);
174
+ return binary;
175
+ }
@@ -1 +1 @@
1
- export declare const LOUTRE_VERSION = "0.6.0";
1
+ export declare const LOUTRE_VERSION = "0.7.0";
@@ -1,2 +1,2 @@
1
1
  // package manifestとのずれを避けるため、scripts/generate-version.mjsがbuild前に更新する。
2
- export const LOUTRE_VERSION = '0.6.0';
2
+ export const LOUTRE_VERSION = '0.7.0';
@@ -409,7 +409,12 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
409
409
  }
410
410
  let lease;
411
411
  try {
412
- lease = applicationRuntime.beginExecution();
412
+ lease = applicationRuntime.beginExecution({
413
+ executionId: match.executionId,
414
+ executionKind: 'http.request',
415
+ graphNodeId: match.executionId,
416
+ name: `OPTIONS ${match.route.path}`,
417
+ });
413
418
  }
414
419
  catch (error) {
415
420
  completePendingIngress();
@@ -418,6 +423,7 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
418
423
  try {
419
424
  const headers = await createCorsPreflightResponseHeaders(match.route.middlewares, request, match.route.method);
420
425
  if (headers) {
426
+ lease.annotate?.({ 'http.status_code': 204 });
421
427
  return new Response(null, { status: 204, headers });
422
428
  }
423
429
  }
@@ -445,7 +451,30 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
445
451
  return Response.json({ error: 'Internal Server Error' }, { status: 500 });
446
452
  }
447
453
  if (!match) {
448
- return Response.json({ error: 'Not Found' }, { status: 404 });
454
+ const completePendingIngress = ingress.enter();
455
+ if (!completePendingIngress) {
456
+ return Response.json({ error: 'Service Unavailable' }, { status: 503 });
457
+ }
458
+ let lease;
459
+ try {
460
+ lease = applicationRuntime.beginExecution({
461
+ executionId: 'http.not-found',
462
+ executionKind: 'http.request',
463
+ name: `${method} ${url.pathname}`,
464
+ });
465
+ }
466
+ catch (error) {
467
+ completePendingIngress();
468
+ throw error;
469
+ }
470
+ try {
471
+ lease.annotate?.({ 'http.status_code': 404 });
472
+ return Response.json({ error: 'Not Found' }, { status: 404 });
473
+ }
474
+ finally {
475
+ lease.complete();
476
+ completePendingIngress();
477
+ }
449
478
  }
450
479
  const completePendingIngress = ingress.enter();
451
480
  if (!completePendingIngress) {
@@ -453,7 +482,12 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
453
482
  }
454
483
  let lease;
455
484
  try {
456
- lease = applicationRuntime.beginExecution();
485
+ lease = applicationRuntime.beginExecution({
486
+ executionId: match.executionId,
487
+ executionKind: 'http.request',
488
+ graphNodeId: match.executionId,
489
+ name: `${match.route.method} ${match.route.path}`,
490
+ });
457
491
  }
458
492
  catch (error) {
459
493
  completePendingIngress();
@@ -462,12 +496,17 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
462
496
  const abortRequest = () => lease.abort(request.signal.reason);
463
497
  let executionOwnedByStream = false;
464
498
  let executionFinished = false;
499
+ let executionResult;
500
+ let hasExecutionResult = false;
465
501
  const finishExecution = () => {
466
502
  if (executionFinished)
467
503
  return;
468
504
  executionFinished = true;
469
505
  request.signal.removeEventListener('abort', abortRequest);
470
- lease.complete();
506
+ if (hasExecutionResult)
507
+ lease.complete(executionResult);
508
+ else
509
+ lease.complete();
471
510
  };
472
511
  const adoptResponseStream = (stream) => {
473
512
  executionOwnedByStream = true;
@@ -486,9 +525,13 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
486
525
  request.signal.addEventListener('abort', abortRequest, { once: true });
487
526
  if (request.signal.aborted)
488
527
  abortRequest();
528
+ const annotateResponse = (response) => {
529
+ lease.annotate?.({ 'http.status_code': response.status });
530
+ return response;
531
+ };
489
532
  try {
490
533
  const corsHeaders = await createCorsActualResponseHeaders(match.route.middlewares, request);
491
- const complete = (response) => applyFrameworkHeadersToResponse(response, corsHeaders);
534
+ const complete = (response) => annotateResponse(applyFrameworkHeadersToResponse(response, corsHeaders));
492
535
  let context;
493
536
  try {
494
537
  context = await createHttpContext(request, url, match.params, match.route, lease.signal);
@@ -509,17 +552,50 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
509
552
  if (!handler) {
510
553
  throw new Error(`LUTRE_HTTP_HANDLER_MISSING: ${match.executionId}.${match.route.name}`);
511
554
  }
512
- const result = await composeLayers({
555
+ const dispatch = () => composeLayers({
513
556
  context,
514
557
  layers: match.route.middlewares,
515
558
  resolve: (token, source) => applicationRuntime.resolve(token, source),
516
- terminal: async (middlewareContext) => handler({
517
- input: middlewareContext.input,
518
- response: middlewareContext.response,
519
- signal: middlewareContext.signal,
520
- state: middlewareContext.state,
521
- }),
559
+ terminal: async (middlewareContext) => {
560
+ const handlerName = `${match.executionId}.${match.route.name}`;
561
+ const handlerOperation = applicationRuntime.beginOperation?.({
562
+ kind: 'http.handler',
563
+ name: handlerName,
564
+ graphNodeId: match.executionId,
565
+ }, {
566
+ input: middlewareContext.input,
567
+ invoke: (input) => replayHttpHandler(applicationRuntime, handler, match, input, middlewareContext.state),
568
+ });
569
+ const invoke = () => handler({
570
+ input: middlewareContext.input,
571
+ response: middlewareContext.response,
572
+ signal: middlewareContext.signal,
573
+ state: middlewareContext.state,
574
+ });
575
+ let result;
576
+ let hasResult = false;
577
+ try {
578
+ result = await (handlerOperation?.run
579
+ ? handlerOperation.run(invoke)
580
+ : invoke());
581
+ hasResult = true;
582
+ return result;
583
+ }
584
+ catch (error) {
585
+ handlerOperation?.fail?.(error);
586
+ throw error;
587
+ }
588
+ finally {
589
+ if (hasResult)
590
+ handlerOperation?.complete(result);
591
+ else
592
+ handlerOperation?.complete();
593
+ }
594
+ },
522
595
  });
596
+ const result = await (lease.run ? lease.run(dispatch) : dispatch());
597
+ executionResult = result;
598
+ hasExecutionResult = true;
523
599
  const finalized = await finalizeHttpResult(match.route.definition, result, lease.signal, finishExecution);
524
600
  if (finalized.streamControl)
525
601
  adoptResponseStream(finalized.streamControl);
@@ -527,11 +603,12 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
527
603
  }
528
604
  catch (error) {
529
605
  if (error instanceof HttpInputDecodeError) {
530
- return applyFrameworkHeadersToResponse(Response.json({ error: 'Invalid request' }, { status: 400 }), await safeCorsHeaders(match.route.middlewares, request));
606
+ return annotateResponse(applyFrameworkHeadersToResponse(Response.json({ error: 'Invalid request' }, { status: 400 }), await safeCorsHeaders(match.route.middlewares, request)));
531
607
  }
532
608
  if (error instanceof HttpInputValidationError) {
533
- return applyFrameworkHeadersToResponse(Response.json({ error: 'Validation failed' }, { status: 400 }), await safeCorsHeaders(match.route.middlewares, request));
609
+ return annotateResponse(applyFrameworkHeadersToResponse(Response.json({ error: 'Validation failed' }, { status: 400 }), await safeCorsHeaders(match.route.middlewares, request)));
534
610
  }
611
+ lease.fail?.(error);
535
612
  try {
536
613
  const mapped = await mapDeclaredError(match.route.definition, error);
537
614
  if (mapped) {
@@ -539,13 +616,13 @@ function createHttpExtensionRuntime(executions, applicationRuntime) {
539
616
  if (finalized.streamControl) {
540
617
  adoptResponseStream(finalized.streamControl);
541
618
  }
542
- return applyFrameworkHeadersToResponse(finalized.response, await safeCorsHeaders(match.route.middlewares, request));
619
+ return annotateResponse(applyFrameworkHeadersToResponse(finalized.response, await safeCorsHeaders(match.route.middlewares, request)));
543
620
  }
544
621
  }
545
622
  catch {
546
623
  // 内部のmapping/finalization errorをclientへ公開しない。
547
624
  }
548
- return applyFrameworkHeadersToResponse(Response.json({ error: 'Internal Server Error' }, { status: 500 }), await safeCorsHeaders(match.route.middlewares, request));
625
+ return annotateResponse(applyFrameworkHeadersToResponse(Response.json({ error: 'Internal Server Error' }, { status: 500 }), await safeCorsHeaders(match.route.middlewares, request)));
549
626
  }
550
627
  finally {
551
628
  if (!executionOwnedByStream)
@@ -595,7 +672,16 @@ async function createHttpContext(request, url, rawParams, route, signal) {
595
672
  ? await validateRequestHeaders(definition.headers, definition.body !== undefined, request.headers)
596
673
  : Object.fromEntries(request.headers.entries());
597
674
  const body = definition?.body ? request.body : undefined;
598
- const response = Object.fromEntries(Object.keys(route.definition.responses).map((name) => [
675
+ const response = createHttpResponseHelpers(route.definition.responses);
676
+ return {
677
+ request,
678
+ input: { params, query, headers, body },
679
+ response,
680
+ signal,
681
+ };
682
+ }
683
+ function createHttpResponseHelpers(responses) {
684
+ return Object.fromEntries(Object.keys(responses).map((name) => [
599
685
  name,
600
686
  (value = {}) => ({
601
687
  kind: 'http-result',
@@ -604,12 +690,40 @@ async function createHttpContext(request, url, rawParams, route, signal) {
604
690
  ...(value.headers === undefined ? {} : { headers: value.headers }),
605
691
  }),
606
692
  ]));
607
- return {
608
- request,
609
- input: { params, query, headers, body },
610
- response,
611
- signal,
612
- };
693
+ }
694
+ async function replayHttpHandler(applicationRuntime, handler, match, input, state) {
695
+ if (typeof input !== 'object' || input === null || Array.isArray(input)) {
696
+ throw new TypeError('LUTRE_DEVTOOLS_HTTP_HANDLER_INPUT_REQUIRED');
697
+ }
698
+ const lease = applicationRuntime.beginExecution({
699
+ executionId: match.executionId,
700
+ executionKind: 'http.handler',
701
+ graphNodeId: match.executionId,
702
+ name: `${match.executionId}.${match.route.name}`,
703
+ });
704
+ const invoke = () => handler({
705
+ input,
706
+ response: createHttpResponseHelpers(match.route.definition.responses),
707
+ signal: lease.signal,
708
+ state,
709
+ });
710
+ let result;
711
+ let hasResult = false;
712
+ try {
713
+ result = await (lease.run ? lease.run(invoke) : invoke());
714
+ hasResult = true;
715
+ return result;
716
+ }
717
+ catch (error) {
718
+ lease.fail?.(error);
719
+ throw error;
720
+ }
721
+ finally {
722
+ if (hasResult)
723
+ lease.complete(result);
724
+ else
725
+ lease.complete();
726
+ }
613
727
  }
614
728
  async function finalizeHttpResult(route, result, signal, completeExecution) {
615
729
  const response = route.responses[result.response];
@@ -97,8 +97,13 @@ function createMessagePortRuntime(executions, applicationRuntime) {
97
97
  }, () => execution.compiled.factory());
98
98
  for (const [method, definition] of Object.entries(execution.compiled.routes)) {
99
99
  const handler = handlers[method];
100
- if (handler)
101
- routes.set(method, { route: definition, handler });
100
+ if (handler) {
101
+ routes.set(method, {
102
+ executionId: execution.id,
103
+ route: definition,
104
+ handler,
105
+ });
106
+ }
102
107
  }
103
108
  }
104
109
  return {
@@ -114,7 +119,12 @@ function createMessagePortRuntime(executions, applicationRuntime) {
114
119
  }
115
120
  let lease;
116
121
  try {
117
- lease = applicationRuntime.beginExecution();
122
+ lease = applicationRuntime.beginExecution({
123
+ executionId: route.executionId,
124
+ executionKind: 'message-port.invocation',
125
+ graphNodeId: route.executionId,
126
+ name: method,
127
+ });
118
128
  }
119
129
  catch (error) {
120
130
  completePendingIngress();
@@ -133,11 +143,12 @@ function createMessagePortRuntime(executions, applicationRuntime) {
133
143
  value: result,
134
144
  }),
135
145
  ]));
136
- const result = await route.handler({
146
+ const invoke = () => route.handler({
137
147
  input: value,
138
148
  response,
139
149
  signal: lease.signal,
140
150
  });
151
+ const result = await (lease.run ? lease.run(invoke) : invoke());
141
152
  const schema = route.route.responses[result.response];
142
153
  if (!schema) {
143
154
  throw new Error(`LUTRE_MESSAGE_PORT_RESPONSE_UNDECLARED: ${result.response}`);
@@ -155,6 +166,10 @@ function createMessagePortRuntime(executions, applicationRuntime) {
155
166
  value: await validateSchema(schema, result.value),
156
167
  };
157
168
  }
169
+ catch (error) {
170
+ lease.fail?.(error);
171
+ throw error;
172
+ }
158
173
  finally {
159
174
  if (!executionOwnedByStream)
160
175
  lease.complete();
@@ -290,6 +305,7 @@ function createLeasedMessagePortStream(schema, source, lease, activeStreams) {
290
305
  else
291
306
  lease.signal.addEventListener('abort', onAbort, { once: true });
292
307
  const closeAfterError = async (error) => {
308
+ lease.fail?.(error);
293
309
  let cleanupError;
294
310
  try {
295
311
  await startIteratorCleanup(error);
@@ -3,8 +3,12 @@ import { Logger } from './logger.js';
3
3
  export declare class DependencyResolutionError extends Error {
4
4
  constructor(message: string);
5
5
  }
6
+ export interface ContainerHooks {
7
+ created?(provider: ProviderDescriptor, value: unknown): void;
8
+ }
6
9
  export interface ContainerOptions {
7
10
  readonly logger?: Logger;
11
+ readonly hooks?: ContainerHooks;
8
12
  readonly environment?: ReadonlyMap<EnvClass, object>;
9
13
  readonly arguments?: ReadonlyMap<ArgsClass, object>;
10
14
  }
@@ -10,11 +10,13 @@ export class Container {
10
10
  #providers = new Map();
11
11
  #applicationCache = new Map();
12
12
  #logger;
13
+ #hooks;
13
14
  #environment = new Map();
14
15
  #arguments = new Map();
15
16
  constructor(providers, options = {}) {
16
17
  this.#logger =
17
18
  options instanceof Logger ? options : (options.logger ?? new Logger());
19
+ this.#hooks = options instanceof Logger ? {} : (options.hooks ?? {});
18
20
  if (!(options instanceof Logger)) {
19
21
  for (const [environment, value] of options.environment ?? []) {
20
22
  this.#environment.set(environment, value);
@@ -132,8 +134,10 @@ export class Container {
132
134
  #create(provider, lineage) {
133
135
  try {
134
136
  switch (provider.kind) {
135
- case 'value':
137
+ case 'value': {
138
+ this.#hooks.created?.(provider, provider.useValue);
136
139
  return provider.useValue;
140
+ }
137
141
  case 'environment': {
138
142
  if (this.#environment.has(provider.provide)) {
139
143
  return this.#environment.get(provider.provide);
@@ -146,14 +150,18 @@ export class Container {
146
150
  }
147
151
  throw new DependencyResolutionError(`LUTRE_ARGS_005: Arguments ${provider.provide.name} requires runtime Arguments before Application initialization.`);
148
152
  }
149
- case 'class':
150
- return this.#instantiate(provider.useClass, lineage);
153
+ case 'class': {
154
+ const value = this.#instantiate(provider.useClass, lineage);
155
+ this.#hooks.created?.(provider, value);
156
+ return value;
157
+ }
151
158
  case 'factory': {
152
159
  const dependencies = provider.inject.map((token) => this.#resolve(token, tokenName(provider.provide), lineage));
153
160
  const value = provider.useFactory(...dependencies);
154
161
  if (isThenable(value)) {
155
162
  throw new DependencyResolutionError('LUTRE_DI_ASYNC_FACTORY: Async factory providers are not supported. Move asynchronous resource initialization to application lifecycle.');
156
163
  }
164
+ this.#hooks.created?.(provider, value);
157
165
  return value;
158
166
  }
159
167
  case 'conditional': {
@@ -163,7 +171,9 @@ export class Container {
163
171
  if (!implementation) {
164
172
  throw new DependencyResolutionError(`No conditional Provider matches ${provider.select.key}=${String(selected)}`);
165
173
  }
166
- return this.#instantiate(implementation, lineage);
174
+ const value = this.#instantiate(implementation, lineage);
175
+ this.#hooks.created?.(provider, value);
176
+ return value;
167
177
  }
168
178
  }
169
179
  }
@@ -1,4 +1,4 @@
1
- import { RuntimeCapabilityRegistry, type ApplicationModel, type ExecutionExtension, type ExecutionExtensionRuntime, type ExecutionKernelRuntime, type ExecutionLease, type RuntimeCapabilityBinding, type TokenLike } from '../core/index.js';
1
+ import { RuntimeCapabilityRegistry, type ApplicationModel, type ExecutionExtension, type ExecutionExtensionRuntime, type ExecutionKernelRuntime, type ExecutionLease, type ExecutionOperationLease, type RuntimeCapabilityBinding, type RuntimeExecutionMetadata, type RuntimeInstrumentation, type RuntimeInvocationRegistration, type RuntimeOperationMetadata, type TokenLike } from '../core/index.js';
2
2
  import { Container } from './di.js';
3
3
  import { Logger } from './logger.js';
4
4
  export interface ApplicationKernelRuntimeOptions {
@@ -7,6 +7,7 @@ export interface ApplicationKernelRuntimeOptions {
7
7
  readonly environmentSource?: unknown;
8
8
  readonly argumentsSource?: unknown;
9
9
  readonly forceShutdownTimeoutMs?: number;
10
+ readonly instrumentation?: RuntimeInstrumentation;
10
11
  }
11
12
  export declare class ApplicationKernelRuntime implements ExecutionKernelRuntime {
12
13
  #private;
@@ -18,6 +19,7 @@ export declare class ApplicationKernelRuntime implements ExecutionKernelRuntime
18
19
  resolve<TValue>(token: TokenLike<TValue>, source?: string): TValue;
19
20
  get<TValue>(token: TokenLike<TValue>): TValue;
20
21
  extensionRuntime<TRuntime extends ExecutionExtensionRuntime>(extension: ExecutionExtension<any, any, any, any, TRuntime>): TRuntime;
21
- beginExecution(): ExecutionLease;
22
+ beginExecution(metadata?: RuntimeExecutionMetadata, invocation?: RuntimeInvocationRegistration): ExecutionLease;
23
+ beginOperation(metadata: RuntimeOperationMetadata, invocation?: RuntimeInvocationRegistration): ExecutionOperationLease;
22
24
  shutdown(signal?: string): Promise<void>;
23
25
  }