Skip to content

feat(desktop): slides template workflow for agent-authored decks#949

Merged
softmarshmallow merged 9 commits into
mainfrom
feat/desktop-home-redesign
Jul 8, 2026
Merged

feat(desktop): slides template workflow for agent-authored decks#949
softmarshmallow merged 9 commits into
mainfrom
feat/desktop-home-redesign

Conversation

@softmarshmallow

@softmarshmallow softmarshmallow commented Jul 5, 2026

Copy link
Copy Markdown
Member

Summary

This PR completes the desktop slides template flow on top of the filesystem-backed skills system and the repo-root public/ origin tree.

The desktop home now treats a picked slides template as concrete context for the first agent turn: the real bundled .canvas deck is loaded for gallery preview, passed through the handoff as template context, and seeded into the agent scratch workspace so the agent can adapt the selected deck instead of reconstructing a deck from a prompt alone.

It also includes the host-side desktop slides workaround for SVG image resources tracked in gridaco/grida#960: saved slide SVGs remain portable, while the desktop slides editor materializes bundle-relative image references into renderable data: URLs before handing SVG text to @grida/svg-editor.

What Changed

  • Rebuilt the desktop welcome slides path around real .canvas templates:
    • gallery previews load actual template decks from /templates/slides/
    • selected templates are carried as structured context, not composer prefill text
    • the welcome handoff opens the normal workspace/file flow with template context attached
  • Added agent/runtime support for template context and scratch seeding:
    • registered context markers for template selections
    • lowered template context into model-visible message parts
    • wrote selected template bytes into the session scratch area before the model turn
  • Kept project creation empty and agent-led:
    • workspaces.createProject no longer seeds a guessed document
    • free-text prompts still let the agent decide the correct document shape
    • explicit template picks provide concrete starting material without reintroducing manifest injection at project creation
  • Added the temporary desktop slides SVG image projection:
    • rewrites only SVG image carriers (image / feImage href and xlink href) for editor rendering
    • resolves relative paths inside the .canvas bundle root
    • leaves saved SVGs portable by restoring generated data: URLs before write
    • applies the same projection to thumbnails and presentation overlay data URIs
  • Updated agent-facing slide/dotcanvas skills:
    • clarifies that .canvas is a bundle folder
    • explains how to adapt scratch-provided templates
    • does not require agents to encode images as data URIs; resource projection remains host/editor work

Why

A typed prompt is ambiguous, so the home should not guess whether to create a board, deck, or another document shape. A clicked template is different: the user selected a concrete deck. This PR uses that concrete deck as first-turn context while keeping actual document creation agent-led and filesystem-backed.

The SVG image change is intentionally scoped as a host workaround. @grida/svg-editor currently accepts SVG text without a first-class resource mapping mechanism, so relative image hrefs inside .canvas bundles do not naturally resolve in the editor. This PR keeps that limitation contained to desktop slides and links the workaround to gridaco/grida#960 for later removal when the editor owns resource resolution.

Verification

  • git diff --check
  • pnpm exec oxfmt --check ...
  • pnpm --filter editor test -- scaffolds/desktop/canvas/slide-svg-resources.test.ts
  • pnpm --filter editor typecheck
  • Pre-commit oxfmt / oxlint passed for the four latest commits

Notes:

  • The canvas resource adapter has unit coverage for relative hrefs, xlink hrefs, skipped absolute/self-contained hrefs, bundle-root containment, failed reads, and restore behavior.
  • The prior daemon/workspace boundary test coverage from the draft remains part of this PR's history.

@vercel vercel Bot temporarily deployed to Preview – blog July 5, 2026 17:12 Inactive
@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
grida Ready Ready Preview, Comment Jul 8, 2026 4:08pm
5 Skipped Deployments
Project Deployment Actions Updated (UTC)
blog Ignored Ignored Jul 8, 2026 4:08pm
code Ignored Ignored Jul 8, 2026 4:08pm
docs Ignored Ignored Preview Jul 8, 2026 4:08pm
backgrounds Skipped Skipped Jul 8, 2026 4:08pm
viewer Skipped Skipped Jul 8, 2026 4:08pm

Request Review

@vercel vercel Bot temporarily deployed to Preview – viewer July 5, 2026 17:12 Inactive
@vercel vercel Bot temporarily deployed to Preview – backgrounds July 5, 2026 17:12 Inactive
@vercel vercel Bot temporarily deployed to Preview – grida July 5, 2026 17:12 Inactive
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR updates workspace creation to mint empty projects, adds scratch-seed and template-context handling through the agent path, reworks desktop startup around presets and slides templates, and adds SVG resource materialization for slide editing.

Changes

Desktop workspace, session startup, and agent flow

Layer / File(s) Summary
Empty workspace creation and default lookup
packages/grida-daemon/src/workspaces.ts, packages/grida-daemon/src/protocol/resources.ts, packages/grida-daemon/src/http/routes/workspaces.ts, packages/grida-daemon/src/workspaces.test.ts, packages/grida-daemon/src/http/routes/workspaces.create.test.ts, packages/grida-daemon/src/server.ts, editor/lib/desktop/bridge.ts, SECURITY.md
Removes seed-based workspace creation, adds default-workspace tracking and lookup, and updates the route, tests, and docs for empty project creation.
Scratch seed and context tokens
packages/grida-ai-agent/src/protocol/run.ts, packages/grida-ai-agent/src/runtime/run-input.ts, packages/grida-ai-agent/src/runtime/index.ts, packages/grida-ai-agent/src/protocol/context.ts, packages/grida-ai-agent/src/runtime/message-view.ts, packages/grida-ai-agent/src/runtime/workspace-agent-bindings.ts, packages/grida-ai-agent/src/index.ts, editor/lib/agent-chat/*, editor/kits/composer/composer-react.tsx, editor/scaffolds/desktop/shared/agent-composer-input.tsx, tests
Adds scratch_seed to run options and request parsing, writes seeded files into session scratch, registers and lowers context tokens, and updates the send/composer plumbing for context-only first-turn submission.
Presets and welcome startup
editor/app/desktop/welcome/page.tsx, editor/lib/desktop/bridge.ts, editor/scaffolds/desktop/home/*, editor/scaffolds/desktop/workbench/agent-pane.tsx, editor/.gitignore
Reworks the welcome page around presets, workspace picking, template/reference selection, and first-turn handoff of scratch/template context, with new template gallery and preview UI.
Slide SVG materialization
editor/scaffolds/desktop/canvas/slide-svg-resources.ts, slide-svg-resources.test.ts, canvas-shell.tsx, slide-surface.tsx, use-workspace-file-save.ts
Materializes SVG resource references into data URLs for editing and restores them on write, with thumbnail and keyboard-navigation updates in the canvas shell.
Fixtures, skills, and build config
fixtures/prompts/README.md, fixtures/prompts/slides-prompts.txt, fixtures/prompts/slides-scenarios.jsonl, skills/dotcanvas/SKILL.md, skills/slides/SKILL.md, public/package.json, public/turbo.json, editor/package.json
Adds prompt fixtures, updates deck/template working instructions, and changes package/build configuration.

Estimated code review effort: 4 (Complex) | ~75 minutes

Possibly related PRs

  • gridaco/grida#792: Both PRs change the desktop welcome-to-first-turn handoff path.
  • gridaco/grida#841: Both PRs modify packages/grida-ai-agent/src/runtime/workspace-agent-bindings.ts hydration and scan logic.
  • gridaco/grida#934: Both PRs modify the managed-root workspace-create flow and its seed/manifest contract.

Suggested labels: desktop, ai

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title matches the main change: a desktop slides template workflow for agent-authored decks.
Description check ✅ Passed The description is clearly related to the changeset and matches the desktop slides template and SVG resource work.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/desktop-home-redesign

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@softmarshmallow softmarshmallow force-pushed the feat/desktop-home-redesign branch from ff98a14 to 84109c4 Compare July 6, 2026 16:31
@softmarshmallow softmarshmallow changed the title feat(desktop): slides studio — templates gallery + dedicated slides skill UX feat(desktop): slides templates gallery + reference-first home (materialize-on-pick TODO) Jul 6, 2026
…oject auto-create

Home redesign slice on top of the merged public/ origin tree (#952).

What lands:
- Slides preset gallery now renders the REAL bundled `.canvas` decks served
  from /templates/slides/ (the public/slides-templates publishing unit),
  hover-scrubbing actual pages via slides-template-loader.ts (code-split;
  fflate + dotcanvas kept out of the home chunk). PlaceholderSlide is gone.
- editor syncs the origin tree on predev/prebuild (`sync:public`);
  /public/templates/ is gitignored on the host.
- Preset rail + chip, workspace picker, reference gallery, composer wiring
  for the reference-first home.
- Daemon `POST /workspaces/create` mints an EMPTY project (no seed, no
  manifest) — document creation is deferred to the agent's first turn. This
  REMOVES the prior seed write authority (manifest-injection surface);
  SECURITY.md GRIDA-SEC-004 updated in lockstep (4 rules -> 3). Boundary
  tests green (140/140).

Known gap (picked up next — see PR body): picking a slides template only
PREFILLS the composer prompt today; it does NOT yet materialize the deck into
the project. The intended flow (create project -> copy the `.canvas` bundle
down -> open the deck) is designed but unimplemented.
@softmarshmallow softmarshmallow changed the title feat(desktop): slides templates gallery + reference-first home (materialize-on-pick TODO) feat(desktop): slides template workflow for agent-authored decks Jul 8, 2026
@softmarshmallow softmarshmallow marked this pull request as ready for review July 8, 2026 15:24
@coderabbitai coderabbitai Bot added ai AI models, prompts, and pricing desktop this is a Grida Desktop App related issue labels Jul 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e92e49ebfc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/grida-ai-agent/src/runtime/index.ts
Comment thread editor/app/desktop/welcome/page.tsx
Comment thread editor/package.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
editor/lib/agent-chat/build-agent-send.ts (1)

57-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extend SendMessageFn to cover the {role, parts} arm and eliminate the as never cast.

The local SendMessageFn type only covers the {text, files} form, so the {role, parts} path at line 113 requires as never. If the AI SDK's sendMessage contract or the parts shape diverges, TypeScript won't catch it. A union return type would restore compile-time safety here.

♻️ Suggested type extension
 export type SendMessageFn = (
-  message: { text: string; files?: FileUIPart[] },
+  message:
+    | { text: string; files?: FileUIPart[] }
+    | { role: "user"; parts: unknown[] },
   options?: { body?: AgentSendBody }
 ) => void | Promise<void>;

Then at the call site:

-      void sendMessage({ role: "user", parts } as never, { body });
+      void sendMessage({ role: "user", parts }, { body });

Also applies to: 104-113

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/lib/agent-chat/build-agent-send.ts` around lines 57 - 60,
`SendMessageFn` only types the `{text, files}` payload, so the `{role, parts}`
send path in `build-agent-send` is forced through an unsafe cast. Extend
`SendMessageFn` to accept both message shapes used by the send flow, and update
the call site in `buildAgentSend`/`sendMessage` to pass the typed `{role,
parts}` object directly without `as never`; keep the return type aligned with
the AI SDK contract so TypeScript can validate both branches.
packages/grida-ai-agent/src/protocol/context.ts (1)

25-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use USER_TEMPLATE_SELECTION as the computed key in CONTEXT_MARKERS.

The registry key "data-user_template_selection" duplicates the value of USER_TEMPLATE_SELECTION. If either changes independently, the lookup in message-view.ts silently breaks. Using the constant as a computed property key makes the dependency explicit.

♻️ Proposed refactor
 export const CONTEXT_MARKERS: Readonly<Record<string, string>> = {
-  "data-user_template_selection": "user_template_selection",
+  [USER_TEMPLATE_SELECTION]: "user_template_selection",
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/grida-ai-agent/src/protocol/context.ts` around lines 25 - 27, Update
CONTEXT_MARKERS in context.ts to use USER_TEMPLATE_SELECTION as the computed
property key instead of a duplicated string literal, so the registry stays
aligned with the constant used by message-view.ts. Keep the existing value
mapping to "user_template_selection", and make sure the dependency is explicit
by referencing USER_TEMPLATE_SELECTION directly in the CONTEXT_MARKERS object
definition.
editor/scaffolds/desktop/canvas/slide-svg-resources.ts (1)

77-95: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Sequential resource reads in the materialization loop.

Each <image>/<feImage> href is read one at a time via await inside the for...of loop. Since each read is independent (different relPath, own map entry), these could be issued concurrently with Promise.all to cut round-trip latency for slides with multiple images.

♻️ Proposed refactor
-  for (const attr of doc.attributes()) {
-    const href = attr.value;
-    const relPath = resolveResourceRelPath({
-      href,
-      bundleBasePath: options.bundleBasePath,
-      slideRelPath: options.slideRelPath,
-    });
-    if (!relPath) continue;
-
-    try {
-      const { base64 } = await readFileBytes(options.workspaceId, relPath);
-      const materialized = toDataUrl(relPath, base64, projectionId, sequence++);
-      restores.set(materialized, escapeXmlAttribute(href));
-      attr.set(materialized);
-    } catch {
-      // Per `#960` this is a render projection, not document validation. A
-      // missing/oversized/binary asset should leave only that image broken.
-    }
-  }
+  await Promise.all(
+    doc.attributes().map(async (attr) => {
+      const href = attr.value;
+      const relPath = resolveResourceRelPath({
+        href,
+        bundleBasePath: options.bundleBasePath,
+        slideRelPath: options.slideRelPath,
+      });
+      if (!relPath) return;
+
+      try {
+        const { base64 } = await readFileBytes(options.workspaceId, relPath);
+        const materialized = toDataUrl(relPath, base64, projectionId, sequence++);
+        restores.set(materialized, escapeXmlAttribute(href));
+        attr.set(materialized);
+      } catch {
+        // Per `#960` this is a render projection, not document validation.
+      }
+    })
+  );

Note: sequence++ under concurrent execution is non-deterministic ordering but still unique per call, so uniqueness is preserved.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/scaffolds/desktop/canvas/slide-svg-resources.ts` around lines 77 - 95,
The resource materialization loop in slide-svg-resources is performing
independent file reads sequentially inside the for...of iteration, which can add
unnecessary latency for slides with multiple images. Refactor the logic around
resolveResourceRelPath, readFileBytes, and toDataUrl so each valid href is
processed concurrently with Promise.all while still preserving the existing
restores map updates and per-item error swallowing behavior. Keep sequence++
unique per materialized resource, and ensure the attr.set and restores.set calls
still happen for each successful read.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@editor/scaffolds/desktop/home/slides-template-loader.ts`:
- Around line 117-143: The loadSlidesTemplates memoization currently caches a
rejected promise when the initial index.json fetch or parsing fails, which
prevents any retry for the rest of the session. Update loadSlidesTemplates and
its memo assignment so that failures clear memo back to null before rethrowing,
allowing a later call to retry instead of permanently reusing the rejected
promise. Use the existing memo variable and the loadSlidesTemplates function as
the place to implement this retry-safe behavior.

In `@fixtures/prompts/slides-prompts.txt`:
- Line 28: The prompt text is not self-sufficient because it asks for a future
paste of meeting notes, which leaves the fixture incomplete. Update the prompt
in the slides prompt fixture to stand alone by replacing the placeholder with a
concrete notes stub or example meeting notes, or move this wording into an
explicitly multi-turn prompt fixture. Use the prompt text itself as the target
to fix, since there is no code symbol here.

---

Nitpick comments:
In `@editor/lib/agent-chat/build-agent-send.ts`:
- Around line 57-60: `SendMessageFn` only types the `{text, files}` payload, so
the `{role, parts}` send path in `build-agent-send` is forced through an unsafe
cast. Extend `SendMessageFn` to accept both message shapes used by the send
flow, and update the call site in `buildAgentSend`/`sendMessage` to pass the
typed `{role, parts}` object directly without `as never`; keep the return type
aligned with the AI SDK contract so TypeScript can validate both branches.

In `@editor/scaffolds/desktop/canvas/slide-svg-resources.ts`:
- Around line 77-95: The resource materialization loop in slide-svg-resources is
performing independent file reads sequentially inside the for...of iteration,
which can add unnecessary latency for slides with multiple images. Refactor the
logic around resolveResourceRelPath, readFileBytes, and toDataUrl so each valid
href is processed concurrently with Promise.all while still preserving the
existing restores map updates and per-item error swallowing behavior. Keep
sequence++ unique per materialized resource, and ensure the attr.set and
restores.set calls still happen for each successful read.

In `@packages/grida-ai-agent/src/protocol/context.ts`:
- Around line 25-27: Update CONTEXT_MARKERS in context.ts to use
USER_TEMPLATE_SELECTION as the computed property key instead of a duplicated
string literal, so the registry stays aligned with the constant used by
message-view.ts. Keep the existing value mapping to "user_template_selection",
and make sure the dependency is explicit by referencing USER_TEMPLATE_SELECTION
directly in the CONTEXT_MARKERS object definition.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06a55810-a201-4c50-801b-45c919eafc25

📥 Commits

Reviewing files that changed from the base of the PR and between 7c51cae and e92e49e.

⛔ Files ignored due to path filters (4)
  • editor/public/assets/desktop-home/presets/image.svg is excluded by !**/*.svg
  • editor/public/assets/desktop-home/presets/slides.svg is excluded by !**/*.svg
  • editor/public/assets/desktop-home/presets/video.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (50)
  • SECURITY.md
  • editor/.gitignore
  • editor/app/desktop/welcome/page.tsx
  • editor/kits/agent-chat/message.tsx
  • editor/kits/composer/composer-react.tsx
  • editor/lib/agent-chat/bridge-transport.test.ts
  • editor/lib/agent-chat/bridge-transport.ts
  • editor/lib/agent-chat/build-agent-send.test.ts
  • editor/lib/agent-chat/build-agent-send.ts
  • editor/lib/agent-chat/index.ts
  • editor/lib/desktop/bridge.ts
  • editor/lib/desktop/welcome-handoff.ts
  • editor/package.json
  • editor/scaffolds/desktop/canvas/canvas-shell.tsx
  • editor/scaffolds/desktop/canvas/slide-surface.tsx
  • editor/scaffolds/desktop/canvas/slide-svg-resources.test.ts
  • editor/scaffolds/desktop/canvas/slide-svg-resources.ts
  • editor/scaffolds/desktop/home/application-preset.ts
  • editor/scaffolds/desktop/home/preset-chip.tsx
  • editor/scaffolds/desktop/home/preset-rail.tsx
  • editor/scaffolds/desktop/home/reference-gallery.tsx
  • editor/scaffolds/desktop/home/slide-scrub-preview.tsx
  • editor/scaffolds/desktop/home/slides-template-gallery.tsx
  • editor/scaffolds/desktop/home/slides-template-loader.ts
  • editor/scaffolds/desktop/home/slides-template-preview-dialog.tsx
  • editor/scaffolds/desktop/home/workspace-picker.tsx
  • editor/scaffolds/desktop/workbench/agent-pane.tsx
  • editor/scaffolds/desktop/workbench/use-workspace-file-save.ts
  • fixtures/prompts/README.md
  • fixtures/prompts/slides-prompts.txt
  • fixtures/prompts/slides-scenarios.jsonl
  • packages/grida-ai-agent/src/index.ts
  • packages/grida-ai-agent/src/protocol/context.ts
  • packages/grida-ai-agent/src/protocol/run.ts
  • packages/grida-ai-agent/src/runtime/index.ts
  • packages/grida-ai-agent/src/runtime/message-view.test.ts
  • packages/grida-ai-agent/src/runtime/message-view.ts
  • packages/grida-ai-agent/src/runtime/run-input.ts
  • packages/grida-ai-agent/src/runtime/workspace-agent-bindings.test.ts
  • packages/grida-ai-agent/src/runtime/workspace-agent-bindings.ts
  • packages/grida-daemon/src/http/routes/workspaces.create.test.ts
  • packages/grida-daemon/src/http/routes/workspaces.ts
  • packages/grida-daemon/src/protocol/resources.ts
  • packages/grida-daemon/src/server.ts
  • packages/grida-daemon/src/workspaces.test.ts
  • packages/grida-daemon/src/workspaces.ts
  • public/package.json
  • public/turbo.json
  • skills/dotcanvas/SKILL.md
  • skills/slides/SKILL.md

Comment thread editor/scaffolds/desktop/home/slides-template-loader.ts
Comment thread fixtures/prompts/slides-prompts.txt Outdated
@coderabbitai coderabbitai Bot added the enhancement New feature or request label Jul 8, 2026
The prior fix relaxed the composer's empty-text guard for `allowEmptySubmit`,
but `composer.submit()` was still called without `allow_empty`, so the composer
core returned null for a blank editor and `submit()` bailed at `if (!message)
return` BEFORE that relaxed guard — a picked-template Send with no typed ask was
still dropped and the template lost. Pass `allow_empty: allowEmptySubmit` into
`composer.submit()` (and widen the composer handle's `submit` type to the core's
`createMessage` params) so the empty message is produced and the guard below
does the gating.
@vercel vercel Bot temporarily deployed to Preview – blog July 8, 2026 16:03 Inactive
@vercel vercel Bot temporarily deployed to Preview – backgrounds July 8, 2026 16:03 Inactive
@vercel vercel Bot temporarily deployed to Preview – viewer July 8, 2026 16:03 Inactive
@coderabbitai coderabbitai Bot removed the enhancement New feature or request label Jul 8, 2026
@softmarshmallow softmarshmallow merged commit 2cc89a8 into main Jul 8, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai AI models, prompts, and pricing desktop this is a Grida Desktop App related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant