mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-28 05:46:58 +02:00
* fix(quick-create): bound dialog height + scroll editor when content overflows Pasting a screenshot into the agent-create prompt expanded the editor unbounded, which dragged DialogContent past the viewport since the agent mode className had no max-height. Manual mode was unaffected because manualDialogContentClass pins `!h-96`. - Cap agent-mode DialogContent at `!max-h-[80vh]` (width stays `!max-w-xl`); short prompts still render compact, tall content stops at 80% of the viewport. - Switch the editor wrapper to `flex-1 min-h-[140px] overflow-y-auto` so it absorbs the remaining vertical space inside the now-bounded DialogContent and scrolls internally instead of pushing the dialog. * feat(quick-create): gate on daemon CLI version with pre-check + server enforcement The agent-create flow depends on multica CLI behavior introduced in v0.2.20 (URL attachment handling, no-retry semantics on `multica issue create` failure — see PR #1851 / MUL-1496). Older daemons either double-create issues on partial CLI failures or mishandle pasted screenshot URLs. Per J's review on MUL-1496, gate the flow at two layers — frontend pre-check for fast feedback, server re-check as the trust boundary, both fail-closed on missing/unparsable versions. Server: - New MinQuickCreateCLIVersion + CheckMinCLIVersion helper in pkg/agent (with sentinel errors for missing vs too-old). - QuickCreateIssue handler reads runtime metadata.cli_version and returns a stable 422 { code: "daemon_version_unsupported", current_version, min_version, runtime_id } before enqueuing. - The check runs after the existing online + ownership validation, so all rejections surface uniformly through the modal's existing error path. Frontend: - New @multica/core/runtimes/cli-version with the min version constant, parser, and runtime-metadata reader (tiny semver, no new lib dep). - AgentCreatePanel resolves the selected agent's runtime, runs the same check, shows an inline amber notice below the agent picker when missing/too old, and disables the Create button. - Submit handler also catches the server's 422 (defensive race — runtime can re-register between pre-check and submit) and surfaces the same wording in the error row. Switching to manual create remains a clean escape hatch — manual mode doesn't talk to a daemon at all, so an outdated CLI doesn't block the user from filing the issue.
62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
/**
|
|
* Frontend mirror of the server's MinQuickCreateCLIVersion gate. The
|
|
* agent-create flow (Quick Create modal) requires the daemon's bundled
|
|
* multica CLI to be at least this version — older daemons either
|
|
* double-create issues on partial CLI failures or mishandle pasted
|
|
* screenshot URLs (see PR #1851 / MUL-1496).
|
|
*
|
|
* Both the frontend pre-validation in the modal and the server's
|
|
* `/api/issues/quick-create` handler enforce this; the server is the
|
|
* authoritative trust boundary, the frontend just lets us tell the user
|
|
* "your daemon needs an upgrade" before they hit submit.
|
|
*/
|
|
export const MIN_QUICK_CREATE_CLI_VERSION = "0.2.20";
|
|
|
|
export type CliVersionState = "ok" | "too_old" | "missing";
|
|
|
|
export interface CliVersionCheck {
|
|
state: CliVersionState;
|
|
/** What the daemon reported, or empty if missing/unparsable. */
|
|
current: string;
|
|
/** The hard minimum we gate on. */
|
|
min: string;
|
|
}
|
|
|
|
const SEMVER_RE = /v?(\d+)\.(\d+)\.(\d+)/;
|
|
|
|
function parseSemver(raw: string): [number, number, number] | null {
|
|
const m = SEMVER_RE.exec(raw.trim());
|
|
if (!m) return null;
|
|
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
}
|
|
|
|
function lessThan(a: [number, number, number], b: [number, number, number]) {
|
|
if (a[0] !== b[0]) return a[0] < b[0];
|
|
if (a[1] !== b[1]) return a[1] < b[1];
|
|
return a[2] < b[2];
|
|
}
|
|
|
|
/**
|
|
* Check a daemon-reported CLI version string against the minimum. Returns
|
|
* `"missing"` for empty/unparsable input (fail closed — same policy as the
|
|
* server) and `"too_old"` for a parsable version below the threshold.
|
|
*/
|
|
export function checkQuickCreateCliVersion(detected: string | undefined | null): CliVersionCheck {
|
|
const current = (detected ?? "").trim();
|
|
const parsed = current ? parseSemver(current) : null;
|
|
if (!parsed) {
|
|
return { state: "missing", current, min: MIN_QUICK_CREATE_CLI_VERSION };
|
|
}
|
|
const min = parseSemver(MIN_QUICK_CREATE_CLI_VERSION)!;
|
|
if (lessThan(parsed, min)) {
|
|
return { state: "too_old", current, min: MIN_QUICK_CREATE_CLI_VERSION };
|
|
}
|
|
return { state: "ok", current, min: MIN_QUICK_CREATE_CLI_VERSION };
|
|
}
|
|
|
|
/** Pull `cli_version` off a runtime row's loosely-typed metadata bag. */
|
|
export function readRuntimeCliVersion(metadata: Record<string, unknown> | undefined): string {
|
|
const v = metadata?.cli_version;
|
|
return typeof v === "string" ? v : "";
|
|
}
|