sidekick-agent-hub 0.13.2 → 0.13.4

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/sidekick-cli.mjs +309 -108
  2. package/package.json +1 -1
@@ -13762,6 +13762,7 @@ var require_EventAggregator = __commonJS({
13762
13762
  "use strict";
13763
13763
  Object.defineProperty(exports, "__esModule", { value: true });
13764
13764
  exports.EventAggregator = void 0;
13765
+ exports.parseTodoDependencies = parseTodoDependencies;
13765
13766
  var jsonl_1 = require_jsonl();
13766
13767
  var planExtractor_1 = require_planExtractor();
13767
13768
  var eventBridge_1 = require_eventBridge();
@@ -13776,6 +13777,26 @@ var require_EventAggregator = __commonJS({
13776
13777
  var DEFAULT_BURN_SAMPLE_MS = 1e4;
13777
13778
  var COMPACTION_DROP_THRESHOLD = 0.8;
13778
13779
  var SNAPSHOT_SCHEMA_VERSION = 1;
13780
+ var GOAL_GATE_REGEX = /\b(CRITICAL|MUST|blocker|required|must.?complete|goal.?gate|essential|do.?not.?skip|blocking)\b/i;
13781
+ function parseTodoDependencies(content, allTodos) {
13782
+ const depPattern = /(?:blocked by|depends on|waiting on|requires)\s+(.+?)(?:\)|$)/i;
13783
+ const match = content.match(depPattern);
13784
+ if (!match)
13785
+ return [];
13786
+ const refs = match[1].split(/\s+and\s+|,\s*|&\s*/).map((r) => r.trim()).filter(Boolean);
13787
+ const result = [];
13788
+ for (const ref of refs) {
13789
+ const refLower = ref.toLowerCase();
13790
+ for (let j = 0; j < allTodos.length; j++) {
13791
+ const otherContent = String(allTodos[j].content || allTodos[j].subject || "").toLowerCase();
13792
+ if (otherContent.includes(refLower) || refLower.includes(otherContent.split(":")[0].trim())) {
13793
+ result.push(`todo-${j}`);
13794
+ break;
13795
+ }
13796
+ }
13797
+ }
13798
+ return result;
13799
+ }
13779
13800
  var EventAggregator5 = class {
13780
13801
  // Options
13781
13802
  timelineCap;
@@ -14550,16 +14571,25 @@ var require_EventAggregator = __commonJS({
14550
14571
  description: input.description,
14551
14572
  activeForm: input.activeForm,
14552
14573
  subagentType: input.subagentType,
14553
- isGoalGate: input.isGoalGate
14574
+ isGoalGate: input.isGoalGate,
14575
+ timestamp: new Date(event.timestamp)
14554
14576
  });
14555
14577
  } else if (name === "TaskUpdate") {
14556
14578
  this.applyTaskUpdate(input);
14579
+ } else if (name === "TodoWrite") {
14580
+ this.handleTodoWrite(input, new Date(event.timestamp));
14581
+ } else if (name === "UpdatePlan") {
14582
+ this.handleUpdatePlan(input, new Date(event.timestamp));
14583
+ } else if ((name === "Agent" || name === "Task") && toolUseId) {
14584
+ this.handleAgentSpawn(toolUseId, input, new Date(event.timestamp));
14557
14585
  }
14558
14586
  } else if (block.type === "tool_result") {
14559
14587
  const toolUseId = block.tool_use_id;
14560
14588
  if (!toolUseId)
14561
14589
  continue;
14562
- this.resolveTaskCreate(toolUseId, block.content ?? block.output, event.timestamp);
14590
+ const isError = block.is_error ?? false;
14591
+ this.resolveTaskCreate(toolUseId, block.content ?? block.output, event.timestamp, isError);
14592
+ this.resolveAgentResult(toolUseId, isError, event.timestamp);
14563
14593
  }
14564
14594
  }
14565
14595
  }
@@ -14579,10 +14609,17 @@ var require_EventAggregator = __commonJS({
14579
14609
  description: input.description,
14580
14610
  activeForm: input.activeForm,
14581
14611
  subagentType: input.subagentType,
14582
- isGoalGate: input.isGoalGate
14612
+ isGoalGate: input.isGoalGate,
14613
+ timestamp: new Date(event.timestamp)
14583
14614
  });
14584
14615
  } else if (event.toolName === "TaskUpdate") {
14585
14616
  this.applyTaskUpdate(input);
14617
+ } else if (event.toolName === "TodoWrite") {
14618
+ this.handleTodoWrite(input, new Date(event.timestamp));
14619
+ } else if (event.toolName === "UpdatePlan") {
14620
+ this.handleUpdatePlan(input, new Date(event.timestamp));
14621
+ } else if ((event.toolName === "Agent" || event.toolName === "Task") && toolUseId) {
14622
+ this.handleAgentSpawn(toolUseId, input, new Date(event.timestamp));
14586
14623
  }
14587
14624
  } else if (event.type === "tool_result") {
14588
14625
  if (!raw)
@@ -14590,7 +14627,9 @@ var require_EventAggregator = __commonJS({
14590
14627
  const toolUseId = raw.tool_use_id;
14591
14628
  if (!toolUseId)
14592
14629
  return;
14593
- this.resolveTaskCreate(toolUseId, raw.content, event.timestamp);
14630
+ const isError = raw.is_error ?? false;
14631
+ this.resolveTaskCreate(toolUseId, raw.content, event.timestamp, isError);
14632
+ this.resolveAgentResult(toolUseId, isError, event.timestamp);
14594
14633
  }
14595
14634
  }
14596
14635
  applyTaskUpdate(input) {
@@ -14607,10 +14646,14 @@ var require_EventAggregator = __commonJS({
14607
14646
  this.activeTaskId = null;
14608
14647
  return;
14609
14648
  }
14649
+ const oldStatus = existing.status;
14610
14650
  existing.status = newStatus;
14611
14651
  existing.updatedAt = /* @__PURE__ */ new Date();
14612
- if (newStatus === "in_progress") {
14652
+ if (newStatus === "in_progress" && oldStatus !== "in_progress") {
14613
14653
  this.activeTaskId = taskId;
14654
+ } else if (oldStatus === "in_progress" && newStatus !== "in_progress") {
14655
+ if (this.activeTaskId === taskId)
14656
+ this.activeTaskId = null;
14614
14657
  }
14615
14658
  }
14616
14659
  if (input.subject)
@@ -14620,19 +14663,31 @@ var require_EventAggregator = __commonJS({
14620
14663
  if (input.activeForm)
14621
14664
  existing.activeForm = input.activeForm;
14622
14665
  if (input.addBlockedBy && Array.isArray(input.addBlockedBy)) {
14623
- existing.blockedBy.push(...input.addBlockedBy);
14666
+ for (const id of input.addBlockedBy) {
14667
+ const idStr = String(id);
14668
+ if (!existing.blockedBy.includes(idStr)) {
14669
+ existing.blockedBy.push(idStr);
14670
+ }
14671
+ }
14624
14672
  }
14625
14673
  if (input.addBlocks && Array.isArray(input.addBlocks)) {
14626
- existing.blocks.push(...input.addBlocks);
14674
+ for (const id of input.addBlocks) {
14675
+ const idStr = String(id);
14676
+ if (!existing.blocks.includes(idStr)) {
14677
+ existing.blocks.push(idStr);
14678
+ }
14679
+ }
14627
14680
  }
14681
+ existing.isGoalGate = this.isGoalGateTask(existing);
14628
14682
  } else {
14629
14683
  const status = input.status || "pending";
14630
14684
  if (status === "deleted")
14631
14685
  return;
14632
14686
  const now = /* @__PURE__ */ new Date();
14633
- this.tasks.set(taskId, {
14687
+ const task = {
14634
14688
  taskId,
14635
14689
  subject: input.subject || `Task ${taskId}`,
14690
+ description: input.description,
14636
14691
  status,
14637
14692
  createdAt: now,
14638
14693
  updatedAt: now,
@@ -14640,27 +14695,31 @@ var require_EventAggregator = __commonJS({
14640
14695
  blocks: [],
14641
14696
  associatedToolCalls: [],
14642
14697
  activeForm: input.activeForm
14643
- });
14698
+ };
14699
+ task.isGoalGate = this.isGoalGateTask(task);
14700
+ this.tasks.set(taskId, task);
14644
14701
  if (status === "in_progress") {
14645
14702
  this.activeTaskId = taskId;
14646
14703
  }
14647
14704
  }
14648
14705
  }
14649
- resolveTaskCreate(toolUseId, content, timestamp) {
14706
+ resolveTaskCreate(toolUseId, content, timestamp, isError) {
14650
14707
  const pending = this.pendingTaskCreates.get(toolUseId);
14651
14708
  if (!pending)
14652
14709
  return;
14653
14710
  this.pendingTaskCreates.delete(toolUseId);
14711
+ if (isError)
14712
+ return;
14654
14713
  const taskId = this.extractTaskIdFromResult(content);
14655
14714
  if (!taskId)
14656
14715
  return;
14657
14716
  const now = new Date(timestamp);
14658
- this.tasks.set(taskId, {
14717
+ const task = {
14659
14718
  taskId,
14660
14719
  subject: pending.subject,
14661
14720
  description: pending.description,
14662
14721
  status: "pending",
14663
- createdAt: now,
14722
+ createdAt: pending.timestamp ?? now,
14664
14723
  updatedAt: now,
14665
14724
  blockedBy: [],
14666
14725
  blocks: [],
@@ -14668,7 +14727,185 @@ var require_EventAggregator = __commonJS({
14668
14727
  activeForm: pending.activeForm,
14669
14728
  subagentType: pending.subagentType,
14670
14729
  isGoalGate: pending.isGoalGate
14671
- });
14730
+ };
14731
+ task.isGoalGate = task.isGoalGate || this.isGoalGateTask(task);
14732
+ this.tasks.set(taskId, task);
14733
+ }
14734
+ // ═══════════════════════════════════════════════════════════════════════
14735
+ // Private: TodoWrite handling (OpenCode)
14736
+ // ═══════════════════════════════════════════════════════════════════════
14737
+ handleTodoWrite(input, now) {
14738
+ const todos = input.todos;
14739
+ if (!Array.isArray(todos))
14740
+ return;
14741
+ for (const [taskId, task] of this.tasks) {
14742
+ if (!task.isSubagent) {
14743
+ this.tasks.delete(taskId);
14744
+ }
14745
+ }
14746
+ if (this.activeTaskId && !this.tasks.has(this.activeTaskId)) {
14747
+ this.activeTaskId = null;
14748
+ }
14749
+ for (let i = 0; i < todos.length; i++) {
14750
+ const todo = todos[i];
14751
+ const taskId = `todo-${i}`;
14752
+ const content = String(todo.content || todo.subject || `Todo ${i + 1}`);
14753
+ const rawStatus = String(todo.status || "pending").toLowerCase();
14754
+ const priority = todo.priority ? String(todo.priority) : void 0;
14755
+ let status;
14756
+ if (rawStatus === "completed" || rawStatus === "done") {
14757
+ status = "completed";
14758
+ } else if (rawStatus === "in_progress" || rawStatus === "in-progress") {
14759
+ status = "in_progress";
14760
+ } else {
14761
+ status = "pending";
14762
+ }
14763
+ const task = {
14764
+ taskId,
14765
+ subject: content,
14766
+ description: priority ? `Priority: ${priority}` : void 0,
14767
+ status,
14768
+ createdAt: now,
14769
+ updatedAt: now,
14770
+ blockedBy: [],
14771
+ blocks: [],
14772
+ associatedToolCalls: []
14773
+ };
14774
+ this.tasks.set(taskId, task);
14775
+ if (status === "in_progress") {
14776
+ this.activeTaskId = taskId;
14777
+ }
14778
+ }
14779
+ for (let i = 0; i < todos.length; i++) {
14780
+ const task = this.tasks.get(`todo-${i}`);
14781
+ if (!task)
14782
+ continue;
14783
+ if (Array.isArray(todos[i].blockedBy)) {
14784
+ for (const ref of todos[i].blockedBy) {
14785
+ const refStr = String(ref);
14786
+ if (!task.blockedBy.includes(refStr)) {
14787
+ task.blockedBy.push(refStr);
14788
+ }
14789
+ }
14790
+ }
14791
+ const deps = parseTodoDependencies(String(todos[i].content || ""), todos);
14792
+ for (const depId of deps) {
14793
+ if (depId !== `todo-${i}` && !task.blockedBy.includes(depId)) {
14794
+ task.blockedBy.push(depId);
14795
+ const depTask = this.tasks.get(depId);
14796
+ if (depTask && !depTask.blocks.includes(`todo-${i}`)) {
14797
+ depTask.blocks.push(`todo-${i}`);
14798
+ }
14799
+ }
14800
+ }
14801
+ }
14802
+ }
14803
+ // ═══════════════════════════════════════════════════════════════════════
14804
+ // Private: UpdatePlan handling (Codex)
14805
+ // ═══════════════════════════════════════════════════════════════════════
14806
+ handleUpdatePlan(input, now) {
14807
+ const plan = input.plan;
14808
+ if (!Array.isArray(plan))
14809
+ return;
14810
+ const seenPlanTaskIds = /* @__PURE__ */ new Set();
14811
+ let activePlanTaskId = null;
14812
+ for (let i = 0; i < plan.length; i++) {
14813
+ const entry = plan[i];
14814
+ const step = String(entry.step || "").trim();
14815
+ if (!step)
14816
+ continue;
14817
+ const rawStatus = String(entry.status || "pending").toLowerCase();
14818
+ let status;
14819
+ if (rawStatus === "completed")
14820
+ status = "completed";
14821
+ else if (rawStatus === "in_progress" || rawStatus === "in-progress")
14822
+ status = "in_progress";
14823
+ else
14824
+ status = "pending";
14825
+ const taskId = `plan-${i}`;
14826
+ seenPlanTaskIds.add(taskId);
14827
+ const existing = this.tasks.get(taskId);
14828
+ if (existing) {
14829
+ existing.subject = step;
14830
+ existing.status = status;
14831
+ existing.updatedAt = now;
14832
+ if (!existing.activeForm) {
14833
+ existing.activeForm = `Working on ${step}`;
14834
+ }
14835
+ } else {
14836
+ const task = {
14837
+ taskId,
14838
+ subject: step,
14839
+ status,
14840
+ createdAt: now,
14841
+ updatedAt: now,
14842
+ activeForm: `Working on ${step}`,
14843
+ blockedBy: [],
14844
+ blocks: [],
14845
+ associatedToolCalls: []
14846
+ };
14847
+ this.tasks.set(taskId, task);
14848
+ }
14849
+ if (status === "in_progress") {
14850
+ activePlanTaskId = taskId;
14851
+ }
14852
+ }
14853
+ for (const [taskId, task] of this.tasks) {
14854
+ if (!taskId.startsWith("plan-"))
14855
+ continue;
14856
+ if (!seenPlanTaskIds.has(taskId) && task.status !== "deleted") {
14857
+ task.status = "deleted";
14858
+ task.updatedAt = now;
14859
+ }
14860
+ }
14861
+ if (activePlanTaskId) {
14862
+ this.activeTaskId = activePlanTaskId;
14863
+ } else if (this.activeTaskId?.startsWith("plan-")) {
14864
+ this.activeTaskId = null;
14865
+ }
14866
+ }
14867
+ // ═══════════════════════════════════════════════════════════════════════
14868
+ // Private: Agent/Task (subagent) as tracked task
14869
+ // ═══════════════════════════════════════════════════════════════════════
14870
+ handleAgentSpawn(toolUseId, input, now) {
14871
+ const agentTaskId = `agent-${toolUseId}`;
14872
+ const description = input.description ? String(input.description) : "Subagent";
14873
+ const subagentType = input.subagent_type || input.subagentType || void 0;
14874
+ const task = {
14875
+ taskId: agentTaskId,
14876
+ subject: description,
14877
+ status: "in_progress",
14878
+ createdAt: now,
14879
+ updatedAt: now,
14880
+ activeForm: subagentType ? `Running ${subagentType} agent` : "Running subagent",
14881
+ blockedBy: [],
14882
+ blocks: [],
14883
+ associatedToolCalls: [],
14884
+ isSubagent: true,
14885
+ subagentType,
14886
+ toolUseId
14887
+ };
14888
+ this.tasks.set(agentTaskId, task);
14889
+ }
14890
+ resolveAgentResult(toolUseId, isError, timestamp) {
14891
+ const agentTaskId = `agent-${toolUseId}`;
14892
+ const agentTask = this.tasks.get(agentTaskId);
14893
+ if (!agentTask)
14894
+ return;
14895
+ agentTask.status = isError ? "deleted" : "completed";
14896
+ agentTask.updatedAt = new Date(timestamp);
14897
+ }
14898
+ // ═══════════════════════════════════════════════════════════════════════
14899
+ // Private: Goal gate detection
14900
+ // ═══════════════════════════════════════════════════════════════════════
14901
+ isGoalGateTask(task) {
14902
+ if (GOAL_GATE_REGEX.test(task.subject))
14903
+ return true;
14904
+ if (task.description && GOAL_GATE_REGEX.test(task.description))
14905
+ return true;
14906
+ if (task.blocks.length >= 3)
14907
+ return true;
14908
+ return false;
14672
14909
  }
14673
14910
  // ═══════════════════════════════════════════════════════════════════════
14674
14911
  // Private: Subagent Tracking from SessionEvent
@@ -16485,8 +16722,8 @@ var require_dist = __commonJS({
16485
16722
  "use strict";
16486
16723
  Object.defineProperty(exports, "__esModule", { value: true });
16487
16724
  exports.findActiveClaudeSession = exports.discoverSessionDirectory = exports.getClaudeSessionDirectory = exports.encodeClaudeWorkspacePath = exports.detectSessionActivity = exports.extractTaskInfo = exports.scanSubagentDir = exports.normalizeCodexToolInput = exports.normalizeCodexToolName = exports.extractPatchFilePaths = exports.CodexRolloutParser = exports.parseDbPartData = exports.parseDbMessageData = exports.convertOpenCodeMessage = exports.detectPlanModeFromText = exports.normalizeToolInput = exports.normalizeToolName = exports.TRUNCATION_PATTERNS = exports.JsonlParser = exports.CodexProvider = exports.OpenCodeProvider = exports.ClaudeCodeProvider = exports.getAllDetectedProviders = exports.detectProvider = exports.readClaudeCodePlanFiles = exports.getPlanAnalytics = exports.writePlans = exports.getLatestPlan = exports.readPlans = exports.readLatestHandoff = exports.readHistory = exports.readNotes = exports.readDecisions = exports.readTasks = exports.getProjectSlugRaw = exports.getProjectSlug = exports.encodeWorkspacePath = exports.getGlobalDataPath = exports.getProjectDataPath = exports.getConfigDir = exports.MAX_PLANS_PER_PROJECT = exports.PLAN_SCHEMA_VERSION = exports.createEmptyTokenTotals = exports.HISTORICAL_DATA_SCHEMA_VERSION = exports.STALENESS_THRESHOLDS = exports.IMPORTANCE_DECAY_FACTORS = exports.KNOWLEDGE_NOTE_SCHEMA_VERSION = exports.DECISION_LOG_SCHEMA_VERSION = exports.normalizeTaskStatus = exports.TASK_PERSISTENCE_SCHEMA_VERSION = void 0;
16488
- exports.PatternExtractor = exports.HeatmapTracker = exports.FrequencyTracker = exports.getSnapshotPath = exports.isSnapshotValid = exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.EventAggregator = exports.getRandomPhrase = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = exports.highlightEvent = exports.formatSessionJson = exports.formatSessionMarkdown = exports.formatSessionText = exports.classifyNoise = exports.shouldMergeWithPrevious = exports.classifyFollowEvent = exports.classifyMessage = exports.getSoftNoiseReason = exports.isHardNoiseFollowEvent = exports.isHardNoise = exports.formatToolSummary = exports.toFollowEvents = exports.createWatcher = exports.parseChangelog = exports.extractProposedPlanShared = exports.parsePlanMarkdownShared = exports.PlanExtractor = exports.composeContext = exports.FilterEngine = exports.searchSessions = exports.CodexDatabase = exports.OpenCodeDatabase = exports.discoverDebugLogs = exports.collapseDuplicates = exports.filterByLevel = exports.parseDebugLog = exports.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionsInDirectory = exports.findAllClaudeSessions = void 0;
16489
- exports.fetchQuota = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.openInBrowser = exports.parseTranscript = exports.generateHtmlReport = void 0;
16725
+ exports.HeatmapTracker = exports.FrequencyTracker = exports.getSnapshotPath = exports.isSnapshotValid = exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.parseTodoDependencies = exports.EventAggregator = exports.getRandomPhrase = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = exports.highlightEvent = exports.formatSessionJson = exports.formatSessionMarkdown = exports.formatSessionText = exports.classifyNoise = exports.shouldMergeWithPrevious = exports.classifyFollowEvent = exports.classifyMessage = exports.getSoftNoiseReason = exports.isHardNoiseFollowEvent = exports.isHardNoise = exports.formatToolSummary = exports.toFollowEvents = exports.createWatcher = exports.parseChangelog = exports.extractProposedPlanShared = exports.parsePlanMarkdownShared = exports.PlanExtractor = exports.composeContext = exports.FilterEngine = exports.searchSessions = exports.CodexDatabase = exports.OpenCodeDatabase = exports.discoverDebugLogs = exports.collapseDuplicates = exports.filterByLevel = exports.parseDebugLog = exports.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionsInDirectory = exports.findAllClaudeSessions = void 0;
16726
+ exports.fetchQuota = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.openInBrowser = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = void 0;
16490
16727
  var taskPersistence_1 = require_taskPersistence();
16491
16728
  Object.defineProperty(exports, "TASK_PERSISTENCE_SCHEMA_VERSION", { enumerable: true, get: function() {
16492
16729
  return taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION;
@@ -16802,6 +17039,9 @@ var require_dist = __commonJS({
16802
17039
  Object.defineProperty(exports, "EventAggregator", { enumerable: true, get: function() {
16803
17040
  return EventAggregator_1.EventAggregator;
16804
17041
  } });
17042
+ Object.defineProperty(exports, "parseTodoDependencies", { enumerable: true, get: function() {
17043
+ return EventAggregator_1.parseTodoDependencies;
17044
+ } });
16805
17045
  var snapshot_1 = require_snapshot();
16806
17046
  Object.defineProperty(exports, "saveSnapshot", { enumerable: true, get: function() {
16807
17047
  return snapshot_1.saveSnapshot;
@@ -18996,7 +19236,7 @@ var init_UpdateCheckService = __esm({
18996
19236
  /** Run the update check (one-shot). */
18997
19237
  async check() {
18998
19238
  try {
18999
- const current = "0.13.2";
19239
+ const current = "0.13.4";
19000
19240
  const cached = this.readCache();
19001
19241
  let latest;
19002
19242
  if (cached && Date.now() - cached.checkedAt < CACHE_TTL_MS) {
@@ -32542,14 +32782,14 @@ var require_react_reconciler_production = __commonJS({
32542
32782
  }
32543
32783
  var exports2 = {};
32544
32784
  "use strict";
32545
- var React16 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
32785
+ var React17 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
32546
32786
  Symbol.for("react.scope");
32547
32787
  var REACT_ACTIVITY_TYPE = Symbol.for("react.activity");
32548
32788
  Symbol.for("react.legacy_hidden");
32549
32789
  Symbol.for("react.tracing_marker");
32550
32790
  var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
32551
32791
  Symbol.for("react.view_transition");
32552
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React16.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
32792
+ var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React17.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
32553
32793
  $$$config.cloneMutableInstance;
32554
32794
  var appendInitialChild = $$$config.appendInitialChild, finalizeInitialChildren = $$$config.finalizeInitialChildren, shouldSetTextContent = $$$config.shouldSetTextContent, createTextInstance = $$$config.createTextInstance;
32555
32795
  $$$config.cloneMutableTextInstance;
@@ -45142,14 +45382,14 @@ var require_react_reconciler_development = __commonJS({
45142
45382
  }
45143
45383
  var exports2 = {};
45144
45384
  "use strict";
45145
- var React16 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
45385
+ var React17 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
45146
45386
  Symbol.for("react.scope");
45147
45387
  var REACT_ACTIVITY_TYPE = Symbol.for("react.activity");
45148
45388
  Symbol.for("react.legacy_hidden");
45149
45389
  Symbol.for("react.tracing_marker");
45150
45390
  var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
45151
45391
  Symbol.for("react.view_transition");
45152
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React16.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
45392
+ var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React17.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
45153
45393
  $$$config.cloneMutableInstance;
45154
45394
  var appendInitialChild = $$$config.appendInitialChild, finalizeInitialChildren = $$$config.finalizeInitialChildren, shouldSetTextContent = $$$config.shouldSetTextContent, createTextInstance = $$$config.createTextInstance;
45155
45395
  $$$config.cloneMutableTextInstance;
@@ -58809,18 +59049,18 @@ var require_react_jsx_runtime_development = __commonJS({
58809
59049
  function isValidElement(object) {
58810
59050
  return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
58811
59051
  }
58812
- var React16 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React16.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
59052
+ var React17 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React17.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
58813
59053
  return null;
58814
59054
  };
58815
- React16 = {
59055
+ React17 = {
58816
59056
  react_stack_bottom_frame: function(callStackForError) {
58817
59057
  return callStackForError();
58818
59058
  }
58819
59059
  };
58820
59060
  var specialPropKeyWarningShown;
58821
59061
  var didWarnAboutElementRef = {};
58822
- var unknownOwnerDebugStack = React16.react_stack_bottom_frame.bind(
58823
- React16,
59062
+ var unknownOwnerDebugStack = React17.react_stack_bottom_frame.bind(
59063
+ React17,
58824
59064
  UnknownOwner
58825
59065
  )();
58826
59066
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -59552,7 +59792,7 @@ function StatusBar({
59552
59792
  ] }),
59553
59793
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { dimColor: true, children: [
59554
59794
  " v",
59555
- "0.13.2"
59795
+ "0.13.4"
59556
59796
  ] }),
59557
59797
  updateInfo && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { color: "yellow", children: [
59558
59798
  " (v",
@@ -59661,22 +59901,13 @@ var init_useSpinner = __esm({
59661
59901
  });
59662
59902
 
59663
59903
  // src/dashboard/branding.ts
59664
- var LOGO_ART, HELP_HEADER;
59904
+ var LOGO_ART;
59665
59905
  var init_branding = __esm({
59666
59906
  "src/dashboard/branding.ts"() {
59667
59907
  "use strict";
59668
- init_phraseFormatters();
59669
59908
  LOGO_ART = [
59670
- " {yellow-fg}\u26A1{/yellow-fg}",
59671
- " {magenta-fg}\u2502{/magenta-fg}",
59672
- " {white-fg}</>{/white-fg} {white-fg}\u256D\u2500\u2500\u2534\u2500\u2500\u256E{/white-fg} {bold}{magenta-fg}S I D E K I C K{/magenta-fg}{/bold}",
59673
- " {white-fg}\u2502{/white-fg} {cyan-fg}\u25CF{/cyan-fg} {cyan-fg}\u25CF{/cyan-fg} {white-fg}\u2502{/white-fg} {bold}Agent Hub{/bold}",
59674
- " {white-fg}\u2502{/white-fg} {green-fg}\u25E1{/green-fg} {white-fg}\u2502{/white-fg} {grey-fg}Terminal Dashboard{/grey-fg}",
59675
- " {white-fg}\u2570\u2500\u2500\u2500\u2500\u2500\u256F{/white-fg}"
59676
- ];
59677
- HELP_HEADER = [
59678
- ...LOGO_ART,
59679
- ""
59909
+ " {bold}{magenta-fg}\u26A1 S I D E K I C K{/magenta-fg}{/bold}",
59910
+ " {grey-fg}Agent Hub \xB7 Terminal Dashboard{/grey-fg}"
59680
59911
  ];
59681
59912
  }
59682
59913
  });
@@ -59684,6 +59915,7 @@ var init_branding = __esm({
59684
59915
  // src/dashboard/ink/SplashOverlay.tsx
59685
59916
  function SplashOverlay() {
59686
59917
  const spinner = useSpinner();
59918
+ const phrase = (0, import_react33.useMemo)(() => (0, import_sidekick_shared10.getRandomPhrase)(), []);
59687
59919
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
59688
59920
  Box_default,
59689
59921
  {
@@ -59698,7 +59930,7 @@ function SplashOverlay() {
59698
59930
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
59699
59931
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "gray", children: [
59700
59932
  " ",
59701
- (0, import_sidekick_shared10.getRandomPhrase)()
59933
+ phrase
59702
59934
  ] }),
59703
59935
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
59704
59936
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { children: [
@@ -59733,10 +59965,11 @@ function SplashOverlay() {
59733
59965
  }
59734
59966
  );
59735
59967
  }
59736
- var import_sidekick_shared10, import_jsx_runtime8;
59968
+ var import_react33, import_sidekick_shared10, import_jsx_runtime8;
59737
59969
  var init_SplashOverlay = __esm({
59738
59970
  async "src/dashboard/ink/SplashOverlay.tsx"() {
59739
59971
  "use strict";
59972
+ import_react33 = __toESM(require_react(), 1);
59740
59973
  await init_build2();
59741
59974
  init_useSpinner();
59742
59975
  import_sidekick_shared10 = __toESM(require_dist(), 1);
@@ -59801,8 +60034,8 @@ function HelpOverlay({ panels, activePanelIndex }) {
59801
60034
  panel.title,
59802
60035
  " Actions"
59803
60036
  ] }),
59804
- actions.map((a) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react33.default.Fragment, { children: helpRow(a.key, a.label) }, a.key)),
59805
- bindings.map((b) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react33.default.Fragment, { children: helpRow(b.keys.join("/"), b.label) }, b.keys[0]))
60037
+ actions.map((a) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react34.default.Fragment, { children: helpRow(a.key, a.label) }, a.key)),
60038
+ bindings.map((b) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react34.default.Fragment, { children: helpRow(b.keys.join("/"), b.label) }, b.keys[0]))
59806
60039
  ] }),
59807
60040
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { children: " " }),
59808
60041
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { bold: true, children: " General" }),
@@ -59815,11 +60048,11 @@ function HelpOverlay({ panels, activePanelIndex }) {
59815
60048
  }
59816
60049
  ) });
59817
60050
  }
59818
- var import_react33, import_jsx_runtime9;
60051
+ var import_react34, import_jsx_runtime9;
59819
60052
  var init_HelpOverlay = __esm({
59820
60053
  async "src/dashboard/ink/HelpOverlay.tsx"() {
59821
60054
  "use strict";
59822
- import_react33 = __toESM(require_react(), 1);
60055
+ import_react34 = __toESM(require_react(), 1);
59823
60056
  await init_build2();
59824
60057
  init_branding();
59825
60058
  await init_parseBlessedTags();
@@ -59935,7 +60168,7 @@ function ChangelogOverlay({ entries, scrollOffset }) {
59935
60168
  " ",
59936
60169
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, color: "cyan", children: [
59937
60170
  "Terminal Dashboard v",
59938
- "0.13.2"
60171
+ "0.13.4"
59939
60172
  ] }),
59940
60173
  latestDate ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "gray", children: [
59941
60174
  " \u2014 ",
@@ -60002,44 +60235,11 @@ function ChangelogOverlay({ entries, scrollOffset }) {
60002
60235
  width,
60003
60236
  children: [
60004
60237
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
60005
- " ",
60006
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "yellow", children: "\u26A1" })
60007
- ] }),
60008
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
60009
- " ",
60010
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "magenta", children: "\u2502" })
60011
- ] }),
60012
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
60013
- " ",
60014
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "</>" }),
60015
- " ",
60016
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "\u256D\u2500\u2500\u2534\u2500\u2500\u256E" }),
60017
- " ",
60018
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { bold: true, color: "magenta", children: "W H A T ' S N E W" })
60019
- ] }),
60020
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
60021
- " ",
60022
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "\u2502" }),
60023
- " ",
60024
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "cyan", children: "\u25CF" }),
60025
- " ",
60026
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "cyan", children: "\u25CF" }),
60027
- " ",
60028
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "\u2502" }),
60029
- " ",
60030
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { bold: true, children: "Sidekick Agent Hub" })
60031
- ] }),
60032
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
60033
- " ",
60034
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "\u2502" }),
60035
60238
  " ",
60036
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "green", children: "\u25E1" }),
60037
- " ",
60038
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "\u2502" })
60039
- ] }),
60040
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
60041
- " ",
60042
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "white", children: "\u2570\u2500\u2500\u2500\u2500\u2500\u256F" })
60239
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, color: "magenta", children: [
60240
+ "\u26A1",
60241
+ " W H A T ' S N E W"
60242
+ ] })
60043
60243
  ] }),
60044
60244
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: " " }),
60045
60245
  canScrollUp && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "gray", children: " \u25B2 scroll up (k)" }),
@@ -60242,7 +60442,7 @@ function InputSink() {
60242
60442
  return null;
60243
60443
  }
60244
60444
  function MouseProvider({ onMouse, children }) {
60245
- (0, import_react34.useEffect)(() => {
60445
+ (0, import_react35.useEffect)(() => {
60246
60446
  enableMouse();
60247
60447
  const handler = (data) => {
60248
60448
  const event = parseMouseEvent(data);
@@ -60264,11 +60464,11 @@ function MouseProvider({ onMouse, children }) {
60264
60464
  children
60265
60465
  ] });
60266
60466
  }
60267
- var import_react34, import_jsx_runtime15;
60467
+ var import_react35, import_jsx_runtime15;
60268
60468
  var init_MouseProvider = __esm({
60269
60469
  async "src/dashboard/ink/mouse/MouseProvider.tsx"() {
60270
60470
  "use strict";
60271
- import_react34 = __toESM(require_react(), 1);
60471
+ import_react35 = __toESM(require_react(), 1);
60272
60472
  await init_build2();
60273
60473
  init_mouseProtocol();
60274
60474
  init_parseMouseEvent();
@@ -60290,7 +60490,7 @@ var init_mouse = __esm({
60290
60490
  var CHANGELOG_default;
60291
60491
  var init_CHANGELOG = __esm({
60292
60492
  "CHANGELOG.md"() {
60293
- CHANGELOG_default = '# Changelog\n\nAll notable changes to the Sidekick Agent Hub CLI will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [0.13.2] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.1] - 2026-03-04\n\n### Added\n\n- **`sidekick quota` Command**: One-shot subscription quota check showing 5-hour and 7-day utilization with color-coded progress bars and reset countdowns \u2014 supports `--json` for machine-readable output\n- **Quota Projections**: Elapsed-time projections shown in `sidekick quota` output and TUI dashboard quota section \u2014 displays projected end-of-window utilization next to current value (e.g., `40% \u2192 100%`), included in `--json` output as `projectedFiveHour` / `projectedSevenDay`\n\n## [0.13.0] - 2026-03-03\n\n_No CLI-specific changes in this release._\n\n## [0.12.10] - 2026-03-01\n\n### Added\n\n- **Events Panel** (key 7): Scrollable live event stream with colored type badges (`[USR]`, `[AST]`, `[TOOL]`, `[RES]`), timestamps, and keyword-highlighted summaries; detail tabs for full event JSON and surrounding context\n- **Charts Panel** (key 8): Tool frequency horizontal bars, event type distribution, 60-minute activity heatmap using `\u2591\u2592\u2593\u2588` intensity characters, and pattern analysis with frequency bars and template text\n- **Multi-Mode Filter**: `/` filter overlay now supports four modes \u2014 substring, fuzzy, regex, and date range \u2014 Tab cycles modes, regex mode shows red validation errors\n- **Search Term Highlighting**: Active filter terms highlighted in blue within side list items\n- **Timeline Keyword Coloring**: Event summaries in the Sessions panel Timeline tab now use semantic keyword coloring \u2014 errors red, success green, tool names cyan, file paths magenta\n\n### Removed\n\n- **Search Panel**: Removed redundant Search panel (previously key 7) \u2014 the `/` filter with multi-mode support serves the same purpose\n\n## [0.12.9] - 2026-02-28\n\n### Added\n\n- **Standalone Data Commands**: `sidekick tasks`, `sidekick decisions`, `sidekick notes`, `sidekick stats`, `sidekick handoff` for accessing project data without launching the TUI\n- **`sidekick search <query>`**: Cross-session full-text search from the terminal\n- **`sidekick context`**: Composite output of tasks, decisions, notes, and handoff for piping into other tools\n- **`--list` flag on `sidekick dump`**: Discover available session IDs before requiring `--session <id>`\n- **Search Panel**: Search panel (panel 7) wired into the TUI dashboard\n\n### Changed\n\n- **`taskMerger` utility**: Duplicate `mergeTasks` logic extracted into shared `taskMerger` utility\n- **Model constants**: Hardcoded model IDs extracted to named constants\n\n### Fixed\n\n- **`convention` icon**: Notes panel icon replaced with valid `tip` type\n- **Linux clipboard**: Now supports Wayland (`wl-copy`) and `xsel` fallbacks, with error messages instead of silent failure\n- **`provider.dispose()`**: Added to `dump` and `report` commands (prevents SQLite connection leaks)\n\n## [0.12.8] - 2026-02-28\n\n### Changed\n\n- **Dashboard UI/UX Polish**: Visual overhaul for better hierarchy, consistency, and readability\n - Splash screen and help overlay now display the robot ASCII logo\n - Toast notifications show severity icons (\u2718 error, \u26A0 warning, \u25CF info) with inner padding\n - Focused pane uses double-border for clear focus indication\n - Section dividers (`\u2500\u2500 Title \u2500\u2500\u2500\u2500`) replace bare bold headers in summary, agents, and context attribution\n - Tab bar: active tab underlined in magenta, inactive tabs dimmed, bracket syntax removed\n - Status bar: segmented layout with `\u2502` separators; keys bold, labels dim\n - Summary metrics condensed: elapsed/events/compactions on one line, tokens on one line with cache rate and cost\n - Sparklines display peak metadata annotations\n - Progress bars use blessed color tags for consistent coloring\n - Help overlay uses dot-leader alignment for all keybinding rows\n - Empty state hints per panel (e.g. "Tasks appear as your agent works.")\n - Session picker groups sessions by provider with section headers when multiple providers are present\n\n## [0.12.7] - 2026-02-27\n\n### Added\n\n- **HTML Session Report**: `sidekick report` command generates a self-contained HTML report and opens it in the default browser\n - Options: `--session`, `--output`, `--theme` (dark/light), `--no-open`, `--no-thinking`\n - TUI Dashboard: press `r` to generate and open an HTML report for the current session\n\n## [0.12.6] - 2026-02-26\n\n### Added\n\n- **Session Dump Command**: `sidekick dump` exports session data in text, markdown, or JSON format with `--format`, `--width`, and `--expand` options\n- **Plans Panel Re-enabled**: Plans panel restored in CLI dashboard with plan file discovery from `~/.claude/plans/`\n- **Enhanced Status Bar**: Session info display improved with richer metadata\n\n### Fixed\n\n- **Old snapshot format migration**: Restoring pre-0.12.3 session snapshots no longer shows empty timeline entries\n\n### Changed\n\n- **Phrase library moved to shared**: CLI-specific phrase formatting kept local, all phrase content now from `sidekick-shared`\n\n## [0.12.5] - 2026-02-24\n\n### Fixed\n\n- **Update check too slow to notice new versions**: Reduced npm registry cache TTL from 24 hours to 4 hours so upgrade notices appear sooner after a new release\n\n## [0.12.4] - 2026-02-24\n\n### Fixed\n\n- **Session crash on upgrade**: Fixed `d.timestamp.getTime is not a function` error when restoring tool call data from session snapshots \u2014 `Date` objects were serialized to strings by JSON but not rehydrated on restore, causing the session monitor to crash on first run after upgrading from 0.12.2 to 0.12.3\n\n## [0.12.3] - 2026-02-24\n\n### Added\n\n- **Latest-node indicator**: The most recently added node in tree and boxed mind map views is now marked with a yellow indicator\n- **Plan analytics in mind map**: Tree and boxed views now display plan progress and per-step metrics\n - Tree view: plan header shows completion stats; steps show complexity, duration, tokens, tool calls, and errors in metadata brackets\n - Box view: progress bar with completion percentage; steps show right-aligned metrics; subtitle shows step count and total duration\n- **Cross-provider plan extraction**: Shared `PlanExtractor` now handles Claude Code (EnterPlanMode/ExitPlanMode) and OpenCode (`<proposed_plan>` XML) plans \u2014 previously only Codex plans were shown\n- **Enriched plan data model**: Plan steps include duration, token count, tool call count, and error messages\n- **Phase-grouped plan display**: When a plan has phase structure, tree and boxed views group steps under phase headers with context lines from the original plan markdown\n- **Node type filter**: Press `f` on the Mind Map tab to cycle through node type filters (file, tool, task, subagent, command, plan, knowledge-note) \u2014 non-matching sections render dimmed in grey\n\n### Fixed\n\n- **Kanban board regression**: Subagent and plan-step tasks now correctly appear in the kanban board\n\n### Changed\n\n- **Plans panel temporarily disabled**: The Plans panel in the CLI dashboard is disabled until plan-mode event capture is reliably working end-to-end. Plan nodes in the mind map remain active.\n- `DashboardState` now delegates to shared `EventAggregator` instead of maintaining its own aggregation logic\n\n## [0.12.2] - 2026-02-23\n\n### Added\n\n- **Update notifications**: The dashboard now checks the npm registry for newer versions on startup and shows a yellow banner in the status bar when an update is available (e.g., `v0.13.0 available \u2014 npm i -g sidekick-agent-hub`). Results are cached for 24 hours to avoid repeated network requests.\n\n## [0.12.1] - 2026-02-23\n\n### Fixed\n\n- **VS Code integration**: Fixed exit code 127 when the extension launches the CLI dashboard on systems using nvm or volta (node binary not found when shell init is bypassed)\n\n## [0.12.0] - 2026-02-22\n\n### Added\n\n- **"Open CLI Dashboard" VS Code Integration**: New VS Code command `Sidekick: Open CLI Dashboard` launches the TUI dashboard in an integrated terminal\n - Install the CLI with `npm install -g sidekick-agent-hub`\n\n## [0.11.0] - 2026-02-19\n\n### Added\n\n- **Initial Release**: Full-screen TUI dashboard for monitoring agent sessions from the terminal\n - Ink-based terminal UI with panels for sessions, tasks, kanban, mind map, notes, decisions, search, files, and git diff\n - Multi-provider support: auto-detects Claude Code, OpenCode, and Codex sessions\n - Reads from `~/.config/sidekick/` \u2014 the same data files the VS Code extension writes\n - Usage: `sidekick dashboard [--project <path>] [--provider <id>]`\n';
60493
+ CHANGELOG_default = '# Changelog\n\nAll notable changes to the Sidekick Agent Hub CLI will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [0.13.4] - 2026-03-08\n\n### Fixed\n\n- **Onboarding Phrase Spam**: Splash screen and detail pane motivational phrases memoized \u2014 no longer flicker every render tick (fixes [#13](https://github.com/cesarandreslopez/sidekick-agent-hub/issues/13))\n\n### Changed\n\n- **Simplified Logo**: Replaced 6-line ASCII robot art with compact text header in splash, help, and changelog overlays\n- **Removed Dead Code**: Removed unused `getSplashContent()` and `HELP_HEADER` exports from branding module\n\n## [0.13.3] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.2] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.1] - 2026-03-04\n\n### Added\n\n- **`sidekick quota` Command**: One-shot subscription quota check showing 5-hour and 7-day utilization with color-coded progress bars and reset countdowns \u2014 supports `--json` for machine-readable output\n- **Quota Projections**: Elapsed-time projections shown in `sidekick quota` output and TUI dashboard quota section \u2014 displays projected end-of-window utilization next to current value (e.g., `40% \u2192 100%`), included in `--json` output as `projectedFiveHour` / `projectedSevenDay`\n\n## [0.13.0] - 2026-03-03\n\n_No CLI-specific changes in this release._\n\n## [0.12.10] - 2026-03-01\n\n### Added\n\n- **Events Panel** (key 7): Scrollable live event stream with colored type badges (`[USR]`, `[AST]`, `[TOOL]`, `[RES]`), timestamps, and keyword-highlighted summaries; detail tabs for full event JSON and surrounding context\n- **Charts Panel** (key 8): Tool frequency horizontal bars, event type distribution, 60-minute activity heatmap using `\u2591\u2592\u2593\u2588` intensity characters, and pattern analysis with frequency bars and template text\n- **Multi-Mode Filter**: `/` filter overlay now supports four modes \u2014 substring, fuzzy, regex, and date range \u2014 Tab cycles modes, regex mode shows red validation errors\n- **Search Term Highlighting**: Active filter terms highlighted in blue within side list items\n- **Timeline Keyword Coloring**: Event summaries in the Sessions panel Timeline tab now use semantic keyword coloring \u2014 errors red, success green, tool names cyan, file paths magenta\n\n### Removed\n\n- **Search Panel**: Removed redundant Search panel (previously key 7) \u2014 the `/` filter with multi-mode support serves the same purpose\n\n## [0.12.9] - 2026-02-28\n\n### Added\n\n- **Standalone Data Commands**: `sidekick tasks`, `sidekick decisions`, `sidekick notes`, `sidekick stats`, `sidekick handoff` for accessing project data without launching the TUI\n- **`sidekick search <query>`**: Cross-session full-text search from the terminal\n- **`sidekick context`**: Composite output of tasks, decisions, notes, and handoff for piping into other tools\n- **`--list` flag on `sidekick dump`**: Discover available session IDs before requiring `--session <id>`\n- **Search Panel**: Search panel (panel 7) wired into the TUI dashboard\n\n### Changed\n\n- **`taskMerger` utility**: Duplicate `mergeTasks` logic extracted into shared `taskMerger` utility\n- **Model constants**: Hardcoded model IDs extracted to named constants\n\n### Fixed\n\n- **`convention` icon**: Notes panel icon replaced with valid `tip` type\n- **Linux clipboard**: Now supports Wayland (`wl-copy`) and `xsel` fallbacks, with error messages instead of silent failure\n- **`provider.dispose()`**: Added to `dump` and `report` commands (prevents SQLite connection leaks)\n\n## [0.12.8] - 2026-02-28\n\n### Changed\n\n- **Dashboard UI/UX Polish**: Visual overhaul for better hierarchy, consistency, and readability\n - Splash screen and help overlay now display the robot ASCII logo\n - Toast notifications show severity icons (\u2718 error, \u26A0 warning, \u25CF info) with inner padding\n - Focused pane uses double-border for clear focus indication\n - Section dividers (`\u2500\u2500 Title \u2500\u2500\u2500\u2500`) replace bare bold headers in summary, agents, and context attribution\n - Tab bar: active tab underlined in magenta, inactive tabs dimmed, bracket syntax removed\n - Status bar: segmented layout with `\u2502` separators; keys bold, labels dim\n - Summary metrics condensed: elapsed/events/compactions on one line, tokens on one line with cache rate and cost\n - Sparklines display peak metadata annotations\n - Progress bars use blessed color tags for consistent coloring\n - Help overlay uses dot-leader alignment for all keybinding rows\n - Empty state hints per panel (e.g. "Tasks appear as your agent works.")\n - Session picker groups sessions by provider with section headers when multiple providers are present\n\n## [0.12.7] - 2026-02-27\n\n### Added\n\n- **HTML Session Report**: `sidekick report` command generates a self-contained HTML report and opens it in the default browser\n - Options: `--session`, `--output`, `--theme` (dark/light), `--no-open`, `--no-thinking`\n - TUI Dashboard: press `r` to generate and open an HTML report for the current session\n\n## [0.12.6] - 2026-02-26\n\n### Added\n\n- **Session Dump Command**: `sidekick dump` exports session data in text, markdown, or JSON format with `--format`, `--width`, and `--expand` options\n- **Plans Panel Re-enabled**: Plans panel restored in CLI dashboard with plan file discovery from `~/.claude/plans/`\n- **Enhanced Status Bar**: Session info display improved with richer metadata\n\n### Fixed\n\n- **Old snapshot format migration**: Restoring pre-0.12.3 session snapshots no longer shows empty timeline entries\n\n### Changed\n\n- **Phrase library moved to shared**: CLI-specific phrase formatting kept local, all phrase content now from `sidekick-shared`\n\n## [0.12.5] - 2026-02-24\n\n### Fixed\n\n- **Update check too slow to notice new versions**: Reduced npm registry cache TTL from 24 hours to 4 hours so upgrade notices appear sooner after a new release\n\n## [0.12.4] - 2026-02-24\n\n### Fixed\n\n- **Session crash on upgrade**: Fixed `d.timestamp.getTime is not a function` error when restoring tool call data from session snapshots \u2014 `Date` objects were serialized to strings by JSON but not rehydrated on restore, causing the session monitor to crash on first run after upgrading from 0.12.2 to 0.12.3\n\n## [0.12.3] - 2026-02-24\n\n### Added\n\n- **Latest-node indicator**: The most recently added node in tree and boxed mind map views is now marked with a yellow indicator\n- **Plan analytics in mind map**: Tree and boxed views now display plan progress and per-step metrics\n - Tree view: plan header shows completion stats; steps show complexity, duration, tokens, tool calls, and errors in metadata brackets\n - Box view: progress bar with completion percentage; steps show right-aligned metrics; subtitle shows step count and total duration\n- **Cross-provider plan extraction**: Shared `PlanExtractor` now handles Claude Code (EnterPlanMode/ExitPlanMode) and OpenCode (`<proposed_plan>` XML) plans \u2014 previously only Codex plans were shown\n- **Enriched plan data model**: Plan steps include duration, token count, tool call count, and error messages\n- **Phase-grouped plan display**: When a plan has phase structure, tree and boxed views group steps under phase headers with context lines from the original plan markdown\n- **Node type filter**: Press `f` on the Mind Map tab to cycle through node type filters (file, tool, task, subagent, command, plan, knowledge-note) \u2014 non-matching sections render dimmed in grey\n\n### Fixed\n\n- **Kanban board regression**: Subagent and plan-step tasks now correctly appear in the kanban board\n\n### Changed\n\n- **Plans panel temporarily disabled**: The Plans panel in the CLI dashboard is disabled until plan-mode event capture is reliably working end-to-end. Plan nodes in the mind map remain active.\n- `DashboardState` now delegates to shared `EventAggregator` instead of maintaining its own aggregation logic\n\n## [0.12.2] - 2026-02-23\n\n### Added\n\n- **Update notifications**: The dashboard now checks the npm registry for newer versions on startup and shows a yellow banner in the status bar when an update is available (e.g., `v0.13.0 available \u2014 npm i -g sidekick-agent-hub`). Results are cached for 24 hours to avoid repeated network requests.\n\n## [0.12.1] - 2026-02-23\n\n### Fixed\n\n- **VS Code integration**: Fixed exit code 127 when the extension launches the CLI dashboard on systems using nvm or volta (node binary not found when shell init is bypassed)\n\n## [0.12.0] - 2026-02-22\n\n### Added\n\n- **"Open CLI Dashboard" VS Code Integration**: New VS Code command `Sidekick: Open CLI Dashboard` launches the TUI dashboard in an integrated terminal\n - Install the CLI with `npm install -g sidekick-agent-hub`\n\n## [0.11.0] - 2026-02-19\n\n### Added\n\n- **Initial Release**: Full-screen TUI dashboard for monitoring agent sessions from the terminal\n - Ink-based terminal UI with panels for sessions, tasks, kanban, mind map, notes, decisions, search, files, and git diff\n - Multi-provider support: auto-detects Claude Code, OpenCode, and Codex sessions\n - Reads from `~/.config/sidekick/` \u2014 the same data files the VS Code extension writes\n - Usage: `sidekick dashboard [--project <path>] [--provider <id>]`\n';
60294
60494
  }
60295
60495
  });
60296
60496
 
@@ -60410,20 +60610,20 @@ function reducer(state, action) {
60410
60610
  }
60411
60611
  }
60412
60612
  function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath, onSessionSwitch, onTogglePin, onGenerateReport }) {
60413
- const [state, dispatch] = (0, import_react35.useReducer)(reducer, initialState);
60613
+ const [state, dispatch] = (0, import_react36.useReducer)(reducer, initialState);
60414
60614
  const { exit } = use_app_default();
60415
60615
  const { columns, rows } = useTerminalSize();
60416
- const toastIdRef = (0, import_react35.useRef)(0);
60417
- const lastAlertCountRef = (0, import_react35.useRef)(0);
60418
- const alertsInitRef = (0, import_react35.useRef)(false);
60419
- const prevDetailLineCountRef = (0, import_react35.useRef)(0);
60420
- (0, import_react35.useEffect)(() => {
60616
+ const toastIdRef = (0, import_react36.useRef)(0);
60617
+ const lastAlertCountRef = (0, import_react36.useRef)(0);
60618
+ const alertsInitRef = (0, import_react36.useRef)(false);
60619
+ const prevDetailLineCountRef = (0, import_react36.useRef)(0);
60620
+ (0, import_react36.useEffect)(() => {
60421
60621
  if (!state.hasReceivedEvents && metrics.eventCount > 0) {
60422
60622
  const prefix = (metrics.sessionStartTime || "").substring(0, 8);
60423
60623
  dispatch({ type: "FIRST_EVENT", sessionPrefix: prefix });
60424
60624
  }
60425
60625
  }, [metrics.eventCount, state.hasReceivedEvents, metrics.sessionStartTime]);
60426
- (0, import_react35.useEffect)(() => {
60626
+ (0, import_react36.useEffect)(() => {
60427
60627
  if (!alertsInitRef.current) {
60428
60628
  lastAlertCountRef.current = metrics.eventCount;
60429
60629
  alertsInitRef.current = true;
@@ -60442,7 +60642,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60442
60642
  }
60443
60643
  lastAlertCountRef.current = metrics.eventCount;
60444
60644
  }, [metrics.eventCount, metrics.timeline]);
60445
- const addToast = (0, import_react35.useCallback)((message, severity) => {
60645
+ const addToast = (0, import_react36.useCallback)((message, severity) => {
60446
60646
  const durations = { error: 4e3, warning: 3e3, info: 2e3 };
60447
60647
  const id = ++toastIdRef.current;
60448
60648
  dispatch({
@@ -60466,7 +60666,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60466
60666
  }
60467
60667
  };
60468
60668
  const sideWidth = getSideWidth();
60469
- const getFilteredItems = (0, import_react35.useCallback)(() => {
60669
+ const getFilteredItems = (0, import_react36.useCallback)(() => {
60470
60670
  let items = panel.getItems(metrics, staticData);
60471
60671
  if (state.sessionFilter && ["tasks", "kanban", "notes", "decisions", "plans"].includes(panel.id)) {
60472
60672
  if (panel.id === "kanban") {
@@ -60511,7 +60711,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60511
60711
  totalItems: currentItems.length,
60512
60712
  viewportHeight: sideViewportHeight
60513
60713
  });
60514
- (0, import_react35.useEffect)(() => {
60714
+ (0, import_react36.useEffect)(() => {
60515
60715
  if (sideScroll.selectedIndex !== state.selectedItemIndex) {
60516
60716
  sideScroll.setSelected(state.selectedItemIndex);
60517
60717
  }
@@ -60519,12 +60719,13 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60519
60719
  const selectedItem = currentItems[clampedSelection];
60520
60720
  const detailTabs = panel.detailTabs;
60521
60721
  const tabIdx = Math.min(state.detailTabIndex, detailTabs.length - 1);
60722
+ const detailPhrase = (0, import_react36.useMemo)(() => getRandomPhraseBlessedTag(), [selectedItem?.id, tabIdx]);
60522
60723
  let detailContent = "";
60523
60724
  if (selectedItem && detailTabs.length > 0 && tabIdx >= 0) {
60524
60725
  const tab2 = detailTabs[tabIdx];
60525
60726
  const tabLabel = tab2.label;
60526
60727
  const skipPhrase = tabLabel === "Timeline" || tabLabel === "Mind Map";
60527
- const prefix = skipPhrase ? "" : getRandomPhraseBlessedTag() + "\n";
60728
+ const prefix = skipPhrase ? "" : detailPhrase + "\n";
60528
60729
  detailContent = prefix + tab2.render(selectedItem, metrics, staticData);
60529
60730
  } else if (!selectedItem) {
60530
60731
  const filterablePanel = ["tasks", "kanban", "notes", "decisions", "plans"].includes(panel.id);
@@ -60533,7 +60734,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60533
60734
  const detailLines = detailContent.split("\n");
60534
60735
  const detailViewportHeight = Math.max(1, rows - 5);
60535
60736
  const activeTab = detailTabs[tabIdx];
60536
- (0, import_react35.useEffect)(() => {
60737
+ (0, import_react36.useEffect)(() => {
60537
60738
  if (!activeTab?.autoScrollBottom) return;
60538
60739
  if (detailLines.length <= detailViewportHeight) return;
60539
60740
  if (detailLines.length > prevDetailLineCountRef.current) {
@@ -60545,12 +60746,12 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60545
60746
  if ("activeDetailTabIndex" in panel) {
60546
60747
  panel.activeDetailTabIndex = state.detailTabIndex;
60547
60748
  }
60548
- const getContextActions = (0, import_react35.useCallback)(() => {
60749
+ const getContextActions = (0, import_react36.useCallback)(() => {
60549
60750
  if (!selectedItem) return [];
60550
60751
  return panel.getActions().filter((a) => !a.condition || a.condition(selectedItem));
60551
60752
  }, [panel, selectedItem]);
60552
60753
  const contextActions = state.overlay === "context-menu" ? getContextActions() : [];
60553
- const buildPanelHints = (0, import_react35.useCallback)(() => {
60754
+ const buildPanelHints = (0, import_react36.useCallback)(() => {
60554
60755
  const parts = [];
60555
60756
  const bindings = panel.getKeybindings?.() || [];
60556
60757
  for (const b of bindings) {
@@ -60566,7 +60767,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60566
60767
  }
60567
60768
  return parts.length > 0 ? parts.join(" ") + " " : "";
60568
60769
  }, [panel, selectedItem, state.focusTarget]);
60569
- const toggleSessionFilter = (0, import_react35.useCallback)(() => {
60770
+ const toggleSessionFilter = (0, import_react36.useCallback)(() => {
60570
60771
  if (state.sessionFilter) {
60571
60772
  dispatch({ type: "SET_SESSION_FILTER", filter: null });
60572
60773
  addToast("Session filter cleared", "info");
@@ -60604,7 +60805,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
60604
60805
  addToast("Cannot filter by this item", "info");
60605
60806
  }
60606
60807
  }, [state.sessionFilter, state.activePanelIndex, selectedItem, panels, metrics, staticData, addToast]);
60607
- const handleMouse = (0, import_react35.useCallback)((event) => {
60808
+ const handleMouse = (0, import_react36.useCallback)((event) => {
60608
60809
  if (state.overlay) {
60609
60810
  if (event.type === "click") {
60610
60811
  dispatch({ type: "SET_OVERLAY", overlay: null });
@@ -61017,11 +61218,11 @@ function filterKanbanColumn(item, filter) {
61017
61218
  data: { status: colData.status, tasks: filtered }
61018
61219
  };
61019
61220
  }
61020
- var import_react35, import_sidekick_shared11, import_jsx_runtime16, changelogEntries, SIDE_PANEL_WIDTH, NARROW_SIDE_WIDTH, MIN_SCREEN_WIDTH, MIN_SCREEN_HEIGHT, WIDE_SIDE_WIDTH, initialState;
61221
+ var import_react36, import_sidekick_shared11, import_jsx_runtime16, changelogEntries, SIDE_PANEL_WIDTH, NARROW_SIDE_WIDTH, MIN_SCREEN_WIDTH, MIN_SCREEN_HEIGHT, WIDE_SIDE_WIDTH, initialState;
61021
61222
  var init_Dashboard = __esm({
61022
61223
  async "src/dashboard/ink/Dashboard.tsx"() {
61023
61224
  "use strict";
61024
- import_react35 = __toESM(require_react(), 1);
61225
+ import_react36 = __toESM(require_react(), 1);
61025
61226
  await init_build2();
61026
61227
  init_phraseFormatters();
61027
61228
  init_useTerminalSize();
@@ -61278,7 +61479,7 @@ async function dashboardAction(_opts, cmd) {
61278
61479
  (0, import_sidekick_shared12.openInBrowser)(outFile);
61279
61480
  };
61280
61481
  const instance = render2(
61281
- import_react36.default.createElement(Dashboard, {
61482
+ import_react37.default.createElement(Dashboard, {
61282
61483
  panels,
61283
61484
  metrics: state.getMetrics(),
61284
61485
  staticData,
@@ -61298,7 +61499,7 @@ async function dashboardAction(_opts, cmd) {
61298
61499
  renderTimer = setTimeout(() => {
61299
61500
  renderTimer = null;
61300
61501
  instance.rerender(
61301
- import_react36.default.createElement(Dashboard, {
61502
+ import_react37.default.createElement(Dashboard, {
61302
61503
  panels,
61303
61504
  metrics: state.getMetrics(),
61304
61505
  staticData,
@@ -61426,11 +61627,11 @@ async function dashboardAction(_opts, cmd) {
61426
61627
  cleanup();
61427
61628
  process.exit(0);
61428
61629
  }
61429
- var import_react36, import_sidekick_shared12, import_sidekick_shared13;
61630
+ var import_react37, import_sidekick_shared12, import_sidekick_shared13;
61430
61631
  var init_dashboard = __esm({
61431
61632
  async "src/commands/dashboard.ts"() {
61432
61633
  "use strict";
61433
- import_react36 = __toESM(require_react(), 1);
61634
+ import_react37 = __toESM(require_react(), 1);
61434
61635
  import_sidekick_shared12 = __toESM(require_dist(), 1);
61435
61636
  import_sidekick_shared13 = __toESM(require_dist(), 1);
61436
61637
  init_cli();
@@ -62445,7 +62646,7 @@ var init_cli = __esm({
62445
62646
  import_sidekick_shared23 = __toESM(require_dist(), 1);
62446
62647
  import_sidekick_shared24 = __toESM(require_dist(), 1);
62447
62648
  program2 = new Command();
62448
- program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.13.2").option("--json", "Output as JSON").option("--project <path>", "Override project path (default: cwd)").option("--provider <id>", "Provider: claude-code, opencode, codex, auto (default: auto)");
62649
+ program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.13.4").option("--json", "Output as JSON").option("--project <path>", "Override project path (default: cwd)").option("--provider <id>", "Provider: claude-code, opencode, codex, auto (default: auto)");
62449
62650
  dashCmd = new Command("dashboard").description("Full-screen TUI dashboard with live session metrics").option("--session <id>", "Follow a specific session (default: most recent)").option("--replay", "Replay existing events before streaming new ones").action(async (_opts, cmd) => {
62450
62651
  const { dashboardAction: dashboardAction2 } = await init_dashboard().then(() => dashboard_exports);
62451
62652
  return dashboardAction2(_opts, cmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sidekick-agent-hub",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "Terminal dashboard for monitoring AI coding agent sessions",
5
5
  "type": "module",
6
6
  "bin": {