@happyvertical/smrt-chat 0.38.19 → 0.38.21

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,182 @@
1
+ import { AIInterface, AIMessage, AITool, ChatOptions } from '@happyvertical/ai';
2
+ import { PrincipalAuditSink, PrincipalBinding, PrincipalRun } from '@happyvertical/smrt-agents';
3
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
4
+ import { PermissionDefinition } from '@happyvertical/smrt-users';
5
+ /** Default ceiling on tool-executing rounds before the loop force-terminates. */
6
+ export declare const DEFAULT_MAX_STEPS = 8;
7
+ /**
8
+ * A single manifest operation the loop can offer and execute. Its {@link slug}
9
+ * is simultaneously the tool's stable name AND its permission-catalog slug — one
10
+ * source of truth for both what the model may call and what the principal must
11
+ * be permitted to do.
12
+ */
13
+ export interface ManifestTool {
14
+ /** Catalog slug (`collection.action`) — the tool name and the permission slug. */
15
+ slug: string;
16
+ /** Collection (permission resource), e.g. `articles`. */
17
+ collection: string;
18
+ /** Registry class name used to resolve the backing collection, e.g. `Article`. */
19
+ className: string;
20
+ /** Catalog action: `read` / `create` / `update` / `delete`, or a public custom method name. */
21
+ action: string;
22
+ /** Qualified class name, when known. */
23
+ qualifiedName?: string;
24
+ /** Human-readable description surfaced to the model. */
25
+ description?: string;
26
+ }
27
+ /**
28
+ * The record of one tool invocation attempt in a loop turn.
29
+ */
30
+ export interface ToolInvocation {
31
+ /** The tool name the model asked for. */
32
+ slug: string;
33
+ /** Parsed arguments (best-effort JSON parse of the model's raw arguments). */
34
+ args: Record<string, unknown>;
35
+ /** Whether the operation executed successfully. */
36
+ ok: boolean;
37
+ /** The JSON-serializable observation fed back to the model. */
38
+ observation: unknown;
39
+ /** True when the call was denied (not on the allow-list / not permitted). */
40
+ rejected: boolean;
41
+ /** Error summary when `ok` is false. */
42
+ error?: string;
43
+ }
44
+ /** Why {@link runToolLoop} returned. */
45
+ export type ToolLoopStopReason = 'stop' | 'max_steps' | 'no_tools';
46
+ /** The outcome of a {@link runToolLoop} turn. */
47
+ export interface ToolLoopResult {
48
+ /** The model's final assistant text. */
49
+ content: string;
50
+ /** Number of tool-executing rounds completed. */
51
+ steps: number;
52
+ /** Why the loop stopped. */
53
+ stoppedReason: ToolLoopStopReason;
54
+ /** Every tool invocation attempted this turn, in order. */
55
+ invocations: ToolInvocation[];
56
+ /** The full working transcript (input messages + assistant/tool turns). */
57
+ messages: AIMessage[];
58
+ /** Total tokens reported by the AI boundary, when available. */
59
+ totalTokens: number;
60
+ }
61
+ /** Context handed to a custom {@link ToolLoopOptions.executeTool} implementation. */
62
+ export interface ToolExecutionContext {
63
+ /** The principal run whose context bounds this execution. */
64
+ run: PrincipalRun;
65
+ /** The manifest operation to execute. */
66
+ tool: ManifestTool;
67
+ /** Parsed tool arguments. */
68
+ args: Record<string, unknown>;
69
+ /** The database handle to operate against (already the RLS-bound tx when on). */
70
+ db?: SmrtClassOptions['db'];
71
+ }
72
+ /**
73
+ * Options for {@link runToolLoop}.
74
+ */
75
+ export interface ToolLoopOptions {
76
+ /** The AI boundary (the only thing mocked in tests). */
77
+ ai: AIInterface;
78
+ /** The initial conversation messages (system / history / user). */
79
+ messages: AIMessage[];
80
+ /** The manifest operations available this turn (already allow-list-filtered). */
81
+ tools: ManifestTool[];
82
+ /** The persona principal every tool call runs as. */
83
+ principal: PrincipalBinding;
84
+ /** Database handle the side-door operations run against. */
85
+ db?: SmrtClassOptions['db'];
86
+ /** Max tool-executing rounds before force-termination. Default {@link DEFAULT_MAX_STEPS}. */
87
+ maxSteps?: number;
88
+ /** Model id passed to the AI boundary. */
89
+ model?: string;
90
+ /** Sampling temperature. */
91
+ temperature?: number;
92
+ /** Max tokens per completion. */
93
+ maxTokens?: number;
94
+ /** Tool-choice behaviour while tools are offered. Default `'auto'`. */
95
+ toolChoice?: ChatOptions['toolChoice'];
96
+ /**
97
+ * Override the side-door executor. The default
98
+ * ({@link invokeManifestTool}) enforces the allow-list + catalog gate and
99
+ * dispatches through the ObjectRegistry. Tests inject a stub to exercise loop
100
+ * mechanics without a backing object.
101
+ */
102
+ executeTool?: (ctx: ToolExecutionContext) => Promise<unknown>;
103
+ /** Notified after each tool invocation (for streaming/telemetry). */
104
+ onInvocation?: (invocation: ToolInvocation) => void | Promise<void>;
105
+ /** The originating user the turn runs on behalf of (audited). */
106
+ onBehalfOfUserId?: string | null;
107
+ /** Canonical agent class, recorded in the audit entry. */
108
+ agentClass?: string;
109
+ /** Audit sink forwarded to {@link executeAsPrincipal}. */
110
+ audit?: PrincipalAuditSink;
111
+ /** Opt into Postgres RLS transaction wrapping. */
112
+ postgresRls?: boolean;
113
+ }
114
+ /**
115
+ * Build the closed catalog of manifest operations available as tools.
116
+ *
117
+ * Reads the manifest-derived {@link PermissionCatalog} and keeps only the
118
+ * entries that name a dispatchable operation (a `(collection, action)` with a
119
+ * resolvable backing class). Pass `allowedTools` to narrow the catalog to a
120
+ * persona's least-privilege allow-list — this is the **offer gate**: a slug not
121
+ * in `allowedTools` is never returned, so it is neither offered to the model nor
122
+ * executed. A missing, `null`, or empty `allowedTools` yields **no tools**
123
+ * (fail-closed) — the same whitelist semantics as `AgentSession`/
124
+ * `PrincipalBinding` (S5 #1392), so forgetting the allow-list can only tighten,
125
+ * never widen, the offered surface. Pass `all: true` to deliberately enumerate
126
+ * the full manifest operation surface (e.g. an admin tool picker) — that is the
127
+ * one explicit escape hatch, never the default.
128
+ */
129
+ export declare function buildManifestToolCatalog(options?: SmrtClassOptions & {
130
+ /** Least-privilege allow-list to narrow the catalog by (fail-closed). */
131
+ allowedTools?: string[] | null;
132
+ /** Explicitly enumerate the ENTIRE manifest operation surface (no narrowing). */
133
+ all?: boolean;
134
+ /** Supply a pre-built catalog (skips the manifest walk). */
135
+ catalog?: PermissionDefinition[];
136
+ }): ManifestTool[];
137
+ /**
138
+ * A provider-safe function name for a catalog slug.
139
+ *
140
+ * Catalog slugs are `collection.action` and routinely contain a `.`, but many
141
+ * providers (OpenAI) restrict function names to `[A-Za-z0-9_-]{1,64}`. This maps
142
+ * the slug into that charset (dots → `-`) for the wire; {@link runToolLoop} maps
143
+ * the returned name back to the tool, and `tool.slug` remains the internal
144
+ * permission id. Distinct slugs stay distinct (the only substituted char is the
145
+ * single `.` separator).
146
+ */
147
+ export declare function toolFunctionName(slug: string): string;
148
+ /**
149
+ * Project a manifest operation into an AI function-tool definition. The function
150
+ * name is the provider-safe rendering of the catalog slug
151
+ * ({@link toolFunctionName}), so the model can only ever name a real operation.
152
+ */
153
+ export declare function manifestToolToAITool(tool: ManifestTool): AITool;
154
+ /**
155
+ * Execute a manifest operation in-process ("side door") under the principal.
156
+ *
157
+ * Enforces both authority dimensions before touching data: the fail-closed tool
158
+ * allow-list ({@link PrincipalRun.assertToolAllowed}) and the catalog permission
159
+ * for the `(collection, action)` ({@link PrincipalRun.assertOperation}) — the
160
+ * door-agnostic teeth that hold on RLS-off adapters and are a redundant second
161
+ * gate under Postgres RLS. Data operations run against the principal context's
162
+ * database (the RLS-bound transaction when RLS is on), so tenant + per-operation
163
+ * enforcement apply exactly as they would through REST or MCP.
164
+ */
165
+ export declare function invokeManifestTool(run: PrincipalRun, tool: ManifestTool, args: Record<string, unknown>, options?: {
166
+ db?: SmrtClassOptions['db'];
167
+ }): Promise<unknown>;
168
+ /**
169
+ * Run a bounded `tool_call → observe → respond` loop over the manifest operation
170
+ * surface, as the persona's bound principal.
171
+ *
172
+ * The whole turn runs inside a single {@link executeAsPrincipal} context, so
173
+ * every tool call shares one published permission snapshot (matching what a
174
+ * Postgres RLS session enforces) and the turn audits once as on-behalf-of the
175
+ * originating user.
176
+ *
177
+ * @param options - The AI boundary, seed messages, allow-list-filtered tools,
178
+ * principal, and ceiling.
179
+ * @returns The final assistant text plus the invocation log and transcript.
180
+ */
181
+ export declare function runToolLoop(options: ToolLoopOptions): Promise<ToolLoopResult>;
182
+ //# sourceMappingURL=tool-loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-loop.d.ts","sourceRoot":"","sources":["../src/tool-loop.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-chat",
3
- "version": "0.38.19",
3
+ "version": "0.38.21",
4
4
  "description": "Chat rooms, DMs, threads, and agent conversations for the SMRT framework",
5
5
  "type": "module",
6
6
  "smrtRawPrimitives": "strict",
@@ -56,10 +56,15 @@
56
56
  "access": "public"
57
57
  },
58
58
  "dependencies": {
59
- "@happyvertical/smrt-core": "0.38.19",
60
- "@happyvertical/smrt-types": "0.38.19",
61
- "@happyvertical/smrt-tenancy": "0.38.19",
62
- "@happyvertical/smrt-ui": "0.38.19"
59
+ "@happyvertical/ai": "^0.77.0",
60
+ "@happyvertical/sql": "^0.77.0",
61
+ "@happyvertical/smrt-agents": "0.38.21",
62
+ "@happyvertical/smrt-core": "0.38.21",
63
+ "@happyvertical/smrt-personas": "0.38.21",
64
+ "@happyvertical/smrt-tenancy": "0.38.21",
65
+ "@happyvertical/smrt-types": "0.38.21",
66
+ "@happyvertical/smrt-ui": "0.38.21",
67
+ "@happyvertical/smrt-users": "0.38.21"
63
68
  },
64
69
  "peerDependencies": {
65
70
  "svelte": "^5.56.4"
@@ -79,9 +84,8 @@
79
84
  "typescript": "^5.9.3",
80
85
  "vite": "^8.1.3",
81
86
  "vitest": "^4.1.9",
82
- "@happyvertical/smrt-agents": "0.38.19",
83
- "@happyvertical/smrt-profiles": "0.38.19",
84
- "@happyvertical/smrt-vitest": "0.38.19"
87
+ "@happyvertical/smrt-profiles": "0.38.21",
88
+ "@happyvertical/smrt-vitest": "0.38.21"
85
89
  },
86
90
  "scripts": {
87
91
  "build": "vite build --mode library && svelte-package -i src/svelte -o dist/svelte --tsconfig tsconfig.svelte.json",