@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,461 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/admin/agents/*` — power_user + admin + super_admin catalog management.
|
|
3
|
+
*
|
|
4
|
+
* Three endpoints (no DELETE by design — agents are archive-only in v1):
|
|
5
|
+
*
|
|
6
|
+
* - `GET /admin/agents` — every agent in the deployment, including archived
|
|
7
|
+
* ones. Lets the admin UI render the catalog with the archived rows
|
|
8
|
+
* filtered in/out via the `[☐ Show archived]` toggle ([06-admin-agents.md]).
|
|
9
|
+
* - `POST /admin/agents` — body `{ display_name, letta_agent_id, tpm_recovery_enabled?, max_recovery_attempts?, default_retry_after_seconds? }`.
|
|
10
|
+
* Validates `letta_agent_id` against Letta (Step 5 wires the real check;
|
|
11
|
+
* Step 4 stubs it through with a `TODO`).
|
|
12
|
+
* - `PATCH /admin/agents/:id` — body `{ display_name?, letta_agent_id?, tpm_recovery_enabled?, max_recovery_attempts?, default_retry_after_seconds?, is_archived? }`.
|
|
13
|
+
* Archive / unarchive is just `{ is_archived: true | false }`. All fields
|
|
14
|
+
* optional; empty patch is a 200 no-op.
|
|
15
|
+
*
|
|
16
|
+
* **No DELETE.** Per §6.3.4 / §11, agents cannot be hard-deleted in v1 —
|
|
17
|
+
* archiving keeps existing sessions readable + writable while preventing new
|
|
18
|
+
* sessions from starting against the agent. Step 12's UI exposes only
|
|
19
|
+
* archive/unarchive; this server enforces the same.
|
|
20
|
+
*
|
|
21
|
+
* @see SPECIFICATIONS.md §6.3.4 — admin agents endpoints
|
|
22
|
+
* @see SPECIFICATIONS.md §6.5 — TPM recovery defaults
|
|
23
|
+
* @see ui-sketches/06-admin-agents.md
|
|
24
|
+
*/
|
|
25
|
+
import { randomUUID } from "node:crypto";
|
|
26
|
+
import { asc, eq } from "drizzle-orm";
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
import { protectedRoute } from "../../auth/middleware.js";
|
|
29
|
+
import { agent, rotatingMessage } from "../../db/schema.js";
|
|
30
|
+
import { errorResponse, jsonResponse, notFound, validationError, } from "../../handlers/responses.js";
|
|
31
|
+
import { seedDirExists, validateSeedName } from "../../letta/sandbox.js";
|
|
32
|
+
import { seedAgentToolsetNone } from "../../letta/settingsFileSeed.js";
|
|
33
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
34
|
+
/* Helpers */
|
|
35
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
36
|
+
/**
|
|
37
|
+
* Wire-format view of an `agent` row for admin consumption. Differs from the
|
|
38
|
+
* user-facing `/agents` response: this one includes `letta_agent_id` (admins
|
|
39
|
+
* need to see + edit it), the TPM-recovery fields, and the archive flag.
|
|
40
|
+
*
|
|
41
|
+
* @param row - the agent row.
|
|
42
|
+
* @returns the JSON-safe response shape.
|
|
43
|
+
*/
|
|
44
|
+
function adminAgentView(row) {
|
|
45
|
+
return {
|
|
46
|
+
id: row.id,
|
|
47
|
+
display_name: row.displayName,
|
|
48
|
+
letta_agent_id: row.lettaAgentId,
|
|
49
|
+
tpm_recovery_enabled: row.tpmRecoveryEnabled,
|
|
50
|
+
max_recovery_attempts: row.maxRecoveryAttempts,
|
|
51
|
+
default_retry_after_seconds: row.defaultRetryAfterSeconds,
|
|
52
|
+
stream_idle_timeout_seconds: row.streamIdleTimeoutSeconds,
|
|
53
|
+
sandbox_seed_name: row.sandboxSeedName,
|
|
54
|
+
fork_source_conversation_id: row.forkSourceConversationId,
|
|
55
|
+
is_archived: row.isArchived,
|
|
56
|
+
created_at: row.createdAt,
|
|
57
|
+
updated_at: row.updatedAt,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** ISO-8601 timestamp with millisecond precision. */
|
|
61
|
+
function nowIso() {
|
|
62
|
+
return new Date().toISOString();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validates that `letta_agent_id` references a real Letta-side agent.
|
|
66
|
+
*
|
|
67
|
+
* Calls `ctx.lettaClient.retrieveAgent(...)` (which wraps
|
|
68
|
+
* `client.agents.retrieve` per §6.4 / §6.4.1) and returns `false` when the
|
|
69
|
+
* SDK reports the agent doesn't exist. The handler turns the `false` into
|
|
70
|
+
* a 400 `letta_agent_not_found` so the React modal can surface the error
|
|
71
|
+
* inline on the field ([06-admin-agents.md]). Any non-404 SDK error
|
|
72
|
+
* propagates so the route catch-all returns a 500.
|
|
73
|
+
*
|
|
74
|
+
* @param ctx - server context (carries the Letta client).
|
|
75
|
+
* @param lettaAgentId - candidate id.
|
|
76
|
+
* @returns `true` if the id resolves to a live Letta agent.
|
|
77
|
+
*
|
|
78
|
+
* @see SPECIFICATIONS.md §6.4.1 — first-class SDK surfaces
|
|
79
|
+
*/
|
|
80
|
+
async function validateLettaAgentId(ctx, lettaAgentId) {
|
|
81
|
+
const found = await ctx.lettaClient.retrieveAgent(lettaAgentId);
|
|
82
|
+
return found !== null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Validates the (optional) `sandbox_seed_name` and (optional)
|
|
86
|
+
* `fork_source_conversation_id` against the filesystem + Letta. Pure for
|
|
87
|
+
* the success / regex-fail cases; talks to Letta only when a fork source
|
|
88
|
+
* was supplied. The caller maps the outcome to one of:
|
|
89
|
+
* - `400 seed_name_invalid`
|
|
90
|
+
* - `400 seed_dir_not_found`
|
|
91
|
+
* - `400 fork_source_not_found`
|
|
92
|
+
* - `400 fork_source_agent_mismatch`
|
|
93
|
+
*
|
|
94
|
+
* `null` / `undefined` values short-circuit the corresponding check —
|
|
95
|
+
* those fields are explicitly opt-in.
|
|
96
|
+
*
|
|
97
|
+
* @param ctx - server context (filesDir + lettaClient).
|
|
98
|
+
* @param fields - candidate values.
|
|
99
|
+
* @returns the resolved outcome.
|
|
100
|
+
*/
|
|
101
|
+
async function validateSpecializedFields(ctx, fields) {
|
|
102
|
+
if (fields.sandboxSeedName !== undefined &&
|
|
103
|
+
fields.sandboxSeedName !== null &&
|
|
104
|
+
fields.sandboxSeedName.length > 0) {
|
|
105
|
+
const nameValidation = validateSeedName(fields.sandboxSeedName);
|
|
106
|
+
if (nameValidation !== "ok") {
|
|
107
|
+
return { kind: "seed_name_invalid" };
|
|
108
|
+
}
|
|
109
|
+
if (!seedDirExists(ctx.filesDir, fields.sandboxSeedName)) {
|
|
110
|
+
return { kind: "seed_dir_not_found" };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (fields.forkSourceConversationId !== undefined &&
|
|
114
|
+
fields.forkSourceConversationId !== null &&
|
|
115
|
+
fields.forkSourceConversationId.length > 0) {
|
|
116
|
+
const ref = fields.forkSourceConversationId;
|
|
117
|
+
if (ref.startsWith("rmsg-")) {
|
|
118
|
+
// The base is a rotating starting message. Validate against the
|
|
119
|
+
// `rotating_message` catalog instead of Letta — its prepared
|
|
120
|
+
// conversation may not exist yet (no rotation has run), which is fine
|
|
121
|
+
// at write time; `POST /sessions` handles the "not ready" case.
|
|
122
|
+
const rmsg = ctx.db
|
|
123
|
+
.select()
|
|
124
|
+
.from(rotatingMessage)
|
|
125
|
+
.where(eq(rotatingMessage.id, ref))
|
|
126
|
+
.get();
|
|
127
|
+
if (!rmsg || rmsg.isArchived) {
|
|
128
|
+
return { kind: "rotating_message_not_found" };
|
|
129
|
+
}
|
|
130
|
+
if (rmsg.lettaAgentId !== fields.expectedLettaAgentId) {
|
|
131
|
+
return {
|
|
132
|
+
kind: "rotating_message_agent_mismatch",
|
|
133
|
+
expectedAgentId: fields.expectedLettaAgentId,
|
|
134
|
+
actualAgentId: rmsg.lettaAgentId,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const conv = await ctx.lettaClient.retrieveConversation(ref);
|
|
140
|
+
if (!conv) {
|
|
141
|
+
return { kind: "fork_source_not_found" };
|
|
142
|
+
}
|
|
143
|
+
if (conv.agentId !== fields.expectedLettaAgentId) {
|
|
144
|
+
return {
|
|
145
|
+
kind: "fork_source_agent_mismatch",
|
|
146
|
+
expectedAgentId: fields.expectedLettaAgentId,
|
|
147
|
+
actualAgentId: conv.agentId,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { kind: "ok" };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Maps a `SpecializedFieldsValidation` failure to the canonical
|
|
156
|
+
* `errorResponse(400, code, message)`. Keeps the create + patch handlers
|
|
157
|
+
* tidy.
|
|
158
|
+
*/
|
|
159
|
+
function respondSpecializedFailure(failure) {
|
|
160
|
+
switch (failure.kind) {
|
|
161
|
+
case "seed_name_invalid":
|
|
162
|
+
return errorResponse(400, "seed_name_invalid", "sandbox_seed_name must match ^[a-zA-Z0-9_-]+$ (no slashes, no dots).");
|
|
163
|
+
case "seed_dir_not_found":
|
|
164
|
+
return errorResponse(400, "seed_dir_not_found", "No seed folder with that name was found under AI_HUB_FILES_DIR/seeds/.");
|
|
165
|
+
case "fork_source_not_found":
|
|
166
|
+
return errorResponse(400, "fork_source_not_found", "No Letta conversation with that id was found.");
|
|
167
|
+
case "fork_source_agent_mismatch":
|
|
168
|
+
return errorResponse(400, "fork_source_agent_mismatch", `The fork source belongs to Letta agent ${failure.actualAgentId}, ` +
|
|
169
|
+
`but this ai-hub agent points at ${failure.expectedAgentId}. Letta's fork ` +
|
|
170
|
+
`API requires the new conversation to share the source's agent.`);
|
|
171
|
+
case "rotating_message_not_found":
|
|
172
|
+
return errorResponse(400, "rotating_message_not_found", "No active rotating starting message with that id was found.");
|
|
173
|
+
case "rotating_message_agent_mismatch":
|
|
174
|
+
return errorResponse(400, "rotating_message_agent_mismatch", `The rotating starting message runs against Letta agent ${failure.actualAgentId}, ` +
|
|
175
|
+
`but this ai-hub agent points at ${failure.expectedAgentId}. A rotating message ` +
|
|
176
|
+
`can only back agents that share its Letta agent (Letta forks must be same-agent).`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Best-effort seed of `~/.letta/settings.json` with `{toolset: "none"}` for
|
|
181
|
+
* the given Letta agent id. Idempotent. Logs the outcome but **does not
|
|
182
|
+
* throw**: if seeding fails (read-only home dir, permission denied, …) the
|
|
183
|
+
* agent creation should still succeed — the toolset suppression is then
|
|
184
|
+
* a runtime concern the operator notices when chats start producing weird
|
|
185
|
+
* file-edit tool calls. The intent here is hands-off automation, not a
|
|
186
|
+
* required precondition.
|
|
187
|
+
*
|
|
188
|
+
* @param ctx - server context (for logging).
|
|
189
|
+
* @param lettaAgentId - id to seed the toolset preference for.
|
|
190
|
+
*
|
|
191
|
+
* @see ../../letta/settingsFileSeed.ts
|
|
192
|
+
*/
|
|
193
|
+
function seedToolsetNoneBestEffort(ctx, lettaAgentId) {
|
|
194
|
+
try {
|
|
195
|
+
seedAgentToolsetNone({
|
|
196
|
+
agentId: lettaAgentId,
|
|
197
|
+
lettaBaseUrl: process.env.LETTA_BASE_URL,
|
|
198
|
+
logger: ctx.logger,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
ctx.logger.warn({
|
|
203
|
+
agent_id: lettaAgentId,
|
|
204
|
+
err: err instanceof Error ? err.message : String(err),
|
|
205
|
+
event: "letta_code_settings_seed_failed",
|
|
206
|
+
}, "Failed to seed Letta Code toolset preference; continuing anyway.");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
210
|
+
/* GET /admin/agents */
|
|
211
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
212
|
+
/**
|
|
213
|
+
* `GET /admin/agents` — every agent in the deployment, archived rows
|
|
214
|
+
* included. The admin UI filters them client-side via the
|
|
215
|
+
* `[☐ Show archived]` toggle ([06-admin-agents.md]).
|
|
216
|
+
*
|
|
217
|
+
* Sorted by `display_name` for stable rendering.
|
|
218
|
+
*
|
|
219
|
+
* Available to `power_user`+ per the §8.2 matrix.
|
|
220
|
+
*
|
|
221
|
+
* @see SPECIFICATIONS.md §6.3.4
|
|
222
|
+
*/
|
|
223
|
+
export const handleListAgents = protectedRoute({ requiredRole: "power_user" }, async (_req, ctx) => {
|
|
224
|
+
const rows = ctx.db.select().from(agent).orderBy(asc(agent.displayName)).all();
|
|
225
|
+
return jsonResponse(200, { agents: rows.map(adminAgentView) });
|
|
226
|
+
});
|
|
227
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
228
|
+
/* POST /admin/agents */
|
|
229
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
230
|
+
/** Body for `POST /admin/agents`. */
|
|
231
|
+
const createAgentSchema = z
|
|
232
|
+
.object({
|
|
233
|
+
display_name: z.string().min(1).max(255),
|
|
234
|
+
letta_agent_id: z.string().min(1).max(255),
|
|
235
|
+
tpm_recovery_enabled: z.boolean().optional(),
|
|
236
|
+
max_recovery_attempts: z.number().int().min(0).max(10).optional(),
|
|
237
|
+
default_retry_after_seconds: z.number().int().min(1).max(3600).optional(),
|
|
238
|
+
/** Per-agent inter-event idle watchdog (seconds). Default 60. */
|
|
239
|
+
stream_idle_timeout_seconds: z.number().int().min(5).max(3600).optional(),
|
|
240
|
+
/**
|
|
241
|
+
* Step-12.5 — name of the seed folder under `{AI_HUB_FILES_DIR}/seeds/`.
|
|
242
|
+
* `null` or `""` clears the field; non-null strings are validated
|
|
243
|
+
* against the safe-name regex + existence on disk.
|
|
244
|
+
*/
|
|
245
|
+
sandbox_seed_name: z.string().max(128).nullable().optional(),
|
|
246
|
+
/**
|
|
247
|
+
* Step-12.5 — Letta conversation id (`conv-…`) to fork from at session
|
|
248
|
+
* create. `null` or `""` clears the field; non-null strings are
|
|
249
|
+
* validated via `client.conversations.retrieve` + agent-id match.
|
|
250
|
+
*/
|
|
251
|
+
fork_source_conversation_id: z.string().max(255).nullable().optional(),
|
|
252
|
+
})
|
|
253
|
+
.strict();
|
|
254
|
+
/**
|
|
255
|
+
* `POST /admin/agents` — create a new ai-hub agent (catalog entry).
|
|
256
|
+
*
|
|
257
|
+
* Validates the Letta-side id via `validateLettaAgentId` (Step 4 stub —
|
|
258
|
+
* always passes; Step 5 wires the real check against the Letta SDK). On a
|
|
259
|
+
* Letta-id miss returns 400 `letta_agent_not_found` with the offending field
|
|
260
|
+
* named, so the React modal can surface the error inline on the field
|
|
261
|
+
* ([06-admin-agents.md]).
|
|
262
|
+
*
|
|
263
|
+
* @see SPECIFICATIONS.md §6.3.4
|
|
264
|
+
* @see ui-sketches/06-admin-agents.md
|
|
265
|
+
*/
|
|
266
|
+
export const handleCreateAgent = protectedRoute({ requiredRole: "power_user" }, async (req, ctx, auth) => {
|
|
267
|
+
let raw;
|
|
268
|
+
try {
|
|
269
|
+
raw = await req.json();
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return validationError("Request body must be valid JSON.");
|
|
273
|
+
}
|
|
274
|
+
const parsed = createAgentSchema.safeParse(raw);
|
|
275
|
+
if (!parsed.success) {
|
|
276
|
+
return validationError(parsed.error.issues[0]?.message ?? "Invalid request body.");
|
|
277
|
+
}
|
|
278
|
+
const body = parsed.data;
|
|
279
|
+
const ok = await validateLettaAgentId(ctx, body.letta_agent_id);
|
|
280
|
+
if (!ok) {
|
|
281
|
+
return errorResponse(400, "letta_agent_not_found", "No Letta agent with that id was found.");
|
|
282
|
+
}
|
|
283
|
+
// Step-12.5 — validate the optional sandbox + fork fields. Runs AFTER
|
|
284
|
+
// the letta_agent_id check so the agent-mismatch error has a clear
|
|
285
|
+
// expected value to compare against (and so an admin entering a bad
|
|
286
|
+
// letta_agent_id only sees that error, not the cascading 400 from
|
|
287
|
+
// the fork validator).
|
|
288
|
+
const specialized = await validateSpecializedFields(ctx, {
|
|
289
|
+
sandboxSeedName: body.sandbox_seed_name,
|
|
290
|
+
forkSourceConversationId: body.fork_source_conversation_id,
|
|
291
|
+
expectedLettaAgentId: body.letta_agent_id,
|
|
292
|
+
});
|
|
293
|
+
if (specialized.kind !== "ok") {
|
|
294
|
+
return respondSpecializedFailure(specialized);
|
|
295
|
+
}
|
|
296
|
+
const id = randomUUID();
|
|
297
|
+
// Empty strings normalize to null so the storage matches the
|
|
298
|
+
// "field cleared" semantics the React modal sends.
|
|
299
|
+
const normalizedSeedName = body.sandbox_seed_name && body.sandbox_seed_name.length > 0
|
|
300
|
+
? body.sandbox_seed_name
|
|
301
|
+
: null;
|
|
302
|
+
const normalizedForkSrc = body.fork_source_conversation_id &&
|
|
303
|
+
body.fork_source_conversation_id.length > 0
|
|
304
|
+
? body.fork_source_conversation_id
|
|
305
|
+
: null;
|
|
306
|
+
ctx.db
|
|
307
|
+
.insert(agent)
|
|
308
|
+
.values({
|
|
309
|
+
id,
|
|
310
|
+
displayName: body.display_name,
|
|
311
|
+
lettaAgentId: body.letta_agent_id,
|
|
312
|
+
tpmRecoveryEnabled: body.tpm_recovery_enabled ?? false,
|
|
313
|
+
maxRecoveryAttempts: body.max_recovery_attempts ?? 2,
|
|
314
|
+
defaultRetryAfterSeconds: body.default_retry_after_seconds ?? 65,
|
|
315
|
+
streamIdleTimeoutSeconds: body.stream_idle_timeout_seconds ?? 60,
|
|
316
|
+
sandboxSeedName: normalizedSeedName,
|
|
317
|
+
forkSourceConversationId: normalizedForkSrc,
|
|
318
|
+
isArchived: false,
|
|
319
|
+
})
|
|
320
|
+
.run();
|
|
321
|
+
const row = ctx.db.select().from(agent).where(eq(agent.id, id)).get();
|
|
322
|
+
if (!row)
|
|
323
|
+
throw new Error("Just-inserted agent vanished.");
|
|
324
|
+
// Seed `~/.letta/settings.json` so Letta Code's bundled CLI suppresses
|
|
325
|
+
// its auto-toolset (Read/Write/Bash/etc.) when chat sessions spawn
|
|
326
|
+
// against this agent. ai-hub wants only the tools the ADE admin
|
|
327
|
+
// explicitly attached. Best-effort: a write failure logs + continues.
|
|
328
|
+
seedToolsetNoneBestEffort(ctx, row.lettaAgentId);
|
|
329
|
+
ctx.logger.info({
|
|
330
|
+
actor_id: auth.user.id,
|
|
331
|
+
agent_id: row.id,
|
|
332
|
+
letta_agent_id: row.lettaAgentId,
|
|
333
|
+
event: "admin_agent_created",
|
|
334
|
+
}, "Admin created an ai-hub agent.");
|
|
335
|
+
return jsonResponse(201, adminAgentView(row));
|
|
336
|
+
});
|
|
337
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
338
|
+
/* PATCH /admin/agents/:id */
|
|
339
|
+
/* ────────────────────────────────────────────────────────────────────────── */
|
|
340
|
+
/** Body for `PATCH /admin/agents/:id`. All fields optional; empty patch is a no-op. */
|
|
341
|
+
const patchAgentSchema = z
|
|
342
|
+
.object({
|
|
343
|
+
display_name: z.string().min(1).max(255).optional(),
|
|
344
|
+
letta_agent_id: z.string().min(1).max(255).optional(),
|
|
345
|
+
tpm_recovery_enabled: z.boolean().optional(),
|
|
346
|
+
max_recovery_attempts: z.number().int().min(0).max(10).optional(),
|
|
347
|
+
default_retry_after_seconds: z.number().int().min(1).max(3600).optional(),
|
|
348
|
+
stream_idle_timeout_seconds: z.number().int().min(5).max(3600).optional(),
|
|
349
|
+
is_archived: z.boolean().optional(),
|
|
350
|
+
/** Step-12.5 — nullable to support explicit clear. */
|
|
351
|
+
sandbox_seed_name: z.string().max(128).nullable().optional(),
|
|
352
|
+
/** Step-12.5 — nullable to support explicit clear. */
|
|
353
|
+
fork_source_conversation_id: z.string().max(255).nullable().optional(),
|
|
354
|
+
})
|
|
355
|
+
.strict();
|
|
356
|
+
/**
|
|
357
|
+
* `PATCH /admin/agents/:id` — partial update.
|
|
358
|
+
*
|
|
359
|
+
* If `letta_agent_id` is in the patch, the same Letta-side validation runs
|
|
360
|
+
* as on create. `is_archived` is the archive / unarchive toggle (no separate
|
|
361
|
+
* endpoint). All fields optional; an empty patch (`{}`) is a 200 no-op that
|
|
362
|
+
* echoes the row unchanged.
|
|
363
|
+
*
|
|
364
|
+
* @see SPECIFICATIONS.md §6.3.4
|
|
365
|
+
* @see ui-sketches/06-admin-agents.md
|
|
366
|
+
*/
|
|
367
|
+
export const handlePatchAgent = protectedRoute({ requiredRole: "power_user" }, async (req, ctx, auth, params) => {
|
|
368
|
+
const id = params.id;
|
|
369
|
+
if (!id)
|
|
370
|
+
return notFound();
|
|
371
|
+
let raw;
|
|
372
|
+
try {
|
|
373
|
+
raw = await req.json();
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
return validationError("Request body must be valid JSON.");
|
|
377
|
+
}
|
|
378
|
+
const parsed = patchAgentSchema.safeParse(raw);
|
|
379
|
+
if (!parsed.success) {
|
|
380
|
+
return validationError(parsed.error.issues[0]?.message ?? "Invalid request body.");
|
|
381
|
+
}
|
|
382
|
+
const body = parsed.data;
|
|
383
|
+
const existing = ctx.db.select().from(agent).where(eq(agent.id, id)).get();
|
|
384
|
+
if (!existing)
|
|
385
|
+
return notFound("Agent not found.");
|
|
386
|
+
if (body.letta_agent_id !== undefined && body.letta_agent_id !== existing.lettaAgentId) {
|
|
387
|
+
const ok = await validateLettaAgentId(ctx, body.letta_agent_id);
|
|
388
|
+
if (!ok) {
|
|
389
|
+
return errorResponse(400, "letta_agent_not_found", "No Letta agent with that id was found.");
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Step-12.5 — validate the specialized fields against the
|
|
393
|
+
// *effective* letta_agent_id (the patched value when supplied,
|
|
394
|
+
// otherwise the existing one). Only validates fields touched by
|
|
395
|
+
// this PATCH; unchanged fields are skipped.
|
|
396
|
+
const effectiveLettaAgentId = body.letta_agent_id ?? existing.lettaAgentId;
|
|
397
|
+
const seedTouched = body.sandbox_seed_name !== undefined;
|
|
398
|
+
const forkTouched = body.fork_source_conversation_id !== undefined;
|
|
399
|
+
if (seedTouched || forkTouched) {
|
|
400
|
+
const specialized = await validateSpecializedFields(ctx, {
|
|
401
|
+
sandboxSeedName: seedTouched ? body.sandbox_seed_name : null,
|
|
402
|
+
forkSourceConversationId: forkTouched
|
|
403
|
+
? body.fork_source_conversation_id
|
|
404
|
+
: null,
|
|
405
|
+
expectedLettaAgentId: effectiveLettaAgentId,
|
|
406
|
+
});
|
|
407
|
+
if (specialized.kind !== "ok") {
|
|
408
|
+
return respondSpecializedFailure(specialized);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const update = { updatedAt: nowIso() };
|
|
412
|
+
if (body.display_name !== undefined)
|
|
413
|
+
update.displayName = body.display_name;
|
|
414
|
+
if (body.letta_agent_id !== undefined)
|
|
415
|
+
update.lettaAgentId = body.letta_agent_id;
|
|
416
|
+
if (body.tpm_recovery_enabled !== undefined)
|
|
417
|
+
update.tpmRecoveryEnabled = body.tpm_recovery_enabled;
|
|
418
|
+
if (body.max_recovery_attempts !== undefined)
|
|
419
|
+
update.maxRecoveryAttempts = body.max_recovery_attempts;
|
|
420
|
+
if (body.default_retry_after_seconds !== undefined)
|
|
421
|
+
update.defaultRetryAfterSeconds = body.default_retry_after_seconds;
|
|
422
|
+
if (body.stream_idle_timeout_seconds !== undefined)
|
|
423
|
+
update.streamIdleTimeoutSeconds = body.stream_idle_timeout_seconds;
|
|
424
|
+
if (body.is_archived !== undefined)
|
|
425
|
+
update.isArchived = body.is_archived;
|
|
426
|
+
// Empty strings + null both normalize to null (consistent with create).
|
|
427
|
+
if (body.sandbox_seed_name !== undefined) {
|
|
428
|
+
update.sandboxSeedName =
|
|
429
|
+
body.sandbox_seed_name && body.sandbox_seed_name.length > 0
|
|
430
|
+
? body.sandbox_seed_name
|
|
431
|
+
: null;
|
|
432
|
+
}
|
|
433
|
+
if (body.fork_source_conversation_id !== undefined) {
|
|
434
|
+
update.forkSourceConversationId =
|
|
435
|
+
body.fork_source_conversation_id &&
|
|
436
|
+
body.fork_source_conversation_id.length > 0
|
|
437
|
+
? body.fork_source_conversation_id
|
|
438
|
+
: null;
|
|
439
|
+
}
|
|
440
|
+
ctx.db.update(agent).set(update).where(eq(agent.id, id)).run();
|
|
441
|
+
const fresh = ctx.db.select().from(agent).where(eq(agent.id, id)).get();
|
|
442
|
+
if (!fresh)
|
|
443
|
+
return notFound();
|
|
444
|
+
// If the patch re-pointed the ai-hub agent at a different Letta agent,
|
|
445
|
+
// seed the new agent's toolset preference too. (We deliberately do NOT
|
|
446
|
+
// remove the old agent's seeded record — it may still be backing live
|
|
447
|
+
// sessions per the §11 schema note: existing sessions keep their
|
|
448
|
+
// original `letta_conversation_id` against the original Letta agent.)
|
|
449
|
+
if (body.letta_agent_id !== undefined &&
|
|
450
|
+
body.letta_agent_id !== existing.lettaAgentId) {
|
|
451
|
+
seedToolsetNoneBestEffort(ctx, body.letta_agent_id);
|
|
452
|
+
}
|
|
453
|
+
ctx.logger.info({
|
|
454
|
+
actor_id: auth.user.id,
|
|
455
|
+
agent_id: id,
|
|
456
|
+
patch_keys: Object.keys(body),
|
|
457
|
+
event: "admin_agent_patched",
|
|
458
|
+
}, "Admin updated an ai-hub agent.");
|
|
459
|
+
return jsonResponse(200, adminAgentView(fresh));
|
|
460
|
+
});
|
|
461
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/routes/admin/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EACL,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,GAAa;IACnC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,YAAY,EAAE,GAAG,CAAC,WAAW;QAC7B,cAAc,EAAE,GAAG,CAAC,YAAY;QAChC,oBAAoB,EAAE,GAAG,CAAC,kBAAkB;QAC5C,qBAAqB,EAAE,GAAG,CAAC,mBAAmB;QAC9C,2BAA2B,EAAE,GAAG,CAAC,wBAAwB;QACzD,2BAA2B,EAAE,GAAG,CAAC,wBAAwB;QACzD,iBAAiB,EAAE,GAAG,CAAC,eAAe;QACtC,2BAA2B,EAAE,GAAG,CAAC,wBAAwB;QACzD,WAAW,EAAE,GAAG,CAAC,UAAU;QAC3B,UAAU,EAAE,GAAG,CAAC,SAAS;QACzB,UAAU,EAAE,GAAG,CAAC,SAAS;KAC1B,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,SAAS,MAAM;IACb,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,KAAK,UAAU,oBAAoB,CACjC,GAAuB,EACvB,YAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAChE,OAAO,KAAK,KAAK,IAAI,CAAC;AACxB,CAAC;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,UAAU,yBAAyB,CACtC,GAAuB,EACvB,MAIC;IAED,IACE,MAAM,CAAC,eAAe,KAAK,SAAS;QACpC,MAAM,CAAC,eAAe,KAAK,IAAI;QAC/B,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EACjC,CAAC;QACD,MAAM,cAAc,GAAG,gBAAgB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAChE,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;YACzD,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC;QACxC,CAAC;IACH,CAAC;IACD,IACE,MAAM,CAAC,wBAAwB,KAAK,SAAS;QAC7C,MAAM,CAAC,wBAAwB,KAAK,IAAI;QACxC,MAAM,CAAC,wBAAwB,CAAC,MAAM,GAAG,CAAC,EAC1C,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,wBAAwB,CAAC;QAC5C,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,gEAAgE;YAChE,6DAA6D;YAC7D,sEAAsE;YACtE,gEAAgE;YAChE,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE;iBAChB,MAAM,EAAE;iBACR,IAAI,CAAC,eAAe,CAAC;iBACrB,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;iBAClC,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC7B,OAAO,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC;YAChD,CAAC;YACD,IAAI,IAAI,CAAC,YAAY,KAAK,MAAM,CAAC,oBAAoB,EAAE,CAAC;gBACtD,OAAO;oBACL,IAAI,EAAE,iCAAiC;oBACvC,eAAe,EAAE,MAAM,CAAC,oBAAoB;oBAC5C,aAAa,EAAE,IAAI,CAAC,YAAY;iBACjC,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAC7D,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;YAC3C,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,oBAAoB,EAAE,CAAC;gBACjD,OAAO;oBACL,IAAI,EAAE,4BAA4B;oBAClC,eAAe,EAAE,MAAM,CAAC,oBAAoB;oBAC5C,aAAa,EAAE,IAAI,CAAC,OAAO;iBAC5B,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,SAAS,yBAAyB,CAChC,OAA6D;IAE7D,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,mBAAmB;YACtB,OAAO,aAAa,CAClB,GAAG,EACH,mBAAmB,EACnB,sEAAsE,CACvE,CAAC;QACJ,KAAK,oBAAoB;YACvB,OAAO,aAAa,CAClB,GAAG,EACH,oBAAoB,EACpB,wEAAwE,CACzE,CAAC;QACJ,KAAK,uBAAuB;YAC1B,OAAO,aAAa,CAClB,GAAG,EACH,uBAAuB,EACvB,+CAA+C,CAChD,CAAC;QACJ,KAAK,4BAA4B;YAC/B,OAAO,aAAa,CAClB,GAAG,EACH,4BAA4B,EAC5B,0CAA0C,OAAO,CAAC,aAAa,IAAI;gBACjE,mCAAmC,OAAO,CAAC,eAAe,iBAAiB;gBAC3E,gEAAgE,CACnE,CAAC;QACJ,KAAK,4BAA4B;YAC/B,OAAO,aAAa,CAClB,GAAG,EACH,4BAA4B,EAC5B,6DAA6D,CAC9D,CAAC;QACJ,KAAK,iCAAiC;YACpC,OAAO,aAAa,CAClB,GAAG,EACH,iCAAiC,EACjC,0DAA0D,OAAO,CAAC,aAAa,IAAI;gBACjF,mCAAmC,OAAO,CAAC,eAAe,uBAAuB;gBACjF,mFAAmF,CACtF,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,yBAAyB,CAChC,GAAuB,EACvB,YAAoB;IAEpB,IAAI,CAAC;QACH,oBAAoB,CAAC;YACnB,OAAO,EAAE,YAAY;YACrB,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;YACxC,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,IAAI,CACb;YACE,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACrD,KAAK,EAAE,iCAAiC;SACzC,EACD,kEAAkE,CACnE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAiB,cAAc,CAC1D,EAAE,YAAY,EAAE,YAAY,EAAE,EAC9B,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IAClB,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IAC/E,OAAO,YAAY,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,CACF,CAAC;AAEF,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF,qCAAqC;AACrC,MAAM,iBAAiB,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAC1C,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC5C,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACjE,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACzE,iEAAiE;IACjE,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACzE;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5D;;;;OAIG;IACH,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACvE,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAiB,cAAc,CAC3D,EAAE,YAAY,EAAE,YAAY,EAAE,EAC9B,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvB,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,eAAe,CAAC,kCAAkC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,uBAAuB,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAEzB,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAChE,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,aAAa,CAClB,GAAG,EACH,uBAAuB,EACvB,wCAAwC,CACzC,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,kEAAkE;IAClE,uBAAuB;IACvB,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC,GAAG,EAAE;QACvD,eAAe,EAAE,IAAI,CAAC,iBAAiB;QACvC,wBAAwB,EAAE,IAAI,CAAC,2BAA2B;QAC1D,oBAAoB,EAAE,IAAI,CAAC,cAAc;KAC1C,CAAC,CAAC;IACH,IAAI,WAAW,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9B,OAAO,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,6DAA6D;IAC7D,mDAAmD;IACnD,MAAM,kBAAkB,GACtB,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC;QACzD,CAAC,CAAC,IAAI,CAAC,iBAAiB;QACxB,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,iBAAiB,GACrB,IAAI,CAAC,2BAA2B;QAChC,IAAI,CAAC,2BAA2B,CAAC,MAAM,GAAG,CAAC;QACzC,CAAC,CAAC,IAAI,CAAC,2BAA2B;QAClC,CAAC,CAAC,IAAI,CAAC;IACX,GAAG,CAAC,EAAE;SACH,MAAM,CAAC,KAAK,CAAC;SACb,MAAM,CAAC;QACN,EAAE;QACF,WAAW,EAAE,IAAI,CAAC,YAAY;QAC9B,YAAY,EAAE,IAAI,CAAC,cAAc;QACjC,kBAAkB,EAAE,IAAI,CAAC,oBAAoB,IAAI,KAAK;QACtD,mBAAmB,EAAE,IAAI,CAAC,qBAAqB,IAAI,CAAC;QACpD,wBAAwB,EAAE,IAAI,CAAC,2BAA2B,IAAI,EAAE;QAChE,wBAAwB,EAAE,IAAI,CAAC,2BAA2B,IAAI,EAAE;QAChE,eAAe,EAAE,kBAAkB;QACnC,wBAAwB,EAAE,iBAAiB;QAC3C,UAAU,EAAE,KAAK;KAClB,CAAC;SACD,GAAG,EAAE,CAAC;IACT,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACtE,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAE3D,uEAAuE;IACvE,mEAAmE;IACnE,gEAAgE;IAChE,sEAAsE;IACtE,yBAAyB,CAAC,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAEjD,GAAG,CAAC,MAAM,CAAC,IAAI,CACb;QACE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;QACtB,QAAQ,EAAE,GAAG,CAAC,EAAE;QAChB,cAAc,EAAE,GAAG,CAAC,YAAY;QAChC,KAAK,EAAE,qBAAqB;KAC7B,EACD,gCAAgC,CACjC,CAAC;IACF,OAAO,YAAY,CAAC,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC,CACF,CAAC;AAEF,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF,uFAAuF;AACvF,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACnD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACrD,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC5C,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACjE,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACzE,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACzE,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,sDAAsD;IACtD,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5D,sDAAsD;IACtD,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACvE,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAiB,cAAc,CAC1D,EAAE,YAAY,EAAE,YAAY,EAAE,EAC9B,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;IAC/B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE;QAAE,OAAO,QAAQ,EAAE,CAAC;IAC3B,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,eAAe,CAAC,kCAAkC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,uBAAuB,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAEzB,MAAM,QAAQ,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IAC3E,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAEnD,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,KAAK,QAAQ,CAAC,YAAY,EAAE,CAAC;QACvF,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAChE,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,aAAa,CAClB,GAAG,EACH,uBAAuB,EACvB,wCAAwC,CACzC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,+DAA+D;IAC/D,gEAAgE;IAChE,4CAA4C;IAC5C,MAAM,qBAAqB,GAAG,IAAI,CAAC,cAAc,IAAI,QAAQ,CAAC,YAAY,CAAC;IAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,KAAK,SAAS,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,2BAA2B,KAAK,SAAS,CAAC;IACnE,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC,GAAG,EAAE;YACvD,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI;YAC5D,wBAAwB,EAAE,WAAW;gBACnC,CAAC,CAAC,IAAI,CAAC,2BAA2B;gBAClC,CAAC,CAAC,IAAI;YACR,oBAAoB,EAAE,qBAAqB;SAC5C,CAAC,CAAC;QACH,IAAI,WAAW,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAC9B,OAAO,yBAAyB,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAuC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3E,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;QAAE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;IAC5E,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS;QAAE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC;IACjF,IAAI,IAAI,CAAC,oBAAoB,KAAK,SAAS;QACzC,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,CAAC;IACxD,IAAI,IAAI,CAAC,qBAAqB,KAAK,SAAS;QAC1C,MAAM,CAAC,mBAAmB,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC1D,IAAI,IAAI,CAAC,2BAA2B,KAAK,SAAS;QAChD,MAAM,CAAC,wBAAwB,GAAG,IAAI,CAAC,2BAA2B,CAAC;IACrE,IAAI,IAAI,CAAC,2BAA2B,KAAK,SAAS;QAChD,MAAM,CAAC,wBAAwB,GAAG,IAAI,CAAC,2BAA2B,CAAC;IACrE,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;QAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC;IACzE,wEAAwE;IACxE,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACzC,MAAM,CAAC,eAAe;YACpB,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC;gBACzD,CAAC,CAAC,IAAI,CAAC,iBAAiB;gBACxB,CAAC,CAAC,IAAI,CAAC;IACb,CAAC;IACD,IAAI,IAAI,CAAC,2BAA2B,KAAK,SAAS,EAAE,CAAC;QACnD,MAAM,CAAC,wBAAwB;YAC7B,IAAI,CAAC,2BAA2B;gBAChC,IAAI,CAAC,2BAA2B,CAAC,MAAM,GAAG,CAAC;gBACzC,CAAC,CAAC,IAAI,CAAC,2BAA2B;gBAClC,CAAC,CAAC,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACxE,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,EAAE,CAAC;IAE9B,uEAAuE;IACvE,uEAAuE;IACvE,sEAAsE;IACtE,iEAAiE;IACjE,sEAAsE;IACtE,IACE,IAAI,CAAC,cAAc,KAAK,SAAS;QACjC,IAAI,CAAC,cAAc,KAAK,QAAQ,CAAC,YAAY,EAC7C,CAAC;QACD,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IACtD,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,IAAI,CACb;QACE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;QACtB,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QAC7B,KAAK,EAAE,qBAAqB;KAC7B,EACD,gCAAgC,CACjC,CAAC;IACF,OAAO,YAAY,CAAC,GAAG,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AAClD,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/admin/rotating-messages/*` — power_user + admin + super_admin management of
|
|
3
|
+
* **rotating starting messages** (auto-refreshing, forkable base conversations).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `/admin/agents` conventions (Zod `.strict()`, `power_user`+ gate,
|
|
6
|
+
* snake_case wire view, archive-only — no DELETE):
|
|
7
|
+
*
|
|
8
|
+
* - `GET /admin/rotating-messages` — every row, archived included.
|
|
9
|
+
* - `POST /admin/rotating-messages` — create; validates `letta_agent_id`
|
|
10
|
+
* against Letta + the schedule shape. Returns the row including its
|
|
11
|
+
* `rmsg-…` `id` — the identifier callers paste into an agent's Base
|
|
12
|
+
* conversation field. `next_rotation_at` is set to now so the first
|
|
13
|
+
* rotation fires on the next scheduler tick.
|
|
14
|
+
* - `PATCH /admin/rotating-messages/:id` — partial update; recomputes
|
|
15
|
+
* `next_rotation_at` when the schedule changes; re-validates the agent when
|
|
16
|
+
* it changes; `is_archived` toggle.
|
|
17
|
+
* - `POST /admin/rotating-messages/:id/rotate-now` — runs a rotation inline
|
|
18
|
+
* (preview / on-demand refresh) and returns the refreshed row.
|
|
19
|
+
*
|
|
20
|
+
* @see docs/server/rotating-messages.md
|
|
21
|
+
*/
|
|
22
|
+
import type { RouteHandler } from "../../handlers/types.js";
|
|
23
|
+
/**
|
|
24
|
+
* `GET /admin/rotating-messages` — every rotating message, archived included.
|
|
25
|
+
* Sorted by `display_name`. `power_user`+ per the §8.2 matrix.
|
|
26
|
+
*/
|
|
27
|
+
export declare const handleListRotatingMessages: RouteHandler;
|
|
28
|
+
/**
|
|
29
|
+
* `POST /admin/rotating-messages` — create a rotating starting message.
|
|
30
|
+
*
|
|
31
|
+
* Validation order mirrors `/admin/agents`: Letta agent first (so a bad agent
|
|
32
|
+
* id surfaces alone), then the schedule shape.
|
|
33
|
+
*/
|
|
34
|
+
export declare const handleCreateRotatingMessage: RouteHandler;
|
|
35
|
+
/**
|
|
36
|
+
* `PATCH /admin/rotating-messages/:id` — partial update.
|
|
37
|
+
*
|
|
38
|
+
* When any schedule-related field is present, the effective schedule (existing
|
|
39
|
+
* values overlaid with the patch) is re-validated and `next_rotation_at` is
|
|
40
|
+
* recomputed from now. When `letta_agent_id` changes it's re-validated against
|
|
41
|
+
* Letta.
|
|
42
|
+
*/
|
|
43
|
+
export declare const handlePatchRotatingMessage: RouteHandler;
|
|
44
|
+
/**
|
|
45
|
+
* `POST /admin/rotating-messages/:id/rotate-now` — runs a rotation inline so
|
|
46
|
+
* the operator can preview / force-refresh without waiting for the schedule.
|
|
47
|
+
* Returns the refreshed row plus the attempt's status. The run may take a
|
|
48
|
+
* while (it spawns the Letta Code subprocess like a real turn).
|
|
49
|
+
*/
|
|
50
|
+
export declare const handleRotateRotatingMessageNow: RouteHandler;
|
|
51
|
+
//# sourceMappingURL=rotatingMessages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotatingMessages.d.ts","sourceRoot":"","sources":["../../../src/routes/admin/rotatingMessages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH,OAAO,KAAK,EAAsB,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAgEhF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,YAUxC,CAAC;AAqBF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,YAoEzC,CAAC;AAoBF;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,EAAE,YAwExC,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,YA6B5C,CAAC"}
|