@kolisachint/hoocode-agent 0.4.53 → 0.4.54

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.
@@ -21,6 +21,7 @@ import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../cor
21
21
  import { SessionManager } from "../../core/session-manager.js";
22
22
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
23
23
  import { taskStore } from "../../core/task-store.js";
24
+ import { TeamApprovalCoordinator } from "../../core/team-approvals.js";
24
25
  import { buildCompactWordmark } from "../../core/wordmark.js";
25
26
  import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
26
27
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
@@ -2124,11 +2125,51 @@ export class InteractiveMode {
2124
2125
  // =========================================================================
2125
2126
  /**
2126
2127
  * Wire a hooteams connection into the TUI. Called by main.ts when `--team`
2127
- * is set, before run(). Enables team focus (app.team.focus), nudging (n)
2128
- * and the attach side panel (a) on the task panel's teams view.
2128
+ * is set, before run(). Enables team focus (app.team.focus), nudging (n),
2129
+ * the attach side panel (a) on the task panel's teams view, and approval
2130
+ * gates: task_paused events (and gates already pending on the server)
2131
+ * surface in the options pane; the answer goes back over
2132
+ * POST /tasks/:id/resume.
2129
2133
  */
2130
2134
  attachTeamClient(client) {
2131
2135
  this.teamClient = client;
2136
+ const approvals = new TeamApprovalCoordinator({
2137
+ present: (approval, signal) => this.presentTeamApproval(approval, signal),
2138
+ resume: (taskId, option) => client.resume(taskId, option),
2139
+ info: (message) => this.showStatus(message),
2140
+ warn: (message) => this.showWarning(message),
2141
+ });
2142
+ client.subscribe((event) => approvals.handleEvent(event));
2143
+ // Gates that opened before we attached don't replay as task_paused.
2144
+ void client.pendingApprovals().then((pending) => {
2145
+ for (const gate of pending)
2146
+ approvals.enqueuePending(gate);
2147
+ }, () => {
2148
+ // Best-effort like the rest of the bridge; live gates still arrive via SSE.
2149
+ });
2150
+ }
2151
+ /**
2152
+ * Show one team approval gate in the options pane and resolve with the
2153
+ * chosen (or free-form) answer, undefined when skipped. Waits politely
2154
+ * while another ask is on screen; the signal (gate answered elsewhere)
2155
+ * dismisses both the wait and the pane.
2156
+ */
2157
+ async presentTeamApproval(approval, signal) {
2158
+ while (this.askOptions && !signal.aborted) {
2159
+ await new Promise((resolve) => setTimeout(resolve, 200));
2160
+ }
2161
+ if (signal.aborted)
2162
+ return undefined;
2163
+ const answers = await this.showAskOptions([
2164
+ {
2165
+ question: approval.question,
2166
+ short: approval.taskId,
2167
+ detail: `team task "${approval.taskId}"${approval.role ? ` (${approval.role})` : ""} is paused until answered`,
2168
+ options: approval.options.map((label) => ({ label })),
2169
+ allowCustom: true,
2170
+ },
2171
+ ], { signal });
2172
+ return answers?.[0];
2132
2173
  }
2133
2174
  /** Move keyboard focus to the task panel's team roster. */
2134
2175
  enterTeamFocus() {