@unson/brainbase-mcp 0.10.1 → 0.10.2
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/package.json +2 -2
- package/ui/graph-projects-view.js +80 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unson/brainbase-mcp",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Local-first Brainbase judgment OS that lets supported AI agents reuse a user's approved goals, priorities, decisions, and judgment criteria.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -336,5 +336,5 @@
|
|
|
336
336
|
"engines": {
|
|
337
337
|
"node": ">=20"
|
|
338
338
|
},
|
|
339
|
-
"gitHead": "
|
|
339
|
+
"gitHead": "d8334b5e94cdc643f5de90ccfc883a5e67fdd9af"
|
|
340
340
|
}
|
|
@@ -148,6 +148,19 @@ function failureText(error) {
|
|
|
148
148
|
return textOrNull(error instanceof Error ? error.message : typeof error === 'string' ? error : null) ?? '理由不明';
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* A host may know the selected project's identity before its Graph list is
|
|
153
|
+
* available. Keep this boundary deliberately small: the early shell only
|
|
154
|
+
* accepts an id and display name, and never treats a host summary as Graph
|
|
155
|
+
* data such as goal, status or participant counts.
|
|
156
|
+
*/
|
|
157
|
+
function normalizeProjectSummary(value) {
|
|
158
|
+
if (!isRecord(value)) return null;
|
|
159
|
+
const id = textOrNull(value.id ?? value.code);
|
|
160
|
+
if (!id) return null;
|
|
161
|
+
return { id, name: textOrNull(value.name) ?? id };
|
|
162
|
+
}
|
|
163
|
+
|
|
151
164
|
/**
|
|
152
165
|
* Mounts 「プロジェクトと関係者」.
|
|
153
166
|
*
|
|
@@ -201,6 +214,9 @@ function failureText(error) {
|
|
|
201
214
|
* @param {(projectId: string) => Promise<object>} [options.loadProjectContext]
|
|
202
215
|
* Optional read-only supplementary sections (tasks/knowledge). A failed
|
|
203
216
|
* context read is kept separate from the Graph detail read.
|
|
217
|
+
* @param {Array<{ id: string, name?: string }> | (() => Array<{ id: string, name?: string }>)} [options.projectSummaries]
|
|
218
|
+
* Optional host-known project identities. These are used only to draw the
|
|
219
|
+
* selected project's early loading shell before the Graph list is read.
|
|
204
220
|
* @param {(container: Element, options: object) => { destroy?: Function }} [options.mountProjectGraph]
|
|
205
221
|
* Host-injected Sigma.js graph mount. When omitted, the shared browser
|
|
206
222
|
* entry is used. The workspace keeps an accessible relation list when
|
|
@@ -232,6 +248,7 @@ export function createGraphProjectsView({
|
|
|
232
248
|
onSelect,
|
|
233
249
|
ownShare,
|
|
234
250
|
loadProjectContext,
|
|
251
|
+
projectSummaries,
|
|
235
252
|
mountProjectGraph,
|
|
236
253
|
} = {}) {
|
|
237
254
|
if (!root) throw new TypeError('root is required');
|
|
@@ -267,6 +284,7 @@ export function createGraphProjectsView({
|
|
|
267
284
|
let knowledgeWorkspace = null;
|
|
268
285
|
let contextRequest = 0;
|
|
269
286
|
let detailRequest = 0;
|
|
287
|
+
let hostListRequest = 0;
|
|
270
288
|
let viewDestroyed = false;
|
|
271
289
|
|
|
272
290
|
const correction = createGraphCorrection({
|
|
@@ -289,6 +307,46 @@ export function createGraphProjectsView({
|
|
|
289
307
|
return state.list.state === 'ok' ? state.list.payload.projects.find((project) => project.id === id) ?? null : null;
|
|
290
308
|
}
|
|
291
309
|
|
|
310
|
+
function projectSummaryFor(id) {
|
|
311
|
+
const target = textOrNull(id);
|
|
312
|
+
if (!target) return null;
|
|
313
|
+
let summaries = projectSummaries;
|
|
314
|
+
try {
|
|
315
|
+
if (typeof summaries === 'function') summaries = summaries();
|
|
316
|
+
} catch {
|
|
317
|
+
summaries = null;
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(summaries)) {
|
|
320
|
+
const summary = summaries.map(normalizeProjectSummary).find((item) => item?.id === target);
|
|
321
|
+
if (summary) return summary;
|
|
322
|
+
}
|
|
323
|
+
const listed = listItem(target);
|
|
324
|
+
return listed ? { id: listed.id, name: listed.name } : { id: target, name: target };
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function renderProjectKnowledgeLoading(id, readState, { onRetry } = {}) {
|
|
328
|
+
const target = textOrNull(id);
|
|
329
|
+
if (!target) return null;
|
|
330
|
+
const project = projectSummaryFor(target);
|
|
331
|
+
const loading = makeElement(doc, 'section', {
|
|
332
|
+
className: 'bb-pkw bb-pkw-loading',
|
|
333
|
+
attrs: { 'aria-label': 'プロジェクトの知識', 'data-project-id': target },
|
|
334
|
+
});
|
|
335
|
+
loading.append(makeElement(doc, 'div', { className: 'bb-pkw-kicker', text: 'プロジェクトの記録' }));
|
|
336
|
+
const header = makeElement(doc, 'header', { className: 'bb-pkw-header' });
|
|
337
|
+
header.append(
|
|
338
|
+
makeElement(doc, 'h2', { text: project.name }),
|
|
339
|
+
makeElement(doc, 'p', { className: 'bb-pkw-lead', text: '目的・関係・判断の根拠を、実際に記録された情報からたどれます。' }),
|
|
340
|
+
);
|
|
341
|
+
loading.append(header);
|
|
342
|
+
const notice = graphStateNotice(doc, readState, {
|
|
343
|
+
onRetry,
|
|
344
|
+
loadingText: 'プロジェクトの記録を読み込んでいます。',
|
|
345
|
+
});
|
|
346
|
+
if (notice) loading.append(notice);
|
|
347
|
+
return loading;
|
|
348
|
+
}
|
|
349
|
+
|
|
292
350
|
function openCorrection(at, open) {
|
|
293
351
|
state.panelAt = at;
|
|
294
352
|
open();
|
|
@@ -456,6 +514,9 @@ export function createGraphProjectsView({
|
|
|
456
514
|
const stateNotice = graphStateNotice(doc, state.list, { onRetry: () => controller.load(), loadingText: 'プロジェクトを読み込んでいます。' });
|
|
457
515
|
if (stateNotice) {
|
|
458
516
|
children.push(stateNotice);
|
|
517
|
+
if (state.selectedId) {
|
|
518
|
+
children.push(renderProjectKnowledgeLoading(state.selectedId, state.list, { onRetry: () => controller.load() }));
|
|
519
|
+
}
|
|
459
520
|
return children;
|
|
460
521
|
}
|
|
461
522
|
const { payload } = state.list;
|
|
@@ -486,6 +547,10 @@ export function createGraphProjectsView({
|
|
|
486
547
|
onTabChange: setKnowledgeTabChrome,
|
|
487
548
|
});
|
|
488
549
|
children.push(knowledgeWorkspace.element);
|
|
550
|
+
} else if (state.selectedId) {
|
|
551
|
+
children.push(renderProjectKnowledgeLoading(state.selectedId, state.detail ?? { state: 'loading' }, {
|
|
552
|
+
onRetry: () => controller.loadDetail(state.selectedId),
|
|
553
|
+
}));
|
|
489
554
|
}
|
|
490
555
|
|
|
491
556
|
if (payload.projects.length === 0) {
|
|
@@ -623,7 +688,10 @@ export function createGraphProjectsView({
|
|
|
623
688
|
const project = loaded?.project ?? listItem(state.selectedId) ?? { id: state.selectedId, name: state.selectedId };
|
|
624
689
|
const children = [workspaceRailHead(doc, { kicker: 'プロジェクト', title: project.name, sub: project.id })];
|
|
625
690
|
if (!loaded) {
|
|
626
|
-
|
|
691
|
+
const readState = detail?.id === state.selectedId
|
|
692
|
+
? detail
|
|
693
|
+
: state.list.state === 'ok' ? { state: 'loading' } : state.list;
|
|
694
|
+
children.push(graphStateNotice(doc, readState, {
|
|
627
695
|
onRetry: () => controller.loadDetail(state.selectedId),
|
|
628
696
|
loadingText: 'このプロジェクトの関係者を読み込んでいます。',
|
|
629
697
|
}));
|
|
@@ -692,13 +760,16 @@ export function createGraphProjectsView({
|
|
|
692
760
|
|
|
693
761
|
/** Reads the host's project list (see `load`). */
|
|
694
762
|
async function loadHostList({ keep = false } = {}) {
|
|
763
|
+
const request = ++hostListRequest;
|
|
764
|
+
if (viewDestroyed) return state.list;
|
|
695
765
|
if (!(keep && state.list.state === 'ok')) {
|
|
696
766
|
state.list = { state: 'loading' };
|
|
697
767
|
controller.render();
|
|
698
768
|
}
|
|
699
|
-
|
|
769
|
+
const result = await client.read('/projects');
|
|
770
|
+
if (viewDestroyed || request !== hostListRequest) return state.list;
|
|
771
|
+
state.list = normalizeProjectList(result);
|
|
700
772
|
if (state.list.state !== 'ok') {
|
|
701
|
-
if (!keep) state.selectedId = null;
|
|
702
773
|
controller.render();
|
|
703
774
|
return state.list;
|
|
704
775
|
}
|
|
@@ -711,16 +782,21 @@ export function createGraphProjectsView({
|
|
|
711
782
|
contextRequest += 1;
|
|
712
783
|
state.selectedId = projects[0]?.id ?? null;
|
|
713
784
|
if (state.selectedId) {
|
|
785
|
+
if (viewDestroyed || request !== hostListRequest) return state.list;
|
|
714
786
|
const reading = controller.loadDetail(state.selectedId);
|
|
715
787
|
notifySelect(state.selectedId);
|
|
716
788
|
await reading;
|
|
789
|
+
if (viewDestroyed || request !== hostListRequest) return state.list;
|
|
717
790
|
return state.list;
|
|
718
791
|
}
|
|
719
792
|
} else if (state.detail?.id !== state.selectedId) {
|
|
720
793
|
// The project the host asked for is listed; read it for the rail.
|
|
794
|
+
if (viewDestroyed || request !== hostListRequest) return state.list;
|
|
721
795
|
await controller.loadDetail(state.selectedId);
|
|
796
|
+
if (viewDestroyed || request !== hostListRequest) return state.list;
|
|
722
797
|
return state.list;
|
|
723
798
|
}
|
|
799
|
+
if (viewDestroyed || request !== hostListRequest) return state.list;
|
|
724
800
|
controller.render();
|
|
725
801
|
return state.list;
|
|
726
802
|
}
|
|
@@ -744,6 +820,7 @@ export function createGraphProjectsView({
|
|
|
744
820
|
destroy() {
|
|
745
821
|
if (viewDestroyed) return;
|
|
746
822
|
viewDestroyed = true;
|
|
823
|
+
hostListRequest += 1;
|
|
747
824
|
detailRequest += 1;
|
|
748
825
|
contextRequest += 1;
|
|
749
826
|
knowledgeWorkspace?.destroy();
|