@syengup/friday-channel-next 0.1.36 → 0.1.38
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/index.js +1 -1
- package/dist/src/agent/dispatch-bridge.d.ts +1 -1
- package/dist/src/agent/node-pairing-bridge.d.ts +11 -8
- package/dist/src/agent/node-pairing-bridge.js +6 -2
- package/dist/src/agent/operator-scope.d.ts +19 -0
- package/dist/src/agent/operator-scope.js +54 -0
- package/dist/src/agent/subagent-registry.js +0 -3
- package/dist/src/channel-actions.js +3 -1
- package/dist/src/channel.js +0 -2
- package/dist/src/collect-message-media-paths.js +10 -1
- package/dist/src/friday-session.js +34 -10
- package/dist/src/history/normalize-message.js +22 -8
- package/dist/src/http/handlers/agent-config.js +10 -4
- package/dist/src/http/handlers/cancel.js +4 -2
- package/dist/src/http/handlers/device-approve.js +3 -1
- package/dist/src/http/handlers/files-download.js +6 -8
- package/dist/src/http/handlers/files.js +1 -1
- package/dist/src/http/handlers/health.js +18 -4
- package/dist/src/http/handlers/history-messages.js +1 -1
- package/dist/src/http/handlers/history-sessions.js +5 -3
- package/dist/src/http/handlers/messages.js +34 -11
- package/dist/src/http/handlers/models-list.js +1 -1
- package/dist/src/http/handlers/nodes-approve.js +1 -6
- package/dist/src/http/handlers/plugin-info.js +1 -1
- package/dist/src/http/server.js +4 -2
- package/dist/src/link-preview/og-parse.js +3 -1
- package/dist/src/plugin-install-info.js +4 -1
- package/dist/src/session/session-manager.js +9 -3
- package/dist/src/session-usage-store.js +3 -1
- package/dist/src/skills-discovery.d.ts +5 -4
- package/dist/src/skills-discovery.js +27 -22
- package/dist/src/sse/offline-queue.js +4 -1
- package/dist/src/tool-catalog.js +2 -3
- package/dist/src/upgrade-runtime.d.ts +1 -1
- package/dist/src/version.js +3 -1
- package/index.ts +43 -35
- package/install.js +131 -43
- package/package.json +10 -1
- package/src/agent/abort-run.ts +2 -3
- package/src/agent/dispatch-bridge.ts +2 -1
- package/src/agent/media-bridge.ts +9 -2
- package/src/agent/node-pairing-bridge.ts +29 -15
- package/src/agent/operator-scope.test.ts +66 -0
- package/src/agent/operator-scope.ts +63 -0
- package/src/agent/run-usage-accumulator.ts +4 -2
- package/src/agent/subagent-registry.ts +0 -4
- package/src/agent-run-context-bridge.ts +3 -1
- package/src/channel-actions.test.ts +10 -4
- package/src/channel-actions.ts +3 -1
- package/src/channel.outbound.test.ts +18 -4
- package/src/channel.ts +121 -123
- package/src/collect-message-media-paths.ts +15 -6
- package/src/config.ts +1 -4
- package/src/e2e/agents-list.e2e.test.ts +9 -2
- package/src/e2e/attachments-inbound.e2e.test.ts +5 -1
- package/src/e2e/attachments-outbound.e2e.test.ts +7 -2
- package/src/e2e/auto-approve.integration.test.ts +13 -7
- package/src/e2e/cancel-reconnect-errors.e2e.test.ts +18 -3
- package/src/e2e/connect-and-connected.e2e.test.ts +5 -1
- package/src/e2e/offline-replay.e2e.test.ts +17 -3
- package/src/e2e/send-text.e2e.test.ts +11 -2
- package/src/e2e/slash-commands.e2e.test.ts +5 -1
- package/src/e2e/status-cors-auth.e2e.test.ts +11 -2
- package/src/e2e/subagent-smoke.e2e.test.ts +68 -28
- package/src/e2e/subagent.e2e.test.ts +136 -53
- package/src/e2e/tool-lifecycle.e2e.test.ts +5 -1
- package/src/friday-session.forward-agent.test.ts +44 -12
- package/src/friday-session.ts +44 -20
- package/src/history/normalize-message.test.ts +35 -8
- package/src/history/normalize-message.ts +24 -12
- package/src/history/read-transcript.ts +1 -4
- package/src/http/handlers/agent-config.test.ts +10 -3
- package/src/http/handlers/agent-config.ts +22 -8
- package/src/http/handlers/agents-list.test.ts +1 -5
- package/src/http/handlers/cancel.test.ts +12 -3
- package/src/http/handlers/cancel.ts +4 -2
- package/src/http/handlers/device-approve.test.ts +12 -3
- package/src/http/handlers/device-approve.ts +33 -21
- package/src/http/handlers/files-download.ts +17 -13
- package/src/http/handlers/files.test.ts +8 -2
- package/src/http/handlers/files.ts +21 -7
- package/src/http/handlers/health.test.ts +43 -11
- package/src/http/handlers/health.ts +22 -6
- package/src/http/handlers/history-messages.test.ts +51 -9
- package/src/http/handlers/history-messages.ts +4 -1
- package/src/http/handlers/history-sessions.test.ts +46 -9
- package/src/http/handlers/history-sessions.ts +5 -3
- package/src/http/handlers/history-set-title.test.ts +14 -5
- package/src/http/handlers/link-preview.test.ts +57 -16
- package/src/http/handlers/link-preview.ts +4 -1
- package/src/http/handlers/messages.test.ts +12 -8
- package/src/http/handlers/messages.ts +67 -19
- package/src/http/handlers/models-list.ts +14 -8
- package/src/http/handlers/nodes-approve.test.ts +15 -4
- package/src/http/handlers/nodes-approve.ts +38 -40
- package/src/http/handlers/plugin-info.ts +5 -6
- package/src/http/handlers/plugin-upgrade.ts +4 -1
- package/src/http/handlers/sse.ts +3 -1
- package/src/http/server.ts +9 -6
- package/src/link-preview/og-parse.test.ts +6 -2
- package/src/link-preview/og-parse.ts +10 -3
- package/src/link-preview/preview-service.ts +4 -1
- package/src/link-preview/ssrf-guard.test.ts +72 -15
- package/src/link-preview/ssrf-guard.ts +2 -1
- package/src/media-fetch.test.ts +7 -2
- package/src/media-fetch.ts +1 -2
- package/src/openclaw.d.ts +26 -9
- package/src/plugin-install-info.ts +20 -9
- package/src/run-metadata.ts +2 -1
- package/src/session/session-manager.ts +19 -11
- package/src/session-usage-snapshot.ts +3 -1
- package/src/session-usage-store.ts +3 -1
- package/src/skills-discovery.test.ts +14 -10
- package/src/skills-discovery.ts +43 -27
- package/src/sse/emitter.test.ts +1 -1
- package/src/sse/emitter.ts +9 -3
- package/src/sse/offline-queue.ts +17 -8
- package/src/test-support/app-simulator.ts +17 -3
- package/src/test-support/mock-dispatch.ts +17 -4
- package/src/thinking-levels.ts +3 -1
- package/src/tool-catalog.ts +16 -7
- package/src/upgrade-runtime.ts +4 -2
- package/src/version.ts +5 -1
- package/tsconfig.json +1 -1
|
@@ -58,12 +58,7 @@ export async function handleNodesApprove(req, res) {
|
|
|
58
58
|
if (pendingMatch) {
|
|
59
59
|
const requestId = pendingMatch.requestId;
|
|
60
60
|
log.info(`approving nodeId=${normalizedNodeId} requestId=${requestId}`);
|
|
61
|
-
const callerScopes = [
|
|
62
|
-
"operator.admin",
|
|
63
|
-
"operator.pairing",
|
|
64
|
-
"operator.read",
|
|
65
|
-
"operator.write",
|
|
66
|
-
];
|
|
61
|
+
const callerScopes = ["operator.admin", "operator.pairing", "operator.read", "operator.write"];
|
|
67
62
|
let approved;
|
|
68
63
|
try {
|
|
69
64
|
approved = await approveNodePairing(requestId, { callerScopes });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { extractBearerToken } from "../middleware/auth.js";
|
|
2
2
|
import { PLUGIN_VERSION } from "../../version.js";
|
|
3
|
-
import { fetchLatestVersion, getInstallSource, semverGreater
|
|
3
|
+
import { fetchLatestVersion, getInstallSource, semverGreater } from "../../plugin-install-info.js";
|
|
4
4
|
export async function handlePluginInfo(req, res) {
|
|
5
5
|
if (req.method !== "GET") {
|
|
6
6
|
res.statusCode = 405;
|
package/dist/src/http/server.js
CHANGED
|
@@ -65,7 +65,8 @@ async function handleFridayNextRoute(req, res) {
|
|
|
65
65
|
if (req.method === "POST" && pathname === "/friday-next/nodes-approve") {
|
|
66
66
|
return await handleNodesApprove(req, res);
|
|
67
67
|
}
|
|
68
|
-
if ((req.method === "PUT" || req.method === "GET") &&
|
|
68
|
+
if ((req.method === "PUT" || req.method === "GET") &&
|
|
69
|
+
pathname === "/friday-next/sessions/settings") {
|
|
69
70
|
return await handleSessionsSettings(req, res);
|
|
70
71
|
}
|
|
71
72
|
if (req.method === "GET" && pathname === "/friday-next/models") {
|
|
@@ -106,7 +107,8 @@ async function handleFridayNextRoute(req, res) {
|
|
|
106
107
|
return await handleHistoryMessages(req, res);
|
|
107
108
|
}
|
|
108
109
|
// Route: PUT /friday-next/sessions/title (sync app session name → server displayName)
|
|
109
|
-
if ((req.method === "PUT" || req.method === "POST") &&
|
|
110
|
+
if ((req.method === "PUT" || req.method === "POST") &&
|
|
111
|
+
pathname === "/friday-next/sessions/title") {
|
|
110
112
|
return await handleHistorySetTitle(req, res);
|
|
111
113
|
}
|
|
112
114
|
// Route: GET /friday-next/link-preview?url=... (Open Graph metadata for preview cards)
|
|
@@ -78,7 +78,9 @@ export function parseOpenGraph(html, baseUrl) {
|
|
|
78
78
|
let metaDescription = null;
|
|
79
79
|
for (const match of slice.matchAll(META_TAG_RE)) {
|
|
80
80
|
const tag = match[0];
|
|
81
|
-
const key = (attributeValue(tag, "property") ?? attributeValue(tag, "name"))
|
|
81
|
+
const key = (attributeValue(tag, "property") ?? attributeValue(tag, "name"))
|
|
82
|
+
?.trim()
|
|
83
|
+
.toLowerCase();
|
|
82
84
|
if (!key)
|
|
83
85
|
continue;
|
|
84
86
|
const content = attributeValue(tag, "content");
|
|
@@ -87,7 +87,10 @@ export async function fetchLatestVersion(nowMs) {
|
|
|
87
87
|
const controller = new AbortController();
|
|
88
88
|
const timer = setTimeout(() => controller.abort(), 5000);
|
|
89
89
|
try {
|
|
90
|
-
const res = await fetch(`https://registry.npmjs.org/${PLUGIN_PACKAGE_NAME}/latest`, {
|
|
90
|
+
const res = await fetch(`https://registry.npmjs.org/${PLUGIN_PACKAGE_NAME}/latest`, {
|
|
91
|
+
signal: controller.signal,
|
|
92
|
+
headers: { Accept: "application/json" },
|
|
93
|
+
});
|
|
91
94
|
if (res.ok) {
|
|
92
95
|
const body = (await res.json());
|
|
93
96
|
if (typeof body.version === "string" && body.version)
|
|
@@ -118,7 +118,11 @@ export function setSessionSettings(sessionKey, settings, historyDir) {
|
|
|
118
118
|
return {};
|
|
119
119
|
upsertSessionEntry(data, fileKey, sessionKey);
|
|
120
120
|
const fieldKeys = [
|
|
121
|
-
"reasoningLevel",
|
|
121
|
+
"reasoningLevel",
|
|
122
|
+
"thinkingLevel",
|
|
123
|
+
"modelRef",
|
|
124
|
+
"providerOverride",
|
|
125
|
+
"modelOverride",
|
|
122
126
|
];
|
|
123
127
|
let updated = false;
|
|
124
128
|
for (const key of fieldKeys) {
|
|
@@ -193,7 +197,7 @@ export function resolveAgentDefaults(sessionKey) {
|
|
|
193
197
|
const ocCfg = (forwardRt.getConfig() ?? {});
|
|
194
198
|
const agents = ocCfg.agents;
|
|
195
199
|
const targetAgentId = agentIdFromSessionKey(sessionKey);
|
|
196
|
-
const agentEntry = agents?.list?.find((a) => agentIdFromSessionKey(`agent:${String(a
|
|
200
|
+
const agentEntry = agents?.list?.find((a) => agentIdFromSessionKey(`agent:${typeof a?.id === "string" ? a.id : typeof a?.id === "number" ? String(a.id) : ""}:x`) === targetAgentId);
|
|
197
201
|
const agentModel = agentEntry?.model;
|
|
198
202
|
const perAgentModel = typeof agentModel === "string"
|
|
199
203
|
? agentModel
|
|
@@ -204,7 +208,9 @@ export function resolveAgentDefaults(sessionKey) {
|
|
|
204
208
|
const agentDefaults = agents?.defaults;
|
|
205
209
|
const model = agentDefaults?.model;
|
|
206
210
|
const globalModel = typeof model?.primary === "string" ? model.primary : undefined;
|
|
207
|
-
const globalThinking = typeof agentDefaults?.thinkingDefault === "string"
|
|
211
|
+
const globalThinking = typeof agentDefaults?.thinkingDefault === "string"
|
|
212
|
+
? agentDefaults.thinkingDefault
|
|
213
|
+
: undefined;
|
|
208
214
|
return { model: perAgentModel ?? globalModel, thinking: perAgentThinking ?? globalThinking };
|
|
209
215
|
}
|
|
210
216
|
catch {
|
|
@@ -24,7 +24,9 @@ export function readSessionUsageSnapshotFromStore(sessionKeyForStore) {
|
|
|
24
24
|
const cfg = access.getConfig();
|
|
25
25
|
const storeConfig = cfg?.session?.store;
|
|
26
26
|
const canonical = toSessionStoreKey(sessionKeyForStore);
|
|
27
|
-
const storePath = access.resolveStorePath(storeConfig, {
|
|
27
|
+
const storePath = access.resolveStorePath(storeConfig, {
|
|
28
|
+
agentId: agentIdFromSessionKey(canonical),
|
|
29
|
+
});
|
|
28
30
|
const store = access.loadSessionStore(storePath, { skipCache: true });
|
|
29
31
|
const entry = store[canonical] ?? store[sessionKeyForStore.trim()];
|
|
30
32
|
if (!entry || typeof entry !== "object")
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* marker core's `loadSkillsFromDir` uses).
|
|
13
13
|
*
|
|
14
14
|
* Each discovered skill is tagged with a `source` category for the UI:
|
|
15
|
-
* - workspace : the agent's own
|
|
15
|
+
* - workspace : the TARGET agent's own workspace `skills/` only — mirroring ControlUI,
|
|
16
|
+
* which scans the single workspace resolved for that agent and never folds
|
|
17
|
+
* in another agent's workspace (main is just another agent, not a shared pool)
|
|
16
18
|
* - installed : managed skills dir (`<configDir>/skills`, sibling of the workspace)
|
|
17
19
|
* - built-in : bundled core skills (`<openclaw>/skills`)
|
|
18
20
|
* - extra : skills from ENABLED extensions (`<openclaw>/dist/extensions/<ext>/skills`,
|
|
@@ -49,9 +51,8 @@ export declare function resolveOpenClawRoot(): string | null;
|
|
|
49
51
|
export declare function enabledExtensionNames(cfg: unknown): Set<string>;
|
|
50
52
|
/**
|
|
51
53
|
* Full set of skills `agentId` can load, sorted by id, each tagged with its source
|
|
52
|
-
* category. Aggregates the agent's workspace, the
|
|
53
|
-
*
|
|
54
|
-
* and failure-tolerant.
|
|
54
|
+
* category. Aggregates the TARGET agent's own workspace, the managed dir, config extra
|
|
55
|
+
* dirs, and bundled core/extension skills. Every source is optional and failure-tolerant.
|
|
55
56
|
*/
|
|
56
57
|
export declare function discoverAvailableSkills(cfg: unknown, agentId: string): DiscoveredSkill[];
|
|
57
58
|
/** Test-only: reset the cached openclaw root. */
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* marker core's `loadSkillsFromDir` uses).
|
|
13
13
|
*
|
|
14
14
|
* Each discovered skill is tagged with a `source` category for the UI:
|
|
15
|
-
* - workspace : the agent's own
|
|
15
|
+
* - workspace : the TARGET agent's own workspace `skills/` only — mirroring ControlUI,
|
|
16
|
+
* which scans the single workspace resolved for that agent and never folds
|
|
17
|
+
* in another agent's workspace (main is just another agent, not a shared pool)
|
|
16
18
|
* - installed : managed skills dir (`<configDir>/skills`, sibling of the workspace)
|
|
17
19
|
* - built-in : bundled core skills (`<openclaw>/skills`)
|
|
18
20
|
* - extra : skills from ENABLED extensions (`<openclaw>/dist/extensions/<ext>/skills`,
|
|
@@ -200,34 +202,37 @@ function resolveDefaultAgentId(cfg) {
|
|
|
200
202
|
}
|
|
201
203
|
/**
|
|
202
204
|
* Full set of skills `agentId` can load, sorted by id, each tagged with its source
|
|
203
|
-
* category. Aggregates the agent's workspace, the
|
|
204
|
-
*
|
|
205
|
-
* and failure-tolerant.
|
|
205
|
+
* category. Aggregates the TARGET agent's own workspace, the managed dir, config extra
|
|
206
|
+
* dirs, and bundled core/extension skills. Every source is optional and failure-tolerant.
|
|
206
207
|
*/
|
|
207
208
|
export function discoverAvailableSkills(cfg, agentId) {
|
|
208
209
|
const c = cfg;
|
|
209
210
|
const resolveWs = getFridayAgentForwardRuntime()?.resolveAgentWorkspaceDir;
|
|
210
211
|
const sources = [];
|
|
211
212
|
if (resolveWs) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
213
|
+
// Workspace skills come ONLY from the target agent's own workspace — matching ControlUI's
|
|
214
|
+
// `resolveSkillsAgentWorkspace`→`buildWorkspaceSkillStatus(workspaceDir)`, which scans the
|
|
215
|
+
// single resolved workspace. Folding in the default agent's workspace (the old behavior)
|
|
216
|
+
// leaked main's skills into every other agent's catalog.
|
|
217
|
+
try {
|
|
218
|
+
const ws = resolveWs(cfg, agentId);
|
|
219
|
+
if (ws)
|
|
220
|
+
sources.push({ dir: path.join(ws, "skills"), source: "workspace" });
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// skip unresolvable workspace
|
|
224
|
+
}
|
|
225
|
+
// Managed skills dir: `<configDir>/skills`. It is agent-independent; anchor it off the
|
|
226
|
+
// DEFAULT agent's workspace parent (the default workspace lives directly under configDir,
|
|
227
|
+
// whereas non-default workspaces may be nested under it).
|
|
228
|
+
try {
|
|
229
|
+
const defaultWs = resolveWs(cfg, resolveDefaultAgentId(c));
|
|
230
|
+
if (defaultWs)
|
|
231
|
+
sources.push({ dir: path.join(path.dirname(defaultWs), "skills"), source: "installed" });
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// skip unresolvable managed dir
|
|
227
235
|
}
|
|
228
|
-
// Managed skills dir: `<configDir>/skills`, the workspace's parent sibling.
|
|
229
|
-
if (defaultWs)
|
|
230
|
-
sources.push({ dir: path.join(path.dirname(defaultWs), "skills"), source: "installed" });
|
|
231
236
|
}
|
|
232
237
|
const extraDirs = c?.skills?.load?.extraDirs;
|
|
233
238
|
if (Array.isArray(extraDirs)) {
|
|
@@ -116,7 +116,10 @@ export class FridaySseOfflineQueue {
|
|
|
116
116
|
continue;
|
|
117
117
|
try {
|
|
118
118
|
const o = JSON.parse(line);
|
|
119
|
-
if (typeof o.id === "number" &&
|
|
119
|
+
if (typeof o.id === "number" &&
|
|
120
|
+
typeof o.event === "string" &&
|
|
121
|
+
o.data &&
|
|
122
|
+
typeof o.data === "object") {
|
|
120
123
|
all.push(o);
|
|
121
124
|
}
|
|
122
125
|
}
|
package/dist/src/tool-catalog.js
CHANGED
|
@@ -108,8 +108,7 @@ function readStringArray(value) {
|
|
|
108
108
|
}
|
|
109
109
|
/** Read an agent's `tools` config block from the host config. */
|
|
110
110
|
function findAgentTools(cfg, agentId) {
|
|
111
|
-
const list = cfg?.agents
|
|
112
|
-
?.list;
|
|
111
|
+
const list = cfg?.agents?.list;
|
|
113
112
|
if (!Array.isArray(list))
|
|
114
113
|
return undefined;
|
|
115
114
|
const entry = list.find((a) => a && typeof a === "object" && normalizeAgentId(a.id) === agentId);
|
|
@@ -154,7 +153,7 @@ export async function buildAgentToolsCatalog(cfg, agentId) {
|
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
155
|
const tools = findAgentTools(cfg, agentId);
|
|
157
|
-
const profile =
|
|
156
|
+
const profile = typeof tools?.profile === "string" && tools.profile.trim() ? tools.profile.trim() : null;
|
|
158
157
|
const allow = new Set(readStringArray(tools?.allow));
|
|
159
158
|
const alsoAllow = new Set(readStringArray(tools?.alsoAllow));
|
|
160
159
|
const deny = new Set(readStringArray(tools?.deny));
|
|
@@ -30,7 +30,7 @@ export type UpgradeRuntime = {
|
|
|
30
30
|
/** Mutate the config file; `afterWrite: { mode: "restart" }` triggers a safe gateway restart. */
|
|
31
31
|
mutateConfigFile: (params: {
|
|
32
32
|
afterWrite: ConfigAfterWrite;
|
|
33
|
-
mutate: (draft: unknown) => unknown
|
|
33
|
+
mutate: (draft: unknown) => unknown;
|
|
34
34
|
}) => Promise<unknown>;
|
|
35
35
|
/**
|
|
36
36
|
* Filesystem path of THIS loaded plugin (`api.source`). Used to infer the install
|
package/dist/src/version.js
CHANGED
|
@@ -20,7 +20,9 @@ function resolvePluginVersion() {
|
|
|
20
20
|
const path = fileURLToPath(new URL(rel, import.meta.url));
|
|
21
21
|
const raw = readFileSync(path, "utf8");
|
|
22
22
|
const pkg = JSON.parse(raw);
|
|
23
|
-
if (pkg.name === "@syengup/friday-channel-next" &&
|
|
23
|
+
if (pkg.name === "@syengup/friday-channel-next" &&
|
|
24
|
+
typeof pkg.version === "string" &&
|
|
25
|
+
pkg.version) {
|
|
24
26
|
return pkg.version;
|
|
25
27
|
}
|
|
26
28
|
}
|
package/index.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import type { ChannelPlugin } from "openclaw/plugin-sdk/core";
|
|
2
1
|
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
|
3
2
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
4
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
PluginHookBeforeToolCallEvent,
|
|
5
|
+
PluginHookAfterToolCallEvent,
|
|
6
|
+
PluginHookToolContext,
|
|
7
|
+
} from "openclaw/plugin-sdk/plugins/types";
|
|
5
8
|
import { fridayNextChannelPlugin } from "./src/channel.js";
|
|
6
9
|
import { setFridayNextRuntime } from "./src/runtime.js";
|
|
7
10
|
import { resolveFridayNextConfig } from "./src/config.js";
|
|
@@ -44,7 +47,7 @@ function deviceIdFromToolContext(ctx: PluginHookToolContext): string | null {
|
|
|
44
47
|
const sk =
|
|
45
48
|
typeof ctx.sessionKey === "string" && ctx.sessionKey.trim()
|
|
46
49
|
? ctx.sessionKey.trim()
|
|
47
|
-
: (ctx.runId ? getOpenClawAgentRunContext(ctx.runId)?.sessionKey?.trim() : undefined) ?? "";
|
|
50
|
+
: ((ctx.runId ? getOpenClawAgentRunContext(ctx.runId)?.sessionKey?.trim() : undefined) ?? "");
|
|
48
51
|
if (sk) {
|
|
49
52
|
const d = resolveFridayDeviceIdForSessionKey(sk);
|
|
50
53
|
if (d) return d;
|
|
@@ -83,7 +86,7 @@ export default defineChannelPluginEntry({
|
|
|
83
86
|
id: "friday-next",
|
|
84
87
|
name: "Friday Next",
|
|
85
88
|
description: "Friday Next Apple 应用通道",
|
|
86
|
-
plugin: fridayNextChannelPlugin
|
|
89
|
+
plugin: fridayNextChannelPlugin,
|
|
87
90
|
setRuntime: setFridayNextRuntime,
|
|
88
91
|
registerFull: (api: OpenClawPluginApi) => {
|
|
89
92
|
setFridayAgentForwardRuntime(api);
|
|
@@ -93,7 +96,9 @@ export default defineChannelPluginEntry({
|
|
|
93
96
|
lastApiRoutesRegistered = new WeakRef(api);
|
|
94
97
|
registerFridayNextHttpRoutes(api);
|
|
95
98
|
} else {
|
|
96
|
-
const cfg = resolveFridayNextConfig(
|
|
99
|
+
const cfg = resolveFridayNextConfig(
|
|
100
|
+
getHostOpenClawConfigSnapshot(getFridayNextRuntime().config),
|
|
101
|
+
);
|
|
97
102
|
sseEmitter.setBacklogLimit(cfg.sseBacklogPerDevice);
|
|
98
103
|
}
|
|
99
104
|
|
|
@@ -147,36 +152,39 @@ export default defineChannelPluginEntry({
|
|
|
147
152
|
};
|
|
148
153
|
});
|
|
149
154
|
|
|
150
|
-
api.on(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
155
|
+
api.on(
|
|
156
|
+
"before_tool_call",
|
|
157
|
+
(event: PluginHookBeforeToolCallEvent, ctx: PluginHookToolContext) => {
|
|
158
|
+
if (!shouldForwardToolEventToFriday(ctx)) return;
|
|
159
|
+
const deviceId = deviceIdFromToolContext(ctx);
|
|
160
|
+
const runId = ctx.runId ?? "(unknown)";
|
|
161
|
+
|
|
162
|
+
const logLine = (detail: string) => {
|
|
163
|
+
hookLogger.debug(
|
|
164
|
+
`[TOOL_CALL] toolName=${event.toolName} runId=${runId} deviceId=${deviceId ?? "(unknown)"} detail=${detail}`,
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
if (!deviceId) {
|
|
169
|
+
logLine("SKIP_no_deviceId");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
logLine("START");
|
|
174
|
+
sseEmitter.broadcastToolEvent(deviceId.toUpperCase(), runId, {
|
|
175
|
+
type: "tool-hook",
|
|
176
|
+
data: {
|
|
177
|
+
when: "before",
|
|
178
|
+
runId,
|
|
179
|
+
deviceId: deviceId.toUpperCase(),
|
|
180
|
+
sessionKey: ctx.sessionKey,
|
|
181
|
+
toolName: event.toolName,
|
|
182
|
+
params: event.params,
|
|
183
|
+
ts: Date.now(),
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
);
|
|
180
188
|
|
|
181
189
|
api.on("after_tool_call", (event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext) => {
|
|
182
190
|
if (!shouldForwardToolEventToFriday(ctx)) return;
|