@economic/agents 2.14.0 → 2.14.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/dist/index.d.mts +15 -2
- package/dist/index.mjs +85 -18
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -226,6 +226,16 @@ interface TurnSnapshot {
|
|
|
226
226
|
frameworkToolNames: string[];
|
|
227
227
|
messages: ModelMessage[];
|
|
228
228
|
}
|
|
229
|
+
type CurrentTurnState<RequestContext extends Record<string, unknown>, UserContext extends Record<string, unknown>> = {
|
|
230
|
+
context?: ToolContext<RequestContext, UserContext>;
|
|
231
|
+
inputTools: ToolSet;
|
|
232
|
+
preparedTools: ToolSet;
|
|
233
|
+
unavailableSkillIds: Set<string>;
|
|
234
|
+
skillsSystemBlock: string;
|
|
235
|
+
visibleSkillNames: string[];
|
|
236
|
+
authorizedSkillNames: Set<string>;
|
|
237
|
+
baseSystem: string;
|
|
238
|
+
};
|
|
229
239
|
type Authentication<UserContext> = {
|
|
230
240
|
success: true;
|
|
231
241
|
userContext?: UserContext;
|
|
@@ -249,8 +259,9 @@ declare abstract class Agent<RequestContext extends Record<string, unknown> = Re
|
|
|
249
259
|
onStart(): Promise<void>;
|
|
250
260
|
configureSession(session: Session): Session;
|
|
251
261
|
onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
|
|
252
|
-
|
|
253
|
-
|
|
262
|
+
protected _turn: CurrentTurnState<RequestContext, UserContext>;
|
|
263
|
+
protected createToolContextForCurrentTurn(requestContext?: RequestContext): ToolContext<RequestContext, UserContext>;
|
|
264
|
+
protected getToolContextForCurrentTurn(): ToolContext<RequestContext, UserContext> | undefined;
|
|
254
265
|
/**
|
|
255
266
|
* Merges the client request `body` into `experimental_context` for tools
|
|
256
267
|
* returned from {@link getTools} only (Think-internal tools are unchanged).
|
|
@@ -508,6 +519,8 @@ declare abstract class ChatAgent<RequestContext extends Record<string, unknown>
|
|
|
508
519
|
* returned immediately and each event reaches the client as it is produced.
|
|
509
520
|
*/
|
|
510
521
|
private streamMessage;
|
|
522
|
+
private streamToolApproval;
|
|
523
|
+
private streamTurn;
|
|
511
524
|
/**
|
|
512
525
|
* Submit feedback for a message by its id.
|
|
513
526
|
* @param messageId - The id of the message to give feedback on.
|
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { Output, convertToModelMessages, generateText, jsonSchema, pruneMessages
|
|
|
4
4
|
import { createRemoteJWKSet, decodeJwt, errors, jwtVerify } from "jose";
|
|
5
5
|
import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
6
6
|
import { genericObservability } from "agents/observability";
|
|
7
|
+
import { applyToolUpdate, toolApprovalUpdate } from "agents/chat";
|
|
7
8
|
import { createCompactFunction, estimateMessageTokens, estimateStringTokens, sanitizeToolPairs, truncateOlderMessages } from "agents/experimental/memory/utils";
|
|
8
9
|
import { nanoid } from "nanoid";
|
|
9
10
|
//#region src/server/features/auth/index.ts
|
|
@@ -1158,13 +1159,17 @@ var Agent = class extends Think {
|
|
|
1158
1159
|
authorizedSkillNames: /* @__PURE__ */ new Set(),
|
|
1159
1160
|
baseSystem: ""
|
|
1160
1161
|
};
|
|
1161
|
-
|
|
1162
|
+
createToolContextForCurrentTurn(requestContext = {}) {
|
|
1162
1163
|
const connectionState = getCurrentAgent().connection?.state;
|
|
1163
1164
|
return {
|
|
1165
|
+
...this._turn.context,
|
|
1164
1166
|
...requestContext,
|
|
1165
1167
|
_userContext: connectionState?.userContext ?? this.userContext
|
|
1166
1168
|
};
|
|
1167
1169
|
}
|
|
1170
|
+
getToolContextForCurrentTurn() {
|
|
1171
|
+
return this._turn.context;
|
|
1172
|
+
}
|
|
1168
1173
|
/**
|
|
1169
1174
|
* Merges the client request `body` into `experimental_context` for tools
|
|
1170
1175
|
* returned from {@link getTools} only (Think-internal tools are unchanged).
|
|
@@ -1175,8 +1180,11 @@ var Agent = class extends Think {
|
|
|
1175
1180
|
async beforeTurn(ctx) {
|
|
1176
1181
|
this.analytics.promptReceived(ctx.messages, ctx.continuation);
|
|
1177
1182
|
this.registerInstanceActivity();
|
|
1178
|
-
const body = await this._applyTokenExchange(
|
|
1179
|
-
|
|
1183
|
+
const body = await this._applyTokenExchange({
|
|
1184
|
+
...this._turn.context,
|
|
1185
|
+
...ctx.body
|
|
1186
|
+
});
|
|
1187
|
+
this._turn.context = this.createToolContextForCurrentTurn(body);
|
|
1180
1188
|
this._turn.inputTools = ctx.tools;
|
|
1181
1189
|
const activeSkillName = this._getLastActivatedSkillName(ctx.messages);
|
|
1182
1190
|
const { tools, activeTools } = await this._prepareTools(ctx.tools, activeSkillName, true);
|
|
@@ -2839,6 +2847,22 @@ var ChatAgent = class extends Agent {
|
|
|
2839
2847
|
if (action === "getMessages" && request.method === "GET") return Response.json(await this.getMessages());
|
|
2840
2848
|
if (action === "getInvocableSkills" && request.method === "GET") return Response.json(await this.getInvocableSkills(auth.userContext));
|
|
2841
2849
|
if (action === "sendMessage" && request.method === "POST") return this.streamMessage(request);
|
|
2850
|
+
if (action === "submitToolApproval" && request.method === "POST") return this.streamToolApproval(request);
|
|
2851
|
+
if (action === "getMessageFeedback" && request.method === "GET") return Response.json(await this.getMessageFeedback());
|
|
2852
|
+
if (action === "submitMessageFeedback" && request.method === "POST") {
|
|
2853
|
+
let payload;
|
|
2854
|
+
try {
|
|
2855
|
+
payload = await request.json();
|
|
2856
|
+
} catch {
|
|
2857
|
+
return Response.json({ error: "Request body must be valid JSON" }, { status: 400 });
|
|
2858
|
+
}
|
|
2859
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return Response.json({ error: "Request body must be an object" }, { status: 400 });
|
|
2860
|
+
const { messageId, rating, comment } = payload;
|
|
2861
|
+
if (!messageId) return Response.json({ error: "Message ID is required" }, { status: 400 });
|
|
2862
|
+
if (rating !== -1 && rating !== 0 && rating !== 1) return Response.json({ error: "Rating must be -1, 0, or 1" }, { status: 400 });
|
|
2863
|
+
if (comment !== void 0 && typeof comment !== "string") return Response.json({ error: "Comment must be a string" }, { status: 400 });
|
|
2864
|
+
return Response.json(await this.submitMessageFeedback(messageId, rating, comment));
|
|
2865
|
+
}
|
|
2842
2866
|
if (action === "cancelChat" && request.method === "POST") {
|
|
2843
2867
|
const { requestId } = await request.json();
|
|
2844
2868
|
this.cancelChat(requestId);
|
|
@@ -2851,38 +2875,81 @@ var ChatAgent = class extends Agent {
|
|
|
2851
2875
|
* returned immediately and each event reaches the client as it is produced.
|
|
2852
2876
|
*/
|
|
2853
2877
|
async streamMessage(request) {
|
|
2854
|
-
let
|
|
2878
|
+
let payload;
|
|
2855
2879
|
try {
|
|
2856
|
-
|
|
2880
|
+
payload = await request.json();
|
|
2857
2881
|
} catch {
|
|
2858
|
-
return Response.json({ error: "
|
|
2882
|
+
return Response.json({ error: "Request body must be valid JSON" }, { status: 400 });
|
|
2859
2883
|
}
|
|
2860
|
-
if (typeof
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2884
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return Response.json({ error: "Request body must be an object" }, { status: 400 });
|
|
2885
|
+
let { message, context } = payload;
|
|
2886
|
+
if (context !== void 0 && (context === null || typeof context !== "object" || Array.isArray(context))) return Response.json({ error: "Context must be an object" }, { status: 400 });
|
|
2887
|
+
if (typeof message === "string") {
|
|
2888
|
+
if (!message.trim()) return Response.json({ error: "Message must not be empty" }, { status: 400 });
|
|
2889
|
+
message = {
|
|
2890
|
+
id: crypto.randomUUID(),
|
|
2891
|
+
role: "user",
|
|
2892
|
+
parts: [{
|
|
2893
|
+
type: "text",
|
|
2894
|
+
text: message
|
|
2895
|
+
}]
|
|
2896
|
+
};
|
|
2897
|
+
} else if (!message || typeof message !== "object" || Array.isArray(message) || typeof message.id !== "string" || !message.id || message.role !== "user" || !Array.isArray(message.parts)) return Response.json({ error: "Message must be a non-empty string or a user UIMessage" }, { status: 400 });
|
|
2898
|
+
const input = context ? () => {
|
|
2899
|
+
this._turn.context = this.createToolContextForCurrentTurn(context);
|
|
2900
|
+
return [message];
|
|
2901
|
+
} : message;
|
|
2902
|
+
return this.streamTurn(input);
|
|
2903
|
+
}
|
|
2904
|
+
async streamToolApproval(request) {
|
|
2905
|
+
let payload;
|
|
2906
|
+
try {
|
|
2907
|
+
payload = await request.json();
|
|
2908
|
+
} catch {
|
|
2909
|
+
return Response.json({ error: "Request body must be valid JSON" }, { status: 400 });
|
|
2910
|
+
}
|
|
2911
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return Response.json({ error: "Request body must be an object" }, { status: 400 });
|
|
2912
|
+
const { toolCallId, approved, context } = payload;
|
|
2913
|
+
if (!toolCallId) return Response.json({ error: "Tool call ID is required" }, { status: 400 });
|
|
2914
|
+
if (typeof approved !== "boolean") return Response.json({ error: "Approved must be a boolean" }, { status: 400 });
|
|
2915
|
+
if (context !== void 0 && (context === null || typeof context !== "object" || Array.isArray(context))) return Response.json({ error: "Context must be an object" }, { status: 400 });
|
|
2916
|
+
return this.streamTurn((messages) => {
|
|
2917
|
+
if (context) this._turn.context = this.createToolContextForCurrentTurn(context);
|
|
2918
|
+
const update = toolApprovalUpdate(toolCallId, approved);
|
|
2919
|
+
let found = false;
|
|
2920
|
+
const updatedMessages = messages.map((message) => {
|
|
2921
|
+
if (found || message.role !== "assistant") return message;
|
|
2922
|
+
const result = applyToolUpdate(message.parts, update);
|
|
2923
|
+
if (!result) return message;
|
|
2924
|
+
found = true;
|
|
2925
|
+
return {
|
|
2926
|
+
...message,
|
|
2927
|
+
parts: result.parts
|
|
2928
|
+
};
|
|
2929
|
+
});
|
|
2930
|
+
if (!found) throw new Error(`No pending tool approval found for ${toolCallId}`);
|
|
2931
|
+
return updatedMessages;
|
|
2932
|
+
});
|
|
2933
|
+
}
|
|
2934
|
+
streamTurn(input) {
|
|
2869
2935
|
const encoder = new TextEncoder();
|
|
2870
2936
|
const readable = new ReadableStream({ start: async (controller) => {
|
|
2871
2937
|
const send = (event, data) => controller.enqueue(encoder.encode(`event: ${event}\ndata: ${data}\n\n`));
|
|
2938
|
+
const sendError = (error) => send("error", JSON.stringify({ error: error instanceof Error ? error.message : String(error) }));
|
|
2872
2939
|
try {
|
|
2873
2940
|
await this.runTurn({
|
|
2874
2941
|
mode: "stream",
|
|
2875
|
-
input
|
|
2942
|
+
input,
|
|
2876
2943
|
callback: {
|
|
2877
2944
|
onStart: (event) => send("start", JSON.stringify(event)),
|
|
2878
2945
|
onEvent: (json) => send("chunk", json),
|
|
2879
2946
|
onDone: () => send("done", "{}"),
|
|
2880
|
-
onError:
|
|
2947
|
+
onError: sendError,
|
|
2881
2948
|
onInterrupted: () => send("interrupted", "{}")
|
|
2882
2949
|
}
|
|
2883
2950
|
});
|
|
2884
2951
|
} catch (error) {
|
|
2885
|
-
|
|
2952
|
+
sendError(error);
|
|
2886
2953
|
} finally {
|
|
2887
2954
|
controller.close();
|
|
2888
2955
|
}
|