@awebai/oats 0.22.16 → 0.22.17

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.
@@ -23,29 +23,44 @@
23
23
  * OATS_TASK (spawn), OATS_REPO/OATS_BRANCH/OATS_WORK (spawn), OATS_META (retire).
24
24
  * Output: JSON { meta, brief, warning } on stdout. Failures warn, never block.
25
25
  */
26
- import { existsSync, mkdirSync, mkdtempSync, writeFileSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
26
+ import { existsSync, mkdirSync, mkdtempSync, writeFileSync, readFileSync, readdirSync, realpathSync, rmSync, writeSync } from "node:fs";
27
27
  import { join, isAbsolute, dirname } from "node:path";
28
28
  import { tmpdir } from "node:os";
29
29
  import { execFile, spawnSync } from "node:child_process";
30
30
  import { reclaimHarvestBranch } from "../lib/harvest-branch.mjs";
31
31
 
32
- const out = (o) => { process.stdout.write(JSON.stringify(o) + "\n"); process.exit(0); };
32
+ // Every answer leaves through here: written whole, then exit. stdout is a
33
+ // pipe when the kernel's operation runner, a Desktop or a test reads it, and
34
+ // on macOS Node writes to a pipe asynchronously: process.exit right after
35
+ // process.stdout.write drops whatever has not left Node's buffer (64 KiB,
36
+ // so a view of one long STATE.md arrived cut). fs.writeSync on fd 1 blocks
37
+ // until the OS has the bytes; EAGAIN (a non-blocking fd whose reader is
38
+ // slower than us) is retried after a short wait. The exit stays synchronous,
39
+ // which the call sites below rely on to end their flow.
40
+ const emit = (text, code) => {
41
+ const buf = Buffer.from(text, "utf8");
42
+ for (let off = 0; off < buf.length;) {
43
+ try { off += writeSync(1, buf, off, buf.length - off); }
44
+ catch (e) { if (e.code !== "EAGAIN") throw e; Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5); }
45
+ }
46
+ process.exit(code);
47
+ };
48
+ const out = (o) => emit(JSON.stringify(o) + "\n", 0);
33
49
  const warn = (m) => out({ warning: `oats-okf: ${String(m).slice(0, 300)}` });
34
50
  // A reported failure must not exit 0: callers and hooks read the status.
35
- const warnFail = (m) => { process.stdout.write(JSON.stringify({ warning: `oats-okf: ${String(m).slice(0, 300)}` }) + "\n"); process.exit(1); };
51
+ const warnFail = (m) => emit(JSON.stringify({ warning: `oats-okf: ${String(m).slice(0, 300)}` }) + "\n", 1);
36
52
 
37
53
  // Desktop CLI API v1: `oats okf harvest --json` emits EXACTLY ONE envelope
38
54
  // object on stdout — {schemaVersion:1,ok,result|error} — and a nonzero exit
39
55
  // on failure. Ordinary (non---json) output keeps the hook JSON shape above.
40
56
  const JSON_MODE = process.argv.includes("--json");
41
- const jsonOk = (result) => { process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: true, result }) + "\n"); process.exit(0); };
42
- const jsonFail = (code, message) => { process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: false, error: { code, message: String(message).slice(0, 300) } }) + "\n"); process.exit(1); };
57
+ const jsonOk = (result) => emit(JSON.stringify({ schemaVersion: 1, ok: true, result }) + "\n", 0);
58
+ const jsonFail = (code, message) => emit(JSON.stringify({ schemaVersion: 1, ok: false, error: { code, message: String(message).slice(0, 300) } }) + "\n", 1);
43
59
 
44
60
  // --help/-h never runs a command here either (the kernel answers it from the
45
61
  // manifest since 0.22.6; this keeps an older kernel from spawning a harvester).
46
62
  if (process.argv.slice(2).some((a) => a === "--help" || a === "-h")) {
47
- process.stdout.write("oats okf harvest [--json] [--from-record] [--force] promote this instance's pending notes (and record windows) into its soul by spawning a memory-harvest worker; --help never runs it\noats okf inspect [--json] answer this instance's working knowledge (STATE.md, log.md, pending notes) as labeled documents\n");
48
- process.exit(0);
63
+ emit("oats okf harvest [--json] [--from-record] [--force] promote this instance's pending notes (and record windows) into its soul by spawning a memory-harvest worker; --help never runs it\noats okf inspect [--json] answer this instance's working knowledge (STATE.md, log.md, pending notes) as labeled documents\n", 0);
49
64
  }
50
65
  const event = process.env.OATS_EVENT || process.argv[2];
51
66
  const instance = process.env.OATS_INSTANCE;
@@ -493,9 +508,9 @@ _(the single next action — keep this current; a fresh session on any model res
493
508
  const notes = existsSync(notesDir) ? readdirSync(notesDir).filter((f) => f.endsWith(".md")).sort() : [];
494
509
  for (const f of notes) { const d = doc(`Pending note: ${f}`, join(notesDir, f)); if (d) documents.push(d); }
495
510
  const summary = documents.length ? `${documents.length} document${documents.length === 1 ? "" : "s"}: ${existsSync(join(home, "STATE.md")) ? "state" : "no state"}, ${existsSync(join(home, "log.md")) ? "log" : "no log"}, ${notes.length} pending note${notes.length === 1 ? "" : "s"}` : "no working memory in this home yet (STATE.md, log.md and notes/ are written by the instance)";
496
- process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: true, result: { summary, documents } }) + "\n"); process.exit(0);
511
+ jsonOk({ summary, documents });
497
512
  } catch (e) {
498
- process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: false, error: { code: "E_INSPECT_FAILED", message: String(e.message || e).slice(0, 300) } }) + "\n"); process.exit(1);
513
+ jsonFail("E_INSPECT_FAILED", e.message || e);
499
514
  }
500
515
  } else if (event === "retire") {
501
516
  // Retirement is intentionally a no-op for knowledge (for now): promotion happens
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "capability": "oats.okf",
3
3
  "command": "okf",
4
- "version": "1.6.0",
4
+ "version": "1.6.1",
5
5
  "compatibility": {
6
6
  "oats": ">=0.22.3"
7
7
  },
@@ -0,0 +1,25 @@
1
+ # OATS v0.22.17
2
+
3
+ Two corrections found by installed acceptance of 0.22.16, nothing else.
4
+
5
+ ## oats.okf 1.6.1
6
+
7
+ A provider view larger than one pipe buffer arrived cut at 65536 bytes
8
+ with exit 0 when the kernel's operation runner or a Desktop read it: the
9
+ provider wrote its envelope and exited at once, and on macOS Node writes
10
+ to a pipe asynchronously. Every answer now leaves the provider whole
11
+ before it exits. The catalog pins v1.6.1; scopes on 1.6.0 keep working
12
+ for small views until their owners run
13
+ `oats update oats.okf --to v1.6.1 --dir <scope>` and re-trust. The
14
+ kernel's runner is unchanged; the regression covers a 128 KiB view
15
+ through an actual pipe, directly and through `oats operation run`, and a
16
+ 300 KiB view from any provider.
17
+
18
+ ## Desktop
19
+
20
+ Workspaces added at runtime survive an app restart: the opened set is
21
+ persisted on its own (not the recent-suggestion store), restored and
22
+ re-validated at startup with absent paths skipped and aliases collapsed,
23
+ and a backend is reused only when it covers every restored workspace. A
24
+ failed persistence write keeps the previous set and reports the failed
25
+ add.
@@ -2,7 +2,7 @@
2
2
  "packages": {
3
3
  "oats.okf": {
4
4
  "url": "https://github.com/awebai/oats-okf.git",
5
- "ref": "v1.6.0",
5
+ "ref": "v1.6.1",
6
6
  "path": "oats-package"
7
7
  },
8
8
  "oats.aweb": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awebai/oats",
3
- "version": "0.22.16",
3
+ "version": "0.22.17",
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",