zelari-code 0.7.5 → 0.7.9
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 +27 -1
- package/dist/cli/app.js +50 -18
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/components/Sidebar.js +86 -39
- package/dist/cli/components/Sidebar.js.map +1 -1
- package/dist/cli/components/SplashScreen.js +204 -0
- package/dist/cli/components/SplashScreen.js.map +1 -0
- package/dist/cli/components/StatusBar.js +22 -18
- package/dist/cli/components/StatusBar.js.map +1 -1
- package/dist/cli/councilConfig.js +38 -0
- package/dist/cli/councilConfig.js.map +1 -0
- package/dist/cli/councilDispatcher.js +38 -32
- package/dist/cli/councilDispatcher.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +80 -61
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/hooks/useExecutionTimer.js +25 -0
- package/dist/cli/hooks/useExecutionTimer.js.map +1 -0
- package/dist/cli/hooks/useGitChanges.js +142 -0
- package/dist/cli/hooks/useGitChanges.js.map +1 -0
- package/dist/cli/hooks/useSlashDispatch.js +9 -2
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
- package/dist/cli/main.bundled.js +2560 -1231
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +9 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/mcpClient.js +14 -6
- package/dist/cli/mcp/mcpClient.js.map +1 -1
- package/dist/cli/updater.js +8 -5
- package/dist/cli/updater.js.map +1 -1
- package/dist/cli/utils/cmdline.js +26 -0
- package/dist/cli/utils/cmdline.js.map +1 -0
- package/dist/cli/utils/paths.js +20 -0
- package/dist/cli/utils/paths.js.map +1 -0
- package/dist/cli/wizard/index.js +1 -1
- package/dist/cli/wizard/index.js.map +1 -1
- package/dist/cli/workspace/completeDesign.js +128 -0
- package/dist/cli/workspace/completeDesign.js.map +1 -0
- package/dist/cli/workspace/planDetect.js +17 -0
- package/dist/cli/workspace/planDetect.js.map +1 -0
- package/dist/cli/workspace/postCouncilHook.js +157 -20
- package/dist/cli/workspace/postCouncilHook.js.map +1 -1
- package/dist/cli/workspace/stubs.js +406 -225
- package/dist/cli/workspace/stubs.js.map +1 -1
- package/package.json +71 -71
package/README.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Zelari Code
|
|
2
2
|
|
|
3
|
+
```
|
|
4
|
+
-#%=
|
|
5
|
+
.*%%%@#:
|
|
6
|
+
=%%%%%%%@*
|
|
7
|
+
+%%%%%%%%%%#.
|
|
8
|
+
+%%%@@@@@@@%@#.
|
|
9
|
+
.*%@@@@@@@@@@@@@%-
|
|
10
|
+
.#%@@@@@@@@@@@@@@@@-
|
|
11
|
+
*%@@@@@@@@@@@@@@@@@%.
|
|
12
|
+
:@%%@@@@@@%:+%@@@@@%@=
|
|
13
|
+
=@%%@@@@@%.=-+%@%%@*
|
|
14
|
+
.=@@%@@@@%.*@*-+@@*.
|
|
15
|
+
-*%@@@@@@@@%.*@@@+:#@@#=.
|
|
16
|
+
*%%%%%%@@@@@@.*#%#=-:+@@@%
|
|
17
|
+
:@%%%%%%@@@@@@.:=.*:*@@@@@@=
|
|
18
|
+
*@%%@%%@@@@@@@*%@*:-:%@@@@@%.
|
|
19
|
+
:@@@%@@@@@@@@@@@@@@#%@@@@@@@@=
|
|
20
|
+
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
|
|
21
|
+
|
|
22
|
+
Z E L A R I C O D E
|
|
23
|
+
N-THEM Studio
|
|
24
|
+
```
|
|
25
|
+
|
|
3
26
|
> AI Council coding agent CLI — multi-agent orchestration with slash commands, provider-agnostic LLM streaming, and self-update.
|
|
4
27
|
|
|
5
28
|

|
|
@@ -143,7 +166,10 @@ Disable auto-check: `ZELARI_DEV=1 zelari-code`
|
|
|
143
166
|
## Features
|
|
144
167
|
|
|
145
168
|
- 🤖 **Multi-agent council** — 6 roles (Caronte, Nettuno, Gerione, Plutone, Minosse, Lucifero) with feedback loops and member promotion
|
|
146
|
-
-
|
|
169
|
+
- ⇧⇥ **Agent/council mode switch** — `shift+tab` toggles free-form prompts between the single agent and the full council pipeline (mode shown in the status line)
|
|
170
|
+
- 🎨 **Rich TUI** — Ink + React: native-scrollback chat stream, input bar with status line below it (mode · provider · model · session · cwd · execution timer)
|
|
171
|
+
- 🗂️ **Live git sidebar** — right-hand panel with the N-THEM emblem and the working-tree changes (`+added`/`-removed` per file, refreshed every 4s; auto-hidden on narrow terminals)
|
|
172
|
+
- ⏱️ **Execution timer** — elapsed time of the in-flight turn in the status line (`⏱ 12s`), frozen as `last 34s` when the run completes
|
|
147
173
|
- 🧠 **Provider-agnostic** — OpenAI-compatible APIs (OpenAI, Together, Groq, custom), xAI Grok with OAuth refresh, GLM/Z.AI
|
|
148
174
|
- 🛠️ **Built-in tools** — filesystem (read/write/edit), shell (bash), search (grep), git operations
|
|
149
175
|
- 📚 **7 coding skills** — refactoring, testing, debugging, review, planning, docs, git-ops
|
package/dist/cli/app.js
CHANGED
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
// hook signatures and remove this annotation. The split is documented in
|
|
4
4
|
// `docs/plans/2026-07-01-app-split.md`.
|
|
5
5
|
import React, { useState, useMemo, useCallback } from 'react';
|
|
6
|
-
import { Box, Static } from 'ink';
|
|
6
|
+
import { Box, Static, useInput, useStdin } from 'ink';
|
|
7
7
|
import { InputBar } from './components/InputBar.js';
|
|
8
8
|
import { LiveRegion } from './components/LiveRegion.js';
|
|
9
9
|
import { StatusBar } from './components/StatusBar.js';
|
|
10
|
+
import { Sidebar, shouldShowSidebar } from './components/Sidebar.js';
|
|
10
11
|
import { renderMessage } from './components/ChatStream.js';
|
|
11
|
-
import { formatSkillList } from './slashCommands.js';
|
|
12
12
|
import { listCodingSkills } from '@zelari/core/skills';
|
|
13
|
+
import { useGitChanges } from './hooks/useGitChanges.js';
|
|
14
|
+
import { useExecutionTimer } from './hooks/useExecutionTimer.js';
|
|
15
|
+
import { shortenCwd } from './utils/paths.js';
|
|
13
16
|
import '@zelari/core/skills/builtin/debugging';
|
|
14
17
|
import '@zelari/core/skills/builtin/docs';
|
|
15
18
|
import '@zelari/core/skills/builtin/git-ops';
|
|
@@ -19,6 +22,7 @@ import '@zelari/core/skills/builtin/review';
|
|
|
19
22
|
import '@zelari/core/skills/builtin/testing';
|
|
20
23
|
import { getProviderConfig, getActiveProvider as getActiveProviderSpec, } from './providerConfig.js';
|
|
21
24
|
import { SessionJsonlWriter } from '@zelari/core/harness';
|
|
25
|
+
import { VERSION } from './main.js';
|
|
22
26
|
import { useSession } from './hooks/useSession.js';
|
|
23
27
|
import { useChatTurn } from './hooks/useChatTurn.js';
|
|
24
28
|
import { useSlashDispatch } from './hooks/useSlashDispatch.js';
|
|
@@ -60,10 +64,26 @@ export function App() {
|
|
|
60
64
|
// printed" index so the ANSI-cleared scrollback stays in sync). Also bumped
|
|
61
65
|
// implicitly by a sessionId change (/new).
|
|
62
66
|
const [clearEpoch, setClearEpoch] = useState(0);
|
|
67
|
+
// v0.7.9: dispatch mode for free-form prompts — 'agent' (single harness
|
|
68
|
+
// turn) or 'council' (6-member pipeline). Toggled with shift+tab.
|
|
69
|
+
const [mode, setMode] = useState('agent');
|
|
63
70
|
const activeProviderSpec = getActiveProviderSpec();
|
|
64
71
|
const activeModel = providerConfig.modelByProvider[activeProviderSpec.id];
|
|
65
72
|
const session = useSession();
|
|
66
73
|
const size = useTerminalSize();
|
|
74
|
+
const gitChanges = useGitChanges();
|
|
75
|
+
const cwd = useMemo(() => shortenCwd(process.cwd(), 32), []);
|
|
76
|
+
// v0.7.9: execution timer — elapsed time of the in-flight turn (shown in
|
|
77
|
+
// the StatusBar as `⏱ 12s`, then frozen as `last 34s` when the run ends).
|
|
78
|
+
const timer = useExecutionTimer(busy);
|
|
79
|
+
// shift+tab → toggle agent/council. ink-text-input ignores tab keys, so
|
|
80
|
+
// this never fights the InputBar. Guarded: useInput needs raw mode.
|
|
81
|
+
const { isRawModeSupported } = useStdin();
|
|
82
|
+
useInput((_input, key) => {
|
|
83
|
+
if (key.tab && key.shift) {
|
|
84
|
+
setMode((m) => (m === 'agent' ? 'council' : 'agent'));
|
|
85
|
+
}
|
|
86
|
+
}, { isActive: isRawModeSupported === true });
|
|
67
87
|
// Throttle layer for the `live` region — coalesces per-token streaming
|
|
68
88
|
// updates (~50-200/sec) into ≤60 renders/sec. The finalized array uses the
|
|
69
89
|
// raw setter (its appends are rare and user-facing).
|
|
@@ -114,38 +134,50 @@ export function App() {
|
|
|
114
134
|
setQueueCount: chatTurn.setQueueCount,
|
|
115
135
|
dispatchPrompt: chatTurn.dispatchPrompt,
|
|
116
136
|
dispatchCouncilPrompt: chatTurn.dispatchCouncilPrompt,
|
|
137
|
+
mode,
|
|
117
138
|
onNewSession,
|
|
118
139
|
onExit,
|
|
119
140
|
onClear,
|
|
120
141
|
});
|
|
121
|
-
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
// what's available without the 40-col Sidebar (which can't coexist with
|
|
125
|
-
// native scrollback — a fixed right column would be printed into every
|
|
126
|
-
// scrollback line).
|
|
142
|
+
// The one-shot banner: printed once as the first Static item. v0.7.9: the
|
|
143
|
+
// skill list is gone (it doubled the banner height and duplicated /help);
|
|
144
|
+
// the banner is now just the wordmark line + cwd + a hint.
|
|
127
145
|
const banner = useMemo(() => {
|
|
128
|
-
const skillList = formatSkillList(skills);
|
|
129
146
|
return {
|
|
130
147
|
id: 'banner-once',
|
|
131
148
|
role: 'system',
|
|
132
149
|
ts: 0,
|
|
133
|
-
content: `zelari-code
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
content: `zelari-code v${VERSION} — ${activeProviderSpec.id}/${activeModel}\n` +
|
|
151
|
+
`cwd: ${cwd}\n` +
|
|
152
|
+
`/help for commands · /skill <name> · shift+tab toggles agent/council`,
|
|
136
153
|
};
|
|
137
|
-
}, [
|
|
154
|
+
}, [activeProviderSpec.id, activeModel, cwd]);
|
|
138
155
|
// The Static feed: banner first, then finalized messages. `key` lets /clear
|
|
139
156
|
// remount Static so its internal "already printed" index resets. clearEpoch
|
|
140
157
|
// is composed in so /clear forces a remount even within the same session.
|
|
158
|
+
//
|
|
159
|
+
// v0.7.9 duplicate-banner fix: before the session bootstraps, sessionId is
|
|
160
|
+
// '' — the first Static mount would print the banner, then the bootstrap
|
|
161
|
+
// sessionId change would remount Static (new key) and print it AGAIN into
|
|
162
|
+
// scrollback. Feed Static nothing until the session id exists, so the
|
|
163
|
+
// banner prints exactly once, after bootstrap.
|
|
141
164
|
const staticKey = `${session.sessionId || 'pre-bootstrap'}-${clearEpoch}`;
|
|
142
|
-
const staticItems =
|
|
165
|
+
const staticItems = session.sessionId
|
|
166
|
+
? [banner, ...session.messages]
|
|
167
|
+
: [];
|
|
168
|
+
// v0.7.9: right Sidebar (logo + git changes). It lives in the dynamic
|
|
169
|
+
// region — a full-height column can't coexist with the native-scrollback
|
|
170
|
+
// <Static> model — so it docks beside the live/status/input block. Hidden
|
|
171
|
+
// on narrow/short terminals to keep the dynamic region under one screen.
|
|
172
|
+
const showSidebar = shouldShowSidebar(size.columns, size.rows);
|
|
143
173
|
return (React.createElement(React.Fragment, null,
|
|
144
174
|
React.createElement(Static, { key: staticKey, items: staticItems }, (item) => renderMessage(item)),
|
|
145
|
-
React.createElement(Box, { flexDirection: "
|
|
146
|
-
React.createElement(
|
|
147
|
-
|
|
148
|
-
|
|
175
|
+
React.createElement(Box, { flexDirection: "row" },
|
|
176
|
+
React.createElement(Box, { flexDirection: "column", flexGrow: 1, paddingX: 1 },
|
|
177
|
+
React.createElement(LiveRegion, { live: session.live, busy: busy }),
|
|
178
|
+
React.createElement(InputBar, { value: input, onChange: setInput, onSubmit: handleSubmit, disabled: busy }),
|
|
179
|
+
React.createElement(StatusBar, { model: activeModel, provider: activeProviderSpec.id, sessionId: session.sessionId ? session.sessionId.slice(0, 8) : '...', sessionActive: session.sessionActive, queueCount: chatTurn.queueCount, busy: busy, mode: mode, cwd: cwd, elapsedMs: timer.elapsedMs, lastMs: timer.lastMs })),
|
|
180
|
+
showSidebar && (React.createElement(Sidebar, { version: VERSION, changes: gitChanges, rows: size.rows })))));
|
|
149
181
|
}
|
|
150
182
|
// Re-export so legacy imports keep working (Task v0.4.2 audit split).
|
|
151
183
|
// New code should import directly from src/cli/hooks/* instead.
|
package/dist/cli/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/cli/app.tsx"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,+EAA+E;AAC/E,yEAAyE;AACzE,wCAAwC;AACxC,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAU,MAAM,OAAO,CAAC;AACtE,OAAO,EAAE,GAAG,EAAQ,MAAM,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/cli/app.tsx"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,+EAA+E;AAC/E,yEAAyE;AACzE,wCAAwC;AACxC,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAU,MAAM,OAAO,CAAC;AACtE,OAAO,EAAE,GAAG,EAAQ,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAiB,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAoB,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,uCAAuC,CAAC;AAC/C,OAAO,kCAAkC,CAAC;AAC1C,OAAO,qCAAqC,CAAC;AAC7C,OAAO,sCAAsC,CAAC;AAC9C,OAAO,yCAAyC,CAAC;AACjD,OAAO,oCAAoC,CAAC;AAC5C,OAAO,qCAAqC,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,iBAAiB,IAAI,qBAAqB,GAC3C,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAG7D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,QAAQ,CAAC;AACnD,MAAM,QAAQ,GAAG,mBAAmB,CAAC;AAErC;;;GAGG;AACH,MAAM,gBAAgB,GAA2B;IAC/C,mBAAmB,EAAE,QAAQ;IAC7B,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,qBAAqB;IAChC,KAAK,EAAE,SAAS;CACjB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,GAAG;IACjB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAChF,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;IACtF,2EAA2E;IAC3E,4EAA4E;IAC5E,2CAA2C;IAC3C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChD,wEAAwE;IACxE,kEAAkE;IAClE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAW,OAAO,CAAC,CAAC;IAEpD,MAAM,kBAAkB,GAAG,qBAAqB,EAAE,CAAC;IACnD,MAAM,WAAW,GAAG,cAAc,CAAC,eAAe,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAE1E,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7D,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAEtC,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,EAAE,kBAAkB,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC1C,QAAQ,CACN,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACd,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,EACD,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,EAAE,CAC1C,CAAC;IAEF,uEAAuE;IACvE,2EAA2E;IAC3E,qDAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,kBAAkB,CACjE,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,OAAO,CAChB,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAAC;QAC3B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,eAAe,EAAE,UAAU;QAC3B,cAAc,EAAE,SAAS;QACzB,OAAO;QACP,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,eAAe;QACf,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IAEH,sEAAsE;IACtE,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,EAAU,EAAE,EAAE;QAC9C,KAAK,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACxC,OAAO,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAExB,wEAAwE;IACxE,wDAAwD;IACxD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,KAAK,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACxC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAExB,uEAAuE;IACvE,yEAAyE;IACzE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,OAAO,CAAC,eAAe,EAAE,CAAC;QAC1B,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,YAAY,GAAG,gBAAgB,CAAC;QACpC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,EAAE,EAAE,EAAE,CAAC;QAC7C,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,QAAQ;QACR,OAAO;QACP,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,iBAAiB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAA4B,CAAC;QAC3E,kBAAkB;QAClB,WAAW;QACX,gBAAgB;QAChB,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,cAAc,EAAE,QAAQ,CAAC,cAAc;QACvC,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB;QACrD,IAAI;QACJ,YAAY;QACZ,MAAM;QACN,OAAO;KACR,CAAC,CAAC;IAEH,0EAA0E;IAC1E,0EAA0E;IAC1E,2DAA2D;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAc,GAAG,EAAE;QACvC,OAAO;YACL,EAAE,EAAE,aAAa;YACjB,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,CAAC;YACL,OAAO,EACL,gBAAgB,OAAO,MAAM,kBAAkB,CAAC,EAAE,IAAI,WAAW,IAAI;gBACrE,QAAQ,GAAG,IAAI;gBACf,sEAAsE;SACzE,CAAC;IACJ,CAAC,EAAE,CAAC,kBAAkB,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;IAE9C,4EAA4E;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,EAAE;IACF,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,+CAA+C;IAC/C,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,SAAS,IAAI,eAAe,IAAI,UAAU,EAAE,CAAC;IAC1E,MAAM,WAAW,GAA2B,OAAO,CAAC,SAAS;QAC3D,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC/B,CAAC,CAAC,EAAE,CAAC;IAEP,sEAAsE;IACtE,yEAAyE;IACzE,0EAA0E;IAC1E,yEAAyE;IACzE,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAE/D,OAAO,CACL;QACE,oBAAC,MAAM,IAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,IACvC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CACvB;QACT,oBAAC,GAAG,IAAC,aAAa,EAAC,KAAK;YAGtB,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAClD,oBAAC,UAAU,IAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAI;gBAC9C,oBAAC,QAAQ,IACP,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,IAAI,GACd;gBACF,oBAAC,SAAS,IACR,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,kBAAkB,CAAC,EAAE,EAC/B,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EACpE,aAAa,EAAE,OAAO,CAAC,aAAa,EACpC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAC/B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,MAAM,EAAE,KAAK,CAAC,MAAM,GACpB,CACE;YACL,WAAW,IAAI,CACd,oBAAC,OAAO,IAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAI,CACpE,CACG,CACL,CACJ,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,gEAAgE;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,yEAAyE;AACzE,kDAAkD;AAClD,KAAK,KAAK,CAAC;AAAC,KAAK,QAAQ,CAAC"}
|
|
@@ -1,46 +1,93 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
* The N-THEM emblem as Braille art (v0.7.9). Each Braille cell packs a 2×4
|
|
5
|
+
* dot grid, so this reads ~4× denser than the ASCII `EMBLEM_MICRO` it
|
|
6
|
+
* replaces while using fewer rows (9 vs 12). Generated by thresholding the
|
|
7
|
+
* splash `EMBLEM_LARGE` glyph densities and resampling to 48×36 dots.
|
|
8
|
+
*/
|
|
9
|
+
const EMBLEM_BRAILLE = `⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣷⣆⡀
|
|
10
|
+
⠀⠀⠀⠀⠀⠀⠀⢀⣶⣿⣿⣿⣿⣿⣿⣦⡀
|
|
11
|
+
⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦
|
|
12
|
+
⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄
|
|
13
|
+
⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⠙⠻⣿⣿⣿⣿⣿⣿⠆
|
|
14
|
+
⠀⠀⠀⠀⣈⣿⣿⣿⣿⣿⣿⣿⠀⣷⣬⡛⢿⣿⣟⣁
|
|
15
|
+
⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⡿⢿⡿⢃⣈⣻⣿⣿⣶
|
|
16
|
+
⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣠⣴⣆⠻⠎⢿⣿⣿⣿⣿⣧
|
|
17
|
+
⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇`;
|
|
18
|
+
/** Column width of the sidebar (border + padding included). */
|
|
19
|
+
export const SIDEBAR_WIDTH = 28;
|
|
20
|
+
/** Sidebar only renders on terminals at least this wide. */
|
|
21
|
+
export const SIDEBAR_MIN_COLUMNS = 96;
|
|
22
|
+
/** The Braille emblem is added only when the terminal is at least this tall. */
|
|
23
|
+
const EMBLEM_MIN_ROWS = 26;
|
|
24
|
+
/** Max file rows before collapsing to "+N more". */
|
|
25
|
+
const MAX_FILES_SHORT = 6;
|
|
26
|
+
const MAX_FILES_TALL = 10;
|
|
27
|
+
/**
|
|
28
|
+
* Pure helper: should the sidebar render at all? It lives in the dynamic
|
|
29
|
+
* region (Ink repaints it), so it must never make that region taller than
|
|
30
|
+
* the terminal — narrow or tiny panes skip it entirely.
|
|
14
31
|
*/
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const showTruncatedIndicator = lines.length > maxSkillLines;
|
|
24
|
-
if (showTruncatedIndicator) {
|
|
25
|
-
visibleSkillLines.push(' ... (more in /skills)');
|
|
26
|
-
}
|
|
27
|
-
return (React.createElement(Box, { flexDirection: "column", width: width, height: height, borderStyle: "single", borderColor: "gray", paddingX: 1 },
|
|
28
|
-
React.createElement(Text, { bold: true, color: "cyan" }, "Skills & sessions"),
|
|
29
|
-
React.createElement(Text, { dimColor: true },
|
|
30
|
-
"Sessions: ",
|
|
31
|
-
sessionCount),
|
|
32
|
-
isSlashMode && React.createElement(Text, { color: "yellow" }, "\u2328 slash command mode"),
|
|
33
|
-
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, visibleSkillLines.map((line, idx) => (
|
|
34
|
-
// B12 fix — combine React's useId() with idx + line content for a
|
|
35
|
-
// guaranteed-unique key. formatSkillList can legitimately emit
|
|
36
|
-
// multiple blank lines or duplicate entries (e.g. the
|
|
37
|
-
// "... (more in /skills)" footer when the list is short), which
|
|
38
|
-
// would otherwise collide when used as a key directly.
|
|
39
|
-
React.createElement(Text, { key: `${uidPrefix}-${idx}:${line}` }, line))))));
|
|
32
|
+
export function shouldShowSidebar(columns, rows) {
|
|
33
|
+
return columns >= SIDEBAR_MIN_COLUMNS && rows >= 16;
|
|
34
|
+
}
|
|
35
|
+
/** Truncate a repo-relative path to `max` chars keeping the tail (filename). */
|
|
36
|
+
export function truncatePath(p, max) {
|
|
37
|
+
if (p.length <= max)
|
|
38
|
+
return p;
|
|
39
|
+
return `…${p.slice(-(max - 1))}`;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* Sidebar — right-hand column of the dynamic region (v0.7.9).
|
|
43
|
+
*
|
|
44
|
+
* Shows the Braille N-THEM emblem (on tall terminals), the wordmark + version, and
|
|
45
|
+
* the current git working-tree changes with +added/-removed line counts
|
|
46
|
+
* (from `useGitChanges`). It CANNOT span the scrollback area — finalized
|
|
47
|
+
* messages are printed natively via <Static> — so it docks next to the
|
|
48
|
+
* live/status/input block at the bottom, which Ink owns and repaints.
|
|
44
49
|
*/
|
|
45
|
-
export
|
|
50
|
+
export function Sidebar({ version, changes, rows }) {
|
|
51
|
+
const showEmblem = rows >= EMBLEM_MIN_ROWS;
|
|
52
|
+
const maxFiles = rows >= EMBLEM_MIN_ROWS + 8 ? MAX_FILES_TALL : MAX_FILES_SHORT;
|
|
53
|
+
const visible = changes.files.slice(0, maxFiles);
|
|
54
|
+
const hidden = changes.files.length - visible.length;
|
|
55
|
+
// Width available for the path inside the box: total − border(2) − padding(2)
|
|
56
|
+
// − the " +NNN -NNN" tail (~11 chars).
|
|
57
|
+
const innerWidth = SIDEBAR_WIDTH - 4;
|
|
58
|
+
return (React.createElement(Box, { flexDirection: "column", width: SIDEBAR_WIDTH, borderStyle: "single", borderColor: "gray", paddingX: 1, flexShrink: 0 },
|
|
59
|
+
showEmblem && (React.createElement(Box, { justifyContent: "center" },
|
|
60
|
+
React.createElement(Text, { color: "cyan" }, EMBLEM_BRAILLE))),
|
|
61
|
+
React.createElement(Box, { justifyContent: "center" },
|
|
62
|
+
React.createElement(Text, { bold: true, color: "white" }, "ZELARI CODE")),
|
|
63
|
+
React.createElement(Box, { justifyContent: "center" },
|
|
64
|
+
React.createElement(Text, { dimColor: true },
|
|
65
|
+
"v",
|
|
66
|
+
version,
|
|
67
|
+
changes.branch ? ` · ${truncatePath(changes.branch, 12)}` : '')),
|
|
68
|
+
React.createElement(Text, { dimColor: true }, '─'.repeat(innerWidth)),
|
|
69
|
+
!changes.isRepo ? (React.createElement(Text, { dimColor: true, italic: true }, "not a git repo")) : changes.files.length === 0 ? (React.createElement(Text, { dimColor: true, italic: true }, "no changes")) : (React.createElement(React.Fragment, null,
|
|
70
|
+
React.createElement(Text, { dimColor: true },
|
|
71
|
+
"changes (",
|
|
72
|
+
changes.files.length,
|
|
73
|
+
")"),
|
|
74
|
+
visible.map((f) => (React.createElement(FileRow, { key: f.path, file: f, pathWidth: innerWidth - 10 }))),
|
|
75
|
+
hidden > 0 && React.createElement(Text, { dimColor: true },
|
|
76
|
+
" +",
|
|
77
|
+
hidden,
|
|
78
|
+
" more\u2026")))));
|
|
79
|
+
}
|
|
80
|
+
function FileRow({ file, pathWidth }) {
|
|
81
|
+
const name = truncatePath(file.path, Math.max(6, pathWidth));
|
|
82
|
+
return (React.createElement(Box, null,
|
|
83
|
+
React.createElement(Text, { wrap: "truncate" },
|
|
84
|
+
React.createElement(Text, { color: file.untracked ? 'yellow' : 'white' }, name),
|
|
85
|
+
file.untracked ? (React.createElement(Text, { color: "yellow" }, " new")) : (React.createElement(React.Fragment, null,
|
|
86
|
+
React.createElement(Text, { color: "green" },
|
|
87
|
+
" +",
|
|
88
|
+
file.added ?? '·'),
|
|
89
|
+
React.createElement(Text, { color: "red" },
|
|
90
|
+
" -",
|
|
91
|
+
file.removed ?? '·'))))));
|
|
92
|
+
}
|
|
46
93
|
//# sourceMappingURL=Sidebar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../../src/cli/components/Sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../../src/cli/components/Sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SplashScreen — one-shot startup splash (v0.7.8).
|
|
3
|
+
*
|
|
4
|
+
* Shows the N-THEM / Zelari emblem (downscaled from the original 400-col
|
|
5
|
+
* ASCII art) centered in the terminal for ~2 seconds — or until any key is
|
|
6
|
+
* pressed — then unmounts and gives way to the normal App.
|
|
7
|
+
*
|
|
8
|
+
* Sizing: four pre-rendered variants (64/44/30/22 columns wide) are
|
|
9
|
+
* embedded as constants; `pickSplashArt` chooses the largest one that fits
|
|
10
|
+
* the current terminal (dropping the version/hint footer on short panes),
|
|
11
|
+
* or returns null when even the micro one doesn't fit (the splash is then
|
|
12
|
+
* skipped entirely).
|
|
13
|
+
*
|
|
14
|
+
* Skipped when stdout is not a TTY (pipes, CI) or `ZELARI_NO_SPLASH=1`.
|
|
15
|
+
*/
|
|
16
|
+
// NOTE: no import from '../main.js' here — main.ts executes `main()` at
|
|
17
|
+
// module scope, so importing it from a component (or a unit test that
|
|
18
|
+
// imports this component) would boot the whole CLI. The version string is
|
|
19
|
+
// passed in as a prop instead.
|
|
20
|
+
import React, { useEffect, useState } from 'react';
|
|
21
|
+
import { Box, Text, useInput, useStdin } from 'ink';
|
|
22
|
+
/** How long the splash stays up before auto-dismissing (ms). */
|
|
23
|
+
export const SPLASH_DURATION_MS = 2000;
|
|
24
|
+
// Downscaled from the source emblem (142×79) by block-averaging glyph
|
|
25
|
+
// density — see docs/plans/2026-07-03-cli-splash-screen.md.
|
|
26
|
+
const EMBLEM_LARGE = ` =%@*-
|
|
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
|
+
const EMBLEM_SMALL = ` =%%*:
|
|
63
|
+
:#%%@@@+
|
|
64
|
+
=%%%%%%%@#.
|
|
65
|
+
.*%%%%%%%%%@%-
|
|
66
|
+
=%%%%%%%%%%%%%@*.
|
|
67
|
+
+%%%%%%@@@@@%%%%@%:
|
|
68
|
+
*%%%%@@@@@@@@@@@%%@%:
|
|
69
|
+
*%%%@@@@@@@@@@@@@@@%@%-
|
|
70
|
+
:#%%@@@@@@@@@@@@@@@@@@@@@+
|
|
71
|
+
:%%%@@@@@@@@@@@@@@@@@@@@@@@+
|
|
72
|
+
#%%@@@@@@@@@@@@@@@@@@@@@@@@@-
|
|
73
|
+
+%%@@@@@@@@@@@@#@@@@@@@@@@@@@%:
|
|
74
|
+
%%%%@@@@@@@@@@%::*@@@@@@@@@%@@=
|
|
75
|
+
-%@%%@@@@@@@@@%:.::*@@@@@%%@@*.
|
|
76
|
+
:%@@%%@@@@@@@%.:%#::*@@%@@@-
|
|
77
|
+
:#@@@%@@@@@@%.:%@%+.-#@@@=
|
|
78
|
+
:+#@@@@@@@%@@@@%.:%@@@%=.+@@@%*-
|
|
79
|
+
.*#%%%%%%@@@@@@@@@@.:%@@@@@*:.+%@@@@#-
|
|
80
|
+
+%%%%%%%%%%@@@@@@@@::##*%* :----%@@@@%.
|
|
81
|
+
.@%%%%%%%%%@@@@@@@@@:.-..-#=:%@@@@@@@@@+
|
|
82
|
+
*@@%%%%%%%%@@@@@@@@@: =#+ +#.-@@@@@@@@@@.
|
|
83
|
+
-@@@%%%%%%%@@@@@@@@@@#%@@@- -.:*@@@@@@@@@*
|
|
84
|
+
%@@@@%@@%@@@@@@@@@@@@@@@@@%**%@@@@@@@@@@@@:
|
|
85
|
+
=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*`;
|
|
86
|
+
const EMBLEM_TINY = ` -%%+
|
|
87
|
+
.*%%%@#:
|
|
88
|
+
=%%%%%%%@*
|
|
89
|
+
+%%%%%%%%%%#.
|
|
90
|
+
+%%%@@@@@@@%@#.
|
|
91
|
+
.*%@@@@@@@@@@@@@%-
|
|
92
|
+
.#%@@@@@@@@@@@@@@@@-
|
|
93
|
+
*%@@@@@@@@@@@@@@@@@%.
|
|
94
|
+
:@%%@@@@@@%:+%@@@@@%@=
|
|
95
|
+
=@%%@@@@@%.=-+%@%%@*
|
|
96
|
+
.=@@%@@@@%.*@*-+@@*.
|
|
97
|
+
-*%@@@@@@@@%.*@@@+:#@@#=.
|
|
98
|
+
*%%%%%%@@@@@@.*#%#=-:+@@@%
|
|
99
|
+
:@%%%%%%@@@@@@.:=.*:*@@@@@@=
|
|
100
|
+
*@%%@%%@@@@@@@*%@*:-:%@@@@@%.
|
|
101
|
+
:@@@%@@@@@@@@@@@@@@#%@@@@@@@@=
|
|
102
|
+
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%#`;
|
|
103
|
+
const EMBLEM_MICRO = ` -#%=
|
|
104
|
+
+%%%%#.
|
|
105
|
+
:#%%%%%%%-
|
|
106
|
+
:%%@@@@@@@@=
|
|
107
|
+
-%@@@@@@@@@@@+
|
|
108
|
+
:%@@@@@@%@@@@@@=
|
|
109
|
+
-%%@@@@@.+%@@%@+
|
|
110
|
+
-@@@@@@:%++%@=
|
|
111
|
+
=*%@@@@@@:@@%=*@#+.
|
|
112
|
+
=%%%%%@@@@:+++-*%@@*
|
|
113
|
+
.%%%%%@@@@@+%+=:%@@@@:
|
|
114
|
+
*@@@@@@@@@@@@@%@@@@@@*`;
|
|
115
|
+
/** Rows the FULL footer (margin + wordmark + version + hint) needs below the art. */
|
|
116
|
+
const FOOTER_ROWS_FULL = 5;
|
|
117
|
+
/** Rows the COMPACT footer (margin + wordmark only) needs — used on short terminals. */
|
|
118
|
+
const FOOTER_ROWS_COMPACT = 2;
|
|
119
|
+
function measure(art) {
|
|
120
|
+
const lines = art.split('\n');
|
|
121
|
+
return {
|
|
122
|
+
art,
|
|
123
|
+
width: Math.max(...lines.map((l) => l.length)),
|
|
124
|
+
height: lines.length,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const VARIANTS = [
|
|
128
|
+
measure(EMBLEM_LARGE),
|
|
129
|
+
measure(EMBLEM_SMALL),
|
|
130
|
+
measure(EMBLEM_TINY),
|
|
131
|
+
measure(EMBLEM_MICRO),
|
|
132
|
+
];
|
|
133
|
+
/**
|
|
134
|
+
* Pure helper: pick the largest emblem variant that fits `columns`×`rows`.
|
|
135
|
+
* Tries the full footer first (wordmark + version + hint); on short
|
|
136
|
+
* terminals falls back to the compact footer (wordmark only) so the
|
|
137
|
+
* splash still shows in low panes like VS Code's integrated terminal.
|
|
138
|
+
* Returns null only when even the micro variant doesn't fit.
|
|
139
|
+
*/
|
|
140
|
+
export function pickSplashArt(columns, rows) {
|
|
141
|
+
// Largest art wins: a bigger emblem with the compact footer beats a
|
|
142
|
+
// smaller emblem with the full footer.
|
|
143
|
+
for (const v of VARIANTS) {
|
|
144
|
+
if (v.width > columns - 2)
|
|
145
|
+
continue;
|
|
146
|
+
if (v.height + FOOTER_ROWS_FULL <= rows)
|
|
147
|
+
return { ...v, compact: false };
|
|
148
|
+
if (v.height + FOOTER_ROWS_COMPACT <= rows)
|
|
149
|
+
return { ...v, compact: true };
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Pure helper: should the splash be shown at all?
|
|
155
|
+
* Skipped for non-TTY stdout (pipes/CI), when ZELARI_NO_SPLASH=1, or when
|
|
156
|
+
* the terminal is too small for even the small variant.
|
|
157
|
+
*/
|
|
158
|
+
export function shouldShowSplash(opts) {
|
|
159
|
+
if (!opts.isTTY)
|
|
160
|
+
return false;
|
|
161
|
+
if (opts.env['ZELARI_NO_SPLASH'] === '1')
|
|
162
|
+
return false;
|
|
163
|
+
return pickSplashArt(opts.columns, opts.rows) !== null;
|
|
164
|
+
}
|
|
165
|
+
function Splash({ onDone, version }) {
|
|
166
|
+
const { isRawModeSupported } = useStdin();
|
|
167
|
+
const columns = process.stdout.columns ?? 80;
|
|
168
|
+
const rows = process.stdout.rows ?? 24;
|
|
169
|
+
const picked = pickSplashArt(columns, rows);
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
const t = setTimeout(onDone, SPLASH_DURATION_MS);
|
|
172
|
+
return () => clearTimeout(t);
|
|
173
|
+
}, [onDone]);
|
|
174
|
+
// Any key skips the splash. Guarded: useInput throws without raw mode.
|
|
175
|
+
useInput(() => {
|
|
176
|
+
onDone();
|
|
177
|
+
}, { isActive: isRawModeSupported === true });
|
|
178
|
+
if (!picked)
|
|
179
|
+
return null;
|
|
180
|
+
return (React.createElement(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", width: columns, height: rows - 1 },
|
|
181
|
+
React.createElement(Text, { color: "cyan" }, picked.art),
|
|
182
|
+
React.createElement(Box, { marginTop: 1 },
|
|
183
|
+
React.createElement(Text, { bold: true, color: "white" }, 'Z E L A R I C O D E')),
|
|
184
|
+
!picked.compact && (React.createElement(Text, { dimColor: true }, `${version ? `v${version} — ` : ''}N-THEM Studio`)),
|
|
185
|
+
!picked.compact && (React.createElement(Text, { dimColor: true, italic: true }, "press any key to skip"))));
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* SplashGate — renders the splash first, then swaps in `children` (the
|
|
189
|
+
* real App). The App therefore mounts only after the splash dismisses,
|
|
190
|
+
* so its <Static> banner and raw-mode input never fight the splash.
|
|
191
|
+
*/
|
|
192
|
+
export function SplashGate({ children, version, }) {
|
|
193
|
+
const [show, setShow] = useState(() => shouldShowSplash({
|
|
194
|
+
isTTY: process.stdout.isTTY === true,
|
|
195
|
+
env: process.env,
|
|
196
|
+
columns: process.stdout.columns ?? 80,
|
|
197
|
+
rows: process.stdout.rows ?? 24,
|
|
198
|
+
}));
|
|
199
|
+
if (show) {
|
|
200
|
+
return React.createElement(Splash, { onDone: () => setShow(false), version: version });
|
|
201
|
+
}
|
|
202
|
+
return React.createElement(React.Fragment, null, children);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=SplashScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SplashScreen.js","sourceRoot":"","sources":["../../../src/cli/components/SplashScreen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
-
import {
|
|
3
|
+
import { formatDuration } from '../utils/duration.js';
|
|
4
4
|
/**
|
|
5
|
-
* StatusBar — single one-line status bar
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* StatusBar — single one-line status bar. v0.7.9: rendered BELOW the input
|
|
6
|
+
* box (the "top bar" position above it is gone), and the token/cost fields
|
|
7
|
+
* are replaced by an execution timer: `⏱ 12s` while a run is in flight,
|
|
8
|
+
* `last 34s` after it completes.
|
|
8
9
|
*
|
|
9
10
|
* Why one line: the static-scrollback model (v0.7.0) needs the dynamic
|
|
10
11
|
* region as short as possible. A single status line + the input bar + the
|
|
11
12
|
* streaming tail is always well under a screen, so no full repaint.
|
|
12
13
|
*/
|
|
13
|
-
export function StatusBar({ model, provider, sessionId, sessionActive,
|
|
14
|
-
const hasCost = typeof totalCostUsd === 'number' && totalCostUsd > 0;
|
|
15
|
-
const costStr = hasCost ? formatCost(totalCostUsd) : '$0.0000';
|
|
16
|
-
const tokStr = formatTokens(totalTokens ?? 0);
|
|
14
|
+
export function StatusBar({ model, provider, sessionId, sessionActive, queueCount = 0, busy = false, mode = 'agent', cwd, elapsedMs = null, lastMs = null, }) {
|
|
17
15
|
return (React.createElement(Box, { paddingX: 1 },
|
|
18
16
|
React.createElement(Text, { color: sessionActive ? 'green' : 'gray' }, sessionActive ? '●' : '○'),
|
|
19
17
|
React.createElement(Text, { dimColor: true }, " "),
|
|
18
|
+
React.createElement(Text, { bold: true, color: mode === 'council' ? 'magenta' : 'cyan' }, mode === 'council' ? '⛬ council' : '⏵ agent'),
|
|
19
|
+
React.createElement(Text, { dimColor: true }, " (shift+tab)"),
|
|
20
|
+
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
20
21
|
React.createElement(Text, { bold: true, color: "cyan" }, provider),
|
|
21
22
|
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
22
23
|
React.createElement(Text, null, model),
|
|
@@ -24,19 +25,22 @@ export function StatusBar({ model, provider, sessionId, sessionActive, totalToke
|
|
|
24
25
|
React.createElement(Text, { dimColor: true },
|
|
25
26
|
"session ",
|
|
26
27
|
sessionId),
|
|
27
|
-
React.createElement(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
cwd ? (React.createElement(React.Fragment, null,
|
|
29
|
+
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
30
|
+
React.createElement(Text, { color: "blue" }, cwd))) : null,
|
|
31
|
+
busy && elapsedMs !== null ? (React.createElement(React.Fragment, null,
|
|
32
|
+
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
33
|
+
React.createElement(Text, { color: "yellow" },
|
|
34
|
+
"\u23F1 ",
|
|
35
|
+
formatDuration(elapsedMs)))) : lastMs !== null ? (React.createElement(React.Fragment, null,
|
|
36
|
+
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
37
|
+
React.createElement(Text, { dimColor: true },
|
|
38
|
+
"last ",
|
|
39
|
+
formatDuration(lastMs)))) : null,
|
|
33
40
|
queueCount > 0 ? (React.createElement(React.Fragment, null,
|
|
34
41
|
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
35
42
|
React.createElement(Text, { color: "magenta" },
|
|
36
43
|
"queue ",
|
|
37
|
-
queueCount))) : null
|
|
38
|
-
busy ? (React.createElement(React.Fragment, null,
|
|
39
|
-
React.createElement(Text, { dimColor: true }, " \u00B7 "),
|
|
40
|
-
React.createElement(Text, { color: "yellow" }, "working"))) : null));
|
|
44
|
+
queueCount))) : null));
|
|
41
45
|
}
|
|
42
46
|
//# sourceMappingURL=StatusBar.js.map
|