@aexhq/agentloop-pi 6.0.0 → 6.1.1
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 +27 -7
- package/dist/loop.component.wasm +0 -0
- package/package.json +4 -2
- package/src/logic.mjs +4 -2
package/README.md
CHANGED
|
@@ -13,8 +13,10 @@ pi's per-turn contract:
|
|
|
13
13
|
`contextWindow - reserveTokens` (default 16384), history older than ~`keepRecentTokens`
|
|
14
14
|
(default 20000) is summarized into pi's structured context checkpoint.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Tools and their Environments coordinate access to shared resources with their own transactions,
|
|
17
|
+
locks or queues. A lock prevents overlap; dependency-sensitive work still needs ordered dispatch
|
|
18
|
+
or a Tool that owns the whole operation. Pi has no per-tool scheduling flag or batch Tool protocol.
|
|
19
|
+
Its steering and follow-up queues are host application concerns and are not ported.
|
|
18
20
|
|
|
19
21
|
```ts
|
|
20
22
|
import { brainEnv } from "@aexhq/brain";
|
|
@@ -32,7 +34,10 @@ The component is built by this package's publisher. Brain consumes the resulting
|
|
|
32
34
|
does not compile its JavaScript source.
|
|
33
35
|
|
|
34
36
|
The loop reads paginated session Events before each turn and saves its observation cursor in
|
|
35
|
-
kv
|
|
37
|
+
kv after saving those observations in the transcript. For unanswered calls in the last saved
|
|
38
|
+
assistant message, it inserts error Tool results explaining that the turn was interrupted and
|
|
39
|
+
the operation may have run. Saved results, media and native provider state are preserved.
|
|
40
|
+
Interrupted turns and environment failures also enter the transcript as runtime observations.
|
|
36
41
|
A failed tool result goes back to the model with `is_error`; the loop does not retry it automatically.
|
|
37
42
|
Brain can release execution between turns without losing this transcript or cursor. The caller
|
|
38
43
|
controls Environment lifetime; a browser closure or provider resource loss can still destroy its
|
|
@@ -48,16 +53,31 @@ Transcript changes and `ctx.kv.read/put/delete` use Brain's state services. KV m
|
|
|
48
53
|
committed inline; missing keys remain distinct from stored JSON null. A later model or
|
|
49
54
|
Tool failure preserves acknowledged writes; turn output contains only the result. Retained
|
|
50
55
|
native model blocks pass through unchanged, and user images enter model context as media.
|
|
51
|
-
|
|
56
|
+
Successful Tool outputs shaped as
|
|
52
57
|
`{ type: "aex_tool_output", version: 1, content, media: [{ type: "image", url }] }`
|
|
53
|
-
|
|
54
|
-
convention; ordinary JSON
|
|
58
|
+
become Tool-result content and native media. Images and PDFs require HTTPS URLs. Browser and MCP
|
|
59
|
+
extensions use this presentation convention; ordinary JSON/base64 remains business data.
|
|
60
|
+
Results keep call IDs and assistant source order, including mixed image/text batches and failed
|
|
61
|
+
siblings. For hosted applications, publish bytes with Aex's attachment API and return its media URL.
|
|
55
62
|
Compaction explicitly resets the response format and installs a summary only after `end_turn`;
|
|
56
63
|
a truncated, refused, or unknown summary leaves the original saved context intact.
|
|
57
64
|
|
|
58
|
-
Version
|
|
65
|
+
Version 6.1 targets Brain SDK 0.24 and preserves the 0.23 WIT and URL-media contract. Existing sessions keep their
|
|
59
66
|
immutable loop implementation; create new sessions to adopt the updated loop. Keep matching
|
|
60
67
|
server/artifacts for recovery. An upgrade does not migrate or delete session data.
|
|
61
68
|
|
|
62
69
|
Image and PDF blocks remain native media in compaction requests. The JSON-length estimate used
|
|
63
70
|
for new context does not measure image/PDF tokens; provider context-limit failures remain explicit.
|
|
71
|
+
|
|
72
|
+
Use `session.send(prompt, { output: { type: AnswerSchema } })` for validated application output.
|
|
73
|
+
Pi finishes when the assistant returns no Tool calls; no special terminal Tool is required.
|
|
74
|
+
Ordinary `send()` returns session state, so `idle` alone does not establish turn success.
|
|
75
|
+
|
|
76
|
+
## Develop the loop
|
|
77
|
+
|
|
78
|
+
From a checkout of this repository, run `npm run test:logic -w packages/loop-pi` or
|
|
79
|
+
`npm run test:logic:watch -w packages/loop-pi`. These execute the existing JavaScript logic tests
|
|
80
|
+
without rebuilding Wasm. Run `npm test -w packages/loop-pi` for the Component build and package
|
|
81
|
+
tests, then the compiled journeys described in the repository README. All release gates remain
|
|
82
|
+
required. A rebuilt Component needs a new admission and session. Package source is not a public
|
|
83
|
+
logic-library entry point, and existing sessions keep their admitted implementation.
|
package/dist/loop.component.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aexhq/agentloop-pi",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "Pi-style parallel-Tool Brain extension",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -31,11 +31,13 @@
|
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "node ../../tools/build-agentloop.mjs src/component.mjs src/index.mjs dist",
|
|
33
33
|
"test": "npm run build && node --test *.test.mjs",
|
|
34
|
+
"test:logic": "node --test loop.test.mjs state.test.mjs",
|
|
35
|
+
"test:logic:watch": "node --test --watch loop.test.mjs state.test.mjs",
|
|
34
36
|
"test:journeys": "node --test test/journeys.mjs",
|
|
35
37
|
"prepack": "npm run build"
|
|
36
38
|
},
|
|
37
39
|
"dependencies": {
|
|
38
|
-
"@aexhq/brain": "0.
|
|
40
|
+
"@aexhq/brain": "0.24.2",
|
|
39
41
|
"zod": "4.4.3"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {}
|
package/src/logic.mjs
CHANGED
|
@@ -67,7 +67,6 @@ export async function runPi(input, context) {
|
|
|
67
67
|
const transcript = cloneJson(input.transcript);
|
|
68
68
|
const observed_sequence = await observeEvents(context, transcript, (await context.kv.read("observed_sequence")) ?? 0);
|
|
69
69
|
const saved = await context.kv.read("checkpoint");
|
|
70
|
-
await context.kv.put("observed_sequence", observed_sequence);
|
|
71
70
|
const checkpoint = saved === undefined ? { summary: null } : cloneJson(saved);
|
|
72
71
|
const body = () => checkpoint.summary === null ? transcript : transcript.slice(1);
|
|
73
72
|
const shouldCompact = () =>
|
|
@@ -104,8 +103,9 @@ export async function runPi(input, context) {
|
|
|
104
103
|
};
|
|
105
104
|
|
|
106
105
|
transcript.push({ role: "user", content: [{ type: "text", text: input.input.message }, ...(input.input.media ?? [])] });
|
|
106
|
+
await context.setTranscript(transcript);
|
|
107
|
+
await context.kv.put("observed_sequence", observed_sequence);
|
|
107
108
|
for (;;) {
|
|
108
|
-
await context.setTranscript(transcript);
|
|
109
109
|
if (shouldCompact()) {
|
|
110
110
|
await compact();
|
|
111
111
|
await context.setTranscript(transcript);
|
|
@@ -127,6 +127,7 @@ export async function runPi(input, context) {
|
|
|
127
127
|
role: "user",
|
|
128
128
|
content: calls.map((call) => ({ type: "tool_result", tool_use_id: call.call_id, content: TRUNCATED_CALL_MESSAGE, is_error: true })),
|
|
129
129
|
});
|
|
130
|
+
await context.setTranscript(transcript);
|
|
130
131
|
continue;
|
|
131
132
|
}
|
|
132
133
|
const results = await context.dispatch(calls.map(placement.invocation));
|
|
@@ -135,6 +136,7 @@ export async function runPi(input, context) {
|
|
|
135
136
|
role: "user",
|
|
136
137
|
content: calls.map(({ call_id }) => toolResult(call_id, byCall.get(call_id))),
|
|
137
138
|
});
|
|
139
|
+
await context.setTranscript(transcript);
|
|
138
140
|
}
|
|
139
141
|
}
|
|
140
142
|
|