forge-openclaw-plugin 0.2.3 → 0.2.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 (117) hide show
  1. package/README.md +114 -6
  2. package/dist/assets/board-CzgvdLO8.js +6 -0
  3. package/dist/assets/board-CzgvdLO8.js.map +1 -0
  4. package/dist/assets/favicon-BCHm9dUV.ico +0 -0
  5. package/dist/assets/index-8d_oM8fL.js +27 -0
  6. package/dist/assets/index-8d_oM8fL.js.map +1 -0
  7. package/dist/assets/index-D4A_bq8m.css +1 -0
  8. package/dist/assets/motion-STUd1O46.js +10 -0
  9. package/dist/assets/motion-STUd1O46.js.map +1 -0
  10. package/dist/assets/plus-jakarta-sans-latin-ext-wght-normal-DmpS2jIq.woff2 +0 -0
  11. package/dist/assets/plus-jakarta-sans-latin-wght-normal-eXO_dkmS.woff2 +0 -0
  12. package/dist/assets/plus-jakarta-sans-vietnamese-wght-normal-qRpaaN48.woff2 +0 -0
  13. package/dist/assets/sora-latin-ext-wght-normal-CawQDOvP.woff2 +0 -0
  14. package/dist/assets/sora-latin-wght-normal-DdqRvwsR.woff2 +0 -0
  15. package/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
  16. package/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
  17. package/dist/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
  18. package/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
  19. package/dist/assets/space-grotesk-latin-ext-500-normal-3dgZTiw9.woff +0 -0
  20. package/dist/assets/space-grotesk-latin-ext-500-normal-DUe3BAxM.woff2 +0 -0
  21. package/dist/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
  22. package/dist/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
  23. package/dist/assets/space-grotesk-vietnamese-500-normal-BTqKIpxg.woff +0 -0
  24. package/dist/assets/space-grotesk-vietnamese-500-normal-BmEvtly_.woff2 +0 -0
  25. package/dist/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
  26. package/dist/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
  27. package/dist/assets/table-CtNlETLc.js +23 -0
  28. package/dist/assets/table-CtNlETLc.js.map +1 -0
  29. package/dist/assets/ui-ThzkR_oW.js +46 -0
  30. package/dist/assets/ui-ThzkR_oW.js.map +1 -0
  31. package/dist/assets/vendor-CRS-psbw.css +1 -0
  32. package/dist/assets/vendor-DyHAI6nk.js +423 -0
  33. package/dist/assets/vendor-DyHAI6nk.js.map +1 -0
  34. package/dist/assets/viz-BJuBCz_G.js +34 -0
  35. package/dist/assets/viz-BJuBCz_G.js.map +1 -0
  36. package/dist/favicon.ico +0 -0
  37. package/dist/favicon.png +0 -0
  38. package/dist/index.html +29 -0
  39. package/dist/openclaw/api-client.d.ts +8 -0
  40. package/dist/openclaw/api-client.js +31 -4
  41. package/dist/openclaw/local-runtime.d.ts +3 -0
  42. package/dist/openclaw/local-runtime.js +135 -0
  43. package/dist/openclaw/parity.d.ts +4 -4
  44. package/dist/openclaw/parity.js +23 -33
  45. package/dist/openclaw/plugin-entry-shared.d.ts +5 -3
  46. package/dist/openclaw/plugin-entry-shared.js +52 -10
  47. package/dist/openclaw/routes.d.ts +12 -3
  48. package/dist/openclaw/routes.js +156 -924
  49. package/dist/openclaw/tools.js +242 -1100
  50. package/dist/server/app.js +2450 -0
  51. package/dist/server/db.js +313 -0
  52. package/dist/server/e2e-server.js +20 -0
  53. package/dist/server/errors.js +15 -0
  54. package/dist/server/index.js +16 -0
  55. package/dist/server/managers/base.js +17 -0
  56. package/dist/server/managers/contracts.js +47 -0
  57. package/dist/server/managers/platform/api-gateway-manager.js +11 -0
  58. package/dist/server/managers/platform/audit-manager.js +15 -0
  59. package/dist/server/managers/platform/authentication-manager.js +56 -0
  60. package/dist/server/managers/platform/authorization-manager.js +56 -0
  61. package/dist/server/managers/platform/background-job-manager.js +10 -0
  62. package/dist/server/managers/platform/configuration-manager.js +33 -0
  63. package/dist/server/managers/platform/database-manager.js +14 -0
  64. package/dist/server/managers/platform/event-bus-manager.js +7 -0
  65. package/dist/server/managers/platform/external-service-manager.js +11 -0
  66. package/dist/server/managers/platform/health-manager.js +7 -0
  67. package/dist/server/managers/platform/migration-manager.js +8 -0
  68. package/dist/server/managers/platform/search-index-manager.js +4 -0
  69. package/dist/server/managers/platform/secrets-manager.js +19 -0
  70. package/dist/server/managers/platform/session-manager.js +121 -0
  71. package/dist/server/managers/platform/storage-manager.js +16 -0
  72. package/dist/server/managers/platform/token-manager.js +37 -0
  73. package/dist/server/managers/platform/transaction-manager.js +8 -0
  74. package/dist/server/managers/platform/trusted-network.js +39 -0
  75. package/dist/server/managers/runtime.js +56 -0
  76. package/dist/server/managers/type-guards.js +4 -0
  77. package/dist/server/openapi.js +3512 -0
  78. package/dist/server/psyche-types.js +395 -0
  79. package/dist/server/repositories/activity-events.js +157 -0
  80. package/dist/server/repositories/collaboration.js +497 -0
  81. package/dist/server/repositories/comments.js +176 -0
  82. package/dist/server/repositories/deleted-entities.js +192 -0
  83. package/dist/server/repositories/domains.js +30 -0
  84. package/dist/server/repositories/event-log.js +64 -0
  85. package/dist/server/repositories/goals.js +159 -0
  86. package/dist/server/repositories/projects.js +214 -0
  87. package/dist/server/repositories/psyche.js +1356 -0
  88. package/dist/server/repositories/rewards.js +675 -0
  89. package/dist/server/repositories/settings.js +399 -0
  90. package/dist/server/repositories/tags.js +160 -0
  91. package/dist/server/repositories/task-runs.js +488 -0
  92. package/dist/server/repositories/tasks.js +413 -0
  93. package/dist/server/services/context.js +214 -0
  94. package/dist/server/services/dashboard.js +170 -0
  95. package/dist/server/services/entity-crud.js +576 -0
  96. package/dist/server/services/gamification.js +215 -0
  97. package/dist/server/services/insights.js +91 -0
  98. package/dist/server/services/projects.js +75 -0
  99. package/dist/server/services/psyche.js +63 -0
  100. package/dist/server/services/relations.js +28 -0
  101. package/dist/server/services/reviews.js +88 -0
  102. package/dist/server/services/run-recovery.js +13 -0
  103. package/dist/server/services/tagging.js +49 -0
  104. package/dist/server/services/task-run-watchdog.js +92 -0
  105. package/dist/server/services/work-time.js +176 -0
  106. package/dist/server/types.js +999 -0
  107. package/dist/server/web.js +91 -0
  108. package/openclaw.plugin.json +22 -10
  109. package/package.json +17 -4
  110. package/server/migrations/001_core.sql +333 -0
  111. package/server/migrations/002_psyche.sql +241 -0
  112. package/server/migrations/003_timer_execution.sql +18 -0
  113. package/server/migrations/004_psyche_linked_entities.sql +5 -0
  114. package/server/migrations/005_adaptive_schemas.sql +157 -0
  115. package/server/migrations/006_psyche_auth_setting.sql +4 -0
  116. package/server/migrations/007_deleted_entities.sql +16 -0
  117. package/skills/forge-openclaw/SKILL.md +189 -275
@@ -0,0 +1,576 @@
1
+ import { getDatabase, runInTransaction } from "../db.js";
2
+ import { deleteComment, getCommentById, listComments, updateComment, createComment } from "../repositories/comments.js";
3
+ import { createInsight, deleteInsight, getInsightById, listInsights, updateInsight } from "../repositories/collaboration.js";
4
+ import { createBehaviorPatternSchema, createBehaviorSchema, createBeliefEntrySchema, createCommentSchema, createEmotionDefinitionSchema, createEventTypeSchema, createModeGuideSessionSchema, createModeProfileSchema, createPsycheValueSchema, createTriggerReportSchema, updateBehaviorPatternSchema, updateBehaviorSchema, updateBeliefEntrySchema, updateCommentSchema, updateEmotionDefinitionSchema, updateEventTypeSchema, updateModeGuideSessionSchema, updateModeProfileSchema, updatePsycheValueSchema, updateTriggerReportSchema } from "../psyche-types.js";
5
+ import { buildSettingsBinPayload, cascadeSoftDeleteAnchoredCollaboration, clearDeletedEntityRecord, getDeletedEntityRecord, listDeletedEntities, restoreAnchoredCollaboration, restoreDeletedEntityRecord, upsertDeletedEntityRecord } from "../repositories/deleted-entities.js";
6
+ import { createGoal, deleteGoal, getGoalById, listGoals, updateGoal } from "../repositories/goals.js";
7
+ import { createBehavior, createBehaviorPattern, createBeliefEntry, createEmotionDefinition, createEventType, createModeGuideSession, createModeProfile, createPsycheValue, createTriggerReport, deleteBehavior, deleteBehaviorPattern, deleteBeliefEntry, deleteEmotionDefinition, deleteEventType, deleteModeGuideSession, deleteModeProfile, deletePsycheValue, deleteTriggerReport, getBehaviorById, getBehaviorPatternById, getBeliefEntryById, getEmotionDefinitionById, getEventTypeById, getModeGuideSessionById, getModeProfileById, getPsycheValueById, getTriggerReportById, listBehaviors, listBehaviorPatterns, listBeliefEntries, listEmotionDefinitions, listEventTypes, listModeGuideSessions, listModeProfiles, listPsycheValues, listTriggerReports, updateBehavior, updateBehaviorPattern, updateBeliefEntry, updateEmotionDefinition, updateEventType, updateModeGuideSession, updateModeProfile, updatePsycheValue, updateTriggerReport } from "../repositories/psyche.js";
8
+ import { createProject, deleteProject, getProjectById, listProjects, updateProject } from "../repositories/projects.js";
9
+ import { createTag, deleteTag, getTagById, listTags, updateTag } from "../repositories/tags.js";
10
+ import { createTask, deleteTask, getTaskById, listTasks, updateTask } from "../repositories/tasks.js";
11
+ import { createGoalSchema, createInsightSchema, createProjectSchema, createTagSchema, createTaskSchema, updateGoalSchema, updateInsightSchema, updateProjectSchema, updateTagSchema, updateTaskSchema } from "../types.js";
12
+ class AtomicBatchRollback extends Error {
13
+ index;
14
+ code;
15
+ messageText;
16
+ constructor(index, code, messageText) {
17
+ super(messageText);
18
+ this.index = index;
19
+ this.code = code;
20
+ this.messageText = messageText;
21
+ this.name = "AtomicBatchRollback";
22
+ }
23
+ }
24
+ const CRUD_ENTITY_CAPABILITIES = {
25
+ goal: {
26
+ entityType: "goal",
27
+ routeBase: "/api/v1/goals",
28
+ list: () => listGoals(),
29
+ get: (id) => getGoalById(id),
30
+ create: (data, context) => createGoal(data, context),
31
+ update: (id, patch, context) => updateGoal(id, patch, context),
32
+ hardDelete: (id, context) => deleteGoal(id, context)
33
+ },
34
+ project: {
35
+ entityType: "project",
36
+ routeBase: "/api/v1/projects",
37
+ list: () => listProjects(),
38
+ get: (id) => getProjectById(id),
39
+ create: (data, context) => createProject(data, context),
40
+ update: (id, patch, context) => updateProject(id, patch, context),
41
+ hardDelete: (id, context) => deleteProject(id, context)
42
+ },
43
+ task: {
44
+ entityType: "task",
45
+ routeBase: "/api/v1/tasks",
46
+ list: () => listTasks(),
47
+ get: (id) => getTaskById(id),
48
+ create: (data, context) => createTask(data, context),
49
+ update: (id, patch, context) => updateTask(id, patch, context),
50
+ hardDelete: (id, context) => deleteTask(id, context)
51
+ },
52
+ tag: {
53
+ entityType: "tag",
54
+ routeBase: "/api/v1/tags",
55
+ list: () => listTags(),
56
+ get: (id) => getTagById(id),
57
+ create: (data, context) => createTag(data, context),
58
+ update: (id, patch, context) => updateTag(id, patch, context),
59
+ hardDelete: (id, context) => deleteTag(id, context)
60
+ },
61
+ comment: {
62
+ entityType: "comment",
63
+ routeBase: "/api/v1/comments",
64
+ list: () => listComments(),
65
+ get: (id) => getCommentById(id),
66
+ create: (data, context) => createComment(data, context),
67
+ update: (id, patch, context) => updateComment(id, patch, context),
68
+ hardDelete: (id, context) => deleteComment(id, context)
69
+ },
70
+ insight: {
71
+ entityType: "insight",
72
+ routeBase: "/api/v1/insights",
73
+ list: () => listInsights(),
74
+ get: (id) => getInsightById(id),
75
+ create: (data, context) => createInsight(data, context),
76
+ update: (id, patch, context) => updateInsight(id, patch, context),
77
+ hardDelete: (id, context) => deleteInsight(id, context)
78
+ },
79
+ psyche_value: {
80
+ entityType: "psyche_value",
81
+ routeBase: "/api/v1/psyche/values",
82
+ list: () => listPsycheValues(),
83
+ get: (id) => getPsycheValueById(id),
84
+ create: (data, context) => createPsycheValue(data, context),
85
+ update: (id, patch, context) => updatePsycheValue(id, patch, context),
86
+ hardDelete: (id, context) => deletePsycheValue(id, context)
87
+ },
88
+ behavior_pattern: {
89
+ entityType: "behavior_pattern",
90
+ routeBase: "/api/v1/psyche/patterns",
91
+ list: () => listBehaviorPatterns(),
92
+ get: (id) => getBehaviorPatternById(id),
93
+ create: (data, context) => createBehaviorPattern(data, context),
94
+ update: (id, patch, context) => updateBehaviorPattern(id, patch, context),
95
+ hardDelete: (id, context) => deleteBehaviorPattern(id, context)
96
+ },
97
+ behavior: {
98
+ entityType: "behavior",
99
+ routeBase: "/api/v1/psyche/behaviors",
100
+ list: () => listBehaviors(),
101
+ get: (id) => getBehaviorById(id),
102
+ create: (data, context) => createBehavior(data, context),
103
+ update: (id, patch, context) => updateBehavior(id, patch, context),
104
+ hardDelete: (id, context) => deleteBehavior(id, context)
105
+ },
106
+ belief_entry: {
107
+ entityType: "belief_entry",
108
+ routeBase: "/api/v1/psyche/beliefs",
109
+ list: () => listBeliefEntries(),
110
+ get: (id) => getBeliefEntryById(id),
111
+ create: (data, context) => createBeliefEntry(data, context),
112
+ update: (id, patch, context) => updateBeliefEntry(id, patch, context),
113
+ hardDelete: (id, context) => deleteBeliefEntry(id, context)
114
+ },
115
+ mode_profile: {
116
+ entityType: "mode_profile",
117
+ routeBase: "/api/v1/psyche/modes",
118
+ list: () => listModeProfiles(),
119
+ get: (id) => getModeProfileById(id),
120
+ create: (data, context) => createModeProfile(data, context),
121
+ update: (id, patch, context) => updateModeProfile(id, patch, context),
122
+ hardDelete: (id, context) => deleteModeProfile(id, context)
123
+ },
124
+ mode_guide_session: {
125
+ entityType: "mode_guide_session",
126
+ routeBase: "/api/v1/psyche/mode-guides",
127
+ list: () => listModeGuideSessions(200),
128
+ get: (id) => getModeGuideSessionById(id),
129
+ create: (data, context) => createModeGuideSession(data, context),
130
+ update: (id, patch, context) => updateModeGuideSession(id, patch, context),
131
+ hardDelete: (id, context) => deleteModeGuideSession(id, context)
132
+ },
133
+ event_type: {
134
+ entityType: "event_type",
135
+ routeBase: "/api/v1/psyche/event-types",
136
+ list: () => listEventTypes(),
137
+ get: (id) => getEventTypeById(id),
138
+ create: (data, context) => createEventType(data, context),
139
+ update: (id, patch, context) => updateEventType(id, patch, context),
140
+ hardDelete: (id, context) => deleteEventType(id, context)
141
+ },
142
+ emotion_definition: {
143
+ entityType: "emotion_definition",
144
+ routeBase: "/api/v1/psyche/emotions",
145
+ list: () => listEmotionDefinitions(),
146
+ get: (id) => getEmotionDefinitionById(id),
147
+ create: (data, context) => createEmotionDefinition(data, context),
148
+ update: (id, patch, context) => updateEmotionDefinition(id, patch, context),
149
+ hardDelete: (id, context) => deleteEmotionDefinition(id, context)
150
+ },
151
+ trigger_report: {
152
+ entityType: "trigger_report",
153
+ routeBase: "/api/v1/psyche/reports",
154
+ list: () => listTriggerReports(200),
155
+ get: (id) => getTriggerReportById(id),
156
+ create: (data, context) => createTriggerReport(data, context),
157
+ update: (id, patch, context) => updateTriggerReport(id, patch, context),
158
+ hardDelete: (id, context) => deleteTriggerReport(id, context)
159
+ }
160
+ };
161
+ export function getCrudEntityCapabilityMatrix() {
162
+ return Object.values(CRUD_ENTITY_CAPABILITIES).map((capability) => ({
163
+ entityType: capability.entityType,
164
+ routeBase: capability.routeBase,
165
+ pluginExposed: true,
166
+ deleteMode: "soft_default",
167
+ inBin: true
168
+ }));
169
+ }
170
+ function getCapability(entityType) {
171
+ return CRUD_ENTITY_CAPABILITIES[entityType];
172
+ }
173
+ const CREATE_ENTITY_SCHEMAS = {
174
+ goal: createGoalSchema,
175
+ project: createProjectSchema,
176
+ task: createTaskSchema,
177
+ tag: createTagSchema,
178
+ comment: createCommentSchema,
179
+ insight: createInsightSchema,
180
+ psyche_value: createPsycheValueSchema,
181
+ behavior_pattern: createBehaviorPatternSchema,
182
+ behavior: createBehaviorSchema,
183
+ belief_entry: createBeliefEntrySchema,
184
+ mode_profile: createModeProfileSchema,
185
+ mode_guide_session: createModeGuideSessionSchema,
186
+ event_type: createEventTypeSchema,
187
+ emotion_definition: createEmotionDefinitionSchema,
188
+ trigger_report: createTriggerReportSchema
189
+ };
190
+ const UPDATE_ENTITY_SCHEMAS = {
191
+ goal: updateGoalSchema,
192
+ project: updateProjectSchema,
193
+ task: updateTaskSchema,
194
+ tag: updateTagSchema,
195
+ comment: updateCommentSchema,
196
+ insight: updateInsightSchema,
197
+ psyche_value: updatePsycheValueSchema,
198
+ behavior_pattern: updateBehaviorPatternSchema,
199
+ behavior: updateBehaviorSchema,
200
+ belief_entry: updateBeliefEntrySchema,
201
+ mode_profile: updateModeProfileSchema,
202
+ mode_guide_session: updateModeGuideSessionSchema,
203
+ event_type: updateEventTypeSchema,
204
+ emotion_definition: updateEmotionDefinitionSchema,
205
+ trigger_report: updateTriggerReportSchema
206
+ };
207
+ function parseCreateInput(entityType, data) {
208
+ return CREATE_ENTITY_SCHEMAS[entityType].parse(data);
209
+ }
210
+ function parseUpdatePatch(entityType, patch) {
211
+ return UPDATE_ENTITY_SCHEMAS[entityType].parse(patch);
212
+ }
213
+ function toOperationError(code, message) {
214
+ return {
215
+ code,
216
+ message
217
+ };
218
+ }
219
+ function markRolledBack(result) {
220
+ if (!result.ok) {
221
+ return result;
222
+ }
223
+ return {
224
+ ok: false,
225
+ entityType: result.entityType,
226
+ id: result.id,
227
+ clientRef: result.clientRef,
228
+ error: toOperationError("rolled_back", "Rolled back because an earlier atomic batch operation failed.")
229
+ };
230
+ }
231
+ function markNotExecuted(entry) {
232
+ return {
233
+ ok: false,
234
+ entityType: entry.entityType,
235
+ id: entry.id,
236
+ clientRef: entry.clientRef,
237
+ error: toOperationError("not_executed", "Skipped because an earlier atomic batch operation failed.")
238
+ };
239
+ }
240
+ function finalizeAtomicRollbackResults(entries, partialResults, rollback) {
241
+ return entries.map((entry, index) => {
242
+ if (index < rollback.index) {
243
+ return markRolledBack(partialResults[index] ?? markNotExecuted(entry));
244
+ }
245
+ if (index === rollback.index) {
246
+ const failedResult = partialResults[index];
247
+ if (failedResult) {
248
+ return failedResult.ok ? markRolledBack(failedResult) : failedResult;
249
+ }
250
+ return {
251
+ ok: false,
252
+ entityType: entry.entityType,
253
+ id: entry.id,
254
+ clientRef: entry.clientRef,
255
+ error: toOperationError(rollback.code, rollback.messageText)
256
+ };
257
+ }
258
+ return markNotExecuted(entry);
259
+ });
260
+ }
261
+ function executeBatchOperation(entries, atomic, execute) {
262
+ if (!atomic) {
263
+ return { results: entries.map((entry) => execute(entry)) };
264
+ }
265
+ const partialResults = [];
266
+ try {
267
+ runInTransaction(() => {
268
+ entries.forEach((entry, index) => {
269
+ const result = execute(entry);
270
+ partialResults[index] = result;
271
+ if (!result.ok) {
272
+ throw new AtomicBatchRollback(index, result.error?.code ?? "batch_failed", result.error?.message ?? "Atomic batch failed.");
273
+ }
274
+ });
275
+ return partialResults;
276
+ });
277
+ return { results: partialResults };
278
+ }
279
+ catch (error) {
280
+ if (error instanceof AtomicBatchRollback) {
281
+ return {
282
+ results: finalizeAtomicRollbackResults(entries, partialResults, error)
283
+ };
284
+ }
285
+ throw error;
286
+ }
287
+ }
288
+ function describeEntity(entityType, entity) {
289
+ const title = typeof entity.title === "string" && entity.title.trim().length > 0
290
+ ? entity.title
291
+ : typeof entity.name === "string" && entity.name.trim().length > 0
292
+ ? entity.name
293
+ : typeof entity.label === "string" && entity.label.trim().length > 0
294
+ ? entity.label
295
+ : typeof entity.summary === "string" && entity.summary.trim().length > 0
296
+ ? entity.summary
297
+ : typeof entity.body === "string" && entity.body.trim().length > 0
298
+ ? entity.body.slice(0, 72)
299
+ : entityType.replaceAll("_", " ");
300
+ const subtitle = typeof entity.description === "string" && entity.description.trim().length > 0
301
+ ? entity.description
302
+ : typeof entity.summary === "string" && entity.summary.trim().length > 0
303
+ ? entity.summary
304
+ : typeof entity.body === "string" && entity.body.trim().length > 0
305
+ ? entity.body
306
+ : "";
307
+ return { title, subtitle };
308
+ }
309
+ function matchesLinkedTo(entityType, entity, linkedTo) {
310
+ switch (entityType) {
311
+ case "project":
312
+ return linkedTo.entityType === "goal" && entity.goalId === linkedTo.id;
313
+ case "task":
314
+ return (linkedTo.entityType === "goal" && entity.goalId === linkedTo.id) || (linkedTo.entityType === "project" && entity.projectId === linkedTo.id);
315
+ case "comment":
316
+ case "insight":
317
+ return entity.entityType === linkedTo.entityType && entity.entityId === linkedTo.id;
318
+ case "psyche_value":
319
+ return ((linkedTo.entityType === "goal" && Array.isArray(entity.linkedGoalIds) && entity.linkedGoalIds.includes(linkedTo.id)) ||
320
+ (linkedTo.entityType === "project" && Array.isArray(entity.linkedProjectIds) && entity.linkedProjectIds.includes(linkedTo.id)) ||
321
+ (linkedTo.entityType === "task" && Array.isArray(entity.linkedTaskIds) && entity.linkedTaskIds.includes(linkedTo.id)));
322
+ case "behavior_pattern":
323
+ return ((linkedTo.entityType === "psyche_value" && Array.isArray(entity.linkedValueIds) && entity.linkedValueIds.includes(linkedTo.id)) ||
324
+ (linkedTo.entityType === "mode_profile" && Array.isArray(entity.linkedModeIds) && entity.linkedModeIds.includes(linkedTo.id)) ||
325
+ (linkedTo.entityType === "belief_entry" && Array.isArray(entity.linkedBeliefIds) && entity.linkedBeliefIds.includes(linkedTo.id)));
326
+ case "behavior":
327
+ return ((linkedTo.entityType === "behavior_pattern" && Array.isArray(entity.linkedPatternIds) && entity.linkedPatternIds.includes(linkedTo.id)) ||
328
+ (linkedTo.entityType === "psyche_value" && Array.isArray(entity.linkedValueIds) && entity.linkedValueIds.includes(linkedTo.id)) ||
329
+ (linkedTo.entityType === "mode_profile" && Array.isArray(entity.linkedModeIds) && entity.linkedModeIds.includes(linkedTo.id)));
330
+ case "belief_entry":
331
+ return ((linkedTo.entityType === "psyche_value" && Array.isArray(entity.linkedValueIds) && entity.linkedValueIds.includes(linkedTo.id)) ||
332
+ (linkedTo.entityType === "behavior" && Array.isArray(entity.linkedBehaviorIds) && entity.linkedBehaviorIds.includes(linkedTo.id)) ||
333
+ (linkedTo.entityType === "mode_profile" && Array.isArray(entity.linkedModeIds) && entity.linkedModeIds.includes(linkedTo.id)) ||
334
+ (linkedTo.entityType === "trigger_report" && Array.isArray(entity.linkedReportIds) && entity.linkedReportIds.includes(linkedTo.id)));
335
+ case "mode_profile":
336
+ return ((linkedTo.entityType === "behavior_pattern" && Array.isArray(entity.linkedPatternIds) && entity.linkedPatternIds.includes(linkedTo.id)) ||
337
+ (linkedTo.entityType === "behavior" && Array.isArray(entity.linkedBehaviorIds) && entity.linkedBehaviorIds.includes(linkedTo.id)) ||
338
+ (linkedTo.entityType === "psyche_value" && Array.isArray(entity.linkedValueIds) && entity.linkedValueIds.includes(linkedTo.id)));
339
+ case "trigger_report":
340
+ return ((linkedTo.entityType === "behavior_pattern" && Array.isArray(entity.linkedPatternIds) && entity.linkedPatternIds.includes(linkedTo.id)) ||
341
+ (linkedTo.entityType === "psyche_value" && Array.isArray(entity.linkedValueIds) && entity.linkedValueIds.includes(linkedTo.id)) ||
342
+ (linkedTo.entityType === "goal" && Array.isArray(entity.linkedGoalIds) && entity.linkedGoalIds.includes(linkedTo.id)) ||
343
+ (linkedTo.entityType === "project" && Array.isArray(entity.linkedProjectIds) && entity.linkedProjectIds.includes(linkedTo.id)) ||
344
+ (linkedTo.entityType === "task" && Array.isArray(entity.linkedTaskIds) && entity.linkedTaskIds.includes(linkedTo.id)) ||
345
+ (linkedTo.entityType === "behavior" && Array.isArray(entity.linkedBehaviorIds) && entity.linkedBehaviorIds.includes(linkedTo.id)) ||
346
+ (linkedTo.entityType === "belief_entry" && Array.isArray(entity.linkedBeliefIds) && entity.linkedBeliefIds.includes(linkedTo.id)) ||
347
+ (linkedTo.entityType === "mode_profile" && Array.isArray(entity.linkedModeIds) && entity.linkedModeIds.includes(linkedTo.id)));
348
+ default:
349
+ return false;
350
+ }
351
+ }
352
+ function matchesQuery(entity, query) {
353
+ if (!query || query.trim().length === 0) {
354
+ return true;
355
+ }
356
+ const haystack = JSON.stringify(entity).toLowerCase();
357
+ return haystack.includes(query.trim().toLowerCase());
358
+ }
359
+ function matchesStatus(entity, statuses) {
360
+ if (!statuses || statuses.length === 0) {
361
+ return true;
362
+ }
363
+ return typeof entity.status === "string" ? statuses.includes(entity.status) : false;
364
+ }
365
+ function purgeAnchoredCollaboration(entityType, entityId) {
366
+ const insightIds = getDatabase()
367
+ .prepare(`SELECT id FROM insights WHERE entity_type = ? AND entity_id = ?`)
368
+ .all(entityType, entityId);
369
+ if (insightIds.length > 0) {
370
+ const placeholders = insightIds.map(() => "?").join(", ");
371
+ getDatabase()
372
+ .prepare(`DELETE FROM insight_feedback WHERE insight_id IN (${placeholders})`)
373
+ .run(...insightIds.map((row) => row.id));
374
+ getDatabase()
375
+ .prepare(`DELETE FROM insights WHERE id IN (${placeholders})`)
376
+ .run(...insightIds.map((row) => row.id));
377
+ getDatabase()
378
+ .prepare(`DELETE FROM deleted_entities WHERE entity_type = 'insight' AND entity_id IN (${placeholders})`)
379
+ .run(...insightIds.map((row) => row.id));
380
+ }
381
+ const commentIds = getDatabase()
382
+ .prepare(`SELECT id FROM entity_comments WHERE entity_type = ? AND entity_id = ?`)
383
+ .all(entityType, entityId);
384
+ if (commentIds.length > 0) {
385
+ const placeholders = commentIds.map(() => "?").join(", ");
386
+ getDatabase()
387
+ .prepare(`DELETE FROM entity_comments WHERE id IN (${placeholders})`)
388
+ .run(...commentIds.map((row) => row.id));
389
+ getDatabase()
390
+ .prepare(`DELETE FROM deleted_entities WHERE entity_type = 'comment' AND entity_id IN (${placeholders})`)
391
+ .run(...commentIds.map((row) => row.id));
392
+ }
393
+ }
394
+ export function deleteEntity(entityType, id, options, context) {
395
+ const capability = getCapability(entityType);
396
+ const mode = options.mode ?? "soft";
397
+ const existing = capability.get(id);
398
+ if (!existing) {
399
+ const deleted = getDeletedEntityRecord(entityType, id);
400
+ if (!deleted || mode !== "hard") {
401
+ return undefined;
402
+ }
403
+ }
404
+ return runInTransaction(() => {
405
+ if (mode === "soft") {
406
+ const entity = capability.get(id);
407
+ if (!entity) {
408
+ return undefined;
409
+ }
410
+ const details = describeEntity(entityType, entity);
411
+ upsertDeletedEntityRecord({
412
+ entityType,
413
+ entityId: id,
414
+ title: details.title,
415
+ subtitle: details.subtitle,
416
+ snapshot: entity,
417
+ deleteReason: options.reason ?? "",
418
+ context
419
+ });
420
+ if (entityType !== "comment" && entityType !== "insight") {
421
+ cascadeSoftDeleteAnchoredCollaboration(entityType, id, context, options.reason ?? "");
422
+ }
423
+ return entity;
424
+ }
425
+ clearDeletedEntityRecord(entityType, id);
426
+ if (entityType !== "comment" && entityType !== "insight") {
427
+ purgeAnchoredCollaboration(entityType, id);
428
+ }
429
+ const deleted = capability.hardDelete(id, context);
430
+ clearDeletedEntityRecord(entityType, id);
431
+ return deleted;
432
+ });
433
+ }
434
+ export function restoreEntity(entityType, id) {
435
+ return runInTransaction(() => {
436
+ const deleted = restoreDeletedEntityRecord(entityType, id);
437
+ if (!deleted) {
438
+ return undefined;
439
+ }
440
+ if (entityType !== "comment" && entityType !== "insight") {
441
+ restoreAnchoredCollaboration(entityType, id);
442
+ }
443
+ return getCapability(entityType).get(id) ?? deleted.snapshot;
444
+ });
445
+ }
446
+ export function createEntities(input, context) {
447
+ return executeBatchOperation(input.operations, input.atomic, (entry) => {
448
+ try {
449
+ const entity = getCapability(entry.entityType).create(parseCreateInput(entry.entityType, entry.data), context);
450
+ return { ok: true, entityType: entry.entityType, clientRef: entry.clientRef, id: String(entity.id ?? ""), entity };
451
+ }
452
+ catch (error) {
453
+ return {
454
+ ok: false,
455
+ entityType: entry.entityType,
456
+ clientRef: entry.clientRef,
457
+ error: toOperationError("create_failed", error instanceof Error ? error.message : String(error))
458
+ };
459
+ }
460
+ });
461
+ }
462
+ export function updateEntities(input, context) {
463
+ return executeBatchOperation(input.operations, input.atomic, (entry) => {
464
+ try {
465
+ const entity = getCapability(entry.entityType).update(entry.id, parseUpdatePatch(entry.entityType, entry.patch), context);
466
+ if (!entity) {
467
+ return {
468
+ ok: false,
469
+ entityType: entry.entityType,
470
+ id: entry.id,
471
+ clientRef: entry.clientRef,
472
+ error: toOperationError("not_found", `${entry.entityType} ${entry.id} was not found.`)
473
+ };
474
+ }
475
+ return { ok: true, entityType: entry.entityType, id: entry.id, clientRef: entry.clientRef, entity };
476
+ }
477
+ catch (error) {
478
+ return {
479
+ ok: false,
480
+ entityType: entry.entityType,
481
+ id: entry.id,
482
+ clientRef: entry.clientRef,
483
+ error: toOperationError("update_failed", error instanceof Error ? error.message : String(error))
484
+ };
485
+ }
486
+ });
487
+ }
488
+ export function deleteEntities(input, context) {
489
+ return executeBatchOperation(input.operations, input.atomic, (entry) => {
490
+ try {
491
+ const entity = deleteEntity(entry.entityType, entry.id, { mode: entry.mode, reason: entry.reason }, context);
492
+ if (!entity) {
493
+ return {
494
+ ok: false,
495
+ entityType: entry.entityType,
496
+ id: entry.id,
497
+ clientRef: entry.clientRef,
498
+ error: toOperationError("not_found", `${entry.entityType} ${entry.id} was not found.`)
499
+ };
500
+ }
501
+ return { ok: true, entityType: entry.entityType, id: entry.id, clientRef: entry.clientRef, entity };
502
+ }
503
+ catch (error) {
504
+ return {
505
+ ok: false,
506
+ entityType: entry.entityType,
507
+ id: entry.id,
508
+ clientRef: entry.clientRef,
509
+ error: toOperationError("delete_failed", error instanceof Error ? error.message : String(error))
510
+ };
511
+ }
512
+ });
513
+ }
514
+ export function restoreEntities(input) {
515
+ return executeBatchOperation(input.operations, input.atomic, (entry) => {
516
+ try {
517
+ const entity = restoreEntity(entry.entityType, entry.id);
518
+ if (!entity) {
519
+ return {
520
+ ok: false,
521
+ entityType: entry.entityType,
522
+ id: entry.id,
523
+ clientRef: entry.clientRef,
524
+ error: toOperationError("not_found", `${entry.entityType} ${entry.id} was not found in the bin.`)
525
+ };
526
+ }
527
+ return { ok: true, entityType: entry.entityType, id: entry.id, clientRef: entry.clientRef, entity };
528
+ }
529
+ catch (error) {
530
+ return {
531
+ ok: false,
532
+ entityType: entry.entityType,
533
+ id: entry.id,
534
+ clientRef: entry.clientRef,
535
+ error: toOperationError("restore_failed", error instanceof Error ? error.message : String(error))
536
+ };
537
+ }
538
+ });
539
+ }
540
+ export function searchEntities(input) {
541
+ const deleted = listDeletedEntities();
542
+ return {
543
+ results: input.searches.map((search) => {
544
+ const entityTypes = search.entityTypes && search.entityTypes.length > 0 ? search.entityTypes : Object.keys(CRUD_ENTITY_CAPABILITIES);
545
+ const liveMatches = entityTypes.flatMap((entityType) => getCapability(entityType)
546
+ .list()
547
+ .filter((entity) => (search.ids && search.ids.length > 0 ? search.ids.includes(String(entity.id ?? "")) : true))
548
+ .filter((entity) => matchesQuery(entity, search.query))
549
+ .filter((entity) => matchesStatus(entity, search.status))
550
+ .filter((entity) => (search.linkedTo ? matchesLinkedTo(entityType, entity, search.linkedTo) : true))
551
+ .slice(0, search.limit)
552
+ .map((entity) => ({ deleted: false, entityType, id: String(entity.id ?? ""), entity })));
553
+ const deletedMatches = search.includeDeleted
554
+ ? deleted
555
+ .filter((item) => entityTypes.includes(item.entityType))
556
+ .filter((item) => (search.ids && search.ids.length > 0 ? search.ids.includes(item.entityId) : true))
557
+ .filter((item) => matchesQuery(item.snapshot, search.query) || matchesQuery(item, search.query))
558
+ .filter((item) => matchesStatus(item.snapshot, search.status))
559
+ .filter((item) => (search.linkedTo ? matchesLinkedTo(item.entityType, item.snapshot, search.linkedTo) : true))
560
+ .slice(0, search.limit)
561
+ .map((item) => ({ deleted: true, entityType: item.entityType, id: item.entityId, entity: item.snapshot, deletedRecord: item }))
562
+ : [];
563
+ return {
564
+ ok: true,
565
+ clientRef: search.clientRef,
566
+ matches: [...liveMatches, ...deletedMatches].slice(0, search.limit)
567
+ };
568
+ })
569
+ };
570
+ }
571
+ export function getSettingsBinPayload() {
572
+ return buildSettingsBinPayload();
573
+ }
574
+ export function getDeletedEntityRecords() {
575
+ return listDeletedEntities();
576
+ }