quoxcli 0.0.0-stage → 0.2.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.
- package/LICENSE +35 -0
- package/README.md +142 -2
- package/bin/quox.js +292 -0
- package/bin/quoxon.js +8 -0
- package/lib/api/endpoints/admin.js +125 -0
- package/lib/api/endpoints/aee.js +38 -0
- package/lib/api/endpoints/agent-attach.js +126 -0
- package/lib/api/endpoints/agents.js +56 -0
- package/lib/api/endpoints/assistants.js +50 -0
- package/lib/api/endpoints/audit.js +14 -0
- package/lib/api/endpoints/auth.js +50 -0
- package/lib/api/endpoints/awareness.js +34 -0
- package/lib/api/endpoints/backup-schedules.js +20 -0
- package/lib/api/endpoints/backups.js +86 -0
- package/lib/api/endpoints/brain.js +140 -0
- package/lib/api/endpoints/budgets.js +62 -0
- package/lib/api/endpoints/calendarq.js +71 -0
- package/lib/api/endpoints/catalog.js +14 -0
- package/lib/api/endpoints/chat.js +54 -0
- package/lib/api/endpoints/consent.js +26 -0
- package/lib/api/endpoints/contactsq.js +66 -0
- package/lib/api/endpoints/conversations.js +32 -0
- package/lib/api/endpoints/custom-roles.js +92 -0
- package/lib/api/endpoints/divisions.js +56 -0
- package/lib/api/endpoints/domains.js +38 -0
- package/lib/api/endpoints/engagement.js +231 -0
- package/lib/api/endpoints/engine.js +11 -0
- package/lib/api/endpoints/entity.js +50 -0
- package/lib/api/endpoints/executions.js +32 -0
- package/lib/api/endpoints/file.js +20 -0
- package/lib/api/endpoints/files.js +26 -0
- package/lib/api/endpoints/github.js +21 -0
- package/lib/api/endpoints/governance.js +43 -0
- package/lib/api/endpoints/hat.js +36 -0
- package/lib/api/endpoints/inbox.js +32 -0
- package/lib/api/endpoints/inboxq.js +120 -0
- package/lib/api/endpoints/index.js +228 -0
- package/lib/api/endpoints/invites.js +19 -0
- package/lib/api/endpoints/llm-policy.js +43 -0
- package/lib/api/endpoints/lucid.js +89 -0
- package/lib/api/endpoints/members.js +32 -0
- package/lib/api/endpoints/memory.js +75 -0
- package/lib/api/endpoints/mfa.js +32 -0
- package/lib/api/endpoints/mon.js +178 -0
- package/lib/api/endpoints/notesq.js +43 -0
- package/lib/api/endpoints/objectives.js +62 -0
- package/lib/api/endpoints/orgs.js +38 -0
- package/lib/api/endpoints/plugins.js +134 -0
- package/lib/api/endpoints/powers.js +75 -0
- package/lib/api/endpoints/prompts.js +69 -0
- package/lib/api/endpoints/qlarity.js +122 -0
- package/lib/api/endpoints/quoxbox.js +55 -0
- package/lib/api/endpoints/quoxchat.js +54 -0
- package/lib/api/endpoints/quoxflow.js +32 -0
- package/lib/api/endpoints/quoxplan.js +114 -0
- package/lib/api/endpoints/quoxseo.js +108 -0
- package/lib/api/endpoints/reach.js +47 -0
- package/lib/api/endpoints/runs.js +38 -0
- package/lib/api/endpoints/safety.js +46 -0
- package/lib/api/endpoints/scim.js +46 -0
- package/lib/api/endpoints/scopes.js +14 -0
- package/lib/api/endpoints/security.js +69 -0
- package/lib/api/endpoints/setup.js +90 -0
- package/lib/api/endpoints/skills.js +180 -0
- package/lib/api/endpoints/sso.js +67 -0
- package/lib/api/endpoints/tags.js +32 -0
- package/lib/api/endpoints/teams.js +56 -0
- package/lib/api/endpoints/telephony.js +46 -0
- package/lib/api/endpoints/tg.js +56 -0
- package/lib/api/endpoints/tools.js +50 -0
- package/lib/api/endpoints/traces.js +157 -0
- package/lib/api/endpoints/triggers.js +70 -0
- package/lib/api/endpoints/user-library.js +41 -0
- package/lib/api/endpoints/users.js +20 -0
- package/lib/api/endpoints/v1.js +499 -0
- package/lib/api/endpoints/vault.js +192 -0
- package/lib/api/endpoints/voice.js +22 -0
- package/lib/api/endpoints/volt.js +84 -0
- package/lib/api/endpoints/ward.js +40 -0
- package/lib/api/endpoints/webhooks.js +46 -0
- package/lib/api/endpoints/workflows.js +162 -0
- package/lib/api/endpoints/x.js +24 -0
- package/lib/api/endpoints.js +15 -0
- package/lib/commands/admin.js +359 -0
- package/lib/commands/aee.js +99 -0
- package/lib/commands/agent.js +201 -0
- package/lib/commands/agentAttach.js +1440 -0
- package/lib/commands/approvals.js +47 -0
- package/lib/commands/assistant.js +114 -0
- package/lib/commands/auth.js +458 -0
- package/lib/commands/awareness.js +88 -0
- package/lib/commands/backup.js +373 -0
- package/lib/commands/brain.js +994 -0
- package/lib/commands/budget.js +241 -0
- package/lib/commands/build.js +156 -0
- package/lib/commands/calendar.js +216 -0
- package/lib/commands/capabilities.js +34 -0
- package/lib/commands/chat.js +240 -0
- package/lib/commands/claude.js +354 -0
- package/lib/commands/config-cmd.js +106 -0
- package/lib/commands/consent.js +84 -0
- package/lib/commands/contacts.js +967 -0
- package/lib/commands/contactsSelftest.js +132 -0
- package/lib/commands/conversation.js +74 -0
- package/lib/commands/department.js +75 -0
- package/lib/commands/dev.js +620 -0
- package/lib/commands/devResident.js +314 -0
- package/lib/commands/devSupervisor.js +1050 -0
- package/lib/commands/discord.js +96 -0
- package/lib/commands/doctor.js +181 -0
- package/lib/commands/domain.js +114 -0
- package/lib/commands/done.js +277 -0
- package/lib/commands/engagement.js +586 -0
- package/lib/commands/entity.js +119 -0
- package/lib/commands/facebook.js +212 -0
- package/lib/commands/file.js +128 -0
- package/lib/commands/fleet.js +882 -0
- package/lib/commands/governance.js +638 -0
- package/lib/commands/gripe.js +324 -0
- package/lib/commands/hat.js +205 -0
- package/lib/commands/helpers.js +79 -0
- package/lib/commands/inbox.js +122 -0
- package/lib/commands/instagram.js +264 -0
- package/lib/commands/integration.js +100 -0
- package/lib/commands/inventory.js +115 -0
- package/lib/commands/invites.js +45 -0
- package/lib/commands/licence.js +280 -0
- package/lib/commands/linkedin.js +178 -0
- package/lib/commands/llm-policy.js +117 -0
- package/lib/commands/llm.js +45 -0
- package/lib/commands/lucid.js +591 -0
- package/lib/commands/mail.js +531 -0
- package/lib/commands/memory.js +284 -0
- package/lib/commands/mon.js +514 -0
- package/lib/commands/monitoring.js +86 -0
- package/lib/commands/motion.js +22 -0
- package/lib/commands/notes.js +1246 -0
- package/lib/commands/notesBatch.js +160 -0
- package/lib/commands/notesBridges.js +56 -0
- package/lib/commands/notesLinks.js +60 -0
- package/lib/commands/notification.js +57 -0
- package/lib/commands/nucleus.js +92 -0
- package/lib/commands/objective.js +229 -0
- package/lib/commands/onboard.js +328 -0
- package/lib/commands/open.js +56 -0
- package/lib/commands/org.js +266 -0
- package/lib/commands/plan.js +906 -0
- package/lib/commands/plugin-doctor.js +1091 -0
- package/lib/commands/plugin.js +539 -0
- package/lib/commands/policy.js +78 -0
- package/lib/commands/powers.js +296 -0
- package/lib/commands/prompt.js +350 -0
- package/lib/commands/qlarity.js +690 -0
- package/lib/commands/quoxbox.js +270 -0
- package/lib/commands/quoxchat.js +266 -0
- package/lib/commands/quoxseo.js +340 -0
- package/lib/commands/reach.js +158 -0
- package/lib/commands/role.js +286 -0
- package/lib/commands/run.js +132 -0
- package/lib/commands/safety.js +107 -0
- package/lib/commands/scim.js +88 -0
- package/lib/commands/scope.js +58 -0
- package/lib/commands/security.js +157 -0
- package/lib/commands/service.js +89 -0
- package/lib/commands/settings.js +99 -0
- package/lib/commands/setup.js +543 -0
- package/lib/commands/skillManifest.js +113 -0
- package/lib/commands/skillRightsFormat.js +38 -0
- package/lib/commands/skills.js +644 -0
- package/lib/commands/slot.js +1198 -0
- package/lib/commands/sso.js +229 -0
- package/lib/commands/status.js +137 -0
- package/lib/commands/tag.js +91 -0
- package/lib/commands/team.js +140 -0
- package/lib/commands/tg.js +240 -0
- package/lib/commands/tiktok.js +218 -0
- package/lib/commands/tool.js +216 -0
- package/lib/commands/trace.js +525 -0
- package/lib/commands/trigger.js +128 -0
- package/lib/commands/vault.js +1424 -0
- package/lib/commands/voice.js +182 -0
- package/lib/commands/volt.js +528 -0
- package/lib/commands/watch.js +115 -0
- package/lib/commands/webhook.js +137 -0
- package/lib/commands/workflow.js +503 -0
- package/lib/commands/x.js +439 -0
- package/lib/core/actingAs.js +136 -0
- package/lib/core/aee.js +53 -0
- package/lib/core/agentAlias.js +163 -0
- package/lib/core/approvalContext.js +61 -0
- package/lib/core/auth.js +350 -0
- package/lib/core/banner.js +143 -0
- package/lib/core/brainPrime.js +90 -0
- package/lib/core/callerSource.js +129 -0
- package/lib/core/claudeLs.js +94 -0
- package/lib/core/client.js +584 -0
- package/lib/core/completions.js +163 -0
- package/lib/core/config.js +551 -0
- package/lib/core/confirm.js +37 -0
- package/lib/core/deeplinks.js +76 -0
- package/lib/core/doneEngineFetch.js +219 -0
- package/lib/core/errors.js +132 -0
- package/lib/core/global-flags.js +90 -0
- package/lib/core/governedSession.js +402 -0
- package/lib/core/lazyCommands.js +119 -0
- package/lib/core/liveSessionsReport.js +112 -0
- package/lib/core/org-override.js +52 -0
- package/lib/core/output.js +239 -0
- package/lib/core/prodEnv.js +7 -0
- package/lib/core/quoxglyph.js +158 -0
- package/lib/core/residentAlarm.js +282 -0
- package/lib/core/residentAuth.js +243 -0
- package/lib/core/residentPump.js +229 -0
- package/lib/core/residentSeed.js +104 -0
- package/lib/core/sessionHeartbeat.js +192 -0
- package/lib/core/sessionsOverview.js +160 -0
- package/lib/core/slotKeeper.js +282 -0
- package/lib/core/supervisorEngine.js +864 -0
- package/lib/core/systemdInstaller.js +256 -0
- package/lib/core/version.js +87 -0
- package/lib/core/websiteSession.js +148 -0
- package/lib/lucid/LucidIntro.jsx +105 -0
- package/lib/lucid/blind.js +71 -0
- package/lib/lucid/deck.js +32 -0
- package/lib/lucid/fmt.js +139 -0
- package/lib/lucid/sitrep.js +173 -0
- package/lib/plugins/loader.js +93 -0
- package/lib/quoxon/activity.js +104 -0
- package/lib/quoxon/api.js +473 -0
- package/lib/quoxon/app.js +1262 -0
- package/lib/quoxon/capabilities.js +75 -0
- package/lib/quoxon/commands.js +154 -0
- package/lib/quoxon/connect.js +467 -0
- package/lib/quoxon/connectCard.js +28 -0
- package/lib/quoxon/context.js +68 -0
- package/lib/quoxon/copy.js +33 -0
- package/lib/quoxon/demo.fixtures.js +24 -0
- package/lib/quoxon/demo.js +35 -0
- package/lib/quoxon/egg.js +36 -0
- package/lib/quoxon/events.js +458 -0
- package/lib/quoxon/gallery.js +223 -0
- package/lib/quoxon/indicator.js +193 -0
- package/lib/quoxon/intent.js +41 -0
- package/lib/quoxon/keys.js +121 -0
- package/lib/quoxon/main.js +244 -0
- package/lib/quoxon/markdown.js +317 -0
- package/lib/quoxon/model.js +205 -0
- package/lib/quoxon/motion/clock.js +69 -0
- package/lib/quoxon/motion/color.js +35 -0
- package/lib/quoxon/motion/frame.js +14 -0
- package/lib/quoxon/motion/reveal.js +54 -0
- package/lib/quoxon/motion/ring.js +79 -0
- package/lib/quoxon/objects/agent.js +61 -0
- package/lib/quoxon/objects/crystal.js +100 -0
- package/lib/quoxon/objects/fetch.js +170 -0
- package/lib/quoxon/objects/index.js +85 -0
- package/lib/quoxon/objects/ladder.js +71 -0
- package/lib/quoxon/objects/memory.js +44 -0
- package/lib/quoxon/objects/model.js +118 -0
- package/lib/quoxon/objects/proof.js +110 -0
- package/lib/quoxon/objects/skill.js +105 -0
- package/lib/quoxon/objects/view.js +76 -0
- package/lib/quoxon/objects/workflow.js +119 -0
- package/lib/quoxon/observers.js +42 -0
- package/lib/quoxon/onboarding/copy.js +235 -0
- package/lib/quoxon/onboarding/credential.js +95 -0
- package/lib/quoxon/onboarding/detect.js +22 -0
- package/lib/quoxon/onboarding/finish.js +119 -0
- package/lib/quoxon/onboarding/index.js +67 -0
- package/lib/quoxon/onboarding/installRunner.js +225 -0
- package/lib/quoxon/onboarding/intent.js +53 -0
- package/lib/quoxon/onboarding/journey.js +73 -0
- package/lib/quoxon/onboarding/preflight.js +142 -0
- package/lib/quoxon/onboarding/runner.js +58 -0
- package/lib/quoxon/onboarding/view.js +625 -0
- package/lib/quoxon/print.js +94 -0
- package/lib/quoxon/qart.js +379 -0
- package/lib/quoxon/qglyph.js +143 -0
- package/lib/quoxon/qhello.js +58 -0
- package/lib/quoxon/qmotion.js +111 -0
- package/lib/quoxon/render.js +648 -0
- package/lib/quoxon/roster.js +221 -0
- package/lib/quoxon/route.js +38 -0
- package/lib/quoxon/rules.js +130 -0
- package/lib/quoxon/session.js +68 -0
- package/lib/quoxon/skills.js +30 -0
- package/lib/quoxon/slash/compact.js +90 -0
- package/lib/quoxon/slash/ledger.js +83 -0
- package/lib/quoxon/slash/listView.js +28 -0
- package/lib/quoxon/slash/palette.js +104 -0
- package/lib/quoxon/slash/paletteController.js +59 -0
- package/lib/quoxon/slash/panels.js +101 -0
- package/lib/quoxon/slash/picker.js +38 -0
- package/lib/quoxon/slash/restart.js +144 -0
- package/lib/quoxon/slash/resume.js +59 -0
- package/lib/quoxon/slash/settings.js +50 -0
- package/lib/quoxon/sound/index.js +186 -0
- package/lib/quoxon/sound/mapping.js +119 -0
- package/lib/quoxon/sound/output.js +52 -0
- package/lib/quoxon/sound/synth.js +122 -0
- package/lib/quoxon/term.js +106 -0
- package/lib/quoxon/textBuffer.js +242 -0
- package/lib/quoxon/theme.js +253 -0
- package/lib/quoxon/transcript.js +150 -0
- package/lib/quoxon/web/qface.js +81 -0
- package/lib/quoxon/welcome.js +52 -0
- package/lib/tui/app.jsx +289 -0
- package/lib/tui/components/Breadcrumb.jsx +42 -0
- package/lib/tui/components/ChatInput.jsx +68 -0
- package/lib/tui/components/Confirm.jsx +32 -0
- package/lib/tui/components/DataTable.jsx +270 -0
- package/lib/tui/components/DetailPanel.jsx +241 -0
- package/lib/tui/components/HelpOverlay.jsx +67 -0
- package/lib/tui/components/Layout.jsx +129 -0
- package/lib/tui/components/Palette.jsx +141 -0
- package/lib/tui/components/SearchInput.jsx +125 -0
- package/lib/tui/components/Sparkline.jsx +55 -0
- package/lib/tui/components/StatusBar.jsx +133 -0
- package/lib/tui/components/Toast.jsx +52 -0
- package/lib/tui/hooks/useApi.js +44 -0
- package/lib/tui/hooks/useHealth.js +90 -0
- package/lib/tui/hooks/usePolledApi.js +86 -0
- package/lib/tui/hooks/useTerminalSize.js +46 -0
- package/lib/tui/index.js +56 -0
- package/lib/tui/intro/Intro.jsx +332 -0
- package/lib/tui/jsx-loader.js +32 -0
- package/lib/tui/keys.js +87 -0
- package/lib/tui/registry.js +49 -0
- package/lib/tui/theme.js +103 -0
- package/lib/tui/views/AdminView.jsx +398 -0
- package/lib/tui/views/AgentView.jsx +204 -0
- package/lib/tui/views/BackupView.jsx +225 -0
- package/lib/tui/views/BrainView.jsx +223 -0
- package/lib/tui/views/ChatView.jsx +468 -0
- package/lib/tui/views/FilesView.jsx +218 -0
- package/lib/tui/views/FleetView.jsx +234 -0
- package/lib/tui/views/GovernanceView.jsx +453 -0
- package/lib/tui/views/HealthView.jsx +216 -0
- package/lib/tui/views/InboxView.jsx +228 -0
- package/lib/tui/views/LucidDeck.jsx +727 -0
- package/lib/tui/views/MainMenu.jsx +123 -0
- package/lib/tui/views/MemoryView.jsx +377 -0
- package/lib/tui/views/ObjectivesView.jsx +230 -0
- package/lib/tui/views/OrgView.jsx +229 -0
- package/lib/tui/views/ToolView.jsx +221 -0
- package/lib/tui/views/VaultView.jsx +422 -0
- package/lib/tui/views/WorkflowView.jsx +329 -0
- package/package.json +72 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Q says hello: "Hi, I'm Quox." decoded in beside the mark (CLI-QUOX, lab fx "decode").
|
|
3
|
+
*
|
|
4
|
+
* Characters resolve left to right; just ahead of the edge they flicker as half-width katakana, just behind
|
|
5
|
+
* it a faint phosphor afterglow fades. The final text is always plain and readable. PURE AND PORTABLE: no
|
|
6
|
+
* Ink, no process, no timers; t is ms since the line started. Output cells { ch, rgb, bold } so the CLI and
|
|
7
|
+
* the web face (web/qface.js) draw the same frames.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Same curated half-width katakana as indicator.js SCRAMBLE_GLYPHS: one cell each, none reads as Latin.
|
|
11
|
+
export const KANA = 'アウカキクケコサタチツヌハヒホマミムメラ';
|
|
12
|
+
export const LEAD_MS = 140, GLOW_MS = 700;
|
|
13
|
+
const SKY = [56, 189, 248];
|
|
14
|
+
const DIM = [58, 66, 82], TXT = [226, 232, 240], GLOWC = [110, 231, 183];
|
|
15
|
+
const mix = (a, b, t) => a.map((v, i) => Math.round(v + (b[i] - v) * t));
|
|
16
|
+
const clamp = (x) => Math.max(0, Math.min(1, x));
|
|
17
|
+
const hash = (a, b, c) => { let h = (a * 374761393 + b * 668265263 + c * 2147483647) | 0; h = Math.imul(h ^ (h >>> 13), 1274126177); return ((h ^ (h >>> 16)) >>> 0) / 4294967296; };
|
|
18
|
+
|
|
19
|
+
/** How long a line of n characters takes to settle (decode plus afterglow). */
|
|
20
|
+
export const helloMs = (text, perChar = 28) => Math.max(1, [...String(text)].length - 1) * perChar + GLOW_MS;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Decode frame of `text` at t ms. fg: rgb for the settled text (default near-white), or a function
|
|
24
|
+
* (i, ch) -> rgb (a gradient). mono: no colour (glyph flicker stays: motion is not colour).
|
|
25
|
+
* Returns [{ ch, rgb, bold }], always text.length cells; blanks are ' ' (never shifting the line).
|
|
26
|
+
*/
|
|
27
|
+
export function helloCells(text, t, { perChar = 28, fg = TXT, mono = false, salt = 7 } = {}) {
|
|
28
|
+
const chars = [...String(text)];
|
|
29
|
+
const fgAt = typeof fg === 'function' ? fg : () => fg;
|
|
30
|
+
return chars.map((ch, i) => {
|
|
31
|
+
if (ch === ' ') return { ch, rgb: null, bold: false };
|
|
32
|
+
const dt = t - i * perChar;
|
|
33
|
+
if (dt < -LEAD_MS) return { ch: ' ', rgb: null, bold: false };
|
|
34
|
+
if (dt < 0) {
|
|
35
|
+
const b = Math.floor(t / 33);
|
|
36
|
+
const k = KANA[Math.floor(hash(i, b, salt) * KANA.length)];
|
|
37
|
+
return { ch: k, rgb: mono ? null : mix(DIM, SKY, 0.35 + 0.65 * hash(i, b + 7, salt)), bold: false };
|
|
38
|
+
}
|
|
39
|
+
const g = dt < GLOW_MS ? (1 - dt / GLOW_MS) ** 1.6 : 0;
|
|
40
|
+
return { ch, rgb: mono ? null : mix(fgAt(i, ch), GLOWC, 0.5 * g), bold: !mono && (dt < 50 || g > 0.55) };
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Is the line fully settled (plain text, no glow) at t? */
|
|
45
|
+
export const helloSettled = (text, t, perChar = 28) => t >= helloMs(text, perChar);
|
|
46
|
+
|
|
47
|
+
/** The settled text's gradient (sky to violet across the line), for callers that want the brand look. */
|
|
48
|
+
export const helloGradient = (text) => {
|
|
49
|
+
const n = Math.max(1, [...String(text)].length - 1);
|
|
50
|
+
return (i) => mix([56, 189, 248], [168, 85, 247], clamp(i / n));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Cells -> truecolor ANSI string (bold where marked). */
|
|
54
|
+
export function helloAnsi(cells) {
|
|
55
|
+
let s = '';
|
|
56
|
+
for (const c of cells) s += (c.bold ? '\x1b[1m' : '') + (c.rgb ? `\x1b[38;2;${c.rgb.join(';')}m` : '') + c.ch + (c.rgb || c.bold ? '\x1b[0m' : '');
|
|
57
|
+
return s;
|
|
58
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ink adaptors for the pure Q frames (qart.js, qglyph.js, qhello.js): the status glyph, the hello intro
|
|
3
|
+
* used by Getting started, and the on-demand Dragon's Eye (/eye). The frame math lives in the pure modules
|
|
4
|
+
* so the web face draws the same frames; this file only maps cells to <Text>.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { Box, Text, useStdout } from 'ink';
|
|
8
|
+
import { qGlyph, glyphMode, colorDepth } from './qglyph.js';
|
|
9
|
+
import { labSize, qDims, introPlan, eyeCellsAt, EYE_MS, INTRO_MS } from './qart.js';
|
|
10
|
+
import { helloCells, helloGradient, helloMs } from './qhello.js';
|
|
11
|
+
import { mono, c, clip } from './theme.js';
|
|
12
|
+
import { reducedMotion } from './motion/clock.js';
|
|
13
|
+
import { FrameContext, useFrame } from './motion/frame.js';
|
|
14
|
+
const isQuiet = () => reducedMotion(); // motion only (NO_COLOR is colour only; QGlyph falls back to the circled Q itself)
|
|
15
|
+
import { termRows } from './term.js';
|
|
16
|
+
|
|
17
|
+
const h = React.createElement;
|
|
18
|
+
const rgbS = (rgb) => (rgb ? `rgb(${rgb.join(',')})` : undefined);
|
|
19
|
+
|
|
20
|
+
/** Runs of same-coloured cells -> one <Text> each (keeps Ink's per-frame tokenising cheap). */
|
|
21
|
+
export function cellNodes(cells, keyBase = 'c') {
|
|
22
|
+
const out = [];
|
|
23
|
+
let run = '', col, bold = false, k = 0;
|
|
24
|
+
const flush = () => { if (run) out.push(h(Text, { key: `${keyBase}${k++}`, color: col, bold }, run)); run = ''; };
|
|
25
|
+
for (const cl of cells) {
|
|
26
|
+
const cc = rgbS(cl.rgb), b = Boolean(cl.bold);
|
|
27
|
+
if (cc !== col || b !== bold) { flush(); col = cc; bold = b; }
|
|
28
|
+
run += cl.ch;
|
|
29
|
+
}
|
|
30
|
+
flush();
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let envCache = null;
|
|
35
|
+
const envGlyph = () => (envCache ??= { mode: glyphMode(process.env), depth: colorDepth(process.env) });
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The status glyph: the perpetual Q for a state at ms (sample it from the shared clock, ~12 fps). One fixed
|
|
39
|
+
* shape; only its colour moves. since: when the state began (failing flashes from there). Ⓠ under NO_COLOR.
|
|
40
|
+
*/
|
|
41
|
+
export function QGlyph({ state = 'working', ms = Date.now(), since = null, quiet = isQuiet() }) {
|
|
42
|
+
const { mode, depth } = envGlyph();
|
|
43
|
+
const g = qGlyph(state, ms, { mono: mono(), quiet, mode, depth, since });
|
|
44
|
+
return h(Text, { bold: true }, ...cellNodes(g.cells, 'g'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---- hello intro (Getting started) ----------------------------------------------------------------------
|
|
48
|
+
import { HELLO } from './onboarding/copy.js';
|
|
49
|
+
export { HELLO };
|
|
50
|
+
/** Total ms of the hello intro: Orbit & Lock, the greeting decode, then (egg) the Dragon's Eye. */
|
|
51
|
+
export const helloIntroMs = ({ eye = false, text = HELLO } = {}) => INTRO_MS + helloMs(text) + (eye ? EYE_MS + 400 : 0);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The Q, then the Q says hello beside it. t: ms since the intro started (Infinity = settled). The greeting
|
|
55
|
+
* decodes in once the Q has locked; the eye (launch egg) plays after the greeting has landed.
|
|
56
|
+
*/
|
|
57
|
+
export function HelloIntro({ item, cols, rows, t = Infinity, eye = false, text = HELLO }) {
|
|
58
|
+
const { stdout } = useStdout();
|
|
59
|
+
const size = labSize(cols, rows ?? termRows(stdout) ?? 40);
|
|
60
|
+
const color = !mono();
|
|
61
|
+
const helloAt = t - INTRO_MS;
|
|
62
|
+
const plan = introPlan(size, { color });
|
|
63
|
+
let cells;
|
|
64
|
+
if (eye && helloAt >= helloMs(text)) cells = eyeCellsAt(size, helloAt - helloMs(text), { color });
|
|
65
|
+
else cells = plan.at(Math.min(t, INTRO_MS));
|
|
66
|
+
const wide = cols >= 60;
|
|
67
|
+
const w = qDims(size).cols;
|
|
68
|
+
const hello = helloCells(text, Number.isFinite(helloAt) ? Math.max(-1000, helloAt) : 1e9, { fg: helloGradient(text), mono: !color });
|
|
69
|
+
const info = h(Box, { flexDirection: 'column', justifyContent: 'center', marginLeft: wide ? 2 : 0, marginTop: wide ? 0 : 1 },
|
|
70
|
+
h(Text, { bold: true }, ...cellNodes(hello, 'h')),
|
|
71
|
+
h(Text, { color: c('dim') }, clip(item?.text || '', cols - (wide ? w + 4 : 2))));
|
|
72
|
+
return h(Box, { flexDirection: wide ? 'row' : 'column', marginBottom: 1 },
|
|
73
|
+
h(Box, { flexDirection: 'column' }, ...cells.map((row, k) => h(Text, { key: k, wrap: 'truncate' }, ...cellNodes(row, `r${k}-`)))),
|
|
74
|
+
info);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ---- /eye: the Dragon's Eye on demand --------------------------------------------------------------------
|
|
78
|
+
const listeners = new Set();
|
|
79
|
+
let eyeStart = null;
|
|
80
|
+
/** Ask the live <EyeLive/> to play the eye now. Returns true (the command was handled). */
|
|
81
|
+
export function playEye(now = Date.now()) { eyeStart = now; for (const fn of listeners) fn(); return true; }
|
|
82
|
+
export const eyePlaying = (now = Date.now()) => eyeStart != null && now - eyeStart < EYE_MS + 400;
|
|
83
|
+
/** How long the eye shows (reduced motion: a still eye for 2 s). The app's shared clock frames it while true. */
|
|
84
|
+
export const eyeActive = (now = Date.now(), quiet = isQuiet()) => eyeStart != null && now - eyeStart < (quiet ? 2000 : EYE_MS + 400);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Mounted once in the live region; renders nothing until /eye. Then the Q opens its eye, blinks once and
|
|
88
|
+
* dissolves, and the component goes back to nothing (it never enters history). Its timer runs only while
|
|
89
|
+
* the eye plays. Reduced motion: a still open eye for two seconds.
|
|
90
|
+
*/
|
|
91
|
+
export function EyeLive({ cols, rows }) {
|
|
92
|
+
const { stdout } = useStdout();
|
|
93
|
+
const onClock = React.useContext(FrameContext) != null; // inside the app: the shared clock drives the frames
|
|
94
|
+
useFrame();
|
|
95
|
+
const [, bump] = React.useState(0);
|
|
96
|
+
React.useEffect(() => { const fn = () => bump((x) => x + 1); listeners.add(fn); return () => listeners.delete(fn); }, []);
|
|
97
|
+
const quiet = isQuiet();
|
|
98
|
+
const playing = eyeStart != null && Date.now() - eyeStart < (quiet ? 2000 : EYE_MS + 400);
|
|
99
|
+
React.useEffect(() => {
|
|
100
|
+
if (!playing || onClock) return undefined; // standalone only (no shared clock): its own bounded timer
|
|
101
|
+
const id = setInterval(() => { bump((x) => x + 1); if (Date.now() - eyeStart >= (quiet ? 2000 : EYE_MS + 400)) clearInterval(id); }, quiet ? 500 : 50);
|
|
102
|
+
return () => clearInterval(id);
|
|
103
|
+
}, [playing, quiet, onClock]);
|
|
104
|
+
if (!playing) return null;
|
|
105
|
+
const size = labSize(cols, rows ?? termRows(stdout) ?? 40);
|
|
106
|
+
const t = quiet ? EYE_MS * 0.42 : Date.now() - eyeStart;
|
|
107
|
+
const cells = eyeCellsAt(size, t, { color: !mono() });
|
|
108
|
+
return h(Box, { flexDirection: 'row', marginTop: 1 },
|
|
109
|
+
h(Box, { flexDirection: 'column' }, ...cells.map((row, k) => h(Text, { key: k, wrap: 'truncate' }, ...cellNodes(row, `e${k}-`)))),
|
|
110
|
+
cols >= 60 ? h(Box, { marginLeft: 2, flexDirection: 'column', justifyContent: 'center' }, h(Text, { color: c('dim') }, "the Dragon's Eye")) : null);
|
|
111
|
+
}
|