@cognipeer/agent-sdk 0.9.0 → 0.9.1

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.cts CHANGED
@@ -444,14 +444,38 @@ type ContentPart$1 = {
444
444
  type: string;
445
445
  [key: string]: any;
446
446
  };
447
+ /**
448
+ * Decides, per call, whether this invocation needs human approval.
449
+ *
450
+ * Return `true` to pause. Returning a non-boolean is treated as `false` except
451
+ * for a thrown error, which is treated as `true` — see `needsApproval`.
452
+ */
453
+ type ToolApprovalPredicate = (args: any) => boolean;
447
454
  interface ToolInterface<TInput = any, TOutput = any, TCallOptions = any> {
448
455
  name: string;
449
456
  description?: string;
450
457
  invoke?: (input: TInput, config?: TCallOptions) => Promise<TOutput> | TOutput;
451
458
  call?: (input: TInput, config?: TCallOptions) => Promise<TOutput> | TOutput;
452
459
  schema?: any;
453
- needsApproval?: boolean;
454
- approvalPrompt?: string;
460
+ /**
461
+ * Whether a call must pause for a human before it runs.
462
+ *
463
+ * A boolean decides for the tool as a whole. A PREDICATE decides per call, with
464
+ * the parsed arguments in hand — which is the only way to express "ask before
465
+ * `rm`, but not before `ls`", because the interesting half of a dangerous tool
466
+ * is usually its arguments, not its name.
467
+ *
468
+ * The predicate runs inside the tools node, immediately before the call would
469
+ * execute, and it must not throw: a predicate that throws is treated as
470
+ * `true`, because a policy that cannot decide has not granted permission.
471
+ */
472
+ needsApproval?: boolean | ToolApprovalPredicate;
473
+ /**
474
+ * The text shown to whoever is asked. A function receives the same arguments
475
+ * the predicate saw, so the prompt can quote what is actually about to happen
476
+ * ("Delete 3 files under /src?") instead of describing the tool in general.
477
+ */
478
+ approvalPrompt?: string | ((args: any) => string | undefined);
455
479
  approvalDefaults?: any;
456
480
  maxExecutionsPerRun?: number | null;
457
481
  /**
@@ -1094,7 +1118,13 @@ type TraceToolDetails = {
1094
1118
  description?: string;
1095
1119
  inputSchema?: any;
1096
1120
  approval?: {
1121
+ /** Set only when the tool answers statically. Absent when `conditional`. */
1097
1122
  required?: boolean;
1123
+ /**
1124
+ * The tool decides per call from its arguments, so no single answer can be
1125
+ * recorded here. The actual verdict for each call is on its approval entry.
1126
+ */
1127
+ conditional?: boolean;
1098
1128
  prompt?: string;
1099
1129
  defaults?: any;
1100
1130
  };
@@ -1874,8 +1904,13 @@ declare function createTool({ name, description, schema, func, needsApproval, ap
1874
1904
  description?: string;
1875
1905
  schema: ZodSchema;
1876
1906
  func: SmartToolFn;
1877
- needsApproval?: boolean;
1878
- approvalPrompt?: string;
1907
+ /**
1908
+ * `true` gates every call; a predicate gates the calls whose ARGUMENTS
1909
+ * warrant it. See ToolApprovalPredicate.
1910
+ */
1911
+ needsApproval?: boolean | ToolApprovalPredicate;
1912
+ /** A function form receives the call's arguments, so the prompt can quote them. */
1913
+ approvalPrompt?: string | ((args: any) => string | undefined);
1879
1914
  approvalDefaults?: any;
1880
1915
  maxExecutionsPerRun?: number | null;
1881
1916
  /** When set, identical args within the same invoke short-circuit to the cached result. */
package/dist/index.d.ts CHANGED
@@ -444,14 +444,38 @@ type ContentPart$1 = {
444
444
  type: string;
445
445
  [key: string]: any;
446
446
  };
447
+ /**
448
+ * Decides, per call, whether this invocation needs human approval.
449
+ *
450
+ * Return `true` to pause. Returning a non-boolean is treated as `false` except
451
+ * for a thrown error, which is treated as `true` — see `needsApproval`.
452
+ */
453
+ type ToolApprovalPredicate = (args: any) => boolean;
447
454
  interface ToolInterface<TInput = any, TOutput = any, TCallOptions = any> {
448
455
  name: string;
449
456
  description?: string;
450
457
  invoke?: (input: TInput, config?: TCallOptions) => Promise<TOutput> | TOutput;
451
458
  call?: (input: TInput, config?: TCallOptions) => Promise<TOutput> | TOutput;
452
459
  schema?: any;
453
- needsApproval?: boolean;
454
- approvalPrompt?: string;
460
+ /**
461
+ * Whether a call must pause for a human before it runs.
462
+ *
463
+ * A boolean decides for the tool as a whole. A PREDICATE decides per call, with
464
+ * the parsed arguments in hand — which is the only way to express "ask before
465
+ * `rm`, but not before `ls`", because the interesting half of a dangerous tool
466
+ * is usually its arguments, not its name.
467
+ *
468
+ * The predicate runs inside the tools node, immediately before the call would
469
+ * execute, and it must not throw: a predicate that throws is treated as
470
+ * `true`, because a policy that cannot decide has not granted permission.
471
+ */
472
+ needsApproval?: boolean | ToolApprovalPredicate;
473
+ /**
474
+ * The text shown to whoever is asked. A function receives the same arguments
475
+ * the predicate saw, so the prompt can quote what is actually about to happen
476
+ * ("Delete 3 files under /src?") instead of describing the tool in general.
477
+ */
478
+ approvalPrompt?: string | ((args: any) => string | undefined);
455
479
  approvalDefaults?: any;
456
480
  maxExecutionsPerRun?: number | null;
457
481
  /**
@@ -1094,7 +1118,13 @@ type TraceToolDetails = {
1094
1118
  description?: string;
1095
1119
  inputSchema?: any;
1096
1120
  approval?: {
1121
+ /** Set only when the tool answers statically. Absent when `conditional`. */
1097
1122
  required?: boolean;
1123
+ /**
1124
+ * The tool decides per call from its arguments, so no single answer can be
1125
+ * recorded here. The actual verdict for each call is on its approval entry.
1126
+ */
1127
+ conditional?: boolean;
1098
1128
  prompt?: string;
1099
1129
  defaults?: any;
1100
1130
  };
@@ -1874,8 +1904,13 @@ declare function createTool({ name, description, schema, func, needsApproval, ap
1874
1904
  description?: string;
1875
1905
  schema: ZodSchema;
1876
1906
  func: SmartToolFn;
1877
- needsApproval?: boolean;
1878
- approvalPrompt?: string;
1907
+ /**
1908
+ * `true` gates every call; a predicate gates the calls whose ARGUMENTS
1909
+ * warrant it. See ToolApprovalPredicate.
1910
+ */
1911
+ needsApproval?: boolean | ToolApprovalPredicate;
1912
+ /** A function form receives the call's arguments, so the prompt can quote them. */
1913
+ approvalPrompt?: string | ((args: any) => string | undefined);
1879
1914
  approvalDefaults?: any;
1880
1915
  maxExecutionsPerRun?: number | null;
1881
1916
  /** When set, identical args within the same invoke short-circuit to the cached result. */
package/dist/index.mjs CHANGED
@@ -424,7 +424,7 @@ function createTool({
424
424
  run: execute,
425
425
  func: execute
426
426
  };
427
- if (typeof needsApproval === "boolean") {
427
+ if (typeof needsApproval === "function" || typeof needsApproval === "boolean") {
428
428
  toolRecord.needsApproval = needsApproval;
429
429
  }
430
430
  if (approvalPrompt !== void 0) {
@@ -3473,6 +3473,29 @@ function selectPendingToolCalls(messages) {
3473
3473
  }
3474
3474
 
3475
3475
  // src/nodes/tools.ts
3476
+ function resolveNeedsApproval(tool, args) {
3477
+ const spec = tool?.needsApproval;
3478
+ if (typeof spec === "function") {
3479
+ try {
3480
+ return Boolean(spec(args));
3481
+ } catch {
3482
+ return true;
3483
+ }
3484
+ }
3485
+ return Boolean(spec);
3486
+ }
3487
+ function resolveApprovalPrompt(tool, args) {
3488
+ const prompt = tool?.approvalPrompt;
3489
+ if (typeof prompt === "function") {
3490
+ try {
3491
+ const resolved = prompt(args);
3492
+ return typeof resolved === "string" && resolved.length > 0 ? resolved : void 0;
3493
+ } catch {
3494
+ return void 0;
3495
+ }
3496
+ }
3497
+ return typeof prompt === "string" ? prompt : void 0;
3498
+ }
3476
3499
  function normalizeMaxExecutionsPerRun(value) {
3477
3500
  if (value === null || value === void 0 || value === "") return null;
3478
3501
  const parsed = Number(value);
@@ -3519,10 +3542,13 @@ function buildToolDetails(tool, toolName) {
3519
3542
  }
3520
3543
  const inputSchema = normalizeToolSchema(tool, toolName);
3521
3544
  if (inputSchema !== void 0) details.inputSchema = inputSchema;
3522
- const needsApproval = typeof tool.needsApproval === "boolean" ? tool.needsApproval : void 0;
3523
- if (needsApproval !== void 0 || tool.approvalPrompt !== void 0 || tool.approvalDefaults !== void 0) {
3545
+ const approvalSpec = tool.needsApproval;
3546
+ const needsApproval = typeof approvalSpec === "boolean" ? approvalSpec : void 0;
3547
+ const conditionalApproval = typeof approvalSpec === "function" ? true : void 0;
3548
+ if (needsApproval !== void 0 || conditionalApproval !== void 0 || tool.approvalPrompt !== void 0 || tool.approvalDefaults !== void 0) {
3524
3549
  details.approval = {
3525
3550
  required: needsApproval,
3551
+ conditional: conditionalApproval,
3526
3552
  prompt: typeof tool.approvalPrompt === "string" ? tool.approvalPrompt : void 0,
3527
3553
  defaults: tool.approvalDefaults !== void 0 ? sanitizeTracePayload(tool.approvalDefaults) : void 0
3528
3554
  };
@@ -3747,7 +3773,7 @@ function createToolsNode(initialTools, opts) {
3747
3773
  }
3748
3774
  }
3749
3775
  let approvalEntry = pendingByCallId.get(toolCallId);
3750
- const needsApproval = Boolean(tool.needsApproval);
3776
+ const needsApproval = resolveNeedsApproval(tool, args);
3751
3777
  if (needsApproval) {
3752
3778
  if (!approvalEntry) {
3753
3779
  approvalEntry = {
@@ -3757,7 +3783,7 @@ function createToolsNode(initialTools, opts) {
3757
3783
  args,
3758
3784
  status: "pending",
3759
3785
  requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
3760
- metadata: tool.approvalPrompt || tool.approvalDefaults ? { prompt: tool.approvalPrompt, defaults: tool.approvalDefaults } : void 0
3786
+ metadata: resolveApprovalPrompt(tool, args) !== void 0 || tool.approvalDefaults !== void 0 ? { prompt: resolveApprovalPrompt(tool, args), defaults: tool.approvalDefaults } : void 0
3761
3787
  };
3762
3788
  pendingApprovals.push(approvalEntry);
3763
3789
  pendingByCallId.set(toolCallId, approvalEntry);