@miadi/stateloom-mcp 0.3.1 → 0.3.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/erd.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { existsSync, readFileSync, readdirSync, writeFileSync } from "fs";
3
3
  import { dirname, join, resolve } from "path";
4
- import { addAttribute, addEntity, addRelationship, checkLinks, checkStateOf, collectNotes, emptyErd, ERD_CARDINALITIES, isErdDefinition, isErdfPath, isSqdfPath, isSysdfPath, removeAttribute, removeEntity, removeRelationship, renderMermaidEr, updateEntity, updateErdSettings, summarizeErd, validateErd, } from "@miadi/stateloom-protocol";
4
+ import { addAttribute, addEntity, addRelationship, checkLinks, checkStateOf, collectNotes, emptyErd, ERD_CARDINALITIES, isErdDefinition, isErdfPath, isSqdfPath, isSysdfPath, removeAttribute, removeEntity, removeRelationship, renderMermaidEr, updateEntity, updateErdSettings, summarizeErd, validateErd, normalizeNotes } from "@miadi/stateloom-protocol";
5
5
  import { stampedOutputPath } from "@miadi/stateloom-cli/render";
6
6
  const ok = (text) => ({ content: [{ type: "text", text }] });
7
7
  const fail = (text) => ({ content: [{ type: "text", text }], isError: true });
@@ -9,7 +9,7 @@ export function readErd(path) {
9
9
  if (!existsSync(path))
10
10
  return null;
11
11
  try {
12
- const parsed = JSON.parse(readFileSync(path, "utf8"));
12
+ const parsed = normalizeNotes(JSON.parse(readFileSync(path, "utf8")));
13
13
  return isErdDefinition(parsed) ? parsed : null;
14
14
  }
15
15
  catch {
@@ -123,7 +123,7 @@ function readSmdf(path) {
123
123
  return null;
124
124
  try {
125
125
  const parsed = JSON.parse(readFileSync(path, "utf8"));
126
- const def = parsed.stateMachine ?? parsed.StateMachine ?? parsed;
126
+ const def = normalizeNotes(parsed.stateMachine ?? parsed.StateMachine ?? parsed);
127
127
  return def && typeof def === "object" && def.state ? def : null;
128
128
  }
129
129
  catch {
package/dist/sequence.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { existsSync, readFileSync, writeFileSync } from "fs";
3
3
  import { dirname, join, resolve } from "path";
4
- import { SQD_FRAGMENT_KINDS, addFragment, addFragmentMessage, addMessage, addParticipant, allMessages, docKindOfPath, emptySequence, isSequenceDefinition, isSqdfPath, moveMessage, moveParticipant, parseMessageRef, removeFragment, removeMessage, removeParticipant, renameParticipant, renderMermaidSequence, summarizeSequence, updateFragment, updateMessage, updateParticipant, updateSqdSettings, validateSequence, } from "@miadi/stateloom-protocol";
4
+ import { SQD_FRAGMENT_KINDS, addFragment, addFragmentMessage, addMessage, addParticipant, allMessages, docKindOfPath, emptySequence, isSequenceDefinition, isSqdfPath, moveMessage, moveParticipant, parseMessageRef, removeFragment, removeMessage, removeParticipant, renameParticipant, renderMermaidSequence, summarizeSequence, updateFragment, updateMessage, updateParticipant, updateSqdSettings, validateSequence, normalizeNotes } from "@miadi/stateloom-protocol";
5
5
  import { stampedOutputPath } from "@miadi/stateloom-cli/render";
6
6
  import { formatNotes } from "./erd.js";
7
7
  import { writeFileAtomic } from "./atomicWrite.js";
@@ -13,7 +13,7 @@ export function readSequence(path) {
13
13
  if (!existsSync(path))
14
14
  return null;
15
15
  try {
16
- const parsed = JSON.parse(readFileSync(path, "utf8"));
16
+ const parsed = normalizeNotes(JSON.parse(readFileSync(path, "utf8")));
17
17
  return isSequenceDefinition(parsed) ? parsed : null;
18
18
  }
19
19
  catch {
package/dist/server.js CHANGED
@@ -65,7 +65,7 @@ import { basename, dirname, join, resolve } from "path";
65
65
  import { fileURLToPath } from "node:url";
66
66
  import { tmpdir } from "os";
67
67
  import { createBridgeClient } from "@miadi/stateloom-client";
68
- import { collectNotes, docKindOfPath, envAlias, isErdfPath, isSqdfPath, isSysdfPath, } from "@miadi/stateloom-protocol";
68
+ import { collectNotes, docKindOfPath, envAlias, isErdfPath, isSqdfPath, isSysdfPath, normalizeNotes, } from "@miadi/stateloom-protocol";
69
69
  import { renderDiagramToFile, defaultOutputPath } from "@miadi/stateloom-cli/render";
70
70
  import { resolveProjectSwitch } from "./projectSwitch.js";
71
71
  import { registerErdTools, erdSummary, erdGetDefinition, erdLoadDefinition, erdRender, erdGetNotes, erdSetNotes, formatNotes, } from "./erd.js";
@@ -108,7 +108,7 @@ function readDef() {
108
108
  try {
109
109
  const raw = readFileSync(PROJECT_FILE, "utf8");
110
110
  const parsed = JSON.parse(raw);
111
- return parsed.stateMachine ?? parsed.StateMachine ?? parsed;
111
+ return normalizeNotes(parsed.stateMachine ?? parsed.StateMachine ?? parsed);
112
112
  }
113
113
  catch (e) {
114
114
  console.error(`[smcraft-mcp] Failed to read ${PROJECT_FILE}:`, e);
@@ -120,7 +120,17 @@ function writeDef(def) {
120
120
  // and load_definition write without reading first, so this is the one place that can refuse.
121
121
  if (docKindOfPath(PROJECT_FILE) !== "machine")
122
122
  throw new Error(noMachine());
123
- writeFileSync(PROJECT_FILE, JSON.stringify({ stateMachine: def }, null, 2), "utf8");
123
+ // Keep the file's own shape: a machine written bare stays bare, so one edit is
124
+ // a small diff and not the whole file re-indented under `stateMachine`.
125
+ let bare = false;
126
+ try {
127
+ const current = JSON.parse(readFileSync(PROJECT_FILE, "utf8"));
128
+ bare = !!current && typeof current === "object" && "state" in current && !("stateMachine" in current) && !("StateMachine" in current);
129
+ }
130
+ catch {
131
+ // A new or unreadable file is written in the loom's own shape.
132
+ }
133
+ writeFileSync(PROJECT_FILE, JSON.stringify(bare ? def : { stateMachine: def }, null, 2) + (bare ? "\n" : ""), "utf8");
124
134
  }
125
135
  // ─── Optional real-time design bridge (env-gated, best-effort) ───────
126
136
  // When STATELOOM_BRIDGE_URL (or legacy SMCRAFT_BRIDGE_URL) is set, each
package/dist/system.js CHANGED
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
3
3
  import { writeFileAtomic } from "./atomicWrite.js";
4
4
  import { basename, dirname, join, resolve } from "path";
5
- import { RECONCILE_MODES, SYSTEM_ACTOR_KINDS, addActor, addMember, checkSystem, docKindOfPath, emptySystem, formatReplay, isSqdfPath, isSysdfPath, isSystemDefinition, machineName, membersByKind, parseFocus, parseMessageRef, reconcileModeOf, reconcileSystem, relativeMemberPath, removeActor, removeMember, renderMermaid, renderMermaidEr, renderMermaidSequence, replayScenario, resolveMemberPath, setReconcileMode, stateOfList, summarizeReconcile, summarizeSystem, updateMember, updateSystemSettings, } from "@miadi/stateloom-protocol";
5
+ import { RECONCILE_MODES, SYSTEM_ACTOR_KINDS, addActor, addMember, checkSystem, docKindOfPath, emptySystem, formatReplay, isSqdfPath, isSysdfPath, isSystemDefinition, machineName, membersByKind, parseFocus, parseMessageRef, reconcileModeOf, reconcileSystem, relativeMemberPath, removeActor, removeMember, renderMermaid, renderMermaidEr, renderMermaidSequence, replayScenario, resolveMemberPath, setReconcileMode, stateOfList, summarizeReconcile, summarizeSystem, updateMember, updateSystemSettings, normalizeNotes } from "@miadi/stateloom-protocol";
6
6
  import { stampedOutputPath } from "@miadi/stateloom-cli/render";
7
7
  import { formatNotes } from "./erd.js";
8
8
  const ok = (text) => ({ content: [{ type: "text", text }] });
@@ -14,7 +14,7 @@ export function readSystem(path) {
14
14
  if (!existsSync(path))
15
15
  return null;
16
16
  try {
17
- const parsed = JSON.parse(readFileSync(path, "utf8"));
17
+ const parsed = normalizeNotes(JSON.parse(readFileSync(path, "utf8")));
18
18
  return isSystemDefinition(parsed) ? parsed : null;
19
19
  }
20
20
  catch {
@@ -76,7 +76,7 @@ function loadMember(host, path, absolute) {
76
76
  catch {
77
77
  return { path, kind, def: null, error: "it is not valid JSON" };
78
78
  }
79
- const def = kind === "machine" ? (parsed?.stateMachine ?? parsed?.StateMachine ?? parsed) : parsed;
79
+ const def = normalizeNotes(kind === "machine" ? (parsed?.stateMachine ?? parsed?.StateMachine ?? parsed) : parsed);
80
80
  return { path, kind, def };
81
81
  }
82
82
  /** One line for set_project_file / get_project_file when the active document is a system. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miadi/stateloom-mcp",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "MCP server for miadi-stateloom (formerly smcraft-mcp) — lets LLM agents design state machines through conversation",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,7 +40,7 @@
40
40
  "dependencies": {
41
41
  "@miadi/stateloom-cli": "^0.1.3",
42
42
  "@miadi/stateloom-client": "^0.1.3",
43
- "@miadi/stateloom-protocol": "^0.1.10",
43
+ "@miadi/stateloom-protocol": "^0.1.11",
44
44
  "@modelcontextprotocol/sdk": "^1.12.1",
45
45
  "zod": "^4.3.6"
46
46
  },