@jc_stack/ez-agents 0.1.0-beta.12
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/.dockerignore +24 -0
- package/.env.example +26 -0
- package/AGENTS.md +84 -0
- package/CHANGELOG.md +39 -0
- package/CONTRIBUTING.md +73 -0
- package/Dockerfile +16 -0
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/SECURITY.md +26 -0
- package/THIRD_PARTY_NOTICES.md +14 -0
- package/bin/ezenciel-agents +2 -0
- package/bin/ezenciel-agents-ai +2 -0
- package/bin/ezenciel-agents-ai.mjs +5 -0
- package/bin/ezenciel-agents-approval +2 -0
- package/bin/ezenciel-agents-approval.mjs +16 -0
- package/bin/ezenciel-agents-create +12 -0
- package/bin/ezenciel-agents-docker +6 -0
- package/bin/ezenciel-agents-host +5 -0
- package/bin/ezenciel-agents-install +2 -0
- package/bin/ezenciel-agents-message +2 -0
- package/bin/ezenciel-agents-message.mjs +16 -0
- package/bin/ezenciel-agents-owner +2 -0
- package/bin/ezenciel-agents-owner.mjs +18 -0
- package/bin/ezenciel-agents-react +2 -0
- package/bin/ezenciel-agents-react.mjs +16 -0
- package/bin/ezenciel-agents-setup.mjs +18 -0
- package/bin/ezenciel-agents-source +2 -0
- package/bin/ezenciel-agents-source.mjs +16 -0
- package/bin/ezenciel-agents-tools.mjs +3 -0
- package/bin/ezenciel-agents.mjs +37 -0
- package/compose.whatsapp.yaml +12 -0
- package/compose.yaml +40 -0
- package/default-plugins.json +1 -0
- package/docker/entrypoint.sh +15 -0
- package/docker/healthcheck.mjs +8 -0
- package/docker/plugin-smoke.mjs +48 -0
- package/docker/pnpm-lock.yaml +415 -0
- package/docker/recovery.ts +11 -0
- package/docker/run.ts +52 -0
- package/docker/smoke.mjs +47 -0
- package/docker/status-smoke.mjs +30 -0
- package/docker/upgrade-smoke.mjs +58 -0
- package/docs/architecture/ai-selection.md +37 -0
- package/docs/architecture/authority-boundaries.md +14 -0
- package/docs/architecture/event-sources.md +34 -0
- package/docs/architecture/telegram-intake.md +29 -0
- package/docs/development-and-testing.md +18 -0
- package/docs/docker-runtime.md +118 -0
- package/docs/host-service.md +80 -0
- package/docs/plugin-contributions.md +34 -0
- package/docs/plugins.md +181 -0
- package/docs/releasing.md +71 -0
- package/docs/setup.md +234 -0
- package/docs/upgrades.md +193 -0
- package/package.json +106 -0
- package/scripts/assert-local-registry.mjs +22 -0
- package/scripts/release-check.mjs +14 -0
- package/scripts/smoke.ts +102 -0
- package/src/agent-install.ts +96 -0
- package/src/ai-cli.ts +22 -0
- package/src/ai.ts +88 -0
- package/src/approval-cli.ts +59 -0
- package/src/approval.ts +119 -0
- package/src/audio.ts +184 -0
- package/src/client-defaults.ts +101 -0
- package/src/config.ts +48 -0
- package/src/control-state.ts +350 -0
- package/src/desktop-bridge.ts +284 -0
- package/src/event-sources.ts +112 -0
- package/src/executor.ts +335 -0
- package/src/files.ts +75 -0
- package/src/format.ts +57 -0
- package/src/host-executor-client.ts +46 -0
- package/src/host-executor-protocol.ts +2 -0
- package/src/host-executor.ts +129 -0
- package/src/identity.ts +17 -0
- package/src/inbox.ts +171 -0
- package/src/index.ts +812 -0
- package/src/install-config.ts +56 -0
- package/src/install-tools.mjs +98 -0
- package/src/menu.ts +123 -0
- package/src/message-send.ts +57 -0
- package/src/message.ts +68 -0
- package/src/owner-args.ts +4 -0
- package/src/owner.ts +30 -0
- package/src/plugins/manager.mjs +272 -0
- package/src/react.ts +33 -0
- package/src/reaction.ts +32 -0
- package/src/read-request.ts +72 -0
- package/src/reply.ts +13 -0
- package/src/runs.ts +445 -0
- package/src/service.ts +28 -0
- package/src/setup.ts +180 -0
- package/src/software-status.ts +23 -0
- package/src/source-cli.ts +18 -0
- package/src/update-attention.ts +18 -0
- package/src/updates/artifact.mjs +83 -0
- package/src/updates/binding.mjs +27 -0
- package/src/updates/control.mjs +131 -0
- package/src/updates/launch.mjs +13 -0
- package/src/updates/runtime.mjs +140 -0
- package/src/updates/status.mjs +49 -0
- package/src/updates/supervisor.mjs +102 -0
- package/src/version.ts +4 -0
- package/src/workspace.ts +32 -0
- package/templates/agent/AGENTS.md +49 -0
- package/templates/agent/SOUL.md +11 -0
- package/templates/agent/TOOLS.md +46 -0
- package/templates/agent/USER.md +5 -0
- package/templates/updates.md +45 -0
- package/test/agent-install.test.ts +48 -0
- package/test/ai-cli.test.ts +28 -0
- package/test/ai.test.ts +105 -0
- package/test/approval.test.ts +40 -0
- package/test/audio.test.ts +77 -0
- package/test/client-defaults.test.ts +64 -0
- package/test/codex-context.test.ts +33 -0
- package/test/config.test.ts +32 -0
- package/test/control-state.test.ts +58 -0
- package/test/desktop-bridge.test.ts +159 -0
- package/test/docker-runtime.test.ts +23 -0
- package/test/event-sources.test.ts +113 -0
- package/test/executor.test.ts +135 -0
- package/test/files.test.ts +50 -0
- package/test/format.test.ts +41 -0
- package/test/host-executor.test.ts +149 -0
- package/test/inbox-burst.test.ts +66 -0
- package/test/inbox.test.ts +102 -0
- package/test/install-config.test.ts +75 -0
- package/test/install-tools.test.mjs +59 -0
- package/test/intake-relay.test.ts +337 -0
- package/test/owner-help.test.mjs +10 -0
- package/test/plugin-manager.test.mjs +157 -0
- package/test/publish-guard.test.ts +21 -0
- package/test/reaction.test.ts +122 -0
- package/test/read-request.test.ts +134 -0
- package/test/relay.test.ts +254 -0
- package/test/release-entrypoints.test.mjs +26 -0
- package/test/runs.test.ts +116 -0
- package/test/security.test.ts +85 -0
- package/test/setup.test.ts +68 -0
- package/test/software-status.test.ts +31 -0
- package/test/update-attention.test.ts +21 -0
- package/test/updates.test.mjs +282 -0
- package/test/upgrade-pause.test.ts +70 -0
- package/test/workspace.test.ts +80 -0
- package/tsconfig.json +19 -0
package/.dockerignore
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
*
|
|
2
|
+
!package.json
|
|
3
|
+
!pnpm-lock.yaml
|
|
4
|
+
!src/**
|
|
5
|
+
!bin/**
|
|
6
|
+
!docker/**
|
|
7
|
+
!templates/**
|
|
8
|
+
!skills/**
|
|
9
|
+
!test/**
|
|
10
|
+
!tsconfig.json
|
|
11
|
+
!scripts/smoke.ts
|
|
12
|
+
!README.md
|
|
13
|
+
!AGENTS.md
|
|
14
|
+
!ez-plugin.json
|
|
15
|
+
!LICENSE
|
|
16
|
+
!SECURITY.md
|
|
17
|
+
!docs/**
|
|
18
|
+
!scripts/assert-local-registry.mjs
|
|
19
|
+
|
|
20
|
+
!THIRD_PARTY_NOTICES.md
|
|
21
|
+
!CONTRIBUTING.md
|
|
22
|
+
!CHANGELOG.md
|
|
23
|
+
!scripts/release-check.mjs
|
|
24
|
+
!default-plugins.json
|
package/.env.example
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# The only credential required for the first smoke test. Keep the real value in .env.
|
|
2
|
+
TELEGRAM_BOT_TOKEN=
|
|
3
|
+
|
|
4
|
+
# Persistent mind, seeded by setup init or first relay start; existing files survive.
|
|
5
|
+
EZ_AGENT_WORKSPACE=./agent
|
|
6
|
+
|
|
7
|
+
# Local, protected authority state. Keep it outside the agent Markdown workspace.
|
|
8
|
+
# EZ_CONTROL_DIR=/absolute/path/outside/agent-workspace
|
|
9
|
+
|
|
10
|
+
# Owner-pairing request lifetime. Default is 900 seconds.
|
|
11
|
+
# EZ_PAIRING_TTL_SECONDS=900
|
|
12
|
+
|
|
13
|
+
# Optional. Default is 300.
|
|
14
|
+
# EZ_EXECUTOR_TIMEOUT_SECONDS=300
|
|
15
|
+
|
|
16
|
+
# CLI Executor adapter. Supported: agy (default), claude, grok, opencode
|
|
17
|
+
# Switch easily with: pnpm run setup <executor-name>
|
|
18
|
+
EZ_EXECUTOR_CLI=agy
|
|
19
|
+
|
|
20
|
+
# Optional: Audio transcription (STT) and voice synthesis (TTS)
|
|
21
|
+
# GEMINI_API_KEY=
|
|
22
|
+
# OPENAI_API_KEY=
|
|
23
|
+
|
|
24
|
+
# Optional: OpenRouter API key for OpenCode CLI (Nemotron 3.5 Lightning)
|
|
25
|
+
# OPENROUTER_API_KEY=
|
|
26
|
+
# OPENCODE_MODEL=openrouter/nvidia/nemotron-3.5-lightning
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# ezenciel-agents — Coding Standards & Architectural Invariants
|
|
2
|
+
|
|
3
|
+
Installed runtime operation uses Docker Compose. Read
|
|
4
|
+
[Docker setup, state and QA](docs/docker-runtime.md). Docker owns relay/plugin services; the existing host CLI and login are shared
|
|
5
|
+
through one generic transport, with separate agent workspaces and sessions.
|
|
6
|
+
|
|
7
|
+
## Installing this package
|
|
8
|
+
|
|
9
|
+
When the user asks to set up or install this repository or package, follow
|
|
10
|
+
[the agent-led setup instructions](docs/setup.md). Handle the technical work
|
|
11
|
+
and ask only for missing information. The user does not need to name or read
|
|
12
|
+
the documentation. Install means onboarding through a real Telegram reply,
|
|
13
|
+
unless the user explicitly asks for package files only. Do not finish with
|
|
14
|
+
developer commands or an uninitialized bot. At a required user step, give one
|
|
15
|
+
concrete action with its exact link; continue after their answer. The coding
|
|
16
|
+
standards below apply when developing the relay.
|
|
17
|
+
|
|
18
|
+
Main-first onboarding is mandatory: initialize an empty registry, complete owner
|
|
19
|
+
pairing and verify an agent-produced Telegram reply before plugin preparation or
|
|
20
|
+
QR onboarding. A supplied plugin archive is deferred input. After main setup,
|
|
21
|
+
plugin requests and onboarding run through the installed agent's Telegram chat,
|
|
22
|
+
not the original installer CLI. Read docs/setup.md for the handoff and diagnostics.
|
|
23
|
+
|
|
24
|
+
This package will be published as an open-source, lightweight Telegram-to-CLI relay. All code added to this package must adhere to these strict invariants to prevent bloat, credential leaks, and rewrites.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 1. Radical Lean Footprint (Zero DB Dependencies)
|
|
29
|
+
- **Runtime dependencies:** Restricted to `grammy` and TypeScript tooling (`tsx`). Do not add databases (no MongoDB, SQLite, Redis, or ORMs) or web frameworks (no Express/Fastify).
|
|
30
|
+
- **Native Node 22+ APIs only:** Use `node:fs/promises`, `node:child_process`, `node:crypto`, `node:path`, and native global `fetch`, `FormData`, and `Blob`.
|
|
31
|
+
- Keep `node_modules` minimal and installable in seconds.
|
|
32
|
+
|
|
33
|
+
## 2. Zero Deterministic Coding Across the Board (Tools, Flows & Dialog)
|
|
34
|
+
- **The relay is dumb plumbing:** The relay only ingests messages, batches them into runs, spawns the CLI executor, and drains outbox items. It is strictly minimal.
|
|
35
|
+
- **Nothing deterministic—not just dialog:** Do not hardcode multi-step tool pipelines, fallback state machines, parameter translation shims, procedural dialog flows, or canned conversational receipts ("Started run...", "I'll message as I go...").
|
|
36
|
+
- **The debugging reflex trap:** When an integration, tool, or flow doesn't work as expected, developers and LLMs have an overwhelming reflex to patch it by writing deterministic procedural code (`if error X -> hardcode Y -> do Z`). **Resist this completely.**
|
|
37
|
+
- **The real engineering work:** Our job is solely to:
|
|
38
|
+
1. Build clean, standalone tools that work reliably with clear Unix interfaces (clear args, predictable stdout/stderr, clean exit codes).
|
|
39
|
+
2. Ensure tools have simple setup and are clearly explained in the agent's workspace so the **agent understands them**.
|
|
40
|
+
3. Let the agent own all flow orchestration, tool chaining, decision making, and error recovery. Question every line of code—if it can be agentic, keep code out of it.
|
|
41
|
+
|
|
42
|
+
## 3. Crash-Safe Atomic Disk State
|
|
43
|
+
- All persistent stores (`ControlStore`, `RunStore`, outbox queue) must be disk-backed JSON files.
|
|
44
|
+
- **Atomic write pattern:** Never write directly to a state file. Always write to a temporary file (`${target}.${process.pid}.tmp`) with mode `0o600`, then atomically `rename` it over the destination.
|
|
45
|
+
- **Path sanitization:** Every ID parameter (`runId`, `outboxId`, `pairingId`) must be validated against `/^[a-zA-Z0-9_-]+$/` before being joined into paths. Never allow directory traversal (`..`).
|
|
46
|
+
|
|
47
|
+
## 4. Strict Subprocess Isolation & Secret Whitelisting
|
|
48
|
+
- **Environment leak prevention:** `TELEGRAM_BOT_TOKEN`, relay internals, and parent daemon secrets must **never** leak into the executor subprocess.
|
|
49
|
+
- The executor environment is built from an explicit whitelist plus bound runtime identifiers. Inspect `src/executor.ts` for the current list; never spread the daemon environment into a child.
|
|
50
|
+
- Executor stdout is ignored for chat delivery. To send updates, the agent must invoke the native binary: `ezenciel-agents-message`.
|
|
51
|
+
|
|
52
|
+
## 5. Telegram Formatting & Rate Limit Safety
|
|
53
|
+
- **Safe HTML formatting:** Never pass raw markdown directly into Telegram with `parse_mode: 'HTML'` or `'MarkdownV2'` without escaping. Use a dedicated sanitizer (`markdownToTelegramHtml`) that escapes `<, >, &` before wrapping tags.
|
|
54
|
+
- **Message chunking:** Chunk all outgoing messages to $\le 4,000$ characters on paragraph (`\n\n`), line (`\n`), or word boundaries.
|
|
55
|
+
- **Rate limits:** Avoid spamming bubbles to respect Telegram’s 1 message/sec per-chat rate limit.
|
|
56
|
+
|
|
57
|
+
## 6. Concurrency & Workspace Invariants
|
|
58
|
+
- **1 Writer Job per Workspace:** The agent's Markdown folder (`./agent/`) is its mind. Never run concurrent background processes writing to the same workspace simultaneously.
|
|
59
|
+
- Executor jobs queue sequentially in `RunStore`; the poller remains available for cancellation and incoming messages. There is no separate planner or automatic chat ACK lane.
|
|
60
|
+
|
|
61
|
+
## 7. Fail-Closed Authority (Channel Access ≠ Execution)
|
|
62
|
+
- Incoming messages from unapproved senders must **never** spawn the executor. First DM registers an unapproved pairing request, then stops.
|
|
63
|
+
- Group messages or unknown DMs fail silently.
|
|
64
|
+
- Stopping work (`/stop`) must terminate the active worker PID immediately (`SIGTERM`, escalating to `SIGKILL` if unclosed after 3s).
|
|
65
|
+
|
|
66
|
+
## 8. Mandatory Adversarial & Negative Tests
|
|
67
|
+
Every pull request modifying authority, execution, or routing must include negative tests:
|
|
68
|
+
1. Unapproved Telegram ID $\rightarrow$ no process spawned.
|
|
69
|
+
2. Group message $\rightarrow$ silent ignore.
|
|
70
|
+
3. Executor environment check $\rightarrow$ asserts `TELEGRAM_BOT_TOKEN` is `undefined`.
|
|
71
|
+
4. Corrupt JSON in store $\rightarrow$ handled gracefully without process crash.
|
|
72
|
+
5. Injected path traversal in IDs $\rightarrow$ rejected.
|
|
73
|
+
|
|
74
|
+
## Public contribution workflow
|
|
75
|
+
|
|
76
|
+
Read CONTRIBUTING.md before edits and docs/releasing.md before a release.
|
|
77
|
+
Maintainers and external agents use the same PR, tests and documentation standard.
|
|
78
|
+
Keep internal plans and private evidence outside this repository.
|
|
79
|
+
|
|
80
|
+
Before edits, follow CONTRIBUTING.md's isolated-work rules: one task per dedicated
|
|
81
|
+
worktree/branch/PR, starting from fetched origin/main. Do not switch or mix work in
|
|
82
|
+
another task's checkout. Stage only this task's changes. Keep its worktree through
|
|
83
|
+
review and QA; independent review and green CI precede an authorized merge.
|
|
84
|
+
Never treat task completion as permission to merge or publish.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0-beta.12 — self-upgrade beta
|
|
4
|
+
|
|
5
|
+
- Agent-owned main/plugin upgrades with stable-default policy, queued maintenance,
|
|
6
|
+
pinned package-manager preflight, private backups and code/config rollback.
|
|
7
|
+
- Main Telegram onboarding before plugin installation, reusable build/preflight tools,
|
|
8
|
+
executor and private-pause fixes, and installed/running version diagnostics.
|
|
9
|
+
- Isolated worktree/PR contribution process and explicit independent review.
|
|
10
|
+
- User-reported VM QA passed main beta.3 to beta.4 upgrade and deliberate beta.11
|
|
11
|
+
activation failure with rollback to beta.4 and a post-recovery Telegram reply.
|
|
12
|
+
- That VM evidence covers earlier candidates. Final beta.12 fresh-host/reboot and
|
|
13
|
+
live WhatsApp upgrade acceptance remain pending; this is a testing beta.
|
|
14
|
+
|
|
15
|
+
Private QA versions beta.3 through beta.11 were not public releases; some were
|
|
16
|
+
deliberately broken rollback fixtures and must never be published.
|
|
17
|
+
|
|
18
|
+
## 0.1.0-beta.2 — distribution preparation (not published)
|
|
19
|
+
|
|
20
|
+
- Publish under `@jc_stack/ez-agents`; GitHub remains `jdorado/ez-agents`.
|
|
21
|
+
- Document pinned npm downloads and retain the beta-only distribution channel.
|
|
22
|
+
- Runtime behavior and dependencies are unchanged from beta.1. Live account and
|
|
23
|
+
reboot acceptance remain deferred.
|
|
24
|
+
|
|
25
|
+
## 0.1.0-beta.1 — initial public beta
|
|
26
|
+
|
|
27
|
+
- Owner-paired Telegram relay using an existing host AI CLI and persistent
|
|
28
|
+
Markdown workspace, with queued execution and explicit messaging tools.
|
|
29
|
+
- Docker runtime, private deployment creation and a local hash-pinned plugin
|
|
30
|
+
manager with explicit installation/start/stop and provider-owned onboarding.
|
|
31
|
+
- Empty default catalog: no unpublished sibling package required.
|
|
32
|
+
- Public contribution, security, packaging and release instructions.
|
|
33
|
+
|
|
34
|
+
Limits: trusted host administration, not hostile-agent isolation. No hosted
|
|
35
|
+
service or remote plugin marketplace. Desktop executor acceptance and optional
|
|
36
|
+
voice providers need separate verification; CLI success is not GUI evidence.
|
|
37
|
+
|
|
38
|
+
Beta acceptance: automated tests, packed installs and Docker fixtures only. Live
|
|
39
|
+
provider onboarding and reboot verification are deferred, not marked passed.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Humans, LLM agents and maintainers use the same small-PR process. Read AGENTS.md
|
|
4
|
+
and the relevant CLI help first. Open an issue for substantial scope changes;
|
|
5
|
+
small fixes need no proposal. Internal plans and private QA belong outside this
|
|
6
|
+
repository. Public docs describe shipped behavior and explicit limitations.
|
|
7
|
+
|
|
8
|
+
1. Fork/branch from main and make one coherent change. Preserve unrelated work.
|
|
9
|
+
2. Install Node 22+ and pnpm 10.30.3. Run `pnpm install --frozen-lockfile`.
|
|
10
|
+
3. Change the code, user instructions and focused tests together. Authority,
|
|
11
|
+
paths, credentials, cancellation and uncertain writes need negative tests.
|
|
12
|
+
4. Run `pnpm verify`, `npm run release:check` and `git diff --check`.
|
|
13
|
+
Packaging/runtime changes also need the Docker checks in docs/releasing.md.
|
|
14
|
+
5. Open a PR explaining the problem, resulting behavior, verification and limits.
|
|
15
|
+
Include a short sanitized reproduction. State which tests were not run.
|
|
16
|
+
6. A maintainer reviews and merges after CI. Maintainers use PRs too. No CLA,
|
|
17
|
+
ticket requirement, custom commit format or additional approval committee.
|
|
18
|
+
|
|
19
|
+
You are responsible for understanding submitted code, including AI-generated
|
|
20
|
+
code, and having the right to contribute it under this repository's license.
|
|
21
|
+
Do not upload conversation dumps, credentials, QR codes or customer records.
|
|
22
|
+
Installation authority alone does not authorize messaging another person.
|
|
23
|
+
Use synthetic providers for routine tests; live tests need a dedicated account
|
|
24
|
+
and explicit recipient authority. A process exit is not provider delivery proof.
|
|
25
|
+
|
|
26
|
+
Report bugs through a GitHub issue with version, OS, Node/Docker versions,
|
|
27
|
+
minimal steps, expected/actual behavior and sanitized output. Feature requests
|
|
28
|
+
should explain the user problem and a small acceptance example. Security reports
|
|
29
|
+
follow SECURITY.md. Release and new-plugin requirements: docs/releasing.md and
|
|
30
|
+
docs/plugin-contributions.md.
|
|
31
|
+
|
|
32
|
+
## Isolated work and review
|
|
33
|
+
|
|
34
|
+
- One coherent change, one branch, one dedicated Git worktree, one PR per
|
|
35
|
+
repository. Create the worktree from freshly fetched origin/main before edits.
|
|
36
|
+
Never develop on main or switch branches in another task's checkout.
|
|
37
|
+
- Inspect git status and git worktree list first. Reuse a worktree only for the
|
|
38
|
+
same task. Preserve other work; never stash, reset or commit another task's
|
|
39
|
+
files. Stage explicit paths or hunks and review the staged diff before committing.
|
|
40
|
+
- Keep worktrees outside the published package. Each task installs its own
|
|
41
|
+
dependencies and uses separate test state, ports and Docker project names.
|
|
42
|
+
Never share live bot tokens or provider profiles between test instances.
|
|
43
|
+
- Keep unrelated fixes/features in separate PRs. For work spanning repositories,
|
|
44
|
+
create one worktree/PR per repository and link dependencies and merge order.
|
|
45
|
+
Branch from an unmerged feature only when the dependency is intentional and
|
|
46
|
+
documented; do not quietly include it in an unrelated PR.
|
|
47
|
+
- Open a draft PR when the change is reviewable. Report its scope, exact commit,
|
|
48
|
+
validation and remaining QA. A completed coding task can remain a draft;
|
|
49
|
+
implementation completion does not authorize merge or npm publication.
|
|
50
|
+
- Before merge, obtain an independent human or agent review of the final diff.
|
|
51
|
+
The implementer's self-check and passing CI are not independent review.
|
|
52
|
+
Reviewers inspect correctness, architecture, state/permissions and negative
|
|
53
|
+
cases. Record reviewer identity/session, reviewed commit, findings and resolution
|
|
54
|
+
in the PR. If review is unavailable, leave it explicitly pending.
|
|
55
|
+
- New substantive commits or conflict resolutions invalidate the affected review
|
|
56
|
+
and test evidence. Refresh against current main, review the resulting diff and
|
|
57
|
+
run the applicable checks. Do not bypass protected-branch requirements.
|
|
58
|
+
- Merge only after review, required CI, applicable QA and maintainer authorization.
|
|
59
|
+
Publish only under the separate release process; commits and merges are not
|
|
60
|
+
releases. Record which source commit and artifact hash were tested.
|
|
61
|
+
- Keep the worktree while its PR or QA is open. After merge or explicit abandonment,
|
|
62
|
+
inspect it for uncommitted/untracked files and local-only commits. Remove only
|
|
63
|
+
the clean task worktree after valuable work is preserved; never force cleanup.
|
|
64
|
+
Delete its branch only after confirming merge or authorized abandonment.
|
|
65
|
+
|
|
66
|
+
Example, substituting a unique task name and an absolute external directory:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
git status --short
|
|
70
|
+
git worktree list
|
|
71
|
+
git fetch origin
|
|
72
|
+
git worktree add -b feat/task-name /absolute/worktrees/task-name origin/main
|
|
73
|
+
```
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM node:22.22.0-bookworm-slim@sha256:dd9d21971ec4395903fa6143c2b9267d048ae01ca6d3ea96f16cb30df6187d94 AS dependencies
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates git util-linux ffmpeg && rm -rf /var/lib/apt/lists/*
|
|
4
|
+
RUN corepack enable && corepack prepare pnpm@10.30.3 --activate
|
|
5
|
+
COPY package.json ./
|
|
6
|
+
COPY docker/pnpm-lock.yaml ./pnpm-lock.yaml
|
|
7
|
+
RUN pnpm install --frozen-lockfile --ignore-scripts
|
|
8
|
+
COPY . .
|
|
9
|
+
FROM dependencies AS test
|
|
10
|
+
RUN pnpm verify
|
|
11
|
+
FROM dependencies AS runtime
|
|
12
|
+
RUN chmod +x docker/entrypoint.sh bin/ezenciel-agents* && mkdir -p /state/control /state/home /workspace && chown node:node /state/control /state/home /workspace
|
|
13
|
+
ENV HOME=/state/home EZ_AGENT_WORKSPACE=/workspace EZ_CONTROL_DIR=/state/control EZ_EXECUTOR_CLI=grok PATH=/app/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
14
|
+
WORKDIR /workspace
|
|
15
|
+
ENTRYPOINT ["/app/docker/entrypoint.sh"]
|
|
16
|
+
CMD ["start"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ezenciel-agents contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# ezenciel-agents
|
|
2
|
+
|
|
3
|
+
Telegram `/status` shows the running relay and host
|
|
4
|
+
versions plus installed plugin versions. The agent's `ez status` adds verified
|
|
5
|
+
plugin runtime states and upgrade job receipts. See [status and upgrades](docs/upgrades.md).
|
|
6
|
+
|
|
7
|
+
**Beta 0.1.0-beta.12 — for testing on a trusted machine.** Offline and Docker
|
|
8
|
+
fixtures are verified. Live account onboarding and reboot acceptance for this
|
|
9
|
+
release are deferred; this is not a production-readiness claim.
|
|
10
|
+
|
|
11
|
+
The npm package is `@jc_stack/ez-agents` (channel `beta`). Download a pinned
|
|
12
|
+
release with `npm pack @jc_stack/ez-agents@0.1.0-beta.12`, or get the tarball and SHA256SUMS from
|
|
13
|
+
[GitHub prereleases](https://github.com/jdorado/ez-agents/releases/tag/v0.1.0-beta.12).
|
|
14
|
+
GitHub remains under `jdorado`; npm uses `jc_stack`. Do not install the unrelated
|
|
15
|
+
unscoped `ez-whatsapp` package.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Installed runtime operation uses Docker Compose. Read
|
|
19
|
+
[Docker setup, state and QA](docs/docker-runtime.md). Docker owns relay/plugin services; the existing host CLI and login are shared
|
|
20
|
+
through one generic transport, with separate agent workspaces and sessions.
|
|
21
|
+
|
|
22
|
+
A minimal Telegram-to-AI-CLI relay. One owner, one persistent Markdown mind.
|
|
23
|
+
|
|
24
|
+
## You are the installing agent
|
|
25
|
+
|
|
26
|
+
If the user says **install** or **set up** this repository/package, complete
|
|
27
|
+
[docs/setup.md](docs/setup.md) yourself. The instructions and commands in this
|
|
28
|
+
repository are addressed to you, the LLM with computer access, not the human.
|
|
29
|
+
|
|
30
|
+
**Your finish line is a working Telegram reply and automatic startup.** Adding
|
|
31
|
+
npm dependencies, printing `--help`, or creating files is not completion.
|
|
32
|
+
Install the main runtime alone first, with an empty plugin catalog. Even when
|
|
33
|
+
WhatsApp is supplied or requested alongside it, defer plugin setup and QR scanning
|
|
34
|
+
until owner pairing and a real agent reply are verified. Then the owner requests
|
|
35
|
+
the plugin in Telegram and the installed agent handles onboarding there. The
|
|
36
|
+
initial host CLI must not install the plugin on that agent's behalf.
|
|
37
|
+
Do not hand the human terminal commands, ask them to start the relay, leave a
|
|
38
|
+
terminal open, read logs, find their numeric Telegram ID, or approve pairing
|
|
39
|
+
from another terminal. You own those steps and their verification.
|
|
40
|
+
|
|
41
|
+
Only involve the human for missing account access, a bot token you cannot
|
|
42
|
+
obtain through authorized tools, confirmation of which Telegram account is
|
|
43
|
+
theirs, or an OS-level authorization prompt you cannot approve yourself. Give
|
|
44
|
+
one concrete action at a time, with the exact link. Resume setup when they
|
|
45
|
+
answer. Explain actual blockers in plain language.
|
|
46
|
+
|
|
47
|
+
### Docker is installer work
|
|
48
|
+
|
|
49
|
+
Docker and Compose are required, but they are **not a prerequisite the human
|
|
50
|
+
must install**. First inspect the host. If Docker is absent, stopped, or lacks
|
|
51
|
+
Compose, install the official supported Docker distribution for that operating
|
|
52
|
+
system yourself, start it, and arrange the normal user access it requires.
|
|
53
|
+
Then verify the engine and Compose with a harmless real container before
|
|
54
|
+
building this package. Do not respond with “install Docker and retry,” a list
|
|
55
|
+
of commands for the human, or a request to open a terminal.
|
|
56
|
+
|
|
57
|
+
An administrator password, native system approval, or Docker Desktop sign-in
|
|
58
|
+
dialog is a human-only boundary. When one appears, explain the single action
|
|
59
|
+
needed and continue immediately after it. Everything else—package install,
|
|
60
|
+
image build, host transport, Compose startup, pairing, and a real Telegram
|
|
61
|
+
reply—is the installing LLM's job.
|
|
62
|
+
|
|
63
|
+
### Recognize this artifact immediately
|
|
64
|
+
|
|
65
|
+
This is a **Node.js npm package**, not a Python package or a Codex skill.
|
|
66
|
+
For a supplied tarball, read `package/README.md` and `package/docs/setup.md`
|
|
67
|
+
from that archive. Install that artifact; do not search npm, PyPI, or skill
|
|
68
|
+
catalogs for its name. Build/run its Docker image; Docker and Compose are
|
|
69
|
+
required on the host and the installing LLM makes them ready if needed. The
|
|
70
|
+
image supplies relay dependencies; the existing host CLI supplies execution.
|
|
71
|
+
|
|
72
|
+
Use the exact scoped npm name and version above, or the supplied tarball/path.
|
|
73
|
+
A bare product name is not a package identity. Inspect the artifact before setup;
|
|
74
|
+
do not substitute a similarly named package.
|
|
75
|
+
|
|
76
|
+
### Installer tools
|
|
77
|
+
|
|
78
|
+
Run these yourself from the installation directory. Read the setup guide for
|
|
79
|
+
credentials, startup, and verified pairing; never present this as human homework.
|
|
80
|
+
|
|
81
|
+
| Tool | Purpose |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `ezenciel-agents-install preflight --executor <path-or-name>` | Check prerequisites, disk and executor identity hints before setup |
|
|
84
|
+
| `ezenciel-agents-install build` | Build once per artifact, with a private log and duplicate-build detection |
|
|
85
|
+
| `ezenciel-agents-install status --deployment <path>` | Distinguish runtime/configuration, pairing and Telegram reply evidence |
|
|
86
|
+
| `ezenciel-agents-create --register-cli <current-cli>` | Record the CLI that installs the initial package |
|
|
87
|
+
| `ezenciel-agents-create --name <name> --purpose <purpose>` | Create an agent inheriting the installation CLI; token via stdin |
|
|
88
|
+
| `ezenciel-agents-host` | Invoke the existing shared host CLI for this deployment |
|
|
89
|
+
| `ezenciel-agents-setup configure <executor>` | Private configuration and missing starter files; preserves personal files |
|
|
90
|
+
| `ezenciel-agents-setup configure <executor> --token-stdin` | Same, with the BotFather token supplied privately through stdin |
|
|
91
|
+
| `ezenciel-agents-setup service` | Start only the Docker relay bound by `docker.env` in the current directory; register the [host service](docs/host-service.md) separately |
|
|
92
|
+
| `ezenciel-agents-owner status` | Inspect the owner and pending pairing requests |
|
|
93
|
+
| `ezenciel-agents-owner approve <telegram-user-id>` | Approve the verified owner; never an arbitrary first sender |
|
|
94
|
+
| `ezenciel-agents-setup status` | Inspect installed executor choices |
|
|
95
|
+
| `ezenciel-agents-setup init` | Seed only missing workspace guidance |
|
|
96
|
+
|
|
97
|
+
Run runtime tools through `ezenciel-agents-docker run --rm relay <command>`
|
|
98
|
+
as shown in the Docker guide. Keep the Docker engine available; Compose owns
|
|
99
|
+
restart and shutdown. The installing agent registers the small host CLI transport with the native service manager.
|
|
100
|
+
|
|
101
|
+
## Runtime and development reference
|
|
102
|
+
|
|
103
|
+
The selected host CLI runs in this agent's persistent workspace and owns its
|
|
104
|
+
Markdown/work files. New conversations and AI changes preserve those files.
|
|
105
|
+
`AGENTS.md`, `SOUL.md`, `USER.md`, and `TOOLS.md` are seeded; `MEMORY.md` is
|
|
106
|
+
optional. Received files go in `inbox/`, tasks and deliverables in `work/`.
|
|
107
|
+
Credentials and control state stay outside the mind. File separation is not
|
|
108
|
+
OS isolation against a process running as the same user.
|
|
109
|
+
|
|
110
|
+
Telegram intake is owner-gated. The executor sends replies with the messaging
|
|
111
|
+
CLI; stdout is not a reply. A process exit code is not delivery proof.
|
|
112
|
+
Voice/media needs its additional providers and tools; defer optional setup
|
|
113
|
+
until the owner asks. Do not advertise unverified integrations.
|
|
114
|
+
|
|
115
|
+
For code development only: `pnpm install`, then `pnpm verify` for offline tests
|
|
116
|
+
and TypeScript. `pnpm smoke` uses real providers and a paired owner; it verifies
|
|
117
|
+
outbound delivery, not the full incoming Telegram path. Never publish publicly
|
|
118
|
+
without authorization. Local registry rehearsal uses `pnpm publish:local`.
|
|
119
|
+
|
|
120
|
+
- [Setup and troubleshooting](docs/setup.md)
|
|
121
|
+
- [Architecture and run semantics](docs/architecture/telegram-intake.md)
|
|
122
|
+
- [Saved AI choices](docs/architecture/ai-selection.md)
|
|
123
|
+
- [Development and verification](docs/development-and-testing.md)
|
|
124
|
+
- [Authority boundaries](docs/architecture/authority-boundaries.md)
|
|
125
|
+
- [Security scope](SECURITY.md)
|
|
126
|
+
|
|
127
|
+
- [Contributing](CONTRIBUTING.md) and [releasing](docs/releasing.md)
|
|
128
|
+
- [First plugin and extension contract](docs/plugins.md)
|
|
129
|
+
- [License and dependency notices](THIRD_PARTY_NOTICES.md)
|
|
130
|
+
|
|
131
|
+
## Agent-owned upgrades
|
|
132
|
+
|
|
133
|
+
This beta includes owner-policy release checks and durable
|
|
134
|
+
main/plugin replacement. See [upgrade setup, tools and recovery](docs/upgrades.md). Earlier main upgrade/rollback VM QA passed; final-release fresh-host/reboot and live plugin upgrade acceptance remain pending.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Supported scope: the latest release, one paired Telegram owner per agent on a
|
|
4
|
+
trusted host. Unknown senders/groups cannot acquire execution authority.
|
|
5
|
+
The host CLI and plugin manager run with the host user's authority, including
|
|
6
|
+
Docker administration. Environment filtering and container profile separation
|
|
7
|
+
reduce accidental exposure; they do not isolate a hostile process from its own
|
|
8
|
+
host user. Markdown roles and approvals are instructions, not an OS sandbox.
|
|
9
|
+
Do not expose this as a public multi-tenant execution service.
|
|
10
|
+
|
|
11
|
+
Keep Telegram tokens, device profiles, QR images, control state and native CLI
|
|
12
|
+
sessions outside source and mind files. Treat incoming provider content as
|
|
13
|
+
untrusted data. Do not bypass owner checks or silently retry uncertain writes.
|
|
14
|
+
|
|
15
|
+
## Reporting
|
|
16
|
+
|
|
17
|
+
On the public GitHub repository use Security → Report a vulnerability (private
|
|
18
|
+
vulnerability reporting). Before publication the maintainer must enable and
|
|
19
|
+
verify that channel. If it is unavailable, open an issue asking only for a private
|
|
20
|
+
contact route; do not include exploit details or sensitive attachments publicly.
|
|
21
|
+
Include affected version, sanitized reproduction, impact and suggested fix.
|
|
22
|
+
There is no paid response SLA. Only the latest release receives fixes; report
|
|
23
|
+
older-version findings with a reproduction on the latest version when possible.
|
|
24
|
+
|
|
25
|
+
Current support target: the latest beta on a trusted single-user host. Report
|
|
26
|
+
privately at https://github.com/jdorado/ez-agents/security/advisories/new.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Third-party software
|
|
2
|
+
|
|
3
|
+
This repository's original source is MIT (LICENSE). Dependencies retain their
|
|
4
|
+
own copyright and licenses; our LICENSE does not relicense them. Preserve the
|
|
5
|
+
license files installed with every dependency and the frozen pnpm-lock.yaml.
|
|
6
|
+
Node/Debian container layers and optional external CLIs have separate terms.
|
|
7
|
+
The container is built locally; no bundled third-party binary image is promised.
|
|
8
|
+
|
|
9
|
+
Direct runtime dependencies: grammy (MIT), tsx (MIT). Development dependencies
|
|
10
|
+
include TypeScript (Apache-2.0) and Node type definitions (MIT). The runtime
|
|
11
|
+
image installs ffmpeg and Debian packages: redistributing that image requires
|
|
12
|
+
review of its exact package build, notices and corresponding-source obligations.
|
|
13
|
+
Docker and the selected host AI CLI are separately installed products, not covered
|
|
14
|
+
by this repository's MIT license.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
const child=spawn(process.execPath,['--import',fileURLToPath(new URL('../node_modules/tsx/dist/loader.mjs',import.meta.url)),fileURLToPath(new URL('../src/ai-cli.ts',import.meta.url)),...process.argv.slice(2)],{stdio:'inherit'})
|
|
5
|
+
child.on('exit',code=>{process.exitCode=code??1})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { dirname, join } from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const require = createRequire(import.meta.url)
|
|
9
|
+
const tsx = require.resolve('tsx')
|
|
10
|
+
const entry = join(here, '..', 'src', 'approval-cli.ts')
|
|
11
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
12
|
+
const child = spawn(process.execPath, ['--import', tsx, entry, ...forwarded], { stdio: 'inherit' })
|
|
13
|
+
child.on('exit', (code, signal) => {
|
|
14
|
+
if (signal) process.kill(process.pid, signal)
|
|
15
|
+
process.exit(code ?? 1)
|
|
16
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
umask 077
|
|
4
|
+
root=$(node -e 'const fs=require("node:fs"),path=require("node:path");process.stdout.write(path.dirname(path.dirname(fs.realpathSync(process.argv[1]))))' "$0")
|
|
5
|
+
: "${EZ_AGENTS_HOME:?Set EZ_AGENTS_HOME to the absolute private installation registry}"
|
|
6
|
+
case "$EZ_AGENTS_HOME" in /*) ;; *) echo 'EZ_AGENTS_HOME must be absolute' >&2; exit 1;; esac
|
|
7
|
+
mkdir -p "$EZ_AGENTS_HOME"
|
|
8
|
+
exec docker run --rm -i --user "$(id -u):$(id -g)" --cap-drop ALL --security-opt no-new-privileges \
|
|
9
|
+
--mount "type=bind,src=$EZ_AGENTS_HOME,dst=/installations" \
|
|
10
|
+
--entrypoint node "${EZ_RELAY_IMAGE:-ezenciel-agents:local}" \
|
|
11
|
+
--import /app/node_modules/tsx/dist/loader.mjs /app/src/agent-install.ts \
|
|
12
|
+
--host-root "$EZ_AGENTS_HOME" --compose-file "$root/compose.yaml" --relay-image "${EZ_RELAY_IMAGE:-ezenciel-agents:local}" "$@"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
root=$(node -e 'const fs=require("node:fs"),path=require("node:path");process.stdout.write(path.dirname(path.dirname(fs.realpathSync(process.argv[1]))))' "$0")
|
|
4
|
+
: "${EZ_DEPLOYMENT_DIR:?Set EZ_DEPLOYMENT_DIR to the absolute deployment directory containing docker.env}"
|
|
5
|
+
case "$EZ_DEPLOYMENT_DIR" in /*) ;; *) echo 'EZ_DEPLOYMENT_DIR must be absolute' >&2; exit 1;; esac
|
|
6
|
+
exec docker compose --project-directory "$root" --env-file "$EZ_DEPLOYMENT_DIR/docker.env" "$@"
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
root=$(node -e 'const fs=require("node:fs"),path=require("node:path");process.stdout.write(path.dirname(path.dirname(fs.realpathSync(process.argv[1]))))' "$0")
|
|
4
|
+
: "${EZ_DEPLOYMENT_DIR:?Set EZ_DEPLOYMENT_DIR to this agent deployment}"
|
|
5
|
+
exec node "$root/src/updates/launch.mjs" "$EZ_DEPLOYMENT_DIR"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { dirname, join } from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const require = createRequire(import.meta.url)
|
|
9
|
+
const tsx = require.resolve('tsx')
|
|
10
|
+
const entry = join(here, '..', 'src', 'message.ts')
|
|
11
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
12
|
+
const child = spawn(process.execPath, ['--import', tsx, entry, ...forwarded], { stdio: 'inherit' })
|
|
13
|
+
child.on('exit', (code, signal) => {
|
|
14
|
+
if (signal) process.kill(process.pid, signal)
|
|
15
|
+
process.exit(code ?? 1)
|
|
16
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { dirname, join } from 'node:path'
|
|
6
|
+
import { fileURLToPath } from 'node:url'
|
|
7
|
+
|
|
8
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const require = createRequire(import.meta.url)
|
|
10
|
+
const tsx = require.resolve('tsx')
|
|
11
|
+
const entry = join(here, '..', 'src', 'owner.ts')
|
|
12
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
13
|
+
const args = existsSync('.env') ? ['--env-file=.env', entry] : [entry]
|
|
14
|
+
const child = spawn(process.execPath, ['--import', tsx, ...args, ...forwarded], { stdio: 'inherit' })
|
|
15
|
+
child.on('exit', (code, signal) => {
|
|
16
|
+
if (signal) process.kill(process.pid, signal)
|
|
17
|
+
process.exit(code ?? 1)
|
|
18
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { dirname, join } from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const require = createRequire(import.meta.url)
|
|
9
|
+
const tsx = require.resolve('tsx')
|
|
10
|
+
const entry = join(here, '..', 'src', 'react.ts')
|
|
11
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
12
|
+
const child = spawn(process.execPath, ['--import', tsx, entry, ...forwarded], { stdio: 'inherit' })
|
|
13
|
+
child.on('exit', (code, signal) => {
|
|
14
|
+
if (signal) process.kill(process.pid, signal)
|
|
15
|
+
process.exit(code ?? 1)
|
|
16
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { dirname, join } from 'node:path'
|
|
6
|
+
import { fileURLToPath } from 'node:url'
|
|
7
|
+
|
|
8
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const require = createRequire(import.meta.url)
|
|
10
|
+
const tsx = require.resolve('tsx')
|
|
11
|
+
const entry = join(here, '..', 'src', 'setup.ts')
|
|
12
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
13
|
+
const args = existsSync('.env') ? ['--env-file=.env', entry] : [entry]
|
|
14
|
+
const child = spawn(process.execPath, ['--import', tsx, ...args, ...forwarded], { stdio: 'inherit' })
|
|
15
|
+
child.on('exit', (code, signal) => {
|
|
16
|
+
if (signal) process.kill(process.pid, signal)
|
|
17
|
+
process.exit(code ?? 1)
|
|
18
|
+
})
|