aegra-hono 0.11.5 → 0.13.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/cli.js CHANGED
@@ -23,7 +23,7 @@ var init_settings = __esm(() => {
23
23
  booleanFromEnv = z.stringbool().default(false);
24
24
  environmentShape = {
25
25
  PROJECT_NAME: z.string().default("Aegra"),
26
- VERSION: z.string().default("0.11.5"),
26
+ VERSION: z.string().default("0.13.0"),
27
27
  ENV_MODE: z.string().default("PRODUCTION"),
28
28
  LOG_VERBOSITY: z.string().default("verbose"),
29
29
  LOG_EXCLUDE_PATHS: z.string().default(""),
@@ -906,4 +906,4 @@ export {
906
906
  main
907
907
  };
908
908
 
909
- //# debugId=010F5F7EA75E374664756E2164756E21
909
+ //# debugId=A19901B09265E35C64756E2164756E21
package/dist/cli.js.map CHANGED
@@ -2,13 +2,13 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/config/settings.ts", "../src/config/project.ts", "../src/core/schema.ts", "../src/core/database.ts", "../src/cli.ts"],
4
4
  "sourcesContent": [
5
- "import { z } from \"zod\";\n\nconst booleanFromEnv = z.stringbool().default(false);\nconst positiveIntFromEnv = (fallback: number) => z.coerce.number().int().positive().default(fallback);\n\nconst environmentShape = {\n PROJECT_NAME: z.string().default(\"Aegra\"),\n VERSION: z.string().default(\"0.11.5\"),\n ENV_MODE: z.string().default(\"PRODUCTION\"),\n LOG_VERBOSITY: z.string().default(\"verbose\"),\n LOG_EXCLUDE_PATHS: z.string().default(\"\"),\n HOST: z.string().default(\"0.0.0.0\"),\n PORT: z.coerce.number().int().min(1).max(65_535).default(2026),\n AEGRA_CONFIG: z.string().default(\"aegra.json\"),\n RUN_MIGRATIONS_ON_STARTUP: z.stringbool().default(true),\n DATABASE_URL: z.string().optional(),\n POSTGRES_USER: z.string().default(\"postgres\"),\n POSTGRES_PASSWORD: z.string().default(\"postgres\"),\n POSTGRES_HOST: z.string().default(\"localhost\"),\n POSTGRES_PORT: z.coerce.number().int().min(1).max(65_535).default(5432),\n POSTGRES_DB: z.string().default(\"aegra\"),\n REDIS_BROKER_ENABLED: booleanFromEnv,\n REDIS_URL: z.string().default(\"redis://localhost:6379/0\"),\n WORKER_COUNT: positiveIntFromEnv(3),\n N_JOBS_PER_WORKER: positiveIntFromEnv(10),\n WORKER_QUEUE_KEY: z.string().default(\"aegra:jobs\"),\n BG_JOB_TIMEOUT_SECS: positiveIntFromEnv(3600),\n BG_JOB_MAX_RETRIES: z.coerce.number().int().nonnegative().default(3),\n WORKER_DRAIN_TIMEOUT: z.coerce.number().nonnegative().default(30),\n STUCK_PENDING_THRESHOLD_SECONDS: positiveIntFromEnv(120),\n LEASE_DURATION_SECONDS: positiveIntFromEnv(30),\n HEARTBEAT_INTERVAL_SECONDS: positiveIntFromEnv(10),\n REAPER_INTERVAL_SECONDS: positiveIntFromEnv(15),\n POSTGRES_POLL_INTERVAL_SECONDS: positiveIntFromEnv(5),\n KEEPALIVE_INTERVAL_SECS: positiveIntFromEnv(5),\n CRON_ENABLED: z.stringbool().default(true),\n CRON_POLL_INTERVAL_SECONDS: positiveIntFromEnv(60),\n CRON_CLAIM_DURATION_SECONDS: positiveIntFromEnv(300),\n CRON_MAX_PER_USER: z.coerce.number().int().nonnegative().default(100),\n CRON_ALLOW_SECONDS_SCHEDULE: booleanFromEnv,\n CRON_TICK_BATCH_SIZE: positiveIntFromEnv(100),\n CRON_MAX_PAYLOAD_BYTES: positiveIntFromEnv(65_536),\n AEGRA_THREAD_TTL: z.string().optional(),\n LANGGRAPH_THREAD_TTL: z.string().optional(),\n MAX_SEARCH_LIMIT: positiveIntFromEnv(1000),\n ENABLE_PROMETHEUS_METRICS: booleanFromEnv,\n FF_V2_EVENT_STREAMING: z.stringbool().default(true),\n OTEL_SERVICE_NAME: z.string().default(\"aegra-backend\"),\n OTEL_TARGETS: z.string().default(\"\"),\n OTEL_CONSOLE_EXPORT: booleanFromEnv,\n OTEL_EXPORTER_OTLP_ENDPOINT: z.string().optional(),\n OTEL_EXPORTER_OTLP_HEADERS: z.string().optional(),\n LANGFUSE_BASE_URL: z.string().default(\"http://localhost:3000\"),\n LANGFUSE_PUBLIC_KEY: z.string().optional(),\n LANGFUSE_SECRET_KEY: z.string().optional(),\n PHOENIX_COLLECTOR_ENDPOINT: z.string().default(\"http://127.0.0.1:6006/v1/traces\"),\n PHOENIX_API_KEY: z.string().optional(),\n};\n\nexport const environmentVariableNames = Object.freeze(Object.keys(environmentShape));\n\nconst environmentSchema = z.object(environmentShape).superRefine((value, issue) => {\n if (value.LEASE_DURATION_SECONDS <= 2 * value.HEARTBEAT_INTERVAL_SECONDS) {\n issue.addIssue({ code: \"custom\", path: [\"LEASE_DURATION_SECONDS\"],\n message: \"LEASE_DURATION_SECONDS must exceed twice HEARTBEAT_INTERVAL_SECONDS\" });\n }\n});\n\nconst raw = environmentSchema.parse(process.env);\n\nexport const settings = {\n ...raw,\n DATABASE_URL:\n raw.DATABASE_URL ??\n `postgresql://${encodeURIComponent(raw.POSTGRES_USER)}:${encodeURIComponent(raw.POSTGRES_PASSWORD)}@${raw.POSTGRES_HOST}:${raw.POSTGRES_PORT}/${raw.POSTGRES_DB}`,\n} as const;\n\nexport type Settings = typeof settings;\n",
5
+ "import { z } from \"zod\";\n\nconst booleanFromEnv = z.stringbool().default(false);\nconst positiveIntFromEnv = (fallback: number) => z.coerce.number().int().positive().default(fallback);\n\nconst environmentShape = {\n PROJECT_NAME: z.string().default(\"Aegra\"),\n VERSION: z.string().default(\"0.13.0\"),\n ENV_MODE: z.string().default(\"PRODUCTION\"),\n LOG_VERBOSITY: z.string().default(\"verbose\"),\n LOG_EXCLUDE_PATHS: z.string().default(\"\"),\n HOST: z.string().default(\"0.0.0.0\"),\n PORT: z.coerce.number().int().min(1).max(65_535).default(2026),\n AEGRA_CONFIG: z.string().default(\"aegra.json\"),\n RUN_MIGRATIONS_ON_STARTUP: z.stringbool().default(true),\n DATABASE_URL: z.string().optional(),\n POSTGRES_USER: z.string().default(\"postgres\"),\n POSTGRES_PASSWORD: z.string().default(\"postgres\"),\n POSTGRES_HOST: z.string().default(\"localhost\"),\n POSTGRES_PORT: z.coerce.number().int().min(1).max(65_535).default(5432),\n POSTGRES_DB: z.string().default(\"aegra\"),\n REDIS_BROKER_ENABLED: booleanFromEnv,\n REDIS_URL: z.string().default(\"redis://localhost:6379/0\"),\n WORKER_COUNT: positiveIntFromEnv(3),\n N_JOBS_PER_WORKER: positiveIntFromEnv(10),\n WORKER_QUEUE_KEY: z.string().default(\"aegra:jobs\"),\n BG_JOB_TIMEOUT_SECS: positiveIntFromEnv(3600),\n BG_JOB_MAX_RETRIES: z.coerce.number().int().nonnegative().default(3),\n WORKER_DRAIN_TIMEOUT: z.coerce.number().nonnegative().default(30),\n STUCK_PENDING_THRESHOLD_SECONDS: positiveIntFromEnv(120),\n LEASE_DURATION_SECONDS: positiveIntFromEnv(30),\n HEARTBEAT_INTERVAL_SECONDS: positiveIntFromEnv(10),\n REAPER_INTERVAL_SECONDS: positiveIntFromEnv(15),\n POSTGRES_POLL_INTERVAL_SECONDS: positiveIntFromEnv(5),\n KEEPALIVE_INTERVAL_SECS: positiveIntFromEnv(5),\n CRON_ENABLED: z.stringbool().default(true),\n CRON_POLL_INTERVAL_SECONDS: positiveIntFromEnv(60),\n CRON_CLAIM_DURATION_SECONDS: positiveIntFromEnv(300),\n CRON_MAX_PER_USER: z.coerce.number().int().nonnegative().default(100),\n CRON_ALLOW_SECONDS_SCHEDULE: booleanFromEnv,\n CRON_TICK_BATCH_SIZE: positiveIntFromEnv(100),\n CRON_MAX_PAYLOAD_BYTES: positiveIntFromEnv(65_536),\n AEGRA_THREAD_TTL: z.string().optional(),\n LANGGRAPH_THREAD_TTL: z.string().optional(),\n MAX_SEARCH_LIMIT: positiveIntFromEnv(1000),\n ENABLE_PROMETHEUS_METRICS: booleanFromEnv,\n FF_V2_EVENT_STREAMING: z.stringbool().default(true),\n OTEL_SERVICE_NAME: z.string().default(\"aegra-backend\"),\n OTEL_TARGETS: z.string().default(\"\"),\n OTEL_CONSOLE_EXPORT: booleanFromEnv,\n OTEL_EXPORTER_OTLP_ENDPOINT: z.string().optional(),\n OTEL_EXPORTER_OTLP_HEADERS: z.string().optional(),\n LANGFUSE_BASE_URL: z.string().default(\"http://localhost:3000\"),\n LANGFUSE_PUBLIC_KEY: z.string().optional(),\n LANGFUSE_SECRET_KEY: z.string().optional(),\n PHOENIX_COLLECTOR_ENDPOINT: z.string().default(\"http://127.0.0.1:6006/v1/traces\"),\n PHOENIX_API_KEY: z.string().optional(),\n};\n\nexport const environmentVariableNames = Object.freeze(Object.keys(environmentShape));\n\nconst environmentSchema = z.object(environmentShape).superRefine((value, issue) => {\n if (value.LEASE_DURATION_SECONDS <= 2 * value.HEARTBEAT_INTERVAL_SECONDS) {\n issue.addIssue({ code: \"custom\", path: [\"LEASE_DURATION_SECONDS\"],\n message: \"LEASE_DURATION_SECONDS must exceed twice HEARTBEAT_INTERVAL_SECONDS\" });\n }\n});\n\nconst raw = environmentSchema.parse(process.env);\n\nexport const settings = {\n ...raw,\n DATABASE_URL:\n raw.DATABASE_URL ??\n `postgresql://${encodeURIComponent(raw.POSTGRES_USER)}:${encodeURIComponent(raw.POSTGRES_PASSWORD)}@${raw.POSTGRES_HOST}:${raw.POSTGRES_PORT}/${raw.POSTGRES_DB}`,\n} as const;\n\nexport type Settings = typeof settings;\n",
6
6
  "import { readFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { z } from \"zod\";\nimport { settings } from \"./settings.ts\";\n\nconst corsSchema = z.object({\n allow_origins: z.array(z.string()).default([\"*\"]),\n allow_methods: z.array(z.string()).default([\"*\"]),\n allow_headers: z.array(z.string()).default([\"*\"]),\n allow_credentials: z.boolean().optional(),\n expose_headers: z.array(z.string()).default([\"Content-Location\", \"Location\"]),\n max_age: z.number().int().nonnegative().default(600),\n});\n\nconst configSchema = z.object({\n dependencies: z.array(z.string()).default([]),\n graphs: z.record(z.string(), z.string()).default({}),\n auth: z.object({ path: z.string(), disable_studio_auth: z.boolean().default(false) }).optional(),\n http: z\n .object({\n app: z.string().optional(),\n enable_custom_route_auth: z.boolean().default(false),\n cors: corsSchema.optional(),\n })\n .optional(),\n store: z\n .object({\n index: z\n .object({ dims: z.number().int().positive(), embed: z.string(), fields: z.array(z.string()).nullable().optional() })\n .nullable()\n .optional(),\n scopes: z.record(z.string(), z.array(z.string())).default({}),\n })\n .optional(),\n checkpointer: z\n .object({\n ttl: z\n .object({\n strategy: z.enum([\"delete\", \"keep_latest\"]).default(\"delete\"),\n default_ttl: z.number().positive().optional(),\n sweep_interval_minutes: z.number().positive().default(5),\n sweep_limit: z.number().int().positive().default(100),\n })\n .nullable()\n .optional(),\n })\n .optional(),\n});\n\nexport type AegraConfig = z.infer<typeof configSchema>;\n\nlet cachedConfig: AegraConfig | undefined;\n\nexport async function loadConfig(): Promise<AegraConfig> {\n if (cachedConfig) return cachedConfig;\n const configPath = resolve(settings.AEGRA_CONFIG);\n const content = await readFile(configPath, \"utf8\");\n cachedConfig = configSchema.parse(JSON.parse(content));\n return cachedConfig;\n}\n\nexport function configDirectory(): string {\n return dirname(resolve(settings.AEGRA_CONFIG));\n}\n\nexport function clearConfigCache(): void {\n cachedConfig = undefined;\n}\n",
7
7
  "import { sql } from \"drizzle-orm\";\nimport { bigint, bigserial, boolean, doublePrecision, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex } from \"drizzle-orm/pg-core\";\nimport type { JsonObject, JsonValue } from \"../types.ts\";\n\nconst timestamps = {\n created_at: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updated_at: timestamp(\"updated_at\", { withTimezone: true }).notNull().defaultNow(),\n};\n\nexport const migrations = pgTable(\"aegra_migrations\", {\n version: integer(\"version\").primaryKey(),\n applied_at: timestamp(\"applied_at\", { withTimezone: true }).notNull().defaultNow(),\n});\n\nexport const assistants = pgTable(\"assistant\", {\n assistant_id: text(\"assistant_id\").primaryKey().default(sql`gen_random_uuid()::text`),\n name: text(\"name\").notNull(),\n description: text(\"description\"),\n graph_id: text(\"graph_id\").notNull(),\n config: jsonb(\"config\").$type<JsonObject>().notNull().default({}),\n context: jsonb(\"context\").$type<JsonObject>().notNull().default({}),\n user_id: text(\"user_id\").notNull(),\n version: integer(\"version\").notNull().default(1),\n metadata: jsonb(\"metadata\").$type<JsonObject>().notNull().default({}),\n ...timestamps,\n}, (table) => [\n index(\"idx_assistant_user\").on(table.user_id),\n unique(\"assistant_user_id_unique\").on(table.user_id, table.assistant_id),\n uniqueIndex(\"idx_assistant_user_graph_config\").on(table.user_id, table.graph_id, sql`md5(${table.config}::text)`),\n index(\"idx_assistant_metadata_gin\").using(\"gin\", sql`${table.metadata} jsonb_path_ops`),\n]);\n\nexport const assistantVersions = pgTable(\"assistant_versions\", {\n assistant_id: text(\"assistant_id\").notNull().references(() => assistants.assistant_id, { onDelete: \"cascade\" }),\n version: integer(\"version\").notNull(),\n graph_id: text(\"graph_id\").notNull(),\n config: jsonb(\"config\").$type<JsonObject>(),\n context: jsonb(\"context\").$type<JsonObject>(),\n metadata: jsonb(\"metadata\").$type<JsonObject>().notNull().default({}),\n name: text(\"name\"),\n description: text(\"description\"),\n created_at: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n}, (table) => [primaryKey({ columns: [table.assistant_id, table.version] })]);\n\nexport const threads = pgTable(\"thread\", {\n thread_id: text(\"thread_id\").primaryKey(),\n status: text(\"status\").notNull().default(\"idle\"),\n metadata_json: jsonb(\"metadata_json\").$type<JsonObject>().notNull().default({}),\n user_id: text(\"user_id\").notNull(),\n ...timestamps,\n}, (table) => [index(\"idx_thread_user\").on(table.user_id),\n index(\"idx_thread_metadata_gin\").using(\"gin\", sql`${table.metadata_json} jsonb_path_ops`)]);\n\nexport const runs = pgTable(\"runs\", {\n run_id: text(\"run_id\").primaryKey().default(sql`gen_random_uuid()::text`),\n thread_id: text(\"thread_id\").notNull().references(() => threads.thread_id, { onDelete: \"cascade\" }),\n assistant_id: text(\"assistant_id\").references(() => assistants.assistant_id, { onDelete: \"cascade\" }),\n status: text(\"status\").notNull().default(\"pending\"),\n input: jsonb(\"input\").$type<JsonObject>(),\n config: jsonb(\"config\").$type<JsonObject>(),\n context: jsonb(\"context\").$type<JsonObject>(),\n output: jsonb(\"output\").$type<JsonObject>(),\n error_message: text(\"error_message\"),\n user_id: text(\"user_id\").notNull(),\n execution_params: jsonb(\"execution_params\").$type<JsonObject>(),\n claimed_by: text(\"claimed_by\"),\n lease_expires_at: timestamp(\"lease_expires_at\", { withTimezone: true }),\n ...timestamps,\n}, (table) => [\n index(\"idx_runs_thread_id\").on(table.thread_id), index(\"idx_runs_status\").on(table.status),\n index(\"idx_runs_user\").on(table.user_id), index(\"idx_runs_assistant_id\").on(table.assistant_id),\n index(\"idx_runs_created_at\").on(table.created_at),\n index(\"idx_runs_lease_reaper\").on(table.status, table.lease_expires_at).where(sql`${table.status} = 'running'`),\n]);\n\nexport const threadEvents = pgTable(\"thread_events\", {\n seq: bigserial(\"seq\", { mode: \"number\" }).primaryKey(),\n thread_id: text(\"thread_id\").notNull().references(() => threads.thread_id, { onDelete: \"cascade\" }),\n run_id: text(\"run_id\").notNull().references(() => runs.run_id, { onDelete: \"cascade\" }),\n user_id: text(\"user_id\").notNull(),\n event_id: text(\"event_id\").notNull().unique(),\n method: text(\"method\").notNull(),\n namespace: text(\"namespace\").array().notNull().default(sql`'{}'::text[]`),\n event_data: jsonb(\"event_data\").$type<JsonValue>().notNull(),\n event_timestamp: bigint(\"event_timestamp\", { mode: \"number\" }).notNull(),\n created_at: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n}, (table) => [index(\"idx_thread_events_replay\").on(table.user_id, table.thread_id, table.seq)]);\n\nexport const crons = pgTable(\"crons\", {\n cron_id: text(\"cron_id\").primaryKey().default(sql`gen_random_uuid()::text`),\n assistant_id: text(\"assistant_id\").notNull().references(() => assistants.assistant_id, { onDelete: \"cascade\" }),\n thread_id: text(\"thread_id\").references(() => threads.thread_id, { onDelete: \"cascade\" }),\n user_id: text(\"user_id\").notNull(),\n schedule: text(\"schedule\").notNull(),\n payload: jsonb(\"payload\").$type<JsonObject>().notNull().default({}),\n metadata: jsonb(\"metadata\").$type<JsonObject>().notNull().default({}),\n on_run_completed: text(\"on_run_completed\"),\n enabled: boolean(\"enabled\").notNull().default(true),\n end_time: timestamp(\"end_time\", { withTimezone: true }),\n next_run_date: timestamp(\"next_run_date\", { withTimezone: true }),\n claimed_until: timestamp(\"claimed_until\", { withTimezone: true }),\n ...timestamps,\n}, (table) => [\n index(\"idx_cron_user\").on(table.user_id), index(\"idx_cron_assistant_id\").on(table.assistant_id),\n index(\"idx_cron_thread_id\").on(table.thread_id), index(\"idx_cron_next_run\").on(table.enabled, table.next_run_date),\n]);\n\nexport const storeItems = pgTable(\"store_items\", {\n user_id: text(\"user_id\").notNull(),\n namespace: text(\"namespace\").array().notNull(),\n key: text(\"key\").notNull(),\n value: jsonb(\"value\").$type<JsonObject>().notNull(),\n ...timestamps,\n}, (table) => [primaryKey({ columns: [table.namespace, table.key] })]);\n\nexport const threadTtl = pgTable(\"thread_ttl\", {\n thread_id: text(\"thread_id\").primaryKey().references(() => threads.thread_id, { onDelete: \"cascade\" }),\n strategy: text(\"strategy\").notNull().default(\"delete\"),\n ttl_minutes: doublePrecision(\"ttl_minutes\").notNull(),\n created_at: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n expires_at: timestamp(\"expires_at\", { withTimezone: true }).notNull(),\n}, (table) => [index(\"idx_thread_ttl_expires_at\").on(table.expires_at)]);\n",
8
8
  "import postgres from \"postgres\";\nimport { drizzle } from \"drizzle-orm/postgres-js\";\nimport { loadConfig } from \"../config/project.ts\";\nimport { settings } from \"../config/settings.ts\";\nimport * as schema from \"./schema.ts\";\n\nexport const client = postgres(settings.DATABASE_URL, {\n max: 20,\n idle_timeout: 30,\n connect_timeout: 10,\n transform: { undefined: null },\n // Bootstrap DDL raises \"already exists\" notices on every boot; keep them only\n // in verbose mode so the structured request log stays readable.\n onnotice: (notice) => {\n if (settings.LOG_VERBOSITY !== \"verbose\") return;\n console.log(JSON.stringify({ event: \"postgres_notice\", severity: notice.severity, code: notice.code, message: notice.message }));\n },\n});\nexport const db = drizzle({ client, schema });\n\nconst migrations = [\n `CREATE TABLE IF NOT EXISTS aegra_migrations (\n version integer PRIMARY KEY,\n applied_at timestamptz NOT NULL DEFAULT now()\n )`,\n `CREATE TABLE IF NOT EXISTS assistant (\n assistant_id text PRIMARY KEY DEFAULT gen_random_uuid()::text,\n name text NOT NULL,\n description text,\n graph_id text NOT NULL,\n config jsonb NOT NULL DEFAULT '{}'::jsonb,\n context jsonb NOT NULL DEFAULT '{}'::jsonb,\n user_id text NOT NULL,\n version integer NOT NULL DEFAULT 1,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n UNIQUE(user_id, assistant_id)\n )`,\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_assistant_user_graph_config\n ON assistant(user_id, graph_id, md5(config::text))`,\n `CREATE INDEX IF NOT EXISTS idx_assistant_user ON assistant(user_id)`,\n `CREATE INDEX IF NOT EXISTS idx_assistant_metadata_gin ON assistant USING gin (metadata jsonb_path_ops)`,\n `CREATE TABLE IF NOT EXISTS assistant_versions (\n assistant_id text NOT NULL REFERENCES assistant(assistant_id) ON DELETE CASCADE,\n version integer NOT NULL,\n graph_id text NOT NULL,\n config jsonb,\n context jsonb,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n name text,\n description text,\n created_at timestamptz NOT NULL DEFAULT now(),\n PRIMARY KEY(assistant_id, version)\n )`,\n `CREATE TABLE IF NOT EXISTS thread (\n thread_id text PRIMARY KEY,\n status text NOT NULL DEFAULT 'idle',\n metadata_json jsonb NOT NULL DEFAULT '{}'::jsonb,\n user_id text NOT NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n )`,\n `CREATE INDEX IF NOT EXISTS idx_thread_user ON thread(user_id)`,\n `CREATE INDEX IF NOT EXISTS idx_thread_metadata_gin ON thread USING gin (metadata_json jsonb_path_ops)`,\n `CREATE TABLE IF NOT EXISTS runs (\n run_id text PRIMARY KEY DEFAULT gen_random_uuid()::text,\n thread_id text NOT NULL REFERENCES thread(thread_id) ON DELETE CASCADE,\n assistant_id text REFERENCES assistant(assistant_id) ON DELETE CASCADE,\n status text NOT NULL DEFAULT 'pending',\n input jsonb,\n config jsonb,\n context jsonb,\n output jsonb,\n error_message text,\n user_id text NOT NULL,\n execution_params jsonb,\n claimed_by text,\n lease_expires_at timestamptz,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n )`,\n `CREATE INDEX IF NOT EXISTS idx_runs_thread_id ON runs(thread_id)`,\n `CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status)`,\n `CREATE INDEX IF NOT EXISTS idx_runs_user ON runs(user_id)`,\n `CREATE INDEX IF NOT EXISTS idx_runs_assistant_id ON runs(assistant_id)`,\n `CREATE INDEX IF NOT EXISTS idx_runs_created_at ON runs(created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_runs_lease_reaper ON runs(status, lease_expires_at) WHERE status = 'running'`,\n `CREATE TABLE IF NOT EXISTS thread_events (\n seq bigserial PRIMARY KEY,\n thread_id text NOT NULL REFERENCES thread(thread_id) ON DELETE CASCADE,\n run_id text NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,\n user_id text NOT NULL,\n event_id text NOT NULL UNIQUE,\n method text NOT NULL,\n namespace text[] NOT NULL DEFAULT '{}',\n event_data jsonb NOT NULL,\n event_timestamp bigint NOT NULL,\n created_at timestamptz NOT NULL DEFAULT now()\n )`,\n `CREATE INDEX IF NOT EXISTS idx_thread_events_replay ON thread_events(user_id, thread_id, seq)`,\n `CREATE TABLE IF NOT EXISTS crons (\n cron_id text PRIMARY KEY DEFAULT gen_random_uuid()::text,\n assistant_id text NOT NULL REFERENCES assistant(assistant_id) ON DELETE CASCADE,\n thread_id text REFERENCES thread(thread_id) ON DELETE CASCADE,\n user_id text NOT NULL,\n schedule text NOT NULL,\n payload jsonb NOT NULL DEFAULT '{}'::jsonb,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n on_run_completed text,\n enabled boolean NOT NULL DEFAULT true,\n end_time timestamptz,\n next_run_date timestamptz,\n claimed_until timestamptz,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n )`,\n `CREATE TABLE IF NOT EXISTS store_items (\n user_id text NOT NULL,\n namespace text[] NOT NULL,\n key text NOT NULL,\n value jsonb NOT NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n PRIMARY KEY(namespace, key)\n )`,\n // Store isolation lives in the namespace head ([\"users\", identity, ...]), so\n // the primary key must not include the writer. Older databases keyed on\n // user_id and are migrated in place; shared scopes otherwise duplicate rows.\n `DO $$\n DECLARE legacy_key boolean;\n BEGIN\n SELECT EXISTS (\n SELECT 1 FROM pg_constraint c\n JOIN pg_class t ON t.oid = c.conrelid\n WHERE t.relname = 'store_items' AND c.contype = 'p'\n AND pg_get_constraintdef(c.oid) = 'PRIMARY KEY (user_id, namespace, key)'\n ) INTO legacy_key;\n IF legacy_key THEN\n IF to_regclass('store_embeddings') IS NOT NULL THEN\n ALTER TABLE store_embeddings DROP CONSTRAINT IF EXISTS store_embeddings_user_id_namespace_key_fkey;\n ALTER TABLE store_embeddings DROP CONSTRAINT IF EXISTS store_embeddings_pkey;\n END IF;\n ALTER TABLE store_items DROP CONSTRAINT store_items_pkey;\n ALTER TABLE store_items ADD CONSTRAINT store_items_pkey PRIMARY KEY (namespace, key);\n IF to_regclass('store_embeddings') IS NOT NULL THEN\n ALTER TABLE store_embeddings ADD CONSTRAINT store_embeddings_pkey PRIMARY KEY (namespace, key);\n ALTER TABLE store_embeddings ADD CONSTRAINT store_embeddings_item_fkey\n FOREIGN KEY (namespace, key) REFERENCES store_items(namespace, key) ON DELETE CASCADE;\n END IF;\n END IF;\n END $$`,\n `CREATE INDEX IF NOT EXISTS idx_cron_user ON crons(user_id)`,\n `CREATE INDEX IF NOT EXISTS idx_cron_assistant_id ON crons(assistant_id)`,\n `CREATE INDEX IF NOT EXISTS idx_cron_thread_id ON crons(thread_id)`,\n `CREATE INDEX IF NOT EXISTS idx_cron_next_run ON crons(enabled, next_run_date)`,\n `CREATE TABLE IF NOT EXISTS thread_ttl (\n thread_id text PRIMARY KEY REFERENCES thread(thread_id) ON DELETE CASCADE,\n strategy text NOT NULL DEFAULT 'delete',\n ttl_minutes double precision NOT NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n expires_at timestamptz NOT NULL\n )`,\n `CREATE INDEX IF NOT EXISTS idx_thread_ttl_expires_at ON thread_ttl(expires_at)`,\n];\n\nexport async function migrate(): Promise<void> {\n for (const statement of migrations) await client.unsafe(statement);\n if ((await loadConfig()).store?.index) {\n await client.unsafe(\"CREATE EXTENSION IF NOT EXISTS vector\");\n await client.unsafe(`CREATE TABLE IF NOT EXISTS store_embeddings (\n user_id text NOT NULL,\n namespace text[] NOT NULL,\n key text NOT NULL,\n embedding vector NOT NULL,\n PRIMARY KEY(namespace, key),\n FOREIGN KEY(namespace, key) REFERENCES store_items(namespace, key) ON DELETE CASCADE\n )`);\n }\n}\n\nexport async function pingDatabase(): Promise<boolean> {\n try {\n await client`SELECT 1`;\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function closeDatabase(): Promise<void> {\n await client.end({ timeout: 5 });\n}\n",
9
9
  "#!/usr/bin/env bun\nimport { mkdir } from \"node:fs/promises\";\nimport { basename, dirname, resolve } from \"node:path\";\n\ntype Options = Record<string, string | boolean>;\n\nfunction usage(exitCode = 1): never {\n console.log(`Usage: aegra <command> [options]\n\nCommands:\n init [path] Create a TypeScript Aegra project\n dev Start with Bun hot reload\n serve Start the production server\n up|down [args] Run Docker Compose\n db upgrade Apply database migrations\n version Print the version\n\nServer options: --host, --port, --config|-c, --env-file|-e\nInit options: --name|-n, --template|-t <basic|hono|auth|full>, --hono-version <version>, --force`);\n process.exit(exitCode);\n}\n\nfunction parseOptions(args: string[]): { positional: string[]; options: Options } {\n const positional: string[] = [];\n const options: Options = {};\n for (let index = 0; index < args.length; index++) {\n const value = args[index]!;\n if (!value.startsWith(\"-\")) { positional.push(value); continue; }\n const [rawName, inline] = value.split(\"=\", 2);\n const name = ({ \"-c\": \"config\", \"-e\": \"env-file\", \"-n\": \"name\", \"-t\": \"template\" } as Record<string, string>)[rawName!] ?? rawName!.replace(/^--/, \"\");\n if ([\"force\", \"help\", \"no-db-check\"].includes(name)) { options[name] = true; continue; }\n const next = inline ?? args[++index];\n if (!next) throw new Error(`Missing value for ${rawName}`);\n options[name] = next;\n }\n return { positional, options };\n}\n\nasync function loadEnv(path: string): Promise<void> {\n const file = Bun.file(path);\n if (!(await file.exists())) return;\n for (const line of (await file.text()).split(/\\r?\\n/)) {\n const match = line.match(/^\\s*(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*?)\\s*$/);\n if (!match || process.env[match[1]!] !== undefined) continue;\n process.env[match[1]!] = match[2]!.replace(/^(['\"])(.*)\\1$/, \"$2\");\n }\n}\n\nfunction run(command: string[], env?: Record<string, string | undefined>): void {\n const result = Bun.spawnSync(command, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\", ...(env ? { env } : {}) });\n if (result.exitCode !== 0) process.exit(result.exitCode);\n}\n\nasync function serverEnvironment(options: Options): Promise<Record<string, string | undefined>> {\n await loadEnv(String(options[\"env-file\"] ?? resolve(\".env\")));\n if (options.host) process.env.HOST = String(options.host);\n if (options.port) process.env.PORT = String(options.port);\n if (options.config) process.env.AEGRA_CONFIG = resolve(String(options.config));\n else if (!process.env.AEGRA_CONFIG && await Bun.file(resolve(\"langgraph.json\")).exists()\n && !(await Bun.file(resolve(\"aegra.json\")).exists())) process.env.AEGRA_CONFIG = \"langgraph.json\";\n return process.env;\n}\n\nfunction slugify(value: string): string {\n return value.toLowerCase().trim().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\") || \"aegra-agent\";\n}\n\nfunction renderEnvironment(options: {\n name: string;\n version: string;\n withAuth: boolean;\n withRedis: boolean;\n}): string {\n return `# Application\nPROJECT_NAME=${options.name}\nVERSION=${options.version}\nENV_MODE=LOCAL\nLOG_VERBOSITY=verbose\nLOG_EXCLUDE_PATHS=/live\nHOST=0.0.0.0\nPORT=2026\nAEGRA_CONFIG=aegra.json\nRUN_MIGRATIONS_ON_STARTUP=true\n\n# PostgreSQL. DATABASE_URL takes precedence over the individual values.\nDATABASE_URL=postgresql://postgres:postgres@localhost:5432/aegra\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=postgres\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_DB=aegra\n\n# Redis and distributed workers. Disabled means in-process execution.\nREDIS_BROKER_ENABLED=${options.withRedis}\nREDIS_URL=redis://localhost:6379/0\nWORKER_COUNT=3\nN_JOBS_PER_WORKER=10\nWORKER_QUEUE_KEY=aegra:jobs\nBG_JOB_TIMEOUT_SECS=3600\nBG_JOB_MAX_RETRIES=3\nWORKER_DRAIN_TIMEOUT=30\nSTUCK_PENDING_THRESHOLD_SECONDS=120\nLEASE_DURATION_SECONDS=30\nHEARTBEAT_INTERVAL_SECONDS=10\nREAPER_INTERVAL_SECONDS=15\nPOSTGRES_POLL_INTERVAL_SECONDS=5\nKEEPALIVE_INTERVAL_SECS=5\n\n# Scheduled runs\nCRON_ENABLED=true\nCRON_POLL_INTERVAL_SECONDS=60\nCRON_CLAIM_DURATION_SECONDS=300\nCRON_MAX_PER_USER=100\nCRON_ALLOW_SECONDS_SCHEDULE=false\nCRON_TICK_BATCH_SIZE=100\nCRON_MAX_PAYLOAD_BYTES=65536\n\n# Thread retention. Set one value to a number of minutes or a JSON TTL policy.\nAEGRA_THREAD_TTL=\nLANGGRAPH_THREAD_TTL=\n\n# Protocol and metrics\nMAX_SEARCH_LIMIT=1000\nENABLE_PROMETHEUS_METRICS=false\nFF_V2_EVENT_STREAMING=true\n\n# OpenTelemetry. OTEL_TARGETS accepts OTLP/GENERIC, LANGFUSE, and PHOENIX.\nOTEL_SERVICE_NAME=aegra-backend\nOTEL_TARGETS=\nOTEL_CONSOLE_EXPORT=false\nOTEL_EXPORTER_OTLP_ENDPOINT=\nOTEL_EXPORTER_OTLP_HEADERS=\nLANGFUSE_BASE_URL=http://localhost:3000\nLANGFUSE_PUBLIC_KEY=\nLANGFUSE_SECRET_KEY=\nPHOENIX_COLLECTOR_ENDPOINT=http://127.0.0.1:6006/v1/traces\nPHOENIX_API_KEY=\n\n# Generated graph and authentication examples\nOPENAI_API_KEY=\nAEGRA_AUTH_TOKEN=${options.withAuth ? \"replace-me\" : \"\"}\n`;\n}\n\nasync function writeProjectFile(root: string, path: string, content: string, force: boolean): Promise<\"created\" | \"skipped\"> {\n const target = resolve(root, path);\n if (!force && await Bun.file(target).exists()) return \"skipped\";\n await mkdir(dirname(target), { recursive: true });\n await Bun.write(target, content);\n return \"created\";\n}\n\nasync function initProject(args: string[]): Promise<void> {\n const { positional, options } = parseOptions(args);\n if (options.help) usage(0);\n const root = resolve(positional[0] ?? \".\");\n const name = String(options.name ?? basename(root));\n const slug = slugify(name);\n const requestedTemplate = String(options.template ?? \"basic\");\n const template = requestedTemplate === \"1\" ? \"basic\" : requestedTemplate;\n if (![\"basic\", \"hono\", \"auth\", \"full\"].includes(template)) {\n throw new Error(\"Template must be one of: basic, hono, auth, full\");\n }\n\n const pkg = await Bun.file(resolve(import.meta.dir, \"../package.json\")).json() as {\n name: string;\n version: string;\n peerDependencies: Record<string, string>;\n peerDependenciesMeta?: Record<string, { optional?: boolean }>;\n devDependencies: Record<string, string>;\n };\n const pinnedVersion = (name: string): string => {\n const version = pkg.devDependencies[name];\n if (!version) throw new Error(`Package metadata is missing ${name}`);\n return version;\n };\n const packageSpec = process.env.AEGRA_INIT_PACKAGE_SPEC?.trim() || pkg.version;\n const bunVersion = pinnedVersion(\"@types/bun\");\n const honoVersion = String(options[\"hono-version\"] ?? \"\").trim() || pinnedVersion(\"hono\");\n // aegra-hono keeps every third-party runtime library as a peer dependency so\n // projects own their versions. Only the required ones are declared, so a new\n // project never installs Redis, metrics, tracing, or embedding provider SDKs\n // it has not enabled.\n const runtimeDependencies: Record<string, string> = {};\n for (const name of Object.keys(pkg.peerDependencies).sort()) {\n if (pkg.peerDependenciesMeta?.[name]?.optional) continue;\n runtimeDependencies[name] = name === \"hono\" ? honoVersion : pinnedVersion(name);\n }\n const escapedName = JSON.stringify(`Hello from ${name}`);\n const graph = `import { AIMessage } from \"@langchain/core/messages\";\\nimport { MessagesAnnotation, StateGraph, START, END } from \"@langchain/langgraph\";\\nimport { defineGraph } from ${JSON.stringify(`${pkg.name}/graph`)};\\n\\nexport const graph = defineGraph(new StateGraph(MessagesAnnotation)\\n .addNode(\"reply\", async () => ({ messages: [new AIMessage(${escapedName})] }))\\n .addEdge(START, \"reply\").addEdge(\"reply\", END).compile());\\n`;\n const withHono = template === \"hono\" || template === \"full\";\n const withAuth = template === \"auth\" || template === \"full\";\n const withRedis = template === \"full\";\n const config = {\n name,\n dependencies: [\"./src\"],\n graphs: { [slug]: \"./src/graph.ts:graph\" },\n ...(withAuth ? { auth: { path: \"./src/auth.ts:auth\" } } : {}),\n ...(withHono ? { http: { app: \"./src/app.ts:app\", ...(withAuth ? { enable_custom_route_auth: true } : {}) } } : {}),\n };\n const redisService = withRedis ? ` redis:\\n image: redis:7-alpine\\n restart: unless-stopped\\n ports:\\n - \"\\${REDIS_PORT:-6379}:6379\"\\n volumes:\\n - redis-data:/data\\n healthcheck:\\n test: [\"CMD\", \"redis-cli\", \"ping\"]\\n interval: 5s\\n timeout: 5s\\n retries: 10\\n\\n` : \"\";\n const redisDependency = withRedis ? ` redis:\\n condition: service_healthy\\n` : \"\";\n const compose = `services:\\n postgres:\\n image: pgvector/pgvector:pg18\\n restart: unless-stopped\\n environment:\\n POSTGRES_USER: \\${POSTGRES_USER:-postgres}\\n POSTGRES_PASSWORD: \\${POSTGRES_PASSWORD:-postgres}\\n POSTGRES_DB: \\${POSTGRES_DB:-aegra}\\n ports:\\n - \"\\${POSTGRES_PORT:-5432}:5432\"\\n volumes:\\n - postgres-data:/var/lib/postgresql\\n healthcheck:\\n test: [\"CMD-SHELL\", \"pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB\"]\\n interval: 5s\\n timeout: 5s\\n retries: 10\\n\\n${redisService} api:\\n build: .\\n restart: unless-stopped\\n ports:\\n - \"\\${PORT:-2026}:2026\"\\n env_file:\\n - .env\\n environment:\\n DATABASE_URL: postgresql://\\${POSTGRES_USER:-postgres}:\\${POSTGRES_PASSWORD:-postgres}@postgres:5432/\\${POSTGRES_DB:-aegra}\\n PORT: \"2026\"\\n AEGRA_CONFIG: /app/aegra.json\\n REDIS_BROKER_ENABLED: \"${withRedis}\"\\n REDIS_URL: redis://redis:6379/0\\n depends_on:\\n postgres:\\n condition: service_healthy\\n${redisDependency} healthcheck:\\n test: [\"CMD\", \"bun\", \"-e\", \"const r=await fetch('http://localhost:2026/health');process.exit(r.ok?0:1)\"]\\n interval: 30s\\n timeout: 10s\\n retries: 3\\n start_period: 10s\\n\\nvolumes:\\n postgres-data:\\n${withRedis ? \" redis-data:\\n\" : \"\"}`;\n const dockerfile = `FROM oven/bun:${bunVersion}-alpine AS install\\nWORKDIR /app\\nCOPY package.json bun.lock ./\\nRUN bun install --frozen-lockfile --production\\n\\nFROM oven/bun:${bunVersion}-alpine AS runtime\\nWORKDIR /app\\nENV NODE_ENV=production\\nCOPY --from=install /app/node_modules ./node_modules\\nCOPY package.json aegra.json ./\\nCOPY src ./src\\nUSER bun\\nEXPOSE 2026\\nCMD [\"bun\", \"run\", \"start\"]\\n`;\n const localServices = `docker compose up -d postgres${withRedis ? \" redis\" : \"\"}`;\n // Redis is the only optional integration the templates switch on. Prometheus\n // metrics, OpenTelemetry tracing, and store embedding providers stay\n // uninstalled until a project enables them and adds the packages itself.\n if (withRedis) runtimeDependencies.ioredis = pinnedVersion(\"ioredis\");\n const packageJson = {\n name: slug,\n private: true,\n type: \"module\",\n scripts: {\n dev: \"aegra dev\",\n start: \"aegra serve\",\n check: \"tsc --noEmit\",\n db: \"aegra db upgrade\",\n \"services:up\": localServices,\n \"services:down\": \"docker compose down\",\n \"docker:up\": \"docker compose up --build -d\",\n \"docker:down\": \"docker compose down\",\n },\n dependencies: {\n [pkg.name]: packageSpec,\n ...runtimeDependencies,\n },\n devDependencies: {\n \"@types/bun\": bunVersion,\n typescript: pinnedVersion(\"typescript\"),\n },\n engines: { bun: `>=${bunVersion}` },\n packageManager: `bun@${bunVersion}`,\n };\n const files: Record<string, string> = {\n \"aegra.json\": `${JSON.stringify(config, null, 2)}\\n`,\n \"package.json\": `${JSON.stringify(packageJson, null, 2)}\\n`,\n \"tsconfig.json\": `${JSON.stringify({ compilerOptions: { target: \"ES2023\", module: \"Preserve\", moduleResolution: \"bundler\", strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true, noEmit: true, types: [\"bun\"], skipLibCheck: true }, include: [\"src\"] }, null, 2)}\\n`,\n \"src/graph.ts\": graph,\n \".env.example\": renderEnvironment({ name, version: pkg.version, withAuth, withRedis }),\n \".gitignore\": `node_modules\\n.env\\ndist\\n*.tsbuildinfo\\n`,\n \".dockerignore\": `node_modules\\n.env\\ndist\\n.git\\n*.log\\n`,\n \"Dockerfile\": dockerfile,\n \"docker-compose.yml\": compose,\n \"README.md\": `# ${name}\\n\\nTypeScript Aegra backend generated with \\`${pkg.name}\\`.\\n\\n## Local development\\n\\n\\`\\`\\`bash\\nbun install\\ncp .env.example .env\\nbun run services:up\\nbun run db\\nbun run dev\\n\\`\\`\\`\\n\\nThe API listens on http://localhost:2026 and exposes its API reference at http://localhost:2026/docs.\\n\\n## Docker\\n\\n\\`\\`\\`bash\\nbun install\\ncp .env.example .env\\nbun run docker:up\\n\\`\\`\\`\\n`,\n };\n if (withHono) files[\"src/app.ts\"] = `import { Hono } from \"hono\";\\nimport { defineApp } from ${JSON.stringify(`${pkg.name}/hono`)};\\nimport type { AppVariables } from ${JSON.stringify(`${pkg.name}/types`)};\\n\\nexport const app = defineApp(new Hono<{ Variables: AppVariables }>().get(\"/hello\", (context) => context.json({ message: ${escapedName} })));\\n`;\n if (withAuth) files[\"src/auth.ts\"] = `import { Auth } from ${JSON.stringify(`${pkg.name}/auth`)};\\n\\nexport const auth = new Auth();\\nauth.authenticate((request) => {\\n const token = process.env.AEGRA_AUTH_TOKEN;\\n if (!token || request.headers.get(\"authorization\") !== \\`Bearer \\${token}\\`) throw new Error(\"Invalid bearer token\");\\n return { identity: request.headers.get(\"x-user-id\")?.trim() || \"authenticated-user\", isAuthenticated: true, permissions: [] };\\n});\\n`;\n let created = 0;\n let skipped = 0;\n for (const [path, content] of Object.entries(files)) {\n if (await writeProjectFile(root, path, content, Boolean(options.force)) === \"created\") created++;\n else skipped++;\n }\n console.log(`Created ${created} files in ${root}${skipped ? ` (${skipped} skipped; use --force to overwrite)` : \"\"}`);\n if (!skipped) {\n const changeDirectory = root === resolve(\".\") ? \"\" : ` cd ${JSON.stringify(root)}\\n`;\n console.log(`\\nNext steps:\\n${changeDirectory} bun install\\n cp .env.example .env\\n bun run services:up\\n bun run db\\n bun run dev`);\n }\n}\n\nexport async function main(argv = process.argv.slice(2)): Promise<void> {\n const [command, ...args] = argv;\n if (!command || command === \"help\" || command === \"--help\") usage(command ? 0 : 1);\n if (command === \"init\") return initProject(args);\n if (command === \"version\" || command === \"--version\") {\n const pkg = await Bun.file(resolve(import.meta.dir, \"../package.json\")).json() as { version: string };\n console.log(pkg.version);\n return;\n }\n if (command === \"dev\" || command === \"serve\") {\n const { options } = parseOptions(args);\n if (options.help) usage(0);\n const env = await serverEnvironment(options);\n const builtEntrypoint = resolve(import.meta.dir, \"index.js\");\n const entrypoint = await Bun.file(builtEntrypoint).exists() ? builtEntrypoint : resolve(import.meta.dir, \"index.ts\");\n if (command === \"dev\") run([\"bun\", \"--hot\", entrypoint], env);\n else await import(entrypoint);\n return;\n }\n if (command === \"up\" || command === \"down\") return run([\"docker\", \"compose\", command, ...args]);\n if (command === \"db\" && args[0] === \"upgrade\") {\n const { options } = parseOptions(args.slice(1));\n await serverEnvironment(options);\n const { migrate, closeDatabase } = await import(\"./core/database.ts\");\n await migrate();\n await closeDatabase();\n console.log(\"Database is up to date\");\n return;\n }\n usage();\n}\n\nif (import.meta.main) main().catch((error: unknown) => { console.error(error instanceof Error ? error.message : error); process.exit(1); });\n"
10
10
  ],
11
11
  "mappings": "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",
12
- "debugId": "010F5F7EA75E374664756E2164756E21",
12
+ "debugId": "A19901B09265E35C64756E2164756E21",
13
13
  "names": []
14
14
  }
package/dist/graph.d.ts CHANGED
@@ -23,6 +23,12 @@ export interface ServerRuntime {
23
23
  store?: BaseStore;
24
24
  context?: JsonObject | null;
25
25
  }
26
- export type GraphFactory = (() => RunnableGraph | Promise<RunnableGraph>) | ((config: RunnableConfig | undefined) => RunnableGraph | Promise<RunnableGraph>) | ((runtime: ServerRuntime) => RunnableGraph | Promise<RunnableGraph>) | ((config: RunnableConfig | undefined, runtime: ServerRuntime) => RunnableGraph | Promise<RunnableGraph>);
27
- export type GraphDefinition = RunnableGraph | GraphFactory;
26
+ export interface GraphInput {
27
+ config: RunnableConfig | undefined;
28
+ runtime: ServerRuntime;
29
+ }
30
+ export interface GraphProvider {
31
+ resolve(input: GraphInput): RunnableGraph | Promise<RunnableGraph>;
32
+ }
33
+ export type GraphDefinition = RunnableGraph | GraphProvider;
28
34
  export declare function defineGraph<T extends GraphDefinition>(graph: T): T;
package/dist/graph.js.map CHANGED
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/graph.ts"],
4
4
  "sourcesContent": [
5
- "import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport type { BaseCheckpointSaver, BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport type { AuthUser, JsonObject } from \"./types.ts\";\n\nexport type RunnableGraph = {\n invoke(input: unknown, options?: Record<string, unknown>): Promise<unknown>;\n stream(input: unknown, options?: Record<string, unknown>): Promise<AsyncIterable<unknown>>;\n getState?(config: RunnableConfig, options?: Record<string, unknown>): Promise<unknown>;\n getStateHistory?(config: RunnableConfig, options?: Record<string, unknown>): AsyncIterable<unknown>;\n updateState?(config: RunnableConfig, values: unknown, asNode?: string): Promise<RunnableConfig>;\n getGraphAsync?(config?: RunnableConfig & { xray?: boolean | number }): Promise<{ toJSON(): Record<string, unknown> }>;\n getSubgraphsAsync?(namespace?: string, recurse?: boolean): AsyncGenerator<[string, RunnableGraph]>;\n builder?: unknown;\n checkpointer?: BaseCheckpointSaver | boolean;\n store?: BaseStore;\n};\n\nexport interface ServerRuntime {\n accessContext: \"threads.create_run\" | \"threads.update\" | \"threads.read\" | \"assistants.read\";\n user: AuthUser;\n store?: BaseStore;\n context?: JsonObject | null;\n}\n\nexport type GraphFactory =\n | (() => RunnableGraph | Promise<RunnableGraph>)\n | ((config: RunnableConfig | undefined) => RunnableGraph | Promise<RunnableGraph>)\n | ((runtime: ServerRuntime) => RunnableGraph | Promise<RunnableGraph>)\n | ((config: RunnableConfig | undefined, runtime: ServerRuntime) => RunnableGraph | Promise<RunnableGraph>);\n\nexport type GraphDefinition = RunnableGraph | GraphFactory;\n\nexport function defineGraph<T extends GraphDefinition>(graph: T): T {\n return graph;\n}\n"
5
+ "import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport type { BaseCheckpointSaver, BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport type { AuthUser, JsonObject } from \"./types.ts\";\n\nexport type RunnableGraph = {\n invoke(input: unknown, options?: Record<string, unknown>): Promise<unknown>;\n stream(input: unknown, options?: Record<string, unknown>): Promise<AsyncIterable<unknown>>;\n getState?(config: RunnableConfig, options?: Record<string, unknown>): Promise<unknown>;\n getStateHistory?(config: RunnableConfig, options?: Record<string, unknown>): AsyncIterable<unknown>;\n updateState?(config: RunnableConfig, values: unknown, asNode?: string): Promise<RunnableConfig>;\n getGraphAsync?(config?: RunnableConfig & { xray?: boolean | number }): Promise<{ toJSON(): Record<string, unknown> }>;\n getSubgraphsAsync?(namespace?: string, recurse?: boolean): AsyncGenerator<[string, RunnableGraph]>;\n builder?: unknown;\n checkpointer?: BaseCheckpointSaver | boolean;\n store?: BaseStore;\n};\n\nexport interface ServerRuntime {\n accessContext: \"threads.create_run\" | \"threads.update\" | \"threads.read\" | \"assistants.read\";\n user: AuthUser;\n store?: BaseStore;\n context?: JsonObject | null;\n}\n\nexport interface GraphInput {\n config: RunnableConfig | undefined;\n runtime: ServerRuntime;\n}\n\nexport interface GraphProvider {\n resolve(input: GraphInput): RunnableGraph | Promise<RunnableGraph>;\n}\n\nexport type GraphDefinition = RunnableGraph | GraphProvider;\n\nexport function defineGraph<T extends GraphDefinition>(graph: T): T {\n return graph;\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;AAgCO,SAAS,WAAsC,CAAC,OAAa;AAAA,EAClE,OAAO;AAAA;",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;AAmCO,SAAS,WAAsC,CAAC,OAAa;AAAA,EAClE,OAAO;AAAA;",
8
8
  "debugId": "3C2AFB1C029A7EE964756E2164756E21",
9
9
  "names": []
10
10
  }
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ var init_settings = __esm(() => {
22
22
  booleanFromEnv = z.stringbool().default(false);
23
23
  environmentShape = {
24
24
  PROJECT_NAME: z.string().default("Aegra"),
25
- VERSION: z.string().default("0.11.5"),
25
+ VERSION: z.string().default("0.13.0"),
26
26
  ENV_MODE: z.string().default("PRODUCTION"),
27
27
  LOG_VERBOSITY: z.string().default("verbose"),
28
28
  LOG_EXCLUDE_PATHS: z.string().default(""),
@@ -472,23 +472,6 @@ var init_database = __esm(() => {
472
472
  ];
473
473
  });
474
474
 
475
- // src/auth.ts
476
- class Auth {
477
- authenticateHandler;
478
- handlers = new Map;
479
- authenticate(handler) {
480
- this.authenticateHandler = handler;
481
- return handler;
482
- }
483
- on(resource, action, handler) {
484
- this.handlers.set(`${resource}:${action}`, handler);
485
- return handler;
486
- }
487
- handler(resource, action) {
488
- return this.handlers.get(`${resource}:${action}`) ?? this.handlers.get(`${resource}:*`) ?? this.handlers.get(`*:${action}`) ?? this.handlers.get("*:*");
489
- }
490
- }
491
-
492
475
  // src/app.ts
493
476
  init_settings();
494
477
  init_project();
@@ -598,6 +581,9 @@ var jsonObjectSchema = z3.record(z3.string(), z3.json());
598
581
  function getAuthorizationValue(context) {
599
582
  return context.get("authorizationValue") ?? {};
600
583
  }
584
+ function getAuthorizationFilter(context) {
585
+ return context.get("authorizationFilter") ?? {};
586
+ }
601
587
  async function parseJson(context, schema) {
602
588
  let body;
603
589
  try {
@@ -656,6 +642,13 @@ function parseOffset(value) {
656
642
  var anonymousUser = { identity: "anonymous", isAuthenticated: false, permissions: [] };
657
643
  var authenticate;
658
644
  var authorizationHandler;
645
+ function isAuthRegistry(value) {
646
+ if (!value || typeof value !== "object")
647
+ return false;
648
+ const candidate = value;
649
+ const handlers = candidate.handlers;
650
+ return (candidate.authenticateHandler === undefined || typeof candidate.authenticateHandler === "function") && typeof candidate.handler === "function" && typeof handlers?.get === "function" && typeof handlers.set === "function";
651
+ }
659
652
  async function initializeAuth() {
660
653
  authenticate = undefined;
661
654
  authorizationHandler = undefined;
@@ -671,7 +664,7 @@ async function initializeAuth() {
671
664
  authenticate = exported;
672
665
  return;
673
666
  }
674
- if (exported instanceof Auth) {
667
+ if (isAuthRegistry(exported)) {
675
668
  authenticate = exported.authenticateHandler;
676
669
  authorizationHandler = (resource, action) => exported.handler(resource, action);
677
670
  } else if (exported && typeof exported === "object") {
@@ -755,10 +748,10 @@ function pathValues(path) {
755
748
  values.cron_id = cronId;
756
749
  return values;
757
750
  }
758
- async function authorizeResource(context, resource, action, value) {
751
+ async function runAuthorizationHandler(context, resource, action, value) {
759
752
  const handler = authorizationHandler?.(resource, action);
760
753
  if (!handler)
761
- return value;
754
+ return { value, filter: {} };
762
755
  const user = context.get("user");
763
756
  const result = await handler({ user, resource, action, permissions: user.permissions }, value);
764
757
  if (result === false)
@@ -766,12 +759,17 @@ async function authorizeResource(context, resource, action, value) {
766
759
  if (result !== undefined && result !== true && (typeof result !== "object" || Array.isArray(result) || result === null)) {
767
760
  throw new Error("Authorization handlers must return an object, true, false, or undefined");
768
761
  }
769
- return result && typeof result === "object" ? { ...value, ...result } : value;
762
+ const filter = result && typeof result === "object" ? result : {};
763
+ return { value: { ...value, ...filter }, filter };
764
+ }
765
+ async function authorizeResource(context, resource, action, value) {
766
+ return (await runAuthorizationHandler(context, resource, action, value)).value;
770
767
  }
771
768
  async function authorize(context) {
772
769
  const event = authorizationEvent(context.req.method, context.req.path);
773
770
  if (!event) {
774
771
  context.set("authorizationValue", {});
772
+ context.set("authorizationFilter", {});
775
773
  return;
776
774
  }
777
775
  let body = {};
@@ -783,12 +781,15 @@ async function authorize(context) {
783
781
  const query = Object.fromEntries(new URL(context.req.url).searchParams);
784
782
  const value = { ...query, ...body, ...pathValues(context.req.path) };
785
783
  const [resource, action] = event;
786
- context.set("authorizationValue", await authorizeResource(context, resource, action, value));
784
+ const authorized = await runAuthorizationHandler(context, resource, action, value);
785
+ context.set("authorizationValue", authorized.value);
786
+ context.set("authorizationFilter", authorized.filter);
787
787
  }
788
788
  var authMiddleware = async (context, next) => {
789
789
  if (!authenticate) {
790
790
  context.set("user", anonymousUser);
791
791
  context.set("authorizationValue", {});
792
+ context.set("authorizationFilter", {});
792
793
  await next();
793
794
  return;
794
795
  }
@@ -1118,20 +1119,6 @@ storeRoutes.post("/store/namespaces", async (context) => {
1118
1119
  });
1119
1120
 
1120
1121
  // src/services/graph-registry.ts
1121
- function firstParameterName(factory) {
1122
- const source = factory.toString();
1123
- const arrow = source.match(/^\s*(?:async\s*)?\(?\s*([A-Za-z_$][\w$]*)/);
1124
- return arrow?.[1] ?? "";
1125
- }
1126
- function callGraphFactory(factory, config, runtime) {
1127
- const callable = factory;
1128
- if (factory.length === 0)
1129
- return callable();
1130
- if (factory.length === 1) {
1131
- return /^(runtime|rt)$/i.test(firstParameterName(factory)) ? callable(runtime) : callable(config);
1132
- }
1133
- return callable(config, runtime);
1134
- }
1135
1122
  var graphs = new Map;
1136
1123
  var checkpointer;
1137
1124
  function deterministicAssistantId(graphId) {
@@ -1152,9 +1139,14 @@ function isRunnableGraph(value) {
1152
1139
  const candidate = value;
1153
1140
  return typeof candidate.invoke === "function" && typeof candidate.stream === "function";
1154
1141
  }
1142
+ function isGraphProvider(value) {
1143
+ if (!value || typeof value !== "object" || isRunnableGraph(value))
1144
+ return false;
1145
+ return typeof value.resolve === "function";
1146
+ }
1155
1147
  function assertGraphDefinition(value, exportName, modulePath) {
1156
- if (typeof value !== "function" && !isRunnableGraph(value)) {
1157
- throw new Error(`Graph export '${exportName}' in ${modulePath} must be a runnable graph or graph factory`);
1148
+ if (!isRunnableGraph(value) && !isGraphProvider(value)) {
1149
+ throw new Error(`Graph export '${exportName}' in ${modulePath} must be a runnable graph or GraphProvider`);
1158
1150
  }
1159
1151
  }
1160
1152
  async function initializeGraphs() {
@@ -1208,9 +1200,9 @@ async function getGraph(graphId, options) {
1208
1200
  store,
1209
1201
  ...options.context !== undefined ? { context: options.context } : {}
1210
1202
  };
1211
- const resolved = typeof configured === "function" ? await callGraphFactory(configured, options.config, runtime) : configured;
1203
+ const resolved = isGraphProvider(configured) ? await configured.resolve({ config: options.config, runtime }) : configured;
1212
1204
  if (!isRunnableGraph(resolved))
1213
- throw new Error(`Graph factory '${graphId}' did not return a runnable graph`);
1205
+ throw new Error(`Graph provider '${graphId}' did not return a runnable graph`);
1214
1206
  if (!resolved.checkpointer && checkpointer)
1215
1207
  resolved.checkpointer = checkpointer;
1216
1208
  return resolved;
@@ -3232,7 +3224,7 @@ var openapi_default = {
3232
3224
  info: {
3233
3225
  title: "Aegra",
3234
3226
  description: "\u751F\u4EA7\u53EF\u7528\u7684 Agent Protocol \u670D\u52A1\u7AEF",
3235
- version: "0.11.5"
3227
+ version: "0.13.0"
3236
3228
  },
3237
3229
  paths: {
3238
3230
  "/info": {
@@ -9523,8 +9515,72 @@ healthRoutes.get("/live", (context) => context.json({ status: "alive" }));
9523
9515
  init_database();
9524
9516
  init_settings();
9525
9517
  import { Hono as Hono8 } from "hono";
9526
- import { and as and9, asc as asc6, desc as desc6, eq as eq9, inArray as inArray6, sql as sql8 } from "drizzle-orm";
9518
+ import { and as and10, asc as asc6, desc as desc6, eq as eq9, inArray as inArray6, sql as sql9 } from "drizzle-orm";
9527
9519
  import { z as z11 } from "zod";
9520
+
9521
+ // src/core/auth-filters.ts
9522
+ import { and as and8, or as or4, sql as sql7 } from "drizzle-orm";
9523
+ var maxFilterDepth = 2;
9524
+ function malformed(reason) {
9525
+ return new ApiError(500, `Auth handler filter ${reason}. Check the filter returned by your auth handler.`);
9526
+ }
9527
+ function isPlainObject2(value) {
9528
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9529
+ }
9530
+ function unwrapMetadataEnvelope(filters) {
9531
+ const envelope = filters.metadata;
9532
+ if (!isPlainObject2(envelope))
9533
+ return filters;
9534
+ const { metadata: _envelope, ...rest } = filters;
9535
+ return { ...envelope, ...rest };
9536
+ }
9537
+ function combine(operator, clauses) {
9538
+ return operator === "and" ? and8(...clauses) : or4(...clauses);
9539
+ }
9540
+ function compileField(column, key, value) {
9541
+ if (!isPlainObject2(value)) {
9542
+ return sql7`${column} @> ${JSON.stringify({ [key]: value ?? null })}::jsonb`;
9543
+ }
9544
+ const entries = Object.entries(value);
9545
+ if (entries.length !== 1) {
9546
+ throw malformed("value must be a dict with exactly one operator key ($eq or $contains)");
9547
+ }
9548
+ const [operator, operand] = entries[0];
9549
+ if (operator === "$eq") {
9550
+ return sql7`${column} @> ${JSON.stringify({ [key]: operand ?? null })}::jsonb`;
9551
+ }
9552
+ if (operator === "$contains") {
9553
+ const items = Array.isArray(operand) ? operand : [operand ?? null];
9554
+ return sql7`(${column} -> ${key}::text) @> ${JSON.stringify(items)}::jsonb`;
9555
+ }
9556
+ throw malformed(`operator '${operator}' is not supported; use $eq or $contains`);
9557
+ }
9558
+ function compileBooleanOperator(column, operator, branches, depth) {
9559
+ if (depth >= maxFilterDepth) {
9560
+ throw malformed(`nests deeper than ${maxFilterDepth} levels`);
9561
+ }
9562
+ if (!Array.isArray(branches) || branches.length < 2) {
9563
+ throw malformed(`'${operator}' must be a list of at least 2 filter objects`);
9564
+ }
9565
+ for (const branch of branches) {
9566
+ if (!isPlainObject2(branch) || !Object.keys(branch).length) {
9567
+ throw malformed(`'${operator}' contains an empty or non-dict branch`);
9568
+ }
9569
+ }
9570
+ const compiled = branches.map((branch) => combine("and", compile(column, branch, depth + 1)));
9571
+ return combine(operator === "$or" ? "or" : "and", compiled);
9572
+ }
9573
+ function compile(column, filters, depth) {
9574
+ return Object.entries(filters).map(([key, value]) => key === "$or" || key === "$and" ? compileBooleanOperator(column, key, value, depth) : compileField(column, key, value));
9575
+ }
9576
+ function buildMetadataFilter(column, filters) {
9577
+ if (!filters || !Object.keys(filters).length)
9578
+ return;
9579
+ const clauses = compile(column, unwrapMetadataEnvelope(filters), 0);
9580
+ return clauses.length ? combine("and", clauses) : undefined;
9581
+ }
9582
+
9583
+ // src/routes/threads.ts
9528
9584
  init_schema();
9529
9585
 
9530
9586
  // src/services/thread-ttl.ts
@@ -9532,7 +9588,7 @@ init_project();
9532
9588
  init_settings();
9533
9589
  init_database();
9534
9590
  import { z as z10 } from "zod";
9535
- import { and as and8, asc as asc5, eq as eq8, inArray as inArray5, lte as lte2, notExists as notExists2, sql as sql7 } from "drizzle-orm";
9591
+ import { and as and9, asc as asc5, eq as eq8, inArray as inArray5, lte as lte2, notExists as notExists2, sql as sql8 } from "drizzle-orm";
9536
9592
  init_schema();
9537
9593
  var ttlSchema = z10.object({
9538
9594
  strategy: z10.enum(["delete", "keep_latest"]).default("delete"),
@@ -9566,26 +9622,26 @@ async function resolveThreadTtl(request) {
9566
9622
  ttlMinutes: requestedMinutes ?? configured?.default_ttl ?? 43200
9567
9623
  };
9568
9624
  }
9569
- async function pruneExpiredThreads(userId) {
9625
+ async function pruneExpiredThreads(userId, metadataFilter) {
9570
9626
  const config = await threadTtlConfig() ?? ttlSchema.parse({});
9571
9627
  return db.transaction(async (transaction) => {
9572
- const activeRun = transaction.select({ value: sql7`1` }).from(runs).where(and8(eq8(runs.thread_id, threadTtl.thread_id), inArray5(runs.status, ["pending", "running"])));
9628
+ const activeRun = transaction.select({ value: sql8`1` }).from(runs).where(and9(eq8(runs.thread_id, threadTtl.thread_id), inArray5(runs.status, ["pending", "running"])));
9573
9629
  const rows = await transaction.select({
9574
9630
  thread_id: threadTtl.thread_id,
9575
9631
  strategy: threadTtl.strategy,
9576
9632
  ttl_minutes: threadTtl.ttl_minutes
9577
- }).from(threadTtl).innerJoin(threads, eq8(threads.thread_id, threadTtl.thread_id)).where(and8(lte2(threadTtl.expires_at, new Date), userId ? eq8(threads.user_id, userId) : undefined, notExists2(activeRun))).orderBy(asc5(threadTtl.expires_at)).limit(config.sweep_limit).for("update", { skipLocked: true });
9633
+ }).from(threadTtl).innerJoin(threads, eq8(threads.thread_id, threadTtl.thread_id)).where(and9(lte2(threadTtl.expires_at, new Date), userId ? eq8(threads.user_id, userId) : undefined, buildMetadataFilter(threads.metadata_json, metadataFilter), notExists2(activeRun))).orderBy(asc5(threadTtl.expires_at)).limit(config.sweep_limit).for("update", { skipLocked: true });
9578
9634
  let deleted = 0;
9579
9635
  let pruned = 0;
9580
9636
  for (const row of rows) {
9581
9637
  if (row.strategy === "keep_latest") {
9582
- await transaction.execute(sql7`DELETE FROM checkpoints c USING (
9638
+ await transaction.execute(sql8`DELETE FROM checkpoints c USING (
9583
9639
  SELECT checkpoint_ns, max(checkpoint_id) latest_id FROM checkpoints WHERE thread_id=${row.thread_id} GROUP BY checkpoint_ns
9584
9640
  ) keep WHERE c.thread_id=${row.thread_id} AND c.checkpoint_ns=keep.checkpoint_ns AND c.checkpoint_id<>keep.latest_id`);
9585
- await transaction.execute(sql7`DELETE FROM checkpoint_writes w WHERE w.thread_id=${row.thread_id} AND NOT EXISTS (
9641
+ await transaction.execute(sql8`DELETE FROM checkpoint_writes w WHERE w.thread_id=${row.thread_id} AND NOT EXISTS (
9586
9642
  SELECT 1 FROM checkpoints c WHERE c.thread_id=w.thread_id AND c.checkpoint_ns=w.checkpoint_ns
9587
9643
  AND c.checkpoint_id=w.checkpoint_id)`);
9588
- await transaction.execute(sql7`DELETE FROM checkpoint_blobs b WHERE b.thread_id=${row.thread_id} AND NOT EXISTS (
9644
+ await transaction.execute(sql8`DELETE FROM checkpoint_blobs b WHERE b.thread_id=${row.thread_id} AND NOT EXISTS (
9589
9645
  SELECT 1 FROM checkpoints c, jsonb_each_text(c.checkpoint->'channel_versions') cv(channel,version)
9590
9646
  WHERE c.thread_id=b.thread_id AND c.checkpoint_ns=b.checkpoint_ns AND cv.channel=b.channel AND cv.version=b.version)`);
9591
9647
  await transaction.update(threadTtl).set({ expires_at: new Date(Date.now() + row.ttl_minutes * 60000) }).where(eq8(threadTtl.thread_id, row.thread_id));
@@ -9666,11 +9722,12 @@ function authorizationFilters3(context) {
9666
9722
  return [
9667
9723
  typeof value.thread_id === "string" ? eq9(threads.thread_id, value.thread_id) : undefined,
9668
9724
  typeof value.status === "string" ? eq9(threads.status, value.status) : undefined,
9669
- Object.keys(metadata).length ? sql8`${threads.metadata_json} @> ${JSON.stringify(metadata)}::jsonb` : undefined
9725
+ Object.keys(metadata).length ? sql9`${threads.metadata_json} @> ${JSON.stringify(metadata)}::jsonb` : undefined,
9726
+ buildMetadataFilter(threads.metadata_json, getAuthorizationFilter(context))
9670
9727
  ].filter((filter) => filter !== undefined);
9671
9728
  }
9672
9729
  async function ownedThread2(threadId, context) {
9673
- const rows = await db.select().from(threads).where(and9(eq9(threads.thread_id, threadId), eq9(threads.user_id, context.get("user").identity), ...authorizationFilters3(context))).limit(1);
9730
+ const rows = await db.select().from(threads).where(and10(eq9(threads.thread_id, threadId), eq9(threads.user_id, context.get("user").identity), ...authorizationFilters3(context))).limit(1);
9674
9731
  if (!rows[0])
9675
9732
  throw new ApiError(404, "Thread not found");
9676
9733
  return thread(rows[0]);
@@ -9682,7 +9739,7 @@ async function graphForThread(threadId, context) {
9682
9739
  const graphId = typeof owned.metadata.graph_id === "string" ? owned.metadata.graph_id : undefined;
9683
9740
  if (graphId)
9684
9741
  return getGraph(graphId, { user, accessContext: "threads.read", config: graphConfig(threadId) });
9685
- const rows = await db.select({ graph_id: assistants.graph_id }).from(assistants).innerJoin(runs, eq9(runs.assistant_id, assistants.assistant_id)).where(and9(eq9(runs.thread_id, threadId), eq9(runs.user_id, userId))).orderBy(desc6(runs.created_at)).limit(1);
9742
+ const rows = await db.select({ graph_id: assistants.graph_id }).from(assistants).innerJoin(runs, eq9(runs.assistant_id, assistants.assistant_id)).where(and10(eq9(runs.thread_id, threadId), eq9(runs.user_id, userId))).orderBy(desc6(runs.created_at)).limit(1);
9686
9743
  if (!rows[0])
9687
9744
  return;
9688
9745
  return getGraph(String(rows[0].graph_id), { user, accessContext: "threads.read", config: graphConfig(threadId) });
@@ -9749,7 +9806,7 @@ threadRoutes.post("/threads", async (context) => {
9749
9806
  });
9750
9807
  if (created[0])
9751
9808
  return context.json(thread(created[0]));
9752
- const existing = await db.select().from(threads).where(and9(eq9(threads.thread_id, id), eq9(threads.user_id, userId))).limit(1);
9809
+ const existing = await db.select().from(threads).where(and10(eq9(threads.thread_id, id), eq9(threads.user_id, userId))).limit(1);
9753
9810
  if (existing[0] && ifExists === "do_nothing")
9754
9811
  return context.json(thread(existing[0]));
9755
9812
  throw new ApiError(409, "Thread already exists");
@@ -9757,7 +9814,7 @@ threadRoutes.post("/threads", async (context) => {
9757
9814
  threadRoutes.get("/threads", async (context) => {
9758
9815
  const userId = context.get("user").identity;
9759
9816
  const filters = authorizationFilters3(context);
9760
- const rows = await db.select().from(threads).where(and9(eq9(threads.user_id, userId), ...filters)).orderBy(desc6(threads.created_at));
9817
+ const rows = await db.select().from(threads).where(and10(eq9(threads.user_id, userId), ...filters)).orderBy(desc6(threads.created_at));
9761
9818
  return context.json({ threads: rows.map((row) => thread(row)), total: rows.length });
9762
9819
  });
9763
9820
  threadRoutes.post("/threads/search", async (context) => {
@@ -9768,7 +9825,7 @@ threadRoutes.post("/threads/search", async (context) => {
9768
9825
  throw new ApiError(422, "Invalid order_by");
9769
9826
  const fieldName = body.sort_by ?? legacy?.[1]?.toLowerCase() ?? "created_at";
9770
9827
  const field = threads[fieldName];
9771
- const rows = await db.select().from(threads).where(and9(eq9(threads.user_id, userId), body.status ? eq9(threads.status, body.status) : undefined, sql8`${threads.metadata_json} @> ${JSON.stringify(body.metadata ?? {})}::jsonb`)).orderBy((body.sort_order ?? legacy?.[2]?.toLowerCase()) === "asc" ? asc6(field) : desc6(field)).limit(clampLimit(body.limit, 20, settings.MAX_SEARCH_LIMIT)).offset(body.offset ?? 0);
9828
+ const rows = await db.select().from(threads).where(and10(eq9(threads.user_id, userId), body.status ? eq9(threads.status, body.status) : undefined, sql9`${threads.metadata_json} @> ${JSON.stringify(body.metadata ?? {})}::jsonb`, buildMetadataFilter(threads.metadata_json, getAuthorizationFilter(context)))).orderBy((body.sort_order ?? legacy?.[2]?.toLowerCase()) === "asc" ? asc6(field) : desc6(field)).limit(clampLimit(body.limit, 20, settings.MAX_SEARCH_LIMIT)).offset(body.offset ?? 0);
9772
9829
  return context.json(rows.map((row) => thread(row)));
9773
9830
  });
9774
9831
  threadRoutes.get("/threads/:threadId", async (context) => context.json(await ownedThread2(context.req.param("threadId"), context)));
@@ -9777,7 +9834,7 @@ threadRoutes.patch("/threads/:threadId", async (context) => {
9777
9834
  const id = context.req.param("threadId");
9778
9835
  const userId = context.get("user").identity;
9779
9836
  const patch = { ...body.metadata ?? {}, ...authorizedMetadata(context) };
9780
- const rows = await db.update(threads).set({ metadata_json: sql8`${threads.metadata_json} || ${JSON.stringify(patch)}::jsonb`, updated_at: new Date }).where(and9(eq9(threads.thread_id, id), eq9(threads.user_id, userId), ...authorizationFilters3(context))).returning();
9837
+ const rows = await db.update(threads).set({ metadata_json: sql9`${threads.metadata_json} || ${JSON.stringify(patch)}::jsonb`, updated_at: new Date }).where(and10(eq9(threads.thread_id, id), eq9(threads.user_id, userId), ...authorizationFilters3(context))).returning();
9781
9838
  if (!rows[0])
9782
9839
  throw new ApiError(404, "Thread not found");
9783
9840
  return context.json(thread(rows[0]));
@@ -9785,16 +9842,16 @@ threadRoutes.patch("/threads/:threadId", async (context) => {
9785
9842
  threadRoutes.delete("/threads/:threadId", async (context) => {
9786
9843
  const threadId = context.req.param("threadId");
9787
9844
  await ownedThread2(threadId, context);
9788
- for (const row of await db.select({ run_id: runs.run_id }).from(runs).where(and9(eq9(runs.thread_id, threadId), inArray6(runs.status, ["pending", "running"])))) {
9845
+ for (const row of await db.select({ run_id: runs.run_id }).from(runs).where(and10(eq9(runs.thread_id, threadId), inArray6(runs.status, ["pending", "running"])))) {
9789
9846
  await cancelActiveRun(String(row.run_id));
9790
9847
  }
9791
9848
  await deleteThreadCheckpoints(threadId);
9792
- const rows = await db.delete(threads).where(and9(eq9(threads.thread_id, threadId), eq9(threads.user_id, context.get("user").identity), ...authorizationFilters3(context))).returning({ thread_id: threads.thread_id });
9849
+ const rows = await db.delete(threads).where(and10(eq9(threads.thread_id, threadId), eq9(threads.user_id, context.get("user").identity), ...authorizationFilters3(context))).returning({ thread_id: threads.thread_id });
9793
9850
  if (!rows[0])
9794
9851
  throw new ApiError(404, "Thread not found");
9795
9852
  return context.json({ status: "deleted" });
9796
9853
  });
9797
- threadRoutes.post("/threads/prune", async (context) => context.json(await pruneExpiredThreads(context.get("user").identity)));
9854
+ threadRoutes.post("/threads/prune", async (context) => context.json(await pruneExpiredThreads(context.get("user").identity, getAuthorizationFilter(context))));
9798
9855
  threadRoutes.get("/threads/:threadId/state", async (context) => {
9799
9856
  const id = context.req.param("threadId");
9800
9857
  const graph = await graphForThread(id, context);
@@ -9985,7 +10042,7 @@ init_database();
9985
10042
  init_settings();
9986
10043
  init_database();
9987
10044
  import { hostname } from "os";
9988
- import { and as and10, asc as asc7, eq as eq10, like, lt as lt3, or as or4 } from "drizzle-orm";
10045
+ import { and as and11, asc as asc7, eq as eq10, like, lt as lt3, or as or5 } from "drizzle-orm";
9989
10046
  init_schema();
9990
10047
  var running = false;
9991
10048
  var workerTasks = [];
@@ -10008,7 +10065,7 @@ async function workerLoop(index2) {
10008
10065
  if (!runId)
10009
10066
  continue;
10010
10067
  try {
10011
- const rows = await db.select().from(runs).where(and10(eq10(runs.run_id, runId), eq10(runs.status, "pending"))).limit(1);
10068
+ const rows = await db.select().from(runs).where(and11(eq10(runs.run_id, runId), eq10(runs.status, "pending"))).limit(1);
10012
10069
  if (!rows[0])
10013
10070
  continue;
10014
10071
  const record = runFromRow(rows[0]);
@@ -10032,7 +10089,7 @@ async function reapAbandonedRuns() {
10032
10089
  const now = new Date;
10033
10090
  const stale = new Date(now.getTime() - settings.STUCK_PENDING_THRESHOLD_SECONDS * 1000);
10034
10091
  const recovered = await db.transaction(async (transaction) => {
10035
- const recoverable = await transaction.select().from(runs).where(or4(and10(eq10(runs.status, "running"), lt3(runs.lease_expires_at, now)), and10(eq10(runs.status, "pending"), lt3(runs.updated_at, stale)))).for("update", { skipLocked: true });
10092
+ const recoverable = await transaction.select().from(runs).where(or5(and11(eq10(runs.status, "running"), lt3(runs.lease_expires_at, now)), and11(eq10(runs.status, "pending"), lt3(runs.updated_at, stale)))).for("update", { skipLocked: true });
10036
10093
  const queued = [];
10037
10094
  const exhausted = [];
10038
10095
  for (const row of recoverable) {
@@ -10086,7 +10143,7 @@ async function stopWorkers() {
10086
10143
  reaper = undefined;
10087
10144
  const drained = Promise.allSettled(workerTasks);
10088
10145
  await Promise.race([drained, Bun.sleep(settings.WORKER_DRAIN_TIMEOUT * 1000)]);
10089
- const interrupted = await db.select({ run_id: runs.run_id }).from(runs).where(and10(eq10(runs.status, "running"), like(runs.claimed_by, `${instanceId}-%`)));
10146
+ const interrupted = await db.select({ run_id: runs.run_id }).from(runs).where(and11(eq10(runs.status, "running"), like(runs.claimed_by, `${instanceId}-%`)));
10090
10147
  for (const row of interrupted) {
10091
10148
  await cancelActiveRun(String(row.run_id), "shutdown");
10092
10149
  }
@@ -10238,4 +10295,4 @@ async function shutdown() {
10238
10295
  process.on("SIGINT", () => void shutdown().then(() => process.exit(0)));
10239
10296
  process.on("SIGTERM", () => void shutdown().then(() => process.exit(0)));
10240
10297
 
10241
- //# debugId=16EEE5114E602D2B64756E2164756E21
10298
+ //# debugId=24B435290B76356164756E2164756E21