@jc_stack/ez-agents 0.1.0-beta.12 → 0.1.0-beta.18
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 +4 -0
- package/.env.example +16 -1
- package/AGENTS.md +16 -4
- package/CHANGELOG.md +71 -0
- package/CONTRIBUTING.md +37 -4
- package/README.md +114 -9
- package/SECURITY.md +7 -1
- package/bin/ezenciel-agents-schedule +2 -0
- package/bin/ezenciel-agents-schedule.mjs +16 -0
- package/bin/ezenciel-agents-task +2 -0
- package/bin/ezenciel-agents-task.mjs +16 -0
- package/compose.yaml +10 -2
- package/docker/recovery.ts +2 -2
- package/docker/run.ts +2 -2
- package/docs/architecture/ai-selection.md +8 -0
- package/docs/architecture/authority-boundaries.md +137 -12
- package/docs/architecture/event-sources.md +12 -7
- package/docs/architecture/telegram-intake.md +1 -1
- package/docs/channel-backend.md +36 -0
- package/docs/docker-runtime.md +35 -0
- package/docs/host-service.md +19 -0
- package/docs/local-qa.md +45 -0
- package/docs/pagerduty.md +42 -0
- package/docs/plugin-catalog.md +71 -0
- package/docs/plugin-contributions.md +12 -0
- package/docs/plugins.md +61 -1
- package/docs/releasing.md +20 -9
- package/docs/repair.md +41 -0
- package/docs/scheduling.md +153 -0
- package/docs/selective-monitoring.md +114 -0
- package/docs/setup.md +46 -0
- package/docs/standalone-cli.md +62 -0
- package/docs/trusted-publishing.md +140 -0
- package/docs/upgrades.md +24 -4
- package/package.json +12 -4
- package/scripts/generate-publish-caller.mjs +60 -0
- package/scripts/smoke-busy-reply.ts +58 -0
- package/scripts/smoke-scheduler.ts +90 -0
- package/scripts/stage-qa.mjs +42 -0
- package/scripts/trusted-beta.mjs +289 -0
- package/src/agent-guidance.ts +5 -0
- package/src/ai-cli.ts +2 -1
- package/src/ai.ts +15 -5
- package/src/channel-backend.ts +46 -0
- package/src/client-defaults.ts +29 -13
- package/src/codex-session.ts +98 -0
- package/src/config.ts +35 -2
- package/src/control-state.ts +24 -7
- package/src/desktop-bridge.ts +37 -12
- package/src/event-sources.ts +2 -1
- package/src/execution-authority.ts +25 -0
- package/src/executor.ts +97 -21
- package/src/failure.ts +32 -0
- package/src/host-executor.ts +48 -19
- package/src/identity.ts +8 -3
- package/src/inbox.ts +11 -3
- package/src/index.ts +315 -91
- package/src/install-tools.mjs +2 -2
- package/src/menu.ts +6 -4
- package/src/model-policy.ts +15 -0
- package/src/owner.ts +3 -3
- package/src/pagerduty.ts +109 -0
- package/src/plugins/exposure.mjs +13 -0
- package/src/plugins/manager.mjs +74 -20
- package/src/plugins/shared.mjs +76 -0
- package/src/process-tree.ts +33 -0
- package/src/repair-policy.ts +13 -0
- package/src/reply-context.ts +67 -0
- package/src/reply-executor.ts +54 -0
- package/src/reply-mcp.ts +23 -0
- package/src/runs.ts +63 -19
- package/src/schedule-cli.ts +98 -0
- package/src/schedule-time.ts +85 -0
- package/src/scheduler.ts +130 -0
- package/src/setup.ts +2 -1
- package/src/software-status.ts +5 -5
- package/src/source-cli.ts +1 -1
- package/src/task-cli.ts +16 -0
- package/src/task-executor.ts +65 -0
- package/src/task-mcp.ts +36 -0
- package/src/task-rpc.ts +45 -0
- package/src/task-workspace.ts +22 -0
- package/src/tasks.ts +210 -0
- package/src/telegram-source.ts +94 -0
- package/src/updates/artifact.mjs +16 -0
- package/src/updates/binding.mjs +4 -1
- package/src/updates/control.mjs +4 -4
- package/src/updates/runtime.mjs +3 -1
- package/src/updates/status.mjs +7 -1
- package/templates/agent/AGENTS.md +10 -2
- package/templates/agent/TOOLS.md +60 -1
- package/templates/agent-guidance.md +13 -0
- package/templates/failure-review.md +9 -0
- package/templates/maintainer-purpose.md +15 -0
- package/templates/standalone-tools.md +20 -0
- package/templates/updates.md +2 -2
- package/test/agent-guidance.test.ts +110 -0
- package/test/ai-cli.test.ts +7 -6
- package/test/ai.test.ts +41 -0
- package/test/busy-reply-relay.test.ts +41 -0
- package/test/channel-backend.test.ts +100 -0
- package/test/client-defaults.test.ts +37 -5
- package/test/codex-context.test.ts +39 -1
- package/test/codex-session.test.ts +51 -0
- package/test/config.test.ts +31 -2
- package/test/desktop-bridge.test.ts +19 -0
- package/test/event-sources.test.ts +47 -11
- package/test/execution-authority.test.ts +42 -0
- package/test/executor.test.ts +53 -2
- package/test/failure.test.ts +250 -0
- package/test/group-owner.test.ts +36 -0
- package/test/helpers/owner-run.ts +13 -0
- package/test/host-executor.test.ts +47 -10
- package/test/intake-relay.test.ts +141 -4
- package/test/local-qa.test.mjs +38 -0
- package/test/model-policy.test.ts +61 -0
- package/test/pagerduty.test.ts +104 -0
- package/test/plugin-manager.test.mjs +73 -3
- package/test/relay.test.ts +2 -2
- package/test/repair-policy.test.ts +23 -0
- package/test/reply.test.ts +131 -0
- package/test/schedule-cli.test.ts +55 -0
- package/test/scheduler-host.test.ts +55 -0
- package/test/scheduler-relay.test.ts +67 -0
- package/test/scheduler.test.ts +104 -0
- package/test/shared-services.test.mjs +98 -0
- package/test/software-status.test.ts +5 -5
- package/test/task-native.test.ts +87 -0
- package/test/tasks.test.ts +187 -0
- package/test/telegram-source.test.ts +75 -0
- package/test/trusted-beta.test.mjs +224 -0
- package/test/updates.test.mjs +35 -3
package/.dockerignore
CHANGED
package/.env.example
CHANGED
|
@@ -11,7 +11,7 @@ EZ_AGENT_WORKSPACE=./agent
|
|
|
11
11
|
# EZ_PAIRING_TTL_SECONDS=900
|
|
12
12
|
|
|
13
13
|
# Optional. Default is 300.
|
|
14
|
-
#
|
|
14
|
+
# Agent execution has no wall-clock timeout. Use /stop or schedule cancel.
|
|
15
15
|
|
|
16
16
|
# CLI Executor adapter. Supported: agy (default), claude, grok, opencode
|
|
17
17
|
# Switch easily with: pnpm run setup <executor-name>
|
|
@@ -24,3 +24,18 @@ EZ_EXECUTOR_CLI=agy
|
|
|
24
24
|
# Optional: OpenRouter API key for OpenCode CLI (Nemotron 3.5 Lightning)
|
|
25
25
|
# OPENROUTER_API_KEY=
|
|
26
26
|
# OPENCODE_MODEL=openrouter/nvidia/nemotron-3.5-lightning
|
|
27
|
+
|
|
28
|
+
# Interactive Codex CLI context limit; native compaction preserves the session.
|
|
29
|
+
EZ_CODEX_AUTO_COMPACT_TOKENS=64000
|
|
30
|
+
|
|
31
|
+
# Automatic core/plugin repair mandate. Set in deployment docker.env for Compose.
|
|
32
|
+
# Does not grant GitHub access, merge or publication permissions.
|
|
33
|
+
EZ_REPAIR_ENABLED=true
|
|
34
|
+
|
|
35
|
+
# Optional PagerDuty incident paging for critical Stocks outages. Put the routing
|
|
36
|
+
# key only in the private relay.env file when running Docker; place the other
|
|
37
|
+
# settings in docker.env so Compose passes them to the relay.
|
|
38
|
+
# PAGERDUTY_ROUTING_KEY=
|
|
39
|
+
# EZ_PAGERDUTY_STOCKS_HEALTH_URL=http://10.97.0.1:3006/health/critical
|
|
40
|
+
# EZ_PAGERDUTY_POLL_SECONDS=30
|
|
41
|
+
# EZ_PAGERDUTY_FAILURE_THRESHOLD=3
|
package/AGENTS.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# ezenciel-agents — Coding Standards & Architectural Invariants
|
|
2
2
|
|
|
3
|
+
Ez supports two independent, composable uses: an autonomous Telegram agent and
|
|
4
|
+
workspace-scoped plugins called by your existing local CLI/GUI executor.
|
|
5
|
+
For CLI-only requests, follow [standalone setup](docs/standalone-cli.md): no Telegram
|
|
6
|
+
pairing, relay or host executor is required. The main-first Telegram onboarding
|
|
7
|
+
rules below apply only when installing the autonomous relay. When both are
|
|
8
|
+
requested, keep each workspace's authority and registry explicit.
|
|
9
|
+
|
|
3
10
|
Installed runtime operation uses Docker Compose. Read
|
|
4
11
|
[Docker setup, state and QA](docs/docker-runtime.md). Docker owns relay/plugin services; the existing host CLI and login are shared
|
|
5
12
|
through one generic transport, with separate agent workspaces and sessions.
|
|
@@ -56,17 +63,17 @@ This package will be published as an open-source, lightweight Telegram-to-CLI re
|
|
|
56
63
|
|
|
57
64
|
## 6. Concurrency & Workspace Invariants
|
|
58
65
|
- **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
|
-
-
|
|
66
|
+
- Main-conversation jobs queue sequentially in `RunStore`. Scheduled/background work uses separate task directories and native CLI sessions (up to four alongside chat). Never share a mutable task directory. Delegation decisions and goal persistence belong to the agent/executor; there is no automatic planner or canned chat ACK. Production executor runs have no wall-clock timeout; cancellation is explicit.
|
|
60
67
|
|
|
61
68
|
## 7. Fail-Closed Authority (Channel Access ≠ Execution)
|
|
62
|
-
- Incoming messages
|
|
63
|
-
-
|
|
69
|
+
- Incoming messages outside the approved owner binding must **never** spawn the executor. A first DM or group message records a pending request only. Explicitly approved owner groups grant owner access to all human members in that exact chat; bots and anonymous posts are ignored.
|
|
70
|
+
- Unapproved group messages from other senders and unknown DMs fail silently. Approved group text uses the existing conversation grant and restricted task runner. Paired-owner group text is discovery routed to the owner's private chat; it grants no group reply authority.
|
|
64
71
|
- Stopping work (`/stop`) must terminate the active worker PID immediately (`SIGTERM`, escalating to `SIGKILL` if unclosed after 3s).
|
|
65
72
|
|
|
66
73
|
## 8. Mandatory Adversarial & Negative Tests
|
|
67
74
|
Every pull request modifying authority, execution, or routing must include negative tests:
|
|
68
75
|
1. Unapproved Telegram ID $\rightarrow$ no process spawned.
|
|
69
|
-
2.
|
|
76
|
+
2. Non-owner group message $\rightarrow$ silent ignore; owner group discovery $\rightarrow$ private destination only.
|
|
70
77
|
3. Executor environment check $\rightarrow$ asserts `TELEGRAM_BOT_TOKEN` is `undefined`.
|
|
71
78
|
4. Corrupt JSON in store $\rightarrow$ handled gracefully without process crash.
|
|
72
79
|
5. Injected path traversal in IDs $\rightarrow$ rejected.
|
|
@@ -82,3 +89,8 @@ worktree/branch/PR, starting from fetched origin/main. Do not switch or mix work
|
|
|
82
89
|
another task's checkout. Stage only this task's changes. Keep its worktree through
|
|
83
90
|
review and QA; independent review and green CI precede an authorized merge.
|
|
84
91
|
Never treat task completion as permission to merge or publish.
|
|
92
|
+
Own the complete engineering/release handoff in CONTRIBUTING.md. Once ready,
|
|
93
|
+
proactively request only missing merge/release authority, then ship and verify;
|
|
94
|
+
do not leave the maintainer to discover ready drafts or operate the release.
|
|
95
|
+
|
|
96
|
+
- In channel-backend mode, the application owns native sessions and actions. Forward normalized inputs with stable run IDs, recover only by idempotent backend submission, and deliver replies through the existing outbox. Never launch a fallback CLI or pass relay credentials into an executor.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.18
|
|
4
|
+
|
|
5
|
+
- Await complete relay cleanup after fatal Telegram polling errors and preserve the primary failure.
|
|
6
|
+
- Refresh package-owned shared guidance in owner worker prompts, including resumed and scheduled work, while preserving personal workspace instructions and restricted worker boundaries.
|
|
7
|
+
- Include the reviewed beta.17 fixes. Earlier immutable unpublished candidates and existing beta acceptance limits remain.
|
|
8
|
+
|
|
9
|
+
## 0.1.0-beta.17
|
|
10
|
+
|
|
11
|
+
- Capture executor stderr before asynchronous PID persistence so fast failures retain actionable, redacted diagnostic evidence for agent-owned recovery.
|
|
12
|
+
- Wait for executor cleanup and final run-state writes when stopping the relay, so shutdown does not return while its state is still being written.
|
|
13
|
+
- Include the reviewed beta.16 runtime and catalog corrections. Earlier unpublished candidates remain preserved; existing beta acceptance limits remain.
|
|
14
|
+
|
|
15
|
+
## 0.1.0-beta.16
|
|
16
|
+
|
|
17
|
+
- Correct stale plugin-publication claims and link the catalog to live npm/GitHub release records. Agents must verify available versions instead of treating a dated catalog snapshot as a blocker.
|
|
18
|
+
- Include the reviewed beta.15 runtime unchanged. Preserve earlier unpublished candidates and existing beta acceptance limits.
|
|
19
|
+
|
|
20
|
+
## 0.1.0-beta.15
|
|
21
|
+
|
|
22
|
+
- Include current reviewed model defaults, reply/status fixes, shared Library services and CPU limits, and the corrected main-CI publisher validation.
|
|
23
|
+
- Testing beta; previously documented live-provider and fresh-host acceptance limits remain.
|
|
24
|
+
|
|
25
|
+
## 0.1.0-beta.14
|
|
26
|
+
|
|
27
|
+
- Preserve agent-specific scheduled authentication and model catalogs; show native
|
|
28
|
+
Codex defaults in status, and support explicitly approved group ownership.
|
|
29
|
+
- Keep owner chat responsive during shared work with restricted reply sessions.
|
|
30
|
+
Capture redacted failure evidence and support quiet, owner-scoped reviews.
|
|
31
|
+
- Add opt-in shared Docker plugin workers and agent-owned repair instructions.
|
|
32
|
+
- Add optional PagerDuty Stocks monitoring with restart-safe recovery. Activation
|
|
33
|
+
requires the companion Stocks critical-health endpoint and private routing-key
|
|
34
|
+
configuration; real trigger/resolve delivery is not yet verified.
|
|
35
|
+
- Publish verified beta artifacts through the shared trusted-publisher workflow.
|
|
36
|
+
|
|
37
|
+
- Add explicit host-owned shared-workspace access and serialize bindings to the
|
|
38
|
+
same resolved repository path while retaining isolated task transcripts.
|
|
39
|
+
- Bound interactive Codex context through native compaction and expose
|
|
40
|
+
content-free launch, execution and delivery timings.
|
|
41
|
+
- Support owner-approved Telegram text groups and ongoing incoming-only grants
|
|
42
|
+
through restricted task execution; retain exact conversation/account authority.
|
|
43
|
+
- Preserve revocation recovery and uncertain-send receipts. Ongoing WhatsApp
|
|
44
|
+
grants require the companion WhatsApp beta.13 provider.
|
|
45
|
+
- Fix graceful container shutdown, isolate CI package sources and await RPC
|
|
46
|
+
fixture cleanup. Make verified release handoff proactive and agent-owned.
|
|
47
|
+
- Beta limits: no group media; live group-recipient and final fresh-host/reboot
|
|
48
|
+
acceptance remain pending. No new live-delivery or latency claims.
|
|
49
|
+
- Default core and plugin automatic updates to the beta channel; preserve saved
|
|
50
|
+
stable-only and manual policies.
|
|
51
|
+
|
|
52
|
+
## 0.1.0-beta.13
|
|
53
|
+
|
|
54
|
+
- Escalate cancelled plugin clients and report container cleanup failures.
|
|
55
|
+
- List the GitHub CLI plugin in the public catalog.
|
|
56
|
+
- Include standalone CLI, native task runtime and integration discovery updates.
|
|
57
|
+
|
|
58
|
+
- Support incoming-only reply tasks without an opening message; refresh installed
|
|
59
|
+
guidance for selective setup, implicit follow-up, and quiet account linking.
|
|
60
|
+
|
|
61
|
+
- Add owner-approved, single-contact messaging tasks, core-bound sends and notes,
|
|
62
|
+
fresh restricted Codex execution, revocation/expiry, and durable uncertain sends.
|
|
63
|
+
- Task execution requires audited Codex 0.153.4 and a message-v1 event source.
|
|
64
|
+
Other external events remain blocked; live provider acceptance is pending.
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
- Add optional per-command exposure declarations and `ez tools exposure` with
|
|
68
|
+
conservative defaults. Declarations do not grant authority.
|
|
69
|
+
- Block registered external events before owner-runtime execution; keep durable
|
|
70
|
+
blocked records visible in work status. This disables prior external wakeups
|
|
71
|
+
until an isolated runner exists. Recheck active paired-owner provenance at
|
|
72
|
+
the local and host launch boundaries.
|
|
73
|
+
|
|
3
74
|
## 0.1.0-beta.12 — self-upgrade beta
|
|
4
75
|
|
|
5
76
|
- Agent-owned main/plugin upgrades with stable-default policy, queued maintenance,
|
package/CONTRIBUTING.md
CHANGED
|
@@ -13,11 +13,15 @@ repository. Public docs describe shipped behavior and explicit limitations.
|
|
|
13
13
|
Packaging/runtime changes also need the Docker checks in docs/releasing.md.
|
|
14
14
|
5. Open a PR explaining the problem, resulting behavior, verification and limits.
|
|
15
15
|
Include a short sanitized reproduction. State which tests were not run.
|
|
16
|
-
6.
|
|
17
|
-
|
|
16
|
+
6. Obtain independent review and required CI, then complete the
|
|
17
|
+
maintainer-authorized merge. Maintainers use PRs too. No CLA, ticket
|
|
18
|
+
requirement, custom commit format or additional approval committee.
|
|
18
19
|
|
|
19
20
|
You are responsible for understanding submitted code, including AI-generated
|
|
20
21
|
code, and having the right to contribute it under this repository's license.
|
|
22
|
+
For unreleased feature testing, follow [local QA](docs/local-qa.md): stage an
|
|
23
|
+
immutable beta candidate and provide a simple PA upgrade instruction and feature
|
|
24
|
+
QA flow. A public release is not required for this handoff.
|
|
21
25
|
Do not upload conversation dumps, credentials, QR codes or customer records.
|
|
22
26
|
Installation authority alone does not authorize messaging another person.
|
|
23
27
|
Use synthetic providers for routine tests; live tests need a dedicated account
|
|
@@ -45,8 +49,8 @@ docs/plugin-contributions.md.
|
|
|
45
49
|
Branch from an unmerged feature only when the dependency is intentional and
|
|
46
50
|
documented; do not quietly include it in an unrelated PR.
|
|
47
51
|
- Open a draft PR when the change is reviewable. Report its scope, exact commit,
|
|
48
|
-
validation and remaining QA.
|
|
49
|
-
implementation completion does not authorize
|
|
52
|
+
validation and remaining QA. Continue through the release handoff below;
|
|
53
|
+
implementation completion alone does not authorize publication.
|
|
50
54
|
- Before merge, obtain an independent human or agent review of the final diff.
|
|
51
55
|
The implementer's self-check and passing CI are not independent review.
|
|
52
56
|
Reviewers inspect correctness, architecture, state/permissions and negative
|
|
@@ -63,6 +67,31 @@ docs/plugin-contributions.md.
|
|
|
63
67
|
the clean task worktree after valuable work is preserved; never force cleanup.
|
|
64
68
|
Delete its branch only after confirming merge or authorized abandonment.
|
|
65
69
|
|
|
70
|
+
## Agent-owned release handoff
|
|
71
|
+
|
|
72
|
+
The agent owns the engineering work through shipping: implement, run proportional
|
|
73
|
+
checks, obtain independent review, repair findings, verify the packed artifact,
|
|
74
|
+
and prepare the release. Reuse valid final-commit evidence; repeat checks when
|
|
75
|
+
changes or failures invalidate it. Do not leave a ready feature silently in draft
|
|
76
|
+
or ask the maintainer to run commands, coordinate reviewers, or operate CI.
|
|
77
|
+
|
|
78
|
+
The maintainer's request is authorization for the requested work and its normal
|
|
79
|
+
implementation steps. Do not ask them to approve the same work again. Once the
|
|
80
|
+
applicable gates pass, execute the requested merge/release and report the packages,
|
|
81
|
+
versions, channel, verification and material limits. Batch related packages in
|
|
82
|
+
dependency order. Prepare the reviewed commits, artifacts and checksums before
|
|
83
|
+
shipping. A request to merge does not silently expand to publication or changing
|
|
84
|
+
a private package's visibility; a request to release already authorizes release.
|
|
85
|
+
If shipping was not requested, report readiness and the next step without treating
|
|
86
|
+
every completed feature as permission to publish.
|
|
87
|
+
|
|
88
|
+
Complete the authorized merge, publication and rollout using
|
|
89
|
+
docs/releasing.md, then verify registry metadata, downloaded artifact and the
|
|
90
|
+
installed runtime. Report the outcome. Escalate only a product decision, missing
|
|
91
|
+
credential/2FA, failed gate that cannot be repaired in scope, or material scope
|
|
92
|
+
change. Human attention belongs on product intent;
|
|
93
|
+
the agent operates the technical workflow.
|
|
94
|
+
|
|
66
95
|
Example, substituting a unique task name and an absolute external directory:
|
|
67
96
|
|
|
68
97
|
```sh
|
|
@@ -71,3 +100,7 @@ git worktree list
|
|
|
71
100
|
git fetch origin
|
|
72
101
|
git worktree add -b feat/task-name /absolute/worktrees/task-name origin/main
|
|
73
102
|
```
|
|
103
|
+
|
|
104
|
+
Beta publishing workflow changes follow [trusted publishing](docs/trusted-publishing.md).
|
|
105
|
+
Validate wrong source, repository, package, version and artifact inputs with
|
|
106
|
+
negative tests. Never dispatch publication to test authentication.
|
package/README.md
CHANGED
|
@@ -1,12 +1,104 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ez — AI assistants for small businesses
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
**A lightweight, open-source foundation for persistent AI assistants, powered by
|
|
4
|
+
existing AI harnesses.** Give an assistant a purpose, a workspace and tools for
|
|
5
|
+
your business, then work with it through chat.
|
|
6
|
+
|
|
7
|
+
Ez is for owners of shops, studios and small teams who want help doing everyday
|
|
8
|
+
work: preparing quotes, maintaining business records, researching decisions or
|
|
9
|
+
following up on an agreed task. Each assistant has its own working context and
|
|
10
|
+
responsibilities. The tools and permissions you configure determine what it can
|
|
11
|
+
do.
|
|
12
|
+
|
|
13
|
+
An AI harness is the client that lets a model reason, use tools and carry out
|
|
14
|
+
work. Ez uses your chosen host CLI and its existing login. The harness does the
|
|
15
|
+
reasoning; Ez connects it to a persistent workspace, messaging, plugins and
|
|
16
|
+
explicit authority boundaries. Telegram is the current owner interface.
|
|
17
|
+
|
|
18
|
+
## What makes an Ez assistant
|
|
19
|
+
|
|
20
|
+
| Part | What it contributes |
|
|
21
|
+
|---|---|
|
|
22
|
+
| **Workspace** | Markdown instructions, business context and working files that persist across conversations and changes of AI. |
|
|
23
|
+
| **Harness** | The existing AI client that plans, chooses tools and executes work. See [AI selection](docs/architecture/ai-selection.md). |
|
|
24
|
+
| **Authority** | A verified owner and explicit limits on delegated work. Receiving a message or installing a tool does not grant permission to act. |
|
|
25
|
+
| **Plugins** | Separately maintained tools and connections, with instructions the agent can discover and use. Provider authentication and receipts belong to the plugin. |
|
|
26
|
+
| **Messaging and continuity** | A way to reach the assistant, return results and continue work in its own environment. |
|
|
27
|
+
|
|
28
|
+
The design starts with one assistant, one mind and clear responsibilities.
|
|
29
|
+
Business instructions live in the workspace; reusable capabilities live in tools
|
|
30
|
+
and plugins. The agent decides how to do the work using those instructions and
|
|
31
|
+
the capabilities available to it.
|
|
32
|
+
|
|
33
|
+
Use the harness's native capabilities when they meet the need. Add a standalone
|
|
34
|
+
plugin when a missing integration earns the maintenance. Ez keeps the surrounding
|
|
35
|
+
runtime small, so your files, tools and business knowledge remain useful as AI
|
|
36
|
+
clients improve.
|
|
37
|
+
|
|
38
|
+
## Plugin catalog
|
|
39
|
+
|
|
40
|
+
Browse the [available plugins](docs/plugin-catalog.md) for capabilities you can
|
|
41
|
+
add to your assistant. The first released plugin is
|
|
42
|
+
[WhatsApp](https://github.com/jdorado/ez-whatsapp), which connects an existing
|
|
43
|
+
WhatsApp account. Ask your working Ez assistant to set it up in Telegram.
|
|
44
|
+
|
|
45
|
+
## Start with one useful job
|
|
46
|
+
|
|
47
|
+
Ez supports two independent, composable uses: an autonomous Telegram agent and
|
|
48
|
+
workspace-scoped plugins called by your existing local CLI/GUI executor.
|
|
49
|
+
For CLI-only requests, follow [standalone setup](docs/standalone-cli.md): no Telegram
|
|
50
|
+
pairing, relay or host executor is required. The main-first Telegram onboarding
|
|
51
|
+
rules below apply only when installing the autonomous relay. When both are
|
|
52
|
+
requested, keep each workspace's authority and registry explicit.
|
|
53
|
+
|
|
54
|
+
Ask an AI agent with computer access to install Ez for a concrete purpose:
|
|
55
|
+
|
|
56
|
+
> Install Ez from https://github.com/jdorado/ez-agents for my business.
|
|
57
|
+
> I want an assistant that helps me prepare customer quotes from my own files.
|
|
58
|
+
> Set it up and verify that I can talk to it in Telegram.
|
|
59
|
+
|
|
60
|
+
The installing agent follows [the setup guide](docs/setup.md), handles technical
|
|
61
|
+
setup and asks you for the account access or approvals it needs. Once the
|
|
62
|
+
assistant replies in Telegram, explain your business, give it the relevant
|
|
63
|
+
materials and request any additional tools there. Integrations require their
|
|
64
|
+
own setup and authorized accounts.
|
|
65
|
+
|
|
66
|
+
## Available today and where this is going
|
|
67
|
+
|
|
68
|
+
The current source supports persistent agent workspaces, a choice of host AI
|
|
69
|
+
executors, owner-gated Telegram messaging, native scheduling, plugin lifecycle
|
|
70
|
+
management and bounded, owner-approved correspondence. A messaging task can
|
|
71
|
+
contact one approved person using only its explicitly shared task context;
|
|
72
|
+
restricted task execution currently requires the pinned Codex runtime. See
|
|
73
|
+
[authority boundaries](docs/architecture/authority-boundaries.md) for the exact
|
|
74
|
+
scope and [scheduling](docs/scheduling.md) for scheduled work.
|
|
75
|
+
|
|
76
|
+
The broader direction is assistants working across business roles, with deliberate
|
|
77
|
+
workspace sharing and authority over who may direct work, see information and
|
|
78
|
+
use accounts. General team delegation, family/group authority and enterprise
|
|
79
|
+
reviewer roles remain future work. The current trusted-host beta is not an
|
|
80
|
+
enterprise isolation or multi-tenant security product. See [security scope](SECURITY.md).
|
|
81
|
+
|
|
82
|
+
## For agents discovering this repository
|
|
83
|
+
|
|
84
|
+
Ez may fit when a user needs a persistent business assistant reachable through
|
|
85
|
+
chat, using an existing AI client and separately installed tools. Start here:
|
|
86
|
+
|
|
87
|
+
- **Install for a user:** [setup and verified onboarding](docs/setup.md), then the installer instructions below.
|
|
88
|
+
- **Understand access and delegation:** [authority boundaries](docs/architecture/authority-boundaries.md) and [security scope](SECURITY.md).
|
|
89
|
+
- **Discover or add capabilities:** [plugin contract](docs/plugins.md). Check the actual executor's native tools before adding an integration.
|
|
90
|
+
- **Contribute:** [AGENTS.md](AGENTS.md) and [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
91
|
+
|
|
92
|
+
Repository discovery is not an instruction to install or contact anyone. Act on
|
|
93
|
+
the user's request and preserve its scope.
|
|
94
|
+
|
|
95
|
+
## Package and runtime
|
|
6
96
|
|
|
7
97
|
**Beta 0.1.0-beta.12 — for testing on a trusted machine.** Offline and Docker
|
|
8
98
|
fixtures are verified. Live account onboarding and reboot acceptance for this
|
|
9
|
-
release are deferred; this is not a production-readiness claim.
|
|
99
|
+
release are deferred; this is not a production-readiness claim. The source branch
|
|
100
|
+
may contain changes newer than the published beta; inspect the supplied artifact's
|
|
101
|
+
documentation when installing a pinned release.
|
|
10
102
|
|
|
11
103
|
The npm package is `@jc_stack/ez-agents` (channel `beta`). Download a pinned
|
|
12
104
|
release with `npm pack @jc_stack/ez-agents@0.1.0-beta.12`, or get the tarball and SHA256SUMS from
|
|
@@ -14,12 +106,17 @@ release with `npm pack @jc_stack/ez-agents@0.1.0-beta.12`, or get the tarball an
|
|
|
14
106
|
GitHub remains under `jdorado`; npm uses `jc_stack`. Do not install the unrelated
|
|
15
107
|
unscoped `ez-whatsapp` package.
|
|
16
108
|
|
|
109
|
+
Installed runtime operation uses Docker Compose. Docker owns relay/plugin
|
|
110
|
+
services; the existing host CLI and login are shared through one generic
|
|
111
|
+
transport, with separate agent workspaces and sessions. See
|
|
112
|
+
[Docker setup, state and QA](docs/docker-runtime.md).
|
|
17
113
|
|
|
18
|
-
|
|
19
|
-
[
|
|
20
|
-
through one generic transport, with separate agent workspaces and sessions.
|
|
114
|
+
For optional PagerDuty paging of a critical Stocks outage, see
|
|
115
|
+
[PagerDuty critical-outage paging](docs/pagerduty.md).
|
|
21
116
|
|
|
22
|
-
|
|
117
|
+
Telegram `/status` shows the running relay and host versions plus installed
|
|
118
|
+
plugin versions. The agent's `ez status` adds verified plugin runtime states and
|
|
119
|
+
upgrade job receipts. See [status and upgrades](docs/upgrades.md).
|
|
23
120
|
|
|
24
121
|
## You are the installing agent
|
|
25
122
|
|
|
@@ -132,3 +229,11 @@ without authorization. Local registry rehearsal uses `pnpm publish:local`.
|
|
|
132
229
|
|
|
133
230
|
This beta includes owner-policy release checks and durable
|
|
134
231
|
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.
|
|
232
|
+
|
|
233
|
+
### Scheduling and background work
|
|
234
|
+
|
|
235
|
+
The core `ezenciel-agents-schedule` CLI accepts instruction text for one-off dates,
|
|
236
|
+
intervals and timezone-aware cron schedules. `create --now` delegates a task to a
|
|
237
|
+
separate CLI session so the owner conversation remains available. Long work has
|
|
238
|
+
no production wall-clock timeout; goals and subagents remain native executor
|
|
239
|
+
features. See [scheduling, recovery and QA](docs/scheduling.md).
|
package/SECURITY.md
CHANGED
|
@@ -6,7 +6,13 @@ The host CLI and plugin manager run with the host user's authority, including
|
|
|
6
6
|
Docker administration. Environment filtering and container profile separation
|
|
7
7
|
reduce accidental exposure; they do not isolate a hostile process from its own
|
|
8
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.
|
|
9
|
+
Do not expose this as a public multi-tenant execution service. Registered external
|
|
10
|
+
events require an approved, account/contact-bound task and the restricted native
|
|
11
|
+
runner; unmatched events remain blocked. The task worker has only core message,
|
|
12
|
+
note and report tools. It has no owner workspace, shell or general network tool.
|
|
13
|
+
The native client, broker and local host user remain trusted. See
|
|
14
|
+
[authority boundaries](docs/architecture/authority-boundaries.md). Plugin exposure
|
|
15
|
+
declarations are metadata, not grants.
|
|
10
16
|
|
|
11
17
|
Keep Telegram tokens, device profiles, QR images, control state and native CLI
|
|
12
18
|
sessions outside source and mind files. Treat incoming provider content as
|
|
@@ -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', 'schedule-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,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', 'task-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
|
+
})
|
package/compose.yaml
CHANGED
|
@@ -8,14 +8,22 @@ services:
|
|
|
8
8
|
restart: unless-stopped
|
|
9
9
|
stop_grace_period: 30s
|
|
10
10
|
cap_drop: [ALL]
|
|
11
|
-
|
|
11
|
+
# Init must forward shutdown to the privilege-dropped relay. The entrypoint
|
|
12
|
+
# still removes every capability from the relay and its executor children.
|
|
13
|
+
cap_add: [CHOWN, DAC_OVERRIDE, FOWNER, SETUID, SETGID, SETPCAP, KILL]
|
|
12
14
|
environment:
|
|
15
|
+
EZ_REPAIR_ENABLED: ${EZ_REPAIR_ENABLED:-true}
|
|
13
16
|
EZ_AGENT_PURPOSE_FILE: /run/agent-purpose.md
|
|
14
|
-
EZ_EXECUTOR_TRANSPORT: host
|
|
17
|
+
EZ_EXECUTOR_TRANSPORT: ${EZ_EXECUTOR_TRANSPORT:-host}
|
|
18
|
+
EZ_CHANNEL_BACKEND_URL: ${EZ_CHANNEL_BACKEND_URL:-}
|
|
15
19
|
EZ_AGENT_WORKSPACE: ${EZ_AGENT_WORKSPACE:?Set this agent workspace}
|
|
16
20
|
EZ_CONTROL_DIR: ${EZ_CONTROL_DIR:?Set this agent control directory}
|
|
17
21
|
EZ_EXECUTOR_CLI: ${EZ_EXECUTOR_CLI:?Set the host installation CLI}
|
|
22
|
+
EZ_CODEX_AUTO_COMPACT_TOKENS: ${EZ_CODEX_AUTO_COMPACT_TOKENS:-64000}
|
|
18
23
|
EZ_EXECUTOR_TIMEOUT_SECONDS: ${EZ_EXECUTOR_TIMEOUT_SECONDS:-300}
|
|
24
|
+
EZ_PAGERDUTY_STOCKS_HEALTH_URL: ${EZ_PAGERDUTY_STOCKS_HEALTH_URL:-}
|
|
25
|
+
EZ_PAGERDUTY_POLL_SECONDS: ${EZ_PAGERDUTY_POLL_SECONDS:-30}
|
|
26
|
+
EZ_PAGERDUTY_FAILURE_THRESHOLD: ${EZ_PAGERDUTY_FAILURE_THRESHOLD:-3}
|
|
19
27
|
secrets: [relay_env]
|
|
20
28
|
configs:
|
|
21
29
|
- source: agent_purpose
|
package/docker/recovery.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { RunStore } from '../src/runs.js'
|
|
|
2
2
|
|
|
3
3
|
// Called only after the deployment's kernel writer lock is held. No worker
|
|
4
4
|
// from a previous container can still own this deployment; PIDs may be reused.
|
|
5
|
-
export const recoverInterruptedRuns = async (controlDir: string) => {
|
|
5
|
+
export const recoverInterruptedRuns = async (controlDir: string, channelBackend = false) => {
|
|
6
6
|
const store = new RunStore(controlDir)
|
|
7
7
|
for (const run of await store.list()) {
|
|
8
8
|
if (run.status === 'running')
|
|
9
|
-
await store.patch(run.id, { status: 'failed', endedAt: new Date().toISOString() })
|
|
9
|
+
await store.patch(run.id, { status: channelBackend && !run.pid ? 'queued' : 'failed', endedAt: new Date().toISOString() })
|
|
10
10
|
}
|
|
11
11
|
}
|
package/docker/run.ts
CHANGED
|
@@ -21,12 +21,12 @@ try { privateEnv = parseEnv(readFileSync(3, 'utf8')) } catch (error) {
|
|
|
21
21
|
if ((error as NodeJS.ErrnoException).code !== 'EINVAL' && (error as NodeJS.ErrnoException).code !== 'EBADF') throw error
|
|
22
22
|
} finally { try { closeSync(3) } catch {} }
|
|
23
23
|
for (const [key, value] of Object.entries(privateEnv)) {
|
|
24
|
-
if (value !== undefined && ['TELEGRAM_BOT_TOKEN', 'GEMINI_API_KEY', 'OPENAI_API_KEY'].includes(key)) process.env[key] = value
|
|
24
|
+
if (value !== undefined && ['TELEGRAM_BOT_TOKEN', 'GEMINI_API_KEY', 'OPENAI_API_KEY', 'EZ_CHANNEL_BACKEND_TOKEN', 'PAGERDUTY_ROUTING_KEY'].includes(key)) process.env[key] = value
|
|
25
25
|
}
|
|
26
26
|
privateEnv = {}
|
|
27
27
|
const [command = 'start', ...args] = process.argv.slice(2)
|
|
28
28
|
process.argv = [process.argv[0], '', ...args]
|
|
29
|
-
if (['start', 'smoke'].includes(command)) await recoverInterruptedRuns(loadConfig().controlDir)
|
|
29
|
+
if (['start', 'smoke'].includes(command)) await recoverInterruptedRuns(loadConfig().controlDir, Boolean(loadConfig().channelBackendUrl))
|
|
30
30
|
if (command === 'start') {
|
|
31
31
|
const relay = createRelay(loadConfig())
|
|
32
32
|
const heartbeat = '/state/control/heartbeat.json'
|
|
@@ -35,3 +35,11 @@ model/effort settings (or `models` for the default model). Claude reads user and
|
|
|
35
35
|
workspace JSON settings; OpenCode reports resolved config. Unknown defaults and
|
|
36
36
|
opaque wrappers remain explicitly “client default”. No credentials are stored,
|
|
37
37
|
no inference runs, no new dependency, and no cross-CLI session transfer.
|
|
38
|
+
|
|
39
|
+
`/status` resolves the configured model and reasoning effort for the current
|
|
40
|
+
client-default seed from the agent's isolated Codex profile when that metadata
|
|
41
|
+
is available. If the profile has no explicit model, it uses Codex's native
|
|
42
|
+
default-model catalog for display. It displays that snapshot only; setup and
|
|
43
|
+
refresh do not save the fallback, so the seed remains a native client default
|
|
44
|
+
for later conversations. Desktop Codex remains its own opaque client default
|
|
45
|
+
rather than inheriting CLI configuration.
|