@adminforth/agent 1.4.0 → 1.6.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.
@@ -21,8 +21,11 @@ export type SequenceDebug = {
21
21
  sequenceId: number;
22
22
  startedAt: string;
23
23
  prompt: string;
24
+ promptTokens: number;
24
25
  reasoning: string;
26
+ reasoningTokens: number;
25
27
  text: string;
28
+ textTokens: number;
26
29
  cachedTokens: number;
27
30
  responseId: string | null;
28
31
  toolCalls: SequenceDebugToolCall[];
@@ -37,14 +40,18 @@ type PendingSequenceDebug = Omit<SequenceDebug, "toolCalls" | "endedAt" | "resul
37
40
  };
38
41
 
39
42
  type SequenceDebugModelCall = {
43
+ promptTokens: number;
40
44
  reasoning: string;
45
+ reasoningTokens: number;
41
46
  text: string;
47
+ textTokens: number;
42
48
  cachedTokens: number;
43
49
  responseId: string | null;
44
50
  resultType: SequenceDebugResultType;
45
51
  };
46
52
 
47
53
  type OpenAiUsageMetadata = {
54
+ input_tokens?: number;
48
55
  input_token_details?: {
49
56
  cache_read?: number;
50
57
  };
@@ -70,8 +77,11 @@ function createPendingSequenceDebug(sequenceId: number): PendingSequenceDebug {
70
77
  sequenceId,
71
78
  startedAt: new Date().toISOString(),
72
79
  prompt: "",
80
+ promptTokens: 0,
73
81
  reasoning: "",
82
+ reasoningTokens: 0,
74
83
  text: "",
84
+ textTokens: 0,
75
85
  cachedTokens: 0,
76
86
  responseId: null,
77
87
  toolCalls: [],
@@ -97,8 +107,11 @@ function finalizeSequenceDebug(sequence: PendingSequenceDebug): SequenceDebug {
97
107
  sequenceId: sequence.sequenceId,
98
108
  startedAt: sequence.startedAt,
99
109
  prompt: sequence.prompt,
110
+ promptTokens: sequence.promptTokens,
100
111
  reasoning: sequence.reasoning,
112
+ reasoningTokens: sequence.reasoningTokens,
101
113
  text: sequence.text,
114
+ textTokens: sequence.textTokens,
102
115
  cachedTokens: sequence.cachedTokens,
103
116
  responseId: sequence.responseId,
104
117
  toolCalls: sequence.toolCalls.map(({ completed: _completed, ...toolCall }) => toolCall),
@@ -176,6 +189,29 @@ function hasToolCallSignal(message: {
176
189
  );
177
190
  }
178
191
 
192
+ function hasTokenCounter(model: unknown): model is {
193
+ getNumTokens: (content: string) => Promise<number>;
194
+ } {
195
+ return (
196
+ typeof model === "object" &&
197
+ model !== null &&
198
+ "getNumTokens" in model &&
199
+ typeof model.getNumTokens === "function"
200
+ );
201
+ }
202
+
203
+ async function countTokens(model: unknown, content: string) {
204
+ if (!content) {
205
+ return 0;
206
+ }
207
+
208
+ if (!hasTokenCounter(model)) {
209
+ return 0;
210
+ }
211
+
212
+ return await model.getNumTokens(content);
213
+ }
214
+
179
215
  function extractSequenceResponseDebug(message: AIMessage): SequenceDebugModelCall {
180
216
  const blocks = getMessageBlocks(message);
181
217
  const reasoning = blocks
@@ -188,8 +224,13 @@ function extractSequenceResponseDebug(message: AIMessage): SequenceDebugModelCal
188
224
  .join("");
189
225
 
190
226
  return {
227
+ promptTokens:
228
+ (message.usage_metadata as OpenAiUsageMetadata | undefined)?.input_tokens ??
229
+ 0,
191
230
  reasoning,
231
+ reasoningTokens: 0,
192
232
  text: textFromBlocks || (typeof message.content === "string" ? message.content : ""),
233
+ textTokens: 0,
193
234
  cachedTokens:
194
235
  (message.usage_metadata as OpenAiUsageMetadata | undefined)
195
236
  ?.input_token_details?.cache_read ?? 0,
@@ -238,8 +279,11 @@ export function createSequenceDebugCollector(): SequenceDebugCollector {
238
279
  },
239
280
  handleModelCallComplete(params) {
240
281
  const sequenceDebug = ensureSequenceDebug();
282
+ sequenceDebug.promptTokens = params.promptTokens;
241
283
  sequenceDebug.reasoning = params.reasoning;
284
+ sequenceDebug.reasoningTokens = params.reasoningTokens;
242
285
  sequenceDebug.text = params.text;
286
+ sequenceDebug.textTokens = params.textTokens;
243
287
  sequenceDebug.cachedTokens = params.cachedTokens;
244
288
  sequenceDebug.responseId = params.responseId;
245
289
  sequenceDebug.resultType = params.resultType;
@@ -311,17 +355,31 @@ export function createSequenceDebugMiddleware(
311
355
  return createMiddleware({
312
356
  name: "SequenceDebugMiddleware",
313
357
  async wrapModelCall(request, handler) {
358
+ const prompt = stringifyPromptForDebug({
359
+ systemMessage: request.systemMessage,
360
+ messages: request.messages,
361
+ tools: request.tools,
362
+ modelSettings: request.modelSettings,
363
+ });
364
+
314
365
  sink.handleModelCallStart(
315
- stringifyPromptForDebug({
316
- systemMessage: request.systemMessage,
317
- messages: request.messages,
318
- tools: request.tools,
319
- modelSettings: request.modelSettings,
320
- }),
366
+ prompt,
321
367
  );
322
368
 
323
369
  const response = await handler(request) as AIMessage;
324
- sink.handleModelCallComplete(extractSequenceResponseDebug(response));
370
+ const debug = extractSequenceResponseDebug(response);
371
+ const [promptTokens, reasoningTokens, textTokens] = await Promise.all([
372
+ debug.promptTokens || countTokens(request.model, prompt),
373
+ countTokens(request.model, debug.reasoning),
374
+ countTokens(request.model, debug.text),
375
+ ]);
376
+
377
+ sink.handleModelCallComplete({
378
+ ...debug,
379
+ promptTokens,
380
+ reasoningTokens,
381
+ textTokens,
382
+ });
325
383
  return response;
326
384
  },
327
385
  });
@@ -6,6 +6,11 @@ import { parse as parseYaml } from "yaml";
6
6
  const PLUGIN_SKILLS_DIRECTORY_PATH = fileURLToPath(
7
7
  new URL("../../custom/skills/", import.meta.url),
8
8
  );
9
+ const USER_PLUGIN_SKILLS_DIRECTORY_PATH_SEGMENTS = [
10
+ "plugins",
11
+ "adminforth-agent",
12
+ "skills",
13
+ ];
9
14
  const SKILL_MARKDOWN_FILENAME = "SKILL.md";
10
15
  const SKILL_FRONTMATTER_SEPARATOR = "\n---\n";
11
16
 
@@ -78,13 +83,31 @@ export function getProjectSkillsDirectoryPath(customComponentsDir: string) {
78
83
  return path.resolve(customComponentsDir, "skills");
79
84
  }
80
85
 
86
+ export function getProjectPluginSkillsDirectoryPath(customComponentsDir: string) {
87
+ return path.resolve(
88
+ customComponentsDir,
89
+ ...USER_PLUGIN_SKILLS_DIRECTORY_PATH_SEGMENTS,
90
+ );
91
+ }
92
+
93
+ function getProjectSkillDirectoryPaths(customComponentsDir: string) {
94
+ return [
95
+ getProjectSkillsDirectoryPath(customComponentsDir),
96
+ getProjectPluginSkillsDirectoryPath(customComponentsDir),
97
+ ];
98
+ }
99
+
81
100
  export async function listBundledSkillManifests() {
82
101
  return await listDirectorySkillManifests(PLUGIN_SKILLS_DIRECTORY_PATH);
83
102
  }
84
103
 
85
104
  export async function listProjectSkillManifests(customComponentsDir: string) {
86
- return await listDirectorySkillManifests(
87
- getProjectSkillsDirectoryPath(customComponentsDir),
105
+ return mergeSkillManifests(
106
+ await Promise.all(
107
+ getProjectSkillDirectoryPaths(customComponentsDir).map(
108
+ listDirectorySkillManifests,
109
+ ),
110
+ ),
88
111
  );
89
112
  }
90
113
 
@@ -114,7 +137,7 @@ export async function loadSkillMarkdown(skillName: string, customComponentsDir:
114
137
  }
115
138
 
116
139
  const directories = [
117
- getProjectSkillsDirectoryPath(customComponentsDir),
140
+ ...getProjectSkillDirectoryPaths(customComponentsDir),
118
141
  PLUGIN_SKILLS_DIRECTORY_PATH,
119
142
  ];
120
143
 
@@ -24,11 +24,17 @@ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
24
24
  "Keep responses short, clear, and practical.",
25
25
  "Answer only what is needed.",
26
26
  "Do not add extra explanations or suggestions unless the user asks.",
27
+ "Always respond in the same natural language as the user's latest message.",
28
+ "This rule applies to confirmations, clarifying questions, progress updates, errors, and final answers.",
29
+ "Do not switch to English just because tool outputs, schemas, skills, or internal instructions are written in English.",
30
+ "Only switch language if the user explicitly asks you to do so.",
27
31
  "Adapt to the user's tone and style of speaking, mirroring their vibe and wording.",
28
32
  "if the user speaks casually, you should respond casually too",
29
- "Never mutate data without a fresh user confirmation for that exact mutation.",
30
- "A previous confirmation does not carry over to later create, update, delete, or action calls.",
31
- "Each separate mutation or explicitly described batch needs its own confirmation immediately before the tool call.",
33
+ "Never mutate data without user confirmation for a clearly described mutation plan.",
34
+ "One confirmation may cover one mutation or one explicitly described batch/sequence of related mutations.",
35
+ "If the confirmed plan has multiple steps, you may execute the whole confirmed plan without asking again between those steps.",
36
+ "If the plan changes, expands, or you want to do anything beyond the confirmed plan, ask for confirmation again.",
37
+ "Do not reuse an old confirmation for a new mutation plan.",
32
38
 
33
39
 
34
40
  ].join(" ");
package/build.log CHANGED
@@ -29,5 +29,5 @@ custom/skills/fetch_data/SKILL.md
29
29
  custom/skills/mutate_data/
30
30
  custom/skills/mutate_data/SKILL.md
31
31
 
32
- sent 170,096 bytes received 413 bytes 341,018.00 bytes/sec
33
- total size is 168,447 speedup is 0.99
32
+ sent 170,361 bytes received 413 bytes 341,548.00 bytes/sec
33
+ total size is 168,687 speedup is 0.99
@@ -29,17 +29,22 @@ When creating new record, show user all data which you gona create and in same m
29
29
 
30
30
  Accept any positive confirmation from user like "yes", "sure", "+", anything non-negative call to action, can be considered as confirmation.
31
31
 
32
- A confirmation is valid only for the exact mutation plan from the immediately previous assistant message.
32
+ A confirmation is valid only for the clearly described mutation plan from the immediately previous assistant message.
33
33
 
34
34
  Never reuse an older confirmation for a later mutation.
35
35
 
36
- After one mutation is executed, confirmation is consumed and reset.
36
+ One confirmation may cover:
37
+ - one single mutation
38
+ - one explicitly described batch
39
+ - one short sequence of related mutations that together implement the same user request
37
40
 
38
- If you want to perform another create/update/delete/action after that, ask for confirmation again even if the user previously said "yes".
41
+ If the confirmed plan contains several related mutation steps, execute that whole confirmed plan without asking again between those steps.
39
42
 
40
- If the mutation plan changes in any way (different record, different fields, different values, different number of records, different action), the old confirmation is invalid and you must ask again.
43
+ Ask for confirmation again if the plan changes in any way: different record, different fields, different values, different number of records, different action, or any extra mutation that was not listed in the confirmation message.
41
44
 
42
- If you are creating or deleting multiple records in one batch, you may ask once only for that exact batch, but you must list the whole batch explicitly in the confirmation message. Any extra record outside that described batch requires a new confirmation.
45
+ If you are creating or deleting multiple records in one batch, you may ask once for that exact batch, but list the whole batch explicitly in the confirmation message. Any extra record outside that described batch requires a new confirmation.
46
+
47
+ After the confirmed plan is finished, do not treat that confirmation as still active for later requests.
43
48
 
44
49
  # Calling actions
45
50
 
@@ -25,8 +25,11 @@ function createPendingSequenceDebug(sequenceId) {
25
25
  sequenceId,
26
26
  startedAt: new Date().toISOString(),
27
27
  prompt: "",
28
+ promptTokens: 0,
28
29
  reasoning: "",
30
+ reasoningTokens: 0,
29
31
  text: "",
32
+ textTokens: 0,
30
33
  cachedTokens: 0,
31
34
  responseId: null,
32
35
  toolCalls: [],
@@ -47,8 +50,11 @@ function finalizeSequenceDebug(sequence) {
47
50
  sequenceId: sequence.sequenceId,
48
51
  startedAt: sequence.startedAt,
49
52
  prompt: sequence.prompt,
53
+ promptTokens: sequence.promptTokens,
50
54
  reasoning: sequence.reasoning,
55
+ reasoningTokens: sequence.reasoningTokens,
51
56
  text: sequence.text,
57
+ textTokens: sequence.textTokens,
52
58
  cachedTokens: sequence.cachedTokens,
53
59
  responseId: sequence.responseId,
54
60
  toolCalls: sequence.toolCalls.map((_a) => {
@@ -98,8 +104,25 @@ function hasToolCallSignal(message) {
98
104
  (Array.isArray((_a = message.additional_kwargs) === null || _a === void 0 ? void 0 : _a.tool_calls) &&
99
105
  message.additional_kwargs.tool_calls.length > 0));
100
106
  }
107
+ function hasTokenCounter(model) {
108
+ return (typeof model === "object" &&
109
+ model !== null &&
110
+ "getNumTokens" in model &&
111
+ typeof model.getNumTokens === "function");
112
+ }
113
+ function countTokens(model, content) {
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ if (!content) {
116
+ return 0;
117
+ }
118
+ if (!hasTokenCounter(model)) {
119
+ return 0;
120
+ }
121
+ return yield model.getNumTokens(content);
122
+ });
123
+ }
101
124
  function extractSequenceResponseDebug(message) {
102
- var _a, _b, _c, _d, _e;
125
+ var _a, _b, _c, _d, _e, _f, _g;
103
126
  const blocks = getMessageBlocks(message);
104
127
  const reasoning = blocks
105
128
  .filter((block) => (block === null || block === void 0 ? void 0 : block.type) === "reasoning")
@@ -110,10 +133,13 @@ function extractSequenceResponseDebug(message) {
110
133
  .map((block) => { var _a; return String((_a = block.text) !== null && _a !== void 0 ? _a : ""); })
111
134
  .join("");
112
135
  return {
136
+ promptTokens: (_b = (_a = message.usage_metadata) === null || _a === void 0 ? void 0 : _a.input_tokens) !== null && _b !== void 0 ? _b : 0,
113
137
  reasoning,
138
+ reasoningTokens: 0,
114
139
  text: textFromBlocks || (typeof message.content === "string" ? message.content : ""),
115
- cachedTokens: (_c = (_b = (_a = message.usage_metadata) === null || _a === void 0 ? void 0 : _a.input_token_details) === null || _b === void 0 ? void 0 : _b.cache_read) !== null && _c !== void 0 ? _c : 0,
116
- responseId: (_e = (_d = message.response_metadata) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : null,
140
+ textTokens: 0,
141
+ cachedTokens: (_e = (_d = (_c = message.usage_metadata) === null || _c === void 0 ? void 0 : _c.input_token_details) === null || _d === void 0 ? void 0 : _d.cache_read) !== null && _e !== void 0 ? _e : 0,
142
+ responseId: (_g = (_f = message.response_metadata) === null || _f === void 0 ? void 0 : _f.id) !== null && _g !== void 0 ? _g : null,
117
143
  resultType: hasToolCallSignal(message) ? "tool_calls" : "final_text",
118
144
  };
119
145
  }
@@ -147,8 +173,11 @@ export function createSequenceDebugCollector() {
147
173
  },
148
174
  handleModelCallComplete(params) {
149
175
  const sequenceDebug = ensureSequenceDebug();
176
+ sequenceDebug.promptTokens = params.promptTokens;
150
177
  sequenceDebug.reasoning = params.reasoning;
178
+ sequenceDebug.reasoningTokens = params.reasoningTokens;
151
179
  sequenceDebug.text = params.text;
180
+ sequenceDebug.textTokens = params.textTokens;
152
181
  sequenceDebug.cachedTokens = params.cachedTokens;
153
182
  sequenceDebug.responseId = params.responseId;
154
183
  sequenceDebug.resultType = params.resultType;
@@ -204,14 +233,23 @@ export function createSequenceDebugMiddleware(sink) {
204
233
  name: "SequenceDebugMiddleware",
205
234
  wrapModelCall(request, handler) {
206
235
  return __awaiter(this, void 0, void 0, function* () {
207
- sink.handleModelCallStart(stringifyPromptForDebug({
236
+ const prompt = stringifyPromptForDebug({
208
237
  systemMessage: request.systemMessage,
209
238
  messages: request.messages,
210
239
  tools: request.tools,
211
240
  modelSettings: request.modelSettings,
212
- }));
241
+ });
242
+ sink.handleModelCallStart(prompt);
213
243
  const response = yield handler(request);
214
- sink.handleModelCallComplete(extractSequenceResponseDebug(response));
244
+ const debug = extractSequenceResponseDebug(response);
245
+ const [promptTokens, reasoningTokens, textTokens] = yield Promise.all([
246
+ debug.promptTokens || countTokens(request.model, prompt),
247
+ countTokens(request.model, debug.reasoning),
248
+ countTokens(request.model, debug.text),
249
+ ]);
250
+ sink.handleModelCallComplete(Object.assign(Object.assign({}, debug), { promptTokens,
251
+ reasoningTokens,
252
+ textTokens }));
215
253
  return response;
216
254
  });
217
255
  },
@@ -12,6 +12,11 @@ import path from "path";
12
12
  import { fileURLToPath } from "url";
13
13
  import { parse as parseYaml } from "yaml";
14
14
  const PLUGIN_SKILLS_DIRECTORY_PATH = fileURLToPath(new URL("../../custom/skills/", import.meta.url));
15
+ const USER_PLUGIN_SKILLS_DIRECTORY_PATH_SEGMENTS = [
16
+ "plugins",
17
+ "adminforth-agent",
18
+ "skills",
19
+ ];
15
20
  const SKILL_MARKDOWN_FILENAME = "SKILL.md";
16
21
  const SKILL_FRONTMATTER_SEPARATOR = "\n---\n";
17
22
  function parseSkillManifest(directoryName, markdown) {
@@ -58,6 +63,15 @@ function mergeSkillManifests(skillGroups) {
58
63
  export function getProjectSkillsDirectoryPath(customComponentsDir) {
59
64
  return path.resolve(customComponentsDir, "skills");
60
65
  }
66
+ export function getProjectPluginSkillsDirectoryPath(customComponentsDir) {
67
+ return path.resolve(customComponentsDir, ...USER_PLUGIN_SKILLS_DIRECTORY_PATH_SEGMENTS);
68
+ }
69
+ function getProjectSkillDirectoryPaths(customComponentsDir) {
70
+ return [
71
+ getProjectSkillsDirectoryPath(customComponentsDir),
72
+ getProjectPluginSkillsDirectoryPath(customComponentsDir),
73
+ ];
74
+ }
61
75
  export function listBundledSkillManifests() {
62
76
  return __awaiter(this, void 0, void 0, function* () {
63
77
  return yield listDirectorySkillManifests(PLUGIN_SKILLS_DIRECTORY_PATH);
@@ -65,7 +79,7 @@ export function listBundledSkillManifests() {
65
79
  }
66
80
  export function listProjectSkillManifests(customComponentsDir) {
67
81
  return __awaiter(this, void 0, void 0, function* () {
68
- return yield listDirectorySkillManifests(getProjectSkillsDirectoryPath(customComponentsDir));
82
+ return mergeSkillManifests(yield Promise.all(getProjectSkillDirectoryPaths(customComponentsDir).map(listDirectorySkillManifests)));
69
83
  });
70
84
  }
71
85
  export function listSkillManifests(customComponentsDir) {
@@ -90,7 +104,7 @@ export function loadSkillMarkdown(skillName, customComponentsDir) {
90
104
  return null;
91
105
  }
92
106
  const directories = [
93
- getProjectSkillsDirectoryPath(customComponentsDir),
107
+ ...getProjectSkillDirectoryPaths(customComponentsDir),
94
108
  PLUGIN_SKILLS_DIRECTORY_PATH,
95
109
  ];
96
110
  for (const skillsDirectoryPath of directories) {
@@ -23,11 +23,17 @@ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
23
23
  "Keep responses short, clear, and practical.",
24
24
  "Answer only what is needed.",
25
25
  "Do not add extra explanations or suggestions unless the user asks.",
26
+ "Always respond in the same natural language as the user's latest message.",
27
+ "This rule applies to confirmations, clarifying questions, progress updates, errors, and final answers.",
28
+ "Do not switch to English just because tool outputs, schemas, skills, or internal instructions are written in English.",
29
+ "Only switch language if the user explicitly asks you to do so.",
26
30
  "Adapt to the user's tone and style of speaking, mirroring their vibe and wording.",
27
31
  "if the user speaks casually, you should respond casually too",
28
- "Never mutate data without a fresh user confirmation for that exact mutation.",
29
- "A previous confirmation does not carry over to later create, update, delete, or action calls.",
30
- "Each separate mutation or explicitly described batch needs its own confirmation immediately before the tool call.",
32
+ "Never mutate data without user confirmation for a clearly described mutation plan.",
33
+ "One confirmation may cover one mutation or one explicitly described batch/sequence of related mutations.",
34
+ "If the confirmed plan has multiple steps, you may execute the whole confirmed plan without asking again between those steps.",
35
+ "If the plan changes, expands, or you want to do anything beyond the confirmed plan, ask for confirmation again.",
36
+ "Do not reuse an old confirmation for a new mutation plan.",
31
37
  ].join(" ");
32
38
  function formatResources(resources) {
33
39
  return resources
@@ -29,17 +29,22 @@ When creating new record, show user all data which you gona create and in same m
29
29
 
30
30
  Accept any positive confirmation from user like "yes", "sure", "+", anything non-negative call to action, can be considered as confirmation.
31
31
 
32
- A confirmation is valid only for the exact mutation plan from the immediately previous assistant message.
32
+ A confirmation is valid only for the clearly described mutation plan from the immediately previous assistant message.
33
33
 
34
34
  Never reuse an older confirmation for a later mutation.
35
35
 
36
- After one mutation is executed, confirmation is consumed and reset.
36
+ One confirmation may cover:
37
+ - one single mutation
38
+ - one explicitly described batch
39
+ - one short sequence of related mutations that together implement the same user request
37
40
 
38
- If you want to perform another create/update/delete/action after that, ask for confirmation again even if the user previously said "yes".
41
+ If the confirmed plan contains several related mutation steps, execute that whole confirmed plan without asking again between those steps.
39
42
 
40
- If the mutation plan changes in any way (different record, different fields, different values, different number of records, different action), the old confirmation is invalid and you must ask again.
43
+ Ask for confirmation again if the plan changes in any way: different record, different fields, different values, different number of records, different action, or any extra mutation that was not listed in the confirmation message.
41
44
 
42
- If you are creating or deleting multiple records in one batch, you may ask once only for that exact batch, but you must list the whole batch explicitly in the confirmation message. Any extra record outside that described batch requires a new confirmation.
45
+ If you are creating or deleting multiple records in one batch, you may ask once for that exact batch, but list the whole batch explicitly in the confirmation message. Any extra record outside that described batch requires a new confirmation.
46
+
47
+ After the confirmed plan is finished, do not treat that confirmation as still active for later requests.
43
48
 
44
49
  # Calling actions
45
50
 
package/dist/index.js CHANGED
@@ -159,6 +159,9 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
159
159
  res.write(`data: ${JSON.stringify(obj)}\n\n`);
160
160
  };
161
161
  const emitToolCallEvent = (event) => {
162
+ if (event.phase === "start") {
163
+ endActiveBlock();
164
+ }
162
165
  sequenceDebugCollector.handleToolCallEvent(event);
163
166
  send({
164
167
  type: "data-tool-call",
package/index.ts CHANGED
@@ -177,6 +177,10 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
177
177
  };
178
178
 
179
179
  const emitToolCallEvent = (event: ToolCallEvent) => {
180
+ if (event.phase === "start") {
181
+ endActiveBlock();
182
+ }
183
+
180
184
  sequenceDebugCollector.handleToolCallEvent(event);
181
185
 
182
186
  send({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/agent",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",