instar 1.3.399 → 1.3.400
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +73 -5
- package/dist/commands/server.js.map +1 -1
- package/dist/core/QuotaAwareScheduler.d.ts +96 -0
- package/dist/core/QuotaAwareScheduler.d.ts.map +1 -0
- package/dist/core/QuotaAwareScheduler.js +134 -0
- package/dist/core/QuotaAwareScheduler.js.map +1 -0
- package/dist/core/SessionManager.d.ts +6 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +6 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SessionRefresh.d.ts +18 -1
- package/dist/core/SessionRefresh.d.ts.map +1 -1
- package/dist/core/SessionRefresh.js +4 -1
- package/dist/core/SessionRefresh.js.map +1 -1
- package/dist/core/frameworkSessionLaunch.d.ts +10 -0
- package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
- package/dist/core/frameworkSessionLaunch.js +10 -6
- package/dist/core/frameworkSessionLaunch.js.map +1 -1
- package/dist/core/types.d.ts +18 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +2 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +26 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +48 -48
- package/upgrades/1.3.400.md +55 -0
- package/upgrades/side-effects/subscription-auth-scheduler.md +90 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQ3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA6JtD,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQ3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA6JtD,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA05BD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,GAC/F,IAAI,CAyUN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAk9TtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
|
package/dist/commands/server.js
CHANGED
|
@@ -378,7 +378,14 @@ let _slackAdapter = null;
|
|
|
378
378
|
// Null until startServer constructs it; the Telegram /restart handler falls
|
|
379
379
|
// back to the inline kill+respawn path when null (e.g. early in boot).
|
|
380
380
|
let _sessionRefresh = null;
|
|
381
|
-
|
|
381
|
+
// Subscription & Auth Standard P1.3 — quota-aware account-swap scheduler. Null
|
|
382
|
+
// until wired (requires SessionRefresh + the subscription pool).
|
|
383
|
+
let _quotaAwareScheduler = null;
|
|
384
|
+
async function spawnSessionForTopic(sessionManager, telegram, sessionName, topicId, latestMessage, topicMemory, userProfile, precomputedContext,
|
|
385
|
+
/** Subscription & Auth Standard P1.3 (additive): launch under this account's
|
|
386
|
+
* config home + record its id (the quota-aware account-swap mechanism).
|
|
387
|
+
* Omitted = unchanged behaviour. */
|
|
388
|
+
accountSwap) {
|
|
382
389
|
const msg = latestMessage || 'Session started — send a message to continue.';
|
|
383
390
|
// If memory is elevated/critical and we have the reaper, try to free memory
|
|
384
391
|
// by cleaning orphans before spawning. Interactive sessions are NEVER blocked
|
|
@@ -619,6 +626,10 @@ async function spawnSessionForTopic(sessionManager, telegram, sessionName, topic
|
|
|
619
626
|
framework,
|
|
620
627
|
...(codexLocalProvider ? { codexLocalProvider } : {}),
|
|
621
628
|
...(codexLocalModelOverride ? { defaultModel: codexLocalModelOverride } : {}),
|
|
629
|
+
// Subscription & Auth Standard P1.3 (additive): account-swap — launch under
|
|
630
|
+
// this account's config home + record its id. Unset = unchanged.
|
|
631
|
+
...(accountSwap?.configHome ? { configHome: accountSwap.configHome } : {}),
|
|
632
|
+
...(accountSwap?.accountId ? { subscriptionAccountId: accountSwap.accountId } : {}),
|
|
622
633
|
});
|
|
623
634
|
// Clear the resume entry after successful spawn to prevent stale reuse
|
|
624
635
|
if (resumeSessionId) {
|
|
@@ -696,7 +707,7 @@ async function respawnSessionForTopic(sessionManager, telegram, targetSession, t
|
|
|
696
707
|
const effectiveMessage = recoveryPrompt
|
|
697
708
|
? `${recoveryPrompt}\n\n${latestMessage || 'Session recovered — continue where you left off.'}`
|
|
698
709
|
: latestMessage;
|
|
699
|
-
const newSessionName = await spawnSessionForTopic(sessionManager, telegram, topicName, topicId, effectiveMessage, topicMemory, userProfile);
|
|
710
|
+
const newSessionName = await spawnSessionForTopic(sessionManager, telegram, topicName, topicId, effectiveMessage, topicMemory, userProfile, undefined, (options?.configHome || options?.accountId) ? { configHome: options?.configHome, accountId: options?.accountId } : undefined);
|
|
700
711
|
telegram.registerTopicSession(topicId, newSessionName, topicName);
|
|
701
712
|
if (!options?.silent) {
|
|
702
713
|
await telegram.sendToTopic(topicId, `Session respawned.`);
|
|
@@ -9261,15 +9272,72 @@ export async function startServer(options) {
|
|
|
9261
9272
|
state,
|
|
9262
9273
|
telegram: telegramRef,
|
|
9263
9274
|
topicResumeMap: _topicResumeMap,
|
|
9264
|
-
respawner: async (sessionName, topicId, followUpPrompt) => {
|
|
9275
|
+
respawner: async (sessionName, topicId, followUpPrompt, accountSwap) => {
|
|
9265
9276
|
// killSession (called inside SessionRefresh) has already fired
|
|
9266
9277
|
// beforeSessionKill (UUID persisted) and destroyed the tmux
|
|
9267
9278
|
// session. respawnSessionForTopic spawns the new tmux running
|
|
9268
9279
|
// `claude --resume <uuid>` and registers the topic mapping.
|
|
9269
|
-
|
|
9280
|
+
// P1.3: accountSwap (when present) re-launches the resume under a
|
|
9281
|
+
// different account's config home — the --resume uuid is account-
|
|
9282
|
+
// agnostic, so the conversation is preserved across the swap.
|
|
9283
|
+
await respawnSessionForTopic(sessionManager, telegramRef, sessionName, topicId, followUpPrompt, topicMemory, undefined, undefined, accountSwap ? { configHome: accountSwap.configHome, accountId: accountSwap.accountId } : undefined);
|
|
9270
9284
|
return telegramRef.getSessionForTopic(topicId) ?? sessionName;
|
|
9271
9285
|
},
|
|
9272
9286
|
});
|
|
9287
|
+
// ── QuotaAwareScheduler (Subscription & Auth Standard P1.3) ──
|
|
9288
|
+
// Selects the optimal account + enforces the continuity guarantee: on
|
|
9289
|
+
// quota pressure it resumes the session under another account (via the
|
|
9290
|
+
// SessionRefresh account-swap path), never letting it die. Auto-trigger
|
|
9291
|
+
// off RateLimitSentinel ships DARK behind a config flag (default off);
|
|
9292
|
+
// the manual route + selection logic are always available.
|
|
9293
|
+
const { QuotaAwareScheduler } = await import('../core/QuotaAwareScheduler.js');
|
|
9294
|
+
_quotaAwareScheduler = new QuotaAwareScheduler({
|
|
9295
|
+
listAccounts: () => subscriptionPool.list(),
|
|
9296
|
+
softThresholdPct: config.subscriptionPool?.swapSoftThresholdPct,
|
|
9297
|
+
refreshFn: async (o) => {
|
|
9298
|
+
if (!_sessionRefresh)
|
|
9299
|
+
return false;
|
|
9300
|
+
const r = await _sessionRefresh.refreshSession({
|
|
9301
|
+
sessionName: o.sessionName,
|
|
9302
|
+
reason: o.reason,
|
|
9303
|
+
configHome: o.configHome,
|
|
9304
|
+
accountId: o.accountId,
|
|
9305
|
+
});
|
|
9306
|
+
return r.ok;
|
|
9307
|
+
},
|
|
9308
|
+
onNoAlternate: (sessionName, exhaustedAccountId) => {
|
|
9309
|
+
void telegramRef.createAttentionItem({
|
|
9310
|
+
id: `subpool-no-alternate-${exhaustedAccountId}`,
|
|
9311
|
+
title: 'Subscription pool — no alternate account to swap to',
|
|
9312
|
+
summary: `Session "${sessionName}" hit account "${exhaustedAccountId}"'s quota and there's no other eligible account in the pool. The session falls back to the existing rate-limit back-off; consider enrolling another account.`,
|
|
9313
|
+
category: 'subscription-pool',
|
|
9314
|
+
priority: 'HIGH',
|
|
9315
|
+
sourceContext: 'subscription-pool:no-alternate',
|
|
9316
|
+
}).catch(() => { });
|
|
9317
|
+
},
|
|
9318
|
+
logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
|
|
9319
|
+
});
|
|
9320
|
+
// DARK auto-trigger: only when explicitly enabled does a rate-limit
|
|
9321
|
+
// escalation drive an account swap. Default off — opt-in per Justin's
|
|
9322
|
+
// tier-2 sign-off (auto-swapping live sessions is real authority).
|
|
9323
|
+
if (config.subscriptionPool?.autoSwapOnRateLimit) {
|
|
9324
|
+
rateLimitSentinel.on('rate-limit:escalated', (rlState) => {
|
|
9325
|
+
const sessionName = rlState?.sessionName;
|
|
9326
|
+
if (!sessionName)
|
|
9327
|
+
return;
|
|
9328
|
+
// Resolve which account this session is running under; only pool-managed
|
|
9329
|
+
// sessions are swap-eligible (others fall back to the existing back-off).
|
|
9330
|
+
const accountId = state.listSessions({ status: 'running' })
|
|
9331
|
+
.find(s => s.tmuxSession === sessionName)?.subscriptionAccountId;
|
|
9332
|
+
if (!accountId)
|
|
9333
|
+
return;
|
|
9334
|
+
void _quotaAwareScheduler?.onQuotaPressure({
|
|
9335
|
+
sessionName,
|
|
9336
|
+
exhaustedAccountId: accountId,
|
|
9337
|
+
nowMs: Date.now(),
|
|
9338
|
+
});
|
|
9339
|
+
});
|
|
9340
|
+
}
|
|
9273
9341
|
}
|
|
9274
9342
|
// ── SessionReaper (SESSION-REAPER-SPEC) ──────────────────────────────
|
|
9275
9343
|
// Pressure-aware reaper of idle-but-alive sessions. Ships OFF + dry-run by
|
|
@@ -11214,7 +11282,7 @@ export async function startServer(options) {
|
|
|
11214
11282
|
catch (err) {
|
|
11215
11283
|
console.log(pc.dim(` [session-pool] rollout gate not wired: ${err instanceof Error ? err.message : String(err)}`));
|
|
11216
11284
|
}
|
|
11217
|
-
const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, quotaPoller, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
|
|
11285
|
+
const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
|
|
11218
11286
|
// Resolve the late-bound topic-operator getter (increment 2e): routing was
|
|
11219
11287
|
// wired before the server existed; from here on inbound binds use the
|
|
11220
11288
|
// server's own store instance.
|