@genesislcap/ai-assistant 15.21.0 → 15.21.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 (29) hide show
  1. package/dist/ai-assistant.api.json +135 -1
  2. package/dist/ai-assistant.d.ts +152 -0
  3. package/dist/chat-driver.cjs +281 -81
  4. package/dist/chat-driver.cjs.map +2 -2
  5. package/dist/chat-driver.mjs +277 -81
  6. package/dist/chat-driver.mjs.map +2 -2
  7. package/dist/custom-elements.json +175 -8
  8. package/dist/dts/components/chat-driver/chat-driver.d.ts +39 -0
  9. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  10. package/dist/dts/components/orchestrating-driver/index.d.ts +2 -1
  11. package/dist/dts/components/orchestrating-driver/index.d.ts.map +1 -1
  12. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +101 -0
  13. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  14. package/dist/dts/config/fallback-agents.d.ts +7 -0
  15. package/dist/dts/config/fallback-agents.d.ts.map +1 -1
  16. package/dist/dts/state/debug-event-log.d.ts +1 -1
  17. package/dist/dts/state/debug-event-log.d.ts.map +1 -1
  18. package/dist/dts/utils/context-tokens.d.ts +25 -3
  19. package/dist/dts/utils/context-tokens.d.ts.map +1 -1
  20. package/dist/dts/utils/history-transform.d.ts +23 -3
  21. package/dist/dts/utils/history-transform.d.ts.map +1 -1
  22. package/dist/esm/components/chat-driver/chat-driver.js +72 -56
  23. package/dist/esm/components/orchestrating-driver/index.js +1 -1
  24. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +266 -36
  25. package/dist/esm/config/fallback-agents.js +12 -1
  26. package/dist/esm/state/debug-event-log.js +7 -2
  27. package/dist/esm/utils/context-tokens.js +27 -3
  28. package/dist/esm/utils/history-transform.js +54 -5
  29. package/package.json +16 -16
@@ -7393,6 +7393,33 @@
7393
7393
  ],
7394
7394
  "extendsTokenRanges": []
7395
7395
  },
7396
+ {
7397
+ "kind": "Variable",
7398
+ "canonicalReference": "@genesislcap/ai-assistant!EMPTY_RESPONSE_NUDGE:var",
7399
+ "docComment": "/**\n * Framed-tail nudge added to a retry after an EMPTY response.\n *\n * Rewritten in GENC-1573. The previous copy (\"You must respond to the user's message. Call the appropriate tool or provide a text response\") told a model that had just returned nothing to respond, without naming the one exit available to an agent that genuinely cannot act: saying so. Across nine failures in the measured session it changed nothing — all 29 attempts came back at 8–9 output tokens — and most of those were on a tool-less agent, for which \"call the appropriate tool\" is not an option at all. This version names the honest answer explicitly.\n *\n * @beta\n */\n",
7400
+ "excerptTokens": [
7401
+ {
7402
+ "kind": "Content",
7403
+ "text": "EMPTY_RESPONSE_NUDGE = "
7404
+ },
7405
+ {
7406
+ "kind": "Content",
7407
+ "text": "\"IMPORTANT: Your previous attempt returned nothing at all, which is never a valid response. Answer the user's last message now, in prose \\u2014 even if all you can honestly say is that you cannot help with it and why. If a tool is the right way to answer, call it. Do not return an empty response.\""
7408
+ }
7409
+ ],
7410
+ "fileUrlPath": "src/components/chat-driver/chat-driver.ts",
7411
+ "initializerTokenRange": {
7412
+ "startIndex": 1,
7413
+ "endIndex": 2
7414
+ },
7415
+ "isReadonly": true,
7416
+ "releaseTag": "Beta",
7417
+ "name": "EMPTY_RESPONSE_NUDGE",
7418
+ "variableTypeTokenRange": {
7419
+ "startIndex": 0,
7420
+ "endIndex": 0
7421
+ }
7422
+ },
7396
7423
  {
7397
7424
  "kind": "Function",
7398
7425
  "canonicalReference": "@genesislcap/ai-assistant!expandToolTree:function(1)",
@@ -14961,6 +14988,33 @@
14961
14988
  "parameters": [],
14962
14989
  "name": "isAiAssistantDocked"
14963
14990
  },
14991
+ {
14992
+ "kind": "Variable",
14993
+ "canonicalReference": "@genesislcap/ai-assistant!MALFORMED_CALL_NUDGE:var",
14994
+ "docComment": "/**\n * Framed-tail nudge added to a retry after a MALFORMED tool call.\n *\n * Exported so tests can assert placement (framed tail, never the system prompt) without pinning the wording — the copy is a prompt, and a prompt should be free to improve.\n *\n * @beta\n */\n",
14995
+ "excerptTokens": [
14996
+ {
14997
+ "kind": "Content",
14998
+ "text": "MALFORMED_CALL_NUDGE = "
14999
+ },
15000
+ {
15001
+ "kind": "Content",
15002
+ "text": "\"IMPORTANT: Use only the structured function-call API to invoke tools. Do not write Python code or use Python-style syntax to call tools.\""
15003
+ }
15004
+ ],
15005
+ "fileUrlPath": "src/components/chat-driver/chat-driver.ts",
15006
+ "initializerTokenRange": {
15007
+ "startIndex": 1,
15008
+ "endIndex": 2
15009
+ },
15010
+ "isReadonly": true,
15011
+ "releaseTag": "Beta",
15012
+ "name": "MALFORMED_CALL_NUDGE",
15013
+ "variableTypeTokenRange": {
15014
+ "startIndex": 0,
15015
+ "endIndex": 0
15016
+ }
15017
+ },
14964
15018
  {
14965
15019
  "kind": "Interface",
14966
15020
  "canonicalReference": "@genesislcap/ai-assistant!ManualSelectionConfig:interface",
@@ -17081,6 +17135,32 @@
17081
17135
  ],
17082
17136
  "name": "restoreMachine"
17083
17137
  },
17138
+ {
17139
+ "kind": "TypeAlias",
17140
+ "canonicalReference": "@genesislcap/ai-assistant!RoutingDecision:type",
17141
+ "docComment": "/**\n * Why {@link OrchestratingDriver.classify} returned the agent it did — reported on the `routing.decided` timeline event.\n *\n * Every value here used to be indistinguishable from the others in the debug log: four separate paths returned the fallback, all four `logger.warn`-only, and `classify` runs outside any ChatDriver turn so it recorded no turn either. Triaging a session where UI work kept landing on the fallback (GENC-1573) it was impossible to tell a legitimate \"no specialist covers this\" from a classifier that never ran — the only surviving signal was that the decision had taken 0.1s rather than the usual 1–5s.\n *\n * @beta\n */\n",
17142
+ "excerptTokens": [
17143
+ {
17144
+ "kind": "Content",
17145
+ "text": "export type RoutingDecision = \n/** The classifier ran and picked a specialist. */\n"
17146
+ },
17147
+ {
17148
+ "kind": "Content",
17149
+ "text": "'classified'\n/** The classifier ran and answered -1: nothing listed covers the request. */\n | 'no-match'\n/**\n * Every classifier-eligible specialist had already handled part of this turn and handed on, so\n * the ballot was empty and no call was made. Distinct from `'no-match'`, which means a\n * classifier RAN and declined — conflating the two re-creates exactly the \"did anything actually\n * get asked?\" ambiguity this event exists to remove.\n */\n | 'ballot-exhausted'\n/** One viable specialist and no fallback — no point asking. */\n | 'single-candidate'\n/** Nothing classifier-eligible was configured. */\n | 'no-specialists'\n/** The registry default exposes no `chat()`, so no classification is possible. */\n | 'provider-unavailable'\n/** Every attempt threw. `detail.error` carries the last message. */\n | 'classifier-failed'\n/** A pin or an active flow owned the turn; the classifier was skipped. */\n | 'pinned'"
17150
+ },
17151
+ {
17152
+ "kind": "Content",
17153
+ "text": ";"
17154
+ }
17155
+ ],
17156
+ "fileUrlPath": "src/components/orchestrating-driver/orchestrating-driver.ts",
17157
+ "releaseTag": "Beta",
17158
+ "name": "RoutingDecision",
17159
+ "typeTokenRange": {
17160
+ "startIndex": 1,
17161
+ "endIndex": 2
17162
+ }
17163
+ },
17084
17164
  {
17085
17165
  "kind": "Interface",
17086
17166
  "canonicalReference": "@genesislcap/ai-assistant!SessionClearedDetail:interface",
@@ -19527,7 +19607,7 @@
19527
19607
  {
19528
19608
  "kind": "Variable",
19529
19609
  "canonicalReference": "@genesislcap/ai-assistant!strictFallbackAgent:var",
19530
- "docComment": "/**\n * A brief, professional fallback agent. States what is available without elaboration. The `{{agents}}` placeholder is replaced at runtime by `OrchestratingDriver` with the generated specialist list.\n *\n * @beta\n */\n",
19610
+ "docComment": "/**\n * A brief, professional fallback agent. States what is available without elaboration. The `{{agents}}` placeholder is replaced at runtime by `OrchestratingDriver` with the generated specialist list.\n *\n * The `{{unroutable}}` placeholder positions `UNROUTABLE_INSTRUCTION` — the framework's instruction for a substantive request no specialist covers, which is otherwise APPENDED to a string-form prompt. Positioned rather than appended for one reason: this preset's whole point is brevity, and appended text would be the last thing the model reads. Putting the block above the brevity rule leaves \"a single short sentence\" with the recency, so the two compose instead of competing. A prompt whose tone rules matter should do the same.\n *\n * @beta\n */\n",
19531
19611
  "excerptTokens": [
19532
19612
  {
19533
19613
  "kind": "Content",
@@ -20898,6 +20978,60 @@
20898
20978
  "endIndex": 6
20899
20979
  }
20900
20980
  },
20981
+ {
20982
+ "kind": "Variable",
20983
+ "canonicalReference": "@genesislcap/ai-assistant!UNROUTABLE_INSTRUCTION:var",
20984
+ "docComment": "/**\n * The instruction a fallback agent needs and, left to itself, tends not to have.\n *\n * A fallback prompt written by a consumer reliably covers two cases — small talk, and a request that belongs to a specialist — because those are the ones you think of when you write it. The case it exists FOR is the third: a substantive request that no specialist covers, and no way to act on it, because a fallback holds no tools and is denied the continuation tool as a leaf.\n *\n * Create's fallback prompt is the worked example (GENC-1573). It covered chit-chat and \"out of scope, here are the specialists\", said nothing about a request nothing can serve, and nothing about a terse follow-up (\"fix it\", \"try again\") aimed at an answer already given. Asked to fix a Kotlin null pointer no agent could touch, it returned nine blank turns across three page loads — a model with no instruction covering its situation and no tool to reach for.\n *\n * So the framework supplies it. Appended to a string-form prompt (or substituted at {@link UNROUTABLE_PLACEHOLDER} if the consumer positions it), because a fallback with no answer for its own reason to exist is a defect in every host, not a matter of taste. It is additive and static: being fixed it cannot destabilise a cached prefix, and the fallback prompt already changes whenever the agents array does (`{{agents}}` interpolates the specialist list). The function form still passes through untouched — a consumer that wants full control has it there.\n *\n * DELIBERATELY CONFINED TO WHAT A TERSE PROMPT CAN ALSO OBEY, and it must stay that way. Since this is appended by default it lands on top of prompts written with their own tone rules, and an earlier draft asked the model to \"state what you can establish… and suggest what the user could do next\" — a direct contradiction of {@link strictFallbackAgent}, a preset THIS PACKAGE ships, whose whole instruction is \"a single short sentence… Do not elaborate\". What is left here is compatible with brevity: say so, don't promise work you cannot do, read a short follow-up in context, and never answer with nothing. Adding anything that presumes room to elaborate breaks a shipped preset — put it in the consumer's own prompt instead.\n *\n * @beta\n */\n",
20985
+ "excerptTokens": [
20986
+ {
20987
+ "kind": "Content",
20988
+ "text": "UNROUTABLE_INSTRUCTION = "
20989
+ },
20990
+ {
20991
+ "kind": "Content",
20992
+ "text": "\"When the request is substantive but nothing above covers it, say so directly. Do not offer to do it yourself, and do not imply a specialist will pick it up.\\n\\nIf the user's message is a short follow-up to something already discussed \\u2014 \\\"fix it\\\", \\\"try again\\\", \\\"why?\\\" \\u2014 read it against the conversation above and answer that, rather than treating it as a new request with no context.\\n\\nNever end your turn without saying something. An empty reply is never a valid response: if you genuinely cannot help, say briefly that you cannot, and why.\""
20993
+ }
20994
+ ],
20995
+ "fileUrlPath": "src/components/orchestrating-driver/orchestrating-driver.ts",
20996
+ "initializerTokenRange": {
20997
+ "startIndex": 1,
20998
+ "endIndex": 2
20999
+ },
21000
+ "isReadonly": true,
21001
+ "releaseTag": "Beta",
21002
+ "name": "UNROUTABLE_INSTRUCTION",
21003
+ "variableTypeTokenRange": {
21004
+ "startIndex": 0,
21005
+ "endIndex": 0
21006
+ }
21007
+ },
21008
+ {
21009
+ "kind": "Variable",
21010
+ "canonicalReference": "@genesislcap/ai-assistant!UNROUTABLE_PLACEHOLDER:var",
21011
+ "docComment": "/**\n * Placeholder a consumer can put in its fallback prompt to position {@link UNROUTABLE_INSTRUCTION} itself, instead of having it appended.\n *\n * @beta\n */\n",
21012
+ "excerptTokens": [
21013
+ {
21014
+ "kind": "Content",
21015
+ "text": "UNROUTABLE_PLACEHOLDER = "
21016
+ },
21017
+ {
21018
+ "kind": "Content",
21019
+ "text": "\"{{unroutable}}\""
21020
+ }
21021
+ ],
21022
+ "fileUrlPath": "src/components/orchestrating-driver/orchestrating-driver.ts",
21023
+ "initializerTokenRange": {
21024
+ "startIndex": 1,
21025
+ "endIndex": 2
21026
+ },
21027
+ "isReadonly": true,
21028
+ "releaseTag": "Beta",
21029
+ "name": "UNROUTABLE_PLACEHOLDER",
21030
+ "variableTypeTokenRange": {
21031
+ "startIndex": 0,
21032
+ "endIndex": 0
21033
+ }
21034
+ },
20901
21035
  {
20902
21036
  "kind": "Variable",
20903
21037
  "canonicalReference": "@genesislcap/ai-assistant!userIconSvg:var",
@@ -2102,6 +2102,23 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
2102
2102
  /** Build the fold-awareness suffix appended to the system prompt each LLM call. */
2103
2103
  private buildFoldSystemPromptSuffix;
2104
2104
  private runToolLoop;
2105
+ /**
2106
+ * Append prose the DRIVER wrote rather than the model — a failure notice, a limit explanation,
2107
+ * the budget wall. Renders as an ordinary assistant bubble and is flagged
2108
+ * `excludeFromProvider`, so it never re-enters the next request.
2109
+ *
2110
+ * Every such notice must go through here. Written as one funnel rather than a flag repeated at
2111
+ * eleven call sites because the failure mode is silent: a notice that keeps the flag reads
2112
+ * identically in the transcript to one that loses it, and the damage only shows up a turn later
2113
+ * as the model echoing its own error message. Measured (GENC-1573): with the empty-response
2114
+ * notice in history, the next turn reproduced it verbatim in 45 output tokens — succeeding,
2115
+ * with no retry and no `turn.error`, while still showing the user a failure. From there the
2116
+ * loop sustains itself whether or not the model answers, which is why "try again" never worked.
2117
+ *
2118
+ * Not for anything the model produced, and not for a widget/interaction message: those are real
2119
+ * turn content and the model must keep seeing them.
2120
+ */
2121
+ private appendDriverNotice;
2105
2122
  private appendToHistory;
2106
2123
  }
2107
2124
 
@@ -2546,6 +2563,20 @@ export declare interface DiagnosticEntry {
2546
2563
  [key: string]: unknown;
2547
2564
  }
2548
2565
 
2566
+ /**
2567
+ * Framed-tail nudge added to a retry after an EMPTY response.
2568
+ *
2569
+ * Rewritten in GENC-1573. The previous copy ("You must respond to the user's message. Call the
2570
+ * appropriate tool or provide a text response") told a model that had just returned nothing to
2571
+ * respond, without naming the one exit available to an agent that genuinely cannot act: saying so.
2572
+ * Across nine failures in the measured session it changed nothing — all 29 attempts came back at
2573
+ * 8–9 output tokens — and most of those were on a tool-less agent, for which "call the appropriate
2574
+ * tool" is not an option at all. This version names the honest answer explicitly.
2575
+ *
2576
+ * @beta
2577
+ */
2578
+ export declare const EMPTY_RESPONSE_NUDGE = "IMPORTANT: Your previous attempt returned nothing at all, which is never a valid response. Answer the user's last message now, in prose \u2014 even if all you can honestly say is that you cannot help with it and why. If a tool is the right way to answer, call it. Do not return an empty response.";
2579
+
2549
2580
  /**
2550
2581
  * Expands a flat list of tool definitions into a nested tree by resolving fold
2551
2582
  * metadata from the corresponding handlers. Use this for debug output so the
@@ -4818,6 +4849,16 @@ export declare function isAiAssistantDocked(): boolean;
4818
4849
  */
4819
4850
  export declare const LOADING_STYLE_ANIMATIONS: readonly ["loading", "waves", "flowingWaves", "plasma"];
4820
4851
 
4852
+ /**
4853
+ * Framed-tail nudge added to a retry after a MALFORMED tool call.
4854
+ *
4855
+ * Exported so tests can assert placement (framed tail, never the system prompt) without pinning
4856
+ * the wording — the copy is a prompt, and a prompt should be free to improve.
4857
+ *
4858
+ * @beta
4859
+ */
4860
+ export declare const MALFORMED_CALL_NUDGE = "IMPORTANT: Use only the structured function-call API to invoke tools. Do not write Python code or use Python-style syntax to call tools.";
4861
+
4821
4862
  /**
4822
4863
  * Opts an agent in to manual selection from the assistant's agent picker.
4823
4864
  *
@@ -5006,6 +5047,26 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
5006
5047
  * release resources cleanly.
5007
5048
  */
5008
5049
  dispose(): Promise<void>;
5050
+ /**
5051
+ * Record one routing decision on the debug timeline — what was chosen, why, what it cost, and
5052
+ * (on a failure) what went wrong.
5053
+ *
5054
+ * This is the event whose absence made GENC-1573 undiagnosable. `classify` reaches the fallback
5055
+ * by four different routes and every one of them only warned to the console; because it runs
5056
+ * outside any ChatDriver turn it produces no `kind:'turn'` entry either, so both the decision
5057
+ * and its spend were invisible in an exported log.
5058
+ *
5059
+ * `usage` is why the spend line exists at all. A classifier call is a real billed request that
5060
+ * never enters the transcript, and `sessionUsage` is derived from the transcript — so classifier
5061
+ * spend is absent from the session total by construction. Recording it per decision keeps it
5062
+ * auditable and tells a reconciler exactly where the gap comes from: sum these to close it.
5063
+ */
5064
+ private recordRouting;
5065
+ /**
5066
+ * The recent-conversation excerpt for the classifier prompt, bounded in size as well as in
5067
+ * message count — see the `CLASSIFIER_MESSAGE_CHARS` docblock for why.
5068
+ */
5069
+ private classifierTranscript;
5009
5070
  private classify;
5010
5071
  /**
5011
5072
  * Returns the agent that the current turn is locked to, if any. Flow-owner
@@ -5016,6 +5077,12 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
5016
5077
  * — protects against stale state after an agents-array reassignment.
5017
5078
  */
5018
5079
  private resolvePinnedAgent;
5080
+ /**
5081
+ * Append prose the ORCHESTRATOR wrote — the handoff cap, the no-specialist apology. Flagged
5082
+ * `excludeFromProvider` for the same reason the driver's own notices are: it is not something a
5083
+ * model said, and feeding it back invites the model to echo it. See
5084
+ * `ChatMessage.excludeFromProvider`.
5085
+ */
5019
5086
  private appendInlineMessage;
5020
5087
  }
5021
5088
 
@@ -5231,6 +5298,42 @@ export declare function restoreMachine(machine: {
5231
5298
  }) => void;
5232
5299
  }, restored: unknown, key?: string): void;
5233
5300
 
5301
+ /**
5302
+ * Why {@link OrchestratingDriver.classify} returned the agent it did — reported on the
5303
+ * `routing.decided` timeline event.
5304
+ *
5305
+ * Every value here used to be indistinguishable from the others in the debug log: four separate
5306
+ * paths returned the fallback, all four `logger.warn`-only, and `classify` runs outside any
5307
+ * ChatDriver turn so it recorded no turn either. Triaging a session where UI work kept landing on
5308
+ * the fallback (GENC-1573) it was impossible to tell a legitimate "no specialist covers this"
5309
+ * from a classifier that never ran — the only surviving signal was that the decision had taken
5310
+ * 0.1s rather than the usual 1–5s.
5311
+ *
5312
+ * @beta
5313
+ */
5314
+ export declare type RoutingDecision =
5315
+ /** The classifier ran and picked a specialist. */
5316
+ 'classified'
5317
+ /** The classifier ran and answered -1: nothing listed covers the request. */
5318
+ | 'no-match'
5319
+ /**
5320
+ * Every classifier-eligible specialist had already handled part of this turn and handed on, so
5321
+ * the ballot was empty and no call was made. Distinct from `'no-match'`, which means a
5322
+ * classifier RAN and declined — conflating the two re-creates exactly the "did anything actually
5323
+ * get asked?" ambiguity this event exists to remove.
5324
+ */
5325
+ | 'ballot-exhausted'
5326
+ /** One viable specialist and no fallback — no point asking. */
5327
+ | 'single-candidate'
5328
+ /** Nothing classifier-eligible was configured. */
5329
+ | 'no-specialists'
5330
+ /** The registry default exposes no `chat()`, so no classification is possible. */
5331
+ | 'provider-unavailable'
5332
+ /** Every attempt threw. `detail.error` carries the last message. */
5333
+ | 'classifier-failed'
5334
+ /** A pin or an active flow owned the turn; the classifier was skipped. */
5335
+ | 'pinned';
5336
+
5234
5337
  /**
5235
5338
  * `detail` of the `AiAssistantEvent.SessionCleared` event. Captured *before*
5236
5339
  * teardown so a host can tidy up whatever the active agent was working on
@@ -5666,6 +5769,13 @@ export declare type StatefulAgentPersistenceContext<S> = Omit<AgentPersistenceCo
5666
5769
  * elaboration. The `{{agents}}` placeholder is replaced at runtime by
5667
5770
  * `OrchestratingDriver` with the generated specialist list.
5668
5771
  *
5772
+ * The `{{unroutable}}` placeholder positions `UNROUTABLE_INSTRUCTION` — the framework's
5773
+ * instruction for a substantive request no specialist covers, which is otherwise APPENDED to a
5774
+ * string-form prompt. Positioned rather than appended for one reason: this preset's whole point is
5775
+ * brevity, and appended text would be the last thing the model reads. Putting the block above the
5776
+ * brevity rule leaves "a single short sentence" with the recency, so the two compose instead of
5777
+ * competing. A prompt whose tone rules matter should do the same.
5778
+ *
5669
5779
  * @beta
5670
5780
  */
5671
5781
  export declare const strictFallbackAgent: FallbackAgentConfig;
@@ -6036,6 +6146,48 @@ export declare interface UnresolvedToolContext {
6036
6146
  */
6037
6147
  export declare type UnresolvedToolInput = (ctx: UnresolvedToolContext) => string | undefined | Promise<string | undefined>;
6038
6148
 
6149
+ /**
6150
+ * The instruction a fallback agent needs and, left to itself, tends not to have.
6151
+ *
6152
+ * A fallback prompt written by a consumer reliably covers two cases — small talk, and a request
6153
+ * that belongs to a specialist — because those are the ones you think of when you write it. The
6154
+ * case it exists FOR is the third: a substantive request that no specialist covers, and no way to
6155
+ * act on it, because a fallback holds no tools and is denied the continuation tool as a leaf.
6156
+ *
6157
+ * Create's fallback prompt is the worked example (GENC-1573). It covered chit-chat and
6158
+ * "out of scope, here are the specialists", said nothing about a request nothing can serve, and
6159
+ * nothing about a terse follow-up ("fix it", "try again") aimed at an answer already given. Asked
6160
+ * to fix a Kotlin null pointer no agent could touch, it returned nine blank turns across three
6161
+ * page loads — a model with no instruction covering its situation and no tool to reach for.
6162
+ *
6163
+ * So the framework supplies it. Appended to a string-form prompt (or substituted at
6164
+ * {@link UNROUTABLE_PLACEHOLDER} if the consumer positions it), because a fallback with no answer
6165
+ * for its own reason to exist is a defect in every host, not a matter of taste. It is additive and
6166
+ * static: being fixed it cannot destabilise a cached prefix, and the fallback prompt already
6167
+ * changes whenever the agents array does (`{{agents}}` interpolates the specialist list). The
6168
+ * function form still passes through untouched — a consumer that wants full control has it there.
6169
+ *
6170
+ * DELIBERATELY CONFINED TO WHAT A TERSE PROMPT CAN ALSO OBEY, and it must stay that way. Since
6171
+ * this is appended by default it lands on top of prompts written with their own tone rules, and
6172
+ * an earlier draft asked the model to "state what you can establish… and suggest what the user
6173
+ * could do next" — a direct contradiction of {@link strictFallbackAgent}, a preset THIS PACKAGE
6174
+ * ships, whose whole instruction is "a single short sentence… Do not elaborate". What is left
6175
+ * here is compatible with brevity: say so, don't promise work you cannot do, read a short
6176
+ * follow-up in context, and never answer with nothing. Adding anything that presumes room to
6177
+ * elaborate breaks a shipped preset — put it in the consumer's own prompt instead.
6178
+ *
6179
+ * @beta
6180
+ */
6181
+ export declare const UNROUTABLE_INSTRUCTION = "When the request is substantive but nothing above covers it, say so directly. Do not offer to do it yourself, and do not imply a specialist will pick it up.\n\nIf the user's message is a short follow-up to something already discussed \u2014 \"fix it\", \"try again\", \"why?\" \u2014 read it against the conversation above and answer that, rather than treating it as a new request with no context.\n\nNever end your turn without saying something. An empty reply is never a valid response: if you genuinely cannot help, say briefly that you cannot, and why.";
6182
+
6183
+ /**
6184
+ * Placeholder a consumer can put in its fallback prompt to position
6185
+ * {@link UNROUTABLE_INSTRUCTION} itself, instead of having it appended.
6186
+ *
6187
+ * @beta
6188
+ */
6189
+ export declare const UNROUTABLE_PLACEHOLDER = "{{unroutable}}";
6190
+
6039
6191
  /** Person silhouette — default user avatar. */
6040
6192
  export declare const userIconSvg = "<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" fill=\"currentColor\"/></svg>";
6041
6193