@kolisachint/hoocode-agent 0.4.52 → 0.4.53

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 (37) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cli/args.d.ts +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +3 -1
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/keybindings.d.ts +5 -0
  7. package/dist/core/keybindings.d.ts.map +1 -1
  8. package/dist/core/keybindings.js +8 -0
  9. package/dist/core/keybindings.js.map +1 -1
  10. package/dist/core/team-auto.d.ts +46 -0
  11. package/dist/core/team-auto.d.ts.map +1 -0
  12. package/dist/core/team-auto.js +163 -0
  13. package/dist/core/team-auto.js.map +1 -0
  14. package/dist/core/team-view.d.ts +29 -2
  15. package/dist/core/team-view.d.ts.map +1 -1
  16. package/dist/core/team-view.js +39 -3
  17. package/dist/core/team-view.js.map +1 -1
  18. package/dist/main.d.ts.map +1 -1
  19. package/dist/main.js +28 -7
  20. package/dist/main.js.map +1 -1
  21. package/dist/modes/interactive/components/task-panel.d.ts +14 -2
  22. package/dist/modes/interactive/components/task-panel.d.ts.map +1 -1
  23. package/dist/modes/interactive/components/task-panel.js +69 -5
  24. package/dist/modes/interactive/components/task-panel.js.map +1 -1
  25. package/dist/modes/interactive/components/team-attach-panel.d.ts +60 -0
  26. package/dist/modes/interactive/components/team-attach-panel.d.ts.map +1 -0
  27. package/dist/modes/interactive/components/team-attach-panel.js +222 -0
  28. package/dist/modes/interactive/components/team-attach-panel.js.map +1 -0
  29. package/dist/modes/interactive/interactive-mode.d.ts +24 -0
  30. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  31. package/dist/modes/interactive/interactive-mode.js +106 -0
  32. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  33. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  34. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  35. package/examples/extensions/sandbox/package.json +1 -1
  36. package/examples/extensions/with-deps/package.json +1 -1
  37. package/package.json +4 -4
@@ -53,6 +53,7 @@ import { SessionSelectorComponent } from "./components/session-selector.js";
53
53
  import { SettingsSelectorComponent } from "./components/settings-selector.js";
54
54
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
55
55
  import { TaskPanelComponent } from "./components/task-panel.js";
56
+ import { TeamAttachPanelComponent } from "./components/team-attach-panel.js";
56
57
  import { ToolExecutionComponent } from "./components/tool-execution.js";
57
58
  import { TreeSelectorComponent } from "./components/tree-selector.js";
58
59
  import { UserMessageComponent } from "./components/user-message.js";
@@ -184,6 +185,10 @@ export class InteractiveMode {
184
185
  widgetContainerBelow;
185
186
  // Task panel shown just above the editor (active subagent tasks)
186
187
  taskPanel;
188
+ // hooteams team client (--team): steering + attach share its single SSE stream
189
+ teamClient = undefined;
190
+ teamAttachPanel = undefined;
191
+ teamAttachHandle = undefined;
187
192
  // Custom footer from extension (undefined = use built-in footer)
188
193
  customFooter = undefined;
189
194
  // Header container that holds the built-in or custom header
@@ -306,6 +311,9 @@ export class InteractiveMode {
306
311
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
307
312
  this.footerDataProvider.setSubagentEnabled(this.session.getActiveToolNames().includes("Task"));
308
313
  this.taskPanel = new TaskPanelComponent(this.ui);
314
+ this.taskPanel.onNudge = (role) => this.showTeamNudgeInput(role);
315
+ this.taskPanel.onAttach = (role) => this.showTeamAttach(role);
316
+ this.taskPanel.onExitFocus = () => this.exitTeamFocus();
309
317
  // Load hide thinking block setting
310
318
  this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
311
319
  // Register themes from resource loader and initialize
@@ -493,6 +501,7 @@ export class InteractiveMode {
493
501
  hint("app.tools.expand", "to expand tools"),
494
502
  hint("app.thinking.toggle", "to expand thinking"),
495
503
  hint("app.tasks.cycleView", "to cycle task panel view"),
504
+ ...(this.teamClient ? [hint("app.team.focus", "to focus team roster")] : []),
496
505
  hint("app.editor.external", "for external editor"),
497
506
  rawKeyHint("/", "for commands"),
498
507
  rawKeyHint("!", "to run bash"),
@@ -2069,6 +2078,7 @@ export class InteractiveMode {
2069
2078
  this.defaultEditor.onAction("app.tasks.cycleView", () => {
2070
2079
  this.taskPanel.cycleView();
2071
2080
  });
2081
+ this.defaultEditor.onAction("app.team.focus", () => this.enterTeamFocus());
2072
2082
  this.defaultEditor.onAction("app.editor.external", () => this.openExternalEditor());
2073
2083
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2074
2084
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
@@ -2109,6 +2119,101 @@ export class InteractiveMode {
2109
2119
  // Silently ignore clipboard errors (may not have permission, etc.)
2110
2120
  }
2111
2121
  }
2122
+ // =========================================================================
2123
+ // hooteams team focus (--team): focus role rows, nudge, attach
2124
+ // =========================================================================
2125
+ /**
2126
+ * 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.
2129
+ */
2130
+ attachTeamClient(client) {
2131
+ this.teamClient = client;
2132
+ }
2133
+ /** Move keyboard focus to the task panel's team roster. */
2134
+ enterTeamFocus() {
2135
+ if (!this.teamClient) {
2136
+ this.showStatus("No team connected. Start with --team <url> to mirror a hooteams server.");
2137
+ return;
2138
+ }
2139
+ if (!taskStore.agents().some((a) => a.kind === "role")) {
2140
+ this.showStatus("Team roster is empty — waiting for roles from the team server.");
2141
+ return;
2142
+ }
2143
+ this.taskPanel.setView("teams");
2144
+ this.ui.setFocus(this.taskPanel);
2145
+ this.ui.requestRender();
2146
+ }
2147
+ /** Leave team focus: detach any side panel and return focus to the editor. */
2148
+ exitTeamFocus() {
2149
+ this.closeTeamAttach();
2150
+ this.ui.setFocus(this.editor);
2151
+ this.ui.requestRender();
2152
+ }
2153
+ /**
2154
+ * Inline nudge editor for a role (n in team focus or while attached).
2155
+ * Swaps the prompt editor for a one-line input; submit fires POST /steer in
2156
+ * the background (the REPL and team focus are never blocked on the network).
2157
+ */
2158
+ showTeamNudgeInput(role) {
2159
+ const client = this.teamClient;
2160
+ if (!client)
2161
+ return;
2162
+ const restoreFocus = () => {
2163
+ this.editorContainer.clear();
2164
+ this.editorContainer.addChild(this.editor);
2165
+ // Return focus where the nudge came from: the attach panel if one is
2166
+ // open, otherwise the team roster.
2167
+ if (this.teamAttachHandle)
2168
+ this.teamAttachHandle.focus();
2169
+ else
2170
+ this.ui.setFocus(this.taskPanel);
2171
+ this.ui.requestRender();
2172
+ };
2173
+ const input = new ExtensionInputComponent(`Nudge ${role}`, undefined, (value) => {
2174
+ input.dispose();
2175
+ restoreFocus();
2176
+ const message = value.trim();
2177
+ if (!message)
2178
+ return;
2179
+ void client.steer(role, message).then(() => this.showStatus(`Nudged ${role}`), (error) => this.showWarning(`Failed to nudge ${role}: ${String(error)}`));
2180
+ }, () => {
2181
+ input.dispose();
2182
+ restoreFocus();
2183
+ }, { tui: this.ui });
2184
+ this.editorContainer.clear();
2185
+ this.editorContainer.addChild(input);
2186
+ this.ui.setFocus(input);
2187
+ this.ui.requestRender();
2188
+ }
2189
+ /** Open the attach side panel for a role (a in team focus). */
2190
+ showTeamAttach(role) {
2191
+ const client = this.teamClient;
2192
+ if (!client)
2193
+ return;
2194
+ // One attached role at a time: re-attaching swaps the panel.
2195
+ this.closeTeamAttach();
2196
+ const panel = new TeamAttachPanelComponent(role, client, {
2197
+ onDetach: () => this.closeTeamAttach(),
2198
+ onNudge: (attachedRole) => this.showTeamNudgeInput(attachedRole),
2199
+ }, this.ui);
2200
+ this.teamAttachPanel = panel;
2201
+ // preFocus is the task panel (attach is triggered from team focus), so
2202
+ // hiding the overlay drops the user back on the role roster.
2203
+ this.teamAttachHandle = this.ui.showOverlay(panel, {
2204
+ anchor: "top-right",
2205
+ width: "45%",
2206
+ minWidth: 36,
2207
+ margin: { top: 1, right: 1 },
2208
+ });
2209
+ }
2210
+ /** Detach the side panel; the role keeps running. Safe to call when closed. */
2211
+ closeTeamAttach() {
2212
+ this.teamAttachPanel?.dispose();
2213
+ this.teamAttachHandle?.hide();
2214
+ this.teamAttachPanel = undefined;
2215
+ this.teamAttachHandle = undefined;
2216
+ }
2112
2217
  setupEditorSubmitHandler() {
2113
2218
  this.defaultEditor.onSubmit = async (text) => {
2114
2219
  text = text.trim();
@@ -2814,6 +2919,7 @@ export class InteractiveMode {
2814
2919
  // This prevents escape sequences from leaking to the parent shell over slow SSH.
2815
2920
  await this.ui.terminal.drainInput(1000);
2816
2921
  this.taskStoreUnsubscribe?.();
2922
+ this.closeTeamAttach();
2817
2923
  this.taskPanel.dispose();
2818
2924
  this.stop();
2819
2925
  await this.runtimeHost.dispose();