forge-openclaw-plugin 0.2.7 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -1
- package/dist/assets/{board-CzgvdLO8.js → board-C_m78kvK.js} +2 -2
- package/dist/assets/{board-CzgvdLO8.js.map → board-C_m78kvK.js.map} +1 -1
- package/dist/assets/index-BWtLtXwb.js +36 -0
- package/dist/assets/index-BWtLtXwb.js.map +1 -0
- package/dist/assets/index-Dp5GXY_z.css +1 -0
- package/dist/assets/{motion-STUd1O46.js → motion-CpZvZumD.js} +2 -2
- package/dist/assets/{motion-STUd1O46.js.map → motion-CpZvZumD.js.map} +1 -1
- package/dist/assets/{table-CtNlETLc.js → table-DtyXTw03.js} +2 -2
- package/dist/assets/{table-CtNlETLc.js.map → table-DtyXTw03.js.map} +1 -1
- package/dist/assets/{ui-ThzkR_oW.js → ui-BXbpiKyS.js} +2 -2
- package/dist/assets/{ui-ThzkR_oW.js.map → ui-BXbpiKyS.js.map} +1 -1
- package/dist/assets/{vendor-DyHAI6nk.js → vendor-QBH6qVEe.js} +84 -74
- package/dist/assets/vendor-QBH6qVEe.js.map +1 -0
- package/dist/assets/{viz-BJuBCz_G.js → viz-w-IMeueL.js} +2 -2
- package/dist/assets/{viz-BJuBCz_G.js.map → viz-w-IMeueL.js.map} +1 -1
- package/dist/index.html +8 -8
- package/dist/openclaw/api-client.d.ts +1 -0
- package/dist/openclaw/local-runtime.d.ts +8 -0
- package/dist/openclaw/local-runtime.js +123 -1
- package/dist/openclaw/plugin-entry-shared.js +12 -0
- package/dist/openclaw/routes.js +4 -0
- package/dist/server/app.js +104 -67
- package/dist/server/demo-data.js +49 -0
- package/dist/server/openapi.js +84 -43
- package/dist/server/psyche-types.js +1 -30
- package/dist/server/repositories/deleted-entities.js +60 -26
- package/dist/server/repositories/goals.js +2 -5
- package/dist/server/repositories/notes.js +359 -0
- package/dist/server/repositories/projects.js +2 -5
- package/dist/server/repositories/psyche.js +11 -14
- package/dist/server/repositories/task-runs.js +2 -0
- package/dist/server/repositories/tasks.js +21 -10
- package/dist/server/seed-demo.js +11 -0
- package/dist/server/services/dashboard.js +4 -1
- package/dist/server/services/entity-crud.js +27 -30
- package/dist/server/services/insights.js +5 -5
- package/dist/server/services/projects.js +3 -1
- package/dist/server/services/psyche.js +4 -4
- package/dist/server/types.js +70 -11
- package/openclaw.plugin.json +12 -1
- package/package.json +1 -1
- package/server/migrations/001_core.sql +78 -0
- package/server/migrations/002_psyche.sql +164 -13
- package/skills/forge-openclaw/SKILL.md +19 -5
- package/dist/assets/index-8d_oM8fL.js +0 -27
- package/dist/assets/index-8d_oM8fL.js.map +0 -1
- package/dist/assets/index-D4A_bq8m.css +0 -1
- package/dist/assets/vendor-DyHAI6nk.js.map +0 -1
- package/dist/server/repositories/comments.js +0 -176
- package/server/migrations/003_timer_execution.sql +0 -18
- package/server/migrations/004_psyche_linked_entities.sql +0 -5
- package/server/migrations/005_adaptive_schemas.sql +0 -157
- package/server/migrations/006_psyche_auth_setting.sql +0 -4
- package/server/migrations/007_deleted_entities.sql +0 -16
package/dist/server/openapi.js
CHANGED
|
@@ -260,8 +260,9 @@ export function buildOpenApiDocument() {
|
|
|
260
260
|
"behavior",
|
|
261
261
|
"belief_entry",
|
|
262
262
|
"mode_profile",
|
|
263
|
+
"mode_guide_session",
|
|
263
264
|
"trigger_report",
|
|
264
|
-
"
|
|
265
|
+
"note",
|
|
265
266
|
"tag",
|
|
266
267
|
"task_run",
|
|
267
268
|
"system",
|
|
@@ -306,6 +307,45 @@ export function buildOpenApiDocument() {
|
|
|
306
307
|
topGoalTitle: nullable({ type: "string" })
|
|
307
308
|
}
|
|
308
309
|
};
|
|
310
|
+
const noteLink = {
|
|
311
|
+
type: "object",
|
|
312
|
+
additionalProperties: false,
|
|
313
|
+
required: ["entityType", "entityId", "anchorKey"],
|
|
314
|
+
properties: {
|
|
315
|
+
entityType: { type: "string" },
|
|
316
|
+
entityId: { type: "string" },
|
|
317
|
+
anchorKey: nullable({ type: "string" })
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const note = {
|
|
321
|
+
type: "object",
|
|
322
|
+
additionalProperties: false,
|
|
323
|
+
required: ["id", "contentMarkdown", "contentPlain", "author", "source", "createdAt", "updatedAt", "links"],
|
|
324
|
+
properties: {
|
|
325
|
+
id: { type: "string" },
|
|
326
|
+
contentMarkdown: { type: "string" },
|
|
327
|
+
contentPlain: { type: "string" },
|
|
328
|
+
author: nullable({ type: "string" }),
|
|
329
|
+
source: { type: "string", enum: ["ui", "openclaw", "agent", "system"] },
|
|
330
|
+
createdAt: { type: "string", format: "date-time" },
|
|
331
|
+
updatedAt: { type: "string", format: "date-time" },
|
|
332
|
+
links: arrayOf({ $ref: "#/components/schemas/NoteLink" })
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
const noteSummary = {
|
|
336
|
+
type: "object",
|
|
337
|
+
additionalProperties: false,
|
|
338
|
+
required: ["count", "latestNoteId", "latestCreatedAt"],
|
|
339
|
+
properties: {
|
|
340
|
+
count: { type: "integer" },
|
|
341
|
+
latestNoteId: nullable({ type: "string" }),
|
|
342
|
+
latestCreatedAt: nullable({ type: "string", format: "date-time" })
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
const notesSummaryByEntity = {
|
|
346
|
+
type: "object",
|
|
347
|
+
additionalProperties: { $ref: "#/components/schemas/NoteSummary" }
|
|
348
|
+
};
|
|
309
349
|
const achievementSignal = {
|
|
310
350
|
type: "object",
|
|
311
351
|
additionalProperties: false,
|
|
@@ -338,7 +378,7 @@ export function buildOpenApiDocument() {
|
|
|
338
378
|
const dashboardPayload = {
|
|
339
379
|
type: "object",
|
|
340
380
|
additionalProperties: false,
|
|
341
|
-
required: ["stats", "goals", "projects", "tasks", "tags", "suggestedTags", "owners", "executionBuckets", "gamification", "achievements", "milestoneRewards", "recentActivity"],
|
|
381
|
+
required: ["stats", "goals", "projects", "tasks", "tags", "suggestedTags", "owners", "executionBuckets", "gamification", "achievements", "milestoneRewards", "recentActivity", "notesSummaryByEntity"],
|
|
342
382
|
properties: {
|
|
343
383
|
stats: {
|
|
344
384
|
type: "object",
|
|
@@ -375,7 +415,8 @@ export function buildOpenApiDocument() {
|
|
|
375
415
|
gamification: { $ref: "#/components/schemas/GamificationProfile" },
|
|
376
416
|
achievements: arrayOf({ $ref: "#/components/schemas/AchievementSignal" }),
|
|
377
417
|
milestoneRewards: arrayOf({ $ref: "#/components/schemas/MilestoneReward" }),
|
|
378
|
-
recentActivity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" })
|
|
418
|
+
recentActivity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
|
|
419
|
+
notesSummaryByEntity: { $ref: "#/components/schemas/NotesSummaryByEntity" }
|
|
379
420
|
}
|
|
380
421
|
};
|
|
381
422
|
const overviewContext = {
|
|
@@ -539,25 +580,27 @@ export function buildOpenApiDocument() {
|
|
|
539
580
|
const taskContextPayload = {
|
|
540
581
|
type: "object",
|
|
541
582
|
additionalProperties: false,
|
|
542
|
-
required: ["task", "goal", "project", "activeTaskRun", "taskRuns", "activity"],
|
|
583
|
+
required: ["task", "goal", "project", "activeTaskRun", "taskRuns", "activity", "notesSummaryByEntity"],
|
|
543
584
|
properties: {
|
|
544
585
|
task: { $ref: "#/components/schemas/Task" },
|
|
545
586
|
goal: nullable({ $ref: "#/components/schemas/Goal" }),
|
|
546
587
|
project: nullable({ $ref: "#/components/schemas/ProjectSummary" }),
|
|
547
588
|
activeTaskRun: nullable({ $ref: "#/components/schemas/TaskRun" }),
|
|
548
589
|
taskRuns: arrayOf({ $ref: "#/components/schemas/TaskRun" }),
|
|
549
|
-
activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" })
|
|
590
|
+
activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
|
|
591
|
+
notesSummaryByEntity: { $ref: "#/components/schemas/NotesSummaryByEntity" }
|
|
550
592
|
}
|
|
551
593
|
};
|
|
552
594
|
const projectBoardPayload = {
|
|
553
595
|
type: "object",
|
|
554
596
|
additionalProperties: false,
|
|
555
|
-
required: ["project", "goal", "tasks", "activity"],
|
|
597
|
+
required: ["project", "goal", "tasks", "activity", "notesSummaryByEntity"],
|
|
556
598
|
properties: {
|
|
557
599
|
project: { $ref: "#/components/schemas/ProjectSummary" },
|
|
558
600
|
goal: { $ref: "#/components/schemas/Goal" },
|
|
559
601
|
tasks: arrayOf({ $ref: "#/components/schemas/Task" }),
|
|
560
|
-
activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" })
|
|
602
|
+
activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
|
|
603
|
+
notesSummaryByEntity: { $ref: "#/components/schemas/NotesSummaryByEntity" }
|
|
561
604
|
}
|
|
562
605
|
};
|
|
563
606
|
const insightsPayload = {
|
|
@@ -745,7 +788,17 @@ export function buildOpenApiDocument() {
|
|
|
745
788
|
additionalProperties: false,
|
|
746
789
|
properties: {
|
|
747
790
|
actor: { type: "string" },
|
|
748
|
-
note: { type: "string", default: "" }
|
|
791
|
+
note: { type: "string", default: "" },
|
|
792
|
+
closeoutNote: {
|
|
793
|
+
type: "object",
|
|
794
|
+
additionalProperties: false,
|
|
795
|
+
required: ["contentMarkdown"],
|
|
796
|
+
properties: {
|
|
797
|
+
contentMarkdown: { type: "string" },
|
|
798
|
+
author: nullable({ type: "string" }),
|
|
799
|
+
links: arrayOf({ $ref: "#/components/schemas/NoteLink" })
|
|
800
|
+
}
|
|
801
|
+
}
|
|
749
802
|
}
|
|
750
803
|
};
|
|
751
804
|
const taskRunFocusInput = {
|
|
@@ -1217,12 +1270,13 @@ export function buildOpenApiDocument() {
|
|
|
1217
1270
|
conceptModel: {
|
|
1218
1271
|
type: "object",
|
|
1219
1272
|
additionalProperties: false,
|
|
1220
|
-
required: ["goal", "project", "task", "taskRun", "insight", "psyche"],
|
|
1273
|
+
required: ["goal", "project", "task", "taskRun", "note", "insight", "psyche"],
|
|
1221
1274
|
properties: {
|
|
1222
1275
|
goal: { type: "string" },
|
|
1223
1276
|
project: { type: "string" },
|
|
1224
1277
|
task: { type: "string" },
|
|
1225
1278
|
taskRun: { type: "string" },
|
|
1279
|
+
note: { type: "string" },
|
|
1226
1280
|
insight: { type: "string" },
|
|
1227
1281
|
psyche: { type: "string" }
|
|
1228
1282
|
}
|
|
@@ -1760,22 +1814,6 @@ export function buildOpenApiDocument() {
|
|
|
1760
1814
|
updatedAt: { type: "string", format: "date-time" }
|
|
1761
1815
|
}
|
|
1762
1816
|
};
|
|
1763
|
-
const comment = {
|
|
1764
|
-
type: "object",
|
|
1765
|
-
additionalProperties: false,
|
|
1766
|
-
required: ["id", "entityType", "entityId", "anchorKey", "body", "author", "source", "createdAt", "updatedAt"],
|
|
1767
|
-
properties: {
|
|
1768
|
-
id: { type: "string" },
|
|
1769
|
-
entityType: { type: "string" },
|
|
1770
|
-
entityId: { type: "string" },
|
|
1771
|
-
anchorKey: nullable({ type: "string" }),
|
|
1772
|
-
body: { type: "string" },
|
|
1773
|
-
author: nullable({ type: "string" }),
|
|
1774
|
-
source: { type: "string", enum: ["ui", "openclaw", "agent", "system"] },
|
|
1775
|
-
createdAt: { type: "string", format: "date-time" },
|
|
1776
|
-
updatedAt: { type: "string", format: "date-time" }
|
|
1777
|
-
}
|
|
1778
|
-
};
|
|
1779
1817
|
const triggerReport = {
|
|
1780
1818
|
type: "object",
|
|
1781
1819
|
additionalProperties: false,
|
|
@@ -1903,7 +1941,7 @@ export function buildOpenApiDocument() {
|
|
|
1903
1941
|
"schemaPressure",
|
|
1904
1942
|
"reports",
|
|
1905
1943
|
"openInsights",
|
|
1906
|
-
"
|
|
1944
|
+
"openNotes",
|
|
1907
1945
|
"committedActions"
|
|
1908
1946
|
],
|
|
1909
1947
|
properties: {
|
|
@@ -1926,7 +1964,7 @@ export function buildOpenApiDocument() {
|
|
|
1926
1964
|
}),
|
|
1927
1965
|
reports: arrayOf({ $ref: "#/components/schemas/TriggerReport" }),
|
|
1928
1966
|
openInsights: { type: "integer" },
|
|
1929
|
-
|
|
1967
|
+
openNotes: { type: "integer" },
|
|
1930
1968
|
committedActions: arrayOf({ type: "string" })
|
|
1931
1969
|
}
|
|
1932
1970
|
};
|
|
@@ -1994,7 +2032,10 @@ export function buildOpenApiDocument() {
|
|
|
1994
2032
|
ModeProfile: modeProfile,
|
|
1995
2033
|
ModeGuideSession: modeGuideSession,
|
|
1996
2034
|
TriggerReport: triggerReport,
|
|
1997
|
-
|
|
2035
|
+
NoteLink: noteLink,
|
|
2036
|
+
Note: note,
|
|
2037
|
+
NoteSummary: noteSummary,
|
|
2038
|
+
NotesSummaryByEntity: notesSummaryByEntity,
|
|
1998
2039
|
PsycheOverviewPayload: psycheOverviewPayload,
|
|
1999
2040
|
Insight: insight,
|
|
2000
2041
|
InsightFeedback: insightFeedback,
|
|
@@ -2445,14 +2486,14 @@ export function buildOpenApiDocument() {
|
|
|
2445
2486
|
},
|
|
2446
2487
|
"/api/v1/psyche/reports/{id}": {
|
|
2447
2488
|
get: {
|
|
2448
|
-
summary: "Get a trigger report with
|
|
2489
|
+
summary: "Get a trigger report with linked notes and insights",
|
|
2449
2490
|
responses: {
|
|
2450
2491
|
"200": jsonResponse({
|
|
2451
2492
|
type: "object",
|
|
2452
|
-
required: ["report", "
|
|
2493
|
+
required: ["report", "notes", "insights"],
|
|
2453
2494
|
properties: {
|
|
2454
2495
|
report: { $ref: "#/components/schemas/TriggerReport" },
|
|
2455
|
-
|
|
2496
|
+
notes: arrayOf({ $ref: "#/components/schemas/Note" }),
|
|
2456
2497
|
insights: arrayOf({ $ref: "#/components/schemas/Insight" })
|
|
2457
2498
|
}
|
|
2458
2499
|
}, "Trigger report detail"),
|
|
@@ -2474,41 +2515,41 @@ export function buildOpenApiDocument() {
|
|
|
2474
2515
|
}
|
|
2475
2516
|
}
|
|
2476
2517
|
},
|
|
2477
|
-
"/api/v1/
|
|
2518
|
+
"/api/v1/notes": {
|
|
2478
2519
|
get: {
|
|
2479
|
-
summary: "List
|
|
2520
|
+
summary: "List notes linked to Forge entities",
|
|
2480
2521
|
responses: {
|
|
2481
|
-
"200": jsonResponse({ type: "object", required: ["
|
|
2522
|
+
"200": jsonResponse({ type: "object", required: ["notes"], properties: { notes: arrayOf({ $ref: "#/components/schemas/Note" }) } }, "Note collection"),
|
|
2482
2523
|
default: { $ref: "#/components/responses/Error" }
|
|
2483
2524
|
}
|
|
2484
2525
|
},
|
|
2485
2526
|
post: {
|
|
2486
|
-
summary: "Create a
|
|
2527
|
+
summary: "Create a note linked to one or more Forge entities",
|
|
2487
2528
|
responses: {
|
|
2488
|
-
"201": jsonResponse({ type: "object", required: ["
|
|
2529
|
+
"201": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Created note"),
|
|
2489
2530
|
default: { $ref: "#/components/responses/Error" }
|
|
2490
2531
|
}
|
|
2491
2532
|
}
|
|
2492
2533
|
},
|
|
2493
|
-
"/api/v1/
|
|
2534
|
+
"/api/v1/notes/{id}": {
|
|
2494
2535
|
get: {
|
|
2495
|
-
summary: "Get a
|
|
2536
|
+
summary: "Get a note",
|
|
2496
2537
|
responses: {
|
|
2497
|
-
"200": jsonResponse({ type: "object", required: ["
|
|
2538
|
+
"200": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Note"),
|
|
2498
2539
|
default: { $ref: "#/components/responses/Error" }
|
|
2499
2540
|
}
|
|
2500
2541
|
},
|
|
2501
2542
|
patch: {
|
|
2502
|
-
summary: "Update a
|
|
2543
|
+
summary: "Update a note",
|
|
2503
2544
|
responses: {
|
|
2504
|
-
"200": jsonResponse({ type: "object", required: ["
|
|
2545
|
+
"200": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Updated note"),
|
|
2505
2546
|
default: { $ref: "#/components/responses/Error" }
|
|
2506
2547
|
}
|
|
2507
2548
|
},
|
|
2508
2549
|
delete: {
|
|
2509
|
-
summary: "Delete a
|
|
2550
|
+
summary: "Delete a note",
|
|
2510
2551
|
responses: {
|
|
2511
|
-
"200": jsonResponse({ type: "object", required: ["
|
|
2552
|
+
"200": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Deleted note"),
|
|
2512
2553
|
default: { $ref: "#/components/responses/Error" }
|
|
2513
2554
|
}
|
|
2514
2555
|
}
|
|
@@ -3,7 +3,6 @@ const trimmedString = z.string().trim();
|
|
|
3
3
|
const nonEmptyTrimmedString = trimmedString.min(1);
|
|
4
4
|
const uniqueStringArraySchema = z.array(nonEmptyTrimmedString);
|
|
5
5
|
export const triggerReportStatusSchema = z.enum(["draft", "reviewed", "integrated"]);
|
|
6
|
-
export const commentSourceSchema = z.enum(["ui", "openclaw", "agent", "system"]);
|
|
7
6
|
export const behaviorKindSchema = z.enum(["away", "committed", "recovery"]);
|
|
8
7
|
export const beliefTypeSchema = z.enum(["absolute", "conditional"]);
|
|
9
8
|
export const modeFamilySchema = z.enum(["coping", "child", "critic_parent", "healthy_adult", "happy_child"]);
|
|
@@ -225,17 +224,6 @@ export const triggerReportSchema = z.object({
|
|
|
225
224
|
createdAt: z.string(),
|
|
226
225
|
updatedAt: z.string()
|
|
227
226
|
});
|
|
228
|
-
export const commentSchema = z.object({
|
|
229
|
-
id: z.string(),
|
|
230
|
-
entityType: nonEmptyTrimmedString,
|
|
231
|
-
entityId: nonEmptyTrimmedString,
|
|
232
|
-
anchorKey: trimmedString.nullable(),
|
|
233
|
-
body: nonEmptyTrimmedString,
|
|
234
|
-
author: trimmedString.nullable(),
|
|
235
|
-
source: commentSourceSchema,
|
|
236
|
-
createdAt: z.string(),
|
|
237
|
-
updatedAt: z.string()
|
|
238
|
-
});
|
|
239
227
|
export const schemaPressureEntrySchema = z.object({
|
|
240
228
|
schemaId: z.string(),
|
|
241
229
|
title: nonEmptyTrimmedString,
|
|
@@ -252,7 +240,7 @@ export const psycheOverviewPayloadSchema = z.object({
|
|
|
252
240
|
reports: z.array(triggerReportSchema),
|
|
253
241
|
schemaPressure: z.array(schemaPressureEntrySchema),
|
|
254
242
|
openInsights: z.number().int().nonnegative(),
|
|
255
|
-
|
|
243
|
+
openNotes: z.number().int().nonnegative(),
|
|
256
244
|
committedActions: z.array(trimmedString)
|
|
257
245
|
});
|
|
258
246
|
export const createPsycheValueSchema = z.object({
|
|
@@ -376,20 +364,3 @@ export const createTriggerReportSchema = z.object({
|
|
|
376
364
|
nextMoves: z.array(trimmedString).default([])
|
|
377
365
|
});
|
|
378
366
|
export const updateTriggerReportSchema = createTriggerReportSchema.partial();
|
|
379
|
-
export const createCommentSchema = z.object({
|
|
380
|
-
entityType: nonEmptyTrimmedString,
|
|
381
|
-
entityId: nonEmptyTrimmedString,
|
|
382
|
-
anchorKey: trimmedString.nullable().default(null),
|
|
383
|
-
body: nonEmptyTrimmedString,
|
|
384
|
-
author: trimmedString.nullable().default(null)
|
|
385
|
-
});
|
|
386
|
-
export const updateCommentSchema = z.object({
|
|
387
|
-
body: nonEmptyTrimmedString,
|
|
388
|
-
author: trimmedString.nullable().default(null)
|
|
389
|
-
});
|
|
390
|
-
export const commentsListQuerySchema = z.object({
|
|
391
|
-
entityType: nonEmptyTrimmedString.optional(),
|
|
392
|
-
entityId: nonEmptyTrimmedString.optional(),
|
|
393
|
-
limit: z.coerce.number().int().positive().max(200).optional()
|
|
394
|
-
});
|
|
395
|
-
export const commentListQuerySchema = commentsListQuerySchema;
|
|
@@ -107,30 +107,64 @@ export function clearDeletedEntityRecord(entityType, entityId) {
|
|
|
107
107
|
.run(entityType, entityId);
|
|
108
108
|
}
|
|
109
109
|
export function cascadeSoftDeleteAnchoredCollaboration(parentEntityType, parentEntityId, context, deleteReason = "") {
|
|
110
|
-
const
|
|
111
|
-
.prepare(`SELECT
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const noteRows = getDatabase()
|
|
111
|
+
.prepare(`SELECT DISTINCT
|
|
112
|
+
notes.id AS id,
|
|
113
|
+
notes.content_markdown AS content_markdown,
|
|
114
|
+
notes.content_plain AS content_plain,
|
|
115
|
+
notes.author AS author,
|
|
116
|
+
notes.source AS source,
|
|
117
|
+
notes.created_at AS created_at,
|
|
118
|
+
notes.updated_at AS updated_at
|
|
119
|
+
FROM notes
|
|
120
|
+
INNER JOIN note_links
|
|
121
|
+
ON note_links.note_id = notes.id
|
|
122
|
+
LEFT JOIN deleted_entities
|
|
123
|
+
ON deleted_entities.entity_type = 'note'
|
|
124
|
+
AND deleted_entities.entity_id = notes.id
|
|
125
|
+
WHERE note_links.entity_type = ?
|
|
126
|
+
AND note_links.entity_id = ?
|
|
127
|
+
AND deleted_entities.entity_id IS NULL`)
|
|
114
128
|
.all(parentEntityType, parentEntityId);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
if (noteRows.length > 0) {
|
|
130
|
+
const placeholders = noteRows.map(() => "?").join(", ");
|
|
131
|
+
const linkRows = getDatabase()
|
|
132
|
+
.prepare(`SELECT note_id, entity_type, entity_id, anchor_key
|
|
133
|
+
FROM note_links
|
|
134
|
+
WHERE note_id IN (${placeholders})
|
|
135
|
+
ORDER BY created_at ASC`)
|
|
136
|
+
.all(...noteRows.map((row) => row.id));
|
|
137
|
+
const linksByNoteId = new Map();
|
|
138
|
+
for (const link of linkRows) {
|
|
139
|
+
const current = linksByNoteId.get(link.note_id) ?? [];
|
|
140
|
+
current.push({
|
|
141
|
+
entityType: link.entity_type,
|
|
142
|
+
entityId: link.entity_id,
|
|
143
|
+
anchorKey: link.anchor_key.trim().length > 0 ? link.anchor_key : null
|
|
144
|
+
});
|
|
145
|
+
linksByNoteId.set(link.note_id, current);
|
|
146
|
+
}
|
|
147
|
+
for (const row of noteRows) {
|
|
148
|
+
const compact = (row.content_plain || row.content_markdown).replace(/\s+/g, " ").trim();
|
|
149
|
+
upsertDeletedEntityRecord({
|
|
150
|
+
entityType: "note",
|
|
151
|
+
entityId: row.id,
|
|
152
|
+
title: compact.slice(0, 72) || "Note",
|
|
153
|
+
subtitle: compact.length > 72 ? compact.slice(72, 168).trim() : `Linked to ${parentEntityType.replaceAll("_", " ")}`,
|
|
154
|
+
snapshot: {
|
|
155
|
+
id: row.id,
|
|
156
|
+
contentMarkdown: row.content_markdown,
|
|
157
|
+
contentPlain: row.content_plain,
|
|
158
|
+
author: row.author,
|
|
159
|
+
source: row.source,
|
|
160
|
+
createdAt: row.created_at,
|
|
161
|
+
updatedAt: row.updated_at,
|
|
162
|
+
links: linksByNoteId.get(row.id) ?? []
|
|
163
|
+
},
|
|
164
|
+
deleteReason,
|
|
165
|
+
context
|
|
166
|
+
});
|
|
167
|
+
}
|
|
134
168
|
}
|
|
135
169
|
const insightRows = getDatabase()
|
|
136
170
|
.prepare(`SELECT id, title, summary, created_at, updated_at
|
|
@@ -160,10 +194,10 @@ export function cascadeSoftDeleteAnchoredCollaboration(parentEntityType, parentE
|
|
|
160
194
|
export function restoreAnchoredCollaboration(parentEntityType, parentEntityId) {
|
|
161
195
|
getDatabase()
|
|
162
196
|
.prepare(`DELETE FROM deleted_entities
|
|
163
|
-
WHERE entity_type = '
|
|
197
|
+
WHERE entity_type = 'note'
|
|
164
198
|
AND entity_id IN (
|
|
165
|
-
SELECT
|
|
166
|
-
FROM
|
|
199
|
+
SELECT DISTINCT note_id
|
|
200
|
+
FROM note_links
|
|
167
201
|
WHERE entity_type = ? AND entity_id = ?
|
|
168
202
|
)`)
|
|
169
203
|
.run(parentEntityType, parentEntityId);
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { getDatabase, runInTransaction } from "../db.js";
|
|
3
3
|
import { recordActivityEvent } from "./activity-events.js";
|
|
4
4
|
import { filterDeletedEntities, filterDeletedIds, isEntityDeleted } from "./deleted-entities.js";
|
|
5
|
+
import { createLinkedNotes } from "./notes.js";
|
|
5
6
|
import { assertGoalRelations } from "../services/relations.js";
|
|
6
7
|
import { pruneLinkedEntityReferences } from "./psyche.js";
|
|
7
8
|
import { goalSchema } from "../types.js";
|
|
@@ -52,6 +53,7 @@ export function createGoal(input, activity) {
|
|
|
52
53
|
.run(id, input.title, input.description, input.horizon, input.status, input.targetPoints, input.themeColor, now, now);
|
|
53
54
|
replaceGoalTags(id, input.tagIds);
|
|
54
55
|
const goal = getGoalById(id);
|
|
56
|
+
createLinkedNotes(input.notes, { entityType: "goal", entityId: goal.id, anchorKey: null }, activity ?? { source: "ui", actor: null });
|
|
55
57
|
if (activity) {
|
|
56
58
|
recordActivityEvent({
|
|
57
59
|
entityType: "goal",
|
|
@@ -130,11 +132,6 @@ export function deleteGoal(goalId, activity) {
|
|
|
130
132
|
}
|
|
131
133
|
return runInTransaction(() => {
|
|
132
134
|
pruneLinkedEntityReferences("goal", goalId);
|
|
133
|
-
getDatabase()
|
|
134
|
-
.prepare(`DELETE FROM entity_comments
|
|
135
|
-
WHERE entity_type = 'goal'
|
|
136
|
-
AND entity_id = ?`)
|
|
137
|
-
.run(goalId);
|
|
138
135
|
getDatabase()
|
|
139
136
|
.prepare(`DELETE FROM goals WHERE id = ?`)
|
|
140
137
|
.run(goalId);
|