loop-task 2.1.10 → 2.1.11

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.
@@ -1,6 +1,7 @@
1
1
  import { t } from "../../shared/i18n/index.js";
2
2
  import { cycleSortMode, cycleStatusFilter } from "../../entities/loops/filters.js";
3
3
  import { cycleProjectSortMode, cycleProjectHasLoopsFilter, cycleProjectIsSystemFilter } from "../../entities/projects/filters.js";
4
+ import { groupRunsByCycle } from "../../widgets/right-panel/RunHistory.js";
4
5
  export function useCommandHandlers(context) {
5
6
  const { activeTab, selected, selectedRunIndex, selectedTask, selectedProjectEntity, tasks, projects, currentProjectId, setCloneMode, setEditTarget, setPendingTaskSelection, setEditTask, setEditProject, setActiveTab, setConfirmState, setCommandsBrowserOpen, setSearchValue, setSearchState, setFilters, setSort, setCurrentProjectId, setProjectFilters, setProjectSelectedIndex, setDebugMode, setExportModal, push, pop, refresh, refreshTasks, refreshProjects, pushToast, loopService, taskService, projectService, exportService, runAction, handleOpenRunLog, } = context;
6
7
  const commandHandlers = {
@@ -109,7 +110,7 @@ export function useCommandHandlers(context) {
109
110
  debug: () => { setDebugMode((prev) => !prev); },
110
111
  logs: () => {
111
112
  if (activeTab === "loops" && selected) {
112
- const reversed = [...selected.runHistory].reverse();
113
+ const reversed = [...groupRunsByCycle(selected.runHistory)].reverse();
113
114
  if (reversed.length > 0) {
114
115
  const run = reversed[Math.min(selectedRunIndex, reversed.length - 1)];
115
116
  handleOpenRunLog(run ?? reversed[0]);
@@ -2,6 +2,7 @@ import { useCallback } from "react";
2
2
  import { copyToClipboard } from "../../shared/clipboard.js";
3
3
  import { commandLine } from "../../shared/ui/format.js";
4
4
  import { t } from "../../shared/i18n/index.js";
5
+ import { groupRunsByCycle } from "../../widgets/right-panel/RunHistory.js";
5
6
  export function useContextualActions(context) {
6
7
  const { activeTab, focusedPanel, selected, selectedRunIndex, selectedTask, selectedProjectEntity, tasks, push, setCloneMode, setEditTarget, setPendingTaskSelection, handleCommand, handleOpenRunLog, pushToast, isBoardView, view, logModalRun, commandsBrowserOpen, confirmState, searchState, setChordState, chordState, } = context;
7
8
  const handleContextualCopy = useCallback(() => {
@@ -57,7 +58,7 @@ export function useContextualActions(context) {
57
58
  "loops:right": () => {
58
59
  if (!selected)
59
60
  return;
60
- const reversed = [...selected.runHistory].reverse();
61
+ const reversed = [...groupRunsByCycle(selected.runHistory)].reverse();
61
62
  if (reversed.length > 0) {
62
63
  const run = reversed[Math.min(selectedRunIndex, reversed.length - 1)];
63
64
  handleOpenRunLog(run ?? reversed[0]);
@@ -4,7 +4,9 @@ import { TYPES } from "../services/types.js";
4
4
  import { t } from "../i18n/index.js";
5
5
  import { LOG_LINES_MAX } from "../config/constants.js";
6
6
  export function useLogStream(selectedId, view, onError) {
7
- const logService = useInject(TYPES.LogService);
7
+ const injectedLogService = useInject(TYPES.LogService);
8
+ const logServiceRef = useRef(injectedLogService);
9
+ const logService = logServiceRef.current;
8
10
  const [logLines, setLogLines] = useState([]);
9
11
  const logSocket = useRef(null);
10
12
  useEffect(() => {
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
2
+ import { useEffect, useRef, useState } from "react";
3
3
  import { Box, Text, useInput, useStdout } from "ink";
4
4
  import { darkTheme as theme } from "../../shared/ui/theme.js";
5
5
  import { t } from "../../shared/i18n/index.js";
@@ -30,7 +30,10 @@ export function LogModal(props) {
30
30
  const [searchQuery, setSearchQuery] = useState("");
31
31
  const [follow, setFollow] = useState(true);
32
32
  const [scrollOffset, setScrollOffset] = useState(0);
33
- const logService = useInject(TYPES.LogService);
33
+ const bottomDistanceRef = useRef(0);
34
+ const injectedLogService = useInject(TYPES.LogService);
35
+ const logServiceRef = useRef(injectedLogService);
36
+ const logService = logServiceRef.current;
34
37
  const { stdout } = useStdout();
35
38
  const terminalHeight = stdout?.rows ?? 24;
36
39
  const MAX_VISIBLE_LINES = Math.max(1, Math.floor(terminalHeight * 0.7) - 7);
@@ -105,13 +108,15 @@ export function LogModal(props) {
105
108
  return;
106
109
  }
107
110
  if (key.downArrow) {
111
+ const base = follow ? Math.max(0, totalLines - MAX_VISIBLE_LINES) : scrollOffset;
108
112
  setFollow(false);
109
- setScrollOffset((o) => Math.min(o + 1, Math.max(0, totalLines - MAX_VISIBLE_LINES)));
113
+ setScrollOffset(Math.min(base + 1, Math.max(0, totalLines - MAX_VISIBLE_LINES)));
110
114
  return;
111
115
  }
112
116
  if (key.upArrow) {
117
+ const base = follow ? Math.max(0, totalLines - MAX_VISIBLE_LINES) : scrollOffset;
113
118
  setFollow(false);
114
- setScrollOffset((o) => Math.max(0, o - 1));
119
+ setScrollOffset(Math.max(0, base - 1));
115
120
  return;
116
121
  }
117
122
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loop-task",
3
- "version": "2.1.10",
3
+ "version": "2.1.11",
4
4
  "description": "Loop engineering toolkit. Run any command on a cadence, in the background, managed from a terminal board. Schedule tests, builds, syncs, or agent prompts.",
5
5
  "type": "module",
6
6
  "bin": {