@hiper2d/ai-agents 0.13.1 → 0.14.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/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +76 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +76 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1527,6 +1527,9 @@ function getProviderSignatureFields(aiType, signature) {
|
|
|
1527
1527
|
if (aiType.startsWith("grok")) {
|
|
1528
1528
|
return { grokEncryptedReasoning: signature };
|
|
1529
1529
|
}
|
|
1530
|
+
if (aiType.startsWith("gpt")) {
|
|
1531
|
+
return { openaiEncryptedReasoning: signature };
|
|
1532
|
+
}
|
|
1530
1533
|
if (aiType.startsWith("muse-")) {
|
|
1531
1534
|
return { metaEncryptedReasoning: signature };
|
|
1532
1535
|
}
|
|
@@ -2351,7 +2354,54 @@ ${instruction}`);
|
|
|
2351
2354
|
* inherited from a default OpenAI can change under us.
|
|
2352
2355
|
*/
|
|
2353
2356
|
reasoningParams() {
|
|
2354
|
-
return
|
|
2357
|
+
return {
|
|
2358
|
+
reasoning: {
|
|
2359
|
+
...this.reasoningEffort ? { effort: toOpenAIEffort(this.reasoningEffort) } : {},
|
|
2360
|
+
// Render reasoning from earlier turns into this sample. It is already the
|
|
2361
|
+
// default on all four models we run, but stated explicitly for the same reason
|
|
2362
|
+
// effort is. It only does anything because we replay the items ourselves.
|
|
2363
|
+
context: "all_turns"
|
|
2364
|
+
}
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2367
|
+
/**
|
|
2368
|
+
* Responses API input items, with each assistant turn's stored reasoning items replayed
|
|
2369
|
+
* immediately before it. OpenAI attaches `encrypted_content` to reasoning items whenever
|
|
2370
|
+
* `store` is false, which is how we call it: the documented stateless route is to preserve
|
|
2371
|
+
* the output items and replay the history yourself, rather than lean on
|
|
2372
|
+
* `previous_response_id` and OpenAI-side session state.
|
|
2373
|
+
*
|
|
2374
|
+
* This was a single flattened string before ("User: ... / Assistant: ..."), which left
|
|
2375
|
+
* nowhere to put reasoning items. The system prompt still travels ONLY as `instructions`.
|
|
2376
|
+
*
|
|
2377
|
+
* Reasoning is readable only within one model family and the API silently omits items it
|
|
2378
|
+
* cannot read, so a bot moved between GPT-6 and GPT-5.6 Terra loses its reasoning and keeps
|
|
2379
|
+
* working. A bot moved to another provider never reaches this code at all: every agent
|
|
2380
|
+
* reads only its own field, and a missing one falls back to a plain message.
|
|
2381
|
+
*/
|
|
2382
|
+
buildResponsesInput(messages) {
|
|
2383
|
+
const input = [];
|
|
2384
|
+
for (const msg of this.prepareMessages(messages)) {
|
|
2385
|
+
if (msg.role === "assistant" && msg.openaiEncryptedReasoning) {
|
|
2386
|
+
try {
|
|
2387
|
+
const items = JSON.parse(msg.openaiEncryptedReasoning);
|
|
2388
|
+
if (Array.isArray(items)) {
|
|
2389
|
+
input.push(...items);
|
|
2390
|
+
}
|
|
2391
|
+
} catch {
|
|
2392
|
+
this.logger("Failed to parse stored encrypted reasoning, replaying message without it");
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
input.push({ role: msg.role, content: msg.content });
|
|
2396
|
+
}
|
|
2397
|
+
return input;
|
|
2398
|
+
}
|
|
2399
|
+
/** The response's reasoning items, JSON-serialized for the caller to store on the message. */
|
|
2400
|
+
extractReasoningItems(response) {
|
|
2401
|
+
const items = (response?.output ?? []).filter(
|
|
2402
|
+
(item) => item?.type === "reasoning" && item.encrypted_content
|
|
2403
|
+
);
|
|
2404
|
+
return items.length > 0 ? JSON.stringify(items) : void 0;
|
|
2355
2405
|
}
|
|
2356
2406
|
/**
|
|
2357
2407
|
* Structured output method using Zod with OpenAI's Responses API
|
|
@@ -2363,7 +2413,7 @@ ${instruction}`);
|
|
|
2363
2413
|
try {
|
|
2364
2414
|
this.logAsking(messages);
|
|
2365
2415
|
this.logMessages(messages);
|
|
2366
|
-
const input = this.
|
|
2416
|
+
const input = this.buildResponsesInput(messages);
|
|
2367
2417
|
const schemaToSend = zodSchema;
|
|
2368
2418
|
let response;
|
|
2369
2419
|
try {
|
|
@@ -2373,6 +2423,8 @@ ${instruction}`);
|
|
|
2373
2423
|
input,
|
|
2374
2424
|
max_output_tokens: this.maxOutputTokens,
|
|
2375
2425
|
prompt_cache_key: this.promptCacheKey,
|
|
2426
|
+
// Stateless: encrypted reasoning is only returned for unstored responses.
|
|
2427
|
+
store: false,
|
|
2376
2428
|
...this.reasoningParams(),
|
|
2377
2429
|
text: {
|
|
2378
2430
|
format: zodTextFormat(schemaToSend, "response_schema")
|
|
@@ -2433,7 +2485,7 @@ ${instruction}`);
|
|
|
2433
2485
|
this.logReply(response.output_parsed, reasoningContent, tokenUsage);
|
|
2434
2486
|
}
|
|
2435
2487
|
this.logger(`\u2705 Response validated successfully with Zod schema`);
|
|
2436
|
-
return [response.output_parsed, reasoningContent, tokenUsage];
|
|
2488
|
+
return [response.output_parsed, reasoningContent, tokenUsage, this.extractReasoningItems(response)];
|
|
2437
2489
|
} catch (error) {
|
|
2438
2490
|
this.logger(this.logTemplates.error(this.name, error));
|
|
2439
2491
|
if (error instanceof ModelError) {
|
|
@@ -2452,13 +2504,14 @@ ${instruction}`);
|
|
|
2452
2504
|
try {
|
|
2453
2505
|
this.logAsking(messages);
|
|
2454
2506
|
this.logMessages(messages);
|
|
2455
|
-
const input = this.
|
|
2507
|
+
const input = this.buildResponsesInput(messages);
|
|
2456
2508
|
const response = await this.client.responses.create({
|
|
2457
2509
|
model: this.model,
|
|
2458
2510
|
instructions: this.instruction,
|
|
2459
2511
|
input,
|
|
2460
2512
|
max_output_tokens: this.maxOutputTokens,
|
|
2461
2513
|
prompt_cache_key: this.promptCacheKey,
|
|
2514
|
+
store: false,
|
|
2462
2515
|
...this.reasoningParams()
|
|
2463
2516
|
});
|
|
2464
2517
|
const content = response.output_text;
|
|
@@ -2500,7 +2553,7 @@ ${instruction}`);
|
|
|
2500
2553
|
}
|
|
2501
2554
|
}
|
|
2502
2555
|
this.logReply(content, "", tokenUsage);
|
|
2503
|
-
return [content, "", tokenUsage];
|
|
2556
|
+
return [content, "", tokenUsage, this.extractReasoningItems(response)];
|
|
2504
2557
|
} catch (error) {
|
|
2505
2558
|
this.logger(this.logTemplates.error(this.name, error));
|
|
2506
2559
|
if (error instanceof ModelError) {
|
|
@@ -4592,13 +4645,29 @@ var QwenAgent = class extends AbstractAgent {
|
|
|
4592
4645
|
const budget = this.thinkingBudgetTokens;
|
|
4593
4646
|
return {
|
|
4594
4647
|
enable_thinking: this.enableThinking,
|
|
4595
|
-
...this.enableThinking && budget !== void 0 ? { thinking_budget: budget } : {}
|
|
4648
|
+
...this.enableThinking && budget !== void 0 ? { thinking_budget: budget } : {},
|
|
4649
|
+
// Lets the model read the `reasoning_content` we replay on assistant messages, so a
|
|
4650
|
+
// bot keeps its own train of thought across turns. Qwen documents models as NOT
|
|
4651
|
+
// reading replayed reasoning unless this is set (qwen3.8-max and qwen3.8-flash are
|
|
4652
|
+
// both on the supported list). Measured 2026-09-22: qwen3.8-max actually used the
|
|
4653
|
+
// replayed reasoning with the flag off too, but we follow the documented contract
|
|
4654
|
+
// rather than rely on that. Stateless — the reasoning comes from our payload, not
|
|
4655
|
+
// from any server-side session.
|
|
4656
|
+
...this.enableThinking ? { preserve_thinking: true } : {}
|
|
4596
4657
|
};
|
|
4597
4658
|
}
|
|
4659
|
+
/**
|
|
4660
|
+
* Assistant turns carry their own `reasoning_content` back so the model can reference what
|
|
4661
|
+
* it was thinking on earlier turns (paired with `preserve_thinking` in thinkingParams).
|
|
4662
|
+
* Qwen's reasoning is PLAIN TEXT, not a signed or encrypted blob, so there is nothing for
|
|
4663
|
+
* another provider to reject: a bot whose model changes mid-game simply stops sending it
|
|
4664
|
+
* and keeps working. The text is the same one the caller already stores as `thinking`.
|
|
4665
|
+
*/
|
|
4598
4666
|
convertToOpenAIMessages(messages) {
|
|
4599
4667
|
return messages.map((msg) => ({
|
|
4600
4668
|
role: msg.role,
|
|
4601
|
-
content: msg.content
|
|
4669
|
+
content: msg.content,
|
|
4670
|
+
...msg.role === "assistant" && msg.thinking ? { reasoning_content: msg.thinking } : {}
|
|
4602
4671
|
}));
|
|
4603
4672
|
}
|
|
4604
4673
|
extractThinkingAndUsage(completion) {
|