@syengup/friday-channel-next 0.1.4 → 0.1.5
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/http/handlers/device-approve.js +14 -0
- package/dist/src/http/middleware/cors.js +1 -1
- package/dist/src/http/server.js +0 -4
- package/dist/src/session/session-manager.d.ts +0 -7
- package/dist/src/session/session-manager.js +1 -38
- package/package.json +1 -1
- package/src/http/handlers/device-approve.ts +17 -0
- package/src/http/middleware/cors.ts +1 -1
- package/src/http/server.ts +0 -5
- package/src/session/session-manager.ts +1 -45
- package/src/http/handlers/sessions-delete.ts +0 -59
|
@@ -45,6 +45,20 @@ export async function handleDeviceApprove(req, res) {
|
|
|
45
45
|
}
|
|
46
46
|
const match = pairing.pending.find((entry) => entry.deviceId.trim().toUpperCase() === normalizedDeviceId);
|
|
47
47
|
if (!match) {
|
|
48
|
+
// Gateway may have already auto-approved the device (e.g. mode="local").
|
|
49
|
+
// Check the paired list before returning 404.
|
|
50
|
+
const pairedDevice = (pairing.paired ?? []).find((entry) => entry.deviceId.trim().toUpperCase() === normalizedDeviceId);
|
|
51
|
+
if (pairedDevice) {
|
|
52
|
+
res.statusCode = 200;
|
|
53
|
+
res.setHeader("Content-Type", "application/json");
|
|
54
|
+
res.end(JSON.stringify({
|
|
55
|
+
ok: true,
|
|
56
|
+
deviceId: normalizedDeviceId,
|
|
57
|
+
alreadyApproved: true,
|
|
58
|
+
approvedAtMs: pairedDevice.approvedAtMs,
|
|
59
|
+
}));
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
48
62
|
res.statusCode = 404;
|
|
49
63
|
res.setHeader("Content-Type", "application/json");
|
|
50
64
|
res.end(JSON.stringify({
|
|
@@ -7,5 +7,5 @@ export function applyCorsHeaders(res) {
|
|
|
7
7
|
return;
|
|
8
8
|
res.setHeader("Access-Control-Allow-Origin", cfg.corsAllowOrigin || "*");
|
|
9
9
|
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Last-Event-ID");
|
|
10
|
-
res.setHeader("Access-Control-Allow-Methods", "GET,POST,
|
|
10
|
+
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
|
|
11
11
|
}
|
package/dist/src/http/server.js
CHANGED
|
@@ -11,7 +11,6 @@ import { handleFilesDownload } from "./handlers/files-download.js";
|
|
|
11
11
|
import { handleCancel } from "./handlers/cancel.js";
|
|
12
12
|
import { handleDeviceApprove } from "./handlers/device-approve.js";
|
|
13
13
|
import { handleNodesApprove } from "./handlers/nodes-approve.js";
|
|
14
|
-
import { handleSessionsDelete } from "./handlers/sessions-delete.js";
|
|
15
14
|
import { handleSessionsSettings } from "./handlers/sessions-settings.js";
|
|
16
15
|
import { handleModelsList } from "./handlers/models-list.js";
|
|
17
16
|
import { handleStatus } from "./handlers/status.js";
|
|
@@ -56,9 +55,6 @@ async function handleFridayNextRoute(req, res) {
|
|
|
56
55
|
if (req.method === "POST" && pathname === "/friday-next/nodes-approve") {
|
|
57
56
|
return await handleNodesApprove(req, res);
|
|
58
57
|
}
|
|
59
|
-
if (req.method === "DELETE" && pathname === "/friday-next/sessions") {
|
|
60
|
-
return await handleSessionsDelete(req, res);
|
|
61
|
-
}
|
|
62
58
|
if ((req.method === "PUT" || req.method === "GET") && pathname === "/friday-next/sessions/settings") {
|
|
63
59
|
return await handleSessionsSettings(req, res);
|
|
64
60
|
}
|
|
@@ -4,13 +4,6 @@ export declare function splitModelRef(modelRef: string): {
|
|
|
4
4
|
};
|
|
5
5
|
export declare function toSessionStoreKey(rawSessionKey: string): string;
|
|
6
6
|
export declare function ensureSessionLevels(sessionKey: string, reasoningLevel: string, thinkingLevel: string, historyDir?: string): void;
|
|
7
|
-
export declare function resolveSessionsDir(historyDir?: string): string;
|
|
8
|
-
export interface DeleteSessionResult {
|
|
9
|
-
sessionKey: string;
|
|
10
|
-
sessionId?: string;
|
|
11
|
-
transcriptDeleted?: boolean;
|
|
12
|
-
}
|
|
13
|
-
export declare function deleteFridaySession(sessionKey: string, historyDir?: string): DeleteSessionResult;
|
|
14
7
|
export interface FridaySessionSettings {
|
|
15
8
|
reasoningLevel?: string;
|
|
16
9
|
thinkingLevel?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import os from "node:os";
|
|
3
|
-
import { readFileSync, writeFileSync
|
|
3
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
const FRIDAY_AGENT_ID = "main";
|
|
5
5
|
const SESSION_ID_RE = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
|
|
6
6
|
function deriveOpenClawBaseDir(historyDir) {
|
|
@@ -96,43 +96,6 @@ function upsertSessionEntry(data, fileKey, sessionKey) {
|
|
|
96
96
|
export function ensureSessionLevels(sessionKey, reasoningLevel, thinkingLevel, historyDir) {
|
|
97
97
|
setSessionSettings(sessionKey, { reasoningLevel, thinkingLevel }, historyDir);
|
|
98
98
|
}
|
|
99
|
-
export function resolveSessionsDir(historyDir) {
|
|
100
|
-
const base = deriveOpenClawBaseDir(historyDir);
|
|
101
|
-
return join(base, "agents/main/sessions");
|
|
102
|
-
}
|
|
103
|
-
export function deleteFridaySession(sessionKey, historyDir) {
|
|
104
|
-
const result = { sessionKey };
|
|
105
|
-
const sessionsFile = resolveSessionsFilePath(historyDir);
|
|
106
|
-
const data = readSessionsData(sessionsFile);
|
|
107
|
-
if (!data)
|
|
108
|
-
return result;
|
|
109
|
-
const fileKey = toSessionStoreKey(sessionKey);
|
|
110
|
-
const entry = data[fileKey];
|
|
111
|
-
if (!entry)
|
|
112
|
-
return result;
|
|
113
|
-
const sessionId = typeof entry["sessionId"] === "string" ? entry["sessionId"] : undefined;
|
|
114
|
-
const sessionFilePath = typeof entry["sessionFile"] === "string" ? entry["sessionFile"] : undefined;
|
|
115
|
-
result.sessionId = sessionId;
|
|
116
|
-
if (sessionFilePath) {
|
|
117
|
-
try {
|
|
118
|
-
unlinkSync(sessionFilePath);
|
|
119
|
-
result.transcriptDeleted = true;
|
|
120
|
-
}
|
|
121
|
-
catch { /* gone already */ }
|
|
122
|
-
}
|
|
123
|
-
if (sessionId) {
|
|
124
|
-
const dir = resolveSessionsDir(historyDir);
|
|
125
|
-
for (const suffix of [".trajectory.jsonl", ".trajectory-path.json"]) {
|
|
126
|
-
try {
|
|
127
|
-
unlinkSync(join(dir, `${sessionId}${suffix}`));
|
|
128
|
-
}
|
|
129
|
-
catch { /* optional */ }
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
delete data[fileKey];
|
|
133
|
-
writeSessionsData(sessionsFile, data);
|
|
134
|
-
return result;
|
|
135
|
-
}
|
|
136
99
|
export function setSessionSettings(sessionKey, settings, historyDir) {
|
|
137
100
|
try {
|
|
138
101
|
const sessionsFile = resolveSessionsFilePath(historyDir);
|
package/package.json
CHANGED
|
@@ -59,6 +59,23 @@ export async function handleDeviceApprove(
|
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
if (!match) {
|
|
62
|
+
// Gateway may have already auto-approved the device (e.g. mode="local").
|
|
63
|
+
// Check the paired list before returning 404.
|
|
64
|
+
const pairedDevice = (pairing.paired ?? []).find(
|
|
65
|
+
(entry) => entry.deviceId.trim().toUpperCase() === normalizedDeviceId,
|
|
66
|
+
);
|
|
67
|
+
if (pairedDevice) {
|
|
68
|
+
res.statusCode = 200;
|
|
69
|
+
res.setHeader("Content-Type", "application/json");
|
|
70
|
+
res.end(JSON.stringify({
|
|
71
|
+
ok: true,
|
|
72
|
+
deviceId: normalizedDeviceId,
|
|
73
|
+
alreadyApproved: true,
|
|
74
|
+
approvedAtMs: (pairedDevice as any).approvedAtMs,
|
|
75
|
+
}));
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
62
79
|
res.statusCode = 404;
|
|
63
80
|
res.setHeader("Content-Type", "application/json");
|
|
64
81
|
res.end(JSON.stringify({
|
|
@@ -8,5 +8,5 @@ export function applyCorsHeaders(res: ServerResponse): void {
|
|
|
8
8
|
if (!cfg.corsEnabled) return;
|
|
9
9
|
res.setHeader("Access-Control-Allow-Origin", cfg.corsAllowOrigin || "*");
|
|
10
10
|
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Last-Event-ID");
|
|
11
|
-
res.setHeader("Access-Control-Allow-Methods", "GET,POST,
|
|
11
|
+
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
|
|
12
12
|
}
|
package/src/http/server.ts
CHANGED
|
@@ -13,7 +13,6 @@ import { handleFilesDownload } from "./handlers/files-download.js";
|
|
|
13
13
|
import { handleCancel } from "./handlers/cancel.js";
|
|
14
14
|
import { handleDeviceApprove } from "./handlers/device-approve.js";
|
|
15
15
|
import { handleNodesApprove } from "./handlers/nodes-approve.js";
|
|
16
|
-
import { handleSessionsDelete } from "./handlers/sessions-delete.js";
|
|
17
16
|
import { handleSessionsSettings } from "./handlers/sessions-settings.js";
|
|
18
17
|
import { handleModelsList } from "./handlers/models-list.js";
|
|
19
18
|
import { handleStatus } from "./handlers/status.js";
|
|
@@ -70,10 +69,6 @@ async function handleFridayNextRoute(
|
|
|
70
69
|
return await handleNodesApprove(req, res);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
if (req.method === "DELETE" && pathname === "/friday-next/sessions") {
|
|
74
|
-
return await handleSessionsDelete(req, res);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
72
|
if ((req.method === "PUT" || req.method === "GET") && pathname === "/friday-next/sessions/settings") {
|
|
78
73
|
return await handleSessionsSettings(req, res);
|
|
79
74
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import os from "node:os";
|
|
3
|
-
import { readFileSync, writeFileSync
|
|
3
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
|
|
5
5
|
const FRIDAY_AGENT_ID = "main";
|
|
6
6
|
const SESSION_ID_RE = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
|
|
@@ -111,50 +111,6 @@ export function ensureSessionLevels(
|
|
|
111
111
|
setSessionSettings(sessionKey, { reasoningLevel, thinkingLevel }, historyDir);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
export function resolveSessionsDir(historyDir?: string): string {
|
|
115
|
-
const base = deriveOpenClawBaseDir(historyDir);
|
|
116
|
-
return join(base, "agents/main/sessions");
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export interface DeleteSessionResult {
|
|
120
|
-
sessionKey: string;
|
|
121
|
-
sessionId?: string;
|
|
122
|
-
transcriptDeleted?: boolean;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function deleteFridaySession(
|
|
126
|
-
sessionKey: string,
|
|
127
|
-
historyDir?: string,
|
|
128
|
-
): DeleteSessionResult {
|
|
129
|
-
const result: DeleteSessionResult = { sessionKey };
|
|
130
|
-
const sessionsFile = resolveSessionsFilePath(historyDir);
|
|
131
|
-
const data = readSessionsData(sessionsFile);
|
|
132
|
-
if (!data) return result;
|
|
133
|
-
|
|
134
|
-
const fileKey = toSessionStoreKey(sessionKey);
|
|
135
|
-
const entry = data[fileKey];
|
|
136
|
-
if (!entry) return result;
|
|
137
|
-
|
|
138
|
-
const sessionId = typeof entry["sessionId"] === "string" ? entry["sessionId"] : undefined;
|
|
139
|
-
const sessionFilePath = typeof entry["sessionFile"] === "string" ? entry["sessionFile"] : undefined;
|
|
140
|
-
result.sessionId = sessionId;
|
|
141
|
-
|
|
142
|
-
if (sessionFilePath) {
|
|
143
|
-
try { unlinkSync(sessionFilePath); result.transcriptDeleted = true; } catch { /* gone already */ }
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (sessionId) {
|
|
147
|
-
const dir = resolveSessionsDir(historyDir);
|
|
148
|
-
for (const suffix of [".trajectory.jsonl", ".trajectory-path.json"]) {
|
|
149
|
-
try { unlinkSync(join(dir, `${sessionId}${suffix}`)); } catch { /* optional */ }
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
delete data[fileKey];
|
|
154
|
-
writeSessionsData(sessionsFile, data);
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
114
|
export interface FridaySessionSettings {
|
|
159
115
|
reasoningLevel?: string;
|
|
160
116
|
thinkingLevel?: string;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
-
import { deleteFridaySession, toSessionStoreKey } from "../../session/session-manager.js";
|
|
3
|
-
import { getActiveRunIds } from "../../agent/active-runs.js";
|
|
4
|
-
import { abortRun } from "../../agent/abort-run.js";
|
|
5
|
-
import { getRunRoute } from "../../run-metadata.js";
|
|
6
|
-
import { sseEmitter } from "../../sse/emitter.js";
|
|
7
|
-
import { readJsonBody } from "../middleware/body.js";
|
|
8
|
-
import { extractBearerToken } from "../middleware/auth.js";
|
|
9
|
-
|
|
10
|
-
async function cancelActiveRunsForSession(sessionKey: string): Promise<string[]> {
|
|
11
|
-
const storeKey = toSessionStoreKey(sessionKey);
|
|
12
|
-
const cancelled: string[] = [];
|
|
13
|
-
for (const runId of getActiveRunIds()) {
|
|
14
|
-
const route = getRunRoute(runId);
|
|
15
|
-
if (route?.sessionKey === storeKey) {
|
|
16
|
-
await abortRun(runId);
|
|
17
|
-
sseEmitter.untrackRun(runId);
|
|
18
|
-
cancelled.push(runId);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return cancelled;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function handleSessionsDelete(
|
|
25
|
-
req: IncomingMessage,
|
|
26
|
-
res: ServerResponse,
|
|
27
|
-
): Promise<boolean> {
|
|
28
|
-
if (req.method !== "DELETE") {
|
|
29
|
-
res.statusCode = 405;
|
|
30
|
-
res.setHeader("Content-Type", "application/json");
|
|
31
|
-
res.end(JSON.stringify({ error: "Method Not Allowed" }));
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const token = extractBearerToken(req);
|
|
36
|
-
if (!token) {
|
|
37
|
-
res.statusCode = 401;
|
|
38
|
-
res.setHeader("Content-Type", "application/json");
|
|
39
|
-
res.end(JSON.stringify({ error: "Unauthorized: bearer token mismatch" }));
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const body = await readJsonBody(req);
|
|
44
|
-
const sessionKey = typeof body?.sessionKey === "string" ? body.sessionKey.trim() : "";
|
|
45
|
-
if (!sessionKey) {
|
|
46
|
-
res.statusCode = 400;
|
|
47
|
-
res.setHeader("Content-Type", "application/json");
|
|
48
|
-
res.end(JSON.stringify({ error: "Missing required field: sessionKey" }));
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const cancelledRuns = await cancelActiveRunsForSession(sessionKey);
|
|
53
|
-
const result = deleteFridaySession(sessionKey);
|
|
54
|
-
|
|
55
|
-
res.statusCode = 200;
|
|
56
|
-
res.setHeader("Content-Type", "application/json");
|
|
57
|
-
res.end(JSON.stringify({ ok: true, ...result, cancelledRuns }));
|
|
58
|
-
return true;
|
|
59
|
-
}
|