rrce-workflow 0.3.10 → 0.3.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.
Files changed (2) hide show
  1. package/dist/index.js +665 -817
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2708,10 +2708,6 @@ function getExposedProjects() {
2708
2708
  }
2709
2709
  return potentialProjects.filter((project) => isProjectExposed(config, project.name, project.sourcePath || project.path));
2710
2710
  }
2711
- function getRAGIndexPath(project) {
2712
- const scanRoot = project.path || project.dataPath;
2713
- return path17.join(project.knowledgePath || path17.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
2714
- }
2715
2711
  function getCodeIndexPath(project) {
2716
2712
  const scanRoot = project.path || project.dataPath;
2717
2713
  return path17.join(project.knowledgePath || path17.join(scanRoot, ".rrce-workflow", "knowledge"), "code-embeddings.json");
@@ -4221,238 +4217,9 @@ var init_Header = __esm({
4221
4217
  }
4222
4218
  });
4223
4219
 
4224
- // src/mcp/ui/Overview.tsx
4225
- import { useMemo } from "react";
4226
- import { Box as Box2, Text as Text2 } from "ink";
4227
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
4228
- var Overview;
4229
- var init_Overview = __esm({
4230
- "src/mcp/ui/Overview.tsx"() {
4231
- "use strict";
4232
- init_Header();
4233
- init_prompts2();
4234
- Overview = ({ serverStatus, stats }) => {
4235
- const agents = useMemo(() => getAllPrompts(), []);
4236
- return /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", flexGrow: 1, children: [
4237
- /* @__PURE__ */ jsx2(Header, {}),
4238
- /* @__PURE__ */ jsxs(Box2, { borderStyle: "round", padding: 1, borderColor: "white", flexDirection: "column", flexGrow: 1, children: [
4239
- /* @__PURE__ */ jsxs(Box2, { justifyContent: "space-between", children: [
4240
- /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", children: [
4241
- /* @__PURE__ */ jsx2(Text2, { bold: true, underline: true, children: "System Status" }),
4242
- /* @__PURE__ */ jsxs(Box2, { marginTop: 1, children: [
4243
- /* @__PURE__ */ jsx2(Text2, { children: "Integrations Installed: " }),
4244
- /* @__PURE__ */ jsx2(Text2, { color: stats.installedIntegrations > 0 ? "green" : "yellow", children: stats.installedIntegrations })
4245
- ] }),
4246
- /* @__PURE__ */ jsxs(Box2, { children: [
4247
- /* @__PURE__ */ jsx2(Text2, { children: "Server Port: " }),
4248
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: serverStatus.port })
4249
- ] })
4250
- ] }),
4251
- /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", marginLeft: 4, children: [
4252
- /* @__PURE__ */ jsx2(Text2, { bold: true, underline: true, children: "Quick Start" }),
4253
- /* @__PURE__ */ jsxs(Box2, { marginTop: 1, flexDirection: "column", children: [
4254
- /* @__PURE__ */ jsx2(Text2, { children: '1. Install "MCP" extension in VSCode / Antigravity' }),
4255
- /* @__PURE__ */ jsx2(Text2, { children: "2. Configure Extension to use this server:" }),
4256
- /* @__PURE__ */ jsx2(Text2, { color: "dim", children: " (This is handled automatically by 'Install to IDE')" }),
4257
- /* @__PURE__ */ jsx2(Text2, { children: "3. In your Agent IDE, ask:" }),
4258
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: ' "Use the rrce tools to analyze this project"' })
4259
- ] })
4260
- ] })
4261
- ] }),
4262
- /* @__PURE__ */ jsxs(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
4263
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Available Agents & Instructions:" }),
4264
- agents.map((agent) => /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", marginTop: 1, children: [
4265
- /* @__PURE__ */ jsxs(Text2, { color: "yellow", children: [
4266
- "\u27A4 ",
4267
- agent.name,
4268
- " ",
4269
- /* @__PURE__ */ jsxs(Text2, { color: "dim", children: [
4270
- "(",
4271
- agent.id,
4272
- ")"
4273
- ] })
4274
- ] }),
4275
- /* @__PURE__ */ jsxs(Text2, { color: "white", children: [
4276
- " ",
4277
- agent.description
4278
- ] }),
4279
- agent.arguments.length > 0 && /* @__PURE__ */ jsxs(Text2, { color: "dim", children: [
4280
- " Args: ",
4281
- agent.arguments.map((a) => a.name + (a.required ? "*" : "")).join(", ")
4282
- ] }),
4283
- /* @__PURE__ */ jsxs(Text2, { color: "cyan", children: [
4284
- ' Instruction: "Use the ',
4285
- agent.name,
4286
- ' to..."'
4287
- ] })
4288
- ] }, agent.id))
4289
- ] }),
4290
- /* @__PURE__ */ jsxs(Box2, { marginTop: 1, flexDirection: "column", children: [
4291
- /* @__PURE__ */ jsx2(Text2, { color: "dim", children: "Controls:" }),
4292
- /* @__PURE__ */ jsx2(Text2, { color: "dim", children: " \u2022 Press 'r' to restart server" }),
4293
- /* @__PURE__ */ jsx2(Text2, { color: "dim", children: " \u2022 Use 1-4 or \u25C4/\u25BA to navigate tabs" }),
4294
- /* @__PURE__ */ jsx2(Text2, { color: "dim", children: " \u2022 Press 'q' to stop server and exit" })
4295
- ] })
4296
- ] })
4297
- ] });
4298
- };
4299
- }
4300
- });
4301
-
4302
- // src/mcp/ui/components/SimpleSelect.tsx
4303
- import { useState } from "react";
4304
- import { Box as Box3, Text as Text3, useInput } from "ink";
4305
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
4306
- function SimpleSelect({
4307
- items,
4308
- onSelect,
4309
- isMulti = false,
4310
- initialSelected = [],
4311
- onSubmit,
4312
- onCancel,
4313
- message
4314
- }) {
4315
- const [selectedIndex, setSelectedIndex] = useState(0);
4316
- const [selectedValues, setSelectedValues] = useState(new Set(initialSelected));
4317
- useInput((input, key) => {
4318
- if (key.upArrow) {
4319
- setSelectedIndex((prev) => prev > 0 ? prev - 1 : items.length - 1);
4320
- }
4321
- if (key.downArrow) {
4322
- setSelectedIndex((prev) => prev < items.length - 1 ? prev + 1 : 0);
4323
- }
4324
- if (input === " " && isMulti) {
4325
- const item = items[selectedIndex];
4326
- if (item) {
4327
- const newSet = new Set(selectedValues);
4328
- if (newSet.has(item.value)) {
4329
- newSet.delete(item.value);
4330
- } else {
4331
- newSet.add(item.value);
4332
- }
4333
- setSelectedValues(newSet);
4334
- }
4335
- }
4336
- if (key.return) {
4337
- if (isMulti) {
4338
- onSubmit?.(Array.from(selectedValues));
4339
- } else {
4340
- const item = items[selectedIndex];
4341
- if (item) onSelect(item);
4342
- }
4343
- }
4344
- if (key.escape) {
4345
- onCancel?.();
4346
- }
4347
- });
4348
- return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
4349
- message && /* @__PURE__ */ jsx3(Box3, { marginBottom: 1, children: /* @__PURE__ */ jsx3(Text3, { bold: true, children: message }) }),
4350
- items.map((item, index) => {
4351
- const isSelected = index === selectedIndex;
4352
- const isChecked = isMulti && selectedValues.has(item.value);
4353
- return /* @__PURE__ */ jsxs2(Box3, { children: [
4354
- /* @__PURE__ */ jsx3(Text3, { color: isSelected ? "cyan" : "white", children: isSelected ? "> " : " " }),
4355
- isMulti && /* @__PURE__ */ jsx3(Text3, { color: isChecked ? "green" : "gray", children: isChecked ? "[x] " : "[ ] " }),
4356
- /* @__PURE__ */ jsx3(Text3, { color: isSelected ? "cyan" : "white", children: item.label })
4357
- ] }, item.key || String(item.value));
4358
- }),
4359
- /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: isMulti ? "Space to toggle, Enter to confirm, Esc to cancel" : "Enter to select, Esc to cancel" }) })
4360
- ] });
4361
- }
4362
- var init_SimpleSelect = __esm({
4363
- "src/mcp/ui/components/SimpleSelect.tsx"() {
4364
- "use strict";
4365
- }
4366
- });
4367
-
4368
- // src/mcp/ui/lib/tasks-fs.ts
4220
+ // src/lib/drift-service.ts
4369
4221
  import * as fs17 from "fs";
4370
4222
  import * as path19 from "path";
4371
- function detectStorageModeFromConfig(workspaceRoot) {
4372
- const configPath = getConfigPath(workspaceRoot);
4373
- try {
4374
- const rrceHome = getEffectiveGlobalBase();
4375
- if (configPath.startsWith(rrceHome)) {
4376
- return "global";
4377
- }
4378
- if (fs17.existsSync(configPath)) {
4379
- const content = fs17.readFileSync(configPath, "utf-8");
4380
- if (content.includes("mode: workspace")) return "workspace";
4381
- if (content.includes("mode: global")) return "global";
4382
- }
4383
- } catch {
4384
- }
4385
- return "global";
4386
- }
4387
- function getEffectiveGlobalBase() {
4388
- const dummy = resolveDataPath("global", "__rrce_dummy__", "");
4389
- return path19.dirname(path19.dirname(dummy));
4390
- }
4391
- function getProjectRRCEData(project) {
4392
- const workspaceRoot = project.sourcePath || project.path;
4393
- const mode = detectStorageModeFromConfig(workspaceRoot);
4394
- return resolveDataPath(mode, project.name, workspaceRoot);
4395
- }
4396
- function listProjectTasks(project) {
4397
- const rrceData = getProjectRRCEData(project);
4398
- const tasksPath = path19.join(rrceData, "tasks");
4399
- if (!fs17.existsSync(tasksPath)) {
4400
- return { projectName: project.name, tasksPath, tasks: [] };
4401
- }
4402
- const tasks = [];
4403
- try {
4404
- const entries = fs17.readdirSync(tasksPath, { withFileTypes: true });
4405
- for (const entry of entries) {
4406
- if (!entry.isDirectory()) continue;
4407
- const metaPath = path19.join(tasksPath, entry.name, "meta.json");
4408
- if (!fs17.existsSync(metaPath)) continue;
4409
- try {
4410
- const raw = fs17.readFileSync(metaPath, "utf-8");
4411
- const meta = JSON.parse(raw);
4412
- if (!meta.task_slug) meta.task_slug = entry.name;
4413
- tasks.push(meta);
4414
- } catch {
4415
- }
4416
- }
4417
- } catch {
4418
- }
4419
- tasks.sort((a, b) => {
4420
- const aTime = Date.parse(a.updated_at || a.created_at || "") || 0;
4421
- const bTime = Date.parse(b.updated_at || b.created_at || "") || 0;
4422
- if (aTime !== bTime) return bTime - aTime;
4423
- return String(a.task_slug).localeCompare(String(b.task_slug));
4424
- });
4425
- return { projectName: project.name, tasksPath, tasks };
4426
- }
4427
- function updateTaskStatus(project, taskSlug, status) {
4428
- const rrceData = getProjectRRCEData(project);
4429
- const metaPath = path19.join(rrceData, "tasks", taskSlug, "meta.json");
4430
- if (!fs17.existsSync(metaPath)) {
4431
- return { ok: false, error: `meta.json not found for task '${taskSlug}'` };
4432
- }
4433
- try {
4434
- const meta = JSON.parse(fs17.readFileSync(metaPath, "utf-8"));
4435
- const next = {
4436
- ...meta,
4437
- status,
4438
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
4439
- };
4440
- fs17.writeFileSync(metaPath, JSON.stringify(next, null, 2));
4441
- return { ok: true, meta: next };
4442
- } catch (e) {
4443
- return { ok: false, error: String(e) };
4444
- }
4445
- }
4446
- var init_tasks_fs = __esm({
4447
- "src/mcp/ui/lib/tasks-fs.ts"() {
4448
- "use strict";
4449
- init_paths();
4450
- }
4451
- });
4452
-
4453
- // src/lib/drift-service.ts
4454
- import * as fs18 from "fs";
4455
- import * as path20 from "path";
4456
4223
  import * as crypto2 from "crypto";
4457
4224
  var DriftService;
4458
4225
  var init_drift_service = __esm({
@@ -4461,26 +4228,26 @@ var init_drift_service = __esm({
4461
4228
  DriftService = class {
4462
4229
  static CHECKSUM_FILENAME = ".rrce-checksums.json";
4463
4230
  static calculateHash(filePath) {
4464
- const content = fs18.readFileSync(filePath);
4231
+ const content = fs17.readFileSync(filePath);
4465
4232
  return crypto2.createHash("md5").update(content).digest("hex");
4466
4233
  }
4467
4234
  static getManifestPath(projectPath) {
4468
- return path20.join(projectPath, this.CHECKSUM_FILENAME);
4235
+ return path19.join(projectPath, this.CHECKSUM_FILENAME);
4469
4236
  }
4470
4237
  static loadManifest(projectPath) {
4471
4238
  const manifestPath = this.getManifestPath(projectPath);
4472
- if (!fs18.existsSync(manifestPath)) {
4239
+ if (!fs17.existsSync(manifestPath)) {
4473
4240
  return {};
4474
4241
  }
4475
4242
  try {
4476
- return JSON.parse(fs18.readFileSync(manifestPath, "utf8"));
4243
+ return JSON.parse(fs17.readFileSync(manifestPath, "utf8"));
4477
4244
  } catch (e) {
4478
4245
  return {};
4479
4246
  }
4480
4247
  }
4481
4248
  static saveManifest(projectPath, manifest) {
4482
4249
  const manifestPath = this.getManifestPath(projectPath);
4483
- fs18.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
4250
+ fs17.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
4484
4251
  }
4485
4252
  /**
4486
4253
  * Generates a manifest for the current state of files in the project
@@ -4488,9 +4255,9 @@ var init_drift_service = __esm({
4488
4255
  static generateManifest(projectPath, files) {
4489
4256
  const manifest = {};
4490
4257
  for (const file of files) {
4491
- const fullPath = path20.join(projectPath, file);
4492
- if (fs18.existsSync(fullPath)) {
4493
- const stats = fs18.statSync(fullPath);
4258
+ const fullPath = path19.join(projectPath, file);
4259
+ if (fs17.existsSync(fullPath)) {
4260
+ const stats = fs17.statSync(fullPath);
4494
4261
  manifest[file] = {
4495
4262
  hash: this.calculateHash(fullPath),
4496
4263
  mtime: stats.mtimeMs
@@ -4506,11 +4273,11 @@ var init_drift_service = __esm({
4506
4273
  const manifest = this.loadManifest(projectPath);
4507
4274
  const modifiedFiles = [];
4508
4275
  for (const [relPath, entry] of Object.entries(manifest)) {
4509
- const fullPath = path20.join(projectPath, relPath);
4510
- if (!fs18.existsSync(fullPath)) {
4276
+ const fullPath = path19.join(projectPath, relPath);
4277
+ if (!fs17.existsSync(fullPath)) {
4511
4278
  continue;
4512
4279
  }
4513
- const stats = fs18.statSync(fullPath);
4280
+ const stats = fs17.statSync(fullPath);
4514
4281
  if (stats.mtimeMs === entry.mtime) {
4515
4282
  continue;
4516
4283
  }
@@ -4556,16 +4323,16 @@ __export(ConfigContext_exports, {
4556
4323
  ConfigProvider: () => ConfigProvider,
4557
4324
  useConfig: () => useConfig
4558
4325
  });
4559
- import { createContext, useContext, useState as useState2, useCallback, useMemo as useMemo2, useEffect as useEffect2 } from "react";
4560
- import * as fs19 from "fs";
4561
- import * as path21 from "path";
4562
- import { jsx as jsx4 } from "react/jsx-runtime";
4326
+ import { createContext, useContext, useState, useCallback, useMemo, useEffect } from "react";
4327
+ import * as fs18 from "fs";
4328
+ import * as path20 from "path";
4329
+ import { jsx as jsx2 } from "react/jsx-runtime";
4563
4330
  function getPackageVersion() {
4564
4331
  try {
4565
4332
  const agentCoreDir = getAgentCoreDir();
4566
- const packageJsonPath = path21.join(path21.dirname(agentCoreDir), "package.json");
4567
- if (fs19.existsSync(packageJsonPath)) {
4568
- return JSON.parse(fs19.readFileSync(packageJsonPath, "utf8")).version;
4333
+ const packageJsonPath = path20.join(path20.dirname(agentCoreDir), "package.json");
4334
+ if (fs18.existsSync(packageJsonPath)) {
4335
+ return JSON.parse(fs18.readFileSync(packageJsonPath, "utf8")).version;
4569
4336
  }
4570
4337
  } catch (e) {
4571
4338
  }
@@ -4589,9 +4356,9 @@ var init_ConfigContext = __esm({
4589
4356
  init_prompts();
4590
4357
  ConfigContext = createContext(null);
4591
4358
  ConfigProvider = ({ children }) => {
4592
- const [config, setConfig] = useState2(() => loadMCPConfig());
4593
- const [projects, setProjects] = useState2(() => scanForProjects());
4594
- const [driftReports, setDriftReports] = useState2({});
4359
+ const [config, setConfig] = useState(() => loadMCPConfig());
4360
+ const [projects, setProjects] = useState(() => scanForProjects());
4361
+ const [driftReports, setDriftReports] = useState({});
4595
4362
  const refresh = useCallback(() => {
4596
4363
  const newConfig = loadMCPConfig();
4597
4364
  const newProjects = scanForProjects();
@@ -4608,17 +4375,17 @@ var init_ConfigContext = __esm({
4608
4375
  }
4609
4376
  setDriftReports(reports);
4610
4377
  }, [projects, config]);
4611
- useEffect2(() => {
4378
+ useEffect(() => {
4612
4379
  checkAllDrift();
4613
4380
  }, [checkAllDrift]);
4614
- const exposedProjects = useMemo2(
4381
+ const exposedProjects = useMemo(
4615
4382
  () => projects.filter((p) => {
4616
4383
  const cfg = findProjectConfig(config, { name: p.name, path: p.path });
4617
4384
  return cfg?.expose ?? config.defaults.includeNew;
4618
4385
  }),
4619
4386
  [projects, config]
4620
4387
  );
4621
- const value = useMemo2(() => ({
4388
+ const value = useMemo(() => ({
4622
4389
  config,
4623
4390
  projects,
4624
4391
  exposedProjects,
@@ -4626,94 +4393,297 @@ var init_ConfigContext = __esm({
4626
4393
  refresh,
4627
4394
  checkAllDrift
4628
4395
  }), [config, projects, exposedProjects, driftReports, refresh, checkAllDrift]);
4629
- return /* @__PURE__ */ jsx4(ConfigContext.Provider, { value, children });
4396
+ return /* @__PURE__ */ jsx2(ConfigContext.Provider, { value, children });
4630
4397
  };
4631
4398
  }
4632
4399
  });
4633
4400
 
4634
- // src/mcp/ui/ui-helpers.ts
4635
- var getStatusIcon, getStatusColor, getChecklistProgress, getCheckbox, getProgressBar, getFolderIcon;
4636
- var init_ui_helpers = __esm({
4637
- "src/mcp/ui/ui-helpers.ts"() {
4638
- "use strict";
4639
- getStatusIcon = (status) => {
4640
- const icons = {
4641
- pending: "\u23F3",
4642
- in_progress: "\u{1F504}",
4643
- blocked: "\u{1F6AB}",
4644
- complete: "\u2705"
4645
- };
4646
- return icons[status] || "\u25CB";
4647
- };
4648
- getStatusColor = (status) => {
4649
- const colors = {
4650
- pending: "yellow",
4651
- in_progress: "yellow",
4652
- blocked: "red",
4653
- complete: "green"
4654
- };
4655
- return colors[status] || "white";
4656
- };
4657
- getChecklistProgress = (checklist) => {
4658
- if (!checklist || checklist.length === 0) {
4659
- return { completed: 0, total: 0, percentage: 0 };
4660
- }
4661
- const completed = checklist.filter((item) => item.status === "done").length;
4662
- return {
4663
- completed,
4664
- total: checklist.length,
4665
- percentage: Math.round(completed / checklist.length * 100)
4666
- };
4667
- };
4668
- getCheckbox = (status) => {
4669
- return status === "done" ? "\u2611" : "\u2610";
4670
- };
4671
- getProgressBar = (percentage, length = 10) => {
4672
- const filled = Math.floor(percentage / 100 * length);
4673
- const empty = length - filled;
4674
- return "\u2588".repeat(filled) + "\u2591".repeat(empty);
4675
- };
4676
- getFolderIcon = (isOpen) => {
4677
- return isOpen ? "\u{1F4C2}" : "\u{1F4C1}";
4678
- };
4401
+ // src/mcp/ui/lib/tasks-fs.ts
4402
+ import * as fs19 from "fs";
4403
+ import * as path21 from "path";
4404
+ function detectStorageModeFromConfig(workspaceRoot) {
4405
+ const configPath = getConfigPath(workspaceRoot);
4406
+ try {
4407
+ const rrceHome = getEffectiveGlobalBase();
4408
+ if (configPath.startsWith(rrceHome)) {
4409
+ return "global";
4410
+ }
4411
+ if (fs19.existsSync(configPath)) {
4412
+ const content = fs19.readFileSync(configPath, "utf-8");
4413
+ if (content.includes("mode: workspace")) return "workspace";
4414
+ if (content.includes("mode: global")) return "global";
4415
+ }
4416
+ } catch {
4679
4417
  }
4680
- });
4681
-
4682
- // src/mcp/ui/ProjectsView.tsx
4683
- import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
4684
- import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
4685
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4686
- function nextStatus(current) {
4687
- const idx = STATUS_CYCLE.indexOf(current || "");
4688
- if (idx === -1) return STATUS_CYCLE[0];
4689
- return STATUS_CYCLE[(idx + 1) % STATUS_CYCLE.length];
4418
+ return "global";
4690
4419
  }
4691
- function projectKey(p) {
4692
- return p.sourcePath ?? p.path;
4420
+ function getEffectiveGlobalBase() {
4421
+ const dummy = resolveDataPath("global", "__rrce_dummy__", "");
4422
+ return path21.dirname(path21.dirname(dummy));
4693
4423
  }
4694
- function formatProjectLabel(p, drift) {
4695
- const root = p.sourcePath ?? p.path;
4696
- const label = `${p.name} (${p.source})${root ? ` - ${root}` : ""}`;
4697
- return label;
4424
+ function getProjectRRCEData(project) {
4425
+ const workspaceRoot = project.sourcePath || project.path;
4426
+ const mode = detectStorageModeFromConfig(workspaceRoot);
4427
+ return resolveDataPath(mode, project.name, workspaceRoot);
4698
4428
  }
4699
- var STATUS_CYCLE, ProjectsView;
4700
- var init_ProjectsView = __esm({
4701
- "src/mcp/ui/ProjectsView.tsx"() {
4702
- "use strict";
4703
- init_SimpleSelect();
4704
- init_config();
4429
+ function listProjectTasks(project) {
4430
+ const rrceData = getProjectRRCEData(project);
4431
+ const tasksPath = path21.join(rrceData, "tasks");
4432
+ if (!fs19.existsSync(tasksPath)) {
4433
+ return { projectName: project.name, tasksPath, tasks: [] };
4434
+ }
4435
+ const tasks = [];
4436
+ try {
4437
+ const entries = fs19.readdirSync(tasksPath, { withFileTypes: true });
4438
+ for (const entry of entries) {
4439
+ if (!entry.isDirectory()) continue;
4440
+ const metaPath = path21.join(tasksPath, entry.name, "meta.json");
4441
+ if (!fs19.existsSync(metaPath)) continue;
4442
+ try {
4443
+ const raw = fs19.readFileSync(metaPath, "utf-8");
4444
+ const meta = JSON.parse(raw);
4445
+ if (!meta.task_slug) meta.task_slug = entry.name;
4446
+ tasks.push(meta);
4447
+ } catch {
4448
+ }
4449
+ }
4450
+ } catch {
4451
+ }
4452
+ tasks.sort((a, b) => {
4453
+ const aTime = Date.parse(a.updated_at || a.created_at || "") || 0;
4454
+ const bTime = Date.parse(b.updated_at || b.created_at || "") || 0;
4455
+ if (aTime !== bTime) return bTime - aTime;
4456
+ return String(a.task_slug).localeCompare(String(b.task_slug));
4457
+ });
4458
+ return { projectName: project.name, tasksPath, tasks };
4459
+ }
4460
+ function updateTaskStatus(project, taskSlug, status) {
4461
+ const rrceData = getProjectRRCEData(project);
4462
+ const metaPath = path21.join(rrceData, "tasks", taskSlug, "meta.json");
4463
+ if (!fs19.existsSync(metaPath)) {
4464
+ return { ok: false, error: `meta.json not found for task '${taskSlug}'` };
4465
+ }
4466
+ try {
4467
+ const meta = JSON.parse(fs19.readFileSync(metaPath, "utf-8"));
4468
+ const next = {
4469
+ ...meta,
4470
+ status,
4471
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
4472
+ };
4473
+ fs19.writeFileSync(metaPath, JSON.stringify(next, null, 2));
4474
+ return { ok: true, meta: next };
4475
+ } catch (e) {
4476
+ return { ok: false, error: String(e) };
4477
+ }
4478
+ }
4479
+ var init_tasks_fs = __esm({
4480
+ "src/mcp/ui/lib/tasks-fs.ts"() {
4481
+ "use strict";
4482
+ init_paths();
4483
+ }
4484
+ });
4485
+
4486
+ // src/mcp/ui/Overview.tsx
4487
+ import { useMemo as useMemo2 } from "react";
4488
+ import { Box as Box2, Text as Text2 } from "ink";
4489
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
4490
+ var Overview;
4491
+ var init_Overview = __esm({
4492
+ "src/mcp/ui/Overview.tsx"() {
4493
+ "use strict";
4494
+ init_Header();
4495
+ init_ConfigContext();
4705
4496
  init_tasks_fs();
4497
+ Overview = ({ serverStatus, stats, logs }) => {
4498
+ const { projects } = useConfig();
4499
+ const activeTasks = useMemo2(() => {
4500
+ const active = [];
4501
+ for (const p of projects) {
4502
+ const { tasks } = listProjectTasks(p);
4503
+ const inProgress = tasks.filter((t) => t.status === "in_progress");
4504
+ for (const t of inProgress) {
4505
+ active.push({ project: p.name, title: t.title || t.task_slug, slug: t.task_slug });
4506
+ }
4507
+ }
4508
+ return active;
4509
+ }, [projects]);
4510
+ const recentLogs = useMemo2(() => {
4511
+ return logs.slice(-5).reverse();
4512
+ }, [logs]);
4513
+ return /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", flexGrow: 1, children: [
4514
+ /* @__PURE__ */ jsx3(Header, {}),
4515
+ /* @__PURE__ */ jsxs(Box2, { borderStyle: "round", paddingX: 1, borderColor: "white", flexDirection: "column", flexGrow: 1, children: [
4516
+ /* @__PURE__ */ jsxs(Box2, { justifyContent: "space-between", children: [
4517
+ /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", width: "50%", children: [
4518
+ /* @__PURE__ */ jsx3(Text2, { bold: true, color: "cyan", children: "\u{1F680} System Cockpit" }),
4519
+ /* @__PURE__ */ jsxs(Box2, { marginTop: 1, children: [
4520
+ /* @__PURE__ */ jsx3(Text2, { children: "Integrations: " }),
4521
+ /* @__PURE__ */ jsxs(Text2, { color: stats.installedIntegrations > 0 ? "green" : "yellow", children: [
4522
+ stats.installedIntegrations,
4523
+ " active"
4524
+ ] })
4525
+ ] }),
4526
+ /* @__PURE__ */ jsxs(Box2, { children: [
4527
+ /* @__PURE__ */ jsx3(Text2, { children: "MCP Server: " }),
4528
+ /* @__PURE__ */ jsx3(Text2, { color: "green", children: "Running" }),
4529
+ /* @__PURE__ */ jsxs(Text2, { color: "dim", children: [
4530
+ " (Port: ",
4531
+ serverStatus.port,
4532
+ ")"
4533
+ ] })
4534
+ ] }),
4535
+ /* @__PURE__ */ jsxs(Box2, { children: [
4536
+ /* @__PURE__ */ jsx3(Text2, { children: "Projects: " }),
4537
+ /* @__PURE__ */ jsxs(Text2, { children: [
4538
+ stats.exposedProjects,
4539
+ " / ",
4540
+ stats.totalProjects,
4541
+ " exposed"
4542
+ ] })
4543
+ ] })
4544
+ ] }),
4545
+ /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", width: "50%", paddingLeft: 2, children: [
4546
+ /* @__PURE__ */ jsx3(Text2, { bold: true, color: "magenta", children: "\u26A1 Slash Commands" }),
4547
+ /* @__PURE__ */ jsxs(Box2, { marginTop: 1, flexDirection: "column", children: [
4548
+ /* @__PURE__ */ jsxs(Text2, { color: "cyan", children: [
4549
+ "/rrce_init ",
4550
+ /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "- Setup workspace" })
4551
+ ] }),
4552
+ /* @__PURE__ */ jsxs(Text2, { color: "cyan", children: [
4553
+ "/rrce_research ",
4554
+ /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "- Clarify requirements" })
4555
+ ] }),
4556
+ /* @__PURE__ */ jsxs(Text2, { color: "cyan", children: [
4557
+ "/rrce_plan ",
4558
+ /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "- Generate plan" })
4559
+ ] }),
4560
+ /* @__PURE__ */ jsxs(Text2, { color: "cyan", children: [
4561
+ "/rrce_execute ",
4562
+ /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "- Run executor" })
4563
+ ] })
4564
+ ] })
4565
+ ] })
4566
+ ] }),
4567
+ /* @__PURE__ */ jsxs(Box2, { marginTop: 1, borderStyle: "single", borderColor: "blue", flexDirection: "column", paddingX: 1, children: [
4568
+ /* @__PURE__ */ jsx3(Text2, { bold: true, color: "blue", children: "\u{1F3C3} Active Tasks" }),
4569
+ activeTasks.length === 0 ? /* @__PURE__ */ jsx3(Box2, { paddingY: 1, children: /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "No tasks currently in progress." }) }) : activeTasks.slice(0, 3).map((t, i) => /* @__PURE__ */ jsxs(Box2, { marginTop: i === 0 ? 0 : 0, children: [
4570
+ /* @__PURE__ */ jsxs(Text2, { color: "yellow", children: [
4571
+ "\u{1F504} ",
4572
+ t.project,
4573
+ ": "
4574
+ ] }),
4575
+ /* @__PURE__ */ jsx3(Text2, { children: t.title })
4576
+ ] }, `${t.project}-${t.slug}`)),
4577
+ activeTasks.length > 3 && /* @__PURE__ */ jsxs(Text2, { color: "dim", children: [
4578
+ " ...and ",
4579
+ activeTasks.length - 3,
4580
+ " more"
4581
+ ] })
4582
+ ] }),
4583
+ /* @__PURE__ */ jsxs(Box2, { marginTop: 1, borderStyle: "single", borderColor: "dim", flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
4584
+ /* @__PURE__ */ jsx3(Text2, { bold: true, color: "dim", children: "\u{1F4DC} Recent Activity" }),
4585
+ /* @__PURE__ */ jsx3(Box2, { flexDirection: "column", marginTop: 0, children: recentLogs.length === 0 ? /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "Waiting for activity..." }) : recentLogs.map((log, i) => /* @__PURE__ */ jsx3(Text2, { color: "white", wrap: "truncate-end", children: log.length > 80 ? log.substring(0, 77) + "..." : log }, i)) })
4586
+ ] }),
4587
+ /* @__PURE__ */ jsxs(Box2, { marginTop: 0, justifyContent: "space-between", children: [
4588
+ /* @__PURE__ */ jsx3(Box2, { children: /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "r:Restart q:Quit 1-4/\u25C4 \u25BA:Tabs" }) }),
4589
+ /* @__PURE__ */ jsx3(Box2, { children: /* @__PURE__ */ jsx3(Text2, { color: "dim", children: "RRCE MCP Hub v0.3.7" }) })
4590
+ ] })
4591
+ ] })
4592
+ ] });
4593
+ };
4594
+ }
4595
+ });
4596
+
4597
+ // src/mcp/ui/components/SimpleSelect.tsx
4598
+ import { useState as useState2 } from "react";
4599
+ import { Box as Box3, Text as Text3, useInput } from "ink";
4600
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
4601
+ function SimpleSelect({
4602
+ items,
4603
+ onSelect,
4604
+ isMulti = false,
4605
+ initialSelected = [],
4606
+ onSubmit,
4607
+ onCancel,
4608
+ message
4609
+ }) {
4610
+ const [selectedIndex, setSelectedIndex] = useState2(0);
4611
+ const [selectedValues, setSelectedValues] = useState2(new Set(initialSelected));
4612
+ useInput((input, key) => {
4613
+ if (key.upArrow) {
4614
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : items.length - 1);
4615
+ }
4616
+ if (key.downArrow) {
4617
+ setSelectedIndex((prev) => prev < items.length - 1 ? prev + 1 : 0);
4618
+ }
4619
+ if (input === " " && isMulti) {
4620
+ const item = items[selectedIndex];
4621
+ if (item) {
4622
+ const newSet = new Set(selectedValues);
4623
+ if (newSet.has(item.value)) {
4624
+ newSet.delete(item.value);
4625
+ } else {
4626
+ newSet.add(item.value);
4627
+ }
4628
+ setSelectedValues(newSet);
4629
+ }
4630
+ }
4631
+ if (key.return) {
4632
+ if (isMulti) {
4633
+ onSubmit?.(Array.from(selectedValues));
4634
+ } else {
4635
+ const item = items[selectedIndex];
4636
+ if (item) onSelect(item);
4637
+ }
4638
+ }
4639
+ if (key.escape) {
4640
+ onCancel?.();
4641
+ }
4642
+ });
4643
+ return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
4644
+ message && /* @__PURE__ */ jsx4(Box3, { marginBottom: 1, children: /* @__PURE__ */ jsx4(Text3, { bold: true, children: message }) }),
4645
+ items.map((item, index) => {
4646
+ const isSelected = index === selectedIndex;
4647
+ const isChecked = isMulti && selectedValues.has(item.value);
4648
+ return /* @__PURE__ */ jsxs2(Box3, { children: [
4649
+ /* @__PURE__ */ jsx4(Text3, { color: isSelected ? "cyan" : "white", children: isSelected ? "> " : " " }),
4650
+ isMulti && /* @__PURE__ */ jsx4(Text3, { color: isChecked ? "green" : "gray", children: isChecked ? "[x] " : "[ ] " }),
4651
+ /* @__PURE__ */ jsx4(Text3, { color: isSelected ? "cyan" : "white", children: item.label })
4652
+ ] }, item.key || String(item.value));
4653
+ }),
4654
+ /* @__PURE__ */ jsx4(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text3, { color: "gray", children: isMulti ? "Space to toggle, Enter to confirm, Esc to cancel" : "Enter to select, Esc to cancel" }) })
4655
+ ] });
4656
+ }
4657
+ var init_SimpleSelect = __esm({
4658
+ "src/mcp/ui/components/SimpleSelect.tsx"() {
4659
+ "use strict";
4660
+ }
4661
+ });
4662
+
4663
+ // src/mcp/ui/ProjectsView.tsx
4664
+ import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
4665
+ import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
4666
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4667
+ function projectKey(p) {
4668
+ return p.sourcePath ?? p.path;
4669
+ }
4670
+ function formatProjectLabel(p) {
4671
+ const root = p.sourcePath ?? p.path;
4672
+ return `${p.name} (${p.source})${root ? ` - ${root}` : ""}`;
4673
+ }
4674
+ var ProjectsView;
4675
+ var init_ProjectsView = __esm({
4676
+ "src/mcp/ui/ProjectsView.tsx"() {
4677
+ "use strict";
4678
+ init_SimpleSelect();
4679
+ init_config();
4706
4680
  init_ConfigContext();
4707
- init_ui_helpers();
4708
- STATUS_CYCLE = ["pending", "in_progress", "blocked", "complete"];
4681
+ init_indexing_jobs();
4682
+ init_config_utils();
4709
4683
  ProjectsView = ({ config: initialConfig, projects: allProjects, onConfigChange }) => {
4710
4684
  const { driftReports, checkAllDrift } = useConfig();
4711
4685
  const [config, setConfig] = useState3(initialConfig);
4712
- const [mode, setMode] = useState3("expose");
4713
- const [expanded, setExpanded] = useState3(() => /* @__PURE__ */ new Set());
4714
- const [selectedIndex, setSelectedIndex] = useState3(0);
4715
- const [taskCache, setTaskCache] = useState3({});
4716
- const [errorLine, setErrorLine] = useState3(null);
4686
+ const [indexingStats, setIndexingStats] = useState3({});
4717
4687
  const sortedProjects = useMemo3(() => {
4718
4688
  return [...allProjects].sort((a, b) => {
4719
4689
  const byName = a.name.localeCompare(b.name);
@@ -4721,113 +4691,70 @@ var init_ProjectsView = __esm({
4721
4691
  return projectKey(a).localeCompare(projectKey(b));
4722
4692
  });
4723
4693
  }, [allProjects]);
4724
- const refreshTasksForProject = (project) => {
4725
- const res = listProjectTasks(project);
4726
- setTaskCache((prev) => ({ ...prev, [projectKey(project)]: res.tasks }));
4727
- };
4728
- const refreshAllTasks = () => {
4729
- const next = {};
4730
- for (const p of sortedProjects) {
4731
- next[projectKey(p)] = listProjectTasks(p).tasks;
4732
- }
4733
- setTaskCache(next);
4734
- };
4694
+ useEffect3(() => {
4695
+ const updateStats = () => {
4696
+ const next = {};
4697
+ for (const p of allProjects) {
4698
+ let projConfig = findProjectConfig(config, { name: p.name, path: p.path });
4699
+ if (!projConfig && p.source === "global") {
4700
+ projConfig = config.projects.find((c) => c.name === p.name);
4701
+ }
4702
+ const enabled = projConfig?.semanticSearch?.enabled || p.semanticSearchEnabled || false;
4703
+ const prog = indexingJobs.getProgress(p.name);
4704
+ next[p.name] = { enabled, ...prog };
4705
+ }
4706
+ setIndexingStats(next);
4707
+ };
4708
+ updateStats();
4709
+ const interval = setInterval(updateStats, 2e3);
4710
+ return () => clearInterval(interval);
4711
+ }, [allProjects, config]);
4735
4712
  useInput2((input, key) => {
4736
- if (input === "t") {
4737
- setErrorLine(null);
4738
- setMode((prev) => prev === "expose" ? "tasks" : "expose");
4739
- return;
4740
- }
4741
4713
  if (input === "u") {
4742
4714
  checkAllDrift();
4743
4715
  return;
4744
4716
  }
4745
- if (mode === "expose") {
4746
- if (input === "a") {
4747
- const newConfig = {
4748
- ...config,
4749
- defaults: {
4750
- ...config.defaults,
4751
- includeNew: !config.defaults.includeNew
4752
- }
4753
- };
4754
- saveMCPConfig(newConfig);
4755
- setConfig(newConfig);
4756
- onConfigChange?.();
4757
- }
4758
- return;
4759
- }
4760
- if (mode === "tasks") {
4761
- if (input === "R") {
4762
- setErrorLine(null);
4763
- refreshAllTasks();
4764
- return;
4765
- }
4766
- if (key.upArrow) {
4767
- setSelectedIndex((prev) => prev > 0 ? prev - 1 : Math.max(0, flattenedRows.length - 1));
4768
- return;
4769
- }
4770
- if (key.downArrow) {
4771
- setSelectedIndex((prev) => prev < flattenedRows.length - 1 ? prev + 1 : 0);
4772
- return;
4773
- }
4774
- if (key.return) {
4775
- const row = flattenedRows[selectedIndex];
4776
- if (row?.kind === "project") {
4777
- const k = projectKey(row.project);
4778
- const next = new Set(expanded);
4779
- if (next.has(k)) {
4780
- next.delete(k);
4781
- } else {
4782
- next.add(k);
4783
- refreshTasksForProject(row.project);
4784
- }
4785
- setExpanded(next);
4717
+ if (input === "a") {
4718
+ const newConfig = {
4719
+ ...config,
4720
+ defaults: {
4721
+ ...config.defaults,
4722
+ includeNew: !config.defaults.includeNew
4786
4723
  }
4787
- return;
4788
- }
4789
- if (input === "s") {
4790
- const row = flattenedRows[selectedIndex];
4791
- if (row?.kind === "task") {
4792
- setErrorLine(null);
4793
- const desired = nextStatus(row.task.status);
4794
- const result = updateTaskStatus(row.project, row.task.task_slug, desired);
4795
- if (!result.ok) {
4796
- setErrorLine(`Failed to update status: ${result.error}`);
4797
- return;
4798
- }
4799
- setTaskCache((prev) => {
4800
- const k = projectKey(row.project);
4801
- const tasks = prev[k] || [];
4802
- const updated = tasks.map((t) => t.task_slug === row.task.task_slug ? result.meta : t);
4803
- return { ...prev, [k]: updated };
4804
- });
4805
- }
4806
- return;
4807
- }
4724
+ };
4725
+ saveMCPConfig(newConfig);
4726
+ setConfig(newConfig);
4727
+ onConfigChange?.();
4808
4728
  }
4809
4729
  });
4810
- useEffect3(() => {
4811
- setSelectedIndex((prev) => {
4812
- if (flattenedRows.length === 0) return 0;
4813
- return Math.min(prev, flattenedRows.length - 1);
4814
- });
4815
- }, [mode, allProjects, expanded, taskCache]);
4816
4730
  const projectItems = useMemo3(() => {
4817
- return allProjects.map((p) => {
4731
+ return sortedProjects.map((p) => {
4818
4732
  const projectConfig = config.projects.find(
4819
4733
  (c) => c.path && c.path === p.path || p.source === "global" && c.name === p.name || !c.path && c.name === p.name
4820
4734
  );
4821
4735
  const isExposed = projectConfig ? projectConfig.expose : config.defaults.includeNew;
4822
4736
  const drift = driftReports[p.path];
4737
+ const idx = indexingStats[p.name];
4738
+ let label = formatProjectLabel(p);
4739
+ if (idx?.state === "running") {
4740
+ label += ` [\u27F3 Indexing ${idx.itemsDone}/${idx.itemsTotal ?? "?"}]`;
4741
+ } else if (idx?.state === "failed") {
4742
+ label += ` [\u2715 Index Fail]`;
4743
+ } else if (idx?.enabled && idx?.state === "complete") {
4744
+ label += ` [\u2713 Indexed]`;
4745
+ }
4746
+ if (drift?.hasDrift) {
4747
+ label += ` \u26A0`;
4748
+ }
4823
4749
  return {
4824
- label: formatProjectLabel(p, drift),
4750
+ label,
4825
4751
  value: p.path,
4826
4752
  key: p.path,
4827
- exposed: isExposed
4753
+ exposed: isExposed,
4754
+ indexing: idx
4828
4755
  };
4829
4756
  });
4830
- }, [allProjects, config, driftReports]);
4757
+ }, [sortedProjects, config, driftReports, indexingStats]);
4831
4758
  const initialSelected = useMemo3(() => {
4832
4759
  return projectItems.filter((p) => p.exposed).map((p) => p.value);
4833
4760
  }, [projectItems]);
@@ -4852,11 +4779,140 @@ var init_ProjectsView = __esm({
4852
4779
  setConfig(newConfig);
4853
4780
  onConfigChange?.();
4854
4781
  };
4855
- const flattenedRows = useMemo3(() => {
4782
+ return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
4783
+ /* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
4784
+ /* @__PURE__ */ jsxs3(Box4, { children: [
4785
+ /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: " Projects " }),
4786
+ /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " \u2022 " }),
4787
+ /* @__PURE__ */ jsxs3(Text4, { color: config.defaults.includeNew ? "green" : "red", children: [
4788
+ "Auto-expose: ",
4789
+ config.defaults.includeNew ? "ON" : "OFF"
4790
+ ] })
4791
+ ] }),
4792
+ /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "a:Toggle Auto u:Drift Space:Select Enter:Save" }) })
4793
+ ] }),
4794
+ /* @__PURE__ */ jsx5(Text4, { color: "dim", children: " Manage which projects are exposed to the MCP server. Indexing status shown in-line." }),
4795
+ /* @__PURE__ */ jsx5(Box4, { marginTop: 1, flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx5(
4796
+ SimpleSelect,
4797
+ {
4798
+ message: "",
4799
+ items: projectItems,
4800
+ isMulti: true,
4801
+ initialSelected,
4802
+ onSelect: () => {
4803
+ },
4804
+ onSubmit: handleSubmit,
4805
+ onCancel: () => {
4806
+ }
4807
+ },
4808
+ JSON.stringify(initialSelected) + config.defaults.includeNew + JSON.stringify(indexingStats)
4809
+ ) }),
4810
+ /* @__PURE__ */ jsx5(Box4, { marginTop: 1, borderStyle: "single", borderColor: "dim", paddingX: 1, children: /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Use 'rrce-workflow wizard' to manage project exposures and settings." }) })
4811
+ ] });
4812
+ };
4813
+ }
4814
+ });
4815
+
4816
+ // src/mcp/ui/ui-helpers.ts
4817
+ var getStatusIcon, getStatusColor, getChecklistProgress, getCheckbox, getProgressBar, getFolderIcon;
4818
+ var init_ui_helpers = __esm({
4819
+ "src/mcp/ui/ui-helpers.ts"() {
4820
+ "use strict";
4821
+ getStatusIcon = (status) => {
4822
+ const icons = {
4823
+ pending: "\u23F3",
4824
+ in_progress: "\u{1F504}",
4825
+ blocked: "\u{1F6AB}",
4826
+ complete: "\u2705"
4827
+ };
4828
+ return icons[status] || "\u25CB";
4829
+ };
4830
+ getStatusColor = (status) => {
4831
+ const colors = {
4832
+ pending: "yellow",
4833
+ in_progress: "yellow",
4834
+ blocked: "red",
4835
+ complete: "green"
4836
+ };
4837
+ return colors[status] || "white";
4838
+ };
4839
+ getChecklistProgress = (checklist) => {
4840
+ if (!checklist || checklist.length === 0) {
4841
+ return { completed: 0, total: 0, percentage: 0 };
4842
+ }
4843
+ const completed = checklist.filter((item) => item.status === "done").length;
4844
+ return {
4845
+ completed,
4846
+ total: checklist.length,
4847
+ percentage: Math.round(completed / checklist.length * 100)
4848
+ };
4849
+ };
4850
+ getCheckbox = (status) => {
4851
+ return status === "done" ? "\u2611" : "\u2610";
4852
+ };
4853
+ getProgressBar = (percentage, length = 10) => {
4854
+ const filled = Math.floor(percentage / 100 * length);
4855
+ const empty = length - filled;
4856
+ return "\u2588".repeat(filled) + "\u2591".repeat(empty);
4857
+ };
4858
+ getFolderIcon = (isOpen) => {
4859
+ return isOpen ? "\u{1F4C2}" : "\u{1F4C1}";
4860
+ };
4861
+ }
4862
+ });
4863
+
4864
+ // src/mcp/ui/TasksView.tsx
4865
+ import { useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
4866
+ import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
4867
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
4868
+ function nextStatus(current) {
4869
+ const idx = STATUS_CYCLE.indexOf(current || "");
4870
+ if (idx === -1) return STATUS_CYCLE[0];
4871
+ return STATUS_CYCLE[(idx + 1) % STATUS_CYCLE.length];
4872
+ }
4873
+ function projectKey2(p) {
4874
+ return p.sourcePath ?? p.path;
4875
+ }
4876
+ function formatProjectLabel2(p) {
4877
+ return `${p.name} (${p.source})`;
4878
+ }
4879
+ var STATUS_CYCLE, TasksView;
4880
+ var init_TasksView = __esm({
4881
+ "src/mcp/ui/TasksView.tsx"() {
4882
+ "use strict";
4883
+ init_tasks_fs();
4884
+ init_ConfigContext();
4885
+ init_ui_helpers();
4886
+ STATUS_CYCLE = ["pending", "in_progress", "blocked", "complete"];
4887
+ TasksView = ({ projects: allProjects }) => {
4888
+ const { driftReports } = useConfig();
4889
+ const [expanded, setExpanded] = useState4(() => /* @__PURE__ */ new Set());
4890
+ const [selectedIndex, setSelectedIndex] = useState4(0);
4891
+ const [taskCache, setTaskCache] = useState4({});
4892
+ const [errorLine, setErrorLine] = useState4(null);
4893
+ const sortedProjects = useMemo4(() => {
4894
+ return [...allProjects].sort((a, b) => {
4895
+ const byName = a.name.localeCompare(b.name);
4896
+ if (byName !== 0) return byName;
4897
+ return projectKey2(a).localeCompare(projectKey2(b));
4898
+ });
4899
+ }, [allProjects]);
4900
+ const refreshTasksForProject = (project) => {
4901
+ const res = listProjectTasks(project);
4902
+ setTaskCache((prev) => ({ ...prev, [projectKey2(project)]: res.tasks }));
4903
+ };
4904
+ const refreshAllTasks = () => {
4905
+ const next = {};
4906
+ for (const p of sortedProjects) {
4907
+ next[projectKey2(p)] = listProjectTasks(p).tasks;
4908
+ }
4909
+ setTaskCache(next);
4910
+ };
4911
+ const flattenedRows = useMemo4(() => {
4856
4912
  const rows = [];
4857
4913
  for (const p of sortedProjects) {
4858
4914
  rows.push({ kind: "project", project: p });
4859
- const k = projectKey(p);
4915
+ const k = projectKey2(p);
4860
4916
  if (!expanded.has(k)) continue;
4861
4917
  const tasks = taskCache[k] || [];
4862
4918
  for (const t of tasks) {
@@ -4868,133 +4924,154 @@ var init_ProjectsView = __esm({
4868
4924
  }
4869
4925
  return rows;
4870
4926
  }, [sortedProjects, expanded, taskCache]);
4927
+ useInput3((input, key) => {
4928
+ if (input === "R") {
4929
+ setErrorLine(null);
4930
+ refreshAllTasks();
4931
+ return;
4932
+ }
4933
+ if (key.upArrow) {
4934
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : Math.max(0, flattenedRows.length - 1));
4935
+ return;
4936
+ }
4937
+ if (key.downArrow) {
4938
+ setSelectedIndex((prev) => prev < flattenedRows.length - 1 ? prev + 1 : 0);
4939
+ return;
4940
+ }
4941
+ if (key.return) {
4942
+ const row = flattenedRows[selectedIndex];
4943
+ if (row?.kind === "project") {
4944
+ const k = projectKey2(row.project);
4945
+ const next = new Set(expanded);
4946
+ if (next.has(k)) {
4947
+ next.delete(k);
4948
+ } else {
4949
+ next.add(k);
4950
+ refreshTasksForProject(row.project);
4951
+ }
4952
+ setExpanded(next);
4953
+ }
4954
+ return;
4955
+ }
4956
+ if (input === "s") {
4957
+ const row = flattenedRows[selectedIndex];
4958
+ if (row?.kind === "task") {
4959
+ setErrorLine(null);
4960
+ const desired = nextStatus(row.task.status);
4961
+ const result = updateTaskStatus(row.project, row.task.task_slug, desired);
4962
+ if (!result.ok) {
4963
+ setErrorLine(`Failed to update status: ${result.error}`);
4964
+ return;
4965
+ }
4966
+ setTaskCache((prev) => {
4967
+ const k = projectKey2(row.project);
4968
+ const tasks = prev[k] || [];
4969
+ const updated = tasks.map((t) => t.task_slug === row.task.task_slug ? result.meta : t);
4970
+ return { ...prev, [k]: updated };
4971
+ });
4972
+ }
4973
+ return;
4974
+ }
4975
+ });
4976
+ useEffect4(() => {
4977
+ setSelectedIndex((prev) => {
4978
+ if (flattenedRows.length === 0) return 0;
4979
+ return Math.min(prev, flattenedRows.length - 1);
4980
+ });
4981
+ }, [flattenedRows]);
4871
4982
  const selectedRow = flattenedRows[selectedIndex];
4872
4983
  const selectedTask = selectedRow?.kind === "task" && selectedRow.task.task_slug !== "__none__" ? selectedRow.task : null;
4873
- if (mode === "expose") {
4874
- return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
4875
- /* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
4876
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: " Projects (Expose Mode) " }),
4877
- /* @__PURE__ */ jsxs3(Box4, { children: [
4878
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "Auto-expose new: " }),
4879
- /* @__PURE__ */ jsx5(Text4, { color: config.defaults.includeNew ? "green" : "red", children: config.defaults.includeNew ? "ON" : "OFF" }),
4880
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " (Press 'a' to toggle)" })
4881
- ] })
4882
- ] }),
4883
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: " Space toggles, Enter saves. Press 't' to switch to Tasks Mode." }),
4884
- /* @__PURE__ */ jsx5(Box4, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx5(
4885
- SimpleSelect,
4886
- {
4887
- message: "",
4888
- items: projectItems,
4889
- isMulti: true,
4890
- initialSelected,
4891
- onSelect: () => {
4892
- },
4893
- onSubmit: handleSubmit,
4894
- onCancel: () => {
4895
- }
4896
- },
4897
- JSON.stringify(initialSelected) + config.defaults.includeNew
4898
- ) })
4899
- ] });
4900
- }
4901
- return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
4902
- /* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
4903
- /* @__PURE__ */ jsxs3(Box4, { children: [
4904
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: "\u2699 Tasks Mode" }),
4905
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " \u2022 " }),
4906
- /* @__PURE__ */ jsxs3(Text4, { children: [
4984
+ return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
4985
+ /* @__PURE__ */ jsxs4(Box5, { justifyContent: "space-between", children: [
4986
+ /* @__PURE__ */ jsxs4(Box5, { children: [
4987
+ /* @__PURE__ */ jsx6(Text5, { bold: true, color: "cyan", children: "\u2699 Tasks" }),
4988
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " \u2022 " }),
4989
+ /* @__PURE__ */ jsxs4(Text5, { children: [
4907
4990
  sortedProjects.length,
4908
4991
  " projects"
4909
4992
  ] }),
4910
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " \u2022 " }),
4911
- /* @__PURE__ */ jsxs3(Text4, { children: [
4993
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " \u2022 " }),
4994
+ /* @__PURE__ */ jsxs4(Text5, { children: [
4912
4995
  Object.values(taskCache).flat().length,
4913
4996
  " tasks"
4914
4997
  ] })
4915
4998
  ] }),
4916
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "t:Expose \u2191/\u2193:Nav Enter:Expand s:Status R:Refresh u:Drift" })
4999
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2191/\u2193:Nav Enter:Expand s:Status R:Refresh" })
4917
5000
  ] }),
4918
- errorLine && /* @__PURE__ */ jsx5(Box4, { marginTop: 0, children: /* @__PURE__ */ jsx5(Text4, { color: "red", children: errorLine }) }),
4919
- /* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "row", flexGrow: 1, children: [
4920
- /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", width: "55%", children: [
4921
- flattenedRows.length === 0 ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "No projects detected." }) : flattenedRows.map((row, idx) => {
5001
+ errorLine && /* @__PURE__ */ jsx6(Box5, { marginTop: 0, children: /* @__PURE__ */ jsx6(Text5, { color: "red", children: errorLine }) }),
5002
+ /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, flexDirection: "row", flexGrow: 1, children: [
5003
+ /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", width: "55%", children: [
5004
+ flattenedRows.length === 0 ? /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "No projects detected." }) : flattenedRows.map((row, idx) => {
4922
5005
  const isSel = idx === selectedIndex;
4923
5006
  if (row.kind === "project") {
4924
- const k = projectKey(row.project);
5007
+ const k = projectKey2(row.project);
4925
5008
  const isOpen = expanded.has(k);
4926
5009
  const count = (taskCache[k] || []).length;
4927
5010
  const drift = driftReports[row.project.path];
4928
- return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", children: [
4929
- /* @__PURE__ */ jsxs3(Box4, { children: [
4930
- /* @__PURE__ */ jsx5(Text4, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
4931
- /* @__PURE__ */ jsxs3(Text4, { color: isSel ? "cyan" : "white", children: [
4932
- getFolderIcon(isOpen),
4933
- " ",
4934
- formatProjectLabel(row.project, drift)
4935
- ] }),
4936
- drift?.hasDrift && /* @__PURE__ */ jsx5(Text4, { color: "magenta", children: " \u26A0" }),
4937
- /* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
4938
- " ",
4939
- count > 0 ? `(${count})` : ""
4940
- ] })
5011
+ return /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsxs4(Box5, { children: [
5012
+ /* @__PURE__ */ jsx6(Text5, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
5013
+ /* @__PURE__ */ jsxs4(Text5, { color: isSel ? "cyan" : "white", children: [
5014
+ getFolderIcon(isOpen),
5015
+ " ",
5016
+ formatProjectLabel2(row.project)
4941
5017
  ] }),
4942
- isSel && drift?.hasDrift && /* @__PURE__ */ jsx5(Box4, { marginLeft: 4, children: /* @__PURE__ */ jsxs3(Text4, { color: "magenta", dimColor: true, italic: true, children: [
4943
- drift.type === "version" ? "New version available. " : "Modifications detected. ",
4944
- "Run 'rrce-workflow wizard' to update."
4945
- ] }) })
4946
- ] }, `p:${k}`);
5018
+ drift?.hasDrift && /* @__PURE__ */ jsx6(Text5, { color: "magenta", children: " \u26A0" }),
5019
+ /* @__PURE__ */ jsxs4(Text5, { color: "dim", children: [
5020
+ " ",
5021
+ count > 0 ? `(${count})` : ""
5022
+ ] })
5023
+ ] }) }, `p:${k}`);
4947
5024
  }
4948
5025
  const taskLabel = row.task.title || row.task.task_slug;
4949
5026
  const status = row.task.status || "";
4950
- return /* @__PURE__ */ jsxs3(Box4, { children: [
4951
- /* @__PURE__ */ jsx5(Text4, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
4952
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: " - " }),
4953
- /* @__PURE__ */ jsx5(Text4, { color: isSel ? "cyan" : "white", children: taskLabel }),
4954
- row.task.task_slug !== "__none__" && /* @__PURE__ */ jsx5(Text4, { backgroundColor: getStatusColor(status), color: "black", children: ` ${getStatusIcon(status)} ${status.toUpperCase().replace("_", " ")} ` })
4955
- ] }, `t:${projectKey(row.project)}:${row.task.task_slug}`);
5027
+ return /* @__PURE__ */ jsxs4(Box5, { children: [
5028
+ /* @__PURE__ */ jsx6(Text5, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
5029
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: " - " }),
5030
+ /* @__PURE__ */ jsx6(Text5, { color: isSel ? "cyan" : "white", children: taskLabel }),
5031
+ row.task.task_slug !== "__none__" && /* @__PURE__ */ jsx6(Text5, { backgroundColor: getStatusColor(status), color: "black", children: ` ${getStatusIcon(status)} ${status.toUpperCase().replace("_", " ")} ` })
5032
+ ] }, `t:${projectKey2(row.project)}:${row.task.task_slug}`);
4956
5033
  }),
4957
- /* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text4, { color: "gray", children: "\u25B2/\u25BC navigate \u2022 Enter expand/collapse \u2022 s cycle status \u2022 R refresh \u2022 t expose mode" }) })
5034
+ /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text5, { color: "gray", children: "\u25B2/\u25BC navigate \u2022 Enter expand/collapse \u2022 s cycle status \u2022 R refresh" }) })
4958
5035
  ] }),
4959
- /* @__PURE__ */ jsx5(Box4, { flexDirection: "column", width: "45%", paddingLeft: 2, children: !selectedTask ? /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", justifyContent: "center", alignItems: "center", gap: 1, children: [
4960
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "dim", children: "\u2500 No Task Selected \u2500" }),
4961
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Use \u2191/\u2193 to navigate, Enter to expand projects" }),
4962
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Press 's' to cycle task status, 't' to switch modes" })
4963
- ] }) : /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", children: [
4964
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: selectedTask.title || selectedTask.task_slug }),
4965
- selectedTask.summary && /* @__PURE__ */ jsx5(Text4, { children: selectedTask.summary }),
4966
- /* @__PURE__ */ jsxs3(Box4, { marginTop: 1, borderStyle: "single", borderColor: "dim", padding: 1, flexDirection: "column", children: [
4967
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: "\u{1F4CB} Status" }),
4968
- /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", marginTop: 0, children: [
4969
- /* @__PURE__ */ jsxs3(Text4, { children: [
4970
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Status:" }),
5036
+ /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", width: "45%", paddingLeft: 2, children: !selectedTask ? /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", justifyContent: "center", alignItems: "center", gap: 1, children: [
5037
+ /* @__PURE__ */ jsx6(Text5, { bold: true, color: "dim", children: "\u2500 No Task Selected \u2500" }),
5038
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Use \u2191/\u2193 to navigate, Enter to expand projects" }),
5039
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Press 's' to cycle task status" })
5040
+ ] }) : /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
5041
+ /* @__PURE__ */ jsx6(Text5, { bold: true, color: "cyan", children: selectedTask.title || selectedTask.task_slug }),
5042
+ selectedTask.summary && /* @__PURE__ */ jsx6(Text5, { children: selectedTask.summary }),
5043
+ /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, borderStyle: "single", borderColor: "dim", padding: 1, flexDirection: "column", children: [
5044
+ /* @__PURE__ */ jsx6(Text5, { bold: true, color: "cyan", children: "\u{1F4CB} Status" }),
5045
+ /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 0, children: [
5046
+ /* @__PURE__ */ jsxs4(Text5, { children: [
5047
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Status:" }),
4971
5048
  " ",
4972
- /* @__PURE__ */ jsx5(Text4, { children: selectedTask.status || "unknown" })
5049
+ /* @__PURE__ */ jsx6(Text5, { children: selectedTask.status || "unknown" })
4973
5050
  ] }),
4974
- /* @__PURE__ */ jsxs3(Text4, { children: [
4975
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Updated:" }),
5051
+ /* @__PURE__ */ jsxs4(Text5, { children: [
5052
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Updated:" }),
4976
5053
  " ",
4977
- /* @__PURE__ */ jsx5(Text4, { children: selectedTask.updated_at || "\u2014" })
5054
+ /* @__PURE__ */ jsx6(Text5, { children: selectedTask.updated_at || "\u2014" })
4978
5055
  ] }),
4979
- /* @__PURE__ */ jsxs3(Text4, { children: [
4980
- /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Tags:" }),
5056
+ /* @__PURE__ */ jsxs4(Text5, { children: [
5057
+ /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "Tags:" }),
4981
5058
  " ",
4982
5059
  " ",
4983
5060
  (() => {
4984
5061
  const tags = selectedTask.tags || [];
4985
- return tags.length > 0 ? tags.map((tag, i) => /* @__PURE__ */ jsxs3(Text4, { children: [
4986
- /* @__PURE__ */ jsx5(Text4, { color: "cyan", children: tag }),
4987
- i < tags.length - 1 && /* @__PURE__ */ jsx5(Text4, { color: "dim", children: ", " })
4988
- ] }, tag)) : /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "\u2014" });
5062
+ return tags.length > 0 ? tags.map((tag, i) => /* @__PURE__ */ jsxs4(Text5, { children: [
5063
+ /* @__PURE__ */ jsx6(Text5, { color: "cyan", children: tag }),
5064
+ i < tags.length - 1 && /* @__PURE__ */ jsx6(Text5, { color: "dim", children: ", " })
5065
+ ] }, tag)) : /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2014" });
4989
5066
  })()
4990
5067
  ] })
4991
5068
  ] })
4992
5069
  ] }),
4993
- /* @__PURE__ */ jsxs3(Box4, { marginTop: 1, borderStyle: "single", borderColor: "dim", padding: 1, flexDirection: "column", children: [
4994
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: "\u{1F4CB} Checklist" }),
4995
- selectedTask.checklist && selectedTask.checklist.length > 0 && /* @__PURE__ */ jsx5(Box4, { marginTop: 0, flexDirection: "column", children: /* @__PURE__ */ jsxs3(Box4, { children: [
4996
- /* @__PURE__ */ jsx5(Text4, { backgroundColor: "white", children: getProgressBar(getChecklistProgress(selectedTask.checklist).percentage) }),
4997
- /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
5070
+ /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, borderStyle: "single", borderColor: "dim", padding: 1, flexDirection: "column", children: [
5071
+ /* @__PURE__ */ jsx6(Text5, { bold: true, color: "cyan", children: "\u{1F4CB} Checklist" }),
5072
+ selectedTask.checklist && selectedTask.checklist.length > 0 && /* @__PURE__ */ jsx6(Box5, { marginTop: 0, flexDirection: "column", children: /* @__PURE__ */ jsxs4(Box5, { children: [
5073
+ /* @__PURE__ */ jsx6(Text5, { backgroundColor: "white", children: getProgressBar(getChecklistProgress(selectedTask.checklist).percentage) }),
5074
+ /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
4998
5075
  " ",
4999
5076
  " ",
5000
5077
  getChecklistProgress(selectedTask.checklist).completed,
@@ -5005,31 +5082,31 @@ var init_ProjectsView = __esm({
5005
5082
  "%)"
5006
5083
  ] })
5007
5084
  ] }) }),
5008
- (selectedTask.checklist || []).length === 0 ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "\u2014" }) : (selectedTask.checklist || []).slice(0, 12).map((c, i) => /* @__PURE__ */ jsxs3(Text4, { children: [
5009
- /* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
5085
+ (selectedTask.checklist || []).length === 0 ? /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2014" }) : (selectedTask.checklist || []).slice(0, 12).map((c, i) => /* @__PURE__ */ jsxs4(Text5, { children: [
5086
+ /* @__PURE__ */ jsxs4(Text5, { color: "dim", children: [
5010
5087
  getCheckbox(c.status || "pending"),
5011
5088
  " "
5012
5089
  ] }),
5013
5090
  c.label || c.id || "item"
5014
5091
  ] }, c.id || i))
5015
5092
  ] }),
5016
- /* @__PURE__ */ jsxs3(Box4, { marginTop: 1, borderStyle: "single", borderColor: "dim", padding: 1, flexDirection: "column", children: [
5017
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: "\u{1F916} Agents" }),
5018
- !selectedTask.agents ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "\u2014" }) : Object.entries(selectedTask.agents).map(([agent, info]) => /* @__PURE__ */ jsxs3(Text4, { children: [
5019
- /* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
5093
+ /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, borderStyle: "single", borderColor: "dim", padding: 1, flexDirection: "column", children: [
5094
+ /* @__PURE__ */ jsx6(Text5, { bold: true, color: "cyan", children: "\u{1F916} Agents" }),
5095
+ !selectedTask.agents ? /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u2014" }) : Object.entries(selectedTask.agents).map(([agent, info]) => /* @__PURE__ */ jsxs4(Text5, { children: [
5096
+ /* @__PURE__ */ jsxs4(Text5, { color: "dim", children: [
5020
5097
  "- ",
5021
5098
  agent,
5022
5099
  ": "
5023
5100
  ] }),
5024
- info?.status === "complete" && /* @__PURE__ */ jsx5(Text4, { color: "green", children: "\u2713" }),
5025
- info?.status === "in_progress" && /* @__PURE__ */ jsx5(Text4, { color: "yellow", children: "\u27F3" }),
5026
- info?.status === "pending" && /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "\u25CB" }),
5027
- info?.blocked && /* @__PURE__ */ jsx5(Text4, { color: "red", children: "\u2715" }),
5028
- /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
5101
+ info?.status === "complete" && /* @__PURE__ */ jsx6(Text5, { color: "green", children: "\u2713" }),
5102
+ info?.status === "in_progress" && /* @__PURE__ */ jsx6(Text5, { color: "yellow", children: "\u27F3" }),
5103
+ info?.status === "pending" && /* @__PURE__ */ jsx6(Text5, { color: "dim", children: "\u25CB" }),
5104
+ info?.blocked && /* @__PURE__ */ jsx6(Text5, { color: "red", children: "\u2715" }),
5105
+ /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
5029
5106
  " ",
5030
5107
  info?.status || "\u2014"
5031
5108
  ] }),
5032
- info?.artifact && /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
5109
+ info?.artifact && /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
5033
5110
  "(",
5034
5111
  info.artifact,
5035
5112
  ")"
@@ -5043,126 +5120,10 @@ var init_ProjectsView = __esm({
5043
5120
  }
5044
5121
  });
5045
5122
 
5046
- // src/mcp/ui/components/InstallWizard.tsx
5047
- import { useState as useState4 } from "react";
5048
- import { Box as Box5, Text as Text5 } from "ink";
5049
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
5050
- var InstallWizard;
5051
- var init_InstallWizard = __esm({
5052
- "src/mcp/ui/components/InstallWizard.tsx"() {
5053
- "use strict";
5054
- init_SimpleSelect();
5055
- init_install();
5056
- InstallWizard = ({ workspacePath, onComplete, onCancel }) => {
5057
- const [status, setStatus] = useState4(checkInstallStatus(workspacePath));
5058
- const [message, setMessage] = useState4("");
5059
- const options = [
5060
- {
5061
- value: "opencode",
5062
- label: "OpenCode",
5063
- hint: status.opencode ? "INSTALLED" : "Not installed"
5064
- },
5065
- {
5066
- value: "antigravity",
5067
- label: "Antigravity IDE",
5068
- hint: status.antigravity ? "INSTALLED" : "Not installed"
5069
- },
5070
- {
5071
- value: "vscode-global",
5072
- label: "VSCode (Global Settings)",
5073
- hint: status.vscodeGlobal ? "INSTALLED" : "Not installed"
5074
- },
5075
- {
5076
- value: "vscode-workspace",
5077
- label: "VSCode (Workspace Config)",
5078
- hint: status.vscodeWorkspace ? "INSTALLED" : "Not installed"
5079
- },
5080
- {
5081
- value: "claude",
5082
- label: "Claude Desktop",
5083
- hint: status.claude ? "INSTALLED" : "Not installed"
5084
- }
5085
- ];
5086
- const initialSelected = [
5087
- ...status.opencode ? ["opencode"] : [],
5088
- ...status.antigravity ? ["antigravity"] : [],
5089
- ...status.vscodeGlobal ? ["vscode-global"] : [],
5090
- ...status.vscodeWorkspace ? ["vscode-workspace"] : [],
5091
- ...status.claude ? ["claude"] : []
5092
- ];
5093
- const handleSubmit = (selectedIds) => {
5094
- const targets = selectedIds;
5095
- let results = [];
5096
- targets.forEach((target) => {
5097
- const success = installToConfig(target, workspacePath);
5098
- const label = getTargetLabel(target);
5099
- results.push(`${label}: ${success ? "Success" : "Failed"}`);
5100
- });
5101
- setStatus(checkInstallStatus(workspacePath));
5102
- setMessage(`Installation updated: ${results.join(", ")}`);
5103
- setTimeout(() => {
5104
- setMessage("");
5105
- onComplete();
5106
- }, 2e3);
5107
- };
5108
- return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
5109
- message && /* @__PURE__ */ jsx6(Text5, { color: "green", children: message }),
5110
- /* @__PURE__ */ jsx6(
5111
- SimpleSelect,
5112
- {
5113
- message: "Select integrations to install:",
5114
- items: options.map((o) => ({
5115
- value: o.value,
5116
- label: o.label + (o.hint === "INSTALLED" ? " (Installed)" : ""),
5117
- key: o.value
5118
- })),
5119
- isMulti: true,
5120
- initialSelected,
5121
- onSelect: () => {
5122
- },
5123
- onSubmit: handleSubmit,
5124
- onCancel
5125
- }
5126
- )
5127
- ] });
5128
- };
5129
- }
5130
- });
5131
-
5132
- // src/mcp/ui/InstallView.tsx
5123
+ // src/mcp/ui/LogViewer.tsx
5133
5124
  import "react";
5134
5125
  import { Box as Box6, Text as Text6 } from "ink";
5135
5126
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
5136
- var InstallView;
5137
- var init_InstallView = __esm({
5138
- "src/mcp/ui/InstallView.tsx"() {
5139
- "use strict";
5140
- init_InstallWizard();
5141
- init_paths();
5142
- InstallView = () => {
5143
- const workspacePath = detectWorkspaceRoot();
5144
- return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "magenta", flexGrow: 1, children: [
5145
- /* @__PURE__ */ jsx7(Text6, { bold: true, color: "magenta", children: " Installation & Configuration " }),
5146
- /* @__PURE__ */ jsx7(Text6, { color: "dim", children: " Configure IDE integrations for OpenCode, VSCode, Claude, and Antigravity." }),
5147
- /* @__PURE__ */ jsx7(Box6, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx7(
5148
- InstallWizard,
5149
- {
5150
- workspacePath,
5151
- onComplete: () => {
5152
- },
5153
- onCancel: () => {
5154
- }
5155
- }
5156
- ) })
5157
- ] });
5158
- };
5159
- }
5160
- });
5161
-
5162
- // src/mcp/ui/LogViewer.tsx
5163
- import "react";
5164
- import { Box as Box7, Text as Text7 } from "ink";
5165
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
5166
5127
  var LogViewer;
5167
5128
  var init_LogViewer = __esm({
5168
5129
  "src/mcp/ui/LogViewer.tsx"() {
@@ -5172,16 +5133,16 @@ var init_LogViewer = __esm({
5172
5133
  const emptyLines = Math.max(0, height - visibleLogs.length);
5173
5134
  const padding = Array(emptyLines).fill("");
5174
5135
  const formatLog = (log) => {
5175
- if (log.includes("[RAG]")) return /* @__PURE__ */ jsx8(Text7, { color: "cyan", children: log });
5176
- if (log.includes("[ERROR]")) return /* @__PURE__ */ jsx8(Text7, { color: "red", children: log });
5177
- if (log.includes("[WARN]")) return /* @__PURE__ */ jsx8(Text7, { color: "yellow", children: log });
5178
- if (log.includes("[INFO]")) return /* @__PURE__ */ jsx8(Text7, { color: "green", children: log });
5179
- if (log.includes("Success")) return /* @__PURE__ */ jsx8(Text7, { color: "green", children: log });
5180
- return /* @__PURE__ */ jsx8(Text7, { children: log });
5136
+ if (log.includes("[RAG]")) return /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: log });
5137
+ if (log.includes("[ERROR]")) return /* @__PURE__ */ jsx7(Text6, { color: "red", children: log });
5138
+ if (log.includes("[WARN]")) return /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: log });
5139
+ if (log.includes("[INFO]")) return /* @__PURE__ */ jsx7(Text6, { color: "green", children: log });
5140
+ if (log.includes("Success")) return /* @__PURE__ */ jsx7(Text6, { color: "green", children: log });
5141
+ return /* @__PURE__ */ jsx7(Text6, { children: log });
5181
5142
  };
5182
- return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "dim", paddingX: 1, height: height + 2, flexGrow: 1, children: [
5183
- padding.map((_, i) => /* @__PURE__ */ jsx8(Text7, { children: " " }, `empty-${i}`)),
5184
- visibleLogs.map((log, i) => /* @__PURE__ */ jsx8(Box7, { children: formatLog(log) }, `log-${i}`))
5143
+ return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "dim", paddingX: 1, height: height + 2, flexGrow: 1, children: [
5144
+ padding.map((_, i) => /* @__PURE__ */ jsx7(Text6, { children: " " }, `empty-${i}`)),
5145
+ visibleLogs.map((log, i) => /* @__PURE__ */ jsx7(Box6, { children: formatLog(log) }, `log-${i}`))
5185
5146
  ] });
5186
5147
  };
5187
5148
  }
@@ -5189,28 +5150,28 @@ var init_LogViewer = __esm({
5189
5150
 
5190
5151
  // src/mcp/ui/StatusBoard.tsx
5191
5152
  import "react";
5192
- import { Box as Box8, Text as Text8 } from "ink";
5193
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
5153
+ import { Box as Box7, Text as Text7 } from "ink";
5154
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
5194
5155
  var StatusBoard;
5195
5156
  var init_StatusBoard = __esm({
5196
5157
  "src/mcp/ui/StatusBoard.tsx"() {
5197
5158
  "use strict";
5198
5159
  StatusBoard = ({ exposedLabel, port, pid, running, hasDrift }) => {
5199
- return /* @__PURE__ */ jsx9(Box8, { borderStyle: "single", borderColor: "cyan", paddingX: 1, flexGrow: 1, children: /* @__PURE__ */ jsxs7(Text8, { children: [
5200
- running ? /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CF RUNNING" }) : /* @__PURE__ */ jsx9(Text8, { color: "red", children: "\u25CF STOPPED" }),
5160
+ return /* @__PURE__ */ jsx8(Box7, { borderStyle: "single", borderColor: "cyan", paddingX: 1, flexGrow: 1, children: /* @__PURE__ */ jsxs6(Text7, { children: [
5161
+ running ? /* @__PURE__ */ jsx8(Text7, { color: "green", children: "\u25CF RUNNING" }) : /* @__PURE__ */ jsx8(Text7, { color: "red", children: "\u25CF STOPPED" }),
5201
5162
  " ",
5202
5163
  "\u2502",
5203
5164
  " \u{1F4CB} ",
5204
- /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: exposedLabel }),
5165
+ /* @__PURE__ */ jsx8(Text7, { color: "yellow", children: exposedLabel }),
5205
5166
  " ",
5206
5167
  "\u2502",
5207
5168
  " Port: ",
5208
- /* @__PURE__ */ jsx9(Text8, { color: "green", children: port }),
5169
+ /* @__PURE__ */ jsx8(Text7, { color: "green", children: port }),
5209
5170
  " ",
5210
5171
  "\u2502",
5211
5172
  " PID: ",
5212
- /* @__PURE__ */ jsx9(Text8, { color: "green", children: pid }),
5213
- hasDrift && /* @__PURE__ */ jsxs7(Text8, { color: "magenta", bold: true, children: [
5173
+ /* @__PURE__ */ jsx8(Text7, { color: "green", children: pid }),
5174
+ hasDrift && /* @__PURE__ */ jsxs6(Text7, { color: "magenta", bold: true, children: [
5214
5175
  " ",
5215
5176
  "\u2502",
5216
5177
  " \u2B06 UPDATE AVAILABLE"
@@ -5220,121 +5181,16 @@ var init_StatusBoard = __esm({
5220
5181
  }
5221
5182
  });
5222
5183
 
5223
- // src/mcp/ui/IndexingStatus.tsx
5224
- import { useState as useState5, useEffect as useEffect5 } from "react";
5225
- import { Box as Box9, Text as Text9 } from "ink";
5226
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
5227
- var IndexingStatus;
5228
- var init_IndexingStatus = __esm({
5229
- "src/mcp/ui/IndexingStatus.tsx"() {
5230
- "use strict";
5231
- init_indexing_jobs();
5232
- init_rag();
5233
- init_resources();
5234
- init_config_utils();
5235
- IndexingStatus = ({ projects, config }) => {
5236
- const [stats, setStats] = useState5([]);
5237
- const [loading, setLoading] = useState5(true);
5238
- useEffect5(() => {
5239
- const fetchStats = async () => {
5240
- const newStats = [];
5241
- for (const project of projects) {
5242
- let projConfig = findProjectConfig(config, { name: project.name, path: project.path });
5243
- if (!projConfig && project.source === "global") {
5244
- projConfig = config.projects.find((p) => p.name === project.name);
5245
- }
5246
- const enabled = projConfig?.semanticSearch?.enabled || project.semanticSearchEnabled || false;
5247
- if (!enabled) {
5248
- const prog = indexingJobs.getProgress(project.name);
5249
- newStats.push({
5250
- projectName: project.name,
5251
- enabled: false,
5252
- state: prog.state,
5253
- itemsDone: prog.itemsDone,
5254
- itemsTotal: prog.itemsTotal,
5255
- currentItem: prog.currentItem,
5256
- totalFiles: 0,
5257
- totalChunks: 0
5258
- });
5259
- continue;
5260
- }
5261
- try {
5262
- const indexPath = getRAGIndexPath(project);
5263
- const rag = new RAGService(indexPath, "dummy");
5264
- const s = rag.getStats();
5265
- const prog = indexingJobs.getProgress(project.name);
5266
- newStats.push({
5267
- projectName: project.name,
5268
- enabled: true,
5269
- state: prog.state,
5270
- itemsDone: prog.itemsDone,
5271
- itemsTotal: prog.itemsTotal,
5272
- currentItem: prog.currentItem,
5273
- totalFiles: s.totalFiles,
5274
- totalChunks: s.totalChunks,
5275
- lastFullIndex: s.lastFullIndex
5276
- });
5277
- } catch (e) {
5278
- const prog = indexingJobs.getProgress(project.name);
5279
- newStats.push({
5280
- projectName: project.name,
5281
- enabled: true,
5282
- state: prog.state,
5283
- itemsDone: prog.itemsDone,
5284
- itemsTotal: prog.itemsTotal,
5285
- currentItem: prog.currentItem,
5286
- totalFiles: 0,
5287
- totalChunks: 0,
5288
- error: String(e)
5289
- });
5290
- }
5291
- }
5292
- setStats(newStats);
5293
- setLoading(false);
5294
- };
5295
- fetchStats();
5296
- const interval = setInterval(fetchStats, 5e3);
5297
- return () => clearInterval(interval);
5298
- }, [projects, config]);
5299
- if (loading && stats.length === 0) {
5300
- return /* @__PURE__ */ jsx10(Text9, { children: "Loading indexing status..." });
5301
- }
5302
- return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "blue", flexGrow: 1, children: [
5303
- /* @__PURE__ */ jsx10(Text9, { bold: true, color: "blue", children: " RAG Indexing Status " }),
5304
- /* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "column", children: [
5305
- /* @__PURE__ */ jsxs8(Box9, { children: [
5306
- /* @__PURE__ */ jsx10(Box9, { width: 25, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Project" }) }),
5307
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Status" }) }),
5308
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "State" }) }),
5309
- /* @__PURE__ */ jsx10(Box9, { width: 18, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Progress" }) }),
5310
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Indexed Files" }) }),
5311
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Total Chunks" }) }),
5312
- /* @__PURE__ */ jsx10(Box9, { children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Last Index" }) })
5313
- ] }),
5314
- stats.length === 0 ? /* @__PURE__ */ jsx10(Text9, { color: "dim", children: "No exposed projects found." }) : stats.map((s) => /* @__PURE__ */ jsxs8(Box9, { marginTop: 0, children: [
5315
- /* @__PURE__ */ jsx10(Box9, { width: 25, children: /* @__PURE__ */ jsx10(Text9, { color: "white", children: s.projectName }) }),
5316
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { color: s.state === "running" ? "yellow" : s.state === "failed" ? "red" : s.enabled ? "green" : "dim", children: s.enabled ? s.state : "disabled" }) }),
5317
- /* @__PURE__ */ jsx10(Box9, { width: 18, children: /* @__PURE__ */ jsx10(Text9, { children: s.state === "running" ? `${s.itemsDone}/${s.itemsTotal ?? "?"}` : "-" }) }),
5318
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { children: s.enabled ? s.totalFiles : "-" }) }),
5319
- /* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { children: s.enabled ? s.totalChunks : "-" }) }),
5320
- /* @__PURE__ */ jsx10(Box9, { children: /* @__PURE__ */ jsx10(Text9, { children: s.lastFullIndex ? new Date(s.lastFullIndex).toLocaleTimeString() : "-" }) })
5321
- ] }, s.projectName))
5322
- ] })
5323
- ] });
5324
- };
5325
- }
5326
- });
5327
-
5328
5184
  // src/mcp/ui/components/TabBar.tsx
5329
5185
  import "react";
5330
- import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
5331
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
5186
+ import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
5187
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
5332
5188
  var TabBar;
5333
5189
  var init_TabBar = __esm({
5334
5190
  "src/mcp/ui/components/TabBar.tsx"() {
5335
5191
  "use strict";
5336
5192
  TabBar = ({ tabs, activeTab, onChange }) => {
5337
- useInput3((input, key) => {
5193
+ useInput4((input, key) => {
5338
5194
  if (key.leftArrow) {
5339
5195
  const index = tabs.findIndex((t) => t.id === activeTab);
5340
5196
  if (index !== -1) {
@@ -5355,11 +5211,11 @@ var init_TabBar = __esm({
5355
5211
  if (tab) onChange(tab.id);
5356
5212
  }
5357
5213
  });
5358
- return /* @__PURE__ */ jsxs9(Box10, { borderStyle: "single", paddingX: 1, borderColor: "gray", children: [
5214
+ return /* @__PURE__ */ jsxs7(Box8, { borderStyle: "single", paddingX: 1, borderColor: "gray", children: [
5359
5215
  tabs.map((tab, index) => {
5360
5216
  const isActive = tab.id === activeTab;
5361
- return /* @__PURE__ */ jsx11(Box10, { marginRight: 2, children: /* @__PURE__ */ jsx11(
5362
- Text10,
5217
+ return /* @__PURE__ */ jsx9(Box8, { marginRight: 2, children: /* @__PURE__ */ jsx9(
5218
+ Text8,
5363
5219
  {
5364
5220
  color: isActive ? "cyan" : "white",
5365
5221
  bold: isActive,
@@ -5368,8 +5224,8 @@ var init_TabBar = __esm({
5368
5224
  }
5369
5225
  ) }, tab.id);
5370
5226
  }),
5371
- /* @__PURE__ */ jsx11(Box10, { flexGrow: 1 }),
5372
- /* @__PURE__ */ jsx11(Text10, { color: "dim", children: "Use \u25C4/\u25BA arrows to navigate" })
5227
+ /* @__PURE__ */ jsx9(Box8, { flexGrow: 1 }),
5228
+ /* @__PURE__ */ jsx9(Text8, { color: "dim", children: "Use \u25C4/\u25BA arrows to navigate" })
5373
5229
  ] });
5374
5230
  };
5375
5231
  }
@@ -5380,62 +5236,54 @@ var App_exports = {};
5380
5236
  __export(App_exports, {
5381
5237
  App: () => App
5382
5238
  });
5383
- import { useState as useState6, useEffect as useEffect6, useMemo as useMemo4, useCallback as useCallback3 } from "react";
5384
- import { Box as Box11, useInput as useInput4, useApp } from "ink";
5239
+ import { useState as useState5, useEffect as useEffect6, useMemo as useMemo5, useCallback as useCallback3 } from "react";
5240
+ import { Box as Box9, useInput as useInput5, useApp } from "ink";
5385
5241
  import fs20 from "fs";
5386
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
5242
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
5387
5243
  var App;
5388
5244
  var init_App = __esm({
5389
5245
  "src/mcp/ui/App.tsx"() {
5390
5246
  "use strict";
5391
5247
  init_Overview();
5392
5248
  init_ProjectsView();
5393
- init_InstallView();
5249
+ init_TasksView();
5394
5250
  init_LogViewer();
5395
5251
  init_StatusBoard();
5396
- init_IndexingStatus();
5397
5252
  init_TabBar();
5398
- init_config();
5399
5253
  init_config_utils();
5400
- init_detection();
5401
5254
  init_logger();
5402
5255
  init_server();
5403
- init_resources();
5404
- init_install();
5405
5256
  init_paths();
5257
+ init_install();
5406
5258
  init_ConfigContext();
5407
5259
  App = ({ onExit, initialPort }) => {
5408
5260
  const { exit } = useApp();
5409
5261
  const { config, projects, exposedProjects, driftReports, refresh: refreshData } = useConfig();
5410
- const [activeTab, setActiveTab] = useState6("overview");
5411
- const [logs, setLogs] = useState6([]);
5412
- const [serverInfo, setServerInfo] = useState6({
5262
+ const [activeTab, setActiveTab] = useState5("overview");
5263
+ const [logs, setLogs] = useState5([]);
5264
+ const [serverInfo, setServerInfo] = useState5({
5413
5265
  port: initialPort,
5414
5266
  pid: process.pid,
5415
5267
  running: false
5416
5268
  });
5417
- const isRAGEnabled = useMemo4(() => {
5269
+ const isRAGEnabled = useMemo5(() => {
5418
5270
  return exposedProjects.some((p) => {
5419
5271
  const cfg = findProjectConfig(config, { name: p.name, path: p.path });
5420
5272
  return cfg?.semanticSearch?.enabled || p.semanticSearchEnabled;
5421
5273
  });
5422
5274
  }, [exposedProjects, config]);
5423
- const hasAnyDrift = useMemo4(
5275
+ const hasAnyDrift = useMemo5(
5424
5276
  () => Object.values(driftReports).some((r) => r.hasDrift),
5425
5277
  [driftReports]
5426
5278
  );
5427
- const tabs = useMemo4(() => {
5428
- const baseTabs = [
5279
+ const tabs = useMemo5(() => {
5280
+ return [
5429
5281
  { id: "overview", label: "Overview" },
5430
5282
  { id: "logs", label: "Logs" },
5431
- { id: "projects", label: "Projects" },
5432
- { id: "install", label: "Install" }
5283
+ { id: "tasks", label: "Tasks" },
5284
+ { id: "projects", label: "Projects" }
5433
5285
  ];
5434
- if (isRAGEnabled) {
5435
- baseTabs.splice(3, 0, { id: "indexing", label: "Indexing" });
5436
- }
5437
- return baseTabs;
5438
- }, [isRAGEnabled]);
5286
+ }, []);
5439
5287
  const workspacePath = detectWorkspaceRoot();
5440
5288
  const installStatus = checkInstallStatus(workspacePath);
5441
5289
  const installedCount = [
@@ -5487,7 +5335,7 @@ var init_App = __esm({
5487
5335
  }, 500);
5488
5336
  return () => clearInterval(interval);
5489
5337
  }, []);
5490
- useInput4(async (input, key) => {
5338
+ useInput5(async (input, key) => {
5491
5339
  if (input === "q" || key.ctrl && input === "c") {
5492
5340
  stopMCPServer();
5493
5341
  onExit();
@@ -5511,10 +5359,10 @@ var init_App = __esm({
5511
5359
  const handleConfigChange = useCallback3(() => {
5512
5360
  refreshData();
5513
5361
  }, [refreshData]);
5514
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", padding: 0, height: termHeight, children: [
5515
- /* @__PURE__ */ jsx12(TabBar, { tabs, activeTab, onChange: setActiveTab }),
5516
- /* @__PURE__ */ jsxs10(Box11, { marginTop: 1, flexGrow: 1, children: [
5517
- activeTab === "overview" && /* @__PURE__ */ jsx12(
5362
+ return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", padding: 0, height: termHeight, children: [
5363
+ /* @__PURE__ */ jsx10(TabBar, { tabs, activeTab, onChange: setActiveTab }),
5364
+ /* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexGrow: 1, children: [
5365
+ activeTab === "overview" && /* @__PURE__ */ jsx10(
5518
5366
  Overview,
5519
5367
  {
5520
5368
  serverStatus: serverInfo,
@@ -5522,15 +5370,15 @@ var init_App = __esm({
5522
5370
  exposedProjects: exposedProjects.length,
5523
5371
  totalProjects: projects.length,
5524
5372
  installedIntegrations: installedCount
5525
- }
5373
+ },
5374
+ logs
5526
5375
  }
5527
5376
  ),
5528
- activeTab === "projects" && /* @__PURE__ */ jsx12(ProjectsView, { config, projects, onConfigChange: handleConfigChange }),
5529
- activeTab === "indexing" && /* @__PURE__ */ jsx12(IndexingStatus, { config, projects: exposedProjects }),
5530
- activeTab === "install" && /* @__PURE__ */ jsx12(InstallView, {}),
5531
- activeTab === "logs" && /* @__PURE__ */ jsx12(LogViewer, { logs, height: contentHeight })
5377
+ activeTab === "logs" && /* @__PURE__ */ jsx10(LogViewer, { logs, height: contentHeight }),
5378
+ activeTab === "tasks" && /* @__PURE__ */ jsx10(TasksView, { projects }),
5379
+ activeTab === "projects" && /* @__PURE__ */ jsx10(ProjectsView, { config, projects, onConfigChange: handleConfigChange })
5532
5380
  ] }),
5533
- /* @__PURE__ */ jsx12(Box11, { marginTop: 0, children: /* @__PURE__ */ jsx12(
5381
+ /* @__PURE__ */ jsx10(Box9, { marginTop: 0, children: /* @__PURE__ */ jsx10(
5534
5382
  StatusBoard,
5535
5383
  {
5536
5384
  exposedLabel: `${exposedProjects.length} / ${projects.length} projects`,
@@ -5548,7 +5396,7 @@ var init_App = __esm({
5548
5396
  // src/mcp/commands/start.ts
5549
5397
  import { confirm as confirm3, isCancel as isCancel5, text } from "@clack/prompts";
5550
5398
  async function handleStartServer() {
5551
- const React13 = await import("react");
5399
+ const React11 = await import("react");
5552
5400
  const { render } = await import("ink");
5553
5401
  const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
5554
5402
  const { ConfigProvider: ConfigProvider2 } = await Promise.resolve().then(() => (init_ConfigContext(), ConfigContext_exports));
@@ -5591,10 +5439,10 @@ async function handleStartServer() {
5591
5439
  }
5592
5440
  process.stdin.resume();
5593
5441
  const app = render(
5594
- React13.createElement(
5442
+ React11.createElement(
5595
5443
  ConfigProvider2,
5596
5444
  null,
5597
- React13.createElement(App2, {
5445
+ React11.createElement(App2, {
5598
5446
  initialPort,
5599
5447
  onExit: () => {
5600
5448
  }
@@ -6407,8 +6255,8 @@ linked_projects:
6407
6255
  async function registerWithMCP(config, workspacePath, workspaceName) {
6408
6256
  if (!config.exposeToMCP) return;
6409
6257
  try {
6410
- const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6411
- const mcpConfig = loadMCPConfig3();
6258
+ const { loadMCPConfig: loadMCPConfig2, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6259
+ const mcpConfig = loadMCPConfig2();
6412
6260
  setProjectConfig2(
6413
6261
  mcpConfig,
6414
6262
  workspaceName,
@@ -6801,8 +6649,8 @@ linked_projects:
6801
6649
  });
6802
6650
  if (shouldExpose && !isCancel9(shouldExpose)) {
6803
6651
  try {
6804
- const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6805
- const mcpConfig = loadMCPConfig3();
6652
+ const { loadMCPConfig: loadMCPConfig2, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6653
+ const mcpConfig = loadMCPConfig2();
6806
6654
  for (const project of selectedProjects) {
6807
6655
  setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
6808
6656
  }