@genesislcap/ai-assistant 15.27.0-agent-log-submit.3 → 15.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/ai-assistant.api.json +77 -838
  2. package/dist/ai-assistant.d.ts +23 -179
  3. package/dist/chat-driver.cjs +13 -14
  4. package/dist/chat-driver.cjs.map +2 -2
  5. package/dist/chat-driver.mjs +13 -14
  6. package/dist/chat-driver.mjs.map +2 -2
  7. package/dist/custom-elements.json +17 -454
  8. package/dist/dts/components/ai-driver/ai-driver.d.ts +11 -12
  9. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
  10. package/dist/dts/components/ai-driver/stub-driver.d.ts +17 -0
  11. package/dist/dts/components/ai-driver/stub-driver.d.ts.map +1 -0
  12. package/dist/dts/components/chat-driver/chat-driver.d.ts +10 -11
  13. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  14. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +2 -2
  15. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  16. package/dist/dts/components/settings-modal/settings-modal.d.ts.map +1 -1
  17. package/dist/dts/components/settings-modal/settings-modal.styles.d.ts.map +1 -1
  18. package/dist/dts/components/settings-modal/settings-modal.template.d.ts +0 -8
  19. package/dist/dts/components/settings-modal/settings-modal.template.d.ts.map +1 -1
  20. package/dist/dts/index.d.ts +0 -1
  21. package/dist/dts/index.d.ts.map +1 -1
  22. package/dist/dts/main/main.d.ts +0 -148
  23. package/dist/dts/main/main.d.ts.map +1 -1
  24. package/dist/esm/components/ai-driver/stub-driver.js +16 -0
  25. package/dist/esm/components/chat-driver/chat-driver.js +11 -12
  26. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +5 -5
  27. package/dist/esm/components/settings-modal/settings-modal.js +0 -1
  28. package/dist/esm/components/settings-modal/settings-modal.styles.js +5 -85
  29. package/dist/esm/components/settings-modal/settings-modal.template.js +23 -167
  30. package/dist/esm/main/main.js +20 -444
  31. package/dist/esm/state/persistence/session-persister.js +20 -20
  32. package/docs/migration-GENC-1580.md +108 -58
  33. package/package.json +16 -16
  34. package/dist/dts/utils/resolve-debug-log-note.d.ts +0 -25
  35. package/dist/dts/utils/resolve-debug-log-note.d.ts.map +0 -1
  36. package/dist/esm/utils/resolve-debug-log-note.js +0 -37
@@ -112,7 +112,7 @@ export class ChatDriver extends EventTarget {
112
112
  this.turnSeq = 0;
113
113
  /**
114
114
  * Monotonic agent-activation counter — the `agentEnd` clock. Advances when the
115
- * active flow ends: a swap to a different-named agent (`applyAgent`) OR an
115
+ * active flow ends: a swap to a different-named agent (`installAgent`) OR an
116
116
  * explicit `releaseAgent` / `completeSubAgent`. A stateful agent re-resolving
117
117
  * the same name across turns keeps one activation. `agentEnd` fires for a
118
118
  * payload once a LATER activation is current (`callActivation < currentActivation`)
@@ -153,7 +153,7 @@ export class ChatDriver extends EventTarget {
153
153
  * Union of every tool name advertised at any point during the current agent
154
154
  * activation. Lets the unknown-tool path tell a *stale* call (a real tool from
155
155
  * an earlier state, now retired — or one an open exclusive fold is hiding)
156
- * apart from a *hallucinated* one. Reset on agent swap in `applyAgent`.
156
+ * apart from a *hallucinated* one. Reset on agent swap in `installAgent`.
157
157
  */
158
158
  this.everSeenToolNames = new Set();
159
159
  /**
@@ -204,7 +204,7 @@ export class ChatDriver extends EventTarget {
204
204
  this.turnCancelled = false;
205
205
  /**
206
206
  * Caches validated provider lookups per name within the current agent. Cleared
207
- * by `applyAgent` so each new agent's static/function-resolved names are
207
+ * by `installAgent` so each new agent's static/function-resolved names are
208
208
  * validated fresh.
209
209
  */
210
210
  this.resolvedProviderCache = new Map();
@@ -560,7 +560,7 @@ export class ChatDriver extends EventTarget {
560
560
  * Make `config` the active agent, firing its lifecycle hooks — `onDeactivate` on the outgoing
561
561
  * agent, then `onActivate` on this one — before installing it.
562
562
  *
563
- * This is the entry point a host should use. {@link ChatDriver.applyAgent} installs a config
563
+ * This is the entry point a host should use. {@link ChatDriver.installAgent} installs a config
564
564
  * *without* firing hooks, which is right for the two callers that need it (the orchestrator,
565
565
  * which fires them through the shared session, and `invokeSubAgent`, where a child's config is
566
566
  * not an activation) and wrong for everyone else.
@@ -570,7 +570,7 @@ export class ChatDriver extends EventTarget {
570
570
  activateAgent(config) {
571
571
  return __awaiter(this, void 0, void 0, function* () {
572
572
  yield this.agentSession.activate(config);
573
- this.applyAgent(config);
573
+ this.installAgent(config);
574
574
  });
575
575
  }
576
576
  /**
@@ -616,11 +616,10 @@ export class ChatDriver extends EventTarget {
616
616
  * {@link ChatDriver.agentSession} and then installs a decorated config, and `invokeSubAgent`,
617
617
  * where the child driver's config is a tool surface rather than an activation.
618
618
  *
619
- * Renamed to `installAgent` in a follow-up (GENC-1580) — see `docs/migration-GENC-1580.md`.
620
- * Until then the name says less than it should, so do not add a third caller to this path
621
- * without checking which of the two above it resembles.
619
+ * Do not add a third caller to this path without checking which of the two above it resembles —
620
+ * whether the hooks should fire is the whole difference between this and `activateAgent`.
622
621
  */
623
- applyAgent(config) {
622
+ installAgent(config) {
624
623
  var _a, _b, _c;
625
624
  // A real swap to a different agent begins a NEW activation — the prior agent's
626
625
  // flow is over, so its `agentEnd`-tagged payloads become collapsible. Guarded
@@ -1426,7 +1425,7 @@ export class ChatDriver extends EventTarget {
1426
1425
  else {
1427
1426
  this.lifecycleController.signal.addEventListener('abort', disposeChild, { once: true });
1428
1427
  }
1429
- child.applyAgent(Object.assign(Object.assign({}, subConfig), { primerHistory: effectivePrimer }));
1428
+ child.installAgent(Object.assign(Object.assign({}, subConfig), { primerHistory: effectivePrimer }));
1430
1429
  // Route interactions back through this driver so widgets render in the
1431
1430
  // parent's (ultimately the root's) history and resolve via the same
1432
1431
  // pending map the main UI is wired to. Recurses naturally for nested
@@ -1773,7 +1772,7 @@ export class ChatDriver extends EventTarget {
1773
1772
  };
1774
1773
  // Re-resolve dynamic tool definitions before each LLM call. The static
1775
1774
  // case is a no-op (factory is undefined and `this.toolDefinitions` was
1776
- // set by applyAgent). Folds operate on `this.toolDefinitions` and are
1775
+ // set by installAgent). Folds operate on `this.toolDefinitions` and are
1777
1776
  // forbidden when a factory is set, so the array form is always valid.
1778
1777
  // Sequential await is required — each iteration must see fresh values
1779
1778
  // before constructing the LLM request.
@@ -1964,7 +1963,7 @@ export class ChatDriver extends EventTarget {
1964
1963
  fallbacks: this.activeFallbacks,
1965
1964
  };
1966
1965
  // Resolve the active provider for this turn. Static names were validated
1967
- // in `applyAgent`; function-form names are validated on first resolution
1966
+ // in `installAgent`; function-form names are validated on first resolution
1968
1967
  // here and cached for the agent's lifetime.
1969
1968
  // oxlint-disable-next-line no-await-in-loop
1970
1969
  const activeProvider = yield this.resolveProviderForTurn(promptCtx);
@@ -156,7 +156,7 @@ export class OrchestratingDriver extends EventTarget {
156
156
  * **The inner driver's session, not one of our own.** One session is the invariant: two would
157
157
  * let the outer and inner driver disagree about which agent is active, and the inner one would
158
158
  * never be activated at all, because this driver installs a *decorated* config through
159
- * `applyAgent` rather than going via `ChatDriver.activateAgent`. This driver keeps the routing
159
+ * `installAgent` rather than going via `ChatDriver.activateAgent`. This driver keeps the routing
160
160
  * decisions; the session owns the lifecycle.
161
161
  */
162
162
  get agentSession() {
@@ -431,7 +431,7 @@ export class OrchestratingDriver extends EventTarget {
431
431
  if (this.cancelled)
432
432
  break;
433
433
  // oxlint-disable-next-line no-await-in-loop
434
- yield this.applyAgent(currentAgent);
434
+ yield this.installAgent(currentAgent);
435
435
  let result;
436
436
  if (isHandoff) {
437
437
  const contextPrimer = handoffSummary
@@ -488,7 +488,7 @@ export class OrchestratingDriver extends EventTarget {
488
488
  break;
489
489
  }
490
490
  // Pinned agents never hand off — the continuation tool is filtered out in
491
- // applyAgent, but this guards against a model hallucinating a handoff result.
491
+ // installAgent, but this guards against a model hallucinating a handoff result.
492
492
  if (result.reason !== 'agent-handoff' || isFallback(currentAgent) || pinned) {
493
493
  break;
494
494
  }
@@ -592,7 +592,7 @@ export class OrchestratingDriver extends EventTarget {
592
592
  getActiveAgent() {
593
593
  return this.agentSession.getActive();
594
594
  }
595
- applyAgent(agent) {
595
+ installAgent(agent) {
596
596
  return __awaiter(this, void 0, void 0, function* () {
597
597
  // The transition — handoff record, lifecycle hooks, restored state, flow lock — belongs to
598
598
  // the session. What is left below is this driver's own job: what the agent may route to, and
@@ -634,7 +634,7 @@ export class OrchestratingDriver extends EventTarget {
634
634
  ]);
635
635
  }
636
636
  this.chatDriver.setProviderHistoryTransform((h) => transformHistoryForAgent(h, agent.name));
637
- this.chatDriver.applyAgent(agentToApply);
637
+ this.chatDriver.installAgent(agentToApply);
638
638
  this.dispatchEvent(new CustomEvent('orchestrating-stop'));
639
639
  this.dispatchEvent(new CustomEvent('agent-changed', { detail: agent }));
640
640
  });
@@ -225,7 +225,6 @@ export class SettingsModalController {
225
225
  (ui === null || ui === void 0 ? void 0 : ui.showNarration) != null ||
226
226
  (ui === null || ui === void 0 ? void 0 : ui.showAgentSwitchIndicator) != null ||
227
227
  (ui === null || ui === void 0 ? void 0 : ui.allowDebugDownload) === true ||
228
- (ui === null || ui === void 0 ? void 0 : ui.debugLogSubmit) != null ||
229
228
  (ui === null || ui === void 0 ? void 0 : ui.animations) != null ||
230
229
  cost.showCost ||
231
230
  cost.showTokens ||
@@ -826,93 +826,13 @@ export const settingsModalStyles = css `
826
826
  line-height: 1.4;
827
827
  }
828
828
 
829
- /* The agent-log row's two actions (Download / Send) side by side. */
830
- .agent-log-actions {
831
- display: flex;
832
- align-items: center;
833
- gap: calc(var(--design-unit) * 2px);
834
- }
835
-
836
- /*
837
- * Row + compose box. The row is normally the section's last child (no divider); inside
838
- * the wrapper it is only the last child while the box is closed, so drop the divider
839
- * explicitly and let the box supply its own spacing beneath the row.
840
- */
841
- .agent-log-block {
842
- display: flex;
843
- flex-direction: column;
844
- }
845
-
846
- .agent-log-block .settings-toggle-row {
847
- border-bottom: none;
848
- padding-bottom: calc(var(--design-unit) * 1px);
849
- }
850
-
851
- .agent-log-compose {
852
- display: flex;
853
- flex-direction: column;
854
- gap: calc(var(--design-unit) * 2px);
855
- margin-top: calc(var(--design-unit) * 2px);
856
- }
857
-
858
- .agent-log-note {
859
- width: 100%;
860
- }
861
-
862
- .agent-log-note::part(control) {
863
- width: 100%;
864
- box-sizing: border-box;
865
- font-size: 13px;
866
- line-height: 1.5;
867
- }
868
-
869
- .agent-log-compose-footer {
870
- display: flex;
871
- align-items: center;
872
- justify-content: space-between;
873
- gap: calc(var(--design-unit) * 3px);
874
- }
875
-
876
- /* Counter / validation / failure line. Hint-coloured until it carries an error. */
877
- .agent-log-compose-hint {
878
- font-size: 12px;
879
- color: var(--neutral-foreground-hint);
880
- min-width: 0;
881
- }
882
-
883
- /*
884
- * Failure state without leaning on --error-color: rapid's fixed brand red is 3.02:1 on a
885
- * light surface, under AA for 12px text, and the failure line is the one that most needs
886
- * reading. The contrast-adaptive foreground plus weight carries it; the text itself also
887
- * changes, so colour was never the only channel.
888
- */
889
- .agent-log-compose-hint.is-error {
890
- color: var(--neutral-foreground-rest);
891
- font-weight: 600;
892
- }
893
-
894
- /* Screen-reader-only live region for submission outcomes (same recipe as main.styles). */
895
- .visually-hidden {
896
- position: absolute;
897
- width: 1px;
898
- height: 1px;
899
- margin: -1px;
900
- padding: 0;
901
- overflow: hidden;
902
- clip-path: inset(50%);
903
- white-space: nowrap;
904
- border: 0;
905
- }
906
-
907
829
  /*
908
- * Inline spinner shown in the agent-log buttons (Download / Send) while the log
909
- * builds (GENC-1351 §5.8) — the lifetime-stitch path is an async provider
910
- * round-trip. Sized to the button label and tinted with currentColor so it tracks
911
- * the button's text colour in every appearance / theme.
830
+ * Inline spinner shown in the "Download agent log" button while the log builds
831
+ * (GENC-1351 §5.8) — the lifetime-stitch path is an async provider round-trip.
832
+ * Sized to the button label and tinted with currentColor so it tracks the
833
+ * button's text colour in every appearance / theme.
912
834
  */
913
- [part='download-button'] .download-spinner,
914
- [part='submit-log-button'] .download-spinner,
915
- [part='agent-log-send-button'] .download-spinner {
835
+ [part='download-button'] .download-spinner {
916
836
  display: inline-block;
917
837
  width: 12px;
918
838
  height: 12px;
@@ -562,171 +562,6 @@ const costSessionHistoryTemplate = (iconTag, buttonTag) => html `
562
562
  </div>
563
563
  `)}
564
564
  `;
565
- /**
566
- * The settings "Agent log" section: the Download / Send row, the always-present status
567
- * live region, and the Send button's compose box. Exported (like
568
- * `settingsUsageMetersTemplate`) so `agent-log-section.template.test.ts` can render it on
569
- * an unconnected element and pin what the getters alone cannot show — that the `when`s,
570
- * `?disabled`s and part tokens are actually wired to them.
571
- */
572
- export const agentLogSectionTemplate = (buttonTag, textareaTag) => html `
573
- ${when((x) => x.settingsAgentLogSectionVisible, html `
574
- <section class="settings-modal-section" part="settings-section-agent-log">
575
- <div class="settings-modal-section-body">
576
- <!--
577
- Row and compose box share a wrapper so the box can drop straight under the
578
- row (full width, no divider between them) while the row keeps its layout.
579
- -->
580
- <div class="agent-log-block" part="agent-log-block">
581
- ${settingsToggleRow('Agent log', (x) => x.debugLogRowDescription,
582
- // The helper appends "-row", so this renders as
583
- // part="download-agent-log-row agent-log-row": the original token stays
584
- // for hosts already styling it, and `agent-log-row` names what the row
585
- // now is — the container of both actions. Pinned in
586
- // agent-log-section.template.test.ts.
587
- 'download-agent-log-row agent-log', html `
588
- <div class="agent-log-actions" part="agent-log-actions">
589
- ${when((x) => { var _a; return ((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.allowDebugDownload) === true; }, html `
590
- <${buttonTag}
591
- part="download-button"
592
- appearance="outline"
593
- ?disabled=${(x) => x.downloadingDebugLog}
594
- @click=${(x) => x.downloadDebugLog()}
595
- >
596
- ${when((x) => x.downloadingDebugLog, html `
597
- <span
598
- class="download-spinner"
599
- part="download-spinner"
600
- aria-hidden="true"
601
- ></span>
602
- `)}
603
- ${(x) => (x.downloadingDebugLog ? 'Downloading…' : 'Download')}
604
- </${buttonTag}>
605
- `)}
606
- ${when((x) => { var _a; return ((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.debugLogSubmit) != null; }, html `
607
- <${buttonTag}
608
- part="submit-log-button"
609
- appearance="outline"
610
- ?disabled=${(x) => x.submittingDebugLog || x.debugLogComposeOpen}
611
- aria-expanded=${(x) => x.debugLogNoteConfig ? String(x.debugLogComposeOpen) : null}
612
- @click=${(x) => x.openDebugLogCompose()}
613
- >
614
- ${when((x) => x.submittingDebugLog && !x.debugLogComposeOpen, html `
615
- <span
616
- class="download-spinner"
617
- part="download-spinner"
618
- aria-hidden="true"
619
- ></span>
620
- `)}
621
- ${(x) => x.debugLogSubmitButtonLabel}
622
- </${buttonTag}>
623
- `)}
624
- </div>
625
- `, 'row-centered')}
626
- <!--
627
- Present whenever Send is configured (not gated on the compose box) so a live region exists
628
- BEFORE an outcome lands in it — one that appears together with its text is
629
- not announced — and so a note-less (note: false) host, whose only visible change is
630
- the button label, is announced too.
631
- -->
632
- ${when((x) => { var _a; return ((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.debugLogSubmit) != null; }, html `
633
- <span
634
- class="visually-hidden"
635
- part="agent-log-status"
636
- role="status"
637
- aria-live="polite"
638
- >
639
- ${(x) => x.debugLogSubmitAnnouncement}
640
- </span>
641
- `)}
642
- ${when((x) => x.debugLogComposeOpen && x.debugLogNoteConfig !== null, html `
643
- <!--
644
- Keys are handled on the wrapper so they mean the same from every control:
645
- Escape cancels the box (and does not reach the dialog, which would close
646
- the whole modal and lose the note) whether focus is on the note, Cancel or
647
- Send; Enter submits only from the note, and only when a submit would
648
- actually go — otherwise the key keeps its default so it is not simply dead.
649
- -->
650
- <div
651
- class="agent-log-compose"
652
- part="agent-log-compose"
653
- @keydown=${(x, c) => {
654
- const e = c.event;
655
- if (e.key === 'Escape') {
656
- x.cancelDebugLogCompose();
657
- return false;
658
- }
659
- if (e.key === 'Enter' &&
660
- !e.shiftKey &&
661
- e.target === x.debugLogNoteEl &&
662
- !x.debugLogSendDisabled) {
663
- void x.submitDebugLog();
664
- return false;
665
- }
666
- return true;
667
- }}
668
- >
669
- <${textareaTag}
670
- ${ref('debugLogNoteEl')}
671
- class="agent-log-note"
672
- part="agent-log-note"
673
- rows="3"
674
- resize="vertical"
675
- aria-label=${(x) => x.debugLogNoteAriaLabel}
676
- placeholder=${(x) => { var _a; return (_a = x.debugLogNoteConfig) === null || _a === void 0 ? void 0 : _a.placeholder; }}
677
- maxlength=${(x) => { var _a; return (_a = x.debugLogNoteConfig) === null || _a === void 0 ? void 0 : _a.maxLength; }}
678
- :value=${(x) => x.debugLogNote}
679
- ?disabled=${(x) => x.submittingDebugLog}
680
- @input=${(x, c) => x.noteDebugLogInput(c.event.target.value)}
681
- ></${textareaTag}>
682
- <div class="agent-log-compose-footer">
683
- <!--
684
- Visual hint only (aria-hidden): a live counter would be announced on
685
- every keystroke, and an IDREF from the text-area cannot reach across
686
- its shadow boundary. AT gets the cap from the note's static aria-label,
687
- the remaining count near the cap and every outcome from the row's
688
- status region.
689
- -->
690
- <span
691
- class="agent-log-compose-hint ${(x) => x.debugLogSubmitResult === 'error' ? 'is-error' : ''}"
692
- part="agent-log-compose-hint"
693
- aria-hidden="true"
694
- >
695
- ${(x) => x.debugLogComposeHint}
696
- </span>
697
- <div class="agent-log-actions">
698
- <${buttonTag}
699
- part="agent-log-cancel-button"
700
- appearance="outline"
701
- ?disabled=${(x) => x.submittingDebugLog}
702
- @click=${(x) => x.cancelDebugLogCompose()}
703
- >
704
- Cancel
705
- </${buttonTag}>
706
- <${buttonTag}
707
- part="agent-log-send-button"
708
- appearance="accent"
709
- ?disabled=${(x) => x.debugLogSendDisabled}
710
- @click=${(x) => x.submitDebugLog()}
711
- >
712
- ${when((x) => x.submittingDebugLog, html `
713
- <span
714
- class="download-spinner"
715
- part="download-spinner"
716
- aria-hidden="true"
717
- ></span>
718
- `)}
719
- ${(x) => (x.submittingDebugLog ? 'Sending…' : x.debugLogSubmitLabel)}
720
- </${buttonTag}>
721
- </div>
722
- </div>
723
- </div>
724
- `)}
725
- </div>
726
- </div>
727
- </section>
728
- `)}
729
- `;
730
565
  /**
731
566
  * Modal shell for assistant settings — Configuration and Usage tabs, section slots for
732
567
  * app-specific UI, and built-in chat-bot toggles.
@@ -737,7 +572,6 @@ export const SettingsModalTemplate = (designSystemPrefix) => {
737
572
  const switchTag = `${designSystemPrefix}-switch`;
738
573
  const iconTag = `${designSystemPrefix}-icon`;
739
574
  const progressTag = `${designSystemPrefix}-progress`;
740
- const textareaTag = `${designSystemPrefix}-text-area`;
741
575
  const tabsTag = `${designSystemPrefix}-tabs`;
742
576
  const tabTag = `${designSystemPrefix}-tab`;
743
577
  const tabPanelTag = `${designSystemPrefix}-tab-panel`;
@@ -768,7 +602,29 @@ export const SettingsModalTemplate = (designSystemPrefix) => {
768
602
  with the assistant's other sections rather than trailing the host's — where, now that the
769
603
  host section carries no heading of its own, it read as one more of the host's settings.
770
604
  -->
771
- ${agentLogSectionTemplate(buttonTag, textareaTag)}
605
+ ${when((x) => { var _a; return ((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.allowDebugDownload) === true; }, html `
606
+ <section class="settings-modal-section" part="settings-section-agent-log">
607
+ <div class="settings-modal-section-body">
608
+ ${settingsToggleRow('Download agent log', "Export a structured debug timeline of this session's agent activity.", 'download-agent-log', html `
609
+ <${buttonTag}
610
+ part="download-button"
611
+ appearance="outline"
612
+ ?disabled=${(x) => x.downloadingDebugLog}
613
+ @click=${(x) => x.downloadDebugLog()}
614
+ >
615
+ ${when((x) => x.downloadingDebugLog, html `
616
+ <span
617
+ class="download-spinner"
618
+ part="download-spinner"
619
+ aria-hidden="true"
620
+ ></span>
621
+ `)}
622
+ ${(x) => (x.downloadingDebugLog ? 'Downloading…' : 'Download')}
623
+ </${buttonTag}>
624
+ `, 'row-centered')}
625
+ </div>
626
+ </section>
627
+ `)}
772
628
  <!--
773
629
  No heading here, by design. This section belongs to the host: only it knows what its
774
630
  settings are called, so the assistant supplies neither text nor icon and the host titles