@threadplane/chat 0.0.46

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,1002 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, ChangeDetectionStrategy, Component, computed, signal, HostListener, inject, ElementRef, effect, afterNextRender } from '@angular/core';
3
+ import { JsonPipe } from '@angular/common';
4
+
5
+ // SPDX-License-Identifier: MIT
6
+ /**
7
+ * Component-scoped CSS variables for the chat-debug devtools chrome.
8
+ *
9
+ * Imported into every chat-debug component / primitive's `styles` array
10
+ * so the defaults are set on each `:host` element. Hosts override by
11
+ * setting any token on `chat-debug` or any ancestor.
12
+ *
13
+ * Independent from `--ngaf-chat-*` (the chat library's theme tokens).
14
+ * Devtools chrome stays dark regardless of host theme by default —
15
+ * matches Chrome DevTools / React DevTools / Redux DevTools convention.
16
+ *
17
+ * Palette anchor: shadcn zinc-900 + accent blue.
18
+ */
19
+ const CHAT_DEBUG_TOKENS = `
20
+ :host {
21
+ --ngaf-chat-debug-bg: #18181b;
22
+ --ngaf-chat-debug-bg-deep: #09090b;
23
+ --ngaf-chat-debug-surface: #1f1f23;
24
+ --ngaf-chat-debug-border: #27272a;
25
+ --ngaf-chat-debug-border-strong: #3f3f46;
26
+ --ngaf-chat-debug-text: #fafafa;
27
+ --ngaf-chat-debug-text-muted: #a1a1aa;
28
+ --ngaf-chat-debug-text-subtle: #71717a;
29
+ --ngaf-chat-debug-accent: #4f8df5;
30
+ --ngaf-chat-debug-success: #4ade80;
31
+ --ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, 0.5);
32
+ --ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, 0.4);
33
+ --ngaf-chat-debug-radius-panel: 12px;
34
+ --ngaf-chat-debug-radius-input: 8px;
35
+ --ngaf-chat-debug-radius-pill: 999px;
36
+ --ngaf-chat-debug-font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
37
+ --ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
38
+ font-family: var(--ngaf-chat-debug-font-sans);
39
+ color: var(--ngaf-chat-debug-text);
40
+
41
+ /*
42
+ * Cascade shim: rewire the chat library's color tokens to debug
43
+ * equivalents so embedded components that consume \`--ngaf-chat-*\`
44
+ * (debug-checkpoint-card, debug-state-diff, debug-state-inspector,
45
+ * any host-projected slot content) pick up the dark devtools surface
46
+ * without each one needing its own re-skin. Geometry / font tokens
47
+ * are left alone — they're neutral.
48
+ */
49
+ --ngaf-chat-bg: var(--ngaf-chat-debug-bg);
50
+ --ngaf-chat-text: var(--ngaf-chat-debug-text);
51
+ --ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);
52
+ --ngaf-chat-separator: var(--ngaf-chat-debug-border);
53
+ --ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);
54
+ --ngaf-chat-font-size-xs: 12px;
55
+ --ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);
56
+ --ngaf-chat-radius-card: 8px;
57
+ --ngaf-chat-success: var(--ngaf-chat-debug-success);
58
+ --ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);
59
+ --ngaf-chat-error-text: #fca5a5;
60
+ --ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);
61
+ --ngaf-chat-warning-text: #fcd34d;
62
+ }
63
+ `;
64
+
65
+ // SPDX-License-Identifier: MIT
66
+ const CHAT_DEBUG_ROOT_STYLES = `
67
+ @layer ngaf-chat-debug {
68
+ :root {
69
+ --ngaf-chat-sidebar-claim-right: 0px;
70
+ --ngaf-chat-debug-panel-size-h: 40vh;
71
+ --ngaf-chat-debug-panel-size-w: 420px;
72
+ }
73
+ :root[data-threadplane-chat-debug="bottom"] {
74
+ --ngaf-chat-debug-claim-bottom: var(--ngaf-chat-debug-panel-size-h, 40vh);
75
+ --ngaf-chat-occupy-bottom: var(--ngaf-chat-debug-panel-size-h, 40vh);
76
+ }
77
+ :root[data-threadplane-chat-debug="right"] {
78
+ --ngaf-chat-debug-claim-right: var(--ngaf-chat-debug-panel-size-w, 420px);
79
+ --ngaf-chat-occupy-right: var(--ngaf-chat-debug-panel-size-w, 420px);
80
+ }
81
+ :root[data-threadplane-chat-debug="left"] {
82
+ --ngaf-chat-debug-claim-left: var(--ngaf-chat-debug-panel-size-w, 420px);
83
+ --ngaf-chat-occupy-left: var(--ngaf-chat-debug-panel-size-w, 420px);
84
+ }
85
+ }
86
+ `;
87
+ const STYLE_ELEMENT_ID = 'ngaf-chat-debug-root-styles';
88
+ function ensureChatDebugRootStyles() {
89
+ if (typeof document === 'undefined')
90
+ return;
91
+ if (document.getElementById(STYLE_ELEMENT_ID))
92
+ return;
93
+ const style = document.createElement('style');
94
+ style.id = STYLE_ELEMENT_ID;
95
+ style.textContent = CHAT_DEBUG_ROOT_STYLES;
96
+ document.head.appendChild(style);
97
+ }
98
+
99
+ // SPDX-License-Identifier: MIT
100
+ class DebugCheckpointCardComponent {
101
+ checkpoint = input.required(...(ngDevMode ? [{ debugName: "checkpoint" }] : []));
102
+ isSelected = input(false, ...(ngDevMode ? [{ debugName: "isSelected" }] : []));
103
+ selected = output();
104
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: DebugCheckpointCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
105
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: DebugCheckpointCardComponent, isStandalone: true, selector: "chat-debug-checkpoint-card", inputs: { checkpoint: { classPropertyName: "checkpoint", publicName: "checkpoint", isSignal: true, isRequired: true, transformFunction: null }, isSelected: { classPropertyName: "isSelected", publicName: "isSelected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, ngImport: i0, template: `
106
+ <button
107
+ class="debug-checkpoint-card"
108
+ [class.debug-checkpoint-card--selected]="isSelected()"
109
+ (click)="selected.emit()"
110
+ >
111
+ <p class="debug-checkpoint-card__title">{{ checkpoint().node ?? 'Unknown' }}</p>
112
+ <div class="debug-checkpoint-card__meta">
113
+ @if (checkpoint().duration !== null && checkpoint().duration !== undefined) {
114
+ <span class="debug-checkpoint-card__badge">{{ checkpoint().duration }}ms</span>
115
+ }
116
+ @if (checkpoint().tokenCount !== null && checkpoint().tokenCount !== undefined) {
117
+ <span class="debug-checkpoint-card__badge">{{ checkpoint().tokenCount }} tok</span>
118
+ }
119
+ </div>
120
+ </button>
121
+ `, isInline: true, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ".debug-checkpoint-card{width:100%;text-align:left;border-radius:var(--ngaf-chat-radius-card);border:1px solid var(--ngaf-chat-separator);padding:8px 12px;cursor:pointer;background:var(--ngaf-chat-bg);transition:background .15s ease,border-color .15s ease}.debug-checkpoint-card:hover{background:color-mix(in srgb,var(--ngaf-chat-text) 5%,transparent)}.debug-checkpoint-card--selected{border-color:var(--ngaf-chat-text-muted);background:color-mix(in srgb,var(--ngaf-chat-text) 5%,transparent)}.debug-checkpoint-card__title{font-size:var(--ngaf-chat-font-size-xs);font-weight:500;color:var(--ngaf-chat-text);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.debug-checkpoint-card__meta{display:flex;gap:8px;margin-top:4px}.debug-checkpoint-card__badge{font-size:var(--ngaf-chat-font-size-xs);padding:2px 6px;border-radius:4px;background:var(--ngaf-chat-surface-alt);color:var(--ngaf-chat-text-muted)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
122
+ }
123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: DebugCheckpointCardComponent, decorators: [{
124
+ type: Component,
125
+ args: [{ selector: 'chat-debug-checkpoint-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
126
+ <button
127
+ class="debug-checkpoint-card"
128
+ [class.debug-checkpoint-card--selected]="isSelected()"
129
+ (click)="selected.emit()"
130
+ >
131
+ <p class="debug-checkpoint-card__title">{{ checkpoint().node ?? 'Unknown' }}</p>
132
+ <div class="debug-checkpoint-card__meta">
133
+ @if (checkpoint().duration !== null && checkpoint().duration !== undefined) {
134
+ <span class="debug-checkpoint-card__badge">{{ checkpoint().duration }}ms</span>
135
+ }
136
+ @if (checkpoint().tokenCount !== null && checkpoint().tokenCount !== undefined) {
137
+ <span class="debug-checkpoint-card__badge">{{ checkpoint().tokenCount }} tok</span>
138
+ }
139
+ </div>
140
+ </button>
141
+ `, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ".debug-checkpoint-card{width:100%;text-align:left;border-radius:var(--ngaf-chat-radius-card);border:1px solid var(--ngaf-chat-separator);padding:8px 12px;cursor:pointer;background:var(--ngaf-chat-bg);transition:background .15s ease,border-color .15s ease}.debug-checkpoint-card:hover{background:color-mix(in srgb,var(--ngaf-chat-text) 5%,transparent)}.debug-checkpoint-card--selected{border-color:var(--ngaf-chat-text-muted);background:color-mix(in srgb,var(--ngaf-chat-text) 5%,transparent)}.debug-checkpoint-card__title{font-size:var(--ngaf-chat-font-size-xs);font-weight:500;color:var(--ngaf-chat-text);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.debug-checkpoint-card__meta{display:flex;gap:8px;margin-top:4px}.debug-checkpoint-card__badge{font-size:var(--ngaf-chat-font-size-xs);padding:2px 6px;border-radius:4px;background:var(--ngaf-chat-surface-alt);color:var(--ngaf-chat-text-muted)}\n"] }]
142
+ }], propDecorators: { checkpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkpoint", required: true }] }], isSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSelected", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }] } });
143
+
144
+ // SPDX-License-Identifier: MIT
145
+ /**
146
+ * Computes a recursive diff between two state objects.
147
+ * Returns an array of DiffEntry describing added, removed, and changed keys.
148
+ */
149
+ function computeStateDiff(before, after, prefix = '') {
150
+ const entries = [];
151
+ const allKeys = new Set([...Object.keys(before), ...Object.keys(after)]);
152
+ for (const key of allKeys) {
153
+ const path = prefix ? `${prefix}.${key}` : key;
154
+ const inBefore = key in before;
155
+ const inAfter = key in after;
156
+ if (!inBefore && inAfter) {
157
+ entries.push({ path, type: 'added', after: after[key] });
158
+ }
159
+ else if (inBefore && !inAfter) {
160
+ entries.push({ path, type: 'removed', before: before[key] });
161
+ }
162
+ else {
163
+ const bVal = before[key];
164
+ const aVal = after[key];
165
+ // Recurse into nested plain objects
166
+ if (isPlainObject(bVal) && isPlainObject(aVal)) {
167
+ entries.push(...computeStateDiff(bVal, aVal, path));
168
+ }
169
+ else if (!deepEqual(bVal, aVal)) {
170
+ entries.push({ path, type: 'changed', before: bVal, after: aVal });
171
+ }
172
+ // If equal, no entry
173
+ }
174
+ }
175
+ return entries;
176
+ }
177
+ function isPlainObject(value) {
178
+ return (typeof value === 'object' &&
179
+ value !== null &&
180
+ !Array.isArray(value) &&
181
+ Object.getPrototypeOf(value) === Object.prototype);
182
+ }
183
+ function deepEqual(a, b) {
184
+ if (a === b)
185
+ return true;
186
+ if (a === null || b === null)
187
+ return false;
188
+ if (typeof a !== typeof b)
189
+ return false;
190
+ if (Array.isArray(a) && Array.isArray(b)) {
191
+ if (a.length !== b.length)
192
+ return false;
193
+ return a.every((item, i) => deepEqual(item, b[i]));
194
+ }
195
+ if (isPlainObject(a) && isPlainObject(b)) {
196
+ const aKeys = Object.keys(a);
197
+ const bKeys = Object.keys(b);
198
+ if (aKeys.length !== bKeys.length)
199
+ return false;
200
+ return aKeys.every((key) => key in b && deepEqual(a[key], b[key]));
201
+ }
202
+ return false;
203
+ }
204
+
205
+ // SPDX-License-Identifier: MIT
206
+ class DebugStateDiffComponent {
207
+ before = input({}, ...(ngDevMode ? [{ debugName: "before" }] : []));
208
+ after = input({}, ...(ngDevMode ? [{ debugName: "after" }] : []));
209
+ diffEntries = computed(() => computeStateDiff(this.before(), this.after()), ...(ngDevMode ? [{ debugName: "diffEntries" }] : []));
210
+ prefix(type) {
211
+ switch (type) {
212
+ case 'added': return '+';
213
+ case 'removed': return '-';
214
+ case 'changed': return '~';
215
+ }
216
+ }
217
+ entryClass(type) {
218
+ switch (type) {
219
+ case 'added': return 'debug-state-diff__entry--added';
220
+ case 'removed': return 'debug-state-diff__entry--removed';
221
+ case 'changed': return 'debug-state-diff__entry--changed';
222
+ }
223
+ }
224
+ /** @deprecated Use entryClass instead — kept for backward compat if any template references it */
225
+ colorClass(type) {
226
+ return this.entryClass(type);
227
+ }
228
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: DebugStateDiffComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
229
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: DebugStateDiffComponent, isStandalone: true, selector: "chat-debug-state-diff", inputs: { before: { classPropertyName: "before", publicName: "before", isSignal: true, isRequired: false, transformFunction: null }, after: { classPropertyName: "after", publicName: "after", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
230
+ @if (diffEntries().length === 0) {
231
+ <p class="debug-state-diff__empty">No changes</p>
232
+ } @else {
233
+ <div class="debug-state-diff__list">
234
+ @for (entry of diffEntries(); track entry.path) {
235
+ <div class="debug-state-diff__entry" [class]="entryClass(entry.type)">
236
+ <span class="debug-state-diff__key">{{ prefix(entry.type) }} {{ entry.path }}</span>
237
+ @if (entry.type === 'changed') {
238
+ <span class="debug-state-diff__value">{{ entry.before | json }} &rarr; {{ entry.after | json }}</span>
239
+ } @else if (entry.type === 'added') {
240
+ <span class="debug-state-diff__value">{{ entry.after | json }}</span>
241
+ } @else {
242
+ <span class="debug-state-diff__value">{{ entry.before | json }}</span>
243
+ }
244
+ </div>
245
+ }
246
+ </div>
247
+ }
248
+ `, isInline: true, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ".debug-state-diff__empty{font-size:var(--ngaf-chat-font-size-xs);color:var(--ngaf-chat-text-muted);font-style:italic;margin:0}.debug-state-diff__list{display:flex;flex-direction:column;gap:4px}.debug-state-diff__entry{font-size:var(--ngaf-chat-font-size-xs);font-family:var(--ngaf-chat-font-mono);padding:4px 8px;border-radius:4px}.debug-state-diff__entry--added{background:var(--ngaf-chat-surface-alt);color:var(--ngaf-chat-success)}.debug-state-diff__entry--removed{background:var(--ngaf-chat-error-bg);color:var(--ngaf-chat-error-text)}.debug-state-diff__entry--changed{background:var(--ngaf-chat-warning-bg);color:var(--ngaf-chat-warning-text)}.debug-state-diff__key{font-weight:600}.debug-state-diff__value{display:block;padding-left:16px;color:var(--ngaf-chat-text-muted)}\n"], dependencies: [{ kind: "pipe", type: JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
249
+ }
250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: DebugStateDiffComponent, decorators: [{
251
+ type: Component,
252
+ args: [{ selector: 'chat-debug-state-diff', standalone: true, imports: [JsonPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: `
253
+ @if (diffEntries().length === 0) {
254
+ <p class="debug-state-diff__empty">No changes</p>
255
+ } @else {
256
+ <div class="debug-state-diff__list">
257
+ @for (entry of diffEntries(); track entry.path) {
258
+ <div class="debug-state-diff__entry" [class]="entryClass(entry.type)">
259
+ <span class="debug-state-diff__key">{{ prefix(entry.type) }} {{ entry.path }}</span>
260
+ @if (entry.type === 'changed') {
261
+ <span class="debug-state-diff__value">{{ entry.before | json }} &rarr; {{ entry.after | json }}</span>
262
+ } @else if (entry.type === 'added') {
263
+ <span class="debug-state-diff__value">{{ entry.after | json }}</span>
264
+ } @else {
265
+ <span class="debug-state-diff__value">{{ entry.before | json }}</span>
266
+ }
267
+ </div>
268
+ }
269
+ </div>
270
+ }
271
+ `, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ".debug-state-diff__empty{font-size:var(--ngaf-chat-font-size-xs);color:var(--ngaf-chat-text-muted);font-style:italic;margin:0}.debug-state-diff__list{display:flex;flex-direction:column;gap:4px}.debug-state-diff__entry{font-size:var(--ngaf-chat-font-size-xs);font-family:var(--ngaf-chat-font-mono);padding:4px 8px;border-radius:4px}.debug-state-diff__entry--added{background:var(--ngaf-chat-surface-alt);color:var(--ngaf-chat-success)}.debug-state-diff__entry--removed{background:var(--ngaf-chat-error-bg);color:var(--ngaf-chat-error-text)}.debug-state-diff__entry--changed{background:var(--ngaf-chat-warning-bg);color:var(--ngaf-chat-warning-text)}.debug-state-diff__key{font-weight:600}.debug-state-diff__value{display:block;padding-left:16px;color:var(--ngaf-chat-text-muted)}\n"] }]
272
+ }], propDecorators: { before: [{ type: i0.Input, args: [{ isSignal: true, alias: "before", required: false }] }], after: [{ type: i0.Input, args: [{ isSignal: true, alias: "after", required: false }] }] } });
273
+
274
+ function toDebugCheckpoint(cp, index) {
275
+ return {
276
+ node: cp.label ?? `Step ${index + 1}`,
277
+ checkpointId: cp.id,
278
+ };
279
+ }
280
+ function extractStateValues(cp) {
281
+ return cp?.values ?? {};
282
+ }
283
+
284
+ // SPDX-License-Identifier: MIT
285
+ /**
286
+ * Pure selection-step function. Exported for unit testing — the component's
287
+ * keyboard handler delegates to it.
288
+ */
289
+ function stepSelection(dir, current, count) {
290
+ if (count === 0)
291
+ return -1;
292
+ switch (dir) {
293
+ case 'down': return Math.min(current + 1, count - 1);
294
+ case 'up': return Math.max(current - 1, 0);
295
+ case 'home': return 0;
296
+ case 'end': return count - 1;
297
+ }
298
+ }
299
+ class TimelineInspectorComponent {
300
+ agent = input.required(...(ngDevMode ? [{ debugName: "agent" }] : []));
301
+ replayRequested = output();
302
+ forkRequested = output();
303
+ selectedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : []));
304
+ checkpoints = computed(() => this.agent().history().map((cp, i) => toDebugCheckpoint(cp, i)), ...(ngDevMode ? [{ debugName: "checkpoints" }] : []));
305
+ currentStateAt(i) {
306
+ return extractStateValues(this.agent().history()[i]);
307
+ }
308
+ previousStateAt(i) {
309
+ if (i <= 0)
310
+ return {};
311
+ return extractStateValues(this.agent().history()[i - 1]);
312
+ }
313
+ onKey(ev) {
314
+ const map = {
315
+ ArrowDown: 'down',
316
+ ArrowUp: 'up',
317
+ Home: 'home',
318
+ End: 'end',
319
+ };
320
+ const dir = map[ev.key];
321
+ if (!dir)
322
+ return;
323
+ ev.preventDefault();
324
+ this.selectedIndex.set(stepSelection(dir, this.selectedIndex(), this.checkpoints().length));
325
+ }
326
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: TimelineInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
327
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: TimelineInspectorComponent, isStandalone: true, selector: "chat-debug-timeline-inspector", inputs: { agent: { classPropertyName: "agent", publicName: "agent", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { replayRequested: "replayRequested", forkRequested: "forkRequested" }, host: { listeners: { "keydown": "onKey($event)" } }, ngImport: i0, template: `
328
+ <div class="timeline__header">
329
+ <span class="timeline__count">
330
+ <span class="timeline__count-badge">{{ checkpoints().length }}</span>
331
+ <span>checkpoint{{ checkpoints().length === 1 ? '' : 's' }}</span>
332
+ </span>
333
+ <button
334
+ type="button"
335
+ class="timeline__clear"
336
+ [disabled]="selectedIndex() < 0"
337
+ (click)="selectedIndex.set(-1)"
338
+ >Clear selection</button>
339
+ </div>
340
+ <div
341
+ class="timeline__list"
342
+ tabindex="0"
343
+ role="listbox"
344
+ aria-label="Checkpoint timeline"
345
+ >
346
+ @if (checkpoints().length === 0) {
347
+ <div class="timeline__empty">No checkpoints yet. Send a message to populate the timeline.</div>
348
+ }
349
+ @for (cp of checkpoints(); let i = $index; track cp.checkpointId ?? i) {
350
+ <div class="timeline__row">
351
+ <chat-debug-checkpoint-card
352
+ [checkpoint]="cp"
353
+ [isSelected]="i === selectedIndex()"
354
+ (selected)="selectedIndex.set(i)"
355
+ />
356
+ @if (i === selectedIndex() && cp.checkpointId) {
357
+ <div class="timeline__row-actions">
358
+ <button class="row-action" type="button" (click)="replayRequested.emit(cp.checkpointId!)">Replay</button>
359
+ <button class="row-action" type="button" (click)="forkRequested.emit(cp.checkpointId!)">Fork</button>
360
+ </div>
361
+ }
362
+ @if (i === selectedIndex()) {
363
+ <div class="timeline__diff">
364
+ <chat-debug-state-diff
365
+ [before]="previousStateAt(i)"
366
+ [after]="currentStateAt(i)"
367
+ />
368
+ </div>
369
+ }
370
+ </div>
371
+ }
372
+ </div>
373
+ `, isInline: true, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ":host{display:flex;flex-direction:column;height:100%;outline:none}.timeline__header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--ngaf-chat-debug-border);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ngaf-chat-debug-text-subtle);background:var(--ngaf-chat-debug-bg)}.timeline__count{display:inline-flex;align-items:center;gap:6px}.timeline__count-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:18px;padding:0 6px;border-radius:9px;background:var(--ngaf-chat-debug-surface);border:1px solid var(--ngaf-chat-debug-border);color:var(--ngaf-chat-debug-text);font-size:11px;font-weight:500;letter-spacing:0;text-transform:none;font-variant-numeric:tabular-nums}.timeline__clear{background:transparent;border:0;cursor:pointer;color:var(--ngaf-chat-debug-text-subtle);font:inherit;font-size:11px;letter-spacing:0;text-transform:none;padding:2px 6px;border-radius:6px;transition:color .12s ease,background .12s ease}.timeline__clear:hover:not(:disabled){color:var(--ngaf-chat-debug-text);background:var(--ngaf-chat-debug-surface)}.timeline__clear:disabled{opacity:.4;cursor:default}.timeline__list{flex:1;overflow-y:auto;padding:12px 16px;display:flex;flex-direction:column;gap:8px;background:var(--ngaf-chat-debug-bg)}.timeline__empty{padding:24px 16px;text-align:center;color:var(--ngaf-chat-debug-text-subtle);font-size:13px}.timeline__row{display:flex;flex-direction:column;gap:8px}.timeline__row-actions{display:none;gap:8px;padding-left:12px}.timeline__row:hover .timeline__row-actions{display:flex}.timeline__row button.row-action{background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:6px;padding:3px 8px;font:inherit;font-size:11px;color:var(--ngaf-chat-debug-text-muted);cursor:pointer;transition:color .12s ease,border-color .12s ease}.timeline__row button.row-action:hover{color:var(--ngaf-chat-debug-text);border-color:var(--ngaf-chat-debug-border-strong)}.timeline__diff{padding:12px;background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:var(--ngaf-chat-debug-radius-input);color:var(--ngaf-chat-debug-text)}\n"], dependencies: [{ kind: "component", type: DebugCheckpointCardComponent, selector: "chat-debug-checkpoint-card", inputs: ["checkpoint", "isSelected"], outputs: ["selected"] }, { kind: "component", type: DebugStateDiffComponent, selector: "chat-debug-state-diff", inputs: ["before", "after"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
374
+ }
375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: TimelineInspectorComponent, decorators: [{
376
+ type: Component,
377
+ args: [{ selector: 'chat-debug-timeline-inspector', standalone: true, imports: [DebugCheckpointCardComponent, DebugStateDiffComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
378
+ <div class="timeline__header">
379
+ <span class="timeline__count">
380
+ <span class="timeline__count-badge">{{ checkpoints().length }}</span>
381
+ <span>checkpoint{{ checkpoints().length === 1 ? '' : 's' }}</span>
382
+ </span>
383
+ <button
384
+ type="button"
385
+ class="timeline__clear"
386
+ [disabled]="selectedIndex() < 0"
387
+ (click)="selectedIndex.set(-1)"
388
+ >Clear selection</button>
389
+ </div>
390
+ <div
391
+ class="timeline__list"
392
+ tabindex="0"
393
+ role="listbox"
394
+ aria-label="Checkpoint timeline"
395
+ >
396
+ @if (checkpoints().length === 0) {
397
+ <div class="timeline__empty">No checkpoints yet. Send a message to populate the timeline.</div>
398
+ }
399
+ @for (cp of checkpoints(); let i = $index; track cp.checkpointId ?? i) {
400
+ <div class="timeline__row">
401
+ <chat-debug-checkpoint-card
402
+ [checkpoint]="cp"
403
+ [isSelected]="i === selectedIndex()"
404
+ (selected)="selectedIndex.set(i)"
405
+ />
406
+ @if (i === selectedIndex() && cp.checkpointId) {
407
+ <div class="timeline__row-actions">
408
+ <button class="row-action" type="button" (click)="replayRequested.emit(cp.checkpointId!)">Replay</button>
409
+ <button class="row-action" type="button" (click)="forkRequested.emit(cp.checkpointId!)">Fork</button>
410
+ </div>
411
+ }
412
+ @if (i === selectedIndex()) {
413
+ <div class="timeline__diff">
414
+ <chat-debug-state-diff
415
+ [before]="previousStateAt(i)"
416
+ [after]="currentStateAt(i)"
417
+ />
418
+ </div>
419
+ }
420
+ </div>
421
+ }
422
+ </div>
423
+ `, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ":host{display:flex;flex-direction:column;height:100%;outline:none}.timeline__header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--ngaf-chat-debug-border);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ngaf-chat-debug-text-subtle);background:var(--ngaf-chat-debug-bg)}.timeline__count{display:inline-flex;align-items:center;gap:6px}.timeline__count-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:18px;padding:0 6px;border-radius:9px;background:var(--ngaf-chat-debug-surface);border:1px solid var(--ngaf-chat-debug-border);color:var(--ngaf-chat-debug-text);font-size:11px;font-weight:500;letter-spacing:0;text-transform:none;font-variant-numeric:tabular-nums}.timeline__clear{background:transparent;border:0;cursor:pointer;color:var(--ngaf-chat-debug-text-subtle);font:inherit;font-size:11px;letter-spacing:0;text-transform:none;padding:2px 6px;border-radius:6px;transition:color .12s ease,background .12s ease}.timeline__clear:hover:not(:disabled){color:var(--ngaf-chat-debug-text);background:var(--ngaf-chat-debug-surface)}.timeline__clear:disabled{opacity:.4;cursor:default}.timeline__list{flex:1;overflow-y:auto;padding:12px 16px;display:flex;flex-direction:column;gap:8px;background:var(--ngaf-chat-debug-bg)}.timeline__empty{padding:24px 16px;text-align:center;color:var(--ngaf-chat-debug-text-subtle);font-size:13px}.timeline__row{display:flex;flex-direction:column;gap:8px}.timeline__row-actions{display:none;gap:8px;padding-left:12px}.timeline__row:hover .timeline__row-actions{display:flex}.timeline__row button.row-action{background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:6px;padding:3px 8px;font:inherit;font-size:11px;color:var(--ngaf-chat-debug-text-muted);cursor:pointer;transition:color .12s ease,border-color .12s ease}.timeline__row button.row-action:hover{color:var(--ngaf-chat-debug-text);border-color:var(--ngaf-chat-debug-border-strong)}.timeline__diff{padding:12px;background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:var(--ngaf-chat-debug-radius-input);color:var(--ngaf-chat-debug-text)}\n"] }]
424
+ }], propDecorators: { agent: [{ type: i0.Input, args: [{ isSignal: true, alias: "agent", required: true }] }], replayRequested: [{ type: i0.Output, args: ["replayRequested"] }], forkRequested: [{ type: i0.Output, args: ["forkRequested"] }], onKey: [{
425
+ type: HostListener,
426
+ args: ['keydown', ['$event']]
427
+ }] } });
428
+
429
+ // SPDX-License-Identifier: MIT
430
+ class DebugStateInspectorComponent {
431
+ state = input({}, ...(ngDevMode ? [{ debugName: "state" }] : []));
432
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: DebugStateInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
433
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: DebugStateInspectorComponent, isStandalone: true, selector: "chat-debug-state-inspector", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
434
+ <div class="debug-state-inspector">
435
+ <pre class="debug-state-inspector__pre">{{ state() | json }}</pre>
436
+ </div>
437
+ `, isInline: true, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ".debug-state-inspector{overflow:auto;max-height:256px}.debug-state-inspector__pre{font-size:var(--ngaf-chat-font-size-xs);font-family:var(--ngaf-chat-font-mono);color:var(--ngaf-chat-text);white-space:pre-wrap;word-break:break-all;margin:0}\n"], dependencies: [{ kind: "pipe", type: JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
438
+ }
439
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: DebugStateInspectorComponent, decorators: [{
440
+ type: Component,
441
+ args: [{ selector: 'chat-debug-state-inspector', standalone: true, imports: [JsonPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: `
442
+ <div class="debug-state-inspector">
443
+ <pre class="debug-state-inspector__pre">{{ state() | json }}</pre>
444
+ </div>
445
+ `, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ".debug-state-inspector{overflow:auto;max-height:256px}.debug-state-inspector__pre{font-size:var(--ngaf-chat-font-size-xs);font-family:var(--ngaf-chat-font-mono);color:var(--ngaf-chat-text);white-space:pre-wrap;word-break:break-all;margin:0}\n"] }]
446
+ }], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }] } });
447
+
448
+ // SPDX-License-Identifier: MIT
449
+ class StateInspectorComponent {
450
+ agent = input.required(...(ngDevMode ? [{ debugName: "agent" }] : []));
451
+ state = computed(() => {
452
+ return this.agent().state();
453
+ }, ...(ngDevMode ? [{ debugName: "state" }] : []));
454
+ justCopied = signal(false, ...(ngDevMode ? [{ debugName: "justCopied" }] : []));
455
+ copy() {
456
+ if (typeof navigator === 'undefined' || !navigator.clipboard)
457
+ return;
458
+ void navigator.clipboard.writeText(JSON.stringify(this.state(), null, 2));
459
+ this.justCopied.set(true);
460
+ setTimeout(() => this.justCopied.set(false), 1500);
461
+ }
462
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: StateInspectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
463
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: StateInspectorComponent, isStandalone: true, selector: "chat-debug-state-tab", inputs: { agent: { classPropertyName: "agent", publicName: "agent", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
464
+ <div class="state__header">
465
+ <span>Current state</span>
466
+ <button type="button" class="state__copy" [class.is-copied]="justCopied()" (click)="copy()">
467
+ @if (justCopied()) {
468
+ <svg width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6L5 8.5L9.5 3.5"/></svg>
469
+ <span>Copied</span>
470
+ } @else {
471
+ <svg width="11" height="11" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="8" height="8" rx="1.2"/><path d="M2 9V2.5C2 2.22 2.22 2 2.5 2H9"/></svg>
472
+ <span>Copy</span>
473
+ }
474
+ </button>
475
+ </div>
476
+ <div class="state__body">
477
+ <chat-debug-state-inspector [state]="state()" />
478
+ </div>
479
+ `, isInline: true, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ":host{display:flex;flex-direction:column;height:100%;background:var(--ngaf-chat-debug-bg)}.state__header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--ngaf-chat-debug-border);background:var(--ngaf-chat-debug-bg);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ngaf-chat-debug-text-subtle)}.state__copy{display:inline-flex;align-items:center;gap:6px;background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:6px;padding:3px 8px;font:inherit;font-size:11px;letter-spacing:0;text-transform:none;color:var(--ngaf-chat-debug-text-muted);cursor:pointer;transition:color .12s ease,border-color .12s ease}.state__copy:hover{color:var(--ngaf-chat-debug-text);border-color:var(--ngaf-chat-debug-border-strong)}.state__copy.is-copied{color:var(--ngaf-chat-debug-success);border-color:var(--ngaf-chat-debug-success)}.state__copy svg{display:block}.state__body{flex:1;overflow-y:auto;padding:12px 16px;color:var(--ngaf-chat-debug-text)}\n"], dependencies: [{ kind: "component", type: DebugStateInspectorComponent, selector: "chat-debug-state-inspector", inputs: ["state"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
480
+ }
481
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: StateInspectorComponent, decorators: [{
482
+ type: Component,
483
+ args: [{ selector: 'chat-debug-state-tab', standalone: true, imports: [DebugStateInspectorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
484
+ <div class="state__header">
485
+ <span>Current state</span>
486
+ <button type="button" class="state__copy" [class.is-copied]="justCopied()" (click)="copy()">
487
+ @if (justCopied()) {
488
+ <svg width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6L5 8.5L9.5 3.5"/></svg>
489
+ <span>Copied</span>
490
+ } @else {
491
+ <svg width="11" height="11" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="8" height="8" rx="1.2"/><path d="M2 9V2.5C2 2.22 2.22 2 2.5 2H9"/></svg>
492
+ <span>Copy</span>
493
+ }
494
+ </button>
495
+ </div>
496
+ <div class="state__body">
497
+ <chat-debug-state-inspector [state]="state()" />
498
+ </div>
499
+ `, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ":host{display:flex;flex-direction:column;height:100%;background:var(--ngaf-chat-debug-bg)}.state__header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--ngaf-chat-debug-border);background:var(--ngaf-chat-debug-bg);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ngaf-chat-debug-text-subtle)}.state__copy{display:inline-flex;align-items:center;gap:6px;background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:6px;padding:3px 8px;font:inherit;font-size:11px;letter-spacing:0;text-transform:none;color:var(--ngaf-chat-debug-text-muted);cursor:pointer;transition:color .12s ease,border-color .12s ease}.state__copy:hover{color:var(--ngaf-chat-debug-text);border-color:var(--ngaf-chat-debug-border-strong)}.state__copy.is-copied{color:var(--ngaf-chat-debug-success);border-color:var(--ngaf-chat-debug-success)}.state__copy svg{display:block}.state__body{flex:1;overflow-y:auto;padding:12px 16px;color:var(--ngaf-chat-debug-text)}\n"] }]
500
+ }], propDecorators: { agent: [{ type: i0.Input, args: [{ isSignal: true, alias: "agent", required: true }] }] } });
501
+
502
+ /**
503
+ * Tiny typed localStorage wrapper namespaced under `{prefix}:`. SSR-safe:
504
+ * when `localStorage` is undefined (server build), read returns undefined
505
+ * and write is a no-op.
506
+ */
507
+ function createPersistence(prefix) {
508
+ const fullKey = (k) => `${prefix}:${k}`;
509
+ return {
510
+ read(key) {
511
+ if (typeof localStorage === 'undefined')
512
+ return undefined;
513
+ const raw = localStorage.getItem(fullKey(key));
514
+ if (raw === null)
515
+ return undefined;
516
+ try {
517
+ return JSON.parse(raw);
518
+ }
519
+ catch {
520
+ return undefined;
521
+ }
522
+ },
523
+ write(key, value) {
524
+ if (typeof localStorage === 'undefined')
525
+ return;
526
+ localStorage.setItem(fullKey(key), JSON.stringify(value));
527
+ },
528
+ };
529
+ }
530
+
531
+ // SPDX-License-Identifier: MIT
532
+ function hasHistory(agent) {
533
+ return typeof agent.history === 'function';
534
+ }
535
+ class ChatDebugComponent {
536
+ agent = input(null, ...(ngDevMode ? [{ debugName: "agent" }] : []));
537
+ dock = input('right', ...(ngDevMode ? [{ debugName: "dock" }] : []));
538
+ defaultOpen = input(false, ...(ngDevMode ? [{ debugName: "defaultOpen" }] : []));
539
+ launcher = input('floating', ...(ngDevMode ? [{ debugName: "launcher" }] : []));
540
+ storageKey = input('chat-debug', ...(ngDevMode ? [{ debugName: "storageKey" }] : []));
541
+ replayRequested = output();
542
+ forkRequested = output();
543
+ openChange = output();
544
+ dockChange = output();
545
+ open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
546
+ dockState = signal('right', ...(ngDevMode ? [{ debugName: "dockState" }] : []));
547
+ /** Set to `true` the first time the user explicitly clicks a dock button.
548
+ * Auto-dock detection becomes a no-op after this flips. Not persisted —
549
+ * fresh session = fresh chance for the smart default. */
550
+ userDockOverride = signal(false, ...(ngDevMode ? [{ debugName: "userDockOverride" }] : []));
551
+ activeTabId = signal('timeline', ...(ngDevMode ? [{ debugName: "activeTabId" }] : []));
552
+ historyAgent = computed(() => {
553
+ const agent = this.agent();
554
+ return agent && hasHistory(agent) ? agent : null;
555
+ }, ...(ngDevMode ? [{ debugName: "historyAgent" }] : []));
556
+ hydrated = signal(false, ...(ngDevMode ? [{ debugName: "hydrated" }] : []));
557
+ /** Reads `agent.status()` reactively for the launcher dot. */
558
+ isStreaming = computed(() => {
559
+ const status = this.agent()?.status?.();
560
+ return status === 'running';
561
+ }, ...(ngDevMode ? [{ debugName: "isStreaming" }] : []));
562
+ tabs = computed(() => {
563
+ if (!this.agent())
564
+ return [];
565
+ return [
566
+ ...(this.historyAgent()
567
+ ? [
568
+ {
569
+ id: 'timeline',
570
+ label: 'Timeline',
571
+ kind: 'builtin-timeline',
572
+ },
573
+ ]
574
+ : []),
575
+ { id: 'state', label: 'State', kind: 'builtin-state' },
576
+ ];
577
+ }, ...(ngDevMode ? [{ debugName: "tabs" }] : []));
578
+ activeTab = computed(() => this.tabs().find((t) => t.id === this.activeTabId()), ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
579
+ hostEl = inject(ElementRef);
580
+ constructor() {
581
+ // Inject chat lib root CSS custom properties so the theme-attribute
582
+ // mappings + edge-claim primitive are in the document, even when
583
+ // chat-debug is mounted without a sibling chat composition.
584
+ ensureChatDebugRootStyles();
585
+ effect(() => {
586
+ const tabs = this.tabs();
587
+ if (tabs.length === 0)
588
+ return;
589
+ if (tabs.some((tab) => tab.id === this.activeTabId()))
590
+ return;
591
+ this.activeTabId.set(tabs[0].id);
592
+ });
593
+ // Restore once after Angular has assigned bound input values. Doing this
594
+ // synchronously in the constructor reads input defaults, then immediately
595
+ // writes those defaults to storage and masks a consumer-provided
596
+ // defaultOpen=true on first load.
597
+ afterNextRender(() => {
598
+ const restore = createPersistence(this.storageKey());
599
+ const persistedOpen = restore.read('open');
600
+ if (!this.open()) {
601
+ this.open.set(persistedOpen ?? this.defaultOpen());
602
+ }
603
+ const persistedDock = restore.read('dock');
604
+ this.dockState.set(persistedDock ?? this.dock());
605
+ const persistedTab = restore.read('tab');
606
+ if (persistedTab)
607
+ this.activeTabId.set(persistedTab);
608
+ this.hydrated.set(true);
609
+ });
610
+ // Write-through effect — reads each writable signal so subsequent
611
+ // changes trigger a fresh run that writes them all to storage.
612
+ effect(() => {
613
+ if (!this.hydrated())
614
+ return;
615
+ const p = createPersistence(this.storageKey());
616
+ p.write('open', this.open());
617
+ p.write('dock', this.dockState());
618
+ p.write('tab', this.activeTabId());
619
+ });
620
+ // Publish the dock the panel currently occupies. Peer panels
621
+ // (e.g. chat-sidebar) read --ngaf-chat-occupy-{right,bottom,left}
622
+ // to avoid overlap.
623
+ effect(() => {
624
+ if (typeof document === 'undefined')
625
+ return;
626
+ const html = document.documentElement;
627
+ if (this.open()) {
628
+ html.dataset['threadplaneChatDebug'] = this.dockState();
629
+ }
630
+ else {
631
+ delete html.dataset['threadplaneChatDebug'];
632
+ }
633
+ });
634
+ // Auto-dock: when the panel transitions from closed → open AND a
635
+ // sibling <chat-sidebar> exists on the page AND the user hasn't
636
+ // overridden the dock this session, prefer bottom-dock so the two
637
+ // panels coexist without stacking on the right edge.
638
+ effect(() => {
639
+ const isOpen = this.open();
640
+ if (!isOpen)
641
+ return;
642
+ if (this.userDockOverride())
643
+ return;
644
+ if (typeof document === 'undefined')
645
+ return;
646
+ if (!document.querySelector('chat-sidebar'))
647
+ return;
648
+ this.dockState.set('bottom');
649
+ });
650
+ }
651
+ setOpen(value) {
652
+ this.open.set(value);
653
+ this.openChange.emit(value);
654
+ }
655
+ setDock(next) {
656
+ this.userDockOverride.set(true);
657
+ this.dockState.set(next);
658
+ this.dockChange.emit(next);
659
+ }
660
+ setActiveTab(id) {
661
+ this.activeTabId.set(id);
662
+ }
663
+ onEsc() {
664
+ if (this.open())
665
+ this.setOpen(false);
666
+ }
667
+ /**
668
+ * Click-outside dismiss. When the panel is open, any click whose
669
+ * composed path doesn't include our host element closes the panel.
670
+ */
671
+ onDocumentClick(event) {
672
+ if (!this.open())
673
+ return;
674
+ const path = event.composedPath();
675
+ if (path.includes(this.hostEl.nativeElement))
676
+ return;
677
+ this.setOpen(false);
678
+ }
679
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatDebugComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
680
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatDebugComponent, isStandalone: true, selector: "chat-debug", inputs: { agent: { classPropertyName: "agent", publicName: "agent", isSignal: true, isRequired: false, transformFunction: null }, dock: { classPropertyName: "dock", publicName: "dock", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, launcher: { classPropertyName: "launcher", publicName: "launcher", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { replayRequested: "replayRequested", forkRequested: "forkRequested", openChange: "openChange", dockChange: "dockChange" }, host: { listeners: { "document:keydown.escape": "onEsc()", "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: `
681
+ @if (!open() && launcher() === 'floating') {
682
+ <button
683
+ type="button"
684
+ class="launcher"
685
+ title="Open chat devtools"
686
+ aria-label="Open chat devtools"
687
+ [attr.aria-pressed]="false"
688
+ (click)="setOpen(true)"
689
+ >
690
+ <span
691
+ class="launcher__dot"
692
+ [class.launcher__dot--streaming]="isStreaming()"
693
+ aria-hidden="true"
694
+ ></span>
695
+ </button>
696
+ } @else if (open() && agent(); as currentAgent) {
697
+ <div
698
+ class="panel"
699
+ [class.panel--right]="dockState() === 'right'"
700
+ [class.panel--bottom]="dockState() === 'bottom'"
701
+ [class.panel--left]="dockState() === 'left'"
702
+ role="region"
703
+ aria-label="Chat devtools"
704
+ >
705
+ <div class="panel__header">
706
+ <h3 class="panel__title">Chat Devtools</h3>
707
+ <div class="panel__actions">
708
+ <div
709
+ class="panel__dock-group"
710
+ role="group"
711
+ aria-label="Dock position"
712
+ >
713
+ <button
714
+ type="button"
715
+ class="panel__dock-btn"
716
+ [class.is-active]="dockState() === 'left'"
717
+ (click)="setDock('left')"
718
+ aria-label="Dock left"
719
+ >
720
+ <svg
721
+ width="14"
722
+ height="14"
723
+ viewBox="0 0 14 14"
724
+ fill="none"
725
+ stroke="currentColor"
726
+ stroke-width="1.5"
727
+ stroke-linecap="round"
728
+ stroke-linejoin="round"
729
+ >
730
+ <rect x="1.5" y="2.5" width="11" height="9" rx="1.2" />
731
+ <line x1="5.5" y1="2.5" x2="5.5" y2="11.5" />
732
+ </svg>
733
+ </button>
734
+ <button
735
+ type="button"
736
+ class="panel__dock-btn"
737
+ [class.is-active]="dockState() === 'bottom'"
738
+ (click)="setDock('bottom')"
739
+ aria-label="Dock bottom"
740
+ >
741
+ <svg
742
+ width="14"
743
+ height="14"
744
+ viewBox="0 0 14 14"
745
+ fill="none"
746
+ stroke="currentColor"
747
+ stroke-width="1.5"
748
+ stroke-linecap="round"
749
+ stroke-linejoin="round"
750
+ >
751
+ <rect x="1.5" y="2.5" width="11" height="9" rx="1.2" />
752
+ <line x1="1.5" y1="8.5" x2="12.5" y2="8.5" />
753
+ </svg>
754
+ </button>
755
+ <button
756
+ type="button"
757
+ class="panel__dock-btn"
758
+ [class.is-active]="dockState() === 'right'"
759
+ (click)="setDock('right')"
760
+ aria-label="Dock right"
761
+ >
762
+ <svg
763
+ width="14"
764
+ height="14"
765
+ viewBox="0 0 14 14"
766
+ fill="none"
767
+ stroke="currentColor"
768
+ stroke-width="1.5"
769
+ stroke-linecap="round"
770
+ stroke-linejoin="round"
771
+ >
772
+ <rect x="1.5" y="2.5" width="11" height="9" rx="1.2" />
773
+ <line x1="8.5" y1="2.5" x2="8.5" y2="11.5" />
774
+ </svg>
775
+ </button>
776
+ </div>
777
+ <button
778
+ type="button"
779
+ class="panel__close"
780
+ (click)="setOpen(false)"
781
+ aria-label="Close"
782
+ >
783
+ <svg
784
+ width="14"
785
+ height="14"
786
+ viewBox="0 0 14 14"
787
+ fill="none"
788
+ stroke="currentColor"
789
+ stroke-width="1.75"
790
+ stroke-linecap="round"
791
+ stroke-linejoin="round"
792
+ >
793
+ <line x1="3" y1="3" x2="11" y2="11" />
794
+ <line x1="11" y1="3" x2="3" y2="11" />
795
+ </svg>
796
+ </button>
797
+ </div>
798
+ </div>
799
+
800
+ @if (tabs().length > 1) {
801
+ <div class="panel__tabs" role="tablist">
802
+ @for (tab of tabs(); track tab.id) {
803
+ <button
804
+ type="button"
805
+ role="tab"
806
+ class="panel__tab"
807
+ [class.is-active]="tab.id === activeTabId()"
808
+ [attr.aria-selected]="tab.id === activeTabId()"
809
+ (click)="setActiveTab(tab.id)"
810
+ >
811
+ {{ tab.label }}
812
+ </button>
813
+ }
814
+ </div>
815
+ }
816
+
817
+ <div class="panel__body">
818
+ @switch (activeTab()?.kind) { @case ('builtin-timeline') { @if
819
+ (historyAgent(); as history) {
820
+ <chat-debug-timeline-inspector
821
+ [agent]="history"
822
+ (replayRequested)="replayRequested.emit($event)"
823
+ (forkRequested)="forkRequested.emit($event)"
824
+ />
825
+ } } @case ('builtin-state') {
826
+ <chat-debug-state-tab [agent]="currentAgent" />
827
+ } }
828
+ </div>
829
+ </div>
830
+ }
831
+ `, isInline: true, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ":host{display:contents}.launcher{position:fixed;top:20px;right:20px;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:var(--ngaf-chat-debug-radius-pill);background:var(--ngaf-chat-debug-bg);border:1px solid var(--ngaf-chat-debug-border);color:var(--ngaf-chat-debug-text);cursor:pointer;z-index:990;box-shadow:var(--ngaf-chat-debug-shadow-pill);transition:background .12s ease,border-color .12s ease;padding:0}.launcher:hover{background:var(--ngaf-chat-debug-surface);border-color:var(--ngaf-chat-debug-border-strong)}.launcher__dot{width:8px;height:8px;border-radius:50%;background:var(--ngaf-chat-debug-success);box-shadow:0 0 8px color-mix(in srgb,var(--ngaf-chat-debug-success) 60%,transparent)}.launcher__dot--streaming{background:var(--ngaf-chat-debug-accent);box-shadow:0 0 8px color-mix(in srgb,var(--ngaf-chat-debug-accent) 70%,transparent);animation:chat-debug-pill-pulse 1.2s ease-in-out infinite}@keyframes chat-debug-pill-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.panel{position:fixed;background:var(--ngaf-chat-debug-bg);color:var(--ngaf-chat-debug-text);border:1px solid var(--ngaf-chat-debug-border);z-index:991;display:flex;flex-direction:column;box-shadow:var(--ngaf-chat-debug-shadow-panel);animation:chat-debug-panel-enter .12s ease}.panel--right{top:0;right:var(--ngaf-chat-sidebar-claim-right, 0);bottom:0;width:var(--panel-size, 420px);border-right:0;border-top-left-radius:var(--ngaf-chat-debug-radius-panel);border-bottom-left-radius:var(--ngaf-chat-debug-radius-panel);transform-origin:bottom right;transition:right .2s ease-out}.panel--left{top:0;left:0;bottom:0;width:var(--panel-size, 420px);border-left:0;border-top-right-radius:var(--ngaf-chat-debug-radius-panel);border-bottom-right-radius:var(--ngaf-chat-debug-radius-panel);transform-origin:bottom left}.panel--bottom{left:0;right:var(--ngaf-chat-sidebar-claim-right, 0);bottom:0;height:var(--panel-size, 40vh);border-bottom:0;border-top-left-radius:var(--ngaf-chat-debug-radius-panel);border-top-right-radius:var(--ngaf-chat-debug-radius-panel);transform-origin:bottom right;transition:right .2s ease-out}@media(max-width:767px){.panel--bottom{display:none}}@keyframes chat-debug-panel-enter{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}.panel__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--ngaf-chat-debug-border);min-height:44px;box-sizing:border-box}.panel__title{margin:0;font-size:13px;font-weight:600;letter-spacing:-.01em;color:var(--ngaf-chat-debug-text)}.panel__actions{display:flex;align-items:center;gap:4px}.panel__dock-group{display:inline-flex;gap:0;padding:2px;background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:6px}.panel__dock-btn{appearance:none;background:transparent;border:0;border-radius:4px;width:24px;height:22px;padding:0;color:var(--ngaf-chat-debug-text-subtle);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.panel__dock-btn:hover{color:var(--ngaf-chat-debug-text)}.panel__dock-btn.is-active{background:var(--ngaf-chat-debug-border);color:var(--ngaf-chat-debug-text)}.panel__dock-btn svg{display:block}.panel__close{appearance:none;background:transparent;border:0;border-radius:6px;width:26px;height:26px;margin-left:4px;color:var(--ngaf-chat-debug-text-subtle);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.panel__close:hover{background:var(--ngaf-chat-debug-surface);color:var(--ngaf-chat-debug-text)}.panel__controls{border-bottom:1px solid var(--ngaf-chat-debug-border);overflow-y:auto;max-height:50%;background:var(--ngaf-chat-debug-bg)}.panel__controls:empty{display:none}.panel__tabs{display:flex;gap:4px;border-bottom:1px solid var(--ngaf-chat-debug-border);padding:0 12px;background:var(--ngaf-chat-debug-bg)}.panel__tab{appearance:none;background:transparent;border:0;border-bottom:2px solid transparent;padding:10px 8px;font:inherit;font-size:13px;font-weight:500;color:var(--ngaf-chat-debug-text-muted);cursor:pointer;transition:color .12s ease,border-color .12s ease;margin-bottom:-1px}.panel__tab:hover{color:var(--ngaf-chat-debug-text)}.panel__tab.is-active{color:var(--ngaf-chat-debug-text);border-bottom-color:var(--ngaf-chat-debug-accent)}.panel__body{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;background:var(--ngaf-chat-debug-bg)}\n"], dependencies: [{ kind: "component", type: TimelineInspectorComponent, selector: "chat-debug-timeline-inspector", inputs: ["agent"], outputs: ["replayRequested", "forkRequested"] }, { kind: "component", type: StateInspectorComponent, selector: "chat-debug-state-tab", inputs: ["agent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
832
+ }
833
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatDebugComponent, decorators: [{
834
+ type: Component,
835
+ args: [{ selector: 'chat-debug', standalone: true, imports: [TimelineInspectorComponent, StateInspectorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
836
+ @if (!open() && launcher() === 'floating') {
837
+ <button
838
+ type="button"
839
+ class="launcher"
840
+ title="Open chat devtools"
841
+ aria-label="Open chat devtools"
842
+ [attr.aria-pressed]="false"
843
+ (click)="setOpen(true)"
844
+ >
845
+ <span
846
+ class="launcher__dot"
847
+ [class.launcher__dot--streaming]="isStreaming()"
848
+ aria-hidden="true"
849
+ ></span>
850
+ </button>
851
+ } @else if (open() && agent(); as currentAgent) {
852
+ <div
853
+ class="panel"
854
+ [class.panel--right]="dockState() === 'right'"
855
+ [class.panel--bottom]="dockState() === 'bottom'"
856
+ [class.panel--left]="dockState() === 'left'"
857
+ role="region"
858
+ aria-label="Chat devtools"
859
+ >
860
+ <div class="panel__header">
861
+ <h3 class="panel__title">Chat Devtools</h3>
862
+ <div class="panel__actions">
863
+ <div
864
+ class="panel__dock-group"
865
+ role="group"
866
+ aria-label="Dock position"
867
+ >
868
+ <button
869
+ type="button"
870
+ class="panel__dock-btn"
871
+ [class.is-active]="dockState() === 'left'"
872
+ (click)="setDock('left')"
873
+ aria-label="Dock left"
874
+ >
875
+ <svg
876
+ width="14"
877
+ height="14"
878
+ viewBox="0 0 14 14"
879
+ fill="none"
880
+ stroke="currentColor"
881
+ stroke-width="1.5"
882
+ stroke-linecap="round"
883
+ stroke-linejoin="round"
884
+ >
885
+ <rect x="1.5" y="2.5" width="11" height="9" rx="1.2" />
886
+ <line x1="5.5" y1="2.5" x2="5.5" y2="11.5" />
887
+ </svg>
888
+ </button>
889
+ <button
890
+ type="button"
891
+ class="panel__dock-btn"
892
+ [class.is-active]="dockState() === 'bottom'"
893
+ (click)="setDock('bottom')"
894
+ aria-label="Dock bottom"
895
+ >
896
+ <svg
897
+ width="14"
898
+ height="14"
899
+ viewBox="0 0 14 14"
900
+ fill="none"
901
+ stroke="currentColor"
902
+ stroke-width="1.5"
903
+ stroke-linecap="round"
904
+ stroke-linejoin="round"
905
+ >
906
+ <rect x="1.5" y="2.5" width="11" height="9" rx="1.2" />
907
+ <line x1="1.5" y1="8.5" x2="12.5" y2="8.5" />
908
+ </svg>
909
+ </button>
910
+ <button
911
+ type="button"
912
+ class="panel__dock-btn"
913
+ [class.is-active]="dockState() === 'right'"
914
+ (click)="setDock('right')"
915
+ aria-label="Dock right"
916
+ >
917
+ <svg
918
+ width="14"
919
+ height="14"
920
+ viewBox="0 0 14 14"
921
+ fill="none"
922
+ stroke="currentColor"
923
+ stroke-width="1.5"
924
+ stroke-linecap="round"
925
+ stroke-linejoin="round"
926
+ >
927
+ <rect x="1.5" y="2.5" width="11" height="9" rx="1.2" />
928
+ <line x1="8.5" y1="2.5" x2="8.5" y2="11.5" />
929
+ </svg>
930
+ </button>
931
+ </div>
932
+ <button
933
+ type="button"
934
+ class="panel__close"
935
+ (click)="setOpen(false)"
936
+ aria-label="Close"
937
+ >
938
+ <svg
939
+ width="14"
940
+ height="14"
941
+ viewBox="0 0 14 14"
942
+ fill="none"
943
+ stroke="currentColor"
944
+ stroke-width="1.75"
945
+ stroke-linecap="round"
946
+ stroke-linejoin="round"
947
+ >
948
+ <line x1="3" y1="3" x2="11" y2="11" />
949
+ <line x1="11" y1="3" x2="3" y2="11" />
950
+ </svg>
951
+ </button>
952
+ </div>
953
+ </div>
954
+
955
+ @if (tabs().length > 1) {
956
+ <div class="panel__tabs" role="tablist">
957
+ @for (tab of tabs(); track tab.id) {
958
+ <button
959
+ type="button"
960
+ role="tab"
961
+ class="panel__tab"
962
+ [class.is-active]="tab.id === activeTabId()"
963
+ [attr.aria-selected]="tab.id === activeTabId()"
964
+ (click)="setActiveTab(tab.id)"
965
+ >
966
+ {{ tab.label }}
967
+ </button>
968
+ }
969
+ </div>
970
+ }
971
+
972
+ <div class="panel__body">
973
+ @switch (activeTab()?.kind) { @case ('builtin-timeline') { @if
974
+ (historyAgent(); as history) {
975
+ <chat-debug-timeline-inspector
976
+ [agent]="history"
977
+ (replayRequested)="replayRequested.emit($event)"
978
+ (forkRequested)="forkRequested.emit($event)"
979
+ />
980
+ } } @case ('builtin-state') {
981
+ <chat-debug-state-tab [agent]="currentAgent" />
982
+ } }
983
+ </div>
984
+ </div>
985
+ }
986
+ `, styles: [":host{--ngaf-chat-debug-bg: #18181b;--ngaf-chat-debug-bg-deep: #09090b;--ngaf-chat-debug-surface: #1f1f23;--ngaf-chat-debug-border: #27272a;--ngaf-chat-debug-border-strong: #3f3f46;--ngaf-chat-debug-text: #fafafa;--ngaf-chat-debug-text-muted: #a1a1aa;--ngaf-chat-debug-text-subtle: #71717a;--ngaf-chat-debug-accent: #4f8df5;--ngaf-chat-debug-success: #4ade80;--ngaf-chat-debug-shadow-panel: 0 8px 32px rgba(0, 0, 0, .5);--ngaf-chat-debug-shadow-pill: 0 6px 18px rgba(0, 0, 0, .4);--ngaf-chat-debug-radius-panel: 12px;--ngaf-chat-debug-radius-input: 8px;--ngaf-chat-debug-radius-pill: 999px;--ngaf-chat-debug-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--ngaf-chat-debug-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;font-family:var(--ngaf-chat-debug-font-sans);color:var(--ngaf-chat-debug-text);--ngaf-chat-bg: var(--ngaf-chat-debug-bg);--ngaf-chat-text: var(--ngaf-chat-debug-text);--ngaf-chat-text-muted: var(--ngaf-chat-debug-text-muted);--ngaf-chat-separator: var(--ngaf-chat-debug-border);--ngaf-chat-surface-alt: var(--ngaf-chat-debug-bg-deep);--ngaf-chat-font-size-xs: 12px;--ngaf-chat-font-mono: var(--ngaf-chat-debug-font-mono);--ngaf-chat-radius-card: 8px;--ngaf-chat-success: var(--ngaf-chat-debug-success);--ngaf-chat-error-bg: color-mix(in srgb, #ef4444 18%, transparent);--ngaf-chat-error-text: #fca5a5;--ngaf-chat-warning-bg: color-mix(in srgb, #f59e0b 18%, transparent);--ngaf-chat-warning-text: #fcd34d}\n", ":host{display:contents}.launcher{position:fixed;top:20px;right:20px;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:var(--ngaf-chat-debug-radius-pill);background:var(--ngaf-chat-debug-bg);border:1px solid var(--ngaf-chat-debug-border);color:var(--ngaf-chat-debug-text);cursor:pointer;z-index:990;box-shadow:var(--ngaf-chat-debug-shadow-pill);transition:background .12s ease,border-color .12s ease;padding:0}.launcher:hover{background:var(--ngaf-chat-debug-surface);border-color:var(--ngaf-chat-debug-border-strong)}.launcher__dot{width:8px;height:8px;border-radius:50%;background:var(--ngaf-chat-debug-success);box-shadow:0 0 8px color-mix(in srgb,var(--ngaf-chat-debug-success) 60%,transparent)}.launcher__dot--streaming{background:var(--ngaf-chat-debug-accent);box-shadow:0 0 8px color-mix(in srgb,var(--ngaf-chat-debug-accent) 70%,transparent);animation:chat-debug-pill-pulse 1.2s ease-in-out infinite}@keyframes chat-debug-pill-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.panel{position:fixed;background:var(--ngaf-chat-debug-bg);color:var(--ngaf-chat-debug-text);border:1px solid var(--ngaf-chat-debug-border);z-index:991;display:flex;flex-direction:column;box-shadow:var(--ngaf-chat-debug-shadow-panel);animation:chat-debug-panel-enter .12s ease}.panel--right{top:0;right:var(--ngaf-chat-sidebar-claim-right, 0);bottom:0;width:var(--panel-size, 420px);border-right:0;border-top-left-radius:var(--ngaf-chat-debug-radius-panel);border-bottom-left-radius:var(--ngaf-chat-debug-radius-panel);transform-origin:bottom right;transition:right .2s ease-out}.panel--left{top:0;left:0;bottom:0;width:var(--panel-size, 420px);border-left:0;border-top-right-radius:var(--ngaf-chat-debug-radius-panel);border-bottom-right-radius:var(--ngaf-chat-debug-radius-panel);transform-origin:bottom left}.panel--bottom{left:0;right:var(--ngaf-chat-sidebar-claim-right, 0);bottom:0;height:var(--panel-size, 40vh);border-bottom:0;border-top-left-radius:var(--ngaf-chat-debug-radius-panel);border-top-right-radius:var(--ngaf-chat-debug-radius-panel);transform-origin:bottom right;transition:right .2s ease-out}@media(max-width:767px){.panel--bottom{display:none}}@keyframes chat-debug-panel-enter{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}.panel__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--ngaf-chat-debug-border);min-height:44px;box-sizing:border-box}.panel__title{margin:0;font-size:13px;font-weight:600;letter-spacing:-.01em;color:var(--ngaf-chat-debug-text)}.panel__actions{display:flex;align-items:center;gap:4px}.panel__dock-group{display:inline-flex;gap:0;padding:2px;background:var(--ngaf-chat-debug-bg-deep);border:1px solid var(--ngaf-chat-debug-border);border-radius:6px}.panel__dock-btn{appearance:none;background:transparent;border:0;border-radius:4px;width:24px;height:22px;padding:0;color:var(--ngaf-chat-debug-text-subtle);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.panel__dock-btn:hover{color:var(--ngaf-chat-debug-text)}.panel__dock-btn.is-active{background:var(--ngaf-chat-debug-border);color:var(--ngaf-chat-debug-text)}.panel__dock-btn svg{display:block}.panel__close{appearance:none;background:transparent;border:0;border-radius:6px;width:26px;height:26px;margin-left:4px;color:var(--ngaf-chat-debug-text-subtle);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.panel__close:hover{background:var(--ngaf-chat-debug-surface);color:var(--ngaf-chat-debug-text)}.panel__controls{border-bottom:1px solid var(--ngaf-chat-debug-border);overflow-y:auto;max-height:50%;background:var(--ngaf-chat-debug-bg)}.panel__controls:empty{display:none}.panel__tabs{display:flex;gap:4px;border-bottom:1px solid var(--ngaf-chat-debug-border);padding:0 12px;background:var(--ngaf-chat-debug-bg)}.panel__tab{appearance:none;background:transparent;border:0;border-bottom:2px solid transparent;padding:10px 8px;font:inherit;font-size:13px;font-weight:500;color:var(--ngaf-chat-debug-text-muted);cursor:pointer;transition:color .12s ease,border-color .12s ease;margin-bottom:-1px}.panel__tab:hover{color:var(--ngaf-chat-debug-text)}.panel__tab.is-active{color:var(--ngaf-chat-debug-text);border-bottom-color:var(--ngaf-chat-debug-accent)}.panel__body{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;background:var(--ngaf-chat-debug-bg)}\n"] }]
987
+ }], ctorParameters: () => [], propDecorators: { agent: [{ type: i0.Input, args: [{ isSignal: true, alias: "agent", required: false }] }], dock: [{ type: i0.Input, args: [{ isSignal: true, alias: "dock", required: false }] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], launcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "launcher", required: false }] }], storageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageKey", required: false }] }], replayRequested: [{ type: i0.Output, args: ["replayRequested"] }], forkRequested: [{ type: i0.Output, args: ["forkRequested"] }], openChange: [{ type: i0.Output, args: ["openChange"] }], dockChange: [{ type: i0.Output, args: ["dockChange"] }], onEsc: [{
988
+ type: HostListener,
989
+ args: ['document:keydown.escape']
990
+ }], onDocumentClick: [{
991
+ type: HostListener,
992
+ args: ['document:click', ['$event']]
993
+ }] } });
994
+
995
+ // SPDX-License-Identifier: MIT
996
+
997
+ /**
998
+ * Generated bundle index. Do not edit.
999
+ */
1000
+
1001
+ export { ChatDebugComponent };
1002
+ //# sourceMappingURL=threadplane-chat-debug.mjs.map