Repository: giselles-ai/giselle
Pull request #947: feat: enhance generation utilities with skipMod option and error handling
Author: login: toyamarinyon
Created: 2025-05-26T00:36:22Z | Merged: 2025-05-26T01:15:57Z

## Background

Currently, the node-generations API retrieves all previously generated Generations and applies data-mod when there are changes to the generation data structure. However, legacy Generations are rarely used in the current application, and treating past data as non-existent can significantly improve development velocity.

## Changes

### Core Functionality
- **Added `skipMod` option to `getGeneration` function**: Allows bypassing data-mod processing for better performance
- **Enhanced error handling in `getNodeGenerations`**: Gracefully handles failures by excluding errored generations from the response
- **Improved cache bypass functionality**: Added `bypassingCache: true` option for reliable data retrieval

### Implementation Details
- Modified `getGeneration` to support `skipMod` option that uses regular `parse()` instead of `parseAndMod()`
- Updated `getNodeGenerations` to use `.catch(() => null)` and filter out null results
- Changed filter logic from `generation !== undefined` to `!!generation` for better null handling

### Testing
- Added comprehensive unit tests for `getGeneration` function
- Fixed TypeScript errors in test implementation
- Covered all new functionality including `skipMod` option behavior

## Benefits

1. **Improved Development Velocity**: Eliminates the need to maintain data-mod compatibility for legacy generations
2. **Better Error Resilience**: API continues to work even when some generations fail to parse
3. **Performance Optimization**: Skipping mod processing reduces computational overhead
4. **Cleaner Response**: Automatically filters out problematic generations instead of failing entirely

## Breaking Changes

None. The changes are backward compatible as the `skipMod` option defaults to `false`, maintaining existing behavior.

## Testing

- ✅ All existing tests pass
- ✅ New unit tests added for `getGeneration` with `skipMod` option
- ✅ Error handling scenarios covered
- ✅ Type safety validated

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced an option to skip modification processing when retrieving generation data, allowing for direct parsing of raw data.
- **Bug Fixes**
  - Improved error handling during generation retrieval to prevent failures from causing interruptions.
- **Tests**
  - Added comprehensive tests to verify generation retrieval behavior under various scenarios, including new options and error cases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/packages/giselle-engine/src/core/generations/get-node-generations.ts b/packages/giselle-engine/src/core/generations/get-node-generations.ts
index 1120c01de8..b881264b15 100644
--- a/packages/giselle-engine/src/core/generations/get-node-generations.ts
+++ b/packages/giselle-engine/src/core/generations/get-node-generations.ts
@@ -26,7 +26,11 @@ export async function getNodeGenerations(args: {
 				getGeneration({
 					generationId: nodeGenerationIndex.id,
 					storage: args.context.storage,
-				}),
+					options: {
+						bypassingCache: true,
+						skipMod: true,
+					},
+				}).catch(() => null),
 			),
-	).then((result) => result.filter((generation) => generation !== undefined));
+	).then((result) => result.filter((generation) => !!generation));
 }
diff --git a/packages/giselle-engine/src/core/generations/utils.test.ts b/packages/giselle-engine/src/core/generations/utils.test.ts
new file mode 100644
index 0000000000..4c30bf674c
--- /dev/null
+++ b/packages/giselle-engine/src/core/generations/utils.test.ts
@@ -0,0 +1,139 @@
+import { parseAndMod } from "@giselle-sdk/data-mod";
+import type { GenerationId, GenerationIndex } from "@giselle-sdk/data-type";
+import { createStorage } from "unstorage";
+import memoryDriver from "unstorage/drivers/memory";
+import { beforeEach, describe, expect, test, vi } from "vitest";
+import { getGeneration, setGenerationIndex } from "./utils";
+
+// Mock parseAndMod to track when it's called
+vi.mock("@giselle-sdk/data-mod", () => ({
+	parseAndMod: vi.fn((schema, data) => {
+		return schema.parse(data);
+	}),
+}));
+
+describe("getGeneration", () => {
+	const storage = createStorage({ driver: memoryDriver() });
+	const generationId: GenerationId = "gnr-1234567890abcdef";
+
+	const mockGenerationIndex: GenerationIndex = {
+		id: generationId,
+		origin: {
+			type: "workspace",
+			id: "wrks-1234567890abcdef",
+		},
+	};
+
+	const mockGeneration = {
+		id: generationId,
+		status: "completed" as const,
+		context: {
+			origin: {
+				type: "workspace" as const,
+				id: "wrks-1234567890abcdef",
+			},
+			operationNode: {
+				id: "nd-1234567890abcdef",
+				type: "operation" as const,
+				inputs: [],
+				outputs: [],
+				content: {
+					type: "textGeneration" as const,
+					llm: {
+						provider: "openai" as const,
+						id: "gpt-4",
+						configurations: {
+							temperature: 0.7,
+							topP: 1.0,
+							presencePenalty: 0.0,
+							frequencyPenalty: 0.0,
+						},
+					},
+				},
+			},
+			connections: [],
+			sourceNodes: [],
+		},
+		messages: [],
+		outputs: [],
+		createdAt: Date.now(),
+		queuedAt: Date.now(),
+		startedAt: Date.now(),
+		completedAt: Date.now(),
+	};
+
+	beforeEach(async () => {
+		await storage.clear();
+		vi.mocked(parseAndMod).mockClear();
+
+		// Set up generation index
+		await setGenerationIndex({
+			storage,
+			generationIndex: mockGenerationIndex,
+		});
+
+		// Set up generation data
+		const generationPath = `workspaces/${mockGenerationIndex.origin.id}/generations/${generationId}/generation.json`;
+		await storage.setItem(generationPath, mockGeneration);
+	});
+
+	test("should use parseAndMod when skipMod is false", async () => {
+		const result = await getGeneration({
+			storage,
+			generationId,
+			options: { skipMod: false },
+		});
+
+		expect(result).toBeDefined();
+		expect(vi.mocked(parseAndMod)).toHaveBeenCalledTimes(2); // Called for Generation and GenerationContext
+		expect(result?.id).toBe(generationId);
+		expect(result?.status).toBe("completed");
+	});
+
+	test("should use parseAndMod when skipMod is undefined", async () => {
+		const result = await getGeneration({
+			storage,
+			generationId,
+		});
+
+		expect(result).toBeDefined();
+		expect(vi.mocked(parseAndMod)).toHaveBeenCalledTimes(2); // Called for Generation and GenerationContext
+		expect(result?.id).toBe(generationId);
+		expect(result?.status).toBe("completed");
+	});
+
+	test("should use regular parse when skipMod is true", async () => {
+		const result = await getGeneration({
+			storage,
+			generationId,
+			options: { skipMod: true },
+		});
+
+		expect(result).toBeDefined();
+		expect(vi.mocked(parseAndMod)).not.toHaveBeenCalled(); // parseAndMod should not be called when skipMod is true
+		expect(result?.id).toBe(generationId);
+		expect(result?.status).toBe("completed");
+	});
+
+	test("should throw error when generation index not found", async () => {
+		const nonExistentId: GenerationId = "gnr-nonexistent1234";
+
+		await expect(
+			getGeneration({
+				storage,
+				generationId: nonExistentId,
+			}),
+		).rejects.toThrow("Generation not found");
+	});
+
+	test("should respect bypassingCache option", async () => {
+		const result = await getGeneration({
+			storage,
+			generationId,
+			options: { bypassingCache: true, skipMod: true },
+		});
+
+		expect(result).toBeDefined();
+		expect(result?.id).toBe(generationId);
+	});
+});
diff --git a/packages/giselle-engine/src/core/generations/utils.ts b/packages/giselle-engine/src/core/generations/utils.ts
index 960a48fbc0..307fe117d9 100644
--- a/packages/giselle-engine/src/core/generations/utils.ts
+++ b/packages/giselle-engine/src/core/generations/utils.ts
@@ -352,6 +352,7 @@ export async function getGeneration(params: {
 	generationId: GenerationId;
 	options?: {
 		bypassingCache?: boolean;
+		skipMod?: boolean;
 	};
 }): Promise<Generation | undefined> {
 	const generationIndex = await getGenerationIndex(params);
@@ -364,6 +365,16 @@ export async function getGeneration(params: {
 			bypassingCache: params.options?.bypassingCache ?? false,
 		},
 	);
+	if (params.options?.skipMod) {
+		const parsedGeneration = Generation.parse(unsafeGeneration);
+		const parsedGenerationContext = GenerationContext.parse(
+			parsedGeneration.context,
+		);
+		return {
+			...parsedGeneration,
+			context: parsedGenerationContext,
+		};
+	}
 	const parsedGeneration = parseAndMod(Generation, unsafeGeneration);
 	const parsedGenerationContext = parseAndMod(
 		GenerationContext,


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

Enhance generation utilities by introducing a `skipMod` option for faster parsing, improving error resilience in `getNodeGenerations`, and adding tests for the new behavior.

- Added `skipMod` flag to `getGeneration` to bypass data-mod processing.
- Updated `getNodeGenerations` to use cache bypass, skipMod, and filter out errored items.
- Added comprehensive unit tests for `getGeneration` including skipMod scenarios.

### Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

| File                                                    | Description                                                         |
| ------------------------------------------------------- | ------------------------------------------------------------------- |
| packages/giselle-engine/src/core/generations/utils.ts   | Added `skipMod` option and alternate parsing path in `getGeneration` |
| packages/giselle-engine/src/core/generations/utils.test.ts | Added tests for `skipMod`, default behavior, error handling, and cache bypass |
| packages/giselle-engine/src/core/generations/get-node-generations.ts | Updated to call `getGeneration` with `bypassingCache`/`skipMod` and filter out null results |


<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**packages/giselle-engine/src/core/generations/get-node-generations.ts:26**
* No unit tests cover the updated logic in getNodeGenerations: tests should verify that skipMod and bypassingCache options are passed correctly and that errored generations are filtered out.
```
export async function getNodeGenerations(args: {
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T00:37:23Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f138fdfec410b250c353de4f7cb895ebdcb2afb5 and 3ded0105ed85c3a5955a294d7ae96cf26e40eff4.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `packages/giselle-engine/src/core/generations/get-node-generations.ts` (1 hunks)
* `packages/giselle-engine/src/core/generations/utils.test.ts` (1 hunks)
* `packages/giselle-engine/src/core/generations/utils.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 GitHub Actions: CI</summary>

<details>
<summary>packages/giselle-engine/src/core/generations/utils.test.ts</summary>

[error] 1-7: Biome organizeImports check failed: Import statements differ from expected output. The import order and names need correction.

---

[error] 68-68: Biome format check failed: File content differs from formatting output. Formatting issues detected at line 68.

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: codeql / languages (javascript) / Perform CodeQL for javascript

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>packages/giselle-engine/src/core/generations/get-node-generations.ts (3)</summary>

`29-34`: **LGTM! Well-implemented options for performance optimization.**

The addition of `skipMod: true` and `bypassingCache: true` options aligns perfectly with the PR objectives to optimize handling of legacy generations by bypassing data-mod processing and ensuring fresh data retrieval.

---

`33-33`: **Excellent error handling implementation.**

The `.catch(() => null)` provides graceful error handling that prevents the entire API from failing due to problematic individual generations, as described in the PR objectives.

---

`35-35`: **Correct filter logic for handling null values.**

The filter using `!!generation` properly excludes both `null` values (from error handling) and other falsy values, ensuring clean API responses.

</details>
<details>
<summary>packages/giselle-engine/src/core/generations/utils.ts (2)</summary>

`355-355`: **Well-designed optional parameter.**

The `skipMod?: boolean` option is properly typed and maintains backward compatibility by being optional.

---

`368-377`: **Correct implementation of the skipMod logic.**

The conditional logic properly bypasses `parseAndMod` when `skipMod` is true, using direct parsing instead. This achieves the performance optimization goal while maintaining the same return structure for consistency.

</details>
<details>
<summary>packages/giselle-engine/src/core/generations/utils.test.ts (1)</summary>

`15-139`: **Excellent comprehensive test coverage.**

The test suite thoroughly covers all the skipMod functionality scenarios and properly verifies the behavior changes. The mock setup and test cases are well-structured.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: CI</summary>

[error] 68-68: Biome format check failed: File content differs from formatting output. Formatting issues detected at line 68.

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T00:39:46Z
user: login: shige
body: Thank you! ⚡ 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-26T01:10:40Z

Review comments:
diff_hunk: @@ -364,6 +365,16 @@ export async function getGeneration(params: {
 			bypassingCache: params.options?.bypassingCache ?? false,
 		},
 	);
+	if (params.options?.skipMod) {
path: packages/giselle-engine/src/core/generations/utils.ts
user: login: Copilot
body: [nitpick] There’s duplicate context parsing logic in both the skipMod branch and the default parseAndMod branch; consider extracting this into a helper function to reduce duplication and improve readability.
created_at: 2025-05-26T00:37:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -26,7 +26,11 @@ export async function getNodeGenerations(args: {
 				getGeneration({
 					generationId: nodeGenerationIndex.id,
 					storage: args.context.storage,
-				}),
+					options: {
+						bypassingCache: true,
+						skipMod: true,
+					},
+				}).catch(() => null),
 			),
-	).then((result) => result.filter((generation) => generation !== undefined));
+	).then((result) => result.filter((generation) => !!generation));
path: packages/giselle-engine/src/core/generations/get-node-generations.ts
user: login: Copilot
body: [nitpick] Consider using `Array.prototype.filter(Boolean)` for brevity and clarity instead of `filter((generation) => !!generation)`.
```suggestion
	).then((result) => result.filter(Boolean));
```
created_at: 2025-05-26T00:37:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,139 @@
+import type { GenerationId, GenerationIndex } from "@giselle-sdk/data-type";
+import { createStorage } from "unstorage";
+import memoryDriver from "unstorage/drivers/memory";
+import { beforeEach, describe, expect, test, vi } from "vitest";
+import { parseAndMod } from "@giselle-sdk/data-mod";
+import { getGeneration, setGenerationIndex } from "./utils";
+
+// Mock parseAndMod to track when it's called
+vi.mock("@giselle-sdk/data-mod", () => ({
+	parseAndMod: vi.fn((schema, data) => {
+		return schema.parse(data);
+	}),
+}));
+
+describe("getGeneration", () => {
+	const storage = createStorage({ driver: memoryDriver() });
+	const generationId: GenerationId = "gnr-1234567890abcdef";
+
+	const mockGenerationIndex: GenerationIndex = {
+		id: generationId,
+		origin: {
+			type: "workspace",
+			id: "wrks-1234567890abcdef",
+		},
+	};
+
+	const mockGeneration = {
+		id: generationId,
+		status: "completed" as const,
+		context: {
+			origin: {
+				type: "workspace" as const,
+				id: "wrks-1234567890abcdef",
+			},
+			operationNode: {
+				id: "nd-1234567890abcdef",
+				type: "operation" as const,
+				inputs: [],
+				outputs: [],
+				content: {
+					type: "textGeneration" as const,
+					llm: {
+						provider: "openai" as const,
+						id: "gpt-4",
+						configurations: {
+							temperature: 0.7,
+							topP: 1.0,
+							presencePenalty: 0.0,
+							frequencyPenalty: 0.0,
+						},
+					},
+				},
+			},
+			connections: [],
+			sourceNodes: [],
+		},
+		messages: [],
+		outputs: [],
+		createdAt: Date.now(),
+		queuedAt: Date.now(),
+		startedAt: Date.now(),
+		completedAt: Date.now(),
+	};
+
+	beforeEach(async () => {
+		await storage.clear();
+		vi.mocked(parseAndMod).mockClear();
+		
path: packages/giselle-engine/src/core/generations/utils.test.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix formatting issue on line 68.**

There's a formatting issue detected by Biome on line 68. Please ensure proper spacing and formatting.



Looking at line 68, it appears there may be trailing whitespace or incorrect indentation. Apply this formatting fix:

```diff
-		
+
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: CI</summary>

[error] 68-68: Biome format check failed: File content differs from formatting output. Formatting issues detected at line 68.

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In packages/giselle-engine/src/core/generations/utils.test.ts at line 68, there
is a formatting issue likely caused by trailing whitespace or incorrect
indentation. Remove any trailing spaces and adjust the indentation to match the
surrounding code style, ensuring consistent spacing and alignment according to
the project's formatting standards.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-26T00:39:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,139 @@
+import type { GenerationId, GenerationIndex } from "@giselle-sdk/data-type";
+import { createStorage } from "unstorage";
+import memoryDriver from "unstorage/drivers/memory";
+import { beforeEach, describe, expect, test, vi } from "vitest";
+import { parseAndMod } from "@giselle-sdk/data-mod";
+import { getGeneration, setGenerationIndex } from "./utils";
+
path: packages/giselle-engine/src/core/generations/utils.test.ts
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Fix import organization to resolve pipeline failure.**

The Biome linter is reporting import organization issues. Please organize the imports according to the project's linting rules.

---

🏁 Script executed:

```shell
#!/bin/bash
# Description: Check the current import organization rules and suggest fixes
# Expected: Find biome configuration and import organization patterns

echo "Checking biome configuration..."
fd -e json biome.json
fd -e json .biome.json

echo "Checking other test files for import patterns..."
fd -e ts -e tsx --exclude node_modules | grep "\.test\." | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && head -10 {}'
```

Length of output: 2337

---

🏁 Script executed:

```shell
#!/bin/bash
# Display the beginning of the root biome.json to inspect import ordering rules
echo "=== Root biome.json (first 200 lines) ==="
sed -n '1,200p' biome.json

# Search for plugins related to import sorting
echo "=== Plugins in biome.json ==="
grep -R '"plugins"' -n biome.json -A 5
```

Length of output: 708

---



</details>

**Organize imports alphabetically by module specifier**

Please reorder the imports in packages/giselle-engine/src/core/generations/utils.test.ts so that external modules are sorted first (by specifier string), then the local “./utils” import. For example:

```diff
- import type { GenerationId, GenerationIndex } from "@giselle-sdk/data-type";
- import { createStorage } from "unstorage";
- import memoryDriver from "unstorage/drivers/memory";
- import { beforeEach, describe, expect, test, vi } from "vitest";
- import { parseAndMod } from "@giselle-sdk/data-mod";
- import { getGeneration, setGenerationIndex } from "./utils";
+ import { parseAndMod } from "@giselle-sdk/data-mod";
+ import type { GenerationId, GenerationIndex } from "@giselle-sdk/data-type";
+ import { createStorage } from "unstorage";
+ import memoryDriver from "unstorage/drivers/memory";
+ import { beforeEach, describe, expect, test, vi } from "vitest";
+ import { getGeneration, setGenerationIndex } from "./utils";
```

This aligns with the default Biome organizeImports rules and matches patterns seen in other test files.  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
import { parseAndMod } from "@giselle-sdk/data-mod";
import type { GenerationId, GenerationIndex } from "@giselle-sdk/data-type";
import { createStorage } from "unstorage";
import memoryDriver from "unstorage/drivers/memory";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { getGeneration, setGenerationIndex } from "./utils";
```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: CI</summary>

[error] 1-7: Biome organizeImports check failed: Import statements differ from expected output. The import order and names need correction.

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In packages/giselle-engine/src/core/generations/utils.test.ts lines 1 to 7, the
imports are not organized according to the project's linting rules. Reorder the
imports so that all external modules are listed first in alphabetical order by
their module specifier strings, followed by the local import from "./utils".
This will align with the Biome linter's default organizeImports rules and
maintain consistency with other test files.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-26T00:39:46Z
author_association: CONTRIBUTOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-05-26T00:36:25Z
body: ###  ⚠️  No Changeset found

Latest commit: cafe0edab0dd9db2005b072cf0c507d6356f3a18

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**



[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/giselles-ai/giselle/new/feat/enhance-generation-utils-with-skip-mod-and-error-handling?filename=.changeset/hungry-sheep-judge.md&value=---%0A%22%40fake-scope%2Ffake-pkg%22%3A%20patch%0A---%0A%0Afeat%3A%20enhance%20generation%20utilities%20with%20skipMod%20option%20and%20error%20handling%0A)

<details><summary>💥 An error occurred when fetching the changed packages and changesets in this PR</summary>

```
Some errors occurred when validating the changesets config:
The package "playground" depends on the ignored package "giselle-sdk", but "playground" is not being ignored. Please add "playground" to the `ignore` option.
The package "studio.giselles.ai" depends on the ignored package "giselle-sdk", but "studio.giselles.ai" is not being ignored. Please add "studio.giselles.ai" to the `ignore` option.
The package "@giselle-internal/workflow-designer-ui" depends on the ignored package "giselle-sdk", but "@giselle-internal/workflow-designer-ui" is not being ignored. Please add "@giselle-internal/workflow-designer-ui" to the `ignore` option.
```

</details>

author_association: NONE
user: login: vercel[bot]
created_at: 2025-05-26T00:36:27Z
body: [vc]: #uLMnmtuukakwDYVk6NIZTx+5Bngsm69a6BKiGGXuj24=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJnaXNlbGxlIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvc3R1ZGlvLmdpc2VsbGVzLmFpIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3IwNi1lZGdlL2dpc2VsbGUvMzl6MlU5SnJpeENRemtiTjNxM0hDV1A0bWJQUyIsInByZXZpZXdVcmwiOiJnaXNlbGxlLWdpdC1mZWF0LWVuaGFuY2UtZ2VuZXJhdGlvbi11dGlscy13aXRoLThiN2ZmYi1yMDYtZWRnZS52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6Imdpc2VsbGUtZ2l0LWZlYXQtZW5oYW5jZS1nZW5lcmF0aW9uLXV0aWxzLXdpdGgtOGI3ZmZiLXIwNi1lZGdlLnZlcmNlbC5hcHAifX0seyJuYW1lIjoiZ2lzZWxsZS1wbGF5Z3JvdW5kIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvcGxheWdyb3VuZCIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9yMDYtZWRnZS9naXNlbGxlLXBsYXlncm91bmQvNnNNcjZzRDJyQXA0djlFQ1dmSEw4ZEU4M2ZFMSIsInByZXZpZXdVcmwiOiJnaXNlbGxlLXBsYXlncm91bmQtZ2l0LWZlYXQtZW5oYW5jZS1nZW5lcmF0aW9uLTVlMTQ5Mi1yMDYtZWRnZS52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6Imdpc2VsbGUtcGxheWdyb3VuZC1naXQtZmVhdC1lbmhhbmNlLWdlbmVyYXRpb24tNWUxNDkyLXIwNi1lZGdlLnZlcmNlbC5hcHAifX1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **giselle** | ✅ Ready ([Inspect](https://vercel.com/r06-edge/giselle/39z2U9JrixCQzkbN3q3HCWP4mbPS)) | [Visit Preview](https://giselle-git-feat-enhance-generation-utils-with-8b7ffb-r06-edge.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/giselle-git-feat-enhance-generation-utils-with-8b7ffb-r06-edge.vercel.app?via=pr-comment-feedback-link) | May 26, 2025 0:44am |
| **giselle-playground** | ✅ Ready ([Inspect](https://vercel.com/r06-edge/giselle-playground/6sMr6sD2rAp4v9ECWfHL8dE83fE1)) | [Visit Preview](https://giselle-playground-git-feat-enhance-generation-5e1492-r06-edge.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/giselle-playground-git-feat-enhance-generation-5e1492-r06-edge.vercel.app?via=pr-comment-feedback-link) | May 26, 2025 0:44am |



author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-05-26T00:36:28Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

The changes introduce a new `skipMod` option to the `getGeneration` utility, allowing the function to bypass modification logic and directly parse generation data. The `getNodeGenerations` function now uses this option and handles errors gracefully. A comprehensive test suite was added to verify the updated behavior, including handling of the new options.

## Changes

| File(s)                                                                 | Change Summary                                                                                              |
|-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| packages/giselle-engine/src/core/generations/get-node-generations.ts    | Updated to pass `bypassingCache: true` and `skipMod: true` to `getGeneration`; improved error handling.     |
| packages/giselle-engine/src/core/generations/utils.ts                   | Added `skipMod` option to `getGeneration` to allow bypassing modification logic during parsing.             |
| packages/giselle-engine/src/core/generations/utils.test.ts              | Added new test suite for `getGeneration` covering `skipMod`, `bypassingCache`, and error scenarios.         |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Caller
    participant getNodeGenerations
    participant getGeneration
    participant Storage

    Caller->>getNodeGenerations: Request generations for node
    loop For each generationId
        getNodeGenerations->>getGeneration: getGeneration({id, options: {bypassingCache: true, skipMod: true}})
        getGeneration->>Storage: Fetch generation data
        alt skipMod is true
            getGeneration->>getGeneration: Parse data directly (skip mod)
        else skipMod is false
            getGeneration->>getGeneration: Parse and modify data
        end
        getGeneration-->>getNodeGenerations: Return generation or null on error
    end
    getNodeGenerations-->>Caller: Return array of valid generations
```

## Poem

> In fields of code where data flows,
> A rabbit hops where logic grows.
> Now skipping mods, with tests in tow,
> Generations parsed, errors low.
> With options clear and bugs in flight,
> The engine hums—oh what a sight!
> 🐇✨

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f138fdfec410b250c353de4f7cb895ebdcb2afb5 and cafe0edab0dd9db2005b072cf0c507d6356f3a18.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `packages/giselle-engine/src/core/generations/get-node-generations.ts` (1 hunks)
* `packages/giselle-engine/src/core/generations/utils.test.ts` (1 hunks)
* `packages/giselle-engine/src/core/generations/utils.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>packages/giselle-engine/src/core/generations/utils.ts (2)</summary><blockquote>

<details>
<summary>packages/data-type/src/generation/index.ts (2)</summary>

* `Generation` (64-125)
* `Generation` (128-128)

</details>
<details>
<summary>packages/data-type/src/generation/context.ts (2)</summary>

* `GenerationContext` (48-59)
* `GenerationContext` (60-60)

</details>

</blockquote></details>
<details>
<summary>packages/giselle-engine/src/core/generations/utils.test.ts (2)</summary><blockquote>

<details>
<summary>packages/data-mod/src/index.ts (1)</summary>

* `parseAndMod` (20-40)

</details>
<details>
<summary>packages/giselle-engine/src/core/generations/utils.ts (3)</summary>

* `setGenerationIndex` (291-299)
* `generationPath` (300-313)
* `getGeneration` (350-387)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: codeql / languages (javascript) / Perform CodeQL for javascript
* GitHub Check: check

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>packages/giselle-engine/src/core/generations/utils.ts (1)</summary>

`355-355`: **LGTM! New skipMod option correctly added.**

The optional `skipMod` parameter is properly typed and positioned in the options object.

</details>
<details>
<summary>packages/giselle-engine/src/core/generations/get-node-generations.ts (1)</summary>

`29-33`: **LGTM! Excellent usage of new skipMod functionality with error handling.**

The options object correctly leverages the new `skipMod: true` and `bypassingCache: true` functionality, and the `.catch(() => null)` provides graceful error handling for problematic generations.

</details>
<details>
<summary>packages/giselle-engine/src/core/generations/utils.test.ts (1)</summary>

`1-139`: **Excellent comprehensive test suite for skipMod functionality.**

This test file provides thorough coverage of the new `skipMod` feature:
- ✅ Tests `skipMod: false` calls `parseAndMod` correctly
- ✅ Tests `skipMod: undefined` (default behavior) calls `parseAndMod`
- ✅ Tests `skipMod: true` bypasses `parseAndMod` entirely
- ✅ Tests error handling for non-existent generations
- ✅ Tests `bypassingCache` option integration
- ✅ Proper mocking setup with realistic test data
- ✅ Clear test names and appropriate assertions

The mock generation data structure is realistic and matches the expected schema. The `beforeEach` setup ensures clean test isolation.

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=giselles-ai/giselle&utm_content=947):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR