@ouro.bot/cli 0.1.0-alpha.991 → 0.1.0-alpha.993

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/changelog.json CHANGED
@@ -1,6 +1,18 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.993",
6
+ "changes": [
7
+ "An agent's reply on Anthropic no longer turns into an earlier note when its answer contains a bracket or a brace: streamed tool arguments stay intact."
8
+ ]
9
+ },
10
+ {
11
+ "version": "0.1.0-alpha.992",
12
+ "changes": [
13
+ "The Butler's container keeps its bundle sync key mount through a release: the root authority's activation, which recreates the container after the upgrade, now mounts the key folder read-only as the upgrade does, and a rollback gives it back only to a release that has bundle sync."
14
+ ]
15
+ },
4
16
  {
5
17
  "version": "0.1.0-alpha.991",
6
18
  "changes": [
@@ -1,5 +1,5 @@
1
1
  {
2
- "runtimeVersion": "0.1.0-alpha.991",
2
+ "runtimeVersion": "0.1.0-alpha.993",
3
3
  "bundleSchemaVersion": 3,
4
4
  "lastUpdated": "2026-09-03T00:00:00.000Z"
5
5
  }
@@ -1,7 +1,7 @@
1
1
  <?xml version="1.0"?>
2
2
  <Container version="2">
3
3
  <Name>ouro-butler</Name>
4
- <Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.991</Repository>
4
+ <Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.993</Repository>
5
5
  <Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
6
6
  <Network>host</Network>
7
7
  <Shell>sh</Shell>
@@ -36,6 +36,7 @@ var _a;
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.SanctuaryAuthorityRootLifecycle = exports.SANCTUARY_UPGRADE_STEPS = exports.SANCTUARY_KEEPER_BOOT_LINES = void 0;
38
38
  exports.predecessorExpectsPsycheMount = predecessorExpectsPsycheMount;
39
+ exports.predecessorHasBundleSync = predecessorHasBundleSync;
39
40
  exports.recordSanctuaryRootLifecycleFailure = recordSanctuaryRootLifecycleFailure;
40
41
  exports.runSanctuaryAuthorityRootCli = runSanctuaryAuthorityRootCli;
41
42
  const node_child_process_1 = require("node:child_process");
@@ -57,6 +58,8 @@ const OFFSET = `${BUNDLE}/state/senses/telegram/offset.json`;
57
58
  const SOCKET = "/run/ouro-authority";
58
59
  // Operator-set grants, root-owned on the host and mounted read-only into the Butler at /etc/ouro/trust/sanctuary.
59
60
  const TRUST = "/mnt/user/appdata/ouro-butler/trust/sanctuary";
61
+ // The bundle sync deploy key's host folder, mounted read-only where the sync wrapper reads it (from alpha.991).
62
+ const SYNC = "/mnt/user/appdata/ouro-butler/sync";
60
63
  const STAGING = "/var/lib/ouro-authority/staging";
61
64
  const CGROUP = "/sys/fs/cgroup/ouro-authority";
62
65
  const BOOT = "/boot/config/custom/ouro-authority/start.sh";
@@ -855,7 +858,7 @@ class SanctuaryAuthorityRootLifecycle {
855
858
  const steps = {
856
859
  stop: () => this.#halt(),
857
860
  switch: async () => { await this.#halt(); this.#switchPackage(journal); },
858
- resident: () => this.#recreateResident(journal.to.imageReference, journal.to.imageId, { psycheMount: false }),
861
+ resident: () => this.#recreateResident(journal.to.imageReference, journal.to.imageId, { psycheMount: false, syncMount: true }),
859
862
  migrate: () => target().#bundle(["--operation", "migrate", "--rollback-image-id", journal.from.imageId, "--target-image-id", journal.to.imageId]),
860
863
  start: () => target().#startUpgraded(),
861
864
  };
@@ -918,7 +921,7 @@ class SanctuaryAuthorityRootLifecycle {
918
921
  predecessor.#publishBoot();
919
922
  if (this.#containers().find((container) => container.Name === "/ouro-butler")?.Image !== journal.from.imageId) {
920
923
  // A predecessor up to alpha.978 expects its psyche read-only over the bundle; alpha.979 and later own a writable one.
921
- predecessor.#recreateResident(journal.from.imageReference, journal.from.imageId, { psycheMount: predecessorExpectsPsycheMount(journal.from.imageReference) });
924
+ predecessor.#recreateResident(journal.from.imageReference, journal.from.imageId, { psycheMount: predecessorExpectsPsycheMount(journal.from.imageReference), syncMount: predecessorHasBundleSync(journal.from.imageReference) });
922
925
  }
923
926
  await predecessor.#startUpgraded(PREDECESSOR_READY_TIMEOUT_MS);
924
927
  this.#remove(UPGRADE);
@@ -1027,8 +1030,12 @@ class SanctuaryAuthorityRootLifecycle {
1027
1030
  #publishBoot() {
1028
1031
  this.#write(BOOT, fs.readFileSync(this.#p(`${ROOT}/package/deploy/unraid/sanctuary-authority-service.sh`), "utf8"));
1029
1032
  }
1030
- /** `psycheMount` adds the read-only psyche mount that releases up to alpha.978 expect; only a rollback to such a release passes true. */
1031
- #recreateResident(reference, imageId, { psycheMount }) {
1033
+ /**
1034
+ * `psycheMount` adds the read-only psyche mount that releases up to alpha.978 expect; only a rollback to such a release
1035
+ * passes true. `syncMount` adds the read-only bundle sync key mount that releases from alpha.991 carry; an older
1036
+ * release's audit refuses it.
1037
+ */
1038
+ #recreateResident(reference, imageId, { psycheMount, syncMount }) {
1032
1039
  if (this.#containers().some((container) => container.Name === "/ouro-butler"))
1033
1040
  this.#docker(["rm", "-f", "ouro-butler"]);
1034
1041
  this.#docker(["create", "--name", "ouro-butler", "--network", "host", "--restart", "unless-stopped", "--user", "10001:10001",
@@ -1036,7 +1043,8 @@ class SanctuaryAuthorityRootLifecycle {
1036
1043
  "-v", `${RUNTIME}:/home/ouro/.ouro-cli:rw`, "-v", `${BUNDLE}:/home/ouro/AgentBundles/sanctuary.ouro:rw`,
1037
1044
  "-v", `${EVENTS}:/run/ouro-events:ro`, "-v", `${SOCKET}:${SOCKET}:ro`,
1038
1045
  ...(psycheMount ? ["-v", `${BUNDLE}/psyche:/home/ouro/AgentBundles/sanctuary.ouro/psyche:ro`] : []),
1039
- "-v", `${TRUST}:/etc/ouro/trust/sanctuary:ro`, reference]);
1046
+ "-v", `${TRUST}:/etc/ouro/trust/sanctuary:ro`,
1047
+ ...(syncMount ? ["-v", `${SYNC}:/run/ouro-sync:ro`] : []), reference]);
1040
1048
  const resident = this.#containers().find((container) => container.Name === "/ouro-butler");
1041
1049
  if (resident?.Image !== imageId || resident.State.Running)
1042
1050
  throw new Error("Sanctuary resident recreation readback failed");
@@ -1260,6 +1268,14 @@ function predecessorExpectsPsycheMount(imageReference) {
1260
1268
  const release = /^0\.1\.0-alpha\.(\d+)$/u.exec(imageReference.slice(imageReference.lastIndexOf(":") + 1));
1261
1269
  return release !== null && Number(release[1]) <= 978;
1262
1270
  }
1271
+ /** Whether a release's image carries bundle sync (alpha.991 or later, or a release with no prerelease tag), so its resident gets the sync key mount. */
1272
+ function predecessorHasBundleSync(imageReference) {
1273
+ const tag = imageReference.slice(imageReference.lastIndexOf(":") + 1);
1274
+ if (/^\d+\.\d+\.\d+$/u.test(tag))
1275
+ return true;
1276
+ const release = /^0\.1\.0-alpha\.(\d+)$/u.exec(tag);
1277
+ return release !== null && Number(release[1]) >= 991;
1278
+ }
1263
1279
  /**
1264
1280
  * Keep the real failure where only root can read it (D-034). Stderr stays generic
1265
1281
  * because a parse error can quote private bytes; the authority root is as private
@@ -204,19 +204,30 @@ function toAnthropicUsage(raw) {
204
204
  total_tokens: totalInputTokens + outputTokens,
205
205
  };
206
206
  }
207
+ function parsesAsJson(text) {
208
+ try {
209
+ return JSON.parse(text);
210
+ }
211
+ catch {
212
+ return undefined;
213
+ }
214
+ }
207
215
  function mergeAnthropicToolArguments(current, partial) {
208
216
  if (!partial)
209
217
  return current;
210
- const trimmedCurrent = current.trim();
218
+ // Restart and merge only apply while the text so far is a complete JSON value (the
219
+ // block's starting input). Mid-stream, a fragment may legitimately start with "{" or
220
+ // "[", or the text so far may end in "}", inside a string: those fragments append.
221
+ const completed = parsesAsJson(current);
211
222
  const trimmedPartial = partial.trim();
212
223
  // If streaming restarts with a full JSON object/array fragment, trust it.
213
- if (trimmedPartial.startsWith("{") || trimmedPartial.startsWith("[")) {
224
+ if (completed !== undefined && (trimmedPartial.startsWith("{") || trimmedPartial.startsWith("["))) {
214
225
  return partial;
215
226
  }
216
227
  // Anthropic can emit block.input as a complete object and then emit
217
228
  // additional members as ',\"k\":v' deltas; merge those safely.
218
- if (trimmedCurrent.startsWith("{") && trimmedCurrent.endsWith("}")) {
219
- const inner = trimmedCurrent.slice(1, -1).trim();
229
+ if (completed !== null && typeof completed === "object" && !Array.isArray(completed)) {
230
+ const inner = current.trim().slice(1, -1).trim();
220
231
  let suffix = partial;
221
232
  if (!inner && suffix.startsWith(",")) {
222
233
  suffix = suffix.slice(1);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.991",
3
+ "version": "0.1.0-alpha.993",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@ouro.bot/cli",
9
- "version": "0.1.0-alpha.991",
9
+ "version": "0.1.0-alpha.993",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.78.0",
12
12
  "@azure/identity": "^4.13.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.991",
3
+ "version": "0.1.0-alpha.993",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },