@thinkwell/acp 0.5.0-alpha.1 → 0.5.0-alpha.2

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/dist/index.d.ts CHANGED
@@ -6,4 +6,8 @@ export { ActiveSession, SessionBuilder } from "./session.js";
6
6
  export type { SessionUpdate, PromptMessage, McpReadyOptions } from "./session.js";
7
7
  export { SacpConnection, connect, connectToConductor } from "./connection.js";
8
8
  export type { SessionOptions } from "./connection.js";
9
+ export { parseSkillMd, validateSkillName, validateSkillDescription } from "./skill.js";
10
+ export type { Skill, VirtualSkill, StoredSkill, SkillTool } from "./skill.js";
11
+ export { createSkillServer } from "./skill-server.js";
12
+ export type { ResolvedSkill } from "./skill-server.js";
9
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACvF,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -6,4 +6,8 @@ export { McpOverAcpHandler } from "./mcp-over-acp-handler.js";
6
6
  export { ActiveSession, SessionBuilder } from "./session.js";
7
7
  // Connection
8
8
  export { SacpConnection, connect, connectToConductor } from "./connection.js";
9
+ // Skills
10
+ export { parseSkillMd, validateSkillName, validateSkillDescription } from "./skill.js";
11
+ // Skill MCP Server
12
+ export { createSkillServer } from "./skill-server.js";
9
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEzE,uBAAuB;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,UAAU;AACV,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG7D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEzE,uBAAuB;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,UAAU;AACV,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG7D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG9E,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAGvF,mBAAmB;AACnB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Skill MCP server builder.
3
+ *
4
+ * Creates an MCP server that exposes three tools for skill interaction:
5
+ * - activate_skill: returns a skill's instruction body
6
+ * - call_skill_tool: dispatches to a virtual skill's tool handler
7
+ * - read_skill_file: reads a file from a stored skill's basePath
8
+ *
9
+ * These tools are registered as standard MCP tools but are intended to be
10
+ * hidden from the prompt (via ThinkBuilder's defineTool pattern).
11
+ */
12
+ import type { McpServer } from "./mcp-server.js";
13
+ import type { VirtualSkill, StoredSkill } from "./skill.js";
14
+ /** A resolved skill is either a VirtualSkill or a StoredSkill. */
15
+ export type ResolvedSkill = VirtualSkill | StoredSkill;
16
+ /**
17
+ * Build an MCP server that provides skill tools.
18
+ *
19
+ * @param skills - resolved skills (virtual or stored) to make available
20
+ * @returns an McpServer with activate_skill, call_skill_tool, and read_skill_file tools
21
+ */
22
+ export declare function createSkillServer(skills: ResolvedSkill[]): McpServer;
23
+ //# sourceMappingURL=skill-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-server.d.ts","sourceRoot":"","sources":["../src/skill-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,WAAW,CAAC;AAOvD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,SAAS,CAmGpE"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Skill MCP server builder.
3
+ *
4
+ * Creates an MCP server that exposes three tools for skill interaction:
5
+ * - activate_skill: returns a skill's instruction body
6
+ * - call_skill_tool: dispatches to a virtual skill's tool handler
7
+ * - read_skill_file: reads a file from a stored skill's basePath
8
+ *
9
+ * These tools are registered as standard MCP tools but are intended to be
10
+ * hidden from the prompt (via ThinkBuilder's defineTool pattern).
11
+ */
12
+ import { readFile } from "node:fs/promises";
13
+ import { resolve, relative, isAbsolute } from "node:path";
14
+ import { mcpServer } from "./mcp-server.js";
15
+ /** Type guard for StoredSkill (has basePath). */
16
+ function isStoredSkill(skill) {
17
+ return "basePath" in skill && typeof skill.basePath === "string";
18
+ }
19
+ /**
20
+ * Build an MCP server that provides skill tools.
21
+ *
22
+ * @param skills - resolved skills (virtual or stored) to make available
23
+ * @returns an McpServer with activate_skill, call_skill_tool, and read_skill_file tools
24
+ */
25
+ export function createSkillServer(skills) {
26
+ const skillsByName = new Map();
27
+ for (const skill of skills) {
28
+ skillsByName.set(skill.name, skill);
29
+ }
30
+ return mcpServer("skills")
31
+ .tool("activate_skill", "Activate a skill by name, returning its full instructions.", {
32
+ type: "object",
33
+ properties: {
34
+ skill_name: { type: "string", description: "The name of the skill to activate" },
35
+ },
36
+ required: ["skill_name"],
37
+ }, { type: "string" }, async (input) => {
38
+ const skill = skillsByName.get(input.skill_name);
39
+ if (!skill) {
40
+ throw new Error(`Unknown skill: "${input.skill_name}"`);
41
+ }
42
+ return skill.body;
43
+ })
44
+ .tool("call_skill_tool", "Call a tool provided by a skill.", {
45
+ type: "object",
46
+ properties: {
47
+ skill_name: { type: "string", description: "The name of the skill that provides the tool" },
48
+ tool_name: { type: "string", description: "The name of the tool to call" },
49
+ input: { description: "Input to pass to the tool handler" },
50
+ },
51
+ required: ["skill_name", "tool_name"],
52
+ }, {}, async (input) => {
53
+ const skill = skillsByName.get(input.skill_name);
54
+ if (!skill) {
55
+ throw new Error(`Unknown skill: "${input.skill_name}"`);
56
+ }
57
+ const tools = skill.tools;
58
+ if (!tools || tools.length === 0) {
59
+ throw new Error(`Skill "${input.skill_name}" has no tools`);
60
+ }
61
+ const tool = tools.find((t) => t.name === input.tool_name);
62
+ if (!tool) {
63
+ throw new Error(`Unknown tool "${input.tool_name}" for skill "${input.skill_name}"`);
64
+ }
65
+ return tool.handler(input.input);
66
+ })
67
+ .tool("read_skill_file", "Read a file from a stored skill's directory.", {
68
+ type: "object",
69
+ properties: {
70
+ skill_name: { type: "string", description: "The name of the skill" },
71
+ path: { type: "string", description: "Relative path to the file within the skill directory" },
72
+ },
73
+ required: ["skill_name", "path"],
74
+ }, { type: "string" }, async (input) => {
75
+ const skill = skillsByName.get(input.skill_name);
76
+ if (!skill) {
77
+ throw new Error(`Unknown skill: "${input.skill_name}"`);
78
+ }
79
+ if (!isStoredSkill(skill)) {
80
+ throw new Error(`Skill "${input.skill_name}" is not a stored skill (no basePath)`);
81
+ }
82
+ // Reject absolute paths outright
83
+ if (isAbsolute(input.path)) {
84
+ throw new Error("Path must be relative");
85
+ }
86
+ const resolved = resolve(skill.basePath, input.path);
87
+ // Path traversal check: resolved path must be within basePath
88
+ const rel = relative(skill.basePath, resolved);
89
+ if (rel.startsWith("..") || isAbsolute(rel)) {
90
+ throw new Error("Path traversal is not allowed");
91
+ }
92
+ return readFile(resolved, "utf-8");
93
+ })
94
+ .build();
95
+ }
96
+ //# sourceMappingURL=skill-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-server.js","sourceRoot":"","sources":["../src/skill-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Skill types and SKILL.md parser for the Agent Skills standard.
3
+ *
4
+ * This module defines the core skill types and provides a parser for
5
+ * SKILL.md files (YAML frontmatter + Markdown body).
6
+ */
7
+ /**
8
+ * A tool bundled with a virtual skill.
9
+ * Same trust model as ThinkBuilder's .tool() -- user-authored handler functions.
10
+ *
11
+ * Unlike top-level .tool() registrations, skill tools are not registered as
12
+ * individual MCP tools with formal schemas. Instead, the skill body documents
13
+ * available tools and their expected inputs as Markdown. The agent invokes them
14
+ * via the generic `call_skill_tool` dispatcher, which routes to the handler.
15
+ */
16
+ export interface SkillTool<I = unknown, O = unknown> {
17
+ name: string;
18
+ description: string;
19
+ handler: (input: I) => Promise<O>;
20
+ }
21
+ /**
22
+ * Base skill definition: metadata + instructions.
23
+ */
24
+ export interface Skill {
25
+ /** Skill name (lowercase, hyphens, matches directory name in the spec) */
26
+ name: string;
27
+ /** When to use this skill (max 1024 chars) */
28
+ description: string;
29
+ /** Full instruction content (Markdown body from SKILL.md) */
30
+ body: string;
31
+ }
32
+ /**
33
+ * A virtual skill defined programmatically, with optional handler functions
34
+ * dispatched via `call_skill_tool`.
35
+ */
36
+ export interface VirtualSkill extends Skill {
37
+ tools?: SkillTool[];
38
+ }
39
+ /**
40
+ * A stored skill loaded from a SKILL.md file on the filesystem.
41
+ * The basePath is used to serve reference docs and assets via `read_skill_file`.
42
+ */
43
+ export interface StoredSkill extends Skill {
44
+ basePath: string;
45
+ }
46
+ /**
47
+ * Validate a skill name per the Agent Skills spec.
48
+ * - 1-64 characters
49
+ * - Lowercase alphanumeric + hyphens
50
+ * - No leading, trailing, or consecutive hyphens
51
+ */
52
+ export declare function validateSkillName(name: unknown): asserts name is string;
53
+ /**
54
+ * Validate a skill description per the Agent Skills spec.
55
+ * - 1-1024 characters
56
+ * - Non-empty (after trimming)
57
+ */
58
+ export declare function validateSkillDescription(description: unknown): asserts description is string;
59
+ /**
60
+ * Parse a SKILL.md file content into a Skill.
61
+ *
62
+ * Extracts YAML frontmatter (delimited by `---`), validates required fields
63
+ * (name, description), and returns the parsed skill with the Markdown body.
64
+ *
65
+ * Optional frontmatter fields (license, compatibility, metadata) are preserved
66
+ * in the returned object but not acted upon.
67
+ *
68
+ * @throws Error if frontmatter is missing, malformed, or required fields are invalid
69
+ */
70
+ export declare function parseSkillMd(content: string): Skill & Record<string, unknown>;
71
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,YAAa,SAAQ,KAAK;IACzC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAWD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAYvE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,IAAI,MAAM,CAS5F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa7E"}
package/dist/skill.js ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Skill types and SKILL.md parser for the Agent Skills standard.
3
+ *
4
+ * This module defines the core skill types and provides a parser for
5
+ * SKILL.md files (YAML frontmatter + Markdown body).
6
+ */
7
+ /** Validation pattern for skill names: lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens. */
8
+ const SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9]))*$/;
9
+ /** Maximum length for skill names. */
10
+ const MAX_NAME_LENGTH = 64;
11
+ /** Maximum length for skill descriptions. */
12
+ const MAX_DESCRIPTION_LENGTH = 1024;
13
+ /**
14
+ * Validate a skill name per the Agent Skills spec.
15
+ * - 1-64 characters
16
+ * - Lowercase alphanumeric + hyphens
17
+ * - No leading, trailing, or consecutive hyphens
18
+ */
19
+ export function validateSkillName(name) {
20
+ if (typeof name !== "string" || name.length === 0) {
21
+ throw new Error("Skill name is required");
22
+ }
23
+ if (name.length > MAX_NAME_LENGTH) {
24
+ throw new Error(`Skill name must be at most ${MAX_NAME_LENGTH} characters, got ${name.length}`);
25
+ }
26
+ if (!SKILL_NAME_PATTERN.test(name)) {
27
+ throw new Error(`Invalid skill name "${name}": must be lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens`);
28
+ }
29
+ }
30
+ /**
31
+ * Validate a skill description per the Agent Skills spec.
32
+ * - 1-1024 characters
33
+ * - Non-empty (after trimming)
34
+ */
35
+ export function validateSkillDescription(description) {
36
+ if (typeof description !== "string" || description.trim().length === 0) {
37
+ throw new Error("Skill description is required");
38
+ }
39
+ if (description.length > MAX_DESCRIPTION_LENGTH) {
40
+ throw new Error(`Skill description must be at most ${MAX_DESCRIPTION_LENGTH} characters, got ${description.length}`);
41
+ }
42
+ }
43
+ /**
44
+ * Parse a SKILL.md file content into a Skill.
45
+ *
46
+ * Extracts YAML frontmatter (delimited by `---`), validates required fields
47
+ * (name, description), and returns the parsed skill with the Markdown body.
48
+ *
49
+ * Optional frontmatter fields (license, compatibility, metadata) are preserved
50
+ * in the returned object but not acted upon.
51
+ *
52
+ * @throws Error if frontmatter is missing, malformed, or required fields are invalid
53
+ */
54
+ export function parseSkillMd(content) {
55
+ const { frontmatter, body } = extractFrontmatter(content);
56
+ const fields = parseYamlFrontmatter(frontmatter);
57
+ validateSkillName(fields.name);
58
+ validateSkillDescription(fields.description);
59
+ return {
60
+ ...fields,
61
+ name: fields.name,
62
+ description: fields.description,
63
+ body,
64
+ };
65
+ }
66
+ /**
67
+ * Extract YAML frontmatter and body from a SKILL.md string.
68
+ * Frontmatter is delimited by opening and closing `---` lines.
69
+ */
70
+ function extractFrontmatter(content) {
71
+ const trimmed = content.trimStart();
72
+ if (!trimmed.startsWith("---")) {
73
+ throw new Error("SKILL.md must begin with YAML frontmatter (---)");
74
+ }
75
+ // Find the closing `---` after the opening one
76
+ const endIndex = trimmed.indexOf("\n---", 3);
77
+ if (endIndex === -1) {
78
+ throw new Error("SKILL.md frontmatter is missing closing ---");
79
+ }
80
+ const frontmatter = trimmed.slice(3, endIndex).trim();
81
+ // Body starts after the closing `---` and its newline
82
+ const afterClosing = endIndex + 4; // "\n---".length
83
+ // Strip the line ending after the closing --- and any single blank line
84
+ const body = trimmed.slice(afterClosing).replace(/^(\r?\n){1,2}/, "");
85
+ return { frontmatter, body };
86
+ }
87
+ /**
88
+ * Minimal YAML parser for SKILL.md frontmatter.
89
+ *
90
+ * Supports only the flat key-value structure needed for skill metadata:
91
+ * simple string values (quoted or unquoted). This is intentionally limited --
92
+ * we don't need nested objects, arrays, or other YAML features.
93
+ */
94
+ function parseYamlFrontmatter(yaml) {
95
+ const result = {};
96
+ for (const line of yaml.split("\n")) {
97
+ const trimmed = line.trim();
98
+ if (trimmed === "" || trimmed.startsWith("#"))
99
+ continue;
100
+ const colonIndex = trimmed.indexOf(":");
101
+ if (colonIndex === -1) {
102
+ throw new Error(`Invalid frontmatter line: ${trimmed}`);
103
+ }
104
+ const key = trimmed.slice(0, colonIndex).trim();
105
+ let value = trimmed.slice(colonIndex + 1).trim();
106
+ // Strip surrounding quotes (single or double)
107
+ if (typeof value === "string") {
108
+ if ((value.startsWith('"') && value.endsWith('"')) ||
109
+ (value.startsWith("'") && value.endsWith("'"))) {
110
+ value = value.slice(1, -1);
111
+ }
112
+ }
113
+ result[key] = value;
114
+ }
115
+ return result;
116
+ }
117
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkwell/acp",
3
- "version": "0.5.0-alpha.1",
3
+ "version": "0.5.0-alpha.2",
4
4
  "description": "TypeScript implementation of ACP (Agent Client Protocol) extensions for Thinkwell",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -27,8 +27,8 @@
27
27
  "dependencies": {
28
28
  "@agentclientprotocol/sdk": "^0.4.0",
29
29
  "uuid": "^11.0.3",
30
- "@thinkwell/conductor": "0.5.0-alpha.1",
31
- "@thinkwell/protocol": "0.5.0-alpha.1"
30
+ "@thinkwell/conductor": "0.5.0-alpha.2",
31
+ "@thinkwell/protocol": "0.5.0-alpha.2"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^24.10.4",