forge-openclaw-plugin 0.2.26 → 0.2.28
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 +60 -3
- package/dist/assets/{board-ta0rUHOf.js → board-DPFvZf-D.js} +2 -2
- package/dist/assets/{board-ta0rUHOf.js.map → board-DPFvZf-D.js.map} +1 -1
- package/dist/assets/index-Auw3JrdE.css +1 -0
- package/dist/assets/index-D1H7myQH.js +85 -0
- package/dist/assets/index-D1H7myQH.js.map +1 -0
- package/dist/assets/knowledge-graph-layout.worker-DRvzPxhP.js +2 -0
- package/dist/assets/knowledge-graph-layout.worker-DRvzPxhP.js.map +1 -0
- package/dist/assets/{motion-fBKPB6yw.js → motion-Bvwc85ch.js} +2 -2
- package/dist/assets/{motion-fBKPB6yw.js.map → motion-Bvwc85ch.js.map} +1 -1
- package/dist/assets/{table-C-IGTQni.js → table-FJQTJvUR.js} +2 -2
- package/dist/assets/{table-C-IGTQni.js.map → table-FJQTJvUR.js.map} +1 -1
- package/dist/assets/{ui-DInOpaYF.js → ui-GXFcgvSw.js} +2 -2
- package/dist/assets/{ui-DInOpaYF.js.map → ui-GXFcgvSw.js.map} +1 -1
- package/dist/assets/vendor-Cwf49UMz.js +1247 -0
- package/dist/assets/vendor-Cwf49UMz.js.map +1 -0
- package/dist/index.html +7 -7
- package/dist/openclaw/local-runtime.js +16 -0
- package/dist/openclaw/routes.d.ts +27 -0
- package/dist/openclaw/routes.js +16 -12
- package/dist/server/server/migrations/037_workbench_public_inputs_and_run_inputs.sql +5 -0
- package/dist/server/server/migrations/038_data_management_settings.sql +11 -0
- package/dist/server/server/migrations/039_life_force_and_action_points.sql +114 -0
- package/dist/server/server/migrations/040_screen_time_domain.sql +89 -0
- package/dist/server/server/migrations/041_companion_source_states.sql +21 -0
- package/dist/server/server/migrations/042_movement_boxes.sql +47 -0
- package/dist/server/server/migrations/043_movement_box_overlap_overrides.sql +26 -0
- package/dist/server/server/src/app.js +1900 -91
- package/dist/server/server/src/connectors/box-registry.js +44 -9
- package/dist/server/server/src/data-management-types.js +107 -0
- package/dist/server/server/src/db.js +68 -4
- package/dist/server/server/src/demo-data.js +2 -2
- package/dist/server/server/src/health.js +702 -18
- package/dist/server/server/src/managers/platform/llm-manager.js +7 -4
- package/dist/server/server/src/managers/platform/mock-workbench-provider.js +149 -0
- package/dist/server/server/src/managers/platform/secrets-manager.js +18 -1
- package/dist/server/server/src/managers/runtime.js +9 -0
- package/dist/server/server/src/movement.js +1971 -112
- package/dist/server/server/src/openapi.js +1390 -105
- package/dist/server/server/src/psyche-types.js +9 -1
- package/dist/server/server/src/repositories/activity-events.js +8 -0
- package/dist/server/server/src/repositories/ai-connectors.js +522 -74
- package/dist/server/server/src/repositories/calendar.js +151 -0
- package/dist/server/server/src/repositories/habits.js +37 -1
- package/dist/server/server/src/repositories/model-settings.js +13 -3
- package/dist/server/server/src/repositories/notes.js +3 -0
- package/dist/server/server/src/repositories/settings.js +380 -18
- package/dist/server/server/src/repositories/tasks.js +170 -10
- package/dist/server/server/src/runtime-data-root.js +82 -0
- package/dist/server/server/src/screen-time.js +802 -0
- package/dist/server/server/src/services/data-management.js +788 -0
- package/dist/server/server/src/services/entity-crud.js +205 -2
- package/dist/server/server/src/services/knowledge-graph.js +1455 -0
- package/dist/server/server/src/services/life-force-model.js +217 -0
- package/dist/server/server/src/services/life-force.js +2506 -0
- package/dist/server/server/src/services/psyche-observation-calendar.js +383 -16
- package/dist/server/server/src/types.js +307 -14
- package/dist/server/server/src/web.js +228 -13
- package/dist/server/src/components/customization/utility-widgets.js +136 -27
- package/dist/server/src/components/ui/info-tooltip.js +25 -0
- package/dist/server/src/components/workbench-boxes/calendar/calendar-boxes.js +78 -0
- package/dist/server/src/components/workbench-boxes/goals/goals-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/habits/habits-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/health/health-boxes.js +63 -8
- package/dist/server/src/components/workbench-boxes/insights/insights-boxes.js +50 -0
- package/dist/server/src/components/workbench-boxes/kanban/kanban-boxes.js +62 -54
- package/dist/server/src/components/workbench-boxes/movement/movement-boxes.js +18 -8
- package/dist/server/src/components/workbench-boxes/notes/notes-boxes.js +56 -38
- package/dist/server/src/components/workbench-boxes/overview/overview-boxes.js +65 -0
- package/dist/server/src/components/workbench-boxes/preferences/preferences-boxes.js +78 -0
- package/dist/server/src/components/workbench-boxes/projects/projects-boxes.js +35 -30
- package/dist/server/src/components/workbench-boxes/psyche/psyche-boxes.js +88 -0
- package/dist/server/src/components/workbench-boxes/questionnaires/questionnaires-boxes.js +61 -0
- package/dist/server/src/components/workbench-boxes/review/review-boxes.js +53 -0
- package/dist/server/src/components/workbench-boxes/shared/define-workbench-box.js +3 -1
- package/dist/server/src/components/workbench-boxes/shared/generic-node-view.js +39 -3
- package/dist/server/src/components/workbench-boxes/strategies/strategies-boxes.js +62 -0
- package/dist/server/src/components/workbench-boxes/tasks/tasks-boxes.js +76 -0
- package/dist/server/src/components/workbench-boxes/today/today-boxes.js +47 -32
- package/dist/server/src/components/workbench-boxes/wiki/wiki-boxes.js +60 -0
- package/dist/server/src/lib/api.js +280 -21
- package/dist/server/src/lib/data-management-types.js +1 -0
- package/dist/server/src/lib/entity-visuals.js +279 -0
- package/dist/server/src/lib/knowledge-graph-types.js +276 -0
- package/dist/server/src/lib/knowledge-graph.js +470 -0
- package/dist/server/src/lib/schemas.js +4 -0
- package/dist/server/src/lib/snapshot-normalizer.js +45 -1
- package/dist/server/src/lib/workbench/contracts.js +229 -0
- package/dist/server/src/lib/workbench/nodes.js +200 -0
- package/dist/server/src/lib/workbench/registry.js +52 -5
- package/dist/server/src/lib/workbench/runtime.js +254 -38
- package/dist/server/src/lib/workbench/tool-catalog.js +68 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server/migrations/037_workbench_public_inputs_and_run_inputs.sql +5 -0
- package/server/migrations/038_data_management_settings.sql +11 -0
- package/server/migrations/039_life_force_and_action_points.sql +114 -0
- package/server/migrations/040_screen_time_domain.sql +89 -0
- package/server/migrations/041_companion_source_states.sql +21 -0
- package/server/migrations/042_movement_boxes.sql +47 -0
- package/server/migrations/043_movement_box_overlap_overrides.sql +26 -0
- package/skills/forge-openclaw/SKILL.md +41 -11
- package/skills/forge-openclaw/entity_conversation_playbooks.md +448 -34
- package/skills/forge-openclaw/psyche_entity_playbooks.md +170 -17
- package/dist/assets/index-Ro0ZF_az.css +0 -1
- package/dist/assets/index-ytlpSj23.js +0 -79
- package/dist/assets/index-ytlpSj23.js.map +0 -1
- package/dist/assets/vendor-lE3tZJcC.js +0 -876
- package/dist/assets/vendor-lE3tZJcC.js.map +0 -1
|
@@ -4,6 +4,7 @@ import { recordActivityEvent } from "./activity-events.js";
|
|
|
4
4
|
import { decorateOwnedEntity, filterOwnedEntities, inferFirstOwnedUserId, setEntityOwner } from "./entity-ownership.js";
|
|
5
5
|
import { getProjectById } from "./projects.js";
|
|
6
6
|
import { getTaskById } from "./tasks.js";
|
|
7
|
+
import { buildCalendarEventActionProfile, buildTaskTimeboxActionProfile, buildWorkBlockTemplateActionProfile, readEntityActionProfile, upsertEntityActionProfile } from "../services/life-force.js";
|
|
7
8
|
import { calendarConnectionSchema, calendarContextConflictSchema, calendarEventSchema, calendarEventLinkSchema, calendarEventSourceSchema, calendarOverviewPayloadSchema, calendarSchema, calendarSchedulingRulesSchema, taskTimeboxSchema, workBlockInstanceSchema, workBlockTemplateSchema } from "../types.js";
|
|
8
9
|
const DEFAULT_SCHEDULING_RULES = {
|
|
9
10
|
allowWorkBlockKinds: [],
|
|
@@ -149,6 +150,11 @@ function mapEvent(row) {
|
|
|
149
150
|
categories: JSON.parse(row.categories_json || "[]"),
|
|
150
151
|
sourceMappings,
|
|
151
152
|
links: listEventLinksForEvent(row.id),
|
|
153
|
+
actionProfile: readEntityActionProfile("calendar_event", row.id, {
|
|
154
|
+
profileKey: `calendar_event_${row.id}`,
|
|
155
|
+
title: row.title,
|
|
156
|
+
entityType: "calendar_event"
|
|
157
|
+
}),
|
|
152
158
|
remoteUpdatedAt: primarySource?.lastSyncedAt ?? null,
|
|
153
159
|
deletedAt: row.deleted_at,
|
|
154
160
|
createdAt: row.created_at,
|
|
@@ -168,11 +174,17 @@ function mapWorkBlockTemplate(row) {
|
|
|
168
174
|
startsOn: row.starts_on,
|
|
169
175
|
endsOn: row.ends_on,
|
|
170
176
|
blockingState: row.blocking_state,
|
|
177
|
+
actionProfile: readEntityActionProfile("work_block_template", row.id, {
|
|
178
|
+
profileKey: `work_block_template_${row.id}`,
|
|
179
|
+
title: row.title,
|
|
180
|
+
entityType: "work_block_template"
|
|
181
|
+
}),
|
|
171
182
|
createdAt: row.created_at,
|
|
172
183
|
updatedAt: row.updated_at
|
|
173
184
|
});
|
|
174
185
|
}
|
|
175
186
|
function mapTimebox(row) {
|
|
187
|
+
const task = getTaskById(row.task_id);
|
|
176
188
|
return taskTimeboxSchema.parse({
|
|
177
189
|
id: row.id,
|
|
178
190
|
taskId: row.task_id,
|
|
@@ -187,6 +199,21 @@ function mapTimebox(row) {
|
|
|
187
199
|
startsAt: row.starts_at,
|
|
188
200
|
endsAt: row.ends_at,
|
|
189
201
|
overrideReason: row.override_reason,
|
|
202
|
+
actionProfile: readEntityActionProfile("task_timebox", row.id, {
|
|
203
|
+
profileKey: `task_timebox_${row.id}`,
|
|
204
|
+
title: row.title,
|
|
205
|
+
entityType: "task_timebox"
|
|
206
|
+
}) ??
|
|
207
|
+
(task
|
|
208
|
+
? buildTaskTimeboxActionProfile({
|
|
209
|
+
timeboxId: row.id,
|
|
210
|
+
title: row.title,
|
|
211
|
+
taskId: row.task_id,
|
|
212
|
+
taskPlannedDurationSeconds: task.plannedDurationSeconds,
|
|
213
|
+
startsAt: row.starts_at,
|
|
214
|
+
endsAt: row.ends_at
|
|
215
|
+
})
|
|
216
|
+
: null),
|
|
190
217
|
createdAt: row.created_at,
|
|
191
218
|
updatedAt: row.updated_at
|
|
192
219
|
});
|
|
@@ -597,6 +624,20 @@ export function createCalendarEvent(input) {
|
|
|
597
624
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
598
625
|
.run(id, preferredCalendar?.connectionId ?? null, preferredCalendar?.id ?? null, "forge", "native", "confirmed", input.title, input.description, input.location, place.label || input.location, place.address, place.timezone, place.latitude, place.longitude, place.source, place.externalPlaceId, input.startAt, input.endAt, normalizeTimezone(input.timezone), input.isAllDay ? 1 : 0, input.availability, input.eventType, JSON.stringify(input.categories), now, now);
|
|
599
626
|
replaceEventLinks(id, input.links);
|
|
627
|
+
upsertEntityActionProfile({
|
|
628
|
+
entityType: "calendar_event",
|
|
629
|
+
entityId: id,
|
|
630
|
+
profile: buildCalendarEventActionProfile({
|
|
631
|
+
eventId: id,
|
|
632
|
+
title: input.title,
|
|
633
|
+
eventType: input.eventType,
|
|
634
|
+
availability: input.availability,
|
|
635
|
+
startAt: input.startAt,
|
|
636
|
+
endAt: input.endAt,
|
|
637
|
+
activityPresetKey: input.activityPresetKey ?? null,
|
|
638
|
+
customSustainRateApPerHour: input.customSustainRateApPerHour ?? null
|
|
639
|
+
})
|
|
640
|
+
});
|
|
600
641
|
setEntityOwner("calendar_event", id, inferCalendarEventOwnerId(input));
|
|
601
642
|
return getCalendarEventById(id);
|
|
602
643
|
}
|
|
@@ -652,6 +693,34 @@ export function updateCalendarEvent(eventId, patch) {
|
|
|
652
693
|
if (patch.links) {
|
|
653
694
|
replaceEventLinks(eventId, patch.links);
|
|
654
695
|
}
|
|
696
|
+
if (patch.title !== undefined ||
|
|
697
|
+
patch.startAt !== undefined ||
|
|
698
|
+
patch.endAt !== undefined ||
|
|
699
|
+
patch.availability !== undefined ||
|
|
700
|
+
patch.eventType !== undefined ||
|
|
701
|
+
patch.activityPresetKey !== undefined ||
|
|
702
|
+
patch.customSustainRateApPerHour !== undefined) {
|
|
703
|
+
upsertEntityActionProfile({
|
|
704
|
+
entityType: "calendar_event",
|
|
705
|
+
entityId: eventId,
|
|
706
|
+
profile: buildCalendarEventActionProfile({
|
|
707
|
+
eventId,
|
|
708
|
+
title: next.title,
|
|
709
|
+
eventType: next.eventType,
|
|
710
|
+
availability: next.availability,
|
|
711
|
+
startAt: next.startAt,
|
|
712
|
+
endAt: next.endAt,
|
|
713
|
+
activityPresetKey: patch.activityPresetKey === undefined
|
|
714
|
+
? current.actionProfile?.metadata?.activityPresetKey
|
|
715
|
+
: patch.activityPresetKey,
|
|
716
|
+
customSustainRateApPerHour: patch.customSustainRateApPerHour === undefined
|
|
717
|
+
? (typeof current.actionProfile?.metadata?.customSustainRateApPerHour === "number"
|
|
718
|
+
? current.actionProfile.metadata.customSustainRateApPerHour
|
|
719
|
+
: null)
|
|
720
|
+
: patch.customSustainRateApPerHour
|
|
721
|
+
})
|
|
722
|
+
});
|
|
723
|
+
}
|
|
655
724
|
if (patch.userId !== undefined || patch.links !== undefined) {
|
|
656
725
|
setEntityOwner("calendar_event", eventId, patch.userId === undefined
|
|
657
726
|
? inferCalendarEventOwnerId({
|
|
@@ -699,6 +768,19 @@ export function createWorkBlockTemplate(input) {
|
|
|
699
768
|
)
|
|
700
769
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
701
770
|
.run(id, input.title, input.kind, input.color, normalizeTimezone(input.timezone), JSON.stringify(input.weekDays), input.startMinute, input.endMinute, input.startsOn ?? null, input.endsOn ?? null, input.blockingState, now, now);
|
|
771
|
+
upsertEntityActionProfile({
|
|
772
|
+
entityType: "work_block_template",
|
|
773
|
+
entityId: id,
|
|
774
|
+
profile: buildWorkBlockTemplateActionProfile({
|
|
775
|
+
templateId: id,
|
|
776
|
+
title: input.title,
|
|
777
|
+
kind: input.kind,
|
|
778
|
+
startMinute: input.startMinute,
|
|
779
|
+
endMinute: input.endMinute,
|
|
780
|
+
activityPresetKey: input.activityPresetKey ?? null,
|
|
781
|
+
customSustainRateApPerHour: input.customSustainRateApPerHour ?? null
|
|
782
|
+
})
|
|
783
|
+
});
|
|
702
784
|
setEntityOwner("work_block_template", id, input.userId);
|
|
703
785
|
return getWorkBlockTemplateById(id);
|
|
704
786
|
});
|
|
@@ -744,6 +826,32 @@ export function updateWorkBlockTemplate(templateId, patch) {
|
|
|
744
826
|
SET title = ?, kind = ?, color = ?, timezone = ?, weekdays_json = ?, start_minute = ?, end_minute = ?, starts_on = ?, ends_on = ?, blocking_state = ?, updated_at = ?
|
|
745
827
|
WHERE id = ?`)
|
|
746
828
|
.run(next.title, next.kind, next.color, next.timezone, JSON.stringify(next.weekDays), next.startMinute, next.endMinute, next.startsOn, next.endsOn, next.blockingState, next.updatedAt, templateId);
|
|
829
|
+
if (patch.title !== undefined ||
|
|
830
|
+
patch.kind !== undefined ||
|
|
831
|
+
patch.startMinute !== undefined ||
|
|
832
|
+
patch.endMinute !== undefined ||
|
|
833
|
+
patch.activityPresetKey !== undefined ||
|
|
834
|
+
patch.customSustainRateApPerHour !== undefined) {
|
|
835
|
+
upsertEntityActionProfile({
|
|
836
|
+
entityType: "work_block_template",
|
|
837
|
+
entityId: templateId,
|
|
838
|
+
profile: buildWorkBlockTemplateActionProfile({
|
|
839
|
+
templateId,
|
|
840
|
+
title: next.title,
|
|
841
|
+
kind: next.kind,
|
|
842
|
+
startMinute: next.startMinute,
|
|
843
|
+
endMinute: next.endMinute,
|
|
844
|
+
activityPresetKey: patch.activityPresetKey === undefined
|
|
845
|
+
? current.actionProfile?.metadata?.activityPresetKey
|
|
846
|
+
: patch.activityPresetKey,
|
|
847
|
+
customSustainRateApPerHour: patch.customSustainRateApPerHour === undefined
|
|
848
|
+
? (typeof current.actionProfile?.metadata?.customSustainRateApPerHour === "number"
|
|
849
|
+
? current.actionProfile.metadata.customSustainRateApPerHour
|
|
850
|
+
: null)
|
|
851
|
+
: patch.customSustainRateApPerHour
|
|
852
|
+
})
|
|
853
|
+
});
|
|
854
|
+
}
|
|
747
855
|
if (patch.userId !== undefined) {
|
|
748
856
|
setEntityOwner("work_block_template", templateId, patch.userId);
|
|
749
857
|
}
|
|
@@ -790,6 +898,7 @@ function deriveWorkBlockInstances(template, query) {
|
|
|
790
898
|
color: template.color,
|
|
791
899
|
blockingState: template.blockingState,
|
|
792
900
|
calendarEventId: null,
|
|
901
|
+
actionProfile: template.actionProfile ?? null,
|
|
793
902
|
createdAt: template.createdAt,
|
|
794
903
|
updatedAt: template.updatedAt
|
|
795
904
|
}));
|
|
@@ -836,12 +945,27 @@ export function getTaskTimeboxById(timeboxId) {
|
|
|
836
945
|
export function createTaskTimebox(input) {
|
|
837
946
|
const now = nowIso();
|
|
838
947
|
const id = `timebox_${randomUUID().replaceAll("-", "").slice(0, 10)}`;
|
|
948
|
+
const task = getTaskById(input.taskId);
|
|
839
949
|
getDatabase()
|
|
840
950
|
.prepare(`INSERT INTO task_timeboxes (
|
|
841
951
|
id, task_id, project_id, connection_id, calendar_id, linked_task_run_id, status, source, title, starts_at, ends_at, override_reason, created_at, updated_at
|
|
842
952
|
)
|
|
843
953
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
844
954
|
.run(id, input.taskId, input.projectId ?? null, input.connectionId ?? null, input.calendarId ?? null, input.linkedTaskRunId ?? null, input.status ?? "planned", input.source ?? "manual", input.title, input.startsAt, input.endsAt, input.overrideReason ?? null, now, now);
|
|
955
|
+
upsertEntityActionProfile({
|
|
956
|
+
entityType: "task_timebox",
|
|
957
|
+
entityId: id,
|
|
958
|
+
profile: buildTaskTimeboxActionProfile({
|
|
959
|
+
timeboxId: id,
|
|
960
|
+
title: input.title,
|
|
961
|
+
taskId: input.taskId,
|
|
962
|
+
taskPlannedDurationSeconds: task?.plannedDurationSeconds ?? null,
|
|
963
|
+
startsAt: input.startsAt,
|
|
964
|
+
endsAt: input.endsAt,
|
|
965
|
+
activityPresetKey: input.activityPresetKey ?? null,
|
|
966
|
+
customSustainRateApPerHour: input.customSustainRateApPerHour ?? null
|
|
967
|
+
})
|
|
968
|
+
});
|
|
845
969
|
setEntityOwner("task_timebox", id, inferTaskTimeboxOwnerId(input));
|
|
846
970
|
return getTaskTimeboxById(id);
|
|
847
971
|
}
|
|
@@ -869,6 +993,33 @@ export function updateTaskTimebox(timeboxId, patch) {
|
|
|
869
993
|
starts_at = ?, ends_at = ?, override_reason = ?, updated_at = ?
|
|
870
994
|
WHERE id = ?`)
|
|
871
995
|
.run(next.connectionId, next.calendarId, next.remoteEventId, next.linkedTaskRunId, next.status, next.source, next.title, next.startsAt, next.endsAt, next.overrideReason, next.updatedAt, timeboxId);
|
|
996
|
+
if (patch.title !== undefined ||
|
|
997
|
+
patch.startsAt !== undefined ||
|
|
998
|
+
patch.endsAt !== undefined ||
|
|
999
|
+
patch.activityPresetKey !== undefined ||
|
|
1000
|
+
patch.customSustainRateApPerHour !== undefined) {
|
|
1001
|
+
const task = getTaskById(current.taskId);
|
|
1002
|
+
upsertEntityActionProfile({
|
|
1003
|
+
entityType: "task_timebox",
|
|
1004
|
+
entityId: timeboxId,
|
|
1005
|
+
profile: buildTaskTimeboxActionProfile({
|
|
1006
|
+
timeboxId,
|
|
1007
|
+
title: next.title,
|
|
1008
|
+
taskId: current.taskId,
|
|
1009
|
+
taskPlannedDurationSeconds: task?.plannedDurationSeconds ?? null,
|
|
1010
|
+
startsAt: next.startsAt,
|
|
1011
|
+
endsAt: next.endsAt,
|
|
1012
|
+
activityPresetKey: patch.activityPresetKey === undefined
|
|
1013
|
+
? current.actionProfile?.metadata?.activityPresetKey
|
|
1014
|
+
: patch.activityPresetKey,
|
|
1015
|
+
customSustainRateApPerHour: patch.customSustainRateApPerHour === undefined
|
|
1016
|
+
? (typeof current.actionProfile?.metadata?.customSustainRateApPerHour === "number"
|
|
1017
|
+
? current.actionProfile.metadata.customSustainRateApPerHour
|
|
1018
|
+
: null)
|
|
1019
|
+
: patch.customSustainRateApPerHour
|
|
1020
|
+
})
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
872
1023
|
if (patch.userId !== undefined) {
|
|
873
1024
|
setEntityOwner("task_timebox", timeboxId, patch.userId);
|
|
874
1025
|
}
|
|
@@ -225,6 +225,39 @@ function getHabitRow(habitId) {
|
|
|
225
225
|
WHERE id = ?`)
|
|
226
226
|
.get(habitId);
|
|
227
227
|
}
|
|
228
|
+
function compareDateDesc(left, right) {
|
|
229
|
+
return new Date(right ?? 0).getTime() - new Date(left ?? 0).getTime();
|
|
230
|
+
}
|
|
231
|
+
function compareDateAsc(left, right) {
|
|
232
|
+
return new Date(left ?? 0).getTime() - new Date(right ?? 0).getTime();
|
|
233
|
+
}
|
|
234
|
+
function sortHabits(habits, orderBy) {
|
|
235
|
+
const nextHabits = [...habits];
|
|
236
|
+
nextHabits.sort((left, right) => {
|
|
237
|
+
if (orderBy === "name") {
|
|
238
|
+
return (left.title.localeCompare(right.title, undefined, { sensitivity: "base" }) ||
|
|
239
|
+
compareDateDesc(left.createdAt, right.createdAt));
|
|
240
|
+
}
|
|
241
|
+
if (orderBy === "streak") {
|
|
242
|
+
return (right.streakCount - left.streakCount ||
|
|
243
|
+
Number(right.dueToday) - Number(left.dueToday) ||
|
|
244
|
+
left.title.localeCompare(right.title, undefined, { sensitivity: "base" }));
|
|
245
|
+
}
|
|
246
|
+
if (orderBy === "created_at") {
|
|
247
|
+
return (compareDateDesc(left.createdAt, right.createdAt) ||
|
|
248
|
+
left.title.localeCompare(right.title, undefined, { sensitivity: "base" }));
|
|
249
|
+
}
|
|
250
|
+
if (orderBy === "updated_at") {
|
|
251
|
+
return (compareDateDesc(left.updatedAt, right.updatedAt) ||
|
|
252
|
+
left.title.localeCompare(right.title, undefined, { sensitivity: "base" }));
|
|
253
|
+
}
|
|
254
|
+
return (Number(right.dueToday) - Number(left.dueToday) ||
|
|
255
|
+
compareDateAsc(left.lastCheckInAt, right.lastCheckInAt) ||
|
|
256
|
+
compareDateDesc(left.updatedAt, right.updatedAt) ||
|
|
257
|
+
left.title.localeCompare(right.title, undefined, { sensitivity: "base" }));
|
|
258
|
+
});
|
|
259
|
+
return nextHabits;
|
|
260
|
+
}
|
|
228
261
|
export function listHabits(filters = {}) {
|
|
229
262
|
const parsed = filters;
|
|
230
263
|
const whereClauses = [];
|
|
@@ -257,7 +290,10 @@ export function listHabits(filters = {}) {
|
|
|
257
290
|
${limitSql}`)
|
|
258
291
|
.all(...params);
|
|
259
292
|
const habits = filterDeletedEntities("habit", rows.map((row) => mapHabit(row)));
|
|
260
|
-
|
|
293
|
+
const filteredHabits = parsed.dueToday
|
|
294
|
+
? habits.filter((habit) => habit.dueToday)
|
|
295
|
+
: habits;
|
|
296
|
+
return sortHabits(filteredHabits, parsed.orderBy);
|
|
261
297
|
}
|
|
262
298
|
export function getHabitById(habitId) {
|
|
263
299
|
if (isEntityDeleted("habit", habitId)) {
|
|
@@ -5,6 +5,7 @@ import { deleteEncryptedSecret, readEncryptedSecret, storeEncryptedSecret } from
|
|
|
5
5
|
import { upsertWikiLlmProfile } from "./wiki-memory.js";
|
|
6
6
|
export const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
7
7
|
export const DEFAULT_OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
8
|
+
export const DEFAULT_MOCK_LLM_BASE_URL = "mock://workbench";
|
|
8
9
|
export const FORGE_MANAGED_WIKI_PROFILE_ID = "wiki_llm_forge_managed";
|
|
9
10
|
export const FORGE_DEFAULT_AGENT_ID = "agt_forge_default";
|
|
10
11
|
function parseMetadata(value) {
|
|
@@ -26,6 +27,9 @@ export function defaultBaseUrlForProvider(provider) {
|
|
|
26
27
|
if (provider === "openai-compatible") {
|
|
27
28
|
return "http://127.0.0.1:11434/v1";
|
|
28
29
|
}
|
|
30
|
+
if (provider === "mock") {
|
|
31
|
+
return DEFAULT_MOCK_LLM_BASE_URL;
|
|
32
|
+
}
|
|
29
33
|
return DEFAULT_OPENAI_BASE_URL;
|
|
30
34
|
}
|
|
31
35
|
function buildConnectionAgentId(connectionId) {
|
|
@@ -36,7 +40,9 @@ export function buildConnectionAgentIdentity(connection) {
|
|
|
36
40
|
? "Chat agent backed by OpenAI Codex OAuth."
|
|
37
41
|
: connection.provider === "openai-compatible"
|
|
38
42
|
? "Chat agent backed by a local or OpenAI-compatible endpoint."
|
|
39
|
-
:
|
|
43
|
+
: connection.provider === "mock"
|
|
44
|
+
? "Chat agent backed by Forge's deterministic mock workflow runtime."
|
|
45
|
+
: "Chat agent backed by the OpenAI API.";
|
|
40
46
|
return {
|
|
41
47
|
id: connection.agentId,
|
|
42
48
|
label: connection.agentLabel,
|
|
@@ -52,7 +58,8 @@ export function buildConnectionAgentIdentity(connection) {
|
|
|
52
58
|
};
|
|
53
59
|
}
|
|
54
60
|
function mapConnection(row) {
|
|
55
|
-
const hasStoredCredential =
|
|
61
|
+
const hasStoredCredential = row.provider === "mock" ||
|
|
62
|
+
(Boolean(row.secret_id) && Boolean(readEncryptedSecret(row.secret_id)));
|
|
56
63
|
return aiModelConnectionSchema.parse({
|
|
57
64
|
id: row.id,
|
|
58
65
|
label: row.label,
|
|
@@ -122,7 +129,10 @@ export function upsertAiModelConnection(input, secrets, options = {}) {
|
|
|
122
129
|
defaultBaseUrlForProvider(provider);
|
|
123
130
|
let secretId = existing?.secret_id ?? null;
|
|
124
131
|
let accountLabel = existing?.account_label ?? null;
|
|
125
|
-
if (parsed.
|
|
132
|
+
if (parsed.provider === "mock") {
|
|
133
|
+
secretId = null;
|
|
134
|
+
}
|
|
135
|
+
else if (parsed.apiKey?.trim()) {
|
|
126
136
|
secretId =
|
|
127
137
|
secretId ?? `mdl_secret_${randomUUID().replaceAll("-", "").slice(0, 10)}`;
|
|
128
138
|
storeEncryptedSecret(secretId, secrets.sealJson({
|
|
@@ -10,6 +10,9 @@ function normalizeAnchorKey(anchorKey) {
|
|
|
10
10
|
return anchorKey.trim().length > 0 ? anchorKey : null;
|
|
11
11
|
}
|
|
12
12
|
function normalizeLinks(links) {
|
|
13
|
+
if (!links) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
13
16
|
const seen = new Set();
|
|
14
17
|
return links.filter((link) => {
|
|
15
18
|
const key = `${link.entityType}:${link.entityId}:${link.anchorKey ?? ""}`;
|