@jc_stack/ez-agents 0.1.0-beta.33 → 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/CHANGELOG.md +25 -0
- 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/plugins.md +15 -0
- package/docs/repair.md +1 -1
- package/docs/setup.md +88 -14
- package/docs/standalone-cli.md +6 -5
- 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/runtime.mjs +1 -1
- 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 +10 -1
- 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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
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
|
+
|
|
3
25
|
## 0.1.0-beta.33
|
|
4
26
|
|
|
5
27
|
- Allow compatible plugin updates to add commands to existing services, registering
|
|
@@ -21,6 +43,9 @@
|
|
|
21
43
|
host CLI configuration needed for restricted read-only plugin commands.
|
|
22
44
|
- Clarify domain-agent positioning while preserving native engine ownership.
|
|
23
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.
|
|
24
49
|
- Answer native app-server requests with their current protocol shapes. Scheduled
|
|
25
50
|
`codex-gui` browser work now surfaces approval requests and grants only its
|
|
26
51
|
active turn session-scoped HTTPS browser-origin and Chrome app elicitations,
|
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
|
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
|
|
package/docs/setup.md
CHANGED
|
@@ -67,8 +67,23 @@ not imported into restricted sessions. No workflow prompt is added to input.
|
|
|
67
67
|
Use the existing owner's host account. Unless a layout was supplied, use
|
|
68
68
|
`${XDG_DATA_HOME:-$HOME/.local/share}/ez/packages/<version>/` for extracted main
|
|
69
69
|
packages and `${XDG_DATA_HOME:-$HOME/.local/share}/ez/agents/` for private deployments.
|
|
70
|
-
Never overwrite an existing package/deployment or extract over its state.
|
|
71
|
-
|
|
70
|
+
Never overwrite an existing package/deployment or extract over its state.
|
|
71
|
+
|
|
72
|
+
Before creation, use your own reasoning and the context already available from
|
|
73
|
+
the owner to write the agent's initial brief. This is not a label or a copy of
|
|
74
|
+
the request. Describe, in concrete language, who the agent serves, what product
|
|
75
|
+
or environment it works in, the outcomes it should help produce, the capabilities
|
|
76
|
+
currently available to it, and important scope boundaries. Include material facts
|
|
77
|
+
you already know about the application; do not invent unknown facts. Omit generic
|
|
78
|
+
personality prose and sections irrelevant to this agent. Keep the result compact
|
|
79
|
+
enough to read on every turn. Ask the owner only when a missing fact would
|
|
80
|
+
materially change the agent being installed.
|
|
81
|
+
|
|
82
|
+
Pass that generated brief as the purpose. For example, a request to create a
|
|
83
|
+
personal assistant should produce a brief tailored to that person's stated work,
|
|
84
|
+
preferences and connected capabilities—not merely `Personal assistant`. A product
|
|
85
|
+
agent should identify the product, user, current product scope and available
|
|
86
|
+
actions without embedding product-specific behavior in Ez Core.
|
|
72
87
|
|
|
73
88
|
Before running Node commands, check `command -v node` and `node --version`.
|
|
74
89
|
If Node 22+ or this package's pinned pnpm is missing, provision it using the
|
|
@@ -163,20 +178,72 @@ so later service starts use the same build without depending on shell environmen
|
|
|
163
178
|
|
|
164
179
|
```sh
|
|
165
180
|
export EZ_AGENTS_HOME=/absolute/private/agents
|
|
166
|
-
bin/ezenciel-agents-create --name family-shopper --purpose '
|
|
181
|
+
bin/ezenciel-agents-create --name family-shopper --purpose 'You are the shopping assistant for the owner and their family. Help plan shared shopping, organize confirmed requests, and use only the installed shopping and messaging capabilities. Do not purchase, message others, or infer household preferences without owner authority.' < /private/bot-token
|
|
167
182
|
export EZ_DEPLOYMENT_DIR="$EZ_AGENTS_HOME/family-shopper"
|
|
168
183
|
```
|
|
169
184
|
|
|
185
|
+
Creation records an isolation class. Packaged Codex defaults to `isolated`: the
|
|
186
|
+
native CLI runs inside the relay, which only has that agent's workspace and control mounts.
|
|
187
|
+
Sibling host paths are absent (`ENOENT`), not merely unreadable. Pass
|
|
188
|
+
`--isolation host-capable` only when the owner needs the installer UID (host
|
|
189
|
+
browser, local git, host files). Other installed CLIs default to `host-capable`
|
|
190
|
+
because they are not packaged in the relay; requesting isolated execution for
|
|
191
|
+
them fails closed. Host-capable reuses the host CLI login and is not an OS tenant
|
|
192
|
+
boundary. The class cannot be changed later by flipping Compose; recreate the agent.
|
|
193
|
+
|
|
194
|
+
Isolated Codex uses the pinned CLI in the relay image and
|
|
195
|
+
`EZ_CODEX_SANDBOX=external` so Codex does not nest a sandbox inside the
|
|
196
|
+
container. Provision that agent's `control/cli/codex/auth.json`; do not bind-mount
|
|
197
|
+
the operator `~/.codex`. The host LaunchAgent is not started. Host-capable agents
|
|
198
|
+
still need [host startup](host-service.md).
|
|
199
|
+
|
|
170
200
|
Agent creation defaults to the CLI recorded when the initial package was
|
|
171
201
|
installed. It needs no `--cli` argument. A later shell or different available CLI
|
|
172
202
|
does not change that saved default. No installed-binary ranking or Grok fallback
|
|
173
203
|
is used.
|
|
204
|
+
|
|
205
|
+
Custom Codex providers such as OpenRouter currently require an explicitly
|
|
206
|
+
host-capable agent: their keys are supplied by the private host-service
|
|
207
|
+
environment. The isolated relay has no custom-provider key injection path.
|
|
208
|
+
Register the provider and initial model set as non-secret installation metadata;
|
|
209
|
+
repeat `--codex-model` for every model the agent may select:
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
bin/ezenciel-agents-create \
|
|
213
|
+
--name family-shopper \
|
|
214
|
+
--purpose 'Help my family plan shopping.' \
|
|
215
|
+
--isolation host-capable \
|
|
216
|
+
--codex-provider openrouter \
|
|
217
|
+
--codex-provider-name OpenRouter \
|
|
218
|
+
--codex-base-url https://openrouter.ai/api/v1 \
|
|
219
|
+
--codex-env-key OPENROUTER_API_KEY \
|
|
220
|
+
--codex-model google/gemini-3.8-flash \
|
|
221
|
+
--codex-model deepseek/deepseek-v4.1-flash \
|
|
222
|
+
< /private/bot-token
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
This stores provider configuration and model IDs in `host-executor.json`, never
|
|
226
|
+
the API key. The key belongs only in the private host-service environment. The
|
|
227
|
+
agent or owner can later change the active provider/model through the existing
|
|
228
|
+
runtime control without reinstalling or editing an environment file:
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
ezenciel-agents-ai list
|
|
232
|
+
ezenciel-agents-ai select --cli codex --provider openrouter \
|
|
233
|
+
--model google/gemini-3.8-flash
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Changing provider starts a fresh native session so a session is never resumed
|
|
237
|
+
against a different backend. Queued work retains the provider/model captured
|
|
238
|
+
when it was admitted.
|
|
174
239
|
The creator writes `host-executor.json`, private secrets, mind/control paths,
|
|
175
240
|
purpose and unique plugin volume names. Duplicate names fail without overwriting.
|
|
176
241
|
`ezenciel-agents-create --list` lists deployments without secrets.
|
|
177
242
|
|
|
178
|
-
Before starting
|
|
243
|
+
Before starting a host-capable transport, initialize the main package’s built-in plugin manager. It runs on the host
|
|
179
244
|
for Docker access and adds no separate package or provider library. The packaged catalog is empty so the relay installs independently.
|
|
245
|
+
Isolated agents still initialize this registry for plugin discovery; they do not
|
|
246
|
+
start `ezenciel-agents-host`.
|
|
180
247
|
Use its empty default catalog. Plugin preparation follows the verified Telegram
|
|
181
248
|
handoff, not this step. Run:
|
|
182
249
|
|
|
@@ -202,16 +269,21 @@ the plugin skill through onboarding and verified use under that same request.
|
|
|
202
269
|
Registry initialization itself does not connect accounts or start plugins.
|
|
203
270
|
Never silently reuse a global `ez` from the old sandbox runtime.
|
|
204
271
|
|
|
205
|
-
4.
|
|
206
|
-
|
|
207
|
-
|
|
272
|
+
4. Isolated agents skip host transport. Run `bin/ezenciel-agents-docker up -d --wait`
|
|
273
|
+
from the deployment directory. Do not register `ezenciel-agents-host` for them;
|
|
274
|
+
starting it fails closed.
|
|
275
|
+
|
|
276
|
+
Host-capable agents follow [host startup templates](host-service.md). Register
|
|
277
|
+
`bin/ezenciel-agents-host` with the host's native service manager, binding
|
|
278
|
+
`EZ_DEPLOYMENT_DIR` and the user's existing CLI PATH/HOME. On macOS use a
|
|
279
|
+
LaunchAgent; on Linux use a user service. Use the absolute Node/package
|
|
208
280
|
paths. This generic transport is the only host execution bridge. Do not start
|
|
209
281
|
another host relay or install another CLI. Verify its heartbeat, then run
|
|
210
282
|
`bin/ezenciel-agents-docker up -d --wait`.
|
|
211
283
|
|
|
212
284
|
`ezenciel-agents-setup service` is Docker-only startup: run it from the
|
|
213
285
|
deployment directory containing `docker.env`. It starts the relay and does
|
|
214
|
-
not install or start the host-executor user service. Complete
|
|
286
|
+
not install or start the host-executor user service. Complete host-capable
|
|
215
287
|
registration above separately.
|
|
216
288
|
|
|
217
289
|
5. Ask the owner to message the exact bot. Verify the pending numeric identity,
|
|
@@ -224,8 +296,8 @@ Never silently reuse a global `ez` from the old sandbox runtime.
|
|
|
224
296
|
stopped to verify repairs, then restore the poller; never replay uncertain
|
|
225
297
|
user actions merely to test delivery.
|
|
226
298
|
|
|
227
|
-
The main runtime is fully installer-owned: build it, register
|
|
228
|
-
|
|
299
|
+
The main runtime is fully installer-owned: build it, register host transport
|
|
300
|
+
only for host-capable agents, bring its Compose project up, and verify restart persistence. Plugins
|
|
229
301
|
are installed by the working Telegram agent when the owner requests their
|
|
230
302
|
capability there; account onboarding and provider confirmation follow that request.
|
|
231
303
|
Never use a missing plugin as a reason
|
|
@@ -238,9 +310,11 @@ current heartbeats and owner-bound completed-run delivery receipts without sendi
|
|
|
238
310
|
messages or exposing tokens. Receipt evidence is historical: separately verify
|
|
239
311
|
the current conversation and restart persistence before declaring setup complete.
|
|
240
312
|
|
|
241
|
-
Purpose
|
|
242
|
-
pairing, files and plugin accounts are separate.
|
|
243
|
-
|
|
313
|
+
Purpose scopes AGENTS.md once; future customization survives restart. Conversations,
|
|
314
|
+
pairing, files and plugin accounts are separate. Isolated agents use the relay
|
|
315
|
+
mount namespace as the filesystem boundary. Host-capable agents share the
|
|
316
|
+
installer UID and CLI login; that class is not a security sandbox against other
|
|
317
|
+
agents under that user.
|
|
244
318
|
Plugins run in their own containers and own their authentication. Install and
|
|
245
319
|
register them only for the requested agent. Never clone another agent's plugin
|
|
246
320
|
credentials. See [runtime, migration and QA](docker-runtime.md).
|
|
@@ -256,7 +330,7 @@ default. Existing queued jobs retain their captured execution choice.
|
|
|
256
330
|
| Symptom | Inspect and recover |
|
|
257
331
|
|---|---|
|
|
258
332
|
| Docker unavailable | Check engine and Compose, start the supported installation; complete any required OS consent. |
|
|
259
|
-
| Bot stays silent | Check pending owner identity, relay health, host heartbeat and outbox; approve only the verified owner. |
|
|
333
|
+
| Bot stays silent | Check pending owner identity, relay health, host heartbeat (host-capable only) and outbox; approve only the verified owner. |
|
|
260
334
|
| CLI exits without reply | Inspect the actual tool result and delivery receipt; stdout is not Telegram output. |
|
|
261
335
|
| Exit 73 | An existing writer holds this deployment; stop the exact duplicate, never delete the kernel lock. |
|
|
262
336
|
| Plugin absent | Check the bound catalog and install/start the reviewed package explicitly; no plugin ships by default. |
|
package/docs/standalone-cli.md
CHANGED
|
@@ -32,8 +32,9 @@ Use `ez tools list --details` for generated installed-plugin descriptions, help
|
|
|
32
32
|
Add that instruction to its existing project instructions without replacing them.
|
|
33
33
|
Use the absolute launcher, or prepend its bin directory to that session's PATH.
|
|
34
34
|
Never overwrite another global `ez`; it may belong to a different installation.
|
|
35
|
-
A company registry remains explicit even when invoked from a different
|
|
36
|
-
|
|
35
|
+
A standalone company registry remains explicit even when invoked from a different
|
|
36
|
+
directory. A relay-bound registry rejects calls from outside its workspace. Other
|
|
37
|
+
projects/accounts must use separate registries and private plugin state.
|
|
37
38
|
|
|
38
39
|
## Install and verify a capability
|
|
39
40
|
|
|
@@ -54,9 +55,9 @@ Native client plugins/connectors are not converted into Ez plugins automatically
|
|
|
54
55
|
|
|
55
56
|
A relay can coexist with CLI-only registries on the same machine. It retains its
|
|
56
57
|
own pairing, single-writer queue, mind and plugin registry. Calling its existing
|
|
57
|
-
bound launcher
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
bound launcher must be run from the owning agent workspace. Never initialize over
|
|
59
|
+
it or select it from another workspace. Coordinate writes with its active jobs.
|
|
60
|
+
Separate registries do not automatically share credentials or data.
|
|
60
61
|
|
|
61
62
|
Continuous monitoring requires a configured event consumer/relay and the plugin's
|
|
62
63
|
supported watcher. CLI-only installation does not create background agent turns.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jc_stack/ez-agents",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.34",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A lightweight foundation for persistent business AI assistants using existing AI harnesses, workspaces and plugins.",
|
|
@@ -15,7 +15,8 @@ const duration=Number(process.argv[2] || 1860),cli=process.argv[3] || 'codex'
|
|
|
15
15
|
const nativeGoal=process.argv[4]==='goal'
|
|
16
16
|
if(!Number.isSafeInteger(duration) || duration<30)throw new Error('Duration must be at least 30 seconds')
|
|
17
17
|
const root=await mkdtemp(join(tmpdir(),'ez-scheduler-smoke-')),workspace=join(root,'agent'),controlDir=join(root,'control')
|
|
18
|
-
await
|
|
18
|
+
const purpose=join(root,'purpose.md');await writeFile(purpose,'Verify native scheduled work and responsive owner chat.\n')
|
|
19
|
+
await initializeWorkspace(workspace,purpose)
|
|
19
20
|
const control=new ControlStore(controlDir,1000),scheduler=new Scheduler(controlDir),runs=new RunStore(controlDir)
|
|
20
21
|
await control.requestPairing(101,101);await control.approveOwner(101)
|
|
21
22
|
const owner=(await control.status()).owner!,execution=await control.captureChoice(initialPreset(cli))
|