@noetic-tools/context 1.2.2 → 1.3.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.
@@ -104,6 +104,7 @@ interface BeforeToolCallLayersParams {
104
104
  layers: ContextLayer[];
105
105
  toolName: string;
106
106
  toolArgs: unknown;
107
+ callId?: string;
107
108
  ctx: ExecutionContext;
108
109
  store: LayerStateStore;
109
110
  }
@@ -209,7 +210,7 @@ export declare function spawnLayers({ layers, parentCtx, childCtx, store, itemSc
209
210
  }[]>;
210
211
  export declare function returnLayers<T>({ layers, parentCtx, childCtx, childLog, result, store, }: ReturnLayersParams<T>): Promise<T>;
211
212
  export declare function completeLayers({ layers, ctx, log, outcome, store, }: CompleteLayersParams): Promise<void>;
212
- export declare function beforeToolCallLayers({ layers, toolName, toolArgs, ctx, store, }: BeforeToolCallLayersParams): Promise<SteeringDecision>;
213
+ export declare function beforeToolCallLayers({ layers, toolName, toolArgs, callId, ctx, store, }: BeforeToolCallLayersParams): Promise<SteeringDecision>;
213
214
  export declare function afterModelCallLayers({ layers, response, ctx, store, }: AfterModelCallLayersParams): Promise<SteeringDecision>;
214
215
  /**
215
216
  * Run history items through every layer's `projectHistory` hook in slot order.
@@ -566,7 +566,7 @@ export async function completeLayers({ layers, ctx, log, outcome, store, }) {
566
566
  }
567
567
  await store.flush?.(ctx.executionId);
568
568
  }
569
- export async function beforeToolCallLayers({ layers, toolName, toolArgs, ctx, store, }) {
569
+ export async function beforeToolCallLayers({ layers, toolName, toolArgs, callId, ctx, store, }) {
570
570
  const sorted = [
571
571
  ...layers,
572
572
  ].sort((a, b) => a.slot - b.slot);
@@ -589,6 +589,7 @@ export async function beforeToolCallLayers({ layers, toolName, toolArgs, ctx, st
589
589
  const result = await withTimeout(layer.hooks.beforeToolCall({
590
590
  toolName,
591
591
  toolArgs,
592
+ callId,
592
593
  ctx,
593
594
  state,
594
595
  }), timeout);
@@ -605,6 +606,15 @@ export async function beforeToolCallLayers({ layers, toolName, toolArgs, ctx, st
605
606
  throw e;
606
607
  }
607
608
  store.diagnostic(layer.id, 'beforeToolCall', e);
609
+ // A permission GATE must fail closed: a hook that threw or timed out is
610
+ // a check that did not run, and for a gating layer that means deny, not
611
+ // the silent approval an abstention would collapse into.
612
+ if (layer.onBeforeToolCallError === 'deny') {
613
+ return {
614
+ action: SteeringAction.Deny,
615
+ guidance: `tool call denied: gating layer '${layer.id}' failed (${e instanceof Error ? e.message : String(e)})`,
616
+ };
617
+ }
608
618
  }
609
619
  }
610
620
  return mostRestrictive(decisions);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noetic-tools/context",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "description": "Context layer system for Noetic agents: the ContextLayer contract, lifecycle, budget/projection machinery, and built-in layer implementations.",
6
6
  "license": "Apache-2.0",
@@ -44,7 +44,7 @@
44
44
  "zod": "^4.0.0"
45
45
  },
46
46
  "dependencies": {
47
- "@noetic-tools/types": "^3.2.2",
47
+ "@noetic-tools/types": "^3.3.0",
48
48
  "zod": "^4.0.0"
49
49
  },
50
50
  "scripts": {