@syengup/friday-channel-next 0.0.13 → 0.0.15

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,28 @@ 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
+
62
+ // Auto-detect best registry (if npmjs.org is unreachable, use npmmirror)
63
+ let registryFlag = "";
64
+ try {
65
+ execSync('curl -s --connect-timeout 3 --max-time 5 https://registry.npmjs.org/ >/dev/null 2>&1');
66
+ } catch {
67
+ warn("Default registry unreachable, using https://registry.npmmirror.com");
68
+ registryFlag = "--registry=https://registry.npmmirror.com";
69
+ }
70
+
56
71
  if (!existsSync(OPENCLAW_CONFIG)) {
57
72
  err(`OpenClaw config not found at ${OPENCLAW_CONFIG}`);
58
73
  err("Make sure OpenClaw is installed and has been run at least once.");
@@ -88,10 +103,10 @@ process.chdir(PLUGIN_DIR);
88
103
  // --------------- install + build ---------------
89
104
 
90
105
  log("Installing dependencies...");
91
- execSync("pnpm install", { stdio: "inherit" });
106
+ execSync(`${PKG} install ${registryFlag}`, { stdio: "inherit" });
92
107
 
93
108
  log("Building TypeScript...");
94
- execSync("pnpm build", { stdio: "inherit" });
109
+ execSync(`${PKG} run build`, { stdio: "inherit" });
95
110
 
96
111
  // --------------- configure OpenClaw ---------------
97
112
 
package/install.sh CHANGED
@@ -22,13 +22,31 @@ 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
+
42
+ # Auto-detect best registry (if npmjs.org is unreachable, use npmmirror)
43
+ if curl -s --connect-timeout 3 https://registry.npmjs.org/ >/dev/null 2>&1; then
44
+ REGISTRY=""
45
+ else
46
+ warn "Default registry unreachable, using https://registry.npmmirror.com"
47
+ REGISTRY="--registry=https://registry.npmmirror.com"
48
+ fi
49
+
32
50
  if [ ! -f "$OPENCLAW_CONFIG" ]; then
33
51
  err "OpenClaw config not found at $OPENCLAW_CONFIG"
34
52
  err "Make sure OpenClaw is installed and has been run at least once."
@@ -48,10 +66,10 @@ fi
48
66
  cd "$PLUGIN_DIR"
49
67
 
50
68
  log "Installing dependencies..."
51
- pnpm install
69
+ $PKG install $REGISTRY
52
70
 
53
71
  log "Building TypeScript..."
54
- pnpm build
72
+ $PKG run build
55
73
 
56
74
  # Step 2: Configure OpenClaw
57
75
 
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.15",
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
- });