@assemblyline-agents/pi 0.1.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/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +503 -0
- package/dist/index.js.map +1 -0
- package/dist/model-stream-retry.d.ts +61 -0
- package/dist/model-stream-retry.d.ts.map +1 -0
- package/dist/model-stream-retry.js +215 -0
- package/dist/model-stream-retry.js.map +1 -0
- package/dist/pi-harness.d.ts +103 -0
- package/dist/pi-harness.d.ts.map +1 -0
- package/dist/pi-harness.js +535 -0
- package/dist/pi-harness.js.map +1 -0
- package/dist/transcript-trim.d.ts +44 -0
- package/dist/transcript-trim.d.ts.map +1 -0
- package/dist/transcript-trim.js +162 -0
- package/dist/transcript-trim.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { Agent } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import { createAssistantMessageEventStream, defaultProviderAuthContext } from "@earendil-works/pi-ai";
|
|
3
|
+
import { resolveModelRetryConfig, streamSimpleWithRetry } from "./model-stream-retry.js";
|
|
4
|
+
const OPENROUTER_MODEL_METADATA_TIMEOUT_MS = 5_000;
|
|
5
|
+
const OPENROUTER_ACCOUNTING_TIMEOUT_MS = 5_000;
|
|
6
|
+
/**
|
|
7
|
+
* A pi model run that ended in `stopReason: "error"`. pi-agent-core catches
|
|
8
|
+
* executor failures (bad/missing API key, provider 4xx/5xx, network) and
|
|
9
|
+
* resolves the run with a synthetic empty assistant message rather than
|
|
10
|
+
* throwing, so without this the runtime would record a successful, empty run.
|
|
11
|
+
*/
|
|
12
|
+
export class PiHarnessRunError extends Error {
|
|
13
|
+
finalAssistant;
|
|
14
|
+
stopReason;
|
|
15
|
+
/** Retryable/fatal/unknown, read duck-typed by the runtime via `modelErrorClassification`. */
|
|
16
|
+
classification;
|
|
17
|
+
constructor(message, finalAssistant, classification = "unknown") {
|
|
18
|
+
super(message);
|
|
19
|
+
this.finalAssistant = finalAssistant;
|
|
20
|
+
this.name = "PiHarnessRunError";
|
|
21
|
+
this.stopReason = finalAssistant.stopReason;
|
|
22
|
+
this.classification = classification;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function createDefaultPiModels(env = process.env) {
|
|
26
|
+
const { builtinModels } = await import("@earendil-works/pi-ai/providers/all");
|
|
27
|
+
const fallback = defaultProviderAuthContext();
|
|
28
|
+
return builtinModels({
|
|
29
|
+
authContext: {
|
|
30
|
+
env: async (name) => {
|
|
31
|
+
const value = env[name];
|
|
32
|
+
if (typeof value === "string" && value.trim().length > 0)
|
|
33
|
+
return value;
|
|
34
|
+
return fallback.env(name);
|
|
35
|
+
},
|
|
36
|
+
fileExists: (path) => fallback.fileExists(path)
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export async function listPiModelSpecs(models) {
|
|
41
|
+
try {
|
|
42
|
+
const catalog = models ?? await createDefaultPiModels();
|
|
43
|
+
const specs = new Set();
|
|
44
|
+
for (const model of catalog.getModels()) {
|
|
45
|
+
specs.add(`${model.provider}/${model.id}`);
|
|
46
|
+
}
|
|
47
|
+
return [...specs].sort();
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function resolvePiModel(models, modelSpec) {
|
|
54
|
+
const slash = modelSpec.indexOf("/");
|
|
55
|
+
if (slash <= 0 || slash === modelSpec.length - 1) {
|
|
56
|
+
throw new Error(`Invalid model specifier "${modelSpec}". Use "provider/model".`);
|
|
57
|
+
}
|
|
58
|
+
const provider = modelSpec.slice(0, slash);
|
|
59
|
+
const modelId = modelSpec.slice(slash + 1);
|
|
60
|
+
const model = models.getModel(provider, modelId);
|
|
61
|
+
if (!model) {
|
|
62
|
+
throw new Error(`Unknown Pi model "${modelSpec}". Register the provider/model with @earendil-works/pi-ai or choose a catalog model.`);
|
|
63
|
+
}
|
|
64
|
+
return model;
|
|
65
|
+
}
|
|
66
|
+
export async function runPiAgentLoop(options) {
|
|
67
|
+
const model = resolvePiModel(options.models, options.modelSpec);
|
|
68
|
+
const retryConfig = resolveModelRetryConfig(options.env);
|
|
69
|
+
let requestIteration = 0;
|
|
70
|
+
let stoppedReason;
|
|
71
|
+
let lastStreamOutcome;
|
|
72
|
+
let agent;
|
|
73
|
+
const initialMessages = options.messages ?? options.recentHistory.map((content) => ({
|
|
74
|
+
role: "user",
|
|
75
|
+
content: [{ type: "text", text: content }],
|
|
76
|
+
timestamp: Date.now()
|
|
77
|
+
}));
|
|
78
|
+
const videos = piVideos(options.media);
|
|
79
|
+
if (videos.length > 0) {
|
|
80
|
+
const videoSupport = await nativeVideoSupport(model, options);
|
|
81
|
+
if (videoSupport !== "supported") {
|
|
82
|
+
return {
|
|
83
|
+
response: nativeVideoUnavailableResponse(options.modelSpec, videoSupport),
|
|
84
|
+
messages: appendCurrentUserMessage(initialMessages, options.message)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const agentOptions = {
|
|
89
|
+
initialState: {
|
|
90
|
+
systemPrompt: options.systemPrompt,
|
|
91
|
+
model,
|
|
92
|
+
messages: initialMessages,
|
|
93
|
+
tools: await options.tools(),
|
|
94
|
+
thinkingLevel: options.reasoning ?? "medium"
|
|
95
|
+
},
|
|
96
|
+
// Tool batches run in parallel by default; pause-capable tools carry
|
|
97
|
+
// executionMode "sequential" on the AgentTool, which serializes any
|
|
98
|
+
// batch that contains one.
|
|
99
|
+
...(options.afterToolCall ? { afterToolCall: options.afterToolCall } : {}),
|
|
100
|
+
streamFn: async (requestModel, context, streamOptions) => {
|
|
101
|
+
if (options.shouldStop?.()) {
|
|
102
|
+
stoppedReason = "control_signal";
|
|
103
|
+
return syntheticStopStream(requestModel);
|
|
104
|
+
}
|
|
105
|
+
if (options.maxIterations !== undefined && requestIteration >= options.maxIterations) {
|
|
106
|
+
stoppedReason = "max_iterations";
|
|
107
|
+
return syntheticStopStream(requestModel);
|
|
108
|
+
}
|
|
109
|
+
requestIteration += 1;
|
|
110
|
+
const request = {
|
|
111
|
+
model: requestModel,
|
|
112
|
+
context
|
|
113
|
+
};
|
|
114
|
+
if (streamOptions)
|
|
115
|
+
request.options = streamOptions;
|
|
116
|
+
await options.onRequestStarted?.(request, { requestIteration });
|
|
117
|
+
const providerOptions = {
|
|
118
|
+
...streamOptions,
|
|
119
|
+
env: { ...compactEnv(streamOptions?.env), ...compactEnv(options.env) }
|
|
120
|
+
};
|
|
121
|
+
if (videos.length > 0) {
|
|
122
|
+
const previousOnPayload = streamOptions?.onPayload;
|
|
123
|
+
providerOptions.onPayload = async (payload, payloadModel) => {
|
|
124
|
+
const transformed = await previousOnPayload?.(payload, payloadModel);
|
|
125
|
+
return injectOpenRouterVideoInputs(transformed ?? payload, videos);
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const iteration = requestIteration;
|
|
129
|
+
return streamSimpleWithRetry({
|
|
130
|
+
streamOnce: (attemptOptions) => options.models.streamSimple(requestModel, context, attemptOptions),
|
|
131
|
+
model: requestModel,
|
|
132
|
+
baseOptions: providerOptions,
|
|
133
|
+
config: retryConfig,
|
|
134
|
+
onRetry: (info) => options.onModelRetry?.(info, { requestIteration: iteration }),
|
|
135
|
+
onOutcome: (outcome) => {
|
|
136
|
+
lastStreamOutcome = outcome;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
prepareNextTurn: async () => ({
|
|
141
|
+
context: {
|
|
142
|
+
systemPrompt: options.systemPrompt,
|
|
143
|
+
messages: agent.state.messages.slice(),
|
|
144
|
+
tools: await options.tools()
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
};
|
|
148
|
+
if (options.sessionId) {
|
|
149
|
+
agent = new Agent({ ...agentOptions, sessionId: options.sessionId });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
agent = new Agent(agentOptions);
|
|
153
|
+
}
|
|
154
|
+
agent.subscribe((event) => options.onEvent?.(event, { requestIteration }));
|
|
155
|
+
// External hard-abort (run cancel / deadline) tears down the in-flight
|
|
156
|
+
// model request; pi surfaces it as stopReason "aborted", an intentional stop.
|
|
157
|
+
let removeAbortListener;
|
|
158
|
+
if (options.signal) {
|
|
159
|
+
const signal = options.signal;
|
|
160
|
+
if (signal.aborted) {
|
|
161
|
+
agent.abort();
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const onAbort = () => agent.abort();
|
|
165
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
166
|
+
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
if (options.mode === "continue") {
|
|
171
|
+
await agent.continue();
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const images = (options.media ?? []).filter((item) => item.type === "image");
|
|
175
|
+
const nativeImages = model.input.includes("image") ? piImages(images) : [];
|
|
176
|
+
const message = images.length > 0
|
|
177
|
+
? mediaPrompt(options.message ?? "", images, model.input.includes("image"))
|
|
178
|
+
: (options.message ?? "");
|
|
179
|
+
await agent.prompt(message, nativeImages);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
removeAbortListener?.();
|
|
184
|
+
}
|
|
185
|
+
const finalAssistant = lastAssistantMessage(agent.state.messages);
|
|
186
|
+
// A genuine model/executor failure surfaces as a synthetic assistant message
|
|
187
|
+
// with stopReason "error"; fail the run instead of returning an empty
|
|
188
|
+
// response the runtime would record as a success. ("aborted" is an
|
|
189
|
+
// intentional stop — shouldStop / cancellation — and is not an error.)
|
|
190
|
+
// Retryable classifications reach here only after the retry envelope in
|
|
191
|
+
// model-stream-retry.ts exhausted its attempts.
|
|
192
|
+
if (finalAssistant?.stopReason === "error") {
|
|
193
|
+
throw new PiHarnessRunError(finalAssistant.errorMessage ?? agent.state.errorMessage ?? "pi model run failed", finalAssistant, lastStreamOutcome?.classification ?? "unknown");
|
|
194
|
+
}
|
|
195
|
+
const messages = agent.state.messages.slice();
|
|
196
|
+
if (stoppedReason && messages.at(-1) === finalAssistant)
|
|
197
|
+
messages.pop();
|
|
198
|
+
const result = {
|
|
199
|
+
response: finalAssistant ? assistantText(finalAssistant) : "",
|
|
200
|
+
messages
|
|
201
|
+
};
|
|
202
|
+
if (finalAssistant)
|
|
203
|
+
result.finalAssistant = finalAssistant;
|
|
204
|
+
if (stoppedReason)
|
|
205
|
+
result.stoppedReason = stoppedReason;
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
function piImages(media) {
|
|
209
|
+
return (media ?? []).filter((item) => item.type === "image").map((item) => ({
|
|
210
|
+
type: "image",
|
|
211
|
+
data: item.data,
|
|
212
|
+
mimeType: item.mimeType
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
function piVideos(media) {
|
|
216
|
+
return (media ?? []).filter((item) => item.type === "video");
|
|
217
|
+
}
|
|
218
|
+
function mediaPrompt(message, media, supportsImages) {
|
|
219
|
+
if (supportsImages || media.length === 0)
|
|
220
|
+
return message;
|
|
221
|
+
return [
|
|
222
|
+
message,
|
|
223
|
+
"",
|
|
224
|
+
"[OpenEve media fallback: the selected model does not accept image input.]",
|
|
225
|
+
...media.map((item) => `- ${item.path ?? item.name ?? item.mimeType} (${item.mimeType})`)
|
|
226
|
+
].join("\n");
|
|
227
|
+
}
|
|
228
|
+
async function nativeVideoSupport(model, options) {
|
|
229
|
+
if (model.provider !== "openrouter" || model.api !== "openai-completions")
|
|
230
|
+
return "unsupported_adapter";
|
|
231
|
+
try {
|
|
232
|
+
const lookup = { modelId: model.id };
|
|
233
|
+
if (options.env)
|
|
234
|
+
lookup.env = options.env;
|
|
235
|
+
if (options.fetch)
|
|
236
|
+
lookup.fetch = options.fetch;
|
|
237
|
+
const modalities = await openRouterModelInputModalities(lookup);
|
|
238
|
+
return modalities.includes("video") ? "supported" : "unsupported_model";
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return "unverified";
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
export async function openRouterModelInputModalities(input) {
|
|
245
|
+
const fetchImpl = input.fetch ?? globalThis.fetch;
|
|
246
|
+
const modelPath = input.modelId.split("/").map((part) => encodeURIComponent(part)).join("/");
|
|
247
|
+
const headers = { accept: "application/json" };
|
|
248
|
+
const apiKey = input.env?.OPENROUTER_API_KEY?.trim();
|
|
249
|
+
if (apiKey)
|
|
250
|
+
headers.authorization = `Bearer ${apiKey}`;
|
|
251
|
+
const response = await fetchImpl(`https://openrouter.ai/api/v1/model/${modelPath}`, {
|
|
252
|
+
headers,
|
|
253
|
+
signal: AbortSignal.timeout(OPENROUTER_MODEL_METADATA_TIMEOUT_MS)
|
|
254
|
+
});
|
|
255
|
+
if (!response.ok) {
|
|
256
|
+
throw new Error(`OpenRouter model metadata returned HTTP ${response.status}.`);
|
|
257
|
+
}
|
|
258
|
+
const payload = await response.json();
|
|
259
|
+
if (!isRecord(payload) || !isRecord(payload.data) || !isRecord(payload.data.architecture)) {
|
|
260
|
+
throw new Error("OpenRouter model metadata omitted architecture.");
|
|
261
|
+
}
|
|
262
|
+
const modalities = payload.data.architecture.input_modalities;
|
|
263
|
+
if (!Array.isArray(modalities))
|
|
264
|
+
throw new Error("OpenRouter model metadata omitted input_modalities.");
|
|
265
|
+
return modalities.filter((value) => typeof value === "string");
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Add complete native videos to the latest user message in an OpenRouter
|
|
269
|
+
* Chat Completions payload. This runs after Pi's text/image conversion because
|
|
270
|
+
* Pi's current public content union does not yet include video.
|
|
271
|
+
*/
|
|
272
|
+
export function injectOpenRouterVideoInputs(payload, videos) {
|
|
273
|
+
if (videos.length === 0)
|
|
274
|
+
return payload;
|
|
275
|
+
if (!isRecord(payload) || !Array.isArray(payload.messages)) {
|
|
276
|
+
throw new Error("Cannot add native video input: OpenRouter payload omitted messages.");
|
|
277
|
+
}
|
|
278
|
+
const messages = payload.messages.slice();
|
|
279
|
+
let userIndex = -1;
|
|
280
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
281
|
+
const message = messages[index];
|
|
282
|
+
if (isRecord(message) && message.role === "user") {
|
|
283
|
+
userIndex = index;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (userIndex < 0)
|
|
288
|
+
throw new Error("Cannot add native video input: OpenRouter payload omitted a user message.");
|
|
289
|
+
const user = messages[userIndex];
|
|
290
|
+
if (!isRecord(user))
|
|
291
|
+
throw new Error("Cannot add native video input: OpenRouter user message is invalid.");
|
|
292
|
+
const content = Array.isArray(user.content)
|
|
293
|
+
? user.content.slice()
|
|
294
|
+
: (typeof user.content === "string" ? [{ type: "text", text: user.content }] : []);
|
|
295
|
+
const existing = new Set(content.flatMap((part) => {
|
|
296
|
+
if (!isRecord(part) || part.type !== "video_url" || !isRecord(part.video_url))
|
|
297
|
+
return [];
|
|
298
|
+
return typeof part.video_url.url === "string" ? [part.video_url.url] : [];
|
|
299
|
+
}));
|
|
300
|
+
for (const video of videos) {
|
|
301
|
+
const url = `data:${video.mimeType};base64,${video.data}`;
|
|
302
|
+
if (!existing.has(url))
|
|
303
|
+
content.push({ type: "video_url", video_url: { url } });
|
|
304
|
+
}
|
|
305
|
+
messages[userIndex] = { ...user, content };
|
|
306
|
+
return { ...payload, messages };
|
|
307
|
+
}
|
|
308
|
+
function nativeVideoUnavailableResponse(modelSpec, support) {
|
|
309
|
+
if (support === "unverified") {
|
|
310
|
+
return `I could not verify whether ${modelSpec} accepts native video input, so I did not send or sample the video. Choose a verified video-capable OpenRouter model or try again when capability discovery is available.`;
|
|
311
|
+
}
|
|
312
|
+
if (support === "unsupported_adapter") {
|
|
313
|
+
return `The current Pi adapter for ${modelSpec} cannot send native video input. I did not extract or sample frames. Choose a video-capable OpenRouter model, or explicitly ask for a frame-based review if that tradeoff is acceptable.`;
|
|
314
|
+
}
|
|
315
|
+
return `The selected model ${modelSpec} does not accept native video input. I did not extract or sample frames. Choose a video-capable OpenRouter model, or explicitly ask for a frame-based review if that tradeoff is acceptable.`;
|
|
316
|
+
}
|
|
317
|
+
function appendCurrentUserMessage(messages, message) {
|
|
318
|
+
if (message === undefined)
|
|
319
|
+
return messages.slice();
|
|
320
|
+
return [
|
|
321
|
+
...messages,
|
|
322
|
+
{
|
|
323
|
+
role: "user",
|
|
324
|
+
content: [{ type: "text", text: message }],
|
|
325
|
+
timestamp: Date.now()
|
|
326
|
+
}
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Empty assistant "stop" response for a loop whose run already paused: no
|
|
331
|
+
* model request is made, the loop sees zero tool calls and ends the loop invocation.
|
|
332
|
+
* Resume-with-toolResult truncates the transcript after the spliced result,
|
|
333
|
+
* so the empty message never reaches a real model request.
|
|
334
|
+
*/
|
|
335
|
+
function syntheticStopStream(model) {
|
|
336
|
+
const message = {
|
|
337
|
+
role: "assistant",
|
|
338
|
+
content: [],
|
|
339
|
+
api: model.api,
|
|
340
|
+
provider: model.provider,
|
|
341
|
+
model: model.id,
|
|
342
|
+
usage: {
|
|
343
|
+
input: 0,
|
|
344
|
+
output: 0,
|
|
345
|
+
cacheRead: 0,
|
|
346
|
+
cacheWrite: 0,
|
|
347
|
+
totalTokens: 0,
|
|
348
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
349
|
+
},
|
|
350
|
+
stopReason: "stop",
|
|
351
|
+
timestamp: Date.now()
|
|
352
|
+
};
|
|
353
|
+
const stream = createAssistantMessageEventStream();
|
|
354
|
+
stream.push({ type: "start", partial: { ...message } });
|
|
355
|
+
stream.push({ type: "done", reason: "stop", message });
|
|
356
|
+
return stream;
|
|
357
|
+
}
|
|
358
|
+
export function piUsageToRuntime(usage) {
|
|
359
|
+
if (!usage)
|
|
360
|
+
return {};
|
|
361
|
+
const out = {};
|
|
362
|
+
if (usage.input !== undefined)
|
|
363
|
+
out.inputTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
364
|
+
if (usage.output !== undefined)
|
|
365
|
+
out.outputTokens = usage.output;
|
|
366
|
+
if (usage.cacheRead !== undefined)
|
|
367
|
+
out.cachedTokens = usage.cacheRead;
|
|
368
|
+
if (usage.cacheWrite !== undefined)
|
|
369
|
+
out.cacheWriteTokens = usage.cacheWrite;
|
|
370
|
+
out.tokenSource = "provider_reported";
|
|
371
|
+
// Pi's catalog-price calculation is not a provider charge, so it is
|
|
372
|
+
// intentionally excluded from source-backed cash accounting.
|
|
373
|
+
out.costSource = "unavailable";
|
|
374
|
+
return out;
|
|
375
|
+
}
|
|
376
|
+
/** Resolve provider-settled usage for a completed Pi assistant message. */
|
|
377
|
+
export async function piMessageAccounting(message, options = {}) {
|
|
378
|
+
const fallback = piUsageToRuntime(message.usage);
|
|
379
|
+
if (message.provider !== "openrouter" || !message.responseId) {
|
|
380
|
+
return {
|
|
381
|
+
usage: fallback,
|
|
382
|
+
billingMode: "api_key",
|
|
383
|
+
...(message.responseId ? { providerRequestId: message.responseId } : {})
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
const reconciled = await openRouterGenerationAccounting(message.responseId, {
|
|
387
|
+
...options,
|
|
388
|
+
fallback
|
|
389
|
+
});
|
|
390
|
+
if (reconciled)
|
|
391
|
+
return reconciled;
|
|
392
|
+
return {
|
|
393
|
+
usage: fallback,
|
|
394
|
+
providerRequestId: message.responseId,
|
|
395
|
+
billingMode: "api_key",
|
|
396
|
+
providerReceipt: {
|
|
397
|
+
generationId: message.responseId,
|
|
398
|
+
reconciliationStatus: "pending"
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/** Fetch an immutable OpenRouter generation receipt for initial or retry reconciliation. */
|
|
403
|
+
export async function openRouterGenerationAccounting(generationId, options = {}) {
|
|
404
|
+
const fallback = options.fallback ?? {};
|
|
405
|
+
const generation = await fetchOpenRouterGeneration({
|
|
406
|
+
generationId,
|
|
407
|
+
...(options.env ? { env: options.env } : {}),
|
|
408
|
+
...(options.fetch ? { fetch: options.fetch } : {})
|
|
409
|
+
});
|
|
410
|
+
if (!generation)
|
|
411
|
+
return undefined;
|
|
412
|
+
const inputTokens = integerField(generation.native_tokens_prompt, generation.tokens_prompt, fallback.inputTokens);
|
|
413
|
+
const outputTokens = integerField(generation.native_tokens_completion, generation.tokens_completion, fallback.outputTokens);
|
|
414
|
+
const cachedTokens = integerField(generation.native_tokens_cached, generation.cached_tokens, fallback.cachedTokens);
|
|
415
|
+
const reasoningTokens = integerField(generation.native_tokens_reasoning, generation.reasoning_tokens);
|
|
416
|
+
const totalCost = numberField(generation.total_cost, generation.usage);
|
|
417
|
+
const upstreamCost = numberField(generation.upstream_inference_cost);
|
|
418
|
+
const byok = generation.is_byok === true;
|
|
419
|
+
const usage = {
|
|
420
|
+
...fallback,
|
|
421
|
+
...(inputTokens !== undefined ? { inputTokens } : {}),
|
|
422
|
+
...(outputTokens !== undefined ? { outputTokens } : {}),
|
|
423
|
+
...(cachedTokens !== undefined ? { cachedTokens } : {}),
|
|
424
|
+
...(reasoningTokens !== undefined ? { reasoningTokens } : {}),
|
|
425
|
+
...(totalCost !== undefined ? { costUsd: totalCost } : {}),
|
|
426
|
+
...(upstreamCost !== undefined ? { upstreamCostUsd: upstreamCost } : {}),
|
|
427
|
+
currency: "USD",
|
|
428
|
+
tokenSource: "provider_reconciled",
|
|
429
|
+
costSource: totalCost !== undefined ? "provider_reconciled" : "unavailable"
|
|
430
|
+
};
|
|
431
|
+
const receipt = {
|
|
432
|
+
generationId,
|
|
433
|
+
reconciliationStatus: "reconciled",
|
|
434
|
+
...(stringField(generation.request_id) ? { requestId: stringField(generation.request_id) } : {}),
|
|
435
|
+
...(stringField(generation.upstream_id) ? { upstreamId: stringField(generation.upstream_id) } : {}),
|
|
436
|
+
...(stringField(generation.provider_name) ? { providerName: stringField(generation.provider_name) } : {}),
|
|
437
|
+
...(stringField(generation.model) ? { model: stringField(generation.model) } : {}),
|
|
438
|
+
...(totalCost !== undefined ? { totalCostUsd: totalCost } : {}),
|
|
439
|
+
...(upstreamCost !== undefined ? { upstreamCostUsd: upstreamCost } : {}),
|
|
440
|
+
...(inputTokens !== undefined ? { inputTokens } : {}),
|
|
441
|
+
...(outputTokens !== undefined ? { outputTokens } : {}),
|
|
442
|
+
...(cachedTokens !== undefined ? { cachedTokens } : {}),
|
|
443
|
+
...(reasoningTokens !== undefined ? { reasoningTokens } : {}),
|
|
444
|
+
byok
|
|
445
|
+
};
|
|
446
|
+
return {
|
|
447
|
+
usage,
|
|
448
|
+
providerRequestId: generationId,
|
|
449
|
+
billingMode: byok ? "byok" : "api_key",
|
|
450
|
+
providerReceipt: receipt
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
async function fetchOpenRouterGeneration(input) {
|
|
454
|
+
const key = input.env?.OPENROUTER_API_KEY?.trim();
|
|
455
|
+
if (!key)
|
|
456
|
+
return undefined;
|
|
457
|
+
const fetchImpl = input.fetch ?? globalThis.fetch;
|
|
458
|
+
for (const delayMs of [0, 150, 500]) {
|
|
459
|
+
if (delayMs > 0)
|
|
460
|
+
await delay(delayMs);
|
|
461
|
+
try {
|
|
462
|
+
const response = await fetchWithTimeout(fetchImpl, `https://openrouter.ai/api/v1/generation?id=${encodeURIComponent(input.generationId)}`, { headers: { authorization: `Bearer ${key}` } }, OPENROUTER_ACCOUNTING_TIMEOUT_MS);
|
|
463
|
+
if (!response.ok)
|
|
464
|
+
continue;
|
|
465
|
+
const body = jsonObject(await response.json());
|
|
466
|
+
const data = jsonObject(body?.data);
|
|
467
|
+
if (data)
|
|
468
|
+
return data;
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
// The ledger records this as unavailable; reconciliation can retry.
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return undefined;
|
|
475
|
+
}
|
|
476
|
+
async function fetchWithTimeout(fetchImpl, url, init, timeoutMs) {
|
|
477
|
+
const controller = new AbortController();
|
|
478
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
479
|
+
timer.unref?.();
|
|
480
|
+
try {
|
|
481
|
+
return await fetchImpl(url, { ...init, signal: controller.signal });
|
|
482
|
+
}
|
|
483
|
+
finally {
|
|
484
|
+
clearTimeout(timer);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function jsonObject(value) {
|
|
488
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value)
|
|
489
|
+
? value
|
|
490
|
+
: undefined;
|
|
491
|
+
}
|
|
492
|
+
function numberField(...values) {
|
|
493
|
+
for (const value of values) {
|
|
494
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
495
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
496
|
+
return parsed;
|
|
497
|
+
}
|
|
498
|
+
return undefined;
|
|
499
|
+
}
|
|
500
|
+
function integerField(...values) {
|
|
501
|
+
const value = numberField(...values);
|
|
502
|
+
return value === undefined ? undefined : Math.floor(value);
|
|
503
|
+
}
|
|
504
|
+
function stringField(value) {
|
|
505
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
506
|
+
}
|
|
507
|
+
function delay(ms) {
|
|
508
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
509
|
+
}
|
|
510
|
+
export function assistantText(message) {
|
|
511
|
+
return message.content
|
|
512
|
+
.filter((block) => block.type === "text")
|
|
513
|
+
.map((block) => block.text)
|
|
514
|
+
.join("");
|
|
515
|
+
}
|
|
516
|
+
function lastAssistantMessage(messages) {
|
|
517
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
518
|
+
const message = messages[index];
|
|
519
|
+
if (message?.role === "assistant")
|
|
520
|
+
return message;
|
|
521
|
+
}
|
|
522
|
+
return undefined;
|
|
523
|
+
}
|
|
524
|
+
function compactEnv(env) {
|
|
525
|
+
const out = {};
|
|
526
|
+
for (const [key, value] of Object.entries(env ?? {})) {
|
|
527
|
+
if (typeof value === "string")
|
|
528
|
+
out[key] = value;
|
|
529
|
+
}
|
|
530
|
+
return out;
|
|
531
|
+
}
|
|
532
|
+
function isRecord(value) {
|
|
533
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
534
|
+
}
|
|
535
|
+
//# sourceMappingURL=pi-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-harness.js","sourceRoot":"","sources":["../src/pi-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type AgentMessage } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { Models } from "@earendil-works/pi-ai";
|
|
3
|
+
/**
|
|
4
|
+
* Conversation transcript trimming for the pi harness, layered the way
|
|
5
|
+
* production agents converge on:
|
|
6
|
+
*
|
|
7
|
+
* 1. A lossless-ish cap pass replaces stale tool-result bodies outside the
|
|
8
|
+
* recent tail with a restorable marker (no model call; tool output is
|
|
9
|
+
* re-derivable from the sandbox or by re-running the tool).
|
|
10
|
+
* 2. When the transcript still exceeds `contextWindow - reserveTokens`, older
|
|
11
|
+
* full turns are summarized into a structured context checkpoint via
|
|
12
|
+
* pi-agent-core's `generateSummary`, keeping approximately
|
|
13
|
+
* `keepRecentTokens` of recent messages verbatim and never separating a
|
|
14
|
+
* tool result from its call. Re-compaction feeds the previous summary back
|
|
15
|
+
* in, updating it instead of stacking summaries.
|
|
16
|
+
*/
|
|
17
|
+
export declare const TRANSCRIPT_SUMMARY_PREFIX = "[OpenEve conversation summary]";
|
|
18
|
+
export declare const DEFAULT_TRANSCRIPT_CONTEXT_WINDOW = 100000;
|
|
19
|
+
export interface PiTranscriptCapResult {
|
|
20
|
+
messages: AgentMessage[];
|
|
21
|
+
cappedToolResults: number;
|
|
22
|
+
}
|
|
23
|
+
/** Cap tool-result text bodies older than the recent-token tail. */
|
|
24
|
+
export declare function capPiToolResults(messages: AgentMessage[], keepRecentTokens: number, toolResultCapChars: number): PiTranscriptCapResult;
|
|
25
|
+
export declare function estimateTranscriptTokens(messages: AgentMessage[]): number;
|
|
26
|
+
/** Resolve the model's context window for trim gating; unknown models use a conservative default. */
|
|
27
|
+
export declare function transcriptContextWindow(models: Models, modelSpec: string): number;
|
|
28
|
+
export interface PiTranscriptCompactionInput {
|
|
29
|
+
messages: AgentMessage[];
|
|
30
|
+
models: Models;
|
|
31
|
+
modelSpec: string;
|
|
32
|
+
reserveTokens: number;
|
|
33
|
+
keepRecentTokens: number;
|
|
34
|
+
signal?: AbortSignal | undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Summarize older full turns into a checkpoint message, keeping the recent
|
|
38
|
+
* tail verbatim. Returns undefined when there is no compactable head (e.g. a
|
|
39
|
+
* single oversized turn). Throws when summarization itself fails so the
|
|
40
|
+
* caller can fall back instead of resuming a transcript that cannot fit.
|
|
41
|
+
*/
|
|
42
|
+
export declare function compactPiTranscript(input: PiTranscriptCompactionInput): Promise<AgentMessage[] | undefined>;
|
|
43
|
+
export declare function isSummaryMessage(message: AgentMessage): boolean;
|
|
44
|
+
//# sourceMappingURL=transcript-trim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-trim.d.ts","sourceRoot":"","sources":["../src/transcript-trim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,KAAK,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACnG,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,yBAAyB,mCAAmC,CAAC;AAC1E,eAAO,MAAM,iCAAiC,SAAU,CAAC;AAKzD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,YAAY,EAAE,EACxB,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,GACzB,qBAAqB,CAkBvB;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAEzE;AAED,qGAAqG;AACrG,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjF;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,YAAY,EAAE,GAAG,SAAS,CAAC,CA2BjH;AAqDD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAK/D"}
|