@aexhq/agentloop-pi 6.2.0 → 7.0.0

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/README.md CHANGED
@@ -33,8 +33,13 @@ const session = await brain.sessions.create({
33
33
  The component is built by this package's publisher. Brain consumes the resulting Component and
34
34
  does not compile its JavaScript source.
35
35
 
36
- The loop reads paginated session Events before each turn and saves its observation cursor in
37
- kv after saving those observations in the transcript. For unanswered calls in the last saved
36
+ The loop reads paginated session Events on user and background activations. After saving
37
+ selected observations in the transcript, it acknowledges Brain's durable processed-through
38
+ sequence (`brain.last_activation`). Return ends a Tool's synchronous part; explicit finish ends
39
+ its whole execution. A dispatch reply presents the observed results and whether the Tool is
40
+ still running. Later results and finish are presented as observations and wake a model call,
41
+ without inserting a user prompt. An activation with no new actionable observations only
42
+ acknowledges its cursor. Results already consumed during dispatch are not presented again. For unanswered calls in the last saved
38
43
  assistant message, it inserts error Tool results explaining that the turn was interrupted and
39
44
  the operation may have run. Saved results, media and native provider state are preserved.
40
45
  Interrupted turns and environment failures also enter the transcript as runtime observations.
@@ -62,8 +67,9 @@ siblings. For hosted applications, publish bytes with Aex's attachment API and r
62
67
  Compaction explicitly resets the response format and installs a summary only after `end_turn`;
63
68
  a truncated, refused, or unknown summary leaves the original saved context intact.
64
69
 
65
- Version 6.2 targets Brain SDK 0.25 and preserves the 0.23 WIT and URL-media contract. Existing sessions keep their
66
- immutable loop implementation; create new sessions to adopt the updated loop. Keep matching
70
+ Version 7.0 targets Brain SDK 0.28 and `brain:agentloop@0.2.0`. The Tool return/completion
71
+ contract is breaking. Existing sessions retain their immutable loop implementation; the
72
+ server upgrade preflight refuses unclosed sessions from the previous contract. Keep matching
67
73
  server/artifacts for recovery. An upgrade does not migrate or delete session data.
68
74
 
69
75
  Image and PDF blocks remain native media in compaction requests. The JSON-length estimate used
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aexhq/agentloop-pi",
3
- "version": "6.2.0",
3
+ "version": "7.0.0",
4
4
  "description": "Pi-style parallel-Tool Brain extension",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,7 +40,7 @@
40
40
  "prepack": "npm run build"
41
41
  },
42
42
  "dependencies": {
43
- "@aexhq/brain": "0.25.1",
43
+ "@aexhq/brain": "0.28.0",
44
44
  "ajv": "8.20.0",
45
45
  "ajv-formats": "3.0.1",
46
46
  "zod": "4.4.3"
package/src/component.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import * as host from "brain:agentloop/host@0.1.0";
1
+ import * as host from "brain:agentloop/host@0.2.0";
2
2
 
3
3
  import { runPi } from "./logic.mjs";
4
4
 
@@ -18,6 +18,7 @@ export async function turn(input) {
18
18
  try {
19
19
  const output = await runPi({
20
20
  input: JSON.parse(input.inputJson),
21
+ kv: JSON.parse(input.kvJson),
21
22
  transcript: JSON.parse(input.transcriptJson),
22
23
  events: JSON.parse(input.eventsJson),
23
24
  configuration: JSON.parse(input.configurationJson),
@@ -33,6 +34,7 @@ export async function turn(input) {
33
34
  put: (key, value) => hosted(() => host.kvPut(key, JSON.stringify(value))),
34
35
  delete: (key) => hosted(() => host.kvDelete(key)),
35
36
  },
37
+ acknowledge: (through) => hosted(() => host.acknowledge(BigInt(through))),
36
38
  events: (after) => JSON.parse(hosted(() => host.events(BigInt(after)))),
37
39
  model: (request) => JSON.parse(hosted(() => host.model(JSON.stringify(request)))),
38
40
  dispatch: (calls) => JSON.parse(hosted(() => host.dispatch(JSON.stringify(calls)))),
package/src/logic.mjs CHANGED
@@ -67,7 +67,7 @@ export async function runPi(input, context) {
67
67
  const placement = toolPlacement(input.tools, options);
68
68
  const output = structuredOutput(options.output);
69
69
  const transcript = cloneJson(input.transcript);
70
- const observed_sequence = await observeEvents(context, transcript, (await context.kv.read("observed_sequence")) ?? 0);
70
+ let observed = await observeEvents(context, transcript, input.kv?.["brain.last_activation"] ?? 0);
71
71
  const saved = await context.kv.read("checkpoint");
72
72
  const checkpoint = saved === undefined ? { summary: null } : cloneJson(saved);
73
73
  const body = () => checkpoint.summary === null ? transcript : transcript.slice(1);
@@ -104,9 +104,10 @@ export async function runPi(input, context) {
104
104
  ...messages.slice(cut));
105
105
  };
106
106
 
107
- transcript.push({ role: "user", content: [{ type: "text", text: input.input.message }, ...(input.input.media ?? [])] });
107
+ if (input.input != null) transcript.push({ role: "user", content: [{ type: "text", text: input.input.message }, ...(input.input.media ?? [])] });
108
108
  await context.setTranscript(transcript);
109
- await context.kv.put("observed_sequence", observed_sequence);
109
+ await context.acknowledge(observed.through);
110
+ if (input.input == null && !observed.actionable) return {};
110
111
  for (;;) {
111
112
  if (shouldCompact()) {
112
113
  await compact();
@@ -145,7 +146,9 @@ export async function runPi(input, context) {
145
146
  role: "user",
146
147
  content: calls.map(({ call_id }) => toolResult(call_id, byCall.get(call_id))),
147
148
  });
149
+ observed = await observeEvents(context, transcript, observed.through, new Set(results.flatMap(result => result.events.map(event => event.sequence))));
148
150
  await context.setTranscript(transcript);
151
+ await context.acknowledge(observed.through);
149
152
  }
150
153
  }
151
154