@jangts/agent-core 0.3.5 → 0.3.6

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 (97) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +28 -26
  3. package/development/docs/api/README.en.md +2 -0
  4. package/development/docs/api/README.md +2 -0
  5. package/development/docs/api/observability.en.md +37 -11
  6. package/development/docs/api/observability.md +64 -11
  7. package/development/docs/api/reference.en.md +469 -348
  8. package/development/docs/api/reference.md +193 -137
  9. package/development/docs/api/types.en.md +1 -0
  10. package/development/docs/api/types.md +1 -0
  11. package/development/docs/api/workflow-views.en.md +64 -0
  12. package/development/docs/api/workflow-views.md +78 -0
  13. package/development/docs/api/workflow.en.md +6 -2
  14. package/development/docs/api/workflow.md +6 -2
  15. package/development/skills/agent-core-app/SKILL.md +12 -0
  16. package/dist/cjs/capabilities/invocation.js +21 -1
  17. package/dist/cjs/capabilities/tool-runtime.js +8 -1
  18. package/dist/cjs/capabilities/tools.js +12 -17
  19. package/dist/cjs/diagnostics/index.js +51 -3
  20. package/dist/cjs/diagnostics/native-sub-flow.js +106 -0
  21. package/dist/cjs/diagnostics/sub-flow.js +278 -32
  22. package/dist/cjs/execution/engine.js +3 -2
  23. package/dist/cjs/execution/events.js +5 -5
  24. package/dist/cjs/execution/reporting.js +18 -28
  25. package/dist/cjs/execution/workflow-chain.js +211 -0
  26. package/dist/cjs/execution/workflow-graph.js +72 -0
  27. package/dist/cjs/execution/workflow.js +34 -6
  28. package/dist/cjs/kits/aggregation.js +17 -14
  29. package/dist/cjs/kits/answering/checks.js +2 -1
  30. package/dist/cjs/kits/answering/flow.js +24 -21
  31. package/dist/cjs/kits/answering/tasks.js +25 -20
  32. package/dist/cjs/kits/delivery.js +36 -24
  33. package/dist/cjs/kits/knowledge/catalog.js +33 -30
  34. package/dist/cjs/kits/policies.js +3 -2
  35. package/dist/cjs/kits/presentation/outputs.js +2 -1
  36. package/dist/cjs/kits/retrieval.js +7 -1
  37. package/dist/cjs/kits/tools.js +1 -0
  38. package/dist/cjs/model/decision-retry.js +2 -1
  39. package/dist/cjs/model/runner.js +20 -5
  40. package/dist/cjs/structs/execution/workflow-views.js +2 -0
  41. package/dist/cjs/support/context/nodes.js +48 -45
  42. package/dist/cjs/support/context/processing.js +6 -3
  43. package/dist/cjs/utils/invocation.js +1 -0
  44. package/dist/esm/capabilities/invocation.js +21 -1
  45. package/dist/esm/capabilities/tool-runtime.js +8 -1
  46. package/dist/esm/capabilities/tools.js +12 -17
  47. package/dist/esm/diagnostics/index.d.ts +1 -0
  48. package/dist/esm/diagnostics/index.js +48 -2
  49. package/dist/esm/diagnostics/native-sub-flow.d.ts +94 -0
  50. package/dist/esm/diagnostics/native-sub-flow.js +101 -0
  51. package/dist/esm/diagnostics/sub-flow.d.ts +56 -4
  52. package/dist/esm/diagnostics/sub-flow.js +271 -32
  53. package/dist/esm/execution/engine.d.ts +1 -0
  54. package/dist/esm/execution/engine.js +3 -2
  55. package/dist/esm/execution/events.js +5 -5
  56. package/dist/esm/execution/reporting.d.ts +6 -12
  57. package/dist/esm/execution/reporting.js +19 -29
  58. package/dist/esm/execution/workflow-chain.d.ts +3 -0
  59. package/dist/esm/execution/workflow-chain.js +208 -0
  60. package/dist/esm/execution/workflow-graph.d.ts +7 -0
  61. package/dist/esm/execution/workflow-graph.js +68 -0
  62. package/dist/esm/execution/workflow.d.ts +6 -0
  63. package/dist/esm/execution/workflow.js +34 -6
  64. package/dist/esm/kits/aggregation.d.ts +1 -1
  65. package/dist/esm/kits/aggregation.js +17 -14
  66. package/dist/esm/kits/answering/checks.js +2 -1
  67. package/dist/esm/kits/answering/flow.js +24 -21
  68. package/dist/esm/kits/answering/tasks.js +25 -20
  69. package/dist/esm/kits/delivery.d.ts +0 -9
  70. package/dist/esm/kits/delivery.js +36 -24
  71. package/dist/esm/kits/knowledge/catalog.js +33 -30
  72. package/dist/esm/kits/policies.d.ts +1 -1
  73. package/dist/esm/kits/policies.js +3 -2
  74. package/dist/esm/kits/presentation/outputs.js +2 -1
  75. package/dist/esm/kits/retrieval.js +7 -1
  76. package/dist/esm/kits/tools.js +1 -0
  77. package/dist/esm/model/decision-retry.d.ts +2 -0
  78. package/dist/esm/model/decision-retry.js +2 -1
  79. package/dist/esm/model/runner.d.ts +2 -0
  80. package/dist/esm/model/runner.js +20 -5
  81. package/dist/esm/structs/capabilities/invocation.d.ts +2 -0
  82. package/dist/esm/structs/capabilities/tools.d.ts +7 -3
  83. package/dist/esm/structs/common.d.ts +2 -0
  84. package/dist/esm/structs/debug.d.ts +36 -20
  85. package/dist/esm/structs/execution/workflow-views.d.ts +123 -0
  86. package/dist/esm/structs/execution/workflow-views.js +1 -0
  87. package/dist/esm/structs/execution/workflow.d.ts +4 -3
  88. package/dist/esm/structs/index.d.ts +1 -0
  89. package/dist/esm/structs/model/runtime.d.ts +2 -0
  90. package/dist/esm/support/context/nodes.js +48 -45
  91. package/dist/esm/support/context/processing.js +6 -3
  92. package/dist/esm/utils/invocation.d.ts +1 -0
  93. package/dist/esm/utils/invocation.js +1 -0
  94. package/package.json +1 -1
  95. package/dist/cjs/utils/debug.js +0 -30
  96. package/dist/esm/utils/debug.d.ts +0 -27
  97. package/dist/esm/utils/debug.js +0 -27
@@ -17,6 +17,7 @@ import { payloadSnapshot } from './sub-flow.js';
17
17
  import { breakWhile } from '../utils/rules.js';
18
18
  export * from '../structs/diagnostics.js';
19
19
  export * from './catalog.js';
20
+ export { SubFlowLogger, ScopedSubFlowLogger } from './sub-flow.js';
20
21
  export { reportedStepStatusCatalog, reportedStepStatuses } from '../structs/debug.js';
21
22
  /**
22
23
  * Configure the optional log consumer of the shared execution fact source.
@@ -107,7 +108,7 @@ export function normalizeDiagnosticEvent(input) {
107
108
  // The count and size bounds match what the sub-flow logger enforces, so a record produced by
108
109
  // Core can never be rejected here; only hand-edited or foreign records can.
109
110
  if (!Array.isArray(steps) ||
110
- steps.length > 256 ||
111
+ steps.length > 1024 ||
111
112
  new Set(steps.map((step) => step?.stepId)).size !== steps.length ||
112
113
  steps.some((step) => !step ||
113
114
  step.origin !== 'reported' ||
@@ -118,7 +119,15 @@ export function normalizeDiagnosticEvent(input) {
118
119
  !Number.isSafeInteger(step.sequence) ||
119
120
  step.sequence < 1 ||
120
121
  (step.status !== undefined && !reportedStepStatuses.includes(step.status)) ||
121
- ['parentStepId', 'relatedDefinitionId', 'caseId', 'summary'].some((key) => step[key] !== undefined && typeof step[key] !== 'string') ||
122
+ [
123
+ 'type',
124
+ 'subnodeId',
125
+ 'parentStepId',
126
+ 'relatedDefinitionId',
127
+ 'relatedInvocationId',
128
+ 'caseId',
129
+ 'summary',
130
+ ].some((key) => step[key] !== undefined && typeof step[key] !== 'string') ||
122
131
  (step.usedModel !== undefined && typeof step.usedModel !== 'boolean') ||
123
132
  (step.revision !== undefined &&
124
133
  (!Number.isSafeInteger(step.revision) ||
@@ -133,6 +142,37 @@ export function normalizeDiagnosticEvent(input) {
133
142
  (!Number.isSafeInteger(raw.subStepsDropped) || Number(raw.subStepsDropped) < 0)) ||
134
143
  (raw.subStepsTruncated !== undefined && typeof raw.subStepsTruncated !== 'boolean'))
135
144
  throw new TypeError('Invalid reported diagnostic steps');
145
+ const originals = new Map();
146
+ let lastSequence = 0;
147
+ for (const step of steps) {
148
+ if (step.operation === undefined)
149
+ continue; // Historical projected snapshots remain readable.
150
+ breakWhile(!['write', 'fix'].includes(step.operation) || step.sequence <= lastSequence, () => new TypeError('Invalid sub-flow record order'));
151
+ lastSequence = step.sequence;
152
+ if (step.operation === 'write') {
153
+ breakWhile(step.targetStepId !== undefined || step.revision !== 1, () => new TypeError('Invalid sub-flow write record'));
154
+ originals.set(step.stepId, {
155
+ revision: 1,
156
+ subnodeId: step.subnodeId,
157
+ type: step.type,
158
+ relatedInvocationId: step.relatedInvocationId,
159
+ });
160
+ }
161
+ else {
162
+ const previous = originals.get(step.targetStepId);
163
+ breakWhile(previous === undefined ||
164
+ step.revision !== previous.revision + 1 ||
165
+ step.subnodeId !== previous.subnodeId ||
166
+ step.type !== previous.type ||
167
+ step.relatedInvocationId !== previous.relatedInvocationId, () => new TypeError('Invalid sub-flow fix reference'));
168
+ originals.set(step.targetStepId, {
169
+ revision: step.revision,
170
+ subnodeId: step.subnodeId,
171
+ type: step.type,
172
+ relatedInvocationId: step.relatedInvocationId,
173
+ });
174
+ }
175
+ }
136
176
  // Structural check only: the returned snapshot is discarded because the clone below already
137
177
  // produces the detached copy kept by the normalized record.
138
178
  for (const step of steps)
@@ -145,8 +185,14 @@ export function normalizeDiagnosticEvent(input) {
145
185
  breakWhile(progress !== undefined &&
146
186
  (!progress ||
147
187
  !['write', 'fix'].includes(progress.operation) ||
188
+ ['type', 'subnodeId', 'relatedInvocationId'].some((key) => progress[key] !== undefined &&
189
+ typeof progress[key] !== 'string') ||
148
190
  typeof progress.stepId !== 'string' ||
149
191
  !progress.stepId ||
192
+ (progress.targetStepId !== undefined &&
193
+ (progress.operation !== 'fix' ||
194
+ typeof progress.targetStepId !== 'string' ||
195
+ !progress.targetStepId)) ||
150
196
  !Number.isSafeInteger(progress.sequence) ||
151
197
  progress.sequence < 1 ||
152
198
  !Number.isSafeInteger(progress.revision) ||
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Optional fixed sub-flow records for native execution boundaries.
3
+ *
4
+ * Callers choose the logger explicitly. A full logger issues a scoped delegate for this call; already-scoped Kit contexts reuse
5
+ * their delegate. Neither path creates storage or changes execution and cancellation.
6
+ * Logging failures are isolated from the wrapped operation.
7
+ *
8
+ * Exports: nativeSubFlowCatalog, nativeSubFlowSync, nativeSubFlowAsync.
9
+ */
10
+ import type { SubFlowLog, ScopedSubFlowLogger } from '../structs/debug.js';
11
+ /** Fixed metadata shared by native producers; pure getters and formatters are not producers. */
12
+ export declare const nativeSubFlowCatalog: {
13
+ readonly model: {
14
+ readonly name: "Model call";
15
+ readonly kind: "model";
16
+ readonly type: "model.call";
17
+ };
18
+ readonly tool: {
19
+ readonly name: "Tool call";
20
+ readonly kind: "tool";
21
+ readonly type: "tool.call";
22
+ };
23
+ readonly invocation: {
24
+ readonly name: "Invocation";
25
+ readonly kind: "invocation";
26
+ readonly type: "handler.call";
27
+ };
28
+ readonly retrieval: {
29
+ readonly name: "Retrieval";
30
+ readonly kind: "retrieval";
31
+ readonly type: "retrieval.run";
32
+ };
33
+ readonly task: {
34
+ readonly name: "Read answer evidence";
35
+ readonly kind: "retrieval";
36
+ readonly type: "evidence.read";
37
+ };
38
+ readonly check: {
39
+ readonly name: "Check answer";
40
+ readonly kind: "validation";
41
+ readonly type: "answer.check";
42
+ };
43
+ readonly output: {
44
+ readonly name: "Compose output";
45
+ readonly kind: "presentation";
46
+ readonly type: "output.compose";
47
+ };
48
+ readonly answer: {
49
+ readonly name: "Answer flow";
50
+ readonly kind: "answering";
51
+ readonly type: "answer.run";
52
+ };
53
+ readonly retry: {
54
+ readonly name: "Retry model proposal";
55
+ readonly kind: "recovery";
56
+ readonly type: "model.retry";
57
+ };
58
+ readonly context: {
59
+ readonly name: "Process context";
60
+ readonly kind: "context";
61
+ readonly type: "context.process";
62
+ };
63
+ readonly recovery: {
64
+ readonly name: "Recovery attempt";
65
+ readonly kind: "recovery";
66
+ readonly type: "recovery.try";
67
+ };
68
+ readonly delivery: {
69
+ readonly name: "Deliver result";
70
+ readonly kind: "delivery";
71
+ readonly type: "delivery.run";
72
+ };
73
+ readonly aggregation: {
74
+ readonly name: "Aggregate queries";
75
+ readonly kind: "retrieval";
76
+ readonly type: "queries.collect";
77
+ };
78
+ readonly knowledge: {
79
+ readonly name: "Read knowledge";
80
+ readonly kind: "retrieval";
81
+ readonly type: "knowledge.read";
82
+ };
83
+ };
84
+ type Producer = keyof typeof nativeSubFlowCatalog;
85
+ type Context = {
86
+ readonly logger?: SubFlowLog;
87
+ readonly signal?: AbortSignal;
88
+ readonly invocationId?: string;
89
+ };
90
+ /** Preserve a synchronous boundary while pairing an optional write with one result revision. */
91
+ export declare function nativeSubFlowSync<Value>(context: Context, producer: Producer, id: string, invoke: (logger?: ScopedSubFlowLogger) => Value): Value;
92
+ /** Await the original operation without introducing another timeout or cancellation race. */
93
+ export declare function nativeSubFlowAsync<Value>(context: Context, producer: Producer, id: string, invoke: (logger?: ScopedSubFlowLogger) => Value | PromiseLike<Value>): Promise<Value>;
94
+ export {};
@@ -0,0 +1,101 @@
1
+ import { SubFlowLogger, requireSubFlowLogger, bindNativeSubFlowLogger } from './sub-flow.js';
2
+ /** Fixed metadata shared by native producers; pure getters and formatters are not producers. */
3
+ export const nativeSubFlowCatalog = {
4
+ model: { name: 'Model call', kind: 'model', type: 'model.call' },
5
+ tool: { name: 'Tool call', kind: 'tool', type: 'tool.call' },
6
+ invocation: { name: 'Invocation', kind: 'invocation', type: 'handler.call' },
7
+ retrieval: { name: 'Retrieval', kind: 'retrieval', type: 'retrieval.run' },
8
+ task: { name: 'Read answer evidence', kind: 'retrieval', type: 'evidence.read' },
9
+ check: { name: 'Check answer', kind: 'validation', type: 'answer.check' },
10
+ output: { name: 'Compose output', kind: 'presentation', type: 'output.compose' },
11
+ answer: { name: 'Answer flow', kind: 'answering', type: 'answer.run' },
12
+ retry: { name: 'Retry model proposal', kind: 'recovery', type: 'model.retry' },
13
+ context: { name: 'Process context', kind: 'context', type: 'context.process' },
14
+ recovery: { name: 'Recovery attempt', kind: 'recovery', type: 'recovery.try' },
15
+ delivery: { name: 'Deliver result', kind: 'delivery', type: 'delivery.run' },
16
+ aggregation: { name: 'Aggregate queries', kind: 'retrieval', type: 'queries.collect' },
17
+ knowledge: { name: 'Read knowledge', kind: 'retrieval', type: 'knowledge.read' },
18
+ };
19
+ /** Start one fixed record; its revision is best-effort and never controls the operation. */
20
+ function begin(context, producer, id) {
21
+ let logger;
22
+ try {
23
+ logger =
24
+ context.logger instanceof SubFlowLogger
25
+ ? bindNativeSubFlowLogger(context.logger, producer, id)
26
+ : context.logger;
27
+ }
28
+ catch {
29
+ /* A recording limit must not turn a valid operation into a failure. */
30
+ }
31
+ let step = -1;
32
+ try {
33
+ if (logger)
34
+ step = logger.write({
35
+ ...nativeSubFlowCatalog[producer],
36
+ relatedDefinitionId: id,
37
+ ...(context.invocationId === undefined
38
+ ? {}
39
+ : { relatedInvocationId: context.invocationId }),
40
+ status: 'running',
41
+ });
42
+ }
43
+ catch {
44
+ /* Optional recording must not change execution. */
45
+ }
46
+ return {
47
+ logger,
48
+ finish: (status) => {
49
+ try {
50
+ if (logger && step !== -1)
51
+ logger.fix(step, { status });
52
+ }
53
+ catch {
54
+ /* A broken or detached logger cannot replace the operation result. */
55
+ }
56
+ },
57
+ };
58
+ }
59
+ /** Signal access is diagnostic metadata and cannot replace an operation failure. */
60
+ function failureStatus(context) {
61
+ try {
62
+ return context.signal?.aborted ? 'cancelled' : 'error';
63
+ }
64
+ catch {
65
+ return 'error';
66
+ }
67
+ }
68
+ /** Preserve a synchronous boundary while pairing an optional write with one result revision. */
69
+ export function nativeSubFlowSync(context, producer, id, invoke) {
70
+ if (producer === 'model' || producer === 'tool' || producer === 'invocation')
71
+ requireSubFlowLogger(context.logger);
72
+ if (!context.logger)
73
+ return invoke();
74
+ const { logger, finish } = begin(context, producer, id);
75
+ try {
76
+ const value = invoke(logger);
77
+ finish('success');
78
+ return value;
79
+ }
80
+ catch (error) {
81
+ finish(failureStatus(context));
82
+ throw error;
83
+ }
84
+ }
85
+ /** Await the original operation without introducing another timeout or cancellation race. */
86
+ export async function nativeSubFlowAsync(context, producer, id, invoke) {
87
+ if (producer === 'model' || producer === 'tool' || producer === 'invocation')
88
+ requireSubFlowLogger(context.logger);
89
+ if (!context.logger)
90
+ return invoke();
91
+ const { logger, finish } = begin(context, producer, id);
92
+ try {
93
+ const value = await invoke(logger);
94
+ finish('success');
95
+ return value;
96
+ }
97
+ catch (error) {
98
+ finish(failureStatus(context));
99
+ throw error;
100
+ }
101
+ }
@@ -1,5 +1,12 @@
1
- import type { RecordedSubStep, SubFlowLogger, SubStepProgress, SubFlowValue } from '../structs/debug.js';
1
+ import type { RecordedSubStep, SubFlowLog, SubFlowStepInput, SubFlowStepFix, SubStepProgress, SubFlowValue } from '../structs/debug.js';
2
2
  import type { DiagnosticIdentity } from '../structs/diagnostics.js';
3
+ type Step = RecordedSubStep & Required<Pick<RecordedSubStep, 'createdAtMs' | 'revision' | 'status'>>;
4
+ /** Validate a committed snapshot without consulting its logger or invoking App code. */
5
+ export declare function captureSubFlowSnapshot(steps: readonly Readonly<RecordedSubStep>[] | undefined, identity?: Readonly<DiagnosticIdentity>): {
6
+ subSteps: readonly Readonly<RecordedSubStep>[];
7
+ subStepsDropped: number;
8
+ subStepsTruncated: boolean;
9
+ };
3
10
  /**
4
11
  * Validate and deep-copy a reported payload.
5
12
  *
@@ -14,6 +21,48 @@ import type { DiagnosticIdentity } from '../structs/diagnostics.js';
14
21
  * limits below.
15
22
  */
16
23
  export declare function payloadSnapshot(input: unknown): Readonly<Record<string, SubFlowValue>>;
24
+ /** Stable diagnostic reasons; untrusted error text and caller payloads never reach the console. */
25
+ declare const rejectionReasons: {
26
+ readonly inactive: "logger is detached or execution is cancelled";
27
+ readonly scope: "target does not belong to this subnode";
28
+ readonly target: "original write record was not found";
29
+ readonly fields: "input contains a forbidden field";
30
+ readonly transition: "status transition is not allowed";
31
+ readonly sealed: "an established fact cannot be overwritten";
32
+ readonly limit: "recording limit exceeded";
33
+ readonly input: "invalid input or result patch";
34
+ };
35
+ type RejectionReason = keyof typeof rejectionReasons;
36
+ /** Unexported issuance token prevents constructing counterfeit full or scoped loggers. */
37
+ declare const loggerToken: unique symbol;
38
+ type Store = SubFlowLog & {
39
+ owns(stepId: string | -1, subnodeId: string): boolean;
40
+ isActive(): boolean;
41
+ nextNativeSubnodeId(kind: string, definitionId: string): string;
42
+ warn(operation: 'write' | 'fix', reason: RejectionReason): void;
43
+ };
44
+ /** Full execution-owned recorder. Owns its store and may issue restricted delegates. */
45
+ export declare class SubFlowLogger implements SubFlowLog {
46
+ #private;
47
+ constructor(token: typeof loggerToken, store: Store);
48
+ write(input: SubFlowStepInput): string | -1;
49
+ fix(stepId: string | -1, patch: SubFlowStepFix): boolean;
50
+ readAll(): readonly Readonly<RecordedSubStep>[];
51
+ /** Issue a delegate for an App-owned logical group; no execution or scheduling is implied. */
52
+ fork(subnodeId: string): ScopedSubFlowLogger;
53
+ }
54
+ /** Non-inheriting delegate. Stores only the original logger and its bound subnode identity. */
55
+ export declare class ScopedSubFlowLogger implements SubFlowLog {
56
+ #private;
57
+ constructor(token: typeof loggerToken, logger: SubFlowLogger, subnodeId: string);
58
+ write(input: Omit<SubFlowStepInput, 'subnodeId'>): string | -1;
59
+ fix(stepId: string | -1, patch: SubFlowStepFix): boolean;
60
+ readAll(): readonly Readonly<RecordedSubStep>[];
61
+ }
62
+ /** Runtime check complements nominal invocation types; scoped or forged inputs cannot invoke. */
63
+ export declare function requireSubFlowLogger(logger: unknown): asserts logger is SubFlowLogger | undefined;
64
+ /** Allocate a short node-local group; the owning node visit already supplies the namespace. */
65
+ export declare function bindNativeSubFlowLogger(logger: SubFlowLogger, kind: string, definitionId: string): ScopedSubFlowLogger;
17
66
  /**
18
67
  * Create a logger bound to one active execution visit.
19
68
  *
@@ -22,14 +71,14 @@ export declare function payloadSnapshot(input: unknown): Readonly<Record<string,
22
71
  *
23
72
  * @param owner Object that owns the visit. `readSubFlowLogger` compares this identity before
24
73
  * returning any step.
25
- * @param active Reports whether the visit is still open; a closed logger rejects writes.
74
+ * @param active Reports whether the visit is still open; a detached logger returns write=-1 and fix=false.
26
75
  * @param content Reports whether content-level detail is enabled. When false, summaries and
27
76
  * payloads are dropped before anything is stored.
28
- * @param changed Called after each accepted write or fix with the progress delta to publish.
77
+ * @param changed Runtime receiver called after each accepted write/fix with its delta and immutable snapshot.
29
78
  * @param identity Diagnostic run and span the logger belongs to; used to reject cross-scope reads.
30
79
  * @returns A frozen logger instance.
31
80
  */
32
- export declare function createSubFlowLogger(owner: object, active: () => boolean, content: () => boolean, changed: (logger: SubFlowLogger, progress: SubStepProgress) => void, identity?: Readonly<DiagnosticIdentity>): SubFlowLogger;
81
+ export declare function createSubFlowLogger(owner: object, active: () => boolean, content: () => boolean, changed: (logger: SubFlowLogger, progress: SubStepProgress, steps: readonly Step[]) => void, identity?: Readonly<DiagnosticIdentity>): SubFlowLogger;
33
82
  /**
34
83
  * Read the steps recorded by a logger issued by this module.
35
84
  *
@@ -44,3 +93,6 @@ export declare function createSubFlowLogger(owner: object, active: () => boolean
44
93
  * belongs to another diagnostic scope.
45
94
  */
46
95
  export declare function readSubFlowLogger(input: unknown, owner?: object, identity?: Readonly<DiagnosticIdentity>): readonly Readonly<RecordedSubStep>[];
96
+ /** Release execution callbacks while preserving the instance's immutable query history. */
97
+ export declare function detachSubFlowLogger(logger: SubFlowLogger): void;
98
+ export {};