slotlock 0.5.1 → 0.5.3

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/assistant.d.ts ADDED
@@ -0,0 +1,263 @@
1
+ import { type SlotlockAgentOperation } from './agent-server.js';
2
+ import type { SlotlockAssistantConversationRecord, SlotlockAssistantSettingsRecord, SlotlockStore } from './store.js';
3
+ export type SlotlockAssistantProvider = 'anthropic' | 'openai';
4
+ /** What the assistant does with each agent operation: run it, propose it, or never offer it. */
5
+ export type SlotlockAssistantToolUse = 'read' | 'propose' | 'excluded';
6
+ /**
7
+ * The tools the model is offered, by agent operation. A record over every operation, so one a later
8
+ * release adds does not compile until it is placed here. Reads run when the model calls them;
9
+ * every write is only proposed, and runs when the member approves it. API keys, webhooks, booking
10
+ * rules, pools, erasure and coverage are application operations, never agent ones, so no entry can
11
+ * offer them.
12
+ */
13
+ export declare const SLOTLOCK_ASSISTANT_TOOL_USE: Readonly<Record<SlotlockAgentOperation, SlotlockAssistantToolUse>>;
14
+ /** Model calls one message may make before the assistant stops and says so. */
15
+ export declare const SLOTLOCK_ASSISTANT_MAX_STEPS = 8;
16
+ /** Characters of one message from a member. */
17
+ export declare const SLOTLOCK_ASSISTANT_MAX_MESSAGE = 2000;
18
+ /**
19
+ * UTF-8 bytes of the stored conversation as JSON, past which the oldest exchanges go first.
20
+ * PostgreSQL's jsonb text adds at most one space per `:` or `,`, so at most half again: under the
21
+ * table's 262,144-byte CHECK on `messages::text` whatever the text.
22
+ */
23
+ export declare const SLOTLOCK_ASSISTANT_MAX_STORED_BYTES = 160000;
24
+ /** UTF-8 bytes of one proposed change's arguments as JSON; a larger one is not proposed. */
25
+ export declare const SLOTLOCK_ASSISTANT_MAX_ACTION_BYTES = 16000;
26
+ /** Proposed changes one conversation may have waiting at once (4 of the largest fit the bound). */
27
+ export declare const SLOTLOCK_ASSISTANT_MAX_PENDING = 4;
28
+ /**
29
+ * The Messages API version this sends: the one @anthropic-ai/sdk 1.3.0 (2026-10-23) sends, read
30
+ * from its source on 2026-10-28. Top-level `system`, `tools[].input_schema`, `tool_use` and
31
+ * `tool_result` blocks are as before in it.
32
+ */
33
+ export declare const SLOTLOCK_ANTHROPIC_VERSION = "2026-10-21";
34
+ /** A model as the assistant calls it, with the key opened. */
35
+ export interface SlotlockAssistantModel {
36
+ provider: SlotlockAssistantProvider;
37
+ baseUrl: string;
38
+ model: string;
39
+ apiKey: string | null;
40
+ }
41
+ export interface SlotlockAssistantCall {
42
+ id: string;
43
+ name: string;
44
+ input: unknown;
45
+ }
46
+ /** One entry of a stored conversation. `note`s are shown to the member and never sent to the model. */
47
+ export type SlotlockAssistantEntry = {
48
+ role: 'user';
49
+ text: string;
50
+ } | {
51
+ role: 'assistant';
52
+ text: string;
53
+ calls: SlotlockAssistantCall[];
54
+ } | {
55
+ role: 'tool';
56
+ results: {
57
+ id: string;
58
+ name: string;
59
+ content: string;
60
+ error: boolean;
61
+ action?: string;
62
+ }[];
63
+ } | {
64
+ role: 'event';
65
+ text: string;
66
+ } | {
67
+ role: 'note';
68
+ text: string;
69
+ };
70
+ /** A proposed write, as the conversation keeps it. */
71
+ export interface SlotlockAssistantAction {
72
+ id: string;
73
+ operation: SlotlockAgentOperation;
74
+ input: Record<string, unknown>;
75
+ status: 'pending' | 'approved' | 'dismissed' | 'done' | 'failed';
76
+ /** What it did (`done`), or the code it failed with (`failed`). */
77
+ outcome?: string;
78
+ /** The change in a sentence, with its resource and event resolved (the confirmation question). */
79
+ summary?: string;
80
+ }
81
+ /** Where the dashboard keeps assistant settings and conversations: the store, under each tenant's RLS. */
82
+ export interface SlotlockAssistantStore {
83
+ getSettings(tenantRef: string): Promise<SlotlockAssistantSettingsRecord | null>;
84
+ putSettings(tenantRef: string, settings: {
85
+ provider: SlotlockAssistantProvider;
86
+ baseUrl: string;
87
+ model: string;
88
+ key: {
89
+ sealed: string;
90
+ hint: string;
91
+ } | null | 'keep';
92
+ }, actor?: string): Promise<{
93
+ saved: boolean;
94
+ }>;
95
+ deleteSettings(tenantRef: string, actor?: string): Promise<boolean>;
96
+ getConversation(tenantRef: string, memberRef: string): Promise<SlotlockAssistantConversationRecord | null>;
97
+ /**
98
+ * Replace a member's messages; keep the stored actions `keep` names, as they stand, and add the
99
+ * `added` ones not stored already (store.ts putAssistantConversation).
100
+ */
101
+ putConversation(tenantRef: string, memberRef: string, conversation: {
102
+ messages: unknown[];
103
+ added: Record<string, Record<string, unknown>>;
104
+ keep: readonly string[];
105
+ }, ttlMs: number): Promise<void>;
106
+ settleAction(tenantRef: string, memberRef: string, actionId: string, from: string, patch: Record<string, unknown>): Promise<Record<string, unknown> | null>;
107
+ deleteConversation(tenantRef: string, memberRef: string): Promise<boolean>;
108
+ }
109
+ /** The assistant's records in the store, each in a transaction under the tenant's row-level security. */
110
+ export declare function createSlotlockAssistantStore(store: SlotlockStore): SlotlockAssistantStore;
111
+ /** The assistant's records in this process: for tests, or a server that only ever runs as one. */
112
+ export declare function createSlotlockMemoryAssistantStore(now?: () => number): SlotlockAssistantStore;
113
+ /** The key sealed for one tenant: `v1.<iv>.<ciphertext and tag>`, base64url. */
114
+ export declare function sealSlotlockAssistantKey(secret: string, tenantRef: string, apiKey: string): Promise<string>;
115
+ /** The key a seal holds, or null when it is not one this secret sealed for this tenant. */
116
+ export declare function openSlotlockAssistantKey(secret: string, tenantRef: string, sealed: string): Promise<string | null>;
117
+ /**
118
+ * A provider base URL as stored: https, or http on localhost or 127.0.0.1 (a model on the server's
119
+ * own machine); no credentials, query or fragment; no trailing slash. Unless `privateUrls`, a URL
120
+ * whose host is `localhost` or a loopback, private, link-local, shared (CGNAT), unique-local or
121
+ * metadata address (the webhooks' isPrivateAddress) is refused as `private`; a name that resolves
122
+ * to one is refused when it is resolved (checkSlotlockAssistantHost, and at each connection).
123
+ */
124
+ export declare function readSlotlockAssistantBaseUrl(value: string, options?: {
125
+ privateUrls?: boolean;
126
+ }): {
127
+ ok: true;
128
+ url: string;
129
+ } | {
130
+ ok: false;
131
+ reason: 'invalid' | 'private';
132
+ };
133
+ /**
134
+ * Whether a base URL's host resolves only to public addresses: `resolve` lists them (dns.lookup's,
135
+ * on Node.js). True when `privateUrls`, or when the host is an IP literal readSlotlockAssistantBaseUrl
136
+ * already checked; false when any address is private. A name that does not resolve is not refused
137
+ * here: the connection fails later, plainly.
138
+ */
139
+ export declare function checkSlotlockAssistantHost(baseUrl: string, options: {
140
+ privateUrls?: boolean;
141
+ resolve?: (hostname: string) => Promise<string[]>;
142
+ }): Promise<boolean>;
143
+ /** A model name: 1-200 printable characters, no spaces. */
144
+ export declare const SLOTLOCK_ASSISTANT_MODEL_NAME: RegExp;
145
+ /** An API key as typed: 1-4,096 printable characters, no spaces. */
146
+ export declare const SLOTLOCK_ASSISTANT_API_KEY: RegExp;
147
+ export interface SlotlockAssistantTool {
148
+ name: SlotlockAgentOperation;
149
+ title: string;
150
+ description: string;
151
+ inputSchema: Record<string, unknown>;
152
+ use: 'read' | 'propose';
153
+ }
154
+ /**
155
+ * The tools the model is offered: every agent tool the assistant reads or proposes, with its input
156
+ * schema less `idempotency_key`, which the dashboard sets itself so an approval runs once.
157
+ */
158
+ export declare function slotlockAssistantTools(): SlotlockAssistantTool[];
159
+ /** Why a provider call failed, in words safe to show (never the key, never the provider's body). */
160
+ export declare class SlotlockAssistantProviderError extends Error {
161
+ readonly reason: 'timeout' | 'refused_key' | 'not_found' | 'rate_limited' | 'unavailable' | 'bad_answer' | 'private_address';
162
+ readonly status?: number | undefined;
163
+ constructor(reason: 'timeout' | 'refused_key' | 'not_found' | 'rate_limited' | 'unavailable' | 'bad_answer' | 'private_address', status?: number | undefined);
164
+ }
165
+ /** What to tell the member a provider failure was. */
166
+ export declare function slotlockAssistantProviderMessage(error: unknown): string;
167
+ /** One answer of the model: its text and the tools it called. */
168
+ export interface SlotlockAssistantModelTurn {
169
+ text: string;
170
+ calls: SlotlockAssistantCall[];
171
+ }
172
+ interface ModelRequest {
173
+ model: SlotlockAssistantModel;
174
+ system: string;
175
+ entries: readonly SlotlockAssistantEntry[];
176
+ tools: readonly {
177
+ name: string;
178
+ description: string;
179
+ inputSchema: Record<string, unknown>;
180
+ }[];
181
+ /** Make the model call this tool (the connection test). */
182
+ force?: string;
183
+ fetch: typeof fetch;
184
+ signal: AbortSignal;
185
+ }
186
+ /** One model call. Throws SlotlockAssistantProviderError, whose message never holds the key. */
187
+ export declare function callSlotlockAssistantModel(request: ModelRequest): Promise<SlotlockAssistantModelTurn>;
188
+ /**
189
+ * The connection test: one request offering one read tool the model must call. True when it
190
+ * answers with exactly one call of that tool with object arguments.
191
+ */
192
+ export declare function testSlotlockAssistantModel(args: {
193
+ model: SlotlockAssistantModel;
194
+ fetch: typeof fetch;
195
+ timeoutMs: number;
196
+ }): Promise<boolean>;
197
+ /** How a tool call came out, as the loop tells the model. */
198
+ export type SlotlockAssistantToolOutcome = {
199
+ ok: true;
200
+ data: Record<string, unknown>;
201
+ } | {
202
+ ok: false;
203
+ code: string;
204
+ details?: Readonly<Record<string, string>>;
205
+ };
206
+ /** A URL checked again before each call: one stored under looser rules is refused, not reached. */
207
+ export declare function slotlockAssistantUrlAllowed(baseUrl: string, privateUrls: boolean): boolean;
208
+ export interface SlotlockAssistantTurnOptions {
209
+ model: SlotlockAssistantModel;
210
+ system: string;
211
+ /** The conversation so far, ending with the member's new message. */
212
+ entries: readonly SlotlockAssistantEntry[];
213
+ fetch: typeof fetch;
214
+ /** Each model call's limit, and the whole turn's. */
215
+ timeoutMs: number;
216
+ turnTimeoutMs: number;
217
+ maxSteps?: number;
218
+ /** Run a read the model asked for. */
219
+ read(operation: SlotlockAgentOperation, input: unknown): Promise<SlotlockAssistantToolOutcome>;
220
+ /** Check a write the model asked for and keep it for the member to approve: its action id. */
221
+ propose(operation: SlotlockAgentOperation, input: unknown): Promise<{
222
+ ok: true;
223
+ actionId: string;
224
+ } | {
225
+ ok: false;
226
+ code: string;
227
+ }>;
228
+ }
229
+ export interface SlotlockAssistantTurnResult {
230
+ /** The entries this turn added. */
231
+ added: SlotlockAssistantEntry[];
232
+ /** Set when the provider failed; `added` then ends with a note saying so. */
233
+ failure?: unknown;
234
+ }
235
+ /**
236
+ * One member message: call the model, run what it reads, keep what it would write, and call it
237
+ * again with the results, up to `maxSteps` calls. Only the offered tools run, whatever the model
238
+ * names; everything else is answered `tool_not_available`.
239
+ */
240
+ export declare function runSlotlockAssistantTurn(options: SlotlockAssistantTurnOptions): Promise<SlotlockAssistantTurnResult>;
241
+ /**
242
+ * The conversation within its bounds: at most MAX_ENTRIES entries and MAX_STORED_CHARACTERS, the
243
+ * oldest exchanges dropped whole, so it always starts at a member's message (a tool result is never
244
+ * kept without the call it answers).
245
+ */
246
+ export declare function boundSlotlockAssistantEntries(entries: readonly SlotlockAssistantEntry[]): SlotlockAssistantEntry[];
247
+ /**
248
+ * The actions a conversation keeps: those its kept entries show, the oldest settled ones dropped
249
+ * first past MAX_ACTIONS_BYTES (a waiting one is kept: SLOTLOCK_ASSISTANT_MAX_PENDING bounds them).
250
+ */
251
+ export declare function pruneSlotlockAssistantActions(entries: readonly SlotlockAssistantEntry[], actions: Readonly<Record<string, Record<string, unknown>>>): Record<string, Record<string, unknown>>;
252
+ /** How many of a conversation's actions wait for the member. */
253
+ export declare function pendingSlotlockAssistantActions(actions: Readonly<Record<string, Record<string, unknown>>>): number;
254
+ /** Read stored entries back, dropping anything malformed. */
255
+ export declare function readSlotlockAssistantEntries(value: unknown): SlotlockAssistantEntry[];
256
+ /** The system prompt: who the model works for, and that what it reads is data, not instructions. */
257
+ export declare function slotlockAssistantSystemPrompt(args: {
258
+ brand: string;
259
+ workspace: string;
260
+ login: string;
261
+ now: Date;
262
+ }): string;
263
+ export {};