Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 29 additions & 26 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
{
"name": "Google-Patent-CLI Dev",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": "true",
"username": "vscode",
"userUid": "1000",
"userGid": "1000",
"upgradePackages": "false"
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/git:1": {}
},
"customizations": {
"vscode": {}
},
"containerEnv": {
"Z_AI_API_KEY": "${localEnv:Z_AI_API_KEY}",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"remoteUser": "vscode"
}
"name": "Google-Patent-CLI Dev",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
},
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": "true",
"username": "vscode",
"userUid": "1000",
"userGid": "1000",
"upgradePackages": "false",
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/git:1": {},
},
"mounts": [
"source=${localEnv:HOME}/.config/gh,target=/home/vscode/.config/gh,type=bind,consistency=cached",
],
"customizations": {
"vscode": {},
},
"containerEnv": {
"Z_AI_API_KEY": "${localEnv:Z_AI_API_KEY}",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"remoteUser": "vscode",
}
8 changes: 8 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ EOF
echo 'eval "$(mise activate bash)"' >> $HOME/.bashrc
echo 'eval "$(mise activate zsh)"' >> $HOME/.zshrc

# Install skill-bench
if ! command -v skill-bench >/dev/null 2>&1; then
echo "[Devcontainer Setup] Installing skill-bench..."
curl -fsSL https://raw.githubusercontent.com/sonesuke/skill-bench/main/scripts/setup.sh | sh
else
echo "[Devcontainer Setup] skill-bench already installed: $(skill-bench --version 2>/dev/null || echo 'unknown')"
fi

# Configure google-patent-cli to use chromium
# Note: chrome_args will be dynamically determined by the app
echo "[Devcontainer Setup] Configuring google-patent-cli..."
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
debug_page.html
patent_page_dom.html
.claude/worktrees/
logs/
.skill-bench/
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ run = "RUSTFLAGS=\"-D warnings\" cargo test --all-targets"
depends = ["fmt", "clippy", "test"]

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

[tasks.skill-test-list]
run = "skill-bench list tests"
Expand Down
23 changes: 20 additions & 3 deletions src/mcp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rmcp::{
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_json::json;
use std::collections::HashMap;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::sync::Arc;
Expand Down Expand Up @@ -231,11 +232,27 @@ impl PatentHandler {
json: &Value,
root_label: Option<&str>,
) -> Option<String> {
let engine = if let Some(label) = root_label {
CypherEngine::from_json_auto_as_root_with_label(json, label).ok()?
// Try to create engine from the provided JSON
let engine_result = if let Some(label) = root_label {
CypherEngine::from_json_auto_as_root_with_label(json, label)
} else {
CypherEngine::from_json_auto(json).ok()?
CypherEngine::from_json_auto(json)
};

let engine = match engine_result {
Ok(e) => e,
Err(_) => {
// If failed (e.g., empty results), create a minimal valid graph
// Create a dummy node that CypherEngine can parse
let fallback_json = if let Some(label) = root_label {
json!({ label: [{"id": "_dummy", "_label": label }] })
} else {
json!({ "Patent": [{"id": "_dummy", "title": "", "url": ""}] })
};
CypherEngine::from_json_auto(&fallback_json).ok()?
}
};

let graph_schema = engine.get_schema();

// Store the engine
Expand Down
2 changes: 1 addition & 1 deletion tests/patent-assignee-check/triggering.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

name = "triggering"
description = "Verify patent-assignee-check skill is triggered when checking assignee variations"
timeout = 120
timeout = 300

test_prompt = """
I want to verify the correct assignee name for "Salesforce" in patent databases.
Expand Down
30 changes: 30 additions & 0 deletions tests/patent-search/functional-empty.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Test Case: Patent Search - Empty Results

name = "functional-empty"
description = "Verify patent-search skill handles empty search results correctly"
timeout = 120

test_prompt = """
Search for patents with query "xyz-nonexistent-patent-123" and limit 5.
Then use execute_cypher to query the dataset.
"""

[[checks]]
name = "mcp_server_loaded"
command = { command = "mcp-loaded", server = "google-patent-cli" }

[[checks]]
name = "skill_loaded"
command = { command = "skill-loaded", skill = "patent-search" }

[[checks]]
name = "patent_search_skill_invoked"
command = { command = "skill-invoked", skill = "patent-search" }

[[checks]]
name = "search_patents_mcp_called"
command = { command = "mcp-success", tool = "search_patents" }

[[checks]]
name = "execute_cypher_mcp_called"
command = { command = "mcp-success", tool = "execute_cypher" }
Loading