@nac3/forge-cli 1.14.0 → 1.15.0
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/chat/server.d.ts.map +1 -1
- package/dist/chat/server.js +71 -7
- package/dist/chat/server.js.map +1 -1
- package/dist/relay/presence_cadence.d.ts +105 -0
- package/dist/relay/presence_cadence.d.ts.map +1 -0
- package/dist/relay/presence_cadence.js +105 -0
- package/dist/relay/presence_cadence.js.map +1 -0
- package/dist/relay/relay_publisher.d.ts +5 -0
- package/dist/relay/relay_publisher.d.ts.map +1 -1
- package/dist/relay/relay_publisher.js +1 -0
- package/dist/relay/relay_publisher.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAKjG,OAAO,EAAoD,KAAK,aAAa,EAAoB,MAAM,aAAa,CAAC;AAErH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAEL,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAczB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAsBjD,OAAO,EAAyD,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
|
package/dist/chat/server.js
CHANGED
|
@@ -48,6 +48,7 @@ import { isAllowedSlot, listAllowedSlots } from '../core/provider_keys.js';
|
|
|
48
48
|
import { toolStatusSection, startToolStatusRefresh, environmentLines } from './tool_status.js';
|
|
49
49
|
import { RelayPublisher } from '../relay/relay_publisher.js';
|
|
50
50
|
import { setInFlightTurn, clearInFlightTurn, inFlightTurn } from '../relay/in_flight_turn.js';
|
|
51
|
+
import { decideBeat, presenceSignature, PRESENCE_TICK_MS } from '../relay/presence_cadence.js';
|
|
51
52
|
import { getInstanceIdentity } from '../relay/instance_identity.js';
|
|
52
53
|
import { isMobilePaired, relayGate } from '../core/mobile_pairing_state.js';
|
|
53
54
|
import { relayPoll } from '../relay/relay_client.js';
|
|
@@ -863,6 +864,18 @@ function broadcastToPanel(event, data) {
|
|
|
863
864
|
catch { /* best-effort */ }
|
|
864
865
|
}
|
|
865
866
|
}
|
|
867
|
+
/* El latido de presencia, forzable desde el camino del turno. El tick de
|
|
868
|
+
* evaluacion (5s) ya detecta el cambio de estado, pero forzarlo en el arranque
|
|
869
|
+
* y el cierre del turno lo hace INSTANTANEO: es la informacion por la que el
|
|
870
|
+
* telefono existe ("que esta haciendo ahora"), y no tiene que pagar ni la
|
|
871
|
+
* resolucion del tick. Null mientras no hay consumidores de relay corriendo. */
|
|
872
|
+
let _forcePresenceBeat = null;
|
|
873
|
+
function forcePresenceBeat() {
|
|
874
|
+
try {
|
|
875
|
+
_forcePresenceBeat?.(true);
|
|
876
|
+
}
|
|
877
|
+
catch { /* best-effort */ }
|
|
878
|
+
}
|
|
866
879
|
let _relayPub = null;
|
|
867
880
|
function getRelayPublisher() {
|
|
868
881
|
if (!relayEnabled())
|
|
@@ -1127,29 +1140,73 @@ function startDesktopCommandConsumer(port, coord = {}) {
|
|
|
1127
1140
|
pollCommands, runTurn, onControl, reply,
|
|
1128
1141
|
onError: () => { },
|
|
1129
1142
|
});
|
|
1130
|
-
/* Item 2 (cross-machine): advertise this instance's presence
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1133
|
-
|
|
1143
|
+
/* Item 2 (cross-machine): advertise this instance's presence so the phone
|
|
1144
|
+
* can list + pick instances across machines and TTL-expire dead ones.
|
|
1145
|
+
* Gated by relayEnabled -> only when a phone is paired.
|
|
1146
|
+
*
|
|
1147
|
+
* La CADENCIA la decide relay/presence_cadence.ts, no este timer: el timer
|
|
1148
|
+
* solo marca el pulso de EVALUACION. Medido contra el D1 (12-oct-2026), el
|
|
1149
|
+
* latido fijo de 15s era el 85% de la ventana retenida del relay y 34 de
|
|
1150
|
+
* los 40 eventos que trae un refresco -- ocioso, inundaba su propia ventana
|
|
1151
|
+
* y dejaba al telefono sin nada que mostrar. Ahora: 15s con turno en vuelo,
|
|
1152
|
+
* 300s ocioso, e inmediato cuando el estado cambia (que es lo que mantiene
|
|
1153
|
+
* instantaneo el anuncio del pedido en proceso). */
|
|
1154
|
+
let lastBeatAt = null;
|
|
1155
|
+
let lastSig = null;
|
|
1156
|
+
const beatPresence = (force = false) => {
|
|
1134
1157
|
try {
|
|
1135
1158
|
const pub = getRelayPublisher();
|
|
1136
1159
|
if (!pub)
|
|
1137
1160
|
return;
|
|
1138
1161
|
const idn = getInstanceIdentity();
|
|
1139
1162
|
const slug = _relayBoardCtx?.slug ?? null;
|
|
1163
|
+
const turn = inFlightTurn();
|
|
1164
|
+
const info = { hostname: idn.hostname, project_slug: slug, turn };
|
|
1165
|
+
const sig = presenceSignature(info);
|
|
1166
|
+
if (!force) {
|
|
1167
|
+
const d = decideBeat({
|
|
1168
|
+
now: Date.now(), lastBeatAt, lastSig, sig, working: !!turn,
|
|
1169
|
+
});
|
|
1170
|
+
if (!d.beat)
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
lastBeatAt = Date.now();
|
|
1174
|
+
lastSig = sig;
|
|
1140
1175
|
pub.presence({
|
|
1141
1176
|
hostname: idn.hostname, pid: idn.pid, port,
|
|
1142
1177
|
...(slug ? { project_slug: slug, project_name: slug } : {}),
|
|
1143
|
-
turn
|
|
1178
|
+
turn,
|
|
1144
1179
|
});
|
|
1145
1180
|
void pub.flush();
|
|
1146
1181
|
}
|
|
1147
1182
|
catch { /* best-effort */ }
|
|
1148
|
-
}
|
|
1183
|
+
};
|
|
1184
|
+
const presenceTimer = setInterval(() => { beatPresence(); }, PRESENCE_TICK_MS);
|
|
1149
1185
|
if (typeof presenceTimer.unref === 'function')
|
|
1150
1186
|
presenceTimer.unref();
|
|
1187
|
+
_forcePresenceBeat = beatPresence;
|
|
1151
1188
|
return {
|
|
1152
|
-
stop() {
|
|
1189
|
+
stop() {
|
|
1190
|
+
clearInterval(peerTimer);
|
|
1191
|
+
clearInterval(presenceTimer);
|
|
1192
|
+
/* Despedida: con la cadencia ociosa en 300s el TTL del telefono son 15
|
|
1193
|
+
* minutos, asi que una instancia que se cierra quedaria fantasma en el
|
|
1194
|
+
* selector todo ese rato. Un ultimo latido marcado `gone` la borra al
|
|
1195
|
+
* instante. Best-effort -- el TTL sigue siendo el respaldo si el
|
|
1196
|
+
* proceso muere sin pasar por aca. */
|
|
1197
|
+
try {
|
|
1198
|
+
const pub = getRelayPublisher();
|
|
1199
|
+
if (pub) {
|
|
1200
|
+
const idn = getInstanceIdentity();
|
|
1201
|
+
pub.presence({ hostname: idn.hostname, pid: idn.pid, port, gone: true });
|
|
1202
|
+
void pub.flush();
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
catch { /* best-effort */ }
|
|
1206
|
+
_forcePresenceBeat = null;
|
|
1207
|
+
chat.stop();
|
|
1208
|
+
control.stop();
|
|
1209
|
+
},
|
|
1153
1210
|
tickOnce: async () => { await refreshPeers(); await chat.tickOnce(); await control.tickOnce(); },
|
|
1154
1211
|
};
|
|
1155
1212
|
}
|
|
@@ -1366,10 +1423,17 @@ function relayForward(event, data) {
|
|
|
1366
1423
|
pub.status('working', { tier: d.tier, provider: d.provider, model: d.model });
|
|
1367
1424
|
pub.activity('remote running...', { kind: 'heartbeat' }); /* first line now; then every 60s */
|
|
1368
1425
|
startRelayHeartbeat();
|
|
1426
|
+
/* El turno en vuelo viaja DENTRO del latido (in_flight_turn.ts): hay que
|
|
1427
|
+
* publicarlo ya, sin esperar el tick, o el telefono no sabe que hay algo
|
|
1428
|
+
* corriendo hasta la proxima evaluacion. */
|
|
1429
|
+
forcePresenceBeat();
|
|
1369
1430
|
}
|
|
1370
1431
|
else if (event === 'turn_complete') {
|
|
1371
1432
|
stopRelayHeartbeat();
|
|
1372
1433
|
pub.status('round_done');
|
|
1434
|
+
/* Simetrico: el latido tiene que dejar de anunciar el turno, o el
|
|
1435
|
+
* telefono sigue mostrando la burbuja "pensando" hasta el proximo. */
|
|
1436
|
+
forcePresenceBeat();
|
|
1373
1437
|
/* refresh the phone's board after each turn (workflow/pendings may
|
|
1374
1438
|
* have changed) -- the pizarron is the value the user keeps. */
|
|
1375
1439
|
publishBoardSnapshot();
|