@lazyingart/agintiflow 0.20.285 → 0.20.286

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.285",
3
+ "version": "0.20.286",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
6
6
  "license": "Apache-2.0",
@@ -2482,6 +2482,93 @@ try {
2482
2482
  invalidFocusedRewrite.errors.some((error) => error.code === "ARGUMENT_PATTERN_MISMATCH"),
2483
2483
  "focused rewrite smoke input did not exercise the semantic pattern failure"
2484
2484
  );
2485
+ const commandDescriptor = {
2486
+ type: "function",
2487
+ function: {
2488
+ name: "run_command",
2489
+ description: "Run one command.",
2490
+ parameters: {
2491
+ type: "object",
2492
+ properties: { command: { type: "string", minLength: 1 } },
2493
+ required: ["command"],
2494
+ additionalProperties: false,
2495
+ },
2496
+ },
2497
+ };
2498
+ const annotatedCommandBatch = [
2499
+ {
2500
+ id: "annotated-command-one",
2501
+ type: "function",
2502
+ function: {
2503
+ name: "run_command",
2504
+ arguments: JSON.stringify({
2505
+ command: "printf one",
2506
+ description: "Inspect the first item",
2507
+ }),
2508
+ },
2509
+ },
2510
+ {
2511
+ id: "annotated-command-two",
2512
+ type: "function",
2513
+ function: {
2514
+ name: "run_command",
2515
+ arguments: JSON.stringify({
2516
+ command: "printf two",
2517
+ description: "Inspect the second item",
2518
+ }),
2519
+ },
2520
+ },
2521
+ ];
2522
+ const recoveredAnnotatedCommands = resolveDispatchableToolCallBatch(
2523
+ annotatedCommandBatch,
2524
+ createToolContract([commandDescriptor])
2525
+ );
2526
+ assert(recoveredAnnotatedCommands.ok, "benign command annotations were not normalized");
2527
+ assert(
2528
+ recoveredAnnotatedCommands.recoveredToolCallAnnotations,
2529
+ "benign command annotation recovery was not recorded"
2530
+ );
2531
+ assert(
2532
+ recoveredAnnotatedCommands.recoveredSequentially,
2533
+ "annotated command batch did not retain bounded sequential dispatch"
2534
+ );
2535
+ assert(
2536
+ recoveredAnnotatedCommands.acceptedToolCalls.length === 1 &&
2537
+ recoveredAnnotatedCommands.deferredToolCalls.length === 1,
2538
+ "annotated command batch did not dispatch one call and defer the suffix"
2539
+ );
2540
+ for (const call of [
2541
+ ...recoveredAnnotatedCommands.acceptedToolCalls,
2542
+ ...recoveredAnnotatedCommands.deferredToolCalls,
2543
+ ]) {
2544
+ assert(
2545
+ !Object.hasOwn(JSON.parse(call.function.arguments), "description"),
2546
+ "non-executable command description reached dispatch"
2547
+ );
2548
+ }
2549
+ const unknownAnnotatedCommand = resolveDispatchableToolCallBatch(
2550
+ [
2551
+ {
2552
+ id: "unknown-command-annotation",
2553
+ type: "function",
2554
+ function: {
2555
+ name: "run_command",
2556
+ arguments: JSON.stringify({
2557
+ command: "printf blocked",
2558
+ rationale: "This key is not an approved annotation",
2559
+ }),
2560
+ },
2561
+ },
2562
+ ],
2563
+ createToolContract([commandDescriptor])
2564
+ );
2565
+ assert(
2566
+ !unknownAnnotatedCommand.ok &&
2567
+ unknownAnnotatedCommand.errors.some(
2568
+ (error) => error.code === "ARGUMENT_ADDITIONAL_PROPERTY"
2569
+ ),
2570
+ "an unknown command annotation bypassed the exact tool schema"
2571
+ );
2485
2572
  const focusedWriterCalls = [];
2486
2573
  const focusedRewriteState = {
2487
2574
  meta: {
@@ -30,6 +30,7 @@ const MAX_VALIDATION_ERRORS = 8;
30
30
  const MAX_VALIDATION_NODES = 50_000;
31
31
  const MAX_SAFE_SEQUENTIAL_READ_CALLS = 4;
32
32
  const MAX_REPORTED_SEQUENTIAL_CALLS = 12;
33
+ const BENIGN_TOOL_CALL_ANNOTATION_KEYS = new Set(["description"]);
33
34
 
34
35
  function cloneValue(value) {
35
36
  return structuredClone(value);
@@ -457,6 +458,69 @@ function recoverBoundedCommitSubject(toolCalls, contract, validation) {
457
458
  };
458
459
  }
459
460
 
461
+ function normalizeBenignToolCallAnnotations(toolCalls, contract) {
462
+ const calls = Array.isArray(toolCalls) ? toolCalls : [];
463
+ if (!calls.length || contract?.[contractMarker] !== true) return null;
464
+
465
+ const normalizedCalls = [];
466
+ const corrections = [];
467
+ for (let index = 0; index < calls.length; index += 1) {
468
+ const call = calls[index];
469
+ const toolName = String(call?.function?.name || "");
470
+ const descriptor = contract.tools.find(
471
+ (candidate) =>
472
+ candidate?.type === "function" && candidate.function?.name === toolName
473
+ );
474
+ if (!descriptor || typeof call?.function?.arguments !== "string") return null;
475
+
476
+ let args;
477
+ try {
478
+ args = JSON.parse(call.function.arguments);
479
+ } catch {
480
+ return null;
481
+ }
482
+ if (!isPlainObject(args)) return null;
483
+
484
+ const parameters = descriptor.function?.parameters;
485
+ const properties = isPlainObject(parameters?.properties)
486
+ ? parameters.properties
487
+ : {};
488
+ const correctedArgs = { ...args };
489
+ const removed = [];
490
+ for (const key of BENIGN_TOOL_CALL_ANNOTATION_KEYS) {
491
+ if (
492
+ parameters?.additionalProperties === false &&
493
+ !Object.hasOwn(properties, key) &&
494
+ Object.hasOwn(correctedArgs, key) &&
495
+ typeof correctedArgs[key] === "string" &&
496
+ correctedArgs[key].length <= 1_000
497
+ ) {
498
+ delete correctedArgs[key];
499
+ removed.push(key);
500
+ corrections.push({
501
+ callIndex: index,
502
+ property: key,
503
+ source: "non-executable-tool-annotation",
504
+ });
505
+ }
506
+ }
507
+
508
+ normalizedCalls.push(
509
+ removed.length
510
+ ? {
511
+ ...call,
512
+ function: {
513
+ ...call.function,
514
+ arguments: JSON.stringify(correctedArgs),
515
+ },
516
+ }
517
+ : call
518
+ );
519
+ }
520
+
521
+ return corrections.length ? { calls: normalizedCalls, corrections } : null;
522
+ }
523
+
460
524
  export function validateToolCallBatch(toolCalls, contract, { maxToolCalls = 1 } = {}) {
461
525
  const errors = [];
462
526
  const addError = (code, callIndex, message) => {
@@ -613,6 +677,27 @@ export function resolveDispatchableToolCallBatch(toolCalls, contract) {
613
677
  };
614
678
  }
615
679
 
680
+ const annotationNormalization = normalizeBenignToolCallAnnotations(calls, contract);
681
+ if (annotationNormalization) {
682
+ const recovered = resolveDispatchableToolCallBatch(
683
+ annotationNormalization.calls,
684
+ contract
685
+ );
686
+ if (recovered.ok) {
687
+ return {
688
+ ...recovered,
689
+ recoveredToolCallAnnotations: true,
690
+ argumentCorrections: [
691
+ ...(Array.isArray(recovered.argumentCorrections)
692
+ ? recovered.argumentCorrections
693
+ : []),
694
+ ...annotationNormalization.corrections,
695
+ ],
696
+ originalCode: validation.code,
697
+ };
698
+ }
699
+ }
700
+
616
701
  const readRangeRecovery = recoverReadFileRangeAlias(calls, contract, validation);
617
702
  if (readRangeRecovery) return readRangeRecovery;
618
703