@genesislcap/ai-assistant 15.24.0-FUI-2603.10 → 15.24.0
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 +2 -2
- package/dist/ai-assistant.d.ts +11 -22
- package/dist/chat-driver.cjs +120 -138
- package/dist/chat-driver.cjs.map +4 -4
- package/dist/chat-driver.mjs +120 -138
- package/dist/chat-driver.mjs.map +4 -4
- package/dist/custom-elements.json +61 -119
- package/dist/dts/components/chat-driver/chat-driver.d.ts +11 -22
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/esm/components/chat-driver/chat-driver.js +142 -92
- package/docs/.gitattributes +2 -0
- package/package.json +16 -16
- package/dist/dts/components/chat-driver/turn-failures.d.ts +0 -96
- package/dist/dts/components/chat-driver/turn-failures.d.ts.map +0 -1
- package/dist/esm/components/chat-driver/turn-failures.js +0 -84
|
@@ -6221,7 +6221,7 @@
|
|
|
6221
6221
|
{
|
|
6222
6222
|
"kind": "PropertySignature",
|
|
6223
6223
|
"canonicalReference": "@genesislcap/ai-assistant!ChatDriverConfig#budgetExhaustedMessage:member",
|
|
6224
|
-
"docComment": "/**\n * Transcript copy appended when the AI-spend budget wall is hit (GENC-1464), used VERBATIM — set it only to own the copy entirely (white-labelling). When unset, the driver composes the bubble per wall: the neutral `
|
|
6224
|
+
"docComment": "/**\n * Transcript copy appended when the AI-spend budget wall is hit (GENC-1464), used VERBATIM — set it only to own the copy entirely (white-labelling). When unset, the driver composes the bubble per wall: the neutral `DEFAULT_BUDGET_EXHAUSTED_MESSAGE`, upgraded with \"switch to another AI provider\" advice only when the 402's `otherVendorAvailable` positively says another metered vendor still has headroom — the same rule the blocked banner applies, so the two surfaces can no longer contradict each other.\n *\n * The assistant element already lets a host override the blocked **banner** via `setBlocked(true, reason)`; without this the transcript **bubble** stayed on the default, so a white-labelled host got its own copy in the banner and the shipped default directly below it. Passing the same effective copy here keeps the two surfaces saying one thing.\n *\n * Deliberately a driver-config field rather than something read off a chat config: `ChatDriver` has no `chatConfig` and is used standalone (see `chat-driver-node`), so threading one in would be a much larger and less reversible change.\n */\n",
|
|
6225
6225
|
"excerptTokens": [
|
|
6226
6226
|
{
|
|
6227
6227
|
"kind": "Content",
|
|
@@ -6388,7 +6388,7 @@
|
|
|
6388
6388
|
{
|
|
6389
6389
|
"kind": "PropertySignature",
|
|
6390
6390
|
"canonicalReference": "@genesislcap/ai-assistant!ChatDriverConfig#providerRefusedMessage:member",
|
|
6391
|
-
"docComment": "/**\n * Overrides the transcript sentence shown when the upstream PROVIDER refuses the account (GENC-1506) — see `
|
|
6391
|
+
"docComment": "/**\n * Overrides the transcript sentence shown when the upstream PROVIDER refuses the account (GENC-1506) — see `DEFAULT_PROVIDER_REFUSED_MESSAGE`.\n *\n * Separate from `budgetExhaustedMessage` because the two conditions are separate: ours is a spend cap a host administrator can raise, this is the vendor declining to serve us at all. A host that white-labels one will usually want to white-label both, but conflating them into one field would force identical copy on two situations with different remedies.\n *\n * Rarely needed: unlike the budget default, the shipped sentence names no vendor and no Genesis, so it is already safe for a white-labelled deployment.\n */\n",
|
|
6392
6392
|
"excerptTokens": [
|
|
6393
6393
|
{
|
|
6394
6394
|
"kind": "Content",
|
package/dist/ai-assistant.d.ts
CHANGED
|
@@ -1719,26 +1719,6 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
|
|
|
1719
1719
|
* the historical `{ reason: 'done' }`.
|
|
1720
1720
|
*/
|
|
1721
1721
|
private turnDone;
|
|
1722
|
-
/**
|
|
1723
|
-
* End the turn on a terminal failure: fail upward when this driver is a sub-agent, speak
|
|
1724
|
-
* to the user when it is not, and hand the reason to the caller either way.
|
|
1725
|
-
*
|
|
1726
|
-
* Only that fork lives here. Each exit keeps its own `recordTurnError` call, because the
|
|
1727
|
-
* telemetry payload is what legitimately differs between them — attempt counts, token
|
|
1728
|
-
* figures, tool names — and folding it in would mean one optional field per condition.
|
|
1729
|
-
*
|
|
1730
|
-
* `overrides.copy` serves the two walls whose prose is composed per occurrence:
|
|
1731
|
-
* `budgetExhaustedBubble` names the vendor and can offer another, `providerRefusedBubble`
|
|
1732
|
-
* prefers a host-supplied message. Every other exit reads its copy from the table.
|
|
1733
|
-
*
|
|
1734
|
-
* One exit stays out: the `BudgetExhaustedError` catch. Not because its shape differs —
|
|
1735
|
-
* its two telemetry payloads are field-for-field identical — but because its main-turn
|
|
1736
|
-
* branch calls `reportBudgetExhausted`, which is public and also serves
|
|
1737
|
-
* `OrchestratingDriver`'s classification phase, where no tool loop is running. That
|
|
1738
|
-
* method has to survive either way, so routing the catch through here would relocate the
|
|
1739
|
-
* duplication rather than remove it.
|
|
1740
|
-
*/
|
|
1741
|
-
private endTurnWithFailure;
|
|
1742
1722
|
/**
|
|
1743
1723
|
* Terminal budget outcome for a wall hit **outside** the tool loop — today,
|
|
1744
1724
|
* `OrchestratingDriver`'s classification phase, which calls the provider
|
|
@@ -1776,6 +1756,15 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
|
|
|
1776
1756
|
* has gone unpaid — so there is nothing here to compose. A host override wins verbatim.
|
|
1777
1757
|
*/
|
|
1778
1758
|
private providerRefusedBubble;
|
|
1759
|
+
/**
|
|
1760
|
+
* Terminal provider-refusal outcome. Mirrors `reportBudgetExhausted` so the two walls behave
|
|
1761
|
+
* identically from the caller's side, while keeping their diagnostics distinct.
|
|
1762
|
+
*
|
|
1763
|
+
* `kind` reaches the debug log and the result but never the transcript: it is what lets an operator
|
|
1764
|
+
* tell "top up the account" from "rotate the key", and with cause-free user copy this is the only
|
|
1765
|
+
* place that distinction survives.
|
|
1766
|
+
*/
|
|
1767
|
+
private reportProviderRefused;
|
|
1779
1768
|
/** The typed failure reason on a loop result, or `undefined` for a clean turn / handoff. */
|
|
1780
1769
|
private static failureReasonOf;
|
|
1781
1770
|
/**
|
|
@@ -2220,7 +2209,7 @@ export declare interface ChatDriverConfig {
|
|
|
2220
2209
|
* Transcript copy appended when the AI-spend budget wall is hit (GENC-1464),
|
|
2221
2210
|
* used VERBATIM — set it only to own the copy entirely (white-labelling).
|
|
2222
2211
|
* When unset, the driver composes the bubble per wall: the neutral
|
|
2223
|
-
* `
|
|
2212
|
+
* `DEFAULT_BUDGET_EXHAUSTED_MESSAGE`, upgraded with "switch to another AI
|
|
2224
2213
|
* provider" advice only when the 402's `otherVendorAvailable` positively says
|
|
2225
2214
|
* another metered vendor still has headroom — the same rule the blocked
|
|
2226
2215
|
* banner applies, so the two surfaces can no longer contradict each other.
|
|
@@ -2239,7 +2228,7 @@ export declare interface ChatDriverConfig {
|
|
|
2239
2228
|
budgetExhaustedMessage?: string;
|
|
2240
2229
|
/**
|
|
2241
2230
|
* Overrides the transcript sentence shown when the upstream PROVIDER refuses the account
|
|
2242
|
-
* (GENC-1506) — see `
|
|
2231
|
+
* (GENC-1506) — see `DEFAULT_PROVIDER_REFUSED_MESSAGE`.
|
|
2243
2232
|
*
|
|
2244
2233
|
* Separate from `budgetExhaustedMessage` because the two conditions are separate: ours is a spend
|
|
2245
2234
|
* cap a host administrator can raise, this is the vendor declining to serve us at all. A host that
|
package/dist/chat-driver.cjs
CHANGED
|
@@ -4400,78 +4400,6 @@ function accumulate(messages, into) {
|
|
|
4400
4400
|
// src/utils/tool-fold.ts
|
|
4401
4401
|
var TOOL_FOLD_SYMBOL = Symbol("toolFold");
|
|
4402
4402
|
|
|
4403
|
-
// src/components/chat-driver/turn-failures.ts
|
|
4404
|
-
var TURN_FAILURE_EXITS = {
|
|
4405
|
-
contextGuard: {
|
|
4406
|
-
subReason: "context_exhausted",
|
|
4407
|
-
resultReason: "context-exhausted",
|
|
4408
|
-
copy: "I had to stop here \u2014 this conversation has filled the available context. Compact it to free up room, then ask me to continue."
|
|
4409
|
-
},
|
|
4410
|
-
contextOverflow: {
|
|
4411
|
-
subReason: "context_exhausted",
|
|
4412
|
-
resultReason: "context-exhausted",
|
|
4413
|
-
copy: DEFAULT_CONTEXT_OVERFLOW_MESSAGE
|
|
4414
|
-
},
|
|
4415
|
-
malformedToolCall: {
|
|
4416
|
-
subReason: "malformed_tool_call",
|
|
4417
|
-
// Not `malformed-tool-call`: the main-turn reason is named after the provider finish
|
|
4418
|
-
// reason (`MALFORMED_FUNCTION_CALL`) that produces it, and is part of the published
|
|
4419
|
-
// TurnFailureReason union, so the two names cannot be brought into line here.
|
|
4420
|
-
resultReason: "malformed-function-call",
|
|
4421
|
-
copy: "While working on your request, I repeatedly called my tools incorrectly. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps."
|
|
4422
|
-
},
|
|
4423
|
-
responseTruncated: {
|
|
4424
|
-
subReason: "response_truncated",
|
|
4425
|
-
resultReason: "response-truncated",
|
|
4426
|
-
copy: "My response was cut off because a single step reached the model output limit. This usually means one step tried to produce too much at once \u2014 try breaking your request into smaller steps."
|
|
4427
|
-
},
|
|
4428
|
-
timeout: {
|
|
4429
|
-
subReason: "timeout",
|
|
4430
|
-
// There is no `timeout` member of TurnFailureReason, so the main turn reports the
|
|
4431
|
-
// generic `exception`. A sub-agent gets the specific reason because its parent
|
|
4432
|
-
// branches on it to decide whether a retry is worth attempting.
|
|
4433
|
-
resultReason: "exception",
|
|
4434
|
-
copy: "The request timed out. You can ask me to try again, or break this into a smaller step."
|
|
4435
|
-
},
|
|
4436
|
-
unknownToolLimit: {
|
|
4437
|
-
subReason: "unknown_tool_limit",
|
|
4438
|
-
resultReason: "unknown-tool-limit",
|
|
4439
|
-
copy: "I'm sorry, I repeatedly tried to use tools that aren't available to me, so I couldn't complete that. If a 'Download agent log' option appears in the Settings (cog) menu, you can download the log and share it with whoever set up this assistant to help fix the issue."
|
|
4440
|
-
},
|
|
4441
|
-
maxIterations: {
|
|
4442
|
-
subReason: "max_iterations",
|
|
4443
|
-
resultReason: "max-iterations",
|
|
4444
|
-
copy: "I've reached my limit for this response. You can ask me to continue and I'll pick up where I left off."
|
|
4445
|
-
},
|
|
4446
|
-
refusal: {
|
|
4447
|
-
subReason: "refusal",
|
|
4448
|
-
resultReason: "refusal",
|
|
4449
|
-
copy: "This request was declined. Try rephrasing it, or breaking it into smaller steps."
|
|
4450
|
-
},
|
|
4451
|
-
emptyResponse: {
|
|
4452
|
-
subReason: "empty_response",
|
|
4453
|
-
resultReason: "empty-response",
|
|
4454
|
-
copy: "While working on your request, I repeatedly generated a blank response. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps."
|
|
4455
|
-
},
|
|
4456
|
-
providerRefused: {
|
|
4457
|
-
subReason: "provider_refused",
|
|
4458
|
-
resultReason: "provider-refused",
|
|
4459
|
-
// Overridden per wall by `ChatDriver.providerRefusedBubble`, which prefers a
|
|
4460
|
-
// host-supplied message; this is the fallback that method returns.
|
|
4461
|
-
copy: DEFAULT_PROVIDER_REFUSED_MESSAGE
|
|
4462
|
-
},
|
|
4463
|
-
budgetExhausted: {
|
|
4464
|
-
subReason: "budget_exhausted",
|
|
4465
|
-
resultReason: "budget-exhausted",
|
|
4466
|
-
// Overridden per wall by `ChatDriver.budgetExhaustedBubble`, which upgrades this with
|
|
4467
|
-
// "switch to another AI" when a second vendor is reachable.
|
|
4468
|
-
copy: DEFAULT_BUDGET_EXHAUSTED_MESSAGE
|
|
4469
|
-
}
|
|
4470
|
-
// `satisfies`, not an annotation: an annotation would widen `resultReason` to
|
|
4471
|
-
// `TurnFailureReason` and cost the literal types that let `turn-failures.test.ts` pin the
|
|
4472
|
-
// two deliberate divergences at compile time instead of at runtime.
|
|
4473
|
-
};
|
|
4474
|
-
|
|
4475
4403
|
// src/components/chat-driver/chat-driver.ts
|
|
4476
4404
|
var toolResultImages = (result) => {
|
|
4477
4405
|
if (!result || typeof result !== "object") return void 0;
|
|
@@ -4846,33 +4774,6 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
4846
4774
|
...providerRefused ? { providerRefused } : {}
|
|
4847
4775
|
};
|
|
4848
4776
|
}
|
|
4849
|
-
/**
|
|
4850
|
-
* End the turn on a terminal failure: fail upward when this driver is a sub-agent, speak
|
|
4851
|
-
* to the user when it is not, and hand the reason to the caller either way.
|
|
4852
|
-
*
|
|
4853
|
-
* Only that fork lives here. Each exit keeps its own `recordTurnError` call, because the
|
|
4854
|
-
* telemetry payload is what legitimately differs between them — attempt counts, token
|
|
4855
|
-
* figures, tool names — and folding it in would mean one optional field per condition.
|
|
4856
|
-
*
|
|
4857
|
-
* `overrides.copy` serves the two walls whose prose is composed per occurrence:
|
|
4858
|
-
* `budgetExhaustedBubble` names the vendor and can offer another, `providerRefusedBubble`
|
|
4859
|
-
* prefers a host-supplied message. Every other exit reads its copy from the table.
|
|
4860
|
-
*
|
|
4861
|
-
* One exit stays out: the `BudgetExhaustedError` catch. Not because its shape differs —
|
|
4862
|
-
* its two telemetry payloads are field-for-field identical — but because its main-turn
|
|
4863
|
-
* branch calls `reportBudgetExhausted`, which is public and also serves
|
|
4864
|
-
* `OrchestratingDriver`'s classification phase, where no tool loop is running. That
|
|
4865
|
-
* method has to survive either way, so routing the catch through here would relocate the
|
|
4866
|
-
* duplication rather than remove it.
|
|
4867
|
-
*/
|
|
4868
|
-
endTurnWithFailure(exit, overrides) {
|
|
4869
|
-
if (this.isSubAgent) {
|
|
4870
|
-
this.failSubAgent(exit.subReason, overrides?.budget, overrides?.providerRefused);
|
|
4871
|
-
} else {
|
|
4872
|
-
this.appendDriverNotice(overrides?.copy ?? exit.copy);
|
|
4873
|
-
}
|
|
4874
|
-
return this.turnDone(exit.resultReason, overrides?.budget, overrides?.providerRefused);
|
|
4875
|
-
}
|
|
4876
4777
|
/**
|
|
4877
4778
|
* Terminal budget outcome for a wall hit **outside** the tool loop — today,
|
|
4878
4779
|
* `OrchestratingDriver`'s classification phase, which calls the provider
|
|
@@ -4901,7 +4802,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
4901
4802
|
*/
|
|
4902
4803
|
budgetExhaustedBubble(wall) {
|
|
4903
4804
|
if (this.budgetExhaustedMessageOverride != null) return this.budgetExhaustedMessageOverride;
|
|
4904
|
-
if (wall?.otherVendorAvailable !== true) return
|
|
4805
|
+
if (wall?.otherVendorAvailable !== true) return DEFAULT_BUDGET_EXHAUSTED_MESSAGE;
|
|
4905
4806
|
const subject = wall?.vendorLabel ? `${wall.vendorLabel}'s AI usage limit` : "your AI usage limit";
|
|
4906
4807
|
return `You've reached ${subject}. Switch to another AI provider in Settings to keep going, or contact your administrator to raise it.`;
|
|
4907
4808
|
}
|
|
@@ -4935,7 +4836,32 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
4935
4836
|
* has gone unpaid — so there is nothing here to compose. A host override wins verbatim.
|
|
4936
4837
|
*/
|
|
4937
4838
|
providerRefusedBubble() {
|
|
4938
|
-
return this.providerRefusedMessageOverride ??
|
|
4839
|
+
return this.providerRefusedMessageOverride ?? DEFAULT_PROVIDER_REFUSED_MESSAGE;
|
|
4840
|
+
}
|
|
4841
|
+
/**
|
|
4842
|
+
* Terminal provider-refusal outcome. Mirrors `reportBudgetExhausted` so the two walls behave
|
|
4843
|
+
* identically from the caller's side, while keeping their diagnostics distinct.
|
|
4844
|
+
*
|
|
4845
|
+
* `kind` reaches the debug log and the result but never the transcript: it is what lets an operator
|
|
4846
|
+
* tell "top up the account" from "rotate the key", and with cause-free user copy this is the only
|
|
4847
|
+
* place that distinction survives.
|
|
4848
|
+
*/
|
|
4849
|
+
reportProviderRefused(e) {
|
|
4850
|
+
const detail = providerRefusedDetailOf(e);
|
|
4851
|
+
this.providerRefusedThisTurn = true;
|
|
4852
|
+
this.providerRefusedDetail = detail;
|
|
4853
|
+
logger2.error("ChatDriver: provider refused the request", e);
|
|
4854
|
+
recordTurnError(this.sessionKey, "provider-refused", {
|
|
4855
|
+
agent: this.activeAgentName,
|
|
4856
|
+
provider: this.lastResolvedProviderName,
|
|
4857
|
+
vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,
|
|
4858
|
+
kind: e.kind,
|
|
4859
|
+
upstreamStatus: e.upstreamStatus,
|
|
4860
|
+
upstreamType: e.upstreamType,
|
|
4861
|
+
isSubAgent: this.isSubAgent
|
|
4862
|
+
});
|
|
4863
|
+
this.appendDriverNotice(this.providerRefusedBubble());
|
|
4864
|
+
return this.turnDone("provider-refused", void 0, detail);
|
|
4939
4865
|
}
|
|
4940
4866
|
/** The typed failure reason on a loop result, or `undefined` for a clean turn / handoff. */
|
|
4941
4867
|
static failureReasonOf(result) {
|
|
@@ -6226,10 +6152,12 @@ Output format (strict):
|
|
|
6226
6152
|
via: "sub-agent",
|
|
6227
6153
|
isSubAgent: this.isSubAgent
|
|
6228
6154
|
});
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6155
|
+
if (this.isSubAgent) {
|
|
6156
|
+
this.failSubAgent("provider_refused", void 0, this.providerRefusedDetail);
|
|
6157
|
+
} else {
|
|
6158
|
+
this.appendDriverNotice(this.providerRefusedBubble());
|
|
6159
|
+
}
|
|
6160
|
+
return this.turnDone("provider-refused", void 0, this.providerRefusedDetail);
|
|
6233
6161
|
}
|
|
6234
6162
|
if (this.budgetExhaustedThisTurn) {
|
|
6235
6163
|
logger2.error("ChatDriver: ending the turn \u2014 a sub-agent hit the AI budget wall");
|
|
@@ -6249,10 +6177,12 @@ Output format (strict):
|
|
|
6249
6177
|
via: "sub-agent",
|
|
6250
6178
|
isSubAgent: this.isSubAgent
|
|
6251
6179
|
});
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6180
|
+
if (this.isSubAgent) {
|
|
6181
|
+
this.failSubAgent("budget_exhausted", this.budgetWallDetail);
|
|
6182
|
+
} else {
|
|
6183
|
+
this.appendDriverNotice(this.budgetExhaustedBubble(this.budgetWallDetail));
|
|
6184
|
+
}
|
|
6185
|
+
return this.turnDone("budget-exhausted", this.budgetWallDetail);
|
|
6256
6186
|
}
|
|
6257
6187
|
const promptCtx = {
|
|
6258
6188
|
agentName: this.activeAgentName ?? "",
|
|
@@ -6417,7 +6347,14 @@ ${tailBody}
|
|
|
6417
6347
|
iterations,
|
|
6418
6348
|
isSubAgent: this.isSubAgent
|
|
6419
6349
|
});
|
|
6420
|
-
|
|
6350
|
+
if (this.isSubAgent) {
|
|
6351
|
+
this.failSubAgent("context_exhausted");
|
|
6352
|
+
} else {
|
|
6353
|
+
this.appendDriverNotice(
|
|
6354
|
+
"I had to stop here \u2014 this conversation has filled the available context. Compact it to free up room, then ask me to continue."
|
|
6355
|
+
);
|
|
6356
|
+
}
|
|
6357
|
+
return this.turnDone("context-exhausted");
|
|
6421
6358
|
}
|
|
6422
6359
|
let response;
|
|
6423
6360
|
try {
|
|
@@ -6447,7 +6384,14 @@ ${tailBody}
|
|
|
6447
6384
|
finishMessage: e.finishMessage,
|
|
6448
6385
|
isSubAgent: this.isSubAgent
|
|
6449
6386
|
});
|
|
6450
|
-
|
|
6387
|
+
if (this.isSubAgent) {
|
|
6388
|
+
this.failSubAgent("malformed_tool_call");
|
|
6389
|
+
} else {
|
|
6390
|
+
this.appendDriverNotice(
|
|
6391
|
+
"While working on your request, I repeatedly called my tools incorrectly. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps."
|
|
6392
|
+
);
|
|
6393
|
+
}
|
|
6394
|
+
return this.turnDone("malformed-function-call");
|
|
6451
6395
|
}
|
|
6452
6396
|
if (e instanceof ResponseTruncatedError) {
|
|
6453
6397
|
logger2.error("ChatDriver: response truncated at the output-token cap", e);
|
|
@@ -6460,7 +6404,14 @@ ${tailBody}
|
|
|
6460
6404
|
tools: e.toolNames,
|
|
6461
6405
|
isSubAgent: this.isSubAgent
|
|
6462
6406
|
});
|
|
6463
|
-
|
|
6407
|
+
if (this.isSubAgent) {
|
|
6408
|
+
this.failSubAgent("response_truncated");
|
|
6409
|
+
} else {
|
|
6410
|
+
this.appendDriverNotice(
|
|
6411
|
+
"My response was cut off because a single step reached the model output limit. This usually means one step tried to produce too much at once \u2014 try breaking your request into smaller steps."
|
|
6412
|
+
);
|
|
6413
|
+
}
|
|
6414
|
+
return this.turnDone("response-truncated");
|
|
6464
6415
|
}
|
|
6465
6416
|
if (e instanceof ContextOverflowError) {
|
|
6466
6417
|
logger2.error("ChatDriver: the prompt exceeded the model context window", e);
|
|
@@ -6473,28 +6424,30 @@ ${tailBody}
|
|
|
6473
6424
|
via: "provider",
|
|
6474
6425
|
isSubAgent: this.isSubAgent
|
|
6475
6426
|
});
|
|
6476
|
-
|
|
6427
|
+
if (this.isSubAgent) {
|
|
6428
|
+
this.failSubAgent("context_exhausted");
|
|
6429
|
+
} else {
|
|
6430
|
+
this.appendDriverNotice(DEFAULT_CONTEXT_OVERFLOW_MESSAGE);
|
|
6431
|
+
}
|
|
6432
|
+
return this.turnDone("context-exhausted");
|
|
6477
6433
|
}
|
|
6478
6434
|
if (e instanceof ProviderRefusedError) {
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
this.
|
|
6482
|
-
|
|
6435
|
+
if (this.isSubAgent) {
|
|
6436
|
+
logger2.error("ChatDriver: provider refused the request", e);
|
|
6437
|
+
recordTurnError(this.sessionKey, "provider-refused", {
|
|
6438
|
+
agent: this.activeAgentName,
|
|
6439
|
+
provider: this.lastResolvedProviderName,
|
|
6440
|
+
vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,
|
|
6441
|
+
kind: e.kind,
|
|
6442
|
+
upstreamStatus: e.upstreamStatus,
|
|
6443
|
+
upstreamType: e.upstreamType,
|
|
6444
|
+
isSubAgent: true
|
|
6445
|
+
});
|
|
6446
|
+
const detail = providerRefusedDetailOf(e);
|
|
6447
|
+
this.failSubAgent("provider_refused", void 0, detail);
|
|
6448
|
+
return this.turnDone("provider-refused", void 0, detail);
|
|
6483
6449
|
}
|
|
6484
|
-
|
|
6485
|
-
recordTurnError(this.sessionKey, "provider-refused", {
|
|
6486
|
-
agent: this.activeAgentName,
|
|
6487
|
-
provider: this.lastResolvedProviderName,
|
|
6488
|
-
vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,
|
|
6489
|
-
kind: e.kind,
|
|
6490
|
-
upstreamStatus: e.upstreamStatus,
|
|
6491
|
-
upstreamType: e.upstreamType,
|
|
6492
|
-
isSubAgent: this.isSubAgent
|
|
6493
|
-
});
|
|
6494
|
-
return this.endTurnWithFailure(TURN_FAILURE_EXITS.providerRefused, {
|
|
6495
|
-
copy: this.providerRefusedBubble(),
|
|
6496
|
-
providerRefused: detail
|
|
6497
|
-
});
|
|
6450
|
+
return this.reportProviderRefused(e);
|
|
6498
6451
|
}
|
|
6499
6452
|
if (e instanceof BudgetExhaustedError) {
|
|
6500
6453
|
this.budgetExhaustedThisTurn = true;
|
|
@@ -6524,7 +6477,14 @@ ${tailBody}
|
|
|
6524
6477
|
message: e.message,
|
|
6525
6478
|
isSubAgent: this.isSubAgent
|
|
6526
6479
|
});
|
|
6527
|
-
|
|
6480
|
+
if (this.isSubAgent) {
|
|
6481
|
+
this.failSubAgent("timeout");
|
|
6482
|
+
} else {
|
|
6483
|
+
this.appendDriverNotice(
|
|
6484
|
+
"The request timed out. You can ask me to try again, or break this into a smaller step."
|
|
6485
|
+
);
|
|
6486
|
+
}
|
|
6487
|
+
return this.turnDone("exception");
|
|
6528
6488
|
}
|
|
6529
6489
|
if (e instanceof DOMException && e.name === "AbortError") {
|
|
6530
6490
|
return this.completeAbortedTurn();
|
|
@@ -6576,11 +6536,11 @@ ${tailBody}
|
|
|
6576
6536
|
iterations -= 1;
|
|
6577
6537
|
continue;
|
|
6578
6538
|
}
|
|
6579
|
-
const
|
|
6539
|
+
const failureReason2 = isRefusal ? "refusal" : "empty-response";
|
|
6580
6540
|
logger2.error(
|
|
6581
6541
|
isRefusal ? "ChatDriver: model refused the request (safety decline) \u2014 not retrying" : "ChatDriver: empty model response after all retries"
|
|
6582
6542
|
);
|
|
6583
|
-
recordTurnError(this.sessionKey,
|
|
6543
|
+
recordTurnError(this.sessionKey, failureReason2, {
|
|
6584
6544
|
agent: this.activeAgentName,
|
|
6585
6545
|
provider: this.lastResolvedProviderName,
|
|
6586
6546
|
attempts: emptyResponseAttempts,
|
|
@@ -6590,7 +6550,14 @@ ${tailBody}
|
|
|
6590
6550
|
isSubAgent: this.isSubAgent,
|
|
6591
6551
|
...response.responseMeta
|
|
6592
6552
|
});
|
|
6593
|
-
|
|
6553
|
+
if (this.isSubAgent) {
|
|
6554
|
+
this.failSubAgent(isRefusal ? "refusal" : "empty_response");
|
|
6555
|
+
} else {
|
|
6556
|
+
this.appendDriverNotice(
|
|
6557
|
+
isRefusal ? "This request was declined. Try rephrasing it, or breaking it into smaller steps." : "While working on your request, I repeatedly generated a blank response. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps."
|
|
6558
|
+
);
|
|
6559
|
+
}
|
|
6560
|
+
return this.turnDone(failureReason2);
|
|
6594
6561
|
} else {
|
|
6595
6562
|
const { reasoning, ...rest } = response;
|
|
6596
6563
|
const displayOnly = {
|
|
@@ -6890,7 +6857,14 @@ RECOVERY: this tool failed once \u2014 you may retry it, or take a different val
|
|
|
6890
6857
|
availableTools: Object.keys(this.toolHandlers),
|
|
6891
6858
|
isSubAgent: this.isSubAgent
|
|
6892
6859
|
});
|
|
6893
|
-
|
|
6860
|
+
if (this.isSubAgent) {
|
|
6861
|
+
this.failSubAgent("unknown_tool_limit");
|
|
6862
|
+
} else {
|
|
6863
|
+
this.appendDriverNotice(
|
|
6864
|
+
"I'm sorry, I repeatedly tried to use tools that aren't available to me, so I couldn't complete that. If a 'Download agent log' option appears in the Settings (cog) menu, you can download the log and share it with whoever set up this assistant to help fix the issue."
|
|
6865
|
+
);
|
|
6866
|
+
}
|
|
6867
|
+
return this.turnDone("unknown-tool-limit");
|
|
6894
6868
|
}
|
|
6895
6869
|
const firstContinuation = systemCalls[0];
|
|
6896
6870
|
if (firstContinuation) {
|
|
@@ -6901,6 +6875,7 @@ RECOVERY: this tool failed once \u2014 you may retry it, or take a different val
|
|
|
6901
6875
|
return this.turnDone();
|
|
6902
6876
|
}
|
|
6903
6877
|
}
|
|
6878
|
+
let failureReason;
|
|
6904
6879
|
if (iterations >= this.maxToolIterations) {
|
|
6905
6880
|
logger2.warn("ChatDriver: reached max tool iterations, stopping");
|
|
6906
6881
|
recordTurnError(this.sessionKey, "max-iterations", {
|
|
@@ -6910,9 +6885,16 @@ RECOVERY: this tool failed once \u2014 you may retry it, or take a different val
|
|
|
6910
6885
|
limit: this.maxToolIterations,
|
|
6911
6886
|
isSubAgent: this.isSubAgent
|
|
6912
6887
|
});
|
|
6913
|
-
|
|
6888
|
+
if (this.isSubAgent) {
|
|
6889
|
+
this.failSubAgent("max_iterations");
|
|
6890
|
+
} else {
|
|
6891
|
+
this.appendDriverNotice(
|
|
6892
|
+
"I've reached my limit for this response. You can ask me to continue and I'll pick up where I left off."
|
|
6893
|
+
);
|
|
6894
|
+
}
|
|
6895
|
+
failureReason = "max-iterations";
|
|
6914
6896
|
}
|
|
6915
|
-
return this.turnDone();
|
|
6897
|
+
return this.turnDone(failureReason);
|
|
6916
6898
|
}
|
|
6917
6899
|
/**
|
|
6918
6900
|
* Append prose the DRIVER wrote rather than the model — a failure notice, a limit explanation,
|