@schoolai/shipyard 3.34.0 → 3.34.1-rc.20260924.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/{chunk-ZGLXU6XJ.js → chunk-CRS3BMH4.js} +2 -2
- package/dist/{chunk-O7PCPQ5T.js → chunk-ZZHFRLKK.js} +3 -3
- package/dist/electron-utility.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{serve-NWLZH6MD.js → serve-ZUI52LNF.js} +200 -13
- package/dist/{serve-NWLZH6MD.js.map → serve-ZUI52LNF.js.map} +1 -1
- package/dist/{start-DCG37IQJ.js → start-2FKA6COR.js} +4 -4
- package/package.json +1 -1
- /package/dist/{chunk-ZGLXU6XJ.js.map → chunk-CRS3BMH4.js.map} +0 -0
- /package/dist/{chunk-O7PCPQ5T.js.map → chunk-ZZHFRLKK.js.map} +0 -0
- /package/dist/{start-DCG37IQJ.js.map → start-2FKA6COR.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getDaemonVersion
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZZHFRLKK.js";
|
|
5
5
|
import {
|
|
6
6
|
WorkerCommandCodec,
|
|
7
7
|
WorkerReplyCodec
|
|
@@ -1116,4 +1116,4 @@ export {
|
|
|
1116
1116
|
shutdownFileWatcherGuard,
|
|
1117
1117
|
guardedSubscribe
|
|
1118
1118
|
};
|
|
1119
|
-
//# sourceMappingURL=chunk-
|
|
1119
|
+
//# sourceMappingURL=chunk-CRS3BMH4.js.map
|
|
@@ -18,8 +18,8 @@ function getDaemonVersion() {
|
|
|
18
18
|
return cached;
|
|
19
19
|
}
|
|
20
20
|
function readDaemonVersion() {
|
|
21
|
-
if ("3.34.
|
|
22
|
-
return "3.34.
|
|
21
|
+
if ("3.34.1".length > 0) {
|
|
22
|
+
return "3.34.1";
|
|
23
23
|
}
|
|
24
24
|
try {
|
|
25
25
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
@@ -48,4 +48,4 @@ function readDaemonVersion() {
|
|
|
48
48
|
export {
|
|
49
49
|
getDaemonVersion
|
|
50
50
|
};
|
|
51
|
-
//# sourceMappingURL=chunk-
|
|
51
|
+
//# sourceMappingURL=chunk-ZZHFRLKK.js.map
|
package/dist/electron-utility.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getDaemonVersion
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZZHFRLKK.js";
|
|
5
5
|
import {
|
|
6
6
|
enableNativeCrashReports
|
|
7
7
|
} from "./chunk-CTVKFKRG.js";
|
|
@@ -71,7 +71,7 @@ async function main() {
|
|
|
71
71
|
await loadAuthFromConfig(env);
|
|
72
72
|
crumb("post-auth-load");
|
|
73
73
|
crumb("pre-serve-import");
|
|
74
|
-
const { serve } = await import("./serve-
|
|
74
|
+
const { serve } = await import("./serve-ZUI52LNF.js");
|
|
75
75
|
crumb("post-serve-import");
|
|
76
76
|
const portQueue = [];
|
|
77
77
|
let acceptor = null;
|
package/dist/index.js
CHANGED
|
@@ -137,7 +137,7 @@ async function handleSubcommand() {
|
|
|
137
137
|
return true;
|
|
138
138
|
}
|
|
139
139
|
if (subcommand === "start") {
|
|
140
|
-
const { startCommand } = await import("./start-
|
|
140
|
+
const { startCommand } = await import("./start-2FKA6COR.js");
|
|
141
141
|
await startCommand();
|
|
142
142
|
return true;
|
|
143
143
|
}
|
|
@@ -159,7 +159,7 @@ async function main() {
|
|
|
159
159
|
const args = parseCliArgs();
|
|
160
160
|
if (args.serve) {
|
|
161
161
|
await loadAuthFromConfig(env);
|
|
162
|
-
const { serve } = await import("./serve-
|
|
162
|
+
const { serve } = await import("./serve-ZUI52LNF.js");
|
|
163
163
|
return serve({ isDev: env.SHIPYARD_DEV });
|
|
164
164
|
}
|
|
165
165
|
logger.error("Use `shipyard start` to run the daemon. Use --help for usage.");
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
guardedSubscribe,
|
|
13
13
|
makeInitialAttemptState,
|
|
14
14
|
shutdownFileWatcherGuard
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-CRS3BMH4.js";
|
|
16
16
|
import {
|
|
17
17
|
TRAILER_SCHEMA_VERSION,
|
|
18
18
|
appendTrailerToMessage,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
} from "./chunk-T5J6HZOQ.js";
|
|
47
47
|
import {
|
|
48
48
|
getDaemonVersion
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-ZZHFRLKK.js";
|
|
50
50
|
import {
|
|
51
51
|
collectPriorCrashDetail,
|
|
52
52
|
getRecentWasmPanicMessages
|
|
@@ -6333,7 +6333,7 @@ function nanoid(size = 21) {
|
|
|
6333
6333
|
}
|
|
6334
6334
|
|
|
6335
6335
|
// src/services/bootstrap/signaling.ts
|
|
6336
|
-
var DAEMON_NPM_VERSION = true ? "3.34.
|
|
6336
|
+
var DAEMON_NPM_VERSION = true ? "3.34.1" : "unknown";
|
|
6337
6337
|
function createDaemonSignaling(config) {
|
|
6338
6338
|
const agentId = config.agentId ?? nanoid();
|
|
6339
6339
|
function send(msg) {
|
|
@@ -80980,14 +80980,41 @@ function buildDevinTaskSubprocess(options) {
|
|
|
80980
80980
|
}
|
|
80981
80981
|
|
|
80982
80982
|
// src/services/serve-factory/rate-limit-account-switch.ts
|
|
80983
|
-
function attributeRateLimitEvents(onEvent, spawnAccountKey) {
|
|
80983
|
+
function attributeRateLimitEvents(onEvent, spawnAccountKey, ctx) {
|
|
80984
80984
|
if (spawnAccountKey === null) return onEvent;
|
|
80985
|
+
const isStale = () => {
|
|
80986
|
+
if (ctx === void 0) return false;
|
|
80987
|
+
const current = ctx.getCurrentAccountKey();
|
|
80988
|
+
if (spawnAccountKey !== null && current !== null && spawnAccountKey !== current) {
|
|
80989
|
+
return true;
|
|
80990
|
+
}
|
|
80991
|
+
const lastSwitchAt = ctx.getLastAccountSwitchAtMs();
|
|
80992
|
+
return lastSwitchAt !== null && ctx.spawnedAtMs < lastSwitchAt;
|
|
80993
|
+
};
|
|
80985
80994
|
return (event) => {
|
|
80986
|
-
if (event.type
|
|
80987
|
-
|
|
80995
|
+
if (event.type === "rate_limit") {
|
|
80996
|
+
const stale = isStale();
|
|
80997
|
+
if (event.accountKey !== void 0 && !stale) {
|
|
80998
|
+
onEvent(event);
|
|
80999
|
+
return;
|
|
81000
|
+
}
|
|
81001
|
+
onEvent({
|
|
81002
|
+
...event,
|
|
81003
|
+
accountKey: event.accountKey ?? spawnAccountKey,
|
|
81004
|
+
...stale ? { spawnAccountStale: true } : {}
|
|
81005
|
+
});
|
|
80988
81006
|
return;
|
|
80989
81007
|
}
|
|
80990
|
-
|
|
81008
|
+
if (event.type === "rate_limit_error") {
|
|
81009
|
+
const stale = isStale();
|
|
81010
|
+
if (!stale) {
|
|
81011
|
+
onEvent(event);
|
|
81012
|
+
return;
|
|
81013
|
+
}
|
|
81014
|
+
onEvent({ ...event, spawnAccountStale: true });
|
|
81015
|
+
return;
|
|
81016
|
+
}
|
|
81017
|
+
onEvent(event);
|
|
80991
81018
|
};
|
|
80992
81019
|
}
|
|
80993
81020
|
function planClaudeAccountTransition(lastKey, next) {
|
|
@@ -81020,12 +81047,15 @@ function applyClaudeAccountSwitch(deps, switched) {
|
|
|
81020
81047
|
});
|
|
81021
81048
|
}
|
|
81022
81049
|
deps.rewarmUnderNewAccount();
|
|
81050
|
+
const retired = deps.retireStaleClaudeLanes();
|
|
81023
81051
|
deps.log({
|
|
81024
81052
|
event: "claude_account_switched",
|
|
81025
81053
|
from: switched.from,
|
|
81026
81054
|
to: switched.to,
|
|
81027
81055
|
clearedTaskIds,
|
|
81028
|
-
newAccountHasRateLimitRecord: record2 !== void 0
|
|
81056
|
+
newAccountHasRateLimitRecord: record2 !== void 0,
|
|
81057
|
+
retiredLanesStopped: retired.stopped,
|
|
81058
|
+
retiredLanesDeferred: retired.deferred
|
|
81029
81059
|
});
|
|
81030
81060
|
}
|
|
81031
81061
|
|
|
@@ -91955,6 +91985,18 @@ var AgentSessionManager = class {
|
|
|
91955
91985
|
*/
|
|
91956
91986
|
#expectedShutdown = false;
|
|
91957
91987
|
#configReloadPending = false;
|
|
91988
|
+
/**
|
|
91989
|
+
* One-shot intent: retire this lane's subprocess for a Claude account
|
|
91990
|
+
* switch as soon as it reaches quiescent warm_idle. Set only by
|
|
91991
|
+
* `prepareAccountReload()` when the lane is mid-turn — aborting a running
|
|
91992
|
+
* turn would lose work, so the retirement is deferred until the turn
|
|
91993
|
+
* completes (the stale-account respawn in RateLimitFlapController is the
|
|
91994
|
+
* backstop if the old account saturates first). Cleared wherever the
|
|
91995
|
+
* pending retirement becomes moot: `stop()`, `dispose()`, subprocess
|
|
91996
|
+
* death, and any fresh `spawn` effect (a new generation already
|
|
91997
|
+
* authenticates under the new account).
|
|
91998
|
+
*/
|
|
91999
|
+
#accountReloadPending = false;
|
|
91958
92000
|
/**
|
|
91959
92001
|
* True while a Cursor tool call is in flight (between `tool_execution_started`
|
|
91960
92002
|
* and `tool_execution_settled` FSM events). When true, `#chooseStallTimeoutMs`
|
|
@@ -92095,6 +92137,7 @@ var AgentSessionManager = class {
|
|
|
92095
92137
|
stop() {
|
|
92096
92138
|
if (this.#configReloadPending) this.#queue.length = 0;
|
|
92097
92139
|
this.#configReloadPending = false;
|
|
92140
|
+
this.#accountReloadPending = false;
|
|
92098
92141
|
this.#dispatch({ type: "stop_commanded" });
|
|
92099
92142
|
}
|
|
92100
92143
|
/** Preserve queued follow-up input across a configuration-only shutdown. */
|
|
@@ -92104,6 +92147,38 @@ var AgentSessionManager = class {
|
|
|
92104
92147
|
this.#dispatch({ type: "stop_commanded" });
|
|
92105
92148
|
return true;
|
|
92106
92149
|
}
|
|
92150
|
+
/**
|
|
92151
|
+
* Retire the live subprocess because the canonical Claude account
|
|
92152
|
+
* changed underneath it. A `warm_idle` process is parked holding the OLD
|
|
92153
|
+
* account's token — stopping it now costs only a resume spawn on the
|
|
92154
|
+
* next user message, so it goes down immediately via the existing
|
|
92155
|
+
* config-reload teardown (queue preserved). A `running`/`spawning`/
|
|
92156
|
+
* `stopping` lane keeps its turn — aborting would lose work — and is
|
|
92157
|
+
* stopped on reaching quiescent warm_idle via `#accountReloadPending`.
|
|
92158
|
+
* No live process (`cold_idle`/`resumable_idle`) means nothing to do.
|
|
92159
|
+
*/
|
|
92160
|
+
prepareAccountReload() {
|
|
92161
|
+
if (this.#state === "warm_idle" && this.#pendingInputs.size === 0) {
|
|
92162
|
+
const from = this.#state;
|
|
92163
|
+
this.prepareConfigReload();
|
|
92164
|
+
this.#config.log({
|
|
92165
|
+
event: "session_account_reload_stopped",
|
|
92166
|
+
taskId: this.#config.taskId,
|
|
92167
|
+
state: from
|
|
92168
|
+
});
|
|
92169
|
+
return "stopped";
|
|
92170
|
+
}
|
|
92171
|
+
if (this.#state === "running" || this.#state === "spawning" || this.#state === "stopping" || this.#state === "warm_idle") {
|
|
92172
|
+
this.#accountReloadPending = true;
|
|
92173
|
+
this.#config.log({
|
|
92174
|
+
event: "session_account_reload_deferred",
|
|
92175
|
+
taskId: this.#config.taskId,
|
|
92176
|
+
state: this.#state
|
|
92177
|
+
});
|
|
92178
|
+
return "deferred";
|
|
92179
|
+
}
|
|
92180
|
+
return "noop";
|
|
92181
|
+
}
|
|
92107
92182
|
rewind(resumeAtMessageId) {
|
|
92108
92183
|
this.#dispatch({ type: "rewind_requested", resumeAtMessageId });
|
|
92109
92184
|
}
|
|
@@ -92184,6 +92259,7 @@ var AgentSessionManager = class {
|
|
|
92184
92259
|
this.#queue = [];
|
|
92185
92260
|
this.#pendingInputs.clear();
|
|
92186
92261
|
this.#eventQueue = [];
|
|
92262
|
+
this.#accountReloadPending = false;
|
|
92187
92263
|
}
|
|
92188
92264
|
/**
|
|
92189
92265
|
* Trace the rewind fork target's whole lifetime: SET when a rewind records
|
|
@@ -92269,6 +92345,17 @@ var AgentSessionManager = class {
|
|
|
92269
92345
|
this.#configReloadPending = false;
|
|
92270
92346
|
if (this.#queue.length > 0) this.#dispatch({ type: "user_message" });
|
|
92271
92347
|
}
|
|
92348
|
+
if (this.#accountReloadPending && this.#state === "warm_idle" && this.#pendingInputs.size === 0) {
|
|
92349
|
+
this.#accountReloadPending = false;
|
|
92350
|
+
this.prepareConfigReload();
|
|
92351
|
+
this.#config.log({
|
|
92352
|
+
event: "session_account_reload_stopped",
|
|
92353
|
+
taskId: this.#config.taskId,
|
|
92354
|
+
state: "warm_idle",
|
|
92355
|
+
deferred: true
|
|
92356
|
+
});
|
|
92357
|
+
}
|
|
92358
|
+
if (event.type === "subprocess_died") this.#accountReloadPending = false;
|
|
92272
92359
|
}
|
|
92273
92360
|
#applyEffects(effects) {
|
|
92274
92361
|
for (const effect of effects) {
|
|
@@ -92279,6 +92366,7 @@ var AgentSessionManager = class {
|
|
|
92279
92366
|
this.#firstStepReceived = false;
|
|
92280
92367
|
this.#lastStreamActivityAt = null;
|
|
92281
92368
|
this.#toolExecutionInFlight = false;
|
|
92369
|
+
this.#accountReloadPending = false;
|
|
92282
92370
|
this.#config.onSpawn(effect.reason, initial?.content ?? []);
|
|
92283
92371
|
break;
|
|
92284
92372
|
}
|
|
@@ -92833,6 +92921,8 @@ var CursorRecoveryController = class {
|
|
|
92833
92921
|
// src/services/conversation/rate-limit-flap-controller.ts
|
|
92834
92922
|
var MAX_RATE_LIMIT_FLAP_RETRIES = 1;
|
|
92835
92923
|
var RATE_LIMIT_FLAP_RETRY_DELAY_MS = 8e3;
|
|
92924
|
+
var MAX_STALE_ACCOUNT_RESPAWNS = 1;
|
|
92925
|
+
var STALE_ACCOUNT_RESPAWN_DELAY_MS = 1e3;
|
|
92836
92926
|
function isLikelyAnthropicFlap(info, nowMs = Date.now()) {
|
|
92837
92927
|
if (info === void 0) return false;
|
|
92838
92928
|
if (info.provider !== void 0 && info.provider !== "anthropic") return false;
|
|
@@ -92885,6 +92975,13 @@ var RateLimitFlapController = class {
|
|
|
92885
92975
|
* sent something fresh, that turn deserves its own retry budget).
|
|
92886
92976
|
*/
|
|
92887
92977
|
#flapRetries = 0;
|
|
92978
|
+
/**
|
|
92979
|
+
* Consecutive stale-account respawns this turn. Independent budget from
|
|
92980
|
+
* `#flapRetries`: the stale path answers "the emitting process predates
|
|
92981
|
+
* the current account", not "Anthropic returned an implausible
|
|
92982
|
+
* rejection". Reset alongside it.
|
|
92983
|
+
*/
|
|
92984
|
+
#staleAccountRespawns = 0;
|
|
92888
92985
|
/**
|
|
92889
92986
|
* Cached most recent `rate_limit` info-event payload. The flap
|
|
92890
92987
|
* discriminator runs at `rate_limit_error` time but the discriminating
|
|
@@ -92912,6 +93009,7 @@ var RateLimitFlapController = class {
|
|
|
92912
93009
|
resetForNewTurn() {
|
|
92913
93010
|
this.cancelPendingRetry();
|
|
92914
93011
|
this.#flapRetries = 0;
|
|
93012
|
+
this.#staleAccountRespawns = 0;
|
|
92915
93013
|
this.#lastInfo = void 0;
|
|
92916
93014
|
}
|
|
92917
93015
|
/**
|
|
@@ -92935,15 +93033,17 @@ var RateLimitFlapController = class {
|
|
|
92935
93033
|
* exhausts into the surfaced banner, not a silent loop. #3932.
|
|
92936
93034
|
*/
|
|
92937
93035
|
noteRecoveredOnTurnComplete(producedOutput) {
|
|
92938
|
-
if (this.#flapRetries === 0) return;
|
|
93036
|
+
if (this.#flapRetries === 0 && this.#staleAccountRespawns === 0) return;
|
|
92939
93037
|
if (!producedOutput) return;
|
|
92940
93038
|
this.cancelPendingRetry();
|
|
92941
93039
|
this.#deps.log({
|
|
92942
93040
|
event: "thread_usage_limit_flap_recovered",
|
|
92943
93041
|
threadId: this.#deps.threadId,
|
|
92944
|
-
retries: this.#flapRetries
|
|
93042
|
+
retries: this.#flapRetries,
|
|
93043
|
+
staleAccountRespawns: this.#staleAccountRespawns
|
|
92945
93044
|
});
|
|
92946
93045
|
this.#flapRetries = 0;
|
|
93046
|
+
this.#staleAccountRespawns = 0;
|
|
92947
93047
|
}
|
|
92948
93048
|
handleEvent(event) {
|
|
92949
93049
|
if (event.type === "rate_limit" && event.info.status === "rejected") {
|
|
@@ -92952,6 +93052,22 @@ var RateLimitFlapController = class {
|
|
|
92952
93052
|
if (this.#timer !== null) return;
|
|
92953
93053
|
const isBlocking = event.type === "rate_limit_error" || event.info.status === "rejected" && event.info.isUsingOverage !== true;
|
|
92954
93054
|
if (!isBlocking) return;
|
|
93055
|
+
if (event.spawnAccountStale === true && this.#deps.getState() === "running" && this.#staleAccountRespawns < MAX_STALE_ACCOUNT_RESPAWNS) {
|
|
93056
|
+
this.#staleAccountRespawns++;
|
|
93057
|
+
this.#deps.log({
|
|
93058
|
+
event: "thread_usage_limit_stale_account_respawn",
|
|
93059
|
+
threadId: this.#deps.threadId,
|
|
93060
|
+
eventType: event.type,
|
|
93061
|
+
retries: this.#staleAccountRespawns
|
|
93062
|
+
});
|
|
93063
|
+
this.#deps.notifyAbortRetry();
|
|
93064
|
+
this.#timer = setTimeout(() => {
|
|
93065
|
+
this.#timer = null;
|
|
93066
|
+
if (this.#deps.isDisposed()) return;
|
|
93067
|
+
this.#deps.respawnForResume();
|
|
93068
|
+
}, STALE_ACCOUNT_RESPAWN_DELAY_MS);
|
|
93069
|
+
return;
|
|
93070
|
+
}
|
|
92955
93071
|
const flapInfo = event.type === "rate_limit" ? event.info : this.#lastInfo;
|
|
92956
93072
|
if (this.#deps.getState() === "running" && this.#flapRetries < MAX_RATE_LIMIT_FLAP_RETRIES && isLikelyAnthropicFlap(flapInfo)) {
|
|
92957
93073
|
this.#flapRetries++;
|
|
@@ -96342,6 +96458,17 @@ var Thread = class {
|
|
|
96342
96458
|
if (this.#agentSystem !== "devin") return false;
|
|
96343
96459
|
return this.#manager.prepareConfigReload();
|
|
96344
96460
|
}
|
|
96461
|
+
/**
|
|
96462
|
+
* Retire this lane's subprocess after a Claude account switch: a parked
|
|
96463
|
+
* warm_idle process holds the old account's token, so it is stopped now
|
|
96464
|
+
* (the next message respawns under the new credential); a running lane
|
|
96465
|
+
* keeps its turn and is retired on reaching warm_idle. Non-Claude lanes
|
|
96466
|
+
* are unaffected by a Claude credential swap.
|
|
96467
|
+
*/
|
|
96468
|
+
retireSubprocessForAccountSwitch() {
|
|
96469
|
+
if (this.#agentSystem !== "claude-code") return "noop";
|
|
96470
|
+
return this.#manager.prepareAccountReload();
|
|
96471
|
+
}
|
|
96345
96472
|
async reconnectMcpServer(serverName) {
|
|
96346
96473
|
if (!this.#subprocess) return;
|
|
96347
96474
|
await this.#subprocess.reconnectMcpServer(serverName);
|
|
@@ -102972,6 +103099,15 @@ function handleMainThreadEvent(ctx, event) {
|
|
|
102972
103099
|
ctx.onAuthNotLoggedIn(ctx.getRuntimeId());
|
|
102973
103100
|
break;
|
|
102974
103101
|
case "rate_limit":
|
|
103102
|
+
if (event.spawnAccountStale === true) {
|
|
103103
|
+
ctx.log({
|
|
103104
|
+
event: "rate_limit_event_dropped_stale_account",
|
|
103105
|
+
taskId: ctx.taskId,
|
|
103106
|
+
spawnAccountKey: event.accountKey ?? null,
|
|
103107
|
+
status: event.info.status
|
|
103108
|
+
});
|
|
103109
|
+
break;
|
|
103110
|
+
}
|
|
102975
103111
|
ctx.onRateLimitEvent(event.info, event.accountKey ?? null);
|
|
102976
103112
|
break;
|
|
102977
103113
|
case "billing_error":
|
|
@@ -108459,6 +108595,23 @@ var Task = class {
|
|
|
108459
108595
|
get mainThread() {
|
|
108460
108596
|
return this.#getPrimary();
|
|
108461
108597
|
}
|
|
108598
|
+
/**
|
|
108599
|
+
* Retire every Claude lane in this task after a canonical-account switch:
|
|
108600
|
+
* the primary thread plus every side thread. Warm-idle lanes stop now
|
|
108601
|
+
* (`stopped`); mid-turn lanes defer until they reach warm_idle
|
|
108602
|
+
* (`deferred`). Non-Claude and process-free lanes are `noop`.
|
|
108603
|
+
*/
|
|
108604
|
+
retireClaudeSubprocessesForAccountSwitch() {
|
|
108605
|
+
const tally = { stopped: 0, deferred: 0 };
|
|
108606
|
+
const apply = (thread) => {
|
|
108607
|
+
const result = thread.retireSubprocessForAccountSwitch();
|
|
108608
|
+
if (result === "stopped") tally.stopped++;
|
|
108609
|
+
else if (result === "deferred") tally.deferred++;
|
|
108610
|
+
};
|
|
108611
|
+
apply(this.#getPrimary());
|
|
108612
|
+
this.#propagateToSideThreads(apply, "retire_for_account_switch_error");
|
|
108613
|
+
return tally;
|
|
108614
|
+
}
|
|
108462
108615
|
/**
|
|
108463
108616
|
* Cancel the sliding-window timer for `uri` and trigger an immediate flush.
|
|
108464
108617
|
* User-initiated path from `flush_resource_batch` control-channel message.
|
|
@@ -111660,6 +111813,20 @@ var TaskManager = class {
|
|
|
111660
111813
|
}
|
|
111661
111814
|
return result;
|
|
111662
111815
|
}
|
|
111816
|
+
/**
|
|
111817
|
+
* Retire every Claude lane across all managed tasks after a canonical
|
|
111818
|
+
* account switch. Called from `applyClaudeAccountSwitch`; returns the
|
|
111819
|
+
* aggregate counts for the `claude_account_switched` log line.
|
|
111820
|
+
*/
|
|
111821
|
+
retireClaudeSubprocessesForAccountSwitch() {
|
|
111822
|
+
const tally = { stopped: 0, deferred: 0 };
|
|
111823
|
+
for (const task of this.#tasks.values()) {
|
|
111824
|
+
const result = task.orchestrator.retireClaudeSubprocessesForAccountSwitch();
|
|
111825
|
+
tally.stopped += result.stopped;
|
|
111826
|
+
tally.deferred += result.deferred;
|
|
111827
|
+
}
|
|
111828
|
+
return tally;
|
|
111829
|
+
}
|
|
111663
111830
|
/**
|
|
111664
111831
|
* Browser-initiated flush for a specific resource URI (PROTOCOL_VERSION 48).
|
|
111665
111832
|
* Resolves the URI to its owning task by extracting the taskId from the
|
|
@@ -113944,9 +114111,13 @@ async function createDaemon(deps) {
|
|
|
113944
114111
|
const claudeAccountSwitchRef = {
|
|
113945
114112
|
current: (switched) => deps.log({ event: "claude_account_switch_before_wiring", ...switched })
|
|
113946
114113
|
};
|
|
114114
|
+
let lastClaudeAccountSwitchAtMs = null;
|
|
113947
114115
|
const commitCapabilities = createCapabilityWriter(
|
|
113948
114116
|
capabilitiesRef,
|
|
113949
|
-
createClaudeAccountTracker((switched) =>
|
|
114117
|
+
createClaudeAccountTracker((switched) => {
|
|
114118
|
+
lastClaudeAccountSwitchAtMs = Date.now();
|
|
114119
|
+
claudeAccountSwitchRef.current(switched);
|
|
114120
|
+
})
|
|
113950
114121
|
);
|
|
113951
114122
|
const rateLimitStoreRef = { current: null };
|
|
113952
114123
|
const gitCheckpoint = createGitCheckpointService();
|
|
@@ -114680,9 +114851,24 @@ async function createDaemon(deps) {
|
|
|
114680
114851
|
});
|
|
114681
114852
|
const selectedModel = settings?.model ?? null;
|
|
114682
114853
|
const profileForModel = selectedModel !== null ? profileRegistry.findByModelId(selectedModel) : null;
|
|
114854
|
+
const spawnProfileId = profileForModel?.id ?? "claude-code";
|
|
114683
114855
|
const onEvent = attributeRateLimitEvents(
|
|
114684
114856
|
unattributedOnEvent,
|
|
114685
|
-
resolveRateLimitAccountKey(capabilitiesRef.current,
|
|
114857
|
+
resolveRateLimitAccountKey(capabilitiesRef.current, spawnProfileId),
|
|
114858
|
+
{
|
|
114859
|
+
/**
|
|
114860
|
+
* Same profile as the spawn key: a non-Claude lane compares against
|
|
114861
|
+
* its own account so cross-profile key shapes never false-flag stale.
|
|
114862
|
+
*/
|
|
114863
|
+
getCurrentAccountKey: () => resolveRateLimitAccountKey(capabilitiesRef.current, spawnProfileId),
|
|
114864
|
+
/**
|
|
114865
|
+
* `lastClaudeAccountSwitchAtMs` is Claude-only — gate it on the
|
|
114866
|
+
* spawn profile so a Codex/Cursor lane spawned before a Claude
|
|
114867
|
+
* switch isn't false-flagged stale by the timestamp rule.
|
|
114868
|
+
*/
|
|
114869
|
+
getLastAccountSwitchAtMs: () => spawnProfileId === "claude-code" ? lastClaudeAccountSwitchAtMs : null,
|
|
114870
|
+
spawnedAtMs: Date.now()
|
|
114871
|
+
}
|
|
114686
114872
|
);
|
|
114687
114873
|
const decision = decideSpawnRoute({
|
|
114688
114874
|
mode,
|
|
@@ -115394,6 +115580,7 @@ async function createDaemon(deps) {
|
|
|
115394
115580
|
preWarmManager.kill();
|
|
115395
115581
|
preWarmManager.resetAndRestart();
|
|
115396
115582
|
},
|
|
115583
|
+
retireStaleClaudeLanes: () => taskManager.retireClaudeSubprocessesForAccountSwitch(),
|
|
115397
115584
|
log: deps.log
|
|
115398
115585
|
},
|
|
115399
115586
|
switched
|
|
@@ -119525,4 +119712,4 @@ export {
|
|
|
119525
119712
|
decideWorkspaceScope,
|
|
119526
119713
|
serve
|
|
119527
119714
|
};
|
|
119528
|
-
//# sourceMappingURL=serve-
|
|
119715
|
+
//# sourceMappingURL=serve-ZUI52LNF.js.map
|