@relaycast/engine 6.3.1 → 7.0.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/dist/adapters/node/index.d.ts.map +1 -1
- package/dist/adapters/node/index.js +2 -0
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/db/migrations/0033_dm_conversation_reservations.sql +114 -0
- package/dist/db/migrations/0034_node_load_reporting.sql +23 -0
- package/dist/db/schema.d.ts +134 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +20 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/action.d.ts +1 -0
- package/dist/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +178 -28
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.d.ts +69 -1
- package/dist/engine/agent.d.ts.map +1 -1
- package/dist/engine/agent.js +186 -58
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/dm.d.ts +32 -0
- package/dist/engine/dm.d.ts.map +1 -1
- package/dist/engine/dm.js +146 -52
- package/dist/engine/dm.js.map +1 -1
- package/dist/engine/node.d.ts +10 -6
- package/dist/engine/node.d.ts.map +1 -1
- package/dist/engine/node.js +50 -5
- package/dist/engine/node.js.map +1 -1
- package/dist/engine/nodeProvider.d.ts +2 -1
- package/dist/engine/nodeProvider.d.ts.map +1 -1
- package/dist/engine/nodeProvider.js +30 -6
- package/dist/engine/nodeProvider.js.map +1 -1
- package/dist/engine/placement.d.ts.map +1 -1
- package/dist/engine/placement.js +15 -4
- package/dist/engine/placement.js.map +1 -1
- package/dist/engine/presence.d.ts.map +1 -1
- package/dist/engine/presence.js +5 -2
- package/dist/engine/presence.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/agent.js +4 -1
- package/dist/routes/agent.js.map +1 -1
- package/package.json +3 -3
package/dist/engine/agent.js
CHANGED
|
@@ -1,10 +1,92 @@
|
|
|
1
|
-
import { eq, and, lt, inArray } from 'drizzle-orm';
|
|
2
|
-
import { agents, channels, channelMembers, actions, deliveries, nodes } from '../db/schema.js';
|
|
1
|
+
import { eq, and, gt, lt, ne, inArray } from 'drizzle-orm';
|
|
2
|
+
import { agents, agentNodeBindings, channels, channelMembers, actions, deliveries, nodes } from '../db/schema.js';
|
|
3
3
|
import { randomHex, sha256Hex } from '../lib/crypto.js';
|
|
4
4
|
import { generateId } from './snowflake.js';
|
|
5
5
|
import { codedError } from '../lib/httpError.js';
|
|
6
|
-
import { directNodeIdForAgent
|
|
7
|
-
|
|
6
|
+
import { directNodeIdForAgent } from './node.js';
|
|
7
|
+
import { runAtomicWrites } from '../ports/database.js';
|
|
8
|
+
/** How long an authenticated agent can be silent before it is no longer present. */
|
|
9
|
+
export const AGENT_LIVENESS_TTL_MS = 5 * 60 * 1000;
|
|
10
|
+
/**
|
|
11
|
+
* How long an agent must be silent before a DIFFERENT node may reclaim its
|
|
12
|
+
* name and overwrite its `token_hash` (`registerAgentViaNode`).
|
|
13
|
+
*
|
|
14
|
+
* Deliberately NOT `AGENT_LIVENESS_TTL_MS`, and deliberately not the `status`
|
|
15
|
+
* column. Presence and identity are different questions: "should the roster
|
|
16
|
+
* show this agent as here" is cheap to get wrong and self-corrects on the next
|
|
17
|
+
* heartbeat, whereas "may another node take this name and be issued a working
|
|
18
|
+
* token for it" is a credential handover that cannot be undone. They must not
|
|
19
|
+
* share a threshold, and they must not share a field that a roster read can
|
|
20
|
+
* write — gating identity on `status` meant a stale-agent sweep, triggered by
|
|
21
|
+
* an `agent list`, silently made records claimable.
|
|
22
|
+
*
|
|
23
|
+
* 24h chosen against measured production data (relaycast-cloud, 2026-08-07):
|
|
24
|
+
* of the 1,578 records whose reclaim eligibility this governs, silence was
|
|
25
|
+
* <5m: 5, 5m-24h: 9, 1d-7d: 1, >7d: 1,568. So 99.4% have been silent over a
|
|
26
|
+
* week and a 24h grace costs essentially nothing steady-state (1,569 eligible
|
|
27
|
+
* vs 1,578) while protecting the ~14 identities a human would still call live.
|
|
28
|
+
*
|
|
29
|
+
* Lower this only with fresh measurements — shortening it converts live agents
|
|
30
|
+
* into reclaimable ones.
|
|
31
|
+
*/
|
|
32
|
+
export const AGENT_RECLAIM_GRACE_MS = 24 * 60 * 60 * 1000;
|
|
33
|
+
/**
|
|
34
|
+
* Status of a row whose name has been released back to the workspace
|
|
35
|
+
* (relaycast#309). The row is retained so the four RESTRICT foreign keys to
|
|
36
|
+
* `agents.id` stay valid and the agent's history keeps its author; only the
|
|
37
|
+
* name is freed. A released row is not a roster member and never serves as a
|
|
38
|
+
* delivery target.
|
|
39
|
+
*/
|
|
40
|
+
export const RELEASED_AGENT_STATUS = 'released';
|
|
41
|
+
/**
|
|
42
|
+
* Marker separating a released agent's original name from its tombstone
|
|
43
|
+
* suffix. Reserved: registration rejects it, which is what makes
|
|
44
|
+
* {@link releasedAgentName} collision-free (see {@link assertRegistrableAgentName}).
|
|
45
|
+
*/
|
|
46
|
+
export const RELEASED_NAME_MARKER = '#released-';
|
|
47
|
+
/**
|
|
48
|
+
* Tombstone name for a released agent.
|
|
49
|
+
*
|
|
50
|
+
* Keyed on the agent id, not a timestamp: the release runs inside an atomic
|
|
51
|
+
* batch where a `UNIQUE(workspace_id, name)` violation aborts the WHOLE unit
|
|
52
|
+
* rather than failing just this statement — which is the exact defect the
|
|
53
|
+
* tombstone exists to avoid. A timestamped name can collide; an id-keyed one
|
|
54
|
+
* cannot, because the id is already unique per workspace.
|
|
55
|
+
*
|
|
56
|
+
* That argument only holds while no ordinary agent can occupy this namespace.
|
|
57
|
+
* Agent names are otherwise arbitrary strings, so without the registration
|
|
58
|
+
* guard a caller could pre-register `<name>#released-<victimId>` and make the
|
|
59
|
+
* victim's release abort. Hence the reserved marker.
|
|
60
|
+
*/
|
|
61
|
+
export function releasedAgentName(name, agentId) {
|
|
62
|
+
return `${name}${RELEASED_NAME_MARKER}${agentId}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Reject names that would land in the reserved tombstone namespace.
|
|
66
|
+
*
|
|
67
|
+
* Called on every registration path. Without it the release path is not
|
|
68
|
+
* atomic-safe: see {@link releasedAgentName}.
|
|
69
|
+
*/
|
|
70
|
+
export function assertRegistrableAgentName(name) {
|
|
71
|
+
if (name.includes(RELEASED_NAME_MARKER)) {
|
|
72
|
+
throw codedError(`Agent name "${name}" is reserved: "${RELEASED_NAME_MARKER}" marks a released agent`, 'invalid_agent_name', 400);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve the public presence status from server-observed activity. Persisted
|
|
77
|
+
* `active` is only the last reported state; it is not proof of current life.
|
|
78
|
+
*/
|
|
79
|
+
export function effectiveAgentStatus(agent, now = Date.now()) {
|
|
80
|
+
// A client-supplied/faulty clock must not create a negative age. The
|
|
81
|
+
// workspace sweep durably clamps future timestamps to its server clock so
|
|
82
|
+
// they subsequently expire normally after one TTL window.
|
|
83
|
+
const observedAt = Math.min(agent.lastSeen.getTime(), now);
|
|
84
|
+
if ((agent.status === 'active' || agent.status === 'online')
|
|
85
|
+
&& now - observedAt > AGENT_LIVENESS_TTL_MS) {
|
|
86
|
+
return 'offline';
|
|
87
|
+
}
|
|
88
|
+
return agent.status === 'online' ? 'active' : agent.status;
|
|
89
|
+
}
|
|
8
90
|
/** Detect unique constraint violations across D1, SQLite, and drizzle error shapes. */
|
|
9
91
|
function isUniqueConstraintError(err) {
|
|
10
92
|
if (!err || typeof err !== 'object')
|
|
@@ -25,31 +107,82 @@ function isUniqueConstraintError(err) {
|
|
|
25
107
|
return false;
|
|
26
108
|
}
|
|
27
109
|
export async function registerAgent(db, workspaceId, data) {
|
|
110
|
+
assertRegistrableAgentName(data.name);
|
|
28
111
|
const agentId = generateId();
|
|
29
112
|
const token = `at_live_${randomHex(16)}`;
|
|
30
113
|
const tokenHash = await sha256Hex(token);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
114
|
+
const directNodeId = directNodeIdForAgent(agentId);
|
|
115
|
+
const directNodeTokenHash = await sha256Hex(`implicit_direct:${workspaceId}:${agentId}:${randomHex(16)}`);
|
|
116
|
+
const now = new Date();
|
|
117
|
+
const [generalChannel] = await db
|
|
118
|
+
.select()
|
|
119
|
+
.from(channels)
|
|
120
|
+
.where(and(eq(channels.workspaceId, workspaceId), eq(channels.name, 'general')));
|
|
121
|
+
// Register the identity, implicit direct node, active binding, and default
|
|
122
|
+
// membership as one atomic unit. A failed direct-node write must not leave a
|
|
123
|
+
// live but undispatchable roster row behind.
|
|
34
124
|
let agent;
|
|
35
125
|
try {
|
|
36
|
-
|
|
37
|
-
.insert(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
126
|
+
const results = await runAtomicWrites(db, (writeDb) => {
|
|
127
|
+
const writes = [writeDb.insert(nodes).values({
|
|
128
|
+
id: directNodeId,
|
|
129
|
+
workspaceId,
|
|
130
|
+
name: `direct-${agentId}`,
|
|
131
|
+
tokenHash: directNodeTokenHash,
|
|
132
|
+
kind: 'ws',
|
|
133
|
+
role: 'direct',
|
|
134
|
+
deliveryAdapter: 'ws.node.v1',
|
|
135
|
+
deliveryConfig: { implicit: true, agent_id: agentId, agent_name: data.name },
|
|
136
|
+
capabilities: [],
|
|
137
|
+
maxAgents: 1,
|
|
138
|
+
activeAgents: 1,
|
|
139
|
+
tags: ['implicit', 'direct'],
|
|
140
|
+
version: 'implicit',
|
|
141
|
+
status: 'offline',
|
|
142
|
+
handlersLive: false,
|
|
143
|
+
load: 0,
|
|
144
|
+
lastHeartbeatAt: null,
|
|
145
|
+
createdAt: now,
|
|
146
|
+
}), writeDb
|
|
147
|
+
.insert(agents)
|
|
148
|
+
.values({
|
|
149
|
+
id: agentId,
|
|
150
|
+
workspaceId,
|
|
151
|
+
name: data.name,
|
|
152
|
+
handle: `@${data.name}`,
|
|
153
|
+
type: data.type || 'agent',
|
|
154
|
+
// Set status explicitly: the column DEFAULT is the deprecated 'online'
|
|
155
|
+
// on databases migrated before 0013, and SQLite can't ALTER a default.
|
|
156
|
+
status: 'active',
|
|
157
|
+
tokenHash,
|
|
158
|
+
persona: data.persona ?? null,
|
|
159
|
+
metadata: data.metadata ?? {},
|
|
160
|
+
capabilities: data.capabilities ?? null,
|
|
161
|
+
locationType: 'via_node',
|
|
162
|
+
locationNodeId: directNodeId,
|
|
163
|
+
})
|
|
164
|
+
.returning()];
|
|
165
|
+
if (generalChannel) {
|
|
166
|
+
writes.push(writeDb.insert(channelMembers).values({
|
|
167
|
+
channelId: generalChannel.id,
|
|
168
|
+
agentId,
|
|
169
|
+
role: 'member',
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
writes.push(writeDb.insert(agentNodeBindings).values({
|
|
173
|
+
id: `anb_${generateId()}`,
|
|
174
|
+
workspaceId,
|
|
175
|
+
agentId,
|
|
176
|
+
nodeId: directNodeId,
|
|
177
|
+
status: 'active',
|
|
178
|
+
sessionRef: null,
|
|
179
|
+
priority: 0,
|
|
180
|
+
createdAt: now,
|
|
181
|
+
updatedAt: now,
|
|
182
|
+
}));
|
|
183
|
+
return writes;
|
|
184
|
+
});
|
|
185
|
+
[agent] = results[1];
|
|
53
186
|
}
|
|
54
187
|
catch (insertErr) {
|
|
55
188
|
// Unique constraint violation on (workspace_id, name) → agent already exists
|
|
@@ -60,19 +193,6 @@ export async function registerAgent(db, workspaceId, data) {
|
|
|
60
193
|
}
|
|
61
194
|
throw insertErr;
|
|
62
195
|
}
|
|
63
|
-
// Auto-join #general
|
|
64
|
-
const [generalChannel] = await db
|
|
65
|
-
.select()
|
|
66
|
-
.from(channels)
|
|
67
|
-
.where(and(eq(channels.workspaceId, workspaceId), eq(channels.name, 'general')));
|
|
68
|
-
if (generalChannel) {
|
|
69
|
-
await db.insert(channelMembers).values({
|
|
70
|
-
channelId: generalChannel.id,
|
|
71
|
-
agentId,
|
|
72
|
-
role: 'member',
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
await ensureDirectNodeForAgent(db, workspaceId, agent);
|
|
76
196
|
return {
|
|
77
197
|
id: agentId,
|
|
78
198
|
// Return the workspace id so a client that joined by workspace key (and
|
|
@@ -88,33 +208,33 @@ export async function registerAgent(db, workspaceId, data) {
|
|
|
88
208
|
};
|
|
89
209
|
}
|
|
90
210
|
export async function listAgents(db, workspaceId, status) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
.from(agents)
|
|
102
|
-
.where(eq(agents.workspaceId, workspaceId));
|
|
103
|
-
}
|
|
211
|
+
// Keep the durable state aligned as a cleanup side effect, while still
|
|
212
|
+
// deriving below so correctness never depends on a cron/sweep having run.
|
|
213
|
+
await sweepStaleAgents(db, workspaceId);
|
|
214
|
+
const rows = await db
|
|
215
|
+
.select()
|
|
216
|
+
.from(agents)
|
|
217
|
+
// Released rows are tombstones retained only to keep history attributable;
|
|
218
|
+
// they are not roster members, so `agent list` must not fill with them.
|
|
219
|
+
.where(and(eq(agents.workspaceId, workspaceId), ne(agents.status, RELEASED_AGENT_STATUS)));
|
|
220
|
+
const requestedStatus = status === 'online' ? 'active' : status;
|
|
104
221
|
return rows.map((a) => ({
|
|
105
222
|
id: a.id,
|
|
106
223
|
name: a.name,
|
|
107
224
|
handle: `@${a.name}`,
|
|
108
225
|
type: a.type,
|
|
109
|
-
status: a
|
|
226
|
+
status: effectiveAgentStatus(a),
|
|
110
227
|
persona: a.persona,
|
|
111
228
|
capabilities: a.capabilities ?? null,
|
|
112
229
|
created_at: a.createdAt.toISOString(),
|
|
113
230
|
last_seen: a.lastSeen.toISOString(),
|
|
114
231
|
metadata: a.metadata,
|
|
115
|
-
}));
|
|
232
|
+
})).filter((agent) => !requestedStatus || requestedStatus === 'all' || agent.status === requestedStatus);
|
|
116
233
|
}
|
|
117
234
|
export async function getAgentByName(db, workspaceId, name) {
|
|
235
|
+
// Match roster reads: detail consumers should observe both derived and
|
|
236
|
+
// durable presence consistently within this workspace.
|
|
237
|
+
await sweepStaleAgents(db, workspaceId);
|
|
118
238
|
const [agent] = await db
|
|
119
239
|
.select()
|
|
120
240
|
.from(agents)
|
|
@@ -174,7 +294,7 @@ export async function getAgentByName(db, workspaceId, name) {
|
|
|
174
294
|
name: agent.name,
|
|
175
295
|
handle: agent.handle ?? `@${agent.name}`,
|
|
176
296
|
type: agent.type,
|
|
177
|
-
status: agent
|
|
297
|
+
status: effectiveAgentStatus(agent),
|
|
178
298
|
persona: agent.persona,
|
|
179
299
|
capabilities: agent.capabilities ?? null,
|
|
180
300
|
created_at: agent.createdAt.toISOString(),
|
|
@@ -227,7 +347,7 @@ export async function updateAgent(db, workspaceId, name, updates) {
|
|
|
227
347
|
name: updated.name,
|
|
228
348
|
handle: `@${updated.name}`,
|
|
229
349
|
type: updated.type,
|
|
230
|
-
status: updated
|
|
350
|
+
status: effectiveAgentStatus(updated),
|
|
231
351
|
persona: updated.persona,
|
|
232
352
|
capabilities: updated.capabilities ?? null,
|
|
233
353
|
created_at: updated.createdAt.toISOString(),
|
|
@@ -252,14 +372,22 @@ export async function touchLastSeen(db, agentId) {
|
|
|
252
372
|
.set({ lastSeen: new Date(), status: 'active' })
|
|
253
373
|
.where(eq(agents.id, agentId));
|
|
254
374
|
}
|
|
255
|
-
export async function sweepStaleAgents(db) {
|
|
256
|
-
const
|
|
375
|
+
export async function sweepStaleAgents(db, workspaceId) {
|
|
376
|
+
const now = new Date();
|
|
377
|
+
const cutoff = new Date(now.getTime() - AGENT_LIVENESS_TTL_MS);
|
|
378
|
+
const future = and(inArray(agents.status, ['active', 'online']), gt(agents.lastSeen, now), ...(workspaceId ? [eq(agents.workspaceId, workspaceId)] : []));
|
|
379
|
+
const normalized = await db
|
|
380
|
+
.update(agents)
|
|
381
|
+
.set({ lastSeen: now })
|
|
382
|
+
.where(future)
|
|
383
|
+
.returning({ id: agents.id });
|
|
384
|
+
const stale = and(inArray(agents.status, ['active', 'online']), lt(agents.lastSeen, cutoff), ...(workspaceId ? [eq(agents.workspaceId, workspaceId)] : []));
|
|
257
385
|
const result = await db
|
|
258
386
|
.update(agents)
|
|
259
387
|
.set({ status: 'offline' })
|
|
260
388
|
// Sweep both 'active' and legacy 'online' agents during the transition period
|
|
261
|
-
.where(
|
|
389
|
+
.where(stale)
|
|
262
390
|
.returning({ id: agents.id });
|
|
263
|
-
return result.length;
|
|
391
|
+
return normalized.length + result.length;
|
|
264
392
|
}
|
|
265
393
|
//# sourceMappingURL=agent.js.map
|
package/dist/engine/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/engine/agent.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/engine/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/dm.d.ts
CHANGED
|
@@ -7,6 +7,38 @@ interface SendDmOptions {
|
|
|
7
7
|
skipA2aIntercept?: boolean;
|
|
8
8
|
mailbox?: MailboxConfig;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Recognize a unique-constraint violation on `dm_conversation_reservations`
|
|
12
|
+
* across every driver this engine actually runs on.
|
|
13
|
+
*
|
|
14
|
+
* THIS ENGINE HAS ALREADY REGRESSED THIS EXACT BUG CLASS ONCE. `engine/agent.ts`
|
|
15
|
+
* gained `isUniqueConstraintError` in PR #193 after clean 409 handling silently
|
|
16
|
+
* became an uncaught 500 against D1, because detection only matched
|
|
17
|
+
* better-sqlite3's error shape. `engine/observerToken.ts` documents the same
|
|
18
|
+
* trap. A first version of this handler matched `.code` and `.message` on the
|
|
19
|
+
* top-level error only — which passes against better-sqlite3 in tests and would
|
|
20
|
+
* have reproduced that regression in the hosted engine, where the driver differs
|
|
21
|
+
* from the one the test suite exercises.
|
|
22
|
+
*
|
|
23
|
+
* Self-hosted runs on better-sqlite3: `.code` is `SQLITE_CONSTRAINT_UNIQUE` and
|
|
24
|
+
* `.message` reads `UNIQUE constraint failed: dm_conversation_reservations...`.
|
|
25
|
+
* The hosted engine runs Cloudflare D1 via `drizzle-orm/d1`, which prefixes
|
|
26
|
+
* `D1_ERROR: ` and may re-wrap the driver error under `.cause` rather than
|
|
27
|
+
* surfacing it at the top level. So the chain has to be walked.
|
|
28
|
+
*
|
|
29
|
+
* Two conditions must BOTH hold somewhere in the chain: the failure is a unique
|
|
30
|
+
* violation, and it names this table. The table check is what stops an unrelated
|
|
31
|
+
* constraint failure on this insert — a FK or NOT NULL on `workspace_id` — from
|
|
32
|
+
* being laundered into a tidy 409 that says something untrue about participant
|
|
33
|
+
* pairs. They are tracked independently across the walk because a wrapper may
|
|
34
|
+
* carry the code while only the wrapped cause carries the message.
|
|
35
|
+
*
|
|
36
|
+
* The walk is iterative and records every object visited in a `WeakSet`,
|
|
37
|
+
* breaking on any revisit rather than only a direct self-reference: a multi-step
|
|
38
|
+
* cycle (`A -> B -> A`) would otherwise blow the stack and turn the check meant
|
|
39
|
+
* to prevent a 500 into one itself. Same reasoning as `isObserverTokenNameConflict`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function isPairReservationConflict(err: unknown): boolean;
|
|
10
42
|
export declare function sendDm(db: Db, workspaceId: string, fromAgentId: string, data: {
|
|
11
43
|
to: string;
|
|
12
44
|
text: string;
|
package/dist/engine/dm.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dm.d.ts","sourceRoot":"","sources":["../../src/engine/dm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"dm.d.ts","sourceRoot":"","sources":["../../src/engine/dm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAoB5C,OAAO,EAAqD,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAE3G,OAAO,EAAiD,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAErG,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,UAAU,aAAa;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CA6B/D;AAkLD,wBAAsB,MAAM,CAC1B,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EACnF,OAAO,GAAE,aAAkB;;;;;;;;;;;;;;;;;;;GAgJ5B;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;kBA8Db,MAAM;oBAAc,MAAM;;;;;;;;;;KAkChG;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7D,OAAO,CAAC,SAAS,EAAE,CAAC,CAwEtB"}
|
package/dist/engine/dm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { eq, and, sql, lt, gt, isNull, inArray } from 'drizzle-orm';
|
|
2
|
-
import { messages, channels, agents, dmConversations, dmParticipants, messageAttachments, } from '../db/schema.js';
|
|
2
|
+
import { messages, channels, agents, dmConversations, dmConversationReservations, dmParticipants, messageAttachments, } from '../db/schema.js';
|
|
3
3
|
import { sha256Hex } from '../lib/crypto.js';
|
|
4
4
|
import { runAtomicWrites } from '../ports/database.js';
|
|
5
5
|
import { generateId } from './snowflake.js';
|
|
@@ -9,62 +9,156 @@ import { buildDirectDeliveryWrite, fetchDirectDeliveryOutcomes, } from './delive
|
|
|
9
9
|
import { DEFAULT_MAILBOX_DEPTH_CAP, DEFAULT_MAILBOX_TTL_MS } from './mailboxConfig.js';
|
|
10
10
|
import { codedError } from '../lib/httpError.js';
|
|
11
11
|
import { fetchAttachmentsBatch, resolveSendAttachments } from './attachments.js';
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Derivation only: this digest does not resolve or claim a conversation.
|
|
14
|
+
* Callers must atomically reserve the derived id before using it.
|
|
15
|
+
*/
|
|
16
|
+
async function deriveDmPairKey(workspaceId, agentA, agentB) {
|
|
13
17
|
const [first, second] = [agentA, agentB].sort();
|
|
14
18
|
return (await sha256Hex(`${workspaceId}:${first}:${second}`)).slice(0, 24);
|
|
15
19
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Recognize a unique-constraint violation on `dm_conversation_reservations`
|
|
22
|
+
* across every driver this engine actually runs on.
|
|
23
|
+
*
|
|
24
|
+
* THIS ENGINE HAS ALREADY REGRESSED THIS EXACT BUG CLASS ONCE. `engine/agent.ts`
|
|
25
|
+
* gained `isUniqueConstraintError` in PR #193 after clean 409 handling silently
|
|
26
|
+
* became an uncaught 500 against D1, because detection only matched
|
|
27
|
+
* better-sqlite3's error shape. `engine/observerToken.ts` documents the same
|
|
28
|
+
* trap. A first version of this handler matched `.code` and `.message` on the
|
|
29
|
+
* top-level error only — which passes against better-sqlite3 in tests and would
|
|
30
|
+
* have reproduced that regression in the hosted engine, where the driver differs
|
|
31
|
+
* from the one the test suite exercises.
|
|
32
|
+
*
|
|
33
|
+
* Self-hosted runs on better-sqlite3: `.code` is `SQLITE_CONSTRAINT_UNIQUE` and
|
|
34
|
+
* `.message` reads `UNIQUE constraint failed: dm_conversation_reservations...`.
|
|
35
|
+
* The hosted engine runs Cloudflare D1 via `drizzle-orm/d1`, which prefixes
|
|
36
|
+
* `D1_ERROR: ` and may re-wrap the driver error under `.cause` rather than
|
|
37
|
+
* surfacing it at the top level. So the chain has to be walked.
|
|
38
|
+
*
|
|
39
|
+
* Two conditions must BOTH hold somewhere in the chain: the failure is a unique
|
|
40
|
+
* violation, and it names this table. The table check is what stops an unrelated
|
|
41
|
+
* constraint failure on this insert — a FK or NOT NULL on `workspace_id` — from
|
|
42
|
+
* being laundered into a tidy 409 that says something untrue about participant
|
|
43
|
+
* pairs. They are tracked independently across the walk because a wrapper may
|
|
44
|
+
* carry the code while only the wrapped cause carries the message.
|
|
45
|
+
*
|
|
46
|
+
* The walk is iterative and records every object visited in a `WeakSet`,
|
|
47
|
+
* breaking on any revisit rather than only a direct self-reference: a multi-step
|
|
48
|
+
* cycle (`A -> B -> A`) would otherwise blow the stack and turn the check meant
|
|
49
|
+
* to prevent a 500 into one itself. Same reasoning as `isObserverTokenNameConflict`.
|
|
50
|
+
*/
|
|
51
|
+
export function isPairReservationConflict(err) {
|
|
52
|
+
const visited = new WeakSet();
|
|
53
|
+
let current = err;
|
|
54
|
+
let sawUniqueViolation = false;
|
|
55
|
+
let namesReservationTable = false;
|
|
56
|
+
while (current && typeof current === 'object') {
|
|
57
|
+
if (visited.has(current))
|
|
58
|
+
break;
|
|
59
|
+
visited.add(current);
|
|
60
|
+
const candidate = current;
|
|
61
|
+
const message = candidate.message ?? '';
|
|
62
|
+
const lowerMessage = message.toLowerCase();
|
|
63
|
+
if (candidate.code === 'SQLITE_CONSTRAINT_UNIQUE'
|
|
64
|
+
|| lowerMessage.includes('unique constraint failed')
|
|
65
|
+
|| (candidate.code === 'SQLITE_CONSTRAINT' && lowerMessage.includes('unique'))) {
|
|
66
|
+
sawUniqueViolation = true;
|
|
67
|
+
}
|
|
68
|
+
if (lowerMessage.includes('dm_conversation_reservations')) {
|
|
69
|
+
namesReservationTable = true;
|
|
70
|
+
}
|
|
71
|
+
current = candidate.cause;
|
|
72
|
+
}
|
|
73
|
+
return sawUniqueViolation && namesReservationTable;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Atomically resolve or reserve a deterministic 1:1 DM id for one exact tuple.
|
|
77
|
+
*
|
|
78
|
+
* The primary-key conflict and conditional no-op update are one SQL statement.
|
|
79
|
+
* An identical tuple returns the existing reservation; a digest collision makes
|
|
80
|
+
* the conflict predicate false, returns no row, and fails closed.
|
|
81
|
+
*
|
|
82
|
+
* TWO DISTINCT COLLISIONS, and both must fail closed with the same coded 409:
|
|
83
|
+
*
|
|
84
|
+
* 1. Same conversation_id, different pair. Caught by the PRIMARY KEY conflict
|
|
85
|
+
* target: the conditional update predicate is false, no row is returned.
|
|
86
|
+
*
|
|
87
|
+
* 2. Same pair, different conversation_id. This violates the pair_unique
|
|
88
|
+
* index, which is NOT the conflict target - SQLite only accepts one - so
|
|
89
|
+
* the statement raises SQLITE_CONSTRAINT_UNIQUE. Raised in review of PR
|
|
90
|
+
* #303 and reachable in practice: migration 0033 backfills whatever `dc.id`
|
|
91
|
+
* a legacy 1:1 already had, without requiring it to equal the current
|
|
92
|
+
* derivation, so the pair can be reserved under an id the next send will
|
|
93
|
+
* not re-derive. Left unhandled that surfaced as a 500.
|
|
94
|
+
*
|
|
95
|
+
* Failing closed is not sufficient on its own. It has to fail closed with the
|
|
96
|
+
* documented code, or a caller cannot tell a refused collision from an engine
|
|
97
|
+
* fault - which is the same distinction the rest of this seam exists to make.
|
|
98
|
+
*/
|
|
99
|
+
async function resolveOrReserveConversation(db, conversationId, workspaceId, sortedPair) {
|
|
100
|
+
const [participantOneId, participantTwoId] = sortedPair;
|
|
101
|
+
let reservation;
|
|
102
|
+
try {
|
|
103
|
+
[reservation] = await db
|
|
104
|
+
.insert(dmConversationReservations)
|
|
105
|
+
.values({
|
|
106
|
+
conversationId,
|
|
45
107
|
workspaceId,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
target: [dmParticipants.conversationId, dmParticipants.agentId],
|
|
56
|
-
set: { leftAt: null },
|
|
57
|
-
};
|
|
58
|
-
await db.insert(dmParticipants).values({
|
|
59
|
-
conversationId: deterministicConversationId,
|
|
60
|
-
agentId: fromAgentId,
|
|
61
|
-
}).onConflictDoUpdate(rejoin);
|
|
62
|
-
await db.insert(dmParticipants).values({
|
|
63
|
-
conversationId: deterministicConversationId,
|
|
64
|
-
agentId: toAgentId,
|
|
65
|
-
}).onConflictDoUpdate(rejoin);
|
|
66
|
-
conversationId = deterministicConversationId;
|
|
108
|
+
participantOneId,
|
|
109
|
+
participantTwoId,
|
|
110
|
+
})
|
|
111
|
+
.onConflictDoUpdate({
|
|
112
|
+
target: dmConversationReservations.conversationId,
|
|
113
|
+
set: { conversationId: sql `excluded.conversation_id` },
|
|
114
|
+
setWhere: and(eq(dmConversationReservations.workspaceId, workspaceId), eq(dmConversationReservations.participantOneId, participantOneId), eq(dmConversationReservations.participantTwoId, participantTwoId)),
|
|
115
|
+
})
|
|
116
|
+
.returning({ conversationId: dmConversationReservations.conversationId });
|
|
67
117
|
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
// Collision (2) above.
|
|
120
|
+
if (!isPairReservationConflict(err))
|
|
121
|
+
throw err;
|
|
122
|
+
throw codedError('DM participant pair is already reserved under a different conversation identifier', 'dm_conversation_id_collision', 409);
|
|
123
|
+
}
|
|
124
|
+
if (!reservation) {
|
|
125
|
+
throw codedError('DM conversation identifier is already reserved for a different participant pair', 'dm_conversation_id_collision', 409);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function resolveConversation(db, workspaceId, fromAgentId, toAgentId) {
|
|
129
|
+
const sortedPair = [fromAgentId, toAgentId].sort();
|
|
130
|
+
const pairKey = await deriveDmPairKey(workspaceId, sortedPair[0], sortedPair[1]);
|
|
131
|
+
const conversationId = `dm_${pairKey}`;
|
|
132
|
+
const channelId = `dmch_${pairKey}`;
|
|
133
|
+
// This is the mandatory resolution seam. It must happen before any metadata
|
|
134
|
+
// creation so exactly one tuple can win a digest collision.
|
|
135
|
+
await resolveOrReserveConversation(db, conversationId, workspaceId, sortedPair);
|
|
136
|
+
await db.insert(channels).values({
|
|
137
|
+
id: channelId,
|
|
138
|
+
workspaceId,
|
|
139
|
+
name: `dm-${pairKey}`,
|
|
140
|
+
channelType: 1,
|
|
141
|
+
}).onConflictDoNothing();
|
|
142
|
+
await db.insert(dmConversations).values({
|
|
143
|
+
id: conversationId,
|
|
144
|
+
workspaceId,
|
|
145
|
+
channelId,
|
|
146
|
+
dmType: '1:1',
|
|
147
|
+
}).onConflictDoNothing();
|
|
148
|
+
// A deterministic 1:1 is a durable relationship. Re-resolution restores a
|
|
149
|
+
// stale departure marker instead of letting roster state disagree with it.
|
|
150
|
+
const rejoin = {
|
|
151
|
+
target: [dmParticipants.conversationId, dmParticipants.agentId],
|
|
152
|
+
set: { leftAt: null },
|
|
153
|
+
};
|
|
154
|
+
await db.insert(dmParticipants).values({
|
|
155
|
+
conversationId,
|
|
156
|
+
agentId: fromAgentId,
|
|
157
|
+
}).onConflictDoUpdate(rejoin);
|
|
158
|
+
await db.insert(dmParticipants).values({
|
|
159
|
+
conversationId,
|
|
160
|
+
agentId: toAgentId,
|
|
161
|
+
}).onConflictDoUpdate(rejoin);
|
|
68
162
|
const [conv] = await db
|
|
69
163
|
.select({ id: dmConversations.id, channelId: dmConversations.channelId })
|
|
70
164
|
.from(dmConversations)
|