@leoustc/ai-runner-codex 0.1.1 → 0.1.2
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/AGENTS.md +5 -0
- package/package.json +1 -1
- package/src/hub.js +11 -5
- package/src/protocol.js +49 -0
package/AGENTS.md
CHANGED
|
@@ -141,6 +141,11 @@ For each valid payload, reply to the Hub as:
|
|
|
141
141
|
{ "requestId": "...", "type": "end", "name": "agent-name" }
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
Large Codex reply text must be split into multiple `message` frames before the
|
|
145
|
+
matching `end`. Each `message.text` chunk should be at most 8 KiB encoded as
|
|
146
|
+
UTF-8. Include `message.chunk` metadata with `index`, `total`, and `maxBytes`
|
|
147
|
+
when a reply has more than one chunk.
|
|
148
|
+
|
|
144
149
|
Errors use:
|
|
145
150
|
|
|
146
151
|
```json
|
package/package.json
CHANGED
package/src/hub.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { codexRequest, codexText, heartbeat, isRoomPayload, registration, reply } from "./protocol.js";
|
|
1
|
+
import { codexRequest, codexText, heartbeat, isRoomPayload, messageReplies, registration, reply } from "./protocol.js";
|
|
2
2
|
import { requestCodex } from "./codex.js";
|
|
3
3
|
import { ensureCodexLogin, isCodexAuthError } from "./login.js";
|
|
4
4
|
|
|
@@ -94,10 +94,10 @@ export class HubClient {
|
|
|
94
94
|
try {
|
|
95
95
|
const response = await this.requestCodexWithLogin(value);
|
|
96
96
|
const text = codexText(response) || "Codex returned no text.";
|
|
97
|
-
this.
|
|
97
|
+
this.sendMessages(value, {
|
|
98
98
|
model: this.config.model,
|
|
99
99
|
text,
|
|
100
|
-
})
|
|
100
|
+
});
|
|
101
101
|
} catch (error) {
|
|
102
102
|
this.send(reply(value, this.config, "error", {
|
|
103
103
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -118,10 +118,10 @@ export class HubClient {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
await ensureCodexLogin(this.config, this.log, async (text) => {
|
|
121
|
-
this.
|
|
121
|
+
this.sendMessages(value, {
|
|
122
122
|
codexLogin: true,
|
|
123
123
|
text,
|
|
124
|
-
})
|
|
124
|
+
});
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
return await requestCodex(this.config, request);
|
|
@@ -210,6 +210,12 @@ export class HubClient {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
sendMessages(payload, message) {
|
|
214
|
+
for (const value of messageReplies(payload, this.config, message)) {
|
|
215
|
+
this.send(value);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
213
219
|
sendNow(value) {
|
|
214
220
|
if (this.socket?.readyState !== WebSocket.OPEN) {
|
|
215
221
|
return false;
|
package/src/protocol.js
CHANGED
|
@@ -36,6 +36,30 @@ export function reply(payload, config, type, message) {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export function messageReplies(payload, config, message, maxBytes = 8 * 1024) {
|
|
40
|
+
if (typeof message?.text !== "string") {
|
|
41
|
+
return [reply(payload, config, "message", message)];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const chunks = splitUtf8Chunks(message.text, maxBytes);
|
|
45
|
+
|
|
46
|
+
return chunks.map((chunk, index) =>
|
|
47
|
+
reply(payload, config, "message", {
|
|
48
|
+
...message,
|
|
49
|
+
text: chunk,
|
|
50
|
+
...(chunks.length > 1
|
|
51
|
+
? {
|
|
52
|
+
chunk: {
|
|
53
|
+
index,
|
|
54
|
+
total: chunks.length,
|
|
55
|
+
maxBytes,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
: {}),
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
export function codexRequest(payload, config) {
|
|
40
64
|
return {
|
|
41
65
|
requestId: payload.requestId,
|
|
@@ -80,3 +104,28 @@ function parseMessage(message) {
|
|
|
80
104
|
}
|
|
81
105
|
}
|
|
82
106
|
|
|
107
|
+
function splitUtf8Chunks(text, maxBytes) {
|
|
108
|
+
const encoder = new TextEncoder();
|
|
109
|
+
const chunks = [];
|
|
110
|
+
let current = "";
|
|
111
|
+
let currentBytes = 0;
|
|
112
|
+
|
|
113
|
+
for (const character of text) {
|
|
114
|
+
const characterBytes = encoder.encode(character).byteLength;
|
|
115
|
+
|
|
116
|
+
if (current && currentBytes + characterBytes > maxBytes) {
|
|
117
|
+
chunks.push(current);
|
|
118
|
+
current = "";
|
|
119
|
+
currentBytes = 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
current += character;
|
|
123
|
+
currentBytes += characterBytes;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (current || chunks.length === 0) {
|
|
127
|
+
chunks.push(current);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return chunks;
|
|
131
|
+
}
|