@sema-agent/server 5.12.0 → 5.13.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/fleet-client.js +27 -2
- package/package.json +2 -2
package/dist/fleet-client.js
CHANGED
|
@@ -103,6 +103,18 @@ export class FleetUsageAccumulator {
|
|
|
103
103
|
return this.cells.size;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
+
/** #123 F1 披露半场(§M):center 的拒绝响应体是操作员唯一的自诊线索(E2E #121:web 端明说了
|
|
107
|
+
* 「address must be a parseable http(s) base URL」而 server 日志只有 `announce 400`)——摘要进错误
|
|
108
|
+
* 信息(cap 200 字符);读体失败不改变结果面(照旧只有状态码)。 */
|
|
109
|
+
async function rejectionSnippet(res) {
|
|
110
|
+
try {
|
|
111
|
+
const text = (await res.text()).slice(0, 200).trim();
|
|
112
|
+
return text ? ` — center said: ${text}` : "";
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
}
|
|
106
118
|
/**
|
|
107
119
|
* Start the worker-side fleet loops. Caller has already gated on "center configured ∧ advertise address set"
|
|
108
120
|
* (startFleetClientFromEnv below) — this function assumes a complete opts.
|
|
@@ -131,7 +143,7 @@ export function startFleetClient(opts) {
|
|
|
131
143
|
// 半开连接钉住;心跳侧每 tick 叠一个在飞请求。
|
|
132
144
|
const res = await f(`${base}/api/fleet/instances`, { method: "POST", headers, body: JSON.stringify(body), signal: AbortSignal.timeout(FLEET_CLIENT_FETCH_TIMEOUT_MS) });
|
|
133
145
|
if (!res.ok)
|
|
134
|
-
throw new Error(`announce ${res.status}`);
|
|
146
|
+
throw new Error(`announce ${res.status}${await rejectionSnippet(res)}`);
|
|
135
147
|
if (failStreak > 0)
|
|
136
148
|
opts.logger?.info("fleet_announce_recovered", { after: failStreak });
|
|
137
149
|
failStreak = 0;
|
|
@@ -156,7 +168,7 @@ export function startFleetClient(opts) {
|
|
|
156
168
|
try {
|
|
157
169
|
const res = await f(`${base}/api/fleet/usage`, { method: "POST", headers, body: JSON.stringify({ reports: [report] }), signal: AbortSignal.timeout(FLEET_CLIENT_FETCH_TIMEOUT_MS) });
|
|
158
170
|
if (!res.ok)
|
|
159
|
-
throw new Error(`usage ${res.status}`);
|
|
171
|
+
throw new Error(`usage ${res.status}${await rejectionSnippet(res)}`);
|
|
160
172
|
}
|
|
161
173
|
catch (err) {
|
|
162
174
|
// Delivery failed → the window was never recorded center-side; carry the amounts forward (no loss, no double).
|
|
@@ -196,6 +208,19 @@ export function startFleetClientFromEnv(cfg, opts) {
|
|
|
196
208
|
const address = opts.advertiseAddress ?? process.env.FLEET_ADVERTISE_ADDRESS;
|
|
197
209
|
if (!cc?.baseUrl || !cc.token || !address)
|
|
198
210
|
return undefined;
|
|
211
|
+
// #123 F1(E2E #121 立案):旋钮**设了但坏形** ≠ 没设——center 端要求可解析的 http(s) base URL,
|
|
212
|
+
// 坏形(如缺 scheme 的 host:port)此前静默通过,启动后 fleet 腿每拍 announce 400、worker 永不注册。
|
|
213
|
+
// env fail-loud 族判据([2443] A1 同族):这里前置响亮拒,部署在起点就失败可见,而不是带病运行。
|
|
214
|
+
let parsed;
|
|
215
|
+
try {
|
|
216
|
+
parsed = new URL(address);
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
parsed = undefined;
|
|
220
|
+
}
|
|
221
|
+
if (parsed === undefined || (parsed.protocol !== "http:" && parsed.protocol !== "https:")) {
|
|
222
|
+
throw new Error(`FLEET_ADVERTISE_ADDRESS must be a parseable http(s) base URL (e.g. "http://10.0.0.5:8090"); got "${address}" — the fleet center rejects any other shape on every announce`);
|
|
223
|
+
}
|
|
199
224
|
if (!cc.worker) {
|
|
200
225
|
opts.logger?.warn("fleet_client_no_worker_scope", { note: "FLEET_ADVERTISE_ADDRESS set but SEMA_REGISTRY_WORKER missing — announce needs the worker (dispatch key); fleet client not started" });
|
|
201
226
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.13.0",
|
|
4
4
|
"description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"sharp": "^0.35.3"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@sema-agent/sdk": "^5.
|
|
71
|
+
"@sema-agent/sdk": "^5.2.0",
|
|
72
72
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
73
73
|
"@types/node": "22.10.2",
|
|
74
74
|
"@types/pg": "^8.20.0",
|