@adhdev/daemon-core 0.9.82-rc.166 → 0.9.82-rc.167

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.
@@ -31,6 +31,7 @@ export interface ModalTuiSpec {
31
31
  questionVariants?: ModalQuestionVariant[];
32
32
  buttonPattern: string;
33
33
  buttonFlags?: string;
34
+ buttonLabelGroup?: number;
34
35
  /**
35
36
  * Optional fallback for terminals that render all options on a single line
36
37
  * (e.g. Antigravity feedback survey: `[0] skip [1] yes [2] no [3] still using`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.166",
3
+ "version": "0.9.82-rc.167",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -556,6 +556,24 @@ function hasDispatchAfterTerminal(meshId: string, sessionId: string, terminalId:
556
556
  return false;
557
557
  }
558
558
 
559
+ function hasUnterminalDirectDispatchLedgerEntry(meshId: string, sessionId: string): boolean {
560
+ // Some dispatch paths can persist task_dispatched before the direct-dispatch DB row is
561
+ // available. Recover routing from ledger order so coordinator self-targets still emit
562
+ // task_completed and pendingCoordinatorEvents.
563
+ const entries = readLedgerEntries(meshId, { tail: 200 });
564
+ for (let i = entries.length - 1; i >= 0; i--) {
565
+ const entry = entries[i];
566
+ if (entry.sessionId !== sessionId) continue;
567
+ if (entry.kind === 'task_completed' || entry.kind === 'task_failed' || entry.kind === 'task_stalled') {
568
+ return false;
569
+ }
570
+ if (entry.kind === 'task_dispatched' && entry.payload?.source === 'direct') {
571
+ return true;
572
+ }
573
+ }
574
+ return false;
575
+ }
576
+
559
577
  function buildLongGeneratingCompletionReconciliation(args: {
560
578
  meshId: string;
561
579
  nodeId?: string;
@@ -1627,7 +1645,7 @@ export function setupMeshEventForwarding(components: DaemonComponents) {
1627
1645
  if (coordinatorMeshId) {
1628
1646
  try {
1629
1647
  const activeDispatches = getActiveDirectDispatches(coordinatorMeshId);
1630
- if (activeDispatches.some(d => d.sessionId === instanceId)) {
1648
+ if (activeDispatches.some(d => d.sessionId === instanceId) || hasUnterminalDirectDispatchLedgerEntry(coordinatorMeshId, instanceId)) {
1631
1649
  meshIdFromDirectDispatch = coordinatorMeshId;
1632
1650
  }
1633
1651
  } catch { /* best-effort */ }
@@ -729,7 +729,7 @@ export class CliProviderInstance implements ProviderInstance {
729
729
  }
730
730
 
731
731
  getSessionModalState(sessionId?: string): SessionModalState {
732
- const adapterStatus = this.adapter.getStatus({ allowParse: false });
732
+ const adapterStatus = this.adapter.getStatus({ allowParse: true });
733
733
  const autoApproveActive = adapterStatus.status === 'waiting_approval' && this.shouldAutoApprove();
734
734
  const visibleStatus = autoApproveActive ? 'generating' : adapterStatus.status;
735
735
  const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
@@ -30,6 +30,10 @@ import type {
30
30
  ResolvedProvider,
31
31
  } from './contracts.js';
32
32
  import { validateProviderDefinition } from './provider-schema.js';
33
+ import {
34
+ loadProvidersActive,
35
+ resolveActiveSource,
36
+ } from './external-sources.js';
33
37
  import type { ProviderSourceMode } from '../config/config.js';
34
38
  import type { ProviderSourceConfigSnapshot, ProviderUserDirSource } from '../config/provider-source-config.js';
35
39
 
@@ -430,10 +434,6 @@ export class ProviderLoader {
430
434
  }
431
435
  } else {
432
436
  // New layout: external/<source-name>/<category>/<type>/…
433
- const {
434
- loadProvidersActive,
435
- resolveActiveSource,
436
- } = require('./external-sources.js') as typeof import('./external-sources.js');
437
437
  const activeFile = loadProvidersActive();
438
438
  let totalLoaded = 0;
439
439
  const ambiguousTypes: { type: string; chosen: string; candidates: string[] }[] = [];
@@ -44,6 +44,7 @@ export interface ModalTuiSpec {
44
44
  questionVariants?: ModalQuestionVariant[];
45
45
  buttonPattern: string;
46
46
  buttonFlags?: string;
47
+ buttonLabelGroup?: number;
47
48
  /**
48
49
  * Optional fallback for terminals that render all options on a single line
49
50
  * (e.g. Antigravity feedback survey: `[0] skip [1] yes [2] no [3] still using`).
@@ -136,12 +137,16 @@ function extractButtons(
136
137
  ): string[] {
137
138
  const buttonRe = compile(spec.buttonPattern, spec.buttonFlags ?? 'm');
138
139
  const out: string[] = [];
140
+ const labelGroup = Number.isInteger(spec.buttonLabelGroup) && (spec.buttonLabelGroup ?? 0) > 0
141
+ ? spec.buttonLabelGroup!
142
+ : 1;
139
143
  let i = windowStart;
140
144
  while (i < windowEnd) {
141
145
  const line = lines[i];
142
146
  const m = buttonRe.exec(line);
143
- if (m && m[1]) {
144
- let label = m[1].trim();
147
+ const captured = m?.[labelGroup] ?? (labelGroup === 1 && m && m.length > 2 ? m[m.length - 1] : undefined);
148
+ if (m && captured) {
149
+ let label = captured.trim();
145
150
  // Continuation lines: when enabled, append indented lines below until
146
151
  // the next button or blank.
147
152
  if (spec.continuationLines) {
@@ -36,6 +36,12 @@
36
36
  "type": "string",
37
37
  "description": "Regex source matching a single button line. Capture group 1 is the button label. Example: `^[\\s❯>]*\\d+\\.\\s+(.+)$`."
38
38
  },
39
+ "buttonLabelGroup": {
40
+ "type": "integer",
41
+ "minimum": 1,
42
+ "default": 1,
43
+ "description": "Capture group number to use as the button label when `buttonPattern` contains non-label groups such as selected-row markers."
44
+ },
39
45
  "buttonFlags": {
40
46
  "type": "string",
41
47
  "pattern": "^[gimsuy]*$",