instar 1.3.399 → 1.3.401
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/dashboard/index.html +48 -18
- 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/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.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/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.400.md +55 -0
- package/upgrades/1.3.401.md +30 -0
- package/upgrades/side-effects/dashboard-stream-phase3-ui.md +58 -0
- package/upgrades/side-effects/subscription-auth-scheduler.md +90 -0
package/dashboard/index.html
CHANGED
|
@@ -212,9 +212,11 @@
|
|
|
212
212
|
background: #3a2a1b;
|
|
213
213
|
color: #fbbf24;
|
|
214
214
|
}
|
|
215
|
-
/* A session running on ANOTHER machine —
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
/* A session running on ANOTHER machine — now clickable; selecting it
|
|
216
|
+
streams its terminal here via the cross-machine relay (§2.2). The badge
|
|
217
|
+
already names the machine, so a slightly dimmed row is enough hint. */
|
|
218
|
+
.session-item.remote { opacity: 0.9; cursor: pointer; }
|
|
219
|
+
.session-item.remote:hover { opacity: 1; }
|
|
218
220
|
|
|
219
221
|
.type-badge {
|
|
220
222
|
padding: 1px 6px;
|
|
@@ -3582,6 +3584,7 @@
|
|
|
3582
3584
|
let remoteSessions = [];
|
|
3583
3585
|
let selfMachineNickname = null;
|
|
3584
3586
|
let activeSession = null;
|
|
3587
|
+
let activeMachineId = null; // non-null when the active session streams from a peer (§2.2)
|
|
3585
3588
|
let term = null;
|
|
3586
3589
|
let fitAddon = null;
|
|
3587
3590
|
let historyLinesLoaded = 2000; // matches initial subscribe capture
|
|
@@ -3677,6 +3680,12 @@
|
|
|
3677
3680
|
ws.onopen = () => {
|
|
3678
3681
|
reconnectAttempts = 0;
|
|
3679
3682
|
updateConnectionStatus(true);
|
|
3683
|
+
// Resubscribe the active session after a (re)connect so a server
|
|
3684
|
+
// restart doesn't strand the terminal (§2.5). Remote sessions carry
|
|
3685
|
+
// their machineId so the resubscribe re-opens the relay.
|
|
3686
|
+
if (activeSession) {
|
|
3687
|
+
wsSend({ type: 'subscribe', session: activeSession, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
|
|
3688
|
+
}
|
|
3680
3689
|
};
|
|
3681
3690
|
|
|
3682
3691
|
ws.onclose = () => {
|
|
@@ -3768,7 +3777,21 @@
|
|
|
3768
3777
|
break;
|
|
3769
3778
|
|
|
3770
3779
|
case 'error':
|
|
3771
|
-
|
|
3780
|
+
// Pool Dashboard Streaming (§2.4): every remote-stream failure state
|
|
3781
|
+
// is shown honestly in the terminal — never a frozen/black screen or
|
|
3782
|
+
// a silent swallow. Only surface errors for the session in view.
|
|
3783
|
+
if (msg.code && term && (msg.session === activeSession || !msg.session)) {
|
|
3784
|
+
const m = {
|
|
3785
|
+
'machine-unreachable': '\r\n\x1b[31m--- That machine is unreachable. ---\x1b[0m\r\n',
|
|
3786
|
+
'peer-stream-lost': '\r\n\x1b[33m--- Stream lost — reconnecting… ---\x1b[0m\r\n',
|
|
3787
|
+
'input-not-allowed': '\r\n\x1b[33m[remote typing is disabled on this machine — turn it on in that machine\'s settings]\x1b[0m\r\n',
|
|
3788
|
+
'session-transferred': `\r\n\x1b[33m--- This session moved to ${msg.newMachineId || 'another machine'} — reselect it to follow. ---\x1b[0m\r\n`,
|
|
3789
|
+
'invalid-session': '\r\n\x1b[31m--- Invalid session name. ---\x1b[0m\r\n',
|
|
3790
|
+
'session-not-found': '\r\n\x1b[31m--- Session not found on that machine. ---\x1b[0m\r\n',
|
|
3791
|
+
}[msg.code];
|
|
3792
|
+
if (m) { term.write(m); break; }
|
|
3793
|
+
}
|
|
3794
|
+
console.error('[ws]', msg.code || msg.message);
|
|
3772
3795
|
break;
|
|
3773
3796
|
}
|
|
3774
3797
|
}
|
|
@@ -3845,13 +3868,12 @@
|
|
|
3845
3868
|
el = document.createElement('div');
|
|
3846
3869
|
el.className = 'session-item';
|
|
3847
3870
|
el.dataset.session = sessionRowKey(session);
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
}
|
|
3871
|
+
// Pool Dashboard Streaming (§2.2): remote sessions are now clickable —
|
|
3872
|
+
// selecting one streams it from its owning machine via the relay.
|
|
3873
|
+
el.title = session.remote
|
|
3874
|
+
? `Running on ${session.machineNickname || session.machineId || 'another machine'} — click to stream it here.`
|
|
3875
|
+
: '';
|
|
3876
|
+
el.onclick = () => selectSession(session.tmuxSession, session);
|
|
3855
3877
|
list.appendChild(el);
|
|
3856
3878
|
}
|
|
3857
3879
|
|
|
@@ -3912,11 +3934,13 @@
|
|
|
3912
3934
|
|
|
3913
3935
|
// ── Terminal ──────────────────────────────────────────────
|
|
3914
3936
|
function selectSession(tmuxSession, session) {
|
|
3915
|
-
// Unsubscribe from previous
|
|
3937
|
+
// Unsubscribe from previous (carry its machineId so a remote unsub routes).
|
|
3916
3938
|
if (activeSession) {
|
|
3917
|
-
wsSend({ type: 'unsubscribe', session: activeSession });
|
|
3939
|
+
wsSend({ type: 'unsubscribe', session: activeSession, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
|
|
3918
3940
|
}
|
|
3919
3941
|
|
|
3942
|
+
// Pool Dashboard Streaming (§2.2): a remote session streams from its owner.
|
|
3943
|
+
activeMachineId = session.remote ? (session.machineId || null) : null;
|
|
3920
3944
|
activeSession = tmuxSession;
|
|
3921
3945
|
userIsFollowing = true; // Reset scroll tracking on session switch
|
|
3922
3946
|
hideResumeButton(); // Carry-over button from prior session would be misleading
|
|
@@ -3958,9 +3982,12 @@
|
|
|
3958
3982
|
initTerminal();
|
|
3959
3983
|
}
|
|
3960
3984
|
|
|
3961
|
-
// Clear and subscribe
|
|
3985
|
+
// Clear and subscribe (remote → carry machineId so the server relays).
|
|
3962
3986
|
term.clear();
|
|
3963
|
-
|
|
3987
|
+
if (activeMachineId) {
|
|
3988
|
+
term.write(`\x1b[2m[streaming from ${session.machineNickname || activeMachineId}…]\x1b[0m\r\n`);
|
|
3989
|
+
}
|
|
3990
|
+
wsSend({ type: 'subscribe', session: tmuxSession, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
|
|
3964
3991
|
|
|
3965
3992
|
// Update active state in sidebar
|
|
3966
3993
|
renderSessionList();
|
|
@@ -4203,25 +4230,28 @@
|
|
|
4203
4230
|
}
|
|
4204
4231
|
|
|
4205
4232
|
// ── Input ────────────────────────────────────────────────
|
|
4233
|
+
// Remote sessions carry machineId so the server relays input to the owner
|
|
4234
|
+
// (which enforces its own allowRemoteInput gate; a refusal returns an
|
|
4235
|
+
// input-not-allowed error frame, surfaced in the terminal — never silent).
|
|
4206
4236
|
function sendInput() {
|
|
4207
4237
|
const input = document.getElementById('termInput');
|
|
4208
4238
|
const text = input.value;
|
|
4209
4239
|
if (!text || !activeSession) return;
|
|
4210
4240
|
|
|
4211
|
-
wsSend({ type: 'input', session: activeSession, text });
|
|
4241
|
+
wsSend({ type: 'input', session: activeSession, text, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
|
|
4212
4242
|
input.value = '';
|
|
4213
4243
|
input.focus();
|
|
4214
4244
|
}
|
|
4215
4245
|
|
|
4216
4246
|
function sendKey(key) {
|
|
4217
4247
|
if (!activeSession) return;
|
|
4218
|
-
wsSend({ type: 'key', session: activeSession, key });
|
|
4248
|
+
wsSend({ type: 'key', session: activeSession, key, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
|
|
4219
4249
|
}
|
|
4220
4250
|
|
|
4221
4251
|
function sendSpecial(text) {
|
|
4222
4252
|
if (!activeSession) return;
|
|
4223
4253
|
// Send literal text without Enter
|
|
4224
|
-
wsSend({ type: 'key', session: activeSession, key: text });
|
|
4254
|
+
wsSend({ type: 'key', session: activeSession, key: text, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
|
|
4225
4255
|
}
|
|
4226
4256
|
|
|
4227
4257
|
// ── New Session Modal ────────────────────────────────────
|
|
@@ -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.
|