@jc_stack/ez-agents 0.1.0-beta.32 → 0.1.0-beta.34
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/.env.example +4 -0
- package/AGENTS.md +46 -31
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +29 -26
- package/Dockerfile +4 -0
- package/README.md +26 -18
- package/THIRD_PARTY_NOTICES.md +4 -4
- package/compose.yaml +2 -1
- package/docker/smoke.mjs +6 -3
- package/docs/application-channel.md +6 -0
- package/docs/architecture/ai-selection.md +3 -1
- package/docs/docker-runtime.md +27 -10
- package/docs/host-service.md +17 -6
- package/docs/plugin-contributions.md +4 -1
- package/docs/plugins.md +15 -0
- package/docs/repair.md +1 -1
- package/docs/setup.md +88 -14
- package/docs/standalone-cli.md +6 -5
- package/docs/upgrades.md +6 -4
- package/package.json +1 -1
- package/scripts/smoke-scheduler.ts +2 -1
- package/src/agent-install.ts +20 -6
- package/src/ai-cli.ts +9 -7
- package/src/ai.ts +7 -7
- package/src/application-channel.ts +10 -10
- package/src/codex-session.ts +5 -3
- package/src/config.ts +6 -1
- package/src/control-state.ts +12 -1
- package/src/executor.ts +91 -9
- package/src/host-executor.ts +25 -6
- package/src/index.ts +1 -0
- package/src/install-config.ts +2 -2
- package/src/install-tools.mjs +3 -1
- package/src/isolation.ts +25 -0
- package/src/menu.ts +9 -6
- package/src/plugins/manager.mjs +49 -6
- package/src/reply-context.ts +0 -1
- package/src/setup.ts +11 -7
- package/src/task-executor.ts +4 -1
- package/src/updates/control.mjs +11 -1
- package/src/updates/runtime.mjs +4 -2
- package/src/updates/supervisor.mjs +17 -3
- package/src/workspace-confine.ts +38 -0
- package/src/workspace.ts +23 -13
- package/templates/agent/AGENTS.md +4 -14
- package/templates/agent-guidance.md +13 -110
- package/templates/agent-purpose.md +1 -0
- package/test/agent-guidance.test.ts +8 -12
- package/test/agent-install.test.ts +34 -0
- package/test/ai-cli.test.ts +18 -0
- package/test/ai.test.ts +48 -0
- package/test/application-channel.test.ts +5 -2
- package/test/application-controls.test.ts +56 -3
- package/test/application-only.test.ts +2 -0
- package/test/codex-context.test.ts +61 -1
- package/test/codex-session.test.ts +6 -1
- package/test/config.test.ts +17 -2
- package/test/engine-handoff.test.ts +5 -2
- package/test/executor.test.ts +38 -1
- package/test/failure.test.ts +6 -0
- package/test/host-executor.test.ts +6 -0
- package/test/install-config.test.ts +17 -6
- package/test/install-tools.test.mjs +6 -0
- package/test/plugin-manager.test.mjs +24 -3
- package/test/scheduler.test.ts +2 -2
- package/test/updates.test.mjs +34 -2
- package/test/workspace-confine.test.ts +47 -0
- package/test/workspace.test.ts +23 -10
- package/templates/agent/SOUL.md +0 -11
- package/templates/agent/USER.md +0 -5
package/.env.example
CHANGED
|
@@ -48,6 +48,10 @@ EZ_REPAIR_ENABLED=true
|
|
|
48
48
|
# Optional native application-only runtime: no Telegram bot or token.
|
|
49
49
|
# Requires EZ_APPLICATION_PORT; administrator bootstrap uses the real operator ID.
|
|
50
50
|
# EZ_TELEGRAM_ENABLED=false
|
|
51
|
+
# Isolation class from agent creation (default isolated).
|
|
52
|
+
# EZ_ISOLATION=isolated
|
|
53
|
+
# EZ_EXECUTOR_TRANSPORT=local
|
|
54
|
+
# Host-capable: EZ_ISOLATION=host-capable and EZ_EXECUTOR_TRANSPORT=host
|
|
51
55
|
# Private application-only local container isolation (optional; default workspace-write).
|
|
52
56
|
# EZ_CODEX_SANDBOX=external
|
|
53
57
|
|
package/AGENTS.md
CHANGED
|
@@ -73,6 +73,35 @@ can be stated briefly and deferred. Reviewers distinguish those blockers from
|
|
|
73
73
|
optional follow-ups and do not hold a working increment for hypothetical polish.
|
|
74
74
|
Measure progress by usable outcomes and feedback, not code or test volume.
|
|
75
75
|
|
|
76
|
+
## Feasibility frame for non-trivial work
|
|
77
|
+
|
|
78
|
+
Before implementing a non-trivial coding, architecture or product change, state
|
|
79
|
+
the user-visible objective, no more than five task-relevant binding constraints,
|
|
80
|
+
the component that owns the failed boundary, the subtraction or simplification
|
|
81
|
+
option, the minimum evidence needed to prove the outcome, and the stop condition.
|
|
82
|
+
Do not restate the full prompt or add this ceremony to minor mechanical edits.
|
|
83
|
+
|
|
84
|
+
A result that violates a binding constraint is invalid even when tests pass or
|
|
85
|
+
the immediate symptom disappears. Check behavioral correctness, architecture and
|
|
86
|
+
ownership, real user-path evidence and authorized side effects separately. Before
|
|
87
|
+
completion, inspect whether the change added a runner, wrapper, state owner, queue,
|
|
88
|
+
retry loop, prompt layer, dependency or configuration format; retain it only when
|
|
89
|
+
the existing owner or contract cannot solve the demonstrated problem. Use one
|
|
90
|
+
bounded constraint review, then stop when sufficient evidence passes unless a
|
|
91
|
+
concrete material risk remains.
|
|
92
|
+
|
|
93
|
+
Frame that review as answers to these questions, not as an open-ended request to
|
|
94
|
+
find flaws:
|
|
95
|
+
|
|
96
|
+
1. Did the solution cross an architecture, ownership or authority boundary?
|
|
97
|
+
2. Did it bypass a binding constraint or preserve the symptom through a workaround?
|
|
98
|
+
3. Did it add machinery where deletion or a simpler existing contract would work?
|
|
99
|
+
4. Does the evidence prove the real user-visible outcome rather than only a proxy?
|
|
100
|
+
5. Is there one concrete unresolved risk severe enough to block completion?
|
|
101
|
+
|
|
102
|
+
If no answer identifies a material blocker, finish. Do not start another review
|
|
103
|
+
round merely to seek more criticism, tests or hypothetical edge cases.
|
|
104
|
+
|
|
76
105
|
## 3. Crash-Safe Atomic Disk State
|
|
77
106
|
- All persistent stores (`ControlStore`, `RunStore`, outbox queue) must be disk-backed JSON files.
|
|
78
107
|
- **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.
|
|
@@ -97,37 +126,23 @@ Measure progress by usable outcomes and feedback, not code or test volume.
|
|
|
97
126
|
- Unapproved group messages from other senders and unknown DMs fail silently unless an exact-contact or any-conversation owner-approved channel grant admits them. Both grant types use the restricted task runner. Paired-owner group text is discovery routed to the owner's private chat; it grants no group reply authority.
|
|
98
127
|
- Stopping work (`/stop`) must terminate the active worker PID immediately (`SIGTERM`, escalating to `SIGKILL` if unclosed after 3s).
|
|
99
128
|
|
|
100
|
-
## 8.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
129
|
+
## 8. Risk-based negative validation
|
|
130
|
+
|
|
131
|
+
Changes to authority, execution, routing, secret isolation or durable state must
|
|
132
|
+
validate the affected failure boundary, not rerun or recreate an unrelated fixed
|
|
133
|
+
checklist. Examples include proving that an unapproved sender spawns no process,
|
|
134
|
+
executor secrets remain absent, invalid IDs cannot traverse paths, ambiguous
|
|
135
|
+
external writes are not retried, and corrupt state fails safely. Add or change a
|
|
136
|
+
test only when it protects the changed contract or a demonstrated regression.
|
|
137
|
+
Existing relevant checks plus focused real-path evidence may be sufficient.
|
|
107
138
|
|
|
108
139
|
## Public contribution workflow
|
|
109
140
|
|
|
110
|
-
Read CONTRIBUTING.md before edits and docs/releasing.md before a release.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Never treat task completion as permission to merge or publish.
|
|
119
|
-
Own the complete engineering/release handoff in CONTRIBUTING.md. Once ready,
|
|
120
|
-
proactively request only missing merge/release authority, then ship and verify;
|
|
121
|
-
do not leave the maintainer to discover ready drafts or operate the release.
|
|
122
|
-
|
|
123
|
-
For every core or plugin PR you author, revise or review, apply CONTRIBUTING.md's
|
|
124
|
-
architecture check and the README's engine/application boundary. A symptom fix
|
|
125
|
-
and green tests do not justify a conflicting execution or context owner. Existing
|
|
126
|
-
legacy channel-backend code is a documented limitation, not a pattern for new
|
|
127
|
-
integrations; applications submit agent turns through the native Ez execution path.
|
|
128
|
-
|
|
129
|
-
A coding-task handoff must include the pushed commit and draft PR URL, checks,
|
|
130
|
-
independent-review status and remaining QA. If PR creation is blocked, state the
|
|
131
|
-
blocker and preserved commit. The merging agent owns the post-merge worktree
|
|
132
|
-
cleanup check and reports removal or the specific reason to retain it. Follow
|
|
133
|
-
CONTRIBUTING.md for squash-merge evidence, ignored files and active-use checks.
|
|
141
|
+
Read CONTRIBUTING.md before edits and docs/releasing.md before a release. It owns
|
|
142
|
+
the worktree, PR, review, merge, release and cleanup process; do not duplicate that
|
|
143
|
+
process here or in feature documentation. For every core or plugin change, apply
|
|
144
|
+
its architecture check and the README's engine/application boundary. A symptom
|
|
145
|
+
fix and green tests do not justify a conflicting execution or context owner.
|
|
146
|
+
Existing legacy channel-backend code is a documented limitation, not a pattern
|
|
147
|
+
for new integrations. Keep internal plans and private evidence outside this
|
|
148
|
+
repository.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.34
|
|
4
|
+
|
|
5
|
+
- Correct setup guidance for host-capable custom Codex providers and replace
|
|
6
|
+
stale pinned-beta installation guidance with current release records.
|
|
7
|
+
|
|
8
|
+
- Record an isolation class at agent creation. The default is `isolated`: the
|
|
9
|
+
native CLI runs in the relay (`EZ_EXECUTOR_TRANSPORT=local`). Pass
|
|
10
|
+
`--isolation host-capable` to reuse the installer UID and host CLI login.
|
|
11
|
+
Mismatched class and transport fail closed. Isolated Codex sets
|
|
12
|
+
`EZ_CODEX_SANDBOX=external`. Host transport is not started for isolated
|
|
13
|
+
agents. Unlabeled existing host transports stay host-capable.
|
|
14
|
+
- Install pinned Codex CLI `0.153.4` in the relay runtime image so isolated
|
|
15
|
+
agents resolve `codex` on PATH. Isolated jobs keep auth in
|
|
16
|
+
`control/cli/codex` and do not link the operator `~/.codex`.
|
|
17
|
+
|
|
18
|
+
- Confine macOS host jobs to their bound workspace and prevent cross-agent
|
|
19
|
+
plugin registry access.
|
|
20
|
+
- Support agent-scoped OpenRouter models through the native Codex engine and
|
|
21
|
+
start a new native session when the provider or model changes.
|
|
22
|
+
- Resolve native CLIs from the host PATH, expose captured presets in application
|
|
23
|
+
run receipts, and seed one purpose-scoped AGENTS.md for new agents.
|
|
24
|
+
|
|
25
|
+
## 0.1.0-beta.33
|
|
26
|
+
|
|
27
|
+
- Allow compatible plugin updates to add commands to existing services, registering
|
|
28
|
+
their aliases atomically while retaining collision checks and rejecting changes
|
|
29
|
+
to existing command routes or deployment authority.
|
|
30
|
+
- Simplify contribution guidance and bound independent constraint reviews without
|
|
31
|
+
changing the native engine, transport or plugin responsibility boundaries.
|
|
32
|
+
|
|
3
33
|
## 0.1.0-beta.32
|
|
4
34
|
|
|
5
35
|
- Add shared authenticated inbound attachment staging for application and
|
|
@@ -13,6 +43,9 @@
|
|
|
13
43
|
host CLI configuration needed for restricted read-only plugin commands.
|
|
14
44
|
- Clarify domain-agent positioning while preserving native engine ownership.
|
|
15
45
|
|
|
46
|
+
- Prevent accidental cross-agent plugin access by rejecting relay-bound registry
|
|
47
|
+
calls outside the owning workspace, and restrict its host-folder bindings to
|
|
48
|
+
workspace roots explicitly granted by the host.
|
|
16
49
|
- Answer native app-server requests with their current protocol shapes. Scheduled
|
|
17
50
|
`codex-gui` browser work now surfaces approval requests and grants only its
|
|
18
51
|
active turn session-scoped HTTPS browser-origin and Chrome app elicitations,
|
package/CONTRIBUTING.md
CHANGED
|
@@ -16,9 +16,11 @@ repository. Public docs describe shipped behavior and explicit limitations.
|
|
|
16
16
|
Packaging/runtime changes also need the Docker checks in docs/releasing.md.
|
|
17
17
|
5. Open a PR explaining the problem, resulting behavior, verification and limits.
|
|
18
18
|
Include a short sanitized reproduction. State which tests were not run.
|
|
19
|
-
6. Obtain independent review and required CI,
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
6. Obtain one bounded independent final-head review and required CI, resolve
|
|
20
|
+
material findings, then complete the authorized merge. An owner or maintainer
|
|
21
|
+
request for a product change or fix authorizes this normal PR/merge loop;
|
|
22
|
+
unsolicited external contributions still require maintainer merge authority.
|
|
23
|
+
No CLA, ticket requirement, custom commit format or additional approval committee.
|
|
22
24
|
|
|
23
25
|
You are responsible for understanding submitted code, including AI-generated
|
|
24
26
|
code, and having the right to contribute it under this repository's license.
|
|
@@ -79,10 +81,10 @@ do not disguise them as supported architecture or start a duplicate repair.
|
|
|
79
81
|
create one worktree/PR per repository and link dependencies and merge order.
|
|
80
82
|
Branch from an unmerged feature only when the dependency is intentional and
|
|
81
83
|
documented; do not quietly include it in an unrelated PR.
|
|
82
|
-
- Push the task branch and open a
|
|
83
|
-
|
|
84
|
-
work
|
|
85
|
-
|
|
84
|
+
- Push the task branch and open a PR when the coherent change is reviewable. Use
|
|
85
|
+
draft status only while implementation or a named gate remains incomplete; do
|
|
86
|
+
not leave completed mergeable work in a draft or only on a local branch.
|
|
87
|
+
Publication remains a separate authority boundary.
|
|
86
88
|
- Every handoff names the repository, worktree, branch, exact commit, PR URL,
|
|
87
89
|
checks, independent-review status and remaining QA with its next action. If
|
|
88
90
|
pushing or PR creation is blocked, report the blocker and preserved local
|
|
@@ -98,9 +100,10 @@ do not disguise them as supported architecture or start a duplicate repair.
|
|
|
98
100
|
- New substantive commits or conflict resolutions invalidate the affected review
|
|
99
101
|
and test evidence. Refresh against current main, review the resulting diff and
|
|
100
102
|
run the applicable checks. Do not bypass protected-branch requirements.
|
|
101
|
-
- Merge only after review, required CI
|
|
102
|
-
Publish only under the separate release
|
|
103
|
-
releases. Record which source commit and
|
|
103
|
+
- Merge only after review, required CI and applicable QA under the authority in
|
|
104
|
+
the contribution checklist above. Publish only under the separate release
|
|
105
|
+
process; commits and merges are not releases. Record which source commit and
|
|
106
|
+
artifact hash were tested.
|
|
104
107
|
- Keep the worktree while its PR or QA is open. After merge or explicit abandonment,
|
|
105
108
|
inspect it for uncommitted/untracked files and local-only commits. Remove only
|
|
106
109
|
the clean task worktree after valuable work is preserved; never force cleanup.
|
|
@@ -124,22 +127,22 @@ and prepare the release. Reuse valid final-commit evidence; repeat checks when
|
|
|
124
127
|
changes or failures invalidate it. Do not leave a ready feature silently in draft
|
|
125
128
|
or ask the maintainer to run commands, coordinate reviewers, or operate CI.
|
|
126
129
|
|
|
127
|
-
The maintainer
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
credential/2FA, failed gate that cannot be repaired in
|
|
141
|
-
change. Human attention belongs on product intent;
|
|
142
|
-
|
|
130
|
+
The owner or maintainer request authorizes the requested work and its normal
|
|
131
|
+
PR/merge steps; do not ask them to approve the same work again. Release remains
|
|
132
|
+
separate authority: a request to merge does not authorize publication or changing
|
|
133
|
+
a private package's visibility, while a request to release authorizes the merge
|
|
134
|
+
and publication needed for that release. Prepare and verify the reviewed commits,
|
|
135
|
+
artifacts and checksums before shipping. If release was not requested, stop after
|
|
136
|
+
the merged contribution loop and report any distinct deployment or publication
|
|
137
|
+
step without performing it.
|
|
138
|
+
|
|
139
|
+
When release is authorized, complete publication using docs/releasing.md, then
|
|
140
|
+
verify registry metadata, the downloaded artifact and any explicitly requested
|
|
141
|
+
installed-runtime QA. Deployment is separate and requires a direct rollout
|
|
142
|
+
request or the target's saved update policy. Report the outcome. Escalate only a
|
|
143
|
+
product decision, missing credential/2FA, failed gate that cannot be repaired in
|
|
144
|
+
scope, or material scope change. Human attention belongs on product intent; the
|
|
145
|
+
agent operates the technical workflow.
|
|
143
146
|
|
|
144
147
|
Example, substituting a unique task name and an absolute external directory:
|
|
145
148
|
|
package/Dockerfile
CHANGED
|
@@ -9,6 +9,10 @@ COPY . .
|
|
|
9
9
|
FROM dependencies AS test
|
|
10
10
|
RUN pnpm verify
|
|
11
11
|
FROM dependencies AS runtime
|
|
12
|
+
# Keep this pin aligned with TASK_CODEX_VERSION. Isolated agents run this CLI
|
|
13
|
+
# in the relay; do not bind-mount the operator's ~/.codex.
|
|
14
|
+
ARG CODEX_CLI_VERSION=0.153.4
|
|
15
|
+
RUN npm install -g @openai/codex@${CODEX_CLI_VERSION} && command -v codex
|
|
12
16
|
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
17
|
RUN node -e 'for (const [name, target] of Object.entries(require("./package.json").bin)) require("node:fs").symlinkSync("/app/" + target, "/usr/local/bin/" + name)'
|
|
14
18
|
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
|
package/README.md
CHANGED
|
@@ -148,15 +148,19 @@ the user's request and preserve its scope.
|
|
|
148
148
|
|
|
149
149
|
## Package and runtime
|
|
150
150
|
|
|
151
|
-
**
|
|
152
|
-
fixtures are verified. Live account onboarding
|
|
153
|
-
|
|
154
|
-
may contain changes newer than the published beta
|
|
155
|
-
documentation when installing a pinned release.
|
|
156
|
-
|
|
157
|
-
The npm package is `@jc_stack/ez-agents
|
|
158
|
-
|
|
159
|
-
|
|
151
|
+
**Published beta releases are for testing on a trusted machine.** Offline and
|
|
152
|
+
Docker fixtures are verified for the selected release. Live account onboarding
|
|
153
|
+
and reboot acceptance remain beta gates; this is not a production-readiness
|
|
154
|
+
claim. The source branch may contain changes newer than the published beta, so
|
|
155
|
+
inspect the supplied artifact's documentation when installing a pinned release.
|
|
156
|
+
|
|
157
|
+
The npm package is `@jc_stack/ez-agents`. Approved beta publications use npm's
|
|
158
|
+
`latest` distribution tag while their versions and GitHub releases remain
|
|
159
|
+
prereleases. For a reproducible download, choose an exact version from
|
|
160
|
+
[GitHub prereleases](https://github.com/jdorado/ez-agents/releases) and substitute
|
|
161
|
+
it for `VERSION` in `npm pack @jc_stack/ez-agents@VERSION`.
|
|
162
|
+
You can also download the release's candidate tarball and verify its SHA-256
|
|
163
|
+
against the attached release receipt or release notes.
|
|
160
164
|
GitHub remains under `jdorado`; npm uses `jc_stack`. Do not install the unrelated
|
|
161
165
|
unscoped `ez-whatsapp` package.
|
|
162
166
|
|
|
@@ -242,28 +246,32 @@ credentials, startup, and verified pairing; never present this as human homework
|
|
|
242
246
|
| `ezenciel-agents-install build` | Build once per artifact, with a private log and duplicate-build detection |
|
|
243
247
|
| `ezenciel-agents-install status --deployment <path>` | Distinguish runtime/configuration, pairing and Telegram reply evidence |
|
|
244
248
|
| `ezenciel-agents-create --register-cli <current-cli>` | Record the CLI that installs the initial package |
|
|
245
|
-
| `ezenciel-agents-create --name <name> --purpose <
|
|
249
|
+
| `ezenciel-agents-create --name <name> --purpose <agent-brief>` | Create an agent from the installing LLM's compact brief; packaged Codex defaults isolated, other CLIs stay host-capable; token via stdin |
|
|
250
|
+
| `ezenciel-agents-create --name <name> --purpose <agent-brief> --isolation host-capable` | Explicitly reuse the host CLI and installer UID |
|
|
246
251
|
| `ezenciel-agents-host` | Invoke the existing shared host CLI for this deployment |
|
|
247
|
-
| `ezenciel-agents-setup configure <executor>` | Private configuration and missing starter files; preserves personal files |
|
|
248
|
-
| `ezenciel-agents-setup configure <executor> --token-stdin` | Same, with the BotFather token supplied privately through stdin |
|
|
252
|
+
| `ezenciel-agents-setup configure <executor> --purpose-file <path>` | Private configuration and missing starter files; fresh workspaces require installer-scoped purpose; preserves personal files |
|
|
253
|
+
| `ezenciel-agents-setup configure <executor> --purpose-file <path> --token-stdin` | Same, with the BotFather token supplied privately through stdin |
|
|
249
254
|
| `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 |
|
|
250
255
|
| `ezenciel-agents-owner status` | Inspect the owner and pending pairing requests |
|
|
251
256
|
| `ezenciel-agents-owner approve <telegram-user-id>` | Approve the verified owner; never an arbitrary first sender |
|
|
252
257
|
| `ezenciel-agents-setup status` | Inspect installed executor choices |
|
|
253
|
-
| `ezenciel-agents-setup init
|
|
258
|
+
| `ezenciel-agents-setup init --purpose-file <path>` | Seed missing workspace guidance; purpose is optional only when AGENTS.md already exists |
|
|
254
259
|
|
|
255
260
|
Run runtime tools through `ezenciel-agents-docker run --rm relay <command>`
|
|
256
261
|
as shown in the Docker guide. Keep the Docker engine available; Compose owns
|
|
257
|
-
restart and shutdown.
|
|
262
|
+
restart and shutdown. Host-capable agents register the small host CLI transport with the native service manager. Isolated agents do not.
|
|
258
263
|
|
|
259
264
|
## Runtime and development reference
|
|
260
265
|
|
|
261
266
|
The selected host CLI runs in this agent's persistent workspace and owns its
|
|
262
267
|
Markdown/work files. New conversations and AI changes preserve those files.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
268
|
+
One compact, purpose-scoped `AGENTS.md` is seeded; `MEMORY.md` is optional.
|
|
269
|
+
The installing LLM authors the initial brief from the owner's request and known
|
|
270
|
+
application context; Ez stores it without trying to infer the product itself.
|
|
271
|
+
Installed plugin snippets and skill paths come from `ez tools list --details`; no tool inventory file needs maintenance. Received files go in `inbox/`, tasks and deliverables in `work/`.
|
|
272
|
+
Credentials and control state stay outside the mind. Isolated agents use relay
|
|
273
|
+
mounts as the filesystem boundary. Host-capable file separation is not OS
|
|
274
|
+
isolation against a process running as the same user.
|
|
267
275
|
|
|
268
276
|
In Telegram, **Conversations** (or `/chats`) lists this agent's saved Ez
|
|
269
277
|
conversations by name. Tap a name to continue its native engine session and
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -8,7 +8,7 @@ The container is built locally; no bundled third-party binary image is promised.
|
|
|
8
8
|
|
|
9
9
|
Direct runtime dependencies: grammy (MIT), tsx (MIT). Development dependencies
|
|
10
10
|
include TypeScript (Apache-2.0) and Node type definitions (MIT). The runtime
|
|
11
|
-
image installs ffmpeg
|
|
12
|
-
review of its exact package build, notices and
|
|
13
|
-
Docker and
|
|
14
|
-
by this repository's MIT license.
|
|
11
|
+
image installs ffmpeg, Debian packages, and pinned `@openai/codex` (Apache-2.0):
|
|
12
|
+
redistributing that image requires review of its exact package build, notices and
|
|
13
|
+
corresponding-source obligations. Docker and a host-capable AI CLI remain
|
|
14
|
+
separately installed products, not covered by this repository's MIT license.
|
package/compose.yaml
CHANGED
|
@@ -17,6 +17,7 @@ services:
|
|
|
17
17
|
EZ_RELAY_UID: ${EZ_RELAY_UID:-1001}
|
|
18
18
|
EZ_REPAIR_ENABLED: ${EZ_REPAIR_ENABLED:-true}
|
|
19
19
|
EZ_AGENT_PURPOSE_FILE: /run/agent-purpose.md
|
|
20
|
+
EZ_ISOLATION: ${EZ_ISOLATION:-}
|
|
20
21
|
EZ_EXECUTOR_TRANSPORT: ${EZ_EXECUTOR_TRANSPORT:-host}
|
|
21
22
|
EZ_CHANNEL_BACKEND_URL: ${EZ_CHANNEL_BACKEND_URL:-}
|
|
22
23
|
EZ_TELEGRAM_WEB_APP: ${EZ_TELEGRAM_WEB_APP:-}
|
|
@@ -50,7 +51,7 @@ services:
|
|
|
50
51
|
retries: 3
|
|
51
52
|
configs:
|
|
52
53
|
agent_purpose:
|
|
53
|
-
file: ${EZ_AGENT_PURPOSE_FILE:-./templates/agent
|
|
54
|
+
file: ${EZ_AGENT_PURPOSE_FILE:-./templates/agent-purpose.md}
|
|
54
55
|
secrets:
|
|
55
56
|
relay_env:
|
|
56
57
|
file: ${EZ_RELAY_ENV_FILE:?Set EZ_RELAY_ENV_FILE to the private relay env file}
|
package/docker/smoke.mjs
CHANGED
|
@@ -10,6 +10,7 @@ const volume = `${holder}-control`;
|
|
|
10
10
|
const application = `${holder}-application`;
|
|
11
11
|
const marker = 'qa-private-secret-never-in-executor';
|
|
12
12
|
writeFileSync(join(dir, 'relay.env'), `TELEGRAM_BOT_TOKEN=${marker}\n`, { mode: 0o600 });
|
|
13
|
+
writeFileSync(join(dir, 'purpose.md'), 'Verify the packaged Ez runtime.\n', { mode: 0o644 });
|
|
13
14
|
writeFileSync(join(dir, 'node'), `#!/bin/sh\nIFS= read -r value <&3\n[ "$value" = "TELEGRAM_BOT_TOKEN=${marker}" ] || exit 91\nexec /usr/local/bin/node "$@"\n`, { mode: 0o555 });
|
|
14
15
|
const run = (args) => spawnSync('docker', args, { encoding: 'utf8', timeout: 60000 });
|
|
15
16
|
try {
|
|
@@ -17,17 +18,19 @@ try {
|
|
|
17
18
|
'--mount',`type=bind,src=${join(dir,'node')},dst=/qa/node,readonly`,'-e','PATH=/qa:/usr/local/bin:/usr/bin:/bin',image,'application','--help']);
|
|
18
19
|
assert.equal(inherited.status,0,inherited.stderr);
|
|
19
20
|
const nonroot = ['--user','20000:20000','--read-only','--cap-drop','ALL','--security-opt','no-new-privileges',
|
|
21
|
+
'--mount',`type=bind,src=${join(dir,'purpose.md')},dst=/run/agent-purpose.md,readonly`,'-e','EZ_AGENT_PURPOSE_FILE=/run/agent-purpose.md',
|
|
20
22
|
'--tmpfs','/tmp:mode=1777','--tmpfs','/state/control:uid=20000,gid=20000,mode=700',
|
|
21
23
|
'--tmpfs','/state/home:uid=20000,gid=20000,mode=700','--tmpfs','/workspace:uid=20000,gid=20000,mode=700',
|
|
22
|
-
'-e','EZ_TELEGRAM_ENABLED=false','-e','EZ_APPLICATION_PORT=8110','-e','EZ_EXECUTOR_TRANSPORT=local','-e','EZ_EXECUTOR_CLI=codex'];
|
|
24
|
+
'-e','EZ_TELEGRAM_ENABLED=false','-e','EZ_APPLICATION_PORT=8110','-e','EZ_ISOLATION=isolated','-e','EZ_EXECUTOR_TRANSPORT=local','-e','EZ_EXECUTOR_CLI=codex'];
|
|
23
25
|
const help = run(['run','--rm',...nonroot,image,'application','--help']);
|
|
24
26
|
assert.equal(help.status,0,help.stderr);
|
|
25
27
|
assert.match(help.stdout,/ezenciel-agents-application/);
|
|
26
28
|
const login = run(['run','--rm',...nonroot,'--entrypoint','/bin/bash',image,'-lc',
|
|
27
|
-
'command -v ezenciel-agents-application && command -v ezenciel-agents-message && ezenciel-agents-message --help']);
|
|
29
|
+
'command -v ezenciel-agents-application && command -v ezenciel-agents-message && command -v codex && ezenciel-agents-message --help && codex --version']);
|
|
28
30
|
assert.equal(login.status,0,login.stderr);
|
|
29
31
|
assert.match(login.stdout,/\/usr\/local\/bin\/ezenciel-agents-application/);
|
|
30
32
|
assert.match(login.stdout,/\/usr\/local\/bin\/ezenciel-agents-message/);
|
|
33
|
+
assert.match(login.stdout,/codex-cli 0\.153\.4/);
|
|
31
34
|
const started = run(['run','-d','--name',application,...nonroot,image,'start']);
|
|
32
35
|
assert.equal(started.status,0,started.stderr);
|
|
33
36
|
let ready = false;
|
|
@@ -82,5 +85,5 @@ try {
|
|
|
82
85
|
assert.equal(run(['kill',holder]).status,0);
|
|
83
86
|
const recovered=run(['run','--rm','-v',`${volume}:/state/control`,image,'exec','node','-e','process.exit(0)']);
|
|
84
87
|
assert.equal(recovered.status,0,recovered.stderr);
|
|
85
|
-
console.log('Docker smoke passed: direct non-root application help/start/health/stop, inherited private descriptor, non-root executor, private secret isolation, literal argv, exit code, no Docker socket, duplicate writer rejection and crash lock release.');
|
|
88
|
+
console.log('Docker smoke passed: direct non-root application help/start/health/stop, inherited private descriptor, non-root executor, isolated Codex on PATH, private secret isolation, literal argv, exit code, no Docker socket, duplicate writer rejection and crash lock release.');
|
|
86
89
|
} finally { run(['rm','-f',holder,application]); run(['volume','rm',volume]); rmSync(dir, {recursive:true, force:true}); }
|
|
@@ -6,6 +6,10 @@ outbox. The application supplies domain tools and keeps its UI/content API; it
|
|
|
6
6
|
can remove its own model runner, continuation loop and engine authentication.
|
|
7
7
|
This is separate from the older outbound channel-backend integration.
|
|
8
8
|
|
|
9
|
+
Run admission, status and inbox receipts include the immutable `preset` captured
|
|
10
|
+
for that run so an application can label delivered messages with the engine choice
|
|
11
|
+
that actually produced them.
|
|
12
|
+
|
|
9
13
|
## Shared runtime controls
|
|
10
14
|
|
|
11
15
|
Register with `--share-owner` (the existing `--share-telegram` spelling is an
|
|
@@ -267,6 +271,8 @@ separate CLI histories. A retry cannot change an admitted turn's AI choice.
|
|
|
267
271
|
|
|
268
272
|
Register owner-chat channels with `--share-owner` and submit `followOwner:true`.
|
|
269
273
|
Web, phone and Telegram then use the same selected native conversation and AI.
|
|
274
|
+
A later same-client provider or model change starts a new native conversation for the next
|
|
275
|
+
admitted turn; already-queued work keeps its original engine.
|
|
270
276
|
This works without Telegram and requires no transcript replay or new runner.
|
|
271
277
|
Scoped application conversations remain separate when the flag is omitted.
|
|
272
278
|
Owner identity does not automatically merge histories or grant learner access.
|
|
@@ -8,7 +8,9 @@ At intake each journal entry receives an immutable preset and conversation ID.
|
|
|
8
8
|
Batches cannot cross that boundary. The run copies that choice and invokes the
|
|
9
9
|
native adapter with its exact model/effort. A later menu change cannot reroute it.
|
|
10
10
|
Old conversation metadata is retained only so accepted work can finish; selecting
|
|
11
|
-
a different CLI never restores that CLI's old history.
|
|
11
|
+
a different CLI never restores that CLI's old history. Selecting a different provider
|
|
12
|
+
or model on the same client does not resume the previous selection's native thread; the next
|
|
13
|
+
admitted turn starts a new native conversation.
|
|
12
14
|
|
|
13
15
|
Grok/Claude accept caller-selected native UUIDs. Codex/OpenCode generate IDs, so
|
|
14
16
|
the adapter reads only their typed JSONL session metadata; stdout never becomes a
|
package/docs/docker-runtime.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Docker runtime and shared host CLI
|
|
2
2
|
|
|
3
|
-
Docker Compose owns each relay and executable plugin.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Docker Compose owns each relay and executable plugin. Isolated agents run the
|
|
4
|
+
native CLI from the relay image (pinned Codex). Host-capable agents reuse the
|
|
5
|
+
CLI the user installed Ez from, with its existing authentication. The relay
|
|
6
|
+
image contains Node, relay dependencies, ffmpeg and that pinned Codex CLI.
|
|
7
7
|
The runtime image exposes Ez commands through the wrappers in `/app/bin`, including
|
|
8
8
|
`ezenciel-agents-application`; application images do not need to link Ez themselves.
|
|
9
9
|
The image also installs package-manifest commands in `/usr/local/bin`, so native
|
|
@@ -13,26 +13,33 @@ belongs to Ez packaging, not an application image or an engine-specific prompt.
|
|
|
13
13
|
## Agent binding
|
|
14
14
|
|
|
15
15
|
Use [agent-led setup](setup.md). `ezenciel-agents-create` accepts a name, purpose,
|
|
16
|
+
optional `--isolation isolated|host-capable` (default `isolated`),
|
|
16
17
|
a bot token through stdin; the CLI defaults to the one recorded at package
|
|
17
18
|
installation by `--register-cli <current-cli>`. It creates a private deployment
|
|
18
19
|
with a unique Compose project, mind, control directory and secret file. Names
|
|
19
20
|
cannot overwrite existing agents. `installation.json` keeps subsequent agents
|
|
20
21
|
on the same CLI. Each agent gets its own purpose and native conversation IDs.
|
|
22
|
+
`isolated` sets `EZ_EXECUTOR_TRANSPORT=local` and runs the native CLI in the
|
|
23
|
+
relay. `host-capable` sets `host` and reuses the installer UID; unlabeled
|
|
24
|
+
existing host transports stay host-capable so they are not flipped.
|
|
21
25
|
|
|
22
26
|
`docker.env` contains explicit absolute paths, never token values:
|
|
23
27
|
|
|
24
28
|
```dotenv
|
|
25
29
|
COMPOSE_PROJECT_NAME=ez-agent-family
|
|
26
30
|
EZ_EXECUTOR_CLI=grok
|
|
31
|
+
EZ_ISOLATION=isolated
|
|
32
|
+
EZ_EXECUTOR_TRANSPORT=local
|
|
27
33
|
EZ_AGENT_WORKSPACE=/absolute/private/agents/family/mind
|
|
28
34
|
EZ_CONTROL_DIR=/absolute/private/agents/family/control
|
|
29
35
|
EZ_RELAY_ENV_FILE=/absolute/private/agents/family/relay.env
|
|
30
36
|
EZ_AGENT_PURPOSE_FILE=/absolute/private/agents/family/purpose.md
|
|
31
37
|
```
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
Host-capable agents run `ezenciel-agents-host` under the host's service manager
|
|
34
40
|
with `EZ_DEPLOYMENT_DIR` bound to that deployment. This small transport invokes
|
|
35
|
-
the existing CLI; it is not a second relay or model loop.
|
|
41
|
+
the existing CLI; it is not a second relay or model loop. Isolated agents do not
|
|
42
|
+
start it. It reads requests from
|
|
36
43
|
the agent's control directory, fixes cwd/control/tool paths from its installation
|
|
37
44
|
binding, strips environment secrets, forwards native output and exit status, and
|
|
38
45
|
propagates cancellation. Requests cannot select another executable. No network
|
|
@@ -41,9 +48,10 @@ is required. Host Node 22+ and the package dependencies run this transport.
|
|
|
41
48
|
|
|
42
49
|
Mount mind and control at identical absolute paths in Docker and on the host,
|
|
43
50
|
so incoming files, message attachments and CLI outputs need no path translation.
|
|
44
|
-
Only that agent's directories are mounted into its relay.
|
|
51
|
+
Only that agent's directories are mounted into its relay. Host-capable CLI reuses the existing login. Codex receives a private per-agent
|
|
45
52
|
state home with linked authentication; global memory/configuration is excluded.
|
|
46
|
-
|
|
53
|
+
Host-capable is not an OS security boundary between agents running as the same user.
|
|
54
|
+
Isolated agents use the relay mounts; sibling host paths are not present.
|
|
47
55
|
Plugin setup also binds `toolsHome` in the host configuration. Codex receives
|
|
48
56
|
write access to that registry and network access for the Docker client; the host
|
|
49
57
|
rejects registries belonging to a different workspace. Restart the host worker
|
|
@@ -146,13 +154,22 @@ default. Existing queued jobs retain their captured execution choice.
|
|
|
146
154
|
|
|
147
155
|
## Codex context isolation
|
|
148
156
|
|
|
149
|
-
|
|
150
|
-
`control/cli/codex
|
|
157
|
+
Isolated agents run the image Codex with `EZ_CODEX_SANDBOX=external`. Auth is a
|
|
158
|
+
real file at that agent's `control/cli/codex/auth.json`. Do not bind-mount the
|
|
159
|
+
operator `~/.codex` or `$HOME` into an isolated relay. Host-capable agents reuse
|
|
160
|
+
the host Codex binary and login, with a
|
|
161
|
+
`control/cli/codex` state directory. The native CLI is resolved from the host
|
|
162
|
+
PATH, not the package `binDir`, so a shared runtime or one agent's wrapper cannot
|
|
163
|
+
retarget another agent's `CODEX_HOME`. Only authentication is linked to the host
|
|
151
164
|
login; global configuration, sessions and memories are not imported. Global
|
|
152
165
|
memory and host skill discovery are disabled for relay jobs. A conversation
|
|
153
166
|
that already received unrelated global context must be replaced with a fresh
|
|
154
167
|
native conversation; disabling injection does not remove prior turn content.
|
|
155
168
|
This prevents automatic context sharing, not adversarial access by the host user.
|
|
169
|
+
On macOS host jobs, Seatbelt also denies sibling directories of the bound
|
|
170
|
+
workspace (a tenant farm), while allowing explicitly shared and additional
|
|
171
|
+
workspace grants and leaving `$HOME` readable for the host CLI.
|
|
172
|
+
Codex then uses `danger-full-access` so it does not apply a nested Seatbelt.
|
|
156
173
|
|
|
157
174
|
## Chat latency
|
|
158
175
|
|
package/docs/host-service.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Host transport startup
|
|
2
2
|
|
|
3
|
-
Register one service per deployment after initializing its tools.
|
|
4
|
-
|
|
3
|
+
Register one service per **host-capable** deployment after initializing its tools.
|
|
4
|
+
Isolated agents run the native CLI in the relay and must not start this service.
|
|
5
|
+
Substitute the exact absolute paths below. Use the existing authenticated host user and include
|
|
5
6
|
its Node 22+, pnpm (or Corepack), Docker and CLI directories in PATH. Resolve the
|
|
6
7
|
actual installed launchers first; shell aliases and interactive shell startup
|
|
7
8
|
files are not available to services. No bot token goes in these service files.
|
|
@@ -21,6 +22,7 @@ Description=Ez family host CLI transport
|
|
|
21
22
|
Type=simple
|
|
22
23
|
Environment=EZ_DEPLOYMENT_DIR=/absolute/private/agents/family
|
|
23
24
|
Environment=PATH=/absolute/node/bin:/absolute/package-manager/bin:/absolute/cli/bin:/usr/local/bin:/usr/bin:/bin
|
|
25
|
+
EnvironmentFile=-%h/.config/ez/family-provider.env
|
|
24
26
|
ExecStart=/absolute/ez-package/package/bin/ezenciel-agents-host
|
|
25
27
|
Restart=on-failure
|
|
26
28
|
RestartSec=5
|
|
@@ -29,6 +31,13 @@ RestartSec=5
|
|
|
29
31
|
WantedBy=default.target
|
|
30
32
|
```
|
|
31
33
|
|
|
34
|
+
When the installation declares a custom Codex provider, create that private
|
|
35
|
+
environment file with mode `0600` and only the referenced key, for example
|
|
36
|
+
`OPENROUTER_API_KEY=...`. Provider and model selection do not belong in the
|
|
37
|
+
environment; they remain agent runtime state. The supervisor forwards only keys
|
|
38
|
+
explicitly named by the agent's provider binding, and the Codex subprocess still
|
|
39
|
+
receives none of the relay or plugin secrets.
|
|
40
|
+
|
|
32
41
|
```sh
|
|
33
42
|
systemctl --user daemon-reload
|
|
34
43
|
systemctl --user enable --now ez-family.service
|
|
@@ -81,10 +90,12 @@ main/plugin replacement. See [upgrade setup, tools and recovery](upgrades.md). E
|
|
|
81
90
|
|
|
82
91
|
## Shared application workspace
|
|
83
92
|
|
|
84
|
-
Codex tasks inherit the agent's `control/cli/codex/auth.json` binding.
|
|
85
|
-
is a link to the host user's existing login.
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
Codex tasks inherit the agent's `control/cli/codex/auth.json` binding. Host-capable
|
|
94
|
+
default is a link to the host user's existing login. Isolated agents use a real
|
|
95
|
+
file in that directory and the image Codex; they do not link `~/.codex`. An
|
|
96
|
+
operator may provision a private agent credential there during migration; new
|
|
97
|
+
task homes link to that binding, preserving it rather than reverting to a
|
|
98
|
+
different or expired host login.
|
|
88
99
|
|
|
89
100
|
An agent binding may set `sharedWorkspace` to an absolute canonical application
|
|
90
101
|
repository. The host resolves its canonical path, adds that directory to Codex
|
|
@@ -28,7 +28,10 @@ Before the first PR, provide:
|
|
|
28
28
|
|
|
29
29
|
Copy CONTRIBUTING.md, SECURITY.md structure, PR template and docs/releasing.md
|
|
30
30
|
from a released Ez repository; adapt commands and security facts to your plugin.
|
|
31
|
-
|
|
31
|
+
Add a short AGENTS.md that states the plugin's ownership boundary and applies the
|
|
32
|
+
same compact feasibility frame and risk-based validation policy; do not copy
|
|
33
|
+
core-only Telegram, state or dependency invariants. Do not copy private QA,
|
|
34
|
+
company policy, proposed features or unsupported claims.
|
|
32
35
|
Public instructions must work without the maintainer's parent workspace. Use
|
|
33
36
|
reviewed local source and its inspected content hash; registry installation is
|
|
34
37
|
inert. Installation is complete only after account onboarding and verified use.
|
package/docs/plugins.md
CHANGED
|
@@ -291,6 +291,21 @@ already exist on the host. Keep indexes and writable metadata in the plugin's
|
|
|
291
291
|
normal volume. This uses Docker bind mounts; it copies no source bytes and
|
|
292
292
|
starts no provider sync. Read-only is the default.
|
|
293
293
|
|
|
294
|
+
For a relay-bound agent, the source must be inside its workspace/shared workspace
|
|
295
|
+
or under a plugin-specific root granted in the agent's external host configuration:
|
|
296
|
+
|
|
297
|
+
```json
|
|
298
|
+
{
|
|
299
|
+
"pluginFolderRoots": {
|
|
300
|
+
"library": ["/absolute/existing/notes"]
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
The agent cannot add this grant through its registry. A missing grant fails before
|
|
306
|
+
Compose or registry state changes. Standalone registries remain operator-owned and
|
|
307
|
+
do not use a relay host allowlist.
|
|
308
|
+
|
|
294
309
|
Stop the plugin before changing a binding:
|
|
295
310
|
|
|
296
311
|
```sh
|
package/docs/repair.md
CHANGED
|
@@ -30,7 +30,7 @@ True makes the capability available; it does not itself grant a repair mandate.
|
|
|
30
30
|
The setting does not change filesystem/GitHub permissions and does
|
|
31
31
|
not cancel an already running task. Explicitly stop active repair work when needed.
|
|
32
32
|
An owner can also disable repairs globally or for a repository in the agent's
|
|
33
|
-
saved
|
|
33
|
+
saved AGENTS.md preferences; carry those restrictions into background task context.
|
|
34
34
|
|
|
35
35
|
## Setup boundary
|
|
36
36
|
|