forge-openclaw-plugin 0.2.51 → 0.2.53

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/dist/index.html CHANGED
@@ -13,7 +13,7 @@
13
13
  />
14
14
  <link rel="icon" type="image/png" href="/forge/assets/favicon-BCHm9dUV.ico" />
15
15
  <link rel="alternate icon" href="/forge/assets/favicon-BCHm9dUV.ico" />
16
- <script type="module" crossorigin src="/forge/assets/index-DX8RiahO.js"></script>
16
+ <script type="module" crossorigin src="/forge/assets/index-BR2FOGKC.js"></script>
17
17
  <link rel="modulepreload" crossorigin href="/forge/assets/vendor-D_NZFJze.js">
18
18
  <link rel="modulepreload" crossorigin href="/forge/assets/board-CAszQU7Y.js">
19
19
  <link rel="modulepreload" crossorigin href="/forge/assets/ui-B5MjRjKe.js">
@@ -19,6 +19,7 @@ const GRAPH_RANGE = {
19
19
  from: "2000-01-01T00:00:00.000Z",
20
20
  to: "2100-01-01T00:00:00.000Z"
21
21
  };
22
+ const KNOWLEDGE_GRAPH_NOTE_LIMIT = 2000;
22
23
  const BASE_NODE_SIZE = {
23
24
  goal: 56,
24
25
  strategy: 52,
@@ -167,6 +168,7 @@ function makeNode(input) {
167
168
  title: truncate(input.title, 90) || input.entityId,
168
169
  subtitle: truncate(input.subtitle, 120),
169
170
  description: truncate(input.description, 220),
171
+ searchText: truncate(input.searchText, 4000) || null,
170
172
  href: input.href ?? null,
171
173
  graphHref: buildKnowledgeGraphFocusHref(input.entityType, input.entityId),
172
174
  iconName: null,
@@ -226,7 +228,16 @@ export function buildKnowledgeGraph(userIds, query = {}) {
226
228
  const tags = filterOwnedEntities("tag", listTags(), userIds);
227
229
  const strategies = listStrategies({ userIds });
228
230
  const habits = listHabits({ userIds });
229
- const notes = listNotes({ userIds });
231
+ const selectedUserIds = new Set(userIds ?? []);
232
+ const notes = listNotes({ limit: KNOWLEDGE_GRAPH_NOTE_LIMIT }).filter((note) => {
233
+ if (selectedUserIds.size === 0) {
234
+ return true;
235
+ }
236
+ if (note.userId && selectedUserIds.has(note.userId)) {
237
+ return true;
238
+ }
239
+ return note.kind === "wiki" && note.userId === null;
240
+ });
230
241
  const insights = listInsights({ userIds });
231
242
  const calendarEvents = listCalendarEvents({ ...GRAPH_RANGE, userIds });
232
243
  const workBlocks = listWorkBlockTemplates({ userIds });
@@ -585,6 +596,7 @@ export function buildKnowledgeGraph(userIds, query = {}) {
585
596
  title: note.title,
586
597
  subtitle: isWiki ? note.slug : note.summary,
587
598
  description: note.summary || note.contentPlain,
599
+ searchText: note.contentPlain,
588
600
  previewStats: [
589
601
  { label: "Kind", value: note.kind },
590
602
  { label: "Links", value: note.links.length },
@@ -135,6 +135,7 @@ function findSpaceForFile(dataRoot, filePath, parsed) {
135
135
  if (row) {
136
136
  return row.id;
137
137
  }
138
+ return ensurePersonalWikiSpaceForLegacyUser(parts[1]);
138
139
  }
139
140
  return "wiki_space_shared";
140
141
  }
@@ -152,6 +153,28 @@ function findExistingNote(input) {
152
153
  .get(input.spaceId, input.slug);
153
154
  return bySlug?.id ?? null;
154
155
  }
156
+ function ensurePersonalWikiSpaceForLegacyUser(userId) {
157
+ const row = getDatabase()
158
+ .prepare(`SELECT id FROM wiki_spaces
159
+ WHERE owner_user_id = ? OR slug = ? OR slug = ? OR id = ?
160
+ ORDER BY created_at ASC
161
+ LIMIT 1`)
162
+ .get(userId, userId, `user-${slugify(userId)}`, `wiki_space_user_${slugify(userId)}`);
163
+ if (row) {
164
+ return row.id;
165
+ }
166
+ const now = new Date().toISOString();
167
+ const id = `wiki_space_user_${slugify(userId)}`;
168
+ getDatabase()
169
+ .prepare(`INSERT INTO wiki_spaces (id, slug, label, description, owner_user_id, visibility, created_at, updated_at)
170
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
171
+ ON CONFLICT(id) DO NOTHING`)
172
+ .run(id, `user-${slugify(userId)}`, `${userId} Wiki`, "Personal Forge wiki space recovered from legacy wiki files.", userId, "personal", now, now);
173
+ const inserted = getDatabase()
174
+ .prepare("SELECT id FROM wiki_spaces WHERE id = ?")
175
+ .get(id);
176
+ return inserted?.id ?? "wiki_space_shared";
177
+ }
155
178
  function upsertLinks(noteId, links) {
156
179
  getDatabase().prepare("DELETE FROM note_links WHERE note_id = ?").run(noteId);
157
180
  const createdAt = new Date().toISOString();
@@ -179,7 +202,8 @@ export async function importLegacyWikiMarkdownToSqlite(input = {}) {
179
202
  apply: input.apply ?? false,
180
203
  deleteFiles: input.deleteFiles ?? false,
181
204
  backupBeforeApply: input.backupBeforeApply ?? false,
182
- backupLabel: input.backupLabel ?? "legacy-wiki-markdown-pre-sqlite-import"
205
+ backupLabel: input.backupLabel ?? "legacy-wiki-markdown-pre-sqlite-import",
206
+ preserveExistingNotes: input.preserveExistingNotes ?? false
183
207
  };
184
208
  const wikiRoot = path.join(options.dataRoot, "wiki");
185
209
  const files = await walkMarkdownFiles(wikiRoot);
@@ -234,6 +258,17 @@ export async function importLegacyWikiMarkdownToSqlite(input = {}) {
234
258
  continue;
235
259
  }
236
260
  if (noteId) {
261
+ const existingNote = getNoteById(noteId, { skipCleanup: true });
262
+ if (options.preserveExistingNotes &&
263
+ existingNote &&
264
+ existingNote.contentMarkdown.trim().length > 0) {
265
+ getDatabase()
266
+ .prepare("UPDATE notes SET source_path = '' WHERE id = ? AND source_path <> ''")
267
+ .run(noteId);
268
+ syncNoteWikiArtifacts(existingNote);
269
+ updated += 1;
270
+ continue;
271
+ }
237
272
  getDatabase()
238
273
  .prepare(`UPDATE notes
239
274
  SET kind = ?, title = ?, slug = ?, space_id = ?, parent_slug = ?, index_order = ?, show_in_index = ?,
@@ -321,7 +356,8 @@ export async function importLegacyWikiMarkdownOnStartup(dataRoot = getEffectiveD
321
356
  dataRoot,
322
357
  apply: true,
323
358
  deleteFiles: false,
324
- backupBeforeApply: true
359
+ backupBeforeApply: true,
360
+ preserveExistingNotes: true
325
361
  });
326
362
  markStartupImportComplete();
327
363
  return result;
@@ -2627,7 +2627,7 @@ export const notesListQuerySchema = z
2627
2627
  userIds: repeatedTrimmedStringQuerySchema,
2628
2628
  updatedFrom: dateOnlySchema.optional(),
2629
2629
  updatedTo: dateOnlySchema.optional(),
2630
- limit: z.coerce.number().int().positive().max(200).optional()
2630
+ limit: z.coerce.number().int().positive().max(2000).optional()
2631
2631
  })
2632
2632
  .superRefine((value, context) => {
2633
2633
  if (value.linkedEntityType !== undefined &&
@@ -147,6 +147,7 @@ export function filterKnowledgeGraphData(graph, query) {
147
147
  node.title,
148
148
  node.subtitle,
149
149
  node.description,
150
+ node.searchText ?? "",
150
151
  node.owner?.displayName ?? "",
151
152
  ...node.tags.map((tag) => tag.label)
152
153
  ]
@@ -2,7 +2,7 @@
2
2
  "id": "forge-openclaw-plugin",
3
3
  "name": "Forge",
4
4
  "description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
5
- "version": "0.2.51",
5
+ "version": "0.2.53",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-openclaw-plugin",
3
- "version": "0.2.51",
3
+ "version": "0.2.53",
4
4
  "description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
5
5
  "type": "module",
6
6
  "license": "MIT",