p-api-agent 0.0.5 → 0.0.7

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.cjs CHANGED
@@ -261,16 +261,133 @@ ${tool_schemas}`;
261
261
  return [...input];
262
262
  }
263
263
  parse_command(raw) {
264
- const json = this.safe_extract_json(raw);
265
- if (!json || typeof json.command !== "string") return null;
266
- return json;
264
+ const normalized = this.normalize_llm_output(raw);
265
+ const json = this.safe_extract_json(normalized);
266
+ if (!json) return null;
267
+ if (typeof json.command === "string") {
268
+ return json;
269
+ }
270
+ return this.adapt_common_tool_call(json);
267
271
  }
268
272
  safe_extract_json(content) {
269
273
  try {
270
274
  return LLM_Utils.extract_json(content);
271
275
  } catch {
272
- return null;
276
+ const json_candidate = this.find_first_json_block(content);
277
+ if (!json_candidate) return null;
278
+ try {
279
+ return LLM_Utils.parse_json(json_candidate);
280
+ } catch {
281
+ return null;
282
+ }
283
+ }
284
+ }
285
+ /**
286
+ * 兼容部分模型返回的函数调用包裹标记,例如:
287
+ * <|FunctionCallBegin|> ... <|FunctionCallEnd|>
288
+ */
289
+ normalize_llm_output(raw) {
290
+ return raw.replace(/<\|FunctionCallBegin\|>/gi, "").replace(/<\|FunctionCallEnd\|>/gi, "").replace(/<\|tool_call\|>/gi, "").replace(/<tool_call>/gi, "").replace(/<\/tool_call>/gi, "").trim();
291
+ }
292
+ /** 从混杂文本中提取第一个 JSON 对象字符串 */
293
+ find_first_json_block(content) {
294
+ const fenced = content.match(/```json\s*([\s\S]*?)\s*```/i);
295
+ if (fenced?.[1]) return fenced[1];
296
+ const objectStart = content.indexOf("{");
297
+ const arrayStart = content.indexOf("[");
298
+ let start = -1;
299
+ let openChar = "{";
300
+ let closeChar = "}";
301
+ if (objectStart >= 0 && (arrayStart < 0 || objectStart < arrayStart)) {
302
+ start = objectStart;
303
+ openChar = "{";
304
+ closeChar = "}";
305
+ } else if (arrayStart >= 0) {
306
+ start = arrayStart;
307
+ openChar = "[";
308
+ closeChar = "]";
309
+ }
310
+ if (start < 0) return null;
311
+ let depth = 0;
312
+ let inString = false;
313
+ let escaped = false;
314
+ for (let i = start; i < content.length; i++) {
315
+ const ch = content[i];
316
+ if (inString) {
317
+ if (escaped) {
318
+ escaped = false;
319
+ continue;
320
+ }
321
+ if (ch === "\\") {
322
+ escaped = true;
323
+ continue;
324
+ }
325
+ if (ch === '"') {
326
+ inString = false;
327
+ }
328
+ continue;
329
+ }
330
+ if (ch === '"') {
331
+ inString = true;
332
+ continue;
333
+ }
334
+ if (ch === openChar) depth++;
335
+ if (ch === closeChar) {
336
+ depth--;
337
+ if (depth === 0) {
338
+ return content.slice(start, i + 1);
339
+ }
340
+ }
341
+ }
342
+ return null;
343
+ }
344
+ /** 兼容常见 Function Calling 输出结构并转换为内部指令 */
345
+ adapt_common_tool_call(json) {
346
+ if (Array.isArray(json) && json.length > 0) {
347
+ return this.adapt_common_tool_call(json[0]);
348
+ }
349
+ if (typeof json?.name === "string") {
350
+ const params = this.normalize_params(json.params ?? json.arguments ?? {});
351
+ return {
352
+ command: "use_tool",
353
+ tool_name: json.name,
354
+ params,
355
+ reasoning: typeof json.reasoning === "string" ? json.reasoning : void 0
356
+ };
357
+ }
358
+ if (typeof json?.function?.name === "string") {
359
+ const params = this.normalize_params(json.function.arguments ?? {});
360
+ return {
361
+ command: "use_tool",
362
+ tool_name: json.function.name,
363
+ params,
364
+ reasoning: typeof json.reasoning === "string" ? json.reasoning : void 0
365
+ };
366
+ }
367
+ const first_tool_call = Array.isArray(json?.tool_calls) ? json.tool_calls[0] : null;
368
+ if (typeof first_tool_call?.function?.name === "string") {
369
+ const params = this.normalize_params(first_tool_call.function.arguments ?? {});
370
+ return {
371
+ command: "use_tool",
372
+ tool_name: first_tool_call.function.name,
373
+ params,
374
+ reasoning: typeof json.reasoning === "string" ? json.reasoning : void 0
375
+ };
376
+ }
377
+ return null;
378
+ }
379
+ normalize_params(params) {
380
+ if (params == null) return {};
381
+ if (typeof params === "string") {
382
+ try {
383
+ const parsed = LLM_Utils.parse_json(params);
384
+ return typeof parsed === "object" && parsed ? parsed : { value: parsed };
385
+ } catch {
386
+ return { value: params };
387
+ }
273
388
  }
389
+ if (typeof params === "object") return params;
390
+ return { value: params };
274
391
  }
275
392
  async call_llm_with_retry(input) {
276
393
  let last_error;
package/dist/index.d.cts CHANGED
@@ -121,6 +121,16 @@ declare class Agent {
121
121
  private normalize_input;
122
122
  private parse_command;
123
123
  private safe_extract_json;
124
+ /**
125
+ * 兼容部分模型返回的函数调用包裹标记,例如:
126
+ * <|FunctionCallBegin|> ... <|FunctionCallEnd|>
127
+ */
128
+ private normalize_llm_output;
129
+ /** 从混杂文本中提取第一个 JSON 对象字符串 */
130
+ private find_first_json_block;
131
+ /** 兼容常见 Function Calling 输出结构并转换为内部指令 */
132
+ private adapt_common_tool_call;
133
+ private normalize_params;
124
134
  private call_llm_with_retry;
125
135
  }
126
136
 
package/dist/index.d.ts CHANGED
@@ -121,6 +121,16 @@ declare class Agent {
121
121
  private normalize_input;
122
122
  private parse_command;
123
123
  private safe_extract_json;
124
+ /**
125
+ * 兼容部分模型返回的函数调用包裹标记,例如:
126
+ * <|FunctionCallBegin|> ... <|FunctionCallEnd|>
127
+ */
128
+ private normalize_llm_output;
129
+ /** 从混杂文本中提取第一个 JSON 对象字符串 */
130
+ private find_first_json_block;
131
+ /** 兼容常见 Function Calling 输出结构并转换为内部指令 */
132
+ private adapt_common_tool_call;
133
+ private normalize_params;
124
134
  private call_llm_with_retry;
125
135
  }
126
136
 
package/dist/index.js CHANGED
@@ -232,16 +232,133 @@ ${tool_schemas}`;
232
232
  return [...input];
233
233
  }
234
234
  parse_command(raw) {
235
- const json = this.safe_extract_json(raw);
236
- if (!json || typeof json.command !== "string") return null;
237
- return json;
235
+ const normalized = this.normalize_llm_output(raw);
236
+ const json = this.safe_extract_json(normalized);
237
+ if (!json) return null;
238
+ if (typeof json.command === "string") {
239
+ return json;
240
+ }
241
+ return this.adapt_common_tool_call(json);
238
242
  }
239
243
  safe_extract_json(content) {
240
244
  try {
241
245
  return LLM_Utils.extract_json(content);
242
246
  } catch {
243
- return null;
247
+ const json_candidate = this.find_first_json_block(content);
248
+ if (!json_candidate) return null;
249
+ try {
250
+ return LLM_Utils.parse_json(json_candidate);
251
+ } catch {
252
+ return null;
253
+ }
254
+ }
255
+ }
256
+ /**
257
+ * 兼容部分模型返回的函数调用包裹标记,例如:
258
+ * <|FunctionCallBegin|> ... <|FunctionCallEnd|>
259
+ */
260
+ normalize_llm_output(raw) {
261
+ return raw.replace(/<\|FunctionCallBegin\|>/gi, "").replace(/<\|FunctionCallEnd\|>/gi, "").replace(/<\|tool_call\|>/gi, "").replace(/<tool_call>/gi, "").replace(/<\/tool_call>/gi, "").trim();
262
+ }
263
+ /** 从混杂文本中提取第一个 JSON 对象字符串 */
264
+ find_first_json_block(content) {
265
+ const fenced = content.match(/```json\s*([\s\S]*?)\s*```/i);
266
+ if (fenced?.[1]) return fenced[1];
267
+ const objectStart = content.indexOf("{");
268
+ const arrayStart = content.indexOf("[");
269
+ let start = -1;
270
+ let openChar = "{";
271
+ let closeChar = "}";
272
+ if (objectStart >= 0 && (arrayStart < 0 || objectStart < arrayStart)) {
273
+ start = objectStart;
274
+ openChar = "{";
275
+ closeChar = "}";
276
+ } else if (arrayStart >= 0) {
277
+ start = arrayStart;
278
+ openChar = "[";
279
+ closeChar = "]";
280
+ }
281
+ if (start < 0) return null;
282
+ let depth = 0;
283
+ let inString = false;
284
+ let escaped = false;
285
+ for (let i = start; i < content.length; i++) {
286
+ const ch = content[i];
287
+ if (inString) {
288
+ if (escaped) {
289
+ escaped = false;
290
+ continue;
291
+ }
292
+ if (ch === "\\") {
293
+ escaped = true;
294
+ continue;
295
+ }
296
+ if (ch === '"') {
297
+ inString = false;
298
+ }
299
+ continue;
300
+ }
301
+ if (ch === '"') {
302
+ inString = true;
303
+ continue;
304
+ }
305
+ if (ch === openChar) depth++;
306
+ if (ch === closeChar) {
307
+ depth--;
308
+ if (depth === 0) {
309
+ return content.slice(start, i + 1);
310
+ }
311
+ }
312
+ }
313
+ return null;
314
+ }
315
+ /** 兼容常见 Function Calling 输出结构并转换为内部指令 */
316
+ adapt_common_tool_call(json) {
317
+ if (Array.isArray(json) && json.length > 0) {
318
+ return this.adapt_common_tool_call(json[0]);
319
+ }
320
+ if (typeof json?.name === "string") {
321
+ const params = this.normalize_params(json.params ?? json.arguments ?? {});
322
+ return {
323
+ command: "use_tool",
324
+ tool_name: json.name,
325
+ params,
326
+ reasoning: typeof json.reasoning === "string" ? json.reasoning : void 0
327
+ };
328
+ }
329
+ if (typeof json?.function?.name === "string") {
330
+ const params = this.normalize_params(json.function.arguments ?? {});
331
+ return {
332
+ command: "use_tool",
333
+ tool_name: json.function.name,
334
+ params,
335
+ reasoning: typeof json.reasoning === "string" ? json.reasoning : void 0
336
+ };
337
+ }
338
+ const first_tool_call = Array.isArray(json?.tool_calls) ? json.tool_calls[0] : null;
339
+ if (typeof first_tool_call?.function?.name === "string") {
340
+ const params = this.normalize_params(first_tool_call.function.arguments ?? {});
341
+ return {
342
+ command: "use_tool",
343
+ tool_name: first_tool_call.function.name,
344
+ params,
345
+ reasoning: typeof json.reasoning === "string" ? json.reasoning : void 0
346
+ };
347
+ }
348
+ return null;
349
+ }
350
+ normalize_params(params) {
351
+ if (params == null) return {};
352
+ if (typeof params === "string") {
353
+ try {
354
+ const parsed = LLM_Utils.parse_json(params);
355
+ return typeof parsed === "object" && parsed ? parsed : { value: parsed };
356
+ } catch {
357
+ return { value: params };
358
+ }
244
359
  }
360
+ if (typeof params === "object") return params;
361
+ return { value: params };
245
362
  }
246
363
  async call_llm_with_retry(input) {
247
364
  let last_error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "p-api-agent",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.mjs",
6
6
  "files": [