@ouro.bot/cli 0.1.0-alpha.876 → 0.1.0-alpha.878

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.
@@ -61,8 +61,9 @@ Promise.all([
61
61
  Promise.resolve().then(() => __importStar(require("../heart/runtime-credentials"))),
62
62
  Promise.resolve().then(() => __importStar(require("../heart/machine-identity"))),
63
63
  Promise.resolve().then(() => __importStar(require("@ouro.bot/friends/a2a-client"))),
64
+ Promise.resolve().then(() => __importStar(require("../a2a/escalation-wiring"))),
64
65
  ])
65
- .then(async ([{ startA2AServer }, { loadOrMintA2AIdentity, readStoredA2ASeed }, { waitForRuntimeCredentialBootstrap, readMachineRuntimeCredentialConfig, refreshMachineRuntimeCredentialConfig, mergeMachineRuntimeCredentialConfig }, { loadOrCreateMachineIdentity }, { ready },]) => {
66
+ .then(async ([{ startA2AServer }, { loadOrMintA2AIdentity, readStoredA2ASeed }, { waitForRuntimeCredentialBootstrap, readMachineRuntimeCredentialConfig, refreshMachineRuntimeCredentialConfig, mergeMachineRuntimeCredentialConfig }, { loadOrCreateMachineIdentity }, { ready }, { escalationOptionsFor, sendOwnerNoticeViaTelegram },]) => {
66
67
  const os = await Promise.resolve().then(() => __importStar(require("node:os")));
67
68
  // Wait for the daemon to deliver the machine-local runtime config (carrying the
68
69
  // a2a identity seed) into the in-memory cache before we read or mint identity.
@@ -109,6 +110,7 @@ Promise.all([
109
110
  },
110
111
  },
111
112
  } : {}),
113
+ ...escalationOptionsFor(agentName, (notice) => sendOwnerNoticeViaTelegram(agentName, notice)),
112
114
  ...(argValue("--host") ? { host: argValue("--host") } : {}),
113
115
  ...(Number.isInteger(port) ? { port } : {}),
114
116
  ...(argValue("--base-url") ? { baseUrl: argValue("--base-url") } : {}),
@@ -133,6 +133,12 @@ function relationshipAwaitCoordinates(awaitFile) {
133
133
  throw new InvalidRelationshipAwaitProvenanceError("Relationship await provenance is invalid");
134
134
  return { friendId: awaitFile.filed_for_friend_id, channel: awaitFile.filed_from, key: awaitFile.filed_from_key, requestId: null };
135
135
  }
136
+ if (awaitFile.filed_from === "a2a" && awaitFile.filed_for_friend_id && awaitFile.filed_from_key) {
137
+ // Filed in a plain (non-delegated) A2A conversation: the peer and conversation are its whole provenance.
138
+ if (Buffer.byteLength(awaitFile.filed_for_friend_id) > 256 || Buffer.byteLength(awaitFile.filed_from_key) > 1_024)
139
+ throw new InvalidRelationshipAwaitProvenanceError("Relationship await provenance is invalid");
140
+ return { friendId: awaitFile.filed_for_friend_id, channel: "a2a", key: awaitFile.filed_from_key, requestId: null };
141
+ }
136
142
  const isSystemAwait = awaitFile.filed_for_friend_id === null
137
143
  && awaitFile.filed_from_key === null
138
144
  && (awaitFile.filed_from === null || awaitFile.filed_from === "unknown" || awaitFile.filed_from === "cli");
@@ -186,14 +192,23 @@ async function resolveRelationshipAwaitAuthority(agentRoot, store, registry, coo
186
192
  if (coordinates.channel === "external-event" && (friend.capabilityProfileId !== "sanctuary-owner" || !registry.profiles["sanctuary-event"])) {
187
193
  throw new StaleRelationshipAwaitError("admission or profile is not active");
188
194
  }
189
- const subjectFriend = coordinates.channel === "a2a" ? await resolveA2APrincipal(agentRoot, store, friend, coordinates.requestId) : friend;
195
+ // A plain peer await carries the peer's own authority and nobody else's: no principal, no delegation grant.
196
+ const plainPeerAwait = coordinates.channel === "a2a" && coordinates.requestId === null;
197
+ // A peer the operator switched to no contact at all is not ticked; every other policy is held to following up on this one internal request.
198
+ if (plainPeerAwait && friend.initiativePolicy === "none")
199
+ throw new StaleRelationshipAwaitError("initiative policy denies contact");
200
+ const subjectFriend = coordinates.channel === "a2a" && !plainPeerAwait ? await resolveA2APrincipal(agentRoot, store, friend, coordinates.requestId) : friend;
190
201
  const authorization = coordinates.channel === "external-event"
191
202
  ? (0, relationship_authorization_2.createRelationshipAuthorizationEvaluator)({ friend, registry, profileId: "sanctuary-event", requestPhase: "follow_up" })
192
- : coordinates.channel === "a2a"
193
- // The follow-up carries the delegating owner's authority (as the delegated command did), but the turn profile
194
- // is the peer's own, which can only narrow it: never wider than a peer chat turn or the original command.
195
- ? (0, relationship_authorization_2.createRelationshipAuthorizationEvaluator)({ friend: subjectFriend, registry, profileId: friend.capabilityProfileId, requestId: coordinates.requestId, requestPhase: "follow_up" })
196
- : (0, relationship_authorization_2.createRelationshipAuthorizationEvaluator)({ friend, registry, requestId: coordinates.requestId, requestPhase: "follow_up" });
203
+ : plainPeerAwait
204
+ // The peer's own profile and trust, nothing wider. Following up is reading its own outbox, not contacting it, so the
205
+ // follow-up phase is opened with an internal request id that exists only for this await and is never shown to the peer.
206
+ ? (0, relationship_authorization_2.createRelationshipAuthorizationEvaluator)({ friend: { ...friend, initiativePolicy: "request_follow_up_only" }, registry, profileId: friend.capabilityProfileId, requestId: `peer-await:${coordinates.key}`, requestPhase: "follow_up" })
207
+ : coordinates.channel === "a2a"
208
+ // The follow-up carries the delegating owner's authority (as the delegated command did), but the turn profile
209
+ // is the peer's own, which can only narrow it: never wider than a peer chat turn or the original command.
210
+ ? (0, relationship_authorization_2.createRelationshipAuthorizationEvaluator)({ friend: subjectFriend, registry, profileId: friend.capabilityProfileId, requestId: coordinates.requestId, requestPhase: "follow_up" })
211
+ : (0, relationship_authorization_2.createRelationshipAuthorizationEvaluator)({ friend, registry, requestId: coordinates.requestId, requestPhase: "follow_up" });
197
212
  if (authorization.subject.friendId !== subjectFriend.id)
198
213
  throw new Error("Relationship await authority friend is ambiguous");
199
214
  if (!authorization.authorizeTool("resolve_await").allowed)
@@ -1233,14 +1248,16 @@ async function runPrivateRuntimeTurn(options) {
1233
1248
  ? parsedAwait.wake_at && (0, tools_awaiting_1.hasActiveExternalEventAwait)(agentName, { recordPath: relationshipAwaitCoordinatesValue.key, awaitName: parsedAwait.name, wakeAt: parsedAwait.wake_at })
1234
1249
  ? { active: true }
1235
1250
  : { active: false, reason: "external event disposition is no longer active" }
1236
- : (0, tools_awaiting_1.inspectRelationshipFollowUp)(agentRoot, {
1237
- friendId: relationshipAwaitCoordinatesValue.friendId,
1238
- channel: relationshipAwaitCoordinatesValue.channel,
1239
- key: relationshipAwaitCoordinatesValue.key,
1240
- requestId: relationshipAwaitCoordinatesValue.requestId,
1241
- awaitName: parsedAwait.name,
1242
- now: now().getTime(),
1243
- });
1251
+ : relationshipAwaitCoordinatesValue.channel === "a2a" && relationshipAwaitCoordinatesValue.requestId === null
1252
+ ? (0, tools_awaiting_1.inspectPeerAwait)(agentRoot, { friendId: relationshipAwaitCoordinatesValue.friendId, key: relationshipAwaitCoordinatesValue.key, awaitName: parsedAwait.name, now: now().getTime() })
1253
+ : (0, tools_awaiting_1.inspectRelationshipFollowUp)(agentRoot, {
1254
+ friendId: relationshipAwaitCoordinatesValue.friendId,
1255
+ channel: relationshipAwaitCoordinatesValue.channel,
1256
+ key: relationshipAwaitCoordinatesValue.key,
1257
+ requestId: relationshipAwaitCoordinatesValue.requestId,
1258
+ awaitName: parsedAwait.name,
1259
+ now: now().getTime(),
1260
+ });
1244
1261
  if (!binding.active) {
1245
1262
  if ((0, tools_awaiting_1.isBrokenBindingReason)(binding.reason))
1246
1263
  (0, tools_awaiting_1.failBrokenAwait)(agentRoot, agentName, parsedAwait.name, binding.reason);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.876",
3
+ "version": "0.1.0-alpha.878",
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.876",
9
+ "version": "0.1.0-alpha.878",
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.876",
3
+ "version": "0.1.0-alpha.878",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },