@1agh/maude 0.43.0 → 0.45.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.
- package/apps/studio/acp/bridge.ts +44 -10
- package/apps/studio/acp/env.ts +23 -0
- package/apps/studio/acp/login-state.ts +263 -0
- package/apps/studio/acp/plugin-bootstrap.ts +31 -25
- package/apps/studio/acp/probe.ts +152 -1
- package/apps/studio/annotations-layer.tsx +396 -46
- package/apps/studio/api.ts +395 -2
- package/apps/studio/bin/_audio-search.mjs +140 -0
- package/apps/studio/bin/_import-asset-pdf-worker.mjs +34 -0
- package/apps/studio/bin/_import-asset.mjs +815 -0
- package/apps/studio/bin/_import-brand.mjs +635 -0
- package/apps/studio/bin/_import-tokens-alias-resolver.mjs +95 -0
- package/apps/studio/bin/_import-tokens.mjs +1201 -0
- package/apps/studio/bin/_transcribe.mjs +419 -0
- package/apps/studio/bin/_transcribe.test.mjs +80 -0
- package/apps/studio/bin/audio-search.sh +28 -0
- package/apps/studio/bin/generate.sh +154 -0
- package/apps/studio/bin/import-asset.sh +34 -0
- package/apps/studio/bin/import-brand.sh +29 -0
- package/apps/studio/bin/import-tokens.sh +33 -0
- package/apps/studio/bin/photo-bg-remove.sh +119 -21
- package/apps/studio/bin/transcribe.sh +39 -0
- package/apps/studio/canvas-edit.ts +197 -2
- package/apps/studio/canvas-lib.tsx +115 -6
- package/apps/studio/client/app.jsx +1954 -685
- package/apps/studio/client/generate-dialog.jsx +352 -0
- package/apps/studio/client/github.js +14 -0
- package/apps/studio/client/inspector-controls.jsx +781 -0
- package/apps/studio/client/panels/BrandUploadPanel.jsx +233 -0
- package/apps/studio/client/panels/ChatPanel.jsx +15 -33
- package/apps/studio/client/panels/IntroVideoDialog.jsx +44 -0
- package/apps/studio/client/panels/OnboardingWizard.jsx +12 -0
- package/apps/studio/client/panels/ReadinessList.jsx +227 -7
- package/apps/studio/client/panels/SettingsPanel.jsx +828 -0
- package/apps/studio/client/panels/SetupChecklist.jsx +223 -0
- package/apps/studio/client/photo-knobs.jsx +167 -172
- package/apps/studio/client/styles/3-shell-maude.css +334 -28
- package/apps/studio/client/styles/4-components.css +223 -0
- package/apps/studio/client/styles/6-acp-chat.css +86 -0
- package/apps/studio/client/tour/quick-setup-tour.js +39 -0
- package/apps/studio/commands/annotation-strokes-command.ts +13 -3
- package/apps/studio/config.schema.json +70 -0
- package/apps/studio/context-menu.tsx +11 -2
- package/apps/studio/context.ts +16 -0
- package/apps/studio/design-setup-readiness.ts +115 -0
- package/apps/studio/dist/client.bundle.js +2097 -2088
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/draw/palette.ts +34 -0
- package/apps/studio/footage/schema.test.ts +92 -0
- package/apps/studio/footage/schema.ts +179 -1
- package/apps/studio/generation/adapters/elevenlabs.ts +370 -0
- package/apps/studio/generation/adapters/gemini.ts +542 -0
- package/apps/studio/generation/adapters/groq.test.ts +80 -0
- package/apps/studio/generation/adapters/groq.ts +247 -0
- package/apps/studio/generation/audio-library.test.ts +95 -0
- package/apps/studio/generation/audio-library.ts +156 -0
- package/apps/studio/generation/captions.test.ts +78 -0
- package/apps/studio/generation/captions.ts +132 -0
- package/apps/studio/generation/download.ts +76 -0
- package/apps/studio/generation/elevenlabs.test.ts +223 -0
- package/apps/studio/generation/gemini.test.ts +350 -0
- package/apps/studio/generation/jobs.test.ts +128 -0
- package/apps/studio/generation/jobs.ts +243 -0
- package/apps/studio/generation/keys.test.ts +75 -0
- package/apps/studio/generation/keys.ts +162 -0
- package/apps/studio/generation/prefs.test.ts +95 -0
- package/apps/studio/generation/prefs.ts +82 -0
- package/apps/studio/generation/registry.ts +88 -0
- package/apps/studio/generation/types.test.ts +123 -0
- package/apps/studio/generation/types.ts +266 -0
- package/apps/studio/generation/whisper-models.test.ts +152 -0
- package/apps/studio/generation/whisper-models.ts +257 -0
- package/apps/studio/generation/whisper-spike-results.md +61 -0
- package/apps/studio/git/service.ts +3 -1
- package/apps/studio/http.ts +867 -9
- package/apps/studio/media/intro.mp4 +0 -0
- package/apps/studio/media-commit-chain.ts +119 -0
- package/apps/studio/paths.ts +10 -0
- package/apps/studio/readiness.ts +108 -20
- package/apps/studio/scaffold-design.ts +1145 -0
- package/apps/studio/server.ts +13 -1
- package/apps/studio/test/_helpers.ts +15 -2
- package/apps/studio/test/acp-bridge.test.ts +34 -1
- package/apps/studio/test/acp-env.test.ts +30 -0
- package/apps/studio/test/acp-plugin-bootstrap.test.ts +23 -57
- package/apps/studio/test/acp-session-plugins.test.ts +72 -1
- package/apps/studio/test/annotation-strokes-command.test.ts +17 -0
- package/apps/studio/test/annotations-layer.test.ts +174 -0
- package/apps/studio/test/canvas-origin-gate.test.ts +37 -0
- package/apps/studio/test/csp-canvas-shell.test.ts +11 -0
- package/apps/studio/test/csrf-write-guard.test.ts +23 -1
- package/apps/studio/test/design-setup-readiness.test.ts +155 -0
- package/apps/studio/test/element-structural-edit.test.ts +108 -0
- package/apps/studio/test/fixtures/fake-claude-auth.mjs +13 -0
- package/apps/studio/test/generate-route.test.ts +106 -0
- package/apps/studio/test/import-asset-browser.test.ts +64 -0
- package/apps/studio/test/import-asset-route.test.ts +71 -0
- package/apps/studio/test/import-asset.test.ts +399 -0
- package/apps/studio/test/import-brand-browser.test.ts +88 -0
- package/apps/studio/test/import-brand-route.test.ts +120 -0
- package/apps/studio/test/import-brand.test.ts +206 -0
- package/apps/studio/test/import-tokens.test.ts +722 -0
- package/apps/studio/test/media-commit-chain.test.ts +210 -0
- package/apps/studio/test/photo-bg-remove-validation.test.ts +71 -0
- package/apps/studio/test/readiness.test.ts +13 -11
- package/apps/studio/test/scaffold-design.test.ts +122 -0
- package/apps/studio/test/tour-overlay.test.tsx +16 -0
- package/apps/studio/tool-palette.tsx +11 -6
- package/apps/studio/ui-prefs.ts +130 -0
- package/apps/studio/use-canvas-media-drop.tsx +4 -2
- package/apps/studio/use-chrome-visibility.tsx +8 -2
- package/apps/studio/whats-new.json +96 -0
- package/apps/studio/ws.ts +5 -0
- package/cli/bin/maude.mjs +6 -6
- package/cli/commands/design.mjs +33 -0
- package/cli/commands/init.mjs +7 -1
- package/cli/lib/gitignore-block.mjs +1 -0
- package/cli/lib/pkg-root.mjs +107 -0
- package/cli/lib/pkg-root.test.mjs +79 -0
- package/cli/lib/reconstruct-toolset.test.mjs +194 -0
- package/cli/lib/update-check.mjs +8 -0
- package/package.json +12 -10
- package/plugins/design/dependencies.json +18 -0
- package/plugins/flow/.claude-plugin/config.schema.json +5 -0
- package/plugins/flow/templates/ai-skeleton/scenario-guide.md +39 -0
- package/plugins/flow/templates/ai-skeleton/scenarios/README.md +2 -0
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
// not-connected explainer (where a user actually hits the wall). Both also use it
|
|
8
8
|
// as the persistent re-check surface — `refresh()` re-probes without a reinstall.
|
|
9
9
|
|
|
10
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
10
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
11
|
+
import { getClaudeAutoSetup, isNativeApp, setClaudeAutoSetup } from '../github.js';
|
|
11
12
|
|
|
12
13
|
/** Fetch + cache the readiness report. `refresh()` re-probes (the re-check button). */
|
|
13
14
|
export function useReadiness(enabled = true) {
|
|
@@ -82,7 +83,165 @@ function Inline({ text }) {
|
|
|
82
83
|
return <>{parts}</>;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
// DDR-166 T0d — a bounded, cancelable poll after "Sign in" is clicked. Capped
|
|
87
|
+
// duration (not indefinite), single-flight (the button disables while
|
|
88
|
+
// polling), and its copy is static text — no animation, so it costs nothing
|
|
89
|
+
// under prefers-reduced-motion.
|
|
90
|
+
const SIGNIN_POLL_MS = 2000;
|
|
91
|
+
const SIGNIN_POLL_MAX_MS = 120000;
|
|
92
|
+
// The installer itself is fire-and-forget server-side (avoids Bun's default
|
|
93
|
+
// 10s idle timeout on a slow network) — poll for its result the same way.
|
|
94
|
+
const INSTALL_POLL_MS = 1500;
|
|
95
|
+
const INSTALL_POLL_MAX_MS = 90000;
|
|
96
|
+
|
|
97
|
+
// DDR-166 T0c/T0d — one component drives both the "install then sign in"
|
|
98
|
+
// chain (mode='install') and the "sign in only" case (mode='signin'), since
|
|
99
|
+
// the poll-after-signin logic is identical either way. The install step
|
|
100
|
+
// itself is a single distinct network call, not a loop — only the sign-in
|
|
101
|
+
// half needs polling (the browser-OAuth completion signal).
|
|
102
|
+
function SetupAction({ mode, refresh }) {
|
|
103
|
+
const [phase, setPhase] = useState('idle'); // idle | installing | waiting | error
|
|
104
|
+
const [error, setError] = useState(null);
|
|
105
|
+
const timerRef = useRef({ interval: null, deadline: 0 });
|
|
106
|
+
|
|
107
|
+
const stopPoll = () => {
|
|
108
|
+
if (timerRef.current.interval) clearInterval(timerRef.current.interval);
|
|
109
|
+
timerRef.current.interval = null;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const pollForSignin = () => {
|
|
113
|
+
setPhase('waiting');
|
|
114
|
+
timerRef.current.deadline = Date.now() + SIGNIN_POLL_MAX_MS;
|
|
115
|
+
timerRef.current.interval = setInterval(async () => {
|
|
116
|
+
if (Date.now() > timerRef.current.deadline) {
|
|
117
|
+
stopPoll();
|
|
118
|
+
setPhase('error');
|
|
119
|
+
setError('Sign-in timed out — try again.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const report = await refresh();
|
|
123
|
+
const claudeItem = report?.items?.find((i) => i.id === 'claude');
|
|
124
|
+
if (claudeItem?.status === 'present') stopPoll();
|
|
125
|
+
}, SIGNIN_POLL_MS);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const runSignin = async () => {
|
|
129
|
+
const res = await fetch('/_api/claude/signin', { method: 'POST' })
|
|
130
|
+
.then((r) => r.json())
|
|
131
|
+
.catch(() => ({ ok: false, reason: 'Could not reach Maude.' }));
|
|
132
|
+
if (!res.ok) {
|
|
133
|
+
setPhase('error');
|
|
134
|
+
setError(res.reason || 'Could not start sign-in.');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
pollForSignin();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const pollForInstall = () => {
|
|
141
|
+
setPhase('installing');
|
|
142
|
+
timerRef.current.deadline = Date.now() + INSTALL_POLL_MAX_MS;
|
|
143
|
+
timerRef.current.interval = setInterval(async () => {
|
|
144
|
+
if (Date.now() > timerRef.current.deadline) {
|
|
145
|
+
stopPoll();
|
|
146
|
+
setPhase('error');
|
|
147
|
+
setError('Install timed out — you can also run the command below yourself.');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const state = await fetch('/_api/claude/install-status')
|
|
151
|
+
.then((r) => r.json())
|
|
152
|
+
.catch(() => null);
|
|
153
|
+
if (!state || state.phase !== 'done') return; // still running
|
|
154
|
+
stopPoll();
|
|
155
|
+
if (!state.ok) {
|
|
156
|
+
setPhase('error');
|
|
157
|
+
setError(state.reason || 'Install failed — you can also run the command below yourself.');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// One click covers both steps: only on verified-fresh install success
|
|
161
|
+
// does this move straight into sign-in with no second click needed.
|
|
162
|
+
await runSignin();
|
|
163
|
+
}, INSTALL_POLL_MS);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const start = async () => {
|
|
167
|
+
setError(null);
|
|
168
|
+
if (mode === 'install') {
|
|
169
|
+
const res = await fetch('/_api/claude/install', { method: 'POST' })
|
|
170
|
+
.then((r) => r.json())
|
|
171
|
+
.catch(() => ({ ok: false, reason: 'Could not reach Maude.' }));
|
|
172
|
+
if (!res.ok) {
|
|
173
|
+
setPhase('error');
|
|
174
|
+
setError(res.reason || 'Could not start the installer.');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
pollForInstall();
|
|
178
|
+
} else {
|
|
179
|
+
await runSignin();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const cancel = async () => {
|
|
184
|
+
stopPoll();
|
|
185
|
+
setPhase('idle');
|
|
186
|
+
await fetch('/_api/claude/signin-cancel', { method: 'POST' }).catch(() => {});
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
useEffect(() => () => stopPoll(), []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
190
|
+
|
|
191
|
+
if (phase === 'installing') {
|
|
192
|
+
return (
|
|
193
|
+
<span className="rdy-fix">
|
|
194
|
+
<span className="rdy-fix-tx">Installing Claude Code…</span>
|
|
195
|
+
</span>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (phase === 'waiting') {
|
|
199
|
+
return (
|
|
200
|
+
<span className="rdy-fix">
|
|
201
|
+
<span className="rdy-fix-tx">Waiting for you to finish signing in in your browser…</span>
|
|
202
|
+
<button type="button" className="rdy-copy" onClick={cancel}>
|
|
203
|
+
Cancel
|
|
204
|
+
</button>
|
|
205
|
+
</span>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return (
|
|
209
|
+
<span className="rdy-fix">
|
|
210
|
+
{error ? <span className="rdy-fix-tx rdy-fix-tx--err">{error}</span> : null}
|
|
211
|
+
<button
|
|
212
|
+
type="button"
|
|
213
|
+
className="rdy-signin"
|
|
214
|
+
data-testid={mode === 'install' ? 'acp-setup-install' : 'acp-setup-signin'}
|
|
215
|
+
onClick={start}
|
|
216
|
+
>
|
|
217
|
+
{mode === 'install' ? 'Set up AI editing' : 'Sign in to Claude'}
|
|
218
|
+
</button>
|
|
219
|
+
</span>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function InstallCommand({ command }) {
|
|
224
|
+
const [copied, setCopied] = useState(false);
|
|
225
|
+
const copy = () => {
|
|
226
|
+
navigator.clipboard?.writeText(command).then(
|
|
227
|
+
() => {
|
|
228
|
+
setCopied(true);
|
|
229
|
+
setTimeout(() => setCopied(false), 1500);
|
|
230
|
+
},
|
|
231
|
+
() => {}
|
|
232
|
+
);
|
|
233
|
+
};
|
|
234
|
+
return (
|
|
235
|
+
<span className="rdy-cmd">
|
|
236
|
+
<code className="rdy-cmd-tx">{command}</code>
|
|
237
|
+
<button type="button" className="rdy-copy" onClick={copy} aria-label="Copy install command">
|
|
238
|
+
{copied ? 'Copied' : 'Copy'}
|
|
239
|
+
</button>
|
|
240
|
+
</span>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function Row({ item, refresh }) {
|
|
86
245
|
const [copied, setCopied] = useState(false);
|
|
87
246
|
const copyFix = () => {
|
|
88
247
|
const cmds = item.remediation?.replace(/`/g, '') ?? '';
|
|
@@ -95,7 +254,10 @@ function Row({ item }) {
|
|
|
95
254
|
);
|
|
96
255
|
};
|
|
97
256
|
return (
|
|
98
|
-
<li
|
|
257
|
+
<li
|
|
258
|
+
className={`rdy-row rdy-row--${item.status}${item.required ? '' : ' rdy-row--opt'}`}
|
|
259
|
+
data-testid={`rdy-row-${item.id}`}
|
|
260
|
+
>
|
|
99
261
|
<span className="rdy-ic" aria-hidden="true">
|
|
100
262
|
<StatusIcon status={item.status} />
|
|
101
263
|
</span>
|
|
@@ -109,11 +271,33 @@ function Row({ item }) {
|
|
|
109
271
|
<span className="rdy-fix-tx">
|
|
110
272
|
<Inline text={item.remediation} />
|
|
111
273
|
</span>
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
|
|
274
|
+
{!item.installCommand && !item.action ? (
|
|
275
|
+
<button type="button" className="rdy-copy" onClick={copyFix} aria-label={`Copy the fix for ${item.label}`}>
|
|
276
|
+
{copied ? 'Copied' : 'Copy'}
|
|
277
|
+
</button>
|
|
278
|
+
) : null}
|
|
279
|
+
</span>
|
|
280
|
+
) : null}
|
|
281
|
+
{item.action === 'signin' && item.resolvedPath ? (
|
|
282
|
+
<span className="rdy-fix-tx rdy-resolved-path">
|
|
283
|
+
{item.resolvedViaMaude ? 'Installed by Maude: ' : 'Found on your PATH: '}
|
|
284
|
+
<code>{item.resolvedPath}</code>
|
|
115
285
|
</span>
|
|
116
286
|
) : null}
|
|
287
|
+
{(item.action === 'install' || item.action === 'signin') && refresh ? (
|
|
288
|
+
<SetupAction mode={item.action} refresh={refresh} />
|
|
289
|
+
) : null}
|
|
290
|
+
{item.installCommand ? (
|
|
291
|
+
<>
|
|
292
|
+
{item.action === 'install' ? (
|
|
293
|
+
<span className="rdy-fix-tx rdy-fallback-label">
|
|
294
|
+
Clicking above runs this command, then opens your browser to sign in. Prefer to do it
|
|
295
|
+
yourself?
|
|
296
|
+
</span>
|
|
297
|
+
) : null}
|
|
298
|
+
<InstallCommand command={item.installCommand} />
|
|
299
|
+
</>
|
|
300
|
+
) : null}
|
|
117
301
|
</span>
|
|
118
302
|
</li>
|
|
119
303
|
);
|
|
@@ -124,7 +308,7 @@ export default function ReadinessList({ report, loading, refresh }) {
|
|
|
124
308
|
<div className="rdy">
|
|
125
309
|
<ul className="rdy-list">
|
|
126
310
|
{report?.items?.map((it) => (
|
|
127
|
-
<Row key={it.id} item={it} />
|
|
311
|
+
<Row key={it.id} item={it} refresh={refresh} />
|
|
128
312
|
))}
|
|
129
313
|
</ul>
|
|
130
314
|
{refresh ? (
|
|
@@ -138,6 +322,41 @@ export default function ReadinessList({ report, loading, refresh }) {
|
|
|
138
322
|
);
|
|
139
323
|
}
|
|
140
324
|
|
|
325
|
+
// DDR-166 Decision 5 — the settings-UI opt-out for the auto-install/auto-
|
|
326
|
+
// sign-in buttons above. DEFAULT ON. Native-only (the toggle is backed by a
|
|
327
|
+
// Tauri command); a terminal-launched `maude design serve` web session has
|
|
328
|
+
// no automated action to opt out of in the first place.
|
|
329
|
+
function AutoSetupToggle() {
|
|
330
|
+
const [on, setOn] = useState(true);
|
|
331
|
+
useEffect(() => {
|
|
332
|
+
let alive = true;
|
|
333
|
+
getClaudeAutoSetup()
|
|
334
|
+
.then((v) => alive && setOn(v !== false))
|
|
335
|
+
.catch(() => {});
|
|
336
|
+
return () => {
|
|
337
|
+
alive = false;
|
|
338
|
+
};
|
|
339
|
+
}, []);
|
|
340
|
+
if (!isNativeApp()) return null;
|
|
341
|
+
return (
|
|
342
|
+
<label className="rdy-autosetup-toggle">
|
|
343
|
+
<input
|
|
344
|
+
type="checkbox"
|
|
345
|
+
checked={on}
|
|
346
|
+
onChange={(e) => {
|
|
347
|
+
const next = e.target.checked;
|
|
348
|
+
setOn(next);
|
|
349
|
+
setClaudeAutoSetup(next).catch(() => setOn(!next));
|
|
350
|
+
}}
|
|
351
|
+
/>
|
|
352
|
+
<span>
|
|
353
|
+
Offer to install Claude Code and sign in automatically. Turn off to see only the copy-paste
|
|
354
|
+
command — takes effect next launch or project switch.
|
|
355
|
+
</span>
|
|
356
|
+
</label>
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
141
360
|
// Standalone readiness modal reachable any time from Help ▸ Check AI editing
|
|
142
361
|
// readiness… (DDR-128, T6 — the persistent re-check surface, not gated on
|
|
143
362
|
// first-run or a disconnected chat). Reuses the shared help-modal chrome (backdrop
|
|
@@ -182,6 +401,7 @@ export function ReadinessDialog({ open, onClose }) {
|
|
|
182
401
|
{loading ? 'Checking…' : "Couldn't reach the readiness probe."}
|
|
183
402
|
</p>
|
|
184
403
|
)}
|
|
404
|
+
<AutoSetupToggle />
|
|
185
405
|
</div>
|
|
186
406
|
</div>
|
|
187
407
|
</div>
|