@substrat-run/engine-assistant 0.0.0-stage → 0.1.28
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/LICENSE +661 -0
- package/README.md +125 -2
- package/dist/entities.d.ts +174 -0
- package/dist/entities.d.ts.map +1 -0
- package/dist/entities.js +110 -0
- package/dist/entities.js.map +1 -0
- package/dist/events.d.ts +106 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +57 -0
- package/dist/events.js.map +1 -0
- package/dist/files.d.ts +32 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +69 -0
- package/dist/files.js.map +1 -0
- package/dist/index.d.ts +356 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +811 -0
- package/dist/index.js.map +1 -0
- package/dist/model.d.ts +12 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +19 -0
- package/dist/model.js.map +1 -0
- package/dist/operations.d.ts +500 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +106 -0
- package/dist/operations.js.map +1 -0
- package/dist/seam.d.ts +5 -0
- package/dist/seam.d.ts.map +1 -0
- package/dist/seam.js +15 -0
- package/dist/seam.js.map +1 -0
- package/dist/shapes.d.ts +428 -0
- package/dist/shapes.d.ts.map +1 -0
- package/dist/shapes.js +134 -0
- package/dist/shapes.js.map +1 -0
- package/package.json +51 -3
package/dist/files.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HOST code, separate from the in-scope engine. Bind `caller` to the authenticated
|
|
3
|
+
* person and `storage` to the assistant host's system principal, in the SAME scope.
|
|
4
|
+
* Never expose `storage` itself to a browser or model tool.
|
|
5
|
+
*/
|
|
6
|
+
import { substratError, uploadLinkFilename } from '@substrat-run/contracts';
|
|
7
|
+
export const ASSISTANT_FILE_MAX_BYTES = 10 * 1024 * 1024;
|
|
8
|
+
const XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|
9
|
+
/** A browser need not guess a spreadsheet's MIME type; the supported suffix fixes it. */
|
|
10
|
+
function contentType(filename) {
|
|
11
|
+
const dot = filename.lastIndexOf('.');
|
|
12
|
+
const extension = dot < 0 ? '' : filename.slice(dot + 1).toLowerCase();
|
|
13
|
+
if (extension === 'xlsx')
|
|
14
|
+
return XLSX;
|
|
15
|
+
if (extension === 'csv')
|
|
16
|
+
return 'text/csv';
|
|
17
|
+
if (extension === 'tsv')
|
|
18
|
+
return 'text/tab-separated-values';
|
|
19
|
+
throw substratError('validation_failed', 'upload a .csv, .tsv or .xlsx file; save older Excel files as .xlsx first');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A host mounts these methods on its own authenticated routes. Bytes bypass invoke;
|
|
23
|
+
* ownership and audit checks go through the engine's real operation handlers.
|
|
24
|
+
* There is intentionally no automatic import: the host's tools preview a diff and
|
|
25
|
+
* use the existing approval/claim flow before changing domain entities.
|
|
26
|
+
*/
|
|
27
|
+
export function assistantFiles(caller, storage) {
|
|
28
|
+
const entity = (threadId) => ({ entityType: 'assistant-thread', entityId: threadId });
|
|
29
|
+
const list = async (threadId) => {
|
|
30
|
+
await caller.invoke('assistant/get-thread', { threadId });
|
|
31
|
+
return storage.list(entity(threadId));
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
async upload(input) {
|
|
35
|
+
const filename = uploadLinkFilename.parse(input.filename);
|
|
36
|
+
const type = contentType(filename);
|
|
37
|
+
if (!input.body.byteLength || input.body.byteLength > ASSISTANT_FILE_MAX_BYTES) {
|
|
38
|
+
throw substratError('validation_failed', `a file must contain between 1 and ${ASSISTANT_FILE_MAX_BYTES} bytes`);
|
|
39
|
+
}
|
|
40
|
+
await caller.invoke('assistant/authorize-file-upload', { threadId: input.threadId });
|
|
41
|
+
return storage.upload({
|
|
42
|
+
entity: entity(input.threadId), filename, contentType: type, body: input.body, visibility: 'internal',
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
list,
|
|
46
|
+
async open(threadId, attachmentId) {
|
|
47
|
+
// Authorize and match the id BEFORE opening any bytes with the host's key.
|
|
48
|
+
const record = (await list(threadId)).find((file) => file.id === attachmentId);
|
|
49
|
+
if (!record)
|
|
50
|
+
throw substratError('not_found', `file not found in thread: ${attachmentId}`);
|
|
51
|
+
const opened = await storage.open(attachmentId);
|
|
52
|
+
if (!opened)
|
|
53
|
+
throw substratError('not_found', `file not found in thread: ${attachmentId}`);
|
|
54
|
+
return opened;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Trusted host lifecycle hook: remove blobs BEFORE erasing a thread's owner. The
|
|
60
|
+
* kernel's subject erasure deletes engine rows, but does not shred attachment blobs.
|
|
61
|
+
* Repeatable; failed blob deletions follow the platform's orphan-sweep policy.
|
|
62
|
+
* Do not expose as an unauthenticated route.
|
|
63
|
+
*/
|
|
64
|
+
export async function purgeAssistantThreadFiles(storage, threadId) {
|
|
65
|
+
for (const file of await storage.list({ entityType: 'assistant-thread', entityId: threadId })) {
|
|
66
|
+
await storage.remove(file.id);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* engine-assistant — composed **by call**, not by event.
|
|
3
|
+
*
|
|
4
|
+
* The record of a chat between a person and an assistant. It owns the invariants of that
|
|
5
|
+
* record and nothing about the model that speaks for it: it never talks to a model, a
|
|
6
|
+
* network or a clock of its own. A host (the platform's assistant host, or a vertical that
|
|
7
|
+
* composes it) runs the loop, and calls these functions to write what happened.
|
|
8
|
+
*
|
|
9
|
+
* What the engine guarantees, each of which a test pins:
|
|
10
|
+
*
|
|
11
|
+
* 1. **The record is append-only and numbered.** Events are rows `(thread, seq)`, `seq`
|
|
12
|
+
* from 1, never updated or removed. `seq` is the cursor a client resumes after.
|
|
13
|
+
* 2. **Only the lease holder writes the assistant's side.** `acquireRun` takes a
|
|
14
|
+
* single-writer lease; `appendEvents` is fenced by it, so a holder that was replaced
|
|
15
|
+
* while still running (a zombie) cannot write. A holder that stopped beating can be
|
|
16
|
+
* replaced.
|
|
17
|
+
* 3. **A gated tool runs once, with the input the user saw.** A tool call that asks for
|
|
18
|
+
* approval is bound to `approvalDigest` of the tagged tuple (deployed version, approver,
|
|
19
|
+
* thread, step, call, operation, expiry, nonce, input; docs/rfc/assistant.md §6.0 point
|
|
20
|
+
* 3), and the bindings are stored beside it. `resolveApproval` RECOMPUTES that digest
|
|
21
|
+
* with the principal who answered and the version the answer arrived under, so an
|
|
22
|
+
* approval from anyone but the thread's subject, for another thread, call or operation,
|
|
23
|
+
* under another deploy, or after the expiry, does not match. `claimExecution` recomputes
|
|
24
|
+
* it with the operation and input the host is about to run, before the expiry. Both
|
|
25
|
+
* moves are conditional writes (`… WHERE state = ? AND digest = ?`, one row changed or
|
|
26
|
+
* refused), so single use is the record's own, not a read that came before it. A
|
|
27
|
+
* `tool-output` for a gated call is refused unless it was claimed. The model cannot
|
|
28
|
+
* change the arguments after the user said yes.
|
|
29
|
+
* 4. **The two sides of the record are written by different keys.** What the user did
|
|
30
|
+
* (`user-message`, `turn-start`, `approval-resolved`) is written by `sendMessage` and
|
|
31
|
+
* `resolveApproval` under `assistant:use`, as the owner. What the assistant did is
|
|
32
|
+
* written by `appendEvents` under `assistant:run`, which is held by a SYSTEM principal
|
|
33
|
+
* (the assistant host's) and by no role a person has — the manifest declares it
|
|
34
|
+
* `holder: 'system'`, and `lint:permissions` refuses a role or entity grant shape that
|
|
35
|
+
* grants it (tools/reserved-keys.mts). Even the run key writes only
|
|
36
|
+
* inside a turn the user opened: with no turn open, `appendEvents` is `no_turn_open`,
|
|
37
|
+
* so a run cannot keep a resting thread busy and lock its owner out.
|
|
38
|
+
* 5. **An event is bounded.** A body over `MAX_EVENT_BYTES` is refused: a large tool
|
|
39
|
+
* result belongs in the operation that produced it, referred to by id, not copied into
|
|
40
|
+
* a Durable Object row.
|
|
41
|
+
*
|
|
42
|
+
* `appendEvents` and the per-delta rows do not emit a platform event each. Forty text deltas
|
|
43
|
+
* make one answer, and an outbox row apiece would be the record written twice. The platform
|
|
44
|
+
* learns the milestones (`events.ts`).
|
|
45
|
+
*
|
|
46
|
+
* Deferred, and stated so an absence reads as intent: message branches (regenerate, edit and
|
|
47
|
+
* resend), participants other than the owner and the assistant (a human agent), the support
|
|
48
|
+
* handoff, and memory. Each is additive: a column, an event type, a table.
|
|
49
|
+
*/
|
|
50
|
+
import { z } from 'zod';
|
|
51
|
+
import { type ModuleRegistration, type OperationContext } from '@substrat-run/kernel';
|
|
52
|
+
import { threadRow } from './entities.js';
|
|
53
|
+
import { type AcquireRunInput, type AppendEventsInput, type AppendedEvents, type ClaimExecutionInput, type CreateThreadInput, type EventsPage, type ListThreadsInput, type ReadEventsInput, type ReleaseRunInput, type ResolveApprovalInput, type SendMessageInput, type SentMessage, type Thread, type ThreadIdInput } from './shapes.js';
|
|
54
|
+
export { MAX_EVENT_BYTES, MAX_MESSAGE_BYTES } from './shapes.js';
|
|
55
|
+
export type { AcquireRunInput, AppendEventsInput, AppendedEvents, ClaimExecutionInput, CreateThreadInput, EventsPage, ListThreadsInput, ReadEventsInput, ReleaseRunInput, ResolveApprovalInput, SendMessageInput, SentMessage, Thread, ThreadIdInput, } from './shapes.js';
|
|
56
|
+
export { assistantEntities, threadRow, eventRow, runRow, toolCallRow } from './entities.js';
|
|
57
|
+
export { assistantOperations, ASSISTANT_PERMISSIONS } from './operations.js';
|
|
58
|
+
export { type AssistantEvents, type AssistantEventType, type AssistantThreadCreatedPayload, type AssistantTurnStartedPayload, type AssistantTurnFinishedPayload, type AssistantApprovalRequestedPayload, type AssistantApprovalResolvedPayload, type AssistantThreadClosedPayload, } from './events.js';
|
|
59
|
+
/**
|
|
60
|
+
* The conflict reasons this engine raises, narrowing the platform's `conflict` code (#113).
|
|
61
|
+
* Additive only: new reasons may appear, existing ones do not change spelling.
|
|
62
|
+
*/
|
|
63
|
+
export declare const ASSISTANT_CONFLICT_REASONS: readonly ['thread_closed', 'turn_in_progress', 'approval_pending', 'no_approval_pending', 'run_in_progress', 'run_fenced', 'not_a_run_event', 'call_state', 'approval_required', 'approval_denied', 'execution_not_claimed', 'already_executed', 'already_resolved', 'digest_mismatch', 'approval_expired', 'no_turn_open'];
|
|
64
|
+
export type AssistantConflictReason = (typeof ASSISTANT_CONFLICT_REASONS)[number];
|
|
65
|
+
export declare const ASSISTANT_PERM: {
|
|
66
|
+
use: string & z.$brand<"PermissionKey">;
|
|
67
|
+
audit: string & z.$brand<"PermissionKey">;
|
|
68
|
+
run: string & z.$brand<"PermissionKey">;
|
|
69
|
+
};
|
|
70
|
+
export declare const assistantManifest: {
|
|
71
|
+
id: string & z.$brand<"ModuleId">;
|
|
72
|
+
version: string;
|
|
73
|
+
kernelContract: string;
|
|
74
|
+
permissions: {
|
|
75
|
+
key: string & z.$brand<"PermissionKey">;
|
|
76
|
+
description: string;
|
|
77
|
+
holder?: "system" | undefined;
|
|
78
|
+
}[];
|
|
79
|
+
events: {
|
|
80
|
+
emits: {
|
|
81
|
+
type: string;
|
|
82
|
+
schemaVersion: number;
|
|
83
|
+
}[];
|
|
84
|
+
consumes: {
|
|
85
|
+
type: string;
|
|
86
|
+
schemaVersion: number;
|
|
87
|
+
from?: string | undefined;
|
|
88
|
+
}[];
|
|
89
|
+
exports?: {
|
|
90
|
+
type: string;
|
|
91
|
+
schemaVersion: number;
|
|
92
|
+
readPermission: string & z.$brand<"PermissionKey">;
|
|
93
|
+
}[] | undefined;
|
|
94
|
+
};
|
|
95
|
+
migrations: {
|
|
96
|
+
journalDir: string;
|
|
97
|
+
compatibleFrom: string;
|
|
98
|
+
};
|
|
99
|
+
attachmentTargets: {
|
|
100
|
+
entityType: string;
|
|
101
|
+
readPermission: string & z.$brand<"PermissionKey">;
|
|
102
|
+
writePermission?: (string & z.$brand<"PermissionKey">) | undefined;
|
|
103
|
+
uploadLinks?: {
|
|
104
|
+
maxBytes: number;
|
|
105
|
+
contentTypes?: string[] | undefined;
|
|
106
|
+
} | undefined;
|
|
107
|
+
}[];
|
|
108
|
+
liveTargets?: {
|
|
109
|
+
entityType: string;
|
|
110
|
+
readPermission: string & z.$brand<"PermissionKey">;
|
|
111
|
+
}[] | undefined;
|
|
112
|
+
entityRelations?: {
|
|
113
|
+
entityType: string;
|
|
114
|
+
parentType: string;
|
|
115
|
+
}[] | undefined;
|
|
116
|
+
guards?: {
|
|
117
|
+
before: string;
|
|
118
|
+
predicate: string;
|
|
119
|
+
config: Record<string, unknown>;
|
|
120
|
+
}[] | undefined;
|
|
121
|
+
schedules?: {
|
|
122
|
+
operation: string;
|
|
123
|
+
cadence: {
|
|
124
|
+
everyMinutes: number;
|
|
125
|
+
};
|
|
126
|
+
input?: Record<string, unknown> | undefined;
|
|
127
|
+
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
128
|
+
purge?: {
|
|
129
|
+
entityType: string;
|
|
130
|
+
} | undefined;
|
|
131
|
+
}[] | undefined;
|
|
132
|
+
peers?: {
|
|
133
|
+
vertical: string;
|
|
134
|
+
operations: string[];
|
|
135
|
+
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
136
|
+
}[] | undefined;
|
|
137
|
+
connections?: {
|
|
138
|
+
provider: string;
|
|
139
|
+
operation: string;
|
|
140
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
141
|
+
options?: Record<string, unknown> | undefined;
|
|
142
|
+
bind?: "every-install" | "on-request" | undefined;
|
|
143
|
+
}[] | undefined;
|
|
144
|
+
freshness?: {
|
|
145
|
+
eventType: string;
|
|
146
|
+
within: {
|
|
147
|
+
hours: number;
|
|
148
|
+
};
|
|
149
|
+
}[] | undefined;
|
|
150
|
+
withdraws?: string[] | undefined;
|
|
151
|
+
entitlementKey: string;
|
|
152
|
+
envSpec?: {
|
|
153
|
+
key: string;
|
|
154
|
+
label?: string | undefined;
|
|
155
|
+
description: string;
|
|
156
|
+
placeholder?: string | undefined;
|
|
157
|
+
kind?: "model" | undefined;
|
|
158
|
+
required: boolean;
|
|
159
|
+
secret: boolean;
|
|
160
|
+
previewCarry?: boolean | undefined;
|
|
161
|
+
default?: string | undefined;
|
|
162
|
+
group?: string | undefined;
|
|
163
|
+
}[] | undefined;
|
|
164
|
+
ownerGrants?: (string & z.$brand<"PermissionKey">)[] | undefined;
|
|
165
|
+
entitlements?: string[] | undefined;
|
|
166
|
+
provides?: string[] | undefined;
|
|
167
|
+
requires?: string[] | undefined;
|
|
168
|
+
api?: string | undefined;
|
|
169
|
+
searchables?: {
|
|
170
|
+
entityType: string;
|
|
171
|
+
fields: string[];
|
|
172
|
+
table?: string | undefined;
|
|
173
|
+
idColumn?: string | undefined;
|
|
174
|
+
tokenizer?: "prefix" | "substring" | undefined;
|
|
175
|
+
}[] | undefined;
|
|
176
|
+
lists?: {
|
|
177
|
+
entityType: string;
|
|
178
|
+
sortable: string[];
|
|
179
|
+
filterable?: string[] | undefined;
|
|
180
|
+
table?: string | undefined;
|
|
181
|
+
idColumn?: string | undefined;
|
|
182
|
+
}[] | undefined;
|
|
183
|
+
entityStates?: {
|
|
184
|
+
archivePermission?: (string & z.$brand<"PermissionKey">) | undefined;
|
|
185
|
+
trashPermission?: (string & z.$brand<"PermissionKey">) | undefined;
|
|
186
|
+
purgeAfterDays?: number | undefined;
|
|
187
|
+
purgeEarly?: boolean | undefined;
|
|
188
|
+
table?: string | undefined;
|
|
189
|
+
idColumn?: string | undefined;
|
|
190
|
+
entityType: string;
|
|
191
|
+
}[] | undefined;
|
|
192
|
+
erasure?: {
|
|
193
|
+
tables: string[];
|
|
194
|
+
entities: {
|
|
195
|
+
entityType: string;
|
|
196
|
+
table: string;
|
|
197
|
+
mode: "blank" | "custom" | "delete" | "unreached";
|
|
198
|
+
subjects?: string[] | undefined;
|
|
199
|
+
fields: {
|
|
200
|
+
name: string;
|
|
201
|
+
blank: "" | null;
|
|
202
|
+
}[];
|
|
203
|
+
}[];
|
|
204
|
+
} | undefined;
|
|
205
|
+
updatedStamps?: {
|
|
206
|
+
table: string;
|
|
207
|
+
idColumn: string;
|
|
208
|
+
at?: string | undefined;
|
|
209
|
+
by?: string | undefined;
|
|
210
|
+
entityType: string;
|
|
211
|
+
}[] | undefined;
|
|
212
|
+
ui?: {
|
|
213
|
+
routes?: {
|
|
214
|
+
path: string;
|
|
215
|
+
screen: string;
|
|
216
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
217
|
+
}[] | undefined;
|
|
218
|
+
nav?: {
|
|
219
|
+
label: string;
|
|
220
|
+
icon?: string | undefined;
|
|
221
|
+
to: string;
|
|
222
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
223
|
+
}[] | undefined;
|
|
224
|
+
entityViews?: {
|
|
225
|
+
entityType: string;
|
|
226
|
+
view: string;
|
|
227
|
+
}[] | undefined;
|
|
228
|
+
widgets?: {
|
|
229
|
+
slot: string;
|
|
230
|
+
component: string;
|
|
231
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
232
|
+
}[] | undefined;
|
|
233
|
+
settingsPanels?: {
|
|
234
|
+
label: string;
|
|
235
|
+
component: string;
|
|
236
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
237
|
+
}[] | undefined;
|
|
238
|
+
} | undefined;
|
|
239
|
+
};
|
|
240
|
+
export declare const assistantMigrations: {
|
|
241
|
+
version: string;
|
|
242
|
+
sql: string;
|
|
243
|
+
}[];
|
|
244
|
+
type ThreadRow = z.infer<typeof threadRow>;
|
|
245
|
+
/**
|
|
246
|
+
* Open a thread for the caller. The caller's principal is the subject: a thread is created
|
|
247
|
+
* for yourself, never on someone else's behalf.
|
|
248
|
+
*/
|
|
249
|
+
export declare function createThread(ctx: OperationContext, rawInput?: CreateThreadInput): Thread;
|
|
250
|
+
/** One thread. The CALLER decides who may see it; see `assertThreadVisible`. */
|
|
251
|
+
export declare function getThread(ctx: OperationContext, rawInput: ThreadIdInput): Thread;
|
|
252
|
+
/**
|
|
253
|
+
* The thread, if the caller may see it: the owner, or someone holding `assistant:audit`.
|
|
254
|
+
* `not_found` otherwise, so a thread's existence is not probed.
|
|
255
|
+
*/
|
|
256
|
+
export declare function assertThreadVisible(ctx: OperationContext, threadId: string): Promise<ThreadRow>;
|
|
257
|
+
/** Threads for one principal, most recently active first. Unpaged: a vertical folding them. */
|
|
258
|
+
export declare function listThreads(ctx: OperationContext, rawInput?: ListThreadsInput & {
|
|
259
|
+
subject: string;
|
|
260
|
+
}): Thread[];
|
|
261
|
+
/** The record after a cursor. The CALLER decides who may read it. */
|
|
262
|
+
export declare function readEvents(ctx: OperationContext, rawInput: ReadEventsInput): EventsPage;
|
|
263
|
+
/**
|
|
264
|
+
* The user says something, which begins a turn. As the owner, under `assistant:use`.
|
|
265
|
+
*
|
|
266
|
+
* Refused while a turn is running (the host is mid-answer) and while an approval is waiting
|
|
267
|
+
* (the user must answer it, or deny it, first), so the record never holds two turns at once.
|
|
268
|
+
*/
|
|
269
|
+
export declare function sendMessage(ctx: OperationContext, rawInput: SendMessageInput): SentMessage;
|
|
270
|
+
/** Ownership is required even when the caller can audit other people's threads. */
|
|
271
|
+
export declare function authorizeFileUpload(ctx: OperationContext, rawInput: ThreadIdInput): Thread;
|
|
272
|
+
/**
|
|
273
|
+
* The user approves or denies a gated tool call. As the owner, under `assistant:use`.
|
|
274
|
+
*
|
|
275
|
+
* An APPROVAL must carry the stored digest (the one the request showed), and that digest must
|
|
276
|
+
* equal the one RECOMPUTED from the stored bindings with the principal who is answering as
|
|
277
|
+
* the approver and `input.version` (the deployed version the host serves the answer under)
|
|
278
|
+
* as the version: an approval of anything else — another input, call, thread or operation,
|
|
279
|
+
* another approver, another deploy — is `digest_mismatch`, never a quiet approval of what is
|
|
280
|
+
* stored. One that arrives at or after the request's expiry is `approval_expired`.
|
|
281
|
+
*
|
|
282
|
+
* A DENIAL needs only the digest the user was shown, with no version or expiry: saying no
|
|
283
|
+
* runs nothing, and it is how the owner clears a request that lapsed or that a deploy made
|
|
284
|
+
* stale, which would otherwise refuse every message (`approval_pending`) for ever. A denial
|
|
285
|
+
* does not end the turn: `approval-resolved` resumes it, like an approval, and the turn stays
|
|
286
|
+
* open (`turn_in_progress` for the owner) until the host writes `turn-finish` or
|
|
287
|
+
* `turn-error`. The owner has no way to end a turn without a run; a host that does not come
|
|
288
|
+
* back leaves closing the thread as the owner's only way out, so a host must run after every
|
|
289
|
+
* answer, a denial included.
|
|
290
|
+
*
|
|
291
|
+
* Single use is the write itself: `UPDATE … WHERE state = 'awaiting-approval' AND digest = ?`,
|
|
292
|
+
* refused unless it changed exactly one row, whatever was read before it.
|
|
293
|
+
*
|
|
294
|
+
* Not fenced by the lease: a run that asked for approval has come to rest, and the user
|
|
295
|
+
* acts between runs. The host starts the next run after this returns.
|
|
296
|
+
*/
|
|
297
|
+
export declare function resolveApproval(ctx: OperationContext, rawInput: ResolveApprovalInput): Promise<{
|
|
298
|
+
seq: number;
|
|
299
|
+
}>;
|
|
300
|
+
/** Close a thread. As the owner. Nothing is appended to a closed thread. */
|
|
301
|
+
export declare function closeThread(ctx: OperationContext, rawInput: ThreadIdInput): Thread;
|
|
302
|
+
/**
|
|
303
|
+
* Take the single-writer lease on a thread. A holder that has beaten within `staleMs` keeps
|
|
304
|
+
* it (`run_in_progress`); one that has not can be replaced, and `tookOver` says so. The same
|
|
305
|
+
* run asking again simply refreshes its beat.
|
|
306
|
+
*/
|
|
307
|
+
export declare function acquireRun(ctx: OperationContext, rawInput: AcquireRunInput): {
|
|
308
|
+
tookOver: boolean;
|
|
309
|
+
};
|
|
310
|
+
/** Give the lease back. A run that no longer holds it releases nothing. */
|
|
311
|
+
export declare function releaseRun(ctx: OperationContext, rawInput: ReleaseRunInput): {
|
|
312
|
+
released: boolean;
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Append what the assistant said and did, fenced by the lease, and enforce the tool-call
|
|
316
|
+
* state machine on the way in.
|
|
317
|
+
*
|
|
318
|
+
* tool-input → `running` (a repeat of a running call is a step restart, and allowed)
|
|
319
|
+
* approval-request → `awaiting-approval`, with its bindings stored; the digest must be
|
|
320
|
+
* `approvalDigest` of those bindings with the thread's subject as the
|
|
321
|
+
* approver, and the expiry still ahead
|
|
322
|
+
* tool-output → `done`; for a gated call only from `executing`, i.e. after
|
|
323
|
+
* `claimExecution`
|
|
324
|
+
* tool-error → `failed`
|
|
325
|
+
* turn-finish → `awaiting-approval` only with an approval waiting, `done` only without
|
|
326
|
+
*
|
|
327
|
+
* Every event is refused (`no_turn_open`) unless a turn is open: the last event is not a
|
|
328
|
+
* resting one (`turn-finish`, `turn-error`), and the thread has at least one.
|
|
329
|
+
*
|
|
330
|
+
* `tool-error` may also fail an `approved` call that was never claimed: the host could not
|
|
331
|
+
* run it (the operation refused, the credential ended). That is the host's word, which is why
|
|
332
|
+
* the run key is a system principal's.
|
|
333
|
+
*
|
|
334
|
+
* The whole batch is in the caller's transaction: a refusal anywhere leaves none of it.
|
|
335
|
+
*/
|
|
336
|
+
export declare function appendEvents(ctx: OperationContext, rawInput: AppendEventsInput): Promise<AppendedEvents>;
|
|
337
|
+
/**
|
|
338
|
+
* Claim the one execution of an approved tool call, with the operation, the deployed version
|
|
339
|
+
* and the input about to be run.
|
|
340
|
+
*
|
|
341
|
+
* This is the gate in front of a write: the host calls it BEFORE invoking the operation, and
|
|
342
|
+
* runs the operation only if it returns. The digest is recomputed from the stored bindings
|
|
343
|
+
* with the claim's operation, version and input and the principal who approved, and must be
|
|
344
|
+
* the one the user approved (`digest_mismatch` otherwise: the model, or a bug, changed the
|
|
345
|
+
* input, or the host is about to run another operation or under another deploy). The call
|
|
346
|
+
* must be approved (not waiting, not denied), the request's expiry still ahead
|
|
347
|
+
* (`approval_expired`: an approval is spent when it is claimed, and one not spent in time
|
|
348
|
+
* runs nothing), and not already claimed (`already_executed`), so a restarted loop cannot run
|
|
349
|
+
* a write twice — that last is the conditional write itself, `… WHERE state = 'approved'`.
|
|
350
|
+
* Fenced by the lease.
|
|
351
|
+
*/
|
|
352
|
+
export declare function claimExecution(ctx: OperationContext, rawInput: ClaimExecutionInput): Promise<{
|
|
353
|
+
claimed: true;
|
|
354
|
+
}>;
|
|
355
|
+
export declare const assistantModule: ModuleRegistration;
|
|
356
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|