@segmentstream-cloud/ontology 0.15.0 → 0.16.0
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/README.md +39 -0
- package/dist/migrate/apply.js +2 -0
- package/dist/migrate/plan.js +14 -4
- package/dist/runtime/service-binding.js +3 -0
- package/dist/service/agent/attachments.d.ts +37 -0
- package/dist/service/agent/attachments.js +225 -0
- package/dist/service/mcp/server.js +26 -3
- package/dist/service/mcp/tools.d.ts +6 -0
- package/dist/service/mcp/tools.js +33 -1
- package/dist/service/runtime-contract.d.ts +3 -0
- package/dist/service/service.js +11 -1
- package/dist/storage/attachments.d.ts +117 -0
- package/dist/storage/attachments.js +536 -0
- package/dist/storage/maintenance.d.ts +4 -1
- package/dist/storage/maintenance.js +7 -2
- package/dist/storage/neon.js +14 -0
- package/dist/storage/provider.d.ts +2 -0
- package/dist/storage/tables.d.ts +8 -0
- package/dist/storage/tables.js +32 -0
- package/package.json +1 -1
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
|
-
|
|
3
|
+
import { maintainAttachments } from "./attachments.js";
|
|
4
|
+
/**
|
|
5
|
+
* A scheduler-owned capability: lifecycle operations only, with persisted deletion fencing. The
|
|
6
|
+
* agent's attachments expire first, so that their files are removed in the same run.
|
|
7
|
+
*/
|
|
4
8
|
export function maintainBlobStorage(sql, provider, limit = 100) {
|
|
5
9
|
return Effect.gen(function* () {
|
|
6
|
-
|
|
10
|
+
const attachments = yield* maintainAttachments(sql, provider, limit);
|
|
11
|
+
let removed = attachments.removed;
|
|
7
12
|
for (let count = 0; count < limit; count += 1) {
|
|
8
13
|
const claim = randomUUID();
|
|
9
14
|
const candidate = yield* sql.withTransaction(Effect.gen(function* () {
|
package/dist/storage/neon.js
CHANGED
|
@@ -175,6 +175,20 @@ export function neonBlobProvider(binding) {
|
|
|
175
175
|
}
|
|
176
176
|
return response.Body.transformToByteArray();
|
|
177
177
|
}),
|
|
178
|
+
read: (key, maxBytes) => attempt("blob.read", async () => {
|
|
179
|
+
const response = await client.send(new GetObjectCommand(object(key)));
|
|
180
|
+
if (!response.Body) {
|
|
181
|
+
throw new Error("Neon returned no object body.");
|
|
182
|
+
}
|
|
183
|
+
if (response.ContentLength !== undefined && response.ContentLength > maxBytes) {
|
|
184
|
+
throw new Error("The stored object exceeds the size it may have.");
|
|
185
|
+
}
|
|
186
|
+
const bytes = await response.Body.transformToByteArray();
|
|
187
|
+
if (bytes.byteLength > maxBytes) {
|
|
188
|
+
throw new Error("The stored object exceeds the size it may have.");
|
|
189
|
+
}
|
|
190
|
+
return bytes;
|
|
191
|
+
}),
|
|
178
192
|
download: ({ key, filename, contentType, inline }) => attempt("blob.download", async () => {
|
|
179
193
|
await client.send(new HeadObjectCommand(object(key)));
|
|
180
194
|
const signedAt = signingDate();
|
|
@@ -61,6 +61,8 @@ declare const BlobProvider_base: Context.ServiceClass<BlobProvider, "@segmentstr
|
|
|
61
61
|
}) => Effect.Effect<void, BlobStorageError>;
|
|
62
62
|
readonly inspect: (key: string) => Effect.Effect<StoredObject | undefined, BlobStorageError>;
|
|
63
63
|
readonly readPrefix: (key: string) => Effect.Effect<Uint8Array, BlobStorageError>;
|
|
64
|
+
/** The whole object, at most `maxBytes`; for verifying an agent attachment's digest. */
|
|
65
|
+
readonly read: (key: string, maxBytes: number) => Effect.Effect<Uint8Array, BlobStorageError>;
|
|
64
66
|
readonly download: (input: {
|
|
65
67
|
key: string;
|
|
66
68
|
filename: string;
|
package/dist/storage/tables.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
/** Storage metadata lives in the ontology database and is migrated by its SDK. */
|
|
2
2
|
export declare const BLOB_TABLES_DDL: ReadonlyArray<string>;
|
|
3
|
+
/** The agent's temporary attachments, beside the blob tables whose storage they share. */
|
|
4
|
+
export declare const ATTACHMENTS_TABLE = "_agent_attachments";
|
|
5
|
+
/**
|
|
6
|
+
* A file a member sent the app's agent: platform metadata, never an ontology record. The bytes are
|
|
7
|
+
* a `_blobs` revision in the same storage as uploads; the row binds them to their owner, the chat
|
|
8
|
+
* and the agent session that received them, and expires 24 hours after receipt unless promoted.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ATTACHMENT_TABLES_DDL: ReadonlyArray<string>;
|
package/dist/storage/tables.js
CHANGED
|
@@ -53,3 +53,35 @@ export const BLOB_TABLES_DDL = [
|
|
|
53
53
|
PRIMARY KEY ("principal_id", "key")
|
|
54
54
|
)`,
|
|
55
55
|
];
|
|
56
|
+
/** The agent's temporary attachments, beside the blob tables whose storage they share. */
|
|
57
|
+
export const ATTACHMENTS_TABLE = "_agent_attachments";
|
|
58
|
+
/**
|
|
59
|
+
* A file a member sent the app's agent: platform metadata, never an ontology record. The bytes are
|
|
60
|
+
* a `_blobs` revision in the same storage as uploads; the row binds them to their owner, the chat
|
|
61
|
+
* and the agent session that received them, and expires 24 hours after receipt unless promoted.
|
|
62
|
+
*/
|
|
63
|
+
export const ATTACHMENT_TABLES_DDL = [
|
|
64
|
+
`CREATE TABLE IF NOT EXISTS "${ATTACHMENTS_TABLE}" (
|
|
65
|
+
"id" uuid PRIMARY KEY,
|
|
66
|
+
"blob_id" uuid NOT NULL UNIQUE REFERENCES "_blobs" ("id"),
|
|
67
|
+
"branch_id" text NOT NULL,
|
|
68
|
+
"owner_id" uuid NOT NULL REFERENCES "user" ("id"),
|
|
69
|
+
"conversation" text NOT NULL,
|
|
70
|
+
"session_id" text,
|
|
71
|
+
"source" text NOT NULL CHECK ("source" IN ('telegram')),
|
|
72
|
+
"source_ref" text NOT NULL,
|
|
73
|
+
"filename" text NOT NULL,
|
|
74
|
+
"content_type" text NOT NULL,
|
|
75
|
+
"size" bigint NOT NULL CHECK ("size" > 0),
|
|
76
|
+
"sha256" text NOT NULL CHECK ("sha256" ~ '^[0-9a-f]{64}$'),
|
|
77
|
+
"state" text NOT NULL CHECK ("state" IN ('received', 'ready', 'promoted', 'discarded', 'expired')),
|
|
78
|
+
"provider_upload_id" text,
|
|
79
|
+
"promotion" jsonb,
|
|
80
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
81
|
+
"expires_at" timestamptz NOT NULL DEFAULT now() + interval '24 hours',
|
|
82
|
+
"removed_at" timestamptz,
|
|
83
|
+
UNIQUE ("owner_id", "conversation", "source_ref")
|
|
84
|
+
)`,
|
|
85
|
+
`CREATE INDEX IF NOT EXISTS "${ATTACHMENTS_TABLE}_expiry_idx" ON "${ATTACHMENTS_TABLE}" ("state", "expires_at")`,
|
|
86
|
+
`CREATE INDEX IF NOT EXISTS "${ATTACHMENTS_TABLE}_sha256_idx" ON "${ATTACHMENTS_TABLE}" ("sha256")`,
|
|
87
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@segmentstream-cloud/ontology",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Define a SegmentStream workspace app's ontology: entities, relationships, roles and actions, written with Effect.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "SegmentStream",
|