instar 1.3.860 → 1.3.862
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 +69 -16
- package/dist/commands/server.js.map +1 -1
- package/dist/core/SessionPoolLocalClaim.d.ts +24 -0
- package/dist/core/SessionPoolLocalClaim.d.ts.map +1 -0
- package/dist/core/SessionPoolLocalClaim.js +38 -0
- package/dist/core/SessionPoolLocalClaim.js.map +1 -0
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.861.md +27 -0
- package/upgrades/1.3.862.md +27 -0
- package/upgrades/side-effects/mesh-endpoint-advertisement-without-tunnel.md +114 -0
- package/upgrades/side-effects/session-pool-self-placement-confirmation.md +99 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0DH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AA0BjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0DH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AA0BjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA8H7D,OAAO,KAAK,EAAW,oBAAoB,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgFtD;;;;;;;;;;;;;;;;;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;AA2pDD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,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,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CAwtBN;AAgmBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgloBtE;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
|
@@ -105,6 +105,7 @@ import { SessionMonitor } from '../monitoring/SessionMonitor.js';
|
|
|
105
105
|
import { SessionRecovery } from '../monitoring/SessionRecovery.js';
|
|
106
106
|
import { MultiMachineCoordinator } from '../core/MultiMachineCoordinator.js';
|
|
107
107
|
import { isRemotelyHandled } from '../core/SessionRouter.js';
|
|
108
|
+
import { confirmLocalPlacementAfterDelivery } from '../core/SessionPoolLocalClaim.js';
|
|
108
109
|
import { decideLeaseGatedSpawn, sharedG3SoakLedger, applyBindingCleanupOnKill } from '../core/leaseGatedSpawn.js';
|
|
109
110
|
import { isSlackSessionKey, reconstructSlackMessage } from '../core/SlackForwardBridge.js';
|
|
110
111
|
import { formatForwardedTopicContext } from '../core/ForwardedTopicContext.js';
|
|
@@ -474,6 +475,11 @@ let _topicResumeMap = null;
|
|
|
474
475
|
// is byte-identical to today's always-local dispatch. Set once in startServer().
|
|
475
476
|
let _sessionRouter = null;
|
|
476
477
|
let _sessionPoolStage = () => 'dark';
|
|
478
|
+
// Self-placement deliberately falls through from SessionRouter into this file's
|
|
479
|
+
// established local inject/spawn tail. Confirming inside SessionRouter would be
|
|
480
|
+
// premature because handleLocally is only that fall-through marker. This callback
|
|
481
|
+
// advances placing → active only after the local tail has actually succeeded.
|
|
482
|
+
let _confirmLocalSessionPoolClaim = null;
|
|
477
483
|
// ── Durable Inbound Message Queue (docs/specs/durable-inbound-message-queue.md) ──
|
|
478
484
|
// The custody engine (null = feature dark / gate failed / invariants violated —
|
|
479
485
|
// every consumer treats null as "refused → today's fall-through").
|
|
@@ -2396,6 +2402,20 @@ getHubClassifierDeps) {
|
|
|
2396
2402
|
console.warn(`[session-pool] route error for topic ${topicId} — falling back to local dispatch: ${err instanceof Error ? err.message : String(err)}`);
|
|
2397
2403
|
}
|
|
2398
2404
|
}
|
|
2405
|
+
// Safe after any successful local delivery. The registry-side callback is
|
|
2406
|
+
// idempotent and confirms only a placing row already owned by this machine,
|
|
2407
|
+
// so ordinary active-session traffic is a strict no-op.
|
|
2408
|
+
const confirmLocalSessionPoolClaim = () => {
|
|
2409
|
+
try {
|
|
2410
|
+
_confirmLocalSessionPoolClaim?.(String(topicId));
|
|
2411
|
+
}
|
|
2412
|
+
catch (err) {
|
|
2413
|
+
// Delivery has already succeeded. A registry read/CAS/emit error must
|
|
2414
|
+
// avoid reclassifying delivery as a spawn failure (or throwing out of
|
|
2415
|
+
// the live-injection handler). The row is re-read by normal routing.
|
|
2416
|
+
console.warn(`[session-pool] local claim confirmation errored for topic ${topicId}; ownership outcome will be re-read: ${err instanceof Error ? err.message : String(err)}`);
|
|
2417
|
+
}
|
|
2418
|
+
};
|
|
2399
2419
|
// ── SpawnAdmission — the binding-verdict seam (ownership-gated-spawn §3.1,
|
|
2400
2420
|
// Layer A / the Ownership-Gated Side Effects standard). Consulted before
|
|
2401
2421
|
// EVERY local session-creating action below. Increment-1 posture: dryRun
|
|
@@ -2465,7 +2485,9 @@ getHubClassifierDeps) {
|
|
|
2465
2485
|
// Use toInjection() — types guarantee sender identity is included in the tag
|
|
2466
2486
|
const injection = toInjection(pipeline, targetSession);
|
|
2467
2487
|
console.log(`[telegram→session] Injecting into ${targetSession}: "${text.slice(0, 80)}"`);
|
|
2468
|
-
sessionManager.injectTelegramMessage(targetSession, topicId, text, pipeline.topicName, pipeline.sender.firstName, pipeline.sender.telegramUserId, parseInt(pipeline.id.replace('tg-', ''), 10) || undefined);
|
|
2488
|
+
const injected = sessionManager.injectTelegramMessage(targetSession, topicId, text, pipeline.topicName, pipeline.sender.firstName, pipeline.sender.telegramUserId, parseInt(pipeline.id.replace('tg-', ''), 10) || undefined);
|
|
2489
|
+
if (injected)
|
|
2490
|
+
confirmLocalSessionPoolClaim();
|
|
2469
2491
|
// Delivery confirmation — only when WE own polling. When lifeline owns
|
|
2470
2492
|
// polling (--no-telegram / standby), it already sends its own confirmation.
|
|
2471
2493
|
if (telegram.isPolling) {
|
|
@@ -2514,6 +2536,7 @@ getHubClassifierDeps) {
|
|
|
2514
2536
|
_topicResumeMap.remove(topicId);
|
|
2515
2537
|
}
|
|
2516
2538
|
respawnSessionForTopic(sessionManager, telegram, targetSession, topicId, text, topicMemory, resolvedUser ?? undefined)
|
|
2539
|
+
.then(() => confirmLocalSessionPoolClaim())
|
|
2517
2540
|
.catch(err => {
|
|
2518
2541
|
console.error(`[telegram→session] Context exhaustion respawn failed:`, err);
|
|
2519
2542
|
telegram.sendToTopic(topicId, `❌ Fresh session restart failed. Try sending your message again.`).catch(() => { });
|
|
@@ -2538,6 +2561,7 @@ getHubClassifierDeps) {
|
|
|
2538
2561
|
const _spawnTokB = spawningTopics.add(topicId);
|
|
2539
2562
|
telegram.sendToTopic(topicId, `🔄 Session restarting — message queued.`).catch(() => { });
|
|
2540
2563
|
respawnSessionForTopic(sessionManager, telegram, targetSession, topicId, text, topicMemory, resolvedUser ?? undefined)
|
|
2564
|
+
.then(() => confirmLocalSessionPoolClaim())
|
|
2541
2565
|
.catch(err => {
|
|
2542
2566
|
console.error(`[telegram→session] Respawn failed:`, err);
|
|
2543
2567
|
// G1 "Agent Is Always Reachable" corollary (2): no silent resource
|
|
@@ -2602,6 +2626,7 @@ getHubClassifierDeps) {
|
|
|
2602
2626
|
// Use the shared spawn helper that includes topic history + user context
|
|
2603
2627
|
spawnSessionForTopic(sessionManager, telegram, spawnName, topicId, text, topicMemory, resolvedUser ?? undefined).then((newSessionName) => {
|
|
2604
2628
|
telegram.registerTopicSession(topicId, newSessionName, spawnName);
|
|
2629
|
+
confirmLocalSessionPoolClaim();
|
|
2605
2630
|
telegram.sendToTopic(topicId, `Session starting up — reading your message now. One moment.`).catch(() => { });
|
|
2606
2631
|
console.log(`[telegram→session] Auto-spawned "${newSessionName}" for topic ${topicId}`);
|
|
2607
2632
|
}).catch((err) => {
|
|
@@ -4570,6 +4595,7 @@ export async function startServer(options) {
|
|
|
4570
4595
|
// construction (far below) can wire the /api/lease[/pull] receivers to real registry fns.
|
|
4571
4596
|
let peerEndpointRecorder;
|
|
4572
4597
|
let getSelfMeshEndpoints;
|
|
4598
|
+
let meshResolver;
|
|
4573
4599
|
// mesh-coherence-live-state-honesty (Fix (b) / Decision #5): the resolved server bind host,
|
|
4574
4600
|
// a BOOT CONSTANT. Declared `let` at OUTER scope (the same scope as getSelfMeshEndpoints)
|
|
4575
4601
|
// and assigned inside the mesh-init block so the peerPresenceTimer closure (far below) can
|
|
@@ -4740,7 +4766,7 @@ export async function startServer(options) {
|
|
|
4740
4766
|
// single-`url` legacy path (byte-for-byte today).
|
|
4741
4767
|
const meshCfg = config.multiMachine?.meshTransport;
|
|
4742
4768
|
const meshEnabled = () => meshCfg?.enabled !== false; // default ON
|
|
4743
|
-
|
|
4769
|
+
meshResolver = new PeerEndpointResolver({
|
|
4744
4770
|
config: {
|
|
4745
4771
|
enabled: meshCfg?.enabled !== false,
|
|
4746
4772
|
hedgeDelayMs: meshCfg?.hedgeDelayMs ?? 1500,
|
|
@@ -20004,7 +20030,12 @@ export async function startServer(options) {
|
|
|
20004
20030
|
nonce: () => `${meshSelfId}:r:${Date.now()}:${++routerNonce}`,
|
|
20005
20031
|
now: () => Date.now(),
|
|
20006
20032
|
});
|
|
20007
|
-
const peerUrl = (machineId) =>
|
|
20033
|
+
const peerUrl = (machineId) => {
|
|
20034
|
+
const entry = meshIdMgr.getActiveMachines().find((m) => m.machineId === machineId)?.entry;
|
|
20035
|
+
if (!entry)
|
|
20036
|
+
return null;
|
|
20037
|
+
return meshResolver.resolve(machineId, entry.endpoints, entry.lastKnownUrl)[0]?.url ?? null;
|
|
20038
|
+
};
|
|
20008
20039
|
_meshSelfId = meshSelfId;
|
|
20009
20040
|
// U4.4 — the offer transport (HOLDER side) + the post-hand-back delivery
|
|
20010
20041
|
// canary (PREFERRED side), both over the signed mesh RPC.
|
|
@@ -20776,6 +20807,23 @@ export async function startServer(options) {
|
|
|
20776
20807
|
});
|
|
20777
20808
|
},
|
|
20778
20809
|
});
|
|
20810
|
+
_confirmLocalSessionPoolClaim = (sk) => {
|
|
20811
|
+
return confirmLocalPlacementAfterDelivery({
|
|
20812
|
+
selfMachineId: meshSelfId,
|
|
20813
|
+
readOwnership: (sessionKey) => ownReg.read(sessionKey),
|
|
20814
|
+
claimOwnership: (sessionKey, machineId) => {
|
|
20815
|
+
const prevOwner = ownReg.read(sessionKey)?.ownerMachineId;
|
|
20816
|
+
const r = ownReg.cas({ type: 'claim', machineId }, { sessionKey, sender: meshSelfId, nonce: `${meshSelfId}:lcl:${++routerNonce}` });
|
|
20817
|
+
return {
|
|
20818
|
+
confirmed: r.ok,
|
|
20819
|
+
afterConfirm: () => emitPlacement(sessionKey, r, 'placed', prevOwner),
|
|
20820
|
+
};
|
|
20821
|
+
},
|
|
20822
|
+
onError: (err) => {
|
|
20823
|
+
console.warn(`[session-pool] local ownership confirmation observer failed for ${sk}; authoritative state will be re-read: ${err instanceof Error ? err.message : String(err)}`);
|
|
20824
|
+
},
|
|
20825
|
+
}, sk);
|
|
20826
|
+
};
|
|
20779
20827
|
_sessionRouter = new routerMod.SessionRouter({
|
|
20780
20828
|
selfMachineId: meshSelfId,
|
|
20781
20829
|
placement: new placeMod.PlacementExecutor(undefined, {
|
|
@@ -20842,6 +20890,12 @@ export async function startServer(options) {
|
|
|
20842
20890
|
const r = ownReg.cas({ type: 'claim', machineId }, { sessionKey: sk, sender: meshSelfId, nonce: `${meshSelfId}:cl:${++routerNonce}` });
|
|
20843
20891
|
emitPlacement(sk, r, 'placed', prevOwner); // placing→active confirmation: a real epoch bump in the registry
|
|
20844
20892
|
},
|
|
20893
|
+
// The local delivery tail runs outside SessionRouter. Confirm its
|
|
20894
|
+
// self-placement only after that tail reports a successful inject or
|
|
20895
|
+
// spawn; a thrown/failed spawn therefore leaves the row in placing.
|
|
20896
|
+
// Guarding the current row makes repeated live injections idempotent.
|
|
20897
|
+
// The adjacent _confirmLocalSessionPoolClaim callback shares this
|
|
20898
|
+
// authoritative registry and nonce stream for the local tail.
|
|
20845
20899
|
deliverMessage: async (target, env) => {
|
|
20846
20900
|
const url = peerUrl(target);
|
|
20847
20901
|
if (!url)
|
|
@@ -22900,27 +22954,26 @@ export async function startServer(options) {
|
|
|
22900
22954
|
// Failure on initial start is non-fatal: the manager keeps trying
|
|
22901
22955
|
// in the background, and the post-exhausted retry timer keeps the
|
|
22902
22956
|
// agent recoverable without requiring a server restart.
|
|
22957
|
+
let bootTunnelUrl = null;
|
|
22903
22958
|
if (tunnel) {
|
|
22904
22959
|
try {
|
|
22905
|
-
|
|
22906
|
-
console.log(pc.green(` Tunnel active: ${pc.bold(
|
|
22907
|
-
// Mesh URL advertisement: record THIS machine's reachable URL into its
|
|
22908
|
-
// registry entry so cross-machine routing (deliver/transfer/lease) can
|
|
22909
|
-
// reach it. Without this, lastKnownUrl is null and every peer is filtered
|
|
22910
|
-
// out (the session pool is inert across machines). The existing
|
|
22911
|
-
// RegistrySyncDebouncer propagates the populated entry to peers.
|
|
22912
|
-
if (coordinator.enabled && coordinator.identity) {
|
|
22913
|
-
const cfUrl = resolveAdvertisedMeshUrl(config.tunnel, tunnelUrl);
|
|
22914
|
-
advertiseSelfMeshUrl(coordinator.managers.identityManager, coordinator.identity.machineId, cfUrl, (m) => console.log(pc.dim(m)));
|
|
22915
|
-
// multi-transport-mesh-comms (Layer 0) — advertise the full endpoint set.
|
|
22916
|
-
await advertiseSelfMeshEndpointsNow(coordinator.managers.identityManager, coordinator.identity.machineId, config, cfUrl);
|
|
22917
|
-
}
|
|
22960
|
+
bootTunnelUrl = await tunnel.start();
|
|
22961
|
+
console.log(pc.green(` Tunnel active: ${pc.bold(bootTunnelUrl)}`));
|
|
22918
22962
|
}
|
|
22919
22963
|
catch (err) {
|
|
22920
22964
|
const msg = err instanceof Error ? err.message : String(err);
|
|
22921
22965
|
console.error(pc.red(` Tunnel start failed (manager will keep retrying in background): ${msg}`));
|
|
22922
22966
|
}
|
|
22923
22967
|
}
|
|
22968
|
+
// Mesh endpoint advertisement is independent of optional tunnel success.
|
|
22969
|
+
// A rate-limited quick tunnel must not suppress healthy LAN/Tailscale ropes:
|
|
22970
|
+
// doing so makes reachable peers appear offline and removes the HTTP lease
|
|
22971
|
+
// medium. Cloudflare is simply omitted when it has no resolved URL.
|
|
22972
|
+
if (coordinator.enabled && coordinator.identity) {
|
|
22973
|
+
const cfUrl = resolveAdvertisedMeshUrl(config.tunnel, bootTunnelUrl);
|
|
22974
|
+
advertiseSelfMeshUrl(coordinator.managers.identityManager, coordinator.identity.machineId, cfUrl, (m) => console.log(pc.dim(m)));
|
|
22975
|
+
await advertiseSelfMeshEndpointsNow(coordinator.managers.identityManager, coordinator.identity.machineId, config, cfUrl);
|
|
22976
|
+
}
|
|
22924
22977
|
// ── Dashboard Topic: always-available link ──────────────────────────
|
|
22925
22978
|
// Retroactive: creates the topic on first run for existing agents.
|
|
22926
22979
|
// Posts tunnel URL + PIN and pins the message for instant access.
|