@agent-native/core 0.12.8 → 0.12.10
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/agent/production-agent.d.ts +2 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +172 -4
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +28 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/templates-meta.d.ts +2 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +1 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +8 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +147 -7
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +3 -2
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/pasted-text.d.ts.map +1 -1
- package/dist/client/composer/pasted-text.js +5 -6
- package/dist/client/composer/pasted-text.js.map +1 -1
- package/dist/client/extensions/ExtensionViewerPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewerPage.js +4 -0
- package/dist/client/extensions/ExtensionViewerPage.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +137 -55
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/extensions/extension-popularity.d.ts +5 -0
- package/dist/client/extensions/extension-popularity.d.ts.map +1 -0
- package/dist/client/extensions/extension-popularity.js +52 -0
- package/dist/client/extensions/extension-popularity.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +0 -35
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +10 -1
- package/dist/extensions/routes.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +1 -0
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +4 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +4 -6
- package/dist/server/agent-discovery.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EventHandler as H3EventHandler } from "h3";
|
|
2
|
-
import type { ActionTool, AgentChatAttachment, AgentChatEvent } from "./types.js";
|
|
2
|
+
import type { ActionTool, AgentChatAttachment, AgentChatEvent, AgentChatStructuredMessage } from "./types.js";
|
|
3
3
|
import type { AgentEngine, EngineTool, EngineMessage, EngineContentPart } from "./engine/types.js";
|
|
4
4
|
import { PROVIDER_TO_ENV } from "./engine/provider-env-vars.js";
|
|
5
5
|
import { subscribeToRun, getActiveRunForThread, getActiveRunForThreadAsync, getRun, abortRun } from "./run-manager.js";
|
|
@@ -127,6 +127,7 @@ export declare function buildUserContentWithAttachments(opts: {
|
|
|
127
127
|
text: string;
|
|
128
128
|
attachments?: AgentChatAttachment[];
|
|
129
129
|
}): EngineContentPart[];
|
|
130
|
+
export declare function structuredHistoryToEngineMessages(history: AgentChatStructuredMessage[] | undefined): EngineMessage[] | null;
|
|
130
131
|
/** Accumulated token usage from an agent loop run */
|
|
131
132
|
export interface AgentLoopUsage {
|
|
132
133
|
inputTokens: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"production-agent.d.ts","sourceRoot":"","sources":["../../src/agent/production-agent.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,IAAI,cAAc,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,KAAK,EACV,UAAU,EACV,mBAAmB,EAEnB,cAAc,
|
|
1
|
+
{"version":3,"file":"production-agent.d.ts","sourceRoot":"","sources":["../../src/agent/production-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -429,6 +429,69 @@ export function buildUserContentWithAttachments(opts) {
|
|
|
429
429
|
});
|
|
430
430
|
return userContent;
|
|
431
431
|
}
|
|
432
|
+
export function structuredHistoryToEngineMessages(history) {
|
|
433
|
+
if (!Array.isArray(history))
|
|
434
|
+
return null;
|
|
435
|
+
const messages = [];
|
|
436
|
+
for (const message of history) {
|
|
437
|
+
if (!message ||
|
|
438
|
+
(message.role !== "user" && message.role !== "assistant") ||
|
|
439
|
+
!Array.isArray(message.content)) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
const content = [];
|
|
443
|
+
for (const part of message.content) {
|
|
444
|
+
if (!part || typeof part !== "object")
|
|
445
|
+
continue;
|
|
446
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
447
|
+
if (part.text.length > 0) {
|
|
448
|
+
content.push({ type: "text", text: part.text });
|
|
449
|
+
}
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (part.type === "tool-call" && message.role === "assistant") {
|
|
453
|
+
const id = typeof part.id === "string"
|
|
454
|
+
? part.id
|
|
455
|
+
: typeof part.toolCallId === "string"
|
|
456
|
+
? part.toolCallId
|
|
457
|
+
: "";
|
|
458
|
+
const name = typeof part.name === "string"
|
|
459
|
+
? part.name
|
|
460
|
+
: typeof part.toolName === "string"
|
|
461
|
+
? part.toolName
|
|
462
|
+
: "";
|
|
463
|
+
if (!id || !name)
|
|
464
|
+
continue;
|
|
465
|
+
content.push({
|
|
466
|
+
type: "tool-call",
|
|
467
|
+
id,
|
|
468
|
+
name,
|
|
469
|
+
input: part.input ?? part.args ?? {},
|
|
470
|
+
});
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
if (part.type === "tool-result" && message.role === "user") {
|
|
474
|
+
if (typeof part.toolCallId !== "string" ||
|
|
475
|
+
typeof part.content !== "string") {
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
content.push({
|
|
479
|
+
type: "tool-result",
|
|
480
|
+
toolCallId: part.toolCallId,
|
|
481
|
+
...(typeof part.toolName === "string"
|
|
482
|
+
? { toolName: part.toolName }
|
|
483
|
+
: {}),
|
|
484
|
+
content: part.content,
|
|
485
|
+
...(part.isError ? { isError: true } : {}),
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (content.length > 0) {
|
|
490
|
+
messages.push({ role: message.role, content });
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return messages.length > 0 ? messages : null;
|
|
494
|
+
}
|
|
432
495
|
/** Build enriched message with file/skill/mention references */
|
|
433
496
|
function enrichMessage(message, references) {
|
|
434
497
|
if (references.length === 0)
|
|
@@ -487,6 +550,52 @@ export function appendAgentLoopContinuation(messages, reason) {
|
|
|
487
550
|
],
|
|
488
551
|
});
|
|
489
552
|
}
|
|
553
|
+
function textFromEngineMessage(message) {
|
|
554
|
+
return message.content
|
|
555
|
+
.filter((part) => part.type === "text")
|
|
556
|
+
.map((part) => part.text)
|
|
557
|
+
.join("\n");
|
|
558
|
+
}
|
|
559
|
+
function isInternalContinuationTurn(messages) {
|
|
560
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
561
|
+
const message = messages[i];
|
|
562
|
+
if (message.role !== "user")
|
|
563
|
+
continue;
|
|
564
|
+
return textFromEngineMessage(message).startsWith(AGENT_INTERNAL_CONTINUE_PROMPT);
|
|
565
|
+
}
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
function seedReadOnlyToolResultsFromHistory(messages, actions) {
|
|
569
|
+
const cache = new Map();
|
|
570
|
+
if (!isInternalContinuationTurn(messages))
|
|
571
|
+
return cache;
|
|
572
|
+
const pendingToolCalls = new Map();
|
|
573
|
+
for (const message of messages) {
|
|
574
|
+
if (message.role === "assistant") {
|
|
575
|
+
for (const part of message.content) {
|
|
576
|
+
if (part.type !== "tool-call")
|
|
577
|
+
continue;
|
|
578
|
+
const entry = actions[part.name];
|
|
579
|
+
if (entry?.readOnly !== true)
|
|
580
|
+
continue;
|
|
581
|
+
pendingToolCalls.set(part.id, {
|
|
582
|
+
name: part.name,
|
|
583
|
+
input: part.input,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
for (const part of message.content) {
|
|
589
|
+
if (part.type !== "tool-result")
|
|
590
|
+
continue;
|
|
591
|
+
const call = pendingToolCalls.get(part.toolCallId);
|
|
592
|
+
if (!call)
|
|
593
|
+
continue;
|
|
594
|
+
cache.set(toolCallCacheKey(call.name, call.input), part.content);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return cache;
|
|
598
|
+
}
|
|
490
599
|
/**
|
|
491
600
|
* Convert ActionEntry registry to EngineTool array.
|
|
492
601
|
*/
|
|
@@ -531,6 +640,22 @@ function stringifyToolInput(input) {
|
|
|
531
640
|
return String(input);
|
|
532
641
|
}
|
|
533
642
|
}
|
|
643
|
+
function stableStringify(value) {
|
|
644
|
+
if (value === null || typeof value !== "object") {
|
|
645
|
+
return JSON.stringify(value);
|
|
646
|
+
}
|
|
647
|
+
if (Array.isArray(value)) {
|
|
648
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
649
|
+
}
|
|
650
|
+
const obj = value;
|
|
651
|
+
return `{${Object.keys(obj)
|
|
652
|
+
.sort()
|
|
653
|
+
.map((key) => `${JSON.stringify(key)}:${stableStringify(obj[key])}`)
|
|
654
|
+
.join(",")}}`;
|
|
655
|
+
}
|
|
656
|
+
function toolCallCacheKey(toolName, input) {
|
|
657
|
+
return `${toolName}:${stableStringify(normalizeToolCallInputForHistory(input))}`;
|
|
658
|
+
}
|
|
534
659
|
function normalizeToolCallInputForHistory(input) {
|
|
535
660
|
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
536
661
|
return input;
|
|
@@ -564,6 +689,8 @@ export async function runAgentLoop(opts) {
|
|
|
564
689
|
runCtx.toolCalls = toolCallHistory;
|
|
565
690
|
runCtx.toolResults = toolResultHistory;
|
|
566
691
|
}
|
|
692
|
+
const readOnlyToolResultCache = seedReadOnlyToolResultsFromHistory(messages, actions);
|
|
693
|
+
const duplicateReadOnlyToolCalls = new Map();
|
|
567
694
|
let finalGuardRetries = 0;
|
|
568
695
|
let iterations = 0;
|
|
569
696
|
while (true) {
|
|
@@ -734,6 +861,36 @@ export async function runAgentLoop(opts) {
|
|
|
734
861
|
isError: true,
|
|
735
862
|
};
|
|
736
863
|
}
|
|
864
|
+
const cacheKey = actionEntry.readOnly === true
|
|
865
|
+
? toolCallCacheKey(toolCall.name, toolCall.input)
|
|
866
|
+
: null;
|
|
867
|
+
if (cacheKey && readOnlyToolResultCache.has(cacheKey)) {
|
|
868
|
+
const repeats = (duplicateReadOnlyToolCalls.get(cacheKey) ?? 0) + 1;
|
|
869
|
+
duplicateReadOnlyToolCalls.set(cacheKey, repeats);
|
|
870
|
+
const previousResult = readOnlyToolResultCache.get(cacheKey) ?? "";
|
|
871
|
+
const result = `Skipped duplicate read-only call to ${toolCall.name}: identical input already ran in this turn. ` +
|
|
872
|
+
`Use the previous result already in the conversation instead of calling this tool again.\n\n` +
|
|
873
|
+
`Previous result:\n${previousResult}`;
|
|
874
|
+
send({
|
|
875
|
+
type: "tool_start",
|
|
876
|
+
tool: toolCall.name,
|
|
877
|
+
input: toolCall.input,
|
|
878
|
+
});
|
|
879
|
+
send({ type: "tool_done", tool: toolCall.name, result });
|
|
880
|
+
recordToolResult(result, false);
|
|
881
|
+
if (repeats >= 3) {
|
|
882
|
+
requestedActionStop ??= {
|
|
883
|
+
message: "I stopped because the agent kept asking for the same read-only context it already had. Please send the request again if you want me to retry from a fresh turn.",
|
|
884
|
+
errorCode: "duplicate_read_only_tool",
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
return {
|
|
888
|
+
type: "tool-result",
|
|
889
|
+
toolCallId: toolCall.id,
|
|
890
|
+
toolName: toolCall.name,
|
|
891
|
+
content: result,
|
|
892
|
+
};
|
|
893
|
+
}
|
|
737
894
|
send({
|
|
738
895
|
type: "tool_start",
|
|
739
896
|
tool: toolCall.name,
|
|
@@ -823,6 +980,15 @@ export async function runAgentLoop(opts) {
|
|
|
823
980
|
}
|
|
824
981
|
send({ type: "tool_done", tool: toolCall.name, result });
|
|
825
982
|
recordToolResult(result, isError);
|
|
983
|
+
if (!isError) {
|
|
984
|
+
if (cacheKey) {
|
|
985
|
+
readOnlyToolResultCache.set(cacheKey, result);
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
readOnlyToolResultCache.clear();
|
|
989
|
+
duplicateReadOnlyToolCalls.clear();
|
|
990
|
+
}
|
|
991
|
+
}
|
|
826
992
|
return {
|
|
827
993
|
type: "tool-result",
|
|
828
994
|
toolCallId: toolCall.id,
|
|
@@ -913,7 +1079,7 @@ export function createProductionAgentHandler(options) {
|
|
|
913
1079
|
setResponseStatus(event, 400);
|
|
914
1080
|
return { error: "Invalid request body" };
|
|
915
1081
|
}
|
|
916
|
-
const { message, history = [], references = [], threadId, attachments, model: requestModel, engine: requestEngine, effort: requestEffort, } = body;
|
|
1082
|
+
const { message, history = [], structuredHistory, references = [], threadId, attachments, model: requestModel, engine: requestEngine, effort: requestEffort, } = body;
|
|
917
1083
|
const requestMode = body.mode === "plan" ? "plan" : "act";
|
|
918
1084
|
const hasMessageText = typeof message === "string" && message.trim().length > 0;
|
|
919
1085
|
const hasAttachments = Array.isArray(attachments) && attachments.length > 0;
|
|
@@ -1210,13 +1376,15 @@ export function createProductionAgentHandler(options) {
|
|
|
1210
1376
|
text: enrichedMessage + screenContext + filesContext + planModeAgentNote,
|
|
1211
1377
|
attachments,
|
|
1212
1378
|
});
|
|
1213
|
-
const
|
|
1214
|
-
|
|
1379
|
+
const historyMessages = structuredHistoryToEngineMessages(structuredHistory) ??
|
|
1380
|
+
history
|
|
1215
1381
|
.filter((m) => m.content.trim())
|
|
1216
1382
|
.map((m) => ({
|
|
1217
1383
|
role: m.role,
|
|
1218
1384
|
content: [{ type: "text", text: m.content }],
|
|
1219
|
-
}))
|
|
1385
|
+
}));
|
|
1386
|
+
const messages = [
|
|
1387
|
+
...historyMessages,
|
|
1220
1388
|
{ role: "user", content: userContent },
|
|
1221
1389
|
];
|
|
1222
1390
|
// If there's already an active run for this thread, reject with 409 so
|