@dexto/tools-plan 1.6.0 → 1.6.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/errors.cjs +126 -0
- package/dist/errors.js +99 -64
- package/dist/index.cjs +36 -0
- package/dist/index.d.cts +224 -0
- package/dist/index.js +9 -12
- package/dist/plan-service-getter.cjs +16 -0
- package/dist/plan-service-getter.js +0 -1
- package/dist/plan-service.cjs +247 -0
- package/dist/plan-service.js +201 -215
- package/dist/plan-service.test.cjs +227 -0
- package/dist/plan-service.test.js +200 -222
- package/dist/tool-factory-config.cjs +38 -0
- package/dist/tool-factory-config.js +13 -30
- package/dist/tool-factory.cjs +71 -0
- package/dist/tool-factory.js +39 -35
- package/dist/tool-factory.test.cjs +96 -0
- package/dist/tool-factory.test.js +90 -95
- package/dist/tools/plan-create-tool.cjs +102 -0
- package/dist/tools/plan-create-tool.d.ts.map +1 -1
- package/dist/tools/plan-create-tool.js +77 -82
- package/dist/tools/plan-create-tool.test.cjs +174 -0
- package/dist/tools/plan-create-tool.test.js +142 -134
- package/dist/tools/plan-read-tool.cjs +65 -0
- package/dist/tools/plan-read-tool.d.ts.map +1 -1
- package/dist/tools/plan-read-tool.js +39 -41
- package/dist/tools/plan-read-tool.test.cjs +109 -0
- package/dist/tools/plan-read-tool.test.js +78 -87
- package/dist/tools/plan-review-tool.cjs +98 -0
- package/dist/tools/plan-review-tool.d.ts.map +1 -1
- package/dist/tools/plan-review-tool.js +73 -87
- package/dist/tools/plan-update-tool.cjs +92 -0
- package/dist/tools/plan-update-tool.d.ts.map +1 -1
- package/dist/tools/plan-update-tool.js +65 -73
- package/dist/tools/plan-update-tool.test.cjs +203 -0
- package/dist/tools/plan-update-tool.test.js +171 -154
- package/dist/types.cjs +44 -0
- package/dist/types.js +17 -24
- package/package.json +8 -7
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var tool_factory_config_exports = {};
|
|
20
|
+
__export(tool_factory_config_exports, {
|
|
21
|
+
PLAN_TOOL_NAMES: () => PLAN_TOOL_NAMES,
|
|
22
|
+
PlanToolsConfigSchema: () => PlanToolsConfigSchema
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(tool_factory_config_exports);
|
|
25
|
+
var import_zod = require("zod");
|
|
26
|
+
const PLAN_TOOL_NAMES = ["plan_create", "plan_read", "plan_update", "plan_review"];
|
|
27
|
+
const PlanToolsConfigSchema = import_zod.z.object({
|
|
28
|
+
type: import_zod.z.literal("plan-tools"),
|
|
29
|
+
basePath: import_zod.z.string().default(".dexto/plans").describe("Base directory for plan storage (relative to working directory)"),
|
|
30
|
+
enabledTools: import_zod.z.array(import_zod.z.enum(PLAN_TOOL_NAMES)).optional().describe(
|
|
31
|
+
`Subset of tools to enable. If not specified, all tools are enabled. Available: ${PLAN_TOOL_NAMES.join(", ")}`
|
|
32
|
+
)
|
|
33
|
+
}).strict();
|
|
34
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
35
|
+
0 && (module.exports = {
|
|
36
|
+
PLAN_TOOL_NAMES,
|
|
37
|
+
PlanToolsConfigSchema
|
|
38
|
+
});
|
|
@@ -1,30 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export const PLAN_TOOL_NAMES = ['plan_create', 'plan_read', 'plan_update', 'plan_review'];
|
|
15
|
-
/**
|
|
16
|
-
* Configuration schema for Plan tools factory
|
|
17
|
-
*/
|
|
18
|
-
export const PlanToolsConfigSchema = z
|
|
19
|
-
.object({
|
|
20
|
-
type: z.literal('plan-tools'),
|
|
21
|
-
basePath: z
|
|
22
|
-
.string()
|
|
23
|
-
.default('.dexto/plans')
|
|
24
|
-
.describe('Base directory for plan storage (relative to working directory)'),
|
|
25
|
-
enabledTools: z
|
|
26
|
-
.array(z.enum(PLAN_TOOL_NAMES))
|
|
27
|
-
.optional()
|
|
28
|
-
.describe(`Subset of tools to enable. If not specified, all tools are enabled. Available: ${PLAN_TOOL_NAMES.join(', ')}`),
|
|
29
|
-
})
|
|
30
|
-
.strict();
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const PLAN_TOOL_NAMES = ["plan_create", "plan_read", "plan_update", "plan_review"];
|
|
3
|
+
const PlanToolsConfigSchema = z.object({
|
|
4
|
+
type: z.literal("plan-tools"),
|
|
5
|
+
basePath: z.string().default(".dexto/plans").describe("Base directory for plan storage (relative to working directory)"),
|
|
6
|
+
enabledTools: z.array(z.enum(PLAN_TOOL_NAMES)).optional().describe(
|
|
7
|
+
`Subset of tools to enable. If not specified, all tools are enabled. Available: ${PLAN_TOOL_NAMES.join(", ")}`
|
|
8
|
+
)
|
|
9
|
+
}).strict();
|
|
10
|
+
export {
|
|
11
|
+
PLAN_TOOL_NAMES,
|
|
12
|
+
PlanToolsConfigSchema
|
|
13
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var tool_factory_exports = {};
|
|
30
|
+
__export(tool_factory_exports, {
|
|
31
|
+
planToolsFactory: () => planToolsFactory
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(tool_factory_exports);
|
|
34
|
+
var path = __toESM(require("node:path"), 1);
|
|
35
|
+
var import_plan_service = require("./plan-service.js");
|
|
36
|
+
var import_plan_create_tool = require("./tools/plan-create-tool.js");
|
|
37
|
+
var import_plan_read_tool = require("./tools/plan-read-tool.js");
|
|
38
|
+
var import_plan_update_tool = require("./tools/plan-update-tool.js");
|
|
39
|
+
var import_plan_review_tool = require("./tools/plan-review-tool.js");
|
|
40
|
+
var import_tool_factory_config = require("./tool-factory-config.js");
|
|
41
|
+
const planToolsFactory = {
|
|
42
|
+
configSchema: import_tool_factory_config.PlanToolsConfigSchema,
|
|
43
|
+
metadata: {
|
|
44
|
+
displayName: "Plan Tools",
|
|
45
|
+
description: "Create and manage implementation plans linked to sessions",
|
|
46
|
+
category: "planning"
|
|
47
|
+
},
|
|
48
|
+
create: (config) => {
|
|
49
|
+
const basePath = path.isAbsolute(config.basePath) ? config.basePath : path.join(process.cwd(), config.basePath);
|
|
50
|
+
let planService;
|
|
51
|
+
const getPlanService = async (context) => {
|
|
52
|
+
if (planService) {
|
|
53
|
+
return planService;
|
|
54
|
+
}
|
|
55
|
+
planService = new import_plan_service.PlanService({ basePath }, context.logger);
|
|
56
|
+
return planService;
|
|
57
|
+
};
|
|
58
|
+
const toolCreators = {
|
|
59
|
+
plan_create: () => (0, import_plan_create_tool.createPlanCreateTool)(getPlanService),
|
|
60
|
+
plan_read: () => (0, import_plan_read_tool.createPlanReadTool)(getPlanService),
|
|
61
|
+
plan_update: () => (0, import_plan_update_tool.createPlanUpdateTool)(getPlanService),
|
|
62
|
+
plan_review: () => (0, import_plan_review_tool.createPlanReviewTool)(getPlanService)
|
|
63
|
+
};
|
|
64
|
+
const toolsToCreate = config.enabledTools ?? import_tool_factory_config.PLAN_TOOL_NAMES;
|
|
65
|
+
return toolsToCreate.map((toolName) => toolCreators[toolName]());
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
69
|
+
0 && (module.exports = {
|
|
70
|
+
planToolsFactory
|
|
71
|
+
});
|
package/dist/tool-factory.js
CHANGED
|
@@ -1,36 +1,40 @@
|
|
|
1
|
-
import * as path from
|
|
2
|
-
import { PlanService } from
|
|
3
|
-
import { createPlanCreateTool } from
|
|
4
|
-
import { createPlanReadTool } from
|
|
5
|
-
import { createPlanUpdateTool } from
|
|
6
|
-
import { createPlanReviewTool } from
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { PlanService } from "./plan-service.js";
|
|
3
|
+
import { createPlanCreateTool } from "./tools/plan-create-tool.js";
|
|
4
|
+
import { createPlanReadTool } from "./tools/plan-read-tool.js";
|
|
5
|
+
import { createPlanUpdateTool } from "./tools/plan-update-tool.js";
|
|
6
|
+
import { createPlanReviewTool } from "./tools/plan-review-tool.js";
|
|
7
|
+
import {
|
|
8
|
+
PLAN_TOOL_NAMES,
|
|
9
|
+
PlanToolsConfigSchema
|
|
10
|
+
} from "./tool-factory-config.js";
|
|
11
|
+
const planToolsFactory = {
|
|
12
|
+
configSchema: PlanToolsConfigSchema,
|
|
13
|
+
metadata: {
|
|
14
|
+
displayName: "Plan Tools",
|
|
15
|
+
description: "Create and manage implementation plans linked to sessions",
|
|
16
|
+
category: "planning"
|
|
17
|
+
},
|
|
18
|
+
create: (config) => {
|
|
19
|
+
const basePath = path.isAbsolute(config.basePath) ? config.basePath : path.join(process.cwd(), config.basePath);
|
|
20
|
+
let planService;
|
|
21
|
+
const getPlanService = async (context) => {
|
|
22
|
+
if (planService) {
|
|
23
|
+
return planService;
|
|
24
|
+
}
|
|
25
|
+
planService = new PlanService({ basePath }, context.logger);
|
|
26
|
+
return planService;
|
|
27
|
+
};
|
|
28
|
+
const toolCreators = {
|
|
29
|
+
plan_create: () => createPlanCreateTool(getPlanService),
|
|
30
|
+
plan_read: () => createPlanReadTool(getPlanService),
|
|
31
|
+
plan_update: () => createPlanUpdateTool(getPlanService),
|
|
32
|
+
plan_review: () => createPlanReviewTool(getPlanService)
|
|
33
|
+
};
|
|
34
|
+
const toolsToCreate = config.enabledTools ?? PLAN_TOOL_NAMES;
|
|
35
|
+
return toolsToCreate.map((toolName) => toolCreators[toolName]());
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
export {
|
|
39
|
+
planToolsFactory
|
|
36
40
|
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_vitest = require("vitest");
|
|
3
|
+
var import_tool_factory = require("./tool-factory.js");
|
|
4
|
+
(0, import_vitest.describe)("planToolsFactory", () => {
|
|
5
|
+
(0, import_vitest.describe)("factory metadata", () => {
|
|
6
|
+
(0, import_vitest.it)("should have metadata", () => {
|
|
7
|
+
(0, import_vitest.expect)(import_tool_factory.planToolsFactory.metadata).toBeDefined();
|
|
8
|
+
(0, import_vitest.expect)(import_tool_factory.planToolsFactory.metadata?.displayName).toBe("Plan Tools");
|
|
9
|
+
(0, import_vitest.expect)(import_tool_factory.planToolsFactory.metadata?.category).toBe("planning");
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
(0, import_vitest.describe)("config schema", () => {
|
|
13
|
+
(0, import_vitest.it)("should validate minimal config", () => {
|
|
14
|
+
const result = import_tool_factory.planToolsFactory.configSchema.safeParse({
|
|
15
|
+
type: "plan-tools"
|
|
16
|
+
});
|
|
17
|
+
(0, import_vitest.expect)(result.success).toBe(true);
|
|
18
|
+
if (result.success) {
|
|
19
|
+
(0, import_vitest.expect)(result.data.basePath).toBe(".dexto/plans");
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
(0, import_vitest.it)("should validate config with custom basePath", () => {
|
|
23
|
+
const result = import_tool_factory.planToolsFactory.configSchema.safeParse({
|
|
24
|
+
type: "plan-tools",
|
|
25
|
+
basePath: "/custom/path"
|
|
26
|
+
});
|
|
27
|
+
(0, import_vitest.expect)(result.success).toBe(true);
|
|
28
|
+
if (result.success) {
|
|
29
|
+
(0, import_vitest.expect)(result.data.basePath).toBe("/custom/path");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
(0, import_vitest.it)("should validate config with enabledTools", () => {
|
|
33
|
+
const result = import_tool_factory.planToolsFactory.configSchema.safeParse({
|
|
34
|
+
type: "plan-tools",
|
|
35
|
+
enabledTools: ["plan_create", "plan_read"]
|
|
36
|
+
});
|
|
37
|
+
(0, import_vitest.expect)(result.success).toBe(true);
|
|
38
|
+
if (result.success) {
|
|
39
|
+
(0, import_vitest.expect)(result.data.enabledTools).toEqual(["plan_create", "plan_read"]);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
(0, import_vitest.it)("should reject invalid tool names", () => {
|
|
43
|
+
const result = import_tool_factory.planToolsFactory.configSchema.safeParse({
|
|
44
|
+
type: "plan-tools",
|
|
45
|
+
enabledTools: ["invalid_tool"]
|
|
46
|
+
});
|
|
47
|
+
(0, import_vitest.expect)(result.success).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
(0, import_vitest.it)("should reject unknown properties", () => {
|
|
50
|
+
const result = import_tool_factory.planToolsFactory.configSchema.safeParse({
|
|
51
|
+
type: "plan-tools",
|
|
52
|
+
unknownProp: "value"
|
|
53
|
+
});
|
|
54
|
+
(0, import_vitest.expect)(result.success).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
(0, import_vitest.describe)("create", () => {
|
|
58
|
+
(0, import_vitest.it)("should create all tools by default", () => {
|
|
59
|
+
const config = import_tool_factory.planToolsFactory.configSchema.parse({
|
|
60
|
+
type: "plan-tools"
|
|
61
|
+
});
|
|
62
|
+
const tools = import_tool_factory.planToolsFactory.create(config);
|
|
63
|
+
(0, import_vitest.expect)(tools).toHaveLength(4);
|
|
64
|
+
const toolIds = tools.map((t) => t.id);
|
|
65
|
+
(0, import_vitest.expect)(toolIds).toContain("plan_create");
|
|
66
|
+
(0, import_vitest.expect)(toolIds).toContain("plan_read");
|
|
67
|
+
(0, import_vitest.expect)(toolIds).toContain("plan_update");
|
|
68
|
+
(0, import_vitest.expect)(toolIds).toContain("plan_review");
|
|
69
|
+
});
|
|
70
|
+
(0, import_vitest.it)("should create only enabled tools", () => {
|
|
71
|
+
const config = import_tool_factory.planToolsFactory.configSchema.parse({
|
|
72
|
+
type: "plan-tools",
|
|
73
|
+
enabledTools: ["plan_create", "plan_read"]
|
|
74
|
+
});
|
|
75
|
+
const tools = import_tool_factory.planToolsFactory.create(config);
|
|
76
|
+
(0, import_vitest.expect)(tools).toHaveLength(2);
|
|
77
|
+
const toolIds = tools.map((t) => t.id);
|
|
78
|
+
(0, import_vitest.expect)(toolIds).toContain("plan_create");
|
|
79
|
+
(0, import_vitest.expect)(toolIds).toContain("plan_read");
|
|
80
|
+
(0, import_vitest.expect)(toolIds).not.toContain("plan_update");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
(0, import_vitest.describe)("tool definitions", () => {
|
|
84
|
+
(0, import_vitest.it)("should have descriptions and input schemas for all tools", () => {
|
|
85
|
+
const config = import_tool_factory.planToolsFactory.configSchema.parse({
|
|
86
|
+
type: "plan-tools"
|
|
87
|
+
});
|
|
88
|
+
const tools = import_tool_factory.planToolsFactory.create(config);
|
|
89
|
+
for (const tool of tools) {
|
|
90
|
+
(0, import_vitest.expect)(tool.description).toBeDefined();
|
|
91
|
+
(0, import_vitest.expect)(tool.description.length).toBeGreaterThan(0);
|
|
92
|
+
(0, import_vitest.expect)(tool.inputSchema).toBeDefined();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -1,100 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
describe('factory metadata', () => {
|
|
10
|
-
it('should have metadata', () => {
|
|
11
|
-
expect(planToolsFactory.metadata).toBeDefined();
|
|
12
|
-
expect(planToolsFactory.metadata?.displayName).toBe('Plan Tools');
|
|
13
|
-
expect(planToolsFactory.metadata?.category).toBe('planning');
|
|
14
|
-
});
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { planToolsFactory } from "./tool-factory.js";
|
|
3
|
+
describe("planToolsFactory", () => {
|
|
4
|
+
describe("factory metadata", () => {
|
|
5
|
+
it("should have metadata", () => {
|
|
6
|
+
expect(planToolsFactory.metadata).toBeDefined();
|
|
7
|
+
expect(planToolsFactory.metadata?.displayName).toBe("Plan Tools");
|
|
8
|
+
expect(planToolsFactory.metadata?.category).toBe("planning");
|
|
15
9
|
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
it('should validate config with custom basePath', () => {
|
|
27
|
-
const result = planToolsFactory.configSchema.safeParse({
|
|
28
|
-
type: 'plan-tools',
|
|
29
|
-
basePath: '/custom/path',
|
|
30
|
-
});
|
|
31
|
-
expect(result.success).toBe(true);
|
|
32
|
-
if (result.success) {
|
|
33
|
-
expect(result.data.basePath).toBe('/custom/path');
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
it('should validate config with enabledTools', () => {
|
|
37
|
-
const result = planToolsFactory.configSchema.safeParse({
|
|
38
|
-
type: 'plan-tools',
|
|
39
|
-
enabledTools: ['plan_create', 'plan_read'],
|
|
40
|
-
});
|
|
41
|
-
expect(result.success).toBe(true);
|
|
42
|
-
if (result.success) {
|
|
43
|
-
expect(result.data.enabledTools).toEqual(['plan_create', 'plan_read']);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
it('should reject invalid tool names', () => {
|
|
47
|
-
const result = planToolsFactory.configSchema.safeParse({
|
|
48
|
-
type: 'plan-tools',
|
|
49
|
-
enabledTools: ['invalid_tool'],
|
|
50
|
-
});
|
|
51
|
-
expect(result.success).toBe(false);
|
|
52
|
-
});
|
|
53
|
-
it('should reject unknown properties', () => {
|
|
54
|
-
const result = planToolsFactory.configSchema.safeParse({
|
|
55
|
-
type: 'plan-tools',
|
|
56
|
-
unknownProp: 'value',
|
|
57
|
-
});
|
|
58
|
-
expect(result.success).toBe(false);
|
|
59
|
-
});
|
|
10
|
+
});
|
|
11
|
+
describe("config schema", () => {
|
|
12
|
+
it("should validate minimal config", () => {
|
|
13
|
+
const result = planToolsFactory.configSchema.safeParse({
|
|
14
|
+
type: "plan-tools"
|
|
15
|
+
});
|
|
16
|
+
expect(result.success).toBe(true);
|
|
17
|
+
if (result.success) {
|
|
18
|
+
expect(result.data.basePath).toBe(".dexto/plans");
|
|
19
|
+
}
|
|
60
20
|
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expect(toolIds).toContain('plan_read');
|
|
71
|
-
expect(toolIds).toContain('plan_update');
|
|
72
|
-
expect(toolIds).toContain('plan_review');
|
|
73
|
-
});
|
|
74
|
-
it('should create only enabled tools', () => {
|
|
75
|
-
const config = planToolsFactory.configSchema.parse({
|
|
76
|
-
type: 'plan-tools',
|
|
77
|
-
enabledTools: ['plan_create', 'plan_read'],
|
|
78
|
-
});
|
|
79
|
-
const tools = planToolsFactory.create(config);
|
|
80
|
-
expect(tools).toHaveLength(2);
|
|
81
|
-
const toolIds = tools.map((t) => t.id);
|
|
82
|
-
expect(toolIds).toContain('plan_create');
|
|
83
|
-
expect(toolIds).toContain('plan_read');
|
|
84
|
-
expect(toolIds).not.toContain('plan_update');
|
|
85
|
-
});
|
|
21
|
+
it("should validate config with custom basePath", () => {
|
|
22
|
+
const result = planToolsFactory.configSchema.safeParse({
|
|
23
|
+
type: "plan-tools",
|
|
24
|
+
basePath: "/custom/path"
|
|
25
|
+
});
|
|
26
|
+
expect(result.success).toBe(true);
|
|
27
|
+
if (result.success) {
|
|
28
|
+
expect(result.data.basePath).toBe("/custom/path");
|
|
29
|
+
}
|
|
86
30
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
expect(tool.inputSchema).toBeDefined();
|
|
97
|
-
}
|
|
98
|
-
});
|
|
31
|
+
it("should validate config with enabledTools", () => {
|
|
32
|
+
const result = planToolsFactory.configSchema.safeParse({
|
|
33
|
+
type: "plan-tools",
|
|
34
|
+
enabledTools: ["plan_create", "plan_read"]
|
|
35
|
+
});
|
|
36
|
+
expect(result.success).toBe(true);
|
|
37
|
+
if (result.success) {
|
|
38
|
+
expect(result.data.enabledTools).toEqual(["plan_create", "plan_read"]);
|
|
39
|
+
}
|
|
99
40
|
});
|
|
41
|
+
it("should reject invalid tool names", () => {
|
|
42
|
+
const result = planToolsFactory.configSchema.safeParse({
|
|
43
|
+
type: "plan-tools",
|
|
44
|
+
enabledTools: ["invalid_tool"]
|
|
45
|
+
});
|
|
46
|
+
expect(result.success).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it("should reject unknown properties", () => {
|
|
49
|
+
const result = planToolsFactory.configSchema.safeParse({
|
|
50
|
+
type: "plan-tools",
|
|
51
|
+
unknownProp: "value"
|
|
52
|
+
});
|
|
53
|
+
expect(result.success).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe("create", () => {
|
|
57
|
+
it("should create all tools by default", () => {
|
|
58
|
+
const config = planToolsFactory.configSchema.parse({
|
|
59
|
+
type: "plan-tools"
|
|
60
|
+
});
|
|
61
|
+
const tools = planToolsFactory.create(config);
|
|
62
|
+
expect(tools).toHaveLength(4);
|
|
63
|
+
const toolIds = tools.map((t) => t.id);
|
|
64
|
+
expect(toolIds).toContain("plan_create");
|
|
65
|
+
expect(toolIds).toContain("plan_read");
|
|
66
|
+
expect(toolIds).toContain("plan_update");
|
|
67
|
+
expect(toolIds).toContain("plan_review");
|
|
68
|
+
});
|
|
69
|
+
it("should create only enabled tools", () => {
|
|
70
|
+
const config = planToolsFactory.configSchema.parse({
|
|
71
|
+
type: "plan-tools",
|
|
72
|
+
enabledTools: ["plan_create", "plan_read"]
|
|
73
|
+
});
|
|
74
|
+
const tools = planToolsFactory.create(config);
|
|
75
|
+
expect(tools).toHaveLength(2);
|
|
76
|
+
const toolIds = tools.map((t) => t.id);
|
|
77
|
+
expect(toolIds).toContain("plan_create");
|
|
78
|
+
expect(toolIds).toContain("plan_read");
|
|
79
|
+
expect(toolIds).not.toContain("plan_update");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe("tool definitions", () => {
|
|
83
|
+
it("should have descriptions and input schemas for all tools", () => {
|
|
84
|
+
const config = planToolsFactory.configSchema.parse({
|
|
85
|
+
type: "plan-tools"
|
|
86
|
+
});
|
|
87
|
+
const tools = planToolsFactory.create(config);
|
|
88
|
+
for (const tool of tools) {
|
|
89
|
+
expect(tool.description).toBeDefined();
|
|
90
|
+
expect(tool.description.length).toBeGreaterThan(0);
|
|
91
|
+
expect(tool.inputSchema).toBeDefined();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
100
95
|
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var plan_create_tool_exports = {};
|
|
20
|
+
__export(plan_create_tool_exports, {
|
|
21
|
+
createPlanCreateTool: () => createPlanCreateTool
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(plan_create_tool_exports);
|
|
24
|
+
var import_zod = require("zod");
|
|
25
|
+
var import_core = require("@dexto/core");
|
|
26
|
+
var import_errors = require("../errors.js");
|
|
27
|
+
const PlanCreateInputSchema = import_zod.z.object({
|
|
28
|
+
title: import_zod.z.string().describe('Plan title (e.g., "Add User Authentication")'),
|
|
29
|
+
content: import_zod.z.string().describe(
|
|
30
|
+
"Plan content in markdown format. Use - [ ] and - [x] for checkboxes to track progress."
|
|
31
|
+
)
|
|
32
|
+
}).strict();
|
|
33
|
+
function createPlanCreateTool(getPlanService) {
|
|
34
|
+
return (0, import_core.defineTool)({
|
|
35
|
+
id: "plan_create",
|
|
36
|
+
description: "Create a new implementation plan for the current session. Shows the plan for approval before saving. Use markdown format for the plan content with clear steps and file references.",
|
|
37
|
+
inputSchema: PlanCreateInputSchema,
|
|
38
|
+
presentation: {
|
|
39
|
+
describeHeader: (input) => (0, import_core.createLocalToolCallHeader)({
|
|
40
|
+
title: "Create Plan",
|
|
41
|
+
argsText: (0, import_core.truncateForHeader)(input.title, 140)
|
|
42
|
+
}),
|
|
43
|
+
/**
|
|
44
|
+
* Generate preview for approval UI
|
|
45
|
+
*/
|
|
46
|
+
preview: async (input, context) => {
|
|
47
|
+
const { content } = input;
|
|
48
|
+
if (!context.sessionId) {
|
|
49
|
+
throw import_errors.PlanError.sessionIdRequired();
|
|
50
|
+
}
|
|
51
|
+
const resolvedPlanService = await getPlanService(context);
|
|
52
|
+
const exists = await resolvedPlanService.exists(context.sessionId);
|
|
53
|
+
if (exists) {
|
|
54
|
+
throw import_errors.PlanError.planAlreadyExists(context.sessionId);
|
|
55
|
+
}
|
|
56
|
+
const lineCount = content.split("\n").length;
|
|
57
|
+
const planPath = resolvedPlanService.getPlanPath(context.sessionId);
|
|
58
|
+
return {
|
|
59
|
+
type: "file",
|
|
60
|
+
title: "Create Plan",
|
|
61
|
+
path: planPath,
|
|
62
|
+
operation: "create",
|
|
63
|
+
content,
|
|
64
|
+
size: Buffer.byteLength(content, "utf8"),
|
|
65
|
+
lineCount
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
async execute(input, context) {
|
|
70
|
+
const { title, content } = input;
|
|
71
|
+
if (!context.sessionId) {
|
|
72
|
+
throw import_errors.PlanError.sessionIdRequired();
|
|
73
|
+
}
|
|
74
|
+
const resolvedPlanService = await getPlanService(context);
|
|
75
|
+
const exists = await resolvedPlanService.exists(context.sessionId);
|
|
76
|
+
if (exists) {
|
|
77
|
+
throw import_errors.PlanError.planAlreadyExists(context.sessionId);
|
|
78
|
+
}
|
|
79
|
+
const plan = await resolvedPlanService.create(context.sessionId, content, { title });
|
|
80
|
+
const planPath = resolvedPlanService.getPlanPath(context.sessionId);
|
|
81
|
+
const _display = {
|
|
82
|
+
type: "file",
|
|
83
|
+
title: "Create Plan",
|
|
84
|
+
path: planPath,
|
|
85
|
+
operation: "create",
|
|
86
|
+
size: Buffer.byteLength(content, "utf8"),
|
|
87
|
+
lineCount: content.split("\n").length
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
path: planPath,
|
|
92
|
+
status: plan.meta.status,
|
|
93
|
+
title: plan.meta.title,
|
|
94
|
+
_display
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
100
|
+
0 && (module.exports = {
|
|
101
|
+
createPlanCreateTool
|
|
102
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-create-tool.d.ts","sourceRoot":"","sources":["../../src/tools/plan-create-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAyC,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,QAAA,MAAM,qBAAqB;;;;;;;;;EASd,CAAC;AAEd;;GAEG;AACH,wBAAgB,oBAAoB,CAChC,cAAc,EAAE,iBAAiB,GAClC,IAAI,CAAC,OAAO,qBAAqB,CAAC,
|
|
1
|
+
{"version":3,"file":"plan-create-tool.d.ts","sourceRoot":"","sources":["../../src/tools/plan-create-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAyC,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,QAAA,MAAM,qBAAqB;;;;;;;;;EASd,CAAC;AAEd;;GAEG;AACH,wBAAgB,oBAAoB,CAChC,cAAc,EAAE,iBAAiB,GAClC,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAkFpC"}
|