@data-club/ai-hub-server 0.0.1
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/auth/argon2.d.ts +72 -0
- package/dist/auth/argon2.d.ts.map +1 -0
- package/dist/auth/argon2.js +145 -0
- package/dist/auth/argon2.js.map +1 -0
- package/dist/auth/encryption.d.ts +52 -0
- package/dist/auth/encryption.d.ts.map +1 -0
- package/dist/auth/encryption.js +98 -0
- package/dist/auth/encryption.js.map +1 -0
- package/dist/auth/jwt.d.ts +133 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +147 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/middleware.d.ts +101 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +161 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/passwordPolicy.d.ts +72 -0
- package/dist/auth/passwordPolicy.d.ts.map +1 -0
- package/dist/auth/passwordPolicy.js +88 -0
- package/dist/auth/passwordPolicy.js.map +1 -0
- package/dist/auth/roleRules.d.ts +200 -0
- package/dist/auth/roleRules.d.ts.map +1 -0
- package/dist/auth/roleRules.js +365 -0
- package/dist/auth/roleRules.js.map +1 -0
- package/dist/auth/userView.d.ts +55 -0
- package/dist/auth/userView.d.ts.map +1 -0
- package/dist/auth/userView.js +77 -0
- package/dist/auth/userView.js.map +1 -0
- package/dist/bootstrap.d.ts +104 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +160 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/db/connection.d.ts +39 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +62 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/migrate.d.ts +31 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +197 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema.d.ts +1902 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +662 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/seed.d.ts +92 -0
- package/dist/db/seed.d.ts.map +1 -0
- package/dist/db/seed.js +160 -0
- package/dist/db/seed.js.map +1 -0
- package/dist/handlers/fetch.d.ts +89 -0
- package/dist/handlers/fetch.d.ts.map +1 -0
- package/dist/handlers/fetch.js +173 -0
- package/dist/handlers/fetch.js.map +1 -0
- package/dist/handlers/nextjs.d.ts +40 -0
- package/dist/handlers/nextjs.d.ts.map +1 -0
- package/dist/handlers/nextjs.js +42 -0
- package/dist/handlers/nextjs.js.map +1 -0
- package/dist/handlers/responses.d.ts +46 -0
- package/dist/handlers/responses.d.ts.map +1 -0
- package/dist/handlers/responses.js +74 -0
- package/dist/handlers/responses.js.map +1 -0
- package/dist/handlers/routeTable.d.ts +21 -0
- package/dist/handlers/routeTable.d.ts.map +1 -0
- package/dist/handlers/routeTable.js +133 -0
- package/dist/handlers/routeTable.js.map +1 -0
- package/dist/handlers/router.d.ts +37 -0
- package/dist/handlers/router.d.ts.map +1 -0
- package/dist/handlers/router.js +82 -0
- package/dist/handlers/router.js.map +1 -0
- package/dist/handlers/sse.d.ts +38 -0
- package/dist/handlers/sse.d.ts.map +1 -0
- package/dist/handlers/sse.js +52 -0
- package/dist/handlers/sse.js.map +1 -0
- package/dist/handlers/types.d.ts +96 -0
- package/dist/handlers/types.d.ts.map +1 -0
- package/dist/handlers/types.js +14 -0
- package/dist/handlers/types.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/letta/client.d.ts +355 -0
- package/dist/letta/client.d.ts.map +1 -0
- package/dist/letta/client.js +529 -0
- package/dist/letta/client.js.map +1 -0
- package/dist/letta/eventTranslator.d.ts +166 -0
- package/dist/letta/eventTranslator.d.ts.map +1 -0
- package/dist/letta/eventTranslator.js +532 -0
- package/dist/letta/eventTranslator.js.map +1 -0
- package/dist/letta/index.d.ts +13 -0
- package/dist/letta/index.d.ts.map +1 -0
- package/dist/letta/index.js +12 -0
- package/dist/letta/index.js.map +1 -0
- package/dist/letta/modelSettings.d.ts +176 -0
- package/dist/letta/modelSettings.d.ts.map +1 -0
- package/dist/letta/modelSettings.js +314 -0
- package/dist/letta/modelSettings.js.map +1 -0
- package/dist/letta/promptWrapping.d.ts +141 -0
- package/dist/letta/promptWrapping.d.ts.map +1 -0
- package/dist/letta/promptWrapping.js +213 -0
- package/dist/letta/promptWrapping.js.map +1 -0
- package/dist/letta/sandbox.d.ts +100 -0
- package/dist/letta/sandbox.d.ts.map +1 -0
- package/dist/letta/sandbox.js +151 -0
- package/dist/letta/sandbox.js.map +1 -0
- package/dist/letta/settingsFileSeed.d.ts +146 -0
- package/dist/letta/settingsFileSeed.d.ts.map +1 -0
- package/dist/letta/settingsFileSeed.js +177 -0
- package/dist/letta/settingsFileSeed.js.map +1 -0
- package/dist/letta/subprocessThrottle.d.ts +151 -0
- package/dist/letta/subprocessThrottle.d.ts.map +1 -0
- package/dist/letta/subprocessThrottle.js +195 -0
- package/dist/letta/subprocessThrottle.js.map +1 -0
- package/dist/letta/tpmRecovery.d.ts +202 -0
- package/dist/letta/tpmRecovery.d.ts.map +1 -0
- package/dist/letta/tpmRecovery.js +314 -0
- package/dist/letta/tpmRecovery.js.map +1 -0
- package/dist/letta/types.d.ts +54 -0
- package/dist/letta/types.d.ts.map +1 -0
- package/dist/letta/types.js +16 -0
- package/dist/letta/types.js.map +1 -0
- package/dist/observability/logger.d.ts +48 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +81 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +53 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +92 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/routes/admin/agents.d.ts +63 -0
- package/dist/routes/admin/agents.d.ts.map +1 -0
- package/dist/routes/admin/agents.js +461 -0
- package/dist/routes/admin/agents.js.map +1 -0
- package/dist/routes/admin/rotatingMessages.d.ts +51 -0
- package/dist/routes/admin/rotatingMessages.d.ts.map +1 -0
- package/dist/routes/admin/rotatingMessages.js +292 -0
- package/dist/routes/admin/rotatingMessages.js.map +1 -0
- package/dist/routes/admin/sessions.d.ts +61 -0
- package/dist/routes/admin/sessions.d.ts.map +1 -0
- package/dist/routes/admin/sessions.js +232 -0
- package/dist/routes/admin/sessions.js.map +1 -0
- package/dist/routes/admin/settings.d.ts +110 -0
- package/dist/routes/admin/settings.d.ts.map +1 -0
- package/dist/routes/admin/settings.js +401 -0
- package/dist/routes/admin/settings.js.map +1 -0
- package/dist/routes/admin/users.d.ts +115 -0
- package/dist/routes/admin/users.d.ts.map +1 -0
- package/dist/routes/admin/users.js +374 -0
- package/dist/routes/admin/users.js.map +1 -0
- package/dist/routes/agents.d.ts +30 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +55 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/auth.d.ts +121 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +422 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/chat.d.ts +97 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +484 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/featureToggles.d.ts +34 -0
- package/dist/routes/featureToggles.d.ts.map +1 -0
- package/dist/routes/featureToggles.js +47 -0
- package/dist/routes/featureToggles.js.map +1 -0
- package/dist/routes/health.d.ts +24 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +37 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/metrics.d.ts +35 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +106 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/sessions.d.ts +161 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +1501 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/stubs.d.ts +25 -0
- package/dist/routes/stubs.d.ts.map +1 -0
- package/dist/routes/stubs.js +25 -0
- package/dist/routes/stubs.js.map +1 -0
- package/dist/state/cron.d.ts +58 -0
- package/dist/state/cron.d.ts.map +1 -0
- package/dist/state/cron.js +160 -0
- package/dist/state/cron.js.map +1 -0
- package/dist/state/rotationRunner.d.ts +96 -0
- package/dist/state/rotationRunner.d.ts.map +1 -0
- package/dist/state/rotationRunner.js +246 -0
- package/dist/state/rotationRunner.js.map +1 -0
- package/dist/state/rotationScheduler.d.ts +76 -0
- package/dist/state/rotationScheduler.d.ts.map +1 -0
- package/dist/state/rotationScheduler.js +124 -0
- package/dist/state/rotationScheduler.js.map +1 -0
- package/dist/state/turnRegistry.d.ts +95 -0
- package/dist/state/turnRegistry.d.ts.map +1 -0
- package/dist/state/turnRegistry.js +149 -0
- package/dist/state/turnRegistry.js.map +1 -0
- package/dist/state/turnRunner.d.ts +134 -0
- package/dist/state/turnRunner.d.ts.map +1 -0
- package/dist/state/turnRunner.js +476 -0
- package/dist/state/turnRunner.js.map +1 -0
- package/package.json +47 -0
- package/src/auth/argon2.ts +152 -0
- package/src/auth/encryption.ts +110 -0
- package/src/auth/jwt.ts +217 -0
- package/src/auth/middleware.ts +250 -0
- package/src/auth/passwordPolicy.ts +99 -0
- package/src/auth/roleRules.ts +497 -0
- package/src/auth/userView.ts +88 -0
- package/src/bootstrap.ts +254 -0
- package/src/db/connection.ts +75 -0
- package/src/db/migrate.ts +212 -0
- package/src/db/schema.ts +750 -0
- package/src/db/seed.ts +236 -0
- package/src/handlers/fetch.ts +251 -0
- package/src/handlers/nextjs.ts +49 -0
- package/src/handlers/responses.ts +95 -0
- package/src/handlers/routeTable.ts +188 -0
- package/src/handlers/router.ts +96 -0
- package/src/handlers/sse.ts +55 -0
- package/src/handlers/types.ts +104 -0
- package/src/index.ts +60 -0
- package/src/letta/client.ts +860 -0
- package/src/letta/eventTranslator.ts +667 -0
- package/src/letta/index.ts +46 -0
- package/src/letta/lettaCliShim.mjs +40 -0
- package/src/letta/sandbox.ts +167 -0
- package/src/letta/settingsFileSeed.ts +254 -0
- package/src/letta/subprocessThrottle.ts +251 -0
- package/src/letta/types.ts +65 -0
- package/src/observability/logger.ts +103 -0
- package/src/observability/metrics.ts +114 -0
- package/src/routes/admin/agents.ts +574 -0
- package/src/routes/admin/rotatingMessages.ts +351 -0
- package/src/routes/admin/sessions.ts +283 -0
- package/src/routes/admin/settings.ts +463 -0
- package/src/routes/admin/users.ts +455 -0
- package/src/routes/agents.ts +66 -0
- package/src/routes/auth.ts +513 -0
- package/src/routes/chat.ts +534 -0
- package/src/routes/featureToggles.ts +52 -0
- package/src/routes/health.ts +44 -0
- package/src/routes/metrics.ts +111 -0
- package/src/routes/sessions.ts +1878 -0
- package/src/state/cron.ts +179 -0
- package/src/state/rotationRunner.ts +326 -0
- package/src/state/rotationScheduler.ts +164 -0
- package/src/state/turnRegistry.ts +210 -0
- package/src/state/turnRunner.ts +588 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-authoritative turn lifecycle (§6.6, §10).
|
|
3
|
+
*
|
|
4
|
+
* `runTurn(...)` is the one entry point that:
|
|
5
|
+
*
|
|
6
|
+
* 1. Inserts the `turn` row in status=running, phase=model_text.
|
|
7
|
+
* 2. Opens a live channel (`turnRegistry.openTurnChannel`) so concurrent
|
|
8
|
+
* resumption attempts can attach.
|
|
9
|
+
* 3. Emits `stream_start` (seq 0).
|
|
10
|
+
* 4. Calls `LettaClient.streamUserMessage(...)` which spawns a Letta
|
|
11
|
+
* Code subprocess, acquires the throttle lease, sends the user
|
|
12
|
+
* message. Returns a `ChatTurnHandle`.
|
|
13
|
+
* 5. Iterates the handle's `events` stream:
|
|
14
|
+
* - Non-terminal SDK messages → `translateSdkMessage(...)` →
|
|
15
|
+
* stamps + persists + broadcasts each emitted ai-hub event.
|
|
16
|
+
* - Terminal `result` SDK message → `finalizeTerminal(...)` →
|
|
17
|
+
* emits the closing `assistant_message_complete` + `stream_end`
|
|
18
|
+
* with the correct reason (`done` / `cancelled` / `error`).
|
|
19
|
+
* 6. On cancellation (caller signal OR `requestTurnCancellation`):
|
|
20
|
+
* calls `handle.abort()` to send `interrupt` to the CLI, keeps
|
|
21
|
+
* draining until terminal, then closes.
|
|
22
|
+
* 7. On throttle rejection (`ServerOverloadedError`): emits
|
|
23
|
+
* `error{code:"server_overloaded"}` + `stream_end{error}`.
|
|
24
|
+
* Transitions turn → failed.
|
|
25
|
+
* 8. On unhandled error: emits `error` + `stream_end{error}`,
|
|
26
|
+
* `turn.status = "failed"`.
|
|
27
|
+
* 9. Always calls `handle.close()` in finally (releases subprocess +
|
|
28
|
+
* throttle lease).
|
|
29
|
+
*
|
|
30
|
+
* @see SPECIFICATIONS.md §6.3.2 — chat / SSE
|
|
31
|
+
* @see SPECIFICATIONS.md §6.6 — state-machine ownership
|
|
32
|
+
* @see SPECIFICATIONS.md §6.9 — cancellation
|
|
33
|
+
* @see SPECIFICATIONS.md §9 — wire protocol
|
|
34
|
+
* @see SPECIFICATIONS.md §10 — state machine
|
|
35
|
+
*/
|
|
36
|
+
import { randomUUID } from "node:crypto";
|
|
37
|
+
import { eq, sql } from "drizzle-orm";
|
|
38
|
+
import { messageUsage, turn, turnEvent } from "../db/schema.js";
|
|
39
|
+
import { ServerOverloadedError } from "../letta/client.js";
|
|
40
|
+
import { finalizeAssistantMessage, finalizeTerminal, initialTranslatorState, translateSdkMessage, } from "../letta/eventTranslator.js";
|
|
41
|
+
import * as metrics from "../observability/metrics.js";
|
|
42
|
+
/** The ai-hub SSE wire-protocol version this server speaks (§9.1). */
|
|
43
|
+
export const WIRE_PROTOCOL_VERSION = "1.0";
|
|
44
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
45
|
+
/* Runner */
|
|
46
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
47
|
+
/**
|
|
48
|
+
* Runs one turn from "user pressed Send" to terminal status. Returns a
|
|
49
|
+
* promise that resolves when the runner has persisted the terminal
|
|
50
|
+
* event(s), closed the live channel, and torn down the Letta Code
|
|
51
|
+
* subprocess.
|
|
52
|
+
*
|
|
53
|
+
* The caller is expected to keep `onEvent` alive for the entire run.
|
|
54
|
+
*
|
|
55
|
+
* @param opts - see `RunTurnOpts`.
|
|
56
|
+
* @returns the turn id and terminal status.
|
|
57
|
+
*/
|
|
58
|
+
export async function runTurn(opts) {
|
|
59
|
+
const turnId = randomUUID();
|
|
60
|
+
const startedAt = new Date().toISOString();
|
|
61
|
+
const startedMs = Date.now();
|
|
62
|
+
metrics.chatRequestsTotal.inc();
|
|
63
|
+
// Step 1 — insert turn row in running/model_text.
|
|
64
|
+
opts.db
|
|
65
|
+
.insert(turn)
|
|
66
|
+
.values({
|
|
67
|
+
id: turnId,
|
|
68
|
+
sessionId: opts.sessionId,
|
|
69
|
+
status: "running",
|
|
70
|
+
phase: "model_text",
|
|
71
|
+
lastSeq: 0,
|
|
72
|
+
idempotencyKey: opts.idempotencyKey ?? null,
|
|
73
|
+
startedAt,
|
|
74
|
+
})
|
|
75
|
+
.run();
|
|
76
|
+
const { openTurnChannel } = await import("./turnRegistry.js");
|
|
77
|
+
const publisher = openTurnChannel(turnId);
|
|
78
|
+
// Compose the caller's signal with the registry-supplied cancel
|
|
79
|
+
// signal: either side can fire to cancel the turn. The registry
|
|
80
|
+
// cancel is what `POST /chat/:id/cancel` triggers from a separate
|
|
81
|
+
// HTTP request.
|
|
82
|
+
const registryCancelSignal = publisher.cancelSignal;
|
|
83
|
+
const cancelController = new AbortController();
|
|
84
|
+
const propagateCancel = () => cancelController.abort();
|
|
85
|
+
if (opts.signal) {
|
|
86
|
+
if (opts.signal.aborted)
|
|
87
|
+
cancelController.abort();
|
|
88
|
+
else
|
|
89
|
+
opts.signal.addEventListener("abort", propagateCancel, { once: true });
|
|
90
|
+
}
|
|
91
|
+
if (registryCancelSignal.aborted)
|
|
92
|
+
cancelController.abort();
|
|
93
|
+
else
|
|
94
|
+
registryCancelSignal.addEventListener("abort", propagateCancel, { once: true });
|
|
95
|
+
let translatorState = initialTranslatorState();
|
|
96
|
+
let nextSeq = 0;
|
|
97
|
+
/** Stamps + persists + broadcasts one event. Also fills in
|
|
98
|
+
* `request_id` on error events — the translator emits them without
|
|
99
|
+
* a request_id (it has no access to the request), so we add it here. */
|
|
100
|
+
const emit = (unsequenced) => {
|
|
101
|
+
let withRequestId = unsequenced;
|
|
102
|
+
if (unsequenced.event === "error") {
|
|
103
|
+
withRequestId = {
|
|
104
|
+
...unsequenced,
|
|
105
|
+
data: { ...unsequenced.data, request_id: opts.requestId },
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const event = { ...withRequestId, seq: nextSeq++ };
|
|
109
|
+
const persistedData = "data" in event ? event.data : {};
|
|
110
|
+
opts.db
|
|
111
|
+
.insert(turnEvent)
|
|
112
|
+
.values({
|
|
113
|
+
turnId,
|
|
114
|
+
seq: event.seq,
|
|
115
|
+
eventName: event.event,
|
|
116
|
+
data: persistedData,
|
|
117
|
+
state: event.state,
|
|
118
|
+
})
|
|
119
|
+
.run();
|
|
120
|
+
publisher.publish(event);
|
|
121
|
+
opts.onEvent(event);
|
|
122
|
+
return event;
|
|
123
|
+
};
|
|
124
|
+
/** Persists turn-row mutations driven by translator-state changes. */
|
|
125
|
+
const syncTurnRow = (status, phase) => {
|
|
126
|
+
const sets = { lastSeq: nextSeq - 1 };
|
|
127
|
+
if (status !== "running") {
|
|
128
|
+
sets.status = status;
|
|
129
|
+
sets.phase = null;
|
|
130
|
+
sets.finishedAt = new Date().toISOString();
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
sets.status = "running";
|
|
134
|
+
sets.phase = phase;
|
|
135
|
+
}
|
|
136
|
+
opts.db.update(turn).set(sets).where(eq(turn.id, turnId)).run();
|
|
137
|
+
};
|
|
138
|
+
let handle = null;
|
|
139
|
+
try {
|
|
140
|
+
// Step 3 — stream_start (emitted once, at the top of the run).
|
|
141
|
+
emit({
|
|
142
|
+
event: "stream_start",
|
|
143
|
+
data: {
|
|
144
|
+
protocol_version: WIRE_PROTOCOL_VERSION,
|
|
145
|
+
session_id: opts.sessionId,
|
|
146
|
+
turn_id: turnId,
|
|
147
|
+
},
|
|
148
|
+
state: { status: "running", phase: "model_text" },
|
|
149
|
+
});
|
|
150
|
+
syncTurnRow("running", "model_text");
|
|
151
|
+
if (cancelController.signal.aborted) {
|
|
152
|
+
// Caller cancelled before we even spawned — emit cancelled and
|
|
153
|
+
// bail without ever calling streamUserMessage.
|
|
154
|
+
throw new AbortLikeError();
|
|
155
|
+
}
|
|
156
|
+
// Step 4 — spawn + send. Throttle gate runs inside
|
|
157
|
+
// streamUserMessage; ServerOverloadedError is caught below and
|
|
158
|
+
// turned into a `server_overloaded` SSE error event.
|
|
159
|
+
const lettaStartedMs = Date.now();
|
|
160
|
+
try {
|
|
161
|
+
handle = await opts.lettaClient.streamUserMessage({
|
|
162
|
+
conversationId: opts.lettaConversationId,
|
|
163
|
+
lettaAgentId: opts.lettaAgentId,
|
|
164
|
+
userMessage: opts.userMessage,
|
|
165
|
+
...(opts.sandboxDir !== null ? { cwd: opts.sandboxDir } : {}),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
metrics.lettaRequestDurationMs.set(Date.now() - lettaStartedMs);
|
|
170
|
+
throw err;
|
|
171
|
+
}
|
|
172
|
+
// Wire the cancel signal to the handle's abort once we have one.
|
|
173
|
+
// If the signal already fired during the await above, abort + bail
|
|
174
|
+
// immediately. Otherwise install a listener for future aborts.
|
|
175
|
+
if (cancelController.signal.aborted) {
|
|
176
|
+
void handle.abort();
|
|
177
|
+
throw new AbortLikeError();
|
|
178
|
+
}
|
|
179
|
+
const onCancel = () => {
|
|
180
|
+
void handle?.abort();
|
|
181
|
+
};
|
|
182
|
+
cancelController.signal.addEventListener("abort", onCancel, { once: true });
|
|
183
|
+
// Step 5 — drain the SDK message stream.
|
|
184
|
+
// Track the last Letta run id we see — used to fetch usage stats
|
|
185
|
+
// after the terminal `result`. The SDK strips Letta message ids
|
|
186
|
+
// from its translated payloads, so we re-fetch via REST
|
|
187
|
+
// (`getRunUsageStats(runId)`) to get both the usage_statistics
|
|
188
|
+
// and the last assistant message id we'll stamp the badge on.
|
|
189
|
+
let lastRunId = null;
|
|
190
|
+
try {
|
|
191
|
+
for await (const sdkMsg of handle.events) {
|
|
192
|
+
// SDKAssistantMessage / SDKReasoningMessage / SDKToolCallMessage
|
|
193
|
+
// each carry `runId`. Take the most recent — a multi-step turn
|
|
194
|
+
// can have several runs, and we want the latest.
|
|
195
|
+
if (sdkMsg.runId) {
|
|
196
|
+
lastRunId = sdkMsg.runId;
|
|
197
|
+
}
|
|
198
|
+
if (sdkMsg.type === "result") {
|
|
199
|
+
// Terminal — finalizeTerminal emits the right closing events
|
|
200
|
+
// based on success / interrupted / error.
|
|
201
|
+
// Override the reason to `cancelled` when our cancel fired
|
|
202
|
+
// (even if the SDK reports success — see the cancel fixture
|
|
203
|
+
// open-question-5 finding: the SDK may complete the run if
|
|
204
|
+
// the interrupt arrived during a tool call).
|
|
205
|
+
const cancelOverride = cancelController.signal.aborted;
|
|
206
|
+
const terminalToUse = cancelOverride
|
|
207
|
+
? { ...sdkMsg, success: false, errorCode: "interrupted" }
|
|
208
|
+
: sdkMsg;
|
|
209
|
+
const step = finalizeTerminal(terminalToUse, translatorState);
|
|
210
|
+
translatorState = step.state;
|
|
211
|
+
for (const ev of step.events) {
|
|
212
|
+
emit(ev);
|
|
213
|
+
}
|
|
214
|
+
syncTurnRow(translatorState.status, null);
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
const step = translateSdkMessage(sdkMsg, translatorState);
|
|
218
|
+
translatorState = step.state;
|
|
219
|
+
for (const ev of step.events) {
|
|
220
|
+
emit(ev);
|
|
221
|
+
}
|
|
222
|
+
syncTurnRow(translatorState.status, translatorState.phase);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
cancelController.signal.removeEventListener("abort", onCancel);
|
|
227
|
+
metrics.lettaRequestDurationMs.set(Date.now() - lettaStartedMs);
|
|
228
|
+
}
|
|
229
|
+
// Step 5.5 — usage emission + persistence. Only fire on successful
|
|
230
|
+
// termination (cancelled / failed turns may or may not have a
|
|
231
|
+
// usable runId, and the badge isn't load-bearing). Best-effort:
|
|
232
|
+
// any failure here logs and continues — we already emitted
|
|
233
|
+
// stream_end above, so the turn is "done" from the client's POV.
|
|
234
|
+
if (lastRunId !== null &&
|
|
235
|
+
translatorState.status === "done") {
|
|
236
|
+
try {
|
|
237
|
+
const usage = await opts.lettaClient.getRunUsageStats(lastRunId);
|
|
238
|
+
if (usage && usage.lastAssistantMessageId) {
|
|
239
|
+
// Persist for /sessions/{id}/messages history rendering.
|
|
240
|
+
opts.db
|
|
241
|
+
.insert(messageUsage)
|
|
242
|
+
.values({
|
|
243
|
+
lettaMessageId: usage.lastAssistantMessageId,
|
|
244
|
+
sessionId: opts.sessionId,
|
|
245
|
+
promptTokens: usage.promptTokens,
|
|
246
|
+
completionTokens: usage.completionTokens,
|
|
247
|
+
totalTokens: usage.totalTokens,
|
|
248
|
+
cachedInputTokens: usage.cachedInputTokens,
|
|
249
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
250
|
+
reasoningTokens: usage.reasoningTokens,
|
|
251
|
+
contextTokens: usage.contextTokens,
|
|
252
|
+
runId: lastRunId,
|
|
253
|
+
})
|
|
254
|
+
.onConflictDoUpdate({
|
|
255
|
+
target: messageUsage.lettaMessageId,
|
|
256
|
+
set: {
|
|
257
|
+
promptTokens: usage.promptTokens,
|
|
258
|
+
completionTokens: usage.completionTokens,
|
|
259
|
+
totalTokens: usage.totalTokens,
|
|
260
|
+
cachedInputTokens: usage.cachedInputTokens,
|
|
261
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
262
|
+
reasoningTokens: usage.reasoningTokens,
|
|
263
|
+
contextTokens: usage.contextTokens,
|
|
264
|
+
runId: lastRunId,
|
|
265
|
+
},
|
|
266
|
+
})
|
|
267
|
+
.run();
|
|
268
|
+
// Live wire event — UI can attach the badge immediately
|
|
269
|
+
// without waiting for a /messages refetch.
|
|
270
|
+
opts.onEvent({
|
|
271
|
+
seq: 0, // emit() bypassed here; the stream's already drained.
|
|
272
|
+
event: "usage",
|
|
273
|
+
data: {
|
|
274
|
+
letta_message_id: usage.lastAssistantMessageId,
|
|
275
|
+
...(usage.promptTokens !== null ? { input: usage.promptTokens } : {}),
|
|
276
|
+
...(usage.completionTokens !== null ? { output: usage.completionTokens } : {}),
|
|
277
|
+
...(usage.cachedInputTokens !== null ? { cache_read: usage.cachedInputTokens } : {}),
|
|
278
|
+
...(usage.cacheWriteTokens !== null ? { cache_write: usage.cacheWriteTokens } : {}),
|
|
279
|
+
...(usage.reasoningTokens !== null ? { reasoning: usage.reasoningTokens } : {}),
|
|
280
|
+
...(usage.contextTokens !== null ? { context: usage.contextTokens } : {}),
|
|
281
|
+
...(usage.totalTokens !== null ? { total: usage.totalTokens } : {}),
|
|
282
|
+
},
|
|
283
|
+
state: { status: "done", phase: null },
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
opts.logger.warn({ err, runId: lastRunId }, "usage-stats fetch/persist failed");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
publisher.close();
|
|
292
|
+
opts.onEvent(null);
|
|
293
|
+
metrics.chatDurationMs.set(Date.now() - startedMs);
|
|
294
|
+
const finalStatus = translatorState.status;
|
|
295
|
+
opts.logger.info({
|
|
296
|
+
event: `turn_${finalStatus}`,
|
|
297
|
+
turn_id: turnId,
|
|
298
|
+
session_id: opts.sessionId,
|
|
299
|
+
}, `Turn ${finalStatus}.`);
|
|
300
|
+
return { turnId, status: finalStatus };
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
if (err instanceof ServerOverloadedError) {
|
|
304
|
+
emit({
|
|
305
|
+
event: "error",
|
|
306
|
+
data: {
|
|
307
|
+
code: "server_overloaded",
|
|
308
|
+
message: err.message,
|
|
309
|
+
},
|
|
310
|
+
state: { status: "failed", phase: null },
|
|
311
|
+
});
|
|
312
|
+
emit({
|
|
313
|
+
event: "stream_end",
|
|
314
|
+
data: { reason: "error" },
|
|
315
|
+
state: { status: "failed", phase: null },
|
|
316
|
+
});
|
|
317
|
+
syncTurnRow("failed", null);
|
|
318
|
+
publisher.close();
|
|
319
|
+
opts.onEvent(null);
|
|
320
|
+
metrics.chatDurationMs.set(Date.now() - startedMs);
|
|
321
|
+
opts.logger.warn({
|
|
322
|
+
event: "turn_rejected_overloaded",
|
|
323
|
+
turn_id: turnId,
|
|
324
|
+
session_id: opts.sessionId,
|
|
325
|
+
gate: err.gate,
|
|
326
|
+
detail: err.detail,
|
|
327
|
+
}, "Turn rejected: server overloaded.");
|
|
328
|
+
return { turnId, status: "failed" };
|
|
329
|
+
}
|
|
330
|
+
if (cancelController.signal.aborted || err instanceof AbortLikeError) {
|
|
331
|
+
// Emit any partial assistant text the turn produced before the
|
|
332
|
+
// cancel landed, then the cancelled stream_end.
|
|
333
|
+
for (const ev of finalizeAssistantMessage(translatorState, "cancelled")) {
|
|
334
|
+
emit(ev);
|
|
335
|
+
}
|
|
336
|
+
emit({
|
|
337
|
+
event: "stream_end",
|
|
338
|
+
data: { reason: "cancelled" },
|
|
339
|
+
state: { status: "cancelled", phase: null },
|
|
340
|
+
});
|
|
341
|
+
syncTurnRow("cancelled", null);
|
|
342
|
+
publisher.close();
|
|
343
|
+
opts.onEvent(null);
|
|
344
|
+
metrics.chatDurationMs.set(Date.now() - startedMs);
|
|
345
|
+
opts.logger.info({ event: "turn_cancelled", turn_id: turnId, session_id: opts.sessionId }, "Turn cancelled.");
|
|
346
|
+
return { turnId, status: "cancelled" };
|
|
347
|
+
}
|
|
348
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
349
|
+
emit({
|
|
350
|
+
event: "error",
|
|
351
|
+
data: { code: classifyServerError(err), message },
|
|
352
|
+
state: { status: "failed", phase: null },
|
|
353
|
+
});
|
|
354
|
+
emit({
|
|
355
|
+
event: "stream_end",
|
|
356
|
+
data: { reason: "error" },
|
|
357
|
+
state: { status: "failed", phase: null },
|
|
358
|
+
});
|
|
359
|
+
syncTurnRow("failed", null);
|
|
360
|
+
publisher.close();
|
|
361
|
+
opts.onEvent(null);
|
|
362
|
+
metrics.chatDurationMs.set(Date.now() - startedMs);
|
|
363
|
+
opts.logger.error({
|
|
364
|
+
event: "turn_failed",
|
|
365
|
+
turn_id: turnId,
|
|
366
|
+
session_id: opts.sessionId,
|
|
367
|
+
err: message,
|
|
368
|
+
}, "Turn failed.");
|
|
369
|
+
return { turnId, status: "failed" };
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
if (handle) {
|
|
373
|
+
try {
|
|
374
|
+
handle.close();
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
// best-effort
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (opts.signal)
|
|
381
|
+
opts.signal.removeEventListener("abort", propagateCancel);
|
|
382
|
+
registryCancelSignal.removeEventListener("abort", propagateCancel);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
386
|
+
/* Helpers */
|
|
387
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
388
|
+
/** Sentinel for "the cancel path fired" — the catch arm checks
|
|
389
|
+
* `err instanceof AbortLikeError` plus the cancel signal. */
|
|
390
|
+
class AbortLikeError extends Error {
|
|
391
|
+
constructor() {
|
|
392
|
+
super("Turn aborted.");
|
|
393
|
+
this.name = "AbortLikeError";
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Maps an unhandled runner error onto an ai-hub `error.code`.
|
|
398
|
+
*
|
|
399
|
+
* Post-migration the set of error sources is much smaller — most of
|
|
400
|
+
* the provider/upstream signals come through the translator (which
|
|
401
|
+
* maps them via `classifyErrorCode`). What lands here is
|
|
402
|
+
* spawn-failure, network-down-to-Letta, decryption errors, and other
|
|
403
|
+
* "couldn't even start the turn" failures.
|
|
404
|
+
*
|
|
405
|
+
* @param err - the unhandled error.
|
|
406
|
+
* @returns the SSE `error.code` to emit.
|
|
407
|
+
*/
|
|
408
|
+
function classifyServerError(err) {
|
|
409
|
+
if (err instanceof Error) {
|
|
410
|
+
const msg = err.message.toLowerCase();
|
|
411
|
+
if (msg.includes("letta") || msg.includes("upstream"))
|
|
412
|
+
return "provider_error";
|
|
413
|
+
}
|
|
414
|
+
return "internal";
|
|
415
|
+
}
|
|
416
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
417
|
+
/* Resumption helpers */
|
|
418
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
419
|
+
/**
|
|
420
|
+
* Replays persisted `turn_event` rows newer than `fromSeq`, returned as
|
|
421
|
+
* ai-hub-shaped events. Used by `GET /chat/:turn_id/events?from_seq=N`
|
|
422
|
+
* for the replay half of resumption.
|
|
423
|
+
*
|
|
424
|
+
* @param db - Drizzle handle.
|
|
425
|
+
* @param turnId - the turn id.
|
|
426
|
+
* @param fromSeq - replays events with `seq > fromSeq`.
|
|
427
|
+
* @returns the persisted events.
|
|
428
|
+
*
|
|
429
|
+
* @see SPECIFICATIONS.md §6.3.2 — resumption
|
|
430
|
+
*/
|
|
431
|
+
export function replayPersistedEvents(db, turnId, fromSeq) {
|
|
432
|
+
const rows = db
|
|
433
|
+
.select()
|
|
434
|
+
.from(turnEvent)
|
|
435
|
+
.where(sql `${turnEvent.turnId} = ${turnId} AND ${turnEvent.seq} > ${fromSeq}`)
|
|
436
|
+
.orderBy(turnEvent.seq)
|
|
437
|
+
.all();
|
|
438
|
+
return rows.map((row) => ({
|
|
439
|
+
event: row.eventName,
|
|
440
|
+
data: row.data,
|
|
441
|
+
state: row.state,
|
|
442
|
+
seq: row.seq,
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Idempotently marks a turn as cancelled in the DB. Returns the row's
|
|
447
|
+
* resulting status. Called by `POST /chat/:turn_id/cancel` after firing
|
|
448
|
+
* `requestTurnCancellation`. The runner's catch arm also persists
|
|
449
|
+
* `cancelled` via `syncTurnRow`; this helper just guarantees the row
|
|
450
|
+
* is updated when the runner has already exited (terminal-after-cancel
|
|
451
|
+
* race).
|
|
452
|
+
*
|
|
453
|
+
* Does not overwrite `done` / `failed` — those are terminal states.
|
|
454
|
+
*
|
|
455
|
+
* @param db - Drizzle handle.
|
|
456
|
+
* @param turnId - the turn to cancel.
|
|
457
|
+
* @returns the row's resulting status, or `null` if no such row.
|
|
458
|
+
*/
|
|
459
|
+
export function markCancelled(db, turnId) {
|
|
460
|
+
const row = db.select().from(turn).where(eq(turn.id, turnId)).get();
|
|
461
|
+
if (!row)
|
|
462
|
+
return null;
|
|
463
|
+
if (row.status === "running") {
|
|
464
|
+
db.update(turn)
|
|
465
|
+
.set({
|
|
466
|
+
status: "cancelled",
|
|
467
|
+
phase: null,
|
|
468
|
+
finishedAt: new Date().toISOString(),
|
|
469
|
+
})
|
|
470
|
+
.where(eq(turn.id, turnId))
|
|
471
|
+
.run();
|
|
472
|
+
return "cancelled";
|
|
473
|
+
}
|
|
474
|
+
return row.status;
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=turnRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turnRunner.js","sourceRoot":"","sources":["../../src/state/turnRunner.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@data-club/ai-hub-server",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Server package for the data-club ai-hub: Web-Standard Fetch handlers, Letta integration, SSE wire protocol, RBAC, admin endpoints. Mounts into per-customer Next.js wrappers via createNextRouteHandler. See docs/SPECIFICATIONS.md §6.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@data-club/letta-code": "^0.26.2",
|
|
22
|
+
"@letta-ai/letta-client": "^1.11.0",
|
|
23
|
+
"@letta-ai/letta-code-sdk": "0.1.14",
|
|
24
|
+
"@node-rs/argon2": "^2.0.2",
|
|
25
|
+
"better-sqlite3": "^11.5.0",
|
|
26
|
+
"drizzle-orm": "^0.36.4",
|
|
27
|
+
"jose": "^5.9.6",
|
|
28
|
+
"pino": "^9.5.0",
|
|
29
|
+
"zod": "^3.23.8",
|
|
30
|
+
"@data-club/ai-hub": "0.0.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
34
|
+
"dotenv": "^16.4.7",
|
|
35
|
+
"pino-pretty": "^11.3.0",
|
|
36
|
+
"tsx": "^4.19.2",
|
|
37
|
+
"typescript": "^5.5.4",
|
|
38
|
+
"vitest": "^1.6.1"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.build.json",
|
|
42
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
43
|
+
"test": "vitest run --passWithNoTests",
|
|
44
|
+
"dev:server": "tsx --tsconfig ./tsconfig.json dev/server.ts",
|
|
45
|
+
"clean": "rm -rf dist .tsbuildinfo"
|
|
46
|
+
}
|
|
47
|
+
}
|