@cereworker/cli 0.6.0 → 26.313.1
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/app.d.ts.map +1 -1
- package/dist/app.js +33 -181
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +87 -0
- package/dist/auth.js.map +1 -0
- package/dist/components/StatusBar.d.ts +3 -1
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +2 -2
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/hooks/useCerebellum.d.ts +7 -0
- package/dist/hooks/useCerebellum.d.ts.map +1 -1
- package/dist/hooks/useCerebellum.js +19 -1
- package/dist/hooks/useCerebellum.js.map +1 -1
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -1
- package/dist/onboard/config-builder.d.ts.map +1 -1
- package/dist/onboard/config-builder.js +12 -0
- package/dist/onboard/config-builder.js.map +1 -1
- package/dist/onboard/steps/cerebellum.d.ts.map +1 -1
- package/dist/onboard/steps/cerebellum.js +29 -1
- package/dist/onboard/steps/cerebellum.js.map +1 -1
- package/dist/onboard/steps/cerebrum.d.ts +3 -0
- package/dist/onboard/steps/cerebrum.d.ts.map +1 -1
- package/dist/onboard/steps/cerebrum.js +81 -26
- package/dist/onboard/steps/cerebrum.js.map +1 -1
- package/dist/onboard/wizard.d.ts.map +1 -1
- package/dist/onboard/wizard.js +6 -1
- package/dist/onboard/wizard.js.map +1 -1
- package/dist/serve.d.ts +3 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +83 -0
- package/dist/serve.js.map +1 -0
- package/dist/service.d.ts +25 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +232 -0
- package/dist/service.js.map +1 -0
- package/package.json +12 -11
- package/scripts/setup.sh +212 -0
package/dist/service.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { Orchestrator, ConversationStore, createLogger } from '@cereworker/core';
|
|
4
|
+
import { CerebrumProvider } from '@cereworker/cerebrum';
|
|
5
|
+
import { createChannelManager } from '@cereworker/channels';
|
|
6
|
+
import { browserToolDefinitions } from '@cereworker/browser';
|
|
7
|
+
import { loadSkills, filterEligibleSkills, SkillRegistry } from '@cereworker/skills';
|
|
8
|
+
import { HippocampusStore, HippocampusCurator, createMemoryTools, } from '@cereworker/hippocampus';
|
|
9
|
+
import { GatewayServer, GatewayNodeClient, createProxyTools } from '@cereworker/gateway';
|
|
10
|
+
const log = createLogger('service');
|
|
11
|
+
export function createService(config) {
|
|
12
|
+
// Create persistent conversation store
|
|
13
|
+
const conversationStore = new ConversationStore();
|
|
14
|
+
const orchestrator = new Orchestrator({
|
|
15
|
+
conversationStore,
|
|
16
|
+
compaction: {
|
|
17
|
+
enabled: config.cerebrum.compaction.enabled,
|
|
18
|
+
threshold: config.cerebrum.compaction.threshold,
|
|
19
|
+
keepRecentMessages: config.cerebrum.compaction.keepRecentMessages,
|
|
20
|
+
contextWindow: config.cerebrum.contextWindow,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
const cerebrumConfig = {
|
|
24
|
+
defaultProvider: config.cerebrum.defaultProvider,
|
|
25
|
+
defaultModel: config.cerebrum.defaultModel,
|
|
26
|
+
providers: config.cerebrum.providers,
|
|
27
|
+
maxSteps: config.cerebrum.maxSteps,
|
|
28
|
+
temperature: config.cerebrum.temperature,
|
|
29
|
+
};
|
|
30
|
+
const cerebrum = new CerebrumProvider(cerebrumConfig, {
|
|
31
|
+
denyList: config.tools.shell.denyList,
|
|
32
|
+
timeout: config.tools.shell.timeout,
|
|
33
|
+
maxOutputSize: config.tools.shell.maxOutputSize,
|
|
34
|
+
autoMode: config.tools.shell.autoMode,
|
|
35
|
+
});
|
|
36
|
+
// Set initial auto mode on orchestrator
|
|
37
|
+
orchestrator.setAutoMode(config.tools.shell.autoMode);
|
|
38
|
+
// Bridge CerebrumProvider to Orchestrator's CerebrumAdapter interface
|
|
39
|
+
orchestrator.setCerebrum({
|
|
40
|
+
stream: async (messages, _tools, callbacks) => {
|
|
41
|
+
await cerebrum.stream(messages, callbacks);
|
|
42
|
+
},
|
|
43
|
+
summarize: async (messages) => {
|
|
44
|
+
return cerebrum.summarize(messages);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
// Load and inject skills
|
|
48
|
+
const skillRegistry = new SkillRegistry();
|
|
49
|
+
const skillDirs = [
|
|
50
|
+
...config.skills.directories,
|
|
51
|
+
join(homedir(), '.cereworker', 'skills'),
|
|
52
|
+
join(process.cwd(), 'skills'),
|
|
53
|
+
];
|
|
54
|
+
const allSkills = loadSkills(skillDirs);
|
|
55
|
+
const eligible = filterEligibleSkills(allSkills);
|
|
56
|
+
skillRegistry.registerAll(eligible);
|
|
57
|
+
const skillPrompt = skillRegistry.buildPrompt();
|
|
58
|
+
if (skillPrompt) {
|
|
59
|
+
orchestrator.setSystemContext(skillPrompt);
|
|
60
|
+
log.info('Skills loaded', { count: eligible.length, total: allSkills.length });
|
|
61
|
+
}
|
|
62
|
+
// Register hippocampus (memory) tools
|
|
63
|
+
let hippocampusStore = null;
|
|
64
|
+
if (config.hippocampus.enabled) {
|
|
65
|
+
hippocampusStore = new HippocampusStore(config.hippocampus.directory);
|
|
66
|
+
const memoryTools = createMemoryTools(hippocampusStore);
|
|
67
|
+
orchestrator.registerTool('memory_read', {
|
|
68
|
+
description: 'Read a memory file (MEMORY.md or a daily log like 2026-03-08.md)',
|
|
69
|
+
parameters: {},
|
|
70
|
+
execute: async (args) => memoryTools.executeMemoryRead(args),
|
|
71
|
+
});
|
|
72
|
+
orchestrator.registerTool('memory_write', {
|
|
73
|
+
description: 'Write/update the main MEMORY.md file with curated long-term notes',
|
|
74
|
+
parameters: {},
|
|
75
|
+
execute: async (args) => memoryTools.executeMemoryWrite(args),
|
|
76
|
+
});
|
|
77
|
+
orchestrator.registerTool('memory_log', {
|
|
78
|
+
description: "Append a note to today's daily log",
|
|
79
|
+
parameters: {},
|
|
80
|
+
execute: async (args) => memoryTools.executeMemoryLog(args),
|
|
81
|
+
});
|
|
82
|
+
orchestrator.registerTool('memory_search', {
|
|
83
|
+
description: 'Search across all memory files for a text pattern',
|
|
84
|
+
parameters: {},
|
|
85
|
+
execute: async (args) => memoryTools.executeMemorySearch(args),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Setup fine-tune data provider (Instinct pillar)
|
|
89
|
+
if (config.hippocampus.enabled && config.cerebellum.finetune?.enabled) {
|
|
90
|
+
const curator = new HippocampusCurator(hippocampusStore, { generate: (prompt) => cerebrum.generate(prompt) });
|
|
91
|
+
const scheduleMap = {
|
|
92
|
+
auto: 'when idle',
|
|
93
|
+
hourly: 'every hour',
|
|
94
|
+
daily: 'every day',
|
|
95
|
+
weekly: 'every week',
|
|
96
|
+
};
|
|
97
|
+
const scheduleHint = scheduleMap[config.cerebellum.finetune.schedule] ?? 'when idle';
|
|
98
|
+
orchestrator.setFineTuneDataProvider(async () => {
|
|
99
|
+
await curator.curate();
|
|
100
|
+
const pairs = curator.getPendingPairs();
|
|
101
|
+
if (pairs.length > 0) {
|
|
102
|
+
curator.markConsumed();
|
|
103
|
+
}
|
|
104
|
+
return pairs;
|
|
105
|
+
}, config.cerebellum.finetune.method);
|
|
106
|
+
log.info('Fine-tune data provider configured', { schedule: scheduleHint });
|
|
107
|
+
}
|
|
108
|
+
// Setup sub-agents
|
|
109
|
+
if (config.subAgents.enabled) {
|
|
110
|
+
orchestrator.setupSubAgents({
|
|
111
|
+
maxConcurrent: config.subAgents.maxConcurrent,
|
|
112
|
+
monitorIntervalMs: config.subAgents.monitorIntervalSeconds * 1000,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Register browser tools with orchestrator
|
|
116
|
+
for (const [name, toolDef] of Object.entries(browserToolDefinitions)) {
|
|
117
|
+
orchestrator.registerTool(name, {
|
|
118
|
+
description: toolDef.description,
|
|
119
|
+
parameters: {},
|
|
120
|
+
execute: async (args) => toolDef.execute(args),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// Create channel manager
|
|
124
|
+
const channelManager = createChannelManager(config);
|
|
125
|
+
// Wire channels to orchestrator
|
|
126
|
+
channelManager.setHandler(async (msg) => {
|
|
127
|
+
await orchestrator.sendMessage(msg.text);
|
|
128
|
+
const messages = orchestrator.getMessages();
|
|
129
|
+
const lastMsg = messages[messages.length - 1];
|
|
130
|
+
return lastMsg?.role === 'cerebrum' ? lastMsg.content : undefined;
|
|
131
|
+
});
|
|
132
|
+
orchestrator.start();
|
|
133
|
+
// Track gateway handles for cleanup
|
|
134
|
+
let gatewayServer = null;
|
|
135
|
+
let gatewayClient = null;
|
|
136
|
+
async function startChannels() {
|
|
137
|
+
const channels = channelManager.list();
|
|
138
|
+
if (channels.length > 0) {
|
|
139
|
+
await channelManager.startAll();
|
|
140
|
+
return channelManager.listConnected().length;
|
|
141
|
+
}
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
async function startGateway(callbacks) {
|
|
145
|
+
const mode = config.gateway.mode;
|
|
146
|
+
if (mode === 'gateway') {
|
|
147
|
+
const server = new GatewayServer({
|
|
148
|
+
port: config.gateway.port,
|
|
149
|
+
token: config.gateway.token,
|
|
150
|
+
invokeTimeoutMs: config.gateway.invokeTimeoutMs,
|
|
151
|
+
pingIntervalMs: config.gateway.pingIntervalMs,
|
|
152
|
+
});
|
|
153
|
+
server.setNodeConnectedHandler((nodeId, capabilities) => {
|
|
154
|
+
const proxyTools = createProxyTools(server, nodeId, capabilities);
|
|
155
|
+
orchestrator.registerTools(proxyTools);
|
|
156
|
+
orchestrator.emit({ type: 'node:connected', nodeId, capabilities });
|
|
157
|
+
const nodeCount = server.listNodes().length;
|
|
158
|
+
orchestrator.setGatewayMode('gateway', { connectedNodes: nodeCount });
|
|
159
|
+
callbacks?.onNodeConnected?.(nodeId, nodeCount);
|
|
160
|
+
});
|
|
161
|
+
server.setNodeDisconnectedHandler((nodeId, reason, capabilities) => {
|
|
162
|
+
for (const cap of capabilities) {
|
|
163
|
+
orchestrator.unregisterTool(`${cap}@${nodeId}`);
|
|
164
|
+
}
|
|
165
|
+
orchestrator.emit({ type: 'node:disconnected', nodeId, reason });
|
|
166
|
+
const remainingNodes = server.listNodes().length;
|
|
167
|
+
orchestrator.setGatewayMode('gateway', { connectedNodes: remainingNodes });
|
|
168
|
+
callbacks?.onNodeDisconnected?.(nodeId, remainingNodes);
|
|
169
|
+
});
|
|
170
|
+
orchestrator.setGatewayMode('gateway', { connectedNodes: 0 });
|
|
171
|
+
await server.start();
|
|
172
|
+
gatewayServer = server;
|
|
173
|
+
log.info('Gateway server started', { port: config.gateway.port });
|
|
174
|
+
return { server, client: null };
|
|
175
|
+
}
|
|
176
|
+
if (mode === 'node') {
|
|
177
|
+
if (!config.gateway.gatewayUrl || !config.gateway.nodeId) {
|
|
178
|
+
log.error('Node mode requires gatewayUrl and nodeId in config');
|
|
179
|
+
return { server: null, client: null };
|
|
180
|
+
}
|
|
181
|
+
const client = new GatewayNodeClient({
|
|
182
|
+
gatewayUrl: config.gateway.gatewayUrl,
|
|
183
|
+
nodeId: config.gateway.nodeId,
|
|
184
|
+
token: config.gateway.token ?? '',
|
|
185
|
+
capabilities: config.gateway.capabilities,
|
|
186
|
+
}, async (tool, args) => {
|
|
187
|
+
const toolDef = orchestrator.tools.get(tool);
|
|
188
|
+
if (!toolDef)
|
|
189
|
+
throw new Error(`Unknown tool: ${tool}`);
|
|
190
|
+
return toolDef.execute(args);
|
|
191
|
+
});
|
|
192
|
+
client.setEmergencyStopHandler(() => {
|
|
193
|
+
orchestrator.emergencyStop();
|
|
194
|
+
});
|
|
195
|
+
orchestrator.setGatewayMode('node', { gatewayUrl: config.gateway.gatewayUrl });
|
|
196
|
+
try {
|
|
197
|
+
await client.connect();
|
|
198
|
+
gatewayClient = client;
|
|
199
|
+
log.info('Connected to gateway', { url: config.gateway.gatewayUrl });
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
log.error('Failed to connect to gateway', { error: err.message });
|
|
203
|
+
}
|
|
204
|
+
return { server: null, client };
|
|
205
|
+
}
|
|
206
|
+
// standalone
|
|
207
|
+
return { server: null, client: null };
|
|
208
|
+
}
|
|
209
|
+
async function shutdown() {
|
|
210
|
+
if (gatewayServer) {
|
|
211
|
+
await gatewayServer.stop();
|
|
212
|
+
gatewayServer = null;
|
|
213
|
+
}
|
|
214
|
+
if (gatewayClient) {
|
|
215
|
+
gatewayClient.disconnect();
|
|
216
|
+
gatewayClient = null;
|
|
217
|
+
}
|
|
218
|
+
channelManager.stopAll();
|
|
219
|
+
orchestrator.stop();
|
|
220
|
+
log.info('Service shut down');
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
orchestrator,
|
|
224
|
+
channelManager,
|
|
225
|
+
cerebrum,
|
|
226
|
+
skillRegistry,
|
|
227
|
+
startChannels,
|
|
228
|
+
startGateway,
|
|
229
|
+
shutdown,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cereworker/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.313.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cereworker": "dist/index.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
|
-
"dist"
|
|
9
|
+
"dist",
|
|
10
|
+
"scripts"
|
|
10
11
|
],
|
|
11
12
|
"publishConfig": {
|
|
12
13
|
"access": "public"
|
|
@@ -21,15 +22,15 @@
|
|
|
21
22
|
"ink": "^5.1.0",
|
|
22
23
|
"@inkjs/ui": "^2.0.0",
|
|
23
24
|
"react": "^18.3.1",
|
|
24
|
-
"@cereworker/
|
|
25
|
-
"@cereworker/
|
|
26
|
-
"@cereworker/
|
|
27
|
-
"@cereworker/
|
|
28
|
-
"@cereworker/
|
|
29
|
-
"@cereworker/
|
|
30
|
-
"@cereworker/
|
|
31
|
-
"@cereworker/
|
|
32
|
-
"@cereworker/
|
|
25
|
+
"@cereworker/core": "26.313.1",
|
|
26
|
+
"@cereworker/config": "26.313.1",
|
|
27
|
+
"@cereworker/cerebrum": "26.313.1",
|
|
28
|
+
"@cereworker/skills": "26.313.1",
|
|
29
|
+
"@cereworker/channels": "26.313.1",
|
|
30
|
+
"@cereworker/browser": "26.313.1",
|
|
31
|
+
"@cereworker/hippocampus": "26.313.1",
|
|
32
|
+
"@cereworker/gateway": "26.313.1",
|
|
33
|
+
"@cereworker/cerebellum-client": "26.313.1"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@types/react": "^18.3.0",
|
package/scripts/setup.sh
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# CereWorker setup script
|
|
5
|
+
# Detects OS and installs Docker and/or build tools.
|
|
6
|
+
# Usage: setup.sh [--docker] [--build-tools] [--all]
|
|
7
|
+
|
|
8
|
+
INSTALL_DOCKER=false
|
|
9
|
+
INSTALL_BUILD=false
|
|
10
|
+
|
|
11
|
+
parse_args() {
|
|
12
|
+
if [ $# -eq 0 ]; then
|
|
13
|
+
INSTALL_DOCKER=true
|
|
14
|
+
INSTALL_BUILD=true
|
|
15
|
+
return
|
|
16
|
+
fi
|
|
17
|
+
for arg in "$@"; do
|
|
18
|
+
case "$arg" in
|
|
19
|
+
--docker) INSTALL_DOCKER=true ;;
|
|
20
|
+
--build-tools) INSTALL_BUILD=true ;;
|
|
21
|
+
--all) INSTALL_DOCKER=true; INSTALL_BUILD=true ;;
|
|
22
|
+
-h|--help)
|
|
23
|
+
echo "Usage: setup.sh [--docker] [--build-tools] [--all]"
|
|
24
|
+
echo " --docker Install Docker"
|
|
25
|
+
echo " --build-tools Install native build tools (build-essential, etc.)"
|
|
26
|
+
echo " --all Install everything (default if no flags given)"
|
|
27
|
+
exit 0
|
|
28
|
+
;;
|
|
29
|
+
*) echo "Unknown flag: $arg"; exit 1 ;;
|
|
30
|
+
esac
|
|
31
|
+
done
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# --- OS detection ---
|
|
35
|
+
|
|
36
|
+
OS=""
|
|
37
|
+
DISTRO="unknown"
|
|
38
|
+
|
|
39
|
+
detect_os() {
|
|
40
|
+
case "$(uname -s)" in
|
|
41
|
+
Linux)
|
|
42
|
+
OS="linux"
|
|
43
|
+
if [ -f /etc/os-release ]; then
|
|
44
|
+
# shellcheck disable=SC1091
|
|
45
|
+
. /etc/os-release
|
|
46
|
+
case "$ID" in
|
|
47
|
+
ubuntu|debian|pop|linuxmint|elementary) DISTRO="debian" ;;
|
|
48
|
+
fedora|rhel|centos|rocky|alma|ol) DISTRO="fedora" ;;
|
|
49
|
+
arch|manjaro|endeavouros) DISTRO="arch" ;;
|
|
50
|
+
*) DISTRO="unknown" ;;
|
|
51
|
+
esac
|
|
52
|
+
fi
|
|
53
|
+
;;
|
|
54
|
+
Darwin)
|
|
55
|
+
OS="macos"
|
|
56
|
+
DISTRO="macos"
|
|
57
|
+
;;
|
|
58
|
+
*)
|
|
59
|
+
echo "Unsupported OS: $(uname -s)"
|
|
60
|
+
exit 1
|
|
61
|
+
;;
|
|
62
|
+
esac
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# --- Presence checks ---
|
|
66
|
+
|
|
67
|
+
has_docker() {
|
|
68
|
+
command -v docker >/dev/null 2>&1
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
has_build_tools() {
|
|
72
|
+
case "$OS" in
|
|
73
|
+
linux)
|
|
74
|
+
case "$DISTRO" in
|
|
75
|
+
debian) dpkg -s build-essential >/dev/null 2>&1 ;;
|
|
76
|
+
fedora) rpm -q gcc make >/dev/null 2>&1 ;;
|
|
77
|
+
arch) pacman -Qi base-devel >/dev/null 2>&1 ;;
|
|
78
|
+
*) command -v gcc >/dev/null 2>&1 && command -v make >/dev/null 2>&1 ;;
|
|
79
|
+
esac
|
|
80
|
+
;;
|
|
81
|
+
macos)
|
|
82
|
+
xcode-select -p >/dev/null 2>&1
|
|
83
|
+
;;
|
|
84
|
+
esac
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# --- Helpers ---
|
|
88
|
+
|
|
89
|
+
need_sudo() {
|
|
90
|
+
if [ "$OS" = "linux" ] && [ "$(id -u)" -ne 0 ]; then
|
|
91
|
+
if ! command -v sudo >/dev/null 2>&1; then
|
|
92
|
+
echo "Error: This script requires sudo but it is not installed."
|
|
93
|
+
echo "Run as root or install sudo first."
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
SUDO="sudo"
|
|
97
|
+
else
|
|
98
|
+
SUDO=""
|
|
99
|
+
fi
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# --- Install functions ---
|
|
103
|
+
|
|
104
|
+
install_docker_linux() {
|
|
105
|
+
echo "Installing Docker via get.docker.com..."
|
|
106
|
+
curl -fsSL https://get.docker.com | $SUDO sh
|
|
107
|
+
# Add current user to docker group
|
|
108
|
+
if [ -n "${SUDO_USER:-}" ]; then
|
|
109
|
+
$SUDO usermod -aG docker "$SUDO_USER"
|
|
110
|
+
elif [ "$(id -u)" -ne 0 ]; then
|
|
111
|
+
$SUDO usermod -aG docker "$USER"
|
|
112
|
+
fi
|
|
113
|
+
echo ""
|
|
114
|
+
echo "NOTE: You may need to log out and back in for the docker group to take effect."
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
install_docker_macos() {
|
|
118
|
+
if command -v brew >/dev/null 2>&1; then
|
|
119
|
+
echo "Installing Docker Desktop via Homebrew..."
|
|
120
|
+
brew install --cask docker
|
|
121
|
+
echo "Open Docker Desktop from Applications to finish setup."
|
|
122
|
+
else
|
|
123
|
+
echo "Homebrew not found. Install Docker Desktop manually:"
|
|
124
|
+
echo " https://docs.docker.com/desktop/install/mac-install/"
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
install_build_tools_linux() {
|
|
130
|
+
case "$DISTRO" in
|
|
131
|
+
debian)
|
|
132
|
+
echo "Installing build-essential..."
|
|
133
|
+
$SUDO apt-get update -qq
|
|
134
|
+
$SUDO apt-get install -y build-essential python3
|
|
135
|
+
;;
|
|
136
|
+
fedora)
|
|
137
|
+
echo "Installing Development Tools..."
|
|
138
|
+
$SUDO dnf groupinstall -y "Development Tools"
|
|
139
|
+
$SUDO dnf install -y python3
|
|
140
|
+
;;
|
|
141
|
+
arch)
|
|
142
|
+
echo "Installing base-devel..."
|
|
143
|
+
$SUDO pacman -S --noconfirm --needed base-devel python
|
|
144
|
+
;;
|
|
145
|
+
*)
|
|
146
|
+
echo "Unknown Linux distro. Install gcc, g++, make, and python3 manually."
|
|
147
|
+
return 1
|
|
148
|
+
;;
|
|
149
|
+
esac
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
install_build_tools_macos() {
|
|
153
|
+
echo "Installing Xcode Command Line Tools..."
|
|
154
|
+
xcode-select --install 2>/dev/null || true
|
|
155
|
+
echo "If a dialog appeared, follow the prompts to complete installation."
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# --- Main ---
|
|
159
|
+
|
|
160
|
+
main() {
|
|
161
|
+
parse_args "$@"
|
|
162
|
+
detect_os
|
|
163
|
+
need_sudo
|
|
164
|
+
|
|
165
|
+
echo "CereWorker Setup"
|
|
166
|
+
echo "OS: $OS Distro: $DISTRO"
|
|
167
|
+
echo ""
|
|
168
|
+
|
|
169
|
+
installed=()
|
|
170
|
+
skipped=()
|
|
171
|
+
|
|
172
|
+
# Docker
|
|
173
|
+
if [ "$INSTALL_DOCKER" = true ]; then
|
|
174
|
+
if has_docker; then
|
|
175
|
+
skipped+=("Docker (already installed)")
|
|
176
|
+
else
|
|
177
|
+
case "$OS" in
|
|
178
|
+
linux) install_docker_linux ;;
|
|
179
|
+
macos) install_docker_macos ;;
|
|
180
|
+
esac
|
|
181
|
+
installed+=("Docker")
|
|
182
|
+
fi
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Build tools
|
|
186
|
+
if [ "$INSTALL_BUILD" = true ]; then
|
|
187
|
+
if has_build_tools; then
|
|
188
|
+
skipped+=("Build tools (already installed)")
|
|
189
|
+
else
|
|
190
|
+
case "$OS" in
|
|
191
|
+
linux) install_build_tools_linux ;;
|
|
192
|
+
macos) install_build_tools_macos ;;
|
|
193
|
+
esac
|
|
194
|
+
installed+=("Build tools")
|
|
195
|
+
fi
|
|
196
|
+
fi
|
|
197
|
+
|
|
198
|
+
# Summary
|
|
199
|
+
echo ""
|
|
200
|
+
echo "--- Summary ---"
|
|
201
|
+
if [ ${#installed[@]} -gt 0 ]; then
|
|
202
|
+
echo "Installed: ${installed[*]}"
|
|
203
|
+
fi
|
|
204
|
+
if [ ${#skipped[@]} -gt 0 ]; then
|
|
205
|
+
echo "Skipped: ${skipped[*]}"
|
|
206
|
+
fi
|
|
207
|
+
if [ ${#installed[@]} -eq 0 ] && [ ${#skipped[@]} -eq 0 ]; then
|
|
208
|
+
echo "Nothing to do."
|
|
209
|
+
fi
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
main "$@"
|