@pasko70/pibo 3.4.3 → 3.4.4
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/agent-runtime/routed-session.js +2 -0
- package/dist/agent-runtimes/codex-native/adapter.js +14 -1
- package/dist/agent-runtimes/codex-native/models.js +4 -4
- package/dist/agent-runtimes/codex-native/process.js +32 -13
- package/dist/agent-runtimes/codex-native/provider-usage.js +115 -0
- package/dist/agent-runtimes/pi/routed-session.js +2 -0
- package/dist/apps/chat-ui/assets/{dist-C8GzUMPk.js → dist-23lt_7qm.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DeMKnZR8.js → dist-Bf2KScPo.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-B4YhOxh0.js → dist-CH3SvpYV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Cyb4rVa6.js → dist-DsgL8w-W.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BkUu8WPA.js → dist-V06sfuZa.js} +1 -1
- package/dist/apps/chat-ui/assets/{index-Dk4mbXAB.js → index-BOemYq-V.js} +3 -3
- package/dist/apps/chat-ui/index.html +1 -1
- package/dist/apps/chat-vscode-web/assets/{index-0oTGFHni.js → index-CMwTB8o8.js} +1 -1
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/gateway/cli.js +104 -16
- package/dist/session-ui/terminalRows.js +7 -7
- package/dist/sessions/pibo-data-store.js +29 -10
- package/dist/web/channel.js +5 -2
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="theme-color" content="#101d22" />
|
|
7
7
|
<title>Pibo</title>
|
|
8
|
-
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-CMwTB8o8.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-b18ZkEo0.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/dist/gateway/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn, execFile } from "node:child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { appendFileSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync } from "node:fs";
|
|
3
4
|
import { homedir } from "node:os";
|
|
4
5
|
import { join } from "node:path";
|
|
5
6
|
import { promisify } from "node:util";
|
|
@@ -205,11 +206,14 @@ function runtimeTelemetryHint(value) {
|
|
|
205
206
|
}
|
|
206
207
|
function runtimeStatus(value) {
|
|
207
208
|
const obj = objectValue(value);
|
|
208
|
-
if (!obj)
|
|
209
|
+
if (!obj || !stringValue(obj.piboSessionId) || typeof obj.processing !== "boolean" || typeof obj.streaming !== "boolean"
|
|
210
|
+
|| !Number.isInteger(obj.queuedMessages) || Number(obj.queuedMessages) < 0)
|
|
209
211
|
return undefined;
|
|
210
212
|
return {
|
|
211
213
|
piboSessionId: stringValue(obj.piboSessionId),
|
|
212
214
|
queuedMessages: numberValue(obj.queuedMessages),
|
|
215
|
+
activeEventId: stringValue(obj.activeEventId),
|
|
216
|
+
queuedEventIds: Array.isArray(obj.queuedEventIds) && obj.queuedEventIds.every((id) => typeof id === "string") ? obj.queuedEventIds : undefined,
|
|
213
217
|
processing: booleanValue(obj.processing),
|
|
214
218
|
streaming: booleanValue(obj.streaming),
|
|
215
219
|
activeTelemetry: runtimeTelemetryHint(obj.activeTelemetry),
|
|
@@ -217,13 +221,14 @@ function runtimeStatus(value) {
|
|
|
217
221
|
}
|
|
218
222
|
function activeRun(value) {
|
|
219
223
|
const obj = objectValue(value);
|
|
220
|
-
if (!obj)
|
|
224
|
+
if (!obj || !stringValue(obj.runId) || !stringValue(obj.status)
|
|
225
|
+
|| !(stringValue(obj.controllerPiboSessionId) || stringValue(obj.piboSessionId)))
|
|
221
226
|
return undefined;
|
|
222
227
|
return {
|
|
223
228
|
runId: stringValue(obj.runId),
|
|
224
229
|
status: stringValue(obj.status),
|
|
225
230
|
toolName: stringValue(obj.toolName),
|
|
226
|
-
piboSessionId: stringValue(obj.piboSessionId),
|
|
231
|
+
piboSessionId: stringValue(obj.controllerPiboSessionId) ?? stringValue(obj.piboSessionId),
|
|
227
232
|
};
|
|
228
233
|
}
|
|
229
234
|
function parseGatewaySafetyPayload(payload, reachable) {
|
|
@@ -231,7 +236,9 @@ function parseGatewaySafetyPayload(payload, reachable) {
|
|
|
231
236
|
const mode = obj && (obj.mode === "dev" || obj.mode === "prod" || obj.mode === "fallback") ? obj.mode : "unknown";
|
|
232
237
|
const runtimeStatuses = Array.isArray(obj?.runtimeStatuses) ? obj.runtimeStatuses.map(runtimeStatus).filter((item) => Boolean(item)) : [];
|
|
233
238
|
const activeRuns = Array.isArray(obj?.activeRuns) ? obj.activeRuns.map(activeRun).filter((item) => Boolean(item)) : [];
|
|
234
|
-
|
|
239
|
+
const incomplete = !Array.isArray(obj?.runtimeStatuses) || !Array.isArray(obj?.activeRuns)
|
|
240
|
+
|| runtimeStatuses.length !== obj.runtimeStatuses.length || activeRuns.length !== obj.activeRuns.length;
|
|
241
|
+
return { reachable, mode, generation: stringValue(obj?.generation), health: obj?.health, runtimeStatuses, activeRuns, ambiguous: incomplete || booleanValue(obj?.ambiguous) };
|
|
235
242
|
}
|
|
236
243
|
export function checkActiveWork(status, target = "web") {
|
|
237
244
|
const reasons = [];
|
|
@@ -249,7 +256,7 @@ export function checkActiveWork(status, target = "web") {
|
|
|
249
256
|
reasons.push(`${id} is processing`);
|
|
250
257
|
if (session.streaming === true)
|
|
251
258
|
reasons.push(`${id} is streaming`);
|
|
252
|
-
if ((session.queuedMessages ?? 0) > 0)
|
|
259
|
+
if ((session.queuedMessages ?? 0) > 0 || (session.activeTelemetry?.queueDepth ?? 0) > 0)
|
|
253
260
|
reasons.push(`${id} has queued messages`);
|
|
254
261
|
if (session.activeTelemetry?.isStale === true) {
|
|
255
262
|
const phase = session.activeTelemetry.activePhase ? ` in ${session.activeTelemetry.activePhase}` : "";
|
|
@@ -260,6 +267,58 @@ export function checkActiveWork(status, target = "web") {
|
|
|
260
267
|
reasons.push(`${run.runId ?? "yielded run"} is ${run.status ?? "active"}`);
|
|
261
268
|
return { unsafe: reasons.length > 0, reasons };
|
|
262
269
|
}
|
|
270
|
+
function blockingSessions(status) {
|
|
271
|
+
return status.runtimeStatuses.filter((session) => session.processing || session.streaming
|
|
272
|
+
|| (session.queuedMessages ?? 0) > 0 || (session.activeTelemetry?.queueDepth ?? 0) > 0 || session.activeTelemetry?.isStale);
|
|
273
|
+
}
|
|
274
|
+
export function restartConfirmationToken(status) {
|
|
275
|
+
if (!status.reachable || status.error || status.ambiguous || status.mode !== "prod" || !status.generation)
|
|
276
|
+
return undefined;
|
|
277
|
+
const sessions = blockingSessions(status);
|
|
278
|
+
if (status.runtimeStatuses.some((session) => !session.piboSessionId || typeof session.processing !== "boolean"
|
|
279
|
+
|| typeof session.streaming !== "boolean" || !Number.isInteger(session.queuedMessages) || session.queuedMessages < 0))
|
|
280
|
+
return undefined;
|
|
281
|
+
if (sessions.some((session) => ((session.processing || session.streaming || session.activeTelemetry?.isStale)
|
|
282
|
+
&& !(session.activeEventId || session.activeTelemetry?.activeTurnId))
|
|
283
|
+
|| (session.queuedMessages > 0 && (session.queuedEventIds?.length !== session.queuedMessages || session.queuedEventIds?.some((id) => !id)))
|
|
284
|
+
|| (session.activeTelemetry?.queueDepth ?? 0) > (session.queuedMessages ?? 0)))
|
|
285
|
+
return undefined;
|
|
286
|
+
if (status.activeRuns.some((run) => !run.runId || !run.piboSessionId || !run.status))
|
|
287
|
+
return undefined;
|
|
288
|
+
// Exclude clock/progress counters: approval describes work identities, not polling time.
|
|
289
|
+
const snapshot = {
|
|
290
|
+
generation: status.generation,
|
|
291
|
+
target: "web", port: targetPort("web"), service: gatewayServiceName("web"), home: managedGatewayHome("web"),
|
|
292
|
+
sessions: sessions.map((session) => ({
|
|
293
|
+
id: session.piboSessionId, activeEventId: session.activeEventId,
|
|
294
|
+
processing: session.processing, streaming: session.streaming,
|
|
295
|
+
queuedEventIds: [...(session.queuedEventIds ?? [])], queuedMessages: session.queuedMessages,
|
|
296
|
+
telemetryTurnId: session.activeTelemetry?.activeTurnId,
|
|
297
|
+
stale: session.activeTelemetry?.isStale === true,
|
|
298
|
+
})).sort((a, b) => a.id.localeCompare(b.id)),
|
|
299
|
+
runs: [...status.activeRuns].sort((a, b) => a.runId.localeCompare(b.runId)),
|
|
300
|
+
};
|
|
301
|
+
return `${RESTART_CONFIRMATION_TOKEN}:${createHash("sha256").update(JSON.stringify(snapshot)).digest("hex")}`;
|
|
302
|
+
}
|
|
303
|
+
function printRestartApproval(status) {
|
|
304
|
+
const token = restartConfirmationToken(status);
|
|
305
|
+
if (token) {
|
|
306
|
+
console.log("Review the listed work and obtain user approval before running:");
|
|
307
|
+
console.log(` pibo gateway web restart --force --confirm ${token}`);
|
|
308
|
+
}
|
|
309
|
+
else
|
|
310
|
+
console.log("Snapshot approval unavailable: status must identify the gateway generation and all active work. Inspect: pibo gateway web doctor");
|
|
311
|
+
}
|
|
312
|
+
function auditRestart(status, decision, force, reason) {
|
|
313
|
+
const home = managedGatewayHome("web");
|
|
314
|
+
mkdirSync(home, { recursive: true });
|
|
315
|
+
appendFileSync(join(home, "gateway-restart-audit.jsonl"), `${JSON.stringify({
|
|
316
|
+
at: new Date().toISOString(), decision, force, reason, snapshot: restartConfirmationToken(status),
|
|
317
|
+
generation: status.generation,
|
|
318
|
+
sessionIds: [...new Set([...blockingSessions(status).map((session) => session.piboSessionId), ...status.activeRuns.map((run) => run.piboSessionId)].filter(Boolean))],
|
|
319
|
+
runIds: status.activeRuns.map((run) => run.runId), reasons: checkActiveWork(status).reasons,
|
|
320
|
+
})}\n`, { mode: 0o600 });
|
|
321
|
+
}
|
|
263
322
|
async function readGatewaySafetyStatus(target) {
|
|
264
323
|
const port = targetPort(target);
|
|
265
324
|
const reachable = await isPortReachable("127.0.0.1", port, 1500);
|
|
@@ -281,6 +340,10 @@ function printSafetyStatus(target, status) {
|
|
|
281
340
|
console.log(` runtime sessions: ${status.runtimeStatuses.length}`);
|
|
282
341
|
for (const session of status.runtimeStatuses) {
|
|
283
342
|
console.log(` ${session.piboSessionId ?? "unknown"}: processing=${session.processing === true} streaming=${session.streaming === true} queued=${session.queuedMessages ?? 0}`);
|
|
343
|
+
if (session.activeEventId)
|
|
344
|
+
console.log(` active event: ${session.activeEventId}`);
|
|
345
|
+
if (session.queuedEventIds?.length)
|
|
346
|
+
console.log(` queued events: ${session.queuedEventIds.join(", ")}`);
|
|
284
347
|
if (session.activeTelemetry) {
|
|
285
348
|
const parts = [
|
|
286
349
|
session.activeTelemetry.activePhase ? `phase=${session.activeTelemetry.activePhase}` : undefined,
|
|
@@ -295,7 +358,7 @@ function printSafetyStatus(target, status) {
|
|
|
295
358
|
}
|
|
296
359
|
console.log(` active yielded runs: ${status.activeRuns.length}`);
|
|
297
360
|
for (const run of status.activeRuns)
|
|
298
|
-
console.log(` ${run.runId ?? "unknown"}: ${run.status ?? "active"}${run.toolName ? ` (${run.toolName})` : ""}`);
|
|
361
|
+
console.log(` ${run.runId ?? "unknown"}: ${run.status ?? "active"}${run.toolName ? ` (${run.toolName})` : ""} session=${run.piboSessionId ?? "unknown"}`);
|
|
299
362
|
}
|
|
300
363
|
function managerRequiresShell(command) {
|
|
301
364
|
return process.platform === "win32" && /\.(?:cmd|bat)$/i.test(command);
|
|
@@ -332,6 +395,7 @@ async function runManagedGatewayCommand(target, command, args, argv = process.ar
|
|
|
332
395
|
}
|
|
333
396
|
else
|
|
334
397
|
console.log(" restart safety: idle");
|
|
398
|
+
printRestartApproval(status);
|
|
335
399
|
}
|
|
336
400
|
if (command === "doctor")
|
|
337
401
|
process.exitCode = status.reachable && !status.error && status.mode === expectedMode(target) ? 0 : 1;
|
|
@@ -380,19 +444,43 @@ async function runManagedGatewayCommand(target, command, args, argv = process.ar
|
|
|
380
444
|
const force = args.includes("--force");
|
|
381
445
|
const confirmIndex = args.indexOf("--confirm");
|
|
382
446
|
const confirmation = confirmIndex >= 0 ? args[confirmIndex + 1] : undefined;
|
|
383
|
-
if (force && confirmation !== RESTART_CONFIRMATION_TOKEN) {
|
|
447
|
+
if (target === "dev" && force && confirmation !== RESTART_CONFIRMATION_TOKEN) {
|
|
384
448
|
console.error(`Force restart requires: --confirm ${RESTART_CONFIRMATION_TOKEN}`);
|
|
385
449
|
process.exitCode = 1;
|
|
386
450
|
return true;
|
|
387
451
|
}
|
|
388
|
-
if (target === "web"
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
452
|
+
if (target === "web") {
|
|
453
|
+
// Both normal and delayed/forced commands inspect again at execution time.
|
|
454
|
+
let current = await readGatewaySafetyStatus(target);
|
|
455
|
+
for (let inspection = 0; inspection < 2; inspection += 1) {
|
|
456
|
+
const active = checkActiveWork(current, target);
|
|
457
|
+
const token = restartConfirmationToken(current);
|
|
458
|
+
printSafetyStatus(target, current);
|
|
394
459
|
for (const reason of active.reasons)
|
|
395
460
|
console.error(`- ${reason}`);
|
|
461
|
+
const blocked = force ? !token || confirmation !== token : active.unsafe;
|
|
462
|
+
if (blocked) {
|
|
463
|
+
const reason = force ? "Snapshot approval is missing, unavailable, or changed." : "Active work or unavailable gateway status.";
|
|
464
|
+
console.error(`Restart blocked: ${reason}`);
|
|
465
|
+
console.error("Ask the user before interrupting active sessions. Obtain fresh approval with: pibo gateway web status");
|
|
466
|
+
printRestartApproval(current);
|
|
467
|
+
try {
|
|
468
|
+
auditRestart(current, "blocked", force, reason);
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
console.error(`Restart audit failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
472
|
+
}
|
|
473
|
+
process.exitCode = 1;
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
if (inspection === 0)
|
|
477
|
+
current = await readGatewaySafetyStatus(target);
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
auditRestart(current, "approved", force, force ? "Unchanged snapshot explicitly approved" : "Gateway idle");
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
console.error(`Restart blocked: cannot record restart audit: ${error instanceof Error ? error.message : String(error)}`);
|
|
396
484
|
process.exitCode = 1;
|
|
397
485
|
return true;
|
|
398
486
|
}
|
|
@@ -642,8 +730,8 @@ Commands:
|
|
|
642
730
|
dev doctor Check dev gateway health
|
|
643
731
|
|
|
644
732
|
Options:
|
|
645
|
-
--force --confirm
|
|
646
|
-
|
|
733
|
+
--force --confirm <snapshot-token>
|
|
734
|
+
Restart only the work explicitly approved from web status
|
|
647
735
|
|
|
648
736
|
Next:
|
|
649
737
|
pibo gateway web status
|
|
@@ -41,14 +41,7 @@ function applyToolDisplayMode(rows, mode) {
|
|
|
41
41
|
const slimRow = {
|
|
42
42
|
...row,
|
|
43
43
|
lines: row.lines.slice(0, 1),
|
|
44
|
-
input: undefined,
|
|
45
|
-
output: undefined,
|
|
46
|
-
error: undefined,
|
|
47
|
-
markdown: undefined,
|
|
48
|
-
expandable: false,
|
|
49
44
|
singleLine: true,
|
|
50
|
-
previewOmission: undefined,
|
|
51
|
-
detailItems: undefined,
|
|
52
45
|
};
|
|
53
46
|
if (mode !== "intent")
|
|
54
47
|
return [slimRow];
|
|
@@ -60,6 +53,13 @@ function applyToolDisplayMode(rows, mode) {
|
|
|
60
53
|
prefix: "bullet",
|
|
61
54
|
tokens: [token(intent, row.status === "error" ? "red" : row.status === "done" ? "green" : "cyan", "semibold")],
|
|
62
55
|
}],
|
|
56
|
+
input: undefined,
|
|
57
|
+
output: undefined,
|
|
58
|
+
error: undefined,
|
|
59
|
+
markdown: undefined,
|
|
60
|
+
expandable: false,
|
|
61
|
+
previewOmission: undefined,
|
|
62
|
+
detailItems: undefined,
|
|
63
63
|
}];
|
|
64
64
|
});
|
|
65
65
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChatDataIngestService } from "../data/ingest-service.js";
|
|
1
|
+
import { ChatDataIngestService, outputIdempotencyKey } from "../data/ingest-service.js";
|
|
2
2
|
import { PiboDataStore } from "../data/pibo-store.js";
|
|
3
3
|
import { PIBO_AGENT_OBSERVATION_AUTO_CURSOR_MAX_SCOPES, createPiboSession, matchesFindInput, } from "./store.js";
|
|
4
4
|
import { createLegacyPiRuntimeSessionBinding, nextRuntimeSessionBinding, RuntimeSessionBindingConflictError, } from "./runtime-binding.js";
|
|
@@ -469,9 +469,26 @@ export class PiboDataSessionStore {
|
|
|
469
469
|
const at = input.at ?? new Date().toISOString();
|
|
470
470
|
const runsBySession = groupRunsByController(input.recoveredRuns ?? []);
|
|
471
471
|
return this.dataStore.transaction(() => {
|
|
472
|
+
// Durable terminal output wins over stale telemetry. Do not send a different
|
|
473
|
+
// recovery payload through the same output identity during startup.
|
|
474
|
+
const terminalErrors = new Map();
|
|
472
475
|
const recoveredTurns = this.dataStore.telemetry.recoverInterruptedTurns({
|
|
473
476
|
at,
|
|
474
|
-
resolveOutcome: (turn) =>
|
|
477
|
+
resolveOutcome: (turn) => {
|
|
478
|
+
const identity = { type: "session_error", piboSessionId: turn.piboSessionId, eventId: recoveryEventId(turn), error: "" };
|
|
479
|
+
const existing = this.dataStore.eventLog.findByIdempotencyKey(outputIdempotencyKey(identity));
|
|
480
|
+
if (existing) {
|
|
481
|
+
const event = {
|
|
482
|
+
...identity,
|
|
483
|
+
error: typeof existing.attributes.error === "string" ? existing.attributes.error : existing.previewText ?? "Runtime error",
|
|
484
|
+
errorDetails: existing.attributes.errorDetails,
|
|
485
|
+
};
|
|
486
|
+
terminalErrors.set(turn.turnId, event);
|
|
487
|
+
const details = event.errorDetails;
|
|
488
|
+
return { status: details?.code === "timeout" ? "timeout" : details?.errorClass === "runtime_abort" ? "aborted" : "error", summary: event.error };
|
|
489
|
+
}
|
|
490
|
+
return recoveryOutcomeForTurn(turn, runsBySession.get(turn.piboSessionId) ?? []);
|
|
491
|
+
},
|
|
475
492
|
});
|
|
476
493
|
if (recoveredTurns.length === 0)
|
|
477
494
|
return [];
|
|
@@ -482,7 +499,8 @@ export class PiboDataSessionStore {
|
|
|
482
499
|
if (!session)
|
|
483
500
|
continue;
|
|
484
501
|
const row = this.db.prepare("SELECT room_id FROM sessions WHERE id = ?").get(session.id);
|
|
485
|
-
const
|
|
502
|
+
const existingError = terminalErrors.get(recovered.turn.turnId);
|
|
503
|
+
const event = existingError ?? {
|
|
486
504
|
type: "session_error",
|
|
487
505
|
piboSessionId: session.id,
|
|
488
506
|
eventId: recoveryEventId(recovered.turn),
|
|
@@ -512,13 +530,14 @@ export class PiboDataSessionStore {
|
|
|
512
530
|
updated_at = ?
|
|
513
531
|
WHERE session_id = ?
|
|
514
532
|
`).run(at, at, at, session.id);
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
533
|
+
if (!existingError)
|
|
534
|
+
ingest.ingestOutputEvent({
|
|
535
|
+
session,
|
|
536
|
+
roomId: row?.room_id ?? undefined,
|
|
537
|
+
actorId: session.id,
|
|
538
|
+
event,
|
|
539
|
+
createdAt: at,
|
|
540
|
+
});
|
|
522
541
|
results.push({
|
|
523
542
|
turnId: recovered.turn.turnId,
|
|
524
543
|
piboSessionId: session.id,
|
package/dist/web/channel.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { createServer } from "node:http";
|
|
2
3
|
import { PiboAuthError } from "../auth/types.js";
|
|
3
4
|
import { handleSimpleAgentApiRequest } from "../api/simple-agent-api.js";
|
|
@@ -190,11 +191,12 @@ function createGatewayRuntimeStatuses(channelContext) {
|
|
|
190
191
|
}
|
|
191
192
|
});
|
|
192
193
|
}
|
|
193
|
-
function createGatewayStatusResponse(channelContext, options) {
|
|
194
|
+
function createGatewayStatusResponse(channelContext, options, generation) {
|
|
194
195
|
const mode = gatewayMode(options);
|
|
195
196
|
return responseJson({
|
|
196
197
|
status: "ok",
|
|
197
198
|
mode,
|
|
199
|
+
generation,
|
|
198
200
|
health: { status: "ok", mode },
|
|
199
201
|
runtimeStatuses: createGatewayRuntimeStatuses(channelContext),
|
|
200
202
|
activeRuns: collectActiveRuns(channelContext),
|
|
@@ -238,6 +240,7 @@ async function waitForServerClose(closePromise, timeoutMs) {
|
|
|
238
240
|
});
|
|
239
241
|
}
|
|
240
242
|
export function createWebHostChannel(options = {}) {
|
|
243
|
+
const generation = randomUUID();
|
|
241
244
|
const host = options.host ?? DEFAULT_WEB_CHANNEL_HOST;
|
|
242
245
|
const port = options.port ?? DEFAULT_WEB_CHANNEL_PORT;
|
|
243
246
|
const shutdownDrainTimeoutMs = options.shutdownDrainTimeoutMs ?? DEFAULT_SHUTDOWN_DRAIN_TIMEOUT_MS;
|
|
@@ -319,7 +322,7 @@ export function createWebHostChannel(options = {}) {
|
|
|
319
322
|
return;
|
|
320
323
|
}
|
|
321
324
|
if (url.pathname === "/gateway/status") {
|
|
322
|
-
await sendResponse(nodeResponse, createGatewayStatusResponse(requireContext(), options));
|
|
325
|
+
await sendResponse(nodeResponse, createGatewayStatusResponse(requireContext(), options, generation));
|
|
323
326
|
return;
|
|
324
327
|
}
|
|
325
328
|
if (url.pathname.startsWith("/api/auth/")) {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pasko70/pibo",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@pasko70/pibo",
|
|
9
|
-
"version": "3.4.
|
|
9
|
+
"version": "3.4.4",
|
|
10
10
|
"workspaces": [
|
|
11
11
|
"packages/workflows"
|
|
12
12
|
],
|