aitasks 1.2.1 → 1.3.0

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 (2) hide show
  1. package/dist/index.js +162 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1890,7 +1890,7 @@ var require_commander = __commonJS((exports) => {
1890
1890
  var require_package = __commonJS((exports, module) => {
1891
1891
  module.exports = {
1892
1892
  name: "aitasks",
1893
- version: "1.2.1",
1893
+ version: "1.3.0",
1894
1894
  description: "CLI task management tool built for AI agents",
1895
1895
  type: "module",
1896
1896
  bin: {
@@ -41546,7 +41546,7 @@ var wrapAnsiLine = (line, maxW) => {
41546
41546
  result2.push(current);
41547
41547
  return result2;
41548
41548
  };
41549
- var RightPane = ({ task, width, height, scrollOffset }) => {
41549
+ var RightPane = ({ task, width, height, scrollOffset, metricsRef }) => {
41550
41550
  const { lines, contentW } = import_react29.useMemo(() => {
41551
41551
  if (!task)
41552
41552
  return { lines: [], contentW: 20 };
@@ -41616,6 +41616,8 @@ var RightPane = ({ task, width, height, scrollOffset }) => {
41616
41616
  const visibleH = Math.max(3, height - 2);
41617
41617
  const maxOffset = Math.max(0, totalLines - visibleH);
41618
41618
  const offset = Math.min(scrollOffset, maxOffset);
41619
+ if (metricsRef)
41620
+ metricsRef.current = { maxOffset, visibleH };
41619
41621
  const visibleLines = lines.slice(offset, offset + visibleH);
41620
41622
  const scrollbar = import_react29.useMemo(() => {
41621
41623
  if (totalLines <= visibleH)
@@ -41728,6 +41730,15 @@ var StatusPicker = ({ task }) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_def
41728
41730
  }, undefined, false, undefined, this)
41729
41731
  ]
41730
41732
  }, undefined, true, undefined, this);
41733
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
41734
+ function getDateKey(ts) {
41735
+ const d2 = new Date(ts);
41736
+ return `${d2.getFullYear()}-${d2.getMonth()}-${d2.getDate()}`;
41737
+ }
41738
+ function formatDateLabel(ts) {
41739
+ const d2 = new Date(ts);
41740
+ return `${MONTHS[d2.getMonth()]} ${d2.getDate()}`;
41741
+ }
41731
41742
  function wrapText2(text, maxW) {
41732
41743
  const words2 = text.split(/\s+/);
41733
41744
  const result2 = [];
@@ -41777,6 +41788,8 @@ var TreeBoardComponent = ({ getTasks }) => {
41777
41788
  const doneCnt = items.filter((i) => i.section === "done").length;
41778
41789
  const result2 = [];
41779
41790
  let firstSection = true;
41791
+ let prevDateKey = null;
41792
+ let prevSection = null;
41780
41793
  for (let idx = 0;idx < items.length; idx++) {
41781
41794
  const item = items[idx];
41782
41795
  if (item.showSectionHeader && item.section !== "middle") {
@@ -41789,7 +41802,19 @@ var TreeBoardComponent = ({ getTasks }) => {
41789
41802
  total: item.section === "in_progress" ? ipTotal : undefined
41790
41803
  });
41791
41804
  firstSection = false;
41805
+ prevDateKey = null;
41806
+ } else if (item.section !== prevSection) {
41807
+ prevDateKey = null;
41808
+ }
41809
+ if (item.indent === 0) {
41810
+ const ts = item.section === "done" ? item.task.completed_at ?? item.task.created_at : item.task.created_at;
41811
+ const dateKey = getDateKey(ts);
41812
+ if (prevDateKey !== null && prevDateKey !== dateKey) {
41813
+ result2.push({ kind: "date-sep", label: formatDateLabel(ts) });
41814
+ }
41815
+ prevDateKey = dateKey;
41792
41816
  }
41817
+ prevSection = item.section;
41793
41818
  result2.push({ kind: "item", item, itemIdx: idx });
41794
41819
  }
41795
41820
  return result2;
@@ -41835,6 +41860,8 @@ var TreeBoardComponent = ({ getTasks }) => {
41835
41860
  return;
41836
41861
  }
41837
41862
  if (input && !key.ctrl && !key.meta) {
41863
+ if (Date.now() < suppressUntilRef.current)
41864
+ return;
41838
41865
  setSearchQuery((q2) => q2 + input);
41839
41866
  return;
41840
41867
  }
@@ -41887,14 +41914,40 @@ var TreeBoardComponent = ({ getTasks }) => {
41887
41914
  leftWidthRef.current = leftWidth;
41888
41915
  const scrollOffsetRef = import_react29.useRef(scrollOffset);
41889
41916
  scrollOffsetRef.current = scrollOffset;
41917
+ const colsRef = import_react29.useRef(cols);
41918
+ colsRef.current = cols;
41919
+ const rowsRef = import_react29.useRef(rows);
41920
+ rowsRef.current = rows;
41921
+ const leftScrollOffsetRef = import_react29.useRef(leftScrollOffset);
41922
+ leftScrollOffsetRef.current = leftScrollOffset;
41923
+ const leftMaxOffsetRef = import_react29.useRef(0);
41924
+ const rightMetricsRef = import_react29.useRef({ maxOffset: 0, visibleH: 0 });
41925
+ const dragRef = import_react29.useRef(null);
41926
+ const visibleLeftRowsRef = import_react29.useRef([]);
41927
+ const suppressUntilRef = import_react29.useRef(0);
41928
+ const searchActiveRef = import_react29.useRef(false);
41890
41929
  import_react29.useEffect(() => {
41891
- process.stdout.write("\x1B[?1000h\x1B[?1006h");
41930
+ process.stdout.write("\x1B[?1002h\x1B[?1006h");
41931
+ const jumpToRow = (row, pane) => {
41932
+ const contentStart = 4;
41933
+ const visH = Math.max(1, rowsRef.current - 4);
41934
+ const relRow = Math.max(0, Math.min(row - contentStart, visH - 1));
41935
+ const ratio = visH > 1 ? relRow / (visH - 1) : 0;
41936
+ if (pane === "left") {
41937
+ setLeftScrollOffset(Math.round(ratio * leftMaxOffsetRef.current));
41938
+ } else {
41939
+ setScrollOffset(Math.round(ratio * rightMetricsRef.current.maxOffset));
41940
+ }
41941
+ };
41892
41942
  const onData = (buf) => {
41893
41943
  const str = buf.toString("latin1");
41894
- const sgr = str.match(/\x1b\[<(\d+);(\d+);(\d+)M/);
41944
+ const sgr = str.match(/\x1b\[<(\d+);(\d+);(\d+)([Mm])/);
41895
41945
  if (sgr) {
41896
41946
  const btn = parseInt(sgr[1], 10);
41897
41947
  const col = parseInt(sgr[2], 10) - 1;
41948
+ const row = parseInt(sgr[3], 10) - 1;
41949
+ const isRelease = sgr[4] === "m";
41950
+ suppressUntilRef.current = Date.now() + 150;
41898
41951
  if (btn === 64 || btn === 65) {
41899
41952
  if (col < leftWidthRef.current) {
41900
41953
  if (btn === 64)
@@ -41907,6 +41960,34 @@ var TreeBoardComponent = ({ getTasks }) => {
41907
41960
  if (btn === 65)
41908
41961
  setScrollOffset((o) => o + 8);
41909
41962
  }
41963
+ return;
41964
+ }
41965
+ if (isRelease) {
41966
+ dragRef.current = null;
41967
+ return;
41968
+ }
41969
+ if (btn === 0 || btn === 32) {
41970
+ const leftSbCol = leftWidthRef.current - 2;
41971
+ const rightSbCol = colsRef.current - 3;
41972
+ if (btn === 0) {
41973
+ if (col === leftSbCol)
41974
+ dragRef.current = "left";
41975
+ else if (col >= rightSbCol)
41976
+ dragRef.current = "right";
41977
+ else {
41978
+ dragRef.current = null;
41979
+ if (col < leftWidthRef.current - 1) {
41980
+ const visRowIdx = row - (searchActiveRef.current ? 4 : 3);
41981
+ const clicked = visibleLeftRowsRef.current[visRowIdx];
41982
+ if (clicked?.kind === "item")
41983
+ setSelectedIdx(clicked.itemIdx);
41984
+ }
41985
+ }
41986
+ }
41987
+ if (dragRef.current === "left")
41988
+ jumpToRow(row, "left");
41989
+ if (dragRef.current === "right")
41990
+ jumpToRow(row, "right");
41910
41991
  }
41911
41992
  return;
41912
41993
  }
@@ -41928,9 +42009,9 @@ var TreeBoardComponent = ({ getTasks }) => {
41928
42009
  }
41929
42010
  }
41930
42011
  };
41931
- process.stdin.on("data", onData);
42012
+ process.stdin.prependListener("data", onData);
41932
42013
  return () => {
41933
- process.stdout.write("\x1B[?1006l\x1B[?1000l");
42014
+ process.stdout.write("\x1B[?1006l\x1B[?1002l");
41934
42015
  process.stdin.off("data", onData);
41935
42016
  };
41936
42017
  }, []);
@@ -41939,8 +42020,12 @@ var TreeBoardComponent = ({ getTasks }) => {
41939
42020
  const leftVisibleH = Math.max(1, rows - 4);
41940
42021
  const leftTotalRows = leftRows.length;
41941
42022
  const leftMaxOffset = Math.max(0, leftTotalRows - leftVisibleH);
42023
+ leftMaxOffsetRef.current = leftMaxOffset;
42024
+ searchActiveRef.current = mode === "search" || !!searchQuery;
41942
42025
  const leftOffset = Math.min(leftScrollOffset, leftMaxOffset);
41943
- const visibleLeftRows = leftRows.slice(leftOffset, leftOffset + leftVisibleH);
42026
+ const rawLeftRows = leftRows.slice(leftOffset, leftOffset + leftVisibleH);
42027
+ const visibleLeftRows = rawLeftRows[0]?.kind === "date-sep" ? rawLeftRows.slice(1) : rawLeftRows;
42028
+ visibleLeftRowsRef.current = visibleLeftRows;
41944
42029
  const leftScrollbar = (() => {
41945
42030
  const bar = Array(leftVisibleH).fill(" ");
41946
42031
  if (leftTotalRows > leftVisibleH) {
@@ -42083,6 +42168,37 @@ var TreeBoardComponent = ({ getTasks }) => {
42083
42168
  ]
42084
42169
  }, `sp-${leftOffset + i}`, true, undefined, this);
42085
42170
  }
42171
+ if (row.kind === "date-sep") {
42172
+ const dashW = Math.max(0, Math.floor((leftInner - 2 - row.label.length - 2) / 2));
42173
+ const dashes = "\u254C".repeat(dashW);
42174
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
42175
+ children: [
42176
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
42177
+ flexGrow: 1,
42178
+ paddingLeft: 1,
42179
+ children: [
42180
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
42181
+ dimColor: true,
42182
+ children: dashes
42183
+ }, undefined, false, undefined, this),
42184
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
42185
+ dimColor: true,
42186
+ children: [
42187
+ " ",
42188
+ row.label,
42189
+ " "
42190
+ ]
42191
+ }, undefined, true, undefined, this),
42192
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
42193
+ dimColor: true,
42194
+ children: dashes
42195
+ }, undefined, false, undefined, this)
42196
+ ]
42197
+ }, undefined, true, undefined, this),
42198
+ sb
42199
+ ]
42200
+ }, `ds-${leftOffset + i}`, true, undefined, this);
42201
+ }
42086
42202
  if (row.kind === "section") {
42087
42203
  const color = row.section === "in_progress" ? "yellow" : "green";
42088
42204
  const label = row.section === "in_progress" ? "IN PROGRESS" : "DONE";
@@ -42139,7 +42255,8 @@ var TreeBoardComponent = ({ getTasks }) => {
42139
42255
  task: selectedTask,
42140
42256
  width: rightInner,
42141
42257
  height: rightHeight,
42142
- scrollOffset
42258
+ scrollOffset,
42259
+ metricsRef: rightMetricsRef
42143
42260
  }, undefined, false, undefined, this)
42144
42261
  }, undefined, false, undefined, this)
42145
42262
  ]
@@ -42215,6 +42332,7 @@ var StaticCard = ({ task }) => {
42215
42332
  };
42216
42333
  var StaticSection = ({ status, tasks }) => {
42217
42334
  const color = STATUS_COLORS3[status];
42335
+ const getTaskDateKey = (t) => getDateKey(status === "done" ? t.completed_at ?? t.created_at : t.created_at);
42218
42336
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
42219
42337
  flexDirection: "column",
42220
42338
  borderStyle: "round",
@@ -42249,9 +42367,41 @@ var StaticSection = ({ status, tasks }) => {
42249
42367
  dimColor: true,
42250
42368
  children: "empty"
42251
42369
  }, undefined, false, undefined, this)
42252
- }, undefined, false, undefined, this) : tasks.map((t) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StaticCard, {
42253
- task: t
42254
- }, t.id, false, undefined, this))
42370
+ }, undefined, false, undefined, this) : tasks.map((t, i) => {
42371
+ const prev = tasks[i - 1];
42372
+ const showSep = prev != null && getTaskDateKey(prev) !== getTaskDateKey(t);
42373
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(import_react29.default.Fragment, {
42374
+ children: [
42375
+ showSep && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
42376
+ paddingLeft: 2,
42377
+ paddingRight: 1,
42378
+ children: [
42379
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
42380
+ dimColor: true,
42381
+ children: [
42382
+ "\u254C".repeat(4),
42383
+ " "
42384
+ ]
42385
+ }, undefined, true, undefined, this),
42386
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
42387
+ dimColor: true,
42388
+ children: [
42389
+ formatDateLabel(status === "done" ? t.completed_at ?? t.created_at : t.created_at),
42390
+ " "
42391
+ ]
42392
+ }, undefined, true, undefined, this),
42393
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
42394
+ dimColor: true,
42395
+ children: "\u254C".repeat(4)
42396
+ }, undefined, false, undefined, this)
42397
+ ]
42398
+ }, undefined, true, undefined, this),
42399
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StaticCard, {
42400
+ task: t
42401
+ }, undefined, false, undefined, this)
42402
+ ]
42403
+ }, t.id, true, undefined, this);
42404
+ })
42255
42405
  ]
42256
42406
  }, undefined, true, undefined, this);
42257
42407
  };
@@ -42985,4 +43135,4 @@ program2.parseAsync(process.argv).catch((err) => {
42985
43135
  process.exit(1);
42986
43136
  });
42987
43137
 
42988
- //# debugId=758BC15FE9C3042464756E2164756E21
43138
+ //# debugId=26C003F11D02306964756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aitasks",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "CLI task management tool built for AI agents",
5
5
  "type": "module",
6
6
  "bin": {