minecraft-bedrock-mcp-server 0.1.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.
Files changed (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +577 -0
  3. package/dist/bridge/event-route.d.ts +11 -0
  4. package/dist/bridge/event-route.d.ts.map +1 -0
  5. package/dist/bridge/event-route.js +28 -0
  6. package/dist/bridge/event-route.js.map +1 -0
  7. package/dist/bridge/handshake-route.d.ts +11 -0
  8. package/dist/bridge/handshake-route.d.ts.map +1 -0
  9. package/dist/bridge/handshake-route.js +45 -0
  10. package/dist/bridge/handshake-route.js.map +1 -0
  11. package/dist/bridge/poll-route.d.ts +11 -0
  12. package/dist/bridge/poll-route.d.ts.map +1 -0
  13. package/dist/bridge/poll-route.js +28 -0
  14. package/dist/bridge/poll-route.js.map +1 -0
  15. package/dist/bridge/result-route.d.ts +10 -0
  16. package/dist/bridge/result-route.d.ts.map +1 -0
  17. package/dist/bridge/result-route.js +23 -0
  18. package/dist/bridge/result-route.js.map +1 -0
  19. package/dist/config/config-error.d.ts +12 -0
  20. package/dist/config/config-error.d.ts.map +1 -0
  21. package/dist/config/config-error.js +13 -0
  22. package/dist/config/config-error.js.map +1 -0
  23. package/dist/config/environment.d.ts +89 -0
  24. package/dist/config/environment.d.ts.map +1 -0
  25. package/dist/config/environment.js +73 -0
  26. package/dist/config/environment.js.map +1 -0
  27. package/dist/config/tls.d.ts +15 -0
  28. package/dist/config/tls.d.ts.map +1 -0
  29. package/dist/config/tls.js +27 -0
  30. package/dist/config/tls.js.map +1 -0
  31. package/dist/errors/bridge-error.d.ts +41 -0
  32. package/dist/errors/bridge-error.d.ts.map +1 -0
  33. package/dist/errors/bridge-error.js +33 -0
  34. package/dist/errors/bridge-error.js.map +1 -0
  35. package/dist/errors/error-codes.d.ts +13 -0
  36. package/dist/errors/error-codes.d.ts.map +1 -0
  37. package/dist/errors/error-codes.js +41 -0
  38. package/dist/errors/error-codes.js.map +1 -0
  39. package/dist/events/subscription-registry.d.ts +55 -0
  40. package/dist/events/subscription-registry.d.ts.map +1 -0
  41. package/dist/events/subscription-registry.js +64 -0
  42. package/dist/events/subscription-registry.js.map +1 -0
  43. package/dist/http/app.d.ts +26 -0
  44. package/dist/http/app.d.ts.map +1 -0
  45. package/dist/http/app.js +88 -0
  46. package/dist/http/app.js.map +1 -0
  47. package/dist/http/authentication.d.ts +11 -0
  48. package/dist/http/authentication.d.ts.map +1 -0
  49. package/dist/http/authentication.js +36 -0
  50. package/dist/http/authentication.js.map +1 -0
  51. package/dist/http/health-route.d.ts +10 -0
  52. package/dist/http/health-route.d.ts.map +1 -0
  53. package/dist/http/health-route.js +18 -0
  54. package/dist/http/health-route.js.map +1 -0
  55. package/dist/http/metrics-route.d.ts +8 -0
  56. package/dist/http/metrics-route.d.ts.map +1 -0
  57. package/dist/http/metrics-route.js +11 -0
  58. package/dist/http/metrics-route.js.map +1 -0
  59. package/dist/index.d.ts +3 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +134 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/mcp/mcp-route.d.ts +12 -0
  64. package/dist/mcp/mcp-route.d.ts.map +1 -0
  65. package/dist/mcp/mcp-route.js +49 -0
  66. package/dist/mcp/mcp-route.js.map +1 -0
  67. package/dist/mcp/mcp-server-factory.d.ts +20 -0
  68. package/dist/mcp/mcp-server-factory.d.ts.map +1 -0
  69. package/dist/mcp/mcp-server-factory.js +23 -0
  70. package/dist/mcp/mcp-server-factory.js.map +1 -0
  71. package/dist/mcp/session-manager.d.ts +30 -0
  72. package/dist/mcp/session-manager.d.ts.map +1 -0
  73. package/dist/mcp/session-manager.js +38 -0
  74. package/dist/mcp/session-manager.js.map +1 -0
  75. package/dist/mcp/tool-registry.d.ts +15 -0
  76. package/dist/mcp/tool-registry.d.ts.map +1 -0
  77. package/dist/mcp/tool-registry.js +27 -0
  78. package/dist/mcp/tool-registry.js.map +1 -0
  79. package/dist/observability/logger.d.ts +16 -0
  80. package/dist/observability/logger.d.ts.map +1 -0
  81. package/dist/observability/logger.js +19 -0
  82. package/dist/observability/logger.js.map +1 -0
  83. package/dist/observability/metrics.d.ts +27 -0
  84. package/dist/observability/metrics.d.ts.map +1 -0
  85. package/dist/observability/metrics.js +72 -0
  86. package/dist/observability/metrics.js.map +1 -0
  87. package/dist/protocol/command.d.ts +92 -0
  88. package/dist/protocol/command.d.ts.map +1 -0
  89. package/dist/protocol/command.js +37 -0
  90. package/dist/protocol/command.js.map +1 -0
  91. package/dist/protocol/event.d.ts +82 -0
  92. package/dist/protocol/event.d.ts.map +1 -0
  93. package/dist/protocol/event.js +37 -0
  94. package/dist/protocol/event.js.map +1 -0
  95. package/dist/protocol/handshake.d.ts +150 -0
  96. package/dist/protocol/handshake.d.ts.map +1 -0
  97. package/dist/protocol/handshake.js +65 -0
  98. package/dist/protocol/handshake.js.map +1 -0
  99. package/dist/protocol/index.d.ts +14 -0
  100. package/dist/protocol/index.d.ts.map +1 -0
  101. package/dist/protocol/index.js +14 -0
  102. package/dist/protocol/index.js.map +1 -0
  103. package/dist/protocol/protocol-version.d.ts +18 -0
  104. package/dist/protocol/protocol-version.d.ts.map +1 -0
  105. package/dist/protocol/protocol-version.js +28 -0
  106. package/dist/protocol/protocol-version.js.map +1 -0
  107. package/dist/protocol/result.d.ts +79 -0
  108. package/dist/protocol/result.d.ts.map +1 -0
  109. package/dist/protocol/result.js +35 -0
  110. package/dist/protocol/result.js.map +1 -0
  111. package/dist/queue/command-id.d.ts +15 -0
  112. package/dist/queue/command-id.d.ts.map +1 -0
  113. package/dist/queue/command-id.js +38 -0
  114. package/dist/queue/command-id.js.map +1 -0
  115. package/dist/queue/command-queue.d.ts +90 -0
  116. package/dist/queue/command-queue.d.ts.map +1 -0
  117. package/dist/queue/command-queue.js +151 -0
  118. package/dist/queue/command-queue.js.map +1 -0
  119. package/dist/queue/command-throttle.d.ts +38 -0
  120. package/dist/queue/command-throttle.d.ts.map +1 -0
  121. package/dist/queue/command-throttle.js +26 -0
  122. package/dist/queue/command-throttle.js.map +1 -0
  123. package/dist/queue/instrumented-command-queue.d.ts +9 -0
  124. package/dist/queue/instrumented-command-queue.d.ts.map +1 -0
  125. package/dist/queue/instrumented-command-queue.js +39 -0
  126. package/dist/queue/instrumented-command-queue.js.map +1 -0
  127. package/dist/queue/pending-commands.d.ts +35 -0
  128. package/dist/queue/pending-commands.d.ts.map +1 -0
  129. package/dist/queue/pending-commands.js +41 -0
  130. package/dist/queue/pending-commands.js.map +1 -0
  131. package/dist/server-info.d.ts +5 -0
  132. package/dist/server-info.d.ts.map +1 -0
  133. package/dist/server-info.js +22 -0
  134. package/dist/server-info.js.map +1 -0
  135. package/dist/structures/structure-file-store.d.ts +22 -0
  136. package/dist/structures/structure-file-store.d.ts.map +1 -0
  137. package/dist/structures/structure-file-store.js +89 -0
  138. package/dist/structures/structure-file-store.js.map +1 -0
  139. package/dist/tools/block-tools.d.ts +4 -0
  140. package/dist/tools/block-tools.d.ts.map +1 -0
  141. package/dist/tools/block-tools.js +111 -0
  142. package/dist/tools/block-tools.js.map +1 -0
  143. package/dist/tools/command-tools.d.ts +4 -0
  144. package/dist/tools/command-tools.d.ts.map +1 -0
  145. package/dist/tools/command-tools.js +23 -0
  146. package/dist/tools/command-tools.js.map +1 -0
  147. package/dist/tools/common-schemas.d.ts +65 -0
  148. package/dist/tools/common-schemas.d.ts.map +1 -0
  149. package/dist/tools/common-schemas.js +32 -0
  150. package/dist/tools/common-schemas.js.map +1 -0
  151. package/dist/tools/effect-tools.d.ts +4 -0
  152. package/dist/tools/effect-tools.d.ts.map +1 -0
  153. package/dist/tools/effect-tools.js +32 -0
  154. package/dist/tools/effect-tools.js.map +1 -0
  155. package/dist/tools/entity-tools.d.ts +4 -0
  156. package/dist/tools/entity-tools.d.ts.map +1 -0
  157. package/dist/tools/entity-tools.js +133 -0
  158. package/dist/tools/entity-tools.js.map +1 -0
  159. package/dist/tools/event-tools.d.ts +4 -0
  160. package/dist/tools/event-tools.d.ts.map +1 -0
  161. package/dist/tools/event-tools.js +84 -0
  162. package/dist/tools/event-tools.js.map +1 -0
  163. package/dist/tools/index.d.ts +4 -0
  164. package/dist/tools/index.d.ts.map +1 -0
  165. package/dist/tools/index.js +30 -0
  166. package/dist/tools/index.js.map +1 -0
  167. package/dist/tools/inventory-tools.d.ts +4 -0
  168. package/dist/tools/inventory-tools.d.ts.map +1 -0
  169. package/dist/tools/inventory-tools.js +52 -0
  170. package/dist/tools/inventory-tools.js.map +1 -0
  171. package/dist/tools/player-tools.d.ts +4 -0
  172. package/dist/tools/player-tools.d.ts.map +1 -0
  173. package/dist/tools/player-tools.js +117 -0
  174. package/dist/tools/player-tools.js.map +1 -0
  175. package/dist/tools/property-tools.d.ts +4 -0
  176. package/dist/tools/property-tools.d.ts.map +1 -0
  177. package/dist/tools/property-tools.js +45 -0
  178. package/dist/tools/property-tools.js.map +1 -0
  179. package/dist/tools/scoreboard-tools.d.ts +4 -0
  180. package/dist/tools/scoreboard-tools.d.ts.map +1 -0
  181. package/dist/tools/scoreboard-tools.js +68 -0
  182. package/dist/tools/scoreboard-tools.js.map +1 -0
  183. package/dist/tools/server-tools.d.ts +4 -0
  184. package/dist/tools/server-tools.d.ts.map +1 -0
  185. package/dist/tools/server-tools.js +25 -0
  186. package/dist/tools/server-tools.js.map +1 -0
  187. package/dist/tools/structure-file-tools.d.ts +4 -0
  188. package/dist/tools/structure-file-tools.d.ts.map +1 -0
  189. package/dist/tools/structure-file-tools.js +57 -0
  190. package/dist/tools/structure-file-tools.js.map +1 -0
  191. package/dist/tools/structure-tools.d.ts +4 -0
  192. package/dist/tools/structure-tools.d.ts.map +1 -0
  193. package/dist/tools/structure-tools.js +91 -0
  194. package/dist/tools/structure-tools.js.map +1 -0
  195. package/dist/tools/tool-definition.d.ts +68 -0
  196. package/dist/tools/tool-definition.d.ts.map +1 -0
  197. package/dist/tools/tool-definition.js +40 -0
  198. package/dist/tools/tool-definition.js.map +1 -0
  199. package/dist/tools/tool-result.d.ts +17 -0
  200. package/dist/tools/tool-result.d.ts.map +1 -0
  201. package/dist/tools/tool-result.js +52 -0
  202. package/dist/tools/tool-result.js.map +1 -0
  203. package/dist/tools/world-tools.d.ts +4 -0
  204. package/dist/tools/world-tools.d.ts.map +1 -0
  205. package/dist/tools/world-tools.js +97 -0
  206. package/dist/tools/world-tools.js.map +1 -0
  207. package/package.json +69 -0
@@ -0,0 +1,151 @@
1
+ import { BridgeError } from "../errors/bridge-error.js";
2
+ import { newCommandId } from "./command-id.js";
3
+ import { createPendingCommands } from "./pending-commands.js";
4
+ /** Creates an in-memory {@link CommandQueue}. */
5
+ export function createCommandQueue(options) {
6
+ const now = options.now ?? Date.now;
7
+ const pending = createPendingCommands();
8
+ const ready = [];
9
+ const waiters = [];
10
+ let lastPollAt = 0;
11
+ let activePolls = 0;
12
+ let closed = false;
13
+ function bridgeConnected() {
14
+ return activePolls > 0 || now() - lastPollAt < options.livenessWindowMs;
15
+ }
16
+ function wakeNextWaiter() {
17
+ waiters.shift()?.wake();
18
+ }
19
+ function dropFromReady(id) {
20
+ const index = ready.findIndex((command) => command.id === id);
21
+ if (index >= 0)
22
+ ready.splice(index, 1);
23
+ }
24
+ function takeReady(max, at) {
25
+ const batch = [];
26
+ while (batch.length < max) {
27
+ const command = ready.shift();
28
+ if (!command)
29
+ break;
30
+ // A command past its deadline has already been (or will be) rejected by
31
+ // the pending registry; never deliver it.
32
+ if (command.deadlineAt <= at)
33
+ continue;
34
+ batch.push({
35
+ id: command.id,
36
+ kind: command.kind,
37
+ payload: command.payload,
38
+ issued_at: new Date(command.issuedAt).toISOString(),
39
+ deadline_ms: command.deadlineAt - at,
40
+ });
41
+ }
42
+ return batch;
43
+ }
44
+ /** Resolves when a command is enqueued, the timeout elapses, or `signal` aborts. */
45
+ function awaitCommand(timeoutMs, signal) {
46
+ return new Promise((resolve) => {
47
+ let settled = false;
48
+ const waiter = { wake: finish };
49
+ const timer = setTimeout(finish, timeoutMs);
50
+ timer.unref();
51
+ signal.addEventListener("abort", finish, { once: true });
52
+ waiters.push(waiter);
53
+ function finish() {
54
+ if (settled)
55
+ return;
56
+ settled = true;
57
+ clearTimeout(timer);
58
+ signal.removeEventListener("abort", finish);
59
+ const index = waiters.indexOf(waiter);
60
+ if (index >= 0)
61
+ waiters.splice(index, 1);
62
+ resolve();
63
+ }
64
+ });
65
+ }
66
+ return {
67
+ async enqueueAndAwait(request) {
68
+ if (closed) {
69
+ throw new BridgeError({
70
+ code: "BRIDGE_DISCONNECTED",
71
+ message: "the command queue is closed",
72
+ });
73
+ }
74
+ if (!bridgeConnected()) {
75
+ throw new BridgeError({
76
+ code: "BRIDGE_DISCONNECTED",
77
+ message: "no behavior pack is connected to the bridge",
78
+ });
79
+ }
80
+ if (pending.size() >= options.maxOutstanding) {
81
+ throw new BridgeError({
82
+ code: "QUEUE_FULL",
83
+ message: `the command queue is at capacity (${options.maxOutstanding} outstanding)`,
84
+ });
85
+ }
86
+ const throttled = options.throttle.tryAdmit(request.kind);
87
+ if (throttled) {
88
+ throw new BridgeError({
89
+ code: "COMMAND_THROTTLED",
90
+ message: `command kind '${request.kind}' is being throttled`,
91
+ retryAfterMs: throttled.retryAfterMs,
92
+ details: { kind: request.kind },
93
+ });
94
+ }
95
+ const id = newCommandId();
96
+ const issuedAt = now();
97
+ const deadlineAt = issuedAt + request.timeoutMs;
98
+ const result = pending.register(id, deadlineAt);
99
+ ready.push({
100
+ id,
101
+ kind: request.kind,
102
+ payload: request.payload,
103
+ issuedAt,
104
+ deadlineAt,
105
+ correlationId: request.correlationId,
106
+ });
107
+ // Once the command settles or times out, make sure it is not left
108
+ // lingering in the ready buffer awaiting delivery.
109
+ void result.then(() => {
110
+ dropFromReady(id);
111
+ }, () => {
112
+ dropFromReady(id);
113
+ });
114
+ wakeNextWaiter();
115
+ return await result;
116
+ },
117
+ async dequeue({ max, timeoutMs, signal }) {
118
+ lastPollAt = now();
119
+ activePolls += 1;
120
+ try {
121
+ if (ready.length === 0 && !signal.aborted && !closed) {
122
+ await awaitCommand(timeoutMs, signal);
123
+ }
124
+ return takeReady(max, now());
125
+ }
126
+ finally {
127
+ activePolls -= 1;
128
+ }
129
+ },
130
+ settle(result) {
131
+ return pending.settle(result.id, result);
132
+ },
133
+ stats() {
134
+ return {
135
+ depth: ready.length,
136
+ inFlight: Math.max(0, pending.size() - ready.length),
137
+ bridgeConnected: bridgeConnected(),
138
+ };
139
+ },
140
+ close() {
141
+ if (closed)
142
+ return;
143
+ closed = true;
144
+ ready.length = 0;
145
+ pending.rejectAll(new BridgeError({ code: "BRIDGE_DISCONNECTED", message: "the bridge is shutting down" }));
146
+ while (waiters.length > 0)
147
+ wakeNextWaiter();
148
+ },
149
+ };
150
+ }
151
+ //# sourceMappingURL=command-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-queue.js","sourceRoot":"","sources":["../../src/queue/command-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /** Result of a denied admission: how long until a retry may succeed. */
2
+ export interface ThrottleDecision {
3
+ readonly retryAfterMs: number;
4
+ }
5
+ /** Token-bucket rate-limit policy for a command kind. */
6
+ export interface ThrottlePolicy {
7
+ /** Sustained admissions per second. */
8
+ readonly ratePerSecond: number;
9
+ /** Bucket capacity — the largest burst admitted at once. */
10
+ readonly burst: number;
11
+ }
12
+ /** Configuration for {@link createCommandThrottle}. */
13
+ export interface CommandThrottleOptions {
14
+ /** Policy applied to any kind without a specific override. */
15
+ readonly defaultPolicy: ThrottlePolicy;
16
+ /** Per-kind policy overrides, keyed by command kind. */
17
+ readonly perKindPolicy?: Readonly<Record<string, ThrottlePolicy>>;
18
+ /** Clock source, injectable for tests. Defaults to `Date.now`. */
19
+ readonly now?: () => number;
20
+ }
21
+ /**
22
+ * Per-kind rate limiter for the bridge enqueue path.
23
+ *
24
+ * Each command kind gets an independent token bucket, shielding the behavior
25
+ * pack's script watchdog from bursts of expensive commands.
26
+ */
27
+ export interface CommandThrottle {
28
+ /**
29
+ * Attempts to admit one command of the given kind.
30
+ *
31
+ * @returns `null` when admitted; a {@link ThrottleDecision} when the kind's
32
+ * bucket is empty.
33
+ */
34
+ tryAdmit(kind: string): ThrottleDecision | null;
35
+ }
36
+ /** Creates a {@link CommandThrottle} from the given policy. */
37
+ export declare function createCommandThrottle(options: CommandThrottleOptions): CommandThrottle;
38
+ //# sourceMappingURL=command-throttle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-throttle.d.ts","sourceRoot":"","sources":["../../src/queue/command-throttle.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,uDAAuD;AACvD,MAAM,WAAW,sBAAsB;IACrC,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,EAAE,cAAc,CAAC;IACvC,wDAAwD;IACxD,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;IAClE,kEAAkE;IAClE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;CACjD;AAOD,+DAA+D;AAC/D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CA4BtF"}
@@ -0,0 +1,26 @@
1
+ /** Creates a {@link CommandThrottle} from the given policy. */
2
+ export function createCommandThrottle(options) {
3
+ const now = options.now ?? Date.now;
4
+ const buckets = new Map();
5
+ function policyFor(kind) {
6
+ return options.perKindPolicy?.[kind] ?? options.defaultPolicy;
7
+ }
8
+ return {
9
+ tryAdmit(kind) {
10
+ const policy = policyFor(kind);
11
+ const at = now();
12
+ const bucket = buckets.get(kind) ?? { tokens: policy.burst, updatedAt: at };
13
+ const elapsedSeconds = Math.max(0, at - bucket.updatedAt) / 1000;
14
+ bucket.tokens = Math.min(policy.burst, bucket.tokens + elapsedSeconds * policy.ratePerSecond);
15
+ bucket.updatedAt = at;
16
+ buckets.set(kind, bucket);
17
+ if (bucket.tokens >= 1) {
18
+ bucket.tokens -= 1;
19
+ return null;
20
+ }
21
+ const retryAfterMs = Math.ceil(((1 - bucket.tokens) / policy.ratePerSecond) * 1000);
22
+ return { retryAfterMs };
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=command-throttle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-throttle.js","sourceRoot":"","sources":["../../src/queue/command-throttle.ts"],"names":[],"mappings":"AA4CA,+DAA+D;AAC/D,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IACnE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,SAAS,SAAS,CAAC,IAAY;QAC7B,OAAO,OAAO,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC;IAChE,CAAC;IAED,OAAO;QACL,QAAQ,CAAC,IAAI;YACX,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;YAE5E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;YACjE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,cAAc,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;YAC9F,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAE1B,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACvB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;gBACnB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAAC;YACpF,OAAO,EAAE,YAAY,EAAE,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Metrics } from "../observability/metrics.js";
2
+ import type { CommandQueue } from "./command-queue.js";
3
+ /**
4
+ * Wraps a {@link CommandQueue}, recording each command's duration and outcome
5
+ * to {@link Metrics}. Composition keeps the base queue free of metrics
6
+ * concerns; the wrapper is applied only when metrics are enabled.
7
+ */
8
+ export declare function createInstrumentedCommandQueue(inner: CommandQueue, metrics: Metrics, now?: () => number): CommandQueue;
9
+ //# sourceMappingURL=instrumented-command-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumented-command-queue.d.ts","sourceRoot":"","sources":["../../src/queue/instrumented-command-queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,OAAO,EAChB,GAAG,GAAE,MAAM,MAAiB,GAC3B,YAAY,CA8Bd"}
@@ -0,0 +1,39 @@
1
+ import { BridgeError } from "../errors/bridge-error.js";
2
+ /**
3
+ * Wraps a {@link CommandQueue}, recording each command's duration and outcome
4
+ * to {@link Metrics}. Composition keeps the base queue free of metrics
5
+ * concerns; the wrapper is applied only when metrics are enabled.
6
+ */
7
+ export function createInstrumentedCommandQueue(inner, metrics, now = Date.now) {
8
+ return {
9
+ async enqueueAndAwait(request) {
10
+ const startedAt = now();
11
+ try {
12
+ const result = await inner.enqueueAndAwait(request);
13
+ metrics.recordCommand({
14
+ kind: request.kind,
15
+ status: result.status,
16
+ code: result.status === "error" ? result.error.code : undefined,
17
+ durationMs: now() - startedAt,
18
+ });
19
+ return result;
20
+ }
21
+ catch (error) {
22
+ metrics.recordCommand({
23
+ kind: request.kind,
24
+ status: "error",
25
+ code: BridgeError.is(error) ? error.code : "INTERNAL",
26
+ durationMs: now() - startedAt,
27
+ });
28
+ throw error;
29
+ }
30
+ },
31
+ dequeue: (options) => inner.dequeue(options),
32
+ settle: (result) => inner.settle(result),
33
+ stats: () => inner.stats(),
34
+ close: () => {
35
+ inner.close();
36
+ },
37
+ };
38
+ }
39
+ //# sourceMappingURL=instrumented-command-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumented-command-queue.js","sourceRoot":"","sources":["../../src/queue/instrumented-command-queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAKxD;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAC5C,KAAmB,EACnB,OAAgB,EAChB,MAAoB,IAAI,CAAC,GAAG;IAE5B,OAAO;QACL,KAAK,CAAC,eAAe,CAAC,OAAuB;YAC3C,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBACpD,OAAO,CAAC,aAAa,CAAC;oBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;oBAC/D,UAAU,EAAE,GAAG,EAAE,GAAG,SAAS;iBAC9B,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,aAAa,CAAC;oBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,MAAM,EAAE,OAAO;oBACf,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU;oBACrD,UAAU,EAAE,GAAG,EAAE,GAAG,SAAS;iBAC9B,CAAC,CAAC;gBACH,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAC5C,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QACxC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE;QAC1B,KAAK,EAAE,GAAG,EAAE;YACV,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { BridgeError } from "../errors/bridge-error.js";
2
+ import type { CommandResult } from "../protocol/result.js";
3
+ import type { CommandId } from "./command-id.js";
4
+ /**
5
+ * Registry of in-flight commands awaiting a correlated result.
6
+ *
7
+ * A command is registered when it is enqueued and removed when the behavior
8
+ * pack settles it or when its deadline elapses.
9
+ */
10
+ export interface PendingCommands {
11
+ /**
12
+ * Registers a command and returns a promise for its result.
13
+ *
14
+ * Resolves with the {@link CommandResult} reported by the behavior pack
15
+ * (whether `ok` or `error`). Rejects with a `COMMAND_TIMEOUT` `BridgeError`
16
+ * if `deadlineAt` is reached first.
17
+ *
18
+ * @param deadlineAt - Absolute epoch-millisecond deadline.
19
+ */
20
+ register(id: CommandId, deadlineAt: number): Promise<CommandResult>;
21
+ /**
22
+ * Delivers a result to a registered command.
23
+ *
24
+ * @returns `true` if a pending command matched; `false` if the id is
25
+ * unknown or already settled (e.g. a result that arrived after timeout).
26
+ */
27
+ settle(id: CommandId, result: CommandResult): boolean;
28
+ /** Rejects every pending command — used during graceful shutdown. */
29
+ rejectAll(error: BridgeError): void;
30
+ /** Number of commands currently awaiting a result. */
31
+ size(): number;
32
+ }
33
+ /** Creates an empty {@link PendingCommands} registry. */
34
+ export declare function createPendingCommands(): PendingCommands;
35
+ //# sourceMappingURL=pending-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-commands.d.ts","sourceRoot":"","sources":["../../src/queue/pending-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEpE;;;;;OAKG;IACH,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC;IAEtD,qEAAqE;IACrE,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAEpC,sDAAsD;IACtD,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,yDAAyD;AACzD,wBAAgB,qBAAqB,IAAI,eAAe,CA0CvD"}
@@ -0,0 +1,41 @@
1
+ import { BridgeError } from "../errors/bridge-error.js";
2
+ /** Creates an empty {@link PendingCommands} registry. */
3
+ export function createPendingCommands() {
4
+ const entries = new Map();
5
+ return {
6
+ register(id, deadlineAt) {
7
+ return new Promise((resolve, reject) => {
8
+ const delayMs = Math.max(0, deadlineAt - Date.now());
9
+ const timer = setTimeout(() => {
10
+ entries.delete(id);
11
+ reject(new BridgeError({
12
+ code: "COMMAND_TIMEOUT",
13
+ message: `command ${id} did not complete within ${delayMs} ms`,
14
+ }));
15
+ }, delayMs);
16
+ timer.unref();
17
+ entries.set(id, { resolve, reject, timer });
18
+ });
19
+ },
20
+ settle(id, result) {
21
+ const entry = entries.get(id);
22
+ if (!entry)
23
+ return false;
24
+ clearTimeout(entry.timer);
25
+ entries.delete(id);
26
+ entry.resolve(result);
27
+ return true;
28
+ },
29
+ rejectAll(error) {
30
+ for (const entry of entries.values()) {
31
+ clearTimeout(entry.timer);
32
+ entry.reject(error);
33
+ }
34
+ entries.clear();
35
+ },
36
+ size() {
37
+ return entries.size;
38
+ },
39
+ };
40
+ }
41
+ //# sourceMappingURL=pending-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-commands.js","sourceRoot":"","sources":["../../src/queue/pending-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AA2CxD,yDAAyD;AACzD,MAAM,UAAU,qBAAqB;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEnD,OAAO;QACL,QAAQ,CAAC,EAAE,EAAE,UAAU;YACrB,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACpD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBACrD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBAC5B,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBACnB,MAAM,CACJ,IAAI,WAAW,CAAC;wBACd,IAAI,EAAE,iBAAiB;wBACvB,OAAO,EAAE,WAAW,EAAE,4BAA4B,OAAO,KAAK;qBAC/D,CAAC,CACH,CAAC;gBACJ,CAAC,EAAE,OAAO,CAAC,CAAC;gBACZ,KAAK,CAAC,KAAK,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,EAAE,EAAE,MAAM;YACf,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAC;YACzB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACnB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,SAAS,CAAC,KAAK;YACb,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACrC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,IAAI;YACF,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** The npm package name. */
2
+ export declare const SERVER_NAME: string;
3
+ /** The npm package version. */
4
+ export declare const SERVER_VERSION: string;
5
+ //# sourceMappingURL=server-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-info.d.ts","sourceRoot":"","sources":["../src/server-info.ts"],"names":[],"mappings":"AAqBA,4BAA4B;AAC5B,eAAO,MAAM,WAAW,QAAgB,CAAC;AAEzC,+BAA+B;AAC/B,eAAO,MAAM,cAAc,QAAmB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { z } from "zod";
4
+ const ManifestSchema = z.object({
5
+ name: z.string(),
6
+ version: z.string(),
7
+ });
8
+ /**
9
+ * Reads the package manifest that ships beside the compiled output (and beside
10
+ * `src/` during development), so the name and version stay in sync with npm.
11
+ */
12
+ function readManifest() {
13
+ const manifestPath = join(import.meta.dirname, "../package.json");
14
+ const raw = JSON.parse(readFileSync(manifestPath, "utf8"));
15
+ return ManifestSchema.parse(raw);
16
+ }
17
+ const manifest = readManifest();
18
+ /** The npm package name. */
19
+ export const SERVER_NAME = manifest.name;
20
+ /** The npm package version. */
21
+ export const SERVER_VERSION = manifest.version;
22
+ //# sourceMappingURL=server-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-info.js","sourceRoot":"","sources":["../src/server-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAEH;;;GAGG;AACH,SAAS,YAAY;IACnB,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAClE,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IACpE,OAAO,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;AAEhC,4BAA4B;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC;AAEzC,+BAA+B;AAC/B,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** Metadata for a `.mcstructure` file. */
2
+ export interface StructureFileInfo {
3
+ readonly name: string;
4
+ readonly bytes: number;
5
+ }
6
+ /**
7
+ * Filesystem access to the `.mcstructure` files in the behavior pack's
8
+ * `structures` folder. Every file name is confined to that folder.
9
+ */
10
+ export interface StructureFileStore {
11
+ /** Lists the `.mcstructure` files present. */
12
+ list(): Promise<StructureFileInfo[]>;
13
+ /** Reads a structure file's raw bytes. */
14
+ read(name: string): Promise<Buffer>;
15
+ /** Writes a structure file, creating the folder if needed. */
16
+ write(name: string, data: Buffer): Promise<StructureFileInfo>;
17
+ /** Deletes a structure file; `false` if it did not exist. */
18
+ remove(name: string): Promise<boolean>;
19
+ }
20
+ /** Creates a {@link StructureFileStore} rooted at `rootDir`. */
21
+ export declare function createStructureFileStore(rootDir: string): StructureFileStore;
22
+ //# sourceMappingURL=structure-file-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-file-store.d.ts","sourceRoot":"","sources":["../../src/structures/structure-file-store.ts"],"names":[],"mappings":"AAMA,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,IAAI,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACrC,0CAA0C;IAC1C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,8DAA8D;IAC9D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9D,6DAA6D;IAC7D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxC;AAMD,gEAAgE;AAChE,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CA8E5E"}
@@ -0,0 +1,89 @@
1
+ import { mkdir, readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
2
+ import { basename, join, resolve } from "node:path";
3
+ import { BridgeError } from "../errors/bridge-error.js";
4
+ const STRUCTURE_EXTENSION = ".mcstructure";
5
+ function isErrno(error) {
6
+ return error instanceof Error && "code" in error;
7
+ }
8
+ /** Creates a {@link StructureFileStore} rooted at `rootDir`. */
9
+ export function createStructureFileStore(rootDir) {
10
+ const root = resolve(rootDir);
11
+ /** Resolves a caller-supplied name to an absolute path inside `root`. */
12
+ function resolveFile(name) {
13
+ const trimmed = name.trim();
14
+ if (trimmed.length === 0 || trimmed !== basename(trimmed) || trimmed.includes("..")) {
15
+ throw new BridgeError({
16
+ code: "STRUCTURE_FILE_ERROR",
17
+ message: `invalid structure file name '${name}'`,
18
+ });
19
+ }
20
+ const fileName = trimmed.endsWith(STRUCTURE_EXTENSION)
21
+ ? trimmed
22
+ : `${trimmed}${STRUCTURE_EXTENSION}`;
23
+ return join(root, fileName);
24
+ }
25
+ return {
26
+ async list() {
27
+ let entries;
28
+ try {
29
+ entries = await readdir(root);
30
+ }
31
+ catch (error) {
32
+ if (isErrno(error) && error.code === "ENOENT")
33
+ return [];
34
+ throw new BridgeError({
35
+ code: "STRUCTURE_FILE_ERROR",
36
+ message: "unable to list the structures folder",
37
+ cause: error,
38
+ });
39
+ }
40
+ const files = [];
41
+ for (const entry of entries) {
42
+ if (!entry.endsWith(STRUCTURE_EXTENSION))
43
+ continue;
44
+ const info = await stat(join(root, entry));
45
+ files.push({ name: entry, bytes: info.size });
46
+ }
47
+ return files;
48
+ },
49
+ async read(name) {
50
+ const path = resolveFile(name);
51
+ try {
52
+ return await readFile(path);
53
+ }
54
+ catch (error) {
55
+ if (isErrno(error) && error.code === "ENOENT") {
56
+ throw new BridgeError({ code: "NOT_FOUND", message: `no structure file '${name}'` });
57
+ }
58
+ throw new BridgeError({
59
+ code: "STRUCTURE_FILE_ERROR",
60
+ message: `unable to read structure file '${name}'`,
61
+ cause: error,
62
+ });
63
+ }
64
+ },
65
+ async write(name, data) {
66
+ const path = resolveFile(name);
67
+ await mkdir(root, { recursive: true });
68
+ await writeFile(path, data);
69
+ return { name: basename(path), bytes: data.byteLength };
70
+ },
71
+ async remove(name) {
72
+ const path = resolveFile(name);
73
+ try {
74
+ await unlink(path);
75
+ return true;
76
+ }
77
+ catch (error) {
78
+ if (isErrno(error) && error.code === "ENOENT")
79
+ return false;
80
+ throw new BridgeError({
81
+ code: "STRUCTURE_FILE_ERROR",
82
+ message: `unable to delete structure file '${name}'`,
83
+ cause: error,
84
+ });
85
+ }
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=structure-file-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-file-store.js","sourceRoot":"","sources":["../../src/structures/structure-file-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type ToolDefinition } from "./tool-definition.js";
2
+ /** Block reads and block writes. */
3
+ export declare const blockTools: readonly ToolDefinition[];
4
+ //# sourceMappingURL=block-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-tools.d.ts","sourceRoot":"","sources":["../../src/tools/block-tools.ts"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI7E,oCAAoC;AACpC,eAAO,MAAM,UAAU,EAAE,SAAS,cAAc,EAyG/C,CAAC"}