@adhdev/daemon-core 0.9.35 → 0.9.36

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.9.35",
3
+ "version": "0.9.36",
4
4
  "description": "ADHDev local session host core \u2014 session registry, protocol, buffers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.35",
3
+ "version": "0.9.36",
4
4
  "description": "ADHDev daemon core \u2014 CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -369,7 +369,17 @@ export class ProviderCliAdapter implements CliAdapter {
369
369
  return baseMessages.slice(-ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
370
370
  }
371
371
 
372
+ private messagesShareStableIdentity(left: any, right: any): boolean {
373
+ if (left === right) return true;
374
+ if (!left || !right) return false;
375
+ if ((left.role || '') !== (right.role || '')) return false;
376
+ if (left.id && right.id && String(left.id) === String(right.id)) return true;
377
+ if (typeof left.index === 'number' && typeof right.index === 'number' && left.index === right.index) return true;
378
+ return false;
379
+ }
380
+
372
381
  private messagesComparable(left: any, right: any): boolean {
382
+ if (this.messagesShareStableIdentity(left, right)) return true;
373
383
  if (!left || !right) return false;
374
384
  if ((left.role || '') !== (right.role || '')) return false;
375
385
  const leftText = normalizeComparableTranscriptText(left.content);
@@ -1723,6 +1733,82 @@ export class ProviderCliAdapter implements CliAdapter {
1723
1733
  this.syncMessageViews();
1724
1734
  }
1725
1735
 
1736
+ private getSharedCommittedPrefixLength(parsedMessages: any[]): number {
1737
+ const committedMessages = this.committedMessages;
1738
+ const max = Math.min(parsedMessages.length, committedMessages.length);
1739
+ let index = 0;
1740
+ while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
1741
+ index += 1;
1742
+ }
1743
+ return index;
1744
+ }
1745
+
1746
+ private hydrateCommittedPrefixForParsedStatus(parsedMessages: any[]): any[] | null {
1747
+ const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
1748
+ if (sharedPrefixLength !== this.committedMessages.length) return null;
1749
+
1750
+ const committedHydratedMessages = this.committedMessages.map((message, index) => {
1751
+ const timestamp = typeof message.timestamp === 'number' && Number.isFinite(message.timestamp)
1752
+ ? message.timestamp
1753
+ : (this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now());
1754
+ const contentValue = message.content;
1755
+ return {
1756
+ role: message.role,
1757
+ content: typeof contentValue === 'string' ? contentValue : String(contentValue || ''),
1758
+ timestamp,
1759
+ receivedAt: typeof message.receivedAt === 'number' && Number.isFinite(message.receivedAt)
1760
+ ? message.receivedAt
1761
+ : timestamp,
1762
+ kind: message.kind,
1763
+ id: message.id || `msg_${index}`,
1764
+ index: typeof message.index === 'number' ? message.index : index,
1765
+ meta: message.meta,
1766
+ senderName: message.senderName,
1767
+ };
1768
+ });
1769
+ const extraMessages = parsedMessages.slice(sharedPrefixLength);
1770
+ if (extraMessages.length === 0) return committedHydratedMessages;
1771
+
1772
+ const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
1773
+ committedMessages: [],
1774
+ scope: this.currentTurnScope,
1775
+ lastOutputAt: this.lastOutputAt,
1776
+ }).map((message, offset) => ({
1777
+ ...message,
1778
+ id: message.id || `msg_${sharedPrefixLength + offset}`,
1779
+ index: typeof message.index === 'number' ? message.index : sharedPrefixLength + offset,
1780
+ }));
1781
+ return [...committedHydratedMessages, ...extraHydratedMessages];
1782
+ }
1783
+
1784
+ private hydrateParsedMessagesForStatus(parsedMessages: any[]): any[] {
1785
+ return this.hydrateCommittedPrefixForParsedStatus(parsedMessages)
1786
+ || hydrateCliParsedMessages(parsedMessages, {
1787
+ committedMessages: this.committedMessages,
1788
+ scope: this.currentTurnScope,
1789
+ lastOutputAt: this.lastOutputAt,
1790
+ });
1791
+ }
1792
+
1793
+ private buildCommittedChatMessages(): any[] {
1794
+ return this.committedMessages.map((message, index) => {
1795
+ const contentValue = message.content;
1796
+ return buildChatMessage({
1797
+ role: message.role,
1798
+ content: typeof contentValue === 'string' ? contentValue : String(contentValue || ''),
1799
+ timestamp: message.timestamp,
1800
+ kind: message.kind,
1801
+ meta: message.meta,
1802
+ senderName: message.senderName,
1803
+ id: message.id || `msg_${index}`,
1804
+ index: typeof message.index === 'number' ? message.index : index,
1805
+ receivedAt: typeof message.receivedAt === 'number'
1806
+ ? message.receivedAt
1807
+ : message.timestamp,
1808
+ });
1809
+ });
1810
+ }
1811
+
1726
1812
  /**
1727
1813
  * Script-based full parse — returns ReadChatResult.
1728
1814
  * Called by command handler / dashboard for rich content rendering.
@@ -1765,7 +1851,7 @@ export class ProviderCliAdapter implements CliAdapter {
1765
1851
  this.onStatusChange?.();
1766
1852
  }
1767
1853
  }
1768
- if (parsed && Array.isArray(parsed.messages)) {
1854
+ if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
1769
1855
  const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
1770
1856
  committedMessages: this.committedMessages,
1771
1857
  scope: this.currentTurnScope,
@@ -1787,25 +1873,13 @@ export class ProviderCliAdapter implements CliAdapter {
1787
1873
  && this.currentStatus === 'idle';
1788
1874
  let result: any;
1789
1875
  if (parsed && Array.isArray(parsed.messages)) {
1790
- const parsedHydratedMessages = hydrateCliParsedMessages(parsed.messages, {
1791
- committedMessages: this.committedMessages,
1792
- scope: this.currentTurnScope,
1793
- lastOutputAt: this.lastOutputAt,
1794
- });
1795
- const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
1796
- ...message,
1797
- id: message.id || `msg_${index}`,
1798
- index: typeof message.index === 'number' ? message.index : index,
1799
- receivedAt: typeof message.receivedAt === 'number'
1800
- ? message.receivedAt
1801
- : message.timestamp,
1802
- }));
1876
+ const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
1803
1877
  const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === 'assistant' && typeof message.content === 'string' && message.content.trim());
1804
1878
  const shouldAdoptParsedIdleReplay =
1805
1879
  !this.currentTurnScope
1806
1880
  && !this.activeModal
1807
1881
  && !!parsedLastAssistant
1808
- && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, committedHydratedMessages)
1882
+ && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, this.committedMessages)
1809
1883
  && (
1810
1884
  this.currentStatus === 'idle'
1811
1885
  || (
@@ -1816,11 +1890,23 @@ export class ProviderCliAdapter implements CliAdapter {
1816
1890
  )
1817
1891
  );
1818
1892
  if (shouldAdoptParsedIdleReplay) {
1819
- this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
1820
- committedMessages: this.committedMessages,
1821
- scope: this.currentTurnScope,
1822
- lastOutputAt: this.lastOutputAt,
1823
- });
1893
+ this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length
1894
+ ? parsedHydratedMessages.map((message) => ({
1895
+ role: message.role,
1896
+ content: typeof message.content === 'string' ? message.content : String(message.content || ''),
1897
+ timestamp: message.timestamp,
1898
+ receivedAt: message.receivedAt,
1899
+ kind: message.kind,
1900
+ id: message.id,
1901
+ index: message.index,
1902
+ meta: message.meta,
1903
+ senderName: message.senderName,
1904
+ }))
1905
+ : normalizeCliParsedMessages(parsed.messages, {
1906
+ committedMessages: this.committedMessages,
1907
+ scope: this.currentTurnScope,
1908
+ lastOutputAt: this.lastOutputAt,
1909
+ });
1824
1910
  this.syncMessageViews();
1825
1911
  if (this.currentStatus !== 'idle' || this.isWaitingForResponse) {
1826
1912
  this.responseBuffer = '';
@@ -1835,25 +1921,15 @@ export class ProviderCliAdapter implements CliAdapter {
1835
1921
  this.onStatusChange?.();
1836
1922
  }
1837
1923
  }
1838
- const effectiveCommittedHydratedMessages = shouldAdoptParsedIdleReplay
1839
- ? this.committedMessages.map((message, index) => buildChatMessage({
1840
- ...message,
1841
- id: message.id || `msg_${index}`,
1842
- index: typeof message.index === 'number' ? message.index : index,
1843
- receivedAt: typeof message.receivedAt === 'number'
1844
- ? message.receivedAt
1845
- : message.timestamp,
1846
- }))
1847
- : committedHydratedMessages;
1848
1924
  const shouldPreferCommittedHistoryReplay =
1849
1925
  !this.currentTurnScope
1850
1926
  && !this.activeModal
1851
- && effectiveCommittedHydratedMessages.length > parsedHydratedMessages.length;
1927
+ && this.committedMessages.length > parsedHydratedMessages.length;
1852
1928
  const shouldPreferCommittedIdleReplay =
1853
1929
  shouldPreferCommittedMessages
1854
1930
  && !shouldAdoptParsedIdleReplay;
1855
1931
  const hydratedMessages = (shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay)
1856
- ? effectiveCommittedHydratedMessages
1932
+ ? this.buildCommittedChatMessages()
1857
1933
  : parsedHydratedMessages;
1858
1934
  result = {
1859
1935
  id: parsed.id || 'cli_session',