@higherdev/cli 0.14.3 → 0.14.4

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/dist/tui/App.js CHANGED
@@ -18,7 +18,8 @@ import { alertOnce } from "./alert.js";
18
18
  import { bubbleRows } from "./height.js";
19
19
  import { planLayout, splitPanels } from "./layout.js";
20
20
  import { parseLine } from "./parse.js";
21
- import { configuredSlugs, acknowledgeInbox, approveEpic, cancelTicket, createAgent, createEpicFromFile, decisionOptions, deleteAgent, loadLiveEvents, listWorkspaceEnv, loadTicketDetail, pollSnapshot, postAgentMessage, queueTicket, resolveDecision, setWorkspacePaused, switchWorkspace, updateAgent, updateProviderCap, updateWorkspace, } from "./data.js";
21
+ import { configuredSlugs, acknowledgeInbox, approveEpic, cancelTicket, createAgent, createEpicFromFile, decisionOptions, deleteAgent, loadLiveEvents, listWorkspaceEnv, loadTicketDetail, pollSnapshot, postAgentMessage, queueTicket, resolveDecision, setWorkspacePaused, switchWorkspace, updateAgent, updateProviderCap, updateWorkspace, waitForReply, } from "./data.js";
22
+ import { inputActive, promptPlaceholder, QUEUED_STEP, REPLY_WAIT_MS, settleChatReply } from "./chat-wait.js";
22
23
  import { editFor, editableKeys, nextValue, seedFor, settingsRows } from "./settings-model.js";
23
24
  import { appendLines, runLabels, toStreamLines } from "./stream.js";
24
25
  import { UI } from "./theme.js";
@@ -215,30 +216,26 @@ export function App({ initial }) {
215
216
  setBusy(false);
216
217
  }
217
218
  }, [config, say]);
218
- const askAgent = useCallback(async (role, text) => {
219
- setBusy(true);
219
+ const askAgent = useCallback((role, text) => {
220
220
  const id = nextId();
221
221
  setMessages((prior) => [...prior, { id, speaker: role, body: "", pending: true }]);
222
222
  const since = new Date().toISOString();
223
- try {
224
- await postAgentMessage(role, text, config);
225
- setMessages((prior) => prior.map((message) => message.id === id
226
- ? { ...message, steps: ["· queued, it answers on the next tick"] }
227
- : message));
228
- const { waitForReply } = await import("./data.js");
229
- const reply = await waitForReply(config, role, since, 180_000);
230
- setMessages((prior) => prior.map((message) => message.id === id
231
- ? { ...message, body: reply ?? "No reply yet. It will land in /inbox.", pending: false, steps: [] }
232
- : message));
233
- }
234
- catch (error) {
235
- const body = error instanceof Error ? error.message : String(error);
236
- setMessages((prior) => prior.map((message) => message.id === id ? { ...message, body, pending: false } : message));
237
- }
238
- finally {
239
- setMessages((prior) => prior.map((message) => message.id === id ? { ...message, done: true } : message));
240
- setBusy(false);
241
- }
223
+ void (async () => {
224
+ try {
225
+ await postAgentMessage(role, text, config);
226
+ setMessages((prior) => prior.map((message) => message.id === id
227
+ ? { ...message, steps: [QUEUED_STEP] }
228
+ : message));
229
+ const reply = await waitForReply(config, role, since, REPLY_WAIT_MS);
230
+ setMessages((prior) => prior.map((message) => message.id === id
231
+ ? { ...message, ...settleChatReply(reply) }
232
+ : message));
233
+ }
234
+ catch (error) {
235
+ const body = error instanceof Error ? error.message : String(error);
236
+ setMessages((prior) => prior.map((message) => message.id === id ? { ...message, body, pending: false, done: true } : message));
237
+ }
238
+ })();
242
239
  }, [config]);
243
240
  const run = useCallback(async (raw) => {
244
241
  const text = raw.trim();
@@ -281,7 +278,7 @@ export function App({ initial }) {
281
278
  if (action.kind === "say") {
282
279
  say("you", text);
283
280
  if (mode !== "browse")
284
- await askAgent(mode, text);
281
+ askAgent(mode, text);
285
282
  else
286
283
  setNotice("Use /architect or /orchestrator before sending a message.");
287
284
  return;
@@ -589,7 +586,7 @@ export function App({ initial }) {
589
586
  setDraft(next);
590
587
  if (editingRef.current)
591
588
  setEditing({ key: editingRef.current.key, draft: next });
592
- }, onSubmit: (value) => void run(value), isActive: !busy, placeholder: busy ? "working…" : "message, or /help", prompt: _jsx(Text, { color: mode === "browse" ? UI.dim : UI.cream, children: mode === "browse" ? "> " : `${mode}> ` }), color: UI.text, onCancel: () => {
589
+ }, onSubmit: (value) => void run(value), isActive: inputActive({ busy, pendingChats: inFlight.length }), placeholder: promptPlaceholder({ busy, pendingChats: inFlight.length }), prompt: _jsx(Text, { color: mode === "browse" ? UI.dim : UI.cream, children: mode === "browse" ? "> " : `${mode}> ` }), color: UI.text, onCancel: () => {
593
590
  if (editing) {
594
591
  setEditing(null);
595
592
  setDraft("");
@@ -0,0 +1,18 @@
1
+ /** How long the TUI waits for an architect or orchestrator reply. */
2
+ export const REPLY_WAIT_MS = 180_000;
3
+ /** Shown in the pending bubble when the wait expires. The reply can still land in /inbox. */
4
+ export const NO_REPLY_NOTE = "No reply yet. It will land in /inbox.";
5
+ export const QUEUED_STEP = "· queued, it answers on the next tick";
6
+ /**
7
+ * The prompt stays live while a chat reply is pending so navigation, /decide,
8
+ * and a follow-up send still work. `busy` is the only lock.
9
+ */
10
+ export function inputActive(state) {
11
+ return !state.busy;
12
+ }
13
+ export function promptPlaceholder(state) {
14
+ return state.busy ? "working…" : "message, or /help";
15
+ }
16
+ export function settleChatReply(reply) {
17
+ return { body: reply ?? NO_REPLY_NOTE, pending: false, steps: [], done: true };
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@higherdev/cli",
3
- "version": "0.14.3",
3
+ "version": "0.14.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "hd": "dist/index.js"