omnius 1.0.7 → 1.0.9
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 +43 -22
- package/dist/index.js +44 -38
- package/npm-shrinkwrap.json +559 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
<a name="top"></a>
|
|
2
2
|
```text
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
|
|
4
|
+
░░ ░░░ ░░░░ ░░ ░░░ ░░ ░░ ░░░░ ░░░ ░░
|
|
5
|
+
▒ ▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒ ▒▒ ▒▒▒▒▒▒▒
|
|
6
|
+
▓ ▓▓▓▓ ▓▓ ▓▓ ▓ ▓ ▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓ ▓▓▓ ▓▓
|
|
7
|
+
█ ████ ██ █ █ ██ ██ █████ █████ ████ ████████ █
|
|
8
|
+
██ ███ ████ ██ ███ ██ ███ ████ ██
|
|
9
|
+
|
|
12
10
|
```
|
|
13
11
|
|
|
14
12
|
<p align="center">
|
|
15
13
|
<strong>AI coding agent powered entirely by open-weight models.</strong><br>
|
|
16
|
-
No API keys. No cloud. Your code never leaves your machine
|
|
14
|
+
No API keys. No cloud. Your code never leaves your machine <i>(unless you want it to!)</i>
|
|
17
15
|
</p>
|
|
18
16
|
|
|
19
17
|
<p align="center">
|
|
@@ -280,8 +278,10 @@ The agent uses tools autonomously in a loop — reading errors, fixing code, and
|
|
|
280
278
|
|
|
281
279
|
- **61 autonomous tools** — file I/O, shell, grep, web search/fetch/crawl, memory (read/write/search), sub-agents, background tasks, image/OCR/PDF, git, diagnostics, vision, desktop automation, browser automation, temporal agency (scheduler/reminders/agenda), structured files, code sandbox, transcription, skills, opencode delegation, cron agents, nexus P2P networking + x402 micropayments, **COHERE cognitive stack** (persistent REPL, recursive LLM calls, memory metabolism, identity kernel, reflection, exploration)
|
|
282
280
|
- **Moondream vision** — see and interact with the desktop via Moondream VLM (caption, query, detect, point-and-click)
|
|
281
|
+
- **Image generation with TUI previews** — `/image <prompt>` and the `generate_image` tool create PNGs under `.omnius/images/`, support explicit `--model` selection, and render generated, pasted, screenshot, and camera-capture images as auto-sized ASCII previews via `image-to-ascii`
|
|
283
282
|
- **Desktop automation** — vision-guided clicking: describe a UI element in natural language, the agent finds and clicks it
|
|
284
283
|
- **Auto-install desktop deps** — screenshot, mouse, OCR, and image tools auto-install missing system packages (scrot, xdotool, tesseract, imagemagick) on first use
|
|
284
|
+
- **Hardware-rated model lists** — first-run setup, `/models`, `/score`, and `/image list` score model fit against detected RAM/VRAM/GPU so text and image model choices are visible before you switch or generate
|
|
285
285
|
- **Parallel tool execution** — read-only tools run concurrently via `Promise.allSettled`
|
|
286
286
|
- **Sub-agent delegation** — spawn independent agents for parallel workstreams
|
|
287
287
|
- **OpenCode delegation** — offload coding tasks to opencode (sst/opencode) as an autonomous sub-agent with auto-install, progress monitoring, and result evaluation
|
|
@@ -339,7 +339,7 @@ The daemon auto-installs Python dependencies (OpenCLIP, torchaudio + soundfile,
|
|
|
339
339
|
- **Temporal agency** — schedule future tasks via OS cron, set cross-session reminders, flag attention items — startup injection surfaces due items automatically
|
|
340
340
|
- **Web crawling** — multi-page web scraping with Crawlee/Playwright for deep documentation extraction
|
|
341
341
|
- **Task templates** — specialized system prompts and tool recommendations for code, document, analysis, plan tasks
|
|
342
|
-
- **Inference capability scoring** — canirun.ai-style hardware assessment at first launch: memory/compute/speed scores, per-model compatibility matrix, recommended model selection
|
|
342
|
+
- **Inference capability scoring** — canirun.ai-style hardware assessment at first launch and on demand: memory/compute/speed scores, per-model compatibility matrix, `/models` runtime fit ratings, `/image list` image-model fit ratings, and recommended model selection
|
|
343
343
|
- **Auto-install everything** — first-run wizard auto-installs Ollama, curl, Python3, python3-venv with platform-aware package managers (apt, dnf, yum, pacman, apk, zypper, brew)
|
|
344
344
|
- **Sponsored inference** — `/sponsor` walks through a 5-step wizard to share your GPU with the world: select endpoints, choose banner animation (8 presets + AI-generated custom), set header message/links, configure transport (cloudflared/libp2p) + rate limits, and go live. Consumers discover sponsors via `/endpoint sponsor`. Secure proxy relay with per-IP rate limiting, daily token budgets, model allowlist, and concurrent request caps. Sponsor's raw API URL is never exposed. See [Sponsored Inference](#sponsored-inference--share-your-gpu-with-the-world) below
|
|
345
345
|
- **P2P inference network** — `/expose` local models or forward any `/endpoint` (Chutes, Groq, OpenRouter, etc.) through the libp2p P2P mesh. Passthrough mode (`/expose passthrough`) relays upstream API requests; `--loadbalance` distributes rate-limited token budgets across peers. `/expose config` provides an arrow-key menu for all settings. Gateway stats show budget remaining from `x-ratelimit-*` headers. Background daemon persists across Omnius restarts
|
|
@@ -357,7 +357,7 @@ The daemon auto-installs Python dependencies (OpenCLIP, torchaudio + soundfile,
|
|
|
357
357
|
- **IPFS sharing surface** — `/ipfs` status page with peer info + identity kernel metrics + memory sentiment. `/ipfs pin <CID>` to pin remote agent content. `/ipfs publish` to share identity kernel. `/ipfs share tool/skill` to publish agent-created tools with secret stripping. `/ipfs import <CID>` to retrieve shared content
|
|
358
358
|
- **Fortemi-React bridge** — `/fortemi start/status/stop` connects to [fortemi-react](https://github.com/robit-man/fortemi-react) (browser-first PGlite+pgvector knowledge system) via JWT auth. Proxy tools: `fortemi_capture`, `fortemi_search`, `fortemi_list`, `fortemi_get` auto-register when bridge is connected
|
|
359
359
|
- **Content ingestion** — `/ingest <file>` imports audio (transcribe via Whisper), PDF (pdftotext), or text files into structured memory with 800-char/100-overlap chunking (matches fortemi pattern)
|
|
360
|
-
- **Image generation** — `generate_image`
|
|
360
|
+
- **Image generation** — `generate_image` supports Ollama image models, Diffusers models, and stable-diffusion.cpp checkpoints/GGUF. SDXL Turbo is the practical default auto-install path under `.omnius/image-gen/.venv`; FLUX.1 dev and Stable Diffusion 3.5 Large are the primary high-realism baselines when hardware allows. `/image list` groups models by type, size, quality expectations, and hardware fit
|
|
361
361
|
- **Node visualization** — [omnius.nexus](https://github.com/robit-man/omnius.nexus) Three.js dashboard: 5-color emotional state mapping (neutral/focused/stressed/dreaming/excited), dynamic node size by memory depth + IPFS storage, activity-modulated connections, identity synchrony golden threads between mutually-pinned agents
|
|
362
362
|
- **TTS sanitizer** — strips markdown syntax (`##`, `**`, `` ` ``), emoji (prevents "white heavy checkmark"), box-drawing chars, and ANSI codes before feeding to ALL TTS engines
|
|
363
363
|
- **LuxTTS gapless playback** — look-ahead pre-synthesis pipeline: next chunk synthesizes while current plays, eliminating inter-sentence gaps. Jetson ARM support with NVIDIA's prebuilt PyTorch wheel
|
|
@@ -368,7 +368,7 @@ The daemon auto-installs Python dependencies (OpenCLIP, torchaudio + soundfile,
|
|
|
368
368
|
- **Self-learning** — auto-fetches docs from the web when encountering unfamiliar APIs
|
|
369
369
|
- **Seamless `/update`** — in-place update and reload with automatic context save/restore
|
|
370
370
|
- **Blessed mode** — `/full-send-bless` infinite warm loop keeps model weights in VRAM, auto-cycles tasks, never exits until you say stop
|
|
371
|
-
- **Telegram bridge** — `/telegram --key <token> --admin <userid>` public ingress/egress with admin filter and mandatory safety filter; bare `/telegram` toggles the service watchdog
|
|
371
|
+
- **Telegram bridge** — `/telegram --key <token> --admin <userid>` public ingress/egress with admin filter, scoped memory, per-chat personality profiles, sandboxed public creative file/image/audio tools, generated-artifact send-back, and mandatory safety filter; bare `/telegram` toggles the service watchdog
|
|
372
372
|
- **Task control** — `/pause` (gentle halt at turn boundary), `/stop` (immediate kill), `/resume` to continue
|
|
373
373
|
- **Model-tier awareness** — dynamic tool sets, prompt complexity, and context limits scale with model size (small/medium/large)
|
|
374
374
|
|
|
@@ -3294,13 +3294,16 @@ omnius
|
|
|
3294
3294
|
|
|
3295
3295
|
The TUI features an animated multilingual phrase carousel, live metrics bar with pastel-colored labels (token in/out, context window usage, human expert speed ratio, cost), rotating tips, syntax-highlighted tool output, and dynamic terminal-width cropping.
|
|
3296
3296
|
|
|
3297
|
+
Image surfaces are first-class in the terminal. `/image` generations, generated-image tool results, pasted image context, screenshots, and camera captures are converted through `image-to-ascii` and sized to the current terminal before being printed into the main scrollback. Each generated image also includes the saved file path below the preview.
|
|
3298
|
+
|
|
3297
3299
|
### Slash Commands
|
|
3298
3300
|
|
|
3299
3301
|
| Command | Description |
|
|
3300
3302
|
|---------|-------------|
|
|
3301
3303
|
| **Model & Endpoint** | |
|
|
3302
3304
|
| `/model <name>` | Switch to a different model |
|
|
3303
|
-
| `/models` | List
|
|
3305
|
+
| `/models` | List available text models with detected hardware-fit ratings |
|
|
3306
|
+
| `/score` | Show the inference capability scorecard: memory, compute, speed, and model compatibility |
|
|
3304
3307
|
| `/endpoint <url>` | Connect to a remote vLLM or OpenAI-compatible API |
|
|
3305
3308
|
| `/endpoint <url> --auth <key>` | Set endpoint with Bearer auth |
|
|
3306
3309
|
| `/endpoint <peerId> --auth <key>` | Connect to a libp2p peer via nexus P2P network |
|
|
@@ -3318,6 +3321,11 @@ The TUI features an animated multilingual phrase carousel, live metrics bar with
|
|
|
3318
3321
|
| **Audio & Vision** | |
|
|
3319
3322
|
| `/voice [model]` | Toggle TTS voice (GLaDOS, Overwatch, Kokoro, LuxTTS, Supertonic) |
|
|
3320
3323
|
| `/listen [mode]` | Toggle live microphone transcription |
|
|
3324
|
+
| `/image` | Open the image-generation model/setup menu |
|
|
3325
|
+
| `/image <prompt>` | Generate an image and show an auto-sized ASCII preview in the TUI |
|
|
3326
|
+
| `/image --model <model> <prompt>` | Generate with an explicit image model |
|
|
3327
|
+
| `/image list` | List image models by category, size, quality expectation, and hardware fit |
|
|
3328
|
+
| `/image setup <ollama\|diffusers\|sdcpp>` | Show setup commands for an image-generation backend |
|
|
3321
3329
|
| `/dream [mode]` | Start dream mode (default, deep, lucid) |
|
|
3322
3330
|
| **Display & Behavior** | |
|
|
3323
3331
|
| `/stream` | Toggle streaming token display with pastel syntax highlighting |
|
|
@@ -3440,7 +3448,7 @@ The steering sub-agent uses the same model and backend as the main agent with `m
|
|
|
3440
3448
|
|
|
3441
3449
|
<div align="right"><a href="#top">back to top</a></div>
|
|
3442
3450
|
|
|
3443
|
-
Connect the agent to a Telegram bot. Telegram can run in auto, chat, or action mode: conversational messages get rapid streamed replies in chat mode, while codebase/file/run requests use dedicated action sub-agents that are visible in the terminal waterfall alongside other agent activity.
|
|
3451
|
+
Connect the agent to a Telegram bot. Telegram can run in auto, chat, or action mode: conversational messages get rapid streamed replies in chat mode, while codebase/file/run requests use dedicated action sub-agents that are visible in the terminal waterfall alongside other agent activity. Public group chats get scoped memory, live reply discretion, and sandboxed creative tools for generating files, audio, and images without exposing the local workspace.
|
|
3444
3452
|
|
|
3445
3453
|
```bash
|
|
3446
3454
|
/telegram --key <token> # Save bot token (persisted to .omnius/settings.json)
|
|
@@ -3469,7 +3477,7 @@ The bot token, admin ID, and interaction mode are persisted to settings, so you
|
|
|
3469
3477
|
|
|
3470
3478
|
Use `/telegram mode auto|chat|action` to control how inbound Telegram messages are routed:
|
|
3471
3479
|
|
|
3472
|
-
- **auto** —
|
|
3480
|
+
- **auto** — the live router decides whether the message is conversational, actionable, or not directed at the bot. Reply-worthy conversational turns use fast streamed chat replies; explicit codebase/file/command/run/test requests use action sub-agents.
|
|
3473
3481
|
- **chat** — every non-command message gets a direct quick-chat completion with no tool loop. This is best for rapid back-and-forth conversation.
|
|
3474
3482
|
- **action** — every non-command message runs through the Telegram sub-agent path with the configured tool policy.
|
|
3475
3483
|
|
|
@@ -3528,13 +3536,13 @@ If a user sends another message while their sub-agent is still running, it's inj
|
|
|
3528
3536
|
|-------|----------|-------|--------|
|
|
3529
3537
|
| **Admin DM** (`--admin`, private chat) | 30 | All tools except shell (overridable) | Full read + write |
|
|
3530
3538
|
| **Admin Group** (admin in group chat) | 15 | Read-only + web + vision/OCR/transcription | Full read + write |
|
|
3531
|
-
| **Public** (everyone else) | 8 | memory
|
|
3539
|
+
| **Public** (everyone else) | 8 | scoped memory, web fetch/search, media analysis, sandboxed creative file/image/audio tools | Scoped per-chat |
|
|
3532
3540
|
|
|
3533
3541
|
**Admin DM** — full agent experience in private chat. File read, grep, glob, memory, web research, all tools except shell (which can be unblocked via config).
|
|
3534
3542
|
|
|
3535
3543
|
**Admin Group** — when the admin speaks in a group chat, the agent responds with read-only capabilities. No system-mutating tools (no shell, no file write, no code execution). Vision, OCR, transcription, and web tools are available for analyzing shared media and answering questions.
|
|
3536
3544
|
|
|
3537
|
-
**Public** — lightweight assistant with safety guardrails. No
|
|
3545
|
+
**Public** — lightweight assistant with safety guardrails. No shell and no access to arbitrary local files. Web search, scoped memory, media analysis, and creative artifact generation are available inside a per-chat sandbox. Reply discretion is active in groups.
|
|
3538
3546
|
|
|
3539
3547
|
### Streaming Responses
|
|
3540
3548
|
|
|
@@ -3542,12 +3550,25 @@ While the sub-agent is working, users see:
|
|
|
3542
3550
|
1. **Typing indicator** — "typing..." appears immediately and refreshes every 4 seconds until the response is ready
|
|
3543
3551
|
2. **Admin live streaming** — a placeholder message is sent immediately, then progressively edited via `editMessageText` with accumulated content + intermediate states (tool calls, results, status updates). Admin sees `🔧 tool_name(...)` and `✔ tool_name: result` inline as the agent works
|
|
3544
3552
|
3. **Markdown → HTML conversion** — all responses are automatically converted from GitHub-flavored Markdown to Telegram-compatible HTML (`<b>`, `<i>`, `<code>`, `<pre>`, `<s>`, `<a>`) with plaintext fallback
|
|
3545
|
-
4. **Final message** —
|
|
3553
|
+
4. **Final message selection** — the bridge prefers the assistant's refined visible content over task-complete summaries, router decisions, memory-stage notes, or `no_reply` markers
|
|
3554
|
+
5. **Artifact send-back** — generated images, documents, and audio files created inside the scoped creative workspace are uploaded back to Telegram via the appropriate Bot API method
|
|
3555
|
+
6. **Final message** — committed via `editMessageText` (admin) or `sendMessage` (public) when the agent completes
|
|
3546
3556
|
|
|
3547
3557
|
### Public User Isolation
|
|
3548
3558
|
|
|
3549
3559
|
Public users get **per-chat isolated memory** — each chat has its own scoped memory namespace (`telegram-{chatId}-{topic}`) so public users can store and retrieve facts about their conversation without accessing or polluting global agent memory. Public tools include: `memory_read`, `memory_write` (scoped), `memory_search`, `web_search`, `web_fetch`.
|
|
3550
3560
|
|
|
3561
|
+
The bridge also maintains a per-chat conversation state file with recent history, participants, relationship signals, and lightweight Zettelkasten memory cards. Each Telegram group or private chat gets its own scoped personality document under `.omnius/scoped-personality/telegram-chat/`; that profile is updated as people talk and injected into future Telegram context so tone, pacing, names, and relationships stay available turn to turn.
|
|
3562
|
+
|
|
3563
|
+
### Public Creative Artifacts
|
|
3564
|
+
|
|
3565
|
+
Public chats can ask Omnius to create files, images, and audio without giving the model arbitrary write access. The bridge injects a per-chat creative workspace under `.omnius/telegram-creative/<chat>/` and exposes scoped tools that can only create or edit files inside that folder. Generated artifacts are tracked by manifest and by tool result text, then uploaded back into the chat.
|
|
3566
|
+
|
|
3567
|
+
- **Images** — the model can call `generate_image` directly when the conversation asks for an image; generated PNGs are sent with `sendPhoto` when Telegram accepts them
|
|
3568
|
+
- **Documents** — Markdown, text, JSON, CSV, and other generated files are sent with `sendDocument`
|
|
3569
|
+
- **Audio** — generated WAV/voice artifacts are sent as audio or voice media based on file type
|
|
3570
|
+
- **Sandbox rule** — public creative tools cannot delete or mutate anything outside the scoped chat folder
|
|
3571
|
+
|
|
3551
3572
|
### Context-Aware Tool Policy
|
|
3552
3573
|
|
|
3553
3574
|
Tools are gated per execution context. The system enforces strict separation between what's available in a terminal session versus a public Telegram group:
|
|
@@ -3557,7 +3578,7 @@ Tools are gated per execution context. The system enforces strict separation bet
|
|
|
3557
3578
|
| `terminal` | All tools | Wide open — shell, file read/write, everything |
|
|
3558
3579
|
| `telegram-admin-dm` | All except shell | Admin DM — full tools, shell blocked by default (overridable) |
|
|
3559
3580
|
| `telegram-admin-group` | Read-only + web + vision/OCR | Admin in public group — no system mutation tools |
|
|
3560
|
-
| `telegram-public` | Memory r/w, web fetch/search | Public users —
|
|
3581
|
+
| `telegram-public` | Memory r/w, web fetch/search, scoped creative tools | Public users — no arbitrary local file access or shell |
|
|
3561
3582
|
| `api` | All tools | API endpoint — configurable |
|
|
3562
3583
|
|
|
3563
3584
|
**System tools** (`shell`, `file_write`, `file_edit`, `file_read`, `file_patch`, `batch_edit`, `grep_search`, `glob_find`, `list_directory`, `code_sandbox`, `codebase_map`, `git_info`, etc.) are **never exposed** in public-facing contexts.
|
|
@@ -3586,9 +3607,9 @@ The bridge distinguishes between **private DMs** and **group/supergroup chats**,
|
|
|
3586
3607
|
|
|
3587
3608
|
- **Admin DM** → full tool access, live streaming via `editMessageText`, project context injected
|
|
3588
3609
|
- **Admin in group** → read-only tools + web + vision/OCR, no live streaming, concise responses
|
|
3589
|
-
- **Public in group** →
|
|
3610
|
+
- **Public in group** → scoped memory + web + media + creative sandbox tools, reply discretion active
|
|
3590
3611
|
|
|
3591
|
-
**Reply discretion** — in group chats, the
|
|
3612
|
+
**Reply discretion** — in group chats, the live router evaluates whether a message warrants a response using the current conversation stream, participants, mentions, replies, and recent tone. Chatter that doesn't involve the bot is silently skipped and retained as context. Skip decisions are not sent back into the chat.
|
|
3592
3613
|
|
|
3593
3614
|
### Media Handling
|
|
3594
3615
|
|
package/dist/index.js
CHANGED
|
@@ -86423,8 +86423,8 @@ var require_follow_redirects = __commonJS({
|
|
|
86423
86423
|
}
|
|
86424
86424
|
return parsed;
|
|
86425
86425
|
}
|
|
86426
|
-
function resolveUrl(
|
|
86427
|
-
return useNativeURL ? new URL3(
|
|
86426
|
+
function resolveUrl(relative15, base3) {
|
|
86427
|
+
return useNativeURL ? new URL3(relative15, base3) : parseUrl(url.resolve(base3, relative15));
|
|
86428
86428
|
}
|
|
86429
86429
|
function validateUrl(input) {
|
|
86430
86430
|
if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
|
|
@@ -245198,21 +245198,21 @@ var require_pattern = __commonJS({
|
|
|
245198
245198
|
exports.removeDuplicateSlashes = removeDuplicateSlashes;
|
|
245199
245199
|
function partitionAbsoluteAndRelative(patterns) {
|
|
245200
245200
|
const absolute = [];
|
|
245201
|
-
const
|
|
245201
|
+
const relative15 = [];
|
|
245202
245202
|
for (const pattern of patterns) {
|
|
245203
|
-
if (
|
|
245203
|
+
if (isAbsolute7(pattern)) {
|
|
245204
245204
|
absolute.push(pattern);
|
|
245205
245205
|
} else {
|
|
245206
|
-
|
|
245206
|
+
relative15.push(pattern);
|
|
245207
245207
|
}
|
|
245208
245208
|
}
|
|
245209
|
-
return [absolute,
|
|
245209
|
+
return [absolute, relative15];
|
|
245210
245210
|
}
|
|
245211
245211
|
exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
|
|
245212
|
-
function
|
|
245212
|
+
function isAbsolute7(pattern) {
|
|
245213
245213
|
return path11.isAbsolute(pattern);
|
|
245214
245214
|
}
|
|
245215
|
-
exports.isAbsolute =
|
|
245215
|
+
exports.isAbsolute = isAbsolute7;
|
|
245216
245216
|
}
|
|
245217
245217
|
});
|
|
245218
245218
|
|
|
@@ -259304,7 +259304,7 @@ var require_util9 = __commonJS({
|
|
|
259304
259304
|
}
|
|
259305
259305
|
path11 = url.path;
|
|
259306
259306
|
}
|
|
259307
|
-
var
|
|
259307
|
+
var isAbsolute7 = exports.isAbsolute(path11);
|
|
259308
259308
|
var parts = path11.split(/\/+/);
|
|
259309
259309
|
for (var part, up = 0, i2 = parts.length - 1; i2 >= 0; i2--) {
|
|
259310
259310
|
part = parts[i2];
|
|
@@ -259324,7 +259324,7 @@ var require_util9 = __commonJS({
|
|
|
259324
259324
|
}
|
|
259325
259325
|
path11 = parts.join("/");
|
|
259326
259326
|
if (path11 === "") {
|
|
259327
|
-
path11 =
|
|
259327
|
+
path11 = isAbsolute7 ? "/" : ".";
|
|
259328
259328
|
}
|
|
259329
259329
|
if (url) {
|
|
259330
259330
|
url.path = path11;
|
|
@@ -259369,7 +259369,7 @@ var require_util9 = __commonJS({
|
|
|
259369
259369
|
exports.isAbsolute = function(aPath) {
|
|
259370
259370
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
259371
259371
|
};
|
|
259372
|
-
function
|
|
259372
|
+
function relative15(aRoot, aPath) {
|
|
259373
259373
|
if (aRoot === "") {
|
|
259374
259374
|
aRoot = ".";
|
|
259375
259375
|
}
|
|
@@ -259388,7 +259388,7 @@ var require_util9 = __commonJS({
|
|
|
259388
259388
|
}
|
|
259389
259389
|
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
|
|
259390
259390
|
}
|
|
259391
|
-
exports.relative =
|
|
259391
|
+
exports.relative = relative15;
|
|
259392
259392
|
var supportsNullProto = (function() {
|
|
259393
259393
|
var obj = /* @__PURE__ */ Object.create(null);
|
|
259394
259394
|
return !("__proto__" in obj);
|
|
@@ -270819,11 +270819,11 @@ ${lanes.join("\n")}
|
|
|
270819
270819
|
return toComponents2;
|
|
270820
270820
|
}
|
|
270821
270821
|
const components = toComponents2.slice(start2);
|
|
270822
|
-
const
|
|
270822
|
+
const relative15 = [];
|
|
270823
270823
|
for (; start2 < fromComponents.length; start2++) {
|
|
270824
|
-
|
|
270824
|
+
relative15.push("..");
|
|
270825
270825
|
}
|
|
270826
|
-
return ["", ...
|
|
270826
|
+
return ["", ...relative15, ...components];
|
|
270827
270827
|
}
|
|
270828
270828
|
function getRelativePathFromDirectory(fromDirectory, to, getCanonicalFileNameOrIgnoreCase) {
|
|
270829
270829
|
Debug.assert(getRootLength(fromDirectory) > 0 === getRootLength(to) > 0, "Paths must either both be absolute or both be relative");
|
|
@@ -315366,9 +315366,9 @@ ${lanes.join("\n")}
|
|
|
315366
315366
|
if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) {
|
|
315367
315367
|
return;
|
|
315368
315368
|
}
|
|
315369
|
-
const
|
|
315369
|
+
const relative15 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
|
|
315370
315370
|
for (const symlinkDirectory of symlinkDirectories) {
|
|
315371
|
-
const option = resolvePath(symlinkDirectory,
|
|
315371
|
+
const option = resolvePath(symlinkDirectory, relative15);
|
|
315372
315372
|
const result2 = cb(option, target === referenceRedirect);
|
|
315373
315373
|
shouldFilterIgnoredPaths = true;
|
|
315374
315374
|
if (result2) return result2;
|
|
@@ -474939,15 +474939,15 @@ var require_path_browserify = __commonJS({
|
|
|
474939
474939
|
normalize: function normalize2(path11) {
|
|
474940
474940
|
assertPath(path11);
|
|
474941
474941
|
if (path11.length === 0) return ".";
|
|
474942
|
-
var
|
|
474942
|
+
var isAbsolute7 = path11.charCodeAt(0) === 47;
|
|
474943
474943
|
var trailingSeparator = path11.charCodeAt(path11.length - 1) === 47;
|
|
474944
|
-
path11 = normalizeStringPosix(path11, !
|
|
474945
|
-
if (path11.length === 0 && !
|
|
474944
|
+
path11 = normalizeStringPosix(path11, !isAbsolute7);
|
|
474945
|
+
if (path11.length === 0 && !isAbsolute7) path11 = ".";
|
|
474946
474946
|
if (path11.length > 0 && trailingSeparator) path11 += "/";
|
|
474947
|
-
if (
|
|
474947
|
+
if (isAbsolute7) return "/" + path11;
|
|
474948
474948
|
return path11;
|
|
474949
474949
|
},
|
|
474950
|
-
isAbsolute: function
|
|
474950
|
+
isAbsolute: function isAbsolute7(path11) {
|
|
474951
474951
|
assertPath(path11);
|
|
474952
474952
|
return path11.length > 0 && path11.charCodeAt(0) === 47;
|
|
474953
474953
|
},
|
|
@@ -474969,7 +474969,7 @@ var require_path_browserify = __commonJS({
|
|
|
474969
474969
|
return ".";
|
|
474970
474970
|
return posix.normalize(joined);
|
|
474971
474971
|
},
|
|
474972
|
-
relative: function
|
|
474972
|
+
relative: function relative15(from3, to) {
|
|
474973
474973
|
assertPath(from3);
|
|
474974
474974
|
assertPath(to);
|
|
474975
474975
|
if (from3 === to) return "";
|
|
@@ -475161,9 +475161,9 @@ var require_path_browserify = __commonJS({
|
|
|
475161
475161
|
var ret = { root: "", dir: "", base: "", ext: "", name: "" };
|
|
475162
475162
|
if (path11.length === 0) return ret;
|
|
475163
475163
|
var code8 = path11.charCodeAt(0);
|
|
475164
|
-
var
|
|
475164
|
+
var isAbsolute7 = code8 === 47;
|
|
475165
475165
|
var start2;
|
|
475166
|
-
if (
|
|
475166
|
+
if (isAbsolute7) {
|
|
475167
475167
|
ret.root = "/";
|
|
475168
475168
|
start2 = 1;
|
|
475169
475169
|
} else {
|
|
@@ -475199,11 +475199,11 @@ var require_path_browserify = __commonJS({
|
|
|
475199
475199
|
preDotState === 0 || // The (right-most) trimmed path component is exactly '..'
|
|
475200
475200
|
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
|
|
475201
475201
|
if (end !== -1) {
|
|
475202
|
-
if (startPart === 0 &&
|
|
475202
|
+
if (startPart === 0 && isAbsolute7) ret.base = ret.name = path11.slice(1, end);
|
|
475203
475203
|
else ret.base = ret.name = path11.slice(startPart, end);
|
|
475204
475204
|
}
|
|
475205
475205
|
} else {
|
|
475206
|
-
if (startPart === 0 &&
|
|
475206
|
+
if (startPart === 0 && isAbsolute7) {
|
|
475207
475207
|
ret.name = path11.slice(1, startDot);
|
|
475208
475208
|
ret.base = path11.slice(1, end);
|
|
475209
475209
|
} else {
|
|
@@ -475213,7 +475213,7 @@ var require_path_browserify = __commonJS({
|
|
|
475213
475213
|
ret.ext = path11.slice(startDot, end);
|
|
475214
475214
|
}
|
|
475215
475215
|
if (startPart > 0) ret.dir = path11.slice(0, startPart - 1);
|
|
475216
|
-
else if (
|
|
475216
|
+
else if (isAbsolute7) ret.dir = "/";
|
|
475217
475217
|
return ret;
|
|
475218
475218
|
},
|
|
475219
475219
|
sep: "/",
|
|
@@ -477799,12 +477799,12 @@ var require_dist3 = __commonJS({
|
|
|
477799
477799
|
return patterns.length > 0 ? buildCrawler(options2, patterns) : [];
|
|
477800
477800
|
}
|
|
477801
477801
|
async function glob3(globInput, options2) {
|
|
477802
|
-
const [crawler,
|
|
477803
|
-
return crawler ? formatPaths(await crawler.withPromise(),
|
|
477802
|
+
const [crawler, relative15] = getCrawler(globInput, options2);
|
|
477803
|
+
return crawler ? formatPaths(await crawler.withPromise(), relative15) : [];
|
|
477804
477804
|
}
|
|
477805
477805
|
function globSync(globInput, options2) {
|
|
477806
|
-
const [crawler,
|
|
477807
|
-
return crawler ? formatPaths(crawler.sync(),
|
|
477806
|
+
const [crawler, relative15] = getCrawler(globInput, options2);
|
|
477807
|
+
return crawler ? formatPaths(crawler.sync(), relative15) : [];
|
|
477808
477808
|
}
|
|
477809
477809
|
exports.convertPathToPattern = convertPathToPattern;
|
|
477810
477810
|
exports.escapePath = escapePath;
|
|
@@ -593843,8 +593843,8 @@ var init_vision_ingress = __esm({
|
|
|
593843
593843
|
});
|
|
593844
593844
|
|
|
593845
593845
|
// packages/cli/src/tui/telegram-bridge.ts
|
|
593846
|
-
import { mkdirSync as mkdirSync60, existsSync as existsSync105, unlinkSync as unlinkSync21, readFileSync as readFileSync86, writeFileSync as writeFileSync57 } from "node:fs";
|
|
593847
|
-
import { join as join120, resolve as resolve39, basename as basename22 } from "node:path";
|
|
593846
|
+
import { mkdirSync as mkdirSync60, existsSync as existsSync105, unlinkSync as unlinkSync21, statSync as statSync35, readFileSync as readFileSync86, writeFileSync as writeFileSync57 } from "node:fs";
|
|
593847
|
+
import { join as join120, resolve as resolve39, basename as basename22, relative as relative13, isAbsolute as isAbsolute6 } from "node:path";
|
|
593848
593848
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
593849
593849
|
import { createHash as createHash19, randomInt } from "node:crypto";
|
|
593850
593850
|
function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
|
|
@@ -594408,6 +594408,10 @@ function telegramImageMime(media) {
|
|
|
594408
594408
|
if (ext === ".tif" || ext === ".tiff") return "image/tiff";
|
|
594409
594409
|
return "image/jpeg";
|
|
594410
594410
|
}
|
|
594411
|
+
function isPathInside(root, path11) {
|
|
594412
|
+
const rel = relative13(resolve39(root), resolve39(path11));
|
|
594413
|
+
return rel === "" || Boolean(rel) && !rel.startsWith("..") && !isAbsolute6(rel);
|
|
594414
|
+
}
|
|
594411
594415
|
function extractTelegramMentionedUsernames(message2, text) {
|
|
594412
594416
|
const usernames = /* @__PURE__ */ new Set();
|
|
594413
594417
|
const entities = [
|
|
@@ -596889,6 +596893,7 @@ Content-Type: ${contentType}\r
|
|
|
596889
596893
|
async sendGeneratedArtifactsFromSubAgent(msg, subAgent, finalText, includeMentioned) {
|
|
596890
596894
|
const root = subAgent.creativeWorkspaceRoot;
|
|
596891
596895
|
if (!root) return;
|
|
596896
|
+
const rootAbs = resolve39(root);
|
|
596892
596897
|
const paths = new Set(subAgent.generatedArtifacts);
|
|
596893
596898
|
for (const path11 of collectGeneratedArtifactPathsFromText(finalText, root)) {
|
|
596894
596899
|
paths.add(path11);
|
|
@@ -596899,8 +596904,9 @@ Content-Type: ${contentType}\r
|
|
|
596899
596904
|
);
|
|
596900
596905
|
for (const path11 of paths) {
|
|
596901
596906
|
const abs = resolve39(path11);
|
|
596907
|
+
if (!isPathInside(rootAbs, abs)) continue;
|
|
596902
596908
|
if (!includeMentioned && alreadySentByText.has(abs)) continue;
|
|
596903
|
-
if (!existsSync105(abs)) continue;
|
|
596909
|
+
if (!existsSync105(abs) || !statSync35(abs).isFile()) continue;
|
|
596904
596910
|
const kind = classifyMedia(abs) ?? "document";
|
|
596905
596911
|
await this.sendMediaReference(msg.chatId, {
|
|
596906
596912
|
original: abs,
|
|
@@ -621378,7 +621384,7 @@ var init_clipboard_media = __esm({
|
|
|
621378
621384
|
|
|
621379
621385
|
// packages/cli/src/tui/interactive.ts
|
|
621380
621386
|
import { cwd } from "node:process";
|
|
621381
|
-
import { resolve as resolve44, join as join136, dirname as dirname38, extname as extname13, relative as
|
|
621387
|
+
import { resolve as resolve44, join as join136, dirname as dirname38, extname as extname13, relative as relative14 } from "node:path";
|
|
621382
621388
|
import { createRequire as createRequire7 } from "node:module";
|
|
621383
621389
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
621384
621390
|
import {
|
|
@@ -622414,7 +622420,7 @@ async function renderAsciiPreviewForToolResult(toolName, output, repoRoot, write
|
|
|
622414
622420
|
const { extractSavedImagePath: extractSavedImagePath2 } = await Promise.resolve().then(() => (init_image_ascii_preview(), image_ascii_preview_exports));
|
|
622415
622421
|
const imagePath = extractSavedImagePath2(output, repoRoot);
|
|
622416
622422
|
if (!imagePath) return;
|
|
622417
|
-
const displayPath =
|
|
622423
|
+
const displayPath = relative14(repoRoot, imagePath).startsWith("..") ? imagePath : relative14(repoRoot, imagePath);
|
|
622418
622424
|
const title = toolName === "generate_image" ? "Generated image" : toolName === "screenshot" ? "Screenshot" : toolName === "camera_capture" ? "Camera frame" : "Image";
|
|
622419
622425
|
await renderAsciiPreviewForImage(imagePath, displayPath, title, writer);
|
|
622420
622426
|
} catch {
|
|
@@ -626415,7 +626421,7 @@ Log: ${nexusLogPath}`)
|
|
|
626415
626421
|
const { pasteClipboardImageToFile: pasteClipboardImageToFile2 } = await Promise.resolve().then(() => (init_clipboard_media(), clipboard_media_exports));
|
|
626416
626422
|
const pasted = pasteClipboardImageToFile2(repoRoot);
|
|
626417
626423
|
if (!pasted) return { ok: false, message: "Clipboard does not contain a supported image or no clipboard reader is available." };
|
|
626418
|
-
const relPath =
|
|
626424
|
+
const relPath = relative14(repoRoot, pasted.path).startsWith("..") ? pasted.path : relative14(repoRoot, pasted.path);
|
|
626419
626425
|
const asciiContextPromise = renderAsciiPreviewForImage(
|
|
626420
626426
|
pasted.path,
|
|
626421
626427
|
relPath,
|