@opencxh/domain 1.264.3 → 1.264.5

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.
@@ -0,0 +1,80 @@
1
+ import { Agent } from '../entities/agent/types';
2
+ import { AssistantMode } from '../entities/ai-message/types';
3
+ /**
4
+ * May this tool be offered to the model this turn — and if it writes, may it run?
5
+ *
6
+ * **One function for the layers that used to be five files.** "Why could it not do that" was
7
+ * answered by `collectTools` (the profile filter), `buildToolRuntime` (the unattended filter),
8
+ * `resolveToolset` (procedure and mode narrowing), `gate.ts` (the suggest gate) and
9
+ * `mode.ts` — each with its own copy of "what counts as a write" and its own idea of the order.
10
+ * They had already drifted once: only the autonomous path could hold a write, only the
11
+ * interactive one could pin a tool.
12
+ *
13
+ * Pure and per-tool on purpose: every one of these rules is about a single tool, and a reader
14
+ * chasing a missing tool should be able to run this in their head.
15
+ *
16
+ * What stays outside: the **scope gate** at the receiving app
17
+ * (`platform-api/ai-tool/registerAiToolProvider`, which authorises `<kind>:<id>` against the
18
+ * acting identity). That belongs to the receiver, not to the caller, and it is the one layer a
19
+ * caller must not be able to answer for itself.
20
+ */
21
+ export type ToolVerdict =
22
+ /** Not offered to the model at all. */
23
+ "hidden"
24
+ /** Offered, and it runs. */
25
+ | "free"
26
+ /** Offered, but a call is captured for approval instead of executed. */
27
+ | "held";
28
+ /** What a verdict is made of. The declared half of a tool plus where it came from. */
29
+ export interface ToolFacts {
30
+ name: string;
31
+ access?: "read" | "write";
32
+ effect?: "internal" | "outward";
33
+ surface?: "interactive";
34
+ produces?: "draft";
35
+ /** Runs on the acting user's own connection (a personal MCP server). */
36
+ personal?: boolean;
37
+ }
38
+ export interface ToolVerdictContext {
39
+ /**
40
+ * Tool names the profile switched on. **`undefined` means no filter** — the catalog asks that
41
+ * way, and it is the difference between "this profile enabled nothing" (an empty set, nothing
42
+ * passes) and "do not filter".
43
+ */
44
+ allowed?: ReadonlySet<string>;
45
+ /** Whether the acting user's own connections take part. Default `"off"`. */
46
+ personalTools?: "off" | "allow";
47
+ /** A procedure's narrowing. Narrows only — a name not already allowed does not come back. */
48
+ narrow?: ReadonlySet<string>;
49
+ /**
50
+ * Is a person watching this turn?
51
+ *
52
+ * `false` hides personal tools and anything delivering to a client surface: an unattended run
53
+ * has nobody to deliver to, and a tool reporting success for something that lands nowhere is
54
+ * worse than a missing tool.
55
+ */
56
+ attended: boolean;
57
+ /** Interactive only: what the user said this turn is for. Narrows. */
58
+ mode?: AssistantMode;
59
+ /** A read lane: nothing that writes, whatever else it declares. */
60
+ readOnly?: boolean;
61
+ /** Is the approval gate on for this turn? Then writes are held instead of run. */
62
+ gate?: boolean;
63
+ /**
64
+ * The agent's mandate, when an agent runs this turn. It may call a tool a read that declares
65
+ * itself a write, and vice versa — an admin's explicit choice about this colleague.
66
+ */
67
+ policy?: Agent["toolPolicy"];
68
+ }
69
+ /**
70
+ * Does this tool mutate anything? **The mandate decides, then the tool, then the safe default.**
71
+ *
72
+ * `policy` → `access` → "write"
73
+ *
74
+ * The agent's policy sits deliberately on top: that is an admin's explicit statement about what
75
+ * this colleague may do unsupervised, and it may be stricter than what the tool says about
76
+ * itself. Without `access`, "unknown = write" applies and a read tool would ask for needless
77
+ * approval — which is why every descriptor should declare it.
78
+ */
79
+ export declare function isWriteTool(tool: ToolFacts, policy?: Agent["toolPolicy"]): boolean;
80
+ export declare function toolVerdict(tool: ToolFacts, ctx: ToolVerdictContext): ToolVerdict;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/domain",
3
- "version": "1.264.3",
3
+ "version": "1.264.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",