@askexenow/exe-os 0.8.39 → 0.8.41

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.
@@ -1887,7 +1887,7 @@ async function listTasks(input) {
1887
1887
  }
1888
1888
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1889
1889
  const result = await client.execute({
1890
- sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC`,
1890
+ sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC LIMIT 1000`,
1891
1891
  args
1892
1892
  });
1893
1893
  return result.rows.map((r) => ({
@@ -2108,6 +2108,34 @@ async function listPendingReviews(limit) {
2108
2108
  });
2109
2109
  return result.rows;
2110
2110
  }
2111
+ async function cleanupOrphanedReviews() {
2112
+ const client = getClient();
2113
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2114
+ const r1 = await client.execute({
2115
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
2116
+ WHERE status = 'needs_review'
2117
+ AND assigned_by = 'system'
2118
+ AND title LIKE 'Review:%'
2119
+ AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2120
+ args: [now]
2121
+ });
2122
+ const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2123
+ const r2 = await client.execute({
2124
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
2125
+ WHERE status = 'needs_review'
2126
+ AND result IS NOT NULL
2127
+ AND updated_at < ?`,
2128
+ args: [now, staleThreshold]
2129
+ });
2130
+ const total = r1.rowsAffected + r2.rowsAffected;
2131
+ if (total > 0) {
2132
+ process.stderr.write(
2133
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2134
+ `
2135
+ );
2136
+ }
2137
+ return total;
2138
+ }
2111
2139
  function getReviewChecklist(role, agent, taskSlug) {
2112
2140
  const roleLower = role.toLowerCase();
2113
2141
  if (roleLower.includes("engineer") || roleLower === "principal engineer") {
@@ -2849,6 +2877,7 @@ var init_skill_learning = __esm({
2849
2877
  // src/lib/tasks.ts
2850
2878
  var tasks_exports = {};
2851
2879
  __export(tasks_exports, {
2880
+ cleanupOrphanedReviews: () => cleanupOrphanedReviews,
2852
2881
  countNewPendingReviewsSince: () => countNewPendingReviewsSince,
2853
2882
  countPendingReviews: () => countPendingReviews,
2854
2883
  createTask: () => createTask,
@@ -2914,6 +2943,21 @@ async function updateTask(input) {
2914
2943
  });
2915
2944
  } catch {
2916
2945
  }
2946
+ try {
2947
+ const client = getClient();
2948
+ const cascaded = await client.execute({
2949
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
2950
+ WHERE parent_task_id = ? AND status = 'needs_review'`,
2951
+ args: [now, taskId]
2952
+ });
2953
+ if (cascaded.rowsAffected > 0) {
2954
+ process.stderr.write(
2955
+ `[cascade] Closed ${cascaded.rowsAffected} orphaned review task(s) for parent ${taskId}
2956
+ `
2957
+ );
2958
+ }
2959
+ } catch {
2960
+ }
2917
2961
  }
2918
2962
  const isTerminal = input.status === "done" || input.status === "needs_review";
2919
2963
  if (isTerminal) {
package/dist/tui/App.js CHANGED
@@ -954,6 +954,7 @@ var config_exports = {};
954
954
  __export(config_exports, {
955
955
  CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
956
956
  CONFIG_PATH: () => CONFIG_PATH,
957
+ COO_AGENT_NAME: () => COO_AGENT_NAME,
957
958
  CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
958
959
  DB_PATH: () => DB_PATH,
959
960
  EXE_AI_DIR: () => EXE_AI_DIR,
@@ -1109,7 +1110,7 @@ async function loadConfigFrom(configPath) {
1109
1110
  return { ...DEFAULT_CONFIG };
1110
1111
  }
1111
1112
  }
1112
- var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
1113
+ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, COO_AGENT_NAME, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
1113
1114
  var init_config = __esm({
1114
1115
  "src/lib/config.ts"() {
1115
1116
  "use strict";
@@ -1117,6 +1118,7 @@ var init_config = __esm({
1117
1118
  DB_PATH = path.join(EXE_AI_DIR, "memories.db");
1118
1119
  MODELS_DIR = path.join(EXE_AI_DIR, "models");
1119
1120
  CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
1121
+ COO_AGENT_NAME = "exe";
1120
1122
  LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
1121
1123
  CURRENT_CONFIG_VERSION = 1;
1122
1124
  DEFAULT_CONFIG = {
@@ -4757,7 +4759,7 @@ async function listTasks(input) {
4757
4759
  }
4758
4760
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
4759
4761
  const result = await client.execute({
4760
- sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC`,
4762
+ sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC LIMIT 1000`,
4761
4763
  args
4762
4764
  });
4763
4765
  return result.rows.map((r) => ({
@@ -4978,6 +4980,34 @@ async function listPendingReviews(limit) {
4978
4980
  });
4979
4981
  return result.rows;
4980
4982
  }
4983
+ async function cleanupOrphanedReviews() {
4984
+ const client = getClient();
4985
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4986
+ const r1 = await client.execute({
4987
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
4988
+ WHERE status = 'needs_review'
4989
+ AND assigned_by = 'system'
4990
+ AND title LIKE 'Review:%'
4991
+ AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
4992
+ args: [now]
4993
+ });
4994
+ const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
4995
+ const r2 = await client.execute({
4996
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
4997
+ WHERE status = 'needs_review'
4998
+ AND result IS NOT NULL
4999
+ AND updated_at < ?`,
5000
+ args: [now, staleThreshold]
5001
+ });
5002
+ const total = r1.rowsAffected + r2.rowsAffected;
5003
+ if (total > 0) {
5004
+ process.stderr.write(
5005
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
5006
+ `
5007
+ );
5008
+ }
5009
+ return total;
5010
+ }
4981
5011
  function getReviewChecklist(role, agent, taskSlug) {
4982
5012
  const roleLower = role.toLowerCase();
4983
5013
  if (roleLower.includes("engineer") || roleLower === "principal engineer") {
@@ -5657,6 +5687,7 @@ var init_skill_learning = __esm({
5657
5687
  // src/lib/tasks.ts
5658
5688
  var tasks_exports = {};
5659
5689
  __export(tasks_exports, {
5690
+ cleanupOrphanedReviews: () => cleanupOrphanedReviews,
5660
5691
  countNewPendingReviewsSince: () => countNewPendingReviewsSince,
5661
5692
  countPendingReviews: () => countPendingReviews,
5662
5693
  createTask: () => createTask,
@@ -5722,6 +5753,21 @@ async function updateTask(input) {
5722
5753
  });
5723
5754
  } catch {
5724
5755
  }
5756
+ try {
5757
+ const client = getClient();
5758
+ const cascaded = await client.execute({
5759
+ sql: `UPDATE tasks SET status = 'done', updated_at = ?
5760
+ WHERE parent_task_id = ? AND status = 'needs_review'`,
5761
+ args: [now, taskId]
5762
+ });
5763
+ if (cascaded.rowsAffected > 0) {
5764
+ process.stderr.write(
5765
+ `[cascade] Closed ${cascaded.rowsAffected} orphaned review task(s) for parent ${taskId}
5766
+ `
5767
+ );
5768
+ }
5769
+ } catch {
5770
+ }
5725
5771
  }
5726
5772
  const isTerminal = input.status === "done" || input.status === "needs_review";
5727
5773
  if (isTerminal) {
@@ -14081,6 +14127,7 @@ var SYNC_OUTPUT_SUPPORTED = supportsSynchronizedOutput();
14081
14127
  var TERMINAL_TYPE = getTerminalType();
14082
14128
 
14083
14129
  // src/tui/Sidebar.tsx
14130
+ import React14 from "react";
14084
14131
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
14085
14132
  var SECTIONS = [
14086
14133
  { key: "command-center", label: "Command Center", shortcut: "1" },
@@ -14135,7 +14182,7 @@ function Sidebar({
14135
14182
  }
14136
14183
 
14137
14184
  // src/tui/Footer.tsx
14138
- import { useState as useState4, useEffect as useEffect6 } from "react";
14185
+ import React15, { useState as useState4, useEffect as useEffect6 } from "react";
14139
14186
  import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
14140
14187
  function Footer() {
14141
14188
  const demo = useDemo();
@@ -14267,6 +14314,7 @@ import path11 from "path";
14267
14314
  import { homedir } from "os";
14268
14315
 
14269
14316
  // src/tui/components/StatusDot.tsx
14317
+ import React16 from "react";
14270
14318
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
14271
14319
  var STATUS_CONFIG = {
14272
14320
  active: { char: "\u25CF", dotColor: "#22C55E", label: "active", labelColor: "#22C55E" },
@@ -15513,12 +15561,12 @@ function ChatMessageRow({ msg }) {
15513
15561
  }
15514
15562
 
15515
15563
  // src/tui/views/Sessions.tsx
15516
- import { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
15564
+ import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
15517
15565
  import path21 from "path";
15518
15566
  import { homedir as homedir2 } from "os";
15519
15567
 
15520
15568
  // src/tui/components/TmuxPane.tsx
15521
- import { useState as useState7, useEffect as useEffect9 } from "react";
15569
+ import React18, { useState as useState7, useEffect as useEffect9 } from "react";
15522
15570
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
15523
15571
  var POLL_INTERVAL_MS = 2e3;
15524
15572
  var CAPTURE_LINES = 35;
@@ -16179,7 +16227,7 @@ function SessionsView({
16179
16227
  }
16180
16228
 
16181
16229
  // src/tui/views/Tasks.tsx
16182
- import { useState as useState10, useEffect as useEffect12, useMemo as useMemo5 } from "react";
16230
+ import React20, { useState as useState10, useEffect as useEffect12, useMemo as useMemo5 } from "react";
16183
16231
  import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
16184
16232
  var STATUS_FILTERS = ["all", "open", "in_progress", "done", "blocked", "needs_review"];
16185
16233
  var PRIORITY_COLORS = {
@@ -16457,7 +16505,7 @@ function TasksView({ onBack }) {
16457
16505
  }
16458
16506
 
16459
16507
  // src/tui/views/Gateway.tsx
16460
- import { useState as useState11, useEffect as useEffect13, useRef as useRef6, useMemo as useMemo6 } from "react";
16508
+ import React21, { useState as useState11, useEffect as useEffect13, useRef as useRef6, useMemo as useMemo6 } from "react";
16461
16509
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
16462
16510
  var MAX_CONVERSATIONS = 20;
16463
16511
  var MAX_MESSAGES_PER_CONVERSATION = 50;
@@ -17019,7 +17067,7 @@ function GatewayView({ onBack }) {
17019
17067
  }
17020
17068
 
17021
17069
  // src/tui/views/Team.tsx
17022
- import { useState as useState12, useEffect as useEffect14 } from "react";
17070
+ import React22, { useState as useState12, useEffect as useEffect14 } from "react";
17023
17071
 
17024
17072
  // src/tui/utils/agent-status.ts
17025
17073
  import { execSync as execSync9 } from "child_process";
@@ -17305,7 +17353,7 @@ function TeamView({ onBack }) {
17305
17353
  }
17306
17354
 
17307
17355
  // src/tui/views/Wiki.tsx
17308
- import { useState as useState13, useEffect as useEffect15 } from "react";
17356
+ import React23, { useState as useState13, useEffect as useEffect15 } from "react";
17309
17357
  import TextInput2 from "ink-text-input";
17310
17358
  import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
17311
17359
  var PANELS = ["Workspaces", "Documents", "Chat"];
@@ -17607,7 +17655,7 @@ function WikiView({ onBack }) {
17607
17655
  }
17608
17656
 
17609
17657
  // src/tui/views/Settings.tsx
17610
- import { useState as useState14, useEffect as useEffect16 } from "react";
17658
+ import React24, { useState as useState14, useEffect as useEffect16 } from "react";
17611
17659
  import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
17612
17660
  var SECTION_NAMES = ["Providers", "Memory", "Runtime", "Employee Models", "Integrations"];
17613
17661
  function SettingsView({ onBack }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.8.39",
3
+ "version": "0.8.41",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "CC-BY-NC-4.0",
6
6
  "type": "module",