@intelligo-dev/core 1.0.0-beta.1 → 1.0.0-beta.13
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/NOTICE +6 -0
- package/README.md +102 -0
- package/dist/attachments/errors.d.ts +7 -0
- package/dist/attachments/errors.d.ts.map +1 -0
- package/dist/attachments/errors.js +11 -0
- package/dist/attachments/errors.js.map +1 -0
- package/dist/attachments/index.d.ts +8 -0
- package/dist/attachments/index.d.ts.map +1 -0
- package/dist/attachments/index.js +7 -0
- package/dist/attachments/index.js.map +1 -0
- package/dist/attachments/service.d.ts +45 -0
- package/dist/attachments/service.d.ts.map +1 -0
- package/dist/attachments/service.js +100 -0
- package/dist/attachments/service.js.map +1 -0
- package/dist/attachments/types.d.ts +6 -0
- package/dist/attachments/types.d.ts.map +1 -0
- package/dist/attachments/types.js +2 -0
- package/dist/attachments/types.js.map +1 -0
- package/dist/conversations/errors.d.ts +2 -8
- package/dist/conversations/errors.d.ts.map +1 -1
- package/dist/conversations/errors.js +2 -8
- package/dist/conversations/errors.js.map +1 -1
- package/dist/conversations/index.d.ts +4 -12
- package/dist/conversations/index.d.ts.map +1 -1
- package/dist/conversations/index.js +2 -11
- package/dist/conversations/index.js.map +1 -1
- package/dist/conversations/service.d.ts +49 -61
- package/dist/conversations/service.d.ts.map +1 -1
- package/dist/conversations/service.js +110 -83
- package/dist/conversations/service.js.map +1 -1
- package/dist/conversations/types.d.ts +1 -4
- package/dist/conversations/types.d.ts.map +1 -1
- package/dist/conversations/types.js +0 -3
- package/dist/conversations/types.js.map +1 -1
- package/dist/db/client.d.ts +21 -10
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +43 -18
- package/dist/db/client.js.map +1 -1
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +3 -7
- package/dist/db/index.js.map +1 -1
- package/dist/db/schema/agents.d.ts +14 -51
- package/dist/db/schema/agents.d.ts.map +1 -1
- package/dist/db/schema/agents.js +9 -21
- package/dist/db/schema/agents.js.map +1 -1
- package/dist/db/schema/ai.d.ts +86 -1556
- package/dist/db/schema/ai.d.ts.map +1 -1
- package/dist/db/schema/ai.js +32 -236
- package/dist/db/schema/ai.js.map +1 -1
- package/dist/db/schema/auth.d.ts +5 -34
- package/dist/db/schema/auth.d.ts.map +1 -1
- package/dist/db/schema/auth.js +25 -56
- package/dist/db/schema/auth.js.map +1 -1
- package/dist/db/schema/billing.d.ts +136 -107
- package/dist/db/schema/billing.d.ts.map +1 -1
- package/dist/db/schema/billing.js +72 -60
- package/dist/db/schema/billing.js.map +1 -1
- package/dist/db/schema/feature-flags.d.ts +3 -12
- package/dist/db/schema/feature-flags.d.ts.map +1 -1
- package/dist/db/schema/feature-flags.js +3 -12
- package/dist/db/schema/feature-flags.js.map +1 -1
- package/dist/db/schema/identity.d.ts +12 -274
- package/dist/db/schema/identity.d.ts.map +1 -1
- package/dist/db/schema/identity.js +19 -104
- package/dist/db/schema/identity.js.map +1 -1
- package/dist/db/schema/index.d.ts +8 -15
- package/dist/db/schema/index.d.ts.map +1 -1
- package/dist/db/schema/index.js +12 -42
- package/dist/db/schema/index.js.map +1 -1
- package/dist/db/schema/notifications.d.ts +3 -17
- package/dist/db/schema/notifications.d.ts.map +1 -1
- package/dist/db/schema/notifications.js +3 -17
- package/dist/db/schema/notifications.js.map +1 -1
- package/dist/db/schema/usage.d.ts +94 -77
- package/dist/db/schema/usage.d.ts.map +1 -1
- package/dist/db/schema/usage.js +59 -89
- package/dist/db/schema/usage.js.map +1 -1
- package/dist/db/validate.d.ts +2 -11
- package/dist/db/validate.d.ts.map +1 -1
- package/dist/db/validate.js +6 -17
- package/dist/db/validate.js.map +1 -1
- package/dist/db/workspace-queries.d.ts +5 -29
- package/dist/db/workspace-queries.d.ts.map +1 -1
- package/dist/db/workspace-queries.js +5 -29
- package/dist/db/workspace-queries.js.map +1 -1
- package/dist/documents/classifier.d.ts +5 -12
- package/dist/documents/classifier.d.ts.map +1 -1
- package/dist/documents/classifier.js +16 -16
- package/dist/documents/classifier.js.map +1 -1
- package/dist/documents/errors.d.ts +2 -10
- package/dist/documents/errors.d.ts.map +1 -1
- package/dist/documents/errors.js +2 -10
- package/dist/documents/errors.js.map +1 -1
- package/dist/documents/index.d.ts +4 -13
- package/dist/documents/index.d.ts.map +1 -1
- package/dist/documents/index.js +3 -12
- package/dist/documents/index.js.map +1 -1
- package/dist/documents/service.d.ts +19 -26
- package/dist/documents/service.d.ts.map +1 -1
- package/dist/documents/service.js +44 -38
- package/dist/documents/service.js.map +1 -1
- package/dist/documents/types.d.ts +6 -10
- package/dist/documents/types.d.ts.map +1 -1
- package/dist/documents/types.js +0 -3
- package/dist/documents/types.js.map +1 -1
- package/dist/email/brand.d.ts +17 -0
- package/dist/email/brand.d.ts.map +1 -0
- package/dist/email/brand.js +9 -0
- package/dist/email/brand.js.map +1 -0
- package/dist/email/index.d.ts +4 -4
- package/dist/email/index.js +4 -4
- package/dist/email/provider.d.ts +1 -7
- package/dist/email/provider.d.ts.map +1 -1
- package/dist/email/provider.js +10 -19
- package/dist/email/provider.js.map +1 -1
- package/dist/email/send.d.ts +12 -12
- package/dist/email/send.d.ts.map +1 -1
- package/dist/email/send.js +5 -19
- package/dist/email/send.js.map +1 -1
- package/dist/email/senders.d.ts +17 -30
- package/dist/email/senders.d.ts.map +1 -1
- package/dist/email/senders.js +33 -47
- package/dist/email/senders.js.map +1 -1
- package/dist/email/templates/base-layout.d.ts +1 -1
- package/dist/email/templates/base-layout.d.ts.map +1 -1
- package/dist/email/templates/base-layout.js +4 -6
- package/dist/email/templates/base-layout.js.map +1 -1
- package/dist/email/templates/index.d.ts +10 -10
- package/dist/email/templates/index.d.ts.map +1 -1
- package/dist/email/templates/index.js +10 -16
- package/dist/email/templates/index.js.map +1 -1
- package/dist/email/templates/password-reset.d.ts +2 -2
- package/dist/email/templates/password-reset.d.ts.map +1 -1
- package/dist/email/templates/password-reset.js +10 -22
- package/dist/email/templates/password-reset.js.map +1 -1
- package/dist/email/templates/payment-failed.d.ts +2 -2
- package/dist/email/templates/payment-failed.d.ts.map +1 -1
- package/dist/email/templates/payment-failed.js +11 -24
- package/dist/email/templates/payment-failed.js.map +1 -1
- package/dist/email/templates/quota-warning.d.ts +4 -4
- package/dist/email/templates/quota-warning.d.ts.map +1 -1
- package/dist/email/templates/quota-warning.js +19 -39
- package/dist/email/templates/quota-warning.js.map +1 -1
- package/dist/email/templates/subscription-confirmed.d.ts +2 -2
- package/dist/email/templates/subscription-confirmed.d.ts.map +1 -1
- package/dist/email/templates/subscription-confirmed.js +13 -28
- package/dist/email/templates/subscription-confirmed.js.map +1 -1
- package/dist/email/templates/trial-expiry.d.ts +2 -2
- package/dist/email/templates/trial-expiry.d.ts.map +1 -1
- package/dist/email/templates/trial-expiry.js +12 -36
- package/dist/email/templates/trial-expiry.js.map +1 -1
- package/dist/email/templates/trial-warning.d.ts +2 -2
- package/dist/email/templates/trial-warning.d.ts.map +1 -1
- package/dist/email/templates/trial-warning.js +15 -32
- package/dist/email/templates/trial-warning.js.map +1 -1
- package/dist/email/templates/verify-email.d.ts +2 -2
- package/dist/email/templates/verify-email.d.ts.map +1 -1
- package/dist/email/templates/verify-email.js +10 -22
- package/dist/email/templates/verify-email.js.map +1 -1
- package/dist/email/templates/welcome.d.ts +2 -2
- package/dist/email/templates/welcome.d.ts.map +1 -1
- package/dist/email/templates/welcome.js +13 -20
- package/dist/email/templates/welcome.js.map +1 -1
- package/dist/email/templates/workspace-invitation.d.ts +2 -2
- package/dist/email/templates/workspace-invitation.d.ts.map +1 -1
- package/dist/email/templates/workspace-invitation.js +12 -26
- package/dist/email/templates/workspace-invitation.js.map +1 -1
- package/dist/env.d.ts +5 -10
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +41 -31
- package/dist/env.js.map +1 -1
- package/dist/identity/audit.d.ts +11 -24
- package/dist/identity/audit.d.ts.map +1 -1
- package/dist/identity/audit.js +13 -27
- package/dist/identity/audit.js.map +1 -1
- package/dist/identity/errors.d.ts +4 -12
- package/dist/identity/errors.d.ts.map +1 -1
- package/dist/identity/errors.js +2 -8
- package/dist/identity/errors.js.map +1 -1
- package/dist/identity/index.d.ts +5 -13
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +4 -12
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/service.d.ts +13 -47
- package/dist/identity/service.d.ts.map +1 -1
- package/dist/identity/service.js +31 -78
- package/dist/identity/service.js.map +1 -1
- package/dist/identity/types.d.ts +1 -4
- package/dist/identity/types.d.ts.map +1 -1
- package/dist/identity/types.js +0 -3
- package/dist/identity/types.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -10
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -18
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +45 -49
- package/dist/logger.js.map +1 -1
- package/dist/money.d.ts +95 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/money.js +208 -0
- package/dist/money.js.map +1 -0
- package/dist/notifications/index.d.ts +9 -43
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +9 -49
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/triggers.d.ts +9 -32
- package/dist/notifications/triggers.d.ts.map +1 -1
- package/dist/notifications/triggers.js +21 -58
- package/dist/notifications/triggers.js.map +1 -1
- package/dist/notifications/types.d.ts +1 -10
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/notifications/types.js +0 -9
- package/dist/notifications/types.js.map +1 -1
- package/dist/prompt.d.ts +38 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +118 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +32 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +60 -0
- package/dist/registry.js.map +1 -0
- package/dist/request-context.d.ts +49 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +100 -0
- package/dist/request-context.js.map +1 -0
- package/dist/storage/index.d.ts +65 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +109 -0
- package/dist/storage/index.js.map +1 -0
- package/package.json +74 -24
- package/src/attachments/errors.ts +18 -0
- package/src/attachments/index.ts +22 -0
- package/src/attachments/service.ts +178 -0
- package/src/attachments/types.ts +6 -0
- package/src/conversations/errors.ts +45 -0
- package/src/conversations/index.ts +39 -0
- package/src/conversations/service.ts +594 -0
- package/src/conversations/types.ts +15 -0
- package/src/db/client.ts +91 -0
- package/src/db/index.ts +3 -0
- package/src/db/migrations/0000_baseline.sql +652 -0
- package/src/db/migrations/0001_reconcile_chain_built_databases.sql +53 -0
- package/src/db/migrations/0002_webhook_claim_lease.sql +1 -0
- package/src/db/migrations/README.md +74 -36
- package/src/db/migrations/legacy-chain.json +197 -0
- package/src/db/migrations/meta/0000_snapshot.json +4182 -157
- package/src/db/migrations/meta/0002_snapshot.json +2478 -368
- package/src/db/migrations/meta/_journal.json +6 -279
- package/src/db/schema/agents.ts +57 -0
- package/src/db/schema/ai.ts +174 -0
- package/src/db/schema/auth.ts +183 -0
- package/src/db/schema/billing.ts +209 -0
- package/src/db/schema/feature-flags.ts +20 -0
- package/src/db/schema/identity.ts +250 -0
- package/src/db/schema/index.ts +12 -0
- package/src/db/schema/notifications.ts +31 -0
- package/src/db/schema/usage.ts +269 -0
- package/src/db/validate.ts +63 -0
- package/src/db/workspace-queries.ts +64 -0
- package/src/documents/classifier.ts +61 -0
- package/src/documents/errors.ts +44 -0
- package/src/documents/index.ts +24 -0
- package/src/documents/service.ts +256 -0
- package/src/documents/types.ts +24 -0
- package/src/email/brand.ts +24 -0
- package/src/email/index.ts +19 -0
- package/src/email/provider.ts +278 -0
- package/src/email/send.ts +169 -0
- package/src/email/senders.ts +292 -0
- package/src/email/templates/base-layout.tsx +145 -0
- package/src/email/templates/index.ts +28 -0
- package/src/email/templates/password-reset.tsx +72 -0
- package/src/email/templates/payment-failed.tsx +77 -0
- package/src/email/templates/quota-warning.tsx +118 -0
- package/src/email/templates/subscription-confirmed.tsx +91 -0
- package/src/email/templates/trial-expiry.tsx +124 -0
- package/src/email/templates/trial-warning.tsx +104 -0
- package/src/email/templates/verify-email.tsx +72 -0
- package/src/email/templates/welcome.tsx +64 -0
- package/src/email/templates/workspace-invitation.tsx +105 -0
- package/src/env.ts +180 -0
- package/src/identity/audit.ts +65 -0
- package/src/identity/errors.ts +44 -0
- package/src/identity/index.ts +26 -0
- package/src/identity/service.ts +202 -0
- package/src/identity/types.ts +28 -0
- package/src/index.ts +4 -0
- package/src/logger.ts +198 -0
- package/src/money.ts +270 -0
- package/src/notifications/index.ts +108 -0
- package/src/notifications/triggers.ts +158 -0
- package/src/notifications/types.ts +18 -0
- package/src/prompt.ts +142 -0
- package/src/registry.ts +75 -0
- package/src/request-context.ts +137 -0
- package/src/storage/index.ts +153 -0
- package/dist/db/schema/rag.d.ts +0 -171
- package/dist/db/schema/rag.d.ts.map +0 -1
- package/dist/db/schema/rag.js +0 -42
- package/dist/db/schema/rag.js.map +0 -1
- package/src/db/migrations/0000_sharp_night_nurse.sql +0 -52
- package/src/db/migrations/0001_hesitant_vapor.sql +0 -40
- package/src/db/migrations/0002_numerous_lady_vermin.sql +0 -235
- package/src/db/migrations/0003_mighty_jean_grey.sql +0 -37
- package/src/db/migrations/0004_cynical_grandmaster.sql +0 -2
- package/src/db/migrations/0005_careful_switch.sql +0 -8
- package/src/db/migrations/0006_tense_blue_marvel.sql +0 -16
- package/src/db/migrations/0007_next_squadron_sinister.sql +0 -1
- package/src/db/migrations/0008_powerful_scream.sql +0 -39
- package/src/db/migrations/0009_sad_ink.sql +0 -1
- package/src/db/migrations/0010_shocking_omega_flight.sql +0 -2
- package/src/db/migrations/0011_ambiguous_otto_octavius.sql +0 -151
- package/src/db/migrations/0011_hnsw_vector_index.sql +0 -17
- package/src/db/migrations/0012_user_profiles.sql +0 -30
- package/src/db/migrations/0013_trending_seasonal_columns.sql +0 -9
- package/src/db/migrations/0014_add_product_type_to_agents.sql +0 -6
- package/src/db/migrations/0015_new_v1_tables.sql +0 -149
- package/src/db/migrations/0016_document_types.sql +0 -30
- package/src/db/migrations/0017_document_metadata.sql +0 -2
- package/src/db/migrations/0018_identity_graph.sql +0 -200
- package/src/db/migrations/0019_db_driven_prompts.sql +0 -20
- package/src/db/migrations/0020_pending_extractions.sql +0 -35
- package/src/db/migrations/0021_rag_documents.sql +0 -39
- package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +0 -70
- package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +0 -17
- package/src/db/migrations/0024_user_memories_hnsw.sql +0 -23
- package/src/db/migrations/0025_audit_trigger_errcode.sql +0 -21
- package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +0 -17
- package/src/db/migrations/0027_billing_settings_mnt_columns.sql +0 -54
- package/src/db/migrations/0028_trial_credits_normalized_email.sql +0 -37
- package/src/db/migrations/0029_usage_records_conversation_idx.sql +0 -13
- package/src/db/migrations/0030_pending_extractions_composite_idx.sql +0 -11
- package/src/db/migrations/0031_rag_documents_hnsw.sql +0 -16
- package/src/db/migrations/0032_rate_limit_unique_idx.sql +0 -16
- package/src/db/migrations/0033_pending_extractions_partial_idx.sql +0 -18
- package/src/db/migrations/0034_rate_limit_count.sql +0 -9
- package/src/db/migrations/0035_credit_reservations.sql +0 -24
- package/src/db/migrations/0036_executions_audit_jobs.sql +0 -96
- package/src/db/migrations/0037_rate_limit_minute_bucket.sql +0 -46
- package/src/db/migrations/0038_user_quotas_generic_usage.sql +0 -25
- package/src/db/migrations/0039_platform_admin_impersonation.sql +0 -27
- package/src/db/migrations/0040_ee_audit_chain.sql +0 -23
- package/src/db/migrations/meta/0001_snapshot.json +0 -631
- package/src/db/migrations/meta/0003_snapshot.json +0 -2488
- package/src/db/migrations/meta/0004_snapshot.json +0 -2500
- package/src/db/migrations/meta/0005_snapshot.json +0 -2548
- package/src/db/migrations/meta/0006_snapshot.json +0 -2650
- package/src/db/migrations/meta/0007_snapshot.json +0 -2657
- package/src/db/migrations/meta/0008_snapshot.json +0 -2719
- package/src/db/migrations/meta/0009_snapshot.json +0 -2726
- package/src/db/migrations/meta/0010_snapshot.json +0 -2739
- package/src/db/migrations/meta/0011_snapshot.json +0 -3886
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where files live. The framework stores attachment rows and hands out URLs;
|
|
3
|
+
* the application binds one adapter (S3, R2, Vercel Blob, disk) from its
|
|
4
|
+
* composition root:
|
|
5
|
+
*
|
|
6
|
+
* import { setStorageAdapter } from "@intelligo-dev/core/storage";
|
|
7
|
+
* setStorageAdapter(createS3Storage({ bucket, region })); // the app's lib/storage.ts
|
|
8
|
+
*
|
|
9
|
+
* An unbound adapter throws where a file is needed. Keys carry the tenant —
|
|
10
|
+
* `ws/<workspaceId>/att/<id>` — so a signed URL for one workspace's file can
|
|
11
|
+
* never be minted from another's row.
|
|
12
|
+
*/
|
|
13
|
+
import { createRegistryRef } from "../registry.js";
|
|
14
|
+
export class StorageUnavailableError extends Error {
|
|
15
|
+
constructor() {
|
|
16
|
+
super("No storage adapter is bound. Call setStorageAdapter() from your " +
|
|
17
|
+
"composition root with your bucket's adapter (S3, R2, Blob), or " +
|
|
18
|
+
"createMemoryStorage() for tests.");
|
|
19
|
+
this.code = "storage_unavailable";
|
|
20
|
+
this.name = "StorageUnavailableError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const adapter = createRegistryRef("core/storage-adapter", undefined);
|
|
24
|
+
export function setStorageAdapter(next) {
|
|
25
|
+
adapter.set(next);
|
|
26
|
+
}
|
|
27
|
+
/** Forget the bound adapter. For tests composing a fresh root. */
|
|
28
|
+
export function clearStorageAdapter() {
|
|
29
|
+
adapter.set(undefined);
|
|
30
|
+
}
|
|
31
|
+
export function hasStorageAdapter() {
|
|
32
|
+
return adapter.get() !== undefined;
|
|
33
|
+
}
|
|
34
|
+
/** @throws {StorageUnavailableError} when nothing is bound. */
|
|
35
|
+
export function getStorageAdapter() {
|
|
36
|
+
const bound = adapter.get();
|
|
37
|
+
if (!bound)
|
|
38
|
+
throw new StorageUnavailableError();
|
|
39
|
+
return bound;
|
|
40
|
+
}
|
|
41
|
+
/** The key a chat attachment is stored under. */
|
|
42
|
+
export function attachmentStorageKey(workspaceId, id) {
|
|
43
|
+
return `ws/${workspaceId}/att/${id}`;
|
|
44
|
+
}
|
|
45
|
+
async function toBytes(body) {
|
|
46
|
+
if (body instanceof Uint8Array)
|
|
47
|
+
return body;
|
|
48
|
+
if (body instanceof Blob)
|
|
49
|
+
return new Uint8Array(await body.arrayBuffer());
|
|
50
|
+
const chunks = [];
|
|
51
|
+
const reader = body.getReader();
|
|
52
|
+
for (;;) {
|
|
53
|
+
const { done, value } = await reader.read();
|
|
54
|
+
if (done)
|
|
55
|
+
break;
|
|
56
|
+
chunks.push(value);
|
|
57
|
+
}
|
|
58
|
+
const size = chunks.reduce((n, c) => n + c.byteLength, 0);
|
|
59
|
+
const out = new Uint8Array(size);
|
|
60
|
+
let offset = 0;
|
|
61
|
+
for (const chunk of chunks) {
|
|
62
|
+
out.set(chunk, offset);
|
|
63
|
+
offset += chunk.byteLength;
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
function toBase64(bytes) {
|
|
68
|
+
if (typeof Buffer !== "undefined")
|
|
69
|
+
return Buffer.from(bytes).toString("base64");
|
|
70
|
+
let binary = "";
|
|
71
|
+
for (const byte of bytes)
|
|
72
|
+
binary += String.fromCharCode(byte);
|
|
73
|
+
return btoa(binary);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Files in memory, "signed" as data URLs, for tests and apps without a
|
|
77
|
+
* bucket. Nothing survives a restart.
|
|
78
|
+
*/
|
|
79
|
+
export function createMemoryStorage() {
|
|
80
|
+
const objects = new Map();
|
|
81
|
+
return {
|
|
82
|
+
objects,
|
|
83
|
+
async put({ key, body, contentType }) {
|
|
84
|
+
const bytes = await toBytes(body);
|
|
85
|
+
objects.set(key, { bytes, contentType });
|
|
86
|
+
return { key, contentType, size: bytes.byteLength };
|
|
87
|
+
},
|
|
88
|
+
async getSignedUrl(key) {
|
|
89
|
+
const object = objects.get(key);
|
|
90
|
+
if (!object)
|
|
91
|
+
throw new Error(`No object at ${key}`);
|
|
92
|
+
return `data:${object.contentType};base64,${toBase64(object.bytes)}`;
|
|
93
|
+
},
|
|
94
|
+
async get(key) {
|
|
95
|
+
const object = objects.get(key);
|
|
96
|
+
if (!object)
|
|
97
|
+
throw new Error(`No object at ${key}`);
|
|
98
|
+
return {
|
|
99
|
+
body: new Blob([object.bytes]).stream(),
|
|
100
|
+
contentType: object.contentType,
|
|
101
|
+
size: object.bytes.byteLength,
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
async delete(key) {
|
|
105
|
+
objects.delete(key);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intelligo-dev/core",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.13",
|
|
4
|
+
"description": "Database schema, email, logging, notifications, and the conversation, document and identity contracts.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"intelligo",
|
|
7
|
+
"ai-saas",
|
|
8
|
+
"saas",
|
|
9
|
+
"typescript",
|
|
10
|
+
"drizzle",
|
|
11
|
+
"postgres",
|
|
12
|
+
"pgvector",
|
|
13
|
+
"conversations",
|
|
14
|
+
"documents"
|
|
15
|
+
],
|
|
4
16
|
"license": "Apache-2.0",
|
|
17
|
+
"author": "Turtuvshin Byambaa <toroo.byamba@gmail.com>",
|
|
5
18
|
"repository": {
|
|
6
19
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/intelligo-
|
|
20
|
+
"url": "git+https://github.com/intelligo-dev/intelligo.git",
|
|
8
21
|
"directory": "packages/core"
|
|
9
22
|
},
|
|
10
|
-
"homepage": "https://
|
|
23
|
+
"homepage": "https://intelligo.dev/docs/packages/core",
|
|
11
24
|
"bugs": {
|
|
12
|
-
"url": "https://github.com/intelligo-
|
|
25
|
+
"url": "https://github.com/intelligo-dev/intelligo/issues"
|
|
13
26
|
},
|
|
14
27
|
"type": "module",
|
|
15
28
|
"exports": {
|
|
@@ -45,10 +58,34 @@
|
|
|
45
58
|
"types": "./dist/identity/index.d.ts",
|
|
46
59
|
"default": "./dist/identity/index.js"
|
|
47
60
|
},
|
|
61
|
+
"./attachments": {
|
|
62
|
+
"types": "./dist/attachments/index.d.ts",
|
|
63
|
+
"default": "./dist/attachments/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./storage": {
|
|
66
|
+
"types": "./dist/storage/index.d.ts",
|
|
67
|
+
"default": "./dist/storage/index.js"
|
|
68
|
+
},
|
|
48
69
|
"./env": {
|
|
49
70
|
"types": "./dist/env.d.ts",
|
|
50
71
|
"default": "./dist/env.js"
|
|
51
72
|
},
|
|
73
|
+
"./registry": {
|
|
74
|
+
"types": "./dist/registry.d.ts",
|
|
75
|
+
"default": "./dist/registry.js"
|
|
76
|
+
},
|
|
77
|
+
"./money": {
|
|
78
|
+
"types": "./dist/money.d.ts",
|
|
79
|
+
"default": "./dist/money.js"
|
|
80
|
+
},
|
|
81
|
+
"./request-context": {
|
|
82
|
+
"types": "./dist/request-context.d.ts",
|
|
83
|
+
"default": "./dist/request-context.js"
|
|
84
|
+
},
|
|
85
|
+
"./prompt": {
|
|
86
|
+
"types": "./dist/prompt.d.ts",
|
|
87
|
+
"default": "./dist/prompt.js"
|
|
88
|
+
},
|
|
52
89
|
"./logger": {
|
|
53
90
|
"types": "./dist/logger.d.ts",
|
|
54
91
|
"import": "./dist/logger.js",
|
|
@@ -56,38 +93,51 @@
|
|
|
56
93
|
}
|
|
57
94
|
},
|
|
58
95
|
"dependencies": {
|
|
59
|
-
"@neondatabase/serverless": "^
|
|
60
|
-
"@react-email/components": "^1.0.
|
|
61
|
-
"dotenv": "^
|
|
62
|
-
"
|
|
63
|
-
"pg": "^8.18.0",
|
|
96
|
+
"@neondatabase/serverless": "^1.1.0",
|
|
97
|
+
"@react-email/components": "^1.0.12",
|
|
98
|
+
"dotenv": "^17.4.2",
|
|
99
|
+
"pg": "8.18.0",
|
|
64
100
|
"pino": "^10.3.1",
|
|
65
|
-
"
|
|
66
|
-
"resend": "^6.9.1",
|
|
67
|
-
"server-only": "^0.0.1",
|
|
68
|
-
"zod": "^3.24.1"
|
|
101
|
+
"resend": "^6.28.1"
|
|
69
102
|
},
|
|
70
103
|
"peerDependencies": {
|
|
71
|
-
"
|
|
104
|
+
"drizzle-orm": "^0.45.1",
|
|
105
|
+
"react": "^19.0.0"
|
|
106
|
+
},
|
|
107
|
+
"peerDependenciesMeta": {
|
|
108
|
+
"react": {
|
|
109
|
+
"optional": true
|
|
110
|
+
}
|
|
72
111
|
},
|
|
73
112
|
"devDependencies": {
|
|
74
|
-
"@types/
|
|
75
|
-
"@types/
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"next": "^16.0.7",
|
|
113
|
+
"@types/pg": "^8.23.1",
|
|
114
|
+
"@types/react": "19.2.18",
|
|
115
|
+
"drizzle-kit": "^0.31.10",
|
|
116
|
+
"drizzle-orm": "^0.45.2",
|
|
117
|
+
"next": "~16.3.5",
|
|
80
118
|
"pino-pretty": "^13.1.3",
|
|
81
|
-
"
|
|
82
|
-
"
|
|
119
|
+
"react": "^19.3.0",
|
|
120
|
+
"tsx": "^4.23.13",
|
|
121
|
+
"typescript": "^5.9.3"
|
|
83
122
|
},
|
|
84
123
|
"files": [
|
|
85
124
|
"dist",
|
|
86
|
-
"src
|
|
125
|
+
"src",
|
|
126
|
+
"!src/**/*.test.ts",
|
|
127
|
+
"!src/**/*.test.tsx",
|
|
128
|
+
"!src/**/__tests__/**",
|
|
129
|
+
"LICENSE",
|
|
130
|
+
"NOTICE",
|
|
131
|
+
"README.md",
|
|
132
|
+
"!dist/**/*.tsbuildinfo"
|
|
87
133
|
],
|
|
88
134
|
"publishConfig": {
|
|
89
135
|
"access": "public"
|
|
90
136
|
},
|
|
137
|
+
"engines": {
|
|
138
|
+
"node": ">=22.14"
|
|
139
|
+
},
|
|
140
|
+
"sideEffects": false,
|
|
91
141
|
"scripts": {
|
|
92
142
|
"type-check": "tsc --noEmit",
|
|
93
143
|
"lint": "eslint .",
|
|
@@ -96,6 +146,6 @@
|
|
|
96
146
|
"db:studio": "drizzle-kit studio",
|
|
97
147
|
"db:push": "drizzle-kit push",
|
|
98
148
|
"db:check": "tsx scripts/check-db.ts",
|
|
99
|
-
"build": "tsc -p tsconfig.build.json"
|
|
149
|
+
"build": "tsc -p tsconfig.build.json && node ../../scripts/fix-esm-extensions.mjs dist"
|
|
100
150
|
}
|
|
101
151
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type AttachmentServiceErrorCode =
|
|
2
|
+
"not_found" | "forbidden" | "invalid_input" | "database_error";
|
|
3
|
+
|
|
4
|
+
export class AttachmentServiceError extends Error {
|
|
5
|
+
constructor(
|
|
6
|
+
public readonly code: AttachmentServiceErrorCode,
|
|
7
|
+
message: string
|
|
8
|
+
) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "AttachmentServiceError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isAttachmentServiceError(
|
|
15
|
+
error: unknown
|
|
16
|
+
): error is AttachmentServiceError {
|
|
17
|
+
return error instanceof AttachmentServiceError;
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rows for the files users put into conversations; the bytes live behind
|
|
3
|
+
* `@intelligo-dev/core/storage`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
attachToConversation,
|
|
8
|
+
createAttachment,
|
|
9
|
+
deleteAttachment,
|
|
10
|
+
getAttachment,
|
|
11
|
+
getAttachments,
|
|
12
|
+
listOrphanAttachments,
|
|
13
|
+
setExtractedText,
|
|
14
|
+
} from "./service";
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
AttachmentServiceError,
|
|
18
|
+
isAttachmentServiceError,
|
|
19
|
+
type AttachmentServiceErrorCode,
|
|
20
|
+
} from "./errors";
|
|
21
|
+
|
|
22
|
+
export type { Attachment, AttachmentActor, InsertAttachment } from "./types";
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-only rows for the files users put into conversations. The bytes
|
|
3
|
+
* live behind the storage port; this table records who uploaded a file,
|
|
4
|
+
* its workspace, type, size and, once the turn is persisted, conversation.
|
|
5
|
+
*
|
|
6
|
+
* Every read and write is scoped to the workspace and the uploader: the ids
|
|
7
|
+
* arrive in the request body, and conversations are user-private, so a
|
|
8
|
+
* workspace-only scope would let a member trade a colleague's attachment id
|
|
9
|
+
* for a signed URL to it.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { and, eq, inArray, isNull, lt } from "drizzle-orm";
|
|
13
|
+
|
|
14
|
+
import { db } from "../db";
|
|
15
|
+
import { attachments } from "../db/schema";
|
|
16
|
+
import { AttachmentServiceError } from "./errors";
|
|
17
|
+
import type { Attachment, AttachmentActor } from "./types";
|
|
18
|
+
|
|
19
|
+
export async function createAttachment(
|
|
20
|
+
actor: AttachmentActor,
|
|
21
|
+
params: {
|
|
22
|
+
id?: string;
|
|
23
|
+
storageKey: string;
|
|
24
|
+
filename: string;
|
|
25
|
+
mediaType: string;
|
|
26
|
+
sizeBytes: number;
|
|
27
|
+
conversationId?: string | null;
|
|
28
|
+
extractedText?: string | null;
|
|
29
|
+
}
|
|
30
|
+
): Promise<Attachment> {
|
|
31
|
+
if (!params.filename.trim()) {
|
|
32
|
+
throw new AttachmentServiceError("invalid_input", "Filename is required");
|
|
33
|
+
}
|
|
34
|
+
if (params.sizeBytes < 0) {
|
|
35
|
+
throw new AttachmentServiceError(
|
|
36
|
+
"invalid_input",
|
|
37
|
+
"Size cannot be negative"
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const [row] = await db
|
|
41
|
+
.insert(attachments)
|
|
42
|
+
.values({
|
|
43
|
+
id: params.id ?? crypto.randomUUID(),
|
|
44
|
+
workspaceId: actor.workspaceId,
|
|
45
|
+
userId: actor.userId,
|
|
46
|
+
conversationId: params.conversationId ?? null,
|
|
47
|
+
storageKey: params.storageKey,
|
|
48
|
+
filename: params.filename,
|
|
49
|
+
mediaType: params.mediaType,
|
|
50
|
+
sizeBytes: params.sizeBytes,
|
|
51
|
+
extractedText: params.extractedText ?? null,
|
|
52
|
+
})
|
|
53
|
+
.returning();
|
|
54
|
+
if (!row) {
|
|
55
|
+
throw new AttachmentServiceError(
|
|
56
|
+
"database_error",
|
|
57
|
+
"Failed to create attachment"
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return row;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** One attachment, if the actor uploaded it in their own workspace. */
|
|
64
|
+
export async function getAttachment(
|
|
65
|
+
actor: AttachmentActor,
|
|
66
|
+
id: string
|
|
67
|
+
): Promise<Attachment> {
|
|
68
|
+
const [row] = await db
|
|
69
|
+
.select()
|
|
70
|
+
.from(attachments)
|
|
71
|
+
.where(
|
|
72
|
+
and(
|
|
73
|
+
eq(attachments.id, id),
|
|
74
|
+
eq(attachments.workspaceId, actor.workspaceId),
|
|
75
|
+
eq(attachments.userId, actor.userId)
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
.limit(1);
|
|
79
|
+
if (!row) {
|
|
80
|
+
throw new AttachmentServiceError("not_found", "Attachment not found");
|
|
81
|
+
}
|
|
82
|
+
return row;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The attachments among `ids` that the actor uploaded. */
|
|
86
|
+
export async function getAttachments(
|
|
87
|
+
actor: AttachmentActor,
|
|
88
|
+
ids: readonly string[]
|
|
89
|
+
): Promise<Attachment[]> {
|
|
90
|
+
if (ids.length === 0) return [];
|
|
91
|
+
return db
|
|
92
|
+
.select()
|
|
93
|
+
.from(attachments)
|
|
94
|
+
.where(
|
|
95
|
+
and(
|
|
96
|
+
inArray(attachments.id, [...ids]),
|
|
97
|
+
eq(attachments.workspaceId, actor.workspaceId),
|
|
98
|
+
eq(attachments.userId, actor.userId)
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Tie uploaded files to the conversation whose turn carried them. */
|
|
104
|
+
export async function attachToConversation(
|
|
105
|
+
actor: AttachmentActor,
|
|
106
|
+
params: { ids: readonly string[]; conversationId: string }
|
|
107
|
+
): Promise<void> {
|
|
108
|
+
if (params.ids.length === 0) return;
|
|
109
|
+
await db
|
|
110
|
+
.update(attachments)
|
|
111
|
+
.set({ conversationId: params.conversationId })
|
|
112
|
+
.where(
|
|
113
|
+
and(
|
|
114
|
+
inArray(attachments.id, [...params.ids]),
|
|
115
|
+
eq(attachments.workspaceId, actor.workspaceId),
|
|
116
|
+
eq(attachments.userId, actor.userId),
|
|
117
|
+
isNull(attachments.conversationId)
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function setExtractedText(
|
|
123
|
+
actor: AttachmentActor,
|
|
124
|
+
params: { id: string; text: string | null }
|
|
125
|
+
): Promise<void> {
|
|
126
|
+
await db
|
|
127
|
+
.update(attachments)
|
|
128
|
+
.set({ extractedText: params.text })
|
|
129
|
+
.where(
|
|
130
|
+
and(
|
|
131
|
+
eq(attachments.id, params.id),
|
|
132
|
+
eq(attachments.workspaceId, actor.workspaceId),
|
|
133
|
+
eq(attachments.userId, actor.userId)
|
|
134
|
+
)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Remove the row. The caller deletes the object behind `storageKey`. */
|
|
139
|
+
export async function deleteAttachment(
|
|
140
|
+
actor: AttachmentActor,
|
|
141
|
+
id: string
|
|
142
|
+
): Promise<Attachment> {
|
|
143
|
+
const [row] = await db
|
|
144
|
+
.delete(attachments)
|
|
145
|
+
.where(
|
|
146
|
+
and(
|
|
147
|
+
eq(attachments.id, id),
|
|
148
|
+
eq(attachments.workspaceId, actor.workspaceId),
|
|
149
|
+
eq(attachments.userId, actor.userId)
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
.returning();
|
|
153
|
+
if (!row) {
|
|
154
|
+
throw new AttachmentServiceError("not_found", "Attachment not found");
|
|
155
|
+
}
|
|
156
|
+
return row;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Uploads that never made it into a conversation — a turn that was
|
|
161
|
+
* refused, a tab closed mid-compose. A maintenance job deletes them
|
|
162
|
+
* and their objects.
|
|
163
|
+
*/
|
|
164
|
+
export async function listOrphanAttachments(params: {
|
|
165
|
+
olderThan: Date;
|
|
166
|
+
limit?: number;
|
|
167
|
+
}): Promise<Attachment[]> {
|
|
168
|
+
return db
|
|
169
|
+
.select()
|
|
170
|
+
.from(attachments)
|
|
171
|
+
.where(
|
|
172
|
+
and(
|
|
173
|
+
isNull(attachments.conversationId),
|
|
174
|
+
lt(attachments.createdAt, params.olderThan)
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
.limit(params.limit ?? 100);
|
|
178
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by the conversations service for every failure it recognizes.
|
|
3
|
+
* Shaping it into a transport envelope is the caller's job.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* - `not_found` — no conversation, or no message, exists at the given
|
|
8
|
+
* id within the actor's workspace/user scope.
|
|
9
|
+
* - `forbidden` — the target row exists but is outside the actor's
|
|
10
|
+
* scope (a different workspace or a different user's conversation).
|
|
11
|
+
* - `invalid_input` — a caller-supplied argument failed a basic
|
|
12
|
+
* invariant (e.g. an empty title, or a batch of messages that
|
|
13
|
+
* reference a conversation the actor does not own).
|
|
14
|
+
* - `database_error` — the underlying insert/update did not return the
|
|
15
|
+
* row it was expected to.
|
|
16
|
+
*/
|
|
17
|
+
export type ConversationServiceErrorCode =
|
|
18
|
+
"not_found" | "forbidden" | "invalid_input" | "database_error";
|
|
19
|
+
|
|
20
|
+
export class ConversationServiceError extends Error {
|
|
21
|
+
readonly code: ConversationServiceErrorCode;
|
|
22
|
+
// The ES2020 target predates `Error.cause`; declared so `err.cause`
|
|
23
|
+
// type-checks for callers.
|
|
24
|
+
readonly cause?: unknown;
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
code: ConversationServiceErrorCode,
|
|
28
|
+
message: string,
|
|
29
|
+
options?: { cause?: unknown }
|
|
30
|
+
) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "ConversationServiceError";
|
|
33
|
+
this.code = code;
|
|
34
|
+
if (options?.cause !== undefined) {
|
|
35
|
+
(this as { cause?: unknown }).cause = options.cause;
|
|
36
|
+
}
|
|
37
|
+
Object.setPrototypeOf(this, ConversationServiceError.prototype);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isConversationServiceError(
|
|
42
|
+
error: unknown
|
|
43
|
+
): error is ConversationServiceError {
|
|
44
|
+
return error instanceof ConversationServiceError;
|
|
45
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createConversation,
|
|
3
|
+
getConversation,
|
|
4
|
+
listConversations,
|
|
5
|
+
getConversationHistory,
|
|
6
|
+
renameConversation,
|
|
7
|
+
deleteConversation,
|
|
8
|
+
deleteAllConversations,
|
|
9
|
+
getMessages,
|
|
10
|
+
saveMessages,
|
|
11
|
+
upsertMessages,
|
|
12
|
+
updateMessage,
|
|
13
|
+
deleteTrailingMessages,
|
|
14
|
+
voteMessage,
|
|
15
|
+
getVotes,
|
|
16
|
+
clearVote,
|
|
17
|
+
updateConversationMetadata,
|
|
18
|
+
setConversationVisibility,
|
|
19
|
+
getPublicConversation,
|
|
20
|
+
getPublicMessages,
|
|
21
|
+
} from "./service";
|
|
22
|
+
export type { ConversationVisibility } from "./service";
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
ConversationServiceError,
|
|
26
|
+
isConversationServiceError,
|
|
27
|
+
type ConversationServiceErrorCode,
|
|
28
|
+
} from "./errors";
|
|
29
|
+
|
|
30
|
+
export type {
|
|
31
|
+
ConversationActor,
|
|
32
|
+
Conversation,
|
|
33
|
+
InsertConversation,
|
|
34
|
+
Message,
|
|
35
|
+
InsertMessage,
|
|
36
|
+
Vote,
|
|
37
|
+
InsertVote,
|
|
38
|
+
ConversationMetadata,
|
|
39
|
+
} from "./types";
|