Skip to content

Commit b2d36c3

Browse files
sonesukeclaude
andauthored
feat: add empty results test and improve devcontainer config (#74)
* fix: handle empty search results by creating fallback dataset When search returns 0 results, CypherEngine::from_json_auto fails to create a graph, causing the dataset to not be stored. This leads to "Dataset not found" errors when execute_cypher is called, forcing the AI agent to fall back to reading the JSON file directly. This commit fixes the issue by creating a minimal fallback dataset with a dummy node when the engine creation fails. Additionally: - Add logs/ and .skill-bench/ to .gitignore - Update mise.toml to run cargo install before skill-test - Increase timeout for patent-assignee-check/triggering test - Install skill-bench in devcontainer setup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add empty results test and improve devcontainer config - Add functional-empty.toml test case for handling empty search results - Update Cargo.lock to version 0.2.0 - Format devcontainer.json with trailing commas - Add GitHub CLI config mount to devcontainer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0c22b7a commit b2d36c3

8 files changed

Lines changed: 92 additions & 32 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,30 @@
11
{
2-
"name": "Google-Patent-CLI Dev",
3-
"build": {
4-
"dockerfile": "Dockerfile",
5-
"context": ".."
6-
},
7-
"features": {
8-
"ghcr.io/devcontainers/features/common-utils:2": {
9-
"installZsh": "true",
10-
"username": "vscode",
11-
"userUid": "1000",
12-
"userGid": "1000",
13-
"upgradePackages": "false"
14-
},
15-
"ghcr.io/devcontainers/features/github-cli:1": {},
16-
"ghcr.io/devcontainers/features/git:1": {}
17-
},
18-
"customizations": {
19-
"vscode": {}
20-
},
21-
"containerEnv": {
22-
"Z_AI_API_KEY": "${localEnv:Z_AI_API_KEY}",
23-
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
24-
},
25-
"postCreateCommand": "bash .devcontainer/post-create.sh",
26-
"remoteUser": "vscode"
27-
}
2+
"name": "Google-Patent-CLI Dev",
3+
"build": {
4+
"dockerfile": "Dockerfile",
5+
"context": "..",
6+
},
7+
"features": {
8+
"ghcr.io/devcontainers/features/common-utils:2": {
9+
"installZsh": "true",
10+
"username": "vscode",
11+
"userUid": "1000",
12+
"userGid": "1000",
13+
"upgradePackages": "false",
14+
},
15+
"ghcr.io/devcontainers/features/github-cli:1": {},
16+
"ghcr.io/devcontainers/features/git:1": {},
17+
},
18+
"mounts": [
19+
"source=${localEnv:HOME}/.config/gh,target=/home/vscode/.config/gh,type=bind,consistency=cached",
20+
],
21+
"customizations": {
22+
"vscode": {},
23+
},
24+
"containerEnv": {
25+
"Z_AI_API_KEY": "${localEnv:Z_AI_API_KEY}",
26+
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
27+
},
28+
"postCreateCommand": "bash .devcontainer/post-create.sh",
29+
"remoteUser": "vscode",
30+
}

.devcontainer/post-create.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ EOF
4141
echo 'eval "$(mise activate bash)"' >> $HOME/.bashrc
4242
echo 'eval "$(mise activate zsh)"' >> $HOME/.zshrc
4343

44+
# Install skill-bench
45+
if ! command -v skill-bench >/dev/null 2>&1; then
46+
echo "[Devcontainer Setup] Installing skill-bench..."
47+
curl -fsSL https://raw.githubusercontent.com/sonesuke/skill-bench/main/scripts/setup.sh | sh
48+
else
49+
echo "[Devcontainer Setup] skill-bench already installed: $(skill-bench --version 2>/dev/null || echo 'unknown')"
50+
fi
51+
4452
# Configure google-patent-cli to use chromium
4553
# Note: chrome_args will be dynamically determined by the app
4654
echo "[Devcontainer Setup] Configuring google-patent-cli..."

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
debug_page.html
33
patent_page_dom.html
44
.claude/worktrees/
5+
logs/
6+
.skill-bench/

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mise.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ run = "RUSTFLAGS=\"-D warnings\" cargo test --all-targets"
1111
depends = ["fmt", "clippy", "test"]
1212

1313
[tasks.skill-test]
14-
run = "skill-bench run tests --plugin-dir claude-plugin --log logs"
14+
run = "cargo install --path . && skill-bench run tests --plugin-dir claude-plugin --log logs"
1515

1616
[tasks.skill-test-list]
1717
run = "skill-bench list tests"

src/mcp/mod.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rmcp::{
1414
};
1515
use serde::{Deserialize, Serialize};
1616
use serde_json::Value;
17+
use serde_json::json;
1718
use std::collections::HashMap;
1819
use std::hash::{DefaultHasher, Hash, Hasher};
1920
use std::sync::Arc;
@@ -231,11 +232,27 @@ impl PatentHandler {
231232
json: &Value,
232233
root_label: Option<&str>,
233234
) -> Option<String> {
234-
let engine = if let Some(label) = root_label {
235-
CypherEngine::from_json_auto_as_root_with_label(json, label).ok()?
235+
// Try to create engine from the provided JSON
236+
let engine_result = if let Some(label) = root_label {
237+
CypherEngine::from_json_auto_as_root_with_label(json, label)
236238
} else {
237-
CypherEngine::from_json_auto(json).ok()?
239+
CypherEngine::from_json_auto(json)
238240
};
241+
242+
let engine = match engine_result {
243+
Ok(e) => e,
244+
Err(_) => {
245+
// If failed (e.g., empty results), create a minimal valid graph
246+
// Create a dummy node that CypherEngine can parse
247+
let fallback_json = if let Some(label) = root_label {
248+
json!({ label: [{"id": "_dummy", "_label": label }] })
249+
} else {
250+
json!({ "Patent": [{"id": "_dummy", "title": "", "url": ""}] })
251+
};
252+
CypherEngine::from_json_auto(&fallback_json).ok()?
253+
}
254+
};
255+
239256
let graph_schema = engine.get_schema();
240257

241258
// Store the engine

tests/patent-assignee-check/triggering.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
name = "triggering"
44
description = "Verify patent-assignee-check skill is triggered when checking assignee variations"
5-
timeout = 120
5+
timeout = 300
66

77
test_prompt = """
88
I want to verify the correct assignee name for "Salesforce" in patent databases.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Test Case: Patent Search - Empty Results
2+
3+
name = "functional-empty"
4+
description = "Verify patent-search skill handles empty search results correctly"
5+
timeout = 120
6+
7+
test_prompt = """
8+
Search for patents with query "xyz-nonexistent-patent-123" and limit 5.
9+
Then use execute_cypher to query the dataset.
10+
"""
11+
12+
[[checks]]
13+
name = "mcp_server_loaded"
14+
command = { command = "mcp-loaded", server = "google-patent-cli" }
15+
16+
[[checks]]
17+
name = "skill_loaded"
18+
command = { command = "skill-loaded", skill = "patent-search" }
19+
20+
[[checks]]
21+
name = "patent_search_skill_invoked"
22+
command = { command = "skill-invoked", skill = "patent-search" }
23+
24+
[[checks]]
25+
name = "search_patents_mcp_called"
26+
command = { command = "mcp-success", tool = "search_patents" }
27+
28+
[[checks]]
29+
name = "execute_cypher_mcp_called"
30+
command = { command = "mcp-success", tool = "execute_cypher" }

0 commit comments

Comments
 (0)