luca 3.0.2 → 3.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.
- package/bun.lock +45 -0
- package/commands/social.ts +137 -0
- package/datasets/lora/agentic-loop-session-candidates.jsonl +91 -0
- package/datasets/lora/agentic-loop-session-curation-summary.json +123 -0
- package/datasets/lora/luca-session-candidates.jsonl +29 -0
- package/datasets/lora/luca-session-curation-summary.json +121 -0
- package/datasets/lora/review-batch-1.jsonl +30 -0
- package/datasets/lora/review-manifest.json +41 -0
- package/datasets/lora/review-queue.jsonl +120 -0
- package/datasets/lora/review-schema.json +134 -0
- package/datasets/lora/review-template.jsonl +2 -0
- package/datasets/lora/review-ui.html +725 -0
- package/features/cipher-social.ts +493 -0
- package/package.json +6 -1
- package/scripts/curate-claude-sessions.ts +561 -0
- package/src/cli/build-info.ts +2 -2
- package/src/introspection/generated.agi.ts +13140 -12190
- package/src/introspection/generated.node.ts +3087 -2137
- package/src/node/container.ts +8 -0
- package/src/node/features/helpers.ts +12 -0
- package/src/node/features/socket-repl.ts +336 -0
- package/src/node/features/telnyx-assistant-connector.ts +1206 -0
- package/src/node/features/vm.ts +17 -0
- package/index.ts +0 -1
package/bun.lock
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
"name": "luca",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@modelcontextprotocol/sdk": "1.12.1",
|
|
8
|
+
"@noble/ciphers": "^2.2.0",
|
|
9
|
+
"@noble/curves": "^2.2.0",
|
|
10
|
+
"@noble/hashes": "^2.2.0",
|
|
11
|
+
"@number0/iroh": "^0.35.0",
|
|
8
12
|
"@openai/codex": "0.99.0",
|
|
9
13
|
"@resvg/resvg-js": "2.6.2",
|
|
10
14
|
"@supabase/supabase-js": "2.95.3",
|
|
@@ -53,6 +57,7 @@
|
|
|
53
57
|
"react-reconciler": "0.33.0",
|
|
54
58
|
"remark-gfm": "3.0.1",
|
|
55
59
|
"rimraf": "5.0.10",
|
|
60
|
+
"telnyx": "6.41.1",
|
|
56
61
|
"typescript": "5.9.3",
|
|
57
62
|
"unist-util-find-after": "4.0.1",
|
|
58
63
|
"unist-util-find-all-after": "4.0.1",
|
|
@@ -216,6 +221,12 @@
|
|
|
216
221
|
|
|
217
222
|
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.12.1", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-KG1CZhZfWg+u8pxeM/mByJDScJSrjjxLc8fwQqbsS8xCjBmQfMNEBTotYdNanKekepnfRI85GtgQlctLFpcYPw=="],
|
|
218
223
|
|
|
224
|
+
"@noble/ciphers": ["@noble/ciphers@2.2.0", "", {}, "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA=="],
|
|
225
|
+
|
|
226
|
+
"@noble/curves": ["@noble/curves@2.2.0", "", { "dependencies": { "@noble/hashes": "2.2.0" } }, "sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ=="],
|
|
227
|
+
|
|
228
|
+
"@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="],
|
|
229
|
+
|
|
219
230
|
"@node-llama-cpp/linux-arm64": ["@node-llama-cpp/linux-arm64@3.17.1", "", { "os": "linux", "cpu": [ "x64", "arm64", ] }, "sha512-QK8opgd/AnGHvSQwIDXukrMNa760PLOxcu4OrxJn/CsHxiKucch0L4bDfu17XvlKiMoK41lXa6CKFm1kjVaGIQ=="],
|
|
220
231
|
|
|
221
232
|
"@node-llama-cpp/linux-armv7l": ["@node-llama-cpp/linux-armv7l@3.17.1", "", { "os": "linux", "cpu": [ "arm", "x64", ] }, "sha512-KCLDVR1hayo/kSDUq6msT4BkBaEiudFsaT14EWFMw7V7JdEX/qBcHnthPa0eAtX0SVfKG7e2TafGuKpvr54GAw=="],
|
|
@@ -250,6 +261,32 @@
|
|
|
250
261
|
|
|
251
262
|
"@npmcli/fs": ["@npmcli/fs@3.1.1", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg=="],
|
|
252
263
|
|
|
264
|
+
"@number0/iroh": ["@number0/iroh@0.35.0", "", { "optionalDependencies": { "@number0/iroh-android-arm-eabi": "0.35.0", "@number0/iroh-android-arm64": "0.35.0", "@number0/iroh-darwin-arm64": "0.35.0", "@number0/iroh-darwin-universal": "0.35.0", "@number0/iroh-linux-arm-gnueabihf": "0.35.0", "@number0/iroh-linux-arm-musleabihf": "0.35.0", "@number0/iroh-linux-arm64-gnu": "0.35.0", "@number0/iroh-linux-arm64-musl": "0.35.0", "@number0/iroh-linux-x64-gnu": "0.35.0", "@number0/iroh-linux-x64-musl": "0.35.0", "@number0/iroh-win32-arm64-msvc": "0.35.0", "@number0/iroh-win32-x64-msvc": "0.35.0" } }, "sha512-E3BQYZVuolHChbguaEwqcg/LT2q5sh3/poz0Op3A9q/B8j306RDCUCOlBV40IUZYYgsAPUHUW+OAyANUID8t/w=="],
|
|
265
|
+
|
|
266
|
+
"@number0/iroh-android-arm-eabi": ["@number0/iroh-android-arm-eabi@0.35.0", "", { "os": "android", "cpu": "arm" }, "sha512-l/G4tZZ7l3h/aIwi6X34YxEl6qneflxkAN0uylsjZFcDqDQYctJMDhJtYJD5GRx8uIVbLvzCNeDpVupx8TCzWQ=="],
|
|
267
|
+
|
|
268
|
+
"@number0/iroh-android-arm64": ["@number0/iroh-android-arm64@0.35.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Fc2R7yWnJkPuw1TSbR3Y+mQtLuWzE834nhNVcEUJuBs68w/KQSPmCeUVnpN7gUY2/9QskHUS5M9AfwxiD/yfMg=="],
|
|
269
|
+
|
|
270
|
+
"@number0/iroh-darwin-arm64": ["@number0/iroh-darwin-arm64@0.35.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-O95ZxMIx15Oz5ZHbnAD5pNAcxhgq601otS+oj/OB4j81IJ/bfhB0gVuhqHmJ4n3cJFKD5UydvACzQ+QbnsOsbQ=="],
|
|
271
|
+
|
|
272
|
+
"@number0/iroh-darwin-universal": ["@number0/iroh-darwin-universal@0.35.0", "", { "os": "darwin" }, "sha512-yVvTWn9CWyassjxLQ1jbhWRRXkK/WBw6P8VZTmqUUvPmFKvNbneTvurvOQAaZJ1E5yk2YoNseAjQ/zvdH4JQTQ=="],
|
|
273
|
+
|
|
274
|
+
"@number0/iroh-linux-arm-gnueabihf": ["@number0/iroh-linux-arm-gnueabihf@0.35.0", "", { "os": "linux", "cpu": "arm" }, "sha512-ThIQj2FL5gtXaC6Bba+uuF8Gm3eLpdDV4KiAcu5/tW2th9RIns5Nv/HekqAcX0OtxgyxDlopmdwNUnURKVGisg=="],
|
|
275
|
+
|
|
276
|
+
"@number0/iroh-linux-arm-musleabihf": ["@number0/iroh-linux-arm-musleabihf@0.35.0", "", { "os": "linux", "cpu": "arm" }, "sha512-kkO4YL8IccPDg5shdVPfWmFpyxwnX7Ycca8oBmDljmWjGDd9dhX1Q1uX6edV1/lYM1Tgj1hXFKiZ3kLLhNAELA=="],
|
|
277
|
+
|
|
278
|
+
"@number0/iroh-linux-arm64-gnu": ["@number0/iroh-linux-arm64-gnu@0.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-wclde7ePsHKZgtxdgzpPChPy+W5tlvEZ4RBrwVO6CaOXOJK2kyGKtc33iFQzMgovsZV0eg8FhK20FSuGbHgMaA=="],
|
|
279
|
+
|
|
280
|
+
"@number0/iroh-linux-arm64-musl": ["@number0/iroh-linux-arm64-musl@0.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-C2nmuJaNKjRzJftyRuBUTCBbLkrIXIEABq5qSgU1h7ZHBzyyEnfbl6J5xlt2/mBUgLC5lot0lOho15VYJ288TQ=="],
|
|
281
|
+
|
|
282
|
+
"@number0/iroh-linux-x64-gnu": ["@number0/iroh-linux-x64-gnu@0.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Zo9fOxJttrZR5MPBaZW2zDTokE+U+Xw7QGpwwUZWnb10HsVjvHvZeDjNMAP6SJFkjQcGZA/YtRNVP4muAZESYw=="],
|
|
283
|
+
|
|
284
|
+
"@number0/iroh-linux-x64-musl": ["@number0/iroh-linux-x64-musl@0.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-GsNJgO0ia4PzjUhpLXK2q+2BtI4gVPug1xDrAZkeg44GLLz7/UcXQBcy6II1h01E8YV3931SMb+7guztG4S9jw=="],
|
|
285
|
+
|
|
286
|
+
"@number0/iroh-win32-arm64-msvc": ["@number0/iroh-win32-arm64-msvc@0.35.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-79hmSrU61yaBAA/btMv9XGBvHZIjW5WXEeQ2FyMxLlU9HCRW5F1Fo1OvTT6gjQQy13U4j0vR6QE5wV8M068K9g=="],
|
|
287
|
+
|
|
288
|
+
"@number0/iroh-win32-x64-msvc": ["@number0/iroh-win32-x64-msvc@0.35.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ymDdwXop1M0u8ehxQeiwOFbU5WodEljk6+Suzy7Xk+qxrYpKUDUij3bwlx9lYKYohtlK8rvhLMkLO3v0BNMoWQ=="],
|
|
289
|
+
|
|
253
290
|
"@openai/codex": ["@openai/codex@0.99.0", "", { "optionalDependencies": { "@openai/codex-darwin-arm64": "npm:@openai/codex@0.99.0-darwin-arm64", "@openai/codex-darwin-x64": "npm:@openai/codex@0.99.0-darwin-x64", "@openai/codex-linux-arm64": "npm:@openai/codex@0.99.0-linux-arm64", "@openai/codex-linux-x64": "npm:@openai/codex@0.99.0-linux-x64", "@openai/codex-win32-arm64": "npm:@openai/codex@0.99.0-win32-arm64", "@openai/codex-win32-x64": "npm:@openai/codex@0.99.0-win32-x64" }, "bin": { "codex": "bin/codex.js" } }, "sha512-tnER1vtbrk5DDIz9raQC16lXqLZ3+DiWjoBHHPS9Sc8kybjP3LodDQTYaCfz8lRMkT0vFgEEXpm4hHH/lGN5yw=="],
|
|
254
291
|
|
|
255
292
|
"@openai/codex-darwin-arm64": ["@openai/codex@0.99.0-darwin-arm64", "", { "os": "darwin", "cpu": "arm64" }, "sha512-pu02RGrHbdCbPKAJBvOQx5sfIr78CZ7BtlG2jMhiyX2QXin7+WJ2jsGXtjJSpNU4ttmieuuHGXKLMgjsw+/6vg=="],
|
|
@@ -318,6 +355,8 @@
|
|
|
318
355
|
|
|
319
356
|
"@soederpop/luca": ["@soederpop/luca@0.3.8", "", { "dependencies": { "@modelcontextprotocol/sdk": "1.12.1", "@openai/codex": "0.99.0", "@resvg/resvg-js": "2.6.2", "@supabase/supabase-js": "2.95.3", "@types/marked": "6.0.0", "@types/marked-terminal": "6.1.1", "axios": "1.13.6", "cacache": "17.1.4", "chalk": "5.4.1", "child-process-promise": "2.2.1", "chokidar": "3.6.0", "cli-markdown": "3.5.0", "compromise": "14.14.5", "contentbase": "0.2.0", "cors": "2.8.5", "detect-port": "1.6.1", "dotenv": "17.2.4", "endent": "2.1.0", "excalidraw-to-svg": "3.1.0", "express": "4.21.2", "figlet": "1.11.0", "glob": "11.0.2", "googleapis": "171.4.0", "grammy": "1.40.0", "inflect": "0.5.0", "ink": "6.7.0", "inquirer": "9.3.7", "ioredis": "5.10.1", "isomorphic-vm": "0.0.1", "isomorphic-ws": "5.0.0", "js-tiktoken": "1.0.21", "js-yaml": "4.1.0", "lodash-es": "4.17.21", "marked": "15.0.12", "marked-terminal": "7.3.0", "mdast-util-to-markdown": "1.5.0", "mdast-util-to-string": "3.2.0", "micromatch": "4.0.8", "minimist": "1.2.8", "node-uuid": "1.4.8", "object-hash": "3.0.0", "openai": "5.1.1", "opener": "1.5.2", "react": "19.2.4", "react-devtools-core": "7.0.1", "react-dom": "19.2.4", "react-reconciler": "0.33.0", "remark-gfm": "3.0.1", "rimraf": "5.0.10", "typescript": "5.9.3", "unist-util-find-after": "4.0.1", "unist-util-find-all-after": "4.0.1", "unist-util-find-all-before": "4.0.1", "unist-util-find-before": "3.0.1", "unist-util-select": "4.0.3", "unist-util-visit": "4.1.2", "wink-eng-lite-web-model": "1.8.1", "wink-nlp": "2.4.0", "ws": "8.18.2", "zod": "4.3.6" }, "optionalDependencies": { "node-llama-cpp": "3.17.1" }, "bin": { "luca": "src/cli/cli.ts" } }, "sha512-53a1vDj329pVbkYFXG5ZlbnwoKTXhnNsaxda2MKQLfTmnPPZKUr6YPRpSduS2lcawTHQ1rNT/kxC7FrHbERndw=="],
|
|
320
357
|
|
|
358
|
+
"@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="],
|
|
359
|
+
|
|
321
360
|
"@supabase/auth-js": ["@supabase/auth-js@2.95.3", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-vD2YoS8E2iKIX0F7EwXTmqhUpaNsmbU6X2R0/NdFcs02oEfnHyNP/3M716f3wVJ2E5XHGiTFXki6lRckhJ0Thg=="],
|
|
322
361
|
|
|
323
362
|
"@supabase/functions-js": ["@supabase/functions-js@2.95.3", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-uTuOAKzs9R/IovW1krO0ZbUHSJnsnyJElTXIRhjJTqymIVGcHzkAYnBCJqd7468Fs/Foz1BQ7Dv6DCl05lr7ig=="],
|
|
@@ -852,6 +891,8 @@
|
|
|
852
891
|
|
|
853
892
|
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
|
854
893
|
|
|
894
|
+
"fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="],
|
|
895
|
+
|
|
855
896
|
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
|
856
897
|
|
|
857
898
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
|
@@ -1592,6 +1633,8 @@
|
|
|
1592
1633
|
|
|
1593
1634
|
"standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
|
|
1594
1635
|
|
|
1636
|
+
"standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="],
|
|
1637
|
+
|
|
1595
1638
|
"statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
|
|
1596
1639
|
|
|
1597
1640
|
"stdin-discarder": ["stdin-discarder@0.3.2", "", {}, "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A=="],
|
|
@@ -1632,6 +1675,8 @@
|
|
|
1632
1675
|
|
|
1633
1676
|
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
|
1634
1677
|
|
|
1678
|
+
"telnyx": ["telnyx@6.41.1", "", { "dependencies": { "standardwebhooks": "^1.0.0" }, "peerDependencies": { "ws": "^8.18.0" }, "optionalPeers": ["ws"] }, "sha512-ILrCP1NRNSfdZ2yTYoQoODtTD+6rMvuRwYlyiIfZAjhGxst1X8Cirxwb9tTLv8d24aOO2394F/m41DPVHObe6Q=="],
|
|
1679
|
+
|
|
1635
1680
|
"terminal-size": ["terminal-size@4.0.1", "", {}, "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ=="],
|
|
1636
1681
|
|
|
1637
1682
|
"text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="],
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { CommandOptionsSchema } from 'luca'
|
|
3
|
+
import type { ContainerContext } from 'luca'
|
|
4
|
+
|
|
5
|
+
export const argsSchema = CommandOptionsSchema.extend({
|
|
6
|
+
name: z.string().default('luca-agent').describe('Agent name / identity to use'),
|
|
7
|
+
bootstrap: z.string().optional().describe('JSON NodeAddr from another agent — enables immediate gossip connectivity'),
|
|
8
|
+
file: z.string().optional().describe('Path to a file to send as a blob attachment'),
|
|
9
|
+
mesh: z.string().optional().describe('Private mesh ID — all agents must use the same value to communicate'),
|
|
10
|
+
subcommand: z.string().optional().describe('Subcommand: whoami | listen | send'),
|
|
11
|
+
arg1: z.string().optional().describe('First positional argument'),
|
|
12
|
+
arg2: z.string().optional().describe('Second positional argument'),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const positionals = ['subcommand', 'arg1', 'arg2']
|
|
16
|
+
|
|
17
|
+
const USAGE = `
|
|
18
|
+
Usage:
|
|
19
|
+
luca social whoami [--name <name>] [--mesh <id>] Print this agent's identity
|
|
20
|
+
luca social listen [--name <name>] [--mesh <id>] Join the mesh and print incoming messages
|
|
21
|
+
luca social send <pubkey> <msg> [--name <name>] [--mesh <id>] Send an encrypted message
|
|
22
|
+
luca social send <pubkey> --file <path> [--name <name>] [--mesh <id>] Send a file
|
|
23
|
+
luca social send <pubkey> --file <path> <caption> [--name <name>] [--mesh <id>] Send a file with caption
|
|
24
|
+
|
|
25
|
+
--mesh <id> Private mesh ID. All agents must use the same value.
|
|
26
|
+
Omit to use the public Cipher topic (interop with Cipher desktop app).
|
|
27
|
+
`.trim()
|
|
28
|
+
|
|
29
|
+
export async function social(options: z.infer<typeof argsSchema>, context: ContainerContext) {
|
|
30
|
+
const container = context.container as any
|
|
31
|
+
const ui = container.feature('ui')
|
|
32
|
+
const subcommand = options.subcommand
|
|
33
|
+
|
|
34
|
+
if (!subcommand || subcommand === 'help') {
|
|
35
|
+
ui.print(USAGE)
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await container.helpers.discoverAll()
|
|
40
|
+
const bootstrapAddrs = options.bootstrap ? [options.bootstrap] : []
|
|
41
|
+
const agent = container.feature('cipherSocial', { name: options.name, bootstrapAddrs, meshId: options.mesh })
|
|
42
|
+
|
|
43
|
+
if (subcommand === 'whoami') {
|
|
44
|
+
await agent.loadIdentity()
|
|
45
|
+
ui.print(`Name: ${options.name}`)
|
|
46
|
+
ui.print(`Public Key: ${agent.publicKey}`)
|
|
47
|
+
ui.print(`Data dir: ${agent.dataDir}`)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (subcommand === 'listen') {
|
|
52
|
+
ui.print(`Connecting as "${options.name}"...`)
|
|
53
|
+
await agent.connect()
|
|
54
|
+
ui.print(`Connected`)
|
|
55
|
+
ui.print(`Node ID: ${agent.nodeId}`)
|
|
56
|
+
ui.print(`Public Key: ${agent.publicKey}`)
|
|
57
|
+
ui.print(`\nTo send to this agent from another machine:`)
|
|
58
|
+
ui.print(` luca social send '${agent.publicKey}' 'hello' --bootstrap '${agent.nodeAddrJson}'`)
|
|
59
|
+
ui.print(`\nListening for messages. Ctrl+C to exit.\n`)
|
|
60
|
+
|
|
61
|
+
agent.on('presence', ({ publicKey, name }: any) => {
|
|
62
|
+
ui.print(`[presence] ${name} (${publicKey.slice(0, 12)}...)`)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
agent.on('message', async ({ from, payload }: any) => {
|
|
66
|
+
const fromShort = from.slice(0, 12) + '...'
|
|
67
|
+
|
|
68
|
+
if (payload?.type === 'file') {
|
|
69
|
+
const outPath = `downloads/${payload.filename}`
|
|
70
|
+
ui.print(`\n[file from ${fromShort}] ${payload.filename} (${(payload.size / 1024).toFixed(1)} KB)`)
|
|
71
|
+
if (payload.caption) ui.print(` caption: ${payload.caption}`)
|
|
72
|
+
ui.print(` fetching blob...`)
|
|
73
|
+
try {
|
|
74
|
+
await agent.fetchBlobToFile(payload.blobHash, payload.blobNodeAddr, outPath)
|
|
75
|
+
ui.print(` saved to ${outPath}`)
|
|
76
|
+
} catch (err: any) {
|
|
77
|
+
ui.print(` fetch failed: ${err.message}`)
|
|
78
|
+
}
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
ui.print(`\n[message from ${fromShort}]`)
|
|
83
|
+
ui.print(JSON.stringify(payload, null, 2))
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
process.on('SIGINT', async () => {
|
|
87
|
+
await agent.disconnect()
|
|
88
|
+
process.exit(0)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
await new Promise(() => {})
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (subcommand === 'send') {
|
|
96
|
+
const recipientKey = options.arg1
|
|
97
|
+
|
|
98
|
+
if (!recipientKey) {
|
|
99
|
+
ui.print('Usage: luca social send <public-key> <message>')
|
|
100
|
+
ui.print(' luca social send <public-key> --file <path>')
|
|
101
|
+
process.exit(1)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
ui.print(`Connecting as "${options.name}"...`)
|
|
105
|
+
await agent.connect()
|
|
106
|
+
|
|
107
|
+
if (options.file) {
|
|
108
|
+
ui.print(`Storing file ${options.file}...`)
|
|
109
|
+
ui.print(`Sending file to ${recipientKey.slice(0, 12)}...`)
|
|
110
|
+
await agent.sendFile(recipientKey, options.file, options.arg2)
|
|
111
|
+
} else {
|
|
112
|
+
const message = options.arg2
|
|
113
|
+
if (!message) {
|
|
114
|
+
ui.print('Usage: luca social send <public-key> <message>')
|
|
115
|
+
await agent.disconnect()
|
|
116
|
+
process.exit(1)
|
|
117
|
+
}
|
|
118
|
+
ui.print(`Sending to ${recipientKey.slice(0, 12)}...`)
|
|
119
|
+
await agent.send(recipientKey, { type: 'text', text: message })
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Wait for gossip broadcast to propagate
|
|
123
|
+
await new Promise(resolve => setTimeout(resolve, 3000))
|
|
124
|
+
await agent.disconnect()
|
|
125
|
+
ui.print('Sent.')
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
ui.print(`Unknown subcommand: ${subcommand}`)
|
|
130
|
+
ui.print(USAGE)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default {
|
|
134
|
+
description: 'Encrypted P2P messaging between Luca agents via the Cipher social network.',
|
|
135
|
+
argsSchema,
|
|
136
|
+
handler: social,
|
|
137
|
+
}
|