@workclaw/openclaw-workclaw 1.0.18 → 1.0.19

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 (142) hide show
  1. package/README.md +364 -345
  2. package/dist/api.d.ts +3 -0
  3. package/dist/api.js +3 -0
  4. package/dist/index.d.ts +11 -0
  5. package/dist/index.js +263 -0
  6. package/dist/setup-entry.d.ts +2 -0
  7. package/dist/setup-entry.js +12 -0
  8. package/dist/src/accounts.d.ts +66 -0
  9. package/dist/src/accounts.js +279 -0
  10. package/dist/src/api/accounts-api.d.ts +2 -0
  11. package/dist/src/api/accounts-api.js +130 -0
  12. package/dist/src/api/prompts-api.d.ts +2 -0
  13. package/dist/src/api/prompts-api.js +103 -0
  14. package/dist/src/api/session-api.d.ts +2 -0
  15. package/dist/src/api/session-api.js +207 -0
  16. package/dist/src/api/skills-api.d.ts +2 -0
  17. package/dist/src/api/skills-api.js +64 -0
  18. package/dist/src/api/workspace.d.ts +3 -0
  19. package/dist/src/api/workspace.js +28 -0
  20. package/dist/src/channel.d.ts +11 -0
  21. package/{src/channel.ts → dist/src/channel.js} +198 -225
  22. package/dist/src/config-schema.d.ts +93 -0
  23. package/dist/src/config-schema.js +56 -0
  24. package/dist/src/connection/workclaw-client.d.ts +147 -0
  25. package/dist/src/connection/workclaw-client.js +351 -0
  26. package/dist/src/gateway/agent-handlers.d.ts +12 -0
  27. package/{src/gateway/agent-handlers.ts → dist/src/gateway/agent-handlers.js} +433 -523
  28. package/dist/src/gateway/config-writer.d.ts +71 -0
  29. package/dist/src/gateway/config-writer.js +312 -0
  30. package/dist/src/gateway/message-context.d.ts +76 -0
  31. package/{src/gateway/message-context.ts → dist/src/gateway/message-context.js} +499 -594
  32. package/dist/src/gateway/message-dispatcher.d.ts +19 -0
  33. package/{src/gateway/message-dispatcher.ts → dist/src/gateway/message-dispatcher.js} +512 -641
  34. package/dist/src/gateway/reconnect.d.ts +27 -0
  35. package/{src/gateway/reconnect.ts → dist/src/gateway/reconnect.js} +206 -253
  36. package/dist/src/gateway/skills-handler.d.ts +29 -0
  37. package/dist/src/gateway/skills-handler.js +576 -0
  38. package/dist/src/gateway/skills-list-handler.d.ts +27 -0
  39. package/dist/src/gateway/skills-list-handler.js +233 -0
  40. package/dist/src/gateway/tools-list-handler.d.ts +30 -0
  41. package/dist/src/gateway/tools-list-handler.js +101 -0
  42. package/dist/src/gateway/workclaw-gateway.d.ts +14 -0
  43. package/dist/src/gateway/workclaw-gateway.js +223 -0
  44. package/dist/src/media/upload.d.ts +13 -0
  45. package/dist/src/media/upload.js +125 -0
  46. package/dist/src/outbound/index.d.ts +36 -0
  47. package/dist/src/outbound/index.js +123 -0
  48. package/dist/src/outbound/workclaw-sender.d.ts +36 -0
  49. package/{src/outbound/workclaw-sender.ts → dist/src/outbound/workclaw-sender.js} +95 -158
  50. package/dist/src/runtime.d.ts +116 -0
  51. package/dist/src/runtime.js +374 -0
  52. package/dist/src/secret-contract-api.d.ts +4 -0
  53. package/dist/src/secret-contract-api.js +4 -0
  54. package/{src/send.ts → dist/src/send.d.ts} +1 -1
  55. package/dist/src/send.js +1 -0
  56. package/dist/src/setup-api.d.ts +3 -0
  57. package/dist/src/setup-api.js +3 -0
  58. package/dist/src/setup-core.d.ts +3 -0
  59. package/dist/src/setup-core.js +13 -0
  60. package/dist/src/setup-surface.d.ts +7 -0
  61. package/dist/src/setup-surface.js +363 -0
  62. package/dist/src/tools/openclaw-workclaw-cron/api/index.d.ts +93 -0
  63. package/dist/src/tools/openclaw-workclaw-cron/api/index.js +209 -0
  64. package/dist/src/tools/openclaw-workclaw-cron/index.d.ts +10 -0
  65. package/{src/tools/openclaw-workclaw-cron/index.ts → dist/src/tools/openclaw-workclaw-cron/index.js} +33 -39
  66. package/dist/src/tools/openclaw-workclaw-cron/src/add/params.d.ts +16 -0
  67. package/dist/src/tools/openclaw-workclaw-cron/src/add/params.js +152 -0
  68. package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.d.ts +18 -0
  69. package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.js +162 -0
  70. package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.d.ts +14 -0
  71. package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.js +80 -0
  72. package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.d.ts +14 -0
  73. package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.js +107 -0
  74. package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.d.ts +14 -0
  75. package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.js +80 -0
  76. package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.d.ts +14 -0
  77. package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.js +107 -0
  78. package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.d.ts +17 -0
  79. package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.js +127 -0
  80. package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.d.ts +14 -0
  81. package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.js +87 -0
  82. package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.d.ts +14 -0
  83. package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.js +107 -0
  84. package/dist/src/tools/openclaw-workclaw-cron/src/update/params.d.ts +17 -0
  85. package/dist/src/tools/openclaw-workclaw-cron/src/update/params.js +164 -0
  86. package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.d.ts +18 -0
  87. package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.js +135 -0
  88. package/dist/src/tools/openclaw-workclaw-cron/types/index.d.ts +52 -0
  89. package/dist/src/tools/openclaw-workclaw-cron/types/index.js +4 -0
  90. package/dist/src/tools/openclaw-workclaw-cron/utils/index.d.ts +40 -0
  91. package/dist/src/tools/openclaw-workclaw-cron/utils/index.js +122 -0
  92. package/dist/src/tools/openclaw-workclaw-system/index.d.ts +10 -0
  93. package/{src/tools/openclaw-workclaw-system/index.ts → dist/src/tools/openclaw-workclaw-system/index.js} +15 -17
  94. package/dist/src/tools/openclaw-workclaw-system/src/get/index.d.ts +8 -0
  95. package/dist/src/tools/openclaw-workclaw-system/src/get/index.js +64 -0
  96. package/dist/src/tools/openclaw-workclaw-system/src/token/index.d.ts +8 -0
  97. package/dist/src/tools/openclaw-workclaw-system/src/token/index.js +78 -0
  98. package/{src/types.ts → dist/src/types.d.ts} +39 -58
  99. package/dist/src/types.js +1 -0
  100. package/dist/src/utils/content.d.ts +15 -0
  101. package/{src/utils/content.ts → dist/src/utils/content.js} +38 -35
  102. package/package.json +62 -49
  103. package/index.ts +0 -302
  104. package/setup-entry.ts +0 -6
  105. package/src/accounts.ts +0 -312
  106. package/src/api/accounts-api.ts +0 -156
  107. package/src/api/prompts-api.ts +0 -116
  108. package/src/api/session-api.ts +0 -238
  109. package/src/api/skills-api.ts +0 -72
  110. package/src/api/workspace.ts +0 -41
  111. package/src/config-schema.ts +0 -110
  112. package/src/connection/workclaw-client.ts +0 -643
  113. package/src/gateway/config-writer.ts +0 -296
  114. package/src/gateway/skills-handler.ts +0 -741
  115. package/src/gateway/skills-list-handler.ts +0 -332
  116. package/src/gateway/tools-list-handler.ts +0 -160
  117. package/src/gateway/workclaw-gateway.ts +0 -367
  118. package/src/media/upload.ts +0 -157
  119. package/src/outbound/index.ts +0 -185
  120. package/src/runtime.ts +0 -497
  121. package/src/tools/openclaw-workclaw-cron/api/index.ts +0 -326
  122. package/src/tools/openclaw-workclaw-cron/src/add/params.ts +0 -177
  123. package/src/tools/openclaw-workclaw-cron/src/add/sync.ts +0 -188
  124. package/src/tools/openclaw-workclaw-cron/src/disable/params.ts +0 -100
  125. package/src/tools/openclaw-workclaw-cron/src/disable/sync.ts +0 -127
  126. package/src/tools/openclaw-workclaw-cron/src/enable/params.ts +0 -100
  127. package/src/tools/openclaw-workclaw-cron/src/enable/sync.ts +0 -127
  128. package/src/tools/openclaw-workclaw-cron/src/notify/sync.ts +0 -148
  129. package/src/tools/openclaw-workclaw-cron/src/remove/params.ts +0 -109
  130. package/src/tools/openclaw-workclaw-cron/src/remove/sync.ts +0 -127
  131. package/src/tools/openclaw-workclaw-cron/src/update/params.ts +0 -195
  132. package/src/tools/openclaw-workclaw-cron/src/update/sync.ts +0 -161
  133. package/src/tools/openclaw-workclaw-cron/types/index.ts +0 -55
  134. package/src/tools/openclaw-workclaw-cron/utils/index.ts +0 -141
  135. package/src/tools/openclaw-workclaw-system/src/get/index.ts +0 -77
  136. package/src/tools/openclaw-workclaw-system/src/token/index.ts +0 -93
  137. package/tests/accounts.test.ts +0 -285
  138. package/tests/message-context.test.ts +0 -313
  139. package/tests/reconnect.test.ts +0 -257
  140. package/tests/workclaw-client.test.ts +0 -112
  141. package/tsconfig.json +0 -14
  142. package/vitest.config.ts +0 -8
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Config Writer - handles writing account config to openclaw.json
3
+ *
4
+ * NOTE: Only agent creation/initialization writes to openclaw.json via writeConfigFile.
5
+ * Runtime dynamic data (openConversationId) is stored in a separate state file
6
+ * to avoid triggering openclaw's config watcher, which would re-parse env vars
7
+ * and potentially overwrite already-resolved values like ${MODEL_API_KEY}.
8
+ */
9
+ type ConfigLogger = {
10
+ info?: (msg: string) => void;
11
+ error?: (msg: string) => void;
12
+ };
13
+ /**
14
+ * Write a new config to the openclaw.json file.
15
+ */
16
+ export declare function writeConfigFile(newConfig: any, cfg: any, log?: ConfigLogger): Promise<void>;
17
+ /**
18
+ * Load openConversationId from the separate state file.
19
+ *
20
+ * Key format: accountId:userId
21
+ *
22
+ * Called at runtime to restore openConversationId after process restart,
23
+ * since cfg is reloaded from openclaw.json which does not contain this value.
24
+ */
25
+ export declare function loadOpenConversationId(accountId: string, userId: string): string | null;
26
+ /**
27
+ * Save openConversationId to a separate state file (with write throttling).
28
+ *
29
+ * Key format: accountId:userId
30
+ * Throttling: if called multiple times within 1 second, only the last value is saved.
31
+ * This avoids excessive disk writes from high-frequency messages.
32
+ *
33
+ * Stored in ~/.openclaw/workclaw-state/conversations.json (separate from openclaw.json)
34
+ * to avoid triggering openclaw's config watcher which would re-parse env vars.
35
+ */
36
+ export declare function saveOpenConversationId(accountId: string, userId: string, openConversationId: string, cfg: any, log?: ConfigLogger): Promise<void>;
37
+ /**
38
+ * Initialize workclaw agent config in one shot (hardware device init).
39
+ *
40
+ * Sets apiKey, agentId, userId and persists to openclaw.json in a single write.
41
+ *
42
+ * NOTE: If apiKey already contains a SecretRef (type: "env"|"file"|"exec"),
43
+ * it is preserved and NOT overwritten, since OpenClaw handles SecretRef resolution.
44
+ */
45
+ export declare function initWorkclawAgent(params: {
46
+ apiKey?: string;
47
+ agentId?: string;
48
+ userId?: string;
49
+ accountId?: string;
50
+ }, cfg: any, log?: ConfigLogger): Promise<void>;
51
+ /**
52
+ * Save userId to cfg memory and persist to openclaw.json.
53
+ *
54
+ * Used during hardware device initialization to persist the default userId.
55
+ */
56
+ export declare function saveWorkClawUserId(accountId: string, userId: string | number, cfg: any, log?: ConfigLogger): Promise<void>;
57
+ /**
58
+ * Save agentId to cfg memory and persist to openclaw.json.
59
+ *
60
+ * Used during hardware device initialization to persist the default agentId.
61
+ */
62
+ export declare function saveWorkClawAgentId(accountId: string, agentId: string | number, cfg: any, log?: ConfigLogger): Promise<void>;
63
+ /**
64
+ * Save apiKey to cfg memory only.
65
+ *
66
+ * Does NOT write to openclaw.json to avoid triggering openclaw's config watcher,
67
+ * which would re-parse env vars (e.g. ${MODEL_API_KEY}) and potentially
68
+ * overwrite resolved values in the runtime cfg.
69
+ */
70
+ export declare function saveWorkClawApiKey(apiKey: string, cfg: any, log?: ConfigLogger): Promise<void>;
71
+ export {};
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Config Writer - handles writing account config to openclaw.json
3
+ *
4
+ * NOTE: Only agent creation/initialization writes to openclaw.json via writeConfigFile.
5
+ * Runtime dynamic data (openConversationId) is stored in a separate state file
6
+ * to avoid triggering openclaw's config watcher, which would re-parse env vars
7
+ * and potentially overwrite already-resolved values like ${MODEL_API_KEY}.
8
+ */
9
+ import { writeFile, readFile, mkdir, rename } from "fs/promises";
10
+ import { existsSync, readFileSync } from "fs";
11
+ import { join } from "path";
12
+ import { homedir } from "os";
13
+ import { execSync } from "child_process";
14
+ import { getWorkclawRuntime } from "../runtime.js";
15
+ /** 修复目录所有权(仅非 Windows 环境) */
16
+ function fixOwner(dir) {
17
+ if (process.platform === 'win32')
18
+ return;
19
+ try {
20
+ execSync(`chown -R node:node "${dir}"`, { stdio: 'ignore' });
21
+ }
22
+ catch { }
23
+ }
24
+ const STATE_DIR = "workclaw-state";
25
+ // 写入节流时间(避免频繁写入)
26
+ const SAVE_THROTTLE_MS = 1000;
27
+ // 每个账户的上次写入时间,key 格式: accountId:userId
28
+ const lastSaveTimeMap = new Map();
29
+ /**
30
+ * Find the actual openclaw.json config path.
31
+ */
32
+ function findConfigPath() {
33
+ // Prefer homedir config over cwd, since cwd might be the project directory
34
+ // which could have a stale or unrelated openclaw.json
35
+ const configPaths = [
36
+ join(homedir(), ".openclaw", "openclaw.json"),
37
+ join(homedir(), ".openclaw", "config.json"),
38
+ join(process.cwd(), "openclaw.json"),
39
+ join(process.cwd(), "config.json"),
40
+ ];
41
+ const found = configPaths.find((p) => existsSync(p));
42
+ return found ?? join(homedir(), ".openclaw", "openclaw.json");
43
+ }
44
+ /**
45
+ * Get the state directory for workclaw runtime data.
46
+ */
47
+ function findStateDir() {
48
+ const configPath = findConfigPath();
49
+ const openclawDir = join(configPath, "..", "..");
50
+ return join(openclawDir, STATE_DIR);
51
+ }
52
+ function getStateFilePath() {
53
+ return join(findStateDir(), "conversations.json");
54
+ }
55
+ /**
56
+ * Write a new config to the openclaw.json file.
57
+ */
58
+ export async function writeConfigFile(newConfig, cfg, log) {
59
+ try {
60
+ const runtime = getWorkclawRuntime();
61
+ const configApi = runtime.config;
62
+ await configApi.writeConfigFile(newConfig);
63
+ log?.info?.(`[WriteConfig] Config written via runtime.config.writeConfigFile`);
64
+ Object.assign(cfg, newConfig);
65
+ }
66
+ catch (err) {
67
+ log?.error?.(`[WriteConfig] Failed to write config: ${String(err)}`);
68
+ throw err;
69
+ }
70
+ }
71
+ /**
72
+ * Load openConversationId from the separate state file.
73
+ *
74
+ * Key format: accountId:userId
75
+ *
76
+ * Called at runtime to restore openConversationId after process restart,
77
+ * since cfg is reloaded from openclaw.json which does not contain this value.
78
+ */
79
+ export function loadOpenConversationId(accountId, userId) {
80
+ const statePath = getStateFilePath();
81
+ const key = `${accountId}:${userId}`;
82
+ try {
83
+ if (!existsSync(statePath))
84
+ return null;
85
+ const content = readFileSync(statePath, "utf-8");
86
+ const state = JSON.parse(content);
87
+ return state[key]?.openConversationId ?? null;
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ /**
94
+ * Save openConversationId to a separate state file (with write throttling).
95
+ *
96
+ * Key format: accountId:userId
97
+ * Throttling: if called multiple times within 1 second, only the last value is saved.
98
+ * This avoids excessive disk writes from high-frequency messages.
99
+ *
100
+ * Stored in ~/.openclaw/workclaw-state/conversations.json (separate from openclaw.json)
101
+ * to avoid triggering openclaw's config watcher which would re-parse env vars.
102
+ */
103
+ export async function saveOpenConversationId(accountId, userId, openConversationId, cfg, log) {
104
+ const key = `${accountId}:${userId}`;
105
+ // Also update cfg memory immediately
106
+ const workclawCfg = cfg?.channels?.['openclaw-workclaw'];
107
+ if (workclawCfg?.accounts?.[accountId]) {
108
+ workclawCfg.accounts[accountId].openConversationId = openConversationId;
109
+ }
110
+ // Throttle: skip if written recently
111
+ const lastSaveTime = lastSaveTimeMap.get(key) ?? 0;
112
+ const now = Date.now();
113
+ if (now - lastSaveTime < SAVE_THROTTLE_MS) {
114
+ return;
115
+ }
116
+ // Write immediately — never lose a pending value on crash
117
+ await doSaveOpenConversationId(key, openConversationId, log);
118
+ lastSaveTimeMap.set(key, now);
119
+ }
120
+ async function doSaveOpenConversationId(key, openConversationId, log) {
121
+ try {
122
+ const statePath = getStateFilePath();
123
+ let state = {};
124
+ if (existsSync(statePath)) {
125
+ try {
126
+ const content = await readFile(statePath, "utf-8");
127
+ state = JSON.parse(content);
128
+ }
129
+ catch (parseErr) {
130
+ log?.error?.(`SaveConversation: Failed to parse state file: ${String(parseErr)}`);
131
+ }
132
+ }
133
+ if (!state[key])
134
+ state[key] = {};
135
+ // Skip write only when the value is the same (and not empty/null)
136
+ const existing = state[key].openConversationId;
137
+ if (existing === openConversationId && existing != null && existing !== "") {
138
+ return;
139
+ }
140
+ state[key].openConversationId = openConversationId;
141
+ // Ensure state dir exists
142
+ const stateDir = findStateDir();
143
+ if (!existsSync(stateDir)) {
144
+ try {
145
+ await mkdir(stateDir, { recursive: true, mode: 0o755 });
146
+ }
147
+ catch (mkdirErr) {
148
+ if (mkdirErr.code === 'EACCES' || mkdirErr.code === 'EPERM') {
149
+ // Docker/non-root: retry with loose permissions
150
+ await mkdir(stateDir, { recursive: true, mode: 0o777 });
151
+ }
152
+ else {
153
+ throw mkdirErr;
154
+ }
155
+ }
156
+ // 修复权限(目录可能已存在但权限不对)
157
+ fixOwner(stateDir);
158
+ }
159
+ // Atomic write: write to tmp file then rename
160
+ const tmpPath = statePath + ".tmp";
161
+ await writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8");
162
+ await rename(tmpPath, statePath);
163
+ log?.info?.(`SaveConversation: Saved openConversationId for key ${key}`);
164
+ }
165
+ catch (err) {
166
+ log?.error?.(`SaveConversation: Failed to write state file: ${String(err)}`);
167
+ }
168
+ }
169
+ /**
170
+ * Initialize workclaw agent config in one shot (hardware device init).
171
+ *
172
+ * Sets apiKey, agentId, userId and persists to openclaw.json in a single write.
173
+ *
174
+ * NOTE: If apiKey already contains a SecretRef (type: "env"|"file"|"exec"),
175
+ * it is preserved and NOT overwritten, since OpenClaw handles SecretRef resolution.
176
+ */
177
+ export async function initWorkclawAgent(params, cfg, log) {
178
+ try {
179
+ const workclawCfg = cfg?.channels?.['openclaw-workclaw'];
180
+ if (!workclawCfg)
181
+ return;
182
+ if (params.apiKey) {
183
+ // Check if existing value is a SecretRef object - if so, skip to preserve it
184
+ const existingApiKey = cfg.models?.providers?.["sophnet-minimax"]?.apiKey;
185
+ if (existingApiKey && typeof existingApiKey === "object" && existingApiKey.type) {
186
+ log?.info?.(`initWorkclawAgent: apiKey is SecretRef (type=${existingApiKey.type}), skipping overwrite`);
187
+ }
188
+ else {
189
+ if (!cfg.models)
190
+ cfg.models = {};
191
+ if (!cfg.models.providers)
192
+ cfg.models.providers = {};
193
+ if (!cfg.models.providers["sophnet-minimax"])
194
+ cfg.models.providers["sophnet-minimax"] = {};
195
+ cfg.models.providers["sophnet-minimax"].apiKey = params.apiKey;
196
+ log?.info?.(`initWorkclawAgent: apiKey set (plain value)`);
197
+ }
198
+ }
199
+ if (params.agentId) {
200
+ if (!cfg.models)
201
+ cfg.models = {};
202
+ if (!cfg.models.providers)
203
+ cfg.models.providers = {};
204
+ if (!cfg.models.providers["sophnet-minimax"])
205
+ cfg.models.providers["sophnet-minimax"] = {};
206
+ cfg.models.providers["sophnet-minimax"].apiKey = params.apiKey;
207
+ log?.info?.(`initWorkclawAgent: apiKey set`);
208
+ }
209
+ if (params.agentId) {
210
+ const accountId = params.accountId || "default";
211
+ const accounts = workclawCfg.accounts ?? {};
212
+ workclawCfg.accounts = accounts;
213
+ if (!accounts[accountId])
214
+ accounts[accountId] = {};
215
+ accounts[accountId].agentId = params.agentId;
216
+ log?.info?.(`initWorkclawAgent: agentId=${params.agentId} set for ${accountId}`);
217
+ }
218
+ if (params.userId) {
219
+ workclawCfg.userId = params.userId;
220
+ log?.info?.(`initWorkclawAgent: userId=${params.userId} set`);
221
+ }
222
+ // Single write to persist all
223
+ await writeConfigFile(cfg, cfg, log);
224
+ log?.info?.(`initWorkclawAgent: all config persisted`);
225
+ }
226
+ catch (err) {
227
+ log?.error?.(`initWorkclawAgent: failed: ${String(err)}`);
228
+ throw err;
229
+ }
230
+ }
231
+ /**
232
+ * Save userId to cfg memory and persist to openclaw.json.
233
+ *
234
+ * Used during hardware device initialization to persist the default userId.
235
+ */
236
+ export async function saveWorkClawUserId(accountId, userId, cfg, log) {
237
+ try {
238
+ const workclawCfg = cfg?.channels?.['openclaw-workclaw'];
239
+ if (!workclawCfg)
240
+ return;
241
+ workclawCfg.userId = userId;
242
+ log?.info?.(`SaveUserId: Saved userId ${userId} for account ${accountId}`);
243
+ // Persist to openclaw.json via framework API
244
+ await writeConfigFile(cfg, cfg, log);
245
+ }
246
+ catch (err) {
247
+ log?.error?.(`SaveUserId: Failed to update cfg: ${String(err)}`);
248
+ throw err;
249
+ }
250
+ }
251
+ /**
252
+ * Save agentId to cfg memory and persist to openclaw.json.
253
+ *
254
+ * Used during hardware device initialization to persist the default agentId.
255
+ */
256
+ export async function saveWorkClawAgentId(accountId, agentId, cfg, log) {
257
+ try {
258
+ const workclawCfg = cfg?.channels?.['openclaw-workclaw'];
259
+ if (!workclawCfg)
260
+ return;
261
+ const accounts = workclawCfg.accounts;
262
+ let savedToAccount = null;
263
+ if (accounts?.[accountId]) {
264
+ accounts[accountId].agentId = agentId;
265
+ savedToAccount = accountId;
266
+ }
267
+ else if (accounts?.["default"]) {
268
+ if (!accounts["default"].agentId) {
269
+ accounts["default"].agentId = agentId;
270
+ savedToAccount = "default";
271
+ log?.info?.(`SaveAgentId: Saved agentId ${agentId} to default account`);
272
+ }
273
+ }
274
+ else {
275
+ log?.info?.(`SaveAgentId: Account ${accountId} not found, default account also missing`);
276
+ }
277
+ if (savedToAccount) {
278
+ log?.info?.(`SaveAgentId: Saved agentId ${agentId} for account ${savedToAccount}`);
279
+ }
280
+ // Persist to openclaw.json via framework API
281
+ await writeConfigFile(cfg, cfg, log);
282
+ }
283
+ catch (err) {
284
+ log?.error?.(`SaveAgentId: Failed to update cfg: ${String(err)}`);
285
+ throw err;
286
+ }
287
+ }
288
+ /**
289
+ * Save apiKey to cfg memory only.
290
+ *
291
+ * Does NOT write to openclaw.json to avoid triggering openclaw's config watcher,
292
+ * which would re-parse env vars (e.g. ${MODEL_API_KEY}) and potentially
293
+ * overwrite resolved values in the runtime cfg.
294
+ */
295
+ export async function saveWorkClawApiKey(apiKey, cfg, log) {
296
+ try {
297
+ if (!cfg.models)
298
+ cfg.models = {};
299
+ if (!cfg.models.providers)
300
+ cfg.models.providers = {};
301
+ if (!cfg.models.providers["sophnet-minimax"])
302
+ cfg.models.providers["sophnet-minimax"] = {};
303
+ cfg.models.providers["sophnet-minimax"].apiKey = apiKey;
304
+ log?.info?.(`SaveApiKey: Saved apiKey to cfg`);
305
+ // Persist to openclaw.json via framework API
306
+ await writeConfigFile(cfg, cfg, log);
307
+ }
308
+ catch (err) {
309
+ log?.error?.(`SaveApiKey: Failed to update cfg: ${String(err)}`);
310
+ throw err;
311
+ }
312
+ }
@@ -0,0 +1,76 @@
1
+ import type { PluginRuntime } from "openclaw/plugin-sdk";
2
+ export interface Attachment {
3
+ url: string;
4
+ fileId: string;
5
+ type: 'image' | 'file';
6
+ name?: string;
7
+ }
8
+ /** Channel/plugin name constant */
9
+ export declare const OPENCLAW_WORKCLAW_CHANNEL = "openclaw-workclaw";
10
+ export interface InboundMessage {
11
+ text: string;
12
+ to: string;
13
+ from: string;
14
+ chatType: "dm" | "group";
15
+ messageId: string;
16
+ rawPayload: string;
17
+ timestamp: number;
18
+ attachments?: Attachment[];
19
+ }
20
+ export interface InboundContextPayload {
21
+ [key: string]: unknown;
22
+ Body: string;
23
+ BodyForAgent: string;
24
+ RawBody: string;
25
+ From: string;
26
+ To: string;
27
+ ChatType: "dm" | "group";
28
+ Provider: string;
29
+ Surface: string;
30
+ Timestamp: number;
31
+ AccountId: string;
32
+ AgentId?: string;
33
+ MessageSid?: string;
34
+ OriginatingChannel: string;
35
+ OriginatingTo: string;
36
+ }
37
+ export type WorkClawMessageType = "agent_message" | "ping" | "disconnect" | "agent_created" | "agent_updated" | "agent_deleted" | "tools_list" | "skills_list" | "skills_event" | "init_agent" | "ignored";
38
+ export interface ParseWorkClawResult {
39
+ type: WorkClawMessageType;
40
+ message?: {
41
+ text: string;
42
+ userId: string;
43
+ openConversationId: string;
44
+ messageId: string;
45
+ agentId?: string | number;
46
+ attachments?: Attachment[];
47
+ };
48
+ pongData?: any;
49
+ eventData?: any;
50
+ }
51
+ export declare function parseInboundMessage(data: string, allowRawJsonPayload?: boolean): Partial<InboundMessage>;
52
+ export declare function parseWorkClawMessage(data: string, log?: {
53
+ info?: (msg: string) => void;
54
+ warn?: (msg: string) => void;
55
+ error?: (msg: string) => void;
56
+ }): ParseWorkClawResult | null;
57
+ /**
58
+ * Build inbound context for WorkClaw channel.
59
+ *
60
+ * When pluginRuntime is provided, performs full session handling:
61
+ * - resolveStorePath, readSessionUpdatedAt, formatInboundEnvelope
62
+ * - finalizeInboundContext, recordInboundSession
63
+ *
64
+ * @param message - The inbound message
65
+ * @param accountId - Account ID
66
+ * @param config - Account config (WorkclawConfig)
67
+ * @param agentId - Target agent ID (optional)
68
+ * @param pluginRuntime - OpenClaw plugin runtime (optional, enables full session handling)
69
+ * @param recordSession - Whether to record session (default true)
70
+ * @param log - Optional logger
71
+ */
72
+ export declare function buildInboundContext(message: InboundMessage, accountId: string, config: any, agentId?: string, pluginRuntime?: PluginRuntime, recordSession?: boolean, log?: {
73
+ info?: (msg: string) => void;
74
+ warn?: (msg: string) => void;
75
+ error?: (msg: string) => void;
76
+ }): Promise<InboundContextPayload>;