@adecore/agents-react 0.41.1 → 0.43.0

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 (34) hide show
  1. package/dist/chat/actions.js +4 -0
  2. package/dist/chat/logic/lightbox.d.ts +31 -0
  3. package/dist/chat/logic/lightbox.js +61 -0
  4. package/dist/chat/logic/timeline.d.ts +1 -0
  5. package/dist/chat/logic/timeline.js +3 -0
  6. package/dist/chat/ui/AnsiOutput.d.ts +3 -2
  7. package/dist/chat/ui/AnsiOutput.js +26 -22
  8. package/dist/chat/ui/ImageView.d.ts +3 -0
  9. package/dist/chat/ui/ImageView.js +761 -437
  10. package/dist/chat/ui/intelligent-ui/renderers/content.js +4 -2
  11. package/dist/chat/ui/rows/MessageRows.js +10 -8
  12. package/dist/chat/ui/rows/Rows.js +42 -39
  13. package/dist/chat/ui/rows/WorkRows.d.ts +4 -2
  14. package/dist/chat/ui/rows/WorkRows.js +580 -211
  15. package/dist/chat/ui/rows/WorkflowRow.js +43 -41
  16. package/dist/host.d.ts +1 -0
  17. package/dist/locales/en/agent-chat.d.ts +9 -0
  18. package/dist/locales/en/agent-chat.js +11 -2
  19. package/dist/locales/nl/agent-chat.d.ts +9 -0
  20. package/dist/locales/nl/agent-chat.js +11 -2
  21. package/package.json +8 -8
  22. package/src/chat/actions.ts +1 -0
  23. package/src/chat/logic/lightbox.ts +88 -0
  24. package/src/chat/logic/timeline.ts +13 -2
  25. package/src/chat/ui/AnsiOutput.tsx +13 -2
  26. package/src/chat/ui/ImageView.tsx +255 -63
  27. package/src/chat/ui/intelligent-ui/renderers/content.tsx +4 -2
  28. package/src/chat/ui/rows/MessageRows.tsx +10 -8
  29. package/src/chat/ui/rows/Rows.tsx +9 -1
  30. package/src/chat/ui/rows/WorkRows.tsx +127 -27
  31. package/src/chat/ui/rows/WorkflowRow.tsx +1 -1
  32. package/src/host.ts +2 -0
  33. package/src/locales/en/agent-chat.ts +11 -2
  34. package/src/locales/nl/agent-chat.ts +11 -2
@@ -418,7 +418,7 @@ function _temp2(part) {
418
418
  return part.count > 0;
419
419
  }
420
420
  export function WorkflowRow(t0) {
421
- const $ = _c(78);
421
+ const $ = _c(79);
422
422
  const {
423
423
  tool,
424
424
  workflow,
@@ -664,42 +664,44 @@ export function WorkflowRow(t0) {
664
664
  t26 = $[52];
665
665
  }
666
666
  let t27;
667
- if ($[53] !== open || $[54] !== opens || $[55] !== tool) {
667
+ if ($[53] !== chatId || $[54] !== open || $[55] !== opens || $[56] !== tool) {
668
668
  t27 = open && opens && /*#__PURE__*/_jsx(ToolBody, {
669
- tool: tool
669
+ tool: tool,
670
+ chatId: chatId
670
671
  });
671
- $[53] = open;
672
- $[54] = opens;
673
- $[55] = tool;
674
- $[56] = t27;
672
+ $[53] = chatId;
673
+ $[54] = open;
674
+ $[55] = opens;
675
+ $[56] = tool;
676
+ $[57] = t27;
675
677
  } else {
676
- t27 = $[56];
678
+ t27 = $[57];
677
679
  }
678
680
  const t28 = "mt-1.5 ml-6";
679
681
  let t29;
680
- if ($[57] !== workflow.name) {
682
+ if ($[58] !== workflow.name) {
681
683
  t29 = workflow.name !== null && /*#__PURE__*/_jsx("div", {
682
684
  className: "truncate text-sm font-medium text-text",
683
685
  children: workflow.name
684
686
  });
685
- $[57] = workflow.name;
686
- $[58] = t29;
687
+ $[58] = workflow.name;
688
+ $[59] = t29;
687
689
  } else {
688
- t29 = $[58];
690
+ t29 = $[59];
689
691
  }
690
692
  let t30;
691
- if ($[59] !== description) {
693
+ if ($[60] !== description) {
692
694
  t30 = description !== null && /*#__PURE__*/_jsx("p", {
693
695
  className: "mt-0.5 line-clamp-2 text-xs text-text-muted",
694
696
  children: description
695
697
  });
696
- $[59] = description;
697
- $[60] = t30;
698
+ $[60] = description;
699
+ $[61] = t30;
698
700
  } else {
699
- t30 = $[60];
701
+ t30 = $[61];
700
702
  }
701
703
  let t31;
702
- if ($[61] !== running || $[62] !== t || $[63] !== workflow.stalledAt) {
704
+ if ($[62] !== running || $[63] !== t || $[64] !== workflow.stalledAt) {
703
705
  t31 = running && workflow.stalledAt !== undefined && /*#__PURE__*/_jsxs("p", {
704
706
  role: "status",
705
707
  className: "mt-1 flex items-start gap-1.5 text-xs text-text-muted",
@@ -711,55 +713,55 @@ export function WorkflowRow(t0) {
711
713
  children: t("rows.workflow.stalled")
712
714
  })]
713
715
  });
714
- $[61] = running;
715
- $[62] = t;
716
- $[63] = workflow.stalledAt;
717
- $[64] = t31;
716
+ $[62] = running;
717
+ $[63] = t;
718
+ $[64] = workflow.stalledAt;
719
+ $[65] = t31;
718
720
  } else {
719
- t31 = $[64];
721
+ t31 = $[65];
720
722
  }
721
723
  let t32;
722
- if ($[65] !== onOpen || $[66] !== provider) {
724
+ if ($[66] !== onOpen || $[67] !== provider) {
723
725
  t32 = phase => /*#__PURE__*/_jsx(PhaseBlock, {
724
726
  phase: phase,
725
727
  provider: provider,
726
728
  onOpen: onOpen
727
729
  }, phase.key);
728
- $[65] = onOpen;
729
- $[66] = provider;
730
- $[67] = t32;
730
+ $[66] = onOpen;
731
+ $[67] = provider;
732
+ $[68] = t32;
731
733
  } else {
732
- t32 = $[67];
734
+ t32 = $[68];
733
735
  }
734
736
  const t33 = phases.map(t32);
735
737
  let t34;
736
- if ($[68] !== t29 || $[69] !== t30 || $[70] !== t31 || $[71] !== t33) {
738
+ if ($[69] !== t29 || $[70] !== t30 || $[71] !== t31 || $[72] !== t33) {
737
739
  t34 = /*#__PURE__*/_jsxs("div", {
738
740
  className: t28,
739
741
  children: [t29, t30, t31, t33]
740
742
  });
741
- $[68] = t29;
742
- $[69] = t30;
743
- $[70] = t31;
744
- $[71] = t33;
745
- $[72] = t34;
743
+ $[69] = t29;
744
+ $[70] = t30;
745
+ $[71] = t31;
746
+ $[72] = t33;
747
+ $[73] = t34;
746
748
  } else {
747
- t34 = $[72];
749
+ t34 = $[73];
748
750
  }
749
751
  let t35;
750
- if ($[73] !== t26 || $[74] !== t27 || $[75] !== t34 || $[76] !== tool.id) {
752
+ if ($[74] !== t26 || $[75] !== t27 || $[76] !== t34 || $[77] !== tool.id) {
751
753
  t35 = /*#__PURE__*/_jsxs("div", {
752
754
  "data-find-item": t22,
753
755
  className: t23,
754
756
  children: [t26, t27, t34]
755
757
  });
756
- $[73] = t26;
757
- $[74] = t27;
758
- $[75] = t34;
759
- $[76] = tool.id;
760
- $[77] = t35;
758
+ $[74] = t26;
759
+ $[75] = t27;
760
+ $[76] = t34;
761
+ $[77] = tool.id;
762
+ $[78] = t35;
761
763
  } else {
762
- t35 = $[77];
764
+ t35 = $[78];
763
765
  }
764
766
  return t35;
765
767
  }
package/dist/host.d.ts CHANGED
@@ -33,6 +33,7 @@ export interface ChatActions {
33
33
  configure(chatId: string, patch: Omit<ChatConfigurePayload, 'chatId'>): Promise<void>;
34
34
  continueOn(chatId: string, account: string): Promise<void>;
35
35
  turnDiff(chatId: string, turnId: string): Promise<ChatCheckpointDiff | null>;
36
+ toolOutput?(chatId: string, itemId: string): Promise<string | null>;
36
37
  stopSubagent(chatId: string, toolUseId: string): Promise<void>;
37
38
  stopTask(chatId: string, taskId: string): Promise<void>;
38
39
  goal?(chatId: string, action: ChatGoalAction): Promise<void>;
@@ -218,6 +218,12 @@ declare const _default: {
218
218
  heredoc: string;
219
219
  moreRuns_one: string;
220
220
  moreRuns_other: string;
221
+ showFullOutput: string;
222
+ showFullDiff: string;
223
+ wholeSize: string;
224
+ fullOutputFailed: string;
225
+ fullDiffFailed: string;
226
+ retry: string;
221
227
  };
222
228
  timeline: {
223
229
  welcome: {
@@ -537,6 +543,9 @@ declare const _default: {
537
543
  zoomIn: string;
538
544
  zoomOut: string;
539
545
  reset: string;
546
+ previous: string;
547
+ next: string;
548
+ position: string;
540
549
  };
541
550
  generatedImage: {
542
551
  label: string;
@@ -217,7 +217,13 @@ export default {
217
217
  alsoRan: '+ {{programs}}',
218
218
  heredoc: 'heredoc',
219
219
  moreRuns_one: '+{{count}}',
220
- moreRuns_other: '+{{count}}'
220
+ moreRuns_other: '+{{count}}',
221
+ showFullOutput: 'Show full output',
222
+ showFullDiff: 'Show full diff',
223
+ wholeSize: '{{size}} in total',
224
+ fullOutputFailed: 'Could not load the full output',
225
+ fullDiffFailed: 'Could not load the full diff',
226
+ retry: 'Try again'
221
227
  },
222
228
  timeline: {
223
229
  welcome: {
@@ -536,7 +542,10 @@ export default {
536
542
  image: {
537
543
  zoomIn: 'Zoom in',
538
544
  zoomOut: 'Zoom out',
539
- reset: 'Reset'
545
+ reset: 'Reset',
546
+ previous: 'Previous image',
547
+ next: 'Next image',
548
+ position: '{{index}} of {{count}}'
540
549
  },
541
550
  generatedImage: {
542
551
  label: 'Generated image',
@@ -218,6 +218,12 @@ declare const _default: {
218
218
  heredoc: string;
219
219
  moreRuns_one: string;
220
220
  moreRuns_other: string;
221
+ showFullOutput: string;
222
+ showFullDiff: string;
223
+ wholeSize: string;
224
+ fullOutputFailed: string;
225
+ fullDiffFailed: string;
226
+ retry: string;
221
227
  };
222
228
  timeline: {
223
229
  welcome: {
@@ -537,6 +543,9 @@ declare const _default: {
537
543
  zoomIn: string;
538
544
  zoomOut: string;
539
545
  reset: string;
546
+ previous: string;
547
+ next: string;
548
+ position: string;
540
549
  };
541
550
  generatedImage: {
542
551
  label: string;
@@ -217,7 +217,13 @@ export default {
217
217
  alsoRan: '+ {{programs}}',
218
218
  heredoc: 'heredoc',
219
219
  moreRuns_one: '+{{count}}',
220
- moreRuns_other: '+{{count}}'
220
+ moreRuns_other: '+{{count}}',
221
+ showFullOutput: 'Volledige uitvoer tonen',
222
+ showFullDiff: 'Volledige diff tonen',
223
+ wholeSize: '{{size}} in totaal',
224
+ fullOutputFailed: 'De volledige uitvoer kon niet worden geladen',
225
+ fullDiffFailed: 'De volledige diff kon niet worden geladen',
226
+ retry: 'Opnieuw proberen'
221
227
  },
222
228
  timeline: {
223
229
  welcome: {
@@ -536,7 +542,10 @@ export default {
536
542
  image: {
537
543
  zoomIn: 'Inzoomen',
538
544
  zoomOut: 'Uitzoomen',
539
- reset: 'Herstellen'
545
+ reset: 'Herstellen',
546
+ previous: 'Vorige afbeelding',
547
+ next: 'Volgende afbeelding',
548
+ position: '{{index}} van {{count}}'
540
549
  },
541
550
  generatedImage: {
542
551
  label: 'Gegenereerde afbeelding',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adecore/agents-react",
3
- "version": "0.41.1",
3
+ "version": "0.43.0",
4
4
  "description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -72,11 +72,11 @@
72
72
  "test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
73
73
  },
74
74
  "dependencies": {
75
- "@adecore/agent-contracts": "0.41.1",
76
- "@adecore/editor": "0.41.1",
77
- "@adecore/editor-react": "0.41.1",
78
- "@adecore/intelligent-ui": "0.41.1",
79
- "@adecore/merge": "0.41.1",
75
+ "@adecore/agent-contracts": "0.43.0",
76
+ "@adecore/editor": "0.43.0",
77
+ "@adecore/editor-react": "0.43.0",
78
+ "@adecore/intelligent-ui": "0.43.0",
79
+ "@adecore/merge": "0.43.0",
80
80
  "@codemirror/commands": "^6.11.1",
81
81
  "@codemirror/language": "^6.13.1",
82
82
  "@codemirror/state": "^6.7.6",
@@ -100,14 +100,14 @@
100
100
  "zustand": "^5.0.16"
101
101
  },
102
102
  "peerDependencies": {
103
- "@adecore/ui": "^0.41.1",
103
+ "@adecore/ui": "^0.43.0",
104
104
  "i18next": "^26.4.2",
105
105
  "react": "^19.3.0",
106
106
  "react-dom": "^19.3.0",
107
107
  "react-i18next": "^17.0.15"
108
108
  },
109
109
  "devDependencies": {
110
- "@adecore/ui": "0.41.1",
110
+ "@adecore/ui": "0.43.0",
111
111
  "@types/bun": "^1.4.4",
112
112
  "@types/react": "^19.3.0",
113
113
  "@types/react-dom": "^19.3.0",
@@ -33,6 +33,7 @@ export function transportActions(transport: ChatTransport): ChatActions {
33
33
  await transport.request('chat.continueOn', { chatId, account });
34
34
  },
35
35
  turnDiff: async (chatId, turnId) => (await transport.request('chat.turnDiff', { chatId, turnId })).diff,
36
+ toolOutput: async (chatId, itemId) => (await transport.request('chat.toolOutput', { chatId, itemId })).output,
36
37
  stopSubagent: async (chatId, toolUseId) => {
37
38
  await transport.request('chat.stopSubagent', { chatId, toolUseId });
38
39
  },
@@ -0,0 +1,88 @@
1
+ export const MIN_SCALE = 1;
2
+ export const MAX_SCALE = 8;
3
+ export const BUTTON_STEP = 1.5;
4
+
5
+ // A trackpad pinch arrives as small ctrl-wheel deltas; a mouse notch with Ctrl is clamped so it does not jump past the detail.
6
+ const PINCH_SPEED = 0.01;
7
+ const PINCH_LIMIT = 50;
8
+
9
+ export interface View {
10
+ readonly scale: number;
11
+ readonly x: number;
12
+ readonly y: number;
13
+ }
14
+
15
+ export const START: View = { scale: 1, x: 0, y: 0 };
16
+
17
+ export interface Size {
18
+ readonly width: number;
19
+ readonly height: number;
20
+ }
21
+
22
+ /* The picture at a scale of 1 and the stage it is centered in, both in layout pixels. */
23
+ export interface Bounds {
24
+ readonly image: Size;
25
+ readonly frame: Size;
26
+ }
27
+
28
+ export interface Point {
29
+ readonly x: number;
30
+ readonly y: number;
31
+ }
32
+
33
+ export interface Wheel {
34
+ readonly deltaX: number;
35
+ readonly deltaY: number;
36
+ readonly ctrlKey: boolean;
37
+ }
38
+
39
+ /* Keeps an edge of the picture from leaving its side of the stage, so a flick of two fingers never loses it. */
40
+ export function clamped(view: View, bounds: Bounds): View {
41
+ const maxX = Math.max(0, (bounds.image.width * view.scale - bounds.frame.width) / 2);
42
+ const maxY = Math.max(0, (bounds.image.height * view.scale - bounds.frame.height) / 2);
43
+
44
+ return { scale: view.scale, x: Math.min(maxX, Math.max(-maxX, view.x)), y: Math.min(maxY, Math.max(-maxY, view.y)) };
45
+ }
46
+
47
+ /*
48
+ * Zooms around a point, which is what makes a pinch over a detail feel like a magnifier instead of
49
+ * a slider. The pixel under the fingers stays where it is while everything else moves away from it.
50
+ * `x` and `y` are offsets from the middle of the stage, so a scale of 1 is always centered.
51
+ */
52
+ export function zoomed(view: View, factor: number, point: Point, bounds: Bounds): View {
53
+ const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, view.scale * factor));
54
+
55
+ if (scale === MIN_SCALE) {
56
+ return START;
57
+ }
58
+
59
+ const ratio = scale / view.scale;
60
+
61
+ return clamped({ scale, x: point.x - (point.x - view.x) * ratio, y: point.y - (point.y - view.y) * ratio }, bounds);
62
+ }
63
+
64
+ export function panned(view: View, deltaX: number, deltaY: number, bounds: Bounds): View {
65
+ if (view.scale <= MIN_SCALE) {
66
+ return view;
67
+ }
68
+
69
+ return clamped({ scale: view.scale, x: view.x + deltaX, y: view.y + deltaY }, bounds);
70
+ }
71
+
72
+ /* A pinch zooms (Chromium reports it as a wheel with Ctrl held) and two fingers pan the zoomed picture. */
73
+ export function wheeled(view: View, wheel: Wheel, point: Point, bounds: Bounds): View {
74
+ if (wheel.ctrlKey) {
75
+ const delta = Math.min(PINCH_LIMIT, Math.max(-PINCH_LIMIT, wheel.deltaY));
76
+
77
+ return zoomed(view, Math.exp(-delta * PINCH_SPEED), point, bounds);
78
+ }
79
+
80
+ return panned(view, -wheel.deltaX, -wheel.deltaY, bounds);
81
+ }
82
+
83
+ /* The image a step away, or null at either end: the row does not wrap around. */
84
+ export function stepped(index: number, count: number, step: -1 | 1): number | null {
85
+ const next = index + step;
86
+
87
+ return next < 0 || next >= count ? null : next;
88
+ }
@@ -56,7 +56,17 @@ export type TimelineRow =
56
56
  | { kind: 'question'; id: string; item: ChatQuestionItem }
57
57
  | { kind: 'note'; id: string; level: 'info' | 'warning' | 'error'; text: string; from?: string }
58
58
  | { kind: 'compaction'; id: string; preTokens: number | null }
59
- | { kind: 'changed-files'; id: string; turnId: string; tools: ChatToolItem[]; diff: ChatCheckpointDiff | null; checkpoint: boolean; baseMoved?: BaseMoved }
59
+ | {
60
+ kind: 'changed-files';
61
+ id: string;
62
+ turnId: string;
63
+ tools: ChatToolItem[];
64
+ diff: ChatCheckpointDiff | null;
65
+ checkpoint: boolean;
66
+ baseMoved?: BaseMoved;
67
+ // Set when `diff` holds back the diffs past its first few, which the host answers whole.
68
+ heldBack?: boolean;
69
+ }
60
70
  | { kind: 'turn-fold'; id: string; turn: ChatTurnItem; label: string; work: string[]; hiddenCount: number; expanded: boolean }
61
71
  | { kind: 'forks'; id: string; turnId: string }
62
72
  | { kind: 'working'; id: string; startedAt: number }
@@ -481,7 +491,8 @@ function changedFilesRow(turn: ChatTurnItem, items: ChatItem[]): TimelineRow | n
481
491
  tools: edits,
482
492
  diff,
483
493
  checkpoint: turn.checkpoint !== undefined,
484
- ...(moved ? { baseMoved: { from: turn.checkpointHead!, to: turn.checkpointHeadAfter! } } : {})
494
+ ...(moved ? { baseMoved: { from: turn.checkpointHead!, to: turn.checkpointHeadAfter! } } : {}),
495
+ ...(turn.checkpointDiffRef ? { heldBack: true } : {})
485
496
  };
486
497
  }
487
498
 
@@ -1,7 +1,18 @@
1
1
  import { useTranslation } from 'react-i18next';
2
2
  import { parseAnsi } from '../logic/ansi';
3
3
 
4
- export function AnsiOutput({ text, limit, tailLines }: { text: string; limit?: number; tailLines?: number }) {
4
+ /* `marksOmitted` off leaves out the count of what the limit cut, for a text that is itself only a beginning. */
5
+ export function AnsiOutput({
6
+ text,
7
+ limit,
8
+ tailLines,
9
+ marksOmitted = true
10
+ }: {
11
+ text: string;
12
+ limit?: number | undefined;
13
+ tailLines?: number;
14
+ marksOmitted?: boolean;
15
+ }) {
5
16
  const { t } = useTranslation('agent-chat');
6
17
  const { tokens, omitted } = parseAnsi(text, { limit, tailLines });
7
18
 
@@ -12,7 +23,7 @@ export function AnsiOutput({ text, limit, tailLines }: { text: string; limit?: n
12
23
  {token.content}
13
24
  </span>
14
25
  ))}
15
- {omitted > 0 && `\n${t('work.moreCharacters', { count: omitted })}`}
26
+ {marksOmitted && omitted > 0 && `\n${t('work.moreCharacters', { count: omitted })}`}
16
27
  </>
17
28
  );
18
29
  }