-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPackage.swift
More file actions
152 lines (142 loc) · 6.63 KB
/
Package.swift
File metadata and controls
152 lines (142 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// swift-tools-version: 6.0
//
// NeuralCompose — Privacy-first macOS BCI communication prototype.
//
// Module layout (MLX isolation is load-bearing):
//
// NeuralComposeApp (executable, SwiftUI)
// │
// ├── BCICore pure-Swift models, protocols, buffers, intent FSM
// ├── BCIEEG BrainFlow facade + synthetic + playback streams
// ├── BCIClassifier Core ML wrapper (ANE-preferred) + mock classifier
// └── BCILLM MLX-Swift adapter + stub predictor + tokenizer
//
// MLX-Swift and swift-transformers are linked ONLY into BCILLM.
// The app target talks to BCILLM through the `NextWordPredicting` protocol from
// BCICore, so there is exactly one MLX runtime copy in the linked binary.
//
// BrainFlow is intentionally NOT a SwiftPM dependency. It is an optional system
// library, surfaced through the BCIBridge C++/Obj-C++ shim and gated by the
// `BCI_BRAINFLOW_AVAILABLE` compile flag. Without it, BCIEEG transparently
// falls back to the synthetic stream so the app builds and runs out-of-the-box.
import PackageDescription
let package = Package(
name: "NeuralCompose",
platforms: [
.macOS(.v14)
],
products: [
.executable(name: "NeuralCompose", targets: ["NeuralComposeApp"]),
.library(name: "BCICore", targets: ["BCICore"]),
.library(name: "BCIEEG", targets: ["BCIEEG"]),
.library(name: "BCIClassifier", targets: ["BCIClassifier"]),
.library(name: "BCILLM", targets: ["BCILLM"]),
],
dependencies: [
// MLX runtime + small-model utilities. Pinned conservatively; bump as
// upstream releases stabilize. BCILLM is the *only* target that
// imports any of these products.
.package(url: "https://github.com/ml-explore/mlx-swift", from: "0.21.2"),
.package(url: "https://github.com/ml-explore/mlx-swift-examples", from: "2.21.0"),
// Tokenizer + chat-template utilities. Used strictly offline.
.package(url: "https://github.com/huggingface/swift-transformers", from: "0.1.20"),
],
targets: [
// ── C++/Obj-C++ bridge ────────────────────────────────────────────
.target(
name: "BCIBridge",
path: "Sources/BCIBridge",
publicHeadersPath: "include",
cxxSettings: [
.headerSearchPath("include"),
// Default to stub mode. Define BCI_BRAINFLOW_AVAILABLE at
// build time (and provide -lBrainflow / header path) to wire
// in a real BrainFlow installation.
.define("BCI_BRIDGE_STUB"),
]
),
// ── Core abstractions, no third-party deps ────────────────────────
.target(
name: "BCICore",
path: "Sources/BCICore",
swiftSettings: strictConcurrency
),
// ── EEG streaming ────────────────────────────────────────────────
.target(
name: "BCIEEG",
dependencies: ["BCICore", "BCIBridge"],
path: "Sources/BCIEEG",
swiftSettings: strictConcurrency
),
// ── Core ML intent classifier ────────────────────────────────────
.target(
name: "BCIClassifier",
dependencies: ["BCICore"],
path: "Sources/BCIClassifier",
swiftSettings: strictConcurrency
),
// ── MLX LLM (isolated) ───────────────────────────────────────────
.target(
name: "BCILLM",
dependencies: [
"BCICore",
.product(name: "MLX", package: "mlx-swift"),
.product(name: "MLXNN", package: "mlx-swift"),
.product(name: "MLXRandom", package: "mlx-swift"),
.product(name: "MLXLLM", package: "mlx-swift-examples"),
.product(name: "MLXLMCommon", package: "mlx-swift-examples"),
.product(name: "Transformers", package: "swift-transformers"),
],
path: "Sources/BCILLM",
swiftSettings: strictConcurrency + [
.define("BCI_HAS_MLX")
]
),
// ── Application ──────────────────────────────────────────────────
.executableTarget(
name: "NeuralComposeApp",
dependencies: ["BCICore", "BCIEEG", "BCIClassifier", "BCILLM"],
path: "Sources/NeuralComposeApp",
// Info.plist lives in Resources/ for reference / Xcode builds but
// is intentionally NOT declared as a SwiftPM resource: SwiftPM
// forbids Info.plist as a top-level resource. `swift run` produces
// a runnable binary without one.
exclude: ["Resources/Info.plist"],
swiftSettings: strictConcurrency
),
// ── Tests ────────────────────────────────────────────────────────
.testTarget(
name: "BCICoreTests",
dependencies: ["BCICore"],
path: "Tests/BCICoreTests"
),
.testTarget(
name: "BCIEEGTests",
dependencies: ["BCIEEG", "BCICore"],
path: "Tests/BCIEEGTests"
),
.testTarget(
name: "BCIClassifierTests",
dependencies: ["BCIClassifier", "BCICore"],
path: "Tests/BCIClassifierTests"
),
.testTarget(
name: "BCILLMTests",
dependencies: ["BCILLM", "BCICore"],
path: "Tests/BCILLMTests"
),
],
cxxLanguageStandard: .cxx17
)
// MARK: - Shared Swift settings
var strictConcurrency: [SwiftSetting] {
[
.enableExperimentalFeature("StrictConcurrency"),
.enableUpcomingFeature("ExistentialAny"),
// Not enabling InternalImportsByDefault — it forces every public
// signature touching Foundation types (UUID, URL, Data) to either
// re-export Foundation or wrap them. The friction isn't worth it
// for an executable + four internal libraries that always link
// together.
]
}