@awebai/oats 0.22.10 → 0.22.14
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/bin/oats.mjs +186 -6
- package/docs/design/2026-09-07-architecture-reassessment.md +131 -0
- package/docs/desktop.md +44 -2
- package/docs/execution-targets.md +21 -0
- package/docs/release-notes/v0.22.11.md +49 -0
- package/docs/release-notes/v0.22.12.md +53 -0
- package/docs/release-notes/v0.22.13.md +44 -0
- package/docs/release-notes/v0.22.14.md +48 -0
- package/docs/schedules.md +143 -0
- package/lib/attachments.mjs +164 -0
- package/lib/schedule-host.mjs +150 -0
- package/lib/schedule.mjs +731 -0
- package/lib/servers.mjs +19 -1
- package/lib/session-viewer.mjs +4 -0
- package/package.json +3 -2
package/lib/servers.mjs
CHANGED
|
@@ -185,7 +185,9 @@ export function runRemote(target, oatsArgs, io = {}) {
|
|
|
185
185
|
let stderr = "";
|
|
186
186
|
let status = 0;
|
|
187
187
|
try {
|
|
188
|
-
|
|
188
|
+
// `io.input` (a Buffer) streams to the remote command's stdin: the only
|
|
189
|
+
// way bytes reach a host, as a quoted argument never could.
|
|
190
|
+
stdout = exec(bin, argv, { encoding: "utf8", stdio: [io.input === undefined ? "ignore" : "pipe", "pipe", "pipe"], ...(io.input === undefined ? {} : { input: io.input }), maxBuffer: 16 * 1024 * 1024, timeout: io.timeoutMs || 300000 });
|
|
189
191
|
} catch (e) {
|
|
190
192
|
stdout = String(e.stdout || "");
|
|
191
193
|
stderr = String(e.stderr || e.message || "");
|
|
@@ -258,6 +260,8 @@ export function checkRemoteSupport(remote, target, oatsArgs, roster) {
|
|
|
258
260
|
: `it does not advertise what it supports (kernels before 0.22.2 do not), so only pi and claude on tmux with no launch options are assumed of it; upgrade it there to use more`;
|
|
259
261
|
const refuse = (what) => { throw serverError("E_REMOTE_INCOMPATIBLE", `remote oats ${remote.version} at ${target.sshHost}: ${what} was not established as supported there (${supports})`); };
|
|
260
262
|
if (runtime && !remote.runtimes.includes(runtime)) refuse(`runtime ${runtime}${flagOf("--runtime") ? "" : ` (the default of soul ${agent} there)`}`);
|
|
263
|
+
// A wake schedule at spawn is saved by the host: it must advertise schedules.
|
|
264
|
+
if (["--wake-json", "--wake-every", "--wake-cron"].some((f) => oatsArgs.includes(f)) && !remote.features.includes("schedule")) refuse("a wake schedule at spawn (the host must advertise the schedule feature)");
|
|
261
265
|
const backend = flagOf("--backend");
|
|
262
266
|
if (backend && !remote.sessionBackends.includes(backend)) refuse(`session backend ${backend}`);
|
|
263
267
|
if (oatsArgs.includes("--yolo") && !remote.launchOptions.includes("yolo")) refuse("the yolo launch option");
|
|
@@ -632,6 +636,20 @@ export function startRemote(serverId, { instance, home, model } = {}, io = {}) {
|
|
|
632
636
|
return { envelope: envelope.ok ? { ...envelope, result: { ...envelope.result, server: serverId, instance: instance || route.snapshot?.instance || envelope.result.instance } } : envelope, stderr, route };
|
|
633
637
|
}
|
|
634
638
|
|
|
639
|
+
/** `oats schedule ...` on the execution host: schedules are host-owned, so
|
|
640
|
+
* every subcommand runs in the server's registered workspace; refused
|
|
641
|
+
* before any remote mutation when the remote kernel does not advertise
|
|
642
|
+
* the schedule feature. The envelope is relayed as is. */
|
|
643
|
+
export function scheduleRemote(serverId, oatsArgs, io = {}) {
|
|
644
|
+
const server = io.server || getServer(serverId);
|
|
645
|
+
const target = targetOf(server);
|
|
646
|
+
const remote = checkRemote(target, io);
|
|
647
|
+
if (!remote.features.includes("schedule")) throw serverError("E_REMOTE_INCOMPATIBLE", `remote oats ${remote.version} at ${target.sshHost} does not advertise schedules; upgrade it there`);
|
|
648
|
+
const args = ["schedule", ...oatsArgs.filter((a) => a !== "--json"), "--dir", target.workspace, "--json"];
|
|
649
|
+
const { envelope, stderr } = runRemote(target, args, io);
|
|
650
|
+
return { envelope: envelope.ok ? { ...envelope, result: { ...envelope.result, server: serverId } } : envelope, stderr, target };
|
|
651
|
+
}
|
|
652
|
+
|
|
635
653
|
export function attachArgv(serverId, { instance, home } = {}, io = {}) {
|
|
636
654
|
const { target, home: remoteHome } = resolveRoute(serverId, { instance, home }, "session attach");
|
|
637
655
|
if (!io.skipVersionCheck) requireSessionRemote(target, io);
|
package/lib/session-viewer.mjs
CHANGED
|
@@ -26,6 +26,10 @@ export function prepareSessionViewer(target, { exec = execFileSync } = {}) {
|
|
|
26
26
|
// when this agent retires. Disable window navigation in the viewer only.
|
|
27
27
|
for (const name of ["prefix", "prefix2"]) run(["set-option", "-t", viewer, name, "None"]);
|
|
28
28
|
run(["set-option", "-t", viewer, "key-table", "oatsview-locked"]);
|
|
29
|
+
// The viewer shows one agent; its status line only repeats that name.
|
|
30
|
+
// Session-scoped on the temporary viewer: the agents' own session and
|
|
31
|
+
// the operator's tmux settings are untouched.
|
|
32
|
+
run(["set-option", "-t", viewer, "status", "off"]);
|
|
29
33
|
run(["unbind-key", "-a", "-q", "-T", "oatsview-locked"]);
|
|
30
34
|
run(["bind-key", "-T", "oatsview-locked", "WheelUpPane", "if-shell", "-F", "#{||:#{pane_in_mode},#{mouse_any_flag}}", "send-keys -M", "copy-mode -e; send-keys -M"]);
|
|
31
35
|
run(["set-option", "-t", viewer, "mouse", "on"]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awebai/oats",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.14",
|
|
4
4
|
"description": "OATS (Open Agent Team Specification) — durable souls, disposable instances, targetable capability packages, and the runtime-neutral oats CLI/kernel.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"packages/record/package.json"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@awebai/pi": "^0.2.1"
|
|
47
|
+
"@awebai/pi": "^0.2.1",
|
|
48
|
+
"croner": "10.0.1"
|
|
48
49
|
},
|
|
49
50
|
"bin": {
|
|
50
51
|
"oats": "./bin/oats.mjs"
|