@cueloop/client 0.1.0-alpha.5 → 0.1.0-alpha.51

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 (152) hide show
  1. package/native/build-pty.sh +51 -0
  2. package/native/build.sh +82 -0
  3. package/native/darwin-arm64/libcuelooppty.dylib +0 -0
  4. package/native/darwin-arm64/libcueloopvt.dylib +0 -0
  5. package/native/src/pty.zig +193 -0
  6. package/native/src/shim.zig +114 -0
  7. package/package.json +36 -31
  8. package/src/App.autoclose.test.tsx +137 -0
  9. package/src/App.diff.test.tsx +158 -22
  10. package/src/App.export.test.tsx +44 -37
  11. package/src/App.plan-review.test.tsx +672 -0
  12. package/src/App.prototype.test.tsx +155 -0
  13. package/src/App.readonly.test.tsx +60 -36
  14. package/src/App.rendering.test.tsx +132 -0
  15. package/src/App.review-panel.test.tsx +136 -0
  16. package/src/App.submit-confirm.test.tsx +218 -0
  17. package/src/App.test.tsx +128 -69
  18. package/src/App.toast.test.tsx +75 -0
  19. package/src/App.tsx +0 -0
  20. package/src/App.walk.test.tsx +289 -0
  21. package/src/__snapshots__/view-plan.regression.test.ts.snap +100 -0
  22. package/src/attribution.test.ts +31 -0
  23. package/src/attribution.ts +38 -0
  24. package/src/clipboard.test.ts +23 -0
  25. package/src/clipboard.ts +30 -0
  26. package/src/components/AnnotationCard.compose-rows.test.ts +49 -0
  27. package/src/components/AnnotationCard.stories.tsx +94 -0
  28. package/src/components/AnnotationCard.tsx +241 -0
  29. package/src/components/Breadcrumb.stories.tsx +19 -0
  30. package/src/components/Breadcrumb.tsx +44 -0
  31. package/src/components/CodeBlock.stories.tsx +42 -0
  32. package/src/components/CodeBlock.tsx +83 -0
  33. package/src/components/CompletionOverlay.stories.tsx +23 -0
  34. package/src/components/CompletionOverlay.tsx +59 -0
  35. package/src/components/ConfirmCard.stories.tsx +35 -0
  36. package/src/components/ConfirmCard.tsx +127 -0
  37. package/src/components/ConfirmDialog.stories.tsx +21 -0
  38. package/src/components/ConfirmDialog.tsx +64 -0
  39. package/src/components/DiffSheet.scroll.test.tsx +123 -0
  40. package/src/components/DiffSheet.stories.tsx +78 -0
  41. package/src/components/DiffSheet.syntax.test.tsx +62 -0
  42. package/src/components/DiffSheet.tsx +355 -0
  43. package/src/components/InboxList.stories.tsx +31 -0
  44. package/src/components/InboxList.tsx +62 -0
  45. package/src/components/KeybindsDialog.stories.tsx +31 -0
  46. package/src/components/KeybindsDialog.tsx +58 -0
  47. package/src/components/MarkerPopover.stories.tsx +58 -0
  48. package/src/components/MarkerPopover.tsx +108 -0
  49. package/src/components/MenuBar.stories.tsx +37 -0
  50. package/src/components/MenuBar.tsx +74 -0
  51. package/src/components/PlanSheet.stories.tsx +113 -0
  52. package/src/components/PlanSheet.tsx +456 -0
  53. package/src/components/PromptDialog.stories.tsx +36 -0
  54. package/src/components/PromptDialog.tsx +78 -0
  55. package/src/components/PrototypeSheet.stories.tsx +20 -0
  56. package/src/components/PrototypeSheet.tsx +358 -0
  57. package/src/components/ReviewPanel.stories.tsx +86 -0
  58. package/src/components/ReviewPanel.tsx +101 -0
  59. package/src/components/ReviewRail.stories.tsx +218 -0
  60. package/src/components/ReviewRail.tsx +317 -0
  61. package/src/components/SettingsDialog.stories.tsx +111 -0
  62. package/src/components/SettingsDialog.tsx +141 -0
  63. package/src/components/SettingsRows.stories.tsx +18 -0
  64. package/src/components/SettingsRows.tsx +108 -0
  65. package/src/components/Toast.stories.tsx +12 -0
  66. package/src/components/Toast.tsx +44 -0
  67. package/src/components/WalkWizard.stories.tsx +100 -0
  68. package/src/components/WalkWizard.tsx +152 -0
  69. package/src/components/__snapshots__/stories.test.tsx.snap +1857 -0
  70. package/src/components/agent-launcher.stories.tsx +26 -0
  71. package/src/components/agent-launcher.test.tsx +49 -0
  72. package/src/components/agent-launcher.tsx +147 -0
  73. package/src/components/diff-sheet-layout.test.ts +127 -0
  74. package/src/components/diff-sheet-layout.ts +167 -0
  75. package/src/components/primitives/Button.stories.tsx +32 -0
  76. package/src/components/primitives/Button.tsx +51 -0
  77. package/src/components/primitives/Card.stories.tsx +25 -0
  78. package/src/components/primitives/Card.tsx +59 -0
  79. package/src/components/primitives/Dialog.stories.tsx +24 -0
  80. package/src/components/primitives/Dialog.tsx +64 -0
  81. package/src/components/primitives/StatusBar.stories.tsx +11 -0
  82. package/src/components/primitives/StatusBar.tsx +22 -0
  83. package/src/components/primitives/Tabs.stories.tsx +29 -0
  84. package/src/components/primitives/Tabs.tsx +98 -0
  85. package/src/components/primitives/Toolbar.stories.tsx +17 -0
  86. package/src/components/primitives/Toolbar.tsx +14 -0
  87. package/src/components/primitives/frame.test.ts +12 -0
  88. package/src/components/primitives/frame.ts +14 -0
  89. package/src/components/quick-actions-editor.stories.tsx +54 -0
  90. package/src/components/quick-actions-editor.tsx +136 -0
  91. package/src/components/stories-app.tsx +123 -0
  92. package/src/components/stories.test.tsx +62 -0
  93. package/src/components/story-fixtures.ts +98 -0
  94. package/src/components/story.ts +69 -0
  95. package/src/components/syntax-highlight.ts +92 -0
  96. package/src/components/terminal-pane.test.tsx +40 -0
  97. package/src/components/terminal-pane.ts +181 -0
  98. package/src/components/theme-context.stories.tsx +46 -0
  99. package/src/components/theme-context.tsx +36 -0
  100. package/src/components/truncate-text.ts +6 -0
  101. package/src/config.test.ts +430 -31
  102. package/src/config.ts +304 -26
  103. package/src/diff-hunk-curate.test.ts +315 -0
  104. package/src/diff-hunk-curate.ts +233 -0
  105. package/src/diff-intraline.test.ts +164 -0
  106. package/src/diff-intraline.ts +132 -0
  107. package/src/diff-syntax.test.ts +96 -0
  108. package/src/diff-syntax.ts +154 -0
  109. package/src/editor.test.ts +143 -0
  110. package/src/editor.ts +123 -9
  111. package/src/ghostty-terminal.test.ts +82 -0
  112. package/src/ghostty-terminal.ts +168 -0
  113. package/src/herdr.test.ts +41 -0
  114. package/src/herdr.ts +27 -0
  115. package/src/index.ts +10 -0
  116. package/src/integrations.test.ts +41 -0
  117. package/src/integrations.ts +30 -0
  118. package/src/intent-dispatch.test.ts +493 -0
  119. package/src/intent-dispatch.ts +428 -0
  120. package/src/key-bindings.test.ts +152 -0
  121. package/src/key-bindings.ts +430 -0
  122. package/src/keymap.test.ts +622 -0
  123. package/src/keymap.ts +339 -0
  124. package/src/kitty-image.test.ts +20 -0
  125. package/src/kitty-image.ts +75 -0
  126. package/src/prototype-browser.test.ts +55 -0
  127. package/src/prototype-browser.ts +243 -0
  128. package/src/pty.test.ts +78 -0
  129. package/src/pty.ts +222 -0
  130. package/src/review-panel.test.ts +113 -0
  131. package/src/review-panel.ts +83 -0
  132. package/src/run.ts +9 -5
  133. package/src/serve.test.ts +24 -9
  134. package/src/serve.ts +7 -7
  135. package/src/session-controller.curate.test.ts +253 -0
  136. package/src/session-controller.share.test.ts +309 -0
  137. package/src/session-controller.ts +914 -0
  138. package/src/share.ts +113 -0
  139. package/src/test-support.test.ts +55 -0
  140. package/src/test-support.ts +187 -0
  141. package/src/theme-presets.ts +168 -0
  142. package/src/theme.ts +38 -17
  143. package/src/version.ts +5 -0
  144. package/src/view-diff.test.ts +19 -8
  145. package/src/view-diff.ts +34 -23
  146. package/src/view-plan.regression.test.ts +60 -0
  147. package/src/view-plan.test.ts +399 -0
  148. package/src/view-plan.ts +495 -0
  149. package/src/walk.test.ts +121 -0
  150. package/src/walk.ts +70 -0
  151. package/src/view.test.ts +0 -157
  152. package/src/view.ts +0 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * The marker-actions popover: the visible form of plan span mode, floated as a
3
+ * bordered card above the marked block. The toolbar card is always shown -
4
+ * `comment · cut · actions · [x]`, each label keyboard-shortcut-backed and
5
+ * clickable. Pressing `actions` drops a second card below it listing the
6
+ * quick-actions; picking one inserts its preset comment. Plan-only: the diff
7
+ * review has no span.
8
+ */
9
+
10
+ import React from "react";
11
+ import type { MouseEvent } from "@opentui/core";
12
+ import type { Theme } from "../theme";
13
+ import type { QuickAction } from "../config";
14
+ import { useComponentTheme } from "./theme-context";
15
+ import { cardHeight } from "./primitives/Card";
16
+ import { FRAME_BORDER_STYLE } from "./primitives/frame";
17
+
18
+ export interface MarkerPopoverProps {
19
+ /** "toolbar" is the bar alone; "actions" also drops the quick-actions card. */
20
+ view: "toolbar" | "actions";
21
+ actions: QuickAction[];
22
+ /** Highlighted action in the dropdown (accent); ignored in toolbar view. */
23
+ actionIndex: number;
24
+ /** Show the cut affordance: owner-only, like every other plan-edit control. */
25
+ canCut: boolean;
26
+ onComment: () => void;
27
+ onCut: () => void;
28
+ onOpenActions: () => void;
29
+ onClose: () => void;
30
+ onPickAction: (index: number) => void;
31
+ onBack: () => void;
32
+ theme?: Theme;
33
+ }
34
+
35
+ export function MarkerPopover({
36
+ view,
37
+ actions,
38
+ actionIndex,
39
+ canCut,
40
+ onComment,
41
+ onCut,
42
+ onOpenActions,
43
+ onClose,
44
+ onPickAction,
45
+ onBack,
46
+ theme,
47
+ }: MarkerPopoverProps): React.ReactNode {
48
+ const tokens = useComponentTheme(theme);
49
+ const cardStyle = {
50
+ border: true,
51
+ borderStyle: FRAME_BORDER_STYLE,
52
+ borderColor: tokens.border,
53
+ backgroundColor: tokens.elevated,
54
+ flexDirection: "column" as const,
55
+ paddingLeft: 1,
56
+ paddingRight: 1,
57
+ };
58
+ const open = view === "actions";
59
+ return (
60
+ <box
61
+ style={{ flexDirection: "column", alignItems: "flex-start" }}
62
+ // a release on the popover is the popover's own click; it must never
63
+ // bubble to the sheet's selection-release fallback and re-enter span mode
64
+ onMouseUp={(event: MouseEvent) => event.stopPropagation()}
65
+ >
66
+ <box style={{ ...cardStyle, height: cardHeight(1) }}>
67
+ <box style={{ flexDirection: "row" }}>
68
+ <text fg={tokens.accent} onMouseUp={onComment}>
69
+ comment
70
+ </text>
71
+ <text fg={tokens.textDim}> · </text>
72
+ {canCut ? (
73
+ <>
74
+ <text fg={tokens.red} onMouseUp={onCut}>
75
+ cut
76
+ </text>
77
+ <text fg={tokens.textDim}> · </text>
78
+ </>
79
+ ) : null}
80
+ <text fg={open ? tokens.accent : tokens.textMuted} onMouseUp={onOpenActions}>
81
+ actions
82
+ </text>
83
+ <text fg={tokens.textDim}> · </text>
84
+ <text fg={tokens.textDim} onMouseUp={onClose}>
85
+ [x]
86
+ </text>
87
+ </box>
88
+ </box>
89
+ {open ? (
90
+ <box style={{ ...cardStyle, height: cardHeight(actions.length + 1) }}>
91
+ {actions.map((action, index) => (
92
+ <text
93
+ key={index}
94
+ fg={index === actionIndex ? tokens.accent : tokens.textMuted}
95
+ onMouseUp={() => onPickAction(index)}
96
+ >
97
+ {index === actionIndex ? "› " : " "}
98
+ {action.prompt}
99
+ </text>
100
+ ))}
101
+ <text fg={tokens.textDim} onMouseUp={onBack}>
102
+ {" "}‹ back
103
+ </text>
104
+ </box>
105
+ ) : null}
106
+ </box>
107
+ );
108
+ }
@@ -0,0 +1,37 @@
1
+ import React from "react";
2
+ import { DARK } from "../theme";
3
+ import type { Story, StoryMeta } from "./story";
4
+ import { MenuBar } from "./MenuBar";
5
+
6
+ export const meta: StoryMeta = { title: "MenuBar" };
7
+
8
+ const callbacks = { onToggle: () => {}, onSettings: () => {}, onKeybinds: () => {} };
9
+
10
+ function BottomFrame({ children }: { children: React.ReactNode }): React.ReactNode {
11
+ return (
12
+ <box
13
+ style={{ flexDirection: "column", width: "100%", height: "100%", justifyContent: "flex-end" }}
14
+ >
15
+ {children}
16
+ </box>
17
+ );
18
+ }
19
+
20
+ export const Closed: Story = {
21
+ render: () => (
22
+ <BottomFrame>
23
+ <MenuBar open={false} version="0.1.0-alpha.32" {...callbacks} />
24
+ </BottomFrame>
25
+ ),
26
+ size: { width: 60, height: 8 },
27
+ };
28
+
29
+ export const Open: Story = {
30
+ render: () => (
31
+ <BottomFrame>
32
+ <MenuBar open version="0.1.0-alpha.32" {...callbacks} />
33
+ </BottomFrame>
34
+ ),
35
+ expectedColors: [DARK.text],
36
+ size: { width: 60, height: 8 },
37
+ };
@@ -0,0 +1,74 @@
1
+ import React from "react";
2
+ import { useTerminalDimensions } from "@opentui/react";
3
+ import type { Theme } from "../theme";
4
+ import { useComponentTheme } from "./theme-context";
5
+ import { FRAME_BORDER_STYLE } from "./primitives/frame";
6
+
7
+ export interface MenuBarProps {
8
+ open: boolean;
9
+ version: string;
10
+ /** The transient status line, shown between the menu and the version. */
11
+ status?: string;
12
+ onToggle: () => void;
13
+ onSettings: () => void;
14
+ onKeybinds: () => void;
15
+ theme?: Theme;
16
+ }
17
+
18
+ const DROPUP_OPTION_ROWS = 2;
19
+
20
+ export function MenuBar({
21
+ open,
22
+ version,
23
+ status,
24
+ onToggle,
25
+ onSettings,
26
+ onKeybinds,
27
+ theme,
28
+ }: MenuBarProps): React.ReactNode {
29
+ const tokens = useComponentTheme(theme);
30
+ const { height: terminalHeight } = useTerminalDimensions();
31
+ const dropupHeight = DROPUP_OPTION_ROWS + 2;
32
+ return (
33
+ <>
34
+ {open ? (
35
+ <box
36
+ style={{
37
+ position: "absolute",
38
+ left: 1,
39
+ top: Math.max(0, terminalHeight - 1 - dropupHeight),
40
+ width: 16,
41
+ height: dropupHeight,
42
+ border: true,
43
+ borderStyle: FRAME_BORDER_STYLE,
44
+ borderColor: tokens.text,
45
+ flexDirection: "column",
46
+ }}
47
+ >
48
+ <box onMouseUp={onSettings}>
49
+ <text fg={tokens.text}> Settings</text>
50
+ </box>
51
+ <box onMouseUp={onKeybinds}>
52
+ <text fg={tokens.text}> Keybinds</text>
53
+ </box>
54
+ </box>
55
+ ) : null}
56
+ <box
57
+ style={{
58
+ flexDirection: "row",
59
+ height: 1,
60
+ backgroundColor: tokens.panel,
61
+ paddingLeft: 1,
62
+ paddingRight: 1,
63
+ }}
64
+ >
65
+ <box onMouseUp={onToggle}>
66
+ <text fg={tokens.textDim}>menu</text>
67
+ </box>
68
+ {status ? <text fg={tokens.accent}>{` ${status}`}</text> : null}
69
+ <box style={{ flexGrow: 1 }} />
70
+ <text fg={tokens.textDim}>v{version}</text>
71
+ </box>
72
+ </>
73
+ );
74
+ }
@@ -0,0 +1,113 @@
1
+ import React from "react";
2
+ import { DARK } from "../theme";
3
+ import type { Story, StoryMeta } from "./story";
4
+ import { buildDisplay } from "../view-plan";
5
+ import { PlanSheet } from "./PlanSheet";
6
+ import { FIXTURE_PLAN, fixtureDisplay, fixtureMarks, fixturePlanSession } from "./story-fixtures";
7
+
8
+ export const meta: StoryMeta = { title: "PlanSheet" };
9
+
10
+ const callbacks = { onLineActivate: () => {} };
11
+
12
+ // a working copy with the context paragraph cut, so it renders as a del block
13
+ const CUT_WORKING = FIXTURE_PLAN.replace("The daemon persists sessions to disk atomically.\n", "");
14
+
15
+ export const AnnotatedPlan: Story = {
16
+ render: () => (
17
+ <PlanSheet
18
+ session={fixturePlanSession()}
19
+ display={fixtureDisplay()}
20
+ marks={fixtureMarks()}
21
+ cursor={2}
22
+ activeSpan={null}
23
+ compose={null}
24
+ popover={null}
25
+ editOrphanCount={0}
26
+ {...callbacks}
27
+ />
28
+ ),
29
+ expectedColors: [DARK.markCommentBackground, DARK.cursorBackground],
30
+ size: { width: 90, height: 28 },
31
+ };
32
+
33
+ export const SpanSelection: Story = {
34
+ render: () => (
35
+ <PlanSheet
36
+ session={fixturePlanSession({ annotations: [] })}
37
+ display={fixtureDisplay()}
38
+ marks={new Map()}
39
+ cursor={2}
40
+ activeSpan={{ displayIndex: 2, start: 0, end: 10 }}
41
+ compose={null}
42
+ popover={null}
43
+ editOrphanCount={0}
44
+ {...callbacks}
45
+ />
46
+ ),
47
+ expectedColors: [DARK.accent],
48
+ size: { width: 90, height: 28 },
49
+ };
50
+
51
+ export const InlineCompose: Story = {
52
+ render: () => (
53
+ <PlanSheet
54
+ session={fixturePlanSession({ annotations: [] })}
55
+ display={fixtureDisplay()}
56
+ marks={new Map()}
57
+ cursor={2}
58
+ activeSpan={{ displayIndex: 2, start: 0, end: 10 }}
59
+ compose={{
60
+ kind: "comment",
61
+ displayIndex: 2,
62
+ quote: "The daemon",
63
+ draft: { text: "Which daemon?", onInput: () => {}, onSave: () => {}, onCancel: () => {} },
64
+ }}
65
+ popover={null}
66
+ editOrphanCount={0}
67
+ {...callbacks}
68
+ />
69
+ ),
70
+ size: { width: 90, height: 30 },
71
+ };
72
+
73
+ /** Span mode shows the marker-actions toolbar inline below the marked block. */
74
+ // The marker popover floats as an absolute overlay; the virtual terminal used
75
+ // for story snapshots cannot composite it, so it is covered by the standalone
76
+ // MarkerPopover stories and a functional App test rather than a PlanSheet snapshot.
77
+
78
+ /** A cut block renders struck-through and grayed inline - no red, no [cut] tag. */
79
+ export const WithCutBlock: Story = {
80
+ render: () => (
81
+ <PlanSheet
82
+ session={fixturePlanSession()}
83
+ display={buildDisplay(FIXTURE_PLAN, CUT_WORKING)}
84
+ marks={new Map()}
85
+ cursor={0}
86
+ activeSpan={null}
87
+ compose={null}
88
+ popover={null}
89
+ editOrphanCount={0}
90
+ {...callbacks}
91
+ />
92
+ ),
93
+ expectedColors: [DARK.textDim],
94
+ size: { width: 90, height: 28 },
95
+ };
96
+
97
+ export const OrphanBanner: Story = {
98
+ render: () => (
99
+ <PlanSheet
100
+ session={fixturePlanSession()}
101
+ display={fixtureDisplay()}
102
+ marks={new Map()}
103
+ cursor={0}
104
+ activeSpan={null}
105
+ compose={null}
106
+ popover={null}
107
+ editOrphanCount={1}
108
+ {...callbacks}
109
+ />
110
+ ),
111
+ expectedColors: [DARK.red],
112
+ size: { width: 90, height: 28 },
113
+ };