@nomad-e/bluma-cli 0.1.84 → 0.3.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.
@@ -0,0 +1,38 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ /** Resultado da leitura de imagem do clipboard */
7
+ export interface ClipboardImageResult {
8
+ /** Caminho para o ficheiro temporário com a imagem */
9
+ path: string
10
+ /** Largura da imagem em pixels */
11
+ width: number
12
+ /** Altura da imagem em pixels */
13
+ height: number
14
+ /** Formato da imagem (PNG, JPEG, etc.) */
15
+ format: string
16
+ }
17
+ /** Erro ao ler imagem do clipboard */
18
+ export const enum ClipboardError {
19
+ /** Clipboard não disponível */
20
+ Unavailable = 0,
21
+ /** Nenhuma imagem no clipboard */
22
+ NoImage = 1,
23
+ /** Erro ao codificar imagem */
24
+ EncodeFailed = 2,
25
+ /** Erro de I/O */
26
+ IoError = 3
27
+ }
28
+ /**
29
+ * Lê uma imagem do clipboard e guarda-a num ficheiro temporário PNG.
30
+ * Retorna o caminho do ficheiro e informações sobre a imagem.
31
+ */
32
+ export declare function readClipboardImage(): ClipboardImageResult
33
+ /** Verifica se há uma imagem disponível no clipboard */
34
+ export declare function hasClipboardImage(): boolean
35
+ /** Lê texto do clipboard */
36
+ export declare function readClipboardText(): string
37
+ /** Escreve texto para o clipboard */
38
+ export declare function writeClipboardText(text: string): void
@@ -0,0 +1,319 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /* prettier-ignore */
4
+
5
+ /* auto-generated by NAPI-RS */
6
+
7
+ const { existsSync, readFileSync } = require('fs')
8
+ const { join } = require('path')
9
+
10
+ const { platform, arch } = process
11
+
12
+ let nativeBinding = null
13
+ let localFileExisted = false
14
+ let loadError = null
15
+
16
+ function isMusl() {
17
+ // For Node 10
18
+ if (!process.report || typeof process.report.getReport !== 'function') {
19
+ try {
20
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
+ return readFileSync(lddPath, 'utf8').includes('musl')
22
+ } catch (e) {
23
+ return true
24
+ }
25
+ } else {
26
+ const { glibcVersionRuntime } = process.report.getReport().header
27
+ return !glibcVersionRuntime
28
+ }
29
+ }
30
+
31
+ switch (platform) {
32
+ case 'android':
33
+ switch (arch) {
34
+ case 'arm64':
35
+ localFileExisted = existsSync(join(__dirname, 'bluma-clipboard.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./bluma-clipboard.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('@nomad-e/bluma-clipboard-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'bluma-clipboard.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./bluma-clipboard.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('@nomad-e/bluma-clipboard-android-arm-eabi')
53
+ }
54
+ } catch (e) {
55
+ loadError = e
56
+ }
57
+ break
58
+ default:
59
+ throw new Error(`Unsupported architecture on Android ${arch}`)
60
+ }
61
+ break
62
+ case 'win32':
63
+ switch (arch) {
64
+ case 'x64':
65
+ localFileExisted = existsSync(
66
+ join(__dirname, 'bluma-clipboard.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./bluma-clipboard.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('@nomad-e/bluma-clipboard-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'bluma-clipboard.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./bluma-clipboard.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('@nomad-e/bluma-clipboard-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'bluma-clipboard.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./bluma-clipboard.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('@nomad-e/bluma-clipboard-win32-arm64-msvc')
101
+ }
102
+ } catch (e) {
103
+ loadError = e
104
+ }
105
+ break
106
+ default:
107
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
+ }
109
+ break
110
+ case 'darwin':
111
+ localFileExisted = existsSync(join(__dirname, 'bluma-clipboard.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./bluma-clipboard.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('@nomad-e/bluma-clipboard-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'bluma-clipboard.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./bluma-clipboard.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('@nomad-e/bluma-clipboard-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'bluma-clipboard.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./bluma-clipboard.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('@nomad-e/bluma-clipboard-darwin-arm64')
142
+ }
143
+ } catch (e) {
144
+ loadError = e
145
+ }
146
+ break
147
+ default:
148
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
+ }
150
+ break
151
+ case 'freebsd':
152
+ if (arch !== 'x64') {
153
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
+ }
155
+ localFileExisted = existsSync(join(__dirname, 'bluma-clipboard.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./bluma-clipboard.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('@nomad-e/bluma-clipboard-freebsd-x64')
161
+ }
162
+ } catch (e) {
163
+ loadError = e
164
+ }
165
+ break
166
+ case 'linux':
167
+ switch (arch) {
168
+ case 'x64':
169
+ if (isMusl()) {
170
+ localFileExisted = existsSync(
171
+ join(__dirname, 'bluma-clipboard.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./bluma-clipboard.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'bluma-clipboard.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./bluma-clipboard.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-x64-gnu')
191
+ }
192
+ } catch (e) {
193
+ loadError = e
194
+ }
195
+ }
196
+ break
197
+ case 'arm64':
198
+ if (isMusl()) {
199
+ localFileExisted = existsSync(
200
+ join(__dirname, 'bluma-clipboard.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./bluma-clipboard.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'bluma-clipboard.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./bluma-clipboard.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-arm64-gnu')
220
+ }
221
+ } catch (e) {
222
+ loadError = e
223
+ }
224
+ }
225
+ break
226
+ case 'arm':
227
+ if (isMusl()) {
228
+ localFileExisted = existsSync(
229
+ join(__dirname, 'bluma-clipboard.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./bluma-clipboard.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'bluma-clipboard.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./bluma-clipboard.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-arm-gnueabihf')
249
+ }
250
+ } catch (e) {
251
+ loadError = e
252
+ }
253
+ }
254
+ break
255
+ case 'riscv64':
256
+ if (isMusl()) {
257
+ localFileExisted = existsSync(
258
+ join(__dirname, 'bluma-clipboard.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./bluma-clipboard.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'bluma-clipboard.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./bluma-clipboard.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'bluma-clipboard.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./bluma-clipboard.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('@nomad-e/bluma-clipboard-linux-s390x-gnu')
293
+ }
294
+ } catch (e) {
295
+ loadError = e
296
+ }
297
+ break
298
+ default:
299
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
300
+ }
301
+ break
302
+ default:
303
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
304
+ }
305
+
306
+ if (!nativeBinding) {
307
+ if (loadError) {
308
+ throw loadError
309
+ }
310
+ throw new Error(`Failed to load native binding`)
311
+ }
312
+
313
+ const { ClipboardError, readClipboardImage, hasClipboardImage, readClipboardText, writeClipboardText } = nativeBinding
314
+
315
+ module.exports.ClipboardError = ClipboardError
316
+ module.exports.readClipboardImage = readClipboardImage
317
+ module.exports.hasClipboardImage = hasClipboardImage
318
+ module.exports.readClipboardText = readClipboardText
319
+ module.exports.writeClipboardText = writeClipboardText
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@nomad-e/bluma-clipboard",
3
+ "version": "0.1.0",
4
+ "description": "Native clipboard support for BluMa CLI using arboard",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "napi": {
8
+ "name": "bluma-clipboard",
9
+ "triples": {
10
+ "additional": [
11
+ "aarch64-apple-darwin",
12
+ "aarch64-linux-android",
13
+ "aarch64-unknown-linux-gnu",
14
+ "aarch64-unknown-linux-musl",
15
+ "aarch64-pc-windows-msvc",
16
+ "armv7-linux-androideabi",
17
+ "armv7-unknown-linux-gnueabihf",
18
+ "x86_64-unknown-linux-musl",
19
+ "x86_64-unknown-freebsd"
20
+ ]
21
+ }
22
+ },
23
+ "license": "Apache-2.0",
24
+ "devDependencies": {
25
+ "@napi-rs/cli": "^2.18.4"
26
+ },
27
+ "engines": {
28
+ "node": ">= 20"
29
+ },
30
+ "scripts": {
31
+ "artifacts": "napi artifacts",
32
+ "build": "napi build --platform --release",
33
+ "build:debug": "napi build --platform",
34
+ "prepublishOnly": "napi prepublish -t npm",
35
+ "universal": "napi universal",
36
+ "version": "napi version"
37
+ }
38
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Paleta BluMa — magenta #FF70FE, ciano #53B2D2, laranja (#d77757).
3
+ * Chaves semânticas (`accent`, `suggestion`, …) mantêm compat com o resto da UI.
4
+ */
5
+ export const BLUMA_TERMINAL = {
6
+ /** Tríade principal (marca) */
7
+ magenta: "#FF70FE",
8
+ blue: "#53B2D2",
9
+ /** Laranja (darkTheme) */
10
+ orange: "#d77757",
11
+ accent: "#d77757",
12
+ accentShimmer: "#eb9f7f",
13
+ /** UI estrutural, links, secções — ciano */
14
+ permission: "#53B2D2",
15
+ permissionShimmer: "#7ecce3",
16
+ promptBorder: "#53B2D2",
17
+ promptBorderShimmer: "#8fd4e8",
18
+ suggestion: "#53B2D2",
19
+ panelBorder: "#53B2D2",
20
+ link: "#53B2D2",
21
+ codeLabel: "#53B2D2",
22
+ heading1: "#53B2D2",
23
+ heading2: "#53B2D2",
24
+ m3Outline: "#53B2D2",
25
+ m3Rail: "#53B2D2",
26
+ /** Ferramentas, bullets fortes — magenta */
27
+ toolLabel: "#FF70FE",
28
+ headingDeep: "#FF70FE",
29
+ listBullet: "#FF70FE",
30
+ listBulletSub: "#53B2D2",
31
+ m3TonalOutline: "#FF70FE",
32
+ merged: "#d896ff",
33
+ subtle: "#505050",
34
+ inactive: "#999999",
35
+ text: "#ffffff",
36
+ success: "#4eba65",
37
+ err: "#ff6b80",
38
+ warn: "#ffc107",
39
+ diffAdded: "#225a2b",
40
+ diffRemoved: "#7a2936",
41
+ diffAddedWord: "#38a660",
42
+ diffRemovedWord: "#b3596b",
43
+ brandBlue: "#53B2D2",
44
+ brandMagenta: "#FF70FE",
45
+ /**
46
+ * Rampa neutra para shimmer no texto “a trabalhar”.
47
+ * O texto base fica branco e o brilho entra em cinzas suaves.
48
+ */
49
+ workingShimmerRamp: [
50
+ "#6b6b6b", // cinza base
51
+ "#7b7b7b", // cinza base+
52
+ "#8f8f8f", // cinza médio
53
+ "#a8a8a8", // cinza claro
54
+ "#e6e6e6", // brilho máximo
55
+ "#a8a8a8", // cinza claro
56
+ "#8f8f8f", // cinza médio
57
+ "#7b7b7b", // cinza base+
58
+ ],
59
+ muted: "#999999",
60
+ dim: "#999999",
61
+ code: "#999999",
62
+ linkUnderline: true,
63
+ toolMeta: "#999999",
64
+ rule: "#505050",
65
+ m3Label: "#999999",
66
+ m3OnSurface: "#ffffff",
67
+ // Material Design 3 surface colors
68
+ surface: "#1E1E1E",
69
+ surfaceVariant: "#2D2D2D",
70
+ surfaceContainer: "#333333",
71
+ onSurfaceVariant: "#B0B0B0",
72
+ outline: "#909090",
73
+ outlineVariant: "#707070",
74
+ // Cores semânticas adicionais para compatibilidade
75
+ primary: "#7C4DFF",
76
+ primaryVariant: "#6C3DCC",
77
+ onPrimary: "#FFFFFF",
78
+ warning: "#ffc107",
79
+ };
@@ -0,0 +1,68 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Layout chat — MessageResponse: indentação suave (RESULT_LINE_GUTTER) + conteúdo.
4
+ * Contexto evita repetir o gutter quando há MessageResponse aninhados.
5
+ */
6
+ import { createContext, useContext } from "react";
7
+ import { Box, Text } from "ink";
8
+ import { BLUMA_TERMINAL as T } from "./blumaTerminal.js";
9
+ import { RESULT_LINE_GUTTER } from "../constants/toolUiSymbols.js";
10
+ import { formatTurnDurationMs } from "../utils/formatTurnDurationMs.js";
11
+ export { formatTurnDurationMs };
12
+ const MessageResponseNestedContext = createContext(false);
13
+ export function MessageResponse({ children, height, }) {
14
+ const nested = useContext(MessageResponseNestedContext);
15
+ if (nested) {
16
+ return _jsx(_Fragment, { children: children });
17
+ }
18
+ return (_jsx(MessageResponseNestedContext.Provider, { value: true, children: _jsxs(Box, { flexDirection: "row", alignItems: "flex-start", height: height, overflow: height !== undefined ? "hidden" : undefined, children: [_jsx(Text, { dimColor: true, children: RESULT_LINE_GUTTER }), _jsx(Box, { flexShrink: 1, flexGrow: 1, flexDirection: "column", children: children })] }) }));
19
+ }
20
+ export function ChatBlock({ children, marginBottom = 1, }) {
21
+ return (_jsx(Box, { flexDirection: "column", marginBottom: marginBottom, children: children }));
22
+ }
23
+ export function ChatUserImageBlock({ imageCount, caption, captionDim = false, }) {
24
+ if (imageCount < 1)
25
+ return null;
26
+ const cap = caption?.trim() ?? "";
27
+ const capLines = cap.length > 0 ? cap.split("\n") : [];
28
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 0, children: [Array.from({ length: imageCount }, (_, i) => (_jsx(Text, { bold: true, color: T.orange, children: `[IMAGE #${i + 1}]` }, `img-${i}`))), capLines.map((line, i) => (_jsxs(Box, { flexDirection: "row", flexWrap: "wrap", children: [_jsx(Text, { dimColor: true, children: i === 0 ? "└─ " : " " }), captionDim ? (_jsx(Text, { dimColor: true, bold: true, wrap: "wrap", children: line })) : (_jsx(Text, { color: T.m3OnSurface, bold: true, wrap: "wrap", children: line }))] }, `cap-${i}`)))] }));
29
+ }
30
+ /** @deprecated usar ChatUserImageBlock */
31
+ export function ChatUserImageTree({ count }) {
32
+ return _jsx(ChatUserImageBlock, { imageCount: count });
33
+ }
34
+ /** Mensagem do utilizador: moldura só topo/fundo (como o InputPrompt), sem `>`. */
35
+ export function ChatUserMessage({ children }) {
36
+ return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: T.m3OnSurface, borderLeft: false, borderRight: false, paddingX: 1, children: children }) }));
37
+ }
38
+ export function ChatMeta({ children }) {
39
+ return (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: children }) }));
40
+ }
41
+ export function ChatStatusRow({ children }) {
42
+ return (_jsxs(Box, { flexDirection: "row", marginBottom: 1, flexWrap: "wrap", children: [_jsxs(Text, { color: T.orange, bold: true, children: ["*", " "] }), children] }));
43
+ }
44
+ export function ChatTurnDuration({ durationMs }) {
45
+ return (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { dimColor: true, children: [_jsx(Text, { color: T.blue, children: "\u00B7 " }), _jsx(Text, { color: T.magenta, children: formatTurnDurationMs(durationMs) })] }) }));
46
+ }
47
+ export function Divider({ width, title, color, }) {
48
+ const w = width ?? 60;
49
+ const char = "─";
50
+ if (title) {
51
+ const titleWidth = title.length + 2;
52
+ const sideWidth = Math.max(0, w - titleWidth);
53
+ const leftWidth = Math.floor(sideWidth / 2);
54
+ const rightWidth = sideWidth - leftWidth;
55
+ return (_jsxs(Text, { color: color, dimColor: !color, children: [char.repeat(leftWidth), " ", _jsx(Text, { dimColor: true, children: title }), " ", char.repeat(rightWidth)] }));
56
+ }
57
+ return _jsx(Text, { color: color, dimColor: !color, children: char.repeat(w) });
58
+ }
59
+ export function M3Surface({ children, marginBottom = 1, }) {
60
+ return _jsx(ChatBlock, { marginBottom: marginBottom, children: children });
61
+ }
62
+ export const M3UserBubble = ChatUserMessage;
63
+ export const M3SystemRow = ChatMeta;
64
+ export const M3InputDock = ({ children }) => (_jsx(Box, { flexDirection: "column", marginTop: 1, children: children }));
65
+ export const M3StatusStrip = ChatStatusRow;
66
+ export function TerminalRule({ width = 48 }) {
67
+ return _jsx(Text, { dimColor: true, children: "─".repeat(Math.max(8, width)) });
68
+ }
@@ -0,0 +1,16 @@
1
+ /** E.g. 211s → `3min · 31s`; under 60s → `45s` or `9.3s` if under 10s. */
2
+ export function formatTurnDurationMs(ms) {
3
+ if (ms < 0) {
4
+ return "0s";
5
+ }
6
+ const secTotal = Math.round(ms / 1000);
7
+ if (secTotal < 60) {
8
+ if (ms < 10_000) {
9
+ return `${(ms / 1000).toFixed(1)}s`;
10
+ }
11
+ return `${secTotal}s`;
12
+ }
13
+ const min = Math.floor(secTotal / 60);
14
+ const sec = secTotal % 60;
15
+ return `${min}min · ${sec}s`;
16
+ }