openclaw-multi-auto 1.4.5 → 1.4.7

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.
Files changed (100) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  3. package/dist/plugin-sdk/mattermost.js +3 -3
  4. package/dist/plugin-sdk/signal.js +2 -2
  5. package/docs/browser-architecture.md +602 -0
  6. package/extensions/googlechat/node_modules/.bin/openclaw +2 -2
  7. package/extensions/memory-core/node_modules/.bin/openclaw +2 -2
  8. package/extensions/memory-lancedb/node_modules/.bin/openai +2 -2
  9. package/extensions/page-action-cache/dist/actions-executor.d.ts +62 -0
  10. package/extensions/page-action-cache/dist/actions-executor.d.ts.map +1 -0
  11. package/extensions/page-action-cache/dist/actions-executor.js +339 -0
  12. package/extensions/page-action-cache/dist/actions-executor.js.map +1 -0
  13. package/extensions/page-action-cache/dist/cache-invalidator.d.ts +70 -0
  14. package/extensions/page-action-cache/dist/cache-invalidator.d.ts.map +1 -0
  15. package/extensions/page-action-cache/dist/cache-invalidator.js +212 -0
  16. package/extensions/page-action-cache/dist/cache-invalidator.js.map +1 -0
  17. package/extensions/page-action-cache/dist/cache-store.d.ts +80 -0
  18. package/extensions/page-action-cache/dist/cache-store.d.ts.map +1 -0
  19. package/extensions/page-action-cache/dist/cache-store.js +361 -0
  20. package/extensions/page-action-cache/dist/cache-store.js.map +1 -0
  21. package/extensions/page-action-cache/dist/cache-strategy.d.ts +65 -0
  22. package/extensions/page-action-cache/dist/cache-strategy.d.ts.map +1 -0
  23. package/extensions/page-action-cache/dist/cache-strategy.js +237 -0
  24. package/extensions/page-action-cache/dist/cache-strategy.js.map +1 -0
  25. package/extensions/page-action-cache/dist/hooks-entry.d.ts +18 -0
  26. package/extensions/page-action-cache/dist/hooks-entry.d.ts.map +1 -0
  27. package/extensions/page-action-cache/dist/hooks-entry.js +27 -0
  28. package/extensions/page-action-cache/dist/hooks-entry.js.map +1 -0
  29. package/extensions/page-action-cache/dist/hooks.d.ts +10 -0
  30. package/extensions/page-action-cache/dist/hooks.d.ts.map +1 -0
  31. package/extensions/page-action-cache/dist/hooks.js +277 -0
  32. package/extensions/page-action-cache/dist/hooks.js.map +1 -0
  33. package/extensions/page-action-cache/dist/index.d.ts +24 -0
  34. package/extensions/page-action-cache/dist/index.d.ts.map +1 -0
  35. package/extensions/page-action-cache/dist/index.js +34 -0
  36. package/extensions/page-action-cache/dist/index.js.map +1 -0
  37. package/extensions/page-action-cache/dist/scenario-recognizer.d.ts +45 -0
  38. package/extensions/page-action-cache/dist/scenario-recognizer.d.ts.map +1 -0
  39. package/extensions/page-action-cache/dist/scenario-recognizer.js +213 -0
  40. package/extensions/page-action-cache/dist/scenario-recognizer.js.map +1 -0
  41. package/extensions/page-action-cache/dist/security-policy.d.ts +62 -0
  42. package/extensions/page-action-cache/dist/security-policy.d.ts.map +1 -0
  43. package/extensions/page-action-cache/dist/security-policy.js +219 -0
  44. package/extensions/page-action-cache/dist/security-policy.js.map +1 -0
  45. package/extensions/page-action-cache/dist/tools.d.ts +209 -0
  46. package/extensions/page-action-cache/dist/tools.d.ts.map +1 -0
  47. package/extensions/page-action-cache/dist/tools.js +383 -0
  48. package/extensions/page-action-cache/dist/tools.js.map +1 -0
  49. package/extensions/page-action-cache/dist/types.d.ts +336 -0
  50. package/extensions/page-action-cache/dist/types.d.ts.map +1 -0
  51. package/extensions/page-action-cache/dist/types.js +8 -0
  52. package/extensions/page-action-cache/dist/types.js.map +1 -0
  53. package/extensions/page-action-cache/dist/ux-enhancer.d.ts +60 -0
  54. package/extensions/page-action-cache/dist/ux-enhancer.d.ts.map +1 -0
  55. package/extensions/page-action-cache/dist/ux-enhancer.js +218 -0
  56. package/extensions/page-action-cache/dist/ux-enhancer.js.map +1 -0
  57. package/extensions/page-action-cache/dist/variable-resolver.d.ts +28 -0
  58. package/extensions/page-action-cache/dist/variable-resolver.d.ts.map +1 -0
  59. package/extensions/page-action-cache/dist/variable-resolver.js +201 -0
  60. package/extensions/page-action-cache/dist/variable-resolver.js.map +1 -0
  61. package/extensions/page-action-cache/docs/API.md +555 -0
  62. package/extensions/page-action-cache/docs/IMPLEMENTATION.md +1792 -0
  63. package/extensions/page-action-cache/docs/INTEGRATION.md +387 -0
  64. package/extensions/page-action-cache/docs/README.md +183 -0
  65. package/extensions/page-action-cache/index.ts +118 -0
  66. package/extensions/page-action-cache/node_modules/.bin/nlc +21 -0
  67. package/extensions/page-action-cache/node_modules/.bin/node-llama-cpp +21 -0
  68. package/extensions/page-action-cache/node_modules/.bin/openclaw +21 -0
  69. package/extensions/page-action-cache/node_modules/.bin/tsc +21 -0
  70. package/extensions/page-action-cache/node_modules/.bin/tsserver +21 -0
  71. package/extensions/page-action-cache/node_modules/.bin/vitest +21 -0
  72. package/extensions/page-action-cache/openclaw.plugin.json +208 -0
  73. package/extensions/page-action-cache/package.json +76 -0
  74. package/extensions/page-action-cache/scripts/npm_publish.sh +80 -0
  75. package/extensions/page-action-cache/skills/page-action-cache/SKILL.md +216 -0
  76. package/extensions/page-action-cache/src/actions-executor.ts +441 -0
  77. package/extensions/page-action-cache/src/cache-invalidator.ts +271 -0
  78. package/extensions/page-action-cache/src/cache-store.ts +457 -0
  79. package/extensions/page-action-cache/src/cache-strategy.ts +327 -0
  80. package/extensions/page-action-cache/src/hooks-entry.ts +114 -0
  81. package/extensions/page-action-cache/src/hooks.ts +332 -0
  82. package/extensions/page-action-cache/src/index.ts +104 -0
  83. package/extensions/page-action-cache/src/scenario-recognizer.ts +259 -0
  84. package/extensions/page-action-cache/src/security-policy.ts +268 -0
  85. package/extensions/page-action-cache/src/tools.ts +437 -0
  86. package/extensions/page-action-cache/src/types.ts +482 -0
  87. package/extensions/page-action-cache/src/ux-enhancer.ts +266 -0
  88. package/extensions/page-action-cache/src/variable-resolver.ts +258 -0
  89. package/extensions/page-action-cache/tests/actions-executor.test.ts +424 -0
  90. package/extensions/page-action-cache/tests/cache-store.test.ts +267 -0
  91. package/extensions/page-action-cache/tests/integration-test.ts +62 -0
  92. package/extensions/page-action-cache/tests/scenario-recognizer.test.ts +140 -0
  93. package/extensions/page-action-cache/tests/variable-resolver.test.ts +187 -0
  94. package/extensions/page-action-cache/tsconfig.json +39 -0
  95. package/package.json +1 -1
  96. package/scripts/create-instance.sh +26 -8
  97. package/scripts/npm_publish.sh +59 -1
  98. package/scripts/publish-extension.sh +343 -0
  99. package/ui/node_modules/.bin/vite +2 -2
  100. package/ui/node_modules/.bin/vitest +2 -2
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Integration Test
3
+ * 集成测试 - 验证扩展的基本功能
4
+ */
5
+
6
+ import { describe, it, expect, beforeAll } from "vitest";
7
+ import { getCacheStore } from "../src/cache-store.js";
8
+
9
+ describe("Page Action Cache Integration", () => {
10
+ let cacheStore = getCacheStore();
11
+
12
+ beforeAll(() => {
13
+ // 清空缓存
14
+ cacheStore.clear();
15
+ });
16
+
17
+ describe("Basic Cache Operations", () => {
18
+ it("should save and retrieve cache entry", () => {
19
+ const url = "https://example.com/login";
20
+ const viewport = { width: 1920, height: 1080 };
21
+ const actions = [
22
+ { type: "type" as const, ref: "#username", text: "test", order: 1 },
23
+ { type: "type" as const, ref: "#password", text: "secret", order: 2 },
24
+ { type: "click" as const, ref: "#submit", order: 3 },
25
+ ];
26
+
27
+ const key = cacheStore.set(url, viewport, actions, {
28
+ scenario: "login",
29
+ cacheLevel: "L3",
30
+ });
31
+
32
+ expect(key).toBeDefined();
33
+ expect(typeof key).toBe("string");
34
+
35
+ const entry = cacheStore.get(url, viewport);
36
+ expect(entry).not.toBeNull();
37
+ expect(entry?.scenario).toBe("login");
38
+ expect(entry?.cacheLevel).toBe("L3");
39
+ expect(entry?.actions).toEqual(actions);
40
+ });
41
+
42
+ it("should return null for non-existent cache", () => {
43
+ const entry = cacheStore.get("https://example.com/nonexistent", viewport);
44
+ expect(entry).toBeNull();
45
+ });
46
+
47
+ it("should delete cache entry", () => {
48
+ const url = "https://example.com/login";
49
+ const viewport = { width: 1920, height: 1080 };
50
+ const actions = [];
51
+ const key = cacheStore.set(url, viewport, actions, {
52
+ scenario: "login",
53
+ cacheLevel: "L3",
54
+ });
55
+
56
+ const deleted = cacheStore.delete(url, viewport);
57
+ expect(deleted).toBe(true);
58
+
59
+ const entry = cacheStore.get(url, viewport);
60
+ expect(entry).toBeNull();
61
+ });
62
+ });
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Scenario Recognizer Tests
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach } from "vitest";
6
+ import { ScenarioRecognizer } from "../src/scenario-recognizer.js";
7
+
8
+ describe("ScenarioRecognizer", () => {
9
+ let recognizer: ScenarioRecognizer;
10
+
11
+ beforeEach(() => {
12
+ recognizer = new ScenarioRecognizer();
13
+ });
14
+
15
+ describe("matchExactRules", () => {
16
+ it("should match login keywords", async () => {
17
+ const match = await recognizer.recognize("登录 example.com", "https://example.com");
18
+ expect(match).not.toBeNull();
19
+ expect(match?.scenario).toBe("login");
20
+ expect(match?.confidence).toBeGreaterThanOrEqual(90);
21
+ });
22
+
23
+ it("should match login URL patterns", async () => {
24
+ const match = await recognizer.recognize(
25
+ "open page",
26
+ "https://example.com/login"
27
+ );
28
+ expect(match).not.toBeNull();
29
+ expect(match?.scenario).toBe("login");
30
+ expect(match?.method).toBe("url");
31
+ });
32
+
33
+ it("should match search keywords", async () => {
34
+ const match = await recognizer.recognize("搜索产品", "https://example.com");
35
+ expect(match).not.toBeNull();
36
+ expect(match?.scenario).toBe("search");
37
+ });
38
+
39
+ it("should match checkout keywords", async () => {
40
+ const match = await recognizer.recognize("结账购物车", "https://example.com/checkout");
41
+ expect(match).not.toBeNull();
42
+ expect(match?.scenario).toBe("checkout");
43
+ });
44
+
45
+ it("should match settings keywords", async () => {
46
+ const match = await recognizer.recognize("修改设置", "https://example.com/settings");
47
+ expect(match).not.toBeNull();
48
+ expect(match?.scenario).toBe("settings");
49
+ });
50
+
51
+ it("should not match unrelated input", async () => {
52
+ const match = await recognizer.recognize("do something random", "https://example.com/random");
53
+ expect(match).toBeNull();
54
+ });
55
+ });
56
+
57
+ describe("confidence levels", () => {
58
+ it("should give high confidence for exact keyword match", async () => {
59
+ const match = await recognizer.recognize("登录 account", "https://example.com");
60
+ expect(match?.confidence).toBeGreaterThanOrEqual(90);
61
+ });
62
+
63
+ it("should give lower confidence for URL match", async () => {
64
+ const match = await recognizer.recognize("open", "https://example.com/login");
65
+ if (match) {
66
+ expect(match.confidence).toBeLessThan(90);
67
+ expect(match.confidence).toBeGreaterThanOrEqual(80);
68
+ }
69
+ });
70
+ });
71
+
72
+ describe("method detection", () => {
73
+ it("should use keyword method for keyword matches", async () => {
74
+ const match = await recognizer.recognize("登录", "https://example.com");
75
+ expect(match?.method).toBe("keyword");
76
+ });
77
+
78
+ it("should use url method for URL pattern matches", async () => {
79
+ const match = await recognizer.recognize("open", "https://example.com/login");
80
+ if (match) {
81
+ expect(match.method).toBe("url");
82
+ }
83
+ });
84
+ });
85
+
86
+ describe("case insensitivity", () => {
87
+ it("should match keywords case-insensitively", async () => {
88
+ const match1 = await recognizer.recognize("登录", "https://example.com");
89
+ const match2 = await recognizer.recognize("LOGIN", "https://example.com");
90
+ const match3 = await recognizer.recognize("Login", "https://example.com");
91
+
92
+ expect(match1?.scenario).toBe("login");
93
+ expect(match2?.scenario).toBe("login");
94
+ expect(match3?.scenario).toBe("login");
95
+ });
96
+
97
+ it("should match URLs case-insensitively", async () => {
98
+ const match1 = await recognizer.recognize("open", "https://example.com/Login");
99
+ const match2 = await recognizer.recognize("open", "https://example.com/LOGIN");
100
+
101
+ expect(match1?.scenario).toBe("login");
102
+ expect(match2?.scenario).toBe("login");
103
+ });
104
+ });
105
+
106
+ describe("getRules", () => {
107
+ it("should return all rules", () => {
108
+ const rules = recognizer.getRules();
109
+ expect(rules.length).toBeGreaterThan(0);
110
+ expect(rules[0]).toHaveProperty("scenario");
111
+ expect(rules[0]).toHaveProperty("keywords");
112
+ expect(rules[0]).toHaveProperty("urlPatterns");
113
+ expect(rules[0]).toHaveProperty("priority");
114
+ expect(rules[0]).toHaveProperty("cacheLevel");
115
+ expect(rules[0]).toHaveProperty("confidence");
116
+ });
117
+ });
118
+
119
+ describe("getRecommendedCacheLevel", () => {
120
+ it("should return L3 for login", () => {
121
+ const level = recognizer.getRecommendedCacheLevel("login");
122
+ expect(level).toBe("L3");
123
+ });
124
+
125
+ it("should return L3 for checkout", () => {
126
+ const level = recognizer.getRecommendedCacheLevel("checkout");
127
+ expect(level).toBe("L3");
128
+ });
129
+
130
+ it("should return L1 for screenshot", () => {
131
+ const level = recognizer.getRecommendedCacheLevel("screenshot");
132
+ expect(level).toBe("L1");
133
+ });
134
+
135
+ it("should return L1 for unknown scenario", () => {
136
+ const level = recognizer.getRecommendedCacheLevel("unknown");
137
+ expect(level).toBe("L1");
138
+ });
139
+ });
140
+ });
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Variable Resolver Tests
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach } from "vitest";
6
+ import { VariableResolver } from "../src/variable-resolver.js";
7
+
8
+ describe("VariableResolver", () => {
9
+ let resolver: VariableResolver;
10
+
11
+ beforeEach(() => {
12
+ resolver = new VariableResolver();
13
+ });
14
+
15
+ describe("login scenario", () => {
16
+ it("should extract username and password", () => {
17
+ const variables = resolver.resolveVariables(
18
+ "登录 example.com,用户名 alice,密码 secret123",
19
+ "login"
20
+ );
21
+
22
+ expect(variables.username).toBe("alice");
23
+ expect(variables.password).toBe("secret123");
24
+ });
25
+
26
+ it("should extract username from different patterns", () => {
27
+ const testCases = [
28
+ "登录 账号 bob",
29
+ "username: charlie",
30
+ "user david",
31
+ ];
32
+
33
+ for (const input of testCases) {
34
+ const variables = resolver.resolveVariables(input, "login");
35
+ expect(variables.username).toBeDefined();
36
+ }
37
+ });
38
+
39
+ it("should extract email as username", () => {
40
+ const variables = resolver.resolveVariables(
41
+ "使用 test@example.com 登录",
42
+ "login"
43
+ );
44
+
45
+ expect(variables.username).toBe("test@example.com");
46
+ });
47
+
48
+ it("should extract password from different patterns", () => {
49
+ const testCases = [
50
+ "密码 mypassword",
51
+ "password: secret",
52
+ "pwd: 123456",
53
+ ];
54
+
55
+ for (const input of testCases) {
56
+ const variables = resolver.resolveVariables(input, "login");
57
+ expect(variables.password).toBeDefined();
58
+ }
59
+ });
60
+ });
61
+
62
+ describe("checkout scenario", () => {
63
+ it("should extract payment method", () => {
64
+ const variables = resolver.resolveVariables(
65
+ "结账,支付方式信用卡",
66
+ "checkout"
67
+ );
68
+
69
+ expect(variables.custom?.paymentMethod).toBe("信用卡");
70
+ });
71
+
72
+ it("should extract amount", () => {
73
+ const variables = resolver.resolveVariables(
74
+ "支付 金额100",
75
+ "checkout"
76
+ );
77
+
78
+ expect(variables.custom?.amount).toBe("100");
79
+ });
80
+ });
81
+
82
+ describe("search scenario", () => {
83
+ it("should extract search query", () => {
84
+ const variables = resolver.resolveVariables("搜索 产品A", "search");
85
+
86
+ expect(variables.custom?.query).toBe("产品A");
87
+ });
88
+
89
+ it("should extract find query", () => {
90
+ const variables = resolver.resolveVariables("查找 测试项目", "search");
91
+
92
+ expect(variables.custom?.query).toBe("测试项目");
93
+ });
94
+ });
95
+
96
+ describe("settings scenario", () => {
97
+ it("should extract key-value pairs", () => {
98
+ const variables = resolver.resolveVariables(
99
+ "设置 language:zh-CN, theme:dark",
100
+ "settings"
101
+ );
102
+
103
+ expect(variables.custom?.language).toBe("zh-CN");
104
+ expect(variables.custom?.theme).toBe("dark");
105
+ });
106
+ });
107
+
108
+ describe("generic resolver", () => {
109
+ it("should extract common fields", () => {
110
+ const variables = resolver.resolveVariables(
111
+ "user:john, email:john@example.com, phone:1234567890",
112
+ "unknown"
113
+ );
114
+
115
+ expect(variables.username).toBe("john");
116
+ expect(variables.email).toBe("john@example.com");
117
+ expect(variables.phone).toBe("1234567890");
118
+ });
119
+
120
+ it("should extract verification code", () => {
121
+ const variables = resolver.resolveVariables(
122
+ "验证码 123456",
123
+ "unknown"
124
+ );
125
+
126
+ expect(variables.code).toBe("123456");
127
+ });
128
+ });
129
+
130
+ describe("validateVariables", () => {
131
+ it("should validate login variables", () => {
132
+ const validVars = { username: "alice", password: "secret" };
133
+ const invalidVars = { password: "secret" }; // Missing username
134
+
135
+ expect(resolver.validateVariables(validVars, "login")).toBe(true);
136
+ expect(resolver.validateVariables(invalidVars, "login")).toBe(false);
137
+ });
138
+
139
+ it("should validate login with email", () => {
140
+ const validVars = { email: "alice@example.com" };
141
+
142
+ expect(resolver.validateVariables(validVars, "login")).toBe(true);
143
+ });
144
+
145
+ it("should always validate checkout variables", () => {
146
+ const vars = { custom: { paymentMethod: "credit" } };
147
+
148
+ expect(resolver.validateVariables(vars, "checkout")).toBe(true);
149
+ });
150
+
151
+ it("should always validate unknown scenarios", () => {
152
+ const emptyVars = {};
153
+
154
+ expect(resolver.validateVariables(emptyVars, "unknown")).toBe(true);
155
+ });
156
+ });
157
+
158
+ describe("mergeVariables", () => {
159
+ it("should merge variables correctly", () => {
160
+ const base = {
161
+ username: "alice",
162
+ custom: { theme: "dark" },
163
+ };
164
+
165
+ const override = {
166
+ password: "secret",
167
+ custom: { language: "en" },
168
+ };
169
+
170
+ const merged = resolver.mergeVariables(base, override);
171
+
172
+ expect(merged.username).toBe("alice");
173
+ expect(merged.password).toBe("secret");
174
+ expect(merged.custom?.theme).toBe("dark");
175
+ expect(merged.custom?.language).toBe("en");
176
+ });
177
+
178
+ it("should override with second object", () => {
179
+ const base = { username: "alice" };
180
+ const override = { username: "bob" };
181
+
182
+ const merged = resolver.mergeVariables(base, override);
183
+
184
+ expect(merged.username).toBe("bob");
185
+ });
186
+ });
187
+ });
@@ -0,0 +1,39 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "sourceMap": true,
12
+ "removeComments": false,
13
+ "noUnusedLocals": true,
14
+ "noUnusedParameters": true,
15
+ "noImplicitReturns": true,
16
+ "noFallthroughCasesInSwitch": true,
17
+ "esModuleInterop": true,
18
+ "skipLibCheck": true,
19
+ "forceConsistentCasingInFileNames": true,
20
+ "strict": true,
21
+ "resolveJsonModule": true,
22
+ "allowSyntheticDefaultImports": true
23
+ },
24
+ "include": [
25
+ "src/**/*"
26
+ ],
27
+ "exclude": [
28
+ "node_modules",
29
+ "dist",
30
+ "**/*.test.ts",
31
+ "**/*.spec.ts"
32
+ ],
33
+ "ts-node": {
34
+ "compilerOptions": {
35
+ "module": "ESNext",
36
+ "esModuleInterop": true
37
+ }
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-multi-auto",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "description": "Multi-channel AI gateway with extensible messaging integrations",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/openclaw/openclaw#readme",
@@ -136,6 +136,16 @@ fi
136
136
 
137
137
  pnpm install --shamefully-hoist --ignore-workspace --registry=https://registry.npmmirror.com --no-frozen-lockfile
138
138
 
139
+ # 安装 page-action-cache 扩展
140
+ echo -e "${BLUE}📦 安装 page-action-cache 扩展...${NC}"
141
+ cd "${INSTANCE_DIR}"
142
+ if pnpm install --registry=https://registry.npmmirror.com @openclaw/page-action-cache@latest; then
143
+ echo -e "${GREEN}✅ page-action-cache 扩展安装成功${NC}"
144
+ else
145
+ echo -e "${YELLOW}⚠️ page-action-cache 扩展安装失败,但将继续实例创建${NC}"
146
+ echo -e "${YELLOW}💡 提示: 可以稍后手动安装: cd ${INSTANCE_DIR} && pnpm install @openclaw/page-action-cache@latest${NC}"
147
+ fi
148
+
139
149
  if [ ! -d "node_modules" ]; then
140
150
  echo -e "${RED}❌ 严重错误: pnpm install 完成但 node_modules 目录未创建!${NC}"
141
151
  exit 1
@@ -264,7 +274,21 @@ cat > "${INSTANCE_DIR}/config/openclaw.json" << EOF
264
274
  }
265
275
  },
266
276
  "commands": { "native": "auto", "restart": false },
267
- "gateway": { "port": ${PORT}, "mode": "local" }
277
+ "gateway": { "port": ${PORT}, "mode": "local" },
278
+ "plugins": {
279
+ "enabled": true,
280
+ "allow": ["page-action-cache"],
281
+ "entries": {
282
+ "page-action-cache": {
283
+ "enabled": true,
284
+ "config": {
285
+ "enabled": true,
286
+ "autoUseCache": true,
287
+ "scenarioRecognitionEnabled": true
288
+ }
289
+ }
290
+ }
291
+ }
268
292
  }
269
293
  EOF
270
294
 
@@ -306,7 +330,7 @@ if [ "$INSTANCE_NAME" = "yunwei" ]; then
306
330
  if [ -d "$item" ]; then
307
331
  # 目录(如 memory、skills)复制到 workspace
308
332
  cp -r "$item" "$INSTANCE_DIR/workspace/"
309
- elif [ -f "$item" ] && [[ "$item" != *.md ]]; then
333
+ elif [ -f "$item" ]; then
310
334
  # 非 .md 文件(如 package.json)也复制到 workspace
311
335
  cp "$item" "$INSTANCE_DIR/workspace/" 2>/dev/null || true
312
336
  fi
@@ -446,12 +470,6 @@ check_port() {
446
470
  fi
447
471
  }
448
472
 
449
- sleep 3
450
- (
451
- cd "$INSTANCE_DIR"
452
- ./start.sh heartbeat
453
- ) >> "$INSTANCE_DIR/workspace/server.log" 2>&1 &
454
-
455
473
  if kill -0 $PID 2>/dev/null; then
456
474
  if check_port; then
457
475
  echo -e "${GREEN}================================================${NC}"
@@ -117,4 +117,62 @@ echo -ne "${YELLOW}🔄 通知镜像同步... ${NC}"
117
117
  PKG_NAME=$(node -e "console.log(require('./package.json').name)")
118
118
  curl -s -X PUT "https://registry-direct.npmmirror.com/${PKG_NAME}/sync?publish=true" > /dev/null && echo -e "${GREEN}[完成]${NC}"
119
119
 
120
- echo -e "${GREEN}🎉 OpenClaw 发布成功!所有用户现在都可以丝滑安装了。${NC}"
120
+ echo -e "${GREEN}🎉 OpenClaw 发布成功!${NC}"
121
+
122
+ # 8. 发布 page-action-cache 扩展
123
+ echo -ne "${BLUE}📦 正在发布 @openclaw/page-action-cache 扩展...${NC}"
124
+
125
+ # 进入扩展目录处理 workspace:* 依赖问题
126
+ cd "$ROOT_DIR/extensions/page-action-cache"
127
+
128
+ # 处理 package.json 中的 workspace:* 依赖(npm 不支持)
129
+ TMP_PACKAGE_JSON="/tmp/page-action-cache-publish-$(date +%s).json"
130
+ cp package.json "$TMP_PACKAGE_JSON"
131
+
132
+ node -e "
133
+ const pkg = JSON.parse(require('fs').readFileSync('$TMP_PACKAGE_JSON', 'utf8'));
134
+ // 移除 workspace:* 依赖
135
+ delete pkg.dependencies;
136
+ // 保留 peerDependencies
137
+ pkg.peerDependencies = pkg.peerDependencies || {};
138
+ require('fs').writeFileSync('$TMP_PACKAGE_JSON', JSON.stringify(pkg, null, 2));
139
+ "
140
+
141
+ # 处理后的 package.json
142
+ cp "$TMP_PACKAGE_JSON" package.json
143
+
144
+ echo -ne "${GREEN}✅ 已处理 package.json(移除 workspace 依赖)${NC}"
145
+
146
+ # 检查是否需要登录
147
+ if ! npm whoami > /dev/null 2>&1; then
148
+ echo -ne "${YELLOW}🔐 page-action-cache 扩展发布需要 npm 登录${NC}"
149
+ echo -ne "${YELLOW}💡 提示: 请执行 npm login 后重新运行此脚本${NC}"
150
+ rm -f "$TMP_PACKAGE_JSON"
151
+ git checkout package.json 2>/dev/null || true
152
+ exit 1
153
+ fi
154
+
155
+ # 发布扩展
156
+ echo -ne "${YELLOW}🚀 正在发布到 npm...${NC}"
157
+ npm publish --access public
158
+
159
+ if [ $? -eq 0 ]; then
160
+ echo -e "${GREEN}✅ @openclaw/page-action-cache 发布成功!${NC}"
161
+ # 通知镜像同步
162
+ curl -s -X PUT "https://registry-direct.npmmirror.com/@openclaw/page-action-cache/sync?publish=true" > /dev/null && echo -e "${GREEN}[完成]${NC}"
163
+ else
164
+ echo -e "${RED}❌ @openclaw/page-action-cache 发布失败${NC}"
165
+ fi
166
+
167
+ # 恢复原始 package.json
168
+ git checkout package.json 2>/dev/null || true
169
+ rm -f "$TMP_PACKAGE_JSON"
170
+
171
+ echo -e "${GREEN}🎉 完整发布流程完成!${NC}"
172
+ echo -e "${GREEN}📋 已发布:${NC}"
173
+ echo -e "${GREEN} - openclaw-multi-auto (v${CUR_VERSION})${NC}"
174
+ echo -e "${GREEN} - @openclaw/page-action-cache (latest)${NC}"
175
+ echo ""
176
+ echo -e "${BLUE}💡 提示:${NC}"
177
+ echo -e "${BLUE} 扩展发布后,需要重启实例才能生效 page-action-cache${NC}"
178
+ echo -e "${BLUE} 运行: cd ~/openclaws/<instance> && ./start.sh${NC}"