@jc_stack/ez-agents 0.1.0-beta.48 → 0.1.0-beta.50
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/AGENTS.md +8 -6
- package/CHANGELOG.md +24 -0
- package/README.md +9 -5
- package/bin/ez +16 -7
- package/docker/broker-update-smoke.mjs +16 -2
- package/docker/upgrade-smoke.mjs +1 -1
- package/docs/architecture/ai-selection.md +9 -1
- package/docs/docker-runtime.md +46 -2
- package/docs/plugin-guide.md +3 -3
- package/docs/plugins.md +13 -10
- package/docs/scheduling.md +84 -6
- package/docs/setup.md +2 -2
- package/docs/standalone-cli.md +4 -4
- package/docs/upgrades.md +13 -23
- package/package.json +1 -1
- package/src/agent-guidance.ts +2 -2
- package/src/ai-cli.ts +28 -15
- package/src/ai.ts +90 -14
- package/src/application-channel.ts +18 -14
- package/src/auth-profile.ts +53 -0
- package/src/codex-session.ts +14 -3
- package/src/control-state.ts +28 -21
- package/src/delivery-socket.ts +2 -0
- package/src/executor.ts +38 -26
- package/src/host-executor-client.ts +19 -7
- package/src/host-executor.ts +35 -10
- package/src/index.ts +320 -122
- package/src/menu.ts +8 -7
- package/src/plugin-broker.mjs +4 -11
- package/src/plugins/manager.mjs +70 -48
- package/src/runs.ts +74 -5
- package/src/schedule-cli.ts +39 -7
- package/src/scheduled-tasks.ts +42 -8
- package/src/scheduler.ts +9 -4
- package/src/session-close.ts +17 -0
- package/src/setup-fallback.ts +159 -0
- package/src/task-executor.ts +3 -2
- package/src/tools-line.d.mts +1 -0
- package/src/tools-line.mjs +3 -0
- package/src/updates/binding.mjs +4 -10
- package/src/updates/control.mjs +3 -2
- package/src/updates/runtime.mjs +79 -41
- package/src/updates/supervisor.mjs +27 -6
- package/src/workspace.ts +12 -1
- package/test/ai.test.ts +48 -2
- package/test/application-channel.test.ts +24 -0
- package/test/application-controls.test.ts +4 -1
- package/test/auth-profiles.test.ts +187 -0
- package/test/intake-relay.test.ts +63 -2
- package/test/model-policy.test.ts +1 -1
- package/test/plugin-broker.test.mjs +51 -1
- package/test/plugin-manager.test.mjs +76 -38
- package/test/run-handoff.test.ts +132 -0
- package/test/scheduled-tasks.test.ts +24 -2
- package/test/session-close.test.ts +17 -0
- package/test/setup-fallback.test.ts +423 -0
- package/test/updates.test.mjs +77 -15
- package/test/workspace.test.ts +6 -0
package/AGENTS.md
CHANGED
|
@@ -16,11 +16,13 @@ through one generic transport, with separate agent workspaces and sessions.
|
|
|
16
16
|
|
|
17
17
|
## Operating-agent instructions
|
|
18
18
|
|
|
19
|
-
Do not inject a coding handbook into production agent minds. The
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
Do not inject a coding handbook into production agent minds. The only
|
|
20
|
+
package-written `AGENTS.md` text is the initial workspace seed: purpose, a short
|
|
21
|
+
engine-neutral `memory/` note and one static line pointing at
|
|
22
|
+
`ez tools list --details`. After seeding the agent owns `AGENTS.md`; inventory is
|
|
23
|
+
generated on read, so do not hardcode command recipes. The one transport-level
|
|
24
|
+
lifecycle prompt is the silent conversation-close turn (`src/session-close.ts`),
|
|
25
|
+
which runs only for owner conversations. Coding defaults for this repository stay in this file and
|
|
24
26
|
CONTRIBUTING.md.
|
|
25
27
|
|
|
26
28
|
## Installing this package
|
|
@@ -105,7 +107,7 @@ If no answer identifies a material blocker, finish. Do not start another review
|
|
|
105
107
|
round merely to seek more criticism, tests or hypothetical edge cases.
|
|
106
108
|
|
|
107
109
|
## 3. Crash-Safe Disk State
|
|
108
|
-
- Persistent authority state (`ControlStore` owner/pairing/sessions/presets, application bindings, schedule definitions) stays in disk-backed JSON files. Run/outbox/inbox bookkeeping is relay memory reached through the delivery socket (`src/delivery-socket.ts`): a restart drops in-flight runs and queued deliveries by design, uncertain sends report unknown rather than success, and Telegram redelivery is the replay mechanism. The live delivery socket also replaces the relay flock as the single-relay guard.
|
|
110
|
+
- Persistent authority state (`ControlStore` owner/pairing/sessions/presets, application bindings, schedule definitions) stays in disk-backed JSON files. Run/outbox/inbox bookkeeping is relay memory reached through the delivery socket (`src/delivery-socket.ts`): a restart drops in-flight runs and queued deliveries by design, uncertain sends report unknown rather than success, and Telegram redelivery is the replay mechanism. The one exception: a graceful stop hands running host-transport runs, whose executors outlive the relay, to the next relay through private `control/run-handoff.json`; that relay adopts and watches them and never relaunches one. The live delivery socket also replaces the relay flock as the single-relay guard.
|
|
109
111
|
- **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.
|
|
110
112
|
- **Path sanitization:** Every ID parameter (`runId`, `outboxId`, `pairingId`) must be validated against `/^[a-zA-Z0-9_-]+$/` before being joined into paths. Never allow directory traversal (`..`).
|
|
111
113
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.50
|
|
4
|
+
|
|
5
|
+
- Share memory across engines through the workspace. New workspaces seed a short `## Memory` note (durable facts in `memory/`, one per file, indexed in `memory/MEMORY.md`); every engine loads `AGENTS.md`, so Codex and Claude read the same files. When a chat conversation is replaced (`/new`, the New button, web app new, or an AI/provider switch), its engine gets one silent turn in that native session to save durable facts; nothing is delivered and the engine decides what to write.
|
|
6
|
+
- Drop the managed `<!-- ez tools -->` AGENTS.md footer. The install seed writes one static line ("Tools: run `ez tools list --details`; each plugin's `--help` gives usage."); update binding replaces an existing footer with that line once and otherwise never writes instructions. `ez tools list --details` now prints per plugin `aliases`, `purpose`, `skills`, `skillReads` and one `example` call (optional manifest `example`, else `<alias> --help`).
|
|
7
|
+
- Stop reporting a live plugin call as a stale lease on isolated agents. Leases record their PID namespace; a lease written in the broker container is judged by its call container's running state, so `ez updates apply` no longer refuses during in-flight calls. Apply and recover only queue the job; main activation now drains in-flight calls before switching instead of failing.
|
|
8
|
+
- Keep host-capable native runs alive across a graceful relay restart. The stopping relay hands running host-transport runs to the next relay instead of cancelling them; it adopts and watches each run with its schedule hold, concurrency slot and message delivery, and records its exit status. Nothing is relaunched; a run that cannot be adopted or whose outcome is unknown is recorded failed and interrupted, holding its schedule, and a run that fails adoption is asked to stop. Core upgrades still wait for idle native work; isolated agents, crashes and queued work keep the previous behavior.
|
|
9
|
+
- Continue a scheduled occurrence on its next saved login when Claude stops at a usage/session limit after work began. The next setup starts a fresh native session with the saved prompt plus one factual line naming the run, stopped setup, its native session and reset time. Only a typed quota rejection the run ended on continues; work after a limit, access denial, other failures, cancellation and unknown outcomes still stop without replay. Attempts record `quota-after-work-began` and each Ez-assigned session ID.
|
|
10
|
+
- Stop isolated plugin calls hanging silently before reaching the broker when the caller leaves a socket stdin open (native engine shells, async Node spawns). Pipes and files are still read to EOF; a socket that sends nothing for one second is treated as no input. Remove a uniquely named call container whenever Compose exits non-zero, so a call that stops between create and start no longer strands it in `Created`.
|
|
11
|
+
- Advance scheduled work to its next saved login after a typed authentication rejection before work. Recognize Claude API-error metadata without marking analysis started; account/organization denials, hooks, model/tool work and uncertain outcomes still stop fallback. Preserve the saved chain for the next occurrence.
|
|
12
|
+
- Let scheduled fallback setups name an owner-provisioned native login profile per setup, with no fixed list length. A quota rejection skips later setups on the same login profile while other accounts stay eligible; model/tool/hook work, access denial, cancellation and uncertain failures still stop the chain.
|
|
13
|
+
- Show each scheduled task's frequency and full primary → fallback path (CLI, login profile, provider, model, effort) in Telegram `/tasks` and `/tasks N`.
|
|
14
|
+
- Report the exact AI selection error (missing client models, missing model, unsupported effort) instead of a generic invalid selection, without changing the saved choice.
|
|
15
|
+
|
|
16
|
+
Beta limits: live fresh-host/reboot acceptance, a live host-capable relay recreate during a running native run, two-real-account channel switching and real exhausted-account/provider rejection remain pending. An adopted scheduled occurrence does not advance to fallback setups, and messages a run sends while no relay is up still fail. The conversation close turn is engine-decided and runs only for owner conversations; existing workspaces do not receive the `## Memory` seed note automatically. Plugin manifests may declare `example`; a plugin that does requires core 0.1.0-beta.50 or newer, and older cores refuse that plugin update (manifest validation) and keep the installed version until core upgrades. Publication does not establish an installed-agent upgrade or authorize provider/domain writes.
|
|
17
|
+
|
|
18
|
+
## 0.1.0-beta.49
|
|
19
|
+
|
|
20
|
+
- Upgrade compatible plugins while native work continues, draining in-flight plugin calls for activation and preserving rollback. Core updates still wait for idle.
|
|
21
|
+
- Keep separate named Codex and Claude native login homes, with account-bound conversations, profile-aware model selection and fail-closed admission.
|
|
22
|
+
- Try ordered saved setups for a scheduled task only after a typed failure before work begins. Hooks, model/tool activity, access denial, cancellation and uncertain transport stop fallback; quota rejection skips the same native CLI/provider scope.
|
|
23
|
+
- Preserve each scheduled attempt's captured auth profile and admit only the active setup on the host transport.
|
|
24
|
+
|
|
25
|
+
Beta limits: live fresh-host/reboot acceptance, two-real-account channel switching and real exhausted-account/provider rejection remain pending. Fallback applies to scheduled agent tasks only; OpenCode/Pi/Grok advance only when their CLI is unavailable. The fallback command does not select named profiles, and different credentials do not establish independent quota allowances. Publication does not establish an installed-agent upgrade or authorize provider/domain writes.
|
|
26
|
+
|
|
3
27
|
## 0.1.0-beta.48
|
|
4
28
|
|
|
5
29
|
- Skip empty or unchanged scheduled work through owner-configured installed read-only plugin preflight. Invalid or unavailable reads fail closed; saved execution settings and recurring timing remain intact. The bound plugin broker is required.
|
package/README.md
CHANGED
|
@@ -172,7 +172,8 @@ transport, with separate agent workspaces and sessions. See
|
|
|
172
172
|
|
|
173
173
|
Telegram `/status` shows the running relay and host versions plus installed
|
|
174
174
|
plugin versions. Its read-only **Scheduled tasks** control lists the paired
|
|
175
|
-
owner's active schedules in alphabetical order, with their
|
|
175
|
+
owner's active schedules in alphabetical order, with their frequency/timezone
|
|
176
|
+
and ordered CLI/login-profile/model/effort execution path (primary → fallbacks),
|
|
176
177
|
next occurrence or current queued/running state, and a short preview of the
|
|
177
178
|
saved invocation prompt; it never creates, changes or runs a task. The agent's `ez status` adds verified plugin
|
|
178
179
|
runtime states and upgrade job receipts. See [status and upgrades](docs/upgrades.md).
|
|
@@ -260,11 +261,14 @@ restart and shutdown. Host-capable agents register the small host CLI transport
|
|
|
260
261
|
|
|
261
262
|
The selected host CLI runs in this agent's persistent workspace and owns its
|
|
262
263
|
Markdown/work files. New conversations and AI changes preserve those files.
|
|
263
|
-
One compact `AGENTS.md` is seeded with the installer purpose
|
|
264
|
-
|
|
264
|
+
One compact `AGENTS.md` is seeded with the installer purpose, a short note to
|
|
265
|
+
keep durable facts in `memory/` (one fact per file, indexed in `memory/MEMORY.md`)
|
|
266
|
+
and one line pointing at `ez tools list --details`. Every engine loads `AGENTS.md`,
|
|
267
|
+
so they share that memory. When a chat conversation is replaced (new conversation
|
|
268
|
+
or AI/provider change), its engine gets one silent turn to save durable facts. The installing LLM authors the initial brief from the owner's request
|
|
265
269
|
and known application context; Ez stores it without trying to infer the product
|
|
266
|
-
itself. Installed plugin
|
|
267
|
-
`ez tools list --details
|
|
270
|
+
itself. Installed plugin aliases, purposes, skills and examples come from
|
|
271
|
+
`ez tools list --details`; no tool inventory file needs maintenance.
|
|
268
272
|
Credentials and control state stay outside the mind. Isolated agents use relay
|
|
269
273
|
mounts as the filesystem boundary. Host-capable file separation is not OS
|
|
270
274
|
isolation against a process running as the same user.
|
package/bin/ez
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createConnection } from 'node:net';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { fstatSync } from 'node:fs';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
5
6
|
import { installedNativeHelp } from '../src/plugins/native-tasks.mjs';
|
|
6
7
|
|
|
7
8
|
const MAX_STDIN_BYTES = 1024 * 1024;
|
|
9
|
+
const SOCKET_STDIN_IDLE_MS = 1000;
|
|
8
10
|
const RUN_ID = /^[A-Za-z0-9_-]{1,160}$/;
|
|
9
11
|
const socketPath = process.env.EZ_PLUGIN_BROKER_SOCKET?.trim();
|
|
10
12
|
const runId = process.env.EZ_RUN_ID?.trim();
|
|
@@ -50,18 +52,25 @@ const request = (payload, signal = undefined) => new Promise((resolve, reject) =
|
|
|
50
52
|
socket.on('connect', () => socket.write(JSON.stringify(payload) + '\n'));
|
|
51
53
|
});
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
// Pipes and files always end, so read them to EOF. A socket is how Node-based
|
|
56
|
+
// parents (native engine shells, agent scripts) wire child stdio, and they
|
|
57
|
+
// often pass it on without ever closing it. Waiting for that EOF hung calls
|
|
58
|
+
// before the broker was contacted, so a socket that stays silent means no input.
|
|
59
|
+
const readStdin = () => new Promise((resolve, reject) => {
|
|
60
|
+
if (process.stdin.isTTY) return resolve('');
|
|
55
61
|
const chunks = [];
|
|
56
62
|
let bytes = 0;
|
|
57
|
-
|
|
63
|
+
const idle = fstatSync(0).isSocket() ? setTimeout(() => { process.stdin.destroy(); resolve(''); }, SOCKET_STDIN_IDLE_MS) : undefined;
|
|
64
|
+
process.stdin.on('data', chunk => {
|
|
65
|
+
clearTimeout(idle);
|
|
58
66
|
const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
59
67
|
bytes += value.length;
|
|
60
|
-
if (bytes > MAX_STDIN_BYTES)
|
|
68
|
+
if (bytes > MAX_STDIN_BYTES) { process.stdin.destroy(); return reject(Error('plugin stdin exceeds the broker limit')); }
|
|
61
69
|
chunks.push(value);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
};
|
|
70
|
+
});
|
|
71
|
+
process.stdin.once('end', () => { clearTimeout(idle); resolve(Buffer.concat(chunks).toString('utf8')); });
|
|
72
|
+
process.stdin.once('error', error => { clearTimeout(idle); reject(error); });
|
|
73
|
+
});
|
|
65
74
|
|
|
66
75
|
const invoke = async (args, stdin) => {
|
|
67
76
|
if (!runId || !RUN_ID.test(runId)) throw Error('EZ_RUN_ID is required for an isolated plugin command');
|
|
@@ -6,8 +6,8 @@ import path from 'node:path';
|
|
|
6
6
|
import assert from 'node:assert/strict';
|
|
7
7
|
import { execFileSync } from 'node:child_process';
|
|
8
8
|
import { createHash } from 'node:crypto';
|
|
9
|
-
import { atomic, snapshot } from '../src/plugins/manager.mjs';
|
|
10
|
-
import { execute, refreshBroker } from '../src/updates/runtime.mjs';
|
|
9
|
+
import { atomic, snapshot, publishBrokerPlugins } from '../src/plugins/manager.mjs';
|
|
10
|
+
import { execute, refreshBroker, verifyBroker, brokerNeedsRefresh } from '../src/updates/runtime.mjs';
|
|
11
11
|
const docker=(...args)=>execFileSync('docker',args,{encoding:'utf8',stdio:['ignore','pipe','pipe'],timeout:120000}).trim();
|
|
12
12
|
const hash=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
13
13
|
if(process.argv[2]!=='--inside') {
|
|
@@ -69,6 +69,20 @@ if(process.argv[2]!=='--inside') {
|
|
|
69
69
|
assert.equal((await mounted()).trim(),ready.hostSha256);assert.equal((await prepare()).trim(),'prepared');
|
|
70
70
|
assert.equal(ready.plugins[0].revision,b.revision);
|
|
71
71
|
console.log(JSON.stringify({stage:'activation',oldBroker,newBroker,relay,hostSha256:ready.hostSha256,registrySha256:ready.registrySha256,revision:b.revision}));
|
|
72
|
+
// With the current host binding already approving both revisions, plugin-only
|
|
73
|
+
// activation/rollback must leave the broker socket and relay intact.
|
|
74
|
+
await publish(a);await publishBrokerPlugins(home,controlDir);
|
|
75
|
+
const pluginRollback=await verifyBroker(config);
|
|
76
|
+
assert.equal(pluginRollback.plugins[0].revision,a.revision);
|
|
77
|
+
assert.equal(await container('plugin-broker'),newBroker);assert.equal(await container('relay'),relay);
|
|
78
|
+
assert.equal(await brokerNeedsRefresh(config),false);assert.equal((await prepare()).trim(),'prepared');
|
|
79
|
+
await publish(b);await publishBrokerPlugins(home,controlDir);
|
|
80
|
+
const pluginActivation=await verifyBroker(config);
|
|
81
|
+
assert.equal(pluginActivation.plugins[0].revision,b.revision);
|
|
82
|
+
assert.equal(await container('plugin-broker'),newBroker);assert.equal(await container('relay'),relay);
|
|
83
|
+
assert.equal((await prepare()).trim(),'prepared');
|
|
84
|
+
console.log('PASS plugin activation/rollback: current registry accepted; broker and relay IDs preserved');
|
|
85
|
+
|
|
72
86
|
await atomic(hostConfig,host([a.revision]));
|
|
73
87
|
await assert.rejects(refreshBroker(config),/STRUCTURAL_READINESS_FAILED/);await assert.rejects(prepare(),/not pinned/);
|
|
74
88
|
console.log('PASS unapproved B remains rejected after recreation');
|
package/docker/upgrade-smoke.mjs
CHANGED
|
@@ -14,7 +14,7 @@ const exec=promisify(execFile),root=await fs.realpath(await fs.mkdtemp(path.join
|
|
|
14
14
|
const source=path.join(root,'source'),home=path.join(root,'tools'),mind=path.join(root,'mind'),control=path.join(root,'control');
|
|
15
15
|
const input=path.resolve(process.env.EZ_WHATSAPP_SOURCE||new URL('../../ez_whatsapp',import.meta.url).pathname);
|
|
16
16
|
const bin=new URL('../bin/ezenciel-agents-tools.mjs',import.meta.url).pathname;
|
|
17
|
-
const call=async(...args)=>JSON.parse((await exec(process.execPath,[bin,'--home',home,...args],{maxBuffer:4*1024*1024})).stdout);
|
|
17
|
+
const call=async(...args)=>JSON.parse((await exec(process.execPath,[bin,'--home',home,...args],{cwd:mind,maxBuffer:4*1024*1024})).stdout);
|
|
18
18
|
let record;
|
|
19
19
|
try {
|
|
20
20
|
for(const dir of [source,mind,control])await fs.mkdir(dir);
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
`menu.ts` owns Telegram controls; `ai.ts` projects installed-client metadata.
|
|
4
4
|
`ControlStore` stores saved presets, the next-conversation default and current choice.
|
|
5
5
|
No provider SDK, model fallback, history migration, or second execution loop.
|
|
6
|
+
A missing catalog entry rejects selection without changing the conversation.
|
|
7
|
+
An unsupported effort reports the exact installed model's advertised levels.
|
|
8
|
+
Missing selectable models do not establish that the active native session is
|
|
9
|
+
unavailable, and editing a scheduled task does not change the chat selection.
|
|
6
10
|
|
|
7
11
|
At intake each journal entry receives an immutable preset and conversation ID.
|
|
8
12
|
Batches cannot cross that boundary. The run copies that choice and invokes the
|
|
@@ -12,7 +16,11 @@ Each named conversation saves its model and reasoning level. Switching back thro
|
|
|
12
16
|
`/ai` shows the current choice and saves changes immediately. Changing model or
|
|
13
17
|
reasoning level on the same client and provider preserves the conversation's name
|
|
14
18
|
and native history; subsequent turns pass the new settings to the native engine.
|
|
15
|
-
Changing client or
|
|
19
|
+
Changing client, provider or auth profile starts a separate native conversation.
|
|
20
|
+
A conversation records its client and auth profile when created; launch rejects a
|
|
21
|
+
choice for another profile, so a native session never resumes under another
|
|
22
|
+
account. Provisioned profiles appear as additional catalog entries for their
|
|
23
|
+
client (see [auth profiles](../docker-runtime.md#auth-profiles)). Old bindings
|
|
16
24
|
remain available so accepted work can finish and owners can reopen their chats.
|
|
17
25
|
|
|
18
26
|
Grok/Claude accept caller-selected native UUIDs. Codex/OpenCode generate IDs, so
|
package/docs/docker-runtime.md
CHANGED
|
@@ -141,6 +141,18 @@ An interrupted Telegram poller keeps authorized work and in-flight deliveries
|
|
|
141
141
|
alive while it retries intake. Run and delivery records are relay memory: a
|
|
142
142
|
relay process restart drops in-flight work by design, Telegram redelivery is the
|
|
143
143
|
intake replay path, and uncertain sends report unknown instead of success.
|
|
144
|
+
Host-capable agents are the exception for running work: their native CLIs run under
|
|
145
|
+
the host transport, so a graceful relay stop (Compose recreate, Docker restart)
|
|
146
|
+
writes those running runs to private `control/run-handoff.json` instead of
|
|
147
|
+
cancelling them. The next relay adopts each one, keeps its concurrency slot and
|
|
148
|
+
schedule hold, accepts its messages and records its exit status; it never
|
|
149
|
+
relaunches a run. A run whose outcome is unknown (no request, claim or result
|
|
150
|
+
record, or an adoption failure) is recorded failed and interrupted, which holds
|
|
151
|
+
its schedule until an explicit edit; the host is asked to cancel it. A request
|
|
152
|
+
the host had not claimed before the relay stopped is failed by the host without
|
|
153
|
+
starting. Records older than 24 hours are ignored, and the file is removed on
|
|
154
|
+
every start. Queued runs and deliveries are still dropped, and messages a run
|
|
155
|
+
sends while no relay is up fail and need a retry.
|
|
144
156
|
A `409 Conflict` still requires the operator to stop the competing poller; it
|
|
145
157
|
remains unhealthy after the startup grace. Pending and uncertain deliveries keep
|
|
146
158
|
their existing receipt semantics; executor stdout is not replayed as a reply.
|
|
@@ -196,8 +208,12 @@ The image pins modern Docker Compose, including its standalone executable, so
|
|
|
196
208
|
existing operator-created volumes retain their data and driver bindings.
|
|
197
209
|
|
|
198
210
|
The relay-side `ez` client sends only declared aliases, literal argument arrays,
|
|
199
|
-
bounded stdin, and the active run ID to the broker.
|
|
200
|
-
|
|
211
|
+
bounded stdin, and the active run ID to the broker. It reads a piped or
|
|
212
|
+
redirected stdin to EOF. A socket stdin, which native engine shells and Node
|
|
213
|
+
child processes often leave open, counts as no input unless data arrives within
|
|
214
|
+
one second; write and close it immediately when a command needs input. The
|
|
215
|
+
broker re-reads owner authority and the registry before every call, pins the
|
|
216
|
+
discovered revision, and
|
|
201
217
|
passes only the installed plugin's `run.application.context.plugins[plugin-id]`
|
|
202
218
|
object as `EZ_PLUGIN_CONTEXT`. Missing, revoked, cross-agent, expired, or reused
|
|
203
219
|
admissions fail closed. Timeouts, cancellation and bounded output produce a
|
|
@@ -295,6 +311,34 @@ Without any login, Claude turns fail closed with the native "not logged in"
|
|
|
295
311
|
error. Host-capable agents use the same agent-bound directory but share the
|
|
296
312
|
installer login in place (`CLAUDE_SECURESTORAGE_CONFIG_DIR` empty).
|
|
297
313
|
|
|
314
|
+
## Auth profiles
|
|
315
|
+
|
|
316
|
+
One agent can keep several owner-provisioned Codex or Claude logins, for example
|
|
317
|
+
a work and a personal account. Each named profile is a separate native home,
|
|
318
|
+
`control/cli/profiles/<name>/<cli>` (`CODEX_HOME` or `CLAUDE_CONFIG_DIR`), with
|
|
319
|
+
its own credentials, configuration and native sessions. The unnamed default
|
|
320
|
+
keeps the bindings above unchanged. Create the empty home and get the exact
|
|
321
|
+
native login command with:
|
|
322
|
+
|
|
323
|
+
```sh
|
|
324
|
+
ezenciel-agents-ai profile add --cli claude --auth-profile work
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Then the owner logs in once with the printed command, inside the relay for
|
|
328
|
+
isolated agents. Claude may instead use a `claude setup-token` token in that
|
|
329
|
+
home's `oauth-token` (mode `600`). Ez never reads, copies or prints the
|
|
330
|
+
credential. A named profile never links the host login or another home: an
|
|
331
|
+
unprovisioned or logged-out profile fails closed with the native error.
|
|
332
|
+
`ezenciel-agents-ai profiles` reports each home's login status (logged in,
|
|
333
|
+
method, credential file names) from the native CLI without tokens or account
|
|
334
|
+
identifiers.
|
|
335
|
+
|
|
336
|
+
Select a profile with `ezenciel-agents-ai select --cli claude --auth-profile work`,
|
|
337
|
+
the profile entries in Choose AI, or `ezenciel-agents-schedule create ...
|
|
338
|
+
--auth-profile work`. A conversation is bound to its CLI and profile; changing
|
|
339
|
+
profile starts a new native conversation, and a run whose request names another
|
|
340
|
+
profile than its captured choice is rejected before launch.
|
|
341
|
+
|
|
298
342
|
## OpenCode auth
|
|
299
343
|
|
|
300
344
|
Isolated agents run the image OpenCode with `XDG_DATA_HOME` set to the
|
package/docs/plugin-guide.md
CHANGED
|
@@ -57,14 +57,14 @@ At minimum, provide:
|
|
|
57
57
|
machine-readable commands, stable exit codes, and readback for writes.
|
|
58
58
|
|
|
59
59
|
The manager snapshots the package according to `package.json.files` plus the
|
|
60
|
-
required manifests and Docker inputs. `ez tools list --details`
|
|
60
|
+
required manifests and Docker inputs. `ez tools list --details` prints aliases, purpose, skill paths, one example call
|
|
61
|
+
(the optional manifest `example`, else `<alias> --help`) and
|
|
61
62
|
`skillReads`: literal command argument arrays for reading each installed skill.
|
|
62
63
|
Use `ez tools skill <plugin> <declared-path>` to return its text and pinned
|
|
63
64
|
revision. The isolated executor cannot open private host package paths directly;
|
|
64
65
|
the authorized broker reads only manifest-declared regular skill files, without
|
|
65
66
|
copying them into the agent workspace. Skill reads reject symlinks and files over
|
|
66
|
-
64 KiB.
|
|
67
|
-
usage snippet or per-turn instruction is needed for this read contract.
|
|
67
|
+
64 KiB. No AGENTS.md text or per-turn instruction is needed for this read contract.
|
|
68
68
|
|
|
69
69
|
Keep one canonical checkout; do not keep
|
|
70
70
|
permanent packaged copies or a second registry. See the full
|
package/docs/plugins.md
CHANGED
|
@@ -27,8 +27,7 @@ node /absolute/ezenciel_agents/bin/ezenciel-agents-tools.mjs init \
|
|
|
27
27
|
Without `--catalog`, init loads an empty packaged catalog. Keep it empty for
|
|
28
28
|
initial main onboarding; no sibling repository, broker or provider account is
|
|
29
29
|
needed. Finish owner pairing and verify an actual Telegram agent reply first.
|
|
30
|
-
Init creates a private registry and `tools/bin/ez
|
|
31
|
-
managed AGENTS.md registry locator, and binds the matching host executor to that bin
|
|
30
|
+
Init creates a private registry and `tools/bin/ez` and binds the matching host executor to that bin
|
|
32
31
|
folder. Native binaries are linked through; the package's own `bin/ez` is replaced
|
|
33
32
|
by that bound launcher, while an unrelated existing `ez` collision fails.
|
|
34
33
|
Both host-bound and isolated `ez --help` list installed native scheduling and delivery helpers
|
|
@@ -307,8 +306,10 @@ never a source of network attachment authority.
|
|
|
307
306
|
|
|
308
307
|
Commands run in one-shot client containers against their own service's volumes;
|
|
309
308
|
stdin, stdout, stderr, literal arguments and exit codes are preserved. SIGINT/
|
|
310
|
-
SIGTERM cancel the Docker call and remove its unique client container
|
|
311
|
-
|
|
309
|
+
SIGTERM cancel the Docker call and remove its unique client container; a Compose
|
|
310
|
+
exit with a non-zero status also removes it, so a call that stopped between
|
|
311
|
+
create and start never remains `Created`. The manager never retries a provider
|
|
312
|
+
operation. Service startup/restart is explicit; commands
|
|
312
313
|
never implicitly start a stopped provider service. Plugin data does not enter the
|
|
313
314
|
relay. The manager sends only a whitelist of Docker client environment variables.
|
|
314
315
|
|
|
@@ -412,10 +413,12 @@ QMD runtimes or edit installed Compose/package files to bypass missing support.
|
|
|
412
413
|
|
|
413
414
|
## Generated capability discovery
|
|
414
415
|
|
|
415
|
-
`ez tools list --details` generates a
|
|
416
|
-
`ez-plugin.json` manifests
|
|
417
|
-
|
|
418
|
-
|
|
416
|
+
`ez tools list --details` generates a self-sufficient index directly from
|
|
417
|
+
installed `ez-plugin.json` manifests. Per plugin it prints `aliases`, a one-line
|
|
418
|
+
`purpose` (the manifest `description`, at most 200 characters), absolute `skills`
|
|
419
|
+
paths and one `example` call. The optional manifest `example` is one line of at
|
|
420
|
+
most 160 characters starting with a declared command alias; without it the
|
|
421
|
+
example is `ez <first alias> --help`. Full instructions stay in the skill. Installation, replacement and removal are reflected
|
|
419
422
|
on the next read, without hooks, LLM calls or a cached inventory file.
|
|
420
423
|
|
|
421
424
|
The additive `skillReads` field supplies literal argument arrays for
|
|
@@ -424,8 +427,8 @@ installed plugin revision, declared path and skill content. Use it in isolated
|
|
|
424
427
|
agents, where host package paths are private. It reads only the installed
|
|
425
428
|
manifest's skills; arbitrary files, symlinks and files over 64 KiB are rejected.
|
|
426
429
|
|
|
427
|
-
`ez tools list` retains its alias mapping for existing clients.
|
|
428
|
-
|
|
430
|
+
`ez tools list` retains its alias mapping for existing clients. The workspace
|
|
431
|
+
seed writes one static line pointing here; nothing else is written. New workspaces do not seed
|
|
429
432
|
TOOLS.md, SOUL.md, USER.md, or an `inbox/`/`work/` layout; upgrades preserve
|
|
430
433
|
legacy notes without rewriting them. Keep owner/account policies in agent
|
|
431
434
|
instructions or linked policy files, separate from plugin metadata.
|
package/docs/scheduling.md
CHANGED
|
@@ -55,6 +55,75 @@ Paused, stale-owner, overlapping or held tasks and unmet conditions cannot be
|
|
|
55
55
|
triggered. Historical deferred tasks keep their source context
|
|
56
56
|
available through `ezenciel-agents-schedule context`.
|
|
57
57
|
|
|
58
|
+
## Ordered setup fallback
|
|
59
|
+
|
|
60
|
+
An agent task may list ordered fallback setups after its saved one, for
|
|
61
|
+
example `claude · opus → claude · sonnet → codex · gpt-6-sol`:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
ezenciel-agents-schedule create --name Daily --cli claude --model opus \
|
|
65
|
+
--cron '0 9 * * *' --timezone Asia/Dubai --text 'Prepare the daily report.' \
|
|
66
|
+
--fallback cli=claude,model=sonnet,effort=medium --fallback cli=codex,model=gpt-6-sol
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`edit` keeps the saved fallbacks unless `--fallback` replaces them or
|
|
70
|
+
`--clear-fallbacks` removes them. Setups must be distinct and each needs a model.
|
|
71
|
+
There is no fixed list-length limit. Each setup captures its own supported CLI,
|
|
72
|
+
model, effort and optional provider; the installed native client owns valid model
|
|
73
|
+
and effort values. The existing failure rules below apply to every setup.
|
|
74
|
+
Each fallback may include `auth-profile=NAME` to select its own owner-provisioned
|
|
75
|
+
Codex or Claude account. Omitting it selects the default login, independently of
|
|
76
|
+
the primary setup. For four separate Claude accounts, provision and log into
|
|
77
|
+
`claude2`, `claude3` and `claude4`, then use:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
ezenciel-agents-schedule create --name Daily --cli claude --model opus \
|
|
81
|
+
--cron '0 9 * * *' --timezone Asia/Dubai --text 'Prepare the daily report.' \
|
|
82
|
+
--fallback cli=claude,model=opus,auth-profile=claude2 \
|
|
83
|
+
--fallback cli=claude,model=opus,auth-profile=claude3 \
|
|
84
|
+
--fallback cli=claude,model=opus,auth-profile=claude4
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Core advances to the next setup only with typed evidence that nothing ran: the
|
|
88
|
+
CLI is not installed or executable, or the provider rejected the turn before any
|
|
89
|
+
model output, tool or hook item (quota/rate limit, billing, overload, server
|
|
90
|
+
error, unavailable model or bad request), including a missing, expired or revoked
|
|
91
|
+
login (typed authentication failure or HTTP401). Native API-error metadata does
|
|
92
|
+
not count as model/tool work. It stops, without replay, on access
|
|
93
|
+
denial (HTTP403, account or organization restriction), cancellation, relay shutdown,
|
|
94
|
+
a schedule edit, a policy or unknown error, an interrupted transport, or any
|
|
95
|
+
other failure after work began. Evidence comes from structured events only: Codex
|
|
96
|
+
native-session `codexErrorInfo` and Claude `stream-json` error fields (scheduled
|
|
97
|
+
Claude runs use `--output-format stream-json`; the host forwards only a compact
|
|
98
|
+
startup summary). Other engines advance only when their CLI is unavailable.
|
|
99
|
+
|
|
100
|
+
The one failure after work began that continues is a Claude usage limit the run
|
|
101
|
+
ended on (for example "You've hit your session limit"): a typed quota rejection
|
|
102
|
+
with no model, tool or hook activity after it. A native session cannot be resumed
|
|
103
|
+
under another login's configuration home, so the next eligible setup starts a fresh
|
|
104
|
+
session with the saved prompt plus one factual line naming the run, the stopped
|
|
105
|
+
setup, its native session and reset time, and that its work may be partly applied.
|
|
106
|
+
The agent reconciles from its own records; core replays nothing else.
|
|
107
|
+
|
|
108
|
+
A login or quota rejection skips the remaining setups in the same scope: the native
|
|
109
|
+
client and login profile (`claude`, `codex` including desktop and custom Codex
|
|
110
|
+
providers), `grok`, or the upstream provider for OpenCode/Pi models. A named
|
|
111
|
+
profile selects a separate owner-provisioned account and is eligible for its own
|
|
112
|
+
attempt; changing only the model in the same profile does not reset its scope.
|
|
113
|
+
Do not provision aliases of the same account to obtain more allowance. Ez does
|
|
114
|
+
not infer account independence from credentials or promise that a shared
|
|
115
|
+
organization's allowance is separate. Each setup runs at most once per occurrence.
|
|
116
|
+
|
|
117
|
+
Every attempt keeps the same run ID, occurrence, schedule revision, workspace,
|
|
118
|
+
delivery binding and scheduled concurrency slot, in a fresh native session.
|
|
119
|
+
`run RUN_ID` shows `attempts`: each setup, quota scope, outcome, failure category
|
|
120
|
+
(`cli-unavailable`, `login-unavailable`, `quota`, `provider-rejected`, `access-denied`,
|
|
121
|
+
`quota-after-work-began`, `after-work-began`, `uncertain`, or `same-login-scope`/`same-quota-scope`
|
|
122
|
+
for a skipped setup), exit code, reported reset time and the session ID Ez assigned. If every setup is unavailable the run fails with
|
|
123
|
+
reason `setups-unavailable`, a summary of each setup, and an owner notice on
|
|
124
|
+
Telegram-bound tasks. Core never purchases credits, enables overage or consumes
|
|
125
|
+
reset credits; the next regular occurrence runs normally.
|
|
126
|
+
|
|
58
127
|
## Registered script schedules
|
|
59
128
|
|
|
60
129
|
A schedule has one execution type. **Agent** schedules run the saved prompt with
|
|
@@ -184,10 +253,13 @@ queued occurrence; already-running work continues until explicitly cancelled.
|
|
|
184
253
|
|
|
185
254
|
`/stop` stops all active work; `cancel RUN_ID` stops one background task. `/cancel`
|
|
186
255
|
clears queued work. Pause/remove a recurring schedule to prevent future runs.
|
|
187
|
-
Stopping the relay also stops its workers
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
256
|
+
Stopping the relay also stops its workers, except on host-capable agents: a
|
|
257
|
+
graceful relay stop hands running host-transport runs to the next relay, which
|
|
258
|
+
adopts them without relaunching (see [Docker runtime](docker-runtime.md)). A
|
|
259
|
+
request the host had not yet claimed when the relay stopped is failed by the host
|
|
260
|
+
without starting. Run and delivery records are otherwise relay memory: a process
|
|
261
|
+
restart drops in-flight runs and queued deliveries by design, so the next
|
|
262
|
+
eligible occurrence dispatches normally and nothing is replayed from disk. Status labels failed runs as history and shows recent reasons; new failures retain their exit code or interruption cause. Typing indicators stop after 30 seconds even when work continues. A failed run that cannot prove whether an external side effect happened stays visible until the agent inspects the evidence and explicitly edits the schedule. Inspect the task's files, native session and delivery
|
|
191
263
|
receipts before deciding whether to resume. A clock cannot reconstruct an
|
|
192
264
|
in-flight process or prove whether an external side effect happened.
|
|
193
265
|
|
|
@@ -269,7 +341,13 @@ The prompt controls diagnosis, authorized recovery and quiet notification behavi
|
|
|
269
341
|
The Telegram Scheduled tasks menu lists enabled schedules that still have a pending
|
|
270
342
|
occurrence or a queued/running occurrence. Finished one-time tasks, paused
|
|
271
343
|
schedules and revisions stopped for review are hidden. Each entry shows the
|
|
272
|
-
|
|
344
|
+
frequency with the cron timezone, the saved primary and fallback setups in order
|
|
345
|
+
(CLI, login profile, model and effort), next occurrence in UTC (or queued/running state),
|
|
273
346
|
and the first sentence of its saved invocation
|
|
274
347
|
prompt, limited to 140 characters. This is a read-only view; history and full
|
|
275
|
-
prompts remain available through the scheduling CLI.
|
|
348
|
+
prompts remain available through the scheduling CLI. `/tasks N` shows the same
|
|
349
|
+
frequency and execution path with the saved instructions. Common minute/hourly,
|
|
350
|
+
daily and weekday rules have plain-language labels; other calendar rules show
|
|
351
|
+
the exact cron expression and timezone. Interval rules show their fixed period,
|
|
352
|
+
and one-time tasks show `Once`. This describes the schedule, not a guarantee of
|
|
353
|
+
work when admission/preflight conditions are unmet.
|
package/docs/setup.md
CHANGED
|
@@ -261,8 +261,8 @@ node /absolute/ezenciel_agents/bin/ezenciel-agents-tools.mjs init \
|
|
|
261
261
|
|
|
262
262
|
This binds a private `ez` and preserves native command access. The default catalog
|
|
263
263
|
is empty. Do not supply a plugin catalog during first-time main onboarding.
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
The seeded
|
|
265
|
+
AGENTS.md already points at `ez tools list --details`. Verify `tools/bin/ez plugins
|
|
266
266
|
available` before the first agent turn. Also execute the agent-bound
|
|
267
267
|
`ezenciel-agents-message --help` through the selected CLI sandbox and verify
|
|
268
268
|
its actual tool output, so absent launchers or blocked execution are detected
|
package/docs/standalone-cli.md
CHANGED
|
@@ -22,14 +22,14 @@ node /absolute/package/bin/ezenciel-agents-tools.mjs init --standalone \
|
|
|
22
22
|
/absolute/private/company-tools/bin/ez plugins list
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Init starts nothing, uses an empty catalog by default
|
|
26
|
-
workspace
|
|
25
|
+
Init starts nothing, uses an empty catalog by default and never writes
|
|
26
|
+
workspace instructions. A registry
|
|
27
27
|
cannot be replaced by rerunning init. Keep the package at its original path:
|
|
28
28
|
the launcher imports it. Status reports `main: null` without a relay binding;
|
|
29
29
|
automated software upgrades currently require a relay deployment.
|
|
30
30
|
|
|
31
|
-
Use `ez tools list --details` for
|
|
32
|
-
Add
|
|
31
|
+
Use `ez tools list --details` for each installed plugin's aliases, purpose, skill paths and one example call. Read only the relevant skill.
|
|
32
|
+
Add "Tools: run `ez tools list --details`; each plugin's `--help` gives usage." to the project's existing instructions, with `ez` resolving to the returned launcher.
|
|
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
35
|
A standalone company registry remains explicit even when invoked from a different
|
package/docs/upgrades.md
CHANGED
|
@@ -16,7 +16,7 @@ automatic channel for core and plugins without a saved policy. Existing explicit
|
|
|
16
16
|
stable or manual policies are preserved. The owner may select either per target.
|
|
17
17
|
The main target and installed plugins version independently.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Core upgrades leave channel admission open while native work runs, then pause it after work is idle and recheck races. Plugin upgrades build while native work continues. Activation closes the existing registry admission lock, drains in-flight plugin command leases, and replaces the plugin under that lock. New native plugin calls wait for admission; an outdated revision fails before provider execution and must be rediscovered. No admitted provider operation is replayed. The shared broker and native sessions remain running. Core upgrades still require the full native-work drain. A plugin update also retains that drain if an operator replaced the broker’s single-file host binding (for example to approve new network pins), because that case still requires broker recreation.
|
|
20
20
|
|
|
21
21
|
The owner chooses the saved update policy. The host supervisor owns
|
|
22
22
|
interruption-safe replacement. There is one host service per agent, not a second
|
|
@@ -153,9 +153,7 @@ is required. Stable automation excludes prereleases, major changes and 0.x minor
|
|
|
153
153
|
changes. Beta policy permits compatible prereleases. Downgrades are rejected;
|
|
154
154
|
rollback is a recovery operation for the previous installation only.
|
|
155
155
|
|
|
156
|
-
`apply` records one durable queued job. **
|
|
157
|
-
queuing it.** It must not wait for completion in that same turn. The supervisor
|
|
158
|
-
pauses new run admission, drains already-started work, then consumes the job.
|
|
156
|
+
`apply` records one durable queued job. **For a core upgrade, the agent must finish its turn after queuing it** so the supervisor can drain native work. A plugin upgrade can complete while that turn continues; only plugin-call admission is held during activation. Calls already executing finish first.
|
|
159
157
|
One job at a time; an unresolved recovery blocks new upgrades. The agent processes
|
|
160
158
|
multiple requested packages over successive update requests.
|
|
161
159
|
|
|
@@ -257,19 +255,15 @@ handbook from workspace `AGENTS.md` (and existing `AGENTS.override.md`).
|
|
|
257
255
|
Personal text outside that block is preserved byte-for-byte. Do not reinsert
|
|
258
256
|
coding, KISS, contribution or repair loops into operating minds.
|
|
259
257
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
Inventory and
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
Codex, Grok and OpenCode discover workspace instructions natively. Claude
|
|
271
|
-
receives the native `--append-system-prompt-file` binding to `AGENTS.md`, alongside
|
|
272
|
-
its own normal instructions. Fresh and resumed owner input is literal; ez does
|
|
258
|
+
Ez writes no managed guidance after the initial workspace seed. Update binding
|
|
259
|
+
(init with a host config, `enable-updates`, upgrade and rollback) replaces a former
|
|
260
|
+
`<!-- ez tools -->` footer once with the seeded static line
|
|
261
|
+
"Tools: run `ez tools list --details`; each plugin's `--help` gives usage." and
|
|
262
|
+
otherwise leaves `AGENTS.md` untouched. Malformed markers and symlinks fail visibly
|
|
263
|
+
rather than overwriting personal work. Inventory and usage are generated on read.
|
|
264
|
+
|
|
265
|
+
Codex, Grok, OpenCode and Claude Code discover workspace `AGENTS.md` natively
|
|
266
|
+
(Claude Code loads it when the workspace has no `CLAUDE.md`). Fresh and resumed owner input is literal; ez does
|
|
273
267
|
not surround it with policies, tool recipes, repair instructions or history.
|
|
274
268
|
The native engine owns instruction loading and its context/token overhead.
|
|
275
269
|
Already running sessions retain their current context until native reload.
|
|
@@ -294,12 +288,8 @@ Actual update transactions retain their existing admission, drain and rollback r
|
|
|
294
288
|
|
|
295
289
|
### Isolated broker readiness
|
|
296
290
|
|
|
297
|
-
Isolated activation and rollback explicitly recreate only `plugin-broker` with
|
|
298
|
-
`--no-deps --force-recreate --no-build --pull never --wait`. Plugin-only refresh
|
|
299
|
-
pins the installed broker image ID; main activation uses the newly built image
|
|
300
|
-
and rollback uses the recorded old image. This refreshes the narrow read-only
|
|
301
|
-
host-configuration file mount after atomic replacement. The relay and native
|
|
302
|
-
sessions are preserved during plugin-only refresh. Host-capable updates do not
|
|
291
|
+
Isolated core activation and rollback explicitly recreate only `plugin-broker` with
|
|
292
|
+
`--no-deps --force-recreate --no-build --pull never --wait`. Core activation uses the newly built image and rollback uses the recorded old image to refresh the single-file host binding. Plugin-only activation and rollback change directory-mounted registry files, verify the existing broker in place, and refresh its generated plugin-version inventory. They preserve the broker socket, relay and native sessions. Host-capable updates do not
|
|
303
293
|
start a broker. Existing update admission and drain remain authoritative.
|
|
304
294
|
|
|
305
295
|
Socket health is liveness only. Before reporting completion, the updater runs
|
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.50",
|
|
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.",
|
package/src/agent-guidance.ts
CHANGED
|
@@ -5,8 +5,8 @@ import path from 'node:path'
|
|
|
5
5
|
const start = '<!-- ez shared guidance: begin -->'
|
|
6
6
|
const end = '<!-- ez shared guidance: end -->'
|
|
7
7
|
|
|
8
|
-
// Drop the obsolete package-owned handbook. Discovery
|
|
9
|
-
// ez tools
|
|
8
|
+
// Drop the obsolete package-owned handbook. Discovery is seeded once and
|
|
9
|
+
// generated by `ez tools list --details`. Personal text outside the markers stays byte-for-byte.
|
|
10
10
|
export async function installAgentGuidance(workspace: string): Promise<void> {
|
|
11
11
|
for (const name of ['AGENTS.md', 'AGENTS.override.md']) {
|
|
12
12
|
const file = path.join(workspace, name)
|