@syengup/friday-channel-next 0.1.17 → 0.1.19
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/src/host-config.js +13 -6
- package/dist/src/http/handlers/messages.js +15 -11
- package/dist/src/logging.d.ts +2 -1
- package/dist/src/logging.js +11 -2
- package/dist/src/runtime.d.ts +2 -1
- package/package.json +1 -1
- package/src/host-config.ts +14 -9
- package/src/http/handlers/messages.ts +21 -11
- package/src/logging.ts +13 -2
- package/src/runtime.ts +3 -1
- package/src/test-support/mock-runtime.ts +2 -0
package/dist/src/host-config.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
function asConfigLoader(value) {
|
|
2
|
+
if (!value || typeof value !== "object")
|
|
3
|
+
return null;
|
|
4
|
+
const v = value;
|
|
5
|
+
if (typeof v.current === "function" || typeof v.loadConfig === "function")
|
|
6
|
+
return v;
|
|
7
|
+
return null;
|
|
5
8
|
}
|
|
6
9
|
export function getHostOpenClawConfigSnapshot(config) {
|
|
7
|
-
|
|
10
|
+
const loader = asConfigLoader(config);
|
|
11
|
+
if (!loader)
|
|
8
12
|
return {};
|
|
9
13
|
try {
|
|
10
|
-
|
|
14
|
+
// Prefer current() to avoid the deprecation warning; fall back to loadConfig() on old gateways.
|
|
15
|
+
if (typeof loader.current === "function")
|
|
16
|
+
return loader.current();
|
|
17
|
+
return loader.loadConfig();
|
|
11
18
|
}
|
|
12
19
|
catch {
|
|
13
20
|
return {};
|
|
@@ -23,12 +23,15 @@ import { fridayAttachmentLookupKey, fridayFilesPublicUrl, readFile, resolveMedia
|
|
|
23
23
|
import { runFridayDispatch } from "../../agent/dispatch-bridge.js";
|
|
24
24
|
import { saveInboundMediaBuffer } from "../../agent/media-bridge.js";
|
|
25
25
|
import { contextTokensFromUsageRecord, getRunMetadata, getRunRoute, hasRunFinalDelivered, markRunFinalDelivered, registerRunRoute, setRunMetadata, } from "../../run-metadata.js";
|
|
26
|
-
import { createFridayNextLogger } from "../../logging.js";
|
|
26
|
+
import { createFridayNextLogger, setFridayNextLogLevel } from "../../logging.js";
|
|
27
27
|
const logger = createFridayNextLogger("messages");
|
|
28
|
-
|
|
28
|
+
// Routine per-message / per-stream lifecycle events log at "debug" so they stay out of
|
|
29
|
+
// the default ("info") OpenClaw log; only genuine problems (rejections, run errors) surface.
|
|
30
|
+
// Raise the friday-next channel logLevel to "debug" to see the full per-message trace.
|
|
31
|
+
const log = (action, deviceId, runId, detail, level = "debug") => {
|
|
29
32
|
const runPart = runId ? ` runId=${runId}` : "";
|
|
30
33
|
const detailPart = detail ? ` detail=${detail}` : "";
|
|
31
|
-
logger
|
|
34
|
+
logger[level](`[${action}] deviceId=${deviceId}${runPart}${detailPart}`);
|
|
32
35
|
};
|
|
33
36
|
function collectReplyPayloadMediaUrls(pl) {
|
|
34
37
|
const fromArr = Array.isArray(pl.mediaUrls)
|
|
@@ -285,7 +288,7 @@ export async function handleMessages(req, res) {
|
|
|
285
288
|
}
|
|
286
289
|
const token = extractBearerToken(req);
|
|
287
290
|
if (!token) {
|
|
288
|
-
log("AUTH_FAILED", "(unknown)", undefined, "missing or invalid token");
|
|
291
|
+
log("AUTH_FAILED", "(unknown)", undefined, "missing or invalid token", "warn");
|
|
289
292
|
res.statusCode = 401;
|
|
290
293
|
res.setHeader("Content-Type", "application/json");
|
|
291
294
|
res.end(JSON.stringify({ error: "Unauthorized: bearer token mismatch" }));
|
|
@@ -293,7 +296,7 @@ export async function handleMessages(req, res) {
|
|
|
293
296
|
}
|
|
294
297
|
const payload = (await readJsonBody(req));
|
|
295
298
|
if (!payload) {
|
|
296
|
-
log("BAD_REQUEST", "(unknown)", undefined, "invalid JSON body");
|
|
299
|
+
log("BAD_REQUEST", "(unknown)", undefined, "invalid JSON body", "warn");
|
|
297
300
|
res.statusCode = 400;
|
|
298
301
|
res.setHeader("Content-Type", "application/json");
|
|
299
302
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
@@ -302,7 +305,7 @@ export async function handleMessages(req, res) {
|
|
|
302
305
|
const { deviceId, text, attachments = [], sessionKey: rawSessionKey } = payload;
|
|
303
306
|
const normalizedDeviceId = deviceId?.trim().toUpperCase();
|
|
304
307
|
if (typeof rawSessionKey !== "string" || !rawSessionKey.length) {
|
|
305
|
-
log("BAD_REQUEST", "(unknown)", undefined, "missing sessionKey");
|
|
308
|
+
log("BAD_REQUEST", "(unknown)", undefined, "missing sessionKey", "warn");
|
|
306
309
|
res.statusCode = 400;
|
|
307
310
|
res.setHeader("Content-Type", "application/json");
|
|
308
311
|
res.end(JSON.stringify({ error: "Missing required field: sessionKey" }));
|
|
@@ -311,14 +314,14 @@ export async function handleMessages(req, res) {
|
|
|
311
314
|
const appSessionKey = rawSessionKey.trim();
|
|
312
315
|
const baseSessionKey = toSessionStoreKey(appSessionKey);
|
|
313
316
|
if (!normalizedDeviceId) {
|
|
314
|
-
log("BAD_REQUEST", "(unknown)", undefined, "missing deviceId");
|
|
317
|
+
log("BAD_REQUEST", "(unknown)", undefined, "missing deviceId", "warn");
|
|
315
318
|
res.statusCode = 400;
|
|
316
319
|
res.setHeader("Content-Type", "application/json");
|
|
317
320
|
res.end(JSON.stringify({ error: "Missing required field: deviceId" }));
|
|
318
321
|
return true;
|
|
319
322
|
}
|
|
320
323
|
if (!text || !text.trim()) {
|
|
321
|
-
log("BAD_REQUEST", normalizedDeviceId, undefined, "missing text");
|
|
324
|
+
log("BAD_REQUEST", normalizedDeviceId, undefined, "missing text", "warn");
|
|
322
325
|
res.statusCode = 400;
|
|
323
326
|
res.setHeader("Content-Type", "application/json");
|
|
324
327
|
res.end(JSON.stringify({ error: "Missing required field: text" }));
|
|
@@ -334,6 +337,7 @@ export async function handleMessages(req, res) {
|
|
|
334
337
|
res.end(JSON.stringify({ accepted: true, deviceId: normalizedDeviceId, runId }));
|
|
335
338
|
log("MESSAGE_RECEIVED", normalizedDeviceId, runId, `textLen=${trimmedText.length} attachments=${attachments.length} sessionKey=${baseSessionKey}`);
|
|
336
339
|
const cfg = resolveFridayNextConfig(getHostOpenClawConfigSnapshot(runtime.config));
|
|
340
|
+
setFridayNextLogLevel(cfg.logLevel);
|
|
337
341
|
// Resolve defaults from the OpenClaw agent config so settings are never left empty. Prefers the
|
|
338
342
|
// target agent's own model/thinking over the global defaults (see resolveAgentDefaults).
|
|
339
343
|
const { model: defaultModel, thinking: defaultThinking } = resolveAgentDefaults(baseSessionKey);
|
|
@@ -415,7 +419,7 @@ export async function handleMessages(req, res) {
|
|
|
415
419
|
}
|
|
416
420
|
},
|
|
417
421
|
onError: (err) => {
|
|
418
|
-
log("RUN_ERROR", normalizedDeviceId, runId, String(err));
|
|
422
|
+
log("RUN_ERROR", normalizedDeviceId, runId, String(err), "error");
|
|
419
423
|
sseEmitter.broadcastToRun(runId, {
|
|
420
424
|
type: "outbound",
|
|
421
425
|
data: {
|
|
@@ -455,7 +459,7 @@ export async function handleMessages(req, res) {
|
|
|
455
459
|
log("RUN_COMPLETE", normalizedDeviceId, runId);
|
|
456
460
|
}
|
|
457
461
|
catch (err) {
|
|
458
|
-
log("RUN_ERROR", normalizedDeviceId, runId, String(err));
|
|
462
|
+
log("RUN_ERROR", normalizedDeviceId, runId, String(err), "error");
|
|
459
463
|
sseEmitter.broadcastToRun(runId, {
|
|
460
464
|
type: "outbound",
|
|
461
465
|
data: {
|
|
@@ -473,7 +477,7 @@ export async function handleMessages(req, res) {
|
|
|
473
477
|
}
|
|
474
478
|
};
|
|
475
479
|
runAgent().catch((err) => {
|
|
476
|
-
log("RUN_ERROR", normalizedDeviceId, runId, String(err));
|
|
480
|
+
log("RUN_ERROR", normalizedDeviceId, runId, String(err), "error");
|
|
477
481
|
sseEmitter.untrackRun(runId);
|
|
478
482
|
});
|
|
479
483
|
return true;
|
package/dist/src/logging.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FridayNextLogLevel } from "./config.js";
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function setFridayNextLogLevel(level: FridayNextLogLevel): void;
|
|
3
|
+
export declare function createFridayNextLogger(scope: string, _level?: FridayNextLogLevel): {
|
|
3
4
|
debug: (message: string) => void;
|
|
4
5
|
info: (message: string) => void;
|
|
5
6
|
warn: (message: string) => void;
|
package/dist/src/logging.js
CHANGED
|
@@ -4,9 +4,18 @@ const levelOrder = {
|
|
|
4
4
|
warn: 30,
|
|
5
5
|
error: 40,
|
|
6
6
|
};
|
|
7
|
-
|
|
7
|
+
// Process-wide active level, honored by every logger at call time. Handlers call
|
|
8
|
+
// setFridayNextLogLevel() once the friday-next channel config resolves, so
|
|
9
|
+
// `channels.friday-next.logLevel: "debug"` turns the full per-message trace back on.
|
|
10
|
+
let activeLevel = "info";
|
|
11
|
+
export function setFridayNextLogLevel(level) {
|
|
12
|
+
activeLevel = level;
|
|
13
|
+
}
|
|
14
|
+
// The optional `level` arg is accepted for call-site compatibility but the effective
|
|
15
|
+
// threshold is the process-wide active level (single knob driven by config.logLevel).
|
|
16
|
+
export function createFridayNextLogger(scope, _level) {
|
|
8
17
|
const base = `[friday-next:${scope}]`;
|
|
9
|
-
const enabled = (current) => levelOrder[current] >= levelOrder[
|
|
18
|
+
const enabled = (current) => levelOrder[current] >= levelOrder[activeLevel];
|
|
10
19
|
return {
|
|
11
20
|
debug: (message) => {
|
|
12
21
|
if (enabled("debug"))
|
package/dist/src/runtime.d.ts
CHANGED
package/package.json
CHANGED
package/src/host-config.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
type HostConfigLoader = {
|
|
2
|
-
|
|
2
|
+
// Modern OpenClaw exposes config.current(); older builds only had config.loadConfig(),
|
|
3
|
+
// which is now deprecated and logs a "runtime-config-load-write" warning on every call.
|
|
4
|
+
current?: () => unknown;
|
|
5
|
+
loadConfig?: () => unknown;
|
|
3
6
|
};
|
|
4
7
|
|
|
5
|
-
function
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
);
|
|
8
|
+
function asConfigLoader(value: unknown): HostConfigLoader | null {
|
|
9
|
+
if (!value || typeof value !== "object") return null;
|
|
10
|
+
const v = value as HostConfigLoader;
|
|
11
|
+
if (typeof v.current === "function" || typeof v.loadConfig === "function") return v;
|
|
12
|
+
return null;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export function getHostOpenClawConfigSnapshot(config: unknown): unknown {
|
|
14
|
-
|
|
16
|
+
const loader = asConfigLoader(config);
|
|
17
|
+
if (!loader) return {};
|
|
15
18
|
try {
|
|
16
|
-
|
|
19
|
+
// Prefer current() to avoid the deprecation warning; fall back to loadConfig() on old gateways.
|
|
20
|
+
if (typeof loader.current === "function") return loader.current();
|
|
21
|
+
return loader.loadConfig!();
|
|
17
22
|
} catch {
|
|
18
23
|
return {};
|
|
19
24
|
}
|
|
@@ -57,14 +57,23 @@ import {
|
|
|
57
57
|
registerRunRoute,
|
|
58
58
|
setRunMetadata,
|
|
59
59
|
} from "../../run-metadata.js";
|
|
60
|
-
import { createFridayNextLogger } from "../../logging.js";
|
|
60
|
+
import { createFridayNextLogger, setFridayNextLogLevel } from "../../logging.js";
|
|
61
61
|
|
|
62
62
|
const logger = createFridayNextLogger("messages");
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
// Routine per-message / per-stream lifecycle events log at "debug" so they stay out of
|
|
65
|
+
// the default ("info") OpenClaw log; only genuine problems (rejections, run errors) surface.
|
|
66
|
+
// Raise the friday-next channel logLevel to "debug" to see the full per-message trace.
|
|
67
|
+
const log = (
|
|
68
|
+
action: string,
|
|
69
|
+
deviceId: string,
|
|
70
|
+
runId?: string,
|
|
71
|
+
detail?: string,
|
|
72
|
+
level: "debug" | "info" | "warn" | "error" = "debug",
|
|
73
|
+
) => {
|
|
65
74
|
const runPart = runId ? ` runId=${runId}` : "";
|
|
66
75
|
const detailPart = detail ? ` detail=${detail}` : "";
|
|
67
|
-
logger
|
|
76
|
+
logger[level](`[${action}] deviceId=${deviceId}${runPart}${detailPart}`);
|
|
68
77
|
};
|
|
69
78
|
|
|
70
79
|
function collectReplyPayloadMediaUrls(pl: { mediaUrls?: string[]; mediaUrl?: string | null }): string[] {
|
|
@@ -381,7 +390,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
381
390
|
|
|
382
391
|
const token = extractBearerToken(req);
|
|
383
392
|
if (!token) {
|
|
384
|
-
log("AUTH_FAILED", "(unknown)", undefined, "missing or invalid token");
|
|
393
|
+
log("AUTH_FAILED", "(unknown)", undefined, "missing or invalid token", "warn");
|
|
385
394
|
res.statusCode = 401;
|
|
386
395
|
res.setHeader("Content-Type", "application/json");
|
|
387
396
|
res.end(JSON.stringify({ error: "Unauthorized: bearer token mismatch" }));
|
|
@@ -390,7 +399,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
390
399
|
|
|
391
400
|
const payload = (await readJsonBody(req)) as FridayMessagePayload | null;
|
|
392
401
|
if (!payload) {
|
|
393
|
-
log("BAD_REQUEST", "(unknown)", undefined, "invalid JSON body");
|
|
402
|
+
log("BAD_REQUEST", "(unknown)", undefined, "invalid JSON body", "warn");
|
|
394
403
|
res.statusCode = 400;
|
|
395
404
|
res.setHeader("Content-Type", "application/json");
|
|
396
405
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
@@ -401,7 +410,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
401
410
|
const normalizedDeviceId = deviceId?.trim().toUpperCase();
|
|
402
411
|
|
|
403
412
|
if (typeof rawSessionKey !== "string" || !rawSessionKey.length) {
|
|
404
|
-
log("BAD_REQUEST", "(unknown)", undefined, "missing sessionKey");
|
|
413
|
+
log("BAD_REQUEST", "(unknown)", undefined, "missing sessionKey", "warn");
|
|
405
414
|
res.statusCode = 400;
|
|
406
415
|
res.setHeader("Content-Type", "application/json");
|
|
407
416
|
res.end(JSON.stringify({ error: "Missing required field: sessionKey" }));
|
|
@@ -412,7 +421,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
412
421
|
const baseSessionKey = toSessionStoreKey(appSessionKey);
|
|
413
422
|
|
|
414
423
|
if (!normalizedDeviceId) {
|
|
415
|
-
log("BAD_REQUEST", "(unknown)", undefined, "missing deviceId");
|
|
424
|
+
log("BAD_REQUEST", "(unknown)", undefined, "missing deviceId", "warn");
|
|
416
425
|
res.statusCode = 400;
|
|
417
426
|
res.setHeader("Content-Type", "application/json");
|
|
418
427
|
res.end(JSON.stringify({ error: "Missing required field: deviceId" }));
|
|
@@ -420,7 +429,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
420
429
|
}
|
|
421
430
|
|
|
422
431
|
if (!text || !text.trim()) {
|
|
423
|
-
log("BAD_REQUEST", normalizedDeviceId, undefined, "missing text");
|
|
432
|
+
log("BAD_REQUEST", normalizedDeviceId, undefined, "missing text", "warn");
|
|
424
433
|
res.statusCode = 400;
|
|
425
434
|
res.setHeader("Content-Type", "application/json");
|
|
426
435
|
res.end(JSON.stringify({ error: "Missing required field: text" }));
|
|
@@ -447,6 +456,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
447
456
|
);
|
|
448
457
|
|
|
449
458
|
const cfg = resolveFridayNextConfig(getHostOpenClawConfigSnapshot(runtime.config));
|
|
459
|
+
setFridayNextLogLevel(cfg.logLevel);
|
|
450
460
|
|
|
451
461
|
// Resolve defaults from the OpenClaw agent config so settings are never left empty. Prefers the
|
|
452
462
|
// target agent's own model/thinking over the global defaults (see resolveAgentDefaults).
|
|
@@ -544,7 +554,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
544
554
|
}
|
|
545
555
|
},
|
|
546
556
|
onError: (err: unknown) => {
|
|
547
|
-
log("RUN_ERROR", normalizedDeviceId, runId, String(err));
|
|
557
|
+
log("RUN_ERROR", normalizedDeviceId, runId, String(err), "error");
|
|
548
558
|
sseEmitter.broadcastToRun(
|
|
549
559
|
runId,
|
|
550
560
|
{
|
|
@@ -588,7 +598,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
588
598
|
});
|
|
589
599
|
log("RUN_COMPLETE", normalizedDeviceId, runId);
|
|
590
600
|
} catch (err) {
|
|
591
|
-
log("RUN_ERROR", normalizedDeviceId, runId, String(err));
|
|
601
|
+
log("RUN_ERROR", normalizedDeviceId, runId, String(err), "error");
|
|
592
602
|
sseEmitter.broadcastToRun(
|
|
593
603
|
runId,
|
|
594
604
|
{
|
|
@@ -610,7 +620,7 @@ export async function handleMessages(req: IncomingMessage, res: ServerResponse):
|
|
|
610
620
|
};
|
|
611
621
|
|
|
612
622
|
runAgent().catch((err) => {
|
|
613
|
-
log("RUN_ERROR", normalizedDeviceId, runId, String(err));
|
|
623
|
+
log("RUN_ERROR", normalizedDeviceId, runId, String(err), "error");
|
|
614
624
|
sseEmitter.untrackRun(runId);
|
|
615
625
|
});
|
|
616
626
|
|
package/src/logging.ts
CHANGED
|
@@ -7,9 +7,20 @@ const levelOrder: Record<FridayNextLogLevel, number> = {
|
|
|
7
7
|
error: 40,
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// Process-wide active level, honored by every logger at call time. Handlers call
|
|
11
|
+
// setFridayNextLogLevel() once the friday-next channel config resolves, so
|
|
12
|
+
// `channels.friday-next.logLevel: "debug"` turns the full per-message trace back on.
|
|
13
|
+
let activeLevel: FridayNextLogLevel = "info";
|
|
14
|
+
|
|
15
|
+
export function setFridayNextLogLevel(level: FridayNextLogLevel): void {
|
|
16
|
+
activeLevel = level;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// The optional `level` arg is accepted for call-site compatibility but the effective
|
|
20
|
+
// threshold is the process-wide active level (single knob driven by config.logLevel).
|
|
21
|
+
export function createFridayNextLogger(scope: string, _level?: FridayNextLogLevel) {
|
|
11
22
|
const base = `[friday-next:${scope}]`;
|
|
12
|
-
const enabled = (current: FridayNextLogLevel) => levelOrder[current] >= levelOrder[
|
|
23
|
+
const enabled = (current: FridayNextLogLevel) => levelOrder[current] >= levelOrder[activeLevel];
|
|
13
24
|
return {
|
|
14
25
|
debug: (message: string) => {
|
|
15
26
|
if (enabled("debug")) console.debug(`${base} ${message}`);
|
package/src/runtime.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createPluginRuntimeStore } from "./vendor/runtime-store.js";
|
|
2
2
|
|
|
3
3
|
type FridayRuntime = {
|
|
4
|
-
|
|
4
|
+
// `current()` is the modern OpenClaw API; `loadConfig()` is the deprecated fallback
|
|
5
|
+
// kept for older gateways.
|
|
6
|
+
config: { current?: () => unknown; loadConfig?: () => unknown };
|
|
5
7
|
logger?: { info?: (...args: unknown[]) => void; warn?: (...args: unknown[]) => void };
|
|
6
8
|
};
|
|
7
9
|
|
|
@@ -66,6 +66,8 @@ export function setMockRuntime(opts: MockRuntimeOptions = {}): void {
|
|
|
66
66
|
};
|
|
67
67
|
setFridayNextRuntime({
|
|
68
68
|
config: {
|
|
69
|
+
// Mirror modern OpenClaw (current()) plus the deprecated alias so both paths resolve.
|
|
70
|
+
current: () => cfg,
|
|
69
71
|
loadConfig: () => cfg,
|
|
70
72
|
},
|
|
71
73
|
logger: {
|