@cryptiklemur/lattice 0.0.0 → 1.1.0

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.
Files changed (41) hide show
  1. package/.github/workflows/release.yml +4 -4
  2. package/.releaserc.json +2 -1
  3. package/client/src/components/auth/PassphrasePrompt.tsx +70 -70
  4. package/client/src/components/mesh/NodeBadge.tsx +24 -24
  5. package/client/src/components/mesh/PairingDialog.tsx +281 -281
  6. package/client/src/components/panels/FileBrowser.tsx +241 -241
  7. package/client/src/components/panels/StickyNotes.tsx +187 -187
  8. package/client/src/components/settings/Appearance.tsx +151 -151
  9. package/client/src/components/settings/MeshStatus.tsx +145 -145
  10. package/client/src/components/settings/SettingsView.tsx +57 -57
  11. package/client/src/components/setup/SetupWizard.tsx +750 -750
  12. package/client/src/components/ui/ErrorBoundary.tsx +56 -56
  13. package/client/src/router.tsx +391 -391
  14. package/client/vite.config.ts +20 -20
  15. package/package.json +1 -1
  16. package/server/src/handlers/chat.ts +194 -194
  17. package/server/src/handlers/settings.ts +109 -109
  18. package/themes/amoled.json +20 -20
  19. package/themes/ayu-light.json +9 -9
  20. package/themes/catppuccin-latte.json +9 -9
  21. package/themes/catppuccin-mocha.json +9 -9
  22. package/themes/clay-light.json +10 -10
  23. package/themes/clay.json +10 -10
  24. package/themes/dracula.json +9 -9
  25. package/themes/everforest-light.json +9 -9
  26. package/themes/everforest.json +9 -9
  27. package/themes/github-light.json +9 -9
  28. package/themes/gruvbox-dark.json +9 -9
  29. package/themes/gruvbox-light.json +9 -9
  30. package/themes/monokai.json +9 -9
  31. package/themes/nord-light.json +9 -9
  32. package/themes/nord.json +9 -9
  33. package/themes/one-dark.json +9 -9
  34. package/themes/one-light.json +9 -9
  35. package/themes/rose-pine-dawn.json +9 -9
  36. package/themes/rose-pine.json +9 -9
  37. package/themes/solarized-dark.json +9 -9
  38. package/themes/solarized-light.json +9 -9
  39. package/themes/tokyo-night-light.json +9 -9
  40. package/themes/tokyo-night.json +9 -9
  41. package/.serena/project.yml +0 -138
@@ -1,145 +1,145 @@
1
- import { useState } from "react";
2
- import { Plus, CircleDot, Circle } from "lucide-react";
3
- import { useWebSocket } from "../../hooks/useWebSocket";
4
- import { useMesh } from "../../hooks/useMesh";
5
- import { PairingDialog } from "../mesh/PairingDialog";
6
- import type { NodeInfo } from "@lattice/shared";
7
-
8
- interface NodeRowProps {
9
- node: NodeInfo;
10
- onUnpair: (nodeId: string) => void;
11
- }
12
-
13
- function NodeRow(props: NodeRowProps) {
14
- var [confirming, setConfirming] = useState(false);
15
-
16
- function handleUnpair() {
17
- if (!confirming) {
18
- setConfirming(true);
19
- return;
20
- }
21
- props.onUnpair(props.node.id);
22
- setConfirming(false);
23
- }
24
-
25
- return (
26
- <div className="flex items-center gap-3 p-3 sm:p-2.5 px-3.5 rounded-lg border border-base-content/15 bg-base-300 mb-2">
27
- {props.node.online ? (
28
- <CircleDot size={10} className="text-success flex-shrink-0" aria-label="Online" />
29
- ) : (
30
- <Circle size={10} className="text-base-content/30 flex-shrink-0" aria-label="Offline" />
31
- )}
32
-
33
- <div className="flex-1 min-w-0">
34
- <div className="text-[13px] font-medium text-base-content truncate">
35
- {props.node.name}
36
- {props.node.isLocal && (
37
- <span className="ml-1.5 text-[10px] font-semibold text-primary uppercase tracking-[0.06em]">
38
- local
39
- </span>
40
- )}
41
- </div>
42
- <div className="text-[11px] text-base-content/40 truncate">
43
- {props.node.address}:{props.node.port}
44
- {!props.node.online && (
45
- <span className="ml-2 text-base-content/30 italic">offline</span>
46
- )}
47
- </div>
48
- </div>
49
-
50
- {!props.node.isLocal && (
51
- <div className="flex gap-1.5 flex-shrink-0">
52
- {confirming ? (
53
- <>
54
- <button
55
- onClick={handleUnpair}
56
- className="btn btn-error btn-xs"
57
- >
58
- Confirm
59
- </button>
60
- <button
61
- onClick={function () { setConfirming(false); }}
62
- className="btn btn-ghost btn-xs"
63
- >
64
- Cancel
65
- </button>
66
- </>
67
- ) : (
68
- <button
69
- onClick={handleUnpair}
70
- className="btn btn-ghost btn-xs border border-base-content/20 hover:btn-error hover:border-error"
71
- >
72
- Unpair
73
- </button>
74
- )}
75
- </div>
76
- )}
77
- </div>
78
- );
79
- }
80
-
81
- export function MeshStatus() {
82
- var ws = useWebSocket();
83
- var { nodes } = useMesh();
84
- var [pairingOpen, setPairingOpen] = useState(false);
85
-
86
- function handleUnpair(nodeId: string) {
87
- ws.send({ type: "mesh:unpair", nodeId });
88
- }
89
-
90
- var localNode = nodes.find(function (n) { return n.isLocal; });
91
- var remoteNodes = nodes.filter(function (n) { return !n.isLocal; });
92
-
93
- return (
94
- <div className="py-2">
95
- <div className="mb-5">
96
- <div className="text-[12px] font-semibold text-base-content/40 mb-2 tracking-[0.06em]">
97
- This Node
98
- </div>
99
- {localNode ? (
100
- <NodeRow node={localNode} onUnpair={handleUnpair} />
101
- ) : (
102
- <div className="text-[12px] text-base-content/40 italic">
103
- Waiting for node info...
104
- </div>
105
- )}
106
- </div>
107
-
108
- <div className="mb-5">
109
- <div className="flex items-center justify-between mb-2">
110
- <div className="text-[12px] font-semibold text-base-content/40 tracking-[0.06em]">
111
- Paired Nodes
112
- </div>
113
- <button
114
- onClick={function () { setPairingOpen(true); }}
115
- className="btn btn-primary btn-sm sm:btn-xs gap-1"
116
- >
117
- <Plus size={10} />
118
- Pair New Node
119
- </button>
120
- </div>
121
-
122
- {remoteNodes.length === 0 ? (
123
- <div className="p-4 rounded-lg border border-dashed border-base-content/15 text-center text-[12px] text-base-content/40 italic">
124
- No paired nodes yet.
125
- </div>
126
- ) : (
127
- remoteNodes.map(function (node) {
128
- return (
129
- <NodeRow
130
- key={node.id}
131
- node={node}
132
- onUnpair={handleUnpair}
133
- />
134
- );
135
- })
136
- )}
137
- </div>
138
-
139
- <PairingDialog
140
- isOpen={pairingOpen}
141
- onClose={function () { setPairingOpen(false); }}
142
- />
143
- </div>
144
- );
145
- }
1
+ import { useState } from "react";
2
+ import { Plus, CircleDot, Circle } from "lucide-react";
3
+ import { useWebSocket } from "../../hooks/useWebSocket";
4
+ import { useMesh } from "../../hooks/useMesh";
5
+ import { PairingDialog } from "../mesh/PairingDialog";
6
+ import type { NodeInfo } from "@lattice/shared";
7
+
8
+ interface NodeRowProps {
9
+ node: NodeInfo;
10
+ onUnpair: (nodeId: string) => void;
11
+ }
12
+
13
+ function NodeRow(props: NodeRowProps) {
14
+ var [confirming, setConfirming] = useState(false);
15
+
16
+ function handleUnpair() {
17
+ if (!confirming) {
18
+ setConfirming(true);
19
+ return;
20
+ }
21
+ props.onUnpair(props.node.id);
22
+ setConfirming(false);
23
+ }
24
+
25
+ return (
26
+ <div className="flex items-center gap-3 p-3 sm:p-2.5 px-3.5 rounded-lg border border-base-content/15 bg-base-300 mb-2">
27
+ {props.node.online ? (
28
+ <CircleDot size={10} className="text-success flex-shrink-0" aria-label="Online" />
29
+ ) : (
30
+ <Circle size={10} className="text-base-content/30 flex-shrink-0" aria-label="Offline" />
31
+ )}
32
+
33
+ <div className="flex-1 min-w-0">
34
+ <div className="text-[13px] font-medium text-base-content truncate">
35
+ {props.node.name}
36
+ {props.node.isLocal && (
37
+ <span className="ml-1.5 text-[10px] font-semibold text-primary uppercase tracking-[0.06em]">
38
+ local
39
+ </span>
40
+ )}
41
+ </div>
42
+ <div className="text-[11px] text-base-content/40 truncate">
43
+ {props.node.address}:{props.node.port}
44
+ {!props.node.online && (
45
+ <span className="ml-2 text-base-content/30 italic">offline</span>
46
+ )}
47
+ </div>
48
+ </div>
49
+
50
+ {!props.node.isLocal && (
51
+ <div className="flex gap-1.5 flex-shrink-0">
52
+ {confirming ? (
53
+ <>
54
+ <button
55
+ onClick={handleUnpair}
56
+ className="btn btn-error btn-xs"
57
+ >
58
+ Confirm
59
+ </button>
60
+ <button
61
+ onClick={function () { setConfirming(false); }}
62
+ className="btn btn-ghost btn-xs"
63
+ >
64
+ Cancel
65
+ </button>
66
+ </>
67
+ ) : (
68
+ <button
69
+ onClick={handleUnpair}
70
+ className="btn btn-ghost btn-xs border border-base-content/20 hover:btn-error hover:border-error"
71
+ >
72
+ Unpair
73
+ </button>
74
+ )}
75
+ </div>
76
+ )}
77
+ </div>
78
+ );
79
+ }
80
+
81
+ export function MeshStatus() {
82
+ var ws = useWebSocket();
83
+ var { nodes } = useMesh();
84
+ var [pairingOpen, setPairingOpen] = useState(false);
85
+
86
+ function handleUnpair(nodeId: string) {
87
+ ws.send({ type: "mesh:unpair", nodeId });
88
+ }
89
+
90
+ var localNode = nodes.find(function (n) { return n.isLocal; });
91
+ var remoteNodes = nodes.filter(function (n) { return !n.isLocal; });
92
+
93
+ return (
94
+ <div className="py-2">
95
+ <div className="mb-5">
96
+ <div className="text-[12px] font-semibold text-base-content/40 mb-2 tracking-[0.06em]">
97
+ This Node
98
+ </div>
99
+ {localNode ? (
100
+ <NodeRow node={localNode} onUnpair={handleUnpair} />
101
+ ) : (
102
+ <div className="text-[12px] text-base-content/40 italic">
103
+ Waiting for node info...
104
+ </div>
105
+ )}
106
+ </div>
107
+
108
+ <div className="mb-5">
109
+ <div className="flex items-center justify-between mb-2">
110
+ <div className="text-[12px] font-semibold text-base-content/40 tracking-[0.06em]">
111
+ Paired Nodes
112
+ </div>
113
+ <button
114
+ onClick={function () { setPairingOpen(true); }}
115
+ className="btn btn-primary btn-sm sm:btn-xs gap-1"
116
+ >
117
+ <Plus size={10} />
118
+ Pair New Node
119
+ </button>
120
+ </div>
121
+
122
+ {remoteNodes.length === 0 ? (
123
+ <div className="p-4 rounded-lg border border-dashed border-base-content/15 text-center text-[12px] text-base-content/40 italic">
124
+ No paired nodes yet.
125
+ </div>
126
+ ) : (
127
+ remoteNodes.map(function (node) {
128
+ return (
129
+ <NodeRow
130
+ key={node.id}
131
+ node={node}
132
+ onUnpair={handleUnpair}
133
+ />
134
+ );
135
+ })
136
+ )}
137
+ </div>
138
+
139
+ <PairingDialog
140
+ isOpen={pairingOpen}
141
+ onClose={function () { setPairingOpen(false); }}
142
+ />
143
+ </div>
144
+ );
145
+ }
@@ -1,57 +1,57 @@
1
- import { useSidebar } from "../../hooks/useSidebar";
2
- import { Menu } from "lucide-react";
3
- import { Appearance } from "./Appearance";
4
- import { ClaudeSettings } from "./ClaudeSettings";
5
- import { Environment } from "./Environment";
6
- import { MeshStatus } from "./MeshStatus";
7
- import { GlobalMcp } from "./GlobalMcp";
8
- import { GlobalSkills } from "./GlobalSkills";
9
- import type { SettingsSection } from "../../stores/sidebar";
10
-
11
- var SECTION_CONFIG: Record<string, { title: string }> = {
12
- appearance: { title: "Appearance" },
13
- claude: { title: "Claude Settings" },
14
- environment: { title: "Environment" },
15
- mcp: { title: "MCP Servers" },
16
- skills: { title: "Skills" },
17
- nodes: { title: "Mesh Nodes" },
18
- };
19
-
20
- function renderSection(section: SettingsSection) {
21
- if (section === "appearance") return <Appearance />;
22
- if (section === "claude") return <ClaudeSettings />;
23
- if (section === "environment") return <Environment />;
24
- if (section === "mcp") return <GlobalMcp />;
25
- if (section === "skills") return <GlobalSkills />;
26
- if (section === "nodes") return <MeshStatus />;
27
- return null;
28
- }
29
-
30
- export function SettingsView() {
31
- var { activeView, toggleDrawer } = useSidebar();
32
-
33
- if (activeView.type !== "settings") {
34
- return null;
35
- }
36
-
37
- var section = activeView.section;
38
- var config = SECTION_CONFIG[section];
39
-
40
- return (
41
- <div className="flex-1 overflow-auto px-4 sm:px-8 py-4 sm:py-6 max-w-3xl">
42
- {config && (
43
- <div className="mb-6 flex items-center gap-3">
44
- <button
45
- className="btn btn-ghost btn-sm btn-square lg:hidden"
46
- aria-label="Toggle sidebar"
47
- onClick={toggleDrawer}
48
- >
49
- <Menu size={18} />
50
- </button>
51
- <h1 className="text-lg font-mono font-bold text-base-content">{config.title}</h1>
52
- </div>
53
- )}
54
- {renderSection(section)}
55
- </div>
56
- );
57
- }
1
+ import { useSidebar } from "../../hooks/useSidebar";
2
+ import { Menu } from "lucide-react";
3
+ import { Appearance } from "./Appearance";
4
+ import { ClaudeSettings } from "./ClaudeSettings";
5
+ import { Environment } from "./Environment";
6
+ import { MeshStatus } from "./MeshStatus";
7
+ import { GlobalMcp } from "./GlobalMcp";
8
+ import { GlobalSkills } from "./GlobalSkills";
9
+ import type { SettingsSection } from "../../stores/sidebar";
10
+
11
+ var SECTION_CONFIG: Record<string, { title: string }> = {
12
+ appearance: { title: "Appearance" },
13
+ claude: { title: "Claude Settings" },
14
+ environment: { title: "Environment" },
15
+ mcp: { title: "MCP Servers" },
16
+ skills: { title: "Skills" },
17
+ nodes: { title: "Mesh Nodes" },
18
+ };
19
+
20
+ function renderSection(section: SettingsSection) {
21
+ if (section === "appearance") return <Appearance />;
22
+ if (section === "claude") return <ClaudeSettings />;
23
+ if (section === "environment") return <Environment />;
24
+ if (section === "mcp") return <GlobalMcp />;
25
+ if (section === "skills") return <GlobalSkills />;
26
+ if (section === "nodes") return <MeshStatus />;
27
+ return null;
28
+ }
29
+
30
+ export function SettingsView() {
31
+ var { activeView, toggleDrawer } = useSidebar();
32
+
33
+ if (activeView.type !== "settings") {
34
+ return null;
35
+ }
36
+
37
+ var section = activeView.section;
38
+ var config = SECTION_CONFIG[section];
39
+
40
+ return (
41
+ <div className="flex-1 overflow-auto px-4 sm:px-8 py-4 sm:py-6 max-w-3xl">
42
+ {config && (
43
+ <div className="mb-6 flex items-center gap-3">
44
+ <button
45
+ className="btn btn-ghost btn-sm btn-square lg:hidden"
46
+ aria-label="Toggle sidebar"
47
+ onClick={toggleDrawer}
48
+ >
49
+ <Menu size={18} />
50
+ </button>
51
+ <h1 className="text-lg font-mono font-bold text-base-content">{config.title}</h1>
52
+ </div>
53
+ )}
54
+ {renderSection(section)}
55
+ </div>
56
+ );
57
+ }