@schoolai/shipyard 3.34.1-rc.20260927.1 → 3.34.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/electron-utility.js +1 -1
- package/dist/index.js +2 -2
- package/dist/{serve-OP4JVMPM.js → serve-LJYQF75A.js} +124 -17
- package/dist/{serve-OP4JVMPM.js.map → serve-LJYQF75A.js.map} +1 -1
- package/dist/{start-MOBEORLT.js → start-E2YHOYBP.js} +2 -2
- package/package.json +1 -1
- /package/dist/{start-MOBEORLT.js.map → start-E2YHOYBP.js.map} +0 -0
package/dist/electron-utility.js
CHANGED
|
@@ -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-LJYQF75A.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-E2YHOYBP.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-LJYQF75A.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.");
|
|
@@ -25629,6 +25629,30 @@ function resolveUsageLimitResetsAtMs(rateLimitStore, capabilities, profileForSpa
|
|
|
25629
25629
|
if (record2.info.isUsingOverage === true) return null;
|
|
25630
25630
|
return pickSoonestSaturatedReset(record2.info, nowMs);
|
|
25631
25631
|
}
|
|
25632
|
+
var USAGE_LIMIT_TRUST_WINDOW_MS = 10 * 6e4;
|
|
25633
|
+
var USAGE_LIMIT_PROBE_TIMEOUT_MS = 9e4;
|
|
25634
|
+
function resolveUsageLimitGate(rateLimitStore, capabilities, profileForSpawn = null, nowMs = Date.now(), mode = "claim") {
|
|
25635
|
+
const resetsAt = resolveUsageLimitResetsAtMs(
|
|
25636
|
+
rateLimitStore,
|
|
25637
|
+
capabilities,
|
|
25638
|
+
profileForSpawn,
|
|
25639
|
+
nowMs
|
|
25640
|
+
);
|
|
25641
|
+
const accountKey = resolveRateLimitAccountKey(capabilities, profileForSpawn);
|
|
25642
|
+
if (resetsAt === null || rateLimitStore === null || accountKey === null) {
|
|
25643
|
+
return { resetsAtMs: resetsAt, probe: null, accountKey };
|
|
25644
|
+
}
|
|
25645
|
+
if (rateLimitStore.isRecordTrusted(accountKey, nowMs, USAGE_LIMIT_TRUST_WINDOW_MS)) {
|
|
25646
|
+
return { resetsAtMs: resetsAt, probe: null, accountKey };
|
|
25647
|
+
}
|
|
25648
|
+
if (mode === "observe") {
|
|
25649
|
+
return { resetsAtMs: null, probe: null, accountKey };
|
|
25650
|
+
}
|
|
25651
|
+
if (rateLimitStore.claimUsageLimitProbe(accountKey, nowMs, USAGE_LIMIT_PROBE_TIMEOUT_MS)) {
|
|
25652
|
+
return { resetsAtMs: null, probe: "claimed", accountKey };
|
|
25653
|
+
}
|
|
25654
|
+
return { resetsAtMs: resetsAt, probe: "blocked", accountKey };
|
|
25655
|
+
}
|
|
25632
25656
|
var SYNTHETIC_REJECTED_WINDOW_MS = 15e3;
|
|
25633
25657
|
function pickSoonestSaturatedReset(info, nowMs) {
|
|
25634
25658
|
let candidate = null;
|
|
@@ -82440,6 +82464,20 @@ function createClaudeAccountTracker(onSwitched) {
|
|
|
82440
82464
|
if (plan.switched !== null) onSwitched(plan.switched);
|
|
82441
82465
|
};
|
|
82442
82466
|
}
|
|
82467
|
+
function createAccountKeySwitchTracker(onSwitched) {
|
|
82468
|
+
const lastKeys = /* @__PURE__ */ new Map();
|
|
82469
|
+
return (next) => {
|
|
82470
|
+
for (const profile of AGENT_IDS) {
|
|
82471
|
+
const key = resolveRateLimitAccountKey(next, profile);
|
|
82472
|
+
if (key === null) continue;
|
|
82473
|
+
const last = lastKeys.get(profile);
|
|
82474
|
+
lastKeys.set(profile, key);
|
|
82475
|
+
if (last !== void 0 && last !== key) {
|
|
82476
|
+
onSwitched({ profile, from: last, to: key });
|
|
82477
|
+
}
|
|
82478
|
+
}
|
|
82479
|
+
};
|
|
82480
|
+
}
|
|
82443
82481
|
function applyClaudeAccountSwitch(deps, switched) {
|
|
82444
82482
|
const clearedTaskIds = [...deps.lastUsageLimitBroadcastByTask.keys()];
|
|
82445
82483
|
deps.lastUsageLimitBroadcastByTask.clear();
|
|
@@ -91221,6 +91259,8 @@ async function buildRateLimitStore(dataDir, opts) {
|
|
|
91221
91259
|
const initial = await loadStoreFile(filePath, opts.logger);
|
|
91222
91260
|
const records = { ...initial.records };
|
|
91223
91261
|
const observed = /* @__PURE__ */ new Set();
|
|
91262
|
+
const switchedInUntrusted = /* @__PURE__ */ new Set();
|
|
91263
|
+
const probeInFlight = /* @__PURE__ */ new Map();
|
|
91224
91264
|
let writeQueue = Promise.resolve();
|
|
91225
91265
|
function enqueueWrite(accountKey) {
|
|
91226
91266
|
const attempt = () => withFileLock(lockPath2, async () => {
|
|
@@ -91245,8 +91285,25 @@ async function buildRateLimitStore(dataDir, opts) {
|
|
|
91245
91285
|
observedSinceLoad(accountKey) {
|
|
91246
91286
|
return observed.has(accountKey);
|
|
91247
91287
|
},
|
|
91288
|
+
isRecordTrusted(accountKey, nowMs, trustWindowMs) {
|
|
91289
|
+
const record2 = records[accountKey];
|
|
91290
|
+
if (!record2) return false;
|
|
91291
|
+
if (switchedInUntrusted.has(accountKey)) return false;
|
|
91292
|
+
return nowMs - record2.updatedAt < trustWindowMs;
|
|
91293
|
+
},
|
|
91294
|
+
markAccountSwitchedIn(accountKey) {
|
|
91295
|
+
switchedInUntrusted.add(accountKey);
|
|
91296
|
+
},
|
|
91297
|
+
claimUsageLimitProbe(accountKey, nowMs, probeTimeoutMs) {
|
|
91298
|
+
const started = probeInFlight.get(accountKey);
|
|
91299
|
+
if (started !== void 0 && nowMs - started < probeTimeoutMs) return false;
|
|
91300
|
+
probeInFlight.set(accountKey, nowMs);
|
|
91301
|
+
return true;
|
|
91302
|
+
},
|
|
91248
91303
|
set(accountKey, info) {
|
|
91249
91304
|
observed.add(accountKey);
|
|
91305
|
+
switchedInUntrusted.delete(accountKey);
|
|
91306
|
+
probeInFlight.delete(accountKey);
|
|
91250
91307
|
const record2 = {
|
|
91251
91308
|
info: normalizeRateLimitResetsToMs(info),
|
|
91252
91309
|
updatedAt: Date.now()
|
|
@@ -91257,6 +91314,8 @@ async function buildRateLimitStore(dataDir, opts) {
|
|
|
91257
91314
|
},
|
|
91258
91315
|
applyEvent(accountKey, info, eventTime) {
|
|
91259
91316
|
observed.add(accountKey);
|
|
91317
|
+
switchedInUntrusted.delete(accountKey);
|
|
91318
|
+
probeInFlight.delete(accountKey);
|
|
91260
91319
|
const prev = records[accountKey]?.info;
|
|
91261
91320
|
const nextInfo = mergeEvent(prev, normalizeRateLimitResetsToMs(info), eventTime);
|
|
91262
91321
|
const record2 = { info: nextInfo, updatedAt: eventTime };
|
|
@@ -91284,6 +91343,8 @@ async function buildRateLimitStore(dataDir, opts) {
|
|
|
91284
91343
|
clearForAccount(accountKey) {
|
|
91285
91344
|
if (!(accountKey in records)) return false;
|
|
91286
91345
|
observed.delete(accountKey);
|
|
91346
|
+
switchedInUntrusted.delete(accountKey);
|
|
91347
|
+
probeInFlight.delete(accountKey);
|
|
91287
91348
|
delete records[accountKey];
|
|
91288
91349
|
enqueueWrite(accountKey);
|
|
91289
91350
|
return true;
|
|
@@ -91293,6 +91354,8 @@ async function buildRateLimitStore(dataDir, opts) {
|
|
|
91293
91354
|
delete records[key];
|
|
91294
91355
|
}
|
|
91295
91356
|
observed.clear();
|
|
91357
|
+
switchedInUntrusted.clear();
|
|
91358
|
+
probeInFlight.clear();
|
|
91296
91359
|
enqueueWrite();
|
|
91297
91360
|
}
|
|
91298
91361
|
};
|
|
@@ -116934,14 +116997,23 @@ async function createDaemon(deps) {
|
|
|
116934
116997
|
current: (reason) => deps.log({ event: "claude_auth_recheck_before_wiring", reason })
|
|
116935
116998
|
};
|
|
116936
116999
|
let lastClaudeAccountSwitchAtMs = null;
|
|
116937
|
-
const commitCapabilities = createCapabilityWriter(
|
|
116938
|
-
capabilitiesRef,
|
|
116939
|
-
createClaudeAccountTracker((switched) => {
|
|
116940
|
-
lastClaudeAccountSwitchAtMs = Date.now();
|
|
116941
|
-
claudeAccountSwitchRef.current(switched);
|
|
116942
|
-
})
|
|
116943
|
-
);
|
|
116944
117000
|
const rateLimitStoreRef = { current: null };
|
|
117001
|
+
const claudeTracker = createClaudeAccountTracker((switched) => {
|
|
117002
|
+
lastClaudeAccountSwitchAtMs = Date.now();
|
|
117003
|
+
claudeAccountSwitchRef.current(switched);
|
|
117004
|
+
});
|
|
117005
|
+
const accountKeySwitchTracker = createAccountKeySwitchTracker((switched) => {
|
|
117006
|
+
rateLimitStoreRef.current?.markAccountSwitchedIn(switched.to);
|
|
117007
|
+
deps.log({
|
|
117008
|
+
event: "rate_limit_record_untrusted_on_switch_in",
|
|
117009
|
+
profile: switched.profile,
|
|
117010
|
+
accountKey: switched.to
|
|
117011
|
+
});
|
|
117012
|
+
});
|
|
117013
|
+
const commitCapabilities = createCapabilityWriter(capabilitiesRef, (next) => {
|
|
117014
|
+
claudeTracker(next);
|
|
117015
|
+
accountKeySwitchTracker(next);
|
|
117016
|
+
});
|
|
116945
117017
|
const gitCheckpoint = createGitCheckpointService();
|
|
116946
117018
|
const skillResolution = buildSkillResolutionService({
|
|
116947
117019
|
shipyardHome: deps.shipyardHome,
|
|
@@ -117658,6 +117730,32 @@ async function createDaemon(deps) {
|
|
|
117658
117730
|
return subprocess;
|
|
117659
117731
|
}
|
|
117660
117732
|
const lastUsageLimitBroadcastByTask = /* @__PURE__ */ new Map();
|
|
117733
|
+
const usageLimitGateForSpawn = (taskId, profileId) => {
|
|
117734
|
+
const gate = resolveUsageLimitGate(
|
|
117735
|
+
rateLimitStoreRef.current,
|
|
117736
|
+
capabilitiesRef.current,
|
|
117737
|
+
profileId
|
|
117738
|
+
);
|
|
117739
|
+
if (gate.probe === "claimed") {
|
|
117740
|
+
const record2 = gate.accountKey === null ? void 0 : rateLimitStoreRef.current?.get(gate.accountKey);
|
|
117741
|
+
deps.log({
|
|
117742
|
+
event: "usage_limit_probe_spawn",
|
|
117743
|
+
taskId,
|
|
117744
|
+
accountKey: gate.accountKey,
|
|
117745
|
+
profile: profileId,
|
|
117746
|
+
recordAgeMs: record2 ? Date.now() - record2.updatedAt : null
|
|
117747
|
+
});
|
|
117748
|
+
} else if (gate.probe === "blocked") {
|
|
117749
|
+
deps.log({
|
|
117750
|
+
event: "usage_limit_probe_blocked",
|
|
117751
|
+
taskId,
|
|
117752
|
+
accountKey: gate.accountKey,
|
|
117753
|
+
profile: profileId,
|
|
117754
|
+
resetsAtMs: gate.resetsAtMs
|
|
117755
|
+
});
|
|
117756
|
+
}
|
|
117757
|
+
return gate.resetsAtMs;
|
|
117758
|
+
};
|
|
117661
117759
|
const spawnSubprocessFn = (reason, initialContent, unattributedOnEvent, canUseTool, settings, cwd, taskId, additionalSystemPrompt, disallowedTools, mode, onCwdChanged, initialMessageKind) => {
|
|
117662
117760
|
const resolvedTaskId = taskId ?? "unknown";
|
|
117663
117761
|
const resolvedCwd = cwd ?? deps.workspaceRoot;
|
|
@@ -117716,11 +117814,7 @@ async function createDaemon(deps) {
|
|
|
117716
117814
|
profileForModel?.id ?? null,
|
|
117717
117815
|
capabilitiesRef.current
|
|
117718
117816
|
),
|
|
117719
|
-
usageLimitResetsAtMs:
|
|
117720
|
-
rateLimitStoreRef.current,
|
|
117721
|
-
capabilitiesRef.current,
|
|
117722
|
-
profileForModel?.id ?? null
|
|
117723
|
-
),
|
|
117817
|
+
usageLimitResetsAtMs: usageLimitGateForSpawn(resolvedTaskId, profileForModel?.id ?? null),
|
|
117724
117818
|
resolvedCwd,
|
|
117725
117819
|
/** Sync: `SpawnSubprocessFn` contract requires synchronous check; policy details live on `isPathPresentSync`. */
|
|
117726
117820
|
cwdExists: isPathPresentSync(resolvedCwd)
|
|
@@ -118406,10 +118500,23 @@ async function createDaemon(deps) {
|
|
|
118406
118500
|
* no-op (returns null), which matches the legacy behavior of "spawn
|
|
118407
118501
|
* unconditionally during early boot."
|
|
118408
118502
|
*/
|
|
118409
|
-
checkUsageLimit: () =>
|
|
118410
|
-
|
|
118411
|
-
|
|
118412
|
-
|
|
118503
|
+
checkUsageLimit: () => (
|
|
118504
|
+
/**
|
|
118505
|
+
* 'observe' — a warm lane is idle until adopted (`initialContent: []`,
|
|
118506
|
+
* no API call), so it can never produce probe evidence; claiming would
|
|
118507
|
+
* only starve real task spawns behind USAGE_LIMIT_PROBE_TIMEOUT_MS.
|
|
118508
|
+
* The task spawn that claims the probe adopts this warm lane, and the
|
|
118509
|
+
* adopting turn's first `rate_limit` event IS the evidence (#5469).
|
|
118510
|
+
* This call also runs in the failure-backoff path — a bookkeeping read
|
|
118511
|
+
* that must not have side effects.
|
|
118512
|
+
*/
|
|
118513
|
+
resolveUsageLimitGate(
|
|
118514
|
+
rateLimitStoreRef.current,
|
|
118515
|
+
capabilitiesRef.current,
|
|
118516
|
+
"claude-code",
|
|
118517
|
+
Date.now(),
|
|
118518
|
+
"observe"
|
|
118519
|
+
).resetsAtMs
|
|
118413
118520
|
),
|
|
118414
118521
|
/** Block the spawn only on an explicit `unauthenticated` flip (unknown/authenticated still spawn). */
|
|
118415
118522
|
checkIsAuthenticated: () => capabilitiesRef.current?.anthropicAuth?.status !== "unauthenticated"
|
|
@@ -122647,4 +122754,4 @@ export {
|
|
|
122647
122754
|
decideWorkspaceScope,
|
|
122648
122755
|
serve
|
|
122649
122756
|
};
|
|
122650
|
-
//# sourceMappingURL=serve-
|
|
122757
|
+
//# sourceMappingURL=serve-LJYQF75A.js.map
|