@happyvertical/smrt-app-shell 0.0.0-stage → 0.60.16

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.
Files changed (56) hide show
  1. package/AGENTS.md +99 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +173 -2
  5. package/agents/engine.md +85 -0
  6. package/dist/engine/app-runtime.d.ts +138 -0
  7. package/dist/engine/app-runtime.js +545 -0
  8. package/dist/engine/app-worker.d.ts +1 -0
  9. package/dist/engine/app-worker.js +62 -0
  10. package/dist/engine/commands.d.ts +94 -0
  11. package/dist/engine/commands.js +30 -0
  12. package/dist/engine/definition.d.ts +192 -0
  13. package/dist/engine/definition.js +497 -0
  14. package/dist/engine/errors.d.ts +23 -0
  15. package/dist/engine/errors.js +35 -0
  16. package/dist/engine/host.d.ts +153 -0
  17. package/dist/engine/host.js +791 -0
  18. package/dist/engine/index.d.ts +6 -0
  19. package/dist/engine/index.js +7 -0
  20. package/dist/engine/sandbox.d.ts +60 -0
  21. package/dist/engine/sandbox.js +260 -0
  22. package/dist/engine/snapshots.d.ts +7 -0
  23. package/dist/engine/snapshots.js +54 -0
  24. package/dist/engine/store.d.ts +39 -0
  25. package/dist/engine/store.js +32 -0
  26. package/dist/engine/worker-handle.d.ts +29 -0
  27. package/dist/engine/worker-handle.js +89 -0
  28. package/dist/engine/worker-protocol.d.ts +22 -0
  29. package/dist/engine/worker-protocol.js +20 -0
  30. package/dist/lib/objects/App.d.ts +60 -0
  31. package/dist/lib/objects/App.js +273 -0
  32. package/dist/lib/objects/AppVersion.d.ts +22 -0
  33. package/dist/lib/objects/AppVersion.js +62 -0
  34. package/dist/lib/objects/Approval.d.ts +39 -0
  35. package/dist/lib/objects/Approval.js +101 -0
  36. package/dist/lib/objects/AssistantMessage.d.ts +24 -0
  37. package/dist/lib/objects/AssistantMessage.js +63 -0
  38. package/dist/lib/objects/AssistantThread.d.ts +16 -0
  39. package/dist/lib/objects/AssistantThread.js +44 -0
  40. package/dist/lib/objects/index.d.ts +5 -0
  41. package/dist/lib/objects/index.js +5 -0
  42. package/dist/lib/server/approvals.d.ts +69 -0
  43. package/dist/lib/server/approvals.js +239 -0
  44. package/dist/lib/server/builder.d.ts +16 -0
  45. package/dist/lib/server/builder.js +71 -0
  46. package/dist/lib/server/events.d.ts +16 -0
  47. package/dist/lib/server/events.js +14 -0
  48. package/dist/lib/server/host.d.ts +22 -0
  49. package/dist/lib/server/host.js +96 -0
  50. package/dist/lib/server/owner.d.ts +33 -0
  51. package/dist/lib/server/owner.js +92 -0
  52. package/dist/lib/server/version-store.d.ts +20 -0
  53. package/dist/lib/server/version-store.js +115 -0
  54. package/dist/manifest.json +1680 -0
  55. package/dist/smrt-knowledge.okf.md +95 -0
  56. package/package.json +80 -3
@@ -0,0 +1,60 @@
1
+ import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
2
+ import { type FieldDef, type MethodDef } from '../../engine/index.ts';
3
+ import { type BuilderResult } from '../server/builder.ts';
4
+ /**
5
+ * The shell's one app: a singleton row holding the current definition. Its
6
+ * static methods are the builder operations (so smrt generates their REST,
7
+ * MCP and CLI). All are owner only. A risky one does not apply: it returns
8
+ * `{ status: 'pending_approval', approvalId, summary, preview }` and waits for
9
+ * the owner's decision (`Approval.decide`).
10
+ */
11
+ export declare class App extends SmrtObject {
12
+ /** Display name of the user app. */
13
+ name: string;
14
+ /** The current version number, `-1` before the first start. */
15
+ currentVersion: number;
16
+ /** The current definition, JSON text (a copy of the AppVersion row). */
17
+ definition: string;
18
+ /** Add a model with its fields. */
19
+ static defineModel(name: string, fields?: Record<string, FieldDef>, label?: string): Promise<BuilderResult>;
20
+ /** Add a field to a model. */
21
+ static addField(model: string, field: string, definition: FieldDef): Promise<BuilderResult>;
22
+ /** Hide a field (kept in the data, not shown). */
23
+ static hideField(model: string, field: string): Promise<BuilderResult>;
24
+ /** Rename a field; its values move with it. */
25
+ static renameField(model: string, from: string, to: string): Promise<BuilderResult>;
26
+ /** Remove a field (risky: needs the owner's approval; values are archived). */
27
+ static removeField(model: string, field: string): Promise<BuilderResult>;
28
+ /** Change a field's type (risky: needs the owner's approval). */
29
+ static changeFieldType(model: string, field: string, definition: FieldDef): Promise<BuilderResult>;
30
+ /** Remove a model (risky: needs the owner's approval; its table is moved aside). */
31
+ static removeModel(model: string): Promise<BuilderResult>;
32
+ /** Add a code method to a model (risky: needs the owner's approval). */
33
+ static addMethod(model: string, name: string, method: MethodDef): Promise<BuilderResult>;
34
+ /** Turn on a shipped recipe such as `profiles`. */
35
+ static enableRecipe(recipe: string): Promise<BuilderResult>;
36
+ /**
37
+ * Undo the last change. If that change converted a field's type, going back
38
+ * would overwrite newer values with the archived originals, so it waits for
39
+ * the owner's approval (`pending_approval`).
40
+ */
41
+ static undo(): Promise<BuilderResult>;
42
+ /** Purge old archives, keeping the last `keep` changes (risky). */
43
+ static cleanUp(keep?: number): Promise<BuilderResult>;
44
+ /** Export the definition (and optionally the records) as a template. */
45
+ static exportTemplate(includeRecords?: boolean): Promise<BuilderResult>;
46
+ /** Import a template, replacing the definition (risky if it has code). */
47
+ static importTemplate(data: Record<string, unknown>): Promise<BuilderResult>;
48
+ /** The models, fields and methods of the app now. */
49
+ static describe(): Promise<{
50
+ name: string;
51
+ version: number;
52
+ recipes: string[];
53
+ models: Record<string, import("../../engine/definition.ts").DescribedModel>;
54
+ }>;
55
+ /** Every version of the app, newest last. */
56
+ static history(): Promise<import("../../engine/host.ts").VersionSummary[]>;
57
+ }
58
+ export declare class AppCollection extends SmrtCollection<App> {
59
+ static readonly _itemClass: typeof App;
60
+ }
@@ -0,0 +1,273 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { field, SmrtCollection, SmrtObject, smrt, } from '@happyvertical/smrt-core';
8
+ import { EngineError, } from "../../engine/index.js";
9
+ import { runCommand } from "../server/builder.js";
10
+ import { getHost } from "../server/host.js";
11
+ import { assertOwner } from "../server/owner.js";
12
+ // The decorator config must be a literal: the smrt() scanner reads it
13
+ // statically (a shared constant would be invisible to it and every generated
14
+ // surface would default to full CRUD). The collection repeats it exactly:
15
+ // core applies a collection's @smrt() config to its item class.
16
+ //
17
+ // `operationPermissions` maps each custom operation onto the collection's own
18
+ // CRUD grant; the owner-only rule itself is `assertOwner()` inside every
19
+ // method (defense in depth: the generated routes also check the grant, but a
20
+ // member role may hold it).
21
+ /**
22
+ * A JSON object argument that may arrive as a JSON string (MCP clients). A
23
+ * wrong shape is a 400 that says what to send, never a server error.
24
+ */
25
+ function obj(value, what, example = '{...}') {
26
+ let v = value;
27
+ if (typeof v === 'string') {
28
+ try {
29
+ v = JSON.parse(v);
30
+ }
31
+ catch {
32
+ throw new EngineError(`${what} must be an object like ${example}`, 'invalid');
33
+ }
34
+ }
35
+ if (!v || typeof v !== 'object' || Array.isArray(v))
36
+ throw new EngineError(`${what} must be an object like ${example}`, 'invalid');
37
+ return v;
38
+ }
39
+ function str(value, what) {
40
+ if (typeof value !== 'string' || !value)
41
+ throw new EngineError(`${what} must be a non-empty string`, 'invalid');
42
+ return value;
43
+ }
44
+ const FIELD_EXAMPLE = "{type: 'integer'}";
45
+ async function run(command) {
46
+ const owner = await assertOwner();
47
+ return runCommand(command, owner.id);
48
+ }
49
+ /**
50
+ * The shell's one app: a singleton row holding the current definition. Its
51
+ * static methods are the builder operations (so smrt generates their REST,
52
+ * MCP and CLI). All are owner only. A risky one does not apply: it returns
53
+ * `{ status: 'pending_approval', approvalId, summary, preview }` and waits for
54
+ * the owner's decision (`Approval.decide`).
55
+ */
56
+ let App = class App extends SmrtObject {
57
+ /** Display name of the user app. */
58
+ name = 'My app';
59
+ /** The current version number, `-1` before the first start. */
60
+ currentVersion = -1;
61
+ /** The current definition, JSON text (a copy of the AppVersion row). */
62
+ definition = '';
63
+ /** Add a model with its fields. */
64
+ static async defineModel(name, fields, label) {
65
+ // The shell's own tools are `app_*` and `approval_*`; an app model with
66
+ // either name would generate colliding tool names.
67
+ if (/^(app|approval)$/i.test(String(name)))
68
+ throw new Error(`"${name}" is reserved for the shell`);
69
+ return run({
70
+ type: 'defineModel',
71
+ name: str(name, 'name'),
72
+ ...(label ? { label: str(label, 'label') } : {}),
73
+ ...(fields === undefined
74
+ ? {}
75
+ : {
76
+ fields: obj(fields, 'fields', "{title: {type: 'text'}}"),
77
+ }),
78
+ });
79
+ }
80
+ /** Add a field to a model. */
81
+ static async addField(model, field, definition) {
82
+ return run({
83
+ type: 'addField',
84
+ model: str(model, 'model'),
85
+ field: str(field, 'field'),
86
+ definition: obj(definition, 'definition', FIELD_EXAMPLE),
87
+ });
88
+ }
89
+ /** Hide a field (kept in the data, not shown). */
90
+ static async hideField(model, field) {
91
+ return run({
92
+ type: 'hideField',
93
+ model: str(model, 'model'),
94
+ field: str(field, 'field'),
95
+ });
96
+ }
97
+ /** Rename a field; its values move with it. */
98
+ static async renameField(model, from, to) {
99
+ return run({
100
+ type: 'renameField',
101
+ model: str(model, 'model'),
102
+ from: str(from, 'from'),
103
+ to: str(to, 'to'),
104
+ });
105
+ }
106
+ /** Remove a field (risky: needs the owner's approval; values are archived). */
107
+ static async removeField(model, field) {
108
+ return run({
109
+ type: 'removeField',
110
+ model: str(model, 'model'),
111
+ field: str(field, 'field'),
112
+ });
113
+ }
114
+ /** Change a field's type (risky: needs the owner's approval). */
115
+ static async changeFieldType(model, field, definition) {
116
+ return run({
117
+ type: 'changeFieldType',
118
+ model: str(model, 'model'),
119
+ field: str(field, 'field'),
120
+ to: obj(definition, 'definition', FIELD_EXAMPLE),
121
+ });
122
+ }
123
+ /** Remove a model (risky: needs the owner's approval; its table is moved aside). */
124
+ static async removeModel(model) {
125
+ return run({ type: 'removeModel', model: str(model, 'model') });
126
+ }
127
+ /** Add a code method to a model (risky: needs the owner's approval). */
128
+ static async addMethod(model, name, method) {
129
+ return run({
130
+ type: 'addMethod',
131
+ model: str(model, 'model'),
132
+ name: str(name, 'name'),
133
+ method: obj(method, 'method', "{description: '...', code: 'return 1;'}"),
134
+ });
135
+ }
136
+ /** Turn on a shipped recipe such as `profiles`. */
137
+ static async enableRecipe(recipe) {
138
+ return run({ type: 'enableRecipe', recipe: str(recipe, 'recipe') });
139
+ }
140
+ /**
141
+ * Undo the last change. If that change converted a field's type, going back
142
+ * would overwrite newer values with the archived originals, so it waits for
143
+ * the owner's approval (`pending_approval`).
144
+ */
145
+ static async undo() {
146
+ return run({ type: 'undo' });
147
+ }
148
+ /** Purge old archives, keeping the last `keep` changes (risky). */
149
+ static async cleanUp(keep) {
150
+ const n = keep === undefined ? 5 : Number(keep);
151
+ if (!Number.isInteger(n) || n < 0)
152
+ throw new Error('keep must be a whole number, zero or more');
153
+ return run({ type: 'cleanUp', keep: n });
154
+ }
155
+ /** Export the definition (and optionally the records) as a template. */
156
+ static async exportTemplate(includeRecords) {
157
+ return run({
158
+ type: 'exportTemplate',
159
+ includeRecords: includeRecords === true,
160
+ });
161
+ }
162
+ /** Import a template, replacing the definition (risky if it has code). */
163
+ static async importTemplate(data) {
164
+ return run({
165
+ type: 'importTemplate',
166
+ data: obj(data, 'data', '{format: 1, definition: {...}}'),
167
+ });
168
+ }
169
+ /** The models, fields and methods of the app now. */
170
+ static async describe() {
171
+ await assertOwner();
172
+ return (await getHost()).describe();
173
+ }
174
+ /** Every version of the app, newest last. */
175
+ static async history() {
176
+ await assertOwner();
177
+ return (await getHost()).versions();
178
+ }
179
+ };
180
+ __decorate([
181
+ field({ type: 'text' })
182
+ ], App.prototype, "name", void 0);
183
+ __decorate([
184
+ field({ type: 'integer' })
185
+ ], App.prototype, "currentVersion", void 0);
186
+ __decorate([
187
+ field({ type: 'text' })
188
+ ], App.prototype, "definition", void 0);
189
+ App = __decorate([
190
+ smrt({
191
+ tableName: 'apps',
192
+ conflictColumns: ['id'],
193
+ api: {
194
+ include: [
195
+ 'defineModel',
196
+ 'addField',
197
+ 'hideField',
198
+ 'renameField',
199
+ 'removeField',
200
+ 'changeFieldType',
201
+ 'removeModel',
202
+ 'addMethod',
203
+ 'enableRecipe',
204
+ 'undo',
205
+ 'cleanUp',
206
+ 'exportTemplate',
207
+ 'importTemplate',
208
+ 'describe',
209
+ 'history',
210
+ ],
211
+ },
212
+ mcp: {
213
+ include: [
214
+ 'defineModel',
215
+ 'addField',
216
+ 'hideField',
217
+ 'renameField',
218
+ 'removeField',
219
+ 'changeFieldType',
220
+ 'removeModel',
221
+ 'addMethod',
222
+ 'enableRecipe',
223
+ 'undo',
224
+ 'cleanUp',
225
+ 'exportTemplate',
226
+ 'importTemplate',
227
+ 'describe',
228
+ 'history',
229
+ ],
230
+ },
231
+ cli: {
232
+ include: [
233
+ 'defineModel',
234
+ 'addField',
235
+ 'hideField',
236
+ 'renameField',
237
+ 'removeField',
238
+ 'changeFieldType',
239
+ 'removeModel',
240
+ 'addMethod',
241
+ 'enableRecipe',
242
+ 'undo',
243
+ 'cleanUp',
244
+ 'exportTemplate',
245
+ 'importTemplate',
246
+ 'describe',
247
+ 'history',
248
+ ],
249
+ },
250
+ operationPermissions: {
251
+ defineModel: { action: 'update' },
252
+ addField: { action: 'update' },
253
+ hideField: { action: 'update' },
254
+ renameField: { action: 'update' },
255
+ removeField: { action: 'update' },
256
+ changeFieldType: { action: 'update' },
257
+ removeModel: { action: 'update' },
258
+ addMethod: { action: 'update' },
259
+ enableRecipe: { action: 'update' },
260
+ undo: { action: 'update' },
261
+ cleanUp: { action: 'update' },
262
+ exportTemplate: { action: 'read' },
263
+ importTemplate: { action: 'update' },
264
+ describe: { action: 'read' },
265
+ history: { action: 'read' },
266
+ },
267
+ })
268
+ ], App);
269
+ export { App };
270
+ // Undecorated on purpose: the item class carries the whole generated surface.
271
+ export class AppCollection extends SmrtCollection {
272
+ static _itemClass = App;
273
+ }
@@ -0,0 +1,22 @@
1
+ import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
2
+ /**
3
+ * One version of the user app's definition (shell.db). Never deleted: an old
4
+ * version's migration is marked `purged` once its archives are cleaned up.
5
+ * Written only by `ShellVersionStore`; no generated surface.
6
+ */
7
+ export declare class AppVersion extends SmrtObject {
8
+ version: number;
9
+ /** Parent version, `-1` for none (the first version). */
10
+ parent: number;
11
+ author: string;
12
+ summary: string;
13
+ /** The whole definition, JSON text. */
14
+ definition: string;
15
+ /** `{ steps, purged? }` JSON text, or empty for a change with no migration. */
16
+ migration: string;
17
+ createdAt: string;
18
+ purged: boolean;
19
+ }
20
+ export declare class AppVersionCollection extends SmrtCollection<AppVersion> {
21
+ static readonly _itemClass: typeof AppVersion;
22
+ }
@@ -0,0 +1,62 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { field, SmrtCollection, SmrtObject, smrt, } from '@happyvertical/smrt-core';
8
+ /**
9
+ * One version of the user app's definition (shell.db). Never deleted: an old
10
+ * version's migration is marked `purged` once its archives are cleaned up.
11
+ * Written only by `ShellVersionStore`; no generated surface.
12
+ */
13
+ let AppVersion = class AppVersion extends SmrtObject {
14
+ version = 0;
15
+ /** Parent version, `-1` for none (the first version). */
16
+ parent = -1;
17
+ author = '';
18
+ summary = '';
19
+ /** The whole definition, JSON text. */
20
+ definition = '';
21
+ /** `{ steps, purged? }` JSON text, or empty for a change with no migration. */
22
+ migration = '';
23
+ createdAt = '';
24
+ purged = false;
25
+ };
26
+ __decorate([
27
+ field({ type: 'integer', required: true })
28
+ ], AppVersion.prototype, "version", void 0);
29
+ __decorate([
30
+ field({ type: 'integer' })
31
+ ], AppVersion.prototype, "parent", void 0);
32
+ __decorate([
33
+ field({ type: 'text' })
34
+ ], AppVersion.prototype, "author", void 0);
35
+ __decorate([
36
+ field({ type: 'text' })
37
+ ], AppVersion.prototype, "summary", void 0);
38
+ __decorate([
39
+ field({ type: 'text' })
40
+ ], AppVersion.prototype, "definition", void 0);
41
+ __decorate([
42
+ field({ type: 'text' })
43
+ ], AppVersion.prototype, "migration", void 0);
44
+ __decorate([
45
+ field({ type: 'text' })
46
+ ], AppVersion.prototype, "createdAt", void 0);
47
+ __decorate([
48
+ field({ type: 'boolean' })
49
+ ], AppVersion.prototype, "purged", void 0);
50
+ AppVersion = __decorate([
51
+ smrt({
52
+ tableName: 'app_versions',
53
+ api: false,
54
+ mcp: false,
55
+ cli: false,
56
+ conflictColumns: ['id'],
57
+ })
58
+ ], AppVersion);
59
+ export { AppVersion };
60
+ export class AppVersionCollection extends SmrtCollection {
61
+ static _itemClass = AppVersion;
62
+ }
@@ -0,0 +1,39 @@
1
+ import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
2
+ import { type ApprovalOutcome } from '../server/approvals.ts';
3
+ export type ApprovalStatus = 'pending' | 'approved' | 'denied' | 'failed';
4
+ /**
5
+ * A risky change waiting for the owner. Created by the shell when a risky
6
+ * builder method, app tool or REST DELETE is attempted; applied only by
7
+ * {@link Approval.decide} (the one place the engine's `approved` flag is set).
8
+ */
9
+ export declare class Approval extends SmrtObject {
10
+ /** The action to run on approval, JSON (`ApprovalAction`). */
11
+ command: string;
12
+ /** Stable hash of the action; one pending row per identical action. */
13
+ actionKey: string;
14
+ summary: string;
15
+ /** What the change would do (counts, affected methods), JSON. */
16
+ preview: string;
17
+ status: ApprovalStatus;
18
+ requestedBy: string;
19
+ decidedBy: string;
20
+ decidedAt: string;
21
+ /** The result of applying it, or the failure, JSON. */
22
+ result: string;
23
+ createdAt: string;
24
+ /**
25
+ * Approve (apply the change) or deny it. Owner only. Approving a change
26
+ * that fails records the failure and leaves nothing half-applied.
27
+ */
28
+ decide(approve: boolean): Promise<ApprovalOutcome>;
29
+ /** The approvals waiting for the owner. */
30
+ static pending(): Promise<import("../server/approvals.ts").ApprovalView[]>;
31
+ }
32
+ /**
33
+ * Undecorated on purpose: the item class carries the whole surface (core
34
+ * applies the collection's config to the item class, so a decorated
35
+ * collection would have to repeat it exactly).
36
+ */
37
+ export declare class ApprovalCollection extends SmrtCollection<Approval> {
38
+ static readonly _itemClass: typeof Approval;
39
+ }
@@ -0,0 +1,101 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { field, SmrtCollection, SmrtObject, smrt, } from '@happyvertical/smrt-core';
8
+ import { decideApproval, listApprovalViews, } from "../server/approvals.js";
9
+ import { assertOwner } from "../server/owner.js";
10
+ // The decorator config must be a literal (the smrt() scanner reads it
11
+ // statically) and is repeated on the collection (core applies a collection's
12
+ // @smrt() config to its item class).
13
+ /**
14
+ * A risky change waiting for the owner. Created by the shell when a risky
15
+ * builder method, app tool or REST DELETE is attempted; applied only by
16
+ * {@link Approval.decide} (the one place the engine's `approved` flag is set).
17
+ */
18
+ let Approval = class Approval extends SmrtObject {
19
+ /** The action to run on approval, JSON (`ApprovalAction`). */
20
+ command = '';
21
+ /** Stable hash of the action; one pending row per identical action. */
22
+ actionKey = '';
23
+ summary = '';
24
+ /** What the change would do (counts, affected methods), JSON. */
25
+ preview = '';
26
+ status = 'pending';
27
+ requestedBy = '';
28
+ decidedBy = '';
29
+ decidedAt = '';
30
+ /** The result of applying it, or the failure, JSON. */
31
+ result = '';
32
+ createdAt = '';
33
+ /**
34
+ * Approve (apply the change) or deny it. Owner only. Approving a change
35
+ * that fails records the failure and leaves nothing half-applied.
36
+ */
37
+ async decide(approve) {
38
+ const owner = await assertOwner();
39
+ return decideApproval(this.id, approve === true, owner.id);
40
+ }
41
+ /** The approvals waiting for the owner. */
42
+ static async pending() {
43
+ await assertOwner();
44
+ return listApprovalViews({ status: 'pending' });
45
+ }
46
+ };
47
+ __decorate([
48
+ field({ type: 'text' })
49
+ ], Approval.prototype, "command", void 0);
50
+ __decorate([
51
+ field({ type: 'text' })
52
+ ], Approval.prototype, "actionKey", void 0);
53
+ __decorate([
54
+ field({ type: 'text' })
55
+ ], Approval.prototype, "summary", void 0);
56
+ __decorate([
57
+ field({ type: 'text' })
58
+ ], Approval.prototype, "preview", void 0);
59
+ __decorate([
60
+ field({ type: 'text' })
61
+ ], Approval.prototype, "status", void 0);
62
+ __decorate([
63
+ field({ type: 'text' })
64
+ ], Approval.prototype, "requestedBy", void 0);
65
+ __decorate([
66
+ field({ type: 'text' })
67
+ ], Approval.prototype, "decidedBy", void 0);
68
+ __decorate([
69
+ field({ type: 'text' })
70
+ ], Approval.prototype, "decidedAt", void 0);
71
+ __decorate([
72
+ field({ type: 'text' })
73
+ ], Approval.prototype, "result", void 0);
74
+ __decorate([
75
+ field({ type: 'text' })
76
+ ], Approval.prototype, "createdAt", void 0);
77
+ Approval = __decorate([
78
+ smrt({
79
+ tableName: 'approvals',
80
+ conflictColumns: ['id'],
81
+ // Only the owner decides. The generated list/get/create/update/delete are
82
+ // not exposed: the owner reads approvals through `pending` and
83
+ // /api/shell/approvals, and rows are written only by the approval service.
84
+ api: { include: ['decide', 'pending'] },
85
+ mcp: { include: ['decide', 'pending'] },
86
+ cli: false,
87
+ operationPermissions: {
88
+ decide: { action: 'update' },
89
+ pending: { action: 'read' },
90
+ },
91
+ })
92
+ ], Approval);
93
+ export { Approval };
94
+ /**
95
+ * Undecorated on purpose: the item class carries the whole surface (core
96
+ * applies the collection's config to the item class, so a decorated
97
+ * collection would have to repeat it exactly).
98
+ */
99
+ export class ApprovalCollection extends SmrtCollection {
100
+ static _itemClass = Approval;
101
+ }
@@ -0,0 +1,24 @@
1
+ import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
2
+ export type AssistantRole = 'user' | 'assistant' | 'tool';
3
+ /**
4
+ * One message of an assistant thread (shell.db): the owner's text, the
5
+ * model's reply (with the tool calls it asked for) or a tool result. Written
6
+ * only by the assistant's thread store; no generated surface.
7
+ */
8
+ export declare class AssistantMessage extends SmrtObject {
9
+ threadId: string;
10
+ /** Order within the thread, from 1. */
11
+ seq: number;
12
+ role: AssistantRole;
13
+ content: string;
14
+ /** Assistant messages: the tool calls the model asked for, JSON. */
15
+ toolCalls: string;
16
+ /** Tool messages: the call this answers. */
17
+ toolCallId: string;
18
+ /** Tool messages: `{ name, ok, summary, approvalId? }` JSON for the chips. */
19
+ meta: string;
20
+ createdAt: string;
21
+ }
22
+ export declare class AssistantMessageCollection extends SmrtCollection<AssistantMessage> {
23
+ static readonly _itemClass: typeof AssistantMessage;
24
+ }
@@ -0,0 +1,63 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { field, SmrtCollection, SmrtObject, smrt, } from '@happyvertical/smrt-core';
8
+ /**
9
+ * One message of an assistant thread (shell.db): the owner's text, the
10
+ * model's reply (with the tool calls it asked for) or a tool result. Written
11
+ * only by the assistant's thread store; no generated surface.
12
+ */
13
+ let AssistantMessage = class AssistantMessage extends SmrtObject {
14
+ threadId = '';
15
+ /** Order within the thread, from 1. */
16
+ seq = 0;
17
+ role = 'user';
18
+ content = '';
19
+ /** Assistant messages: the tool calls the model asked for, JSON. */
20
+ toolCalls = '';
21
+ /** Tool messages: the call this answers. */
22
+ toolCallId = '';
23
+ /** Tool messages: `{ name, ok, summary, approvalId? }` JSON for the chips. */
24
+ meta = '';
25
+ createdAt = '';
26
+ };
27
+ __decorate([
28
+ field({ type: 'text' })
29
+ ], AssistantMessage.prototype, "threadId", void 0);
30
+ __decorate([
31
+ field({ type: 'integer' })
32
+ ], AssistantMessage.prototype, "seq", void 0);
33
+ __decorate([
34
+ field({ type: 'text' })
35
+ ], AssistantMessage.prototype, "role", void 0);
36
+ __decorate([
37
+ field({ type: 'text' })
38
+ ], AssistantMessage.prototype, "content", void 0);
39
+ __decorate([
40
+ field({ type: 'text' })
41
+ ], AssistantMessage.prototype, "toolCalls", void 0);
42
+ __decorate([
43
+ field({ type: 'text' })
44
+ ], AssistantMessage.prototype, "toolCallId", void 0);
45
+ __decorate([
46
+ field({ type: 'text' })
47
+ ], AssistantMessage.prototype, "meta", void 0);
48
+ __decorate([
49
+ field({ type: 'text' })
50
+ ], AssistantMessage.prototype, "createdAt", void 0);
51
+ AssistantMessage = __decorate([
52
+ smrt({
53
+ tableName: 'assistant_messages',
54
+ api: false,
55
+ mcp: false,
56
+ cli: false,
57
+ conflictColumns: ['id'],
58
+ })
59
+ ], AssistantMessage);
60
+ export { AssistantMessage };
61
+ export class AssistantMessageCollection extends SmrtCollection {
62
+ static _itemClass = AssistantMessage;
63
+ }
@@ -0,0 +1,16 @@
1
+ import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
2
+ /**
3
+ * One assistant conversation (shell.db). Written only by the assistant's
4
+ * thread store (`$lib/server/assistant/threads`), owner scoped; no generated
5
+ * surface.
6
+ */
7
+ export declare class AssistantThread extends SmrtObject {
8
+ /** The owner's user id. */
9
+ ownerId: string;
10
+ title: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }
14
+ export declare class AssistantThreadCollection extends SmrtCollection<AssistantThread> {
15
+ static readonly _itemClass: typeof AssistantThread;
16
+ }