@khalilgharbaoui/opencode-claude-code-plugin 0.37.1 → 0.38.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/README.md +1 -1
- package/dist/index.js +120 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +52 -13
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ Nothing in the picker? [Troubleshooting](./docs/troubleshooting/symptoms.md) is
|
|
|
55
55
|
|---|---|
|
|
56
56
|
| **Selective tool proxy** | Choose, per tool, whether Claude Code or opencode executes it. Proxied calls end on an event (the result, an abort, the next message, the child exiting), never on a clock. [Guide](./docs/guides/tool-proxy.md) |
|
|
57
57
|
| **Claude's own tools, MCP and skills** | `Read`, `Grep`, `Glob`, `WebSearch` run in Claude Code; your opencode MCP servers are bridged in; your opencode skills can be staged for Claude's `Skill` tool. [MCP](./docs/configuration/mcp.md) · [Skills](./docs/configuration/skills.md) |
|
|
58
|
-
| **Several accounts
|
|
58
|
+
| **Several accounts** | `"accounts": ["personal", "work"]` becomes one provider per account. Out of usage mid-task? One line says which account, which window and when it resets in your own time zone, and names the others to pick a model from. [Accounts](./docs/configuration/accounts.md) |
|
|
59
59
|
| **Subagents: your account, their model** | `forceModel`, `reasoningEffort` and `cacheTtl` in an agent file, inheriting the caller's account. `task_batch` runs several subagents at once. [Subagents](./docs/configuration/subagents.md) |
|
|
60
60
|
| **18 models, reasoning variants, fast mode** | Haiku 4.5 through Opus 5.5, Fable and Mythos, each with a `(N×)` list-price suffix, `low` to `max` effort variants, and a fallback chain for a model this account cannot run today. [Models](./docs/models.md) |
|
|
61
61
|
| **`/btw` and `/claude-code-doctor`** | Side questions on the live process, and a health report whose `bundle` form is redacted by allowlist so it is safe to paste into a public issue. [`/btw`](./docs/guides/btw.md) · [Doctor](./docs/guides/doctor.md) |
|
package/dist/index.js
CHANGED
|
@@ -584,6 +584,20 @@ function formatResetsAt(resetsAt) {
|
|
|
584
584
|
const date = new Date(ms);
|
|
585
585
|
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
|
|
586
586
|
}
|
|
587
|
+
function formatLocalMinute(ms) {
|
|
588
|
+
const when = new Date(ms);
|
|
589
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
590
|
+
return `${when.getFullYear()}-${pad(when.getMonth() + 1)}-${pad(when.getDate())} ${pad(when.getHours())}:${pad(when.getMinutes())}`;
|
|
591
|
+
}
|
|
592
|
+
function formatResetsAtLocal(resetsAt) {
|
|
593
|
+
const ms = resetsAtToMs(resetsAt);
|
|
594
|
+
if (ms === void 0 || Number.isNaN(new Date(ms).getTime())) return void 0;
|
|
595
|
+
return formatLocalMinute(ms);
|
|
596
|
+
}
|
|
597
|
+
function describeRateLimitWindow(rateLimitType) {
|
|
598
|
+
if (!rateLimitType) return void 0;
|
|
599
|
+
return RATE_LIMIT_WINDOWS[rateLimitType] ?? rateLimitType;
|
|
600
|
+
}
|
|
587
601
|
function rateLimitKey(info) {
|
|
588
602
|
return [
|
|
589
603
|
info.status ?? "?",
|
|
@@ -599,7 +613,7 @@ function isRateLimitRejected(info) {
|
|
|
599
613
|
}
|
|
600
614
|
function describeRateLimit(info) {
|
|
601
615
|
if (!info.status && !info.overageStatus) return null;
|
|
602
|
-
const window = info.rateLimitType
|
|
616
|
+
const window = describeRateLimitWindow(info.rateLimitType);
|
|
603
617
|
const resets = formatResetsAt(info.resetsAt);
|
|
604
618
|
const overageResets = formatResetsAt(info.overageResetsAt);
|
|
605
619
|
const key = rateLimitKey(info);
|
|
@@ -614,9 +628,7 @@ function describeRateLimit(info) {
|
|
|
614
628
|
if (resetAt) parts.push(`Resets at ${resetAt}.`);
|
|
615
629
|
parts.push(RATE_LIMIT_ACTION);
|
|
616
630
|
const message = parts.join(" ");
|
|
617
|
-
return { key, level: "warn", message, transcript:
|
|
618
|
-
${RATE_LIMIT_MARKER} ${message}
|
|
619
|
-
` };
|
|
631
|
+
return { key, level: "warn", message, transcript: null };
|
|
620
632
|
}
|
|
621
633
|
if (info.status === "allowed_warning" || info.overageStatus === "allowed_warning") {
|
|
622
634
|
const used = info.utilization === void 0 ? "" : ` (${Math.round(info.utilization * 100)}% used)`;
|
|
@@ -1083,6 +1095,7 @@ var PLAN_MODE_APPROVAL_QUESTION = "Do you want to proceed with this plan?";
|
|
|
1083
1095
|
var OPENCODE_QUESTION_RESULT_PREFIX = "User has answered your questions: ";
|
|
1084
1096
|
var OPENCODE_QUESTION_RESULT_SUFFIX = ". You can now continue with the user's answers in mind.";
|
|
1085
1097
|
var OPENCODE_UNANSWERED = "Unanswered";
|
|
1098
|
+
var DCP_MESSAGE_ID_SUFFIX = /(?:\s*<dcp-message-id>[^<>]*<\/dcp-message-id>)+\s*$/;
|
|
1086
1099
|
var KEY_SEPARATOR = "\0";
|
|
1087
1100
|
function isPlanModeQuestionActive(input) {
|
|
1088
1101
|
if (input.compactionMode) return false;
|
|
@@ -1182,15 +1195,16 @@ function unwrapToolOutput(part) {
|
|
|
1182
1195
|
}
|
|
1183
1196
|
}
|
|
1184
1197
|
function unwrapOpencodeQuestionResult(value, question) {
|
|
1185
|
-
const
|
|
1198
|
+
const untagged = value.replace(DCP_MESSAGE_ID_SUFFIX, "");
|
|
1199
|
+
const sentence = untagged.trim();
|
|
1186
1200
|
if (!sentence.startsWith(OPENCODE_QUESTION_RESULT_PREFIX) || !sentence.endsWith(OPENCODE_QUESTION_RESULT_SUFFIX)) {
|
|
1187
|
-
return
|
|
1201
|
+
return untagged;
|
|
1188
1202
|
}
|
|
1189
1203
|
const body = sentence.slice(
|
|
1190
1204
|
OPENCODE_QUESTION_RESULT_PREFIX.length,
|
|
1191
1205
|
sentence.length - OPENCODE_QUESTION_RESULT_SUFFIX.length
|
|
1192
1206
|
);
|
|
1193
|
-
if (!body.startsWith('"') || !body.endsWith('"')) return
|
|
1207
|
+
if (!body.startsWith('"') || !body.endsWith('"')) return untagged;
|
|
1194
1208
|
let answer;
|
|
1195
1209
|
const head = question === void 0 ? void 0 : `"${question}"="`;
|
|
1196
1210
|
if (head && body.startsWith(head) && body.length > head.length) {
|
|
@@ -1199,7 +1213,7 @@ function unwrapOpencodeQuestionResult(value, question) {
|
|
|
1199
1213
|
const split = body.lastIndexOf('"="');
|
|
1200
1214
|
if (split > 0) answer = body.slice(split + 3, -1);
|
|
1201
1215
|
}
|
|
1202
|
-
if (answer === void 0) return
|
|
1216
|
+
if (answer === void 0) return untagged;
|
|
1203
1217
|
return answer === OPENCODE_UNANSWERED ? "" : answer;
|
|
1204
1218
|
}
|
|
1205
1219
|
function collectAnswerStrings(value, question) {
|
|
@@ -1257,6 +1271,13 @@ var ACCOUNT_LIMIT_PATTERNS = [
|
|
|
1257
1271
|
/you[’'`]?ve hit your individual spend limit/i
|
|
1258
1272
|
];
|
|
1259
1273
|
var ACCOUNT_BLOCK_MARKER = "\u258C **claude account:**";
|
|
1274
|
+
var USAGE_LIMIT_MARKER = "\u258C **usage limit:**";
|
|
1275
|
+
function describeOtherAccounts(candidates) {
|
|
1276
|
+
const names = candidates.map((candidate) => normalizeAccountName(candidate)).filter(Boolean).map((candidate) => `"${candidate}"`);
|
|
1277
|
+
if (names.length === 0) return "";
|
|
1278
|
+
const joined = names.length === 1 ? names[0] : `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}`;
|
|
1279
|
+
return `the ${joined} account`;
|
|
1280
|
+
}
|
|
1260
1281
|
var ACCOUNT_BLOCKS = {
|
|
1261
1282
|
authentication_failed: { what: "is not logged in (its login expired or was revoked)", login: true },
|
|
1262
1283
|
oauth_org_not_allowed: { what: "belongs to an organization that does not allow this login", login: false },
|
|
@@ -1280,17 +1301,51 @@ function formatAccountBlockNote(input) {
|
|
|
1280
1301
|
const block = ACCOUNT_BLOCKS[input.kind];
|
|
1281
1302
|
const account = normalizeAccountName(input.account || DEFAULT_ACCOUNT);
|
|
1282
1303
|
const fix = block.login ? `Log in again with \`${loginCommandFor(input.configDir)}\`, then resend your message.` : "Check the account at claude.ai, then resend your message.";
|
|
1283
|
-
const
|
|
1304
|
+
const others = input.offeringSwitch ? "" : describeOtherAccounts(input.candidates ?? []);
|
|
1305
|
+
const then = input.offeringSwitch ? " Or pick another account below." : others ? ` Or pick a model from ${others} and resend.` : "";
|
|
1284
1306
|
return `
|
|
1285
1307
|
${ACCOUNT_BLOCK_MARKER} the Claude account "${account}" ${block.what}. ${fix}${then}
|
|
1286
1308
|
`;
|
|
1287
1309
|
}
|
|
1310
|
+
function formatUsageLimitNote(input) {
|
|
1311
|
+
const account = normalizeAccountName(input.sourceAccount || DEFAULT_ACCOUNT);
|
|
1312
|
+
const window = describeRateLimitWindow(input.window);
|
|
1313
|
+
const resets = formatResetsAtLocal(input.resetsAt);
|
|
1314
|
+
const others = describeOtherAccounts(input.candidates);
|
|
1315
|
+
const what = [
|
|
1316
|
+
`the Claude account "${account}" is out of usage`,
|
|
1317
|
+
window ? ` in ${window}` : "",
|
|
1318
|
+
resets ? `, which resets at ${resets}` : "",
|
|
1319
|
+
"."
|
|
1320
|
+
].join("");
|
|
1321
|
+
const advice = others ? `Pick a model from ${others} and resend your message, or wait for the window to reset.` : "Wait for the window to reset, or enable extra usage on the account.";
|
|
1322
|
+
return `
|
|
1323
|
+
${USAGE_LIMIT_MARKER} ${what} ${advice}
|
|
1324
|
+
`;
|
|
1325
|
+
}
|
|
1288
1326
|
function isAccountLimitError(input) {
|
|
1289
1327
|
if (input.rateLimit && isRateLimitRejected(input.rateLimit)) return true;
|
|
1290
1328
|
const text = input.resultText;
|
|
1291
1329
|
if (typeof text !== "string" || text.length === 0) return false;
|
|
1292
1330
|
return ACCOUNT_LIMIT_PATTERNS.some((pattern) => pattern.test(text));
|
|
1293
1331
|
}
|
|
1332
|
+
var lastAccountLimits = /* @__PURE__ */ new Map();
|
|
1333
|
+
function rememberAccountLimit(account, facts) {
|
|
1334
|
+
const name = normalizeAccountName(account || DEFAULT_ACCOUNT);
|
|
1335
|
+
if (!name) return;
|
|
1336
|
+
lastAccountLimits.set(name, { resetsAt: facts.resetsAt, window: facts.window });
|
|
1337
|
+
}
|
|
1338
|
+
function recallAccountLimit(account, now = Date.now()) {
|
|
1339
|
+
const name = normalizeAccountName(account || DEFAULT_ACCOUNT);
|
|
1340
|
+
const facts = lastAccountLimits.get(name);
|
|
1341
|
+
if (!facts) return {};
|
|
1342
|
+
const resetsAtMs = resetsAtToMs(facts.resetsAt);
|
|
1343
|
+
const fresh = resetsAtMs !== void 0 && resetsAtMs > now;
|
|
1344
|
+
return {
|
|
1345
|
+
...fresh ? { resetsAt: facts.resetsAt } : {},
|
|
1346
|
+
...facts.window === void 0 ? {} : { window: facts.window }
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1294
1349
|
var accountOverrides = /* @__PURE__ */ new Map();
|
|
1295
1350
|
function setAccountOverride(source, target, until, now = Date.now()) {
|
|
1296
1351
|
const from = normalizeAccountName(source || DEFAULT_ACCOUNT);
|
|
@@ -1358,7 +1413,7 @@ function isAccountFailoverQuestionActive(input) {
|
|
|
1358
1413
|
if (input.compactionMode) return false;
|
|
1359
1414
|
if (input.interactive) return false;
|
|
1360
1415
|
if (input.childSession) return false;
|
|
1361
|
-
if (input.configured
|
|
1416
|
+
if (input.configured !== "ask") return false;
|
|
1362
1417
|
if (input.candidates.length === 0) return false;
|
|
1363
1418
|
return input.opencodeHasQuestion;
|
|
1364
1419
|
}
|
|
@@ -5474,6 +5529,7 @@ var PLUGIN_LOG_MESSAGES = /* @__PURE__ */ new Set([
|
|
|
5474
5529
|
"btw: early aside failed; the message will ask again",
|
|
5475
5530
|
"cannot interrupt this transport; waiting for the turn to end",
|
|
5476
5531
|
"claude --version output unparseable",
|
|
5532
|
+
"claude account is out of usage; the turn ends with a note",
|
|
5477
5533
|
"claude already registers a different skill under this name; not bridging ours",
|
|
5478
5534
|
"claude cli < 2.1.142 detected; Opus 4.7 thinking summaries unavailable. Run `npm i -g @anthropic-ai/claude-code` to upgrade.",
|
|
5479
5535
|
"claude cli does not support --plugin-dir; opencode skills will not be bridged. Run `npm i -g @anthropic-ai/claude-code` to upgrade.",
|
|
@@ -6328,11 +6384,6 @@ function compareBuilds(loaded, onDisk) {
|
|
|
6328
6384
|
rebuiltAt: onDisk.mtimeMs
|
|
6329
6385
|
};
|
|
6330
6386
|
}
|
|
6331
|
-
function formatLocalMinute(ms) {
|
|
6332
|
-
const when = new Date(ms);
|
|
6333
|
-
const pad = (value) => String(value).padStart(2, "0");
|
|
6334
|
-
return `${when.getFullYear()}-${pad(when.getMonth() + 1)}-${pad(when.getDate())} ${pad(when.getHours())}:${pad(when.getMinutes())}`;
|
|
6335
|
-
}
|
|
6336
6387
|
function formatStaleBuildNote(stale) {
|
|
6337
6388
|
const loadedAt = formatLocalMinute(stale.loadedAt);
|
|
6338
6389
|
if (stale.kind === "version") {
|
|
@@ -7558,6 +7609,7 @@ var PLUGIN_NOTE_MARKERS = [
|
|
|
7558
7609
|
SILENT_TURN_MARKER,
|
|
7559
7610
|
FAILOVER_MARKER,
|
|
7560
7611
|
ACCOUNT_BLOCK_MARKER,
|
|
7612
|
+
USAGE_LIMIT_MARKER,
|
|
7561
7613
|
MODEL_FALLBACK_MARKER,
|
|
7562
7614
|
UNATTENDED_REPLAY_MARKER,
|
|
7563
7615
|
STALE_BUILD_MARKER
|
|
@@ -9968,6 +10020,7 @@ function createTurnState(init) {
|
|
|
9968
10020
|
lastCallUsage: void 0,
|
|
9969
10021
|
resultFailure: void 0,
|
|
9970
10022
|
accountLimitHit: null,
|
|
10023
|
+
usageLimitNote: false,
|
|
9971
10024
|
accountBlock: null,
|
|
9972
10025
|
modelRefusal: null,
|
|
9973
10026
|
drainBuffer: [],
|
|
@@ -10748,6 +10801,7 @@ function createLineHandler(state, ctx) {
|
|
|
10748
10801
|
resetsAt: info.resetsAt ?? info.overageResetsAt,
|
|
10749
10802
|
window: info.rateLimitType
|
|
10750
10803
|
};
|
|
10804
|
+
rememberAccountLimit(ctx.sourceAccount, state.accountLimitHit);
|
|
10751
10805
|
}
|
|
10752
10806
|
const note = reportRateLimitEvent(msg);
|
|
10753
10807
|
if (note) {
|
|
@@ -11031,6 +11085,13 @@ ${plan}
|
|
|
11031
11085
|
if (hasText) {
|
|
11032
11086
|
state.hasReceivedContent = true;
|
|
11033
11087
|
}
|
|
11088
|
+
const apiErrorReply = msg.is_api_error_message === true;
|
|
11089
|
+
const limitErrorReply = apiErrorReply && ctx.usageLimitNoteActive && !state.accountBlock && (msg.error === "rate_limit" || isAccountLimitError({
|
|
11090
|
+
resultText: msg.message.content.filter((b) => b.type === "text" && b.text).map((b) => String(b.text)).join("\n")
|
|
11091
|
+
}));
|
|
11092
|
+
if (limitErrorReply) {
|
|
11093
|
+
state.accountLimitHit ??= recallAccountLimit(ctx.sourceAccount);
|
|
11094
|
+
}
|
|
11034
11095
|
if (hasText && !hasToolUse) {
|
|
11035
11096
|
startResultFallback(state);
|
|
11036
11097
|
}
|
|
@@ -11039,6 +11100,7 @@ ${plan}
|
|
|
11039
11100
|
}
|
|
11040
11101
|
for (const block2 of msg.message.content) {
|
|
11041
11102
|
if (block2.type === "text" && block2.text) {
|
|
11103
|
+
if (limitErrorReply) continue;
|
|
11042
11104
|
resetLastVisibleTextBlock(state);
|
|
11043
11105
|
const blockId = state.startTextBlock();
|
|
11044
11106
|
state.controller.enqueue({
|
|
@@ -11251,7 +11313,15 @@ ${plan}
|
|
|
11251
11313
|
if (deliverPendingCompletions(state)) {
|
|
11252
11314
|
return;
|
|
11253
11315
|
}
|
|
11254
|
-
if (!state.
|
|
11316
|
+
if (!state.accountLimitHit && msg.is_error && isAccountLimitError({
|
|
11317
|
+
resultText: typeof msg.result === "string" ? msg.result : null
|
|
11318
|
+
})) {
|
|
11319
|
+
state.accountLimitHit = recallAccountLimit(ctx.sourceAccount);
|
|
11320
|
+
}
|
|
11321
|
+
state.usageLimitNote = ctx.usageLimitNoteActive && !!state.accountLimitHit && // An expired login or a billing hold writes its own note just below
|
|
11322
|
+
// and says what to run; two notes about one failure is one too many.
|
|
11323
|
+
!state.accountBlock && msg.is_error === true;
|
|
11324
|
+
if (!state.currentTextId && msg.is_error && !state.usageLimitNote && typeof msg.result === "string" && msg.result.trim().length > 0) {
|
|
11255
11325
|
const errId = state.startTextBlock();
|
|
11256
11326
|
state.controller.enqueue({
|
|
11257
11327
|
type: "text-delta",
|
|
@@ -11259,11 +11329,6 @@ ${plan}
|
|
|
11259
11329
|
delta: msg.result
|
|
11260
11330
|
});
|
|
11261
11331
|
}
|
|
11262
|
-
if (!state.accountLimitHit && msg.is_error && isAccountLimitError({
|
|
11263
|
-
resultText: typeof msg.result === "string" ? msg.result : null
|
|
11264
|
-
})) {
|
|
11265
|
-
state.accountLimitHit = {};
|
|
11266
|
-
}
|
|
11267
11332
|
if (ctx.modelFallbackArmed && !state.modelRefusal) {
|
|
11268
11333
|
state.modelRefusal = modelRefusalFromResult(msg);
|
|
11269
11334
|
}
|
|
@@ -11277,7 +11342,11 @@ ${plan}
|
|
|
11277
11342
|
kind: state.accountBlock,
|
|
11278
11343
|
account: ctx.sourceAccount,
|
|
11279
11344
|
configDir: ctx.config.configDir,
|
|
11280
|
-
offeringSwitch
|
|
11345
|
+
offeringSwitch,
|
|
11346
|
+
// Read only when the form is not taking the turn, which is the
|
|
11347
|
+
// default: moving the work by hand is then the operator's only
|
|
11348
|
+
// route and nothing else on screen says it exists (h #g194).
|
|
11349
|
+
candidates: ctx.failoverAccounts
|
|
11281
11350
|
})
|
|
11282
11351
|
});
|
|
11283
11352
|
state.endTextBlock();
|
|
@@ -12156,7 +12225,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12156
12225
|
this.config.failoverAccounts,
|
|
12157
12226
|
sourceAccount
|
|
12158
12227
|
);
|
|
12159
|
-
const failoverAskActive = failoverAccounts.length > 0 && this.config.accountFailover
|
|
12228
|
+
const failoverAskActive = failoverAccounts.length > 0 && this.config.accountFailover === "ask" && !compactionMode && !useInteractive && // A `doGenerate` caller takes the override and reports the plain
|
|
12160
12229
|
// rate-limit error, never the form. See `TurnMode`.
|
|
12161
12230
|
mode !== "generate" && isAccountFailoverQuestionActive({
|
|
12162
12231
|
configured: this.config.accountFailover,
|
|
@@ -12169,6 +12238,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12169
12238
|
// the operator is usually not even looking at.
|
|
12170
12239
|
childSession: !!await fetchSessionParentId(affinity)
|
|
12171
12240
|
});
|
|
12241
|
+
const usageLimitNoteActive = !compactionMode && mode !== "generate" && !failoverAskActive;
|
|
12172
12242
|
let staleBuild = null;
|
|
12173
12243
|
if (!compactionMode && mode !== "generate" && affinity !== "default") {
|
|
12174
12244
|
staleBuild = staleBuildWatch().check();
|
|
@@ -12716,6 +12786,26 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12716
12786
|
return;
|
|
12717
12787
|
}
|
|
12718
12788
|
}
|
|
12789
|
+
if (state.usageLimitNote) {
|
|
12790
|
+
log.warn("claude account is out of usage; the turn ends with a note", {
|
|
12791
|
+
sessionKey: sk,
|
|
12792
|
+
account: sourceAccount,
|
|
12793
|
+
window: state.accountLimitHit?.window ?? null,
|
|
12794
|
+
resetsAt: state.accountLimitHit?.resetsAt ?? null,
|
|
12795
|
+
candidates: failoverAccounts
|
|
12796
|
+
});
|
|
12797
|
+
controller.enqueue({
|
|
12798
|
+
type: "text-delta",
|
|
12799
|
+
id: state.startTextBlock(),
|
|
12800
|
+
delta: formatUsageLimitNote({
|
|
12801
|
+
sourceAccount,
|
|
12802
|
+
candidates: failoverAccounts,
|
|
12803
|
+
resetsAt: state.accountLimitHit?.resetsAt,
|
|
12804
|
+
window: state.accountLimitHit?.window
|
|
12805
|
+
})
|
|
12806
|
+
});
|
|
12807
|
+
state.endTextBlock();
|
|
12808
|
+
}
|
|
12719
12809
|
if (runAutoContinue(state, msg)) return;
|
|
12720
12810
|
for (const [idx, reasoningId] of state.reasoningIds) {
|
|
12721
12811
|
if (state.reasoningStarted.get(idx)) {
|
|
@@ -12789,6 +12879,8 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12789
12879
|
planModeQuestionActive,
|
|
12790
12880
|
sourceAccount,
|
|
12791
12881
|
failoverAskActive,
|
|
12882
|
+
usageLimitNoteActive,
|
|
12883
|
+
failoverAccounts,
|
|
12792
12884
|
modelFallbackArmed,
|
|
12793
12885
|
attempt,
|
|
12794
12886
|
handleControlRequest: handleControlRequest2,
|
|
@@ -13855,7 +13947,11 @@ function createClaudeCode(settings = {}) {
|
|
|
13855
13947
|
configDir: settings.configDir,
|
|
13856
13948
|
failoverAccounts: settings.failoverAccounts,
|
|
13857
13949
|
baseCliPath: settings.baseCliPath ?? cliPath,
|
|
13858
|
-
|
|
13950
|
+
// Passed through, with no default applied here: the form is opt-in and
|
|
13951
|
+
// `isAccountFailoverQuestionActive` asks for an explicit `"ask"`, so an
|
|
13952
|
+
// unset option must stay unset rather than being written to one mode or
|
|
13953
|
+
// the other in only one of the two entry points (h #g194).
|
|
13954
|
+
accountFailover: settings.accountFailover,
|
|
13859
13955
|
providerID: settings.providerID,
|
|
13860
13956
|
skipPermissions: preset?.skipPermissions ?? settings.skipPermissions ?? true,
|
|
13861
13957
|
permissionMode: preset?.permissionMode ?? settings.permissionMode,
|