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.
Files changed (171) hide show
  1. package/CLAUDE.md +10 -13
  2. package/README.md +21 -15
  3. package/dashboard/dist/assets/index-BbR7zIdK.js.map +1 -1
  4. package/dashboard/package.json +1 -1
  5. package/dist/activities/hard-terminate.d.ts +2 -2
  6. package/dist/activities/hard-terminate.js +3 -9
  7. package/dist/activities/maestro.d.ts +8 -13
  8. package/dist/activities/maestro.js +3 -10
  9. package/dist/activities/outbox.js +16 -2
  10. package/dist/activities/resolve.d.ts +18 -7
  11. package/dist/activities/resolve.js +58 -46
  12. package/dist/adapters/base.js +3 -0
  13. package/dist/adapters/claude-code/adapter.js +7 -0
  14. package/dist/cli/command-center-command.js +15 -1
  15. package/dist/cli/commands.d.ts +8 -0
  16. package/dist/cli/commands.js +79 -11
  17. package/dist/cli/daemon-command.js +19 -33
  18. package/dist/cli/help-text.js +9 -7
  19. package/dist/cli/home-command.d.ts +26 -0
  20. package/dist/cli/home-command.js +156 -0
  21. package/dist/cli/removed-verbs.d.ts +0 -4
  22. package/dist/cli/removed-verbs.js +23 -12
  23. package/dist/cli/sa-preflight.d.ts +0 -14
  24. package/dist/cli/sa-preflight.js +1 -17
  25. package/dist/cli/startup.d.ts +1 -10
  26. package/dist/cli/startup.js +0 -40
  27. package/dist/cli.js +34 -80
  28. package/dist/client/core.js +13 -15
  29. package/dist/client/index.d.ts +2 -1
  30. package/dist/client/interface.d.ts +5 -14
  31. package/dist/client/with-spawn.d.ts +9 -4
  32. package/dist/client/with-spawn.js +7 -10
  33. package/dist/config.d.ts +14 -13
  34. package/dist/config.js +14 -0
  35. package/dist/constants.d.ts +50 -0
  36. package/dist/constants.js +60 -1
  37. package/dist/daemon.js +81 -0
  38. package/dist/http/auth.d.ts +3 -21
  39. package/dist/http/auth.js +10 -31
  40. package/dist/http/event-types.d.ts +38 -4
  41. package/dist/http/orphans.d.ts +3 -3
  42. package/dist/http/orphans.js +3 -3
  43. package/dist/http/server.d.ts +0 -5
  44. package/dist/http/server.js +79 -29
  45. package/dist/http/snapshot.js +3 -0
  46. package/dist/http/writes.d.ts +1 -1
  47. package/dist/http/writes.js +25 -2
  48. package/dist/observability/nondeterminism-alarm.d.ts +113 -0
  49. package/dist/observability/nondeterminism-alarm.js +162 -0
  50. package/dist/palette/index.d.ts +6 -7
  51. package/dist/palette/index.js +6 -7
  52. package/dist/pi/mission-control/actions.d.ts +67 -1
  53. package/dist/pi/mission-control/actions.js +61 -0
  54. package/dist/pi/mission-control/extension.d.ts +77 -0
  55. package/dist/pi/mission-control/extension.js +171 -0
  56. package/dist/pi/workflow-client.d.ts +14 -16
  57. package/dist/pi/workflow-client.js +18 -44
  58. package/dist/server-tools.js +30 -29
  59. package/dist/server.js +42 -0
  60. package/dist/tools/action-guard.d.ts +23 -0
  61. package/dist/tools/action-guard.js +33 -0
  62. package/dist/tools/coat-check.d.ts +20 -0
  63. package/dist/tools/coat-check.js +129 -0
  64. package/dist/tools/gate.d.ts +13 -0
  65. package/dist/tools/gate.js +88 -0
  66. package/dist/tools/schedule.d.ts +18 -0
  67. package/dist/tools/schedule.js +93 -1
  68. package/dist/tools/stage.d.ts +17 -0
  69. package/dist/tools/stage.js +85 -1
  70. package/dist/tools/state.d.ts +14 -0
  71. package/dist/tools/state.js +95 -0
  72. package/dist/types.d.ts +54 -7
  73. package/dist/upgrade/boot-guard.d.ts +95 -0
  74. package/dist/upgrade/boot-guard.js +88 -0
  75. package/dist/upgrade/from-upgrade.d.ts +95 -0
  76. package/dist/upgrade/from-upgrade.js +330 -0
  77. package/dist/upgrade/phase-engine.js +4 -1
  78. package/dist/utils/duration.d.ts +3 -6
  79. package/dist/utils/duration.js +3 -6
  80. package/dist/utils/format-hosts.d.ts +1 -1
  81. package/dist/utils/format-hosts.js +0 -2
  82. package/dist/utils/grpc-shutdown-guard.js +0 -4
  83. package/dist/utils/hosts.d.ts +4 -10
  84. package/dist/utils/hosts.js +12 -28
  85. package/dist/utils/orphan-guard.d.ts +37 -0
  86. package/dist/utils/orphan-guard.js +26 -0
  87. package/dist/utils/search-attributes.d.ts +28 -18
  88. package/dist/utils/search-attributes.js +48 -18
  89. package/dist/utils/visibility-deadline.d.ts +16 -0
  90. package/dist/utils/visibility-deadline.js +16 -0
  91. package/dist/workflows/maestro-signals.d.ts +0 -13
  92. package/dist/workflows/maestro-signals.js +6 -14
  93. package/dist/workflows/maestro.js +27 -32
  94. package/dist/workflows/scheduler.js +7 -1
  95. package/dist/workflows/session.js +237 -153
  96. package/dist/workflows/signals.d.ts +9 -1
  97. package/dist/workflows/signals.js +8 -6
  98. package/package.json +1 -6
  99. package/workflow-bundle.js +478 -225
  100. package/dist/cli/legacy-migration.d.ts +0 -35
  101. package/dist/cli/legacy-migration.js +0 -341
  102. package/dist/client/ensure-conductor-spawned.d.ts +0 -35
  103. package/dist/client/ensure-conductor-spawned.js +0 -48
  104. package/dist/tui/App.d.ts +0 -85
  105. package/dist/tui/App.js +0 -1791
  106. package/dist/tui/bootstrap-types.d.ts +0 -46
  107. package/dist/tui/bootstrap-types.js +0 -7
  108. package/dist/tui/commands.d.ts +0 -71
  109. package/dist/tui/commands.js +0 -1375
  110. package/dist/tui/components/ChatView.d.ts +0 -35
  111. package/dist/tui/components/ChatView.js +0 -54
  112. package/dist/tui/components/CommandPalette.d.ts +0 -21
  113. package/dist/tui/components/CommandPalette.js +0 -67
  114. package/dist/tui/components/ConversationStream.d.ts +0 -114
  115. package/dist/tui/components/ConversationStream.js +0 -307
  116. package/dist/tui/components/CreateEnsembleWizard.d.ts +0 -19
  117. package/dist/tui/components/CreateEnsembleWizard.js +0 -223
  118. package/dist/tui/components/DestroyConfirmModal.d.ts +0 -17
  119. package/dist/tui/components/DestroyConfirmModal.js +0 -62
  120. package/dist/tui/components/ErrorView.d.ts +0 -31
  121. package/dist/tui/components/ErrorView.js +0 -129
  122. package/dist/tui/components/HomeView.d.ts +0 -54
  123. package/dist/tui/components/HomeView.js +0 -306
  124. package/dist/tui/components/LoadLineupModal.d.ts +0 -18
  125. package/dist/tui/components/LoadLineupModal.js +0 -79
  126. package/dist/tui/components/MainView.d.ts +0 -21
  127. package/dist/tui/components/MainView.js +0 -107
  128. package/dist/tui/components/NewEnsembleModal.d.ts +0 -9
  129. package/dist/tui/components/NewEnsembleModal.js +0 -73
  130. package/dist/tui/components/Picker.d.ts +0 -23
  131. package/dist/tui/components/Picker.js +0 -70
  132. package/dist/tui/components/PlayerDetailView.d.ts +0 -26
  133. package/dist/tui/components/PlayerDetailView.js +0 -118
  134. package/dist/tui/components/PromptArea.d.ts +0 -50
  135. package/dist/tui/components/PromptArea.js +0 -303
  136. package/dist/tui/components/RecruitWizard.d.ts +0 -17
  137. package/dist/tui/components/RecruitWizard.js +0 -221
  138. package/dist/tui/components/RestoreConfirmModal.d.ts +0 -18
  139. package/dist/tui/components/RestoreConfirmModal.js +0 -71
  140. package/dist/tui/components/ScheduleWizard.d.ts +0 -19
  141. package/dist/tui/components/ScheduleWizard.js +0 -259
  142. package/dist/tui/components/Splash.d.ts +0 -23
  143. package/dist/tui/components/Splash.js +0 -221
  144. package/dist/tui/components/StatusBar.d.ts +0 -48
  145. package/dist/tui/components/StatusBar.js +0 -128
  146. package/dist/tui/components/StatusOverlay.d.ts +0 -15
  147. package/dist/tui/components/StatusOverlay.js +0 -76
  148. package/dist/tui/components/TitleBar.d.ts +0 -10
  149. package/dist/tui/components/TitleBar.js +0 -21
  150. package/dist/tui/index.d.ts +0 -15
  151. package/dist/tui/index.js +0 -162
  152. package/dist/tui/ink-context.d.ts +0 -18
  153. package/dist/tui/ink-context.js +0 -59
  154. package/dist/tui/ink-loader.d.ts +0 -26
  155. package/dist/tui/ink-loader.js +0 -42
  156. package/dist/tui/removed-commands.d.ts +0 -9
  157. package/dist/tui/removed-commands.js +0 -22
  158. package/dist/tui/sse-handler.d.ts +0 -52
  159. package/dist/tui/sse-handler.js +0 -157
  160. package/dist/tui/store.d.ts +0 -598
  161. package/dist/tui/store.js +0 -753
  162. package/dist/tui/utils/format.d.ts +0 -56
  163. package/dist/tui/utils/format.js +0 -155
  164. package/dist/tui/utils/fullscreen.d.ts +0 -23
  165. package/dist/tui/utils/fullscreen.js +0 -71
  166. package/dist/tui/utils/history.d.ts +0 -10
  167. package/dist/tui/utils/history.js +0 -85
  168. package/dist/tui/utils/platform.d.ts +0 -45
  169. package/dist/tui/utils/platform.js +0 -258
  170. package/dist/tui/utils/theme.d.ts +0 -21
  171. package/dist/tui/utils/theme.js +0 -24
@@ -1,221 +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.RecruitWizard = RecruitWizard;
37
- /**
38
- * RecruitWizard — step-by-step wizard for spawning a new player session.
39
- *
40
- * Minimal-Box pattern: single <Text> root for all static content (0 Yoga nodes),
41
- * with ONE <Box> wrapper for Ink's TextInput when a text-input step is active.
42
- */
43
- const react_1 = __importStar(require("react"));
44
- const ink_context_1 = require("../ink-context");
45
- const theme_1 = require("../utils/theme");
46
- /** Step labels for display. */
47
- const STEP_LABELS = {
48
- name: 'Player name',
49
- agent: 'Agent',
50
- type: 'Player type',
51
- workDir: 'Working directory',
52
- message: 'Initial message (optional)',
53
- host: 'Host',
54
- confirm: 'Confirm',
55
- done: 'Done',
56
- };
57
- const TEXT_INPUT_STEPS = new Set(['name', 'type', 'workDir', 'message', 'host']);
58
- function RecruitWizard({ state, onAnswer, onBack, onConfirm, onCancel, onDone }) {
59
- const { Box, Text, TextInput, useInput } = (0, ink_context_1.useInk)();
60
- const [inputValue, setInputValue] = (0, react_1.useState)('');
61
- const [agentIndex, setAgentIndex] = (0, react_1.useState)(state.answers.agent === 'copilot' ? 1 : 0);
62
- const agents = ['claude', 'copilot'];
63
- // Global keybindings for wizard
64
- useInput((0, react_1.useCallback)((input, key) => {
65
- if (key.escape) {
66
- onCancel();
67
- return;
68
- }
69
- if (key.backspace && state.step !== 'name' && state.step !== 'done' && !inputValue) {
70
- onBack();
71
- return;
72
- }
73
- if (state.step === 'agent') {
74
- if (key.leftArrow || key.rightArrow) {
75
- setAgentIndex(i => i === 0 ? 1 : 0);
76
- }
77
- if (key.return) {
78
- onAnswer({ agent: agents[agentIndex] });
79
- setInputValue('');
80
- }
81
- }
82
- if (state.step === 'confirm') {
83
- if (key.return)
84
- onConfirm();
85
- }
86
- if (state.step === 'done') {
87
- if (key.return)
88
- onDone();
89
- }
90
- }, [state.step, agentIndex, inputValue, onAnswer, onBack, onCancel, onConfirm, onDone]));
91
- // Text input submit for text steps
92
- const handleTextSubmit = (0, react_1.useCallback)((value) => {
93
- const trimmed = value.trim();
94
- switch (state.step) {
95
- case 'name':
96
- if (!trimmed)
97
- return;
98
- onAnswer({ name: trimmed });
99
- break;
100
- case 'type':
101
- onAnswer({ playerType: trimmed });
102
- break;
103
- case 'workDir':
104
- onAnswer({ workDir: trimmed || state.answers.workDir });
105
- break;
106
- case 'message':
107
- onAnswer({ initialMessage: trimmed });
108
- break;
109
- case 'host':
110
- onAnswer({ host: trimmed || 'localhost' });
111
- break;
112
- }
113
- setInputValue('');
114
- }, [state.step, state.answers.workDir, onAnswer]);
115
- // ── Build all content as nested Text children ──
116
- const children = [];
117
- // Header
118
- children.push(react_1.default.createElement(react_1.default.Fragment, { key: 'hdr' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent }, ' Recruit New Player'), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ' (Esc to cancel, Backspace to go back)')));
119
- // Completed steps
120
- const steps = ['name', 'agent', 'type', 'workDir', 'message', 'host'];
121
- for (const s of steps) {
122
- if (s === state.step)
123
- break;
124
- const value = getAnswerDisplay(s, state.answers);
125
- children.push('\n');
126
- children.push(react_1.default.createElement(react_1.default.Fragment, { key: `done-${s}` }, react_1.default.createElement(Text, { color: theme_1.THEME.success }, ' \u2714 '), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, `${STEP_LABELS[s]}: `), react_1.default.createElement(Text, { color: theme_1.THEME.text }, value)));
127
- }
128
- // Current step content
129
- if (state.step === 'agent') {
130
- children.push('\n\n');
131
- children.push(react_1.default.createElement(react_1.default.Fragment, { key: 'agent-q' }, react_1.default.createElement(Text, { color: theme_1.THEME.accent }, ' ? '), react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, `${STEP_LABELS.agent}:`)));
132
- children.push('\n');
133
- for (let i = 0; i < agents.length; i++) {
134
- const selected = i === agentIndex;
135
- const icon = selected ? '\u25CF' : '\u25CB';
136
- children.push(react_1.default.createElement(Text, { key: `ag-${agents[i]}`, color: selected ? theme_1.THEME.accent : theme_1.THEME.dim, bold: selected }, ` ${icon} ${agents[i]} `));
137
- }
138
- children.push('\n');
139
- children.push(react_1.default.createElement(Text, { key: 'ag-hint', color: theme_1.THEME.dim }, ' \u2190\u2192 to select, Enter to confirm'));
140
- }
141
- else if (state.step === 'confirm') {
142
- const a = state.answers;
143
- children.push('\n\n');
144
- children.push(react_1.default.createElement(Text, { key: 'sum-h', bold: true, color: theme_1.THEME.accent }, ' Recruit Summary:'));
145
- children.push('\n');
146
- children.push(react_1.default.createElement(Text, { key: 'sum-n', color: theme_1.THEME.text }, ` Name: ${a.name}`));
147
- children.push('\n');
148
- children.push(react_1.default.createElement(Text, { key: 'sum-a', color: theme_1.THEME.text }, ` Agent: ${a.agent}`));
149
- children.push('\n');
150
- children.push(react_1.default.createElement(Text, { key: 'sum-t', color: theme_1.THEME.text }, ` Type: ${a.playerType || '(default)'}`));
151
- children.push('\n');
152
- children.push(react_1.default.createElement(Text, { key: 'sum-d', color: theme_1.THEME.text }, ` Directory: ${a.workDir}`));
153
- children.push('\n');
154
- children.push(react_1.default.createElement(Text, { key: 'sum-m', color: theme_1.THEME.text }, ` Message: ${a.initialMessage || '(none)'}`));
155
- children.push('\n');
156
- children.push(react_1.default.createElement(Text, { key: 'sum-h2', color: theme_1.THEME.text }, ` Host: ${a.host}`));
157
- children.push('\n\n');
158
- children.push(react_1.default.createElement(Text, { key: 'sum-hint', color: theme_1.THEME.dim }, ' Press Enter to recruit, Esc to cancel'));
159
- }
160
- else if (state.step === 'done') {
161
- children.push('\n\n');
162
- if (state.error) {
163
- children.push(react_1.default.createElement(Text, { key: 'err', color: theme_1.THEME.error, bold: true }, ` \u2717 Recruit failed: ${state.error}`));
164
- children.push('\n');
165
- children.push(react_1.default.createElement(Text, { key: 'err-h', color: theme_1.THEME.dim }, ' Press Enter to return'));
166
- }
167
- else {
168
- children.push(react_1.default.createElement(Text, { key: 'ok1', color: theme_1.THEME.success }, ' \u2714 Workflow created'));
169
- children.push('\n');
170
- children.push(react_1.default.createElement(Text, { key: 'ok2', color: theme_1.THEME.success }, ' \u2714 Initial message queued'));
171
- children.push('\n');
172
- children.push(react_1.default.createElement(Text, { key: 'ok3', color: theme_1.THEME.success }, ' \u2714 Process spawned'));
173
- children.push('\n\n');
174
- children.push(react_1.default.createElement(Text, { key: 'ok-h', color: theme_1.THEME.dim }, ' Press Enter to return'));
175
- }
176
- }
177
- else if (state.submitting) {
178
- children.push('\n\n');
179
- children.push(react_1.default.createElement(Text, { key: 'sub', color: theme_1.THEME.warning }, ` Recruiting ${state.answers.name}...`));
180
- }
181
- else if (TEXT_INPUT_STEPS.has(state.step)) {
182
- // Text input step — prompt line as Text, input in minimal Box
183
- const defaultHint = getDefaultHint(state.step, state.answers);
184
- children.push('\n\n');
185
- children.push(react_1.default.createElement(react_1.default.Fragment, { key: 'inp-q' }, react_1.default.createElement(Text, { color: theme_1.THEME.accent }, ' ? '), react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, `${STEP_LABELS[state.step]}:`), defaultHint
186
- ? react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ` (${defaultHint})`)
187
- : null));
188
- // TextInput needs a Box — this is the only Box in the component
189
- // It renders AFTER the Text block below
190
- }
191
- // For text-input steps: render Text block + Box(TextInput) in a Fragment
192
- // For all other steps: single Text element (0 Yoga Box nodes)
193
- if (TEXT_INPUT_STEPS.has(state.step) && !state.submitting) {
194
- return react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement(Text, null, ...children), react_1.default.createElement(Box, { marginLeft: 3 }, react_1.default.createElement(Text, { color: theme_1.THEME.accent }, '> '), react_1.default.createElement(TextInput, {
195
- value: inputValue,
196
- onChange: setInputValue,
197
- onSubmit: handleTextSubmit,
198
- })));
199
- }
200
- return react_1.default.createElement(Text, null, ...children);
201
- }
202
- function getAnswerDisplay(step, answers) {
203
- switch (step) {
204
- case 'name': return answers.name;
205
- case 'agent': return answers.agent;
206
- case 'type': return answers.playerType || '(default)';
207
- case 'workDir': return answers.workDir;
208
- case 'message': return answers.initialMessage || '(none)';
209
- case 'host': return answers.host;
210
- default: return '';
211
- }
212
- }
213
- function getDefaultHint(step, answers) {
214
- switch (step) {
215
- case 'workDir': return answers.workDir;
216
- case 'host': return 'localhost';
217
- case 'message': return 'press Enter to skip';
218
- case 'type': return 'press Enter for default';
219
- default: return null;
220
- }
221
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * Single-keypress y/N confirmation before restoring an offline ensemble.
3
- * Restore is recoverable (operator can `shutdown` again), so no typed
4
- * confirmation — that's reserved for `destroy`.
5
- */
6
- import React from 'react';
7
- export interface RestoreConfirmModalProps {
8
- ensemble: string;
9
- /** Number of offline players in the ensemble (conductor excluded from the count). */
10
- playerCount: number;
11
- /** Conductor name if known — falls back to the default "conductor" label. */
12
- conductorName?: string;
13
- onConfirm: () => void;
14
- onCancel: () => void;
15
- submitting?: boolean;
16
- error?: string | null;
17
- }
18
- export declare function RestoreConfirmModal(props: RestoreConfirmModalProps): React.ReactElement;
@@ -1,71 +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.RestoreConfirmModal = RestoreConfirmModal;
37
- /**
38
- * Single-keypress y/N confirmation before restoring an offline ensemble.
39
- * Restore is recoverable (operator can `shutdown` again), so no typed
40
- * confirmation — that's reserved for `destroy`.
41
- */
42
- const react_1 = __importStar(require("react"));
43
- const ink_context_1 = require("../ink-context");
44
- const theme_1 = require("../utils/theme");
45
- function RestoreConfirmModal(props) {
46
- const { ensemble, playerCount, conductorName, onConfirm, onCancel, submitting, error } = props;
47
- const { Box, Text, useInput } = (0, ink_context_1.useInk)();
48
- useInput((0, react_1.useCallback)((input, key) => {
49
- if (submitting)
50
- return;
51
- if (key.escape) {
52
- onCancel();
53
- return;
54
- }
55
- const ch = input.toLowerCase();
56
- if (ch === 'y') {
57
- onConfirm();
58
- return;
59
- }
60
- if (ch === 'n' || key.return) {
61
- onCancel();
62
- return;
63
- }
64
- }, [submitting, onCancel, onConfirm]));
65
- const conductorLabel = conductorName ?? 'conductor';
66
- return react_1.default.createElement(Box, { flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent }, ' Restore offline ensemble'), react_1.default.createElement(Box, { marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { color: theme_1.THEME.text }, ` Ensemble: ${ensemble}`), react_1.default.createElement(Text, { color: theme_1.THEME.text }, ` Offline players: ${playerCount}${playerCount === 0 ? ' (conductor only)' : ''}`), react_1.default.createElement(Text, { color: theme_1.THEME.text }, ` Conductor: ${conductorLabel}`)), error
67
- ? react_1.default.createElement(Text, { color: theme_1.THEME.error }, ` \u2717 ${error}`)
68
- : null, submitting
69
- ? react_1.default.createElement(Box, { marginTop: 1 }, react_1.default.createElement(Text, { color: theme_1.THEME.warning }, `\u2026 Restoring "${ensemble}" on this host\u2026`))
70
- : react_1.default.createElement(Box, { marginTop: 1 }, react_1.default.createElement(Text, { bold: true }, ' Restore to this computer? '), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, '[y/N] (Esc to cancel)')));
71
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * ScheduleWizard — step-by-step wizard for creating a scheduled message.
3
- * Steps: target → message → schedule type → timing → timezone (cron only) → confirm.
4
- * Escape cancels. Backspace on empty input goes back a step.
5
- *
6
- * Minimal-Box pattern: single <Text> root for all static content (0 Yoga nodes).
7
- * Uses manual key handling — no TextInput component, so zero Box elements needed.
8
- */
9
- import React from 'react';
10
- import type { ScheduleWizardState, ScheduleAnswers } from '../store';
11
- export interface ScheduleWizardProps {
12
- state: ScheduleWizardState;
13
- onAnswer: (answer: Partial<ScheduleAnswers>) => void;
14
- onBack: () => void;
15
- onConfirm: () => void;
16
- onCancel: () => void;
17
- onDone: () => void;
18
- }
19
- export declare function ScheduleWizard({ state, onAnswer, onBack, onConfirm, onCancel, onDone }: ScheduleWizardProps): React.CElement<{}, React.Component<{}, any, any>>;
@@ -1,259 +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.ScheduleWizard = ScheduleWizard;
37
- /**
38
- * ScheduleWizard — step-by-step wizard for creating a scheduled message.
39
- * Steps: target → message → schedule type → timing → timezone (cron only) → confirm.
40
- * Escape cancels. Backspace on empty input goes back a step.
41
- *
42
- * Minimal-Box pattern: single <Text> root for all static content (0 Yoga nodes).
43
- * Uses manual key handling — no TextInput component, so zero Box elements needed.
44
- */
45
- const react_1 = __importStar(require("react"));
46
- const ink_context_1 = require("../ink-context");
47
- const theme_1 = require("../utils/theme");
48
- const STEP_LABELS = {
49
- target: 'Target player',
50
- message: 'Message to deliver',
51
- schedType: 'Schedule type',
52
- timing: 'Timing',
53
- timezone: 'Timezone (for cron)',
54
- confirm: 'Confirm',
55
- done: 'Done',
56
- };
57
- const SCHED_TYPE_OPTIONS = [
58
- { value: 'delay', label: 'One-shot delay', hint: 'e.g., 5m, 1h, 30s' },
59
- { value: 'at', label: 'Fixed time', hint: 'e.g., 2026-04-07T09:00:00' },
60
- { value: 'every', label: 'Recurring interval', hint: 'e.g., 30m, 1h, 6h' },
61
- { value: 'cron', label: 'Cron expression', hint: 'e.g., 0 9 * * * (daily 9am)' },
62
- ];
63
- const TIMING_HINTS = {
64
- delay: 'Enter delay duration (e.g., 5m, 1h, 30s):',
65
- at: 'Enter ISO datetime (e.g., 2026-04-07T09:00:00):',
66
- every: 'Enter interval (e.g., 30m, 1h, 6h):',
67
- cron: 'Enter cron expression (e.g., 0 9 * * *):',
68
- };
69
- function ScheduleWizard({ state, onAnswer, onBack, onConfirm, onCancel, onDone }) {
70
- const { Text, useInput } = (0, ink_context_1.useInk)();
71
- const [inputValue, setInputValue] = (0, react_1.useState)('');
72
- const [showRequired, setShowRequired] = (0, react_1.useState)(false);
73
- const [typeIndex, setTypeIndex] = (0, react_1.useState)(SCHED_TYPE_OPTIONS.findIndex(o => o.value === state.answers.schedType));
74
- useInput((0, react_1.useCallback)((input, key) => {
75
- if (key.escape) {
76
- onCancel();
77
- return;
78
- }
79
- // Done step
80
- if (state.step === 'done') {
81
- if (key.return)
82
- onDone();
83
- return;
84
- }
85
- // Backspace on empty input → go back
86
- if ((key.backspace || key.delete) && state.step !== 'target' && !inputValue) {
87
- onBack();
88
- return;
89
- }
90
- // Schedule type selection step
91
- if (state.step === 'schedType') {
92
- if (key.upArrow) {
93
- setTypeIndex(i => Math.max(0, i - 1));
94
- return;
95
- }
96
- if (key.downArrow) {
97
- setTypeIndex(i => Math.min(SCHED_TYPE_OPTIONS.length - 1, i + 1));
98
- return;
99
- }
100
- if (key.return) {
101
- const selected = SCHED_TYPE_OPTIONS[typeIndex];
102
- const name = `${state.answers.target}-${selected.value}-${Date.now().toString(36)}`;
103
- onAnswer({ schedType: selected.value, name });
104
- setInputValue('');
105
- return;
106
- }
107
- return;
108
- }
109
- // Confirm step
110
- if (state.step === 'confirm') {
111
- if (key.return) {
112
- onConfirm();
113
- }
114
- return;
115
- }
116
- // Empty enter — show validation hint
117
- if (key.return && !inputValue.trim() && ['target', 'message', 'timing', 'timezone'].includes(state.step)) {
118
- setShowRequired(true);
119
- return;
120
- }
121
- // Text input steps
122
- if (key.return && inputValue.trim()) {
123
- const val = inputValue.trim();
124
- switch (state.step) {
125
- case 'target':
126
- onAnswer({ target: val });
127
- break;
128
- case 'message':
129
- onAnswer({ message: val });
130
- break;
131
- case 'timing':
132
- onAnswer({ timing: val });
133
- break;
134
- case 'timezone':
135
- onAnswer({ timezone: val });
136
- break;
137
- }
138
- setInputValue('');
139
- return;
140
- }
141
- // Backspace
142
- if (key.backspace || key.delete) {
143
- if (inputValue.length > 0)
144
- setInputValue(v => v.slice(0, -1));
145
- return;
146
- }
147
- // Regular character
148
- if (input && !key.ctrl && !key.meta && !key.tab) {
149
- setInputValue(v => v + input);
150
- if (showRequired)
151
- setShowRequired(false);
152
- }
153
- }, [state.step, inputValue, typeIndex, onAnswer, onBack, onConfirm, onCancel, onDone, state.answers.target]));
154
- // ── Progress indicator ──
155
- const steps = ['target', 'message', 'schedType', 'timing', 'confirm'];
156
- const currentStepIdx = steps.indexOf(state.step === 'timezone' ? 'timing' : state.step === 'done' ? 'confirm' : state.step);
157
- const progressDots = steps.map((_, i) => i <= currentStepIdx ? '\u25CF' : '\u25CB').join(' ');
158
- // ── Build content ──
159
- const children = [];
160
- // Header
161
- children.push(react_1.default.createElement(react_1.default.Fragment, { key: 'hdr' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent }, ' Create Schedule'), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ` ${progressDots}`)));
162
- // Completed answers as breadcrumbs
163
- const completedSteps = [];
164
- if (state.answers.target && state.step !== 'target') {
165
- completedSteps.push(['Target', state.answers.target]);
166
- }
167
- if (state.answers.message && state.step !== 'message' && state.step !== 'target') {
168
- const msg = state.answers.message.length > 40 ? state.answers.message.slice(0, 37) + '...' : state.answers.message;
169
- completedSteps.push(['Message', msg]);
170
- }
171
- if (state.answers.schedType && ['timing', 'timezone', 'confirm', 'done'].includes(state.step)) {
172
- completedSteps.push(['Type', state.answers.schedType]);
173
- }
174
- if (state.answers.timing && ['timezone', 'confirm', 'done'].includes(state.step)) {
175
- completedSteps.push(['Timing', state.answers.timing]);
176
- }
177
- for (const [label, value] of completedSteps) {
178
- children.push('\n');
179
- children.push(react_1.default.createElement(Text, { key: `bc-${label}`, color: theme_1.THEME.dim }, ` \u2713 ${label}: ${value}`));
180
- }
181
- // Current step content
182
- if (state.step === 'schedType') {
183
- children.push('\n\n');
184
- children.push(react_1.default.createElement(Text, { key: 'prompt', color: theme_1.THEME.text }, ` ${STEP_LABELS[state.step]}:`));
185
- for (let i = 0; i < SCHED_TYPE_OPTIONS.length; i++) {
186
- const opt = SCHED_TYPE_OPTIONS[i];
187
- const selected = i === typeIndex;
188
- children.push('\n');
189
- children.push(react_1.default.createElement(Text, {
190
- key: `opt-${i}`,
191
- color: selected ? theme_1.THEME.accent : theme_1.THEME.textMuted,
192
- bold: selected,
193
- }, ` ${selected ? '\u25B6' : ' '} ${opt.label} ${selected ? `(${opt.hint})` : ''}`));
194
- }
195
- children.push('\n\n');
196
- children.push(react_1.default.createElement(Text, { key: 'nav', color: theme_1.THEME.dim }, ' \u2191\u2193 select, Enter to confirm'));
197
- }
198
- else if (state.step === 'confirm') {
199
- // Summary with text-based border
200
- const boxWidth = 50;
201
- const hLine = '\u2500'.repeat(boxWidth);
202
- children.push('\n\n');
203
- children.push(react_1.default.createElement(Text, { key: 'bt', color: theme_1.THEME.dim }, ` \u250C${hLine}\u2510`));
204
- children.push('\n');
205
- children.push(react_1.default.createElement(Text, { key: 'bh', bold: true, color: theme_1.THEME.text }, ' \u2502 Schedule Summary'));
206
- children.push(react_1.default.createElement(Text, { key: 'bh2', color: theme_1.THEME.dim }, ' '.repeat(boxWidth - 17) + '\u2502'));
207
- const summaryLines = [
208
- `Name: ${state.answers.name}`,
209
- `Target: ${state.answers.target}`,
210
- `Message: ${state.answers.message}`,
211
- `Type: ${state.answers.schedType}`,
212
- `Timing: ${state.answers.timing}`,
213
- ];
214
- if (state.answers.timezone) {
215
- summaryLines.push(`Timezone: ${state.answers.timezone}`);
216
- }
217
- for (let i = 0; i < summaryLines.length; i++) {
218
- const line = summaryLines[i];
219
- const pad = ' '.repeat(Math.max(0, boxWidth - line.length - 2));
220
- children.push('\n');
221
- children.push(react_1.default.createElement(Text, { key: `sl-${i}`, color: theme_1.THEME.textMuted }, ` \u2502 ${line}`));
222
- children.push(react_1.default.createElement(Text, { key: `sp-${i}`, color: theme_1.THEME.dim }, `${pad}\u2502`));
223
- }
224
- children.push('\n');
225
- children.push(react_1.default.createElement(Text, { key: 'bb', color: theme_1.THEME.dim }, ` \u2514${hLine}\u2518`));
226
- children.push('\n\n');
227
- children.push(react_1.default.createElement(Text, { key: 'confirm-hint', color: theme_1.THEME.dim }, ' Enter to create, Esc to cancel, Backspace to go back'));
228
- if (state.submitting) {
229
- children.push('\n');
230
- children.push(react_1.default.createElement(Text, { key: 'submitting', color: theme_1.THEME.warning }, ' Creating schedule...'));
231
- }
232
- }
233
- else if (state.step === 'done') {
234
- children.push('\n');
235
- if (state.error) {
236
- children.push(react_1.default.createElement(Text, { key: 'err', color: theme_1.THEME.error }, `\n \u2717 ${state.error}`));
237
- children.push('\n');
238
- children.push(react_1.default.createElement(Text, { key: 'err-hint', color: theme_1.THEME.dim }, ' Press Enter to dismiss.'));
239
- }
240
- else {
241
- children.push(react_1.default.createElement(Text, { key: 'ok', color: theme_1.THEME.success }, `\n \u2713 Schedule "${state.answers.name}" created!`));
242
- children.push('\n');
243
- children.push(react_1.default.createElement(Text, { key: 'ok-hint', color: theme_1.THEME.dim }, ' Press Enter to return.'));
244
- }
245
- }
246
- else {
247
- // Text input steps
248
- const hint = state.step === 'timing' ? TIMING_HINTS[state.answers.schedType] : `${STEP_LABELS[state.step]}:`;
249
- children.push('\n\n');
250
- children.push(react_1.default.createElement(Text, { key: 'prompt', color: theme_1.THEME.text }, ` ${hint}`));
251
- children.push('\n');
252
- children.push(react_1.default.createElement(react_1.default.Fragment, { key: 'input' }, react_1.default.createElement(Text, { color: theme_1.THEME.accent }, ' > '), react_1.default.createElement(Text, { color: theme_1.THEME.text }, inputValue), react_1.default.createElement(Text, { color: theme_1.THEME.accent }, '\u2588'), showRequired ? react_1.default.createElement(Text, { color: 'red' }, ' (required)') : null));
253
- if (state.step !== 'target') {
254
- children.push('\n');
255
- children.push(react_1.default.createElement(Text, { key: 'back-hint', color: theme_1.THEME.dim }, ' Backspace on empty to go back, Esc to cancel'));
256
- }
257
- }
258
- return react_1.default.createElement(Text, null, ...children);
259
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * Splash screen — landing/home screen with animated metronome, connection
3
- * status, and ensemble picker.
4
- *
5
- * Uses a single Text element with nested virtual-text nodes to minimize
6
- * Yoga layout nodes (target: <10 total).
7
- */
8
- import React from 'react';
9
- export interface EnsembleInfo {
10
- name: string;
11
- playerCount: number;
12
- hasConductor: boolean;
13
- }
14
- export interface SplashProps {
15
- status: string;
16
- ensemble?: string;
17
- version: string;
18
- connected?: boolean;
19
- ensembles?: EnsembleInfo[];
20
- onContinue?: (selectedEnsemble?: string) => void;
21
- onCreateEnsemble?: () => void;
22
- }
23
- export declare function Splash({ status, version, connected, ensembles, onContinue, onCreateEnsemble }: SplashProps): React.CElement<{}, React.Component<{}, any, any>>;