Repository navigation
feat: extract reusable CLI package primitives - #784
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (21)
✅ Files skipped from review due to trivial changes (5)
🚧 Files skipped from review as they are similar to previous changes (16)
📝 WalkthroughWalkthroughThis PR extracts shared factories for HTML app revision commands, block-document AI adapters, and DuckDB database AI adapters, then updates sqlrooms-cli-ui and mosaic to use those shared implementations and exported constants. ChangesShared HTML app revision commands and block-document DTO
Shared block-document AI command adapter
Shared DuckDB database AI adapter
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Host
participant createHtmlAppRevisionCommands
participant resolveHtmlAppCommandAppId
participant commitHtmlAppRevision
Host->>createHtmlAppRevisionCommands: execute HTML_APP_WRITE_REVISION_COMMAND_ID
createHtmlAppRevisionCommands->>resolveHtmlAppCommandAppId: resolve appId
resolveHtmlAppCommandAppId-->>createHtmlAppRevisionCommands: appId
createHtmlAppRevisionCommands->>commitHtmlAppRevision: commit patch/metadata
commitHtmlAppRevision-->>createHtmlAppRevisionCommands: revisionId, revisionName
createHtmlAppRevisionCommands-->>Host: success payload
sequenceDiagram
participant Adapter as createBlockDocumentCommandAiAdapter
participant Store
participant Commands as invokeCommand
Adapter->>Store: ensureBlockDocument(artifactId)
Adapter->>Commands: invokeCommand(BLOCK_DOCUMENT_APPEND_BLOCKS_COMMAND_ID, payload, {surface: 'ai', actor: BLOCK_DOCUMENT_AGENT_ACTOR})
Commands-->>Adapter: result (blockId/blockIds)
Adapter-->>Store: return derived blockId
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
packages/mosaic/src/index.ts (1)
447-447: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover the new root re-export with a public-entrypoint test.
The current test only imports from
../src/ai, so it doesn't lock in the newpackages/mosaic/src/index.tswiring. Add one assertion through the package root entrypoint to keep this API covered.🤖 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/mosaic/src/index.ts` at line 447, The new root re-export in the package entrypoint is not covered by tests, so add a public-entrypoint assertion for createDuckDbDatabaseAiAdapter through the main index export. Update the existing public API test suite to import from the package root (the module that contains the createDuckDbDatabaseAiAdapter re-export) and verify the symbol is available there, alongside the current ../src/ai coverage.Source: Coding guidelines
packages/app-runtime/src/HtmlAppRevisionCommands.ts (1)
36-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
.removeDefault()is a deprecated legacy alias in Zod 4.Confirmed via Zod docs: in Zod 4,
.removeDefault()onZodDefaultstill works but is a "Legacy method (deprecated)";.unwrap()is the current equivalent. Not a functional bug, but worth migrating to avoid relying on a deprecated API.♻️ Proposed fix
const HtmlAppRestoreRevisionCommandInput = - HtmlAppRevisionCommandInput.removeDefault().extend({ + HtmlAppRevisionCommandInput.unwrap().extend({ revisionId: z.string().describe('Target revision id for restore.'), });🤖 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/app-runtime/src/HtmlAppRevisionCommands.ts` around lines 36 - 39, The `HtmlAppRestoreRevisionCommandInput` schema is using the deprecated Zod 4 legacy alias `.removeDefault()`. Update the `HtmlAppRevisionCommandInput` transformation to use `.unwrap()` instead, keeping the same schema shape while removing reliance on the deprecated API.packages/documents/__tests__/createBlockDocumentCommandAiAdapter.test.ts (1)
71-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the failure and validation branches.
Current tests only cover the happy path and a compatible-artifact predicate. Missing coverage for:
addBlock/ensureBlockDocumentthrowing when the artifact type doesn't matchisBlockDocumentArtifact, andaddBlockthrowing whenresult.successisfalse.As per coding guidelines, "Add or update tests when changing behavior or public API, when practical."
🤖 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/documents/__tests__/createBlockDocumentCommandAiAdapter.test.ts` around lines 71 - 111, Add tests for the missing failure paths in createBlockDocumentCommandAiAdapter: verify addBlock and ensureBlockDocument reject when the store artifact type does not satisfy isBlockDocumentArtifact, and verify addBlock throws when invokeCommand returns a result with success set to false. Extend the existing createMockStore-based setup in createBlockDocumentCommandAiAdapter.test.ts to simulate these cases, and assert the errors are surfaced from the adapter methods. Keep the happy-path expectations intact while covering the validation and command-failure branches.Source: Coding guidelines
apps/sqlrooms-cli-ui/src/ai/createAddHtmlAppBlockDocumentBlockTool.ts (1)
46-53: 🗄️ Data Integrity & Integration | 🔵 TrivialUnsafe
ascast hides a field mismatch betweenHtmlAppBlockDocumentBlockandBlockDocumentStatefulBlockBlock.
HtmlAppBlockDocumentBlock(from@sqlrooms/app-runtime) includes anintentfield thatBlockDocumentStatefulBlockBlockdoesn't declare (see companion comment onhtml-app-block-document.ts). The cast type-checks only because extra properties don't break structural subtyping, but it silently papers over the fact that the two types aren't actually the same shape. If any downstream consumer re-validates against the zod schema,intentwould be dropped without a compile-time signal here.Consider a purpose-built return type (or narrowing/validating explicitly) instead of an
ascast, so a future schema/field drift surfaces as a type error rather than a silent runtime behavior change.🤖 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 `@apps/sqlrooms-cli-ui/src/ai/createAddHtmlAppBlockDocumentBlockTool.ts` around lines 46 - 53, The unsafe cast in createAddHtmlAppBlockDocumentBlockTool is masking a shape mismatch between HtmlAppBlockDocumentBlock and BlockDocumentStatefulBlockBlock. Remove the blanket as assertion and make the return type explicit by either returning the exact runtime block shape from createHtmlAppRuntimeBlockDocumentBlock or introducing a dedicated mapped/validated return type that includes the intent field if it is meant to survive. Use the createHtmlAppRuntimeBlockDocumentBlock result and the block return type in this module to ensure any future schema drift becomes a compile-time error instead of being silently dropped.
🤖 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 `@packages/app-runtime/__tests__/HtmlAppRevisionCommands.test.ts`:
- Around line 78-140: The test suite for createHtmlAppRevisionCommands is
missing coverage for HTML_APP_RENAME_COMMAND_ID, so add a rename test alongside
the existing write/restore/undo/redo cases. Exercise the rename command through
getCommand(...).execute with a real title change and a mutating renameHtmlApp
mock, and assert the returned appId/title/revision fields. Make sure the test
covers the branching behavior in the rename path, including the
commit-vs-plain-rename flow and the title-unchanged detection in
HtmlAppRevisionCommands.
In `@packages/app-runtime/src/html-app-block-document.ts`:
- Around line 3-13: Add tsdoc to the exported type HtmlAppBlockDocumentBlock in
html-app-block-document.ts so it matches the documentation style used by
CreateHtmlAppBlockDocumentBlockOptions and the exported function. Add a brief
top-level doc comment describing what the type represents and, if helpful, note
any key fields such as type, blockType, ownership, and intent; keep it directly
above the HtmlAppBlockDocumentBlock declaration.
In `@packages/app-runtime/src/HtmlAppRevisionCommands.ts`:
- Around line 218-263: The Rename HTML app command currently claims to be
idempotent even though HtmlAppRevisionCommands.execute can create a new revision
via commitHtmlAppRevision whenever files or metadata trigger the revision path,
which can duplicate history on retries. Update the command metadata for
HTML_APP_RENAME_COMMAND_ID so it no longer advertises blanket idempotence, or
make it conditional if the command framework supports that, and keep the
behavior in execute consistent with the title-only path handled by
renameHtmlApp.
- Around line 244-284: The unchanged-result check in HtmlAppRevisionCommands
uses the mutable current app.title, which can be updated by
commitHtmlAppRevision or renameHtmlApp before the response is built. Update the
success payload logic in the rename command to compare against previousTitle
instead of app.title so the `html-app-title-unchanged` code is only returned
when the title truly did not change; keep the rest of the response data sourced
from nextApp as it is now.
---
Nitpick comments:
In `@apps/sqlrooms-cli-ui/src/ai/createAddHtmlAppBlockDocumentBlockTool.ts`:
- Around line 46-53: The unsafe cast in createAddHtmlAppBlockDocumentBlockTool
is masking a shape mismatch between HtmlAppBlockDocumentBlock and
BlockDocumentStatefulBlockBlock. Remove the blanket as assertion and make the
return type explicit by either returning the exact runtime block shape from
createHtmlAppRuntimeBlockDocumentBlock or introducing a dedicated
mapped/validated return type that includes the intent field if it is meant to
survive. Use the createHtmlAppRuntimeBlockDocumentBlock result and the block
return type in this module to ensure any future schema drift becomes a
compile-time error instead of being silently dropped.
In `@packages/app-runtime/src/HtmlAppRevisionCommands.ts`:
- Around line 36-39: The `HtmlAppRestoreRevisionCommandInput` schema is using
the deprecated Zod 4 legacy alias `.removeDefault()`. Update the
`HtmlAppRevisionCommandInput` transformation to use `.unwrap()` instead, keeping
the same schema shape while removing reliance on the deprecated API.
In `@packages/documents/__tests__/createBlockDocumentCommandAiAdapter.test.ts`:
- Around line 71-111: Add tests for the missing failure paths in
createBlockDocumentCommandAiAdapter: verify addBlock and ensureBlockDocument
reject when the store artifact type does not satisfy isBlockDocumentArtifact,
and verify addBlock throws when invokeCommand returns a result with success set
to false. Extend the existing createMockStore-based setup in
createBlockDocumentCommandAiAdapter.test.ts to simulate these cases, and assert
the errors are surfaced from the adapter methods. Keep the happy-path
expectations intact while covering the validation and command-failure branches.
In `@packages/mosaic/src/index.ts`:
- Line 447: The new root re-export in the package entrypoint is not covered by
tests, so add a public-entrypoint assertion for createDuckDbDatabaseAiAdapter
through the main index export. Update the existing public API test suite to
import from the package root (the module that contains the
createDuckDbDatabaseAiAdapter re-export) and verify the symbol is available
there, alongside the current ../src/ai coverage.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 67207c93-5313-4636-8bc6-5e9d1f1c1a71
📒 Files selected for processing (21)
apps/sqlrooms-cli-ui/src/__tests__/createHtmlAppRevisionCommands.test.tsapps/sqlrooms-cli-ui/src/__tests__/createWorksheetAiAdapter.test.tsapps/sqlrooms-cli-ui/src/ai/createAddHtmlAppBlockDocumentBlockTool.tsapps/sqlrooms-cli-ui/src/createDatabaseAiAdapter.tsapps/sqlrooms-cli-ui/src/createHtmlAppAgent.tsapps/sqlrooms-cli-ui/src/createHtmlAppRevisionCommands.tsapps/sqlrooms-cli-ui/src/createWorksheetAiAdapter.tspackages/app-runtime/README.mdpackages/app-runtime/__tests__/HtmlAppRevisionCommands.test.tspackages/app-runtime/src/HtmlAppRevisionCommands.tspackages/app-runtime/src/html-app-block-document.tspackages/app-runtime/src/index.tspackages/documents/README.mdpackages/documents/__tests__/createBlockDocumentCommandAiAdapter.test.tspackages/documents/src/createBlockDocumentCommandAiAdapter.tspackages/documents/src/index.tspackages/mosaic/README.mdpackages/mosaic/__tests__/createDatabaseAiAdapter.test.tspackages/mosaic/src/ai.tspackages/mosaic/src/ai/createDatabaseAiAdapter.tspackages/mosaic/src/index.ts
1a3d28b to
7377770
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/documents/__tests__/createBlockDocumentCommandAiAdapter.test.ts (1)
8-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing coverage for
setCurrentBlockDocument.The mock store already tracks
setCurrentArtifact(Line 20, exposed at Line 67) but no test ever callsadapter.setCurrentBlockDocumentor asserts it delegates tostore.getState().artifacts.setCurrentArtifact. Since this is one of the four public methods introduced by the new adapter factory, it's worth adding a small test for parity with the other three methods.✅ Suggested test addition
+ it('delegates setCurrentBlockDocument to the artifacts store', () => { + const {store} = createMockStore(); + const adapter = createBlockDocumentCommandAiAdapter({store}); + const spy = jest.spyOn(store.getState().artifacts, 'setCurrentArtifact'); + + adapter.setCurrentBlockDocument('doc-1'); + + expect(spy).toHaveBeenCalledWith('doc-1'); + });As per coding guidelines, "Add or update tests when changing behavior or public API, when practical."
Also applies to: 71-155
🤖 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/documents/__tests__/createBlockDocumentCommandAiAdapter.test.ts` around lines 8 - 69, Add test coverage for the adapter’s setCurrentBlockDocument public method by using the existing createMockStore helper and asserting it calls store.getState().artifacts.setCurrentArtifact; the mock already exposes setCurrentArtifact but no test exercises this delegation. Update the createBlockDocumentCommandAiAdapter test suite to invoke adapter.setCurrentBlockDocument and verify the underlying artifact state setter is called with the expected block document/artifact input, alongside the other adapter method parity checks.Source: Coding guidelines
packages/app-runtime/__tests__/HtmlAppRevisionCommands.test.ts (1)
127-215: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRename tests still skip the
files-provided branch.
shouldCommitRevision = files || (metadata && previousTitle !== trimmedTitle)in the implementation has a distinct path whenfilesis supplied (forces a commit even without metadata/title change), but no test exercises it here.As per coding guidelines, "Add or update tests when changing behavior or public API, when practical."
it('commits a revision when files are provided even without a title change', async () => { const {commands, state, renameHtmlApp, commitHtmlAppRevision} = createState(); const result = await getCommand( commands, HTML_APP_RENAME_COMMAND_ID, ).execute(createCommandContext(state), { appId: 'app-1', title: 'App', files: {'/index.html': '<html><title>App v2</title></html>'}, }); expect(renameHtmlApp).not.toHaveBeenCalled(); expect(commitHtmlAppRevision).toHaveBeenCalled(); expect(result).toMatchObject({success: true, commandId: HTML_APP_RENAME_COMMAND_ID}); });🤖 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/app-runtime/__tests__/HtmlAppRevisionCommands.test.ts` around lines 127 - 215, The rename command tests still miss the branch where files force a revision commit even when the title does not change. Add a test alongside the existing HTML_APP_RENAME_COMMAND_ID cases that executes the command with files provided and the same title, then assert renameHtmlApp is not called, commitHtmlAppRevision is called, and the result is successful. Use createState and getCommand to cover the files-driven path in the rename command implementation.Source: Coding guidelines
🤖 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.
Nitpick comments:
In `@packages/app-runtime/__tests__/HtmlAppRevisionCommands.test.ts`:
- Around line 127-215: The rename command tests still miss the branch where
files force a revision commit even when the title does not change. Add a test
alongside the existing HTML_APP_RENAME_COMMAND_ID cases that executes the
command with files provided and the same title, then assert renameHtmlApp is not
called, commitHtmlAppRevision is called, and the result is successful. Use
createState and getCommand to cover the files-driven path in the rename command
implementation.
In `@packages/documents/__tests__/createBlockDocumentCommandAiAdapter.test.ts`:
- Around line 8-69: Add test coverage for the adapter’s setCurrentBlockDocument
public method by using the existing createMockStore helper and asserting it
calls store.getState().artifacts.setCurrentArtifact; the mock already exposes
setCurrentArtifact but no test exercises this delegation. Update the
createBlockDocumentCommandAiAdapter test suite to invoke
adapter.setCurrentBlockDocument and verify the underlying artifact state setter
is called with the expected block document/artifact input, alongside the other
adapter method parity checks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 21b73895-2402-4dfd-88f1-641b89fc0d0d
📒 Files selected for processing (21)
apps/sqlrooms-cli-ui/src/__tests__/createHtmlAppRevisionCommands.test.tsapps/sqlrooms-cli-ui/src/__tests__/createWorksheetAiAdapter.test.tsapps/sqlrooms-cli-ui/src/ai/createAddHtmlAppBlockDocumentBlockTool.tsapps/sqlrooms-cli-ui/src/createDatabaseAiAdapter.tsapps/sqlrooms-cli-ui/src/createHtmlAppAgent.tsapps/sqlrooms-cli-ui/src/createHtmlAppRevisionCommands.tsapps/sqlrooms-cli-ui/src/createWorksheetAiAdapter.tspackages/app-runtime/README.mdpackages/app-runtime/__tests__/HtmlAppRevisionCommands.test.tspackages/app-runtime/src/HtmlAppRevisionCommands.tspackages/app-runtime/src/html-app-block-document.tspackages/app-runtime/src/index.tspackages/documents/README.mdpackages/documents/__tests__/createBlockDocumentCommandAiAdapter.test.tspackages/documents/src/createBlockDocumentCommandAiAdapter.tspackages/documents/src/index.tspackages/mosaic/README.mdpackages/mosaic/__tests__/createDatabaseAiAdapter.test.tspackages/mosaic/src/ai.tspackages/mosaic/src/ai/createDatabaseAiAdapter.tspackages/mosaic/src/index.ts
✅ Files skipped from review due to trivial changes (5)
- packages/mosaic/src/ai/createDatabaseAiAdapter.ts
- apps/sqlrooms-cli-ui/src/createHtmlAppAgent.ts
- packages/app-runtime/README.md
- packages/documents/README.md
- packages/mosaic/README.md
🚧 Files skipped from review as they are similar to previous changes (14)
- packages/mosaic/tests/createDatabaseAiAdapter.test.ts
- packages/documents/src/index.ts
- packages/mosaic/src/index.ts
- packages/mosaic/src/ai.ts
- apps/sqlrooms-cli-ui/src/tests/createWorksheetAiAdapter.test.ts
- apps/sqlrooms-cli-ui/src/createDatabaseAiAdapter.ts
- packages/documents/src/createBlockDocumentCommandAiAdapter.ts
- packages/app-runtime/src/html-app-block-document.ts
- apps/sqlrooms-cli-ui/src/createWorksheetAiAdapter.ts
- apps/sqlrooms-cli-ui/src/ai/createAddHtmlAppBlockDocumentBlockTool.ts
- apps/sqlrooms-cli-ui/src/tests/createHtmlAppRevisionCommands.test.ts
- packages/app-runtime/src/index.ts
- apps/sqlrooms-cli-ui/src/createHtmlAppRevisionCommands.ts
- packages/app-runtime/src/HtmlAppRevisionCommands.ts
7377770 to
43c6f86
Compare
Summary
@sqlrooms/documentswith canonical append command and actor constants.@sqlrooms/app-runtime.Validation
pnpm buildpnpm --filter @sqlrooms/documents test --runInBand createBlockDocumentCommandAiAdapter.test.tspnpm --filter @sqlrooms/app-runtime test --runInBand HtmlAppRevisionCommands.test.tspnpm --filter @sqlrooms/mosaic test --runInBand createDatabaseAiAdapter.test.tspnpm --filter sqlrooms-cli-app test --runInBand createWorksheetAiAdapter.test.ts createHtmlAppRevisionCommands.test.tsknip,turbo typecheck,madge --circular,turbo testThe Obsidian plan checklist is updated through Stage 6; Follow-up remains unchecked as requested.
Summary by CodeRabbit