Skip to content

33 feature add skills#34

Merged
maximedogawa merged 3 commits into
mainfrom
33-feature-add-skills
Apr 17, 2026
Merged

33 feature add skills#34
maximedogawa merged 3 commits into
mainfrom
33-feature-add-skills

Conversation

@maximedogawa
Copy link
Copy Markdown
Collaborator

@maximedogawa maximedogawa commented Apr 17, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Skills management system—create, delete, and enable/disable skills from the dashboard.
    • Integrated ClawHub registry for discovering and installing community skills.
    • Added Skills panel to dashboard.
  • Documentation

    • Added Skills guide explaining skill structure, metadata, and usage patterns.
    • Documented Weather skill with wttr.in and Open-Meteo integration.
  • Improvements

    • Updated fetch tool configuration for improved autonomous API access.

- Added a new skills module to manage lightweight context templates for the agent.
- Implemented API endpoints for fetching, adding, deleting, and enabling/disabling skills.
- Created a user interface component for managing skills, including browsing and installing from ClawHub.
- Documented the skills format and usage in a new markdown file.
- Enhanced the agent's prompt with available skills to improve response accuracy.
- Introduced constants for skill hints to improve the clarity of the system prompt for the weather skill.
- Updated the skills prompt to include mandatory hints for the weather skill, ensuring proper usage of APIs.
- Added a truncation function to manage prompt length while maintaining readability.
- Enhanced the weather skill's README to clarify usage instructions and fallback mechanisms for fetching weather data.
@maximedogawa maximedogawa linked an issue Apr 17, 2026 that may be closed by this pull request
6 tasks
@maximedogawa maximedogawa self-assigned this Apr 17, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

Warning

Rate limit exceeded

@maximedogawa has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 38 minutes and 54 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 38 minutes and 54 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c29435eb-b18e-4f21-8147-1e568b84ea2d

📥 Commits

Reviewing files that changed from the base of the PR and between 3f7f6d5 and 218701f.

📒 Files selected for processing (15)
  • doc/custom-mcp-tools.md
  • doc/skills.md
  • src-tauri/src/infrastructure/http_server.rs
  • src-tauri/src/modules/bot/agent.rs
  • src-tauri/src/modules/skills/service.rs
  • src-tauri/src/modules/skills/types.rs
  • src-tauri/src/modules/tool_engine/service.rs
  • src-tauri/src/modules/tool_engine/types.rs
  • src/modules/skills/api/index.ts
  • src/modules/skills/components/SkillsPanel.tsx
  • src/modules/skills/types.ts
  • src/modules/toolengine/components/ToolEnginePanel.tsx
  • src/modules/toolengine/index.ts
  • tools/mcp-tools.json
  • tools/skills/weather/mandatory.md
📝 Walkthrough

Walkthrough

This change introduces a comprehensive "skills" system—lightweight markdown-based context templates for the agent—with backend service for management (list, create, delete, enable/disable, ClawHub search/install), frontend API client, and React UI component integrated into the dashboard.

Changes

Cohort / File(s) Summary
Documentation & Examples
doc/skills.md, tools/skills/weather/README.md
Added skills documentation defining structure, metadata, folder layout, and procedures; included weather skill example with wttr.in and Open-Meteo integration guidance.
Backend Configuration
src-tauri/Cargo.toml, tools/mcp-tools.json
Added zip crate dependency (v2 with deflate feature); updated fetch tool to run with --ignore-robots-txt flag.
Backend HTTP API
src-tauri/src/infrastructure/http_server.rs
Registered /v1/skills routes for listing, creating, deleting, enabling/disabling, and searching skills; added request/response DTOs; mapped error responses (BAD_REQUEST for custom operations, BAD_GATEWAY for ClawHub operations).
Backend Skills Module
src-tauri/src/modules/skills/mod.rs, src-tauri/src/modules/skills/types.rs, src-tauri/src/modules/skills/service.rs
Introduced skills module with type definitions (Skill, SkillOrigin, ClawHubSkill), and comprehensive service layer for skill discovery, parsing, persistence, CRUD operations, ClawHub integration (search/install via reqwest), prompt hint generation, and comprehensive test coverage.
Backend Integration
src-tauri/src/modules/mod.rs, src-tauri/src/modules/bot/agent.rs
Exposed skills module; integrated skills_prompt_hint() into agent's system prompt when tools are enabled.
Frontend API & Types
src/modules/skills/api/index.ts, src/modules/skills/types.ts, src/modules/skills/index.ts
Created typed TypeScript API client for skills endpoints with timeout handling and error parsing; defined Skill, SkillOrigin, ClawHubSkill types; exposed through barrel module.
Frontend UI Component
src/modules/skills/components/SkillsPanel.tsx, src/pages/DashboardPage.tsx
Implemented SkillsPanel component with skill listing, add/delete custom skills, enable/disable toggling (with optimistic updates), and ClawHub browse/search/install modal flow; integrated panel into dashboard page.

Sequence Diagram

sequenceDiagram
    actor User as User
    participant Client as Frontend
    participant Server as Tauri Server
    participant Service as Skills Service
    participant ClawHub as ClawHub API
    participant FS as Filesystem

    User->>Client: Click "Install from ClawHub"
    Client->>Server: POST /v1/skills/clawhub/search?q=weather
    Server->>Service: search_clawhub(query)
    Service->>ClawHub: GET https://clawhub.ai/api/search?q=weather
    ClawHub-->>Service: ClawHubSearchResponse { results }
    Service-->>Server: Vec<ClawHubSkill>
    Server-->>Client: { results }
    Client->>User: Display search results
    
    User->>Client: Click Install on weather skill
    Client->>Server: POST /v1/skills/clawhub/install { slug: "weather" }
    Server->>Service: install_clawhub_skill(store_path, slug)
    Service->>ClawHub: GET https://clawhub.ai/api/v1/download?slug=weather
    ClawHub-->>Service: Zip file (bytes)
    Service->>Service: Extract SKILL.md from zip
    Service->>FS: Write to $APP_DATA/skills/weather/README.md
    FS-->>Service: ✓
    Service->>FS: Update .disabled.json (remove if present)
    FS-->>Service: ✓
    Service-->>Server: Skill { slug, name, enabled, body, ... }
    Server-->>Client: { ok: true, skill }
    Client->>Client: Reload skills, close modal
    Client->>User: Display success, show new skill
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes


🐰 twitches whiskers with delight

Hop and skip, a skill is born,
From bundled seeds and custom corn—
ClawHub orchards, we fetch and weave,
Weather whispers help us breathe,
Markdown magic prompts so bright,
Skills abound—oh what a sight!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title '33 feature add skills' is vague and primarily references an issue number rather than describing the actual change, making it difficult for reviewers to understand the PR's purpose from the title alone. Revise the title to be more descriptive, such as 'Add skills management system with local and ClawHub integration' or 'Implement skills module with UI panel and API endpoints'.
✅ Passed checks (1 passed)
Check name Status Explanation
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 33-feature-add-skills

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
tools/mcp-tools.json (1)

58-81: ⚠️ Potential issue | 🟡 Minor

Consider the policy implications of enabling --ignore-robots-txt globally.

Setting --ignore-robots-txt as a permanent default for the fetch MCP server bypasses robots.txt for every host the agent fetches, not just public APIs like Open-Meteo that don't serve a meaningful robots policy. This may conflict with site terms of service and could expose users to compliance/abuse risks when the agent autonomously crawls arbitrary URLs.

A more conservative approach would be to keep robots.txt enforcement on by default and either (a) document an opt-in for users who need it, or (b) restrict the bypass to a known allowlist of API hosts. At minimum, the user-facing description should make the bypass behavior visible in the install/enable UI so users can make an informed choice.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/mcp-tools.json` around lines 58 - 81, The config currently enables the
flag --ignore-robots-txt in the mcp_server_cmd array which disables robots.txt
globally; remove that flag from mcp_server_cmd, update the description field to
disclose that robots.txt is enforced by default and provide an opt-in, and add a
new explicit config key (e.g., "ignore_robots_by_default": false or
"robots_ignore_allowlist": ["open-meteo.com"]) to allow either a user opt-in or
a host allowlist; adjust any UI/install text to surface this choice so the agent
does not bypass robots.txt for arbitrary hosts by default.
🧹 Nitpick comments (7)
src-tauri/src/modules/skills/types.rs (1)

15-38: Consider a serde default for origin too.

Skill derives Deserialize, and enabled has default_true, but origin has no default. Any JSON deserialization path (e.g. cached state, future IPC payload, or a ClawHub response that omits it) will hard-fail here. Since origin is effectively always set by parse_skill/list_skills, either drop Deserialize from Skill or give origin a sensible default (e.g. Custom) to match the laxness applied to the other fields.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/modules/skills/types.rs` around lines 15 - 38, The Skill struct
currently deserializes without a default for the origin field, causing failures
when origin is omitted; add a serde default for origin (e.g. #[serde(default =
"default_origin")] or #[serde(default)]) and provide a matching default function
or implement Default for the SkillOrigin enum that returns SkillOrigin::Custom,
then reference that default in the Skill struct's origin field so existing
parse_skill/list_skills deserialization paths remain tolerant.
src-tauri/src/modules/bot/agent.rs (1)

342-346: Prompt growth — watch the cumulative size.

skills_hint is appended on every turn and, per SKILL_HINT_BODY_CAP = 1600, each enabled skill contributes up to ~1.6 KB plus the weather mandatory block. With several enabled skills this can dominate the system prompt for small local models and silently push user/history context out of the window. Consider either capping total hint size or logging the final system prompt length once for observability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/modules/bot/agent.rs` around lines 342 - 346, The prompt grows
unbounded because skills::skills_prompt_hint(&state.store_path) (skills_hint) is
appended every turn and can exceed SKILL_HINT_BODY_CAP cumulatively; modify the
code around where skills_hint is produced and used (the skills_hint variable and
the format call building the system prompt) to enforce a total hint-cap: compute
skills_hint via skills::skills_prompt_hint, then trim or truncate it to a
configured MAX_TOTAL_SKILL_HINT_BYTES (or aggregate per-skill entries until the
cap), and/or log the final system prompt length once for observability (use
processLogger or equivalent) so small local models won’t be pushed out of
context. Ensure you reference SKILL_HINT_BODY_CAP when choosing the cap and keep
the truncation deterministic (e.g., cut from the end and add an ellipsis) before
inserting into the format string.
src-tauri/Cargo.toml (1)

37-37: deflate-only feature set is a correct minimization.

ClawHub archives only need deflate for SKILL.md extraction. Just note: if ClawHub ever ships zips using deflate64, bzip2, zstd, or (more likely) stored-but-encrypted entries, extract_skill_md will fail with an opaque zip entry N: ... error. Probably fine, but worth surfacing a clearer error message if it happens in practice.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/Cargo.toml` at line 37, Summary: The Cargo.toml minimizes zip
features to deflate only but extract_skill_md can fail opaquely for unsupported
compression/encryption; update extract_skill_md to surface clearer errors.
Modify the extract_skill_md function to catch and map zip read/extraction errors
(e.g., unsupported compression methods like deflate64, bzip2, zstd or
encrypted/stored entries) to a descriptive error that includes the zip entry
name/index and the detected compression/encryption info; specifically wrap
errors coming from ZipArchive/ZipFile reads and return a contextual message
instead of the opaque "zip entry N: ..." error so callers can distinguish
unsupported compression vs corrupted archives. Ensure the new error preserves
the original error as an inner source for debugging.
src/modules/skills/components/SkillsPanel.tsx (1)

168-175: Minor UX: Cancel doesn't reset addError/form state.

Clicking Cancel only toggles showAdd; a prior addError (and any typed slug/markdown) is preserved and reappears next time the form opens. Consider clearing on close:

🧹 Suggested tweak
-            onClick={() => setShowAdd((v) => !v)}
+            onClick={() => {
+              setShowAdd((v) => !v);
+              setAddError(null);
+            }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/skills/components/SkillsPanel.tsx` around lines 168 - 175, The
Cancel button currently only toggles showAdd and leaves prior addError and form
inputs intact; update the onClick handler (or introduce a helper like
resetAddForm) so when closing the add form it also clears addError and resets
the form state (e.g., call setAddError(undefined/null) and reset slug/markdown
state via setSlug('') and setMarkdown('') or the equivalent state setters)
before or after calling setShowAdd((v) => !v), so reopening the form is clean.
src-tauri/src/modules/skills/service.rs (2)

55-63: Silent fallback on a corrupted .disabled.json re-enables every skill.

If the JSON file exists but is malformed (partial write, manual edit), read_disabled_set returns an empty set, which means every previously-disabled skill silently becomes enabled again — with no log to trace it. Consider logging at warn! when parsing fails so the failure mode is at least observable.

🪵 Suggested fix
-    serde_json::from_str::<Vec<String>>(&raw)
-        .map(|v| v.into_iter().collect())
-        .unwrap_or_default()
+    match serde_json::from_str::<Vec<String>>(&raw) {
+        Ok(v) => v.into_iter().collect(),
+        Err(e) => {
+            log::warn!("corrupt {}: {e}; treating all skills as enabled", path.display());
+            HashSet::new()
+        }
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/modules/skills/service.rs` around lines 55 - 63,
read_disabled_set currently swallows JSON parse errors and returns an empty
HashSet, silently re-enabling all skills; change the
serde_json::from_str::<Vec<String>>(&raw).map(...).unwrap_or_default() path to
detect parse failures and log a warn including the parse error and the disabled
file path (use disabled_file_path(store_path) or path and the error from
serde_json) before returning the default set; keep the same return behavior but
emit a warn! so malformed .disabled.json is observable (update code in
read_disabled_set to use unwrap_or_else or match on the Result and call warn!).

87-139: Hardcoding a skill-specific hint in the generic service is a code smell.

WEATHER_SKILL_MANDATORY_HINT plus the skills.iter().any(|s| s.slug == "weather") branch (line 135–137) tightly couples the generic skills module to one specific skill. As the comment notes, this exists because the body gets truncated — but that pattern will recur for any richer skill, and repeating this branch per slug won't scale.

Consider one of:

  • Raising SKILL_HINT_BODY_CAP (or making it per-skill via frontmatter, e.g. hint_cap: 4096) so the README's own emphasis survives; then drop the override block entirely.
  • Letting skills declare a mandatory: frontmatter section that's always appended verbatim regardless of truncation.
  • At minimum, moving the literal into tools/skills/weather/README.md and keying the override generically (e.g. a mandatory.md sibling the service appends when present).

This keeps service.rs agnostic of specific skills and removes the duplication-with-README that the comment already flags.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/modules/skills/service.rs` around lines 87 - 139, The code
currently hardcodes WEATHER_SKILL_MANDATORY_HINT and checks
skills.iter().any(|s| s.slug == "weather") inside skills_prompt_hint, coupling
the generic skills service to one skill; instead make this generic by allowing
each Skill to provide an optional mandatory hint (e.g. a new Skill.mandatory:
Option<String> populated by list_skills or by reading a mandatory.md next to the
skill README) and change skills_prompt_hint to append that per-skill mandatory
text after each skill's truncated body (or always append untruncated mandatory
regardless of SKILL_HINT_BODY_CAP); alternatively increase SKILL_HINT_BODY_CAP
or make it per-skill via a hint_cap frontmatter, but prefer adding
Skill.mandatory and removing WEATHER_SKILL_MANDATORY_HINT and the slug check so
service.rs stays skill-agnostic and reads mandatory content from each skill (use
existing functions truncate_for_prompt, list_skills, and Skill struct to locate
where to add the field).
src/modules/skills/types.ts (1)

19-25: Minor: version?: string | null should be version?: string for consistency.

The Rust ClawHubSkill uses Option<String> with #[serde(skip_serializing_if = "Option::is_none")], meaning the backend never serializes None as null. The client will never receive a null value here. Removing | null keeps the type consistent with Skill.version and accurately reflects the actual backend behavior.

♻️ Proposed alignment
-  version?: string | null;
+  version?: string;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/skills/types.ts` around lines 19 - 25, The ClawHubSkill type's
version field is incorrectly declared as "version?: string | null"; update the
ClawHubSkill type so the version property is optional string only (version?:
string) to match backend serialization (Option<String> not null) and align with
Skill.version; locate the ClawHubSkill type declaration to make this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@doc/skills.md`:
- Around line 23-31: The fenced code block in doc/skills.md is missing a
language hint which triggers markdownlint MD040; update the opening fence from
``` to ```text (or ```plaintext) for the code block that contains the directory
listing so the linter is silenced and copy/paste fidelity is preserved.

In `@src-tauri/src/infrastructure/http_server.rs`:
- Around line 1335-1352: handle_skills_set_enabled currently toggles the
disabled set even for slugs that don't exist; before calling
skills_service::set_skill_enabled, call
skills_service::list_skills(&state.store_path) (or an equivalent existence-check
API) and verify the slug is present, returning (StatusCode::NOT_FOUND,
Json(ErrorResponse { error: "skill not found".into() })) if it isn't; only call
skills_service::set_skill_enabled and emit the log when the slug exists, and map
other errors to StatusCode::BAD_REQUEST as before.
- Around line 1297-1307: The handler handle_skills_delete currently maps all
delete_custom_skill errors to BAD_REQUEST; change it to inspect the error
returned by skills_service::delete_custom_skill and return StatusCode::NOT_FOUND
when the error indicates the missing directory (e.g. matches the message "custom
skill '<slug>' not found" or your DeleteError::NotFound variant if you
refactor), otherwise keep returning StatusCode::BAD_REQUEST with
Json(ErrorResponse). Update the error mapping closure where delete_custom_skill
is called so NotFound -> (StatusCode::NOT_FOUND, Json(ErrorResponse{...})) and
other errors -> (StatusCode::BAD_REQUEST, Json(ErrorResponse{...})).

In `@src/modules/skills/api/index.ts`:
- Around line 18-26: The parseApiError function can return empty strings because
it uses the nullish coalescing operator (??) which doesn't treat empty string as
missing; update the try branch in parseApiError to use logical OR (||) so that
when body.error is "" or body is {} it falls back to raw.trim() and then to
`HTTP ${resp.status}`; keep the same behavior for the catch branch and reference
the existing symbols parseApiError, resp, raw, and body.error when making the
change.

---

Outside diff comments:
In `@tools/mcp-tools.json`:
- Around line 58-81: The config currently enables the flag --ignore-robots-txt
in the mcp_server_cmd array which disables robots.txt globally; remove that flag
from mcp_server_cmd, update the description field to disclose that robots.txt is
enforced by default and provide an opt-in, and add a new explicit config key
(e.g., "ignore_robots_by_default": false or "robots_ignore_allowlist":
["open-meteo.com"]) to allow either a user opt-in or a host allowlist; adjust
any UI/install text to surface this choice so the agent does not bypass
robots.txt for arbitrary hosts by default.

---

Nitpick comments:
In `@src-tauri/Cargo.toml`:
- Line 37: Summary: The Cargo.toml minimizes zip features to deflate only but
extract_skill_md can fail opaquely for unsupported compression/encryption;
update extract_skill_md to surface clearer errors. Modify the extract_skill_md
function to catch and map zip read/extraction errors (e.g., unsupported
compression methods like deflate64, bzip2, zstd or encrypted/stored entries) to
a descriptive error that includes the zip entry name/index and the detected
compression/encryption info; specifically wrap errors coming from
ZipArchive/ZipFile reads and return a contextual message instead of the opaque
"zip entry N: ..." error so callers can distinguish unsupported compression vs
corrupted archives. Ensure the new error preserves the original error as an
inner source for debugging.

In `@src-tauri/src/modules/bot/agent.rs`:
- Around line 342-346: The prompt grows unbounded because
skills::skills_prompt_hint(&state.store_path) (skills_hint) is appended every
turn and can exceed SKILL_HINT_BODY_CAP cumulatively; modify the code around
where skills_hint is produced and used (the skills_hint variable and the format
call building the system prompt) to enforce a total hint-cap: compute
skills_hint via skills::skills_prompt_hint, then trim or truncate it to a
configured MAX_TOTAL_SKILL_HINT_BYTES (or aggregate per-skill entries until the
cap), and/or log the final system prompt length once for observability (use
processLogger or equivalent) so small local models won’t be pushed out of
context. Ensure you reference SKILL_HINT_BODY_CAP when choosing the cap and keep
the truncation deterministic (e.g., cut from the end and add an ellipsis) before
inserting into the format string.

In `@src-tauri/src/modules/skills/service.rs`:
- Around line 55-63: read_disabled_set currently swallows JSON parse errors and
returns an empty HashSet, silently re-enabling all skills; change the
serde_json::from_str::<Vec<String>>(&raw).map(...).unwrap_or_default() path to
detect parse failures and log a warn including the parse error and the disabled
file path (use disabled_file_path(store_path) or path and the error from
serde_json) before returning the default set; keep the same return behavior but
emit a warn! so malformed .disabled.json is observable (update code in
read_disabled_set to use unwrap_or_else or match on the Result and call warn!).
- Around line 87-139: The code currently hardcodes WEATHER_SKILL_MANDATORY_HINT
and checks skills.iter().any(|s| s.slug == "weather") inside skills_prompt_hint,
coupling the generic skills service to one skill; instead make this generic by
allowing each Skill to provide an optional mandatory hint (e.g. a new
Skill.mandatory: Option<String> populated by list_skills or by reading a
mandatory.md next to the skill README) and change skills_prompt_hint to append
that per-skill mandatory text after each skill's truncated body (or always
append untruncated mandatory regardless of SKILL_HINT_BODY_CAP); alternatively
increase SKILL_HINT_BODY_CAP or make it per-skill via a hint_cap frontmatter,
but prefer adding Skill.mandatory and removing WEATHER_SKILL_MANDATORY_HINT and
the slug check so service.rs stays skill-agnostic and reads mandatory content
from each skill (use existing functions truncate_for_prompt, list_skills, and
Skill struct to locate where to add the field).

In `@src-tauri/src/modules/skills/types.rs`:
- Around line 15-38: The Skill struct currently deserializes without a default
for the origin field, causing failures when origin is omitted; add a serde
default for origin (e.g. #[serde(default = "default_origin")] or
#[serde(default)]) and provide a matching default function or implement Default
for the SkillOrigin enum that returns SkillOrigin::Custom, then reference that
default in the Skill struct's origin field so existing parse_skill/list_skills
deserialization paths remain tolerant.

In `@src/modules/skills/components/SkillsPanel.tsx`:
- Around line 168-175: The Cancel button currently only toggles showAdd and
leaves prior addError and form inputs intact; update the onClick handler (or
introduce a helper like resetAddForm) so when closing the add form it also
clears addError and resets the form state (e.g., call
setAddError(undefined/null) and reset slug/markdown state via setSlug('') and
setMarkdown('') or the equivalent state setters) before or after calling
setShowAdd((v) => !v), so reopening the form is clean.

In `@src/modules/skills/types.ts`:
- Around line 19-25: The ClawHubSkill type's version field is incorrectly
declared as "version?: string | null"; update the ClawHubSkill type so the
version property is optional string only (version?: string) to match backend
serialization (Option<String> not null) and align with Skill.version; locate the
ClawHubSkill type declaration to make this change.
🪄 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: aee1c5df-effb-44ac-9532-7d5b0376bdb7

📥 Commits

Reviewing files that changed from the base of the PR and between bc3a96d and 3f7f6d5.

⛔ Files ignored due to path filters (1)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • doc/skills.md
  • src-tauri/Cargo.toml
  • src-tauri/src/infrastructure/http_server.rs
  • src-tauri/src/modules/bot/agent.rs
  • src-tauri/src/modules/mod.rs
  • src-tauri/src/modules/skills/mod.rs
  • src-tauri/src/modules/skills/service.rs
  • src-tauri/src/modules/skills/types.rs
  • src/modules/skills/api/index.ts
  • src/modules/skills/components/SkillsPanel.tsx
  • src/modules/skills/index.ts
  • src/modules/skills/types.ts
  • src/pages/DashboardPage.tsx
  • tools/mcp-tools.json
  • tools/skills/weather/README.md

Comment thread doc/skills.md Outdated
Comment thread src-tauri/src/infrastructure/http_server.rs
Comment thread src-tauri/src/infrastructure/http_server.rs
Comment thread src/modules/skills/api/index.ts
- Added support for `ignore_robots_txt` in the tool catalog, allowing tools to bypass robots.txt restrictions when opted in.
- Introduced `robots_ignore_allowlist` for future per-host policy management, currently serving as informational.
- Updated the skills management system to include a `mandatory.md` file for skills, providing additional rules and guidelines.
- Enhanced error handling in skills API to return more specific error messages for non-existent skills.
- Improved the skills prompt to include mandatory hints and manage prompt length effectively.
@maximedogawa maximedogawa merged commit f448d7b into main Apr 17, 2026
1 check passed
@maximedogawa maximedogawa deleted the 33-feature-add-skills branch April 17, 2026 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add Skills

1 participant