Skip to content

feat(tasks): install and apply skill bundle artifacts in the sandbox#2924

Open
tatoalo wants to merge 1 commit into
local-skill-02-bundlerfrom
local-skill-03-agent-install
Open

feat(tasks): install and apply skill bundle artifacts in the sandbox#2924
tatoalo wants to merge 1 commit into
local-skill-02-bundlerfrom
local-skill-03-agent-install

Conversation

@tatoalo

@tatoalo tatoalo commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

for cloud tasks, local skill invocations only sent the slash command text. User-local and repo-local skills were available in the local editor but not in the cloud sandbox

Changes

  • let's bundle uploadable local skills into zip artifacts with SHA-256 metadata and send them through the existing cloud artifact upload flow.

  • install skill_bundle artifacts in the agent server before prompt delivery, inject the bundled skill instructions for the invoked turn, and suppress the raw slash command from the model-facing prompt so local skills behave like actual skills rather than unsupported commands

  • refresh slash command metadata when a follow-up command is submitted, so newly created local skills can be selected and invoked without starting a brand-new task.

closes #2260

tatoalo commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit bcbc926.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff (1)

  1. packages/agent/src/server/agent-server.ts, line 686-693 (link)

    P2 TOCTOU race in deduplication guard

    The check-then-act pattern is not safe across await boundaries. Two concurrent calls for the same installKey can both pass the guard before either call adds the key to installedSkillBundles (which happens only after the full install at line ~755). If installSkillBundleArtifacts is ever called concurrently for the same artifact — e.g., if a future code path triggers it in parallel — both calls will race through rm/mkdir/write, potentially corrupting the extracted tree or causing ENOENT when call B removes the directory that call A is still writing into.

    A straightforward fix is to add the key to installedSkillBundles immediately after the guard passes (as a "claimed" sentinel) and reset it on failure, or to use a Map<string, Promise<void>> of in-flight installs.

Reviews (1): Last reviewed commit: "feat(tasks): install and apply skill bun..." | Re-trigger Greptile

Comment thread packages/agent/src/adapters/claude/claude-agent.ts
Comment thread packages/agent/src/adapters/claude/claude-agent.ts
@tatoalo tatoalo force-pushed the local-skill-02-bundler branch from 259d373 to e8dec75 Compare June 25, 2026 09:48
@tatoalo tatoalo force-pushed the local-skill-03-agent-install branch from dbe89f8 to bcbc926 Compare June 25, 2026 09:48
@tatoalo tatoalo self-assigned this Jun 25, 2026
@tatoalo tatoalo requested a review from a team June 25, 2026 10:41
@tatoalo tatoalo marked this pull request as ready for review June 25, 2026 10:41
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Reviews (2): Last reviewed commit: "feat(tasks): install and apply skill bun..." | Re-trigger Greptile

return text;
}

function isLocalSkillCommandChunk(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This feels kinda risky to me what if a the string is "hello please run /skill_name - thank you" could the tokens split the skill name?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

chunk is an ACP prompt content block, not model tokens, and the matcher is anchored to a slash command at the start of the trimmed block so that ^ example would not fly

It also can't reach this as a "skill" at all since localSkillName is only set when the leading text block parses as / and exactly equals an installed skill_bundle artifact's skill_name. The name is captured and compared by full equality so ther;s no tokenization, no prefix matches, and the skill name never feeds the regex

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.

2 participants