callman-mcp 0.1.0 → 0.2.0
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/CHANGELOG.md +82 -0
- package/README.md +45 -16
- package/dist/client/api.d.ts +64 -3
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +67 -2
- package/dist/client/api.js.map +1 -1
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +33 -7
- package/dist/client/errors.js.map +1 -1
- package/dist/client/types.d.ts +91 -2
- package/dist/client/types.d.ts.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +7 -2
- package/dist/context.js.map +1 -1
- package/dist/domain/contracts.d.ts +893 -0
- package/dist/domain/contracts.d.ts.map +1 -0
- package/dist/domain/contracts.js +90 -0
- package/dist/domain/contracts.js.map +1 -0
- package/dist/domain/diagram/build.d.ts +520 -18
- package/dist/domain/diagram/build.d.ts.map +1 -1
- package/dist/domain/diagram/build.js +65 -19
- package/dist/domain/diagram/build.js.map +1 -1
- package/dist/domain/diagram/patch.d.ts +624 -51
- package/dist/domain/diagram/patch.d.ts.map +1 -1
- package/dist/domain/diagram/patch.js +180 -40
- package/dist/domain/diagram/patch.js.map +1 -1
- package/dist/domain/diagram/style.d.ts +315 -0
- package/dist/domain/diagram/style.d.ts.map +1 -0
- package/dist/domain/diagram/style.js +124 -0
- package/dist/domain/diagram/style.js.map +1 -0
- package/dist/domain/diagram/summarize.d.ts +8 -0
- package/dist/domain/diagram/summarize.d.ts.map +1 -1
- package/dist/domain/diagram/summarize.js +28 -13
- package/dist/domain/diagram/summarize.js.map +1 -1
- package/dist/domain/requestIntegrations.d.ts +719 -0
- package/dist/domain/requestIntegrations.d.ts.map +1 -0
- package/dist/domain/requestIntegrations.js +222 -0
- package/dist/domain/requestIntegrations.js.map +1 -0
- package/dist/domain/requestShape.d.ts +1350 -152
- package/dist/domain/requestShape.d.ts.map +1 -1
- package/dist/domain/requestShape.js +336 -121
- package/dist/domain/requestShape.js.map +1 -1
- package/dist/domain/resolve.d.ts +2 -1
- package/dist/domain/resolve.d.ts.map +1 -1
- package/dist/domain/resolve.js +5 -1
- package/dist/domain/resolve.js.map +1 -1
- package/dist/domain/scenario/build.d.ts +82 -26
- package/dist/domain/scenario/build.d.ts.map +1 -1
- package/dist/domain/scenario/build.js +196 -65
- package/dist/domain/scenario/build.js.map +1 -1
- package/dist/domain/scenario/nodeConfig.d.ts +11 -0
- package/dist/domain/scenario/nodeConfig.d.ts.map +1 -0
- package/dist/domain/scenario/nodeConfig.js +251 -0
- package/dist/domain/scenario/nodeConfig.js.map +1 -0
- package/dist/domain/scenario/summarize.d.ts +145 -25
- package/dist/domain/scenario/summarize.d.ts.map +1 -1
- package/dist/domain/scenario/summarize.js +84 -29
- package/dist/domain/scenario/summarize.js.map +1 -1
- package/dist/lib/mask.d.ts +0 -18
- package/dist/lib/mask.d.ts.map +1 -1
- package/dist/lib/mask.js +2 -44
- package/dist/lib/mask.js.map +1 -1
- package/dist/lib/pagination.d.ts +3 -2
- package/dist/lib/pagination.d.ts.map +1 -1
- package/dist/lib/pagination.js +13 -8
- package/dist/lib/pagination.js.map +1 -1
- package/dist/lib/redact.d.ts +12 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +50 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/strict.d.ts +4 -0
- package/dist/lib/strict.d.ts.map +1 -0
- package/dist/lib/strict.js +14 -0
- package/dist/lib/strict.js.map +1 -0
- package/dist/prompts/index.js +7 -7
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/docs/contracts.d.ts +2 -0
- package/dist/resources/docs/contracts.d.ts.map +1 -0
- package/dist/resources/docs/contracts.js +74 -0
- package/dist/resources/docs/contracts.js.map +1 -0
- package/dist/resources/docs/diagramSchema.d.ts +1 -1
- package/dist/resources/docs/diagramSchema.d.ts.map +1 -1
- package/dist/resources/docs/diagramSchema.js +95 -28
- package/dist/resources/docs/diagramSchema.js.map +1 -1
- package/dist/resources/docs/overview.d.ts +1 -1
- package/dist/resources/docs/overview.d.ts.map +1 -1
- package/dist/resources/docs/overview.js +29 -7
- package/dist/resources/docs/overview.js.map +1 -1
- package/dist/resources/docs/requestSchema.d.ts +1 -1
- package/dist/resources/docs/requestSchema.d.ts.map +1 -1
- package/dist/resources/docs/requestSchema.js +85 -16
- package/dist/resources/docs/requestSchema.js.map +1 -1
- package/dist/resources/generated/aiPacks.d.ts +1 -1
- package/dist/resources/generated/aiPacks.d.ts.map +1 -1
- package/dist/resources/generated/aiPacks.js +3 -2
- package/dist/resources/generated/aiPacks.js.map +1 -1
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +19 -19
- package/dist/resources/index.js.map +1 -1
- package/dist/run/executeCollection.d.ts +3 -1
- package/dist/run/executeCollection.d.ts.map +1 -1
- package/dist/run/executeCollection.js +16 -4
- package/dist/run/executeCollection.js.map +1 -1
- package/dist/run/summarize.d.ts +17 -6
- package/dist/run/summarize.d.ts.map +1 -1
- package/dist/run/summarize.js +48 -41
- package/dist/run/summarize.js.map +1 -1
- package/dist/run/types.d.ts +1 -0
- package/dist/run/types.d.ts.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/catalog.d.ts +1 -1
- package/dist/tools/catalog.d.ts.map +1 -1
- package/dist/tools/catalog.js +18 -0
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/collections.d.ts.map +1 -1
- package/dist/tools/collections.js +53 -41
- package/dist/tools/collections.js.map +1 -1
- package/dist/tools/contracts.d.ts +4 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +201 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/diagrams.d.ts.map +1 -1
- package/dist/tools/diagrams.js +19 -10
- package/dist/tools/diagrams.js.map +1 -1
- package/dist/tools/environments.d.ts.map +1 -1
- package/dist/tools/environments.js +184 -64
- package/dist/tools/environments.js.map +1 -1
- package/dist/tools/import.d.ts.map +1 -1
- package/dist/tools/import.js +111 -20
- package/dist/tools/import.js.map +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +19 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/lookups.d.ts +38 -7
- package/dist/tools/lookups.d.ts.map +1 -1
- package/dist/tools/lookups.js +113 -10
- package/dist/tools/lookups.js.map +1 -1
- package/dist/tools/meta.d.ts.map +1 -1
- package/dist/tools/meta.js +9 -4
- package/dist/tools/meta.js.map +1 -1
- package/dist/tools/requests.d.ts.map +1 -1
- package/dist/tools/requests.js +138 -50
- package/dist/tools/requests.js.map +1 -1
- package/dist/tools/run.d.ts.map +1 -1
- package/dist/tools/run.js +84 -28
- package/dist/tools/run.js.map +1 -1
- package/dist/tools/scenarios.d.ts.map +1 -1
- package/dist/tools/scenarios.js +238 -75
- package/dist/tools/scenarios.js.map +1 -1
- package/dist/tools/shared.d.ts +1 -0
- package/dist/tools/shared.d.ts.map +1 -1
- package/dist/tools/shared.js +9 -1
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/workspaces.d.ts.map +1 -1
- package/dist/tools/workspaces.js +44 -7
- package/dist/tools/workspaces.js.map +1 -1
- package/dist-cjs/client/api.js +67 -2
- package/dist-cjs/client/errors.js +33 -7
- package/dist-cjs/context.js +7 -2
- package/dist-cjs/domain/contracts.js +93 -0
- package/dist-cjs/domain/diagram/build.js +71 -20
- package/dist-cjs/domain/diagram/patch.js +179 -39
- package/dist-cjs/domain/diagram/style.js +130 -0
- package/dist-cjs/domain/diagram/summarize.js +28 -13
- package/dist-cjs/domain/requestIntegrations.js +228 -0
- package/dist-cjs/domain/requestShape.js +342 -121
- package/dist-cjs/domain/resolve.js +5 -1
- package/dist-cjs/domain/scenario/build.js +197 -65
- package/dist-cjs/domain/scenario/nodeConfig.js +260 -0
- package/dist-cjs/domain/scenario/summarize.js +86 -29
- package/dist-cjs/lib/mask.js +3 -48
- package/dist-cjs/lib/pagination.js +13 -8
- package/dist-cjs/lib/redact.js +53 -0
- package/dist-cjs/lib/strict.js +18 -0
- package/dist-cjs/prompts/index.js +7 -7
- package/dist-cjs/resources/docs/contracts.js +76 -0
- package/dist-cjs/resources/docs/diagramSchema.js +95 -28
- package/dist-cjs/resources/docs/overview.js +29 -7
- package/dist-cjs/resources/docs/requestSchema.js +85 -16
- package/dist-cjs/resources/generated/aiPacks.js +3 -2
- package/dist-cjs/resources/index.js +17 -17
- package/dist-cjs/run/executeCollection.js +16 -4
- package/dist-cjs/run/summarize.js +48 -41
- package/dist-cjs/server.js +1 -1
- package/dist-cjs/tools/catalog.js +18 -0
- package/dist-cjs/tools/collections.js +52 -40
- package/dist-cjs/tools/contracts.js +204 -0
- package/dist-cjs/tools/diagrams.js +19 -10
- package/dist-cjs/tools/environments.js +182 -62
- package/dist-cjs/tools/import.js +107 -16
- package/dist-cjs/tools/index.js +21 -2
- package/dist-cjs/tools/lookups.js +123 -11
- package/dist-cjs/tools/meta.js +9 -4
- package/dist-cjs/tools/requests.js +134 -46
- package/dist-cjs/tools/run.js +82 -26
- package/dist-cjs/tools/scenarios.js +235 -72
- package/dist-cjs/tools/shared.js +11 -2
- package/dist-cjs/tools/workspaces.js +43 -6
- package/package.json +2 -2
|
@@ -5,25 +5,45 @@ const callman_core_1 = require("callman-core");
|
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const errors_js_1 = require("../../client/errors.js");
|
|
7
7
|
const ids_js_1 = require("../../lib/ids.js");
|
|
8
|
+
const strict_js_1 = require("../../lib/strict.js");
|
|
8
9
|
const build_js_1 = require("./build.js");
|
|
10
|
+
const style_js_1 = require("./style.js");
|
|
9
11
|
// Incremental edits to a stored diagram — the model sends operations, not a
|
|
10
12
|
// 200-node document. Removing a node drops the edges attached to it.
|
|
13
|
+
const nodeShape = build_js_1.diagramNodeInputSchema.shape;
|
|
14
|
+
const edgeShape = build_js_1.diagramEdgeInputSchema.shape;
|
|
15
|
+
const nodeChangesSchema = (0, strict_js_1.strictObject)({
|
|
16
|
+
type: nodeShape.type.optional(),
|
|
17
|
+
label: nodeShape.label,
|
|
18
|
+
parent: zod_1.z.string().max(64).nullable().optional().describe('New container id; null or "" moves the node to the top level'),
|
|
19
|
+
position: nodeShape.position,
|
|
20
|
+
size: nodeShape.size,
|
|
21
|
+
style: style_js_1.nodeStylePatchSchema.optional(),
|
|
22
|
+
rotation: nodeShape.rotation.unwrap().nullable().optional().describe("Degrees, clockwise; null resets"),
|
|
23
|
+
locked: nodeShape.locked,
|
|
24
|
+
hidden: nodeShape.hidden,
|
|
25
|
+
data: zod_1.z.record(zod_1.z.unknown()).nullable().optional().describe("MERGED shallowly into the node's data; a key set to null is removed, data: null clears it"),
|
|
26
|
+
}, "field", "updateNode changes");
|
|
27
|
+
const edgeChangesSchema = (0, strict_js_1.strictObject)({
|
|
28
|
+
source: edgeShape.source.optional(),
|
|
29
|
+
target: edgeShape.target.optional(),
|
|
30
|
+
label: edgeShape.label.describe('"" removes the label'),
|
|
31
|
+
semantic: edgeShape.semantic,
|
|
32
|
+
color: style_js_1.colorInputSchema.nullable().optional().describe("Line CSS color; null restores the default"),
|
|
33
|
+
routing: edgeShape.routing,
|
|
34
|
+
markerEnd: edgeShape.markerEnd,
|
|
35
|
+
markerStart: edgeShape.markerStart,
|
|
36
|
+
}, "field", "updateEdge changes");
|
|
37
|
+
// Every op is strict: a field at the wrong level ({ op: "updateNode", id, label })
|
|
38
|
+
// is an error, not a silent no-op that still counts as "applied".
|
|
11
39
|
exports.diagramPatchOpSchema = zod_1.z.discriminatedUnion("op", [
|
|
12
|
-
|
|
13
|
-
zod_1.z.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}),
|
|
18
|
-
|
|
19
|
-
zod_1.z.object({ op: zod_1.z.literal("addEdge"), edge: build_js_1.diagramEdgeInputSchema }),
|
|
20
|
-
zod_1.z.object({
|
|
21
|
-
op: zod_1.z.literal("updateEdge"),
|
|
22
|
-
id: zod_1.z.string().min(1),
|
|
23
|
-
changes: build_js_1.diagramEdgeInputSchema.partial().omit({ id: true }),
|
|
24
|
-
}),
|
|
25
|
-
zod_1.z.object({ op: zod_1.z.literal("removeEdge"), id: zod_1.z.string().min(1) }),
|
|
26
|
-
zod_1.z.object({ op: zod_1.z.literal("setTitle"), title: zod_1.z.string().min(1).max(200) }),
|
|
40
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("addNode"), node: build_js_1.diagramNodeInputSchema }, "field", "addNode ops"),
|
|
41
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("updateNode"), id: zod_1.z.string().min(1), changes: nodeChangesSchema }, "field", "updateNode ops"),
|
|
42
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("removeNode"), id: zod_1.z.string().min(1) }, "field", "removeNode ops"),
|
|
43
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("addEdge"), edge: build_js_1.diagramEdgeInputSchema }, "field", "addEdge ops"),
|
|
44
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("updateEdge"), id: zod_1.z.string().min(1), changes: edgeChangesSchema }, "field", "updateEdge ops"),
|
|
45
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("removeEdge"), id: zod_1.z.string().min(1) }, "field", "removeEdge ops"),
|
|
46
|
+
(0, strict_js_1.strictObject)({ op: zod_1.z.literal("setTitle"), title: zod_1.z.string().min(1).max(200) }, "field", "setTitle ops"),
|
|
27
47
|
]);
|
|
28
48
|
const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
29
49
|
const strict = options.strictTypes !== false;
|
|
@@ -34,11 +54,14 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
34
54
|
const removedNodeIds = [];
|
|
35
55
|
const removedEdgeIds = [];
|
|
36
56
|
const warnings = [];
|
|
57
|
+
const moved = new Set();
|
|
37
58
|
const nextNodeId = (0, ids_js_1.sequentialIds)("n", nodes.keys());
|
|
38
59
|
const nextEdgeId = (0, ids_js_1.sequentialIds)("e", edges.keys());
|
|
39
60
|
const resolveType = (type, id) => {
|
|
40
|
-
if ((0, callman_core_1.getDiagramComponent)(type))
|
|
61
|
+
if ((0, callman_core_1.getDiagramComponent)(type)) {
|
|
62
|
+
(0, build_js_1.assertNotConnector)(type, id);
|
|
41
63
|
return type;
|
|
64
|
+
}
|
|
42
65
|
const suggestions = (0, build_js_1.suggestComponentTypes)(type);
|
|
43
66
|
if (strict) {
|
|
44
67
|
throw new errors_js_1.ToolInputError("DIAGRAM_UNKNOWN_COMPONENT_TYPE", `Unknown component type "${type}" on ${id}.`, {
|
|
@@ -69,9 +92,17 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
69
92
|
size: op.node.size ?? def?.defaultSize ?? { width: 140, height: 60 },
|
|
70
93
|
label: op.node.label ?? (type === "rect" && op.node.type !== "rect" ? op.node.type : def?.defaultLabel),
|
|
71
94
|
...(op.node.parent ? { parentId: op.node.parent } : {}),
|
|
72
|
-
...(op.node.style ? { style: op.node.style } : {}),
|
|
95
|
+
...(op.node.style ? { style: (0, style_js_1.applyStyleInput)(undefined, op.node.style) } : {}),
|
|
96
|
+
...(op.node.rotation ? { rotation: op.node.rotation } : {}),
|
|
97
|
+
...(op.node.locked ? { locked: true } : {}),
|
|
98
|
+
...(op.node.hidden ? { hidden: true } : {}),
|
|
73
99
|
...(op.node.data ? { data: op.node.data } : {}),
|
|
74
100
|
});
|
|
101
|
+
if (op.node.parent) {
|
|
102
|
+
const warning = (0, build_js_1.parentWarning)(id, op.node.parent, nodes.get(op.node.parent)?.type);
|
|
103
|
+
if (warning)
|
|
104
|
+
warnings.push(warning);
|
|
105
|
+
}
|
|
75
106
|
if (!op.node.position)
|
|
76
107
|
addedNodeIds.push(id);
|
|
77
108
|
break;
|
|
@@ -81,19 +112,72 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
81
112
|
if (!node)
|
|
82
113
|
throw new errors_js_1.ToolInputError("DIAGRAM_NODE_NOT_FOUND", `Node "${op.id}" does not exist.`);
|
|
83
114
|
const changes = op.changes;
|
|
84
|
-
if (changes.parent
|
|
115
|
+
if (changes.parent && !nodes.has(changes.parent)) {
|
|
85
116
|
throw new errors_js_1.ToolInputError("DIAGRAM_PARENT_NOT_FOUND", `Parent "${changes.parent}" does not exist.`);
|
|
86
117
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
118
|
+
if (changes.parent && changes.parent === op.id)
|
|
119
|
+
throw new errors_js_1.ToolInputError("DIAGRAM_PARENT_CYCLE", `Node "${op.id}" cannot contain itself.`);
|
|
120
|
+
const next = { ...node };
|
|
121
|
+
if (changes.type !== undefined)
|
|
122
|
+
next.type = resolveType(changes.type, op.id);
|
|
123
|
+
if (changes.label !== undefined)
|
|
124
|
+
next.label = changes.label;
|
|
125
|
+
if (changes.position !== undefined)
|
|
126
|
+
next.position = changes.position;
|
|
127
|
+
if (changes.size !== undefined)
|
|
128
|
+
next.size = changes.size;
|
|
129
|
+
if (changes.parent !== undefined) {
|
|
130
|
+
if (changes.parent)
|
|
131
|
+
next.parentId = changes.parent;
|
|
132
|
+
else
|
|
133
|
+
delete next.parentId;
|
|
134
|
+
}
|
|
135
|
+
if (changes.style !== undefined) {
|
|
136
|
+
const style = changes.style === null ? undefined : (0, style_js_1.applyStyleInput)(node.style, changes.style);
|
|
137
|
+
if (style)
|
|
138
|
+
next.style = style;
|
|
139
|
+
else
|
|
140
|
+
delete next.style;
|
|
141
|
+
}
|
|
142
|
+
if (changes.rotation !== undefined) {
|
|
143
|
+
if (changes.rotation)
|
|
144
|
+
next.rotation = changes.rotation;
|
|
145
|
+
else
|
|
146
|
+
delete next.rotation;
|
|
147
|
+
}
|
|
148
|
+
if (changes.locked !== undefined) {
|
|
149
|
+
if (changes.locked)
|
|
150
|
+
next.locked = true;
|
|
151
|
+
else
|
|
152
|
+
delete next.locked;
|
|
153
|
+
}
|
|
154
|
+
if (changes.hidden !== undefined) {
|
|
155
|
+
if (changes.hidden)
|
|
156
|
+
next.hidden = true;
|
|
157
|
+
else
|
|
158
|
+
delete next.hidden;
|
|
159
|
+
}
|
|
160
|
+
if (changes.data !== undefined) {
|
|
161
|
+
const data = changes.data === null ? {} : { ...(node.data ?? {}) };
|
|
162
|
+
for (const [key, value] of Object.entries(changes.data ?? {})) {
|
|
163
|
+
if (value === null)
|
|
164
|
+
delete data[key];
|
|
165
|
+
else
|
|
166
|
+
data[key] = value;
|
|
167
|
+
}
|
|
168
|
+
if (Object.keys(data).length > 0)
|
|
169
|
+
next.data = data;
|
|
170
|
+
else
|
|
171
|
+
delete next.data;
|
|
172
|
+
}
|
|
173
|
+
if (changes.position !== undefined || changes.size !== undefined || changes.parent !== undefined)
|
|
174
|
+
moved.add(op.id);
|
|
175
|
+
if (changes.parent) {
|
|
176
|
+
const warning = (0, build_js_1.parentWarning)(op.id, changes.parent, nodes.get(changes.parent)?.type);
|
|
177
|
+
if (warning)
|
|
178
|
+
warnings.push(warning);
|
|
179
|
+
}
|
|
180
|
+
nodes.set(op.id, next);
|
|
97
181
|
break;
|
|
98
182
|
}
|
|
99
183
|
case "removeNode": {
|
|
@@ -130,7 +214,8 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
130
214
|
...(op.edge.label ? { label: op.edge.label } : {}),
|
|
131
215
|
routing: op.edge.routing ?? "orthogonal",
|
|
132
216
|
markerEnd: op.edge.markerEnd ?? "classicThin",
|
|
133
|
-
...(
|
|
217
|
+
...(op.edge.markerStart && op.edge.markerStart !== "none" ? { markerStart: op.edge.markerStart } : {}),
|
|
218
|
+
...(semantic || op.edge.color ? { style: (0, build_js_1.edgeStyleFor)(semantic, op.edge.color) } : {}),
|
|
134
219
|
});
|
|
135
220
|
break;
|
|
136
221
|
}
|
|
@@ -139,20 +224,46 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
139
224
|
if (!edge)
|
|
140
225
|
throw new errors_js_1.ToolInputError("DIAGRAM_EDGE_NOT_FOUND", `Edge "${op.id}" does not exist.`);
|
|
141
226
|
const changes = op.changes;
|
|
142
|
-
const next = {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
227
|
+
const next = { ...edge };
|
|
228
|
+
if (changes.source !== undefined)
|
|
229
|
+
next.source = changes.source;
|
|
230
|
+
if (changes.target !== undefined)
|
|
231
|
+
next.target = changes.target;
|
|
232
|
+
if (changes.label !== undefined) {
|
|
233
|
+
if (changes.label)
|
|
234
|
+
next.label = changes.label;
|
|
235
|
+
else
|
|
236
|
+
delete next.label;
|
|
237
|
+
}
|
|
238
|
+
if (changes.routing !== undefined)
|
|
239
|
+
next.routing = changes.routing;
|
|
240
|
+
if (changes.markerEnd !== undefined)
|
|
241
|
+
next.markerEnd = changes.markerEnd;
|
|
242
|
+
if (changes.markerStart !== undefined) {
|
|
243
|
+
if (changes.markerStart === "none")
|
|
244
|
+
delete next.markerStart;
|
|
245
|
+
else
|
|
246
|
+
next.markerStart = changes.markerStart;
|
|
247
|
+
}
|
|
248
|
+
// The semantic owns the line tuple (dash + width); the color is kept
|
|
249
|
+
// unless it is changed explicitly.
|
|
250
|
+
if (changes.semantic !== undefined || changes.color !== undefined) {
|
|
251
|
+
const stroke = changes.color === null ? undefined : changes.color !== undefined ? (0, style_js_1.toTokenRef)(changes.color) : edge.style?.stroke;
|
|
252
|
+
const line = changes.semantic !== undefined ? (0, callman_core_1.semanticStyle)(changes.semantic) : { ...(edge.style ?? {}) };
|
|
253
|
+
delete line.stroke;
|
|
254
|
+
const style = { ...line, ...(stroke ? { stroke } : {}) };
|
|
255
|
+
if (Object.keys(style).length > 0)
|
|
256
|
+
next.style = style;
|
|
257
|
+
else
|
|
258
|
+
delete next.style;
|
|
259
|
+
}
|
|
151
260
|
for (const endpoint of [next.source, next.target]) {
|
|
152
261
|
if (endpoint && !nodes.has(endpoint) && !edges.has(endpoint)) {
|
|
153
262
|
throw new errors_js_1.ToolInputError("DIAGRAM_EDGE_ENDPOINT_NOT_FOUND", `Edge endpoint "${endpoint}" does not exist.`);
|
|
154
263
|
}
|
|
155
264
|
}
|
|
265
|
+
if (changes.source !== undefined || changes.target !== undefined)
|
|
266
|
+
clearRoute(next);
|
|
156
267
|
edges.set(op.id, next);
|
|
157
268
|
break;
|
|
158
269
|
}
|
|
@@ -164,6 +275,28 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
164
275
|
}
|
|
165
276
|
}
|
|
166
277
|
}
|
|
278
|
+
const reroutedEdgeIds = [];
|
|
279
|
+
if (moved.size > 0) {
|
|
280
|
+
// A moved container carries its children: their edges are stale too.
|
|
281
|
+
const affected = new Set(moved);
|
|
282
|
+
let grew = true;
|
|
283
|
+
while (grew) {
|
|
284
|
+
grew = false;
|
|
285
|
+
for (const node of nodes.values()) {
|
|
286
|
+
if (node.parentId && affected.has(node.parentId) && !affected.has(node.id)) {
|
|
287
|
+
affected.add(node.id);
|
|
288
|
+
grew = true;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (const edge of edges.values()) {
|
|
293
|
+
const touches = (edge.source && affected.has(edge.source)) || (edge.target && affected.has(edge.target));
|
|
294
|
+
if (touches && (edge.waypoints || edge.sourceAnchor || edge.targetAnchor || edge.routing === "straight")) {
|
|
295
|
+
clearRoute(edge);
|
|
296
|
+
reroutedEdgeIds.push(edge.id);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
167
300
|
const document = (0, callman_core_1.normalizeDiagramStyles)({
|
|
168
301
|
...doc,
|
|
169
302
|
meta: { ...doc.meta, title, updatedAt: new Date().toISOString() },
|
|
@@ -174,6 +307,13 @@ const applyDiagramPatch = (doc, ops, options = {}) => {
|
|
|
174
307
|
if (!parsed.ok) {
|
|
175
308
|
throw new errors_js_1.ToolInputError("DIAGRAM_DOCUMENT_INVALID", `The patched document is invalid: ${parsed.errors.join("; ")}`, { errors: parsed.errors });
|
|
176
309
|
}
|
|
177
|
-
return { document: parsed.document, addedNodeIds, removedNodeIds, removedEdgeIds, warnings };
|
|
310
|
+
return { document: parsed.document, addedNodeIds, removedNodeIds, removedEdgeIds, reroutedEdgeIds, warnings };
|
|
178
311
|
};
|
|
179
312
|
exports.applyDiagramPatch = applyDiagramPatch;
|
|
313
|
+
// Drop a saved route so the studio re-routes the edge orthogonally.
|
|
314
|
+
const clearRoute = (edge) => {
|
|
315
|
+
delete edge.waypoints;
|
|
316
|
+
delete edge.sourceAnchor;
|
|
317
|
+
delete edge.targetAnchor;
|
|
318
|
+
edge.routing = "orthogonal";
|
|
319
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.styleView = exports.applyStyleInput = exports.fromTokenRef = exports.toTokenRef = exports.nodeStylePatchSchema = exports.nodeStyleInputSchema = exports.STYLE_KEYS = exports.colorInputSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const strict_js_1 = require("../../lib/strict.js");
|
|
6
|
+
// The visual style a model may set on a node — exactly the DiagramStyle
|
|
7
|
+
// fields the Diagram Studio renders, typed, so a misspelled key
|
|
8
|
+
// ("strokeColor", "borderColor", "fontWeight") is REJECTED with the list of
|
|
9
|
+
// valid keys instead of being dropped by core's normalizer while the tool
|
|
10
|
+
// reports success. Colors are plain CSS strings on the way in and on the way
|
|
11
|
+
// out; the stored form is core's TokenRef (`{ raw: "#3B82F6" }`).
|
|
12
|
+
exports.colorInputSchema = zod_1.z
|
|
13
|
+
.union([
|
|
14
|
+
zod_1.z.string().trim().min(1).max(64),
|
|
15
|
+
zod_1.z.object({ raw: zod_1.z.string().trim().min(1).max(64) }).strict(),
|
|
16
|
+
zod_1.z.object({ token: zod_1.z.string().trim().min(1).max(64) }).strict(),
|
|
17
|
+
])
|
|
18
|
+
.describe('CSS color: "#3B82F6", "rgb(59,130,246)", "rgba(59,130,246,0.08)" or a name like "tomato"');
|
|
19
|
+
const FONT_BOLD = 1;
|
|
20
|
+
const FONT_ITALIC = 2;
|
|
21
|
+
const FONT_UNDERLINE = 4;
|
|
22
|
+
const styleFields = {
|
|
23
|
+
fill: exports.colorInputSchema.describe('Background CSS color, e.g. "#EFF6FF". A translucent "rgba(59,130,246,0.08)" tints a container without hiding its children'),
|
|
24
|
+
stroke: exports.colorInputSchema.describe('Border CSS color, e.g. "#3B82F6"'),
|
|
25
|
+
textColor: exports.colorInputSchema.describe('Label CSS color, e.g. "#1E3A8A"'),
|
|
26
|
+
strokeWidth: zod_1.z.number().min(0).max(20).describe("Border width in px (default ~1.5)"),
|
|
27
|
+
dashed: zod_1.z.boolean().describe("Dashed border (containers are dashed by default)"),
|
|
28
|
+
dashPattern: zod_1.z.string().regex(/^\d+(\.\d+)?( \d+(\.\d+)?)+$/, 'SVG dash array like "6 4" or "1 3"').describe('Dash array when dashed: "6 4" dashed, "1 3" dotted'),
|
|
29
|
+
radius: zod_1.z.number().min(0).max(200).describe("Corner radius in px"),
|
|
30
|
+
rounded: zod_1.z.boolean().describe("Rounded corners with the default radius"),
|
|
31
|
+
fontSize: zod_1.z.number().min(6).max(96).describe("Label font size in px"),
|
|
32
|
+
fontFamily: zod_1.z.string().min(1).max(100),
|
|
33
|
+
bold: zod_1.z.boolean().describe("Bold label"),
|
|
34
|
+
italic: zod_1.z.boolean().describe("Italic label"),
|
|
35
|
+
underline: zod_1.z.boolean().describe("Underlined label"),
|
|
36
|
+
align: zod_1.z.enum(["left", "center", "right"]).describe("Horizontal label alignment"),
|
|
37
|
+
verticalAlign: zod_1.z.enum(["top", "middle", "bottom"]).describe("Vertical label alignment"),
|
|
38
|
+
shadow: zod_1.z.boolean(),
|
|
39
|
+
opacity: zod_1.z.number().min(0).max(100).describe("0 (invisible) – 100 (opaque)"),
|
|
40
|
+
};
|
|
41
|
+
exports.STYLE_KEYS = Object.keys(styleFields);
|
|
42
|
+
exports.nodeStyleInputSchema = (0, strict_js_1.strictObject)(Object.fromEntries(Object.entries(styleFields).map(([key, schema]) => [key, schema.optional()])), "style key").describe(`Visual style. Keys: ${exports.STYLE_KEYS.join(", ")}. Colors are CSS strings.`);
|
|
43
|
+
// On updateNode a key set to null removes it; `style: null` clears the style.
|
|
44
|
+
exports.nodeStylePatchSchema = (0, strict_js_1.strictObject)(Object.fromEntries(Object.entries(styleFields).map(([key, schema]) => [key, schema.nullable().optional()])), "style key")
|
|
45
|
+
.nullable()
|
|
46
|
+
.describe(`Style changes, MERGED into the node's current style: only the keys you pass change, a key set to null is removed, style: null clears it. Keys: ${exports.STYLE_KEYS.join(", ")}.`);
|
|
47
|
+
const toTokenRef = (color) => (typeof color === "string" ? { raw: color.trim() } : color);
|
|
48
|
+
exports.toTokenRef = toTokenRef;
|
|
49
|
+
const fromTokenRef = (ref) => {
|
|
50
|
+
if (!ref)
|
|
51
|
+
return undefined;
|
|
52
|
+
return "raw" in ref ? ref.raw : { token: ref.token };
|
|
53
|
+
};
|
|
54
|
+
exports.fromTokenRef = fromTokenRef;
|
|
55
|
+
// Input (plain colors, bold/italic/underline flags) → stored DiagramStyle.
|
|
56
|
+
// `base` is the node's current style for a merge; null values delete.
|
|
57
|
+
const applyStyleInput = (base, input) => {
|
|
58
|
+
const out = { ...(base ?? {}) };
|
|
59
|
+
const assign = (key, value) => {
|
|
60
|
+
if (value === undefined)
|
|
61
|
+
return;
|
|
62
|
+
if (value === null)
|
|
63
|
+
delete out[key];
|
|
64
|
+
else
|
|
65
|
+
out[key] = value;
|
|
66
|
+
};
|
|
67
|
+
for (const key of ["fill", "stroke", "textColor"]) {
|
|
68
|
+
const value = input[key];
|
|
69
|
+
assign(key, value === undefined || value === null ? value : (0, exports.toTokenRef)(value));
|
|
70
|
+
}
|
|
71
|
+
assign("strokeWidth", input.strokeWidth);
|
|
72
|
+
assign("dashed", input.dashed);
|
|
73
|
+
assign("dashPattern", input.dashPattern);
|
|
74
|
+
assign("radius", input.radius);
|
|
75
|
+
assign("rounded", input.rounded);
|
|
76
|
+
assign("fontSize", input.fontSize);
|
|
77
|
+
assign("fontFamily", input.fontFamily);
|
|
78
|
+
assign("align", input.align);
|
|
79
|
+
assign("verticalAlign", input.verticalAlign);
|
|
80
|
+
assign("shadow", input.shadow);
|
|
81
|
+
assign("opacity", input.opacity);
|
|
82
|
+
// The studio stores bold/italic/underline as ONE maxGraph bitmask.
|
|
83
|
+
const flags = [
|
|
84
|
+
[input.bold, FONT_BOLD],
|
|
85
|
+
[input.italic, FONT_ITALIC],
|
|
86
|
+
[input.underline, FONT_UNDERLINE],
|
|
87
|
+
];
|
|
88
|
+
if (flags.some(([value]) => value !== undefined)) {
|
|
89
|
+
let mask = out.fontStyle ?? 0;
|
|
90
|
+
for (const [value, bit] of flags) {
|
|
91
|
+
if (value === true)
|
|
92
|
+
mask |= bit;
|
|
93
|
+
else if (value === false || value === null)
|
|
94
|
+
mask &= ~bit;
|
|
95
|
+
}
|
|
96
|
+
if (mask === 0)
|
|
97
|
+
delete out.fontStyle;
|
|
98
|
+
else
|
|
99
|
+
out.fontStyle = mask;
|
|
100
|
+
}
|
|
101
|
+
// fontWeight is not rendered by the studio (bold lives in fontStyle).
|
|
102
|
+
delete out.fontWeight;
|
|
103
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
104
|
+
};
|
|
105
|
+
exports.applyStyleInput = applyStyleInput;
|
|
106
|
+
// Stored DiagramStyle → the same compact shape a model writes, so what
|
|
107
|
+
// get_diagram returns can be sent straight back in a patch.
|
|
108
|
+
const styleView = (style) => {
|
|
109
|
+
if (!style)
|
|
110
|
+
return undefined;
|
|
111
|
+
const out = {};
|
|
112
|
+
for (const key of ["fill", "stroke", "textColor"]) {
|
|
113
|
+
const value = (0, exports.fromTokenRef)(style[key]);
|
|
114
|
+
if (value !== undefined)
|
|
115
|
+
out[key] = value;
|
|
116
|
+
}
|
|
117
|
+
for (const key of ["strokeWidth", "dashed", "dashPattern", "radius", "rounded", "fontSize", "fontFamily", "align", "verticalAlign", "shadow", "opacity"]) {
|
|
118
|
+
if (style[key] !== undefined)
|
|
119
|
+
out[key] = style[key];
|
|
120
|
+
}
|
|
121
|
+
const mask = style.fontStyle ?? 0;
|
|
122
|
+
if (mask & FONT_BOLD)
|
|
123
|
+
out.bold = true;
|
|
124
|
+
if (mask & FONT_ITALIC)
|
|
125
|
+
out.italic = true;
|
|
126
|
+
if (mask & FONT_UNDERLINE)
|
|
127
|
+
out.underline = true;
|
|
128
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
129
|
+
};
|
|
130
|
+
exports.styleView = styleView;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.diagramFullView = exports.diagramGraphView = exports.diagramListView = void 0;
|
|
4
4
|
const callman_core_1 = require("callman-core");
|
|
5
5
|
const truncate_js_1 = require("../../lib/truncate.js");
|
|
6
|
+
const style_js_1 = require("./style.js");
|
|
6
7
|
// Compact views of a stored diagram: the list row, the graph (what is
|
|
7
8
|
// connected to what, with the edge meaning read back from its style) and
|
|
8
9
|
// the full document behind a size gate.
|
|
@@ -21,21 +22,35 @@ const diagramListView = (diagram) => {
|
|
|
21
22
|
};
|
|
22
23
|
};
|
|
23
24
|
exports.diagramListView = diagramListView;
|
|
25
|
+
// Style and flags come back in the same compact shape the tools accept, so a
|
|
26
|
+
// model can read a node's look and send a patch without the full document.
|
|
24
27
|
const diagramGraphView = (doc) => ({
|
|
25
28
|
title: doc.meta.title,
|
|
26
|
-
nodes: doc.nodes.map((node) =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
})
|
|
29
|
+
nodes: doc.nodes.map((node) => {
|
|
30
|
+
const style = (0, style_js_1.styleView)(node.style);
|
|
31
|
+
return {
|
|
32
|
+
id: node.id,
|
|
33
|
+
type: node.type,
|
|
34
|
+
label: node.label ?? null,
|
|
35
|
+
...(node.parentId ? { parent: node.parentId } : {}),
|
|
36
|
+
...(style ? { style } : {}),
|
|
37
|
+
...(node.rotation ? { rotation: node.rotation } : {}),
|
|
38
|
+
...(node.locked ? { locked: true } : {}),
|
|
39
|
+
...(node.hidden ? { hidden: true } : {}),
|
|
40
|
+
};
|
|
41
|
+
}),
|
|
42
|
+
edges: doc.edges.map((edge) => {
|
|
43
|
+
const color = (0, style_js_1.fromTokenRef)(edge.style?.stroke);
|
|
44
|
+
return {
|
|
45
|
+
id: edge.id,
|
|
46
|
+
source: edge.source ?? null,
|
|
47
|
+
target: edge.target ?? null,
|
|
48
|
+
label: edge.label ?? null,
|
|
49
|
+
semantic: (0, callman_core_1.semanticFromStyle)(edge.style),
|
|
50
|
+
...(color ? { color } : {}),
|
|
51
|
+
...(edge.markerStart ? { markerStart: edge.markerStart } : {}),
|
|
52
|
+
};
|
|
53
|
+
}),
|
|
39
54
|
});
|
|
40
55
|
exports.diagramGraphView = diagramGraphView;
|
|
41
56
|
const diagramFullView = (doc) => {
|