@capybara-hq/plugin-sdk 0.1.0-rc.0 → 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,8 +14,8 @@ npm packages; the host provides it at runtime.
14
14
  npm install @capybara-hq/plugin-sdk
15
15
  ```
16
16
 
17
- - Writing an extension: [.agents/skills/writing-extensions](https://github.com/capybara-hq/core/tree/main/.agents/skills/writing-extensions)
18
- and the reference plugin [plugins/example-counter](https://github.com/capybara-hq/core/tree/main/plugins/example-counter).
17
+ - Writing an extension: [.agents/skills/writing-extensions](https://github.com/capybara-hq/plugins/tree/main/.agents/skills/writing-extensions)
18
+ in capybara-hq/plugins and its reference plugin [plugins/example-counter](https://github.com/capybara-hq/plugins/tree/main/plugins/example-counter).
19
19
  - Writing a plugin (manifest, skills, connector templates, dependencies, marketplaces):
20
20
  [.agents/skills/writing-plugins](https://github.com/capybara-hq/core/tree/main/.agents/skills/writing-plugins).
21
21
  - The repository: [capybara-hq/core](https://github.com/capybara-hq/core).
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Agent templates (`agents/<name>.md` in a plugin; sub-agents spec §16.1): Markdown with YAML
3
3
  * frontmatter, the body being the instructions. A template is a type an agent with the builtin
4
- * `agent` tool can dispatch as a sub-agent (`<plugin>:<name>` in its roster). Used by the kernel,
4
+ * `Agent` tool can dispatch as a sub-agent (`<plugin>:<name>` in its roster). Used by the kernel,
5
5
  * the packer and `capybara-plugin check`.
6
6
  */
7
7
  import { readFrontmatter } from "./frontmatter.js";
package/dist/hooks.d.ts CHANGED
@@ -7,12 +7,12 @@ import type { ContentBlock, ModelRequest, ModelUsage } from "./model.js";
7
7
  export declare const HOOKS_AVAILABLE: readonly ["model.request", "model.response", "tool.preExecute", "tool.postExecute", "usage.report"];
8
8
  /** A mount point that `ctx.hooks.on` accepts. */
9
9
  export type AvailableHook = (typeof HOOKS_AVAILABLE)[number];
10
- /** Where a sub-agent was dispatched from: the parent conversation, its run and the `agent` call. */
10
+ /** Where a sub-agent was dispatched from: the parent conversation, its run and the `Agent` call. */
11
11
  export interface HookParentScope {
12
12
  conversationId: string;
13
13
  runId: string;
14
14
  /**
15
- * The `agent` call's id; `skill-<seq>` for a person's forked skill invocation, which has no
15
+ * The `Agent` call's id; `skill-<seq>` for a person's forked skill invocation, which has no
16
16
  * tool call in the parent's log.
17
17
  */
18
18
  callId: string;
@@ -111,6 +111,7 @@ export interface ModelResponseHookPayload extends HookScope {
111
111
  export interface ToolPreHookPayload extends HookScope {
112
112
  step: number;
113
113
  callId: string;
114
+ /** The model-visible key: a builtin name, `mcp__<slug>__<tool>` or `plugin__<plugin>__<tool>`; split it with `parseToolKey`. */
114
115
  toolKey: string;
115
116
  specHash: string;
116
117
  input: unknown;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const SDK_VERSION = "0.1.0-rc.0";
1
+ export declare const SDK_VERSION = "0.1.0-rc.1";
2
2
  export * from "./agent-template.js";
3
3
  export * from "./bootstrap.js";
4
4
  export * from "./cards.js";
@@ -24,4 +24,5 @@ export * from "./skill.js";
24
24
  export * from "./skill-invocation.js";
25
25
  export * from "./storage.js";
26
26
  export * from "./tool.js";
27
+ export * from "./tool-key.js";
27
28
  export * from "./ui.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export const SDK_VERSION = "0.1.0-rc.0";
1
+ export const SDK_VERSION = "0.1.0-rc.1";
2
2
  export * from "./agent-template.js";
3
3
  export * from "./bootstrap.js";
4
4
  export * from "./cards.js";
@@ -24,4 +24,5 @@ export * from "./skill.js";
24
24
  export * from "./skill-invocation.js";
25
25
  export * from "./storage.js";
26
26
  export * from "./tool.js";
27
+ export * from "./tool-key.js";
27
28
  export * from "./ui.js";
@@ -37,7 +37,7 @@ export declare function renderSkillBody(body: string, invocation: SkillInvocatio
37
37
  export interface RenderSkillInvocationInput {
38
38
  /**
39
39
  * The name the person typed after `/` (`fix-issue`, or `<plugin>:<name>`): used in the lead, the
40
- * `name="…"` attribute and the `skill_load` argument (where the qualified form resolves).
40
+ * `name="…"` attribute and the `Skill` argument (where the qualified form resolves).
41
41
  */
42
42
  name: string;
43
43
  /**
@@ -53,9 +53,9 @@ export interface RenderSkillInvocationInput {
53
53
  args: string;
54
54
  /** Decided by the caller from the agent's tools and the version's manifest. */
55
55
  lines: {
56
- /** The version has files besides SKILL.md: `load` when the agent has `skill_load`. */
56
+ /** The version has files besides SKILL.md: `load` when the agent has `Skill`. */
57
57
  files?: "load" | "unavailable";
58
- /** The body has shell injections and the agent has `sandbox_bash`. */
58
+ /** The body has shell injections and the agent has `Bash`. */
59
59
  shellHint?: boolean;
60
60
  };
61
61
  /** false: leave out the lead sentence (a forked skill's task for the sub-agent). Default true. */
@@ -180,13 +180,13 @@ export function renderSkillInvocation(i) {
180
180
  }
181
181
  parts.push(`<skill_invocation name="${escapeAttr(i.name)}" version="${i.version}">\n${body}\n</skill_invocation>`);
182
182
  if (i.lines.files === "load") {
183
- parts.push(`Its files are not in the sandbox yet: call skill_load with "${i.name}" to copy them to ${SKILLS_SANDBOX_ROOT}/${i.skillName}/ before running its scripts.`);
183
+ parts.push(`Its files are not in the sandbox yet: call Skill with "${i.name}" to copy them to ${SKILLS_SANDBOX_ROOT}/${i.skillName}/ before running its scripts.`);
184
184
  }
185
185
  else if (i.lines.files === "unavailable") {
186
186
  parts.push("Its other files are not available in this conversation.");
187
187
  }
188
188
  if (i.lines.shellHint) {
189
- parts.push("Lines written as !`command` were meant to run before you read this; run those commands with sandbox_bash if you need their output.");
189
+ parts.push("Lines written as !`command` were meant to run before you read this; run those commands with Bash if you need their output.");
190
190
  }
191
191
  return parts.join("\n\n");
192
192
  }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Model-visible tool key grammar (aligned with Claude Code):
3
+ *
4
+ * - builtin: `^[A-Z][A-Za-z]{1,31}$` (PascalCase), e.g. `Edit`
5
+ * - connector: `mcp__<slug>__<tool>`, e.g. `mcp__crm__search_accounts`
6
+ * - extension: `plugin__<plugin>__<tool>`, e.g. `plugin__todo__write`
7
+ *
8
+ * Pure functions only; extensions that match keys (hooks) use `parseToolKey` instead of splitting.
9
+ */
10
+ export type ParsedToolKey = {
11
+ kind: "builtin";
12
+ name: string;
13
+ } | {
14
+ kind: "connector";
15
+ slug: string;
16
+ tool: string;
17
+ } | {
18
+ kind: "extension";
19
+ plugin: string;
20
+ tool: string;
21
+ };
22
+ export declare const BUILTIN_TOOL_NAME_RE: RegExp;
23
+ /** Parse a tool key; `null` when it fits none of the three forms. */
24
+ export declare function parseToolKey(key: string): ParsedToolKey | null;
25
+ /** `mcp__<slug>__<tool>` */
26
+ export declare function connectorToolKey(slug: string, tool: string): string;
27
+ /** `plugin__<plugin>__<tool>` */
28
+ export declare function extensionToolKey(plugin: string, tool: string): string;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Model-visible tool key grammar (aligned with Claude Code):
3
+ *
4
+ * - builtin: `^[A-Z][A-Za-z]{1,31}$` (PascalCase), e.g. `Edit`
5
+ * - connector: `mcp__<slug>__<tool>`, e.g. `mcp__crm__search_accounts`
6
+ * - extension: `plugin__<plugin>__<tool>`, e.g. `plugin__todo__write`
7
+ *
8
+ * Pure functions only; extensions that match keys (hooks) use `parseToolKey` instead of splitting.
9
+ */
10
+ export const BUILTIN_TOOL_NAME_RE = /^[A-Z][A-Za-z]{1,31}$/;
11
+ const SEP = "__";
12
+ /** Parse a tool key; `null` when it fits none of the three forms. */
13
+ export function parseToolKey(key) {
14
+ if (!key.includes(SEP)) {
15
+ return BUILTIN_TOOL_NAME_RE.test(key) ? { kind: "builtin", name: key } : null;
16
+ }
17
+ const first = key.indexOf(SEP);
18
+ const family = key.slice(0, first);
19
+ if (family !== "mcp" && family !== "plugin")
20
+ return null;
21
+ const rest = key.slice(first + SEP.length);
22
+ const second = rest.indexOf(SEP);
23
+ if (second <= 0)
24
+ return null;
25
+ const owner = rest.slice(0, second);
26
+ const tool = rest.slice(second + SEP.length);
27
+ if (tool === "")
28
+ return null;
29
+ return family === "mcp"
30
+ ? { kind: "connector", slug: owner, tool }
31
+ : { kind: "extension", plugin: owner, tool };
32
+ }
33
+ /** `mcp__<slug>__<tool>` */
34
+ export function connectorToolKey(slug, tool) {
35
+ return `mcp${SEP}${slug}${SEP}${tool}`;
36
+ }
37
+ /** `plugin__<plugin>__<tool>` */
38
+ export function extensionToolKey(plugin, tool) {
39
+ return `plugin${SEP}${plugin}${SEP}${tool}`;
40
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capybara-hq/plugin-sdk",
3
- "version": "0.1.0-rc.0",
3
+ "version": "0.1.0-rc.1",
4
4
  "description": "Capybara plugin SDK: the types and pure functions plugins are written against",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {