@openclawbrain/openclaw 0.3.6 → 0.4.0

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 (62) hide show
  1. package/README.md +23 -228
  2. package/dist/extension/index.js +3 -2
  3. package/dist/extension/index.js.map +1 -1
  4. package/dist/extension/runtime-guard.js +1 -1
  5. package/dist/extension/runtime-guard.js.map +1 -1
  6. package/dist/src/attachment-truth.d.ts +32 -22
  7. package/dist/src/attachment-truth.js +338 -186
  8. package/dist/src/index.d.ts +75 -1719
  9. package/dist/src/index.js +7 -6882
  10. package/dist/src/runtime-core.js +574 -0
  11. package/extension/index.ts +3 -2
  12. package/extension/runtime-guard.ts +1 -1
  13. package/openclaw.plugin.json +1 -1
  14. package/package.json +17 -17
  15. package/dist/src/attachment-truth.js.map +0 -1
  16. package/dist/src/cli.d.ts +0 -170
  17. package/dist/src/cli.js +0 -5583
  18. package/dist/src/cli.js.map +0 -1
  19. package/dist/src/daemon.d.ts +0 -70
  20. package/dist/src/daemon.js +0 -955
  21. package/dist/src/daemon.js.map +0 -1
  22. package/dist/src/import-export.d.ts +0 -36
  23. package/dist/src/import-export.js +0 -171
  24. package/dist/src/import-export.js.map +0 -1
  25. package/dist/src/index.js.map +0 -1
  26. package/dist/src/learning-spine.d.ts +0 -50
  27. package/dist/src/learning-spine.js.map +0 -1
  28. package/dist/src/local-session-passive-learning.d.ts +0 -61
  29. package/dist/src/local-session-passive-learning.js +0 -454
  30. package/dist/src/local-session-passive-learning.js.map +0 -1
  31. package/dist/src/ollama-client.d.ts +0 -46
  32. package/dist/src/ollama-client.js +0 -231
  33. package/dist/src/ollama-client.js.map +0 -1
  34. package/dist/src/openclaw-home-layout.d.ts +0 -17
  35. package/dist/src/openclaw-home-layout.js +0 -182
  36. package/dist/src/openclaw-home-layout.js.map +0 -1
  37. package/dist/src/openclaw-hook-truth.d.ts +0 -33
  38. package/dist/src/openclaw-hook-truth.js +0 -260
  39. package/dist/src/openclaw-hook-truth.js.map +0 -1
  40. package/dist/src/openclaw-plugin-install.d.ts +0 -40
  41. package/dist/src/openclaw-plugin-install.js +0 -282
  42. package/dist/src/provider-config.d.ts +0 -64
  43. package/dist/src/provider-config.js +0 -306
  44. package/dist/src/provider-config.js.map +0 -1
  45. package/dist/src/resolve-activation-root.d.ts +0 -27
  46. package/dist/src/resolve-activation-root.js +0 -190
  47. package/dist/src/resolve-activation-root.js.map +0 -1
  48. package/dist/src/semantic-metadata.d.ts +0 -5
  49. package/dist/src/semantic-metadata.js +0 -70
  50. package/dist/src/semantic-metadata.js.map +0 -1
  51. package/dist/src/session-store.d.ts +0 -168
  52. package/dist/src/session-store.js +0 -250
  53. package/dist/src/session-store.js.map +0 -1
  54. package/dist/src/session-tail.d.ts +0 -73
  55. package/dist/src/session-tail.js +0 -602
  56. package/dist/src/session-tail.js.map +0 -1
  57. package/dist/src/shadow-extension-proof.d.ts +0 -43
  58. package/dist/src/shadow-extension-proof.js +0 -218
  59. package/dist/src/shadow-extension-proof.js.map +0 -1
  60. package/dist/src/teacher-labeler.d.ts +0 -50
  61. package/dist/src/teacher-labeler.js +0 -424
  62. package/dist/src/teacher-labeler.js.map +0 -1
@@ -1,220 +1,372 @@
1
1
  import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
2
2
  import path from "node:path";
3
- import { inspectOpenClawHome } from "./openclaw-home-layout.js";
4
- import { resolveOpenClawHomeFromExtensionEntryPath } from "./openclaw-plugin-install.js";
3
+
5
4
  const ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT = "openclaw_profile_runtime_load_proofs.v1";
6
5
  const ATTACHMENT_TRUTH_DIRNAME = "attachment-truth";
7
6
  const ATTACHMENT_RUNTIME_LOAD_PROOFS_BASENAME = "runtime-load-proofs.json";
7
+
8
8
  function toErrorMessage(error) {
9
- return error instanceof Error ? error.message : String(error);
9
+ return error instanceof Error ? error.message : String(error);
10
10
  }
11
+
11
12
  function canonicalizeFilesystemPath(filePath) {
12
- const resolvedPath = path.resolve(filePath);
13
- try {
14
- return realpathSync(resolvedPath);
15
- }
16
- catch {
17
- return resolvedPath;
18
- }
13
+ const resolvedPath = path.resolve(filePath);
14
+
15
+ try {
16
+ return realpathSync(resolvedPath);
17
+ } catch {
18
+ return resolvedPath;
19
+ }
20
+ }
21
+
22
+ function normalizeOptionalString(value) {
23
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
19
24
  }
25
+
20
26
  function normalizeIsoTimestamp(value, fieldName, fallbackValue) {
21
- const candidate = value ?? fallbackValue;
22
- if (candidate === undefined || candidate === null || candidate.trim().length === 0) {
23
- throw new Error(`${fieldName} is required`);
24
- }
25
- if (Number.isNaN(Date.parse(candidate))) {
26
- throw new Error(`${fieldName} must be an ISO timestamp`);
27
- }
28
- return new Date(candidate).toISOString();
27
+ const candidate = value ?? fallbackValue;
28
+
29
+ if (candidate === undefined || candidate === null || candidate.trim().length === 0) {
30
+ throw new Error(`${fieldName} is required`);
31
+ }
32
+
33
+ if (Number.isNaN(Date.parse(candidate))) {
34
+ throw new Error(`${fieldName} must be an ISO timestamp`);
35
+ }
36
+
37
+ return new Date(candidate).toISOString();
29
38
  }
39
+
30
40
  function readRecord(value) {
31
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
32
- return null;
33
- }
34
- return value;
41
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
42
+ return null;
43
+ }
44
+
45
+ return value;
35
46
  }
36
- function validateRuntimeLoadProofRecord(value, index) {
37
- const record = readRecord(value);
38
- if (record === null) {
39
- throw new Error(`profiles[${index}] must be an object`);
40
- }
41
- const openclawHome = typeof record.openclawHome === "string" && record.openclawHome.trim().length > 0
42
- ? canonicalizeFilesystemPath(record.openclawHome)
43
- : null;
44
- const profileId = record.profileId === null ? null : typeof record.profileId === "string" && record.profileId.trim().length > 0
45
- ? record.profileId.trim()
46
- : undefined;
47
- const profileSource = record.profileSource === "openclaw_json_profile" ||
48
- record.profileSource === "openclaw_json_single_profile_key" ||
49
- record.profileSource === "directory_name" ||
50
- record.profileSource === "none"
51
- ? record.profileSource
52
- : null;
53
- const extensionEntryPath = typeof record.extensionEntryPath === "string" && record.extensionEntryPath.trim().length > 0
54
- ? canonicalizeFilesystemPath(record.extensionEntryPath)
55
- : null;
56
- const loadedAt = typeof record.loadedAt === "string" && record.loadedAt.trim().length > 0
57
- ? normalizeIsoTimestamp(record.loadedAt, `profiles[${index}].loadedAt`)
58
- : null;
59
- if (openclawHome === null) {
60
- throw new Error(`profiles[${index}].openclawHome must be a non-empty string`);
61
- }
62
- if (profileId === undefined) {
63
- throw new Error(`profiles[${index}].profileId must be null or a non-empty string`);
64
- }
65
- if (profileSource === null) {
66
- throw new Error(`profiles[${index}].profileSource must be a supported OpenClaw profile source`);
67
- }
68
- if (extensionEntryPath === null) {
69
- throw new Error(`profiles[${index}].extensionEntryPath must be a non-empty string`);
70
- }
71
- if (loadedAt === null) {
72
- throw new Error(`profiles[${index}].loadedAt must be a non-empty ISO timestamp`);
47
+
48
+ function listConfiguredProfileIds(config) {
49
+ const profiles = readRecord(config?.profiles);
50
+
51
+ if (profiles === null) {
52
+ return [];
53
+ }
54
+
55
+ return Object.keys(profiles)
56
+ .map((profileId) => profileId.trim())
57
+ .filter((profileId) => profileId.length > 0)
58
+ .sort((left, right) => left.localeCompare(right));
59
+ }
60
+
61
+ function deriveDirectoryProfileId(openclawHome) {
62
+ const basename = path.basename(openclawHome);
63
+
64
+ if (!basename.startsWith(".openclaw-")) {
65
+ return null;
66
+ }
67
+
68
+ const derived = basename.slice(".openclaw-".length).trim();
69
+ return derived.length > 0 ? derived : null;
70
+ }
71
+
72
+ function inspectOpenClawHome(openclawHome) {
73
+ const resolvedHome = path.resolve(openclawHome);
74
+ const openclawJsonPath = path.join(resolvedHome, "openclaw.json");
75
+ let config = null;
76
+
77
+ if (existsSync(openclawJsonPath)) {
78
+ try {
79
+ config = readRecord(JSON.parse(readFileSync(openclawJsonPath, "utf8")));
80
+ } catch {
81
+ config = null;
73
82
  }
83
+ }
84
+
85
+ const configuredProfileIds = listConfiguredProfileIds(config);
86
+ const directProfile = normalizeOptionalString(config?.profile);
87
+
88
+ if (directProfile !== null) {
89
+ return {
90
+ profileId: directProfile,
91
+ profileSource: "openclaw_json_profile",
92
+ };
93
+ }
94
+
95
+ if (configuredProfileIds.length === 1) {
96
+ return {
97
+ profileId: configuredProfileIds[0],
98
+ profileSource: "openclaw_json_single_profile_key",
99
+ };
100
+ }
101
+
102
+ const directoryProfile = deriveDirectoryProfileId(resolvedHome);
103
+ if (directoryProfile !== null) {
74
104
  return {
75
- openclawHome,
76
- profileId,
77
- profileSource,
78
- extensionEntryPath,
79
- loadedAt
105
+ profileId: directoryProfile,
106
+ profileSource: "directory_name",
80
107
  };
108
+ }
109
+
110
+ return {
111
+ profileId: null,
112
+ profileSource: "none",
113
+ };
81
114
  }
82
- function validateRuntimeLoadProofs(activationRoot, value) {
83
- const record = readRecord(value);
84
- if (record === null) {
85
- throw new Error("runtime load proof file must contain an object");
86
- }
87
- if (record.contract !== ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT) {
88
- throw new Error(`runtime load proof contract must be ${ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT}`);
89
- }
90
- if (record.runtimeOwner !== "openclaw") {
91
- throw new Error("runtime load proof runtimeOwner must be openclaw");
92
- }
93
- if (typeof record.activationRoot !== "string" || record.activationRoot.trim().length === 0) {
94
- throw new Error("runtime load proof activationRoot must be a non-empty string");
115
+
116
+ function resolveOpenClawHomeFromExtensionEntryPath(extensionEntryPath) {
117
+ let currentPath = path.resolve(extensionEntryPath);
118
+
119
+ while (true) {
120
+ const parentPath = path.dirname(currentPath);
121
+
122
+ if (parentPath === currentPath) {
123
+ break;
95
124
  }
96
- const resolvedActivationRoot = path.resolve(record.activationRoot);
97
- if (resolvedActivationRoot !== activationRoot) {
98
- throw new Error(`runtime load proof activationRoot mismatch: expected ${activationRoot}, received ${resolvedActivationRoot}`);
125
+
126
+ if (path.basename(parentPath) === "extensions") {
127
+ return path.dirname(parentPath);
99
128
  }
100
- const updatedAt = typeof record.updatedAt === "string" && record.updatedAt.trim().length > 0
101
- ? normalizeIsoTimestamp(record.updatedAt, "updatedAt")
102
- : null;
103
- if (updatedAt === null) {
104
- throw new Error("runtime load proof updatedAt must be a non-empty ISO timestamp");
105
- }
106
- if (!Array.isArray(record.profiles)) {
107
- throw new Error("runtime load proof profiles must be an array");
108
- }
109
- const profiles = record.profiles.map((entry, index) => validateRuntimeLoadProofRecord(entry, index));
110
- return {
111
- contract: ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT,
112
- runtimeOwner: "openclaw",
113
- activationRoot,
114
- updatedAt,
115
- profiles
116
- };
129
+
130
+ currentPath = parentPath;
131
+ }
132
+
133
+ return null;
134
+ }
135
+
136
+ function validateRuntimeLoadProofRecord(value, index) {
137
+ const record = readRecord(value);
138
+
139
+ if (record === null) {
140
+ throw new Error(`profiles[${index}] must be an object`);
141
+ }
142
+
143
+ const openclawHome =
144
+ typeof record.openclawHome === "string" && record.openclawHome.trim().length > 0
145
+ ? canonicalizeFilesystemPath(record.openclawHome)
146
+ : null;
147
+ const profileId =
148
+ record.profileId === null
149
+ ? null
150
+ : typeof record.profileId === "string" && record.profileId.trim().length > 0
151
+ ? record.profileId.trim()
152
+ : undefined;
153
+ const profileSource =
154
+ record.profileSource === "openclaw_json_profile" ||
155
+ record.profileSource === "openclaw_json_single_profile_key" ||
156
+ record.profileSource === "directory_name" ||
157
+ record.profileSource === "none"
158
+ ? record.profileSource
159
+ : null;
160
+ const extensionEntryPath =
161
+ typeof record.extensionEntryPath === "string" && record.extensionEntryPath.trim().length > 0
162
+ ? canonicalizeFilesystemPath(record.extensionEntryPath)
163
+ : null;
164
+ const loadedAt =
165
+ typeof record.loadedAt === "string" && record.loadedAt.trim().length > 0
166
+ ? normalizeIsoTimestamp(record.loadedAt, `profiles[${index}].loadedAt`)
167
+ : null;
168
+
169
+ if (openclawHome === null) {
170
+ throw new Error(`profiles[${index}].openclawHome must be a non-empty string`);
171
+ }
172
+
173
+ if (profileId === undefined) {
174
+ throw new Error(`profiles[${index}].profileId must be null or a non-empty string`);
175
+ }
176
+
177
+ if (profileSource === null) {
178
+ throw new Error(`profiles[${index}].profileSource must be a supported OpenClaw profile source`);
179
+ }
180
+
181
+ if (extensionEntryPath === null) {
182
+ throw new Error(`profiles[${index}].extensionEntryPath must be a non-empty string`);
183
+ }
184
+
185
+ if (loadedAt === null) {
186
+ throw new Error(`profiles[${index}].loadedAt must be a non-empty ISO timestamp`);
187
+ }
188
+
189
+ return {
190
+ openclawHome,
191
+ profileId,
192
+ profileSource,
193
+ extensionEntryPath,
194
+ loadedAt,
195
+ };
196
+ }
197
+
198
+ function validateRuntimeLoadProofs(activationRoot, value) {
199
+ const record = readRecord(value);
200
+
201
+ if (record === null) {
202
+ throw new Error("runtime load proof file must contain an object");
203
+ }
204
+
205
+ if (record.contract !== ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT) {
206
+ throw new Error(`runtime load proof contract must be ${ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT}`);
207
+ }
208
+
209
+ if (record.runtimeOwner !== "openclaw") {
210
+ throw new Error("runtime load proof runtimeOwner must be openclaw");
211
+ }
212
+
213
+ if (typeof record.activationRoot !== "string" || record.activationRoot.trim().length === 0) {
214
+ throw new Error("runtime load proof activationRoot must be a non-empty string");
215
+ }
216
+
217
+ const resolvedActivationRoot = path.resolve(record.activationRoot);
218
+ if (resolvedActivationRoot !== activationRoot) {
219
+ throw new Error(
220
+ `runtime load proof activationRoot mismatch: expected ${activationRoot}, received ${resolvedActivationRoot}`,
221
+ );
222
+ }
223
+
224
+ const updatedAt =
225
+ typeof record.updatedAt === "string" && record.updatedAt.trim().length > 0
226
+ ? normalizeIsoTimestamp(record.updatedAt, "updatedAt")
227
+ : null;
228
+
229
+ if (updatedAt === null) {
230
+ throw new Error("runtime load proof updatedAt must be a non-empty ISO timestamp");
231
+ }
232
+
233
+ if (!Array.isArray(record.profiles)) {
234
+ throw new Error("runtime load proof profiles must be an array");
235
+ }
236
+
237
+ const profiles = record.profiles.map((entry, index) => validateRuntimeLoadProofRecord(entry, index));
238
+
239
+ return {
240
+ contract: ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT,
241
+ runtimeOwner: "openclaw",
242
+ activationRoot,
243
+ updatedAt,
244
+ profiles,
245
+ };
117
246
  }
247
+
118
248
  function buildEmptyRuntimeLoadProofs(activationRoot, updatedAt) {
119
- return {
120
- contract: ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT,
121
- runtimeOwner: "openclaw",
122
- activationRoot,
123
- updatedAt,
124
- profiles: []
125
- };
249
+ return {
250
+ contract: ATTACHMENT_RUNTIME_LOAD_PROOFS_CONTRACT,
251
+ runtimeOwner: "openclaw",
252
+ activationRoot,
253
+ updatedAt,
254
+ profiles: [],
255
+ };
126
256
  }
257
+
127
258
  function writeRuntimeLoadProofs(proofPath, proofs) {
128
- mkdirSync(path.dirname(proofPath), { recursive: true });
129
- writeFileSync(proofPath, `${JSON.stringify(proofs, null, 2)}\n`, "utf8");
259
+ mkdirSync(path.dirname(proofPath), { recursive: true });
260
+ writeFileSync(proofPath, `${JSON.stringify(proofs, null, 2)}\n`, "utf8");
130
261
  }
262
+
131
263
  function deriveOpenClawHomeFromExtensionEntryPath(extensionEntryPath) {
132
- const openclawHome = resolveOpenClawHomeFromExtensionEntryPath(extensionEntryPath);
133
- if (openclawHome === null) {
134
- throw new Error(`extension entry path ${extensionEntryPath} is not nested under an OpenClaw extensions dir`);
135
- }
136
- return canonicalizeFilesystemPath(openclawHome);
264
+ const openclawHome = resolveOpenClawHomeFromExtensionEntryPath(extensionEntryPath);
265
+
266
+ if (openclawHome === null) {
267
+ throw new Error(`extension entry path ${extensionEntryPath} is not nested under an OpenClaw extensions dir`);
268
+ }
269
+
270
+ return canonicalizeFilesystemPath(openclawHome);
137
271
  }
272
+
138
273
  export function resolveAttachmentRuntimeLoadProofsPath(activationRoot) {
139
- return path.join(path.resolve(activationRoot), ATTACHMENT_TRUTH_DIRNAME, ATTACHMENT_RUNTIME_LOAD_PROOFS_BASENAME);
274
+ return path.join(path.resolve(activationRoot), ATTACHMENT_TRUTH_DIRNAME, ATTACHMENT_RUNTIME_LOAD_PROOFS_BASENAME);
140
275
  }
276
+
141
277
  export function listOpenClawProfileRuntimeLoadProofs(activationRoot) {
142
- const resolvedActivationRoot = path.resolve(activationRoot);
143
- const proofPath = resolveAttachmentRuntimeLoadProofsPath(resolvedActivationRoot);
144
- if (!existsSync(proofPath)) {
145
- return {
146
- path: proofPath,
147
- proofs: null,
148
- error: null
149
- };
150
- }
151
- try {
152
- const parsed = JSON.parse(readFileSync(proofPath, "utf8"));
153
- return {
154
- path: proofPath,
155
- proofs: validateRuntimeLoadProofs(resolvedActivationRoot, parsed),
156
- error: null
157
- };
158
- }
159
- catch (error) {
160
- return {
161
- path: proofPath,
162
- proofs: null,
163
- error: toErrorMessage(error)
164
- };
165
- }
278
+ const resolvedActivationRoot = path.resolve(activationRoot);
279
+ const proofPath = resolveAttachmentRuntimeLoadProofsPath(resolvedActivationRoot);
280
+
281
+ if (!existsSync(proofPath)) {
282
+ return {
283
+ path: proofPath,
284
+ proofs: null,
285
+ error: null,
286
+ };
287
+ }
288
+
289
+ try {
290
+ const parsed = JSON.parse(readFileSync(proofPath, "utf8"));
291
+
292
+ return {
293
+ path: proofPath,
294
+ proofs: validateRuntimeLoadProofs(resolvedActivationRoot, parsed),
295
+ error: null,
296
+ };
297
+ } catch (error) {
298
+ return {
299
+ path: proofPath,
300
+ proofs: null,
301
+ error: toErrorMessage(error),
302
+ };
303
+ }
166
304
  }
305
+
167
306
  export function recordOpenClawProfileRuntimeLoadProof(input) {
168
- const activationRoot = path.resolve(input.activationRoot);
169
- const loadedAt = normalizeIsoTimestamp(input.loadedAt, "loadedAt", new Date().toISOString());
170
- const extensionEntryPath = canonicalizeFilesystemPath(input.extensionEntryPath);
171
- const openclawHome = deriveOpenClawHomeFromExtensionEntryPath(extensionEntryPath);
172
- const inspection = inspectOpenClawHome(openclawHome);
173
- const loadedProofs = listOpenClawProfileRuntimeLoadProofs(activationRoot);
174
- if (loadedProofs.error !== null) {
175
- throw new Error(`runtime load proof file ${loadedProofs.path} is unreadable: ${loadedProofs.error}`);
176
- }
177
- const nextRecord = {
178
- openclawHome: canonicalizeFilesystemPath(openclawHome),
179
- profileId: inspection.profileId,
180
- profileSource: inspection.profileSource,
181
- loadedAt,
182
- extensionEntryPath
183
- };
184
- const nextProofs = loadedProofs.proofs === null
185
- ? buildEmptyRuntimeLoadProofs(activationRoot, loadedAt)
186
- : {
187
- ...loadedProofs.proofs,
188
- updatedAt: loadedAt,
189
- profiles: [...loadedProofs.proofs.profiles]
307
+ const activationRoot = path.resolve(input.activationRoot);
308
+ const loadedAt = normalizeIsoTimestamp(input.loadedAt, "loadedAt", new Date().toISOString());
309
+ const extensionEntryPath = canonicalizeFilesystemPath(input.extensionEntryPath);
310
+ const openclawHome = deriveOpenClawHomeFromExtensionEntryPath(extensionEntryPath);
311
+ const inspection = inspectOpenClawHome(openclawHome);
312
+ const loadedProofs = listOpenClawProfileRuntimeLoadProofs(activationRoot);
313
+
314
+ if (loadedProofs.error !== null) {
315
+ throw new Error(`runtime load proof file ${loadedProofs.path} is unreadable: ${loadedProofs.error}`);
316
+ }
317
+
318
+ const nextRecord = {
319
+ openclawHome: canonicalizeFilesystemPath(openclawHome),
320
+ profileId: inspection.profileId,
321
+ profileSource: inspection.profileSource,
322
+ loadedAt,
323
+ extensionEntryPath,
324
+ };
325
+ const nextProofs =
326
+ loadedProofs.proofs === null
327
+ ? buildEmptyRuntimeLoadProofs(activationRoot, loadedAt)
328
+ : {
329
+ ...loadedProofs.proofs,
330
+ updatedAt: loadedAt,
331
+ profiles: [...loadedProofs.proofs.profiles],
190
332
  };
191
- nextProofs.profiles = nextProofs.profiles
192
- .filter((record) => canonicalizeFilesystemPath(record.openclawHome) !== nextRecord.openclawHome)
193
- .concat(nextRecord)
194
- .sort((left, right) => left.openclawHome.localeCompare(right.openclawHome));
195
- writeRuntimeLoadProofs(loadedProofs.path, nextProofs);
196
- return nextRecord;
333
+
334
+ nextProofs.profiles = nextProofs.profiles
335
+ .filter((record) => canonicalizeFilesystemPath(record.openclawHome) !== nextRecord.openclawHome)
336
+ .concat(nextRecord)
337
+ .sort((left, right) => left.openclawHome.localeCompare(right.openclawHome));
338
+
339
+ writeRuntimeLoadProofs(loadedProofs.path, nextProofs);
340
+ return nextRecord;
197
341
  }
342
+
198
343
  export function clearOpenClawProfileRuntimeLoadProof(input) {
199
- const activationRoot = path.resolve(input.activationRoot);
200
- const clearedAt = normalizeIsoTimestamp(input.clearedAt, "clearedAt", new Date().toISOString());
201
- const openclawHome = canonicalizeFilesystemPath(input.openclawHome);
202
- const loadedProofs = listOpenClawProfileRuntimeLoadProofs(activationRoot);
203
- if (loadedProofs.error !== null) {
204
- throw new Error(`runtime load proof file ${loadedProofs.path} is unreadable: ${loadedProofs.error}`);
205
- }
206
- if (loadedProofs.proofs === null) {
207
- return false;
208
- }
209
- const filteredProfiles = loadedProofs.proofs.profiles.filter((record) => canonicalizeFilesystemPath(record.openclawHome) !== openclawHome);
210
- if (filteredProfiles.length === loadedProofs.proofs.profiles.length) {
211
- return false;
212
- }
213
- writeRuntimeLoadProofs(loadedProofs.path, {
214
- ...loadedProofs.proofs,
215
- updatedAt: clearedAt,
216
- profiles: filteredProfiles
217
- });
218
- return true;
219
- }
220
- //# sourceMappingURL=attachment-truth.js.map
344
+ const activationRoot = path.resolve(input.activationRoot);
345
+ const clearedAt = normalizeIsoTimestamp(input.clearedAt, "clearedAt", new Date().toISOString());
346
+ const openclawHome = canonicalizeFilesystemPath(input.openclawHome);
347
+ const loadedProofs = listOpenClawProfileRuntimeLoadProofs(activationRoot);
348
+
349
+ if (loadedProofs.error !== null) {
350
+ throw new Error(`runtime load proof file ${loadedProofs.path} is unreadable: ${loadedProofs.error}`);
351
+ }
352
+
353
+ if (loadedProofs.proofs === null) {
354
+ return false;
355
+ }
356
+
357
+ const filteredProfiles = loadedProofs.proofs.profiles.filter(
358
+ (record) => canonicalizeFilesystemPath(record.openclawHome) !== openclawHome,
359
+ );
360
+
361
+ if (filteredProfiles.length === loadedProofs.proofs.profiles.length) {
362
+ return false;
363
+ }
364
+
365
+ writeRuntimeLoadProofs(loadedProofs.path, {
366
+ ...loadedProofs.proofs,
367
+ updatedAt: clearedAt,
368
+ profiles: filteredProfiles,
369
+ });
370
+
371
+ return true;
372
+ }