@marimo-team/islands 0.23.7-dev42 → 0.23.7-dev44
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.
- package/dist/{code-visibility-CTdccsPx.js → code-visibility-DdsQjrbj.js} +1 -1
- package/dist/main.js +2 -2
- package/dist/{reveal-component-BpKkH57S.js → reveal-component-VQUwqDAL.js} +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/editor/actions/pair-with-agent-modal.tsx +140 -49
package/package.json
CHANGED
|
@@ -18,14 +18,16 @@ import { assertNever } from "@/utils/assertNever";
|
|
|
18
18
|
import { asRemoteURL, useRuntimeManager } from "@/core/runtime/config";
|
|
19
19
|
import { API } from "@/core/network/api";
|
|
20
20
|
|
|
21
|
-
type AgentTab = "claude" | "codex" | "opencode";
|
|
21
|
+
type AgentTab = "claude" | "codex" | "opencode" | "prompt";
|
|
22
|
+
|
|
23
|
+
const TERMINAL_TABS = ["claude", "codex", "opencode"] as const;
|
|
22
24
|
|
|
23
25
|
function getMarimoCommand(): string {
|
|
24
26
|
return import.meta.env.DEV ? "uv run marimo" : "uvx marimo@latest";
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
function
|
|
28
|
-
agent: AgentTab,
|
|
29
|
+
function getTerminalCommand(
|
|
30
|
+
agent: Exclude<AgentTab, "prompt">,
|
|
29
31
|
url: string,
|
|
30
32
|
withToken: boolean,
|
|
31
33
|
): string {
|
|
@@ -43,6 +45,21 @@ function getPromptCommand(
|
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
function getRawPrompt(url: string, token: string | null): string {
|
|
49
|
+
const tokenHint = token
|
|
50
|
+
? `\n\nUse this auth token when calling \`execute-code.sh\`: \`execute-code.sh --url '${url}' --token '${token}'\`.`
|
|
51
|
+
: "";
|
|
52
|
+
return [
|
|
53
|
+
"Use the /marimo-pair skill to pair-program on a running marimo notebook.",
|
|
54
|
+
"",
|
|
55
|
+
`Connect to the notebook at: ${url}`,
|
|
56
|
+
"",
|
|
57
|
+
`Use \`execute-code.sh --url ${url}\` from the marimo-pair skill to execute code in the notebook.${tokenHint}`,
|
|
58
|
+
"",
|
|
59
|
+
"Once you are connected, send a fun toast (mo.status.toast(...)) to the user inside marimo letting them know you're ready to pair.",
|
|
60
|
+
].join("\n");
|
|
61
|
+
}
|
|
62
|
+
|
|
46
63
|
function maskToken(token: string): string {
|
|
47
64
|
if (token.length <= 4) {
|
|
48
65
|
return "****";
|
|
@@ -52,6 +69,13 @@ function maskToken(token: string): string {
|
|
|
52
69
|
|
|
53
70
|
const SKILL_INSTALL = "npx skills add marimo-team/marimo-pair";
|
|
54
71
|
|
|
72
|
+
const AGENT_LABELS: Record<AgentTab, string> = {
|
|
73
|
+
claude: "Claude",
|
|
74
|
+
codex: "Codex",
|
|
75
|
+
opencode: "OpenCode",
|
|
76
|
+
prompt: "Prompt",
|
|
77
|
+
};
|
|
78
|
+
|
|
55
79
|
function useAuthToken(): string | null {
|
|
56
80
|
const [token, setToken] = useState<string | null>(null);
|
|
57
81
|
useEffect(() => {
|
|
@@ -75,10 +99,9 @@ export const PairWithAgentModal: React.FC<{
|
|
|
75
99
|
const authToken = useAuthToken();
|
|
76
100
|
const hasToken = Boolean(authToken);
|
|
77
101
|
const remoteUrl = runtimeManager.httpURL.toString();
|
|
78
|
-
const promptCommand = getPromptCommand(activeTab, remoteUrl, hasToken);
|
|
79
102
|
|
|
80
103
|
return (
|
|
81
|
-
<DialogContent className="sm:max-w-
|
|
104
|
+
<DialogContent className="sm:max-w-2xl">
|
|
82
105
|
<DialogHeader>
|
|
83
106
|
<DialogTitle>Pair with an agent</DialogTitle>
|
|
84
107
|
<DialogDescription>
|
|
@@ -96,49 +119,75 @@ export const PairWithAgentModal: React.FC<{
|
|
|
96
119
|
</DialogHeader>
|
|
97
120
|
|
|
98
121
|
<div className="flex flex-col gap-4 py-2">
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
value={activeTab}
|
|
108
|
-
onValueChange={(v) => setActiveTab(v as AgentTab)}
|
|
109
|
-
>
|
|
110
|
-
<TabsList className="w-full">
|
|
111
|
-
<TabsTrigger value="claude" className="flex-1">
|
|
112
|
-
Claude
|
|
113
|
-
</TabsTrigger>
|
|
114
|
-
<TabsTrigger value="codex" className="flex-1">
|
|
115
|
-
Codex
|
|
122
|
+
<Tabs
|
|
123
|
+
value={activeTab}
|
|
124
|
+
onValueChange={(v) => setActiveTab(v as AgentTab)}
|
|
125
|
+
>
|
|
126
|
+
<TabsList className="w-full">
|
|
127
|
+
{(["claude", "codex", "opencode", "prompt"] as const).map((tab) => (
|
|
128
|
+
<TabsTrigger key={tab} value={tab} className="flex-1">
|
|
129
|
+
{AGENT_LABELS[tab]}
|
|
116
130
|
</TabsTrigger>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
</TabsTrigger>
|
|
120
|
-
</TabsList>
|
|
131
|
+
))}
|
|
132
|
+
</TabsList>
|
|
121
133
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
134
|
+
{TERMINAL_TABS.map((tab) => (
|
|
135
|
+
<TabsContent
|
|
136
|
+
key={tab}
|
|
137
|
+
value={tab}
|
|
138
|
+
className="mt-4 flex flex-col gap-4"
|
|
139
|
+
>
|
|
140
|
+
<Step
|
|
141
|
+
index={1}
|
|
142
|
+
title="Install the skill"
|
|
143
|
+
hint="Run once per machine."
|
|
144
|
+
>
|
|
145
|
+
<CommandBlock command={SKILL_INSTALL} />
|
|
146
|
+
</Step>
|
|
147
|
+
<Step index={2} title="Run in your terminal">
|
|
148
|
+
<CommandBlock
|
|
149
|
+
command={getTerminalCommand(tab, remoteUrl, hasToken)}
|
|
150
|
+
/>
|
|
151
|
+
</Step>
|
|
152
|
+
{hasToken && authToken && (
|
|
153
|
+
<Step index={3} title="Paste when prompted for a token">
|
|
154
|
+
<CommandBlock
|
|
155
|
+
command={authToken}
|
|
156
|
+
display={maskToken(authToken)}
|
|
157
|
+
/>
|
|
158
|
+
</Step>
|
|
159
|
+
)}
|
|
127
160
|
</TabsContent>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
161
|
+
))}
|
|
162
|
+
|
|
163
|
+
<TabsContent value="prompt" className="mt-4 flex flex-col gap-4">
|
|
164
|
+
<Step
|
|
165
|
+
index={1}
|
|
166
|
+
title="Make sure the marimo-pair skill is available to your agent"
|
|
167
|
+
hint="Skip if your agent already has it."
|
|
168
|
+
>
|
|
169
|
+
<CommandBlock command={SKILL_INSTALL} />
|
|
170
|
+
</Step>
|
|
171
|
+
<Step
|
|
172
|
+
index={2}
|
|
173
|
+
title="Copy this prompt into your agent"
|
|
174
|
+
hint={
|
|
175
|
+
hasToken
|
|
176
|
+
? "Includes your auth token — keep it private."
|
|
177
|
+
: undefined
|
|
178
|
+
}
|
|
179
|
+
>
|
|
180
|
+
<CommandBlock
|
|
181
|
+
command={getRawPrompt(remoteUrl, authToken)}
|
|
182
|
+
display={getRawPrompt(
|
|
183
|
+
remoteUrl,
|
|
184
|
+
authToken ? maskToken(authToken) : null,
|
|
185
|
+
)}
|
|
186
|
+
multiline={true}
|
|
187
|
+
/>
|
|
188
|
+
</Step>
|
|
189
|
+
</TabsContent>
|
|
190
|
+
</Tabs>
|
|
142
191
|
</div>
|
|
143
192
|
|
|
144
193
|
<DialogFooter>
|
|
@@ -150,10 +199,28 @@ export const PairWithAgentModal: React.FC<{
|
|
|
150
199
|
);
|
|
151
200
|
};
|
|
152
201
|
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
202
|
+
const Step: React.FC<{
|
|
203
|
+
index: number;
|
|
204
|
+
title: string;
|
|
205
|
+
hint?: string;
|
|
206
|
+
children: React.ReactNode;
|
|
207
|
+
}> = ({ index, title, hint, children }) => (
|
|
208
|
+
<div className="flex flex-col gap-2">
|
|
209
|
+
<div className="flex items-baseline gap-2">
|
|
210
|
+
<span className="text-sm font-medium">
|
|
211
|
+
{index}. {title}
|
|
212
|
+
</span>
|
|
213
|
+
{hint && <span className="text-xs text-muted-foreground">{hint}</span>}
|
|
214
|
+
</div>
|
|
215
|
+
{children}
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
const CommandBlock: React.FC<{
|
|
220
|
+
command: string;
|
|
221
|
+
display?: string;
|
|
222
|
+
multiline?: boolean;
|
|
223
|
+
}> = ({ command, display, multiline = false }) => {
|
|
157
224
|
const [copied, setCopied] = useState(false);
|
|
158
225
|
|
|
159
226
|
const copy = Events.stopPropagation(async (e) => {
|
|
@@ -163,6 +230,30 @@ const CommandBlock: React.FC<{ command: string; display?: string }> = ({
|
|
|
163
230
|
setTimeout(() => setCopied(false), 2000);
|
|
164
231
|
});
|
|
165
232
|
|
|
233
|
+
if (multiline) {
|
|
234
|
+
return (
|
|
235
|
+
<div className="relative rounded-md bg-muted">
|
|
236
|
+
<pre className="max-h-64 overflow-auto whitespace-pre-wrap break-words px-3 py-2 pr-10 font-mono text-xs select-all">
|
|
237
|
+
{display ?? command}
|
|
238
|
+
</pre>
|
|
239
|
+
<Tooltip content="Copied!" open={copied}>
|
|
240
|
+
<Button
|
|
241
|
+
onClick={copy}
|
|
242
|
+
size="xs"
|
|
243
|
+
variant="ghost"
|
|
244
|
+
className="absolute right-1 top-1"
|
|
245
|
+
>
|
|
246
|
+
{copied ? (
|
|
247
|
+
<CheckIcon size={14} strokeWidth={1.5} />
|
|
248
|
+
) : (
|
|
249
|
+
<CopyIcon size={14} strokeWidth={1.5} />
|
|
250
|
+
)}
|
|
251
|
+
</Button>
|
|
252
|
+
</Tooltip>
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
166
257
|
return (
|
|
167
258
|
<div className="flex items-center gap-2 rounded-md bg-muted px-3 py-2 font-mono text-xs">
|
|
168
259
|
<code className="flex-1 select-all break-words">
|