@meshmakers/octo-ai-console 3.4.180 → 3.4.200

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.
@@ -161,10 +161,10 @@ class AiAdapterClientService {
161
161
  tenantBase() {
162
162
  return `${this.options.baseUrl}/${encodeURIComponent(this.options.tenantId)}/v1`;
163
163
  }
164
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiAdapterClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
165
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiAdapterClientService });
164
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiAdapterClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
165
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiAdapterClientService });
166
166
  }
167
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiAdapterClientService, decorators: [{
167
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiAdapterClientService, decorators: [{
168
168
  type: Injectable
169
169
  }] });
170
170
 
@@ -308,10 +308,10 @@ class AiSessionStreamService {
308
308
  : `/${this.options.hubPath}`;
309
309
  return `${this.options.baseUrl}/${this.options.tenantId}${trimmed}`;
310
310
  }
311
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiSessionStreamService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
312
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiSessionStreamService });
311
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiSessionStreamService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
312
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiSessionStreamService });
313
313
  }
314
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiSessionStreamService, decorators: [{
314
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiSessionStreamService, decorators: [{
315
315
  type: Injectable
316
316
  }] });
317
317
 
@@ -362,7 +362,8 @@ function provideOctoAiConsole(options) {
362
362
  * `--mm-ai-status-*` custom properties.
363
363
  */
364
364
  class AiJobStatusBadgeComponent {
365
- status = input.required(...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
365
+ status = input.required(/* @ts-ignore */
366
+ ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
366
367
  variant = computed(() => {
367
368
  switch (this.status()) {
368
369
  case 'Running':
@@ -382,11 +383,12 @@ class AiJobStatusBadgeComponent {
382
383
  default:
383
384
  return 'queued';
384
385
  }
385
- }, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
386
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiJobStatusBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
387
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: AiJobStatusBadgeComponent, isStandalone: true, selector: "mm-ai-job-status-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<span class=\"mm-ai-status-badge mm-ai-status-badge--{{ variant() }}\">\n {{ status() }}\n</span>\n", styles: [":host{display:inline-block;--mm-ai-status-running-bg: #1f6feb;--mm-ai-status-running-fg: #ffffff;--mm-ai-status-queued-bg: #6e7681;--mm-ai-status-queued-fg: #ffffff;--mm-ai-status-paused-bg: #d29922;--mm-ai-status-paused-fg: #1c1c1c;--mm-ai-status-completed-bg: #2ea44f;--mm-ai-status-completed-fg: #ffffff;--mm-ai-status-failed-bg: #d73a49;--mm-ai-status-failed-fg: #ffffff;--mm-ai-status-blocked-bg: #8957e5;--mm-ai-status-blocked-fg: #ffffff}.mm-ai-status-badge{display:inline-block;padding:.15rem .65rem;border-radius:9999px;font-size:.8rem;font-weight:600;line-height:1.2;letter-spacing:.01em}.mm-ai-status-badge--running{background:var(--mm-ai-status-running-bg);color:var(--mm-ai-status-running-fg)}.mm-ai-status-badge--queued{background:var(--mm-ai-status-queued-bg);color:var(--mm-ai-status-queued-fg)}.mm-ai-status-badge--paused{background:var(--mm-ai-status-paused-bg);color:var(--mm-ai-status-paused-fg)}.mm-ai-status-badge--completed{background:var(--mm-ai-status-completed-bg);color:var(--mm-ai-status-completed-fg)}.mm-ai-status-badge--failed{background:var(--mm-ai-status-failed-bg);color:var(--mm-ai-status-failed-fg)}.mm-ai-status-badge--blocked{background:var(--mm-ai-status-blocked-bg);color:var(--mm-ai-status-blocked-fg)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
386
+ }, /* @ts-ignore */
387
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
388
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiJobStatusBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
389
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: AiJobStatusBadgeComponent, isStandalone: true, selector: "mm-ai-job-status-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<span class=\"mm-ai-status-badge mm-ai-status-badge--{{ variant() }}\">\n {{ status() }}\n</span>\n", styles: [":host{display:inline-block;--mm-ai-status-running-bg: #1f6feb;--mm-ai-status-running-fg: #ffffff;--mm-ai-status-queued-bg: #6e7681;--mm-ai-status-queued-fg: #ffffff;--mm-ai-status-paused-bg: #d29922;--mm-ai-status-paused-fg: #1c1c1c;--mm-ai-status-completed-bg: #2ea44f;--mm-ai-status-completed-fg: #ffffff;--mm-ai-status-failed-bg: #d73a49;--mm-ai-status-failed-fg: #ffffff;--mm-ai-status-blocked-bg: #8957e5;--mm-ai-status-blocked-fg: #ffffff}.mm-ai-status-badge{display:inline-block;padding:.15rem .65rem;border-radius:9999px;font-size:.8rem;font-weight:600;line-height:1.2;letter-spacing:.01em}.mm-ai-status-badge--running{background:var(--mm-ai-status-running-bg);color:var(--mm-ai-status-running-fg)}.mm-ai-status-badge--queued{background:var(--mm-ai-status-queued-bg);color:var(--mm-ai-status-queued-fg)}.mm-ai-status-badge--paused{background:var(--mm-ai-status-paused-bg);color:var(--mm-ai-status-paused-fg)}.mm-ai-status-badge--completed{background:var(--mm-ai-status-completed-bg);color:var(--mm-ai-status-completed-fg)}.mm-ai-status-badge--failed{background:var(--mm-ai-status-failed-bg);color:var(--mm-ai-status-failed-fg)}.mm-ai-status-badge--blocked{background:var(--mm-ai-status-blocked-bg);color:var(--mm-ai-status-blocked-fg)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
388
390
  }
389
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiJobStatusBadgeComponent, decorators: [{
391
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiJobStatusBadgeComponent, decorators: [{
390
392
  type: Component,
391
393
  args: [{ selector: 'mm-ai-job-status-badge', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"mm-ai-status-badge mm-ai-status-badge--{{ variant() }}\">\n {{ status() }}\n</span>\n", styles: [":host{display:inline-block;--mm-ai-status-running-bg: #1f6feb;--mm-ai-status-running-fg: #ffffff;--mm-ai-status-queued-bg: #6e7681;--mm-ai-status-queued-fg: #ffffff;--mm-ai-status-paused-bg: #d29922;--mm-ai-status-paused-fg: #1c1c1c;--mm-ai-status-completed-bg: #2ea44f;--mm-ai-status-completed-fg: #ffffff;--mm-ai-status-failed-bg: #d73a49;--mm-ai-status-failed-fg: #ffffff;--mm-ai-status-blocked-bg: #8957e5;--mm-ai-status-blocked-fg: #ffffff}.mm-ai-status-badge{display:inline-block;padding:.15rem .65rem;border-radius:9999px;font-size:.8rem;font-weight:600;line-height:1.2;letter-spacing:.01em}.mm-ai-status-badge--running{background:var(--mm-ai-status-running-bg);color:var(--mm-ai-status-running-fg)}.mm-ai-status-badge--queued{background:var(--mm-ai-status-queued-bg);color:var(--mm-ai-status-queued-fg)}.mm-ai-status-badge--paused{background:var(--mm-ai-status-paused-bg);color:var(--mm-ai-status-paused-fg)}.mm-ai-status-badge--completed{background:var(--mm-ai-status-completed-bg);color:var(--mm-ai-status-completed-fg)}.mm-ai-status-badge--failed{background:var(--mm-ai-status-failed-bg);color:var(--mm-ai-status-failed-fg)}.mm-ai-status-badge--blocked{background:var(--mm-ai-status-blocked-bg);color:var(--mm-ai-status-blocked-fg)}\n"] }]
392
394
  }], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: true }] }] } });
@@ -404,12 +406,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
404
406
  * never offers Cancel.
405
407
  */
406
408
  class AiSessionListComponent {
407
- sessions = input.required(...(ngDevMode ? [{ debugName: "sessions" }] : /* istanbul ignore next */ []));
408
- selectedSessionId = input(null, ...(ngDevMode ? [{ debugName: "selectedSessionId" }] : /* istanbul ignore next */ []));
409
+ sessions = input.required(/* @ts-ignore */
410
+ ...(ngDevMode ? [{ debugName: "sessions" }] : /* istanbul ignore next */ []));
411
+ selectedSessionId = input(null, /* @ts-ignore */
412
+ ...(ngDevMode ? [{ debugName: "selectedSessionId" }] : /* istanbul ignore next */ []));
409
413
  sessionSelected = output();
410
414
  cancelRequested = output();
411
415
  deleteRequested = output();
412
- orderedSessions = computed(() => [...this.sessions()].sort((a, b) => b.startedAt.localeCompare(a.startedAt)), ...(ngDevMode ? [{ debugName: "orderedSessions" }] : /* istanbul ignore next */ []));
416
+ orderedSessions = computed(() => [...this.sessions()].sort((a, b) => b.startedAt.localeCompare(a.startedAt)), /* @ts-ignore */
417
+ ...(ngDevMode ? [{ debugName: "orderedSessions" }] : /* istanbul ignore next */ []));
413
418
  /**
414
419
  * Terminal status set, kept in sync with the C# `AiAgentSessionService.IsTerminal`
415
420
  * predicate. Delete is gated to this set; Cancel is gated to its complement.
@@ -458,10 +463,10 @@ class AiSessionListComponent {
458
463
  const days = Math.floor(hours / 24);
459
464
  return `${days}d ago`;
460
465
  }
461
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiSessionListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
462
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AiSessionListComponent, isStandalone: true, selector: "mm-ai-session-list", inputs: { sessions: { classPropertyName: "sessions", publicName: "sessions", isSignal: true, isRequired: true, transformFunction: null }, selectedSessionId: { classPropertyName: "selectedSessionId", publicName: "selectedSessionId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sessionSelected: "sessionSelected", cancelRequested: "cancelRequested", deleteRequested: "deleteRequested" }, ngImport: i0, template: "<ul class=\"mm-ai-session-list\">\n @for (session of orderedSessions(); track session.sessionRtId) {\n <li\n class=\"mm-ai-session-list__row\"\n [class.mm-ai-session-list__row--selected]=\"\n session.sessionRtId === selectedSessionId()\n \"\n >\n <button\n type=\"button\"\n class=\"mm-ai-session-list__button\"\n (click)=\"onSelect(session.sessionRtId)\"\n >\n <!--\n Row layout: goal + status badge on top, meta + actions on the\n bottom. The two-line shape lets a narrow sidebar (Refinery\n Studio caps the column at 18rem) breathe \u2014 the previous\n horizontal cram had the goal text overlap the action buttons\n on every row.\n -->\n <div class=\"mm-ai-session-list__top\">\n <span class=\"mm-ai-session-list__goal\">{{ session.goalSummary }}</span>\n <mm-ai-job-status-badge [status]=\"session.status\" />\n </div>\n <div class=\"mm-ai-session-list__bottom\">\n <span class=\"mm-ai-session-list__meta\">\n {{ age(session.startedAt) }}\n <span class=\"mm-ai-session-list__dot\">\u00B7</span>\n {{ session.tokensConsumed }} tok\n </span>\n @if (session.previewUrl) {\n <!--\n #4136 \u2014 preview-deploy URL the server surfaces when the\n worker pod's nginx sidecar has a build to serve. Opens in\n a new tab so the sidebar scroll position survives.\n stopPropagation prevents the row click from also firing.\n -->\n <a\n class=\"mm-ai-session-list__preview\"\n [href]=\"session.previewUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"$event.stopPropagation()\"\n >\n Preview\n </a>\n }\n <span class=\"mm-ai-session-list__spacer\"></span>\n <span class=\"mm-ai-session-list__actions\">\n @if (canCancel(session.status)) {\n <button\n type=\"button\"\n class=\"mm-ai-session-list__action mm-ai-session-list__action--cancel\"\n [attr.aria-label]=\"'Cancel session ' + session.goalSummary\"\n (click)=\"onCancel(session.sessionRtId, $event)\"\n >\n Cancel\n </button>\n }\n @if (canDelete(session.status)) {\n <button\n type=\"button\"\n class=\"mm-ai-session-list__action mm-ai-session-list__action--delete\"\n [attr.aria-label]=\"'Delete session ' + session.goalSummary\"\n (click)=\"onDelete(session.sessionRtId, $event)\"\n >\n Delete\n </button>\n }\n </span>\n </div>\n </button>\n </li>\n } @empty {\n <li class=\"mm-ai-session-list__empty\">No sessions yet.</li>\n }\n</ul>\n", styles: [":host{display:block;--mm-ai-list-bg: #16191d;--mm-ai-list-row-bg: #1f2227;--mm-ai-list-row-selected: #2a3142;--mm-ai-list-border: #2f343b;--mm-ai-list-text: #e6e6e6;--mm-ai-list-muted: #9aa0a6;--mm-ai-list-accent: #64ceb9;--mm-ai-list-action-cancel: #da9162;--mm-ai-list-action-delete: #ec658f}.mm-ai-session-list{list-style:none;margin:0;padding:0;background:var(--mm-ai-list-bg);border-radius:.5rem;display:flex;flex-direction:column;gap:.25rem;padding:.25rem}.mm-ai-session-list__row{background:var(--mm-ai-list-row-bg);border:1px solid var(--mm-ai-list-border);border-radius:.4rem}.mm-ai-session-list__row--selected{background:var(--mm-ai-list-row-selected)}.mm-ai-session-list__button{width:100%;display:flex;flex-direction:column;gap:.3rem;padding:.5rem .75rem;background:transparent;color:var(--mm-ai-list-text);border:none;cursor:pointer;text-align:left;font-family:inherit;min-width:0}.mm-ai-session-list__button:hover{background:#ffffff08}.mm-ai-session-list__top{display:flex;align-items:center;gap:.5rem;min-width:0}.mm-ai-session-list__goal{flex:1;min-width:0;font-size:.85rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mm-ai-session-list__bottom{display:flex;align-items:center;gap:.5rem;font-size:.7rem;color:var(--mm-ai-list-muted);font-variant-numeric:tabular-nums;min-width:0}.mm-ai-session-list__meta{display:inline-flex;align-items:baseline;gap:.35rem;flex-shrink:0}.mm-ai-session-list__dot{opacity:.5}.mm-ai-session-list__spacer{flex:1}.mm-ai-session-list__preview{color:var(--mm-ai-list-accent);font-size:.7rem;text-decoration:underline;text-underline-offset:2px;flex-shrink:0}.mm-ai-session-list__preview:hover{text-decoration-thickness:2px}.mm-ai-session-list__empty{padding:1rem;text-align:center;color:var(--mm-ai-list-muted);font-style:italic}.mm-ai-session-list__actions{display:flex;gap:.25rem;flex-shrink:0;opacity:.45;transition:opacity .15s ease}.mm-ai-session-list__row:hover .mm-ai-session-list__actions,.mm-ai-session-list__row--selected .mm-ai-session-list__actions{opacity:1}.mm-ai-session-list__action{padding:.15rem .5rem;background:transparent;border:1px solid var(--mm-ai-list-border);border-radius:.25rem;color:var(--mm-ai-list-text);font-family:inherit;font-size:.65rem;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:border-color .15s ease,color .15s ease,background-color .15s ease}.mm-ai-session-list__action:hover{background:#ffffff0a}.mm-ai-session-list__action--cancel{color:var(--mm-ai-list-action-cancel);border-color:color-mix(in srgb,var(--mm-ai-list-action-cancel) 40%,transparent)}.mm-ai-session-list__action--cancel:hover{border-color:var(--mm-ai-list-action-cancel)}.mm-ai-session-list__action--delete{color:var(--mm-ai-list-action-delete);border-color:color-mix(in srgb,var(--mm-ai-list-action-delete) 40%,transparent)}.mm-ai-session-list__action--delete:hover{border-color:var(--mm-ai-list-action-delete)}\n"], dependencies: [{ kind: "component", type: AiJobStatusBadgeComponent, selector: "mm-ai-job-status-badge", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
466
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiSessionListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
467
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: AiSessionListComponent, isStandalone: true, selector: "mm-ai-session-list", inputs: { sessions: { classPropertyName: "sessions", publicName: "sessions", isSignal: true, isRequired: true, transformFunction: null }, selectedSessionId: { classPropertyName: "selectedSessionId", publicName: "selectedSessionId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sessionSelected: "sessionSelected", cancelRequested: "cancelRequested", deleteRequested: "deleteRequested" }, ngImport: i0, template: "<ul class=\"mm-ai-session-list\">\n @for (session of orderedSessions(); track session.sessionRtId) {\n <li\n class=\"mm-ai-session-list__row\"\n [class.mm-ai-session-list__row--selected]=\"\n session.sessionRtId === selectedSessionId()\n \"\n >\n <button\n type=\"button\"\n class=\"mm-ai-session-list__button\"\n (click)=\"onSelect(session.sessionRtId)\"\n >\n <!--\n Row layout: goal + status badge on top, meta + actions on the\n bottom. The two-line shape lets a narrow sidebar (Refinery\n Studio caps the column at 18rem) breathe \u2014 the previous\n horizontal cram had the goal text overlap the action buttons\n on every row.\n -->\n <div class=\"mm-ai-session-list__top\">\n <span class=\"mm-ai-session-list__goal\">{{ session.goalSummary }}</span>\n <mm-ai-job-status-badge [status]=\"session.status\" />\n </div>\n <div class=\"mm-ai-session-list__bottom\">\n <span class=\"mm-ai-session-list__meta\">\n {{ age(session.startedAt) }}\n <span class=\"mm-ai-session-list__dot\">\u00B7</span>\n {{ session.tokensConsumed }} tok\n </span>\n @if (session.previewUrl) {\n <!--\n #4136 \u2014 preview-deploy URL the server surfaces when the\n worker pod's nginx sidecar has a build to serve. Opens in\n a new tab so the sidebar scroll position survives.\n stopPropagation prevents the row click from also firing.\n -->\n <a\n class=\"mm-ai-session-list__preview\"\n [href]=\"session.previewUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"$event.stopPropagation()\"\n >\n Preview\n </a>\n }\n <span class=\"mm-ai-session-list__spacer\"></span>\n <span class=\"mm-ai-session-list__actions\">\n @if (canCancel(session.status)) {\n <button\n type=\"button\"\n class=\"mm-ai-session-list__action mm-ai-session-list__action--cancel\"\n [attr.aria-label]=\"'Cancel session ' + session.goalSummary\"\n (click)=\"onCancel(session.sessionRtId, $event)\"\n >\n Cancel\n </button>\n }\n @if (canDelete(session.status)) {\n <button\n type=\"button\"\n class=\"mm-ai-session-list__action mm-ai-session-list__action--delete\"\n [attr.aria-label]=\"'Delete session ' + session.goalSummary\"\n (click)=\"onDelete(session.sessionRtId, $event)\"\n >\n Delete\n </button>\n }\n </span>\n </div>\n </button>\n </li>\n } @empty {\n <li class=\"mm-ai-session-list__empty\">No sessions yet.</li>\n }\n</ul>\n", styles: [":host{display:block;--mm-ai-list-bg: #16191d;--mm-ai-list-row-bg: #1f2227;--mm-ai-list-row-selected: #2a3142;--mm-ai-list-border: #2f343b;--mm-ai-list-text: #e6e6e6;--mm-ai-list-muted: #9aa0a6;--mm-ai-list-accent: #64ceb9;--mm-ai-list-action-cancel: #da9162;--mm-ai-list-action-delete: #ec658f}.mm-ai-session-list{list-style:none;margin:0;padding:0;background:var(--mm-ai-list-bg);border-radius:.5rem;display:flex;flex-direction:column;gap:.25rem;padding:.25rem}.mm-ai-session-list__row{background:var(--mm-ai-list-row-bg);border:1px solid var(--mm-ai-list-border);border-radius:.4rem}.mm-ai-session-list__row--selected{background:var(--mm-ai-list-row-selected)}.mm-ai-session-list__button{width:100%;display:flex;flex-direction:column;gap:.3rem;padding:.5rem .75rem;background:transparent;color:var(--mm-ai-list-text);border:none;cursor:pointer;text-align:left;font-family:inherit;min-width:0}.mm-ai-session-list__button:hover{background:#ffffff08}.mm-ai-session-list__top{display:flex;align-items:center;gap:.5rem;min-width:0}.mm-ai-session-list__goal{flex:1;min-width:0;font-size:.85rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mm-ai-session-list__bottom{display:flex;align-items:center;gap:.5rem;font-size:.7rem;color:var(--mm-ai-list-muted);font-variant-numeric:tabular-nums;min-width:0}.mm-ai-session-list__meta{display:inline-flex;align-items:baseline;gap:.35rem;flex-shrink:0}.mm-ai-session-list__dot{opacity:.5}.mm-ai-session-list__spacer{flex:1}.mm-ai-session-list__preview{color:var(--mm-ai-list-accent);font-size:.7rem;text-decoration:underline;text-underline-offset:2px;flex-shrink:0}.mm-ai-session-list__preview:hover{text-decoration-thickness:2px}.mm-ai-session-list__empty{padding:1rem;text-align:center;color:var(--mm-ai-list-muted);font-style:italic}.mm-ai-session-list__actions{display:flex;gap:.25rem;flex-shrink:0;opacity:.45;transition:opacity .15s ease}.mm-ai-session-list__row:hover .mm-ai-session-list__actions,.mm-ai-session-list__row--selected .mm-ai-session-list__actions{opacity:1}.mm-ai-session-list__action{padding:.15rem .5rem;background:transparent;border:1px solid var(--mm-ai-list-border);border-radius:.25rem;color:var(--mm-ai-list-text);font-family:inherit;font-size:.65rem;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:border-color .15s ease,color .15s ease,background-color .15s ease}.mm-ai-session-list__action:hover{background:#ffffff0a}.mm-ai-session-list__action--cancel{color:var(--mm-ai-list-action-cancel);border-color:color-mix(in srgb,var(--mm-ai-list-action-cancel) 40%,transparent)}.mm-ai-session-list__action--cancel:hover{border-color:var(--mm-ai-list-action-cancel)}.mm-ai-session-list__action--delete{color:var(--mm-ai-list-action-delete);border-color:color-mix(in srgb,var(--mm-ai-list-action-delete) 40%,transparent)}.mm-ai-session-list__action--delete:hover{border-color:var(--mm-ai-list-action-delete)}\n"], dependencies: [{ kind: "component", type: AiJobStatusBadgeComponent, selector: "mm-ai-job-status-badge", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
463
468
  }
464
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiSessionListComponent, decorators: [{
469
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiSessionListComponent, decorators: [{
465
470
  type: Component,
466
471
  args: [{ selector: 'mm-ai-session-list', imports: [AiJobStatusBadgeComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"mm-ai-session-list\">\n @for (session of orderedSessions(); track session.sessionRtId) {\n <li\n class=\"mm-ai-session-list__row\"\n [class.mm-ai-session-list__row--selected]=\"\n session.sessionRtId === selectedSessionId()\n \"\n >\n <button\n type=\"button\"\n class=\"mm-ai-session-list__button\"\n (click)=\"onSelect(session.sessionRtId)\"\n >\n <!--\n Row layout: goal + status badge on top, meta + actions on the\n bottom. The two-line shape lets a narrow sidebar (Refinery\n Studio caps the column at 18rem) breathe \u2014 the previous\n horizontal cram had the goal text overlap the action buttons\n on every row.\n -->\n <div class=\"mm-ai-session-list__top\">\n <span class=\"mm-ai-session-list__goal\">{{ session.goalSummary }}</span>\n <mm-ai-job-status-badge [status]=\"session.status\" />\n </div>\n <div class=\"mm-ai-session-list__bottom\">\n <span class=\"mm-ai-session-list__meta\">\n {{ age(session.startedAt) }}\n <span class=\"mm-ai-session-list__dot\">\u00B7</span>\n {{ session.tokensConsumed }} tok\n </span>\n @if (session.previewUrl) {\n <!--\n #4136 \u2014 preview-deploy URL the server surfaces when the\n worker pod's nginx sidecar has a build to serve. Opens in\n a new tab so the sidebar scroll position survives.\n stopPropagation prevents the row click from also firing.\n -->\n <a\n class=\"mm-ai-session-list__preview\"\n [href]=\"session.previewUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"$event.stopPropagation()\"\n >\n Preview\n </a>\n }\n <span class=\"mm-ai-session-list__spacer\"></span>\n <span class=\"mm-ai-session-list__actions\">\n @if (canCancel(session.status)) {\n <button\n type=\"button\"\n class=\"mm-ai-session-list__action mm-ai-session-list__action--cancel\"\n [attr.aria-label]=\"'Cancel session ' + session.goalSummary\"\n (click)=\"onCancel(session.sessionRtId, $event)\"\n >\n Cancel\n </button>\n }\n @if (canDelete(session.status)) {\n <button\n type=\"button\"\n class=\"mm-ai-session-list__action mm-ai-session-list__action--delete\"\n [attr.aria-label]=\"'Delete session ' + session.goalSummary\"\n (click)=\"onDelete(session.sessionRtId, $event)\"\n >\n Delete\n </button>\n }\n </span>\n </div>\n </button>\n </li>\n } @empty {\n <li class=\"mm-ai-session-list__empty\">No sessions yet.</li>\n }\n</ul>\n", styles: [":host{display:block;--mm-ai-list-bg: #16191d;--mm-ai-list-row-bg: #1f2227;--mm-ai-list-row-selected: #2a3142;--mm-ai-list-border: #2f343b;--mm-ai-list-text: #e6e6e6;--mm-ai-list-muted: #9aa0a6;--mm-ai-list-accent: #64ceb9;--mm-ai-list-action-cancel: #da9162;--mm-ai-list-action-delete: #ec658f}.mm-ai-session-list{list-style:none;margin:0;padding:0;background:var(--mm-ai-list-bg);border-radius:.5rem;display:flex;flex-direction:column;gap:.25rem;padding:.25rem}.mm-ai-session-list__row{background:var(--mm-ai-list-row-bg);border:1px solid var(--mm-ai-list-border);border-radius:.4rem}.mm-ai-session-list__row--selected{background:var(--mm-ai-list-row-selected)}.mm-ai-session-list__button{width:100%;display:flex;flex-direction:column;gap:.3rem;padding:.5rem .75rem;background:transparent;color:var(--mm-ai-list-text);border:none;cursor:pointer;text-align:left;font-family:inherit;min-width:0}.mm-ai-session-list__button:hover{background:#ffffff08}.mm-ai-session-list__top{display:flex;align-items:center;gap:.5rem;min-width:0}.mm-ai-session-list__goal{flex:1;min-width:0;font-size:.85rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mm-ai-session-list__bottom{display:flex;align-items:center;gap:.5rem;font-size:.7rem;color:var(--mm-ai-list-muted);font-variant-numeric:tabular-nums;min-width:0}.mm-ai-session-list__meta{display:inline-flex;align-items:baseline;gap:.35rem;flex-shrink:0}.mm-ai-session-list__dot{opacity:.5}.mm-ai-session-list__spacer{flex:1}.mm-ai-session-list__preview{color:var(--mm-ai-list-accent);font-size:.7rem;text-decoration:underline;text-underline-offset:2px;flex-shrink:0}.mm-ai-session-list__preview:hover{text-decoration-thickness:2px}.mm-ai-session-list__empty{padding:1rem;text-align:center;color:var(--mm-ai-list-muted);font-style:italic}.mm-ai-session-list__actions{display:flex;gap:.25rem;flex-shrink:0;opacity:.45;transition:opacity .15s ease}.mm-ai-session-list__row:hover .mm-ai-session-list__actions,.mm-ai-session-list__row--selected .mm-ai-session-list__actions{opacity:1}.mm-ai-session-list__action{padding:.15rem .5rem;background:transparent;border:1px solid var(--mm-ai-list-border);border-radius:.25rem;color:var(--mm-ai-list-text);font-family:inherit;font-size:.65rem;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:border-color .15s ease,color .15s ease,background-color .15s ease}.mm-ai-session-list__action:hover{background:#ffffff0a}.mm-ai-session-list__action--cancel{color:var(--mm-ai-list-action-cancel);border-color:color-mix(in srgb,var(--mm-ai-list-action-cancel) 40%,transparent)}.mm-ai-session-list__action--cancel:hover{border-color:var(--mm-ai-list-action-cancel)}.mm-ai-session-list__action--delete{color:var(--mm-ai-list-action-delete);border-color:color-mix(in srgb,var(--mm-ai-list-action-delete) 40%,transparent)}.mm-ai-session-list__action--delete:hover{border-color:var(--mm-ai-list-action-delete)}\n"] }]
467
472
  }], propDecorators: { sessions: [{ type: i0.Input, args: [{ isSignal: true, alias: "sessions", required: true }] }], selectedSessionId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedSessionId", required: false }] }], sessionSelected: [{ type: i0.Output, args: ["sessionSelected"] }], cancelRequested: [{ type: i0.Output, args: ["cancelRequested"] }], deleteRequested: [{ type: i0.Output, args: ["deleteRequested"] }] } });
@@ -791,18 +796,21 @@ function stringifyToolContent(content) {
791
796
  * marked) is gated on a CSP review and a markdown-corpus regression test.
792
797
  */
793
798
  class AiChatStreamComponent {
794
- events = input.required(...(ngDevMode ? [{ debugName: "events" }] : /* istanbul ignore next */ []));
799
+ events = input.required(/* @ts-ignore */
800
+ ...(ngDevMode ? [{ debugName: "events" }] : /* istanbul ignore next */ []));
795
801
  /**
796
802
  * Sorted + parsed. Recomputes whenever the input signal changes; the sort
797
803
  * is stable so live appends from SignalR keep prior render positions.
798
804
  */
799
- parsedEvents = computed(() => parseAndOrder(this.events()), ...(ngDevMode ? [{ debugName: "parsedEvents" }] : /* istanbul ignore next */ []));
805
+ parsedEvents = computed(() => parseAndOrder(this.events()), /* @ts-ignore */
806
+ ...(ngDevMode ? [{ debugName: "parsedEvents" }] : /* istanbul ignore next */ []));
800
807
  /**
801
808
  * Per-event "show raw JSON" toggle. Keyed by sequence so live appends
802
809
  * don't flicker existing toggles closed. A `Set<number>` rather than a
803
810
  * record so add / delete avoids `keyof` shenanigans.
804
811
  */
805
- expandedSet = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedSet" }] : /* istanbul ignore next */ []));
812
+ expandedSet = signal(new Set(), /* @ts-ignore */
813
+ ...(ngDevMode ? [{ debugName: "expandedSet" }] : /* istanbul ignore next */ []));
806
814
  isExpanded(sequence) {
807
815
  return this.expandedSet().has(sequence);
808
816
  }
@@ -866,10 +874,10 @@ class AiChatStreamComponent {
866
874
  return String(value);
867
875
  }
868
876
  }
869
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiChatStreamComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
870
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AiChatStreamComponent, isStandalone: true, selector: "mm-ai-chat-stream", inputs: { events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mm-ai-chat\">\n @for (parsed of parsedEvents(); track parsed.event.sequence) {\n @switch (parsed.view.kind) {\n @case ('assistant') {\n <article class=\"mm-ai-chat__bubble mm-ai-chat__bubble--assistant\">\n <header class=\"mm-ai-chat__bubble-header\">\n <span class=\"mm-ai-chat__role\">Assistant</span>\n @if (parsed.view.model; as model) {\n <span class=\"mm-ai-chat__meta\">{{ model }}</span>\n }\n @if (parsed.view.usage; as usage) {\n <span class=\"mm-ai-chat__meta\">\n {{ formatTokenCount(usage.input + usage.output) }}\n </span>\n }\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n @for (part of parsed.view.parts; track $index) {\n @switch (part.type) {\n @case ('text') {\n <p class=\"mm-ai-chat__text\">{{ part.text }}</p>\n }\n @case ('tool_use') {\n <div class=\"mm-ai-chat__tool-use\">\n <header class=\"mm-ai-chat__tool-use-header\">\n <span class=\"mm-ai-chat__tool-badge\">tool</span>\n <span class=\"mm-ai-chat__tool-name\">{{ part.toolName }}</span>\n </header>\n <pre class=\"mm-ai-chat__tool-input\">{{ formatRaw(part.input) }}</pre>\n </div>\n }\n }\n }\n </article>\n }\n\n @case ('tool-result') {\n <article\n class=\"mm-ai-chat__tool-result\"\n [class.mm-ai-chat__tool-result--error]=\"parsed.view.isError\"\n >\n <header class=\"mm-ai-chat__tool-result-header\">\n <span class=\"mm-ai-chat__role\">Tool result</span>\n @if (parsed.view.isError) {\n <span class=\"mm-ai-chat__error-badge\">error</span>\n }\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n <pre class=\"mm-ai-chat__tool-result-body\">{{ parsed.view.content }}</pre>\n </article>\n }\n\n @case ('result') {\n <article class=\"mm-ai-chat__result\"\n [class.mm-ai-chat__result--error]=\"parsed.view.isError\">\n <header class=\"mm-ai-chat__result-header\">\n <span class=\"mm-ai-chat__role\">{{ parsed.view.reason }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n @if (parsed.view.text) {\n <p class=\"mm-ai-chat__result-text\">{{ parsed.view.text }}</p>\n }\n <dl class=\"mm-ai-chat__result-stats\">\n <div>\n <dt>Duration</dt>\n <dd>{{ formatDuration(parsed.view.durationMs) }}</dd>\n </div>\n <div>\n <dt>Tokens (in/out)</dt>\n <dd>\n @if (parsed.view.usage) {\n {{ formatTokenCount(parsed.view.usage.input) }}\n /\n {{ formatTokenCount(parsed.view.usage.output) }}\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div>\n <dt>Cost</dt>\n <dd>{{ formatCost(parsed.view.costUsd) }}</dd>\n </div>\n </dl>\n </article>\n }\n\n @case ('system') {\n <button\n type=\"button\"\n class=\"mm-ai-chat__system\"\n [class.mm-ai-chat__system--init]=\"parsed.view.subKind === 'init'\"\n [class.mm-ai-chat__system--hook]=\"parsed.view.subKind === 'hook'\"\n [class.mm-ai-chat__system--rate]=\"parsed.view.subKind === 'rate-limit'\"\n [attr.aria-expanded]=\"isExpanded(parsed.event.sequence)\"\n (click)=\"toggleRaw(parsed.event.sequence)\"\n >\n <span class=\"mm-ai-chat__system-chevron\">\n {{ isExpanded(parsed.event.sequence) ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-chat__system-summary\">{{ parsed.view.summary }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </button>\n @if (isExpanded(parsed.event.sequence)) {\n <pre class=\"mm-ai-chat__system-detail\">{{ formatRaw(parsed.view.raw) }}</pre>\n }\n }\n\n @case ('status-change') {\n <div class=\"mm-ai-chat__status\">\n <span class=\"mm-ai-chat__status-label\">Status</span>\n <span class=\"mm-ai-chat__status-value\">{{ parsed.view.status }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </div>\n }\n\n @case ('unknown') {\n <button\n type=\"button\"\n class=\"mm-ai-chat__system mm-ai-chat__system--unknown\"\n [attr.aria-expanded]=\"isExpanded(parsed.event.sequence)\"\n (click)=\"toggleRaw(parsed.event.sequence)\"\n >\n <span class=\"mm-ai-chat__system-chevron\">\n {{ isExpanded(parsed.event.sequence) ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-chat__system-summary\">{{ parsed.view.summary }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </button>\n @if (isExpanded(parsed.event.sequence)) {\n <pre class=\"mm-ai-chat__system-detail\">{{ formatRaw(parsed.view.raw) }}</pre>\n }\n }\n }\n } @empty {\n <div class=\"mm-ai-chat__empty\">\n No events yet \u2014 the worker hasn't emitted anything.\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-chat-bg: transparent;--mm-ai-chat-card-bg: rgba(31, 46, 64, .55);--mm-ai-chat-card-bg-elevated: rgba(31, 46, 64, .85);--mm-ai-chat-border: rgba(100, 206, 185, .18);--mm-ai-chat-border-strong: rgba(100, 206, 185, .4);--mm-ai-chat-text: #e6e6e6;--mm-ai-chat-muted: #9292a6;--mm-ai-chat-accent-assistant: #64ceb9;--mm-ai-chat-accent-tool: #00a8dc;--mm-ai-chat-accent-tool-result: #00a8dc;--mm-ai-chat-accent-system: #6c4da8;--mm-ai-chat-accent-rate-limit: #da9162;--mm-ai-chat-accent-result: #64ceb9;--mm-ai-chat-accent-error: #ec658f}.mm-ai-chat{display:flex;flex-direction:column;gap:.5rem;padding:.25rem;background:var(--mm-ai-chat-bg);color:var(--mm-ai-chat-text);font-size:.85rem;line-height:1.45}.mm-ai-chat__empty{color:var(--mm-ai-chat-muted);text-align:center;padding:1.5rem;font-style:italic}.mm-ai-chat__bubble{background:var(--mm-ai-chat-card-bg);border:1px solid var(--mm-ai-chat-border);border-left:3px solid var(--mm-ai-chat-accent-assistant);border-radius:.5rem;padding:.6rem .75rem;display:flex;flex-direction:column;gap:.5rem}.mm-ai-chat__bubble-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__role{font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mm-ai-chat-accent-assistant)}.mm-ai-chat__meta{font-family:Roboto Mono,monospace;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__time{margin-left:auto;font-variant-numeric:tabular-nums;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__text{margin:0;white-space:pre-wrap;word-break:break-word}.mm-ai-chat__tool-use{border:1px solid var(--mm-ai-chat-border);border-left:2px solid var(--mm-ai-chat-accent-tool);border-radius:.35rem;background:var(--mm-ai-chat-card-bg-elevated);padding:.4rem .5rem}.mm-ai-chat__tool-use-header{display:flex;align-items:baseline;gap:.4rem;font-size:.7rem}.mm-ai-chat__tool-badge{background:var(--mm-ai-chat-accent-tool);color:#07172b;padding:0 6px;border-radius:.25rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:.65rem}.mm-ai-chat__tool-name{font-family:Roboto Mono,monospace;color:var(--mm-ai-chat-text);font-weight:600}.mm-ai-chat__tool-input{margin:.35rem 0 0;font-family:Roboto Mono,monospace;font-size:.75rem;white-space:pre-wrap;word-break:break-word;color:var(--mm-ai-chat-muted);max-height:14rem;overflow-y:auto}.mm-ai-chat__tool-result{background:var(--mm-ai-chat-card-bg);border:1px solid var(--mm-ai-chat-border);border-left:3px solid var(--mm-ai-chat-accent-tool-result);border-radius:.5rem;padding:.55rem .75rem;margin-left:1.25rem}.mm-ai-chat__tool-result--error{border-left-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__tool-result-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__tool-result-header .mm-ai-chat__role{color:var(--mm-ai-chat-accent-tool-result)}.mm-ai-chat__error-badge{background:var(--mm-ai-chat-accent-error);color:#07172b;padding:0 6px;border-radius:.25rem;font-size:.6rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.mm-ai-chat__tool-result-body{margin:.4rem 0 0;font-family:Roboto Mono,monospace;font-size:.75rem;white-space:pre-wrap;word-break:break-word;max-height:18rem;overflow-y:auto}.mm-ai-chat__result{background:var(--mm-ai-chat-card-bg-elevated);border:1px solid var(--mm-ai-chat-border-strong);border-top:3px solid var(--mm-ai-chat-accent-result);border-radius:.5rem;padding:.7rem .85rem;display:flex;flex-direction:column;gap:.5rem}.mm-ai-chat__result--error{border-top-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__result-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__result-header .mm-ai-chat__role{color:var(--mm-ai-chat-accent-result);text-transform:uppercase}.mm-ai-chat__result-text{margin:0;white-space:pre-wrap;word-break:break-word;font-style:italic;color:var(--mm-ai-chat-text)}.mm-ai-chat__result-stats{margin:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(7rem,1fr));gap:.5rem;font-family:Roboto Mono,monospace;font-size:.75rem}.mm-ai-chat__result-stats div{display:flex;flex-direction:column;gap:.2rem;padding:.4rem .5rem;background:#64ceb90f;border-radius:.3rem}.mm-ai-chat__result-stats dt{font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;color:var(--mm-ai-chat-muted)}.mm-ai-chat__result-stats dd{margin:0;color:var(--mm-ai-chat-text);font-variant-numeric:tabular-nums}.mm-ai-chat__system{all:unset;cursor:pointer;display:flex;align-items:center;gap:.5rem;padding:.35rem .6rem;background:#64ceb908;border:1px solid var(--mm-ai-chat-border);border-left:2px solid var(--mm-ai-chat-accent-system);border-radius:.4rem;font-size:.78rem;color:var(--mm-ai-chat-muted);transition:background-color .15s ease}.mm-ai-chat__system:hover{background:#64ceb90f}.mm-ai-chat__system:focus-visible{outline:2px solid var(--mm-ai-chat-accent-assistant);outline-offset:1px}.mm-ai-chat__system--init{border-left-color:var(--mm-ai-chat-accent-tool)}.mm-ai-chat__system--hook{border-left-color:var(--mm-ai-chat-accent-system)}.mm-ai-chat__system--rate{border-left-color:var(--mm-ai-chat-accent-rate-limit)}.mm-ai-chat__system--unknown{border-left-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__system-chevron{font-size:.7rem;width:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__system-summary{flex:1;color:var(--mm-ai-chat-text);font-variant-numeric:tabular-nums}.mm-ai-chat__system-detail{margin:-.25rem 0 0 1.5rem;padding:.5rem .6rem;background:#00000040;border-radius:.35rem;font-family:Roboto Mono,monospace;font-size:.7rem;white-space:pre-wrap;word-break:break-word;max-height:22rem;overflow-y:auto;color:var(--mm-ai-chat-muted)}.mm-ai-chat__status{display:flex;align-items:baseline;gap:.5rem;padding:.25rem .5rem;font-size:.7rem;color:var(--mm-ai-chat-muted);text-transform:uppercase;letter-spacing:.06em}.mm-ai-chat__status-label{color:var(--mm-ai-chat-muted)}.mm-ai-chat__status-value{color:var(--mm-ai-chat-text);font-weight:600}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
877
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiChatStreamComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
878
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: AiChatStreamComponent, isStandalone: true, selector: "mm-ai-chat-stream", inputs: { events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mm-ai-chat\">\n @for (parsed of parsedEvents(); track parsed.event.sequence) {\n @switch (parsed.view.kind) {\n @case ('assistant') {\n <article class=\"mm-ai-chat__bubble mm-ai-chat__bubble--assistant\">\n <header class=\"mm-ai-chat__bubble-header\">\n <span class=\"mm-ai-chat__role\">Assistant</span>\n @if (parsed.view.model; as model) {\n <span class=\"mm-ai-chat__meta\">{{ model }}</span>\n }\n @if (parsed.view.usage; as usage) {\n <span class=\"mm-ai-chat__meta\">\n {{ formatTokenCount(usage.input + usage.output) }}\n </span>\n }\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n @for (part of parsed.view.parts; track $index) {\n @switch (part.type) {\n @case ('text') {\n <p class=\"mm-ai-chat__text\">{{ part.text }}</p>\n }\n @case ('tool_use') {\n <div class=\"mm-ai-chat__tool-use\">\n <header class=\"mm-ai-chat__tool-use-header\">\n <span class=\"mm-ai-chat__tool-badge\">tool</span>\n <span class=\"mm-ai-chat__tool-name\">{{ part.toolName }}</span>\n </header>\n <pre class=\"mm-ai-chat__tool-input\">{{ formatRaw(part.input) }}</pre>\n </div>\n }\n }\n }\n </article>\n }\n\n @case ('tool-result') {\n <article\n class=\"mm-ai-chat__tool-result\"\n [class.mm-ai-chat__tool-result--error]=\"parsed.view.isError\"\n >\n <header class=\"mm-ai-chat__tool-result-header\">\n <span class=\"mm-ai-chat__role\">Tool result</span>\n @if (parsed.view.isError) {\n <span class=\"mm-ai-chat__error-badge\">error</span>\n }\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n <pre class=\"mm-ai-chat__tool-result-body\">{{ parsed.view.content }}</pre>\n </article>\n }\n\n @case ('result') {\n <article class=\"mm-ai-chat__result\"\n [class.mm-ai-chat__result--error]=\"parsed.view.isError\">\n <header class=\"mm-ai-chat__result-header\">\n <span class=\"mm-ai-chat__role\">{{ parsed.view.reason }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n @if (parsed.view.text) {\n <p class=\"mm-ai-chat__result-text\">{{ parsed.view.text }}</p>\n }\n <dl class=\"mm-ai-chat__result-stats\">\n <div>\n <dt>Duration</dt>\n <dd>{{ formatDuration(parsed.view.durationMs) }}</dd>\n </div>\n <div>\n <dt>Tokens (in/out)</dt>\n <dd>\n @if (parsed.view.usage) {\n {{ formatTokenCount(parsed.view.usage.input) }}\n /\n {{ formatTokenCount(parsed.view.usage.output) }}\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div>\n <dt>Cost</dt>\n <dd>{{ formatCost(parsed.view.costUsd) }}</dd>\n </div>\n </dl>\n </article>\n }\n\n @case ('system') {\n <button\n type=\"button\"\n class=\"mm-ai-chat__system\"\n [class.mm-ai-chat__system--init]=\"parsed.view.subKind === 'init'\"\n [class.mm-ai-chat__system--hook]=\"parsed.view.subKind === 'hook'\"\n [class.mm-ai-chat__system--rate]=\"parsed.view.subKind === 'rate-limit'\"\n [attr.aria-expanded]=\"isExpanded(parsed.event.sequence)\"\n (click)=\"toggleRaw(parsed.event.sequence)\"\n >\n <span class=\"mm-ai-chat__system-chevron\">\n {{ isExpanded(parsed.event.sequence) ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-chat__system-summary\">{{ parsed.view.summary }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </button>\n @if (isExpanded(parsed.event.sequence)) {\n <pre class=\"mm-ai-chat__system-detail\">{{ formatRaw(parsed.view.raw) }}</pre>\n }\n }\n\n @case ('status-change') {\n <div class=\"mm-ai-chat__status\">\n <span class=\"mm-ai-chat__status-label\">Status</span>\n <span class=\"mm-ai-chat__status-value\">{{ parsed.view.status }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </div>\n }\n\n @case ('unknown') {\n <button\n type=\"button\"\n class=\"mm-ai-chat__system mm-ai-chat__system--unknown\"\n [attr.aria-expanded]=\"isExpanded(parsed.event.sequence)\"\n (click)=\"toggleRaw(parsed.event.sequence)\"\n >\n <span class=\"mm-ai-chat__system-chevron\">\n {{ isExpanded(parsed.event.sequence) ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-chat__system-summary\">{{ parsed.view.summary }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </button>\n @if (isExpanded(parsed.event.sequence)) {\n <pre class=\"mm-ai-chat__system-detail\">{{ formatRaw(parsed.view.raw) }}</pre>\n }\n }\n }\n } @empty {\n <div class=\"mm-ai-chat__empty\">\n No events yet \u2014 the worker hasn't emitted anything.\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-chat-bg: transparent;--mm-ai-chat-card-bg: rgba(31, 46, 64, .55);--mm-ai-chat-card-bg-elevated: rgba(31, 46, 64, .85);--mm-ai-chat-border: rgba(100, 206, 185, .18);--mm-ai-chat-border-strong: rgba(100, 206, 185, .4);--mm-ai-chat-text: #e6e6e6;--mm-ai-chat-muted: #9292a6;--mm-ai-chat-accent-assistant: #64ceb9;--mm-ai-chat-accent-tool: #00a8dc;--mm-ai-chat-accent-tool-result: #00a8dc;--mm-ai-chat-accent-system: #6c4da8;--mm-ai-chat-accent-rate-limit: #da9162;--mm-ai-chat-accent-result: #64ceb9;--mm-ai-chat-accent-error: #ec658f}.mm-ai-chat{display:flex;flex-direction:column;gap:.5rem;padding:.25rem;background:var(--mm-ai-chat-bg);color:var(--mm-ai-chat-text);font-size:.85rem;line-height:1.45}.mm-ai-chat__empty{color:var(--mm-ai-chat-muted);text-align:center;padding:1.5rem;font-style:italic}.mm-ai-chat__bubble{background:var(--mm-ai-chat-card-bg);border:1px solid var(--mm-ai-chat-border);border-left:3px solid var(--mm-ai-chat-accent-assistant);border-radius:.5rem;padding:.6rem .75rem;display:flex;flex-direction:column;gap:.5rem}.mm-ai-chat__bubble-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__role{font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mm-ai-chat-accent-assistant)}.mm-ai-chat__meta{font-family:Roboto Mono,monospace;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__time{margin-left:auto;font-variant-numeric:tabular-nums;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__text{margin:0;white-space:pre-wrap;word-break:break-word}.mm-ai-chat__tool-use{border:1px solid var(--mm-ai-chat-border);border-left:2px solid var(--mm-ai-chat-accent-tool);border-radius:.35rem;background:var(--mm-ai-chat-card-bg-elevated);padding:.4rem .5rem}.mm-ai-chat__tool-use-header{display:flex;align-items:baseline;gap:.4rem;font-size:.7rem}.mm-ai-chat__tool-badge{background:var(--mm-ai-chat-accent-tool);color:#07172b;padding:0 6px;border-radius:.25rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:.65rem}.mm-ai-chat__tool-name{font-family:Roboto Mono,monospace;color:var(--mm-ai-chat-text);font-weight:600}.mm-ai-chat__tool-input{margin:.35rem 0 0;font-family:Roboto Mono,monospace;font-size:.75rem;white-space:pre-wrap;word-break:break-word;color:var(--mm-ai-chat-muted);max-height:14rem;overflow-y:auto}.mm-ai-chat__tool-result{background:var(--mm-ai-chat-card-bg);border:1px solid var(--mm-ai-chat-border);border-left:3px solid var(--mm-ai-chat-accent-tool-result);border-radius:.5rem;padding:.55rem .75rem;margin-left:1.25rem}.mm-ai-chat__tool-result--error{border-left-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__tool-result-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__tool-result-header .mm-ai-chat__role{color:var(--mm-ai-chat-accent-tool-result)}.mm-ai-chat__error-badge{background:var(--mm-ai-chat-accent-error);color:#07172b;padding:0 6px;border-radius:.25rem;font-size:.6rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.mm-ai-chat__tool-result-body{margin:.4rem 0 0;font-family:Roboto Mono,monospace;font-size:.75rem;white-space:pre-wrap;word-break:break-word;max-height:18rem;overflow-y:auto}.mm-ai-chat__result{background:var(--mm-ai-chat-card-bg-elevated);border:1px solid var(--mm-ai-chat-border-strong);border-top:3px solid var(--mm-ai-chat-accent-result);border-radius:.5rem;padding:.7rem .85rem;display:flex;flex-direction:column;gap:.5rem}.mm-ai-chat__result--error{border-top-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__result-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__result-header .mm-ai-chat__role{color:var(--mm-ai-chat-accent-result);text-transform:uppercase}.mm-ai-chat__result-text{margin:0;white-space:pre-wrap;word-break:break-word;font-style:italic;color:var(--mm-ai-chat-text)}.mm-ai-chat__result-stats{margin:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(7rem,1fr));gap:.5rem;font-family:Roboto Mono,monospace;font-size:.75rem}.mm-ai-chat__result-stats div{display:flex;flex-direction:column;gap:.2rem;padding:.4rem .5rem;background:#64ceb90f;border-radius:.3rem}.mm-ai-chat__result-stats dt{font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;color:var(--mm-ai-chat-muted)}.mm-ai-chat__result-stats dd{margin:0;color:var(--mm-ai-chat-text);font-variant-numeric:tabular-nums}.mm-ai-chat__system{all:unset;cursor:pointer;display:flex;align-items:center;gap:.5rem;padding:.35rem .6rem;background:#64ceb908;border:1px solid var(--mm-ai-chat-border);border-left:2px solid var(--mm-ai-chat-accent-system);border-radius:.4rem;font-size:.78rem;color:var(--mm-ai-chat-muted);transition:background-color .15s ease}.mm-ai-chat__system:hover{background:#64ceb90f}.mm-ai-chat__system:focus-visible{outline:2px solid var(--mm-ai-chat-accent-assistant);outline-offset:1px}.mm-ai-chat__system--init{border-left-color:var(--mm-ai-chat-accent-tool)}.mm-ai-chat__system--hook{border-left-color:var(--mm-ai-chat-accent-system)}.mm-ai-chat__system--rate{border-left-color:var(--mm-ai-chat-accent-rate-limit)}.mm-ai-chat__system--unknown{border-left-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__system-chevron{font-size:.7rem;width:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__system-summary{flex:1;color:var(--mm-ai-chat-text);font-variant-numeric:tabular-nums}.mm-ai-chat__system-detail{margin:-.25rem 0 0 1.5rem;padding:.5rem .6rem;background:#00000040;border-radius:.35rem;font-family:Roboto Mono,monospace;font-size:.7rem;white-space:pre-wrap;word-break:break-word;max-height:22rem;overflow-y:auto;color:var(--mm-ai-chat-muted)}.mm-ai-chat__status{display:flex;align-items:baseline;gap:.5rem;padding:.25rem .5rem;font-size:.7rem;color:var(--mm-ai-chat-muted);text-transform:uppercase;letter-spacing:.06em}.mm-ai-chat__status-label{color:var(--mm-ai-chat-muted)}.mm-ai-chat__status-value{color:var(--mm-ai-chat-text);font-weight:600}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
871
879
  }
872
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiChatStreamComponent, decorators: [{
880
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiChatStreamComponent, decorators: [{
873
881
  type: Component,
874
882
  args: [{ selector: 'mm-ai-chat-stream', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mm-ai-chat\">\n @for (parsed of parsedEvents(); track parsed.event.sequence) {\n @switch (parsed.view.kind) {\n @case ('assistant') {\n <article class=\"mm-ai-chat__bubble mm-ai-chat__bubble--assistant\">\n <header class=\"mm-ai-chat__bubble-header\">\n <span class=\"mm-ai-chat__role\">Assistant</span>\n @if (parsed.view.model; as model) {\n <span class=\"mm-ai-chat__meta\">{{ model }}</span>\n }\n @if (parsed.view.usage; as usage) {\n <span class=\"mm-ai-chat__meta\">\n {{ formatTokenCount(usage.input + usage.output) }}\n </span>\n }\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n @for (part of parsed.view.parts; track $index) {\n @switch (part.type) {\n @case ('text') {\n <p class=\"mm-ai-chat__text\">{{ part.text }}</p>\n }\n @case ('tool_use') {\n <div class=\"mm-ai-chat__tool-use\">\n <header class=\"mm-ai-chat__tool-use-header\">\n <span class=\"mm-ai-chat__tool-badge\">tool</span>\n <span class=\"mm-ai-chat__tool-name\">{{ part.toolName }}</span>\n </header>\n <pre class=\"mm-ai-chat__tool-input\">{{ formatRaw(part.input) }}</pre>\n </div>\n }\n }\n }\n </article>\n }\n\n @case ('tool-result') {\n <article\n class=\"mm-ai-chat__tool-result\"\n [class.mm-ai-chat__tool-result--error]=\"parsed.view.isError\"\n >\n <header class=\"mm-ai-chat__tool-result-header\">\n <span class=\"mm-ai-chat__role\">Tool result</span>\n @if (parsed.view.isError) {\n <span class=\"mm-ai-chat__error-badge\">error</span>\n }\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n <pre class=\"mm-ai-chat__tool-result-body\">{{ parsed.view.content }}</pre>\n </article>\n }\n\n @case ('result') {\n <article class=\"mm-ai-chat__result\"\n [class.mm-ai-chat__result--error]=\"parsed.view.isError\">\n <header class=\"mm-ai-chat__result-header\">\n <span class=\"mm-ai-chat__role\">{{ parsed.view.reason }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </header>\n @if (parsed.view.text) {\n <p class=\"mm-ai-chat__result-text\">{{ parsed.view.text }}</p>\n }\n <dl class=\"mm-ai-chat__result-stats\">\n <div>\n <dt>Duration</dt>\n <dd>{{ formatDuration(parsed.view.durationMs) }}</dd>\n </div>\n <div>\n <dt>Tokens (in/out)</dt>\n <dd>\n @if (parsed.view.usage) {\n {{ formatTokenCount(parsed.view.usage.input) }}\n /\n {{ formatTokenCount(parsed.view.usage.output) }}\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div>\n <dt>Cost</dt>\n <dd>{{ formatCost(parsed.view.costUsd) }}</dd>\n </div>\n </dl>\n </article>\n }\n\n @case ('system') {\n <button\n type=\"button\"\n class=\"mm-ai-chat__system\"\n [class.mm-ai-chat__system--init]=\"parsed.view.subKind === 'init'\"\n [class.mm-ai-chat__system--hook]=\"parsed.view.subKind === 'hook'\"\n [class.mm-ai-chat__system--rate]=\"parsed.view.subKind === 'rate-limit'\"\n [attr.aria-expanded]=\"isExpanded(parsed.event.sequence)\"\n (click)=\"toggleRaw(parsed.event.sequence)\"\n >\n <span class=\"mm-ai-chat__system-chevron\">\n {{ isExpanded(parsed.event.sequence) ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-chat__system-summary\">{{ parsed.view.summary }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </button>\n @if (isExpanded(parsed.event.sequence)) {\n <pre class=\"mm-ai-chat__system-detail\">{{ formatRaw(parsed.view.raw) }}</pre>\n }\n }\n\n @case ('status-change') {\n <div class=\"mm-ai-chat__status\">\n <span class=\"mm-ai-chat__status-label\">Status</span>\n <span class=\"mm-ai-chat__status-value\">{{ parsed.view.status }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </div>\n }\n\n @case ('unknown') {\n <button\n type=\"button\"\n class=\"mm-ai-chat__system mm-ai-chat__system--unknown\"\n [attr.aria-expanded]=\"isExpanded(parsed.event.sequence)\"\n (click)=\"toggleRaw(parsed.event.sequence)\"\n >\n <span class=\"mm-ai-chat__system-chevron\">\n {{ isExpanded(parsed.event.sequence) ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-chat__system-summary\">{{ parsed.view.summary }}</span>\n <time class=\"mm-ai-chat__time\">{{ formatTime(parsed.event.at) }}</time>\n </button>\n @if (isExpanded(parsed.event.sequence)) {\n <pre class=\"mm-ai-chat__system-detail\">{{ formatRaw(parsed.view.raw) }}</pre>\n }\n }\n }\n } @empty {\n <div class=\"mm-ai-chat__empty\">\n No events yet \u2014 the worker hasn't emitted anything.\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-chat-bg: transparent;--mm-ai-chat-card-bg: rgba(31, 46, 64, .55);--mm-ai-chat-card-bg-elevated: rgba(31, 46, 64, .85);--mm-ai-chat-border: rgba(100, 206, 185, .18);--mm-ai-chat-border-strong: rgba(100, 206, 185, .4);--mm-ai-chat-text: #e6e6e6;--mm-ai-chat-muted: #9292a6;--mm-ai-chat-accent-assistant: #64ceb9;--mm-ai-chat-accent-tool: #00a8dc;--mm-ai-chat-accent-tool-result: #00a8dc;--mm-ai-chat-accent-system: #6c4da8;--mm-ai-chat-accent-rate-limit: #da9162;--mm-ai-chat-accent-result: #64ceb9;--mm-ai-chat-accent-error: #ec658f}.mm-ai-chat{display:flex;flex-direction:column;gap:.5rem;padding:.25rem;background:var(--mm-ai-chat-bg);color:var(--mm-ai-chat-text);font-size:.85rem;line-height:1.45}.mm-ai-chat__empty{color:var(--mm-ai-chat-muted);text-align:center;padding:1.5rem;font-style:italic}.mm-ai-chat__bubble{background:var(--mm-ai-chat-card-bg);border:1px solid var(--mm-ai-chat-border);border-left:3px solid var(--mm-ai-chat-accent-assistant);border-radius:.5rem;padding:.6rem .75rem;display:flex;flex-direction:column;gap:.5rem}.mm-ai-chat__bubble-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__role{font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mm-ai-chat-accent-assistant)}.mm-ai-chat__meta{font-family:Roboto Mono,monospace;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__time{margin-left:auto;font-variant-numeric:tabular-nums;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__text{margin:0;white-space:pre-wrap;word-break:break-word}.mm-ai-chat__tool-use{border:1px solid var(--mm-ai-chat-border);border-left:2px solid var(--mm-ai-chat-accent-tool);border-radius:.35rem;background:var(--mm-ai-chat-card-bg-elevated);padding:.4rem .5rem}.mm-ai-chat__tool-use-header{display:flex;align-items:baseline;gap:.4rem;font-size:.7rem}.mm-ai-chat__tool-badge{background:var(--mm-ai-chat-accent-tool);color:#07172b;padding:0 6px;border-radius:.25rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:.65rem}.mm-ai-chat__tool-name{font-family:Roboto Mono,monospace;color:var(--mm-ai-chat-text);font-weight:600}.mm-ai-chat__tool-input{margin:.35rem 0 0;font-family:Roboto Mono,monospace;font-size:.75rem;white-space:pre-wrap;word-break:break-word;color:var(--mm-ai-chat-muted);max-height:14rem;overflow-y:auto}.mm-ai-chat__tool-result{background:var(--mm-ai-chat-card-bg);border:1px solid var(--mm-ai-chat-border);border-left:3px solid var(--mm-ai-chat-accent-tool-result);border-radius:.5rem;padding:.55rem .75rem;margin-left:1.25rem}.mm-ai-chat__tool-result--error{border-left-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__tool-result-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__tool-result-header .mm-ai-chat__role{color:var(--mm-ai-chat-accent-tool-result)}.mm-ai-chat__error-badge{background:var(--mm-ai-chat-accent-error);color:#07172b;padding:0 6px;border-radius:.25rem;font-size:.6rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.mm-ai-chat__tool-result-body{margin:.4rem 0 0;font-family:Roboto Mono,monospace;font-size:.75rem;white-space:pre-wrap;word-break:break-word;max-height:18rem;overflow-y:auto}.mm-ai-chat__result{background:var(--mm-ai-chat-card-bg-elevated);border:1px solid var(--mm-ai-chat-border-strong);border-top:3px solid var(--mm-ai-chat-accent-result);border-radius:.5rem;padding:.7rem .85rem;display:flex;flex-direction:column;gap:.5rem}.mm-ai-chat__result--error{border-top-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__result-header{display:flex;align-items:baseline;gap:.5rem;font-size:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__result-header .mm-ai-chat__role{color:var(--mm-ai-chat-accent-result);text-transform:uppercase}.mm-ai-chat__result-text{margin:0;white-space:pre-wrap;word-break:break-word;font-style:italic;color:var(--mm-ai-chat-text)}.mm-ai-chat__result-stats{margin:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(7rem,1fr));gap:.5rem;font-family:Roboto Mono,monospace;font-size:.75rem}.mm-ai-chat__result-stats div{display:flex;flex-direction:column;gap:.2rem;padding:.4rem .5rem;background:#64ceb90f;border-radius:.3rem}.mm-ai-chat__result-stats dt{font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;color:var(--mm-ai-chat-muted)}.mm-ai-chat__result-stats dd{margin:0;color:var(--mm-ai-chat-text);font-variant-numeric:tabular-nums}.mm-ai-chat__system{all:unset;cursor:pointer;display:flex;align-items:center;gap:.5rem;padding:.35rem .6rem;background:#64ceb908;border:1px solid var(--mm-ai-chat-border);border-left:2px solid var(--mm-ai-chat-accent-system);border-radius:.4rem;font-size:.78rem;color:var(--mm-ai-chat-muted);transition:background-color .15s ease}.mm-ai-chat__system:hover{background:#64ceb90f}.mm-ai-chat__system:focus-visible{outline:2px solid var(--mm-ai-chat-accent-assistant);outline-offset:1px}.mm-ai-chat__system--init{border-left-color:var(--mm-ai-chat-accent-tool)}.mm-ai-chat__system--hook{border-left-color:var(--mm-ai-chat-accent-system)}.mm-ai-chat__system--rate{border-left-color:var(--mm-ai-chat-accent-rate-limit)}.mm-ai-chat__system--unknown{border-left-color:var(--mm-ai-chat-accent-error)}.mm-ai-chat__system-chevron{font-size:.7rem;width:.7rem;color:var(--mm-ai-chat-muted)}.mm-ai-chat__system-summary{flex:1;color:var(--mm-ai-chat-text);font-variant-numeric:tabular-nums}.mm-ai-chat__system-detail{margin:-.25rem 0 0 1.5rem;padding:.5rem .6rem;background:#00000040;border-radius:.35rem;font-family:Roboto Mono,monospace;font-size:.7rem;white-space:pre-wrap;word-break:break-word;max-height:22rem;overflow-y:auto;color:var(--mm-ai-chat-muted)}.mm-ai-chat__status{display:flex;align-items:baseline;gap:.5rem;padding:.25rem .5rem;font-size:.7rem;color:var(--mm-ai-chat-muted);text-transform:uppercase;letter-spacing:.06em}.mm-ai-chat__status-label{color:var(--mm-ai-chat-muted)}.mm-ai-chat__status-value{color:var(--mm-ai-chat-text);font-weight:600}\n"] }]
875
883
  }], propDecorators: { events: [{ type: i0.Input, args: [{ isSignal: true, alias: "events", required: true }] }] } });
@@ -880,8 +888,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
880
888
  * pretty-printed JSON so the host doesn't need its own json formatter.
881
889
  */
882
890
  class AiToolCallComponent {
883
- call = input.required(...(ngDevMode ? [{ debugName: "call" }] : /* istanbul ignore next */ []));
884
- expanded = signal(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
891
+ call = input.required(/* @ts-ignore */
892
+ ...(ngDevMode ? [{ debugName: "call" }] : /* istanbul ignore next */ []));
893
+ expanded = signal(false, /* @ts-ignore */
894
+ ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
885
895
  statusVariant = computed(() => {
886
896
  const status = this.call().status;
887
897
  switch (status) {
@@ -897,12 +907,15 @@ class AiToolCallComponent {
897
907
  default:
898
908
  return 'pending';
899
909
  }
900
- }, ...(ngDevMode ? [{ debugName: "statusVariant" }] : /* istanbul ignore next */ []));
901
- argumentsJson = computed(() => this.format(this.call().arguments), ...(ngDevMode ? [{ debugName: "argumentsJson" }] : /* istanbul ignore next */ []));
910
+ }, /* @ts-ignore */
911
+ ...(ngDevMode ? [{ debugName: "statusVariant" }] : /* istanbul ignore next */ []));
912
+ argumentsJson = computed(() => this.format(this.call().arguments), /* @ts-ignore */
913
+ ...(ngDevMode ? [{ debugName: "argumentsJson" }] : /* istanbul ignore next */ []));
902
914
  resultJson = computed(() => {
903
915
  const result = this.call().result;
904
916
  return result === undefined ? null : this.format(result);
905
- }, ...(ngDevMode ? [{ debugName: "resultJson" }] : /* istanbul ignore next */ []));
917
+ }, /* @ts-ignore */
918
+ ...(ngDevMode ? [{ debugName: "resultJson" }] : /* istanbul ignore next */ []));
906
919
  toggleExpanded() {
907
920
  this.expanded.update((v) => !v);
908
921
  }
@@ -917,10 +930,10 @@ class AiToolCallComponent {
917
930
  return String(value);
918
931
  }
919
932
  }
920
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiToolCallComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
921
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AiToolCallComponent, isStandalone: true, selector: "mm-ai-tool-call", inputs: { call: { classPropertyName: "call", publicName: "call", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mm-ai-tool-call mm-ai-tool-call--{{ statusVariant() }}\">\n <button\n type=\"button\"\n class=\"mm-ai-tool-call__header\"\n (click)=\"toggleExpanded()\"\n [attr.aria-expanded]=\"expanded()\"\n >\n <span class=\"mm-ai-tool-call__chevron\">\n {{ expanded() ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-tool-call__name\">{{ call().toolName }}</span>\n <span class=\"mm-ai-tool-call__status\">{{ call().status }}</span>\n @if (call().durationMs != null) {\n <span class=\"mm-ai-tool-call__duration\">\n {{ call().durationMs }}ms\n </span>\n }\n </button>\n\n @if (expanded()) {\n <div class=\"mm-ai-tool-call__body\">\n <div class=\"mm-ai-tool-call__section\">\n <h4 class=\"mm-ai-tool-call__heading\">Arguments</h4>\n <pre class=\"mm-ai-tool-call__code\">{{ argumentsJson() }}</pre>\n </div>\n\n @if (resultJson() !== null) {\n <div class=\"mm-ai-tool-call__section\">\n <h4 class=\"mm-ai-tool-call__heading\">Result</h4>\n <pre class=\"mm-ai-tool-call__code\">{{ resultJson() }}</pre>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-tool-bg: #1f2227;--mm-ai-tool-border: #2f343b;--mm-ai-tool-text: #e6e6e6;--mm-ai-tool-muted: #9aa0a6;--mm-ai-tool-success: #2ea44f;--mm-ai-tool-failed: #d73a49;--mm-ai-tool-rejected: #d29922;--mm-ai-tool-pending: #6e7681;--mm-ai-tool-code-bg: #16191d}.mm-ai-tool-call{border:1px solid var(--mm-ai-tool-border);border-radius:.5rem;background:var(--mm-ai-tool-bg);color:var(--mm-ai-tool-text);margin:.4rem 0;overflow:hidden}.mm-ai-tool-call--succeeded{border-left:3px solid var(--mm-ai-tool-success)}.mm-ai-tool-call--failed{border-left:3px solid var(--mm-ai-tool-failed)}.mm-ai-tool-call--rejected{border-left:3px solid var(--mm-ai-tool-rejected)}.mm-ai-tool-call--pending{border-left:3px solid var(--mm-ai-tool-pending)}.mm-ai-tool-call__header{width:100%;display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;color:inherit;border:none;cursor:pointer;text-align:left;font-family:inherit;font-size:.9rem}.mm-ai-tool-call__header:hover{background:#ffffff0a}.mm-ai-tool-call__chevron{width:1rem;text-align:center;color:var(--mm-ai-tool-muted)}.mm-ai-tool-call__name{font-weight:600;flex:1}.mm-ai-tool-call__status,.mm-ai-tool-call__duration{font-size:.75rem;color:var(--mm-ai-tool-muted);font-variant-numeric:tabular-nums}.mm-ai-tool-call__body{border-top:1px solid var(--mm-ai-tool-border);padding:.5rem .75rem}.mm-ai-tool-call__section+.mm-ai-tool-call__section{margin-top:.75rem}.mm-ai-tool-call__heading{margin:0 0 .25rem;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;color:var(--mm-ai-tool-muted)}.mm-ai-tool-call__code{margin:0;padding:.5rem .6rem;background:var(--mm-ai-tool-code-bg);border-radius:.3rem;font-size:.8rem;overflow-x:auto;white-space:pre-wrap;word-break:break-word}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
933
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiToolCallComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
934
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: AiToolCallComponent, isStandalone: true, selector: "mm-ai-tool-call", inputs: { call: { classPropertyName: "call", publicName: "call", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mm-ai-tool-call mm-ai-tool-call--{{ statusVariant() }}\">\n <button\n type=\"button\"\n class=\"mm-ai-tool-call__header\"\n (click)=\"toggleExpanded()\"\n [attr.aria-expanded]=\"expanded()\"\n >\n <span class=\"mm-ai-tool-call__chevron\">\n {{ expanded() ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-tool-call__name\">{{ call().toolName }}</span>\n <span class=\"mm-ai-tool-call__status\">{{ call().status }}</span>\n @if (call().durationMs != null) {\n <span class=\"mm-ai-tool-call__duration\">\n {{ call().durationMs }}ms\n </span>\n }\n </button>\n\n @if (expanded()) {\n <div class=\"mm-ai-tool-call__body\">\n <div class=\"mm-ai-tool-call__section\">\n <h4 class=\"mm-ai-tool-call__heading\">Arguments</h4>\n <pre class=\"mm-ai-tool-call__code\">{{ argumentsJson() }}</pre>\n </div>\n\n @if (resultJson() !== null) {\n <div class=\"mm-ai-tool-call__section\">\n <h4 class=\"mm-ai-tool-call__heading\">Result</h4>\n <pre class=\"mm-ai-tool-call__code\">{{ resultJson() }}</pre>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-tool-bg: #1f2227;--mm-ai-tool-border: #2f343b;--mm-ai-tool-text: #e6e6e6;--mm-ai-tool-muted: #9aa0a6;--mm-ai-tool-success: #2ea44f;--mm-ai-tool-failed: #d73a49;--mm-ai-tool-rejected: #d29922;--mm-ai-tool-pending: #6e7681;--mm-ai-tool-code-bg: #16191d}.mm-ai-tool-call{border:1px solid var(--mm-ai-tool-border);border-radius:.5rem;background:var(--mm-ai-tool-bg);color:var(--mm-ai-tool-text);margin:.4rem 0;overflow:hidden}.mm-ai-tool-call--succeeded{border-left:3px solid var(--mm-ai-tool-success)}.mm-ai-tool-call--failed{border-left:3px solid var(--mm-ai-tool-failed)}.mm-ai-tool-call--rejected{border-left:3px solid var(--mm-ai-tool-rejected)}.mm-ai-tool-call--pending{border-left:3px solid var(--mm-ai-tool-pending)}.mm-ai-tool-call__header{width:100%;display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;color:inherit;border:none;cursor:pointer;text-align:left;font-family:inherit;font-size:.9rem}.mm-ai-tool-call__header:hover{background:#ffffff0a}.mm-ai-tool-call__chevron{width:1rem;text-align:center;color:var(--mm-ai-tool-muted)}.mm-ai-tool-call__name{font-weight:600;flex:1}.mm-ai-tool-call__status,.mm-ai-tool-call__duration{font-size:.75rem;color:var(--mm-ai-tool-muted);font-variant-numeric:tabular-nums}.mm-ai-tool-call__body{border-top:1px solid var(--mm-ai-tool-border);padding:.5rem .75rem}.mm-ai-tool-call__section+.mm-ai-tool-call__section{margin-top:.75rem}.mm-ai-tool-call__heading{margin:0 0 .25rem;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;color:var(--mm-ai-tool-muted)}.mm-ai-tool-call__code{margin:0;padding:.5rem .6rem;background:var(--mm-ai-tool-code-bg);border-radius:.3rem;font-size:.8rem;overflow-x:auto;white-space:pre-wrap;word-break:break-word}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
922
935
  }
923
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiToolCallComponent, decorators: [{
936
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiToolCallComponent, decorators: [{
924
937
  type: Component,
925
938
  args: [{ selector: 'mm-ai-tool-call', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mm-ai-tool-call mm-ai-tool-call--{{ statusVariant() }}\">\n <button\n type=\"button\"\n class=\"mm-ai-tool-call__header\"\n (click)=\"toggleExpanded()\"\n [attr.aria-expanded]=\"expanded()\"\n >\n <span class=\"mm-ai-tool-call__chevron\">\n {{ expanded() ? '\u25BE' : '\u25B8' }}\n </span>\n <span class=\"mm-ai-tool-call__name\">{{ call().toolName }}</span>\n <span class=\"mm-ai-tool-call__status\">{{ call().status }}</span>\n @if (call().durationMs != null) {\n <span class=\"mm-ai-tool-call__duration\">\n {{ call().durationMs }}ms\n </span>\n }\n </button>\n\n @if (expanded()) {\n <div class=\"mm-ai-tool-call__body\">\n <div class=\"mm-ai-tool-call__section\">\n <h4 class=\"mm-ai-tool-call__heading\">Arguments</h4>\n <pre class=\"mm-ai-tool-call__code\">{{ argumentsJson() }}</pre>\n </div>\n\n @if (resultJson() !== null) {\n <div class=\"mm-ai-tool-call__section\">\n <h4 class=\"mm-ai-tool-call__heading\">Result</h4>\n <pre class=\"mm-ai-tool-call__code\">{{ resultJson() }}</pre>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-tool-bg: #1f2227;--mm-ai-tool-border: #2f343b;--mm-ai-tool-text: #e6e6e6;--mm-ai-tool-muted: #9aa0a6;--mm-ai-tool-success: #2ea44f;--mm-ai-tool-failed: #d73a49;--mm-ai-tool-rejected: #d29922;--mm-ai-tool-pending: #6e7681;--mm-ai-tool-code-bg: #16191d}.mm-ai-tool-call{border:1px solid var(--mm-ai-tool-border);border-radius:.5rem;background:var(--mm-ai-tool-bg);color:var(--mm-ai-tool-text);margin:.4rem 0;overflow:hidden}.mm-ai-tool-call--succeeded{border-left:3px solid var(--mm-ai-tool-success)}.mm-ai-tool-call--failed{border-left:3px solid var(--mm-ai-tool-failed)}.mm-ai-tool-call--rejected{border-left:3px solid var(--mm-ai-tool-rejected)}.mm-ai-tool-call--pending{border-left:3px solid var(--mm-ai-tool-pending)}.mm-ai-tool-call__header{width:100%;display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;color:inherit;border:none;cursor:pointer;text-align:left;font-family:inherit;font-size:.9rem}.mm-ai-tool-call__header:hover{background:#ffffff0a}.mm-ai-tool-call__chevron{width:1rem;text-align:center;color:var(--mm-ai-tool-muted)}.mm-ai-tool-call__name{font-weight:600;flex:1}.mm-ai-tool-call__status,.mm-ai-tool-call__duration{font-size:.75rem;color:var(--mm-ai-tool-muted);font-variant-numeric:tabular-nums}.mm-ai-tool-call__body{border-top:1px solid var(--mm-ai-tool-border);padding:.5rem .75rem}.mm-ai-tool-call__section+.mm-ai-tool-call__section{margin-top:.75rem}.mm-ai-tool-call__heading{margin:0 0 .25rem;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;color:var(--mm-ai-tool-muted)}.mm-ai-tool-call__code{margin:0;padding:.5rem .6rem;background:var(--mm-ai-tool-code-bg);border-radius:.3rem;font-size:.8rem;overflow-x:auto;white-space:pre-wrap;word-break:break-word}\n"] }]
926
939
  }], propDecorators: { call: [{ type: i0.Input, args: [{ isSignal: true, alias: "call", required: true }] }] } });
@@ -936,10 +949,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
936
949
  * window, ng-bootstrap, …) — each host shop already has one.
937
950
  */
938
951
  class AiApprovalModalComponent {
939
- request = input.required(...(ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []));
952
+ request = input.required(/* @ts-ignore */
953
+ ...(ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []));
940
954
  decide = output();
941
955
  dismiss = output();
942
- comment = signal('', ...(ngDevMode ? [{ debugName: "comment" }] : /* istanbul ignore next */ []));
956
+ comment = signal('', /* @ts-ignore */
957
+ ...(ngDevMode ? [{ debugName: "comment" }] : /* istanbul ignore next */ []));
943
958
  prettyPayload = computed(() => {
944
959
  try {
945
960
  return JSON.stringify(JSON.parse(this.request().payload), null, 2);
@@ -947,7 +962,8 @@ class AiApprovalModalComponent {
947
962
  catch {
948
963
  return this.request().payload;
949
964
  }
950
- }, ...(ngDevMode ? [{ debugName: "prettyPayload" }] : /* istanbul ignore next */ []));
965
+ }, /* @ts-ignore */
966
+ ...(ngDevMode ? [{ debugName: "prettyPayload" }] : /* istanbul ignore next */ []));
951
967
  approve() {
952
968
  this.decide.emit({
953
969
  outcome: 'Approved',
@@ -967,10 +983,10 @@ class AiApprovalModalComponent {
967
983
  const trimmed = this.comment().trim();
968
984
  return trimmed.length > 0 ? trimmed : undefined;
969
985
  }
970
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiApprovalModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
971
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: AiApprovalModalComponent, isStandalone: true, selector: "mm-ai-approval-modal", inputs: { request: { classPropertyName: "request", publicName: "request", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { decide: "decide", dismiss: "dismiss" }, ngImport: i0, template: "<div class=\"mm-ai-approval\">\n <header class=\"mm-ai-approval__header\">\n <h3 class=\"mm-ai-approval__title\">Approve tool call</h3>\n <button\n type=\"button\"\n class=\"mm-ai-approval__close\"\n (click)=\"onDismiss()\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n </header>\n\n <div class=\"mm-ai-approval__meta\">\n <div><span>Tool:</span> <code>{{ request().toolName }}</code></div>\n <div><span>Reason:</span> <code>{{ request().reason }}</code></div>\n <div><span>Session:</span> <code>{{ request().sessionId }}</code></div>\n </div>\n\n <div class=\"mm-ai-approval__section\">\n <h4 class=\"mm-ai-approval__heading\">Payload</h4>\n <pre class=\"mm-ai-approval__code\">{{ prettyPayload() }}</pre>\n </div>\n\n <div class=\"mm-ai-approval__section\">\n <h4 class=\"mm-ai-approval__heading\">Comment <span>(optional)</span></h4>\n <textarea\n class=\"mm-ai-approval__comment\"\n [ngModel]=\"comment()\"\n (ngModelChange)=\"comment.set($event)\"\n rows=\"3\"\n placeholder=\"Why is this approved or rejected?\"\n ></textarea>\n </div>\n\n <footer class=\"mm-ai-approval__actions\">\n <button\n type=\"button\"\n class=\"mm-ai-approval__btn mm-ai-approval__btn--reject\"\n (click)=\"reject()\"\n >\n Reject\n </button>\n <button\n type=\"button\"\n class=\"mm-ai-approval__btn mm-ai-approval__btn--approve\"\n (click)=\"approve()\"\n >\n Approve\n </button>\n </footer>\n</div>\n", styles: [":host{display:block;--mm-ai-approval-bg: #1f2227;--mm-ai-approval-border: #2f343b;--mm-ai-approval-text: #e6e6e6;--mm-ai-approval-muted: #9aa0a6;--mm-ai-approval-approve: #2ea44f;--mm-ai-approval-reject: #d73a49;--mm-ai-approval-code-bg: #16191d}.mm-ai-approval{background:var(--mm-ai-approval-bg);color:var(--mm-ai-approval-text);border:1px solid var(--mm-ai-approval-border);border-radius:.6rem;padding:1rem 1.25rem;width:min(36rem,100%)}.mm-ai-approval__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.mm-ai-approval__title{margin:0;font-size:1rem}.mm-ai-approval__close{background:transparent;color:var(--mm-ai-approval-muted);border:none;font-size:1.4rem;cursor:pointer;line-height:1;padding:0 .25rem}.mm-ai-approval__close:hover{color:var(--mm-ai-approval-text)}.mm-ai-approval__meta{display:grid;gap:.25rem;font-size:.85rem;margin-bottom:.75rem}.mm-ai-approval__meta span{color:var(--mm-ai-approval-muted);margin-right:.35rem}.mm-ai-approval__meta code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.mm-ai-approval__section{margin-bottom:.75rem}.mm-ai-approval__heading{margin:0 0 .3rem;font-size:.75rem;color:var(--mm-ai-approval-muted);text-transform:uppercase;letter-spacing:.04em}.mm-ai-approval__heading span{text-transform:none;letter-spacing:0;opacity:.6}.mm-ai-approval__code{margin:0;padding:.5rem .6rem;background:var(--mm-ai-approval-code-bg);border-radius:.3rem;font-size:.8rem;overflow-x:auto;white-space:pre-wrap;word-break:break-word;max-height:14rem}.mm-ai-approval__comment{width:100%;box-sizing:border-box;padding:.5rem .6rem;background:var(--mm-ai-approval-code-bg);color:inherit;border:1px solid var(--mm-ai-approval-border);border-radius:.3rem;font-family:inherit;font-size:.85rem;resize:vertical}.mm-ai-approval__actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem}.mm-ai-approval__btn{padding:.45rem 1rem;border-radius:.3rem;font-weight:600;border:none;cursor:pointer;font-size:.85rem}.mm-ai-approval__btn--approve{background:var(--mm-ai-approval-approve);color:#fff}.mm-ai-approval__btn--reject{background:var(--mm-ai-approval-reject);color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
986
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiApprovalModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
987
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: AiApprovalModalComponent, isStandalone: true, selector: "mm-ai-approval-modal", inputs: { request: { classPropertyName: "request", publicName: "request", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { decide: "decide", dismiss: "dismiss" }, ngImport: i0, template: "<div class=\"mm-ai-approval\">\n <header class=\"mm-ai-approval__header\">\n <h3 class=\"mm-ai-approval__title\">Approve tool call</h3>\n <button\n type=\"button\"\n class=\"mm-ai-approval__close\"\n (click)=\"onDismiss()\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n </header>\n\n <div class=\"mm-ai-approval__meta\">\n <div><span>Tool:</span> <code>{{ request().toolName }}</code></div>\n <div><span>Reason:</span> <code>{{ request().reason }}</code></div>\n <div><span>Session:</span> <code>{{ request().sessionId }}</code></div>\n </div>\n\n <div class=\"mm-ai-approval__section\">\n <h4 class=\"mm-ai-approval__heading\">Payload</h4>\n <pre class=\"mm-ai-approval__code\">{{ prettyPayload() }}</pre>\n </div>\n\n <div class=\"mm-ai-approval__section\">\n <h4 class=\"mm-ai-approval__heading\">Comment <span>(optional)</span></h4>\n <textarea\n class=\"mm-ai-approval__comment\"\n [ngModel]=\"comment()\"\n (ngModelChange)=\"comment.set($event)\"\n rows=\"3\"\n placeholder=\"Why is this approved or rejected?\"\n ></textarea>\n </div>\n\n <footer class=\"mm-ai-approval__actions\">\n <button\n type=\"button\"\n class=\"mm-ai-approval__btn mm-ai-approval__btn--reject\"\n (click)=\"reject()\"\n >\n Reject\n </button>\n <button\n type=\"button\"\n class=\"mm-ai-approval__btn mm-ai-approval__btn--approve\"\n (click)=\"approve()\"\n >\n Approve\n </button>\n </footer>\n</div>\n", styles: [":host{display:block;--mm-ai-approval-bg: #1f2227;--mm-ai-approval-border: #2f343b;--mm-ai-approval-text: #e6e6e6;--mm-ai-approval-muted: #9aa0a6;--mm-ai-approval-approve: #2ea44f;--mm-ai-approval-reject: #d73a49;--mm-ai-approval-code-bg: #16191d}.mm-ai-approval{background:var(--mm-ai-approval-bg);color:var(--mm-ai-approval-text);border:1px solid var(--mm-ai-approval-border);border-radius:.6rem;padding:1rem 1.25rem;width:min(36rem,100%)}.mm-ai-approval__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.mm-ai-approval__title{margin:0;font-size:1rem}.mm-ai-approval__close{background:transparent;color:var(--mm-ai-approval-muted);border:none;font-size:1.4rem;cursor:pointer;line-height:1;padding:0 .25rem}.mm-ai-approval__close:hover{color:var(--mm-ai-approval-text)}.mm-ai-approval__meta{display:grid;gap:.25rem;font-size:.85rem;margin-bottom:.75rem}.mm-ai-approval__meta span{color:var(--mm-ai-approval-muted);margin-right:.35rem}.mm-ai-approval__meta code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.mm-ai-approval__section{margin-bottom:.75rem}.mm-ai-approval__heading{margin:0 0 .3rem;font-size:.75rem;color:var(--mm-ai-approval-muted);text-transform:uppercase;letter-spacing:.04em}.mm-ai-approval__heading span{text-transform:none;letter-spacing:0;opacity:.6}.mm-ai-approval__code{margin:0;padding:.5rem .6rem;background:var(--mm-ai-approval-code-bg);border-radius:.3rem;font-size:.8rem;overflow-x:auto;white-space:pre-wrap;word-break:break-word;max-height:14rem}.mm-ai-approval__comment{width:100%;box-sizing:border-box;padding:.5rem .6rem;background:var(--mm-ai-approval-code-bg);color:inherit;border:1px solid var(--mm-ai-approval-border);border-radius:.3rem;font-family:inherit;font-size:.85rem;resize:vertical}.mm-ai-approval__actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem}.mm-ai-approval__btn{padding:.45rem 1rem;border-radius:.3rem;font-weight:600;border:none;cursor:pointer;font-size:.85rem}.mm-ai-approval__btn--approve{background:var(--mm-ai-approval-approve);color:#fff}.mm-ai-approval__btn--reject{background:var(--mm-ai-approval-reject);color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
972
988
  }
973
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiApprovalModalComponent, decorators: [{
989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiApprovalModalComponent, decorators: [{
974
990
  type: Component,
975
991
  args: [{ selector: 'mm-ai-approval-modal', imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mm-ai-approval\">\n <header class=\"mm-ai-approval__header\">\n <h3 class=\"mm-ai-approval__title\">Approve tool call</h3>\n <button\n type=\"button\"\n class=\"mm-ai-approval__close\"\n (click)=\"onDismiss()\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n </header>\n\n <div class=\"mm-ai-approval__meta\">\n <div><span>Tool:</span> <code>{{ request().toolName }}</code></div>\n <div><span>Reason:</span> <code>{{ request().reason }}</code></div>\n <div><span>Session:</span> <code>{{ request().sessionId }}</code></div>\n </div>\n\n <div class=\"mm-ai-approval__section\">\n <h4 class=\"mm-ai-approval__heading\">Payload</h4>\n <pre class=\"mm-ai-approval__code\">{{ prettyPayload() }}</pre>\n </div>\n\n <div class=\"mm-ai-approval__section\">\n <h4 class=\"mm-ai-approval__heading\">Comment <span>(optional)</span></h4>\n <textarea\n class=\"mm-ai-approval__comment\"\n [ngModel]=\"comment()\"\n (ngModelChange)=\"comment.set($event)\"\n rows=\"3\"\n placeholder=\"Why is this approved or rejected?\"\n ></textarea>\n </div>\n\n <footer class=\"mm-ai-approval__actions\">\n <button\n type=\"button\"\n class=\"mm-ai-approval__btn mm-ai-approval__btn--reject\"\n (click)=\"reject()\"\n >\n Reject\n </button>\n <button\n type=\"button\"\n class=\"mm-ai-approval__btn mm-ai-approval__btn--approve\"\n (click)=\"approve()\"\n >\n Approve\n </button>\n </footer>\n</div>\n", styles: [":host{display:block;--mm-ai-approval-bg: #1f2227;--mm-ai-approval-border: #2f343b;--mm-ai-approval-text: #e6e6e6;--mm-ai-approval-muted: #9aa0a6;--mm-ai-approval-approve: #2ea44f;--mm-ai-approval-reject: #d73a49;--mm-ai-approval-code-bg: #16191d}.mm-ai-approval{background:var(--mm-ai-approval-bg);color:var(--mm-ai-approval-text);border:1px solid var(--mm-ai-approval-border);border-radius:.6rem;padding:1rem 1.25rem;width:min(36rem,100%)}.mm-ai-approval__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.mm-ai-approval__title{margin:0;font-size:1rem}.mm-ai-approval__close{background:transparent;color:var(--mm-ai-approval-muted);border:none;font-size:1.4rem;cursor:pointer;line-height:1;padding:0 .25rem}.mm-ai-approval__close:hover{color:var(--mm-ai-approval-text)}.mm-ai-approval__meta{display:grid;gap:.25rem;font-size:.85rem;margin-bottom:.75rem}.mm-ai-approval__meta span{color:var(--mm-ai-approval-muted);margin-right:.35rem}.mm-ai-approval__meta code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.mm-ai-approval__section{margin-bottom:.75rem}.mm-ai-approval__heading{margin:0 0 .3rem;font-size:.75rem;color:var(--mm-ai-approval-muted);text-transform:uppercase;letter-spacing:.04em}.mm-ai-approval__heading span{text-transform:none;letter-spacing:0;opacity:.6}.mm-ai-approval__code{margin:0;padding:.5rem .6rem;background:var(--mm-ai-approval-code-bg);border-radius:.3rem;font-size:.8rem;overflow-x:auto;white-space:pre-wrap;word-break:break-word;max-height:14rem}.mm-ai-approval__comment{width:100%;box-sizing:border-box;padding:.5rem .6rem;background:var(--mm-ai-approval-code-bg);color:inherit;border:1px solid var(--mm-ai-approval-border);border-radius:.3rem;font-family:inherit;font-size:.85rem;resize:vertical}.mm-ai-approval__actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem}.mm-ai-approval__btn{padding:.45rem 1rem;border-radius:.3rem;font-weight:600;border:none;cursor:pointer;font-size:.85rem}.mm-ai-approval__btn--approve{background:var(--mm-ai-approval-approve);color:#fff}.mm-ai-approval__btn--reject{background:var(--mm-ai-approval-reject);color:#fff}\n"] }]
976
992
  }], propDecorators: { request: [{ type: i0.Input, args: [{ isSignal: true, alias: "request", required: true }] }], decide: [{ type: i0.Output, args: ["decide"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }] } });
@@ -982,11 +998,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
982
998
  * adapter already aggregated.
983
999
  */
984
1000
  class AiQuotaIndicatorComponent {
985
- dailyConsumed = input.required(...(ngDevMode ? [{ debugName: "dailyConsumed" }] : /* istanbul ignore next */ []));
986
- dailyCap = input.required(...(ngDevMode ? [{ debugName: "dailyCap" }] : /* istanbul ignore next */ []));
987
- monthlyConsumed = input(null, ...(ngDevMode ? [{ debugName: "monthlyConsumed" }] : /* istanbul ignore next */ []));
988
- monthlyCap = input(null, ...(ngDevMode ? [{ debugName: "monthlyCap" }] : /* istanbul ignore next */ []));
989
- dailyPercent = computed(() => this.percent(this.dailyConsumed(), this.dailyCap()), ...(ngDevMode ? [{ debugName: "dailyPercent" }] : /* istanbul ignore next */ []));
1001
+ dailyConsumed = input.required(/* @ts-ignore */
1002
+ ...(ngDevMode ? [{ debugName: "dailyConsumed" }] : /* istanbul ignore next */ []));
1003
+ dailyCap = input.required(/* @ts-ignore */
1004
+ ...(ngDevMode ? [{ debugName: "dailyCap" }] : /* istanbul ignore next */ []));
1005
+ monthlyConsumed = input(null, /* @ts-ignore */
1006
+ ...(ngDevMode ? [{ debugName: "monthlyConsumed" }] : /* istanbul ignore next */ []));
1007
+ monthlyCap = input(null, /* @ts-ignore */
1008
+ ...(ngDevMode ? [{ debugName: "monthlyCap" }] : /* istanbul ignore next */ []));
1009
+ dailyPercent = computed(() => this.percent(this.dailyConsumed(), this.dailyCap()), /* @ts-ignore */
1010
+ ...(ngDevMode ? [{ debugName: "dailyPercent" }] : /* istanbul ignore next */ []));
990
1011
  monthlyPercent = computed(() => {
991
1012
  const consumed = this.monthlyConsumed();
992
1013
  const cap = this.monthlyCap();
@@ -994,12 +1015,15 @@ class AiQuotaIndicatorComponent {
994
1015
  return null;
995
1016
  }
996
1017
  return this.percent(consumed, cap);
997
- }, ...(ngDevMode ? [{ debugName: "monthlyPercent" }] : /* istanbul ignore next */ []));
998
- dailyState = computed(() => this.toState(this.dailyPercent()), ...(ngDevMode ? [{ debugName: "dailyState" }] : /* istanbul ignore next */ []));
1018
+ }, /* @ts-ignore */
1019
+ ...(ngDevMode ? [{ debugName: "monthlyPercent" }] : /* istanbul ignore next */ []));
1020
+ dailyState = computed(() => this.toState(this.dailyPercent()), /* @ts-ignore */
1021
+ ...(ngDevMode ? [{ debugName: "dailyState" }] : /* istanbul ignore next */ []));
999
1022
  monthlyState = computed(() => {
1000
1023
  const pct = this.monthlyPercent();
1001
1024
  return pct == null ? null : this.toState(pct);
1002
- }, ...(ngDevMode ? [{ debugName: "monthlyState" }] : /* istanbul ignore next */ []));
1025
+ }, /* @ts-ignore */
1026
+ ...(ngDevMode ? [{ debugName: "monthlyState" }] : /* istanbul ignore next */ []));
1003
1027
  percent(consumed, cap) {
1004
1028
  if (cap <= 0) {
1005
1029
  return 0;
@@ -1015,10 +1039,10 @@ class AiQuotaIndicatorComponent {
1015
1039
  }
1016
1040
  return 'ok';
1017
1041
  }
1018
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiQuotaIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1019
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AiQuotaIndicatorComponent, isStandalone: true, selector: "mm-ai-quota-indicator", inputs: { dailyConsumed: { classPropertyName: "dailyConsumed", publicName: "dailyConsumed", isSignal: true, isRequired: true, transformFunction: null }, dailyCap: { classPropertyName: "dailyCap", publicName: "dailyCap", isSignal: true, isRequired: true, transformFunction: null }, monthlyConsumed: { classPropertyName: "monthlyConsumed", publicName: "monthlyConsumed", isSignal: true, isRequired: false, transformFunction: null }, monthlyCap: { classPropertyName: "monthlyCap", publicName: "monthlyCap", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"mm-ai-quota\">\n <div class=\"mm-ai-quota__row\">\n <span class=\"mm-ai-quota__label\">Daily</span>\n <div class=\"mm-ai-quota__bar mm-ai-quota__bar--{{ dailyState() }}\">\n <div class=\"mm-ai-quota__fill\" [style.width.%]=\"dailyPercent()\"></div>\n </div>\n <span class=\"mm-ai-quota__count\">\n {{ dailyConsumed() }} / {{ dailyCap() }} ({{ dailyPercent() }}%)\n </span>\n </div>\n\n @if (monthlyPercent() !== null) {\n <div class=\"mm-ai-quota__row\">\n <span class=\"mm-ai-quota__label\">Monthly</span>\n <div class=\"mm-ai-quota__bar mm-ai-quota__bar--{{ monthlyState() }}\">\n <div class=\"mm-ai-quota__fill\" [style.width.%]=\"monthlyPercent()\"></div>\n </div>\n <span class=\"mm-ai-quota__count\">\n {{ monthlyConsumed() }} / {{ monthlyCap() }} ({{ monthlyPercent() }}%)\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-quota-track-bg: #2a2a2a;--mm-ai-quota-ok: #2ea44f;--mm-ai-quota-warning: #d29922;--mm-ai-quota-critical: #d73a49}.mm-ai-quota{display:flex;flex-direction:column;gap:.5rem;font-size:.85rem}.mm-ai-quota__row{display:grid;grid-template-columns:4.5rem 1fr auto;align-items:center;gap:.5rem}.mm-ai-quota__label{font-weight:600;opacity:.7}.mm-ai-quota__bar{height:.5rem;border-radius:9999px;background:var(--mm-ai-quota-track-bg);overflow:hidden}.mm-ai-quota__bar--ok .mm-ai-quota__fill{background:var(--mm-ai-quota-ok)}.mm-ai-quota__bar--warning .mm-ai-quota__fill{background:var(--mm-ai-quota-warning)}.mm-ai-quota__bar--critical .mm-ai-quota__fill{background:var(--mm-ai-quota-critical)}.mm-ai-quota__fill{height:100%;transition:width .2s ease}.mm-ai-quota__count{font-variant-numeric:tabular-nums;opacity:.8}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1042
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiQuotaIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: AiQuotaIndicatorComponent, isStandalone: true, selector: "mm-ai-quota-indicator", inputs: { dailyConsumed: { classPropertyName: "dailyConsumed", publicName: "dailyConsumed", isSignal: true, isRequired: true, transformFunction: null }, dailyCap: { classPropertyName: "dailyCap", publicName: "dailyCap", isSignal: true, isRequired: true, transformFunction: null }, monthlyConsumed: { classPropertyName: "monthlyConsumed", publicName: "monthlyConsumed", isSignal: true, isRequired: false, transformFunction: null }, monthlyCap: { classPropertyName: "monthlyCap", publicName: "monthlyCap", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"mm-ai-quota\">\n <div class=\"mm-ai-quota__row\">\n <span class=\"mm-ai-quota__label\">Daily</span>\n <div class=\"mm-ai-quota__bar mm-ai-quota__bar--{{ dailyState() }}\">\n <div class=\"mm-ai-quota__fill\" [style.width.%]=\"dailyPercent()\"></div>\n </div>\n <span class=\"mm-ai-quota__count\">\n {{ dailyConsumed() }} / {{ dailyCap() }} ({{ dailyPercent() }}%)\n </span>\n </div>\n\n @if (monthlyPercent() !== null) {\n <div class=\"mm-ai-quota__row\">\n <span class=\"mm-ai-quota__label\">Monthly</span>\n <div class=\"mm-ai-quota__bar mm-ai-quota__bar--{{ monthlyState() }}\">\n <div class=\"mm-ai-quota__fill\" [style.width.%]=\"monthlyPercent()\"></div>\n </div>\n <span class=\"mm-ai-quota__count\">\n {{ monthlyConsumed() }} / {{ monthlyCap() }} ({{ monthlyPercent() }}%)\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-quota-track-bg: #2a2a2a;--mm-ai-quota-ok: #2ea44f;--mm-ai-quota-warning: #d29922;--mm-ai-quota-critical: #d73a49}.mm-ai-quota{display:flex;flex-direction:column;gap:.5rem;font-size:.85rem}.mm-ai-quota__row{display:grid;grid-template-columns:4.5rem 1fr auto;align-items:center;gap:.5rem}.mm-ai-quota__label{font-weight:600;opacity:.7}.mm-ai-quota__bar{height:.5rem;border-radius:9999px;background:var(--mm-ai-quota-track-bg);overflow:hidden}.mm-ai-quota__bar--ok .mm-ai-quota__fill{background:var(--mm-ai-quota-ok)}.mm-ai-quota__bar--warning .mm-ai-quota__fill{background:var(--mm-ai-quota-warning)}.mm-ai-quota__bar--critical .mm-ai-quota__fill{background:var(--mm-ai-quota-critical)}.mm-ai-quota__fill{height:100%;transition:width .2s ease}.mm-ai-quota__count{font-variant-numeric:tabular-nums;opacity:.8}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1020
1044
  }
1021
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiQuotaIndicatorComponent, decorators: [{
1045
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiQuotaIndicatorComponent, decorators: [{
1022
1046
  type: Component,
1023
1047
  args: [{ selector: 'mm-ai-quota-indicator', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mm-ai-quota\">\n <div class=\"mm-ai-quota__row\">\n <span class=\"mm-ai-quota__label\">Daily</span>\n <div class=\"mm-ai-quota__bar mm-ai-quota__bar--{{ dailyState() }}\">\n <div class=\"mm-ai-quota__fill\" [style.width.%]=\"dailyPercent()\"></div>\n </div>\n <span class=\"mm-ai-quota__count\">\n {{ dailyConsumed() }} / {{ dailyCap() }} ({{ dailyPercent() }}%)\n </span>\n </div>\n\n @if (monthlyPercent() !== null) {\n <div class=\"mm-ai-quota__row\">\n <span class=\"mm-ai-quota__label\">Monthly</span>\n <div class=\"mm-ai-quota__bar mm-ai-quota__bar--{{ monthlyState() }}\">\n <div class=\"mm-ai-quota__fill\" [style.width.%]=\"monthlyPercent()\"></div>\n </div>\n <span class=\"mm-ai-quota__count\">\n {{ monthlyConsumed() }} / {{ monthlyCap() }} ({{ monthlyPercent() }}%)\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block;--mm-ai-quota-track-bg: #2a2a2a;--mm-ai-quota-ok: #2ea44f;--mm-ai-quota-warning: #d29922;--mm-ai-quota-critical: #d73a49}.mm-ai-quota{display:flex;flex-direction:column;gap:.5rem;font-size:.85rem}.mm-ai-quota__row{display:grid;grid-template-columns:4.5rem 1fr auto;align-items:center;gap:.5rem}.mm-ai-quota__label{font-weight:600;opacity:.7}.mm-ai-quota__bar{height:.5rem;border-radius:9999px;background:var(--mm-ai-quota-track-bg);overflow:hidden}.mm-ai-quota__bar--ok .mm-ai-quota__fill{background:var(--mm-ai-quota-ok)}.mm-ai-quota__bar--warning .mm-ai-quota__fill{background:var(--mm-ai-quota-warning)}.mm-ai-quota__bar--critical .mm-ai-quota__fill{background:var(--mm-ai-quota-critical)}.mm-ai-quota__fill{height:100%;transition:width .2s ease}.mm-ai-quota__count{font-variant-numeric:tabular-nums;opacity:.8}\n"] }]
1024
1048
  }], propDecorators: { dailyConsumed: [{ type: i0.Input, args: [{ isSignal: true, alias: "dailyConsumed", required: true }] }], dailyCap: [{ type: i0.Input, args: [{ isSignal: true, alias: "dailyCap", required: true }] }], monthlyConsumed: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthlyConsumed", required: false }] }], monthlyCap: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthlyCap", required: false }] }] } });
@@ -1036,12 +1060,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1036
1060
  */
1037
1061
  class AiCredentialTicketIssueComponent {
1038
1062
  client = inject(AiAdapterClientService);
1039
- scope = signal('CredentialRegister', ...(ngDevMode ? [{ debugName: "scope" }] : /* istanbul ignore next */ []));
1040
- ttlMinutes = signal(5, ...(ngDevMode ? [{ debugName: "ttlMinutes" }] : /* istanbul ignore next */ []));
1041
- issuing = signal(false, ...(ngDevMode ? [{ debugName: "issuing" }] : /* istanbul ignore next */ []));
1042
- issued = signal(null, ...(ngDevMode ? [{ debugName: "issued" }] : /* istanbul ignore next */ []));
1043
- error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
1044
- copied = signal(false, ...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
1063
+ scope = signal('CredentialRegister', /* @ts-ignore */
1064
+ ...(ngDevMode ? [{ debugName: "scope" }] : /* istanbul ignore next */ []));
1065
+ ttlMinutes = signal(5, /* @ts-ignore */
1066
+ ...(ngDevMode ? [{ debugName: "ttlMinutes" }] : /* istanbul ignore next */ []));
1067
+ issuing = signal(false, /* @ts-ignore */
1068
+ ...(ngDevMode ? [{ debugName: "issuing" }] : /* istanbul ignore next */ []));
1069
+ issued = signal(null, /* @ts-ignore */
1070
+ ...(ngDevMode ? [{ debugName: "issued" }] : /* istanbul ignore next */ []));
1071
+ error = signal(null, /* @ts-ignore */
1072
+ ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
1073
+ copied = signal(false, /* @ts-ignore */
1074
+ ...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
1045
1075
  /** Available scope choices — kept in sync with `AiCredentialTicketScope`. */
1046
1076
  scopes = [
1047
1077
  {
@@ -1124,10 +1154,10 @@ class AiCredentialTicketIssueComponent {
1124
1154
  }
1125
1155
  return 'Failed to reach the AI Adapter — check the network.';
1126
1156
  }
1127
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiCredentialTicketIssueComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1128
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AiCredentialTicketIssueComponent, isStandalone: true, selector: "mm-ai-credential-ticket-issue", ngImport: i0, template: "<section class=\"mm-ai-ticket\">\n <header class=\"mm-ai-ticket__header\">\n <div class=\"mm-ai-ticket__title\">Issue credential ticket</div>\n <div class=\"mm-ai-ticket__subtitle\">\n Mint a one-time code an operator redeems on their own machine.\n </div>\n </header>\n\n @if (!issued()) {\n <form\n class=\"mm-ai-ticket__form\"\n (ngSubmit)=\"onIssue()\"\n #issueForm=\"ngForm\"\n >\n <label class=\"mm-ai-ticket__field\">\n <span class=\"mm-ai-ticket__label\">Scope</span>\n <select\n class=\"mm-ai-ticket__select\"\n [ngModel]=\"scope()\"\n (ngModelChange)=\"scope.set($event)\"\n name=\"scope\"\n [disabled]=\"issuing()\"\n >\n @for (s of scopes; track s.value) {\n <option [value]=\"s.value\">{{ s.label }}</option>\n }\n </select>\n </label>\n <p class=\"mm-ai-ticket__hint\">\n @for (s of scopes; track s.value) {\n @if (s.value === scope()) {\n {{ s.hint }}\n }\n }\n </p>\n\n <label class=\"mm-ai-ticket__field\">\n <span class=\"mm-ai-ticket__label\">TTL (minutes)</span>\n <input\n class=\"mm-ai-ticket__input\"\n type=\"number\"\n min=\"1\"\n max=\"60\"\n step=\"1\"\n [ngModel]=\"ttlMinutes()\"\n (ngModelChange)=\"ttlMinutes.set(+$event)\"\n name=\"ttlMinutes\"\n [disabled]=\"issuing()\"\n />\n </label>\n <p class=\"mm-ai-ticket__hint\">\n Default 5 minutes. Server clamps to 60 \u2014 long TTLs leak.\n </p>\n\n <div class=\"mm-ai-ticket__actions\">\n <button\n class=\"mm-ai-ticket__button mm-ai-ticket__button--primary\"\n type=\"submit\"\n [disabled]=\"issuing()\"\n >\n @if (issuing()) {\n Issuing\u2026\n } @else {\n Issue ticket\n }\n </button>\n </div>\n\n @if (error()) {\n <p class=\"mm-ai-ticket__error\">{{ error() }}</p>\n }\n </form>\n } @else {\n <div class=\"mm-ai-ticket__result\">\n <p class=\"mm-ai-ticket__result-label\">\n One-time code (copy now \u2014 not shown again):\n </p>\n <div class=\"mm-ai-ticket__code-row\">\n <code class=\"mm-ai-ticket__code\">{{ issued()!.code }}</code>\n <button\n class=\"mm-ai-ticket__button mm-ai-ticket__button--secondary\"\n type=\"button\"\n (click)=\"onCopy()\"\n >\n @if (copied()) {\n Copied\n } @else {\n Copy\n }\n </button>\n </div>\n <dl class=\"mm-ai-ticket__meta\">\n <div>\n <dt>Scope</dt>\n <dd>{{ issued()!.scope }}</dd>\n </div>\n <div>\n <dt>Expires at</dt>\n <dd>{{ issued()!.expiresAt }}</dd>\n </div>\n <div>\n <dt>Ticket rtId</dt>\n <dd><code>{{ issued()!.rtId }}</code></dd>\n </div>\n </dl>\n <div class=\"mm-ai-ticket__actions\">\n <button\n class=\"mm-ai-ticket__button\"\n type=\"button\"\n (click)=\"onClear()\"\n >\n Issue another\n </button>\n </div>\n </div>\n }\n</section>\n", styles: [":host{display:block;--mm-ai-ticket-bg: #16191d;--mm-ai-ticket-surface: #1f2227;--mm-ai-ticket-border: #2f343b;--mm-ai-ticket-text: #e6e6e6;--mm-ai-ticket-muted: #9aa0a6;--mm-ai-ticket-accent: #64ceb9;--mm-ai-ticket-error: #ec658f;--mm-ai-ticket-code-bg: #0f1115}.mm-ai-ticket{background:var(--mm-ai-ticket-bg);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.5rem;padding:1rem 1.25rem;display:flex;flex-direction:column;gap:.85rem;font-family:inherit}.mm-ai-ticket__header{display:flex;flex-direction:column;gap:.15rem}.mm-ai-ticket__title{font-size:1rem;font-weight:600}.mm-ai-ticket__subtitle{font-size:.8rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__form,.mm-ai-ticket__result{display:flex;flex-direction:column;gap:.6rem}.mm-ai-ticket__field{display:flex;flex-direction:column;gap:.25rem}.mm-ai-ticket__label{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__select,.mm-ai-ticket__input{background:var(--mm-ai-ticket-surface);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.3rem;padding:.4rem .55rem;font-family:inherit;font-size:.9rem}.mm-ai-ticket__select:focus,.mm-ai-ticket__input:focus{outline:2px solid var(--mm-ai-ticket-accent);outline-offset:1px}.mm-ai-ticket__select:disabled,.mm-ai-ticket__input:disabled{opacity:.6;cursor:not-allowed}.mm-ai-ticket__hint{margin:0;font-size:.75rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__actions{display:flex;gap:.5rem;margin-top:.25rem}.mm-ai-ticket__button{background:var(--mm-ai-ticket-surface);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.3rem;padding:.4rem .85rem;font-family:inherit;font-size:.85rem;cursor:pointer}.mm-ai-ticket__button:hover:not(:disabled){border-color:var(--mm-ai-ticket-accent)}.mm-ai-ticket__button:disabled{opacity:.5;cursor:not-allowed}.mm-ai-ticket__button--primary{background:var(--mm-ai-ticket-accent);color:#0a0c0f;border-color:var(--mm-ai-ticket-accent)}.mm-ai-ticket__error{margin:0;font-size:.8rem;color:var(--mm-ai-ticket-error)}.mm-ai-ticket__result-label{margin:0;font-size:.85rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__code-row{display:flex;align-items:center;gap:.5rem}.mm-ai-ticket__code{flex:1;background:var(--mm-ai-ticket-code-bg);color:var(--mm-ai-ticket-accent);padding:.5rem .75rem;border-radius:.3rem;font-family:Roboto Mono,ui-monospace,monospace;font-size:1.05rem;letter-spacing:.1em;-webkit-user-select:all;user-select:all}.mm-ai-ticket__meta{display:grid;grid-template-columns:max-content 1fr;gap:.2rem .75rem;margin:0;font-size:.8rem}.mm-ai-ticket__meta>div{display:contents}.mm-ai-ticket__meta dt{color:var(--mm-ai-ticket-muted);text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.mm-ai-ticket__meta dd{margin:0;font-family:Roboto Mono,ui-monospace,monospace}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1157
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiCredentialTicketIssueComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1158
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: AiCredentialTicketIssueComponent, isStandalone: true, selector: "mm-ai-credential-ticket-issue", ngImport: i0, template: "<section class=\"mm-ai-ticket\">\n <header class=\"mm-ai-ticket__header\">\n <div class=\"mm-ai-ticket__title\">Issue credential ticket</div>\n <div class=\"mm-ai-ticket__subtitle\">\n Mint a one-time code an operator redeems on their own machine.\n </div>\n </header>\n\n @if (!issued()) {\n <form\n class=\"mm-ai-ticket__form\"\n (ngSubmit)=\"onIssue()\"\n #issueForm=\"ngForm\"\n >\n <label class=\"mm-ai-ticket__field\">\n <span class=\"mm-ai-ticket__label\">Scope</span>\n <select\n class=\"mm-ai-ticket__select\"\n [ngModel]=\"scope()\"\n (ngModelChange)=\"scope.set($event)\"\n name=\"scope\"\n [disabled]=\"issuing()\"\n >\n @for (s of scopes; track s.value) {\n <option [value]=\"s.value\">{{ s.label }}</option>\n }\n </select>\n </label>\n <p class=\"mm-ai-ticket__hint\">\n @for (s of scopes; track s.value) {\n @if (s.value === scope()) {\n {{ s.hint }}\n }\n }\n </p>\n\n <label class=\"mm-ai-ticket__field\">\n <span class=\"mm-ai-ticket__label\">TTL (minutes)</span>\n <input\n class=\"mm-ai-ticket__input\"\n type=\"number\"\n min=\"1\"\n max=\"60\"\n step=\"1\"\n [ngModel]=\"ttlMinutes()\"\n (ngModelChange)=\"ttlMinutes.set(+$event)\"\n name=\"ttlMinutes\"\n [disabled]=\"issuing()\"\n />\n </label>\n <p class=\"mm-ai-ticket__hint\">\n Default 5 minutes. Server clamps to 60 \u2014 long TTLs leak.\n </p>\n\n <div class=\"mm-ai-ticket__actions\">\n <button\n class=\"mm-ai-ticket__button mm-ai-ticket__button--primary\"\n type=\"submit\"\n [disabled]=\"issuing()\"\n >\n @if (issuing()) {\n Issuing\u2026\n } @else {\n Issue ticket\n }\n </button>\n </div>\n\n @if (error()) {\n <p class=\"mm-ai-ticket__error\">{{ error() }}</p>\n }\n </form>\n } @else {\n <div class=\"mm-ai-ticket__result\">\n <p class=\"mm-ai-ticket__result-label\">\n One-time code (copy now \u2014 not shown again):\n </p>\n <div class=\"mm-ai-ticket__code-row\">\n <code class=\"mm-ai-ticket__code\">{{ issued()!.code }}</code>\n <button\n class=\"mm-ai-ticket__button mm-ai-ticket__button--secondary\"\n type=\"button\"\n (click)=\"onCopy()\"\n >\n @if (copied()) {\n Copied\n } @else {\n Copy\n }\n </button>\n </div>\n <dl class=\"mm-ai-ticket__meta\">\n <div>\n <dt>Scope</dt>\n <dd>{{ issued()!.scope }}</dd>\n </div>\n <div>\n <dt>Expires at</dt>\n <dd>{{ issued()!.expiresAt }}</dd>\n </div>\n <div>\n <dt>Ticket rtId</dt>\n <dd><code>{{ issued()!.rtId }}</code></dd>\n </div>\n </dl>\n <div class=\"mm-ai-ticket__actions\">\n <button\n class=\"mm-ai-ticket__button\"\n type=\"button\"\n (click)=\"onClear()\"\n >\n Issue another\n </button>\n </div>\n </div>\n }\n</section>\n", styles: [":host{display:block;--mm-ai-ticket-bg: #16191d;--mm-ai-ticket-surface: #1f2227;--mm-ai-ticket-border: #2f343b;--mm-ai-ticket-text: #e6e6e6;--mm-ai-ticket-muted: #9aa0a6;--mm-ai-ticket-accent: #64ceb9;--mm-ai-ticket-error: #ec658f;--mm-ai-ticket-code-bg: #0f1115}.mm-ai-ticket{background:var(--mm-ai-ticket-bg);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.5rem;padding:1rem 1.25rem;display:flex;flex-direction:column;gap:.85rem;font-family:inherit}.mm-ai-ticket__header{display:flex;flex-direction:column;gap:.15rem}.mm-ai-ticket__title{font-size:1rem;font-weight:600}.mm-ai-ticket__subtitle{font-size:.8rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__form,.mm-ai-ticket__result{display:flex;flex-direction:column;gap:.6rem}.mm-ai-ticket__field{display:flex;flex-direction:column;gap:.25rem}.mm-ai-ticket__label{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__select,.mm-ai-ticket__input{background:var(--mm-ai-ticket-surface);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.3rem;padding:.4rem .55rem;font-family:inherit;font-size:.9rem}.mm-ai-ticket__select:focus,.mm-ai-ticket__input:focus{outline:2px solid var(--mm-ai-ticket-accent);outline-offset:1px}.mm-ai-ticket__select:disabled,.mm-ai-ticket__input:disabled{opacity:.6;cursor:not-allowed}.mm-ai-ticket__hint{margin:0;font-size:.75rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__actions{display:flex;gap:.5rem;margin-top:.25rem}.mm-ai-ticket__button{background:var(--mm-ai-ticket-surface);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.3rem;padding:.4rem .85rem;font-family:inherit;font-size:.85rem;cursor:pointer}.mm-ai-ticket__button:hover:not(:disabled){border-color:var(--mm-ai-ticket-accent)}.mm-ai-ticket__button:disabled{opacity:.5;cursor:not-allowed}.mm-ai-ticket__button--primary{background:var(--mm-ai-ticket-accent);color:#0a0c0f;border-color:var(--mm-ai-ticket-accent)}.mm-ai-ticket__error{margin:0;font-size:.8rem;color:var(--mm-ai-ticket-error)}.mm-ai-ticket__result-label{margin:0;font-size:.85rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__code-row{display:flex;align-items:center;gap:.5rem}.mm-ai-ticket__code{flex:1;background:var(--mm-ai-ticket-code-bg);color:var(--mm-ai-ticket-accent);padding:.5rem .75rem;border-radius:.3rem;font-family:Roboto Mono,ui-monospace,monospace;font-size:1.05rem;letter-spacing:.1em;-webkit-user-select:all;user-select:all}.mm-ai-ticket__meta{display:grid;grid-template-columns:max-content 1fr;gap:.2rem .75rem;margin:0;font-size:.8rem}.mm-ai-ticket__meta>div{display:contents}.mm-ai-ticket__meta dt{color:var(--mm-ai-ticket-muted);text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.mm-ai-ticket__meta dd{margin:0;font-family:Roboto Mono,ui-monospace,monospace}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1129
1159
  }
1130
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiCredentialTicketIssueComponent, decorators: [{
1160
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiCredentialTicketIssueComponent, decorators: [{
1131
1161
  type: Component,
1132
1162
  args: [{ selector: 'mm-ai-credential-ticket-issue', imports: [CommonModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"mm-ai-ticket\">\n <header class=\"mm-ai-ticket__header\">\n <div class=\"mm-ai-ticket__title\">Issue credential ticket</div>\n <div class=\"mm-ai-ticket__subtitle\">\n Mint a one-time code an operator redeems on their own machine.\n </div>\n </header>\n\n @if (!issued()) {\n <form\n class=\"mm-ai-ticket__form\"\n (ngSubmit)=\"onIssue()\"\n #issueForm=\"ngForm\"\n >\n <label class=\"mm-ai-ticket__field\">\n <span class=\"mm-ai-ticket__label\">Scope</span>\n <select\n class=\"mm-ai-ticket__select\"\n [ngModel]=\"scope()\"\n (ngModelChange)=\"scope.set($event)\"\n name=\"scope\"\n [disabled]=\"issuing()\"\n >\n @for (s of scopes; track s.value) {\n <option [value]=\"s.value\">{{ s.label }}</option>\n }\n </select>\n </label>\n <p class=\"mm-ai-ticket__hint\">\n @for (s of scopes; track s.value) {\n @if (s.value === scope()) {\n {{ s.hint }}\n }\n }\n </p>\n\n <label class=\"mm-ai-ticket__field\">\n <span class=\"mm-ai-ticket__label\">TTL (minutes)</span>\n <input\n class=\"mm-ai-ticket__input\"\n type=\"number\"\n min=\"1\"\n max=\"60\"\n step=\"1\"\n [ngModel]=\"ttlMinutes()\"\n (ngModelChange)=\"ttlMinutes.set(+$event)\"\n name=\"ttlMinutes\"\n [disabled]=\"issuing()\"\n />\n </label>\n <p class=\"mm-ai-ticket__hint\">\n Default 5 minutes. Server clamps to 60 \u2014 long TTLs leak.\n </p>\n\n <div class=\"mm-ai-ticket__actions\">\n <button\n class=\"mm-ai-ticket__button mm-ai-ticket__button--primary\"\n type=\"submit\"\n [disabled]=\"issuing()\"\n >\n @if (issuing()) {\n Issuing\u2026\n } @else {\n Issue ticket\n }\n </button>\n </div>\n\n @if (error()) {\n <p class=\"mm-ai-ticket__error\">{{ error() }}</p>\n }\n </form>\n } @else {\n <div class=\"mm-ai-ticket__result\">\n <p class=\"mm-ai-ticket__result-label\">\n One-time code (copy now \u2014 not shown again):\n </p>\n <div class=\"mm-ai-ticket__code-row\">\n <code class=\"mm-ai-ticket__code\">{{ issued()!.code }}</code>\n <button\n class=\"mm-ai-ticket__button mm-ai-ticket__button--secondary\"\n type=\"button\"\n (click)=\"onCopy()\"\n >\n @if (copied()) {\n Copied\n } @else {\n Copy\n }\n </button>\n </div>\n <dl class=\"mm-ai-ticket__meta\">\n <div>\n <dt>Scope</dt>\n <dd>{{ issued()!.scope }}</dd>\n </div>\n <div>\n <dt>Expires at</dt>\n <dd>{{ issued()!.expiresAt }}</dd>\n </div>\n <div>\n <dt>Ticket rtId</dt>\n <dd><code>{{ issued()!.rtId }}</code></dd>\n </div>\n </dl>\n <div class=\"mm-ai-ticket__actions\">\n <button\n class=\"mm-ai-ticket__button\"\n type=\"button\"\n (click)=\"onClear()\"\n >\n Issue another\n </button>\n </div>\n </div>\n }\n</section>\n", styles: [":host{display:block;--mm-ai-ticket-bg: #16191d;--mm-ai-ticket-surface: #1f2227;--mm-ai-ticket-border: #2f343b;--mm-ai-ticket-text: #e6e6e6;--mm-ai-ticket-muted: #9aa0a6;--mm-ai-ticket-accent: #64ceb9;--mm-ai-ticket-error: #ec658f;--mm-ai-ticket-code-bg: #0f1115}.mm-ai-ticket{background:var(--mm-ai-ticket-bg);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.5rem;padding:1rem 1.25rem;display:flex;flex-direction:column;gap:.85rem;font-family:inherit}.mm-ai-ticket__header{display:flex;flex-direction:column;gap:.15rem}.mm-ai-ticket__title{font-size:1rem;font-weight:600}.mm-ai-ticket__subtitle{font-size:.8rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__form,.mm-ai-ticket__result{display:flex;flex-direction:column;gap:.6rem}.mm-ai-ticket__field{display:flex;flex-direction:column;gap:.25rem}.mm-ai-ticket__label{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__select,.mm-ai-ticket__input{background:var(--mm-ai-ticket-surface);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.3rem;padding:.4rem .55rem;font-family:inherit;font-size:.9rem}.mm-ai-ticket__select:focus,.mm-ai-ticket__input:focus{outline:2px solid var(--mm-ai-ticket-accent);outline-offset:1px}.mm-ai-ticket__select:disabled,.mm-ai-ticket__input:disabled{opacity:.6;cursor:not-allowed}.mm-ai-ticket__hint{margin:0;font-size:.75rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__actions{display:flex;gap:.5rem;margin-top:.25rem}.mm-ai-ticket__button{background:var(--mm-ai-ticket-surface);color:var(--mm-ai-ticket-text);border:1px solid var(--mm-ai-ticket-border);border-radius:.3rem;padding:.4rem .85rem;font-family:inherit;font-size:.85rem;cursor:pointer}.mm-ai-ticket__button:hover:not(:disabled){border-color:var(--mm-ai-ticket-accent)}.mm-ai-ticket__button:disabled{opacity:.5;cursor:not-allowed}.mm-ai-ticket__button--primary{background:var(--mm-ai-ticket-accent);color:#0a0c0f;border-color:var(--mm-ai-ticket-accent)}.mm-ai-ticket__error{margin:0;font-size:.8rem;color:var(--mm-ai-ticket-error)}.mm-ai-ticket__result-label{margin:0;font-size:.85rem;color:var(--mm-ai-ticket-muted)}.mm-ai-ticket__code-row{display:flex;align-items:center;gap:.5rem}.mm-ai-ticket__code{flex:1;background:var(--mm-ai-ticket-code-bg);color:var(--mm-ai-ticket-accent);padding:.5rem .75rem;border-radius:.3rem;font-family:Roboto Mono,ui-monospace,monospace;font-size:1.05rem;letter-spacing:.1em;-webkit-user-select:all;user-select:all}.mm-ai-ticket__meta{display:grid;grid-template-columns:max-content 1fr;gap:.2rem .75rem;margin:0;font-size:.8rem}.mm-ai-ticket__meta>div{display:contents}.mm-ai-ticket__meta dt{color:var(--mm-ai-ticket-muted);text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.mm-ai-ticket__meta dd{margin:0;font-family:Roboto Mono,ui-monospace,monospace}\n"] }]
1133
1163
  }] });
@@ -1150,9 +1180,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1150
1180
  */
1151
1181
  class AiNewAppDialogComponent {
1152
1182
  /** Available templates from the adapter — typically 3 in Phase 1. */
1153
- templates = input.required(...(ngDevMode ? [{ debugName: "templates" }] : /* istanbul ignore next */ []));
1183
+ templates = input.required(/* @ts-ignore */
1184
+ ...(ngDevMode ? [{ debugName: "templates" }] : /* istanbul ignore next */ []));
1154
1185
  /** Tenant name shown in the dialog header so the operator confirms the scope. */
1155
- tenantName = input('', ...(ngDevMode ? [{ debugName: "tenantName" }] : /* istanbul ignore next */ []));
1186
+ tenantName = input('', /* @ts-ignore */
1187
+ ...(ngDevMode ? [{ debugName: "tenantName" }] : /* istanbul ignore next */ []));
1156
1188
  /**
1157
1189
  * Emitted on Submit with the fully interpolated Goal + the picked template id.
1158
1190
  * Named `confirmed` (not `submit`) because Angular flags native-event collisions
@@ -1165,13 +1197,17 @@ class AiNewAppDialogComponent {
1165
1197
  */
1166
1198
  cancelled = output();
1167
1199
  /** rtId-style id of the picked template, or empty until the operator picks one. */
1168
- selectedTemplateId = signal('', ...(ngDevMode ? [{ debugName: "selectedTemplateId" }] : /* istanbul ignore next */ []));
1169
- projectName = signal('', ...(ngDevMode ? [{ debugName: "projectName" }] : /* istanbul ignore next */ []));
1170
- primaryEntity = signal('', ...(ngDevMode ? [{ debugName: "primaryEntity" }] : /* istanbul ignore next */ []));
1200
+ selectedTemplateId = signal('', /* @ts-ignore */
1201
+ ...(ngDevMode ? [{ debugName: "selectedTemplateId" }] : /* istanbul ignore next */ []));
1202
+ projectName = signal('', /* @ts-ignore */
1203
+ ...(ngDevMode ? [{ debugName: "projectName" }] : /* istanbul ignore next */ []));
1204
+ primaryEntity = signal('', /* @ts-ignore */
1205
+ ...(ngDevMode ? [{ debugName: "primaryEntity" }] : /* istanbul ignore next */ []));
1171
1206
  selectedTemplate = computed(() => {
1172
1207
  const id = this.selectedTemplateId();
1173
1208
  return this.templates().find((t) => t.id === id) ?? null;
1174
- }, ...(ngDevMode ? [{ debugName: "selectedTemplate" }] : /* istanbul ignore next */ []));
1209
+ }, /* @ts-ignore */
1210
+ ...(ngDevMode ? [{ debugName: "selectedTemplate" }] : /* istanbul ignore next */ []));
1175
1211
  /**
1176
1212
  * Rendered Goal string the operator sees in the preview block. Stays empty
1177
1213
  * until a template is picked AND every required placeholder has a value, so
@@ -1186,7 +1222,8 @@ class AiNewAppDialogComponent {
1186
1222
  return '';
1187
1223
  }
1188
1224
  return this.interpolate(template.goalTemplate);
1189
- }, ...(ngDevMode ? [{ debugName: "renderedGoal" }] : /* istanbul ignore next */ []));
1225
+ }, /* @ts-ignore */
1226
+ ...(ngDevMode ? [{ debugName: "renderedGoal" }] : /* istanbul ignore next */ []));
1190
1227
  /** True when every placeholder the picked template declares has a non-empty value. */
1191
1228
  allRequiredFilled = computed(() => {
1192
1229
  const template = this.selectedTemplate();
@@ -1197,7 +1234,8 @@ class AiNewAppDialogComponent {
1197
1234
  const value = this.valueFor(key);
1198
1235
  return value !== null && value.trim().length > 0;
1199
1236
  });
1200
- }, ...(ngDevMode ? [{ debugName: "allRequiredFilled" }] : /* istanbul ignore next */ []));
1237
+ }, /* @ts-ignore */
1238
+ ...(ngDevMode ? [{ debugName: "allRequiredFilled" }] : /* istanbul ignore next */ []));
1201
1239
  onSubmit() {
1202
1240
  const template = this.selectedTemplate();
1203
1241
  if (!template || !this.allRequiredFilled()) {
@@ -1233,10 +1271,10 @@ class AiNewAppDialogComponent {
1233
1271
  return value !== null ? value.trim() : full;
1234
1272
  });
1235
1273
  }
1236
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiNewAppDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1237
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AiNewAppDialogComponent, isStandalone: true, selector: "mm-ai-new-app-dialog", inputs: { templates: { classPropertyName: "templates", publicName: "templates", isSignal: true, isRequired: true, transformFunction: null }, tenantName: { classPropertyName: "tenantName", publicName: "tenantName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, ngImport: i0, template: "<div class=\"mm-ai-new-app\">\n <header class=\"mm-ai-new-app__header\">\n <h3 class=\"mm-ai-new-app__title\">\n New App\n @if (tenantName(); as tenant) {\n <span class=\"mm-ai-new-app__tenant\"> \u00B7 {{ tenant }}</span>\n }\n </h3>\n <button\n type=\"button\"\n class=\"mm-ai-new-app__close\"\n (click)=\"onCancel()\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n </header>\n\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">Template</h4>\n <ul class=\"mm-ai-new-app__templates\" role=\"radiogroup\" aria-label=\"Template\">\n @for (template of templates(); track template.id) {\n <li>\n <label\n class=\"mm-ai-new-app__template\"\n [class.mm-ai-new-app__template--active]=\"\n selectedTemplateId() === template.id\n \"\n >\n <input\n type=\"radio\"\n name=\"mm-ai-new-app-template\"\n [value]=\"template.id\"\n [checked]=\"selectedTemplateId() === template.id\"\n (change)=\"selectedTemplateId.set(template.id)\"\n />\n <span class=\"mm-ai-new-app__template-body\">\n <strong class=\"mm-ai-new-app__template-name\">{{ template.name }}</strong>\n <span class=\"mm-ai-new-app__template-description\">\n {{ template.description }}\n </span>\n </span>\n </label>\n </li>\n }\n </ul>\n </div>\n\n @if (selectedTemplate(); as template) {\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">Parameters</h4>\n <div class=\"mm-ai-new-app__field\">\n <label for=\"mm-ai-new-app-project-name\">Project name</label>\n <input\n id=\"mm-ai-new-app-project-name\"\n type=\"text\"\n [ngModel]=\"projectName()\"\n (ngModelChange)=\"projectName.set($event)\"\n placeholder=\"e.g. customer-list\"\n autocomplete=\"off\"\n />\n </div>\n <div class=\"mm-ai-new-app__field\">\n <label for=\"mm-ai-new-app-primary-entity\">Primary entity (CK type)</label>\n <input\n id=\"mm-ai-new-app-primary-entity\"\n type=\"text\"\n [ngModel]=\"primaryEntity()\"\n (ngModelChange)=\"primaryEntity.set($event)\"\n placeholder=\"e.g. Customer\"\n autocomplete=\"off\"\n />\n </div>\n </div>\n\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">\n Generated Goal <span>(this is what Claude will see)</span>\n </h4>\n <pre class=\"mm-ai-new-app__preview\">{{\n renderedGoal() ||\n 'Fill in every field above to preview the Goal that will be sent.'\n }}</pre>\n </div>\n }\n\n <footer class=\"mm-ai-new-app__actions\">\n <button\n type=\"button\"\n class=\"mm-ai-new-app__btn mm-ai-new-app__btn--cancel\"\n (click)=\"onCancel()\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n class=\"mm-ai-new-app__btn mm-ai-new-app__btn--submit\"\n [disabled]=\"!allRequiredFilled()\"\n (click)=\"onSubmit()\"\n >\n Create App Session\n </button>\n </footer>\n</div>\n", styles: [":host{display:block;--mm-ai-new-app-bg: #1f2227;--mm-ai-new-app-border: #2f343b;--mm-ai-new-app-text: #e6e6e6;--mm-ai-new-app-muted: #9aa0a6;--mm-ai-new-app-accent: #2ea44f;--mm-ai-new-app-accent-soft: rgba(46, 164, 79, .15);--mm-ai-new-app-cancel: #44494f;--mm-ai-new-app-code-bg: #16191d}.mm-ai-new-app{background:var(--mm-ai-new-app-bg);color:var(--mm-ai-new-app-text);border:1px solid var(--mm-ai-new-app-border);border-radius:.6rem;padding:1rem 1.25rem;width:min(40rem,100%)}.mm-ai-new-app__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.mm-ai-new-app__title{margin:0;font-size:1rem}.mm-ai-new-app__tenant{color:var(--mm-ai-new-app-muted);font-weight:400}.mm-ai-new-app__close{background:transparent;color:var(--mm-ai-new-app-muted);border:none;font-size:1.4rem;cursor:pointer;line-height:1;padding:0 .25rem}.mm-ai-new-app__close:hover{color:var(--mm-ai-new-app-text)}.mm-ai-new-app__section{margin-bottom:.75rem}.mm-ai-new-app__heading{margin:0 0 .35rem;font-size:.75rem;color:var(--mm-ai-new-app-muted);text-transform:uppercase;letter-spacing:.04em}.mm-ai-new-app__heading span{text-transform:none;letter-spacing:0;opacity:.6}.mm-ai-new-app__templates{list-style:none;margin:0;padding:0;display:grid;gap:.4rem}.mm-ai-new-app__template{display:flex;gap:.6rem;padding:.55rem .7rem;border:1px solid var(--mm-ai-new-app-border);border-radius:.35rem;cursor:pointer;align-items:flex-start}.mm-ai-new-app__template--active{background:var(--mm-ai-new-app-accent-soft);border-color:var(--mm-ai-new-app-accent)}.mm-ai-new-app__template input[type=radio]{margin-top:.2rem}.mm-ai-new-app__template-body{display:grid;gap:.2rem}.mm-ai-new-app__template-name{font-size:.9rem}.mm-ai-new-app__template-description{font-size:.8rem;color:var(--mm-ai-new-app-muted)}.mm-ai-new-app__field{display:grid;gap:.25rem;margin-bottom:.5rem;font-size:.85rem}.mm-ai-new-app__field label{color:var(--mm-ai-new-app-muted)}.mm-ai-new-app__field input{padding:.45rem .55rem;background:var(--mm-ai-new-app-code-bg);color:inherit;border:1px solid var(--mm-ai-new-app-border);border-radius:.3rem;font-family:inherit;font-size:.9rem}.mm-ai-new-app__preview{margin:0;padding:.5rem .6rem;background:var(--mm-ai-new-app-code-bg);border-radius:.3rem;font-size:.8rem;white-space:pre-wrap;word-break:break-word;max-height:12rem;overflow-y:auto}.mm-ai-new-app__actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem}.mm-ai-new-app__btn{padding:.45rem 1rem;border-radius:.3rem;font-weight:600;border:none;cursor:pointer;font-size:.85rem}.mm-ai-new-app__btn--submit{background:var(--mm-ai-new-app-accent);color:#fff}.mm-ai-new-app__btn--submit:disabled{opacity:.5;cursor:not-allowed}.mm-ai-new-app__btn--cancel{background:var(--mm-ai-new-app-cancel);color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1274
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiNewAppDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1275
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: AiNewAppDialogComponent, isStandalone: true, selector: "mm-ai-new-app-dialog", inputs: { templates: { classPropertyName: "templates", publicName: "templates", isSignal: true, isRequired: true, transformFunction: null }, tenantName: { classPropertyName: "tenantName", publicName: "tenantName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, ngImport: i0, template: "<div class=\"mm-ai-new-app\">\n <header class=\"mm-ai-new-app__header\">\n <h3 class=\"mm-ai-new-app__title\">\n New App\n @if (tenantName(); as tenant) {\n <span class=\"mm-ai-new-app__tenant\"> \u00B7 {{ tenant }}</span>\n }\n </h3>\n <button\n type=\"button\"\n class=\"mm-ai-new-app__close\"\n (click)=\"onCancel()\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n </header>\n\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">Template</h4>\n <ul class=\"mm-ai-new-app__templates\" role=\"radiogroup\" aria-label=\"Template\">\n @for (template of templates(); track template.id) {\n <li>\n <label\n class=\"mm-ai-new-app__template\"\n [class.mm-ai-new-app__template--active]=\"\n selectedTemplateId() === template.id\n \"\n >\n <input\n type=\"radio\"\n name=\"mm-ai-new-app-template\"\n [value]=\"template.id\"\n [checked]=\"selectedTemplateId() === template.id\"\n (change)=\"selectedTemplateId.set(template.id)\"\n />\n <span class=\"mm-ai-new-app__template-body\">\n <strong class=\"mm-ai-new-app__template-name\">{{ template.name }}</strong>\n <span class=\"mm-ai-new-app__template-description\">\n {{ template.description }}\n </span>\n </span>\n </label>\n </li>\n }\n </ul>\n </div>\n\n @if (selectedTemplate(); as template) {\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">Parameters</h4>\n <div class=\"mm-ai-new-app__field\">\n <label for=\"mm-ai-new-app-project-name\">Project name</label>\n <input\n id=\"mm-ai-new-app-project-name\"\n type=\"text\"\n [ngModel]=\"projectName()\"\n (ngModelChange)=\"projectName.set($event)\"\n placeholder=\"e.g. customer-list\"\n autocomplete=\"off\"\n />\n </div>\n <div class=\"mm-ai-new-app__field\">\n <label for=\"mm-ai-new-app-primary-entity\">Primary entity (CK type)</label>\n <input\n id=\"mm-ai-new-app-primary-entity\"\n type=\"text\"\n [ngModel]=\"primaryEntity()\"\n (ngModelChange)=\"primaryEntity.set($event)\"\n placeholder=\"e.g. Customer\"\n autocomplete=\"off\"\n />\n </div>\n </div>\n\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">\n Generated Goal <span>(this is what Claude will see)</span>\n </h4>\n <pre class=\"mm-ai-new-app__preview\">{{\n renderedGoal() ||\n 'Fill in every field above to preview the Goal that will be sent.'\n }}</pre>\n </div>\n }\n\n <footer class=\"mm-ai-new-app__actions\">\n <button\n type=\"button\"\n class=\"mm-ai-new-app__btn mm-ai-new-app__btn--cancel\"\n (click)=\"onCancel()\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n class=\"mm-ai-new-app__btn mm-ai-new-app__btn--submit\"\n [disabled]=\"!allRequiredFilled()\"\n (click)=\"onSubmit()\"\n >\n Create App Session\n </button>\n </footer>\n</div>\n", styles: [":host{display:block;--mm-ai-new-app-bg: #1f2227;--mm-ai-new-app-border: #2f343b;--mm-ai-new-app-text: #e6e6e6;--mm-ai-new-app-muted: #9aa0a6;--mm-ai-new-app-accent: #2ea44f;--mm-ai-new-app-accent-soft: rgba(46, 164, 79, .15);--mm-ai-new-app-cancel: #44494f;--mm-ai-new-app-code-bg: #16191d}.mm-ai-new-app{background:var(--mm-ai-new-app-bg);color:var(--mm-ai-new-app-text);border:1px solid var(--mm-ai-new-app-border);border-radius:.6rem;padding:1rem 1.25rem;width:min(40rem,100%)}.mm-ai-new-app__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.mm-ai-new-app__title{margin:0;font-size:1rem}.mm-ai-new-app__tenant{color:var(--mm-ai-new-app-muted);font-weight:400}.mm-ai-new-app__close{background:transparent;color:var(--mm-ai-new-app-muted);border:none;font-size:1.4rem;cursor:pointer;line-height:1;padding:0 .25rem}.mm-ai-new-app__close:hover{color:var(--mm-ai-new-app-text)}.mm-ai-new-app__section{margin-bottom:.75rem}.mm-ai-new-app__heading{margin:0 0 .35rem;font-size:.75rem;color:var(--mm-ai-new-app-muted);text-transform:uppercase;letter-spacing:.04em}.mm-ai-new-app__heading span{text-transform:none;letter-spacing:0;opacity:.6}.mm-ai-new-app__templates{list-style:none;margin:0;padding:0;display:grid;gap:.4rem}.mm-ai-new-app__template{display:flex;gap:.6rem;padding:.55rem .7rem;border:1px solid var(--mm-ai-new-app-border);border-radius:.35rem;cursor:pointer;align-items:flex-start}.mm-ai-new-app__template--active{background:var(--mm-ai-new-app-accent-soft);border-color:var(--mm-ai-new-app-accent)}.mm-ai-new-app__template input[type=radio]{margin-top:.2rem}.mm-ai-new-app__template-body{display:grid;gap:.2rem}.mm-ai-new-app__template-name{font-size:.9rem}.mm-ai-new-app__template-description{font-size:.8rem;color:var(--mm-ai-new-app-muted)}.mm-ai-new-app__field{display:grid;gap:.25rem;margin-bottom:.5rem;font-size:.85rem}.mm-ai-new-app__field label{color:var(--mm-ai-new-app-muted)}.mm-ai-new-app__field input{padding:.45rem .55rem;background:var(--mm-ai-new-app-code-bg);color:inherit;border:1px solid var(--mm-ai-new-app-border);border-radius:.3rem;font-family:inherit;font-size:.9rem}.mm-ai-new-app__preview{margin:0;padding:.5rem .6rem;background:var(--mm-ai-new-app-code-bg);border-radius:.3rem;font-size:.8rem;white-space:pre-wrap;word-break:break-word;max-height:12rem;overflow-y:auto}.mm-ai-new-app__actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem}.mm-ai-new-app__btn{padding:.45rem 1rem;border-radius:.3rem;font-weight:600;border:none;cursor:pointer;font-size:.85rem}.mm-ai-new-app__btn--submit{background:var(--mm-ai-new-app-accent);color:#fff}.mm-ai-new-app__btn--submit:disabled{opacity:.5;cursor:not-allowed}.mm-ai-new-app__btn--cancel{background:var(--mm-ai-new-app-cancel);color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1238
1276
  }
1239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AiNewAppDialogComponent, decorators: [{
1277
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: AiNewAppDialogComponent, decorators: [{
1240
1278
  type: Component,
1241
1279
  args: [{ selector: 'mm-ai-new-app-dialog', imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mm-ai-new-app\">\n <header class=\"mm-ai-new-app__header\">\n <h3 class=\"mm-ai-new-app__title\">\n New App\n @if (tenantName(); as tenant) {\n <span class=\"mm-ai-new-app__tenant\"> \u00B7 {{ tenant }}</span>\n }\n </h3>\n <button\n type=\"button\"\n class=\"mm-ai-new-app__close\"\n (click)=\"onCancel()\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n </header>\n\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">Template</h4>\n <ul class=\"mm-ai-new-app__templates\" role=\"radiogroup\" aria-label=\"Template\">\n @for (template of templates(); track template.id) {\n <li>\n <label\n class=\"mm-ai-new-app__template\"\n [class.mm-ai-new-app__template--active]=\"\n selectedTemplateId() === template.id\n \"\n >\n <input\n type=\"radio\"\n name=\"mm-ai-new-app-template\"\n [value]=\"template.id\"\n [checked]=\"selectedTemplateId() === template.id\"\n (change)=\"selectedTemplateId.set(template.id)\"\n />\n <span class=\"mm-ai-new-app__template-body\">\n <strong class=\"mm-ai-new-app__template-name\">{{ template.name }}</strong>\n <span class=\"mm-ai-new-app__template-description\">\n {{ template.description }}\n </span>\n </span>\n </label>\n </li>\n }\n </ul>\n </div>\n\n @if (selectedTemplate(); as template) {\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">Parameters</h4>\n <div class=\"mm-ai-new-app__field\">\n <label for=\"mm-ai-new-app-project-name\">Project name</label>\n <input\n id=\"mm-ai-new-app-project-name\"\n type=\"text\"\n [ngModel]=\"projectName()\"\n (ngModelChange)=\"projectName.set($event)\"\n placeholder=\"e.g. customer-list\"\n autocomplete=\"off\"\n />\n </div>\n <div class=\"mm-ai-new-app__field\">\n <label for=\"mm-ai-new-app-primary-entity\">Primary entity (CK type)</label>\n <input\n id=\"mm-ai-new-app-primary-entity\"\n type=\"text\"\n [ngModel]=\"primaryEntity()\"\n (ngModelChange)=\"primaryEntity.set($event)\"\n placeholder=\"e.g. Customer\"\n autocomplete=\"off\"\n />\n </div>\n </div>\n\n <div class=\"mm-ai-new-app__section\">\n <h4 class=\"mm-ai-new-app__heading\">\n Generated Goal <span>(this is what Claude will see)</span>\n </h4>\n <pre class=\"mm-ai-new-app__preview\">{{\n renderedGoal() ||\n 'Fill in every field above to preview the Goal that will be sent.'\n }}</pre>\n </div>\n }\n\n <footer class=\"mm-ai-new-app__actions\">\n <button\n type=\"button\"\n class=\"mm-ai-new-app__btn mm-ai-new-app__btn--cancel\"\n (click)=\"onCancel()\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n class=\"mm-ai-new-app__btn mm-ai-new-app__btn--submit\"\n [disabled]=\"!allRequiredFilled()\"\n (click)=\"onSubmit()\"\n >\n Create App Session\n </button>\n </footer>\n</div>\n", styles: [":host{display:block;--mm-ai-new-app-bg: #1f2227;--mm-ai-new-app-border: #2f343b;--mm-ai-new-app-text: #e6e6e6;--mm-ai-new-app-muted: #9aa0a6;--mm-ai-new-app-accent: #2ea44f;--mm-ai-new-app-accent-soft: rgba(46, 164, 79, .15);--mm-ai-new-app-cancel: #44494f;--mm-ai-new-app-code-bg: #16191d}.mm-ai-new-app{background:var(--mm-ai-new-app-bg);color:var(--mm-ai-new-app-text);border:1px solid var(--mm-ai-new-app-border);border-radius:.6rem;padding:1rem 1.25rem;width:min(40rem,100%)}.mm-ai-new-app__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.mm-ai-new-app__title{margin:0;font-size:1rem}.mm-ai-new-app__tenant{color:var(--mm-ai-new-app-muted);font-weight:400}.mm-ai-new-app__close{background:transparent;color:var(--mm-ai-new-app-muted);border:none;font-size:1.4rem;cursor:pointer;line-height:1;padding:0 .25rem}.mm-ai-new-app__close:hover{color:var(--mm-ai-new-app-text)}.mm-ai-new-app__section{margin-bottom:.75rem}.mm-ai-new-app__heading{margin:0 0 .35rem;font-size:.75rem;color:var(--mm-ai-new-app-muted);text-transform:uppercase;letter-spacing:.04em}.mm-ai-new-app__heading span{text-transform:none;letter-spacing:0;opacity:.6}.mm-ai-new-app__templates{list-style:none;margin:0;padding:0;display:grid;gap:.4rem}.mm-ai-new-app__template{display:flex;gap:.6rem;padding:.55rem .7rem;border:1px solid var(--mm-ai-new-app-border);border-radius:.35rem;cursor:pointer;align-items:flex-start}.mm-ai-new-app__template--active{background:var(--mm-ai-new-app-accent-soft);border-color:var(--mm-ai-new-app-accent)}.mm-ai-new-app__template input[type=radio]{margin-top:.2rem}.mm-ai-new-app__template-body{display:grid;gap:.2rem}.mm-ai-new-app__template-name{font-size:.9rem}.mm-ai-new-app__template-description{font-size:.8rem;color:var(--mm-ai-new-app-muted)}.mm-ai-new-app__field{display:grid;gap:.25rem;margin-bottom:.5rem;font-size:.85rem}.mm-ai-new-app__field label{color:var(--mm-ai-new-app-muted)}.mm-ai-new-app__field input{padding:.45rem .55rem;background:var(--mm-ai-new-app-code-bg);color:inherit;border:1px solid var(--mm-ai-new-app-border);border-radius:.3rem;font-family:inherit;font-size:.9rem}.mm-ai-new-app__preview{margin:0;padding:.5rem .6rem;background:var(--mm-ai-new-app-code-bg);border-radius:.3rem;font-size:.8rem;white-space:pre-wrap;word-break:break-word;max-height:12rem;overflow-y:auto}.mm-ai-new-app__actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem}.mm-ai-new-app__btn{padding:.45rem 1rem;border-radius:.3rem;font-weight:600;border:none;cursor:pointer;font-size:.85rem}.mm-ai-new-app__btn--submit{background:var(--mm-ai-new-app-accent);color:#fff}.mm-ai-new-app__btn--submit:disabled{opacity:.5;cursor:not-allowed}.mm-ai-new-app__btn--cancel{background:var(--mm-ai-new-app-cancel);color:#fff}\n"] }]
1242
1280
  }], propDecorators: { templates: [{ type: i0.Input, args: [{ isSignal: true, alias: "templates", required: true }] }], tenantName: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenantName", required: false }] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });