agent-tempo 1.7.0 → 2.0.0-beta.2
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/CLAUDE.md +10 -13
- package/README.md +21 -15
- package/dashboard/dist/assets/index-BbR7zIdK.js.map +1 -1
- package/dashboard/package.json +1 -1
- package/dist/activities/hard-terminate.d.ts +2 -2
- package/dist/activities/hard-terminate.js +3 -9
- package/dist/activities/maestro.d.ts +8 -13
- package/dist/activities/maestro.js +3 -10
- package/dist/activities/outbox.js +16 -2
- package/dist/activities/resolve.d.ts +18 -7
- package/dist/activities/resolve.js +58 -46
- package/dist/adapters/base.js +3 -0
- package/dist/adapters/claude-code/adapter.js +7 -0
- package/dist/cli/command-center-command.js +15 -1
- package/dist/cli/commands.d.ts +8 -0
- package/dist/cli/commands.js +79 -11
- package/dist/cli/daemon-command.js +19 -33
- package/dist/cli/help-text.js +9 -7
- package/dist/cli/home-command.d.ts +26 -0
- package/dist/cli/home-command.js +156 -0
- package/dist/cli/removed-verbs.d.ts +0 -4
- package/dist/cli/removed-verbs.js +23 -12
- package/dist/cli/sa-preflight.d.ts +0 -14
- package/dist/cli/sa-preflight.js +1 -17
- package/dist/cli/startup.d.ts +1 -10
- package/dist/cli/startup.js +0 -40
- package/dist/cli.js +34 -80
- package/dist/client/core.js +13 -15
- package/dist/client/index.d.ts +2 -1
- package/dist/client/interface.d.ts +5 -14
- package/dist/client/with-spawn.d.ts +9 -4
- package/dist/client/with-spawn.js +7 -10
- package/dist/config.d.ts +14 -13
- package/dist/config.js +14 -0
- package/dist/constants.d.ts +50 -0
- package/dist/constants.js +60 -1
- package/dist/daemon.js +81 -0
- package/dist/http/auth.d.ts +3 -21
- package/dist/http/auth.js +10 -31
- package/dist/http/event-types.d.ts +38 -4
- package/dist/http/orphans.d.ts +3 -3
- package/dist/http/orphans.js +3 -3
- package/dist/http/server.d.ts +0 -5
- package/dist/http/server.js +79 -29
- package/dist/http/snapshot.js +3 -0
- package/dist/http/writes.d.ts +1 -1
- package/dist/http/writes.js +25 -2
- package/dist/observability/nondeterminism-alarm.d.ts +113 -0
- package/dist/observability/nondeterminism-alarm.js +162 -0
- package/dist/palette/index.d.ts +6 -7
- package/dist/palette/index.js +6 -7
- package/dist/pi/mission-control/actions.d.ts +67 -1
- package/dist/pi/mission-control/actions.js +61 -0
- package/dist/pi/mission-control/extension.d.ts +77 -0
- package/dist/pi/mission-control/extension.js +171 -0
- package/dist/pi/workflow-client.d.ts +14 -16
- package/dist/pi/workflow-client.js +18 -44
- package/dist/server-tools.js +30 -29
- package/dist/server.js +42 -0
- package/dist/tools/action-guard.d.ts +23 -0
- package/dist/tools/action-guard.js +33 -0
- package/dist/tools/coat-check.d.ts +20 -0
- package/dist/tools/coat-check.js +129 -0
- package/dist/tools/gate.d.ts +13 -0
- package/dist/tools/gate.js +88 -0
- package/dist/tools/schedule.d.ts +18 -0
- package/dist/tools/schedule.js +93 -1
- package/dist/tools/stage.d.ts +17 -0
- package/dist/tools/stage.js +85 -1
- package/dist/tools/state.d.ts +14 -0
- package/dist/tools/state.js +95 -0
- package/dist/types.d.ts +54 -7
- package/dist/upgrade/boot-guard.d.ts +95 -0
- package/dist/upgrade/boot-guard.js +88 -0
- package/dist/upgrade/from-upgrade.d.ts +95 -0
- package/dist/upgrade/from-upgrade.js +330 -0
- package/dist/upgrade/phase-engine.js +4 -1
- package/dist/utils/duration.d.ts +3 -6
- package/dist/utils/duration.js +3 -6
- package/dist/utils/format-hosts.d.ts +1 -1
- package/dist/utils/format-hosts.js +0 -2
- package/dist/utils/grpc-shutdown-guard.js +0 -4
- package/dist/utils/hosts.d.ts +4 -10
- package/dist/utils/hosts.js +12 -28
- package/dist/utils/orphan-guard.d.ts +37 -0
- package/dist/utils/orphan-guard.js +26 -0
- package/dist/utils/search-attributes.d.ts +28 -18
- package/dist/utils/search-attributes.js +48 -18
- package/dist/utils/visibility-deadline.d.ts +16 -0
- package/dist/utils/visibility-deadline.js +16 -0
- package/dist/workflows/maestro-signals.d.ts +0 -13
- package/dist/workflows/maestro-signals.js +6 -14
- package/dist/workflows/maestro.js +27 -32
- package/dist/workflows/scheduler.js +7 -1
- package/dist/workflows/session.js +237 -153
- package/dist/workflows/signals.d.ts +9 -1
- package/dist/workflows/signals.js +8 -6
- package/package.json +1 -6
- package/workflow-bundle.js +478 -225
- package/dist/cli/legacy-migration.d.ts +0 -35
- package/dist/cli/legacy-migration.js +0 -341
- package/dist/client/ensure-conductor-spawned.d.ts +0 -35
- package/dist/client/ensure-conductor-spawned.js +0 -48
- package/dist/tui/App.d.ts +0 -85
- package/dist/tui/App.js +0 -1791
- package/dist/tui/bootstrap-types.d.ts +0 -46
- package/dist/tui/bootstrap-types.js +0 -7
- package/dist/tui/commands.d.ts +0 -71
- package/dist/tui/commands.js +0 -1375
- package/dist/tui/components/ChatView.d.ts +0 -35
- package/dist/tui/components/ChatView.js +0 -54
- package/dist/tui/components/CommandPalette.d.ts +0 -21
- package/dist/tui/components/CommandPalette.js +0 -67
- package/dist/tui/components/ConversationStream.d.ts +0 -114
- package/dist/tui/components/ConversationStream.js +0 -307
- package/dist/tui/components/CreateEnsembleWizard.d.ts +0 -19
- package/dist/tui/components/CreateEnsembleWizard.js +0 -223
- package/dist/tui/components/DestroyConfirmModal.d.ts +0 -17
- package/dist/tui/components/DestroyConfirmModal.js +0 -62
- package/dist/tui/components/ErrorView.d.ts +0 -31
- package/dist/tui/components/ErrorView.js +0 -129
- package/dist/tui/components/HomeView.d.ts +0 -54
- package/dist/tui/components/HomeView.js +0 -306
- package/dist/tui/components/LoadLineupModal.d.ts +0 -18
- package/dist/tui/components/LoadLineupModal.js +0 -79
- package/dist/tui/components/MainView.d.ts +0 -21
- package/dist/tui/components/MainView.js +0 -107
- package/dist/tui/components/NewEnsembleModal.d.ts +0 -9
- package/dist/tui/components/NewEnsembleModal.js +0 -73
- package/dist/tui/components/Picker.d.ts +0 -23
- package/dist/tui/components/Picker.js +0 -70
- package/dist/tui/components/PlayerDetailView.d.ts +0 -26
- package/dist/tui/components/PlayerDetailView.js +0 -118
- package/dist/tui/components/PromptArea.d.ts +0 -50
- package/dist/tui/components/PromptArea.js +0 -303
- package/dist/tui/components/RecruitWizard.d.ts +0 -17
- package/dist/tui/components/RecruitWizard.js +0 -221
- package/dist/tui/components/RestoreConfirmModal.d.ts +0 -18
- package/dist/tui/components/RestoreConfirmModal.js +0 -71
- package/dist/tui/components/ScheduleWizard.d.ts +0 -19
- package/dist/tui/components/ScheduleWizard.js +0 -259
- package/dist/tui/components/Splash.d.ts +0 -23
- package/dist/tui/components/Splash.js +0 -221
- package/dist/tui/components/StatusBar.d.ts +0 -48
- package/dist/tui/components/StatusBar.js +0 -128
- package/dist/tui/components/StatusOverlay.d.ts +0 -15
- package/dist/tui/components/StatusOverlay.js +0 -76
- package/dist/tui/components/TitleBar.d.ts +0 -10
- package/dist/tui/components/TitleBar.js +0 -21
- package/dist/tui/index.d.ts +0 -15
- package/dist/tui/index.js +0 -162
- package/dist/tui/ink-context.d.ts +0 -18
- package/dist/tui/ink-context.js +0 -59
- package/dist/tui/ink-loader.d.ts +0 -26
- package/dist/tui/ink-loader.js +0 -42
- package/dist/tui/removed-commands.d.ts +0 -9
- package/dist/tui/removed-commands.js +0 -22
- package/dist/tui/sse-handler.d.ts +0 -52
- package/dist/tui/sse-handler.js +0 -157
- package/dist/tui/store.d.ts +0 -598
- package/dist/tui/store.js +0 -753
- package/dist/tui/utils/format.d.ts +0 -56
- package/dist/tui/utils/format.js +0 -155
- package/dist/tui/utils/fullscreen.d.ts +0 -23
- package/dist/tui/utils/fullscreen.js +0 -71
- package/dist/tui/utils/history.d.ts +0 -10
- package/dist/tui/utils/history.js +0 -85
- package/dist/tui/utils/platform.d.ts +0 -45
- package/dist/tui/utils/platform.js +0 -258
- package/dist/tui/utils/theme.d.ts +0 -21
- package/dist/tui/utils/theme.js +0 -24
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Picker = Picker;
|
|
7
|
-
/**
|
|
8
|
-
* Picker — generic interactive list overlay.
|
|
9
|
-
* Renders as a SINGLE Text element (1 Yoga node) with newlines for rows.
|
|
10
|
-
*/
|
|
11
|
-
const react_1 = __importDefault(require("react"));
|
|
12
|
-
const ink_context_1 = require("../ink-context");
|
|
13
|
-
const theme_1 = require("../utils/theme");
|
|
14
|
-
const MAX_VISIBLE = 10;
|
|
15
|
-
function Picker({ title, items, selectedIndex, hint }) {
|
|
16
|
-
const { Text } = (0, ink_context_1.useInk)();
|
|
17
|
-
if (items.length === 0) {
|
|
18
|
-
return react_1.default.createElement(Text, null, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent }, ` ${title}`), '\n', react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ' (none)'));
|
|
19
|
-
}
|
|
20
|
-
// Window around selected index
|
|
21
|
-
let startIdx = 0;
|
|
22
|
-
if (items.length > MAX_VISIBLE) {
|
|
23
|
-
startIdx = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE / 2), items.length - MAX_VISIBLE));
|
|
24
|
-
}
|
|
25
|
-
const visible = items.slice(startIdx, startIdx + MAX_VISIBLE);
|
|
26
|
-
const hasAbove = startIdx > 0;
|
|
27
|
-
const hasBelow = startIdx + MAX_VISIBLE < items.length;
|
|
28
|
-
const children = [];
|
|
29
|
-
// Title
|
|
30
|
-
children.push(react_1.default.createElement(Text, { key: 'title', bold: true, color: theme_1.THEME.accent }, ` ${title}`));
|
|
31
|
-
children.push('\n');
|
|
32
|
-
// Scroll-up
|
|
33
|
-
if (hasAbove) {
|
|
34
|
-
children.push(react_1.default.createElement(Text, { key: 'above', color: theme_1.THEME.dim }, ` \u2191 ${startIdx} more above`));
|
|
35
|
-
children.push('\n');
|
|
36
|
-
}
|
|
37
|
-
// Items (with optional group headers)
|
|
38
|
-
let lastGroup;
|
|
39
|
-
for (let i = 0; i < visible.length; i++) {
|
|
40
|
-
const item = visible[i];
|
|
41
|
-
const actualIdx = startIdx + i;
|
|
42
|
-
const isSelected = actualIdx === selectedIndex;
|
|
43
|
-
const indicator = isSelected ? '\u25B8 ' : ' ';
|
|
44
|
-
const currentMark = item.current ? ' \u25C0' : '';
|
|
45
|
-
const labelColor = isSelected ? theme_1.THEME.accent : (item.color || theme_1.THEME.text);
|
|
46
|
-
const icon = item.icon ? `${item.icon} ` : '';
|
|
47
|
-
// Group header
|
|
48
|
-
if (item.group && item.group !== lastGroup) {
|
|
49
|
-
if (i > 0 || lastGroup !== undefined)
|
|
50
|
-
children.push('\n');
|
|
51
|
-
children.push('\n');
|
|
52
|
-
children.push(react_1.default.createElement(Text, { key: `grp-${item.group}`, color: theme_1.THEME.dim }, ` \u2500\u2500 ${item.group} \u2500\u2500`));
|
|
53
|
-
lastGroup = item.group;
|
|
54
|
-
}
|
|
55
|
-
if (i > 0 || lastGroup !== undefined)
|
|
56
|
-
children.push('\n');
|
|
57
|
-
children.push(react_1.default.createElement(react_1.default.Fragment, { key: item.id }, react_1.default.createElement(Text, { color: isSelected ? theme_1.THEME.accent : theme_1.THEME.dim }, indicator), react_1.default.createElement(Text, { color: labelColor, bold: isSelected }, `${icon}${item.label}`), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ` ${item.detail}`), item.meta ? react_1.default.createElement(Text, { color: theme_1.THEME.muted }, ` ${item.meta}`) : null, currentMark ? react_1.default.createElement(Text, { color: theme_1.THEME.warning }, currentMark) : null));
|
|
58
|
-
}
|
|
59
|
-
// Scroll-down
|
|
60
|
-
if (hasBelow) {
|
|
61
|
-
children.push('\n');
|
|
62
|
-
children.push(react_1.default.createElement(Text, { key: 'below', color: theme_1.THEME.dim }, ` \u2193 ${items.length - startIdx - MAX_VISIBLE} more below`));
|
|
63
|
-
}
|
|
64
|
-
// Hint
|
|
65
|
-
if (hint) {
|
|
66
|
-
children.push('\n');
|
|
67
|
-
children.push(react_1.default.createElement(Text, { key: 'hint', color: theme_1.THEME.dim }, ` ${hint}`));
|
|
68
|
-
}
|
|
69
|
-
return react_1.default.createElement(Text, null, ...children);
|
|
70
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PlayerDetailView — shows player metadata + scrollable message history.
|
|
3
|
-
* Single <Text> pattern, zero Yoga nodes — all content pre-formatted as strings.
|
|
4
|
-
*
|
|
5
|
-
* PR-F cross-host indicator (design §16, brief §8 answer 3 — Option 3):
|
|
6
|
-
* - Local session (`player.hostname === localHost`) → omit "Host:" field
|
|
7
|
-
* from the metadata line (reduces noise; local is the common case).
|
|
8
|
-
* - Remote session → show `Host: {hostname}` in `THEME.accent` (amber).
|
|
9
|
-
* Zero new Yoga nodes: the host segment goes into the same `<Text>` children
|
|
10
|
-
* tree as an additional nested `<Text>` (virtual text node, not a Box).
|
|
11
|
-
*/
|
|
12
|
-
import React from 'react';
|
|
13
|
-
import type { MaestroPlayerInfo, SessionMetadata, Message, SentMessage } from '../../types';
|
|
14
|
-
export interface PlayerDetailViewProps {
|
|
15
|
-
playerId: string;
|
|
16
|
-
ensemble: string;
|
|
17
|
-
player: MaestroPlayerInfo | null;
|
|
18
|
-
metadata: SessionMetadata | null;
|
|
19
|
-
messages: Array<Message | (SentMessage & {
|
|
20
|
-
direction: 'sent';
|
|
21
|
-
})>;
|
|
22
|
-
scrollOffset: number;
|
|
23
|
-
/** Local TUI process hostname. When equal to the player's hostname, the Host field is omitted. */
|
|
24
|
-
localHost?: string;
|
|
25
|
-
}
|
|
26
|
-
export declare function PlayerDetailView({ playerId, player, metadata, messages, scrollOffset, localHost, }: PlayerDetailViewProps): React.CElement<{}, React.Component<{}, any, any>>;
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PlayerDetailView = PlayerDetailView;
|
|
7
|
-
/**
|
|
8
|
-
* PlayerDetailView — shows player metadata + scrollable message history.
|
|
9
|
-
* Single <Text> pattern, zero Yoga nodes — all content pre-formatted as strings.
|
|
10
|
-
*
|
|
11
|
-
* PR-F cross-host indicator (design §16, brief §8 answer 3 — Option 3):
|
|
12
|
-
* - Local session (`player.hostname === localHost`) → omit "Host:" field
|
|
13
|
-
* from the metadata line (reduces noise; local is the common case).
|
|
14
|
-
* - Remote session → show `Host: {hostname}` in `THEME.accent` (amber).
|
|
15
|
-
* Zero new Yoga nodes: the host segment goes into the same `<Text>` children
|
|
16
|
-
* tree as an additional nested `<Text>` (virtual text node, not a Box).
|
|
17
|
-
*/
|
|
18
|
-
const react_1 = __importDefault(require("react"));
|
|
19
|
-
const ink_context_1 = require("../ink-context");
|
|
20
|
-
const theme_1 = require("../utils/theme");
|
|
21
|
-
const format_1 = require("../utils/format");
|
|
22
|
-
const platform_1 = require("../utils/platform");
|
|
23
|
-
const MAX_VISIBLE = 20;
|
|
24
|
-
function isSent(m) {
|
|
25
|
-
return 'direction' in m && m.direction === 'sent';
|
|
26
|
-
}
|
|
27
|
-
function formatTime(ts) {
|
|
28
|
-
try {
|
|
29
|
-
const d = new Date(ts);
|
|
30
|
-
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return '??:??';
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function PlayerDetailView({ playerId, player, metadata, messages, scrollOffset, localHost, }) {
|
|
37
|
-
const { Text } = (0, ink_context_1.useInk)();
|
|
38
|
-
const children = [];
|
|
39
|
-
// Header — player identity
|
|
40
|
-
const icon = player?.isConductor ? '\u2605 ' : ' ';
|
|
41
|
-
children.push(react_1.default.createElement(Text, { key: 'name', bold: true, color: theme_1.THEME.accent }, `${icon}${playerId}`));
|
|
42
|
-
// Metadata line 1: Type · Status [· Host when remote]
|
|
43
|
-
// Collapse the attachment phase via the Option-B helpers in utils/format.
|
|
44
|
-
const type = player?.playerType || player?.agentType || '(default)';
|
|
45
|
-
const status = (0, format_1.phaseToLabel)(player?.phase);
|
|
46
|
-
const phaseIcons = (0, platform_1.statusIcons)((0, platform_1.supportsUnicode)());
|
|
47
|
-
const statusDot = phaseIcons[(0, format_1.phaseToIconName)(player?.phase)];
|
|
48
|
-
const host = player?.hostname || metadata?.hostname || '';
|
|
49
|
-
const showRemoteHost = Boolean(host && localHost && host !== localHost);
|
|
50
|
-
children.push('\n');
|
|
51
|
-
if (showRemoteHost) {
|
|
52
|
-
// Remote — Host segment rendered in amber, same Text tree (zero Yoga nodes).
|
|
53
|
-
children.push(react_1.default.createElement(Text, { key: 'meta1', color: theme_1.THEME.dim }, ` Type: ${type} \u00B7 Status: ${statusDot} ${status} \u00B7 Host: `, react_1.default.createElement(Text, { color: theme_1.THEME.accent }, host)));
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
// Local (or unknown) — omit Host entirely.
|
|
57
|
-
children.push(react_1.default.createElement(Text, { key: 'meta1', color: theme_1.THEME.dim }, ` Type: ${type} \u00B7 Status: ${statusDot} ${status}`));
|
|
58
|
-
}
|
|
59
|
-
// Metadata line 2: Branch · Dir
|
|
60
|
-
const branch = player?.gitBranch || metadata?.gitBranch || '';
|
|
61
|
-
const dir = metadata?.workDir || player?.workDir || '';
|
|
62
|
-
if (branch || dir) {
|
|
63
|
-
children.push('\n');
|
|
64
|
-
const parts = [];
|
|
65
|
-
if (branch)
|
|
66
|
-
parts.push(`Branch: ${branch}`);
|
|
67
|
-
if (dir)
|
|
68
|
-
parts.push(`Dir: ${dir}`);
|
|
69
|
-
children.push(react_1.default.createElement(Text, { key: 'meta2', color: theme_1.THEME.dim }, ` ${parts.join(' \u00B7 ')}`));
|
|
70
|
-
}
|
|
71
|
-
// Part
|
|
72
|
-
if (player?.part) {
|
|
73
|
-
children.push('\n');
|
|
74
|
-
children.push(react_1.default.createElement(Text, { key: 'part', color: theme_1.THEME.textMuted }, ` Part: ${player.part}`));
|
|
75
|
-
}
|
|
76
|
-
// Divider
|
|
77
|
-
children.push('\n\n');
|
|
78
|
-
children.push(react_1.default.createElement(Text, { key: 'div', color: theme_1.THEME.border }, ' ' + '\u2500'.repeat(55)));
|
|
79
|
-
// Messages header
|
|
80
|
-
const total = messages.length;
|
|
81
|
-
const windowStart = Math.min(scrollOffset, Math.max(0, total - MAX_VISIBLE));
|
|
82
|
-
const visible = messages.slice(windowStart, windowStart + MAX_VISIBLE);
|
|
83
|
-
const earlierCount = windowStart;
|
|
84
|
-
children.push('\n');
|
|
85
|
-
if (total === 0) {
|
|
86
|
-
children.push(react_1.default.createElement(Text, { key: 'nomsg', color: theme_1.THEME.dim }, ' No messages yet.'));
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
children.push(react_1.default.createElement(Text, { key: 'mhdr', color: theme_1.THEME.dim }, ` Messages (${total} total \u00B7 showing ${visible.length})`));
|
|
90
|
-
// #110: use the plural-aware helper instead of hardcoded "earlier messages".
|
|
91
|
-
// The helper returns null for count ≤ 0 / non-finite, subsuming the prior
|
|
92
|
-
// `if (earlierCount > 0)` guard. Singular/plural split is covered by the
|
|
93
|
-
// helper's unit tests in `tests/tui/chat-cap.test.ts`.
|
|
94
|
-
const earlierIndicator = (0, format_1.formatEarlierIndicator)(earlierCount);
|
|
95
|
-
if (earlierIndicator) {
|
|
96
|
-
children.push('\n');
|
|
97
|
-
children.push(react_1.default.createElement(Text, { key: 'earlier', color: theme_1.THEME.dim }, ` ${earlierIndicator}`));
|
|
98
|
-
}
|
|
99
|
-
for (let i = 0; i < visible.length; i++) {
|
|
100
|
-
const m = visible[i];
|
|
101
|
-
const time = formatTime(m.timestamp);
|
|
102
|
-
children.push('\n');
|
|
103
|
-
if (isSent(m)) {
|
|
104
|
-
const preview = m.text.length > 80 ? m.text.slice(0, 77).replace(/\n/g, ' ') + '...' : m.text.replace(/\n/g, ' ');
|
|
105
|
-
children.push(react_1.default.createElement(react_1.default.Fragment, { key: `m-${i}` }, react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ` ${time} `), react_1.default.createElement(Text, { color: theme_1.THEME.accent, bold: true }, '\u276F '), react_1.default.createElement(Text, { color: theme_1.THEME.text }, preview)));
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
const msg = m;
|
|
109
|
-
const preview = msg.text.length > 80 ? msg.text.slice(0, 77).replace(/\n/g, ' ') + '...' : msg.text.replace(/\n/g, ' ');
|
|
110
|
-
children.push(react_1.default.createElement(react_1.default.Fragment, { key: `m-${i}` }, react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ` ${time} \u2190 `), react_1.default.createElement(Text, { color: theme_1.THEME.accent }, `${msg.from}: `), react_1.default.createElement(Text, { color: theme_1.THEME.text }, preview)));
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
// Footer hint
|
|
115
|
-
children.push('\n\n');
|
|
116
|
-
children.push(react_1.default.createElement(Text, { key: 'hint', color: theme_1.THEME.dim }, ' \u2191\u2193 scroll \u00B7 Esc back \u00B7 /cue to chat'));
|
|
117
|
-
return react_1.default.createElement(Text, null, ...children);
|
|
118
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PromptArea — pinned bottom input area with tab completion and command history.
|
|
3
|
-
*
|
|
4
|
-
* UNCONTROLLED: Input value lives in local useState, NOT in parent state.
|
|
5
|
-
* This prevents parent re-renders on every keystroke, keeping Yoga node
|
|
6
|
-
* recalculation to this subtree only (~4 nodes).
|
|
7
|
-
*
|
|
8
|
-
* Parent communicates via:
|
|
9
|
-
* - inputRef.current.setValue(v) — to set input programmatically (palette select)
|
|
10
|
-
* - inputRef.current.getValue() — to read current value
|
|
11
|
-
* - onInputChange(v) — called on every keystroke (for palette filtering via ref, no dispatch)
|
|
12
|
-
* - onSubmit(v) — called on Enter
|
|
13
|
-
*/
|
|
14
|
-
import React from 'react';
|
|
15
|
-
/** Commands that take a player name as their first argument. */
|
|
16
|
-
export interface PromptAreaHandle {
|
|
17
|
-
setValue: (v: string) => void;
|
|
18
|
-
getValue: () => string;
|
|
19
|
-
}
|
|
20
|
-
export interface PromptAreaProps {
|
|
21
|
-
/** Hint text displayed above the input. */
|
|
22
|
-
hints: string;
|
|
23
|
-
/** Called when user presses Enter. */
|
|
24
|
-
onSubmit: (value: string) => void;
|
|
25
|
-
/** Disable input (e.g., during splash or recruit wizard). */
|
|
26
|
-
disabled?: boolean;
|
|
27
|
-
/** Available command names (without '/') for tab completion. */
|
|
28
|
-
commandNames?: string[];
|
|
29
|
-
/** Available player names for argument completion. */
|
|
30
|
-
playerNames?: string[];
|
|
31
|
-
/** Initial command history (loaded from disk). */
|
|
32
|
-
initialHistory?: string[];
|
|
33
|
-
/** Called when history is updated (for persistence). */
|
|
34
|
-
onHistoryUpdate?: (entries: string[]) => void;
|
|
35
|
-
/** Called on every input change (lightweight — caller should use ref, not dispatch). */
|
|
36
|
-
onInputChange?: (value: string) => void;
|
|
37
|
-
/** Whether the command palette is visible. */
|
|
38
|
-
paletteVisible?: boolean;
|
|
39
|
-
/** Called when palette should show/hide. */
|
|
40
|
-
onPaletteToggle?: (visible: boolean) => void;
|
|
41
|
-
/** Called to navigate palette up. */
|
|
42
|
-
onPaletteUp?: () => void;
|
|
43
|
-
/** Called to navigate palette down. */
|
|
44
|
-
onPaletteDown?: () => void;
|
|
45
|
-
/** Called when palette item is selected. */
|
|
46
|
-
onPaletteSelect?: () => void;
|
|
47
|
-
/** Ref for parent to read/set input value. */
|
|
48
|
-
inputRef?: React.Ref<PromptAreaHandle>;
|
|
49
|
-
}
|
|
50
|
-
export declare const PromptArea: React.NamedExoticComponent<PromptAreaProps>;
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.PromptArea = void 0;
|
|
37
|
-
/**
|
|
38
|
-
* PromptArea — pinned bottom input area with tab completion and command history.
|
|
39
|
-
*
|
|
40
|
-
* UNCONTROLLED: Input value lives in local useState, NOT in parent state.
|
|
41
|
-
* This prevents parent re-renders on every keystroke, keeping Yoga node
|
|
42
|
-
* recalculation to this subtree only (~4 nodes).
|
|
43
|
-
*
|
|
44
|
-
* Parent communicates via:
|
|
45
|
-
* - inputRef.current.setValue(v) — to set input programmatically (palette select)
|
|
46
|
-
* - inputRef.current.getValue() — to read current value
|
|
47
|
-
* - onInputChange(v) — called on every keystroke (for palette filtering via ref, no dispatch)
|
|
48
|
-
* - onSubmit(v) — called on Enter
|
|
49
|
-
*/
|
|
50
|
-
const react_1 = __importStar(require("react"));
|
|
51
|
-
const ink_context_1 = require("../ink-context");
|
|
52
|
-
const theme_1 = require("../utils/theme");
|
|
53
|
-
const commands_1 = require("../commands");
|
|
54
|
-
const MAX_HISTORY = 50;
|
|
55
|
-
exports.PromptArea = react_1.default.memo(function PromptArea({ hints, onSubmit, disabled, commandNames = [], playerNames = [], initialHistory = [], onHistoryUpdate, onInputChange, paletteVisible, onPaletteToggle, onPaletteUp, onPaletteDown, onPaletteSelect, inputRef, }) {
|
|
56
|
-
const { Box, Text, useInput } = (0, ink_context_1.useInk)();
|
|
57
|
-
// ── LOCAL input state (uncontrolled — no parent dispatch per keystroke) ──
|
|
58
|
-
const [value, setValueState] = (0, react_1.useState)('');
|
|
59
|
-
const valueRef = (0, react_1.useRef)('');
|
|
60
|
-
const setValue = (0, react_1.useCallback)((v) => {
|
|
61
|
-
valueRef.current = v;
|
|
62
|
-
ref.current.value = v; // Keep ref in sync between renders (prevents stale reads on rapid input)
|
|
63
|
-
setValueState(v);
|
|
64
|
-
}, []);
|
|
65
|
-
// ── Expose handle for parent ──
|
|
66
|
-
(0, react_1.useImperativeHandle)(inputRef, () => ({
|
|
67
|
-
setValue: (v) => setValue(v),
|
|
68
|
-
getValue: () => valueRef.current,
|
|
69
|
-
}), [setValue]);
|
|
70
|
-
// ── Internal state ──
|
|
71
|
-
const [history, setHistory] = (0, react_1.useState)(() => [...initialHistory]);
|
|
72
|
-
const [historyIndex, setHistoryIndex] = (0, react_1.useState)(-1);
|
|
73
|
-
const savedInput = (0, react_1.useRef)('');
|
|
74
|
-
const [completionHint, setCompletionHint] = (0, react_1.useState)('');
|
|
75
|
-
const [tabMatches, setTabMatches] = (0, react_1.useState)([]);
|
|
76
|
-
const [tabCycleIndex, setTabCycleIndex] = (0, react_1.useState)(0);
|
|
77
|
-
// ── Ref for all values the useInput callback reads (stable callback pattern) ──
|
|
78
|
-
const ref = (0, react_1.useRef)({
|
|
79
|
-
value: '', onSubmit, disabled, commandNames, playerNames,
|
|
80
|
-
history, historyIndex, tabMatches, tabCycleIndex,
|
|
81
|
-
paletteVisible, onPaletteToggle, onPaletteUp, onPaletteDown, onPaletteSelect,
|
|
82
|
-
onHistoryUpdate, onInputChange,
|
|
83
|
-
});
|
|
84
|
-
ref.current = {
|
|
85
|
-
value: valueRef.current, onSubmit, disabled, commandNames, playerNames,
|
|
86
|
-
history, historyIndex, tabMatches, tabCycleIndex,
|
|
87
|
-
paletteVisible, onPaletteToggle, onPaletteUp, onPaletteDown, onPaletteSelect,
|
|
88
|
-
onHistoryUpdate, onInputChange,
|
|
89
|
-
};
|
|
90
|
-
// ── Helpers (read from ref) ──
|
|
91
|
-
const doChange = (0, react_1.useCallback)((newValue) => {
|
|
92
|
-
const r = ref.current;
|
|
93
|
-
setValue(newValue);
|
|
94
|
-
r.onInputChange?.(newValue);
|
|
95
|
-
// Avoid new refs when already in default state — prevents unnecessary re-renders
|
|
96
|
-
setCompletionHint(prev => prev === '' ? prev : '');
|
|
97
|
-
setTabMatches(prev => prev.length === 0 ? prev : []);
|
|
98
|
-
setTabCycleIndex(prev => prev === 0 ? prev : 0);
|
|
99
|
-
// Only toggle palette when visibility actually changes — avoids parent dispatch on every keystroke
|
|
100
|
-
if (r.onPaletteToggle) {
|
|
101
|
-
// The palette shows for: "/cmd", "@name", and "/PLAYER_PARAM_CMD <partial>".
|
|
102
|
-
// classifyPaletteInput centralizes the rule so PromptArea + App stay in sync.
|
|
103
|
-
const shouldShow = (0, commands_1.classifyPaletteInput)(newValue) !== null;
|
|
104
|
-
if (shouldShow !== !!r.paletteVisible) {
|
|
105
|
-
r.onPaletteToggle(shouldShow);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}, [setValue]);
|
|
109
|
-
// PLAYER_PARAM_COMMANDS and SUBCOMMAND_MAP imported from commands.ts
|
|
110
|
-
const getCompletions = (0, react_1.useCallback)((input) => {
|
|
111
|
-
const r = ref.current;
|
|
112
|
-
const trimmed = input.trimStart();
|
|
113
|
-
// Command name completion: /par → /players
|
|
114
|
-
if (trimmed.startsWith('/') && !trimmed.includes(' ')) {
|
|
115
|
-
const partial = trimmed.slice(1).toLowerCase();
|
|
116
|
-
if (!partial)
|
|
117
|
-
return r.commandNames.map(c => `/${c} `);
|
|
118
|
-
return r.commandNames
|
|
119
|
-
.filter(c => c.startsWith(partial) && c !== partial)
|
|
120
|
-
.map(c => `/${c} `);
|
|
121
|
-
}
|
|
122
|
-
// Parameter completion: /stop te → /stop tempo-eng
|
|
123
|
-
if (trimmed.startsWith('/') && trimmed.includes(' ')) {
|
|
124
|
-
const spaceIdx = trimmed.indexOf(' ');
|
|
125
|
-
const cmd = trimmed.slice(1, spaceIdx).toLowerCase();
|
|
126
|
-
const afterCmd = trimmed.slice(spaceIdx + 1);
|
|
127
|
-
const parts = afterCmd.split(' ');
|
|
128
|
-
const partial = parts[parts.length - 1].toLowerCase();
|
|
129
|
-
const prefix = trimmed.slice(0, trimmed.length - parts[parts.length - 1].length);
|
|
130
|
-
// First param: player name for player commands (prefix + segment match)
|
|
131
|
-
if (parts.length === 1 && commands_1.PLAYER_PARAM_COMMANDS.has(cmd)) {
|
|
132
|
-
const names = r.playerNames || [];
|
|
133
|
-
const matches = names.filter(n => {
|
|
134
|
-
const lower = n.toLowerCase();
|
|
135
|
-
if (lower === partial)
|
|
136
|
-
return false;
|
|
137
|
-
return lower.startsWith(partial) || lower.split('-').some(seg => seg.startsWith(partial));
|
|
138
|
-
});
|
|
139
|
-
if (matches.length > 0)
|
|
140
|
-
return matches.map(n => `${prefix}${n} `);
|
|
141
|
-
}
|
|
142
|
-
// First param: subcommand for structured commands
|
|
143
|
-
if (parts.length === 1 && commands_1.SUBCOMMAND_MAP[cmd]) {
|
|
144
|
-
const subs = commands_1.SUBCOMMAND_MAP[cmd];
|
|
145
|
-
const matches = subs.filter(s => s.startsWith(partial) && s !== partial);
|
|
146
|
-
if (matches.length > 0)
|
|
147
|
-
return matches.map(s => `${prefix}${s} `);
|
|
148
|
-
}
|
|
149
|
-
// Second param after subcommand: player name for worktree create/remove
|
|
150
|
-
if (parts.length === 2 && cmd === 'worktree' && (parts[0] === 'create' || parts[0] === 'remove')) {
|
|
151
|
-
const names = r.playerNames || [];
|
|
152
|
-
const matches = names.filter(n => n.toLowerCase().startsWith(partial) && n.toLowerCase() !== partial);
|
|
153
|
-
if (matches.length > 0)
|
|
154
|
-
return matches.map(n => `${prefix}${n} `);
|
|
155
|
-
}
|
|
156
|
-
return [];
|
|
157
|
-
}
|
|
158
|
-
// @player completion: @tem → @tempo-eng
|
|
159
|
-
if (trimmed.startsWith('@') && !trimmed.includes(' ')) {
|
|
160
|
-
const partial = trimmed.slice(1).toLowerCase();
|
|
161
|
-
if (!partial)
|
|
162
|
-
return r.playerNames.map(n => `@${n} `);
|
|
163
|
-
return r.playerNames
|
|
164
|
-
.filter(n => {
|
|
165
|
-
const lower = n.toLowerCase();
|
|
166
|
-
if (lower === partial)
|
|
167
|
-
return false;
|
|
168
|
-
return lower.startsWith(partial) || lower.split('-').some(seg => seg.startsWith(partial));
|
|
169
|
-
})
|
|
170
|
-
.map(n => `@${n} `);
|
|
171
|
-
}
|
|
172
|
-
return [];
|
|
173
|
-
}, []);
|
|
174
|
-
// ── Stable useInput callback (never recreated) ──
|
|
175
|
-
useInput((0, react_1.useCallback)((input, key) => {
|
|
176
|
-
const r = ref.current;
|
|
177
|
-
if (r.disabled)
|
|
178
|
-
return;
|
|
179
|
-
// ── Command palette mode ──
|
|
180
|
-
if (r.paletteVisible) {
|
|
181
|
-
if (key.upArrow) {
|
|
182
|
-
r.onPaletteUp?.();
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if (key.downArrow) {
|
|
186
|
-
r.onPaletteDown?.();
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
if (key.tab) {
|
|
190
|
-
r.onPaletteSelect?.();
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
if (key.return) {
|
|
194
|
-
// Enter always submits. Use Tab to accept a palette suggestion. This
|
|
195
|
-
// avoids accept-vs-submit ambiguity when the typed command already
|
|
196
|
-
// matches exactly but the palette has no remaining suggestions
|
|
197
|
-
// (e.g. "/destroy conductor"). Close the palette and fall through to
|
|
198
|
-
// the regular Enter/submit block below.
|
|
199
|
-
r.onPaletteToggle?.(false);
|
|
200
|
-
}
|
|
201
|
-
if (key.escape) {
|
|
202
|
-
r.onPaletteToggle?.(false);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
// Tab: complete
|
|
207
|
-
if (key.tab) {
|
|
208
|
-
const matches = r.tabMatches.length > 0 ? r.tabMatches : getCompletions(r.value);
|
|
209
|
-
if (matches.length === 0)
|
|
210
|
-
return;
|
|
211
|
-
if (matches.length === 1) {
|
|
212
|
-
setValue(matches[0]);
|
|
213
|
-
r.onInputChange?.(matches[0]);
|
|
214
|
-
setCompletionHint('');
|
|
215
|
-
setTabMatches([]);
|
|
216
|
-
setTabCycleIndex(0);
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
const newMatches = r.tabMatches.length > 0 ? r.tabMatches : matches;
|
|
220
|
-
const idx = r.tabMatches.length > 0 ? (r.tabCycleIndex + 1) % newMatches.length : 0;
|
|
221
|
-
setValue(newMatches[idx]);
|
|
222
|
-
r.onInputChange?.(newMatches[idx]);
|
|
223
|
-
setTabMatches(newMatches);
|
|
224
|
-
setTabCycleIndex(idx);
|
|
225
|
-
const options = newMatches.map(m => m.trim().split(/\s+/).pop() || '');
|
|
226
|
-
setCompletionHint(options.join(' '));
|
|
227
|
-
}
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
// Up arrow: previous history
|
|
231
|
-
if (key.upArrow && !r.paletteVisible) {
|
|
232
|
-
if (r.history.length === 0)
|
|
233
|
-
return;
|
|
234
|
-
if (r.historyIndex === -1)
|
|
235
|
-
savedInput.current = r.value;
|
|
236
|
-
const newIdx = Math.min(r.historyIndex + 1, r.history.length - 1);
|
|
237
|
-
setHistoryIndex(newIdx);
|
|
238
|
-
const histValue = r.history[r.history.length - 1 - newIdx];
|
|
239
|
-
setValue(histValue);
|
|
240
|
-
r.onInputChange?.(histValue);
|
|
241
|
-
setCompletionHint('');
|
|
242
|
-
setTabMatches([]);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
// Down arrow: next history
|
|
246
|
-
if (key.downArrow && !r.paletteVisible) {
|
|
247
|
-
if (r.historyIndex <= 0) {
|
|
248
|
-
setHistoryIndex(-1);
|
|
249
|
-
setValue(savedInput.current);
|
|
250
|
-
r.onInputChange?.(savedInput.current);
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
const newIdx = r.historyIndex - 1;
|
|
254
|
-
setHistoryIndex(newIdx);
|
|
255
|
-
const histValue = r.history[r.history.length - 1 - newIdx];
|
|
256
|
-
setValue(histValue);
|
|
257
|
-
r.onInputChange?.(histValue);
|
|
258
|
-
setCompletionHint('');
|
|
259
|
-
setTabMatches([]);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
// Enter: submit
|
|
263
|
-
if (key.return) {
|
|
264
|
-
const trimmed = r.value.trim();
|
|
265
|
-
if (trimmed) {
|
|
266
|
-
if (r.history.length === 0 || r.history[r.history.length - 1] !== trimmed) {
|
|
267
|
-
const updated = [...r.history, trimmed].slice(-MAX_HISTORY);
|
|
268
|
-
setHistory(updated);
|
|
269
|
-
if (r.onHistoryUpdate)
|
|
270
|
-
r.onHistoryUpdate(updated);
|
|
271
|
-
}
|
|
272
|
-
setHistoryIndex(-1);
|
|
273
|
-
savedInput.current = '';
|
|
274
|
-
r.onSubmit(trimmed);
|
|
275
|
-
}
|
|
276
|
-
setValue('');
|
|
277
|
-
r.onInputChange?.('');
|
|
278
|
-
setCompletionHint('');
|
|
279
|
-
setTabMatches([]);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
// Backspace
|
|
283
|
-
if (key.backspace || key.delete) {
|
|
284
|
-
if (r.value.length > 0)
|
|
285
|
-
doChange(r.value.slice(0, -1));
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
// Regular character input
|
|
289
|
-
if (input && !key.ctrl && !key.meta) {
|
|
290
|
-
doChange(r.value + input);
|
|
291
|
-
}
|
|
292
|
-
}, [doChange, getCompletions, setValue])); // Stable — reads ref.current
|
|
293
|
-
// ── Render (minimal nodes: 1 Box + 2-3 Text, nested Text = 0 Yoga nodes) ──
|
|
294
|
-
return react_1.default.createElement(Box, { flexDirection: 'column', paddingX: 1 }, completionHint
|
|
295
|
-
? react_1.default.createElement(Text, { color: theme_1.THEME.muted }, ` ${completionHint}`)
|
|
296
|
-
: null,
|
|
297
|
-
// Prompt line with inline placeholder hint (like Claude Code)
|
|
298
|
-
react_1.default.createElement(Text, null, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent }, '\u2669 '), disabled
|
|
299
|
-
? react_1.default.createElement(Text, { color: theme_1.THEME.muted }, '...')
|
|
300
|
-
: value
|
|
301
|
-
? react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement(Text, { color: theme_1.THEME.text }, value), react_1.default.createElement(Text, { color: theme_1.THEME.accent }, '\u2588'))
|
|
302
|
-
: react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement(Text, { color: theme_1.THEME.accent }, '\u2588'), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, hints))));
|
|
303
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RecruitWizard — step-by-step wizard for spawning a new player session.
|
|
3
|
-
*
|
|
4
|
-
* Minimal-Box pattern: single <Text> root for all static content (0 Yoga nodes),
|
|
5
|
-
* with ONE <Box> wrapper for Ink's TextInput when a text-input step is active.
|
|
6
|
-
*/
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import type { RecruitState, RecruitAnswers } from '../store';
|
|
9
|
-
export interface RecruitWizardProps {
|
|
10
|
-
state: RecruitState;
|
|
11
|
-
onAnswer: (answer: Partial<RecruitAnswers>) => void;
|
|
12
|
-
onBack: () => void;
|
|
13
|
-
onConfirm: () => void;
|
|
14
|
-
onCancel: () => void;
|
|
15
|
-
onDone: () => void;
|
|
16
|
-
}
|
|
17
|
-
export declare function RecruitWizard({ state, onAnswer, onBack, onConfirm, onCancel, onDone }: RecruitWizardProps): React.FunctionComponentElement<React.FragmentProps> | React.CElement<{}, React.Component<{}, any, any>>;
|