@noetic-tools/types 3.2.2 → 3.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.
@@ -42,8 +42,10 @@ interface ContextCallModelRequestWithTools extends ContextCallModelRequestBase {
42
42
  }
43
43
  interface ContextCallModelRequestWithoutTools extends ContextCallModelRequestBase {
44
44
  tools?: undefined;
45
- ctx?: undefined;
46
- layers?: undefined;
45
+ /** Accepted without tools — it carries the broadcaster for streaming (see `CallModelRequestWithoutTools`). */
46
+ ctx?: Context;
47
+ layers?: ContextLayer[];
48
+ allowedToolNames?: undefined;
47
49
  }
48
50
  export type ContextCallModelRequest = ContextCallModelRequestWithTools | ContextCallModelRequestWithoutTools;
49
51
  export interface ContextDetachedSpawnOverrides {
@@ -118,7 +120,7 @@ export interface ContextHarness {
118
120
  setRootCwd(nextCwd: string): void;
119
121
  getLayerState<T>(executionId: string, layerId: string): T | undefined;
120
122
  setLayerState<T>(executionId: string, layerId: string, state: T): void;
121
- beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context): Promise<SteeringDecision>;
123
+ beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context, callId?: string): Promise<SteeringDecision>;
122
124
  afterModelCall(layers: ContextLayer[], response: LLMResponse, ctx: Context): Promise<SteeringDecision>;
123
125
  runAppendPipeline(layers: ContextLayer[], items: Item[], ctx: Context): Promise<ContextAppendPipelineResult>;
124
126
  /** Pinned anchor output and epoch bookkeeping for prompt-cache anchoring. Absent on a harness that predates it. */
@@ -372,6 +372,16 @@ export interface ContextLayer<TState = unknown> {
372
372
  * (its `recall`/`store`/etc. are skipped). Opt in only for non-critical layers.
373
373
  */
374
374
  onInitError?: 'throw' | 'disable';
375
+ /**
376
+ * What a failed `beforeToolCall` hook (throw or timeout) means for the
377
+ * pending tool call.
378
+ * - `'abstain'` (default): log a diagnostic and let the remaining layers /
379
+ * the default decide — correct for observational layers, where a bug must
380
+ * not block every tool.
381
+ * - `'deny'`: the call is denied — correct for permission GATES, where a
382
+ * failed check must fail closed rather than silently approving.
383
+ */
384
+ onBeforeToolCallError?: 'abstain' | 'deny';
375
385
  /**
376
386
  * Recall mode controlling whether this layer's `recall()` blocks the model call.
377
387
  * - `'atomic'` (default): recall runs synchronously in the hot path; the
@@ -101,12 +101,17 @@ interface CallModelRequestWithTools extends CallModelRequestBase {
101
101
  /** When set, restricts which tools the model may invoke for this call. */
102
102
  allowedToolNames?: string[];
103
103
  }
104
- /** @public Request shape when no tools are provided — ctx is only needed for tool
105
- * execution callbacks in convertTools, so it is omitted here. */
104
+ /**
105
+ * @public Request shape when no tools are provided. `ctx` is still accepted —
106
+ * it carries the session broadcaster, without which a tool-less call streams
107
+ * nothing to `getFullStream`/`getTextStream` — it just isn't *required* the
108
+ * way the tools variant needs it for execution callbacks.
109
+ */
106
110
  interface CallModelRequestWithoutTools extends CallModelRequestBase {
107
111
  tools?: undefined;
108
- ctx?: undefined;
109
- layers?: undefined;
112
+ ctx?: Context;
113
+ layers?: ContextLayer[];
114
+ allowedToolNames?: undefined;
110
115
  }
111
116
  /** @public Request object for `AgentHarnessContract.callModel()`. Encapsulates all parameters needed for an LLM call using only Noetic types. */
112
117
  export type CallModelRequest = CallModelRequestWithTools | CallModelRequestWithoutTools;
@@ -117,6 +122,13 @@ export interface ExecuteOptions {
117
122
  state?: unknown;
118
123
  /** Context layers to apply to the execution context. Overrides harness-level layers if provided. */
119
124
  contextLayers?: ContextLayer[];
125
+ /**
126
+ * Additional context layers appended AFTER the effective layer set
127
+ * (harness-level layers, or `contextLayers` when that override is given).
128
+ * Use this to inject a per-turn layer — a permission gate, an observer —
129
+ * without discarding the layers the harness was built with.
130
+ */
131
+ extraContextLayers?: ContextLayer[];
120
132
  /** Override the harness's default delivery mode for this message only. */
121
133
  deliveryMode?: DeliveryMode;
122
134
  /**
@@ -244,6 +256,8 @@ export interface AgentHarnessContract<TParams extends Record<string, unknown> =
244
256
  threadId?: string;
245
257
  resourceId?: string;
246
258
  contextLayers?: ContextLayer[];
259
+ /** Additional layers appended AFTER the effective layer set (see `ExecuteOptions.extraContextLayers`). */
260
+ extraContextLayers?: ContextLayer[];
247
261
  /** Override the new context's initial cwd. */
248
262
  cwdInit?: string;
249
263
  }): Context;
@@ -318,7 +332,7 @@ export interface AgentHarnessContract<TParams extends Record<string, unknown> =
318
332
  createSpan(name: string, parent: Span | null): Span;
319
333
  getLayerState<T>(executionId: string, layerId: string): T | undefined;
320
334
  setLayerState<T>(executionId: string, layerId: string, state: T): void;
321
- beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context): Promise<SteeringDecision>;
335
+ beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context, callId?: string): Promise<SteeringDecision>;
322
336
  afterModelCall(layers: ContextLayer[], response: LLMResponse, ctx: Context): Promise<SteeringDecision>;
323
337
  /**
324
338
  * Project the history items through every layer's `projectHistory` hook in
@@ -42,6 +42,15 @@ export interface LedgerEntry {
42
42
  export interface BeforeToolCallParams<TState = unknown> {
43
43
  toolName: string;
44
44
  toolArgs: unknown;
45
+ /**
46
+ * Correlation id of the pending call — the same id carried by the
47
+ * `tool_call_started` framework event (the model's `callId` on model-driven
48
+ * calls, the step id on a direct `invokeTool`). Lets a gating layer tie its
49
+ * decision to the call it is reported as, e.g. when forwarding the request
50
+ * to an external approver. Optional because a custom caller of the gate may
51
+ * have no call identity; every built-in tool-executing path supplies it.
52
+ */
53
+ callId?: string;
45
54
  ctx: ExecutionContext;
46
55
  state: TState;
47
56
  }
@@ -1,4 +1,5 @@
1
1
  import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ import type { AcpToolKind } from './acp.js';
2
3
  import type { FunctionCallItem, FunctionCallOutputItem, Item, ItemSchemaExtensions, ToolResultExtensionItem } from './items.js';
3
4
  import type { InferSchemaOutput } from './schema.js';
4
5
  type ToolExecutionResult<O extends StandardSchemaV1> = Promise<InferSchemaOutput<O>> | AsyncGenerator<unknown, InferSchemaOutput<O>>;
@@ -50,6 +51,33 @@ export interface ToolUiDeclaration<I extends StandardSchemaV1 = StandardSchemaV1
50
51
  /** Replaces the tool's region when execution throws. */
51
52
  error?(err: unknown, args: InferSchemaOutput<I>): UiFragment | null;
52
53
  }
54
+ /**
55
+ * How a tool call presents in an ACP client's UI when the harness is served
56
+ * as an ACP agent (`toAcpAgent`/`serveAcp` in `@noetic-tools/acp`).
57
+ *
58
+ * Presentation only — it never gates anything. An undeclared tool falls back
59
+ * to kind `other` with its name as the title. Declared as methods (bivariant
60
+ * params) for the same reason as `ToolUiDeclaration`.
61
+ * @public
62
+ */
63
+ export interface ToolAcpDeclaration<I extends StandardSchemaV1 = StandardSchemaV1> {
64
+ /** ACP tool kind (`read`, `edit`, `execute`, …) for editor rendering. */
65
+ kind?: AcpToolKind;
66
+ /** Human-readable title; a function receives the call's parsed args. */
67
+ title?: string | ToolAcpTitleFn<I>;
68
+ /** File paths the call affects, surfaced as ACP `locations`. */
69
+ locations?(args: InferSchemaOutput<I>): string[];
70
+ }
71
+ /**
72
+ * Bivariant function type for `ToolAcpDeclaration.title` — a union member
73
+ * cannot use method syntax, so the method-bearing object type is indexed to
74
+ * recover the same bivariance `ToolUiDeclaration`'s methods get, keeping a
75
+ * concretely-typed tool assignable to the erased `Tool` form.
76
+ * @public
77
+ */
78
+ export type ToolAcpTitleFn<I extends StandardSchemaV1 = StandardSchemaV1> = {
79
+ bivariant(args: InferSchemaOutput<I>): string;
80
+ }['bivariant'];
53
81
  /**
54
82
  * A tool definition that an LLM can invoke during execution.
55
83
  *
@@ -105,5 +133,7 @@ export interface Tool<I extends StandardSchemaV1 = StandardSchemaV1, O extends S
105
133
  context?: ToolContextDeclaration;
106
134
  /** Optional UI declaration — the runtime emits the rendered fragments at call/progress/result points. */
107
135
  ui?: ToolUiDeclaration<I, O>;
136
+ /** Optional ACP presentation — how the call renders in an ACP client when the harness is served as an agent. */
137
+ acp?: ToolAcpDeclaration<I>;
108
138
  }
109
139
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noetic-tools/types",
3
- "version": "3.2.2",
3
+ "version": "3.3.0",
4
4
  "type": "module",
5
5
  "description": "Foundational type contracts and primitives shared across the Noetic framework (items, LLM config, adapters, steering, errors).",
6
6
  "license": "Apache-2.0",