@neuralis/brain-core 0.3.1 → 0.3.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/README.md +41 -40
- package/app/README.md +3 -3
- package/app/filesystem/FilesystemHost.tsx +7 -0
- package/app/filesystem/README.md +1 -1
- package/app/filesystem/api/index.ts +4 -4
- package/app/filesystem/hooks/README.md +1 -1
- package/app/filesystem/hooks/useFilesystemSSE.ts +41 -1
- package/app/filesystem/host/README.md +2 -2
- package/app/filesystem/host/buildFilesystemHostValue.ts +9 -2
- package/app/filesystem/lib/sourceKindForm.ts +109 -5
- package/app/filesystem/store/filesystemStore.ts +13 -3
- package/app/filesystem/ui/DiscoverDock.tsx +5 -1
- package/app/filesystem/ui/FileTree.tsx +34 -8
- package/app/filesystem/ui/FilesystemWidget.tsx +10 -2
- package/app/filesystem/ui/GitControlPanel.tsx +2 -2
- package/app/filesystem/ui/PendingChangesPanel.tsx +1 -1
- package/app/filesystem/ui/README.md +14 -13
- package/app/filesystem/ui/SourcesPanel.tsx +124 -24
- package/app/filesystem/ui/VectorHealthPanel.tsx +2 -2
- package/dist/app/host.js +41 -37
- package/dist/src/channels/filesystem.d.ts +1 -1
- package/dist/src/channels/filesystem.js +1 -1
- package/dist/src/domain/mime.d.ts +3 -3
- package/dist/src/domain/mime.js +3 -3
- package/dist/src/domain/scopeAccessCtx.d.ts +2 -2
- package/dist/src/domain/scopeAccessCtx.js +2 -2
- package/dist/src/domain/types.d.ts +8 -1
- package/dist/src/domain/types.d.ts.map +1 -1
- package/dist/src/events/pending.d.ts +1 -1
- package/dist/src/events/pending.js +1 -1
- package/dist/src/git/sourceGitControl.d.ts +2 -2
- package/dist/src/git/sourceGitControl.js +3 -3
- package/dist/src/lifecycle.d.ts +1 -1
- package/dist/src/routes/approve.d.ts +1 -1
- package/dist/src/routes/approve.js +1 -1
- package/dist/src/routes/events.d.ts +1 -1
- package/dist/src/routes/events.js +1 -1
- package/dist/src/routes/git.d.ts +7 -7
- package/dist/src/routes/git.js +18 -18
- package/dist/src/routes/health.d.ts +6 -6
- package/dist/src/routes/health.js +12 -12
- package/dist/src/routes/helpers/sourceNotConfigured.d.ts +1 -1
- package/dist/src/routes/helpers/sourceNotConfigured.js +1 -1
- package/dist/src/routes/helpers.d.ts +1 -1
- package/dist/src/routes/helpers.js +1 -1
- package/dist/src/routes/list.d.ts +1 -1
- package/dist/src/routes/list.js +1 -1
- package/dist/src/routes/pending.d.ts +4 -4
- package/dist/src/routes/pending.js +9 -9
- package/dist/src/routes/policies.d.ts +4 -4
- package/dist/src/routes/policies.d.ts.map +1 -1
- package/dist/src/routes/policies.js +11 -11
- package/dist/src/routes/policies.js.map +1 -1
- package/dist/src/routes/raw.d.ts +1 -1
- package/dist/src/routes/raw.js +1 -1
- package/dist/src/routes/read.d.ts +1 -1
- package/dist/src/routes/read.js +1 -1
- package/dist/src/routes/search.d.ts +1 -1
- package/dist/src/routes/search.js +1 -1
- package/dist/src/routes/sources.d.ts +20 -5
- package/dist/src/routes/sources.d.ts.map +1 -1
- package/dist/src/routes/sources.js +118 -118
- package/dist/src/routes/sources.js.map +1 -1
- package/dist/src/routes/upload.d.ts +1 -1
- package/dist/src/routes/upload.js +1 -1
- package/dist/src/routes/write.d.ts +2 -2
- package/dist/src/routes/write.js +2 -2
- package/dist/src/services/BridgeService.d.ts +7 -1
- package/dist/src/services/BridgeService.d.ts.map +1 -1
- package/dist/src/services/BridgeService.js +15 -3
- package/dist/src/services/BridgeService.js.map +1 -1
- package/dist/src/services/FilesystemService.d.ts +1 -1
- package/dist/src/services/FilesystemService.js +2 -2
- package/dist/src/services/declaredSources.d.ts +9 -3
- package/dist/src/services/declaredSources.d.ts.map +1 -1
- package/dist/src/services/declaredSources.js +2 -1
- package/dist/src/services/declaredSources.js.map +1 -1
- package/dist/src/tools/execCtx.d.ts +2 -2
- package/dist/src/tools/execCtx.js +2 -2
- package/dist/src/tools/fs_read.d.ts.map +1 -1
- package/dist/src/tools/fs_read.js +5 -0
- package/dist/src/tools/fs_read.js.map +1 -1
- package/dist/src/usecases/embeddingBacklog.js +1 -1
- package/dist/src/usecases/embeddingBacklog.js.map +1 -1
- package/dist/src/usecases/readFiles.d.ts.map +1 -1
- package/dist/src/usecases/readFiles.js +84 -1
- package/dist/src/usecases/readFiles.js.map +1 -1
- package/dist/src/usecases/syncPointWrites.d.ts +2 -0
- package/dist/src/usecases/syncPointWrites.d.ts.map +1 -1
- package/dist/src/usecases/syncPointWrites.js +5 -1
- package/dist/src/usecases/syncPointWrites.js.map +1 -1
- package/dist/src/usecases/vectorMaintenance.js +1 -1
- package/dist/src/usecases/vectorMaintenance.js.map +1 -1
- package/dist/src/usecases/write/content.js +1 -1
- package/dist/tools/fs_list.json +1 -1
- package/dist/tools/fs_read.json +1 -1
- package/dist/tools/fs_search.json +1 -1
- package/dist/tools/fs_write.json +1 -1
- package/instructions/brain-model.md +1 -1
- package/package.json +70 -63
- package/rules/brain-rules.md +2 -2
- package/skills/brain-start/SKILL.md +1 -1
- package/skills/connect-business-data/SKILL.md +1 -1
- package/skills/create-package/SKILL.md +8 -8
- package/skills/create-package/references/connectors-and-uri-policies.md +7 -2
- package/skills/create-package/references/runtime-and-build.md +1 -1
- package/skills/create-package/references/skills-and-context.md +1 -1
- package/skills/create-package/references/test-and-ship.md +4 -4
- package/skills/create-package/scripts/check-package.sh +1 -1
- package/skills/git/SKILL.md +23 -23
- package/skills/manage-files/SKILL.md +13 -13
- package/skills/manage-files/scripts/upload.sh +1 -1
- package/skills/manage-sources/SKILL.md +55 -54
- package/skills/manage-sources/scripts/reembed.sh +1 -1
- package/skills/manage-uri-policy/SKILL.md +9 -9
- package/skills/organize/SKILL.md +1 -1
- package/skills/sync/SKILL.md +2 -2
- package/tools/fs_list.json +1 -1
- package/tools/fs_read.json +1 -1
- package/tools/fs_search.json +1 -1
- package/tools/fs_write.json +1 -1
- package/workflows/sources-digest.json +1 -1
- package/docs/drive-overview.md +0 -59
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
type LucideIcon,
|
|
31
31
|
} from 'lucide-react';
|
|
32
32
|
import { meetsRequires } from '@neuralis/package-system/access';
|
|
33
|
-
import { SkillLauncher } from '@neuralis/package-system/client';
|
|
33
|
+
import { SkillLauncher, createPackageApi } from '@neuralis/package-system/client';
|
|
34
34
|
import { cn } from '../lib/cn';
|
|
35
35
|
import {
|
|
36
36
|
listSourceConfigs,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
type DiscoverableSourceSuggestion,
|
|
56
56
|
} from '../api';
|
|
57
57
|
import { dimmedSourceTone, getSourceVisualTone, sourceLiveReasonLabel } from '../lib/treeVisualState';
|
|
58
|
-
import { rootFieldMeta } from '../lib/sourceKindForm';
|
|
58
|
+
import { fieldControl, rootFieldMeta, selectOptionsFrom, type OptionsRoute, type SelectOption } from '../lib/sourceKindForm';
|
|
59
59
|
import { resolveIconWithFallback, resolveLucideIcon } from '../lib/iconResolver';
|
|
60
60
|
import { useFilesystemStore } from '../store/filesystemStore';
|
|
61
61
|
import { fileKey, sourceFromUri, sourceRootUri } from '../store/helpers';
|
|
@@ -479,6 +479,8 @@ export function SourcesPanel(props: Props) {
|
|
|
479
479
|
const setPendingSourceSuggestion = useFilesystemStore((s) => s.setPendingSourceSuggestion);
|
|
480
480
|
const refresh = useFilesystemStore((s) => s.refresh);
|
|
481
481
|
const sourceSummaries = useFilesystemStore((s) => s.sources);
|
|
482
|
+
// A `devices` frame bumps it: the device `select` re-reads its options.
|
|
483
|
+
const deviceRevision = useFilesystemStore((s) => s.deviceRevision);
|
|
482
484
|
|
|
483
485
|
// Source-key suggestion inputs: the signed-in user (for the user-scope
|
|
484
486
|
// qualifier) and the active agent's name (for the agent-scope qualifier).
|
|
@@ -489,13 +491,13 @@ export function SourcesPanel(props: Props) {
|
|
|
489
491
|
// `recognizesPackages` toggle in the UI. Server is the enforcement floor; this
|
|
490
492
|
// only HIDES the control. Undefined priority (no signal) ⇒ hide (deny-by-default).
|
|
491
493
|
const isOwnerEffective = (host.currentRole?.priority ?? 99) <= 2;
|
|
492
|
-
// warded-wren — affordance mirror for the `
|
|
494
|
+
// warded-wren — affordance mirror for the `sources.mount` gate that now covers
|
|
493
495
|
// browse and the discoverable list. Same shape as `FileTree`'s: the ONE shared
|
|
494
496
|
// kernel predicate, a copy at the boundary because the host keeps the grant
|
|
495
497
|
// list readonly, and it authorizes NOTHING — the routes stay the boundary.
|
|
496
498
|
// Hidden, never a disabled row (the S2 discipline).
|
|
497
499
|
const canMount = useMemo(
|
|
498
|
-
() => meetsRequires({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, { features: ['
|
|
500
|
+
() => meetsRequires({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, { features: ['sources.mount'] }),
|
|
499
501
|
[host.grantedFeatures],
|
|
500
502
|
);
|
|
501
503
|
const agentSlug = useMemo(() => {
|
|
@@ -609,8 +611,8 @@ export function SourcesPanel(props: Props) {
|
|
|
609
611
|
const selectedKindNeedsPath = rootField.needed;
|
|
610
612
|
// The container-plane affordances: the `/mounts` volume picker, the
|
|
611
613
|
// `neuralis:mount` callout, and Browse (which readdirs in the SERVER process,
|
|
612
|
-
// i.e. the wrong machine for a host-plane root —
|
|
613
|
-
//
|
|
614
|
+
// i.e. the wrong machine for a host-plane root — that root lives on the paired
|
|
615
|
+
// device chosen below, bounded by that device's own allowlist).
|
|
614
616
|
const showContainerPathChrome = selectedKindNeedsPath && rootField.container;
|
|
615
617
|
|
|
616
618
|
/**
|
|
@@ -1420,7 +1422,7 @@ export function SourcesPanel(props: Props) {
|
|
|
1420
1422
|
? 'This connector does not need a local path. Choose the scope and URI scheme; the package owns the runtime binding.'
|
|
1421
1423
|
: rootField.container
|
|
1422
1424
|
? 'Mount any folder from your system. The path must be accessible to the server process.'
|
|
1423
|
-
: 'A
|
|
1425
|
+
: 'A folder on the device you choose below \u2014 your own paired machine. It needs no volume mount here; that device\u2019s own allowlist (neuralis device grant) still limits what is reachable.'}
|
|
1424
1426
|
</div>
|
|
1425
1427
|
)}
|
|
1426
1428
|
<div className="space-y-2">
|
|
@@ -1466,23 +1468,41 @@ export function SourcesPanel(props: Props) {
|
|
|
1466
1468
|
</div>
|
|
1467
1469
|
{Object.entries(schemaObject(selectedKind).properties)
|
|
1468
1470
|
.filter(([key]) => key !== 'root')
|
|
1469
|
-
.map(([key, prop]) =>
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1471
|
+
.map(([key, prop]) => {
|
|
1472
|
+
const field = fieldControl(prop, selectedKind?.packageId ?? '');
|
|
1473
|
+
const setValue = (value: string) => setAddDraft((d) => ({
|
|
1474
|
+
...d,
|
|
1475
|
+
config: { ...d.config, [key]: value },
|
|
1476
|
+
}));
|
|
1477
|
+
return (
|
|
1478
|
+
<div key={key} className="space-y-1">
|
|
1479
|
+
<div className="text-[9px] font-semibold uppercase tracking-wider text-white/35">
|
|
1480
|
+
{(prop as any)?.['x-neuralis']?.ui?.label ?? key}
|
|
1481
|
+
</div>
|
|
1482
|
+
{field.control === 'select' ? (
|
|
1483
|
+
<OptionsRouteSelect
|
|
1484
|
+
route={field.options}
|
|
1485
|
+
revision={deviceRevision}
|
|
1486
|
+
projectId={projectId}
|
|
1487
|
+
agentId={agentId}
|
|
1488
|
+
value={String(addDraft.config[key] ?? '')}
|
|
1489
|
+
onChange={setValue}
|
|
1490
|
+
/>
|
|
1491
|
+
) : (
|
|
1492
|
+
<input
|
|
1493
|
+
type={field.numeric ? 'number' : 'text'}
|
|
1494
|
+
value={String(addDraft.config[key] ?? '')}
|
|
1495
|
+
onChange={(e) => setValue(e.target.value)}
|
|
1496
|
+
placeholder={(prop as any)?.['x-neuralis']?.ui?.placeholder ?? (prop as any)?.description ?? key}
|
|
1497
|
+
className={inputCls}
|
|
1498
|
+
/>
|
|
1499
|
+
)}
|
|
1500
|
+
{field.control === 'text' && field.refused ? (
|
|
1501
|
+
<div className="text-[9px] text-amber-300/80">{field.refused}</div>
|
|
1502
|
+
) : null}
|
|
1473
1503
|
</div>
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
value={String(addDraft.config[key] ?? '')}
|
|
1477
|
-
onChange={(e) => setAddDraft((d) => ({
|
|
1478
|
-
...d,
|
|
1479
|
-
config: { ...d.config, [key]: e.target.value },
|
|
1480
|
-
}))}
|
|
1481
|
-
placeholder={(prop as any)?.['x-neuralis']?.ui?.placeholder ?? (prop as any)?.description ?? key}
|
|
1482
|
-
className={inputCls}
|
|
1483
|
-
/>
|
|
1484
|
-
</div>
|
|
1485
|
-
))}
|
|
1504
|
+
);
|
|
1505
|
+
})}
|
|
1486
1506
|
{/* Directory browser (non-Docker only) */}
|
|
1487
1507
|
{showContainerPathChrome && !isDocker && browseOpen && (
|
|
1488
1508
|
<div className="rounded-md bg-white/[0.03] border border-white/[0.1] overflow-hidden">
|
|
@@ -1887,7 +1907,7 @@ export function SourcesPanel(props: Props) {
|
|
|
1887
1907
|
adjacent SkillLauncher hands the same uri-policy edit to
|
|
1888
1908
|
the agent. Its visibility is DERIVED from the host's
|
|
1889
1909
|
per-caller skill catalog (the `manage-uri-policy` skill
|
|
1890
|
-
declares `
|
|
1910
|
+
declares `sources.policy` itself) — never re-stated here. */}
|
|
1891
1911
|
<div>
|
|
1892
1912
|
<div className="flex items-center gap-1.5 py-1">
|
|
1893
1913
|
<button type="button" onClick={() => toggleSubSection(config.source, 'perms')}
|
|
@@ -2355,3 +2375,83 @@ export function SourcesPanel(props: Props) {
|
|
|
2355
2375
|
</div>
|
|
2356
2376
|
);
|
|
2357
2377
|
}
|
|
2378
|
+
|
|
2379
|
+
// ---------------------------------------------------------------------------
|
|
2380
|
+
// `select` field: options answered by a route in the DECLARING package
|
|
2381
|
+
// ---------------------------------------------------------------------------
|
|
2382
|
+
|
|
2383
|
+
/**
|
|
2384
|
+
* A dimmed option (an offline device): a muted text colour mixed OPAQUE into
|
|
2385
|
+
* the option's own surface, inline — the global `select option` rule outranks
|
|
2386
|
+
* any utility class, while an inline colour wins. Never `opacity`: the muted
|
|
2387
|
+
* colour is computed opaque against the same surface the option paints.
|
|
2388
|
+
*/
|
|
2389
|
+
const DIMMED_OPTION_STYLE = {
|
|
2390
|
+
color: 'color-mix(in srgb, var(--control-text) 48%, rgb(var(--w-composer-bg-rgb, 30, 32, 38)))',
|
|
2391
|
+
} as const;
|
|
2392
|
+
|
|
2393
|
+
/**
|
|
2394
|
+
* A config field declared `x-neuralis.ui.control: "select"`. ONE request per
|
|
2395
|
+
* mount (and per project/agent change) to the declaring package's
|
|
2396
|
+
* `optionsRoute`, through that package's own route client — never this
|
|
2397
|
+
* package's — and ONE quiet re-read per `revision` bump (a burst of `devices`
|
|
2398
|
+
* frames): the shown list stays until the new answer replaces it. A failed
|
|
2399
|
+
* load is SHOWN, never an empty list; the list is UX only, the declaring
|
|
2400
|
+
* package re-checks the value when the source is created.
|
|
2401
|
+
*/
|
|
2402
|
+
function OptionsRouteSelect({
|
|
2403
|
+
route,
|
|
2404
|
+
revision,
|
|
2405
|
+
projectId,
|
|
2406
|
+
agentId,
|
|
2407
|
+
value,
|
|
2408
|
+
onChange,
|
|
2409
|
+
}: {
|
|
2410
|
+
route: OptionsRoute;
|
|
2411
|
+
revision: number;
|
|
2412
|
+
projectId?: string | null;
|
|
2413
|
+
agentId: string;
|
|
2414
|
+
value: string;
|
|
2415
|
+
onChange: (value: string) => void;
|
|
2416
|
+
}) {
|
|
2417
|
+
const [options, setOptions] = useState<SelectOption[] | null>(null);
|
|
2418
|
+
const [loadError, setLoadError] = useState<string | null>(null);
|
|
2419
|
+
// The route is re-derived on every render; the effect keys on its VALUE.
|
|
2420
|
+
const { slug, path } = route;
|
|
2421
|
+
const query = new URLSearchParams(route.params).toString();
|
|
2422
|
+
// A new route/project/agent starts from "Loading…"; a revision bump does not.
|
|
2423
|
+
const scopeKey = `${slug}\n${path}\n${query}\n${projectId ?? ''}\n${agentId}`;
|
|
2424
|
+
const loadedScope = useRef<string | null>(null);
|
|
2425
|
+
useEffect(() => {
|
|
2426
|
+
let live = true;
|
|
2427
|
+
if (loadedScope.current !== scopeKey) {
|
|
2428
|
+
loadedScope.current = scopeKey;
|
|
2429
|
+
setOptions(null);
|
|
2430
|
+
}
|
|
2431
|
+
setLoadError(null);
|
|
2432
|
+
const api = createPackageApi({
|
|
2433
|
+
slug,
|
|
2434
|
+
getProjectId: () => projectId ?? null,
|
|
2435
|
+
getAgentId: () => agentId || null,
|
|
2436
|
+
});
|
|
2437
|
+
api.get<unknown>(path, Object.fromEntries(new URLSearchParams(query))).then(
|
|
2438
|
+
(answer) => { if (live) setOptions(selectOptionsFrom(answer)); },
|
|
2439
|
+
(err: unknown) => { if (live) setLoadError(err instanceof Error ? err.message : 'Could not load the options'); },
|
|
2440
|
+
);
|
|
2441
|
+
return () => { live = false; };
|
|
2442
|
+
}, [slug, path, query, projectId, agentId, scopeKey, revision]);
|
|
2443
|
+
|
|
2444
|
+
if (loadError) return <div className="text-[9px] text-red-300/80">{loadError}</div>;
|
|
2445
|
+
if (options === null) return <div className="text-[9px] text-white/30 animate-pulse">Loading…</div>;
|
|
2446
|
+
if (options.length === 0) return <div className="text-[9px] text-white/40 italic">Nothing to choose from.</div>;
|
|
2447
|
+
return (
|
|
2448
|
+
<select value={value} onChange={(e) => onChange(e.target.value)} className={selectCls}>
|
|
2449
|
+
<option value="" disabled>Choose…</option>
|
|
2450
|
+
{options.map((o) => (
|
|
2451
|
+
<option key={o.value} value={o.value} style={o.dimmed ? DIMMED_OPTION_STYLE : undefined}>
|
|
2452
|
+
{o.label}
|
|
2453
|
+
</option>
|
|
2454
|
+
))}
|
|
2455
|
+
</select>
|
|
2456
|
+
);
|
|
2457
|
+
}
|
|
@@ -76,8 +76,8 @@ const ACTION_COPY: Record<ActionKind, { label: string; explainer: string; toolti
|
|
|
76
76
|
export function VectorHealthPanel({ agentId, projectId }: Props) {
|
|
77
77
|
const client = useFilesystemStore((s) => s.client);
|
|
78
78
|
const host = useFilesystemHost();
|
|
79
|
-
// A mirror only — the server's `
|
|
80
|
-
const canWrite = hasFeature({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, '
|
|
79
|
+
// A mirror only — the server's `files.write` escalation is the gate.
|
|
80
|
+
const canWrite = hasFeature({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, 'files.write');
|
|
81
81
|
const [report, setReport] = useState<HealthReport | null>(null);
|
|
82
82
|
/** Snapshot taken right BEFORE a destructive action runs, so we can show a
|
|
83
83
|
* before/after delta on the stat cards once the post-action refetch lands. */
|