instar 1.2.81 → 1.2.83
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 +110 -11
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +23 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +7 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +59 -75
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +43 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +123 -24
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/types.d.ts +26 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +153 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -0
- package/dist/monitoring/SessionReaper.js +376 -0
- package/dist/monitoring/SessionReaper.js.map +1 -0
- package/dist/monitoring/TokenLedger.d.ts +12 -0
- package/dist/monitoring/TokenLedger.d.ts.map +1 -1
- package/dist/monitoring/TokenLedger.js +22 -0
- package/dist/monitoring/TokenLedger.js.map +1 -1
- package/dist/monitoring/transcriptProber.d.ts +44 -0
- package/dist/monitoring/transcriptProber.d.ts.map +1 -0
- package/dist/monitoring/transcriptProber.js +57 -0
- package/dist/monitoring/transcriptProber.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +21 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +3 -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 +3 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +108 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/CollaborationSurfacer.d.ts +67 -18
- package/dist/threadline/CollaborationSurfacer.d.ts.map +1 -1
- package/dist/threadline/CollaborationSurfacer.js +132 -37
- package/dist/threadline/CollaborationSurfacer.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +21 -0
- package/upgrades/1.2.81.md +13 -0
- package/upgrades/1.2.82.md +26 -0
- package/upgrades/1.2.83.md +26 -0
- package/upgrades/side-effects/1.2.81.md +127 -0
- package/upgrades/side-effects/session-reaper.md +42 -0
- package/upgrades/side-effects/threadline-notification-routing.md +46 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0QH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiqDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0QH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiqDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6pMtE;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
|
@@ -4874,6 +4874,12 @@ export async function startServer(options) {
|
|
|
4874
4874
|
// is OFF for Telegram by default and, when enabled, coalesces into ONE
|
|
4875
4875
|
// consolidated message to the existing system topic. No new-topic-per-event.
|
|
4876
4876
|
// Spec: docs/specs/silently-stopped-trio.md.
|
|
4877
|
+
//
|
|
4878
|
+
// Captured out of the trio block so the SessionReaper's recovery veto can
|
|
4879
|
+
// compose socket + silence in too (SESSION-REAPER-SPEC §4 "compose, don't
|
|
4880
|
+
// replace"). undefined when the corresponding sentinel is disabled.
|
|
4881
|
+
let socketRecoveryActive;
|
|
4882
|
+
let silenceRecoveryActive;
|
|
4877
4883
|
{
|
|
4878
4884
|
const { SocketDisconnectSentinel } = await import('../monitoring/SocketDisconnectSentinel.js');
|
|
4879
4885
|
const { ActiveWorkSilenceSentinel } = await import('../monitoring/ActiveWorkSilenceSentinel.js');
|
|
@@ -4926,6 +4932,7 @@ export async function startServer(options) {
|
|
|
4926
4932
|
socketSentinel.on('recovered', (n) => notifier.record('recovered', 'socket-disconnect', n));
|
|
4927
4933
|
socketSentinel.on('recovery-error', (e) => notifier.record('recovery-error', 'socket-disconnect', e.sessionName, e.err instanceof Error ? e.err.message : String(e.err)));
|
|
4928
4934
|
socketSentinel.start();
|
|
4935
|
+
socketRecoveryActive = (s) => socketSentinel.isRecoveryActive(s);
|
|
4929
4936
|
console.log(pc.green(' SocketDisconnectSentinel enabled (connection-drop recovery)'));
|
|
4930
4937
|
}
|
|
4931
4938
|
const silenceCfg = config.monitoring?.activeWorkSilenceSentinel ?? { enabled: true };
|
|
@@ -4939,11 +4946,23 @@ export async function startServer(options) {
|
|
|
4939
4946
|
silenceSentinel.on('recovered', (n) => notifier.record('recovered', 'active-silence', n));
|
|
4940
4947
|
silenceSentinel.on('nudge-error', (e) => notifier.record('nudge-error', 'active-silence', e.sessionName, e.err instanceof Error ? e.err.message : String(e.err)));
|
|
4941
4948
|
silenceSentinel.start();
|
|
4949
|
+
silenceRecoveryActive = (s) => silenceSentinel.isRecoveryActive(s);
|
|
4942
4950
|
console.log(pc.green(telegramEscalation
|
|
4943
4951
|
? ' ActiveWorkSilenceSentinel enabled (silent-freeze watchdog — Telegram escalation ON, consolidated)'
|
|
4944
4952
|
: ' ActiveWorkSilenceSentinel enabled (silent-freeze watchdog — logs only, Telegram escalation OFF)'));
|
|
4945
4953
|
}
|
|
4946
4954
|
}
|
|
4955
|
+
// Recompose the zombie-kill veto to include ALL four recovery sentinels now
|
|
4956
|
+
// that socket + silence exist (the interim set above covered only compaction
|
|
4957
|
+
// + rate-limit, before those two were constructed). This single composed
|
|
4958
|
+
// predicate is the superset — it drops none — and is reused as the
|
|
4959
|
+
// SessionReaper's recovery gate (G) so the reaper never kills a session any
|
|
4960
|
+
// sentinel is reviving. SESSION-REAPER-SPEC §4 "compose, don't replace".
|
|
4961
|
+
const composedRecoveryActive = (session) => compactionSentinel.isRecoveryActive(session.tmuxSession) ||
|
|
4962
|
+
rateLimitSentinel.isRecoveryActive(session.tmuxSession) ||
|
|
4963
|
+
(socketRecoveryActive?.(session.tmuxSession) ?? false) ||
|
|
4964
|
+
(silenceRecoveryActive?.(session.tmuxSession) ?? false);
|
|
4965
|
+
sessionManager.setActiveRecoveryChecker(composedRecoveryActive);
|
|
4947
4966
|
// Trigger 1: PreCompact hook event — report to sentinel.
|
|
4948
4967
|
hookEventReceiver.on('PreCompact', () => {
|
|
4949
4968
|
// Delay to let compaction + recovery hooks finish
|
|
@@ -6632,16 +6651,17 @@ export async function startServer(options) {
|
|
|
6632
6651
|
});
|
|
6633
6652
|
if (decision.suppress) {
|
|
6634
6653
|
console.log(`[relay] warrants-reply gate suppressed reply (${decision.verdict.signal}) for ${senderName} thread ${gateThreadId.slice(0, 8)}`);
|
|
6635
|
-
// On budget exhaustion,
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6654
|
+
// On budget exhaustion, surface ONE status notice — never silently
|
|
6655
|
+
// drop. CMT-519: route it to the SILENT Threadline hub (not a
|
|
6656
|
+
// per-event attention topic, not the parent topic the operator is
|
|
6657
|
+
// working in). This is housekeeping, not a user task.
|
|
6658
|
+
if (decision.verdict.budgetExhausted && collaborationSurfacer) {
|
|
6659
|
+
void collaborationSurfacer.notify({
|
|
6660
|
+
threadId: gateThreadId,
|
|
6661
|
+
title: 'Conversation loop paused',
|
|
6662
|
+
body: `Stopped auto-replying to a thread with ${senderName} that kept going with no new content (thread ${gateThreadId.slice(0, 8)}). Say "re-engage" in this topic if you want me to pick it back up.`,
|
|
6663
|
+
peerName: senderName,
|
|
6664
|
+
}).catch(escErr => console.warn(`[relay] loop-gate hub notice failed: ${escErr instanceof Error ? escErr.message : escErr}`));
|
|
6645
6665
|
}
|
|
6646
6666
|
return; // short-circuit ALL three routing branches
|
|
6647
6667
|
}
|
|
@@ -7192,7 +7212,86 @@ export async function startServer(options) {
|
|
|
7192
7212
|
},
|
|
7193
7213
|
});
|
|
7194
7214
|
}
|
|
7195
|
-
|
|
7215
|
+
// ── SessionReaper (SESSION-REAPER-SPEC) ──────────────────────────────
|
|
7216
|
+
// Pressure-aware reaper of idle-but-alive sessions. Ships OFF + dry-run by
|
|
7217
|
+
// default; the classifier's positive-evidence + confidence-contract is what
|
|
7218
|
+
// guarantees it never reaps a working session. Reuses composedRecoveryActive
|
|
7219
|
+
// (gate G) so it defers to every recovery sentinel. Pressure is freemem-tiered
|
|
7220
|
+
// for v1 (advisory; spawn-denial-primary is a tracked follow-up) — and note
|
|
7221
|
+
// an over-eager tier can only reap a GENUINELY-idle session sooner, never a
|
|
7222
|
+
// working one (the classifier protects working sessions regardless of tier).
|
|
7223
|
+
const { SessionReaper, fileAuditSink } = await import('../monitoring/SessionReaper.js');
|
|
7224
|
+
const _os = await import('node:os');
|
|
7225
|
+
const _resolveTopic = (tmuxSession) => {
|
|
7226
|
+
const t = telegram?.getTopicForSession(tmuxSession);
|
|
7227
|
+
if (t == null)
|
|
7228
|
+
return null;
|
|
7229
|
+
const n = typeof t === 'number' ? t : Number(t);
|
|
7230
|
+
return Number.isFinite(n) ? n : null;
|
|
7231
|
+
};
|
|
7232
|
+
const sessionReaper = new SessionReaper({
|
|
7233
|
+
listRunningSessions: () => sessionManager.listRunningSessions(),
|
|
7234
|
+
captureOutput: (s, n) => sessionManager.captureOutput(s, n) ?? '',
|
|
7235
|
+
hasActiveProcesses: (s) => sessionManager.hasActiveProcesses(s),
|
|
7236
|
+
frameworkForSession: (s) => sessionManager.frameworkForSession(s),
|
|
7237
|
+
isRecoveryActive: (session) => composedRecoveryActive(session),
|
|
7238
|
+
isRelayLeaseActive: (id) => sessionManager.isRelayLeaseActive(id),
|
|
7239
|
+
hasPendingInjection: (s) => sessionManager.getPendingInjection(s) != null,
|
|
7240
|
+
topicBinding: _resolveTopic,
|
|
7241
|
+
// Gate I is a v1 stub (returns false): active conversation is already
|
|
7242
|
+
// covered by the relay-lease + pending-injection gates and by render
|
|
7243
|
+
// stasis (a session being talked to is not render-static for the full
|
|
7244
|
+
// hysteresis+threshold window). Promoting to a real message-recency
|
|
7245
|
+
// query is a tracked tuning follow-up.
|
|
7246
|
+
recentUserMessage: () => false,
|
|
7247
|
+
activeCommitmentForTopic: (topicId) => {
|
|
7248
|
+
try {
|
|
7249
|
+
return commitmentTracker.getActive().some(c => c.topicId === topicId);
|
|
7250
|
+
}
|
|
7251
|
+
catch {
|
|
7252
|
+
return true;
|
|
7253
|
+
} // cannot tell → protect
|
|
7254
|
+
},
|
|
7255
|
+
activeSubagentCount: (csid) => {
|
|
7256
|
+
try {
|
|
7257
|
+
return csid ? subagentTracker.getActiveSubagents(csid).length : 0;
|
|
7258
|
+
}
|
|
7259
|
+
catch {
|
|
7260
|
+
return 1;
|
|
7261
|
+
} // cannot tell → protect
|
|
7262
|
+
},
|
|
7263
|
+
buildOrAutonomousActive: (topicId) => {
|
|
7264
|
+
const fresh = (p) => {
|
|
7265
|
+
try {
|
|
7266
|
+
return fs.existsSync(p) && (Date.now() - fs.statSync(p).mtimeMs) < 30 * 60_000;
|
|
7267
|
+
}
|
|
7268
|
+
catch {
|
|
7269
|
+
return false;
|
|
7270
|
+
}
|
|
7271
|
+
};
|
|
7272
|
+
if (topicId != null && fresh(path.join(config.stateDir, 'autonomous', `${topicId}.local.md`)))
|
|
7273
|
+
return true;
|
|
7274
|
+
return fresh(path.join(config.stateDir, 'state', 'build', 'build-state.json'));
|
|
7275
|
+
},
|
|
7276
|
+
protectedSessions: () => sessionManager.getProtectedSessions(),
|
|
7277
|
+
pressure: () => {
|
|
7278
|
+
const total = _os.totalmem();
|
|
7279
|
+
const freePct = total > 0 ? (_os.freemem() / total) * 100 : 100;
|
|
7280
|
+
const tier = freePct < 5 ? 'critical' : freePct < 12 ? 'moderate' : 'normal';
|
|
7281
|
+
return { tier, inputs: { freePct: Math.round(freePct * 10) / 10 } };
|
|
7282
|
+
},
|
|
7283
|
+
terminate: (id, reason) => sessionManager.terminateSession(id, reason),
|
|
7284
|
+
markReaping: (id) => sessionManager.markReaping(id),
|
|
7285
|
+
clearReaping: (id) => sessionManager.clearReaping(id),
|
|
7286
|
+
audit: fileAuditSink(config.stateDir),
|
|
7287
|
+
}, config.monitoring?.sessionReaper);
|
|
7288
|
+
sessionReaper.start();
|
|
7289
|
+
if (config.monitoring?.sessionReaper?.enabled) {
|
|
7290
|
+
console.log(pc.green(config.monitoring.sessionReaper.dryRun === false
|
|
7291
|
+
? ' SessionReaper enabled (idle-session reaper — LIVE)'
|
|
7292
|
+
: ' SessionReaper enabled (idle-session reaper — dry-run, logs only)'));
|
|
7293
|
+
}
|
|
7294
|
+
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, semanticMemory, activitySentinel, rateLimitSentinel, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, 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, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, proxyCoordinator, topicIntentStore, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper });
|
|
7196
7295
|
// Boot-recovery (tunnel-failure-resilience spec Part 6): if the agent
|
|
7197
7296
|
// died mid-relay-episode, the persisted tunnel.json carries
|
|
7198
7297
|
// rotationPending=true. Rotate the dashboard PIN + authToken BEFORE
|