instar 1.3.605 → 1.3.607
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 +140 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +29 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/coordination/CrossMachineMandate.d.ts +53 -0
- package/dist/coordination/CrossMachineMandate.d.ts.map +1 -0
- package/dist/coordination/CrossMachineMandate.js +76 -0
- package/dist/coordination/CrossMachineMandate.js.map +1 -0
- package/dist/core/AccountCredentialShare.d.ts +115 -0
- package/dist/core/AccountCredentialShare.d.ts.map +1 -0
- package/dist/core/AccountCredentialShare.js +113 -0
- package/dist/core/AccountCredentialShare.js.map +1 -0
- package/dist/core/AccountFollowMeGrants.d.ts +92 -0
- package/dist/core/AccountFollowMeGrants.d.ts.map +1 -0
- package/dist/core/AccountFollowMeGrants.js +106 -0
- package/dist/core/AccountFollowMeGrants.js.map +1 -0
- package/dist/core/AutonomousSessions.d.ts +24 -0
- package/dist/core/AutonomousSessions.d.ts.map +1 -1
- package/dist/core/AutonomousSessions.js +22 -0
- package/dist/core/AutonomousSessions.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +12 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/PairingEpochManager.d.ts +68 -0
- package/dist/core/PairingEpochManager.d.ts.map +1 -0
- package/dist/core/PairingEpochManager.js +88 -0
- package/dist/core/PairingEpochManager.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts +13 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +105 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SecretStore.d.ts +44 -0
- package/dist/core/SecretStore.d.ts.map +1 -1
- package/dist/core/SecretStore.js +126 -0
- package/dist/core/SecretStore.js.map +1 -1
- package/dist/core/SecretSync.d.ts.map +1 -1
- package/dist/core/SecretSync.js +6 -0
- package/dist/core/SecretSync.js.map +1 -1
- package/dist/core/SubscriptionAccountMetaReplicatedStore.d.ts +106 -0
- package/dist/core/SubscriptionAccountMetaReplicatedStore.d.ts.map +1 -0
- package/dist/core/SubscriptionAccountMetaReplicatedStore.js +263 -0
- package/dist/core/SubscriptionAccountMetaReplicatedStore.js.map +1 -0
- package/dist/core/SubscriptionPool.d.ts +23 -5
- package/dist/core/SubscriptionPool.d.ts.map +1 -1
- package/dist/core/SubscriptionPool.js +30 -6
- package/dist/core/SubscriptionPool.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +12 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +29 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/AutonomousProgressHeartbeat.d.ts +169 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.d.ts.map +1 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.js +296 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.js.map +1 -0
- package/dist/monitoring/ProxyCoordinator.d.ts +1 -1
- package/dist/monitoring/ProxyCoordinator.d.ts.map +1 -1
- package/dist/monitoring/autonomousHeartbeatScrub.d.ts +44 -0
- package/dist/monitoring/autonomousHeartbeatScrub.d.ts.map +1 -0
- package/dist/monitoring/autonomousHeartbeatScrub.js +81 -0
- package/dist/monitoring/autonomousHeartbeatScrub.js.map +1 -0
- package/dist/monitoring/sentinelWiring.d.ts +14 -0
- package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
- package/dist/monitoring/sentinelWiring.js +19 -0
- package/dist/monitoring/sentinelWiring.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +10 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +9 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +15 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +10 -0
- package/upgrades/1.3.606.md +28 -0
- package/upgrades/1.3.607.md +25 -0
- package/upgrades/side-effects/autonomous-progress-heartbeat-ratchet-fix.md +36 -0
- package/upgrades/side-effects/autonomous-progress-heartbeat.md +40 -0
- package/upgrades/side-effects/ws52-account-follow-me-pr1.md +74 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAsBtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,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,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,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;AAoCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAsBtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,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,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ietE;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
|
@@ -3440,6 +3440,17 @@ export async function startServer(options) {
|
|
|
3440
3440
|
// verification-failed propagates as a tombstone (ThreadlinePairingReplicatedStore).
|
|
3441
3441
|
const { THREADLINE_PAIRING_KIND_REGISTRATION } = await import('../core/ThreadlinePairingReplicatedStore.js');
|
|
3442
3442
|
replicatedKindRegistry.register(THREADLINE_PAIRING_KIND_REGISTRATION);
|
|
3443
|
+
// WS5.2 Account Follow-Me §6.1a — register the `subscription-account-meta` kind onto the
|
|
3444
|
+
// registry: registry follow-me = METADATA ONLY (a redacted, credential-free projection of a
|
|
3445
|
+
// SubscriptionAccount; configHome + every credential field STRIPPED). Dual-registry's dynamic
|
|
3446
|
+
// half (the static half is CoherenceJournal.JOURNAL_KINDS, which now lists
|
|
3447
|
+
// 'subscription-account-meta'). Registration is INERT — emission/serve/pull stay gated behind
|
|
3448
|
+
// `multiMachine.accountFollowMe.enabled` (default false ⇒ strict no-op, NO account metadata
|
|
3449
|
+
// crosses a machine boundary). The recordKey is the account id (charset-clamped). This kind
|
|
3450
|
+
// carries NO login: the credential half is the SEPARATE account-credential-share verb +
|
|
3451
|
+
// re-mint-per-machine default (Mechanism B); see ws52-account-follow-me-security.md.
|
|
3452
|
+
const { SUBSCRIPTION_ACCOUNT_META_KIND_REGISTRATION } = await import('../core/SubscriptionAccountMetaReplicatedStore.js');
|
|
3453
|
+
replicatedKindRegistry.register(SUBSCRIPTION_ACCOUNT_META_KIND_REGISTRATION);
|
|
3443
3454
|
// ── WS2 SEND-SIDE wiring (docs/specs/WS2-SEND-SIDE-EMISSION-SPEC.md). The
|
|
3444
3455
|
// substrate above ships the registry + receive/serve machinery + advert; THIS
|
|
3445
3456
|
// wires the SEND half that was deferred ("the journal-backed emitter is attached
|
|
@@ -3542,7 +3553,17 @@ export async function startServer(options) {
|
|
|
3542
3553
|
// `enabled` is already the resolved boolean — the funnels keep their unchanged
|
|
3543
3554
|
// `enabled === true` semantics but now see a live flag on a dev agent. An explicit
|
|
3544
3555
|
// operator `enabled` in config still wins (force-dark false / fleet-flip true).
|
|
3545
|
-
const
|
|
3556
|
+
const _stateSyncStoresBase = resolveStateSyncStores(config);
|
|
3557
|
+
// WS5.2 §6.1a — the `subscriptionAccountMeta` store gates on `multiMachine.accountFollowMe`
|
|
3558
|
+
// (NOT a `stateSync.*` flag). Inject its dev-gate-resolved enabled-state into the SAME
|
|
3559
|
+
// store-flags map the generic emitter + receive-advert consult, so account-meta emission +
|
|
3560
|
+
// the receive capability gate on accountFollowMe (dev-live / fleet-dark) coherently. When the
|
|
3561
|
+
// gate resolves OFF the entry is absent ⇒ the emitter's `enabled===true` check fails ⇒ strict
|
|
3562
|
+
// no-op (no account metadata ever crosses), exactly like the dark stateSync stores.
|
|
3563
|
+
const _accountFollowMeEnabled = resolveDevAgentGate(config.multiMachine?.accountFollowMe?.enabled, config);
|
|
3564
|
+
const _stateSyncStoresResolved = _accountFollowMeEnabled
|
|
3565
|
+
? { ...(_stateSyncStoresBase ?? {}), subscriptionAccountMeta: { enabled: true } }
|
|
3566
|
+
: _stateSyncStoresBase;
|
|
3546
3567
|
// WS2 send-side: the generic journal-backed record emitter (the concrete emitter
|
|
3547
3568
|
// the per-store managers' emit hooks call). Needs the journal sink, the HLC clock,
|
|
3548
3569
|
// the registry (store → kind), this machine's origin id, the resolved stateSync
|
|
@@ -8841,6 +8862,11 @@ export async function startServer(options) {
|
|
|
8841
8862
|
let socketRecoveryActive;
|
|
8842
8863
|
let silenceRecoveryActive;
|
|
8843
8864
|
let wedgeRecoveryActive;
|
|
8865
|
+
// Lifted out of the trio block so AutonomousProgressHeartbeat (wired later,
|
|
8866
|
+
// near PromiseBeacon) can read ActiveWorkSilenceSentinel's ALREADY-COMPUTED
|
|
8867
|
+
// lastOutputAt snapshot (predicate #8 — a shared/cached read, never its own
|
|
8868
|
+
// tmux capture). undefined when the silence sentinel is disabled.
|
|
8869
|
+
let sharedOutputTracker;
|
|
8844
8870
|
{
|
|
8845
8871
|
const { SocketDisconnectSentinel } = await import('../monitoring/SocketDisconnectSentinel.js');
|
|
8846
8872
|
const { ActiveWorkSilenceSentinel } = await import('../monitoring/ActiveWorkSilenceSentinel.js');
|
|
@@ -8894,6 +8920,9 @@ export async function startServer(options) {
|
|
|
8894
8920
|
const silenceCfg = config.monitoring?.activeWorkSilenceSentinel ?? { enabled: true };
|
|
8895
8921
|
if (silenceCfg.enabled !== false) {
|
|
8896
8922
|
const tracker = new OutputActivityTracker(sessionSurface);
|
|
8923
|
+
// Share this tracker's snapshot with AutonomousProgressHeartbeat
|
|
8924
|
+
// (predicate #8 reads its lastOutputAt — never its own capture).
|
|
8925
|
+
sharedOutputTracker = tracker;
|
|
8897
8926
|
// Auto-heal ladder (DARK, off by default): when a confirmed-silent session
|
|
8898
8927
|
// can't be nudged back, respawn it fresh (conversation preserved via
|
|
8899
8928
|
// --resume) instead of only asking the user. Gated by autoRecover; the
|
|
@@ -9220,6 +9249,20 @@ export async function startServer(options) {
|
|
|
9220
9249
|
if (subscriptionPool.size() > 0) {
|
|
9221
9250
|
console.log(pc.green(` Subscription pool: ${subscriptionPool.size()} account(s) registered`));
|
|
9222
9251
|
}
|
|
9252
|
+
// WS5.2 §6.1a — wire cross-machine registry follow-me (METADATA ONLY). When the generic
|
|
9253
|
+
// record emitter exists AND accountFollowMe resolves enabled (the entry was injected into
|
|
9254
|
+
// _stateSyncStoresResolved above), attach the emit adapter so an account add/status/quota
|
|
9255
|
+
// change/remove replicates a REDACTED projection (projectAccountToMeta strips configHome +
|
|
9256
|
+
// every credential field by allowlist). The emitter itself re-checks the store-flag gate, so
|
|
9257
|
+
// a dark/fleet agent is a strict no-op even if the adapter is attached. NO login crosses.
|
|
9258
|
+
if (replicatedRecordEmitter && _accountFollowMeEnabled) {
|
|
9259
|
+
const emitter = replicatedRecordEmitter;
|
|
9260
|
+
const { SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey, buildSubscriptionAccountMetaData, buildSubscriptionAccountMetaTombstoneData, } = await import('../core/SubscriptionAccountMetaReplicatedStore.js');
|
|
9261
|
+
subscriptionPool.setMetaReplicationEmitter({
|
|
9262
|
+
emitPut: (acct) => emitter.emit(SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey(acct.id), (hlc, origin, observed) => buildSubscriptionAccountMetaData({ account: acct, hlc, origin, observed })),
|
|
9263
|
+
emitDelete: (accountId, deletedAt) => emitter.emit(SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey(accountId), (hlc, origin, observed) => buildSubscriptionAccountMetaTombstoneData({ accountId, hlc, origin, deletedAt, observed })),
|
|
9264
|
+
});
|
|
9265
|
+
}
|
|
9223
9266
|
// POOL-AWARE QUOTA THROTTLE wiring (docs/specs/POOL-AWARE-QUOTA-THROTTLE-SPEC.md):
|
|
9224
9267
|
// give the global quota brake the SAME placeability predicate the placement layer
|
|
9225
9268
|
// (selectAccount) uses, reading the LIVE SubscriptionPool. Effect: the brake never
|
|
@@ -10404,6 +10447,102 @@ export async function startServer(options) {
|
|
|
10404
10447
|
});
|
|
10405
10448
|
promiseBeacon.start();
|
|
10406
10449
|
globalThis.__instarPromiseBeacon = promiseBeacon;
|
|
10450
|
+
// ── AutonomousProgressHeartbeat ──────────────────────────────────
|
|
10451
|
+
// Hedged, change-gated, sparse liveness BACKSTOP for an autonomous run
|
|
10452
|
+
// gone silent-to-user while its terminal output is STILL changing. NOT
|
|
10453
|
+
// the suppressed PromiseBeacon §B1 filler — much higher bar (long
|
|
10454
|
+
// user-silence gate + corroborated recent output change from
|
|
10455
|
+
// ActiveWorkSilenceSentinel's shared snapshot + per-topic cooldown +
|
|
10456
|
+
// widening per-run backoff + hard cap + the shared one-voice lease).
|
|
10457
|
+
// DEV-GATED dark: enabled via resolveDevAgentGate (LIVE on a dev agent,
|
|
10458
|
+
// DARK on the fleet); dryRun defaults true (would-emit log, no send).
|
|
10459
|
+
// Spec: docs/specs/autonomous-progress-heartbeat.md.
|
|
10460
|
+
try {
|
|
10461
|
+
const ahRawCfg = config.monitoring?.autonomousHeartbeat ?? {};
|
|
10462
|
+
const ahEnabled = resolveDevAgentGate(ahRawCfg.enabled, config);
|
|
10463
|
+
if (ahEnabled && telegram) {
|
|
10464
|
+
const { AutonomousProgressHeartbeat } = await import('../monitoring/AutonomousProgressHeartbeat.js');
|
|
10465
|
+
const { activeAutonomousJobs, autonomousRunRemainingForTopic, readAutonomousRunMarkers, } = await import('../core/AutonomousSessions.js');
|
|
10466
|
+
const { ParallelActivityIndex: AHParallelActivityIndex } = await import('../core/ParallelActivityIndex.js');
|
|
10467
|
+
// Own ParallelActivityIndex (focus source) — fetched ONCE per tick
|
|
10468
|
+
// and indexed by topic inside the deps closure.
|
|
10469
|
+
const ahActivityIndex = new AHParallelActivityIndex({ stateDir: config.stateDir });
|
|
10470
|
+
const localTelegram2 = telegram;
|
|
10471
|
+
const autonomousHeartbeat = new AutonomousProgressHeartbeat({
|
|
10472
|
+
listActiveAutonomousRuns: () => {
|
|
10473
|
+
const out = [];
|
|
10474
|
+
const now = Date.now();
|
|
10475
|
+
for (const job of activeAutonomousJobs(config.stateDir)) {
|
|
10476
|
+
if (job.topic == null)
|
|
10477
|
+
continue; // legacy single-file job has no topic
|
|
10478
|
+
const remaining = autonomousRunRemainingForTopic(config.stateDir, job.topic, now);
|
|
10479
|
+
if (!remaining)
|
|
10480
|
+
continue;
|
|
10481
|
+
const topicId = Number(job.topic);
|
|
10482
|
+
if (!Number.isFinite(topicId))
|
|
10483
|
+
continue;
|
|
10484
|
+
out.push({
|
|
10485
|
+
topicId,
|
|
10486
|
+
sessionName: localTelegram2.getSessionForTopic(topicId) ?? null,
|
|
10487
|
+
remainingSeconds: remaining.remainingSeconds,
|
|
10488
|
+
});
|
|
10489
|
+
}
|
|
10490
|
+
return out;
|
|
10491
|
+
},
|
|
10492
|
+
getRunMarkers: (topicId) => readAutonomousRunMarkers(config.stateDir, topicId),
|
|
10493
|
+
isSessionAlive: (name) => sessionManager.isSessionAlive(name),
|
|
10494
|
+
getTopicHistory: (topicId) => localTelegram2.getTopicHistory(topicId, 50).map((e) => ({
|
|
10495
|
+
fromUser: e.fromUser,
|
|
10496
|
+
at: new Date(e.timestamp).getTime(),
|
|
10497
|
+
})),
|
|
10498
|
+
// Predicate #8 — read ActiveWorkSilenceSentinel's ALREADY-computed
|
|
10499
|
+
// snapshot (the shared OutputActivityTracker). NEVER a capture.
|
|
10500
|
+
// undefined when the silence sentinel is disabled → fails closed.
|
|
10501
|
+
getSharedLastOutputAt: (name) => sharedOutputTracker ? sharedOutputTracker.lastOutputAtFor(name) : null,
|
|
10502
|
+
getFocusForTopic: (() => {
|
|
10503
|
+
// Index the cross-topic activities ONCE per tick (O(1)/topic).
|
|
10504
|
+
let cachedAt = 0;
|
|
10505
|
+
let cache = new Map();
|
|
10506
|
+
return (topicId) => {
|
|
10507
|
+
const now = Date.now();
|
|
10508
|
+
if (now - cachedAt > 5_000) {
|
|
10509
|
+
cache = new Map(ahActivityIndex.activities(now).map((a) => [a.topicId, a.focus]));
|
|
10510
|
+
cachedAt = now;
|
|
10511
|
+
}
|
|
10512
|
+
return cache.get(topicId) ?? null;
|
|
10513
|
+
};
|
|
10514
|
+
})(),
|
|
10515
|
+
proxyCoordinator,
|
|
10516
|
+
sendMessage: async (topicId, text, metadata) => {
|
|
10517
|
+
const url = `http://localhost:${config.port}/telegram/reply/${topicId}`;
|
|
10518
|
+
const response = await fetch(url, {
|
|
10519
|
+
method: 'POST',
|
|
10520
|
+
headers: {
|
|
10521
|
+
'Content-Type': 'application/json',
|
|
10522
|
+
'Authorization': `Bearer ${config.authToken}`,
|
|
10523
|
+
},
|
|
10524
|
+
body: JSON.stringify({ text, metadata }),
|
|
10525
|
+
});
|
|
10526
|
+
if (!response.ok)
|
|
10527
|
+
throw new Error(`Autonomous-heartbeat reply failed: ${response.status}`);
|
|
10528
|
+
},
|
|
10529
|
+
}, {
|
|
10530
|
+
enabled: true, // gate already resolved above
|
|
10531
|
+
dryRun: ahRawCfg.dryRun !== false,
|
|
10532
|
+
silenceThresholdMinutes: ahRawCfg.silenceThresholdMinutes,
|
|
10533
|
+
tickIntervalMs: ahRawCfg.tickIntervalMs,
|
|
10534
|
+
maxHeartbeatsPerRun: ahRawCfg.maxHeartbeatsPerRun,
|
|
10535
|
+
recentOutputChangeWindowMs: ahRawCfg.recentOutputChangeWindowMs,
|
|
10536
|
+
});
|
|
10537
|
+
autonomousHeartbeat.start();
|
|
10538
|
+
globalThis.__instarAutonomousHeartbeat = autonomousHeartbeat;
|
|
10539
|
+
guardRegistry.register('monitoring.autonomousHeartbeat.enabled', () => autonomousHeartbeat.guardStatus());
|
|
10540
|
+
console.log(pc.green(` AutonomousProgressHeartbeat enabled (silence backstop — ${(ahRawCfg.dryRun !== false) ? 'dry-run observe-only' : 'LIVE'})`));
|
|
10541
|
+
}
|
|
10542
|
+
}
|
|
10543
|
+
catch (err) {
|
|
10544
|
+
console.warn('[AutonomousProgressHeartbeat] init failed (non-fatal):', err.message);
|
|
10545
|
+
}
|
|
10407
10546
|
// ── "keep watching" resume detector ─────────────────────────────
|
|
10408
10547
|
// When a user replies on a topic that has any auto-paused beacons,
|
|
10409
10548
|
// a literal "keep watching" match resumes them. Brittle detector
|