@tikoci/rosetta 0.9.1 → 0.9.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # rosetta
2
2
 
3
- MCP server that gives AI assistants searchable access to the complete [MikroTik RouterOS documentation](https://help.mikrotik.com/docs/spaces/ROS/overview) — 317 pages, 4,860 properties, 40,000-entry command tree, hardware specs for 144 products, 518 YouTube video transcripts, and direct links to help.mikrotik.com.
3
+ MCP server that gives AI assistants searchable access to MikroTik RouterOS documentation — 317 legacy Confluence-export pages, 4,860 properties, 40,000-entry command tree, hardware specs for 144 products, 518 YouTube video transcripts, and direct links to source docs. MikroTik's current help system is the Docusaurus site at <https://manual.mikrotik.com>; rosetta's prose-doc extraction still needs a major migration away from the retired Confluence export.
4
4
 
5
5
  If you need MikroTik docs, you likely have a MikroTik. Install rosetta once as a container on your router using [RouterOS /app](#install-on-mikrotik-app), and any AI assistant on the network can use it. Or [run it locally](#install-locally-with-bun) on your workstation. **No AI required** — rosetta includes a [terminal browser](#browse-without-ai) for searching the database directly.
6
6
 
@@ -12,7 +12,7 @@ Instead of vector embeddings, rosetta uses **SQLite [FTS5](https://www.sqlite.or
12
12
 
13
13
  | Data Source | Coverage |
14
14
  |-------------|----------|
15
- | Documentation pages | 317 pages (~515K words) from help.mikrotik.com |
15
+ | Documentation pages | 317 pages (~515K words) from the retired help.mikrotik.com Confluence export |
16
16
  | Property definitions | 4,860 with types, defaults, descriptions |
17
17
  | Command tree | 5,114 commands, 551 dirs, 34K arguments |
18
18
  | Version history | 46 RouterOS versions tracked (7.9–7.23beta2) |
@@ -21,13 +21,13 @@ Instead of vector embeddings, rosetta uses **SQLite [FTS5](https://www.sqlite.or
21
21
  | YouTube transcripts | 518 videos, ~1,890 chapter-level segments |
22
22
  | Callout blocks | 1,034 warnings, notes, and tips |
23
23
 
24
- Documentation covers RouterOS **v7 only**, aligned with the long-term release (~7.22) at export time.
24
+ Documentation covers RouterOS **v7 only**, aligned with the long-term release (~7.22) at the March 2026 Confluence-export time. Future official doc updates are expected on <https://manual.mikrotik.com>, including a Docusaurus CLI Reference generated from `/console/inspect` data.
25
25
 
26
26
  ---
27
27
 
28
28
  ## Install on MikroTik (/app)
29
29
 
30
- RouterOS 7.22+ includes the [/app](https://help.mikrotik.com/docs/spaces/ROS/pages/328068) feature for running containers directly on the router. This is the simplest way to deploy rosetta — install once, and any AI assistant on your network can connect to the MCP endpoint URL shown in the router UI.
30
+ RouterOS 7.22+ includes the [/app](https://manual.mikrotik.com/docs/CLI%20Reference/container/app) feature for running containers directly on the router. This is the simplest way to deploy rosetta — install once, and any AI assistant on your network can connect to the MCP endpoint URL shown in the router UI.
31
31
 
32
32
  **Requirements:** RouterOS 7.22+, x86 or ARM64 architecture (CCR, RB5009, hAP ax series, CHR, etc.), container package installed, device-mode enabled.
33
33
 
@@ -49,7 +49,7 @@ After reboot:
49
49
  /system/device-mode/update mode=advanced container=yes
50
50
  ```
51
51
 
52
- See MikroTik's [Container documentation](https://help.mikrotik.com/docs/spaces/ROS/pages/Container) for full prerequisites and troubleshooting.
52
+ See MikroTik's [Container documentation](https://manual.mikrotik.com/docs/Extended%20features/Container/) for full prerequisites and troubleshooting.
53
53
 
54
54
  ### 2. Add the rosetta app
55
55
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tikoci/rosetta",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "RouterOS documentation as SQLite FTS5 — RAG search + command glossary via MCP",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -109,10 +109,7 @@ describe.skipIf(!hasTestDb && !dbWasExplicitlyConfigured)(
109
109
  });
110
110
 
111
111
  const transportErrors: Error[] = [];
112
- let resolveClosed!: () => void;
113
- const closeSeen = new Promise<void>((resolve) => {
114
- resolveClosed = resolve;
115
- });
112
+ const { promise: closeSeen, resolve: resolveClosed } = Promise.withResolvers<void>();
116
113
  let closeCount = 0;
117
114
 
118
115
  client = new Client({ name: "stdio-test-client", version: "1.0.0" });
package/src/setup.ts CHANGED
@@ -11,6 +11,7 @@ import { execSync } from "node:child_process";
11
11
  import {
12
12
  closeSync,
13
13
  existsSync,
14
+ fstatSync,
14
15
  openSync,
15
16
  readdirSync,
16
17
  readSync,
@@ -24,6 +25,7 @@ import { gunzipSync } from "bun";
24
25
  import { detectMode, resolveBaseDir, resolveDbPath, resolveVersion, SCHEMA_VERSION } from "./paths.ts";
25
26
 
26
27
  declare const REPO_URL: string;
28
+ const REPLACE_DB_TIMEOUT_MS = 30_000;
27
29
 
28
30
  const GITHUB_REPO =
29
31
  typeof REPO_URL !== "undefined" ? REPO_URL : "tikoci/rosetta";
@@ -72,14 +74,12 @@ function dbHasData(dbPath: string): boolean {
72
74
  }
73
75
 
74
76
  function looksLikeSqliteFile(dbPath: string): boolean {
75
- if (!existsSync(dbPath)) return false;
76
-
77
77
  let fd: number | null = null;
78
78
  try {
79
- const stats = statSync(dbPath);
79
+ fd = openSync(dbPath, "r");
80
+ const stats = fstatSync(fd);
80
81
  if (!stats.isFile() || stats.size < SQLITE_MAGIC.length) return false;
81
82
 
82
- fd = openSync(dbPath, "r");
83
83
  const header = Buffer.alloc(SQLITE_MAGIC.length);
84
84
  const bytesRead = readSync(fd, header, 0, header.byteLength, 0);
85
85
  return bytesRead === header.byteLength && header.toString("utf8") === SQLITE_MAGIC;
@@ -301,7 +301,7 @@ function isReplaceRaceError(e: unknown): boolean {
301
301
  }
302
302
 
303
303
  async function replaceDbFile(tmpPath: string, dbPath: string): Promise<void> {
304
- const deadline = Date.now() + 30_000;
304
+ const deadline = Date.now() + REPLACE_DB_TIMEOUT_MS;
305
305
  let lastError: unknown = null;
306
306
 
307
307
  while (Date.now() <= deadline) {
@@ -310,7 +310,6 @@ async function replaceDbFile(tmpPath: string, dbPath: string): Promise<void> {
310
310
  return;
311
311
  } catch (e) {
312
312
  if (!isReplaceRaceError(e)) throw e;
313
- lastError = e;
314
313
  }
315
314
 
316
315
  tryUnlink(dbPath);
@@ -475,8 +474,8 @@ export async function downloadDb(
475
474
  cleanupDbArtifacts(tmpPath);
476
475
  lastError = new Error(
477
476
  `Downloaded DB schema=${probe.schemaVersion} does not match this rosetta build (expected ${SCHEMA_VERSION}). ` +
478
- `This usually means the cached package version is older than the published DB. ` +
479
- `Run: bunx @tikoci/rosetta@latest --refresh`,
477
+ `This usually means your MCP client is still using a cached older package version. ` +
478
+ `Restart the MCP client to let bunx re-resolve the latest package, or run: bunx @tikoci/rosetta@latest --refresh`,
480
479
  );
481
480
  if (isLast) throw lastError;
482
481
  log(` ${lastError.message}`);