Skip to content
This repository was archived by the owner on Jun 29, 2026. It is now read-only.

Refactor workspace AI tool surface and add codemode runtime#22

Merged
urjitc merged 7 commits into
mainfrom
refactor/workspace-ai-tool-surface
Jun 23, 2026
Merged

Refactor workspace AI tool surface and add codemode runtime#22
urjitc merged 7 commits into
mainfrom
refactor/workspace-ai-tool-surface

Conversation

@urjitc

@urjitc urjitc commented Jun 23, 2026

Copy link
Copy Markdown
Member

Summary

  • normalize the workspace AI tool contracts around items/failed style outputs and surface output schemas in the inspector
  • collapse duplicated workspace tool and runtime registration boilerplate to keep the AI tool surface easier to maintain
  • add the codemode runtime, loader binding, and extracted UTC time tools for the new execution path

Testing

  • pnpm -C web run typecheck
  • pre-commit hooks on both commits (biome, compiler, typecheck)

Summary by cubic

Refactored the workspace AI tool surface with strict input/output schemas and consistent { items, failed } results, and added a codemode runtime to run sandboxed JavaScript with tools and optional state FS. Time tools now support IANA time zones and return formatted local time; the chat UI gets a floating toolbar and transcript rail.

  • New Features

    • Added codemode_execute via @cloudflare/codemode; bound LOADER and exported CodemodeRuntime. state is provided only when the workspace implements an FS; active tools are selected per turn.
    • Time tools: time_get_current and time_calculate_relative accept optional time_zone, return UTC timestamps plus localDateTime, and use strict input/output schemas. Inspector now shows tool output schemas.
  • Refactors

    • Workspace reads: only documents/files are readable; folder paths fail with path_is_folder. Files report status: ready | pending | failed | unsupported with slimmer paging; removed legacy read shims.
    • Tools are strict and validate outputs; results consistently use { items, failed }. Consolidated registration; replaced multiple sandbox file ops with sandbox_bash when available; codemode_execute always available with narrowed state wiring.
    • Web tools return structured results with truncation flags: markdown { content, truncated }, links { items, truncated }. Kernel list now returns { path, more, items, failed } with items { path, type }.
    • Tightened chat panel chrome with a floating toolbar and a transcript rail for consistent spacing.

Written for commit 80da38d. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • AI tools now expose and display output schemas in the inspector.
    • Added time tools (time_get_current, time_calculate_relative) with optional IANA time zone support.
  • Improvements
    • Web tools’ markdown/link results were refined to return clearer truncated payloads.
    • Workspace AI/kernel operations were streamlined to return simpler items + failed results (with less nested metadata).
    • AI chat loading/transcript UI now uses a consistent transcript rail layout.
  • Improvements
    • Updated AI gateway authentication configuration (new API key binding).

@capy-ai

capy-ai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e34aa5f9-207a-4dbe-b6e6-1250e368a1ce

📥 Commits

Reviewing files that changed from the base of the PR and between e5609d2 and 80da38d.

📒 Files selected for processing (13)
  • src/features/workspaces/ai/ai-thread-runtime.ts
  • src/features/workspaces/ai/ai-thread.ts
  • src/features/workspaces/ai/time-tools.ts
  • src/features/workspaces/ai/web-tools.ts
  • src/features/workspaces/ai/workspace-kernel-ai-read.ts
  • src/features/workspaces/ai/workspace-tools.ts
  • src/features/workspaces/components/AiChatPanel.tsx
  • src/features/workspaces/components/ai-chat/AiChatMessageList.tsx
  • src/features/workspaces/components/ai-chat/AiChatPanelToolbar.tsx
  • src/features/workspaces/components/ai-chat/AiChatTranscriptRail.tsx
  • src/features/workspaces/components/ai-chat/ai-chat-layout.ts
  • src/features/workspaces/kernel/workspace-kernel-rows.ts
  • src/features/workspaces/kernel/workspace-kernel-types.ts

📝 Walkthrough

Walkthrough

The PR integrates @cloudflare/codemode as a runtime dependency and wires it into the AI thread via a new codemode_execute tool and createAIThreadTurnToolConfig. All workspace kernel CRUD operations (list, create, delete, move, rename, read, edit) are normalized to return { items, failed }, dropping nested item objects, title, and batch status. Workspace tools gain explicit Zod output schemas and a centralized thread-tool wrapper. Time tools are extracted to a new module, web truncation helpers are replaced with structured alternatives, inspector views gain outputSchema display, and AI chat UI components adopt a centralized transcript rail layout.

Changes

AI Tooling Overhaul: Codemode Integration, Normalized Contracts, Catalog Runtime

Layer / File(s) Summary
Codemode dependency and runtime wiring
package.json, src/server.ts, wrangler.jsonc, worker-configuration.d.ts
Adds @cloudflare/codemode@^0.4.1, re-exports CodemodeRuntime from the server entry, configures a LOADER worker binding, and updates environment types to include LOADER and replace AI_GATEWAY_ID with AI_GATEWAY_API_KEY.
Inspector outputSchema type, parsing, serialization, and UI
src/features/workspaces/ai/ai-inspector-view-types.ts, src/features/workspaces/ai/ai-inspector-view-parsing.ts, src/features/workspaces/ai/ai-inspector-serialization.ts, src/features/workspaces/components/ai-chat/AiChatInspectorViews.tsx
Adds optional outputSchema to AIInspectorToolDefinitionView, populates and sanitizes it in parsing/serialization via getInspectableSchema, and renders an "Output schema" JsonDisclosure in ToolDefinitionCard alongside the "Input schema".
Workspace kernel result contract normalization
src/features/workspaces/ai/workspace-kernel-ai-common.ts, src/features/workspaces/kernel/workspace-kernel-list.ts, src/features/workspaces/ai/workspace-kernel-ai-create.ts, src/features/workspaces/ai/workspace-kernel-ai-delete.ts, src/features/workspaces/ai/workspace-kernel-ai-move.ts, src/features/workspaces/ai/workspace-kernel-ai-rename.ts, src/features/workspaces/ai/workspace-kernel-ai-edit.ts, src/features/workspaces/ai/workspace-kernel-ai-read.ts
Removes WorkspaceKernelAiBatchStatus/getWorkspaceKernelAiBatchStatus. All CRUD operations return { items, failed } — flattening nested item objects, removing title/status/count/deleted/moved/renamed/created fields. Read items use new { type, path, status, content?, page? } shape; folders throw instead of listing. List wraps WorkspaceKernelPathError to populate failed.
Workspace tools Zod output schemas and thread-tool wrapper
src/features/workspaces/ai/workspace-tools.ts
Introduces createFailureSchema, explicit Zod output schemas for all workspace operations (list/read/create/delete/move/rename/edit), and createWorkspaceThreadTool to centralize strict tool creation with thread context injection. Removes recursive from read input. Adds typed input examples for move and delete.
Time tools extraction and web tools truncation
src/features/workspaces/ai/time-tools.ts, src/features/workspaces/ai/web-tools.ts
Extracts createAIThreadTimeTools into a new module with time_get_current and time_calculate_relative backed by Zod schemas, time zone resolution, and UTC calendar arithmetic. Replaces truncateText/boundJsonResult in web tools with truncateMarkdown/truncateLinks returning { content/items, truncated } instead of prior fallback behavior.
AI thread tool catalog, codemode_execute, and turn config
src/features/workspaces/ai/ai-thread-runtime.ts, src/features/workspaces/ai/ai-thread.ts
Replaces AI_THREAD_ACTIVE_TOOLS/getAIThreadActiveTools with catalog-based system. Adds codemode_execute tool wired to Durable Object state and sandbox filesystem. Exports createAIThreadTurnToolConfig selecting tools by canMutate and timeZone. ai-thread.ts beforeTurn spreads the turn config instead of setting activeTools.
AI chat UI components with transcript rail layout
src/features/workspaces/components/ai-chat/AiChatTranscriptRail.tsx, src/features/workspaces/components/ai-chat/ai-chat-layout.ts, src/features/workspaces/components/AiChatPanel.tsx, src/features/workspaces/components/ai-chat/AiChatMessageList.tsx, src/features/workspaces/components/ai-chat/AiChatPanelToolbar.tsx
Introduces AiChatTranscriptRail component and aiChatMessageTopInsetClassName constant. Wraps message rows, error states, and loading content with the transcript rail and conditional top inset. Refactors AiChatPanelToolbar from fixed header to absolutely positioned top-right container.
Workspace kernel event and type cleanup
src/features/workspaces/kernel/workspace-kernel-rows.ts, src/features/workspaces/kernel/workspace-kernel-types.ts
Simplifies parseWorkspaceEventPayload to directly JSON.parse without conditional normalization. Removes "needs_review" from WorkspaceKernelFileProjectionStatus union.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(100, 149, 237, 0.5)
    Note over AIThread,CodemodeRuntime: Per-turn tool configuration
    participant AIThread as AIThread.beforeTurn
    participant TurnConfig as createAIThreadTurnToolConfig
    participant Catalog as AIThreadToolCatalog
    participant CodemodeRuntime as CodemodeRuntime (LOADER)
  end
  AIThread->>TurnConfig: { env, ctx, workspace, getThreadContext, canMutate, timeZone }
  TurnConfig->>Catalog: getActiveToolNames(canMutate)
  Catalog-->>TurnConfig: string[] of active tool names
  TurnConfig->>Catalog: getCodemodeTools(canMutate)
  Catalog-->>TurnConfig: filtered ToolSet for codemode sandbox
  TurnConfig->>CodemodeRuntime: install codemode_execute(sandbox backend + tool subset)
  TurnConfig-->>AIThread: { activeTools, tools } spread into TurnConfig
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • ThinkEx-OSS/new-thinkex#11: Modifies the same ai-thread-runtime.ts and ai-thread.ts files around canMutate tool selection and active-tool wiring, directly overlapping with the getAIThreadActiveToolscreateAIThreadTurnToolConfig refactor.
  • ThinkEx-OSS/new-thinkex#16: Modifies src/features/workspaces/components/ai-chat/AiChatMessageList.tsx row rendering structure and container layout, overlapping with the transcript rail wrapper changes.

Suggested labels

capy

Poem

🐇 Hopping through the code one night,
I shuffled tools from left to right.
items and failed — clean and neat,
No more nested shapes to defeat!
The codemode sandbox starts to hum,
A catalog of tools, all come.
✨ This bunny's work here is done! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main objectives: refactoring workspace AI tool contracts and introducing codemode runtime support, which directly align with the extensive changes across AI tool files.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 refactor/workspace-ai-tool-surface

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.

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/workspaces/ai/workspace-kernel-ai-read.ts (1)

206-225: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Empty files incorrectly treated as failed.

Line 206 uses a falsy check projection?.content && which will fail for empty files that have content: "" (empty string). An empty but successfully extracted file with status: "ready" and content: "" will bypass lines 212-218, fall through to line 221, and getFileReadStatus will return "failed" at line 246, incorrectly marking the empty file as failed.

🐛 Proposed fix to handle empty files correctly
-	if (projection?.content && isReadableProjectionStatus(projection.status)) {
+	if (projection && projection.content !== null && isReadableProjectionStatus(projection.status)) {
 		const page = pageWorkspaceAiMarkdown(projection.content, {
 			limit: input.contentLimit,
 			offset: input.contentOffset,
 		});
🤖 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 `@src/features/workspaces/ai/workspace-kernel-ai-read.ts` around lines 206 -
225, The condition on line 206 using `projection?.content &&` performs a falsy
check that incorrectly treats empty strings as missing content, causing empty
files to fall through to the getFileReadStatus call which incorrectly marks them
as failed. Change the condition to explicitly check if projection.content is not
null and not undefined (rather than relying on truthiness), so that empty files
with a valid "ready" status are properly handled in the first return block
instead of being misclassified as failed in the second return statement.
🧹 Nitpick comments (1)
src/features/workspaces/ai/web-tools.ts (1)

31-58: 🗄️ Data Integrity & Integration | 🔵 Trivial

Add output schemas to web_markdown and web_links tools for consistency and discoverability.

The web_markdown and web_links tools return structured objects { content, truncated } and { items, truncated } respectively, but lack outputSchema definitions. Other tools in the codebase (see time_get_current and time_calculate_relative in time-tools.ts) include output schemas to expose their contract to tool metadata and inspector systems. Without these schemas, the new structured web result contract is not discoverable.

Suggested schema wiring
+const webMarkdownOutputSchema = z.object({
+	content: z.string(),
+	truncated: z.boolean(),
+});
+
+const webLinksOutputSchema = z.object({
+	items: z.array(z.string()),
+	truncated: z.boolean(),
+});
+
 export function createAIThreadWebTools(env: Env): ToolSet {
 	const browser = env.BROWSER as unknown as QuickActionBinding;
 
 	return {
 		web_markdown: tool({
 			description:
 				"Load a public webpage and return its rendered content as Markdown.",
 			inputSchema: browserPageInputSchema,
 			inputExamples: browserPageInputExamples,
+			outputSchema: webMarkdownOutputSchema,
 			strict: true,
 			execute: async ({ url }) => {
 				const safeUrl = assertPublicHttpUrl(url);
 				return truncateMarkdown(
@@
 		web_links: tool({
 			description: "Load a public webpage and return its rendered links.",
 			inputSchema: browserPageInputSchema,
 			inputExamples: browserPageInputExamples,
+			outputSchema: webLinksOutputSchema,
 			strict: true,
 			execute: async ({ url }) => {
🤖 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 `@src/features/workspaces/ai/web-tools.ts` around lines 31 - 58, The
web_markdown and web_links tools are missing outputSchema definitions that
describe their return values, making their output contract not discoverable by
tool metadata and inspector systems. Add an outputSchema property to both the
web_markdown tool and web_links tool definitions that describes their respective
return structures: web_markdown returns { content, truncated } and web_links
returns { items, truncated }. Follow the same pattern used in other tools like
time_get_current and time_calculate_relative from time-tools.ts to ensure
consistency across the codebase.
🤖 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 `@src/features/workspaces/ai/ai-thread-runtime.ts`:
- Around line 84-106: Remove the unsafe type assertion `as WorkspaceFsLike` on
the input.workspace parameter being passed to createWorkspaceStateBackend in the
createAIThreadTurnToolConfig function. Instead, update the input parameter type
in the function signature to accept WorkspaceFsLike instead of WorkspaceLike,
ensuring the workspace object is known to implement all 16 required methods that
createWorkspaceStateBackend expects, rather than just the 8 methods provided by
WorkspaceLike.

In `@src/features/workspaces/ai/time-tools.ts`:
- Around line 14-15: The createRelativeOffsetFieldSchema function creates a Zod
schema with only a minimum bound (.min(0)) but no maximum bound, allowing
arbitrarily large offset values that can produce invalid Date objects when used
at line 81. Add a .max() constraint to the z.number().int() chain to limit the
offset values to a safe range that will not produce invalid dates, ensuring
dates remain within valid bounds when calculations are performed.

In `@src/features/workspaces/ai/web-tools.ts`:
- Around line 77-85: The truncateLinks function inefficiently serializes the
entire items array to JSON before checking if it exceeds
MAX_BROWSER_RESULT_CHARS, creating a large intermediate string in memory even
when truncation is needed. Instead of calling JSON.stringify on the full array
upfront, incrementally build the JSON representation by adding items one at a
time and stop accumulating once the length would exceed the character limit.
This avoids allocating unnecessary memory for pages with many links.

---

Outside diff comments:
In `@src/features/workspaces/ai/workspace-kernel-ai-read.ts`:
- Around line 206-225: The condition on line 206 using `projection?.content &&`
performs a falsy check that incorrectly treats empty strings as missing content,
causing empty files to fall through to the getFileReadStatus call which
incorrectly marks them as failed. Change the condition to explicitly check if
projection.content is not null and not undefined (rather than relying on
truthiness), so that empty files with a valid "ready" status are properly
handled in the first return block instead of being misclassified as failed in
the second return statement.

---

Nitpick comments:
In `@src/features/workspaces/ai/web-tools.ts`:
- Around line 31-58: The web_markdown and web_links tools are missing
outputSchema definitions that describe their return values, making their output
contract not discoverable by tool metadata and inspector systems. Add an
outputSchema property to both the web_markdown tool and web_links tool
definitions that describes their respective return structures: web_markdown
returns { content, truncated } and web_links returns { items, truncated }.
Follow the same pattern used in other tools like time_get_current and
time_calculate_relative from time-tools.ts to ensure consistency across the
codebase.
🪄 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: f99b4808-2a43-4e54-8f6e-fe22ecab0fa6

📥 Commits

Reviewing files that changed from the base of the PR and between 66cb310 and e5609d2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (21)
  • package.json
  • src/features/workspaces/ai/ai-inspector-serialization.ts
  • src/features/workspaces/ai/ai-inspector-view-parsing.ts
  • src/features/workspaces/ai/ai-inspector-view-types.ts
  • src/features/workspaces/ai/ai-thread-runtime.ts
  • src/features/workspaces/ai/ai-thread.ts
  • src/features/workspaces/ai/time-tools.ts
  • src/features/workspaces/ai/web-tools.ts
  • src/features/workspaces/ai/workspace-kernel-ai-common.ts
  • src/features/workspaces/ai/workspace-kernel-ai-create.ts
  • src/features/workspaces/ai/workspace-kernel-ai-delete.ts
  • src/features/workspaces/ai/workspace-kernel-ai-edit.ts
  • src/features/workspaces/ai/workspace-kernel-ai-move.ts
  • src/features/workspaces/ai/workspace-kernel-ai-read.ts
  • src/features/workspaces/ai/workspace-kernel-ai-rename.ts
  • src/features/workspaces/ai/workspace-tools.ts
  • src/features/workspaces/components/ai-chat/AiChatInspectorViews.tsx
  • src/features/workspaces/kernel/workspace-kernel-list.ts
  • src/server.ts
  • worker-configuration.d.ts
  • wrangler.jsonc
💤 Files with no reviewable changes (1)
  • src/features/workspaces/ai/workspace-kernel-ai-common.ts

Comment thread src/features/workspaces/ai/ai-thread-runtime.ts
Comment thread src/features/workspaces/ai/time-tools.ts Outdated
Comment thread src/features/workspaces/ai/web-tools.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR normalizes workspace AI tool contracts to a consistent { items, failed } shape, adds strict input/output schemas surfaced in the inspector, collapses tool-registration boilerplate into a descriptor-driven catalog, and introduces a codemode_execute tool backed by @cloudflare/codemode for sandboxed JavaScript execution with workspace/web/time tool access.

  • Output contract normalization: All workspace mutation tools (create, delete, move, rename, edit) and workspace_read_items now return { items, failed } instead of bespoke shapes, with Zod output schemas exposed to the inspector.
  • Read tool simplification: workspace_read_items now only handles documents and files; folder paths return a path_is_folder failure (root path only — see comment), and per-item detail is collapsed into a single status enum.
  • Codemode runtime: CodemodeRuntime is exported from server.ts, LOADER binding added to wrangler.jsonc/worker-configuration.d.ts, and codemode_execute is wired per-turn via createAIThreadTurnToolConfig with access to the full (access-scoped) tool catalog.

Confidence Score: 3/5

The PR is largely safe but has one defect in the read path that turns a normal user input (a non-root folder path) into an unhandled server error.

The read tool now throws a generic, uncaught Error when the caller passes any non-root folder path (e.g., /My Documents). The root-path guard covers only /; all other folder items resolve to status: item and reach readWorkspaceKernelAiItem, which throws before the catch block can handle it. This is a latent crash introduced by the simplification of the read path.

src/features/workspaces/ai/workspace-kernel-ai-read.ts — the non-root folder guard is missing between the path-resolution switch and the readWorkspaceKernelAiItem call.

Important Files Changed

Filename Overview
src/features/workspaces/ai/workspace-kernel-ai-read.ts Read tool simplified to documents/files only, removes folder listing support. Non-root folder paths now throw unhandled errors instead of returning a clean failure (P1). Minor semantic issue where extraction-ready-but-empty files map to "failed" status.
src/features/workspaces/ai/ai-thread-runtime.ts Replaced monolithic tool registration with a descriptor-driven catalog; extracts codemode turn config. Clean refactor; codemode_execute is always included in activeTools and provided per-turn via createAIThreadTurnToolConfig.
src/features/workspaces/ai/workspace-tools.ts Adds strict output schemas to all workspace tools; consolidates tool creation via createWorkspaceThreadTool helper, removing per-tool requireThreadContext boilerplate. Looks correct and consistent.
src/features/workspaces/ai/time-tools.ts New file extracting time tools with strict schemas and output schemas. Logic mirrors what was previously in ai-thread-runtime.ts; no functional changes.
src/features/workspaces/kernel/workspace-kernel-list.ts List result now returns { path, more, items, failed } with error surfacing via WorkspaceKernelPathError catch. Renames entries→items and drops title field. Correct.
src/features/workspaces/ai/ai-thread.ts Replaces manual activeTools with spread of createAIThreadTurnToolConfig, which injects codemode_execute and the correct active-tools list per turn. Base tools still come from getTools().
src/server.ts Exports CodemodeRuntime from @cloudflare/codemode alongside existing Durable Object classes.
wrangler.jsonc Adds worker_loaders binding for LOADER required by @cloudflare/codemode.

Comments Outside Diff (1)

  1. src/features/workspaces/ai/workspace-kernel-ai-read.ts, line 87-127 (link)

    P1 Non-root folder path throws unhandled error

    resolveWorkspaceKernelAiPath returns { status: "item", item, path } for every resolved path — including non-root folders. The only folder guard here is the resolution.status === "root" check, which only catches the literal / root. Passing /My Documents returns status: "item" with item.type === "folder", falls through to readWorkspaceKernelAiItem, and hits throw new Error("Folder paths should be handled before item reads."). That generic Error is not a WorkspaceAiContentPageError, so the catch block on line 115 re-throws it as an unhandled server error rather than returning a clean { code: "path_is_folder" } failure in result.failed.

    Add an explicit folder check for the "item" resolution before calling readWorkspaceKernelAiItem:

    if (resolution.status === "item" && resolution.item.type === "folder") {
        result.failed.push({ code: "path_is_folder", index, path: resolution.path });
        continue;
    }
    

    Fix in Cursor

Fix All in Cursor

Reviews (1): Last reviewed commit: "feat(workspace-ai): add codemode runtime..." | Re-trigger Greptile

Comment on lines 245 to 247
if (projection.status === "ready" || projection.status === "needs_review") {
return "failed";
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 "ready"/"needs_review" with empty content mapped to "failed"

This branch is reached when projection.status is "ready" or "needs_review" but projection.content is falsy (the projection completed but yielded no text). Returning "failed" in that case may mislead the AI model — extraction didn't fail, the file just had no extractable text (e.g., an image-only PDF whose extraction produced an empty string). A status of "unsupported" or a dedicated "empty" value would better convey the actual situation without implying an error in the pipeline.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 22 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/features/workspaces/ai/workspace-kernel-ai-read.ts
Comment thread src/features/workspaces/ai/time-tools.ts Outdated

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 12 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/workspaces/kernel/workspace-kernel-rows.ts">

<violation number="1" location="src/features/workspaces/kernel/workspace-kernel-rows.ts:73">
P2: Deleted-event payload backward-compat handling was removed, so legacy kernel_events payloads can silently skip deletions. Keep a deleted-event normalization/fallback for `itemId` and missing arrays.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

return Array.isArray(value)
? value.filter((item): item is string => typeof item === "string")
: [];
return JSON.parse(row.payload_json) as WorkspaceRealtimeEvent["payload"];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Deleted-event payload backward-compat handling was removed, so legacy kernel_events payloads can silently skip deletions. Keep a deleted-event normalization/fallback for itemId and missing arrays.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/workspaces/kernel/workspace-kernel-rows.ts, line 73:

<comment>Deleted-event payload backward-compat handling was removed, so legacy kernel_events payloads can silently skip deletions. Keep a deleted-event normalization/fallback for `itemId` and missing arrays.</comment>

<file context>
@@ -70,37 +70,5 @@ export function mapKernelEventRow(
-	return Array.isArray(value)
-		? value.filter((item): item is string => typeof item === "string")
-		: [];
+	return JSON.parse(row.payload_json) as WorkspaceRealtimeEvent["payload"];
 }
</file context>
Suggested change
return JSON.parse(row.payload_json) as WorkspaceRealtimeEvent["payload"];
const payload = JSON.parse(row.payload_json) as unknown;
if (row.type === "workspace.item.deleted") {
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
return { itemIds: [], deletedItemIds: [] };
}
const record = payload as Record<string, unknown>;
const itemIds = Array.isArray(record.itemIds)
? record.itemIds.filter((item): item is string => typeof item === "string")
: [];
const legacyItemId = typeof record.itemId === "string" ? record.itemId : null;
return {
itemIds: itemIds.length > 0 ? itemIds : legacyItemId ? [legacyItemId] : [],
deletedItemIds: Array.isArray(record.deletedItemIds)
? record.deletedItemIds.filter((item): item is string => typeof item === "string")
: [],
};
}
return payload as WorkspaceRealtimeEvent["payload"];

@urjitc
urjitc merged commit 4eef6de into main Jun 23, 2026
1 of 2 checks passed
@urjitc
urjitc deleted the refactor/workspace-ai-tool-surface branch June 24, 2026 05:00
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant