@elizaos/plugin-vision 2.0.0-alpha.9 → 2.0.3-beta.5
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/LICENSE +21 -0
- package/README.md +112 -0
- package/auto-enable.ts +29 -0
- package/dist/action.d.ts +3 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/audio-capture-stream.d.ts +42 -0
- package/dist/audio-capture-stream.d.ts.map +1 -0
- package/dist/audio-capture.d.ts +25 -0
- package/dist/audio-capture.d.ts.map +1 -0
- package/dist/computeruse-ocr-bridge.d.ts +50 -0
- package/dist/computeruse-ocr-bridge.d.ts.map +1 -0
- package/dist/config.d.ts +68 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/describe-backpressure.d.ts +90 -0
- package/dist/describe-backpressure.d.ts.map +1 -0
- package/dist/dirty-tile-describer.d.ts +102 -0
- package/dist/dirty-tile-describer.d.ts.map +1 -0
- package/dist/dirty-tile-scene.d.ts +56 -0
- package/dist/dirty-tile-scene.d.ts.map +1 -0
- package/dist/entity-tracker.d.ts +33 -0
- package/dist/entity-tracker.d.ts.map +1 -0
- package/dist/face-detector-ggml.d.ts +60 -0
- package/dist/face-detector-ggml.d.ts.map +1 -0
- package/dist/face-detector-mediapipe.d.ts +25 -0
- package/dist/face-detector-mediapipe.d.ts.map +1 -0
- package/dist/face-recognition-ggml.d.ts +94 -0
- package/dist/face-recognition-ggml.d.ts.map +1 -0
- package/dist/get-screen-elements.d.ts +90 -0
- package/dist/get-screen-elements.d.ts.map +1 -0
- package/dist/get-screen.d.ts +60 -0
- package/dist/get-screen.d.ts.map +1 -0
- package/dist/image/sharp-compat.d.ts +89 -0
- package/dist/image/sharp-compat.d.ts.map +1 -0
- package/dist/image-input.d.ts +15 -0
- package/dist/image-input.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7992 -6026
- package/dist/index.js.map +42 -26
- package/dist/lifecycle.d.ts +94 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/mobile/capacitor-camera.d.ts +85 -0
- package/dist/mobile/capacitor-camera.d.ts.map +1 -0
- package/dist/native/doctr-ffi.d.ts +40 -0
- package/dist/native/doctr-ffi.d.ts.map +1 -0
- package/dist/native/yolo-ffi.d.ts +21 -0
- package/dist/native/yolo-ffi.d.ts.map +1 -0
- package/dist/ocr-host-windows.d.ts +34 -0
- package/dist/ocr-host-windows.d.ts.map +1 -0
- package/dist/ocr-service-apple-vision-macos.d.ts +51 -0
- package/dist/ocr-service-apple-vision-macos.d.ts.map +1 -0
- package/dist/ocr-service-doctr.d.ts +61 -0
- package/dist/ocr-service-doctr.d.ts.map +1 -0
- package/dist/ocr-service-linux-tesseract.d.ts +85 -0
- package/dist/ocr-service-linux-tesseract.d.ts.map +1 -0
- package/dist/ocr-service-paddleocr.d.ts +59 -0
- package/dist/ocr-service-paddleocr.d.ts.map +1 -0
- package/dist/ocr-service-windows.d.ts +41 -0
- package/dist/ocr-service-windows.d.ts.map +1 -0
- package/dist/ocr-service.d.ts +91 -0
- package/dist/ocr-service.d.ts.map +1 -0
- package/dist/ocr-with-coords.d.ts +103 -0
- package/dist/ocr-with-coords.d.ts.map +1 -0
- package/dist/person-detector.d.ts +17 -0
- package/dist/person-detector.d.ts.map +1 -0
- package/dist/provider.d.ts +3 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/routes.d.ts +7 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/screen-capture-bridge.d.ts +51 -0
- package/dist/screen-capture-bridge.d.ts.map +1 -0
- package/dist/screen-capture.d.ts +17 -0
- package/dist/screen-capture.d.ts.map +1 -0
- package/dist/screen-tiler.d.ts +75 -0
- package/dist/screen-tiler.d.ts.map +1 -0
- package/dist/service.d.ts +176 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/set-of-marks-provider.d.ts +64 -0
- package/dist/set-of-marks-provider.d.ts.map +1 -0
- package/dist/som.d.ts +135 -0
- package/dist/som.d.ts.map +1 -0
- package/dist/som.js +184 -0
- package/dist/som.js.map +11 -0
- package/dist/test-input.d.ts +25 -0
- package/dist/test-input.d.ts.map +1 -0
- package/dist/types.d.ts +241 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vision-context-augmenter.d.ts +93 -0
- package/dist/vision-context-augmenter.d.ts.map +1 -0
- package/dist/vision-worker-manager.d.ts +51 -0
- package/dist/vision-worker-manager.d.ts.map +1 -0
- package/dist/workers/ocr-worker.d.ts +2 -0
- package/dist/workers/ocr-worker.d.ts.map +1 -0
- package/dist/workers/ocr-worker.js +1066 -121865
- package/dist/workers/ocr-worker.js.map +10 -130
- package/dist/workers/screen-capture-worker.d.ts +2 -0
- package/dist/workers/screen-capture-worker.d.ts.map +1 -0
- package/dist/workers/screen-capture-worker.js +371 -8
- package/dist/workers/screen-capture-worker.js.map +5 -4
- package/dist/workers/worker-logger.d.ts +10 -0
- package/dist/workers/worker-logger.d.ts.map +1 -0
- package/dist/yolo-detector.d.ts +37 -0
- package/dist/yolo-detector.d.ts.map +1 -0
- package/native/doctr.cpp/CMakeLists.txt +58 -0
- package/native/doctr.cpp/README.md +62 -0
- package/native/doctr.cpp/include/doctr.h +91 -0
- package/native/doctr.cpp/scripts/convert.py +98 -0
- package/native/doctr.cpp/src/doctr_det.cpp +112 -0
- package/native/doctr.cpp/src/doctr_rec.cpp +103 -0
- package/native/macos-vision-ocr.swift +113 -0
- package/native/mobilefacenet.cpp/README.md +13 -0
- package/native/movenet.cpp/README.md +10 -0
- package/native/retinaface.cpp/README.md +12 -0
- package/native/yolo.cpp/CMakeLists.txt +57 -0
- package/native/yolo.cpp/README.md +64 -0
- package/native/yolo.cpp/build.mjs +76 -0
- package/native/yolo.cpp/include/yolo.h +62 -0
- package/native/yolo.cpp/scripts/convert.py +248 -0
- package/native/yolo.cpp/src/yolo.cpp +425 -0
- package/native/yolo.cpp/verify/compare.py +99 -0
- package/native/yolo.cpp/verify/make_ref.py +75 -0
- package/native/yolo.cpp/verify/run_ggml.mjs +78 -0
- package/native/yolo.cpp/verify/run_ts.mjs +26 -0
- package/package.json +50 -24
- package/registry-entry.json +43 -0
- package/scripts/vendor-tesseract-linux.mjs +177 -0
- package/build.config.ts +0 -70
- package/dist/workers/florence2-worker.js +0 -114850
- package/dist/workers/florence2-worker.js.map +0 -92
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// End-to-end integration test of the REAL TypeScript detector path:
|
|
2
|
+
// yolo-detector.ts -> native/yolo-ffi.ts -> libyolo.dll -> parseYoloV8 -> NMS
|
|
3
|
+
// Run from the plugin root with bun so workspace deps (@elizaos/core, sharp)
|
|
4
|
+
// resolve:
|
|
5
|
+
// ELIZA_YOLO_GGUF=... ELIZA_YOLO_LIB=... bun native/yolo.cpp/verify/run_ts.mjs
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { YOLODetector } from "../../../src/yolo-detector.ts";
|
|
10
|
+
|
|
11
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const img = readFileSync(join(HERE, "bus.jpg"));
|
|
13
|
+
|
|
14
|
+
console.error("isAvailable:", await YOLODetector.isAvailable());
|
|
15
|
+
const det = new YOLODetector({ scoreThreshold: 0.25, nmsIouThreshold: 0.5 });
|
|
16
|
+
await det.initialize();
|
|
17
|
+
const objs = await det.detect(img);
|
|
18
|
+
console.log(`detections: ${objs.length}`);
|
|
19
|
+
for (const o of objs) {
|
|
20
|
+
const b = o.boundingBox;
|
|
21
|
+
console.log(
|
|
22
|
+
` ${o.type.padEnd(12)} ${o.confidence.toFixed(3)} ` +
|
|
23
|
+
`bbox=(${b.x.toFixed(0)},${b.y.toFixed(0)},${b.width.toFixed(0)},${b.height.toFixed(0)})`,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
await det.dispose();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/plugin-vision",
|
|
3
3
|
"description": "Vision plugin for ElizaOS - provides camera integration and visual awareness",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.3-beta.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -29,53 +29,79 @@
|
|
|
29
29
|
"exports": {
|
|
30
30
|
"./package.json": "./package.json",
|
|
31
31
|
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"eliza-source": {
|
|
34
|
+
"types": "./src/index.ts",
|
|
35
|
+
"import": "./src/index.ts",
|
|
36
|
+
"default": "./src/index.ts"
|
|
37
|
+
},
|
|
32
38
|
"import": {
|
|
33
39
|
"types": "./dist/index.d.ts",
|
|
34
40
|
"default": "./dist/index.js"
|
|
35
41
|
}
|
|
42
|
+
},
|
|
43
|
+
"./*.css": "./dist/*.css",
|
|
44
|
+
"./*": {
|
|
45
|
+
"types": "./dist/*.d.ts",
|
|
46
|
+
"eliza-source": {
|
|
47
|
+
"types": "./src/*.ts",
|
|
48
|
+
"import": "./src/*.ts",
|
|
49
|
+
"default": "./src/*.ts"
|
|
50
|
+
},
|
|
51
|
+
"import": "./dist/*.js",
|
|
52
|
+
"default": "./dist/*.js"
|
|
36
53
|
}
|
|
37
54
|
},
|
|
38
55
|
"files": [
|
|
56
|
+
"registry-entry.json",
|
|
39
57
|
"dist",
|
|
58
|
+
"native",
|
|
59
|
+
"scripts",
|
|
40
60
|
"README.md",
|
|
41
61
|
".npmignore",
|
|
42
62
|
"package.json",
|
|
43
|
-
"
|
|
63
|
+
"auto-enable.ts"
|
|
44
64
|
],
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"zod": "^4.3.6"
|
|
65
|
+
"elizaos": {
|
|
66
|
+
"plugin": {
|
|
67
|
+
"autoEnableModule": "./auto-enable.ts",
|
|
68
|
+
"capabilities": [
|
|
69
|
+
"vision"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
53
72
|
},
|
|
54
|
-
"
|
|
55
|
-
"@
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"@tensorflow-models/posenet": "^2.2.2",
|
|
59
|
-
"@tensorflow/tfjs-node": "^4.22.0"
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@elizaos/core": "2.0.3-beta.5",
|
|
75
|
+
"jimp": "^1.6.0",
|
|
76
|
+
"sharp": "^0.34.3"
|
|
60
77
|
},
|
|
61
78
|
"devDependencies": {
|
|
62
|
-
"@biomejs/biome": "^2.
|
|
79
|
+
"@biomejs/biome": "^2.4.14",
|
|
80
|
+
"@elizaos/plugin-computeruse": "2.0.3-beta.5",
|
|
63
81
|
"@types/bun": "^1.3.5",
|
|
64
82
|
"@types/node": "^25.0.3",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
83
|
+
"typescript": "^6.0.3",
|
|
84
|
+
"vitest": "^4.1.4"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"@elizaos/plugin-computeruse": "2.0.3-beta.5"
|
|
88
|
+
},
|
|
89
|
+
"peerDependenciesMeta": {
|
|
90
|
+
"@elizaos/plugin-computeruse": {
|
|
91
|
+
"optional": true
|
|
92
|
+
}
|
|
69
93
|
},
|
|
70
94
|
"scripts": {
|
|
71
95
|
"dev": "bun run build.ts --watch",
|
|
72
|
-
"clean": "rm
|
|
96
|
+
"clean": "node ../../packages/scripts/rm-path-recursive.mjs dist .turbo",
|
|
73
97
|
"lint": "echo \"Lint skipped for release\"",
|
|
74
98
|
"typecheck": "echo \"Typecheck skipped for release\"",
|
|
75
99
|
"test": "vitest run",
|
|
76
100
|
"lint:check": "bun run lint",
|
|
77
101
|
"build": "bun run build.ts",
|
|
78
102
|
"build:ts": "bun run build.ts",
|
|
103
|
+
"build:native": "bun run native/yolo.cpp/build.mjs",
|
|
104
|
+
"build:weights": "python native/yolo.cpp/scripts/convert.py --variant yolov8n",
|
|
79
105
|
"format": "bunx @biomejs/biome format --write .",
|
|
80
106
|
"format:check": "bunx @biomejs/biome format ."
|
|
81
107
|
},
|
|
@@ -95,8 +121,8 @@
|
|
|
95
121
|
}
|
|
96
122
|
}
|
|
97
123
|
},
|
|
98
|
-
"gitHead": "
|
|
99
|
-
"
|
|
124
|
+
"gitHead": "ff6157011c9459670021cc28a6797592a78b8817",
|
|
125
|
+
"eliza": {
|
|
100
126
|
"platforms": [
|
|
101
127
|
"node"
|
|
102
128
|
],
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "vision",
|
|
3
|
+
"name": "Vision",
|
|
4
|
+
"description": "Vision plugin for ElizaOS - provides camera integration and visual awareness",
|
|
5
|
+
"npmName": "@elizaos/plugin-vision",
|
|
6
|
+
"version": "2.0.0-beta.0",
|
|
7
|
+
"source": "bundled",
|
|
8
|
+
"tags": ["vision", "camera", "ai-vision"],
|
|
9
|
+
"config": {
|
|
10
|
+
"CAMERA_NAME": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"required": false,
|
|
13
|
+
"sensitive": false,
|
|
14
|
+
"label": "Name",
|
|
15
|
+
"help": "Camera name to search for (lowercase partial match)",
|
|
16
|
+
"advanced": false
|
|
17
|
+
},
|
|
18
|
+
"PIXEL_CHANGE_THRESHOLD": {
|
|
19
|
+
"type": "number",
|
|
20
|
+
"required": false,
|
|
21
|
+
"sensitive": false,
|
|
22
|
+
"label": "Change Threshold",
|
|
23
|
+
"help": "Percentage of pixels that must change to trigger VLM update (default: 50)",
|
|
24
|
+
"advanced": false
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"render": {
|
|
28
|
+
"visible": true,
|
|
29
|
+
"pinTo": [],
|
|
30
|
+
"style": "card",
|
|
31
|
+
"icon": "Eye",
|
|
32
|
+
"group": "media",
|
|
33
|
+
"groupOrder": 8,
|
|
34
|
+
"actions": ["enable", "configure"]
|
|
35
|
+
},
|
|
36
|
+
"resources": {
|
|
37
|
+
"homepage": "https://elizaos.ai",
|
|
38
|
+
"repository": "https://github.com/elizaos/elizaos"
|
|
39
|
+
},
|
|
40
|
+
"dependsOn": [],
|
|
41
|
+
"kind": "plugin",
|
|
42
|
+
"subtype": "media"
|
|
43
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Stage a PORTABLE tesseract into the app bundle so on-device/desktop OCR
|
|
4
|
+
* "just ships and works" with no host `apt install tesseract-ocr` (#9105).
|
|
5
|
+
*
|
|
6
|
+
* Output layout (consumed by `ocr-service-linux-tesseract.ts` `resolveTesseract`
|
|
7
|
+
* via `ELIZA_VISION_VENDOR_DIR`):
|
|
8
|
+
*
|
|
9
|
+
* <out>/tesseract/
|
|
10
|
+
* bin/tesseract the CLI
|
|
11
|
+
* lib/libtesseract.so* liblept.so* the shared libs (rest come from the host)
|
|
12
|
+
* tessdata/<lang>.traineddata the language model(s)
|
|
13
|
+
* tessdata/configs/tsv ... REQUIRED — tesseract reads the `tsv` output
|
|
14
|
+
* config from here; without configs/ the
|
|
15
|
+
* `tsv` arg silently fails ("Can't open tsv")
|
|
16
|
+
* and the OCR returns zero rows.
|
|
17
|
+
*
|
|
18
|
+
* Linux x64 only (the desktop build host). macOS uses Apple Vision, Windows uses
|
|
19
|
+
* Windows.Media.Ocr, Android uses the native Tesseract4Android bridge — each
|
|
20
|
+
* provider is platform-resolved in plugin-vision/src/index.ts.
|
|
21
|
+
*
|
|
22
|
+
* Usage: node scripts/vendor-tesseract-linux.mjs [--out <dir>] [--langs eng,...]
|
|
23
|
+
* Build-time prereq: `apt-get download` works (no sudo needed — it only fetches
|
|
24
|
+
* .debs); `dpkg-deb` extracts them. Run on the Linux build host.
|
|
25
|
+
*/
|
|
26
|
+
import { execFileSync } from "node:child_process";
|
|
27
|
+
import {
|
|
28
|
+
copyFileSync,
|
|
29
|
+
cpSync,
|
|
30
|
+
existsSync,
|
|
31
|
+
mkdirSync,
|
|
32
|
+
mkdtempSync,
|
|
33
|
+
readdirSync,
|
|
34
|
+
realpathSync,
|
|
35
|
+
statSync,
|
|
36
|
+
} from "node:fs";
|
|
37
|
+
import { tmpdir } from "node:os";
|
|
38
|
+
import { dirname, join } from "node:path";
|
|
39
|
+
import { fileURLToPath } from "node:url";
|
|
40
|
+
|
|
41
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
42
|
+
function arg(name, def) {
|
|
43
|
+
const i = process.argv.indexOf(name);
|
|
44
|
+
return i >= 0 && process.argv[i + 1] ? process.argv[i + 1] : def;
|
|
45
|
+
}
|
|
46
|
+
const outDir = arg("--out", join(here, "..", "vendor"));
|
|
47
|
+
const langs = arg("--langs", "eng")
|
|
48
|
+
.split(",")
|
|
49
|
+
.map((s) => s.trim())
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
const dest = join(outDir, "tesseract");
|
|
52
|
+
|
|
53
|
+
if (process.platform !== "linux") {
|
|
54
|
+
console.log(
|
|
55
|
+
`[vendor-tesseract] non-linux host (${process.platform}); skipping (platform provider handles OCR).`,
|
|
56
|
+
);
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const work = mkdtempSync(join(tmpdir(), "vendor-tess-"));
|
|
61
|
+
const pkgs = [
|
|
62
|
+
"tesseract-ocr",
|
|
63
|
+
"libtesseract5",
|
|
64
|
+
"liblept5",
|
|
65
|
+
...langs.map((l) => `tesseract-ocr-${l}`),
|
|
66
|
+
];
|
|
67
|
+
console.log(`[vendor-tesseract] downloading: ${pkgs.join(", ")}`);
|
|
68
|
+
execFileSync("apt-get", ["download", ...pkgs], { cwd: work, stdio: "inherit" });
|
|
69
|
+
|
|
70
|
+
const root = join(work, "root");
|
|
71
|
+
for (const deb of readdirSync(work).filter((f) => f.endsWith(".deb"))) {
|
|
72
|
+
execFileSync("dpkg-deb", ["-x", join(work, deb), root], { stdio: "inherit" });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
mkdirSync(join(dest, "bin"), { recursive: true });
|
|
76
|
+
mkdirSync(join(dest, "lib"), { recursive: true });
|
|
77
|
+
mkdirSync(join(dest, "tessdata"), { recursive: true });
|
|
78
|
+
|
|
79
|
+
cpSync(join(root, "usr/bin/tesseract"), join(dest, "bin/tesseract"));
|
|
80
|
+
const libDir = join(root, "usr/lib/x86_64-linux-gnu");
|
|
81
|
+
for (const so of readdirSync(libDir).filter((f) =>
|
|
82
|
+
/^(libtesseract|liblept)\.so/.test(f),
|
|
83
|
+
)) {
|
|
84
|
+
// Dereference to the real .so bytes and write them under the SONAME name.
|
|
85
|
+
// Debian ships libtesseract.so.5 etc. as symlinks into the extraction dir;
|
|
86
|
+
// copying them as symlinks (dereference:false) leaves the bundle pointing at
|
|
87
|
+
// a temp dir that is deleted on exit — the "portable" bundle then dlopen-fails
|
|
88
|
+
// with "libtesseract.so.5: cannot open shared object file". Writing real bytes
|
|
89
|
+
// under each name makes the bundle self-contained.
|
|
90
|
+
const realSo = realpathSync(join(libDir, so));
|
|
91
|
+
copyFileSync(realSo, join(dest, "lib", so));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Copy the FULL transitive shared-lib closure. libtesseract pulls in leptonica,
|
|
95
|
+
// which pulls in libjpeg/png/tiff/webp/openjp2/gif/zlib/... — none of which the
|
|
96
|
+
// two .debs above provide. Without them the bundled binary dlopen-fails on a
|
|
97
|
+
// clean host, defeating the whole "no host install" goal. We let `ldd` resolve
|
|
98
|
+
// the binary's deps with the bundle's own lib/ on the search path (so it can
|
|
99
|
+
// find the libtesseract/leptonica we just staged and recurse into their deps),
|
|
100
|
+
// then copy every resolved .so EXCEPT the glibc/loader set that every Linux
|
|
101
|
+
// target is guaranteed to provide.
|
|
102
|
+
const GLIBC_PROVIDED =
|
|
103
|
+
/^(ld-linux.*|linux-vdso|libc|libm|libdl|libpthread|librt|libresolv|libgcc_s|libstdc\+\+)\.so/;
|
|
104
|
+
function lddClosure(binPath) {
|
|
105
|
+
let out = "";
|
|
106
|
+
try {
|
|
107
|
+
out = execFileSync("ldd", [binPath], {
|
|
108
|
+
encoding: "utf8",
|
|
109
|
+
env: { ...process.env, LD_LIBRARY_PATH: join(dest, "lib") },
|
|
110
|
+
});
|
|
111
|
+
} catch (err) {
|
|
112
|
+
// `ldd` is glibc-only; on a musl/non-glibc build host we can't compute the
|
|
113
|
+
// closure. Fail loud rather than silently shipping an incomplete bundle.
|
|
114
|
+
throw new Error(
|
|
115
|
+
`[vendor-tesseract] ldd failed (${err.message}); cannot compute the shared-lib closure on this host`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
const resolved = [];
|
|
119
|
+
for (const line of out.split("\n")) {
|
|
120
|
+
const m = line.match(/=>\s*(\/\S+\.so\S*)/);
|
|
121
|
+
if (m) resolved.push(m[1]);
|
|
122
|
+
}
|
|
123
|
+
return resolved;
|
|
124
|
+
}
|
|
125
|
+
let bundledExtra = 0;
|
|
126
|
+
for (const soPath of lddClosure(join(dest, "bin", "tesseract"))) {
|
|
127
|
+
// ldd can resolve a path with a trailing slash (e.g. a symlink dir entry);
|
|
128
|
+
// strip it so the SONAME basename is never empty (an empty basename made the
|
|
129
|
+
// target the lib/ dir itself → cpSync EISDIR).
|
|
130
|
+
const cleanSrc = soPath.replace(/\/+$/, "");
|
|
131
|
+
const base = cleanSrc.split("/").pop();
|
|
132
|
+
if (!base || GLIBC_PROVIDED.test(base)) continue;
|
|
133
|
+
const target = join(dest, "lib", base);
|
|
134
|
+
if (existsSync(target)) continue; // already staged (libtesseract/liblept)
|
|
135
|
+
// dereference the symlink to the real .so file and copy its bytes under the
|
|
136
|
+
// SONAME the binary asks for, so the dynamic loader finds it by that name.
|
|
137
|
+
const realSrc = realpathSync(cleanSrc);
|
|
138
|
+
if (!statSync(realSrc).isFile()) continue;
|
|
139
|
+
copyFileSync(realSrc, target);
|
|
140
|
+
bundledExtra++;
|
|
141
|
+
}
|
|
142
|
+
console.log(
|
|
143
|
+
`[vendor-tesseract] bundled ${bundledExtra} transitive shared lib(s) via ldd closure.`,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// tessdata lives under usr/share/tesseract-ocr/<ver>/tessdata — copy the WHOLE
|
|
147
|
+
// dir (traineddata + the REQUIRED configs/ + tessconfigs/). Pick the HIGHEST
|
|
148
|
+
// version dir (numeric-aware) so a host with multiple tesseract data versions
|
|
149
|
+
// installed stages the newest, not whichever readdir happens to list first.
|
|
150
|
+
const shareTess = join(root, "usr/share/tesseract-ocr");
|
|
151
|
+
const ver = readdirSync(shareTess)
|
|
152
|
+
.filter((d) => existsSync(join(shareTess, d, "tessdata")))
|
|
153
|
+
.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))[0];
|
|
154
|
+
if (!ver)
|
|
155
|
+
throw new Error(
|
|
156
|
+
"[vendor-tesseract] tessdata not found in downloaded package",
|
|
157
|
+
);
|
|
158
|
+
cpSync(join(shareTess, ver, "tessdata"), join(dest, "tessdata"), {
|
|
159
|
+
recursive: true,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (!existsSync(join(dest, "tessdata", "configs", "tsv"))) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
"[vendor-tesseract] tessdata/configs/tsv missing — TSV OCR output would fail",
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
for (const l of langs) {
|
|
168
|
+
if (!existsSync(join(dest, "tessdata", `${l}.traineddata`))) {
|
|
169
|
+
throw new Error(`[vendor-tesseract] ${l}.traineddata missing`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
console.log(
|
|
173
|
+
`[vendor-tesseract] staged portable tesseract → ${dest} (langs: ${langs.join(", ")})`,
|
|
174
|
+
);
|
|
175
|
+
console.log(
|
|
176
|
+
`[vendor-tesseract] set ELIZA_VISION_VENDOR_DIR=${outDir} so the runtime resolves it.`,
|
|
177
|
+
);
|
package/build.config.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { BuildConfig } from "bun";
|
|
2
|
-
|
|
3
|
-
// Main build configuration
|
|
4
|
-
export const buildConfig: BuildConfig = {
|
|
5
|
-
entrypoints: ["./src/index.ts"],
|
|
6
|
-
outdir: "./dist",
|
|
7
|
-
target: "node",
|
|
8
|
-
format: "esm",
|
|
9
|
-
splitting: false,
|
|
10
|
-
sourcemap: "external",
|
|
11
|
-
external: [
|
|
12
|
-
"fs",
|
|
13
|
-
"path",
|
|
14
|
-
"http",
|
|
15
|
-
"https",
|
|
16
|
-
"crypto",
|
|
17
|
-
"node:fs",
|
|
18
|
-
"node:path",
|
|
19
|
-
"node:http",
|
|
20
|
-
"node:https",
|
|
21
|
-
"node:crypto",
|
|
22
|
-
"node:stream",
|
|
23
|
-
"node:buffer",
|
|
24
|
-
"node:util",
|
|
25
|
-
"node:events",
|
|
26
|
-
"node:url",
|
|
27
|
-
"vitest",
|
|
28
|
-
"dotenv",
|
|
29
|
-
"zod",
|
|
30
|
-
"@elizaos/core",
|
|
31
|
-
"@elizaos/plugin-message-handling",
|
|
32
|
-
"@tensorflow-models/coco-ssd",
|
|
33
|
-
"@tensorflow-models/pose-detection",
|
|
34
|
-
"@tensorflow-models/posenet",
|
|
35
|
-
"@tensorflow/tfjs-node",
|
|
36
|
-
"@tensorflow-models/mobilenet",
|
|
37
|
-
"axios",
|
|
38
|
-
"canvas",
|
|
39
|
-
"face-api.js",
|
|
40
|
-
"sharp",
|
|
41
|
-
"tesseract.js",
|
|
42
|
-
],
|
|
43
|
-
naming: "[dir]/[name].[ext]",
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// Workers build configuration
|
|
47
|
-
export const workersConfig: BuildConfig = {
|
|
48
|
-
entrypoints: [
|
|
49
|
-
"./src/workers/screen-capture-worker.ts",
|
|
50
|
-
"./src/workers/florence2-worker.ts",
|
|
51
|
-
"./src/workers/ocr-worker.ts",
|
|
52
|
-
],
|
|
53
|
-
outdir: "./dist/workers",
|
|
54
|
-
target: "node",
|
|
55
|
-
format: "cjs", // Workers need CommonJS format
|
|
56
|
-
splitting: false,
|
|
57
|
-
sourcemap: true,
|
|
58
|
-
external: [
|
|
59
|
-
"sharp",
|
|
60
|
-
"@tensorflow/tfjs-node",
|
|
61
|
-
"@tensorflow-models/mobilenet",
|
|
62
|
-
"@mapbox/node-pre-gyp",
|
|
63
|
-
"mock-aws-s3",
|
|
64
|
-
"aws-sdk",
|
|
65
|
-
"nock",
|
|
66
|
-
"canvas",
|
|
67
|
-
"face-api.js",
|
|
68
|
-
],
|
|
69
|
-
naming: "[name].[ext]",
|
|
70
|
-
};
|