@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.
- package/dist/ai-assistant.api.json +135 -1
- package/dist/ai-assistant.d.ts +152 -0
- package/dist/chat-driver.cjs +281 -81
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +277 -81
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +175 -8
- package/dist/dts/components/chat-driver/chat-driver.d.ts +39 -0
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/index.d.ts +2 -1
- package/dist/dts/components/orchestrating-driver/index.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +101 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/config/fallback-agents.d.ts +7 -0
- package/dist/dts/config/fallback-agents.d.ts.map +1 -1
- package/dist/dts/state/debug-event-log.d.ts +1 -1
- package/dist/dts/state/debug-event-log.d.ts.map +1 -1
- package/dist/dts/utils/context-tokens.d.ts +25 -3
- package/dist/dts/utils/context-tokens.d.ts.map +1 -1
- package/dist/dts/utils/history-transform.d.ts +23 -3
- package/dist/dts/utils/history-transform.d.ts.map +1 -1
- package/dist/esm/components/chat-driver/chat-driver.js +72 -56
- package/dist/esm/components/orchestrating-driver/index.js +1 -1
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +266 -36
- package/dist/esm/config/fallback-agents.js +12 -1
- package/dist/esm/state/debug-event-log.js +7 -2
- package/dist/esm/utils/context-tokens.js +27 -3
- package/dist/esm/utils/history-transform.js +54 -5
- 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",
|
package/dist/ai-assistant.d.ts
CHANGED
|
@@ -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
|
|