@agent-native/core 0.126.0 → 0.127.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 (152) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +71 -0
  3. package/corpus/core/docs/content/external-agents-catalog.mdx +14 -11
  4. package/corpus/core/docs/content/mcp-protocol.mdx +9 -4
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/a2a/index.ts +2 -0
  7. package/corpus/core/src/agent/production-agent.ts +6 -1
  8. package/corpus/core/src/agent/run-manager.ts +37 -0
  9. package/corpus/core/src/agent/run-store.ts +18 -0
  10. package/corpus/core/src/client/MultiTabAssistantChat.tsx +75 -43
  11. package/corpus/core/src/client/agent-chat.ts +19 -1
  12. package/corpus/core/src/client/chat/tool-call-display.tsx +25 -0
  13. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +23 -0
  14. package/corpus/core/src/client/settings/AgentsSection.tsx +565 -71
  15. package/corpus/core/src/client/settings/SecretsSection.tsx +71 -36
  16. package/corpus/core/src/client/use-chat-models.ts +54 -37
  17. package/corpus/core/src/localization/default-messages.ts +11 -0
  18. package/corpus/core/src/mcp/ask-app-task-handle.ts +183 -0
  19. package/corpus/core/src/mcp/builtin-tools.ts +146 -34
  20. package/corpus/core/src/server/agent-capabilities.ts +8 -1
  21. package/corpus/core/src/server/agent-chat-plugin.ts +17 -0
  22. package/corpus/core/src/server/agent-discovery.ts +1 -1
  23. package/corpus/core/src/server/agent-peer-probe.ts +133 -0
  24. package/corpus/core/src/server/core-routes-plugin.ts +67 -0
  25. package/corpus/core/src/shared/mcp-embed-headers.ts +4 -0
  26. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
  27. package/corpus/templates/design/app/hooks/use-question-flow.ts +21 -1
  28. package/corpus/templates/design/changelog/2026-07-28-the-model-you-pick-when-starting-a-new-design-is-now-used-fo.md +6 -0
  29. package/corpus/templates/dispatch/changelog/2026-07-28-pending-apps-are-hidden-by-default-and-app-ownership-details.md +6 -0
  30. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +5 -1
  31. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +5 -0
  32. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +31 -8
  33. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +15 -0
  34. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +78 -8
  35. package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +179 -0
  36. package/corpus/templates/slides/app/components/presentation/present-channel.ts +15 -0
  37. package/corpus/templates/slides/app/i18n/en-US.ts +10 -1
  38. package/corpus/templates/slides/app/lib/export-google-slides-client.ts +67 -0
  39. package/corpus/templates/slides/app/lib/export-pptx-client.ts +16 -3
  40. package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -0
  41. package/corpus/templates/slides/app/pages/Presentation.tsx +11 -3
  42. package/corpus/templates/slides/changelog/2026-07-28-export-to-google-slides-now-creates-the-deck-directly-in-you.md +6 -0
  43. package/corpus/templates/slides/changelog/2026-07-28-opening-a-presentation-link-directly-no-longer-bounces-back-.md +6 -0
  44. package/corpus/templates/slides/changelog/2026-07-28-presenter-view-open-a-second-window-while-presenting-to-see-.md +6 -0
  45. package/corpus/templates/slides/server/routes/api/exports/google-slides.post.ts +90 -0
  46. package/corpus/toolkit/CHANGELOG.md +6 -0
  47. package/corpus/toolkit/package.json +1 -1
  48. package/corpus/toolkit/src/composer/TiptapComposer.tsx +143 -111
  49. package/corpus/toolkit/src/composer/runtime-adapters.tsx +2 -0
  50. package/dist/a2a/index.d.ts +2 -0
  51. package/dist/a2a/index.d.ts.map +1 -1
  52. package/dist/a2a/index.js +1 -0
  53. package/dist/a2a/index.js.map +1 -1
  54. package/dist/agent/production-agent.d.ts +2 -2
  55. package/dist/agent/production-agent.d.ts.map +1 -1
  56. package/dist/agent/production-agent.js +6 -3
  57. package/dist/agent/production-agent.js.map +1 -1
  58. package/dist/agent/run-manager.d.ts +11 -0
  59. package/dist/agent/run-manager.d.ts.map +1 -1
  60. package/dist/agent/run-manager.js +34 -1
  61. package/dist/agent/run-manager.js.map +1 -1
  62. package/dist/agent/run-store.d.ts +8 -0
  63. package/dist/agent/run-store.d.ts.map +1 -1
  64. package/dist/agent/run-store.js +16 -0
  65. package/dist/agent/run-store.js.map +1 -1
  66. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  67. package/dist/client/MultiTabAssistantChat.js +60 -31
  68. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  69. package/dist/client/agent-chat.d.ts +6 -0
  70. package/dist/client/agent-chat.d.ts.map +1 -1
  71. package/dist/client/agent-chat.js +13 -1
  72. package/dist/client/agent-chat.js.map +1 -1
  73. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  74. package/dist/client/chat/tool-call-display.js +14 -0
  75. package/dist/client/chat/tool-call-display.js.map +1 -1
  76. package/dist/client/resources/mcp-integration-catalog.d.ts +6 -0
  77. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  78. package/dist/client/resources/mcp-integration-catalog.js +16 -0
  79. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  80. package/dist/client/settings/AgentsSection.d.ts.map +1 -1
  81. package/dist/client/settings/AgentsSection.js +250 -30
  82. package/dist/client/settings/AgentsSection.js.map +1 -1
  83. package/dist/client/settings/SecretsSection.d.ts.map +1 -1
  84. package/dist/client/settings/SecretsSection.js +16 -2
  85. package/dist/client/settings/SecretsSection.js.map +1 -1
  86. package/dist/client/use-chat-models.d.ts.map +1 -1
  87. package/dist/client/use-chat-models.js +46 -27
  88. package/dist/client/use-chat-models.js.map +1 -1
  89. package/dist/collab/routes.d.ts +1 -1
  90. package/dist/localization/default-messages.d.ts +9 -0
  91. package/dist/localization/default-messages.d.ts.map +1 -1
  92. package/dist/localization/default-messages.js +9 -0
  93. package/dist/localization/default-messages.js.map +1 -1
  94. package/dist/mcp/ask-app-task-handle.d.ts +25 -0
  95. package/dist/mcp/ask-app-task-handle.d.ts.map +1 -0
  96. package/dist/mcp/ask-app-task-handle.js +136 -0
  97. package/dist/mcp/ask-app-task-handle.js.map +1 -0
  98. package/dist/mcp/builtin-tools.d.ts +3 -3
  99. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  100. package/dist/mcp/builtin-tools.js +115 -38
  101. package/dist/mcp/builtin-tools.js.map +1 -1
  102. package/dist/observability/routes.d.ts +1 -1
  103. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  104. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  105. package/dist/server/agent-capabilities.d.ts +7 -1
  106. package/dist/server/agent-capabilities.d.ts.map +1 -1
  107. package/dist/server/agent-capabilities.js +1 -0
  108. package/dist/server/agent-capabilities.js.map +1 -1
  109. package/dist/server/agent-chat-plugin.d.ts +7 -0
  110. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  111. package/dist/server/agent-chat-plugin.js +16 -1
  112. package/dist/server/agent-chat-plugin.js.map +1 -1
  113. package/dist/server/agent-discovery.d.ts +1 -0
  114. package/dist/server/agent-discovery.d.ts.map +1 -1
  115. package/dist/server/agent-discovery.js +1 -1
  116. package/dist/server/agent-discovery.js.map +1 -1
  117. package/dist/server/agent-peer-probe.d.ts +37 -0
  118. package/dist/server/agent-peer-probe.d.ts.map +1 -0
  119. package/dist/server/agent-peer-probe.js +90 -0
  120. package/dist/server/agent-peer-probe.js.map +1 -0
  121. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  122. package/dist/server/core-routes-plugin.js +53 -0
  123. package/dist/server/core-routes-plugin.js.map +1 -1
  124. package/dist/shared/mcp-embed-headers.d.ts +1 -0
  125. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  126. package/dist/shared/mcp-embed-headers.js +4 -0
  127. package/dist/shared/mcp-embed-headers.js.map +1 -1
  128. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
  129. package/docs/content/external-agents-catalog.mdx +14 -11
  130. package/docs/content/mcp-protocol.mdx +9 -4
  131. package/package.json +2 -2
  132. package/src/a2a/index.ts +2 -0
  133. package/src/agent/production-agent.ts +6 -1
  134. package/src/agent/run-manager.ts +37 -0
  135. package/src/agent/run-store.ts +18 -0
  136. package/src/client/MultiTabAssistantChat.tsx +75 -43
  137. package/src/client/agent-chat.ts +19 -1
  138. package/src/client/chat/tool-call-display.tsx +25 -0
  139. package/src/client/resources/mcp-integration-catalog.ts +23 -0
  140. package/src/client/settings/AgentsSection.tsx +565 -71
  141. package/src/client/settings/SecretsSection.tsx +71 -36
  142. package/src/client/use-chat-models.ts +54 -37
  143. package/src/localization/default-messages.ts +11 -0
  144. package/src/mcp/ask-app-task-handle.ts +183 -0
  145. package/src/mcp/builtin-tools.ts +146 -34
  146. package/src/server/agent-capabilities.ts +8 -1
  147. package/src/server/agent-chat-plugin.ts +17 -0
  148. package/src/server/agent-discovery.ts +1 -1
  149. package/src/server/agent-peer-probe.ts +133 -0
  150. package/src/server/core-routes-plugin.ts +67 -0
  151. package/src/shared/mcp-embed-headers.ts +4 -0
  152. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
@@ -1 +1 @@
1
- {"version":3,"file":"MultiTabAssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/MultiTabAssistantChat.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AA4BxE,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AA0B5B,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,uBAAuB,CAAC;AA2a/B,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IACzC,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsGD,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACpE;AAyED,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,kBAAkB,EAClB,OAAO,GAAG,UAAU,CACrB,GAAG;IACF,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5E,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7E,sGAAsG;IACtG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,wBAAwB,CAAC;IACnD,2DAA2D;IAC3D,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,iEAAiE;IACjE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,UAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAqB,EACrB,MAAqD,EACrD,UAAU,EACV,mBAA0B,EAC1B,YAAY,EACZ,aAAqB,EACrB,KAAY,EACZ,GAAG,KAAK,EACT,EAAE,0BAA0B,qBAg1D5B"}
1
+ {"version":3,"file":"MultiTabAssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/MultiTabAssistantChat.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AA4BxE,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AA0B5B,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,uBAAuB,CAAC;AA6a/B,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IACzC,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsGD,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACpE;AAyED,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,kBAAkB,EAClB,OAAO,GAAG,UAAU,CACrB,GAAG;IACF,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5E,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7E,sGAAsG;IACtG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,wBAAwB,CAAC;IACnD,2DAA2D;IAC3D,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,iEAAiE;IACjE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,UAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAqB,EACrB,MAAqD,EACrD,UAAU,EACV,mBAA0B,EAC1B,YAAY,EACZ,aAAqB,EACrB,KAAY,EACZ,GAAG,KAAK,EACT,EAAE,0BAA0B,qBA82D5B"}
@@ -78,19 +78,27 @@ function writeStoredModelSelection(key, selection) {
78
78
  function resolveModelSelection(selection, groups) {
79
79
  if (!selection?.model)
80
80
  return undefined;
81
- if (groups.length === 0) {
82
- return {
83
- model: selection.model,
84
- effort: resolveReasoningEffortSelection(selection.model, selection.effort),
85
- };
86
- }
87
- const preferredGroup = groups.find((group) => group.engine === selection.engine &&
88
- group.models.includes(selection.model));
89
- const fallbackGroup = groups.find((group) => group.models.includes(selection.model));
90
- if (groups.length > 0 && !preferredGroup && !fallbackGroup) {
91
- return undefined;
92
- }
93
- const engine = preferredGroup?.engine ?? fallbackGroup?.engine ?? selection.engine;
81
+ // Engine precedence turns on whether the catalog OFFERS the supplied engine,
82
+ // not on whether that engine advertises this model:
83
+ // offered → honor it. A gateway's advertised list is its built-in
84
+ // catalog, not what the endpoint serves, and one model id
85
+ // sits under several groups (claude-sonnet-5 under both
86
+ // anthropic and builder) — so a model-only match would
87
+ // reroute the turn to a different provider and bill it there.
88
+ // not offered → heal to a group that serves the model. A selection left
89
+ // on `builder` after disconnecting it must still run on the
90
+ // user's own key; the same model through another configured
91
+ // provider is the point of bring-your-own-key.
92
+ // `builder` is in the catalog exactly when Builder is connected, so this is a
93
+ // real availability signal rather than a guess.
94
+ const suppliedEngine = selection.engine?.trim()
95
+ ? selection.engine
96
+ : undefined;
97
+ const engine = (groups.some((group) => group.engine === suppliedEngine)
98
+ ? suppliedEngine
99
+ : undefined) ??
100
+ groups.find((group) => group.models.includes(selection.model))?.engine ??
101
+ suppliedEngine;
94
102
  if (!engine && groups.length > 0)
95
103
  return undefined;
96
104
  const effort = resolveReasoningEffortSelection(selection.model, selection.effort);
@@ -644,8 +652,12 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
644
652
  .catch(() => null),
645
653
  ])
646
654
  .then(([enginesData, envKeys, builderStatus]) => {
647
- if (!enginesData?.engines)
655
+ if (!enginesData?.engines) {
656
+ // Leaves `availableModels` empty for the session, so an override with
657
+ // no engine of its own has nothing to resolve against.
658
+ console.warn("[agent-chat] no engine list; model overrides cannot be catalog-resolved");
648
659
  return;
660
+ }
649
661
  const configuredKeys = new Set(envKeys
650
662
  .filter((k) => k.configured)
651
663
  .map((k) => k.key));
@@ -1094,7 +1106,7 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1094
1106
  // Dedup the live post against the cold-start replay; first one wins.
1095
1107
  if (!claimAgentChatSubmit(parsed.submitMessageId))
1096
1108
  return;
1097
- const { message, context, openSidebar, model, effort, newTab, background, submit, images, submitMessageId, } = parsed;
1109
+ const { message, context, openSidebar, model, engine, effort, newTab, background, submit, images, submitMessageId, } = parsed;
1098
1110
  const requestedTabId = parsed.tabId;
1099
1111
  const requestMode = parsed.requestMode ?? requestModeFromExecMode(props.execMode);
1100
1112
  // Make sure the sidebar is visible to show the response, unless the
@@ -1119,28 +1131,37 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1119
1131
  ...(requestMode ? { requestMode } : {}),
1120
1132
  ...(submitMessageId ? { submitMessageId } : {}),
1121
1133
  };
1134
+ // Resolved once, up front, and carried with the send until a thread
1135
+ // exists to key it by. Applying it only when `model` matched
1136
+ // `availableModels` dropped every override that arrived before the
1137
+ // engines fetch resolved — and the cold-start replay below runs at mount,
1138
+ // when that list is always still empty.
1139
+ let modelOverride;
1140
+ if (model) {
1141
+ const catalogEngine = availableModels.find((g) => g.models.includes(model))?.engine;
1142
+ const overrideEngine = engine ?? catalogEngine;
1143
+ if (!overrideEngine && availableModels.length > 0) {
1144
+ console.warn(`[agent-chat] model override "${model}" is in no engine group and carries no engine; the server will substitute its default`);
1145
+ }
1146
+ modelOverride = {
1147
+ model,
1148
+ ...(overrideEngine ? { engine: overrideEngine } : {}),
1149
+ effort: resolveReasoningEffortSelection(model, isReasoningEffort(effort) ? effort : undefined),
1150
+ };
1151
+ }
1122
1152
  const sendToTab = (threadId) => {
1123
1153
  if (isAgentChatSubmitCancelled(submitMessageId))
1124
1154
  return;
1125
- // If a model override was specified, apply it only if we recognize it
1126
- if (model) {
1127
- const matchedGroup = availableModels.find((g) => g.models.includes(model));
1128
- if (matchedGroup) {
1129
- const selectedEffort = resolveReasoningEffortSelection(model, isReasoningEffort(effort) ? effort : undefined);
1130
- threadModelRef.current.set(threadId, {
1131
- model,
1132
- engine: matchedGroup.engine,
1133
- effort: selectedEffort,
1134
- });
1135
- bumpModelSelectionVersion();
1136
- }
1155
+ if (modelOverride) {
1156
+ threadModelRef.current.set(threadId, modelOverride);
1157
+ bumpModelSelectionVersion();
1137
1158
  }
1138
1159
  const ref = chatRefs.current.get(threadId);
1139
1160
  if (ref) {
1140
1161
  deliverPendingSend(ref, send);
1141
1162
  }
1142
1163
  else {
1143
- pendingDeliveries.current.push({ threadId, send });
1164
+ pendingDeliveries.current.push({ threadId, send, modelOverride });
1144
1165
  }
1145
1166
  };
1146
1167
  if (newTab) {
@@ -1178,7 +1199,11 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1178
1199
  else {
1179
1200
  // Cold start: no thread yet. Queue for the first active thread (the
1180
1201
  // bootstrap effect creates it) rather than racing a second create.
1181
- pendingDeliveries.current.push({ threadId: null, send });
1202
+ pendingDeliveries.current.push({
1203
+ threadId: null,
1204
+ send,
1205
+ modelOverride,
1206
+ });
1182
1207
  }
1183
1208
  }
1184
1209
  };
@@ -1230,17 +1255,21 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1230
1255
  continue;
1231
1256
  const threadId = delivery.threadId ?? active ?? null;
1232
1257
  const ref = threadId ? chatRefs.current.get(threadId) : null;
1258
+ if (threadId && delivery.modelOverride) {
1259
+ threadModelRef.current.set(threadId, delivery.modelOverride);
1260
+ bumpModelSelectionVersion();
1261
+ }
1233
1262
  if (threadId && ref) {
1234
1263
  const { send } = delivery;
1235
1264
  setTimeout(() => deliverPendingSend(ref, send), 50);
1236
1265
  }
1237
1266
  else {
1238
1267
  // Not ready — keep it, pinning the resolved threadId once known.
1239
- remaining.push(threadId ? { threadId, send: delivery.send } : delivery);
1268
+ remaining.push(threadId ? { ...delivery, threadId, send: delivery.send } : delivery);
1240
1269
  }
1241
1270
  }
1242
1271
  pendingDeliveries.current = remaining;
1243
- }, [openTabIds, activeThreadId]);
1272
+ }, [openTabIds, activeThreadId, bumpModelSelectionVersion]);
1244
1273
  // Listen for chatRunning completion events
1245
1274
  useEffect(() => {
1246
1275
  const handler = (e) => {