@substrat-run/engine-assistant 0.0.0-stage → 0.1.27

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/dist/shapes.js ADDED
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The published shapes and the declared inputs of engine-assistant, in one place so the
3
+ * in-scope functions in `index.ts` and the declared operations in `operations.ts` read the
4
+ * same definition rather than two that drift.
5
+ *
6
+ * Published shapes are camelCase projections; the stored rows (snake_case) are in
7
+ * `entities.ts`. A caller never sees a row.
8
+ */
9
+ import { z } from '@substrat-run/contracts';
10
+ import { ASSISTANT_MESSAGE_FILES_MAX, assistantStreamBody, assistantStreamEvent } from '@substrat-run/contracts/assistant-stream';
11
+ /**
12
+ * The longest an event body may serialise to, in UTF-8 bytes: the Durable Object row limit
13
+ * is in bytes. A large tool result belongs in the operation that produced it, by id.
14
+ */
15
+ export const MAX_EVENT_BYTES = 64 * 1024;
16
+ /**
17
+ * The longest a user's message may be, in UTF-8 bytes of its text AS SERIALISED (escapes
18
+ * included). Half the event bound, so a message that passes the input schema always fits in
19
+ * its `user-message` event: a message is refused as a message, at the boundary, never as an
20
+ * oversized event further in.
21
+ */
22
+ export const MAX_MESSAGE_BYTES = 32 * 1024;
23
+ /** UTF-8 byte length of a string, without a platform encoder (module code has none in its types). */
24
+ export function utf8Length(s) {
25
+ let bytes = 0;
26
+ for (const ch of s) {
27
+ const cp = ch.codePointAt(0);
28
+ bytes += cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;
29
+ }
30
+ return bytes;
31
+ }
32
+ const threadId = z.string().min(1).max(64);
33
+ const runId = z.string().min(1).max(64);
34
+ const callId = z.string().min(1).max(64);
35
+ const deployedVersion = z.string().min(1).max(128);
36
+ /** One thread, projected. */
37
+ export const thread = z.object({
38
+ id: z.string(),
39
+ /** The principal the thread belongs to. */
40
+ subject: z.string(),
41
+ title: z.string().nullable(),
42
+ status: z.enum(['open', 'closed']),
43
+ createdAt: z.string(),
44
+ lastEventAt: z.string(),
45
+ closedAt: z.string().nullable(),
46
+ });
47
+ export const createThreadInput = z.object({ title: z.string().max(200).optional() });
48
+ export const listThreadsInput = z.object({
49
+ /** Another principal's threads: needs `assistant:audit`. Unset means the caller's own. */
50
+ subject: z.string().min(1).optional(),
51
+ status: z.enum(['open', 'closed']).optional(),
52
+ });
53
+ export const threadIdInput = z.object({ threadId });
54
+ /** A bounded read of the record, by the cursor a client resumes after. */
55
+ export const readEventsInput = z.object({
56
+ threadId,
57
+ /** Events strictly after this `seq`. 0 reads from the start. */
58
+ after: z.number().int().nonnegative().default(0),
59
+ limit: z.number().int().min(1).max(1000).default(500),
60
+ });
61
+ export const eventsPage = z.object({
62
+ events: z.array(assistantStreamEvent),
63
+ /** The `seq` of the last event returned, or `after` when there were none. */
64
+ lastSeq: z.number().int().nonnegative(),
65
+ });
66
+ export const sendMessageInput = z.object({
67
+ threadId,
68
+ // 32 000 characters is the stream protocol's own bound on `user-message`; the byte bound is
69
+ // the engine's, and is what a message in a wide script meets first.
70
+ text: z
71
+ .string()
72
+ .max(32_000)
73
+ .superRefine((text, ctx) => {
74
+ const bytes = utf8Length(JSON.stringify(text));
75
+ if (bytes > MAX_MESSAGE_BYTES) {
76
+ ctx.addIssue({
77
+ code: 'custom',
78
+ message: `the message is ${bytes} bytes; a message may be at most ${MAX_MESSAGE_BYTES} bytes — send it in shorter parts`,
79
+ });
80
+ }
81
+ })
82
+ .default(''),
83
+ /** IDs of files already uploaded to THIS thread. Metadata is resolved by the engine. */
84
+ attachmentIds: z.array(z.string().min(1).max(64)).min(1).max(ASSISTANT_MESSAGE_FILES_MAX).optional(),
85
+ }).superRefine((input, ctx) => {
86
+ if (!input.text.length && !input.attachmentIds?.length) {
87
+ ctx.addIssue({ code: 'custom', message: 'send text or at least one file' });
88
+ }
89
+ if (input.attachmentIds && new Set(input.attachmentIds).size !== input.attachmentIds.length) {
90
+ ctx.addIssue({ code: 'custom', path: ['attachmentIds'], message: 'a file may appear only once in a message' });
91
+ }
92
+ });
93
+ export const sentMessage = z.object({ firstSeq: z.number().int().positive(), lastSeq: z.number().int().positive() });
94
+ export const resolveApprovalInput = z.object({
95
+ threadId,
96
+ callId,
97
+ /** The digest the user was shown: the request's `digest`. */
98
+ digest: z.string().regex(/^[0-9a-f]{64}$/),
99
+ approved: z.boolean(),
100
+ /**
101
+ * The deployed version the answer arrives under, as the HOST knows it (never the client):
102
+ * an approval given under another version than the request was made under is refused.
103
+ */
104
+ version: deployedVersion,
105
+ });
106
+ export const resolvedApproval = z.object({ seq: z.number().int().positive() });
107
+ export const acquireRunInput = z.object({
108
+ threadId,
109
+ runId,
110
+ /** A holder that has not beaten for this long may be replaced. Default 15 s. */
111
+ staleMs: z.number().int().min(500).max(600_000).optional(),
112
+ });
113
+ export const acquiredRun = z.object({ tookOver: z.boolean() });
114
+ export const releaseRunInput = z.object({ threadId, runId });
115
+ export const releasedRun = z.object({ released: z.boolean() });
116
+ export const appendEventsInput = z.object({
117
+ threadId,
118
+ runId,
119
+ events: z.array(assistantStreamBody).min(1).max(200),
120
+ });
121
+ export const appendedEvents = z.object({ events: z.array(assistantStreamEvent) });
122
+ export const claimExecutionInput = z.object({
123
+ threadId,
124
+ runId,
125
+ callId,
126
+ /** The operation the host is about to run: it must be the one the user approved. */
127
+ operation: z.string().min(1).max(128),
128
+ /** The deployed version the host runs it under: it must be the one the request was made under. */
129
+ version: deployedVersion,
130
+ /** The input the host is about to execute: it must hash to what the user approved. */
131
+ input: z.unknown(),
132
+ });
133
+ export const claimedExecution = z.object({ claimed: z.literal(true) });
134
+ //# sourceMappingURL=shapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../src/shapes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@substrat-run/engine-assistant",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.27",
4
+ "description": "Substrat engine: the assistant's record — chat threads as an append-only event log, a single-writer run lease, and tool calls whose gated writes need an approval bound to the exact input",
5
+ "license": "AGPL-3.0-only",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/substrat-run/substrat.git",
9
+ "directory": "engines/assistant"
10
+ },
11
+ "homepage": "https://substrat.net/engines",
12
+ "type": "module",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ "./files": {
17
+ "types": "./dist/files.d.ts",
18
+ "default": "./dist/files.js"
19
+ },
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "default": "./dist/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "dependencies": {
32
+ "@substrat-run/contracts": "^0.175.0",
33
+ "@substrat-run/kernel": "^0.175.0"
34
+ },
35
+ "devDependencies": {
36
+ "typescript": "^7.0.0",
37
+ "vitest": "^5.0.5",
38
+ "zod": "^4.4.3",
39
+ "@substrat-run/engine-test-kit": "^0.3.102",
40
+ "@substrat-run/contract-tests": "^0.175.0",
41
+ "@substrat-run/model-emit": "0.11.5"
42
+ },
43
+ "peerDependencies": {
44
+ "zod": "^4.4.0"
45
+ },
46
+ "substrat": {
47
+ "conformance": "test/conformance.ts"
48
+ },
49
+ "scripts": {
50
+ "build": "tsc -p tsconfig.json",
51
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
52
+ "test": "vitest run"
53
+ }
6
54
  }