@syengup/friday-channel-next 0.0.13 → 0.0.14

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/install.js CHANGED
@@ -46,13 +46,19 @@ function isRunningFromNpmPackage() {
46
46
 
47
47
  // --------------- prerequisites ---------------
48
48
 
49
- const required = ["pnpm", "node", "openclaw"];
49
+ const required = ["node", "openclaw"];
50
50
  const missing = required.filter((c) => !has(c));
51
51
  if (missing.length) {
52
52
  missing.forEach((c) => err(`${c} is required but not found. Install it first.`));
53
53
  process.exit(1);
54
54
  }
55
55
 
56
+ const PKG = has("pnpm") ? "pnpm" : has("npm") ? "npm" : null;
57
+ if (!PKG) {
58
+ err("pnpm or npm is required but not found. Install one first.");
59
+ process.exit(1);
60
+ }
61
+
56
62
  if (!existsSync(OPENCLAW_CONFIG)) {
57
63
  err(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);
58
64
  err("Make sure OpenClaw is installed and has been run at least once.");
@@ -88,10 +94,10 @@ process.chdir(PLUGIN_DIR);
88
94
  // --------------- install + build ---------------
89
95
 
90
96
  log("Installing dependencies...");
91
- execSync("pnpm install", { stdio: "inherit" });
97
+ execSync(`${PKG} install`, { stdio: "inherit" });
92
98
 
93
99
  log("Building TypeScript...");
94
- execSync("pnpm build", { stdio: "inherit" });
100
+ execSync(`${PKG} run build`, { stdio: "inherit" });
95
101
 
96
102
  // --------------- configure OpenClaw ---------------
97
103
 
package/install.sh CHANGED
@@ -22,13 +22,23 @@ err() { printf " ${RED}X${NC} %s\\n" "$1" >&2; }
22
22
  trap 'err "Install failed."' ERR
23
23
 
24
24
  # Check prerequisites
25
- for cmd in pnpm node git openclaw; do
25
+ for cmd in node git openclaw; do
26
26
  if ! command -v "$cmd" &>/dev/null; then
27
27
  err "$cmd is required but not found. Install it first."
28
28
  exit 1
29
29
  fi
30
30
  done
31
31
 
32
+ # Auto-detect package manager (prefer pnpm, fall back to npm)
33
+ if command -v pnpm &>/dev/null; then
34
+ PKG="pnpm"
35
+ elif command -v npm &>/dev/null; then
36
+ PKG="npm"
37
+ else
38
+ err "pnpm or npm is required but not found. Install one first."
39
+ exit 1
40
+ fi
41
+
32
42
  if [ ! -f "$OPENCLAW_CONFIG" ]; then
33
43
  err "OpenClaw config not found at $OPENCLAW_CONFIG"
34
44
  err "Make sure OpenClaw is installed and has been run at least once."
@@ -48,10 +58,10 @@ fi
48
58
  cd "$PLUGIN_DIR"
49
59
 
50
60
  log "Installing dependencies..."
51
- pnpm install
61
+ $PKG install
52
62
 
53
63
  log "Building TypeScript..."
54
- pnpm build
64
+ $PKG run build
55
65
 
56
66
  # Step 2: Configure OpenClaw
57
67
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syengup/friday-channel-next",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "OpenClaw Friday Next Apple channel plugin",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,6 +11,14 @@
11
11
  "tsconfig.json",
12
12
  "openclaw.plugin.json"
13
13
  ],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "test": "npm run test:unit && npm run test:e2e",
17
+ "test:unit": "vitest run",
18
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
19
+ "test:smoke": "node scripts/e2e-smoke.mjs",
20
+ "test:msg-live": "node scripts/message-roundtrip-live.mjs"
21
+ },
14
22
  "bin": {
15
23
  "friday-channel-next": "./install.js",
16
24
  "install-friday-next": "./install.js"
@@ -56,13 +64,5 @@
56
64
  "typescript": "^6.0.3",
57
65
  "vitest": "^4.1.5",
58
66
  "zod": "^4.3.6"
59
- },
60
- "scripts": {
61
- "build": "tsc -p tsconfig.json",
62
- "test": "pnpm test:unit && pnpm test:e2e",
63
- "test:unit": "vitest run",
64
- "test:e2e": "vitest run --config vitest.e2e.config.ts",
65
- "test:smoke": "node scripts/e2e-smoke.mjs",
66
- "test:msg-live": "node scripts/message-roundtrip-live.mjs"
67
67
  }
68
- }
68
+ }
package/dist/index.js DELETED
@@ -1,176 +0,0 @@
1
- import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
2
- import { fridayNextChannelPlugin } from "./src/channel.js";
3
- import { setFridayNextRuntime } from "./src/runtime.js";
4
- import { resolveFridayNextConfig } from "./src/config.js";
5
- import { getHostOpenClawConfigSnapshot } from "./src/host-config.js";
6
- import { registerFridayNextHttpRoutes } from "./src/http/server.js";
7
- import { getFridayNextRuntime } from "./src/runtime.js";
8
- import { sseEmitter } from "./src/sse/emitter.js";
9
- import { forwardAgentEventRaw, getLastRegisteredFridayDeviceId, resolveFridayDeviceIdForSessionKey, } from "./src/friday-session.js";
10
- import { setFridayAgentForwardRuntime } from "./src/agent-forward-runtime.js";
11
- import { getOpenClawAgentRunContext } from "./src/agent-run-context-bridge.js";
12
- export { fridayNextChannelPlugin } from "./src/channel.js";
13
- export { setFridayNextRuntime } from "./src/runtime.js";
14
- /** `api.on` returns void — register tool hooks at most once per process. */
15
- let fridayNextToolHooksRegistered = false;
16
- let disposeAgentEventListener = null;
17
- /** Avoid duplicate `registerHttpRoute` when gateway re-invokes `registerFull`. */
18
- let fridayNextPluginHttpRegistered = false;
19
- function deviceIdFromToolContext(ctx) {
20
- if (ctx.runId) {
21
- const d = sseEmitter.getDeviceIdByRunId(ctx.runId);
22
- if (d)
23
- return d;
24
- }
25
- const sk = typeof ctx.sessionKey === "string" && ctx.sessionKey.trim()
26
- ? ctx.sessionKey.trim()
27
- : (ctx.runId ? getOpenClawAgentRunContext(ctx.runId)?.sessionKey?.trim() : undefined) ?? "";
28
- if (sk) {
29
- const d = resolveFridayDeviceIdForSessionKey(sk);
30
- if (d)
31
- return d;
32
- }
33
- const sole = sseEmitter.getSoleConnectedDeviceId();
34
- if (sole)
35
- return sole;
36
- const last = getLastRegisteredFridayDeviceId();
37
- if (last)
38
- return last;
39
- return null;
40
- }
41
- function isFridaySessionKey(sk) {
42
- return /^friday-next-/i.test(sk) || /^agent:main:friday-next-/i.test(sk);
43
- }
44
- function shouldForwardToolEventToFriday(ctx) {
45
- if (ctx.runId) {
46
- if (sseEmitter.getDeviceIdByRunId(ctx.runId))
47
- return true;
48
- const runSk = getOpenClawAgentRunContext(ctx.runId)?.sessionKey?.trim() ?? "";
49
- if (runSk) {
50
- if (resolveFridayDeviceIdForSessionKey(runSk))
51
- return true;
52
- if (isFridaySessionKey(runSk))
53
- return true;
54
- }
55
- }
56
- const sk = typeof ctx.sessionKey === "string" ? ctx.sessionKey.trim() : "";
57
- if (sk) {
58
- if (resolveFridayDeviceIdForSessionKey(sk))
59
- return true;
60
- if (isFridaySessionKey(sk))
61
- return true;
62
- }
63
- return false;
64
- }
65
- export default defineChannelPluginEntry({
66
- id: "friday-next",
67
- name: "Friday Next",
68
- description: "Friday Next Apple 应用通道",
69
- plugin: fridayNextChannelPlugin,
70
- setRuntime: setFridayNextRuntime,
71
- registerFull: (api) => {
72
- setFridayAgentForwardRuntime(api);
73
- if (!fridayNextPluginHttpRegistered) {
74
- fridayNextPluginHttpRegistered = true;
75
- registerFridayNextHttpRoutes(api);
76
- }
77
- else {
78
- const cfg = resolveFridayNextConfig(getHostOpenClawConfigSnapshot(getFridayNextRuntime().config));
79
- sseEmitter.setBacklogLimit(cfg.sseBacklogPerDevice);
80
- }
81
- disposeAgentEventListener?.();
82
- disposeAgentEventListener = api.runtime.events.onAgentEvent((evt) => {
83
- forwardAgentEventRaw({
84
- runId: evt.runId,
85
- seq: evt.seq,
86
- ts: evt.ts,
87
- stream: evt.stream,
88
- data: evt.data,
89
- sessionKey: evt.sessionKey,
90
- });
91
- });
92
- if (fridayNextToolHooksRegistered) {
93
- return;
94
- }
95
- fridayNextToolHooksRegistered = true;
96
- api.on("subagent_delivery_target", (event) => {
97
- if (!event.expectsCompletionMessage)
98
- return;
99
- const ch = event.requesterOrigin?.channel?.trim().toLowerCase();
100
- if (ch !== "friday-next")
101
- return;
102
- const sk = event.requesterSessionKey?.trim();
103
- if (!sk)
104
- return;
105
- const raw = resolveFridayDeviceIdForSessionKey(sk);
106
- if (!raw)
107
- return;
108
- const to = raw.toUpperCase();
109
- return {
110
- origin: {
111
- channel: "friday-next",
112
- accountId: event.requesterOrigin?.accountId?.trim() || "default",
113
- to,
114
- },
115
- };
116
- });
117
- api.on("before_tool_call", (event, ctx) => {
118
- if (!shouldForwardToolEventToFriday(ctx))
119
- return;
120
- const deviceId = deviceIdFromToolContext(ctx);
121
- const runId = ctx.runId ?? "(unknown)";
122
- const logLine = (detail) => {
123
- const ts = new Date().toISOString();
124
- console.error(`[Friday-HOOK] [${ts}] [TOOL_CALL] toolName=${event.toolName} runId=${runId} deviceId=${deviceId ?? "(unknown)"} detail=${detail}`);
125
- };
126
- if (!deviceId) {
127
- logLine("SKIP_no_deviceId");
128
- return;
129
- }
130
- logLine("START");
131
- sseEmitter.broadcastToolEvent(deviceId.toUpperCase(), runId, {
132
- type: "tool-hook",
133
- data: {
134
- when: "before",
135
- runId,
136
- deviceId: deviceId.toUpperCase(),
137
- sessionKey: ctx.sessionKey,
138
- toolName: event.toolName,
139
- params: event.params,
140
- ts: Date.now(),
141
- },
142
- });
143
- });
144
- api.on("after_tool_call", (event, ctx) => {
145
- if (!shouldForwardToolEventToFriday(ctx))
146
- return;
147
- const deviceId = deviceIdFromToolContext(ctx);
148
- const runId = ctx.runId ?? "(unknown)";
149
- const logLine = (detail) => {
150
- const ts = new Date().toISOString();
151
- console.error(`[Friday-HOOK] [${ts}] [TOOL_DONE] toolName=${event.toolName} runId=${runId} deviceId=${deviceId ?? "(unknown)"} detail=${detail}`);
152
- };
153
- if (!deviceId) {
154
- logLine("SKIP_no_deviceId");
155
- return;
156
- }
157
- logLine("END");
158
- const normalizedDeviceId = deviceId.toUpperCase();
159
- sseEmitter.broadcastToolEvent(normalizedDeviceId, runId, {
160
- type: "tool-hook",
161
- data: {
162
- when: "after",
163
- runId,
164
- deviceId: normalizedDeviceId,
165
- sessionKey: ctx.sessionKey,
166
- toolName: event.toolName,
167
- toolCallId: event.toolCallId,
168
- error: event.error ?? null,
169
- result: event.result,
170
- durationMs: event.durationMs ?? null,
171
- ts: Date.now(),
172
- },
173
- });
174
- });
175
- },
176
- });