toolfactory 0.2.0 → 0.2.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 +1 -1
- package/dist/surfaces/dsh.js +2 -1
- package/dist/surfaces/dsh.test.js +30 -1
- package/dist/surfaces/web.d.ts +1 -1
- package/dist/surfaces/web.js +1 -1
- package/dist/toolfactory/cli.js +1 -1
- package/dist/toolfactory/mcp.js +1 -1
- package/package.json +1 -1
- package/src/surfaces/dsh.test.ts +31 -1
- package/src/surfaces/dsh.ts +2 -1
- package/src/surfaces/web.ts +1 -1
- package/src/toolfactory/cli.ts +1 -1
- package/src/toolfactory/mcp.ts +1 -1
- package/web/dist/assets/{index-CVm6m4s0.js → index-BHR6gCfm.js} +1 -1
- package/web/dist/index.html +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ generated and every surface still installs, builds and publishes.
|
|
|
22
22
|
- **Gemini CLI extension** — `gemini extensions install https://github.com/GoatInAHat/toolfactory`
|
|
23
23
|
- **OpenClaw plugin** — `openclaw plugins install --link hosts/openclaw` from a checkout
|
|
24
24
|
- **Hermes plugin** — `hermes plugins install https://github.com/GoatInAHat/toolfactory#hosts/hermes/toolfactory_hermes`
|
|
25
|
-
- **DSH plugin** (experimental) — `dsh plugin --profile <profile> add ./hosts/dsh` from a checkout, or the release tarball `toolfactory-dsh-0.2.
|
|
25
|
+
- **DSH plugin** (experimental) — `dsh plugin --profile <profile> add ./hosts/dsh` from a checkout, or the release tarball `toolfactory-dsh-0.2.1.tgz`
|
|
26
26
|
- **Web app** — `npx -y toolfactory mcp --http --open` serves the operations page beside the
|
|
27
27
|
MCP endpoint on one port and opens it; over MCP or a skill, the `web` operation does the same and
|
|
28
28
|
returns the URL.
|
package/dist/surfaces/dsh.js
CHANGED
|
@@ -82,7 +82,8 @@ function patch(project, launch) {
|
|
|
82
82
|
failOnStartupError: true,
|
|
83
83
|
}),
|
|
84
84
|
};
|
|
85
|
-
|
|
85
|
+
// Region replacement starts immediately after the comment marker.
|
|
86
|
+
return `\n${yamlStringify([{ insert: [row] }], { lineWidth: 0 })}`;
|
|
86
87
|
}
|
|
87
88
|
function patchTemplate() {
|
|
88
89
|
return `${PATCH_BEGIN}\n${PATCH_END}\n\n# Yours: add Cordis rows or local code configuration below this marker.\n`;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
1
4
|
import { describe, expect, it } from "vitest";
|
|
2
5
|
import { parse as parseYaml } from "yaml";
|
|
6
|
+
import { apply, replaceRegions } from "../project/apply.js";
|
|
3
7
|
import { DSH_PIN, surface as dsh } from "./dsh.js";
|
|
4
8
|
const echo = { name: "echo", inputSchema: { type: "object" }, requires: [] };
|
|
5
9
|
const browse = {
|
|
@@ -37,10 +41,35 @@ const files = Object.fromEntries(dsh.plan(project).map((file) => {
|
|
|
37
41
|
? file.content
|
|
38
42
|
: file.kind === "merge"
|
|
39
43
|
? JSON.stringify(file.patch)
|
|
40
|
-
: file.
|
|
44
|
+
: (replaceRegions(file.template, file) ?? file.template),
|
|
41
45
|
];
|
|
42
46
|
}));
|
|
43
47
|
describe("dsh", () => {
|
|
48
|
+
it("rebuilds legacy patch regions without commenting out insert or losing authored rows", () => {
|
|
49
|
+
const root = mkdtempSync(join(tmpdir(), "toolfactory-dsh-"));
|
|
50
|
+
try {
|
|
51
|
+
const plan = dsh.plan({ ...project, root });
|
|
52
|
+
const patches = plan.filter((file) => file.kind === "region");
|
|
53
|
+
apply(root, plan, project.toolfactoryVersion);
|
|
54
|
+
for (const file of patches) {
|
|
55
|
+
const path = join(root, file.path);
|
|
56
|
+
const legacy = readFileSync(path, "utf8").replace("# tf:mcp\n", "# tf:mcp");
|
|
57
|
+
writeFileSync(path, `${legacy}\n- insert:\n - id: authored\n`);
|
|
58
|
+
}
|
|
59
|
+
apply(root, plan, project.toolfactoryVersion);
|
|
60
|
+
for (const file of patches) {
|
|
61
|
+
const rendered = readFileSync(join(root, file.path), "utf8");
|
|
62
|
+
expect(rendered).toMatch(/^# tf:mcp\n- insert:/);
|
|
63
|
+
expect(parseYaml(rendered, { logLevel: "silent" })).toMatchObject([
|
|
64
|
+
{ insert: [{ id: "mcp-hello-tool" }] },
|
|
65
|
+
{ insert: [{ id: "authored" }] },
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
rmSync(root, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
44
73
|
it("is two shipped files and no code: the bundle manifest and one mcp-client insert row", () => {
|
|
45
74
|
// `dsh.bundle.patch` is DSH's whole acceptance test for a bundle; a dependency would be wrong,
|
|
46
75
|
// because @deepseek-ai/dsh-mcp-client is @deepseek-ai/dsh's own.
|
package/dist/surfaces/web.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare const WEB_SCAFFOLD: {
|
|
|
37
37
|
readonly "@tailwindcss/vite": "^4.3.3";
|
|
38
38
|
readonly "class-variance-authority": "^0.7.1";
|
|
39
39
|
readonly cn: "^0.2.6";
|
|
40
|
-
readonly "lucide-react": "^1.
|
|
40
|
+
readonly "lucide-react": "^1.43.0";
|
|
41
41
|
readonly react: "^19.2.8";
|
|
42
42
|
readonly "react-dom": "^19.2.8";
|
|
43
43
|
readonly shadcn: "^4.21.0";
|
package/dist/surfaces/web.js
CHANGED
|
@@ -150,7 +150,7 @@ export default defineConfig({
|
|
|
150
150
|
"@tailwindcss/vite": "^4.3.3",
|
|
151
151
|
"class-variance-authority": "^0.7.1",
|
|
152
152
|
cn: "^0.2.6",
|
|
153
|
-
"lucide-react": "^1.
|
|
153
|
+
"lucide-react": "^1.43.0",
|
|
154
154
|
react: "^19.2.8",
|
|
155
155
|
"react-dom": "^19.2.8",
|
|
156
156
|
shadcn: "^4.21.0",
|
package/dist/toolfactory/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ const operations = [...authored, web];
|
|
|
11
11
|
const program = new Command()
|
|
12
12
|
.name("toolfactory")
|
|
13
13
|
.description("Build an agent tool once; ship it as Agent Skills, MCP servers, Agent Plugins / Claude / Codex / Cursor bundles, OpenClaw and Hermes plugins, CLIs, and packages, with the tests and releases to match.")
|
|
14
|
-
.version("0.2.
|
|
14
|
+
.version("0.2.1");
|
|
15
15
|
for (const op of operations) {
|
|
16
16
|
if (!serves(op, "cli"))
|
|
17
17
|
continue;
|
package/dist/toolfactory/mcp.js
CHANGED
|
@@ -30,7 +30,7 @@ const operations = [...authored, web];
|
|
|
30
30
|
const introspecting = Boolean(process.env.TOOLFACTORY_INTROSPECT);
|
|
31
31
|
/** Builds one server instance with every servable operation registered; called once for stdio, once per HTTP request. */
|
|
32
32
|
function createServer() {
|
|
33
|
-
const server = new McpServer({ name: "toolfactory", version: "0.2.
|
|
33
|
+
const server = new McpServer({ name: "toolfactory", version: "0.2.1" });
|
|
34
34
|
for (const op of operations) {
|
|
35
35
|
if (!introspecting && !serves(op, "mcp"))
|
|
36
36
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolfactory",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Build an agent tool once; ship it as Agent Skills, MCP servers, Agent Plugins / Claude / Codex / Cursor bundles, OpenClaw and Hermes plugins, CLIs, and packages, with the tests and releases to match.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/src/surfaces/dsh.test.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
1
4
|
import { describe, expect, it } from "vitest";
|
|
2
5
|
import { parse as parseYaml } from "yaml";
|
|
3
6
|
import type { Operation, Project } from "../model.js";
|
|
7
|
+
import { apply, replaceRegions } from "../project/apply.js";
|
|
4
8
|
import { DSH_PIN, surface as dsh } from "./dsh.js";
|
|
5
9
|
|
|
6
10
|
const echo: Operation = { name: "echo", inputSchema: { type: "object" }, requires: [] };
|
|
@@ -42,12 +46,38 @@ const files = Object.fromEntries(
|
|
|
42
46
|
? file.content
|
|
43
47
|
: file.kind === "merge"
|
|
44
48
|
? JSON.stringify(file.patch)
|
|
45
|
-
: file.
|
|
49
|
+
: (replaceRegions(file.template, file) ?? file.template),
|
|
46
50
|
];
|
|
47
51
|
}),
|
|
48
52
|
);
|
|
49
53
|
|
|
50
54
|
describe("dsh", () => {
|
|
55
|
+
it("rebuilds legacy patch regions without commenting out insert or losing authored rows", () => {
|
|
56
|
+
const root = mkdtempSync(join(tmpdir(), "toolfactory-dsh-"));
|
|
57
|
+
try {
|
|
58
|
+
const plan = dsh.plan({ ...project, root });
|
|
59
|
+
const patches = plan.filter((file) => file.kind === "region");
|
|
60
|
+
apply(root, plan, project.toolfactoryVersion);
|
|
61
|
+
for (const file of patches) {
|
|
62
|
+
const path = join(root, file.path);
|
|
63
|
+
const legacy = readFileSync(path, "utf8").replace("# tf:mcp\n", "# tf:mcp");
|
|
64
|
+
writeFileSync(path, `${legacy}\n- insert:\n - id: authored\n`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
apply(root, plan, project.toolfactoryVersion);
|
|
68
|
+
for (const file of patches) {
|
|
69
|
+
const rendered = readFileSync(join(root, file.path), "utf8");
|
|
70
|
+
expect(rendered).toMatch(/^# tf:mcp\n- insert:/);
|
|
71
|
+
expect(parseYaml(rendered, { logLevel: "silent" })).toMatchObject([
|
|
72
|
+
{ insert: [{ id: "mcp-hello-tool" }] },
|
|
73
|
+
{ insert: [{ id: "authored" }] },
|
|
74
|
+
]);
|
|
75
|
+
}
|
|
76
|
+
} finally {
|
|
77
|
+
rmSync(root, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
51
81
|
it("is two shipped files and no code: the bundle manifest and one mcp-client insert row", () => {
|
|
52
82
|
// `dsh.bundle.patch` is DSH's whole acceptance test for a bundle; a dependency would be wrong,
|
|
53
83
|
// because @deepseek-ai/dsh-mcp-client is @deepseek-ai/dsh's own.
|
package/src/surfaces/dsh.ts
CHANGED
|
@@ -90,7 +90,8 @@ function patch(project: Project, launch: { command: string; args: string[] }): s
|
|
|
90
90
|
failOnStartupError: true,
|
|
91
91
|
}),
|
|
92
92
|
};
|
|
93
|
-
|
|
93
|
+
// Region replacement starts immediately after the comment marker.
|
|
94
|
+
return `\n${yamlStringify([{ insert: [row] }], { lineWidth: 0 })}`;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
function patchTemplate(): string {
|
package/src/surfaces/web.ts
CHANGED
|
@@ -154,7 +154,7 @@ export default defineConfig({
|
|
|
154
154
|
"@tailwindcss/vite": "^4.3.3",
|
|
155
155
|
"class-variance-authority": "^0.7.1",
|
|
156
156
|
cn: "^0.2.6",
|
|
157
|
-
"lucide-react": "^1.
|
|
157
|
+
"lucide-react": "^1.43.0",
|
|
158
158
|
react: "^19.2.8",
|
|
159
159
|
"react-dom": "^19.2.8",
|
|
160
160
|
shadcn: "^4.21.0",
|
package/src/toolfactory/cli.ts
CHANGED
|
@@ -13,7 +13,7 @@ const operations = [...authored, web];
|
|
|
13
13
|
const program = new Command()
|
|
14
14
|
.name("toolfactory")
|
|
15
15
|
.description("Build an agent tool once; ship it as Agent Skills, MCP servers, Agent Plugins / Claude / Codex / Cursor bundles, OpenClaw and Hermes plugins, CLIs, and packages, with the tests and releases to match.")
|
|
16
|
-
.version("0.2.
|
|
16
|
+
.version("0.2.1");
|
|
17
17
|
|
|
18
18
|
for (const op of operations) {
|
|
19
19
|
if (!serves(op, "cli")) continue;
|
package/src/toolfactory/mcp.ts
CHANGED
|
@@ -33,7 +33,7 @@ const introspecting = Boolean(process.env.TOOLFACTORY_INTROSPECT);
|
|
|
33
33
|
|
|
34
34
|
/** Builds one server instance with every servable operation registered; called once for stdio, once per HTTP request. */
|
|
35
35
|
function createServer(): McpServer {
|
|
36
|
-
const server = new McpServer({ name: "toolfactory", version: "0.2.
|
|
36
|
+
const server = new McpServer({ name: "toolfactory", version: "0.2.1" });
|
|
37
37
|
for (const op of operations) {
|
|
38
38
|
if (!introspecting && !serves(op, "mcp")) continue;
|
|
39
39
|
server.registerTool(
|