@vellumai/assistant 0.4.30 → 0.4.32
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/ARCHITECTURE.md +1 -1
- package/Dockerfile +14 -8
- package/README.md +2 -2
- package/docs/architecture/memory.md +28 -29
- package/docs/runbook-trusted-contacts.md +1 -4
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -7
- package/src/__tests__/anthropic-provider.test.ts +86 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/checker.test.ts +37 -98
- package/src/__tests__/commit-message-enrichment-service.test.ts +15 -4
- package/src/__tests__/config-schema.test.ts +6 -14
- package/src/__tests__/conflict-policy.test.ts +76 -0
- package/src/__tests__/conflict-store.test.ts +14 -20
- package/src/__tests__/contacts-tools.test.ts +8 -61
- package/src/__tests__/contradiction-checker.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-server-session-init.test.ts +1 -19
- package/src/__tests__/followup-tools.test.ts +0 -30
- package/src/__tests__/gemini-provider.test.ts +79 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-routing-invariants.test.ts +6 -4
- package/src/__tests__/ipc-snapshot.test.ts +0 -4
- package/src/__tests__/managed-proxy-context.test.ts +163 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +13 -12
- package/src/__tests__/memory-regressions.test.ts +6 -6
- package/src/__tests__/openai-provider.test.ts +82 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +134 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +269 -0
- package/src/__tests__/recurrence-types.test.ts +0 -15
- package/src/__tests__/registry.test.ts +0 -10
- package/src/__tests__/schedule-tools.test.ts +28 -44
- package/src/__tests__/script-proxy-session-runtime.test.ts +6 -1
- package/src/__tests__/session-agent-loop.test.ts +0 -2
- package/src/__tests__/session-conflict-gate.test.ts +243 -388
- package/src/__tests__/session-profile-injection.test.ts +0 -2
- package/src/__tests__/session-runtime-assembly.test.ts +2 -3
- package/src/__tests__/session-skill-tools.test.ts +0 -49
- package/src/__tests__/session-workspace-cache-state.test.ts +0 -1
- package/src/__tests__/session-workspace-injection.test.ts +0 -1
- package/src/__tests__/session-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/task-management-tools.test.ts +111 -0
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -1
- package/src/__tests__/twilio-config.test.ts +0 -3
- package/src/amazon/session.ts +30 -91
- package/src/approvals/guardian-decision-primitive.ts +11 -7
- package/src/approvals/guardian-request-resolvers.ts +5 -3
- package/src/calls/call-controller.ts +423 -571
- package/src/calls/finalize-call.ts +20 -0
- package/src/calls/relay-access-wait.ts +340 -0
- package/src/calls/relay-server.ts +269 -899
- package/src/calls/relay-setup-router.ts +307 -0
- package/src/calls/relay-verification.ts +280 -0
- package/src/calls/twilio-config.ts +1 -8
- package/src/calls/voice-control-protocol.ts +184 -0
- package/src/calls/voice-session-bridge.ts +1 -8
- package/src/config/agent-schema.ts +1 -1
- package/src/config/bundled-skills/contacts/SKILL.md +7 -18
- package/src/config/bundled-skills/contacts/TOOLS.json +4 -20
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +2 -4
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +6 -12
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +3 -24
- package/src/config/bundled-skills/followups/TOOLS.json +0 -4
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -10
- package/src/config/bundled-tool-registry.ts +0 -5
- package/src/config/core-schema.ts +1 -1
- package/src/config/env.ts +0 -10
- package/src/config/feature-flag-registry.json +1 -1
- package/src/config/loader.ts +19 -0
- package/src/config/memory-schema.ts +0 -10
- package/src/config/schema.ts +2 -2
- package/src/config/system-prompt.ts +6 -0
- package/src/contacts/contact-store.ts +36 -62
- package/src/contacts/contacts-write.ts +14 -3
- package/src/contacts/types.ts +9 -4
- package/src/daemon/handlers/config-heartbeat.ts +1 -2
- package/src/daemon/handlers/contacts.ts +2 -2
- package/src/daemon/handlers/guardian-actions.ts +1 -1
- package/src/daemon/handlers/session-history.ts +398 -0
- package/src/daemon/handlers/session-user-message.ts +982 -0
- package/src/daemon/handlers/sessions.ts +9 -1337
- package/src/daemon/ipc-contract/contacts.ts +2 -2
- package/src/daemon/ipc-contract/sessions.ts +0 -6
- package/src/daemon/ipc-contract-inventory.json +0 -1
- package/src/daemon/lifecycle.ts +0 -29
- package/src/daemon/session-agent-loop.ts +1 -45
- package/src/daemon/session-conflict-gate.ts +21 -82
- package/src/daemon/session-memory.ts +7 -52
- package/src/daemon/session-process.ts +3 -1
- package/src/daemon/session-runtime-assembly.ts +18 -35
- package/src/heartbeat/heartbeat-service.ts +5 -1
- package/src/home-base/app-link-store.ts +0 -7
- package/src/memory/conflict-intent.ts +3 -6
- package/src/memory/conflict-policy.ts +34 -0
- package/src/memory/conflict-store.ts +10 -18
- package/src/memory/contradiction-checker.ts +2 -2
- package/src/memory/conversation-attention-store.ts +1 -1
- package/src/memory/conversation-store.ts +0 -51
- package/src/memory/db-init.ts +8 -0
- package/src/memory/job-handlers/conflict.ts +24 -7
- package/src/memory/migrations/105-contacts-and-triage.ts +4 -7
- package/src/memory/migrations/134-contacts-notes-column.ts +68 -0
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +31 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/migrations/registry.ts +6 -0
- package/src/memory/recall-cache.ts +0 -5
- package/src/memory/schema/calls.ts +274 -0
- package/src/memory/schema/contacts.ts +125 -0
- package/src/memory/schema/conversations.ts +129 -0
- package/src/memory/schema/guardian.ts +172 -0
- package/src/memory/schema/index.ts +8 -0
- package/src/memory/schema/infrastructure.ts +205 -0
- package/src/memory/schema/memory-core.ts +196 -0
- package/src/memory/schema/notifications.ts +191 -0
- package/src/memory/schema/tasks.ts +78 -0
- package/src/memory/schema.ts +1 -1402
- package/src/memory/slack-thread-store.ts +0 -69
- package/src/messaging/index.ts +0 -1
- package/src/messaging/types.ts +0 -38
- package/src/notifications/decisions-store.ts +2 -105
- package/src/notifications/deliveries-store.ts +0 -11
- package/src/notifications/preferences-store.ts +1 -58
- package/src/permissions/checker.ts +6 -17
- package/src/providers/anthropic/client.ts +6 -2
- package/src/providers/gemini/client.ts +13 -2
- package/src/providers/managed-proxy/constants.ts +55 -0
- package/src/providers/managed-proxy/context.ts +77 -0
- package/src/providers/registry.ts +112 -0
- package/src/runtime/auth/__tests__/guard-tests.test.ts +51 -23
- package/src/runtime/guardian-action-service.ts +3 -2
- package/src/runtime/guardian-outbound-actions.ts +3 -3
- package/src/runtime/guardian-reply-router.ts +4 -4
- package/src/runtime/http-server.ts +83 -710
- package/src/runtime/http-types.ts +0 -16
- package/src/runtime/middleware/auth.ts +0 -12
- package/src/runtime/routes/app-routes.ts +33 -0
- package/src/runtime/routes/approval-routes.ts +32 -0
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +6 -3
- package/src/runtime/routes/attachment-routes.ts +32 -0
- package/src/runtime/routes/brain-graph-routes.ts +27 -0
- package/src/runtime/routes/call-routes.ts +41 -0
- package/src/runtime/routes/channel-readiness-routes.ts +20 -0
- package/src/runtime/routes/channel-routes.ts +70 -0
- package/src/runtime/routes/contact-routes.ts +371 -29
- package/src/runtime/routes/conversation-attention-routes.ts +15 -0
- package/src/runtime/routes/conversation-routes.ts +192 -194
- package/src/runtime/routes/debug-routes.ts +15 -0
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/global-search-routes.ts +17 -2
- package/src/runtime/routes/guardian-action-routes.ts +23 -1
- package/src/runtime/routes/guardian-approval-interception.ts +2 -1
- package/src/runtime/routes/guardian-bootstrap-routes.ts +26 -1
- package/src/runtime/routes/guardian-refresh-routes.ts +20 -0
- package/src/runtime/routes/identity-routes.ts +20 -0
- package/src/runtime/routes/inbound-message-handler.ts +8 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +5 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +2 -1
- package/src/runtime/routes/integration-routes.ts +83 -0
- package/src/runtime/routes/invite-routes.ts +31 -0
- package/src/runtime/routes/migration-routes.ts +47 -17
- package/src/runtime/routes/pairing-routes.ts +18 -0
- package/src/runtime/routes/secret-routes.ts +20 -0
- package/src/runtime/routes/surface-action-routes.ts +26 -0
- package/src/runtime/routes/trust-rules-routes.ts +31 -0
- package/src/runtime/routes/twilio-routes.ts +79 -0
- package/src/schedule/recurrence-types.ts +1 -11
- package/src/tools/followups/followup_create.ts +9 -3
- package/src/tools/mcp/mcp-tool-factory.ts +0 -17
- package/src/tools/memory/definitions.ts +0 -6
- package/src/tools/network/script-proxy/session-manager.ts +38 -3
- package/src/tools/schedule/create.ts +1 -3
- package/src/tools/schedule/update.ts +9 -6
- package/src/twitter/session.ts +29 -77
- package/src/util/cookie-session.ts +114 -0
- package/src/workspace/git-service.ts +6 -4
- package/src/__tests__/conversation-routes.test.ts +0 -99
- package/src/__tests__/get-weather.test.ts +0 -393
- package/src/__tests__/task-tools.test.ts +0 -685
- package/src/__tests__/weather-skill-regression.test.ts +0 -276
- package/src/autonomy/autonomy-resolver.ts +0 -62
- package/src/autonomy/autonomy-store.ts +0 -138
- package/src/autonomy/disposition-mapper.ts +0 -31
- package/src/autonomy/index.ts +0 -11
- package/src/autonomy/types.ts +0 -43
- package/src/config/bundled-skills/weather/SKILL.md +0 -38
- package/src/config/bundled-skills/weather/TOOLS.json +0 -36
- package/src/config/bundled-skills/weather/icon.svg +0 -24
- package/src/config/bundled-skills/weather/tools/get-weather.ts +0 -12
- package/src/contacts/startup-migration.ts +0 -21
- package/src/messaging/triage-engine.ts +0 -344
- package/src/tools/weather/service.ts +0 -712
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
2
|
+
|
|
3
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
4
|
+
import { callPendingQuestions, callSessions } from "./calls.js";
|
|
5
|
+
|
|
6
|
+
export const guardianActionRequests = sqliteTable(
|
|
7
|
+
"guardian_action_requests",
|
|
8
|
+
{
|
|
9
|
+
id: text("id").primaryKey(),
|
|
10
|
+
assistantId: text("assistant_id")
|
|
11
|
+
.notNull()
|
|
12
|
+
.default(DAEMON_INTERNAL_ASSISTANT_ID),
|
|
13
|
+
kind: text("kind").notNull(), // 'ask_guardian'
|
|
14
|
+
sourceChannel: text("source_channel").notNull(), // 'voice'
|
|
15
|
+
sourceConversationId: text("source_conversation_id").notNull(),
|
|
16
|
+
callSessionId: text("call_session_id")
|
|
17
|
+
.notNull()
|
|
18
|
+
.references(() => callSessions.id, { onDelete: "cascade" }),
|
|
19
|
+
pendingQuestionId: text("pending_question_id")
|
|
20
|
+
.notNull()
|
|
21
|
+
.references(() => callPendingQuestions.id, { onDelete: "cascade" }),
|
|
22
|
+
questionText: text("question_text").notNull(),
|
|
23
|
+
requestCode: text("request_code").notNull(), // short human-readable code for routing replies
|
|
24
|
+
status: text("status").notNull().default("pending"), // pending | answered | expired | cancelled
|
|
25
|
+
answerText: text("answer_text"),
|
|
26
|
+
answeredByChannel: text("answered_by_channel"),
|
|
27
|
+
answeredByExternalUserId: text("answered_by_external_user_id"),
|
|
28
|
+
answeredAt: integer("answered_at"),
|
|
29
|
+
expiresAt: integer("expires_at").notNull(),
|
|
30
|
+
expiredReason: text("expired_reason"), // call_timeout | sweep_timeout | cancelled
|
|
31
|
+
followupState: text("followup_state").notNull().default("none"), // none | awaiting_guardian_choice | dispatching | completed | declined | failed
|
|
32
|
+
lateAnswerText: text("late_answer_text"),
|
|
33
|
+
lateAnsweredAt: integer("late_answered_at"),
|
|
34
|
+
followupAction: text("followup_action"), // call_back | message_back | decline
|
|
35
|
+
followupCompletedAt: integer("followup_completed_at"),
|
|
36
|
+
toolName: text("tool_name"), // tool identity for tool-approval requests
|
|
37
|
+
inputDigest: text("input_digest"), // canonical SHA-256 digest of tool input
|
|
38
|
+
supersededByRequestId: text("superseded_by_request_id"), // links to the request that replaced this one
|
|
39
|
+
supersededAt: integer("superseded_at"), // epoch ms when supersession occurred
|
|
40
|
+
createdAt: integer("created_at").notNull(),
|
|
41
|
+
updatedAt: integer("updated_at").notNull(),
|
|
42
|
+
},
|
|
43
|
+
(table) => [
|
|
44
|
+
index("idx_guardian_action_requests_session_status_created").on(
|
|
45
|
+
table.callSessionId,
|
|
46
|
+
table.status,
|
|
47
|
+
table.createdAt,
|
|
48
|
+
),
|
|
49
|
+
],
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
export const guardianActionDeliveries = sqliteTable(
|
|
53
|
+
"guardian_action_deliveries",
|
|
54
|
+
{
|
|
55
|
+
id: text("id").primaryKey(),
|
|
56
|
+
requestId: text("request_id")
|
|
57
|
+
.notNull()
|
|
58
|
+
.references(() => guardianActionRequests.id, { onDelete: "cascade" }),
|
|
59
|
+
destinationChannel: text("destination_channel").notNull(), // 'telegram' | 'sms' | 'vellum'
|
|
60
|
+
destinationConversationId: text("destination_conversation_id"),
|
|
61
|
+
destinationChatId: text("destination_chat_id"),
|
|
62
|
+
destinationExternalUserId: text("destination_external_user_id"),
|
|
63
|
+
status: text("status").notNull().default("pending"), // pending | sent | failed | answered | expired | cancelled
|
|
64
|
+
sentAt: integer("sent_at"),
|
|
65
|
+
respondedAt: integer("responded_at"),
|
|
66
|
+
lastError: text("last_error"),
|
|
67
|
+
createdAt: integer("created_at").notNull(),
|
|
68
|
+
updatedAt: integer("updated_at").notNull(),
|
|
69
|
+
},
|
|
70
|
+
(table) => [
|
|
71
|
+
index("idx_guardian_action_deliveries_dest_conversation").on(
|
|
72
|
+
table.destinationConversationId,
|
|
73
|
+
),
|
|
74
|
+
],
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
export const canonicalGuardianRequests = sqliteTable(
|
|
78
|
+
"canonical_guardian_requests",
|
|
79
|
+
{
|
|
80
|
+
id: text("id").primaryKey(),
|
|
81
|
+
kind: text("kind").notNull(),
|
|
82
|
+
sourceType: text("source_type").notNull(),
|
|
83
|
+
sourceChannel: text("source_channel"),
|
|
84
|
+
conversationId: text("conversation_id"),
|
|
85
|
+
requesterExternalUserId: text("requester_external_user_id"),
|
|
86
|
+
requesterChatId: text("requester_chat_id"),
|
|
87
|
+
guardianExternalUserId: text("guardian_external_user_id"),
|
|
88
|
+
guardianPrincipalId: text("guardian_principal_id"),
|
|
89
|
+
callSessionId: text("call_session_id"),
|
|
90
|
+
pendingQuestionId: text("pending_question_id"),
|
|
91
|
+
questionText: text("question_text"),
|
|
92
|
+
requestCode: text("request_code"),
|
|
93
|
+
toolName: text("tool_name"),
|
|
94
|
+
inputDigest: text("input_digest"),
|
|
95
|
+
status: text("status").notNull().default("pending"),
|
|
96
|
+
answerText: text("answer_text"),
|
|
97
|
+
decidedByExternalUserId: text("decided_by_external_user_id"),
|
|
98
|
+
decidedByPrincipalId: text("decided_by_principal_id"),
|
|
99
|
+
followupState: text("followup_state"),
|
|
100
|
+
expiresAt: text("expires_at"),
|
|
101
|
+
createdAt: text("created_at").notNull(),
|
|
102
|
+
updatedAt: text("updated_at").notNull(),
|
|
103
|
+
},
|
|
104
|
+
(table) => [
|
|
105
|
+
index("idx_canonical_guardian_requests_status").on(table.status),
|
|
106
|
+
index("idx_canonical_guardian_requests_guardian").on(
|
|
107
|
+
table.guardianExternalUserId,
|
|
108
|
+
table.status,
|
|
109
|
+
),
|
|
110
|
+
index("idx_canonical_guardian_requests_conversation").on(
|
|
111
|
+
table.conversationId,
|
|
112
|
+
table.status,
|
|
113
|
+
),
|
|
114
|
+
index("idx_canonical_guardian_requests_source").on(
|
|
115
|
+
table.sourceType,
|
|
116
|
+
table.status,
|
|
117
|
+
),
|
|
118
|
+
index("idx_canonical_guardian_requests_kind").on(table.kind, table.status),
|
|
119
|
+
index("idx_canonical_guardian_requests_request_code").on(table.requestCode),
|
|
120
|
+
],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
export const canonicalGuardianDeliveries = sqliteTable(
|
|
124
|
+
"canonical_guardian_deliveries",
|
|
125
|
+
{
|
|
126
|
+
id: text("id").primaryKey(),
|
|
127
|
+
requestId: text("request_id")
|
|
128
|
+
.notNull()
|
|
129
|
+
.references(() => canonicalGuardianRequests.id, { onDelete: "cascade" }),
|
|
130
|
+
destinationChannel: text("destination_channel").notNull(),
|
|
131
|
+
destinationConversationId: text("destination_conversation_id"),
|
|
132
|
+
destinationChatId: text("destination_chat_id"),
|
|
133
|
+
destinationMessageId: text("destination_message_id"),
|
|
134
|
+
status: text("status").notNull().default("pending"),
|
|
135
|
+
createdAt: text("created_at").notNull(),
|
|
136
|
+
updatedAt: text("updated_at").notNull(),
|
|
137
|
+
},
|
|
138
|
+
(table) => [
|
|
139
|
+
index("idx_canonical_guardian_deliveries_request_id").on(table.requestId),
|
|
140
|
+
index("idx_canonical_guardian_deliveries_status").on(table.status),
|
|
141
|
+
],
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
export const scopedApprovalGrants = sqliteTable(
|
|
145
|
+
"scoped_approval_grants",
|
|
146
|
+
{
|
|
147
|
+
id: text("id").primaryKey(),
|
|
148
|
+
assistantId: text("assistant_id").notNull(),
|
|
149
|
+
scopeMode: text("scope_mode").notNull(), // 'request_id' | 'tool_signature'
|
|
150
|
+
requestId: text("request_id"),
|
|
151
|
+
toolName: text("tool_name"),
|
|
152
|
+
inputDigest: text("input_digest"),
|
|
153
|
+
requestChannel: text("request_channel").notNull(),
|
|
154
|
+
decisionChannel: text("decision_channel").notNull(),
|
|
155
|
+
executionChannel: text("execution_channel"), // null = any channel
|
|
156
|
+
conversationId: text("conversation_id"),
|
|
157
|
+
callSessionId: text("call_session_id"),
|
|
158
|
+
requesterExternalUserId: text("requester_external_user_id"),
|
|
159
|
+
guardianExternalUserId: text("guardian_external_user_id"),
|
|
160
|
+
status: text("status").notNull(), // 'active' | 'consumed' | 'expired' | 'revoked'
|
|
161
|
+
expiresAt: text("expires_at").notNull(),
|
|
162
|
+
consumedAt: text("consumed_at"),
|
|
163
|
+
consumedByRequestId: text("consumed_by_request_id"),
|
|
164
|
+
createdAt: text("created_at").notNull(),
|
|
165
|
+
updatedAt: text("updated_at").notNull(),
|
|
166
|
+
},
|
|
167
|
+
(table) => [
|
|
168
|
+
index("idx_scoped_grants_request_id").on(table.requestId),
|
|
169
|
+
index("idx_scoped_grants_tool_sig").on(table.toolName, table.inputDigest),
|
|
170
|
+
index("idx_scoped_grants_status_expires").on(table.status, table.expiresAt),
|
|
171
|
+
],
|
|
172
|
+
);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./calls.js";
|
|
2
|
+
export * from "./contacts.js";
|
|
3
|
+
export * from "./conversations.js";
|
|
4
|
+
export * from "./guardian.js";
|
|
5
|
+
export * from "./infrastructure.js";
|
|
6
|
+
export * from "./memory-core.js";
|
|
7
|
+
export * from "./notifications.js";
|
|
8
|
+
export * from "./tasks.js";
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import {
|
|
2
|
+
blob,
|
|
3
|
+
index,
|
|
4
|
+
integer,
|
|
5
|
+
real,
|
|
6
|
+
sqliteTable,
|
|
7
|
+
text,
|
|
8
|
+
} from "drizzle-orm/sqlite-core";
|
|
9
|
+
|
|
10
|
+
export const accounts = sqliteTable("accounts", {
|
|
11
|
+
id: text("id").primaryKey(),
|
|
12
|
+
service: text("service").notNull(),
|
|
13
|
+
username: text("username"),
|
|
14
|
+
email: text("email"),
|
|
15
|
+
displayName: text("display_name"),
|
|
16
|
+
status: text("status").notNull().default("active"),
|
|
17
|
+
credentialRef: text("credential_ref"),
|
|
18
|
+
metadataJson: text("metadata_json"),
|
|
19
|
+
createdAt: integer("created_at").notNull(),
|
|
20
|
+
updatedAt: integer("updated_at").notNull(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const reminders = sqliteTable("reminders", {
|
|
24
|
+
id: text("id").primaryKey(),
|
|
25
|
+
label: text("label").notNull(),
|
|
26
|
+
message: text("message").notNull(),
|
|
27
|
+
fireAt: integer("fire_at").notNull(), // epoch ms, absolute timestamp
|
|
28
|
+
mode: text("mode").notNull(), // 'notify' | 'execute'
|
|
29
|
+
status: text("status").notNull(), // 'pending' | 'firing' | 'fired' | 'cancelled'
|
|
30
|
+
firedAt: integer("fired_at"),
|
|
31
|
+
conversationId: text("conversation_id"),
|
|
32
|
+
routingIntent: text("routing_intent").notNull().default("all_channels"), // 'single_channel' | 'multi_channel' | 'all_channels'
|
|
33
|
+
routingHintsJson: text("routing_hints_json").notNull().default("{}"),
|
|
34
|
+
createdAt: integer("created_at").notNull(),
|
|
35
|
+
updatedAt: integer("updated_at").notNull(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const cronJobs = sqliteTable("cron_jobs", {
|
|
39
|
+
id: text("id").primaryKey(),
|
|
40
|
+
name: text("name").notNull(),
|
|
41
|
+
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
|
42
|
+
cronExpression: text("cron_expression").notNull(), // e.g. '0 9 * * 1-5'
|
|
43
|
+
scheduleSyntax: text("schedule_syntax").notNull().default("cron"), // 'cron' | 'rrule'
|
|
44
|
+
timezone: text("timezone"), // e.g. 'America/Los_Angeles'
|
|
45
|
+
message: text("message").notNull(),
|
|
46
|
+
nextRunAt: integer("next_run_at").notNull(),
|
|
47
|
+
lastRunAt: integer("last_run_at"),
|
|
48
|
+
lastStatus: text("last_status"), // 'ok' | 'error'
|
|
49
|
+
retryCount: integer("retry_count").notNull().default(0),
|
|
50
|
+
createdBy: text("created_by").notNull(), // 'agent' | 'user'
|
|
51
|
+
createdAt: integer("created_at").notNull(),
|
|
52
|
+
updatedAt: integer("updated_at").notNull(),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const cronRuns = sqliteTable("cron_runs", {
|
|
56
|
+
id: text("id").primaryKey(),
|
|
57
|
+
jobId: text("job_id")
|
|
58
|
+
.notNull()
|
|
59
|
+
.references(() => cronJobs.id, { onDelete: "cascade" }),
|
|
60
|
+
status: text("status").notNull(), // 'ok' | 'error'
|
|
61
|
+
startedAt: integer("started_at").notNull(),
|
|
62
|
+
finishedAt: integer("finished_at"),
|
|
63
|
+
durationMs: integer("duration_ms"),
|
|
64
|
+
output: text("output"),
|
|
65
|
+
error: text("error"),
|
|
66
|
+
conversationId: text("conversation_id"),
|
|
67
|
+
createdAt: integer("created_at").notNull(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Recurrence-centric aliases — prefer these in new code.
|
|
71
|
+
// Physical table names remain `cron_jobs` / `cron_runs` for migration compatibility.
|
|
72
|
+
export const scheduleJobs = cronJobs;
|
|
73
|
+
export const scheduleRuns = cronRuns;
|
|
74
|
+
|
|
75
|
+
export const sharedAppLinks = sqliteTable("shared_app_links", {
|
|
76
|
+
id: text("id").primaryKey(),
|
|
77
|
+
shareToken: text("share_token").notNull().unique(),
|
|
78
|
+
bundleData: blob("bundle_data", { mode: "buffer" }).notNull(),
|
|
79
|
+
bundleSizeBytes: integer("bundle_size_bytes").notNull(),
|
|
80
|
+
manifestJson: text("manifest_json").notNull(),
|
|
81
|
+
downloadCount: integer("download_count").notNull().default(0),
|
|
82
|
+
createdAt: integer("created_at").notNull(),
|
|
83
|
+
expiresAt: integer("expires_at"),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export const homeBaseAppLinks = sqliteTable("home_base_app_links", {
|
|
87
|
+
id: text("id").primaryKey(),
|
|
88
|
+
appId: text("app_id").notNull(),
|
|
89
|
+
source: text("source").notNull(),
|
|
90
|
+
createdAt: integer("created_at").notNull(),
|
|
91
|
+
updatedAt: integer("updated_at").notNull(),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export const publishedPages = sqliteTable("published_pages", {
|
|
95
|
+
id: text("id").primaryKey(),
|
|
96
|
+
deploymentId: text("deployment_id").notNull().unique(),
|
|
97
|
+
publicUrl: text("public_url").notNull(),
|
|
98
|
+
pageTitle: text("page_title"),
|
|
99
|
+
htmlHash: text("html_hash").notNull(),
|
|
100
|
+
publishedAt: integer("published_at").notNull(),
|
|
101
|
+
status: text("status").notNull().default("active"),
|
|
102
|
+
appId: text("app_id"),
|
|
103
|
+
projectSlug: text("project_slug"),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export const watchers = sqliteTable("watchers", {
|
|
107
|
+
id: text("id").primaryKey(),
|
|
108
|
+
name: text("name").notNull(),
|
|
109
|
+
providerId: text("provider_id").notNull(),
|
|
110
|
+
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
|
111
|
+
pollIntervalMs: integer("poll_interval_ms").notNull().default(60000),
|
|
112
|
+
actionPrompt: text("action_prompt").notNull(),
|
|
113
|
+
watermark: text("watermark"),
|
|
114
|
+
conversationId: text("conversation_id"),
|
|
115
|
+
status: text("status").notNull().default("idle"), // idle | polling | error | disabled
|
|
116
|
+
consecutiveErrors: integer("consecutive_errors").notNull().default(0),
|
|
117
|
+
lastError: text("last_error"),
|
|
118
|
+
lastPollAt: integer("last_poll_at"),
|
|
119
|
+
nextPollAt: integer("next_poll_at").notNull(),
|
|
120
|
+
configJson: text("config_json"),
|
|
121
|
+
credentialService: text("credential_service").notNull(),
|
|
122
|
+
createdAt: integer("created_at").notNull(),
|
|
123
|
+
updatedAt: integer("updated_at").notNull(),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const watcherEvents = sqliteTable("watcher_events", {
|
|
127
|
+
id: text("id").primaryKey(),
|
|
128
|
+
watcherId: text("watcher_id")
|
|
129
|
+
.notNull()
|
|
130
|
+
.references(() => watchers.id, { onDelete: "cascade" }),
|
|
131
|
+
externalId: text("external_id").notNull(),
|
|
132
|
+
eventType: text("event_type").notNull(),
|
|
133
|
+
summary: text("summary").notNull(),
|
|
134
|
+
payloadJson: text("payload_json").notNull(),
|
|
135
|
+
disposition: text("disposition").notNull().default("pending"), // pending | silent | notify | escalate | error
|
|
136
|
+
llmAction: text("llm_action"),
|
|
137
|
+
processedAt: integer("processed_at"),
|
|
138
|
+
createdAt: integer("created_at").notNull(),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
export const llmRequestLogs = sqliteTable("llm_request_logs", {
|
|
142
|
+
id: text("id").primaryKey(),
|
|
143
|
+
conversationId: text("conversation_id").notNull(),
|
|
144
|
+
requestPayload: text("request_payload").notNull(),
|
|
145
|
+
responsePayload: text("response_payload").notNull(),
|
|
146
|
+
createdAt: integer("created_at").notNull(),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
export const llmUsageEvents = sqliteTable(
|
|
150
|
+
"llm_usage_events",
|
|
151
|
+
{
|
|
152
|
+
id: text("id").primaryKey(),
|
|
153
|
+
createdAt: integer("created_at").notNull(),
|
|
154
|
+
conversationId: text("conversation_id"),
|
|
155
|
+
runId: text("run_id"),
|
|
156
|
+
requestId: text("request_id"),
|
|
157
|
+
actor: text("actor").notNull(),
|
|
158
|
+
provider: text("provider").notNull(),
|
|
159
|
+
model: text("model").notNull(),
|
|
160
|
+
inputTokens: integer("input_tokens").notNull(),
|
|
161
|
+
outputTokens: integer("output_tokens").notNull(),
|
|
162
|
+
cacheCreationInputTokens: integer("cache_creation_input_tokens"),
|
|
163
|
+
cacheReadInputTokens: integer("cache_read_input_tokens"),
|
|
164
|
+
estimatedCostUsd: real("estimated_cost_usd"),
|
|
165
|
+
pricingStatus: text("pricing_status").notNull(),
|
|
166
|
+
metadataJson: text("metadata_json"),
|
|
167
|
+
},
|
|
168
|
+
(table) => [
|
|
169
|
+
index("idx_llm_usage_events_conversation_id").on(table.conversationId),
|
|
170
|
+
],
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
export const actorTokenRecords = sqliteTable("actor_token_records", {
|
|
174
|
+
id: text("id").primaryKey(),
|
|
175
|
+
tokenHash: text("token_hash").notNull(),
|
|
176
|
+
assistantId: text("assistant_id").notNull(),
|
|
177
|
+
guardianPrincipalId: text("guardian_principal_id").notNull(),
|
|
178
|
+
hashedDeviceId: text("hashed_device_id").notNull(),
|
|
179
|
+
platform: text("platform").notNull(),
|
|
180
|
+
status: text("status").notNull().default("active"),
|
|
181
|
+
issuedAt: integer("issued_at").notNull(),
|
|
182
|
+
expiresAt: integer("expires_at"),
|
|
183
|
+
createdAt: integer("created_at").notNull(),
|
|
184
|
+
updatedAt: integer("updated_at").notNull(),
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
export const actorRefreshTokenRecords = sqliteTable(
|
|
188
|
+
"actor_refresh_token_records",
|
|
189
|
+
{
|
|
190
|
+
id: text("id").primaryKey(),
|
|
191
|
+
tokenHash: text("token_hash").notNull(),
|
|
192
|
+
familyId: text("family_id").notNull(),
|
|
193
|
+
assistantId: text("assistant_id").notNull(),
|
|
194
|
+
guardianPrincipalId: text("guardian_principal_id").notNull(),
|
|
195
|
+
hashedDeviceId: text("hashed_device_id").notNull(),
|
|
196
|
+
platform: text("platform").notNull(),
|
|
197
|
+
status: text("status").notNull().default("active"),
|
|
198
|
+
issuedAt: integer("issued_at").notNull(),
|
|
199
|
+
absoluteExpiresAt: integer("absolute_expires_at").notNull(),
|
|
200
|
+
inactivityExpiresAt: integer("inactivity_expires_at").notNull(),
|
|
201
|
+
lastUsedAt: integer("last_used_at"),
|
|
202
|
+
createdAt: integer("created_at").notNull(),
|
|
203
|
+
updatedAt: integer("updated_at").notNull(),
|
|
204
|
+
},
|
|
205
|
+
);
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import {
|
|
2
|
+
blob,
|
|
3
|
+
index,
|
|
4
|
+
integer,
|
|
5
|
+
real,
|
|
6
|
+
sqliteTable,
|
|
7
|
+
text,
|
|
8
|
+
uniqueIndex,
|
|
9
|
+
} from "drizzle-orm/sqlite-core";
|
|
10
|
+
|
|
11
|
+
import { conversations, messages } from "./conversations.js";
|
|
12
|
+
|
|
13
|
+
export const memorySegments = sqliteTable(
|
|
14
|
+
"memory_segments",
|
|
15
|
+
{
|
|
16
|
+
id: text("id").primaryKey(),
|
|
17
|
+
messageId: text("message_id")
|
|
18
|
+
.notNull()
|
|
19
|
+
.references(() => messages.id, { onDelete: "cascade" }),
|
|
20
|
+
conversationId: text("conversation_id")
|
|
21
|
+
.notNull()
|
|
22
|
+
.references(() => conversations.id, { onDelete: "cascade" }),
|
|
23
|
+
role: text("role").notNull(),
|
|
24
|
+
segmentIndex: integer("segment_index").notNull(),
|
|
25
|
+
text: text("text").notNull(),
|
|
26
|
+
tokenEstimate: integer("token_estimate").notNull(),
|
|
27
|
+
scopeId: text("scope_id").notNull().default("default"),
|
|
28
|
+
contentHash: text("content_hash"),
|
|
29
|
+
createdAt: integer("created_at").notNull(),
|
|
30
|
+
updatedAt: integer("updated_at").notNull(),
|
|
31
|
+
},
|
|
32
|
+
(table) => [index("idx_memory_segments_scope_id").on(table.scopeId)],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
export const memoryItems = sqliteTable(
|
|
36
|
+
"memory_items",
|
|
37
|
+
{
|
|
38
|
+
id: text("id").primaryKey(),
|
|
39
|
+
kind: text("kind").notNull(),
|
|
40
|
+
subject: text("subject").notNull(),
|
|
41
|
+
statement: text("statement").notNull(),
|
|
42
|
+
status: text("status").notNull(),
|
|
43
|
+
confidence: real("confidence").notNull(),
|
|
44
|
+
importance: real("importance"),
|
|
45
|
+
accessCount: integer("access_count").notNull().default(0),
|
|
46
|
+
fingerprint: text("fingerprint").notNull(),
|
|
47
|
+
verificationState: text("verification_state")
|
|
48
|
+
.notNull()
|
|
49
|
+
.default("assistant_inferred"),
|
|
50
|
+
scopeId: text("scope_id").notNull().default("default"),
|
|
51
|
+
firstSeenAt: integer("first_seen_at").notNull(),
|
|
52
|
+
lastSeenAt: integer("last_seen_at").notNull(),
|
|
53
|
+
lastUsedAt: integer("last_used_at"),
|
|
54
|
+
validFrom: integer("valid_from"),
|
|
55
|
+
invalidAt: integer("invalid_at"),
|
|
56
|
+
},
|
|
57
|
+
(table) => [
|
|
58
|
+
index("idx_memory_items_scope_id").on(table.scopeId),
|
|
59
|
+
index("idx_memory_items_fingerprint").on(table.fingerprint),
|
|
60
|
+
],
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
export const memoryItemSources = sqliteTable(
|
|
64
|
+
"memory_item_sources",
|
|
65
|
+
{
|
|
66
|
+
memoryItemId: text("memory_item_id")
|
|
67
|
+
.notNull()
|
|
68
|
+
.references(() => memoryItems.id, { onDelete: "cascade" }),
|
|
69
|
+
messageId: text("message_id")
|
|
70
|
+
.notNull()
|
|
71
|
+
.references(() => messages.id, { onDelete: "cascade" }),
|
|
72
|
+
evidence: text("evidence"),
|
|
73
|
+
createdAt: integer("created_at").notNull(),
|
|
74
|
+
},
|
|
75
|
+
(table) => [
|
|
76
|
+
index("idx_memory_item_sources_memory_item_id").on(table.memoryItemId),
|
|
77
|
+
],
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
export const memoryItemConflicts = sqliteTable(
|
|
81
|
+
"memory_item_conflicts",
|
|
82
|
+
{
|
|
83
|
+
id: text("id").primaryKey(),
|
|
84
|
+
scopeId: text("scope_id").notNull().default("default"),
|
|
85
|
+
existingItemId: text("existing_item_id")
|
|
86
|
+
.notNull()
|
|
87
|
+
.references(() => memoryItems.id, { onDelete: "cascade" }),
|
|
88
|
+
candidateItemId: text("candidate_item_id")
|
|
89
|
+
.notNull()
|
|
90
|
+
.references(() => memoryItems.id, { onDelete: "cascade" }),
|
|
91
|
+
relationship: text("relationship").notNull(),
|
|
92
|
+
status: text("status").notNull(),
|
|
93
|
+
clarificationQuestion: text("clarification_question"),
|
|
94
|
+
resolutionNote: text("resolution_note"),
|
|
95
|
+
lastAskedAt: integer("last_asked_at"),
|
|
96
|
+
resolvedAt: integer("resolved_at"),
|
|
97
|
+
createdAt: integer("created_at").notNull(),
|
|
98
|
+
updatedAt: integer("updated_at").notNull(),
|
|
99
|
+
},
|
|
100
|
+
(table) => [index("idx_memory_item_conflicts_scope_id").on(table.scopeId)],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
export const memorySummaries = sqliteTable(
|
|
104
|
+
"memory_summaries",
|
|
105
|
+
{
|
|
106
|
+
id: text("id").primaryKey(),
|
|
107
|
+
scope: text("scope").notNull(),
|
|
108
|
+
scopeKey: text("scope_key").notNull(),
|
|
109
|
+
summary: text("summary").notNull(),
|
|
110
|
+
tokenEstimate: integer("token_estimate").notNull(),
|
|
111
|
+
version: integer("version").notNull().default(1),
|
|
112
|
+
scopeId: text("scope_id").notNull().default("default"),
|
|
113
|
+
startAt: integer("start_at").notNull(),
|
|
114
|
+
endAt: integer("end_at").notNull(),
|
|
115
|
+
createdAt: integer("created_at").notNull(),
|
|
116
|
+
updatedAt: integer("updated_at").notNull(),
|
|
117
|
+
},
|
|
118
|
+
(table) => [
|
|
119
|
+
index("idx_memory_summaries_scope_id").on(table.scopeId),
|
|
120
|
+
uniqueIndex("idx_memory_summaries_scope_scope_key").on(
|
|
121
|
+
table.scope,
|
|
122
|
+
table.scopeKey,
|
|
123
|
+
),
|
|
124
|
+
],
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
export const memoryEmbeddings = sqliteTable(
|
|
128
|
+
"memory_embeddings",
|
|
129
|
+
{
|
|
130
|
+
id: text("id").primaryKey(),
|
|
131
|
+
targetType: text("target_type").notNull(),
|
|
132
|
+
targetId: text("target_id").notNull(),
|
|
133
|
+
provider: text("provider").notNull(),
|
|
134
|
+
model: text("model").notNull(),
|
|
135
|
+
dimensions: integer("dimensions").notNull(),
|
|
136
|
+
vectorJson: text("vector_json"),
|
|
137
|
+
vectorBlob: blob("vector_blob"),
|
|
138
|
+
contentHash: text("content_hash"),
|
|
139
|
+
createdAt: integer("created_at").notNull(),
|
|
140
|
+
updatedAt: integer("updated_at").notNull(),
|
|
141
|
+
},
|
|
142
|
+
(table) => [
|
|
143
|
+
uniqueIndex("idx_memory_embeddings_target_provider_model").on(
|
|
144
|
+
table.targetType,
|
|
145
|
+
table.targetId,
|
|
146
|
+
table.provider,
|
|
147
|
+
table.model,
|
|
148
|
+
),
|
|
149
|
+
],
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
export const memoryJobs = sqliteTable("memory_jobs", {
|
|
153
|
+
id: text("id").primaryKey(),
|
|
154
|
+
type: text("type").notNull(),
|
|
155
|
+
payload: text("payload").notNull(),
|
|
156
|
+
status: text("status").notNull(),
|
|
157
|
+
attempts: integer("attempts").notNull().default(0),
|
|
158
|
+
deferrals: integer("deferrals").notNull().default(0),
|
|
159
|
+
runAfter: integer("run_after").notNull(),
|
|
160
|
+
lastError: text("last_error"),
|
|
161
|
+
startedAt: integer("started_at"),
|
|
162
|
+
createdAt: integer("created_at").notNull(),
|
|
163
|
+
updatedAt: integer("updated_at").notNull(),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export const memoryCheckpoints = sqliteTable("memory_checkpoints", {
|
|
167
|
+
key: text("key").primaryKey(),
|
|
168
|
+
value: text("value").notNull(),
|
|
169
|
+
updatedAt: integer("updated_at").notNull(),
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
export const memoryEntities = sqliteTable("memory_entities", {
|
|
173
|
+
id: text("id").primaryKey(),
|
|
174
|
+
name: text("name").notNull(),
|
|
175
|
+
type: text("type").notNull(),
|
|
176
|
+
aliases: text("aliases"),
|
|
177
|
+
description: text("description"),
|
|
178
|
+
firstSeenAt: integer("first_seen_at").notNull(),
|
|
179
|
+
lastSeenAt: integer("last_seen_at").notNull(),
|
|
180
|
+
mentionCount: integer("mention_count").notNull().default(1),
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
export const memoryEntityRelations = sqliteTable("memory_entity_relations", {
|
|
184
|
+
id: text("id").primaryKey(),
|
|
185
|
+
sourceEntityId: text("source_entity_id").notNull(),
|
|
186
|
+
targetEntityId: text("target_entity_id").notNull(),
|
|
187
|
+
relation: text("relation").notNull(),
|
|
188
|
+
evidence: text("evidence"),
|
|
189
|
+
firstSeenAt: integer("first_seen_at").notNull(),
|
|
190
|
+
lastSeenAt: integer("last_seen_at").notNull(),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
export const memoryItemEntities = sqliteTable("memory_item_entities", {
|
|
194
|
+
memoryItemId: text("memory_item_id").notNull(),
|
|
195
|
+
entityId: text("entity_id").notNull(),
|
|
196
|
+
});
|