@agent-team-foundation/first-tree-hub 0.8.3 → 0.8.4

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.
@@ -2,8 +2,8 @@
2
2
  import "../logger-core-2yeIU1fc-B-__AsQO.mjs";
3
3
  import { C as setConfigValue, S as serverConfigSchema, _ as loadAgents, b as resetConfigMeta, c as saveCredentials, f as agentConfigSchema, g as initConfig, h as getConfigValue, i as loadCredentials, l as DEFAULT_CONFIG_DIR, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, r as ensureFreshAdminToken, s as saveAgentConfig, u as DEFAULT_DATA_DIR, v as readConfigFile, y as resetConfig } from "../bootstrap-99vUYmLs.mjs";
4
4
  import "../observability-CJzDFY_G-CmvgUuzc.mjs";
5
- import { A as stopPostgres, C as checkServerReachable, F as SdkError, I as SessionRegistry, L as cleanWorkspaces, M as createOwner, P as FirstTreeHubSDK, R as applyClientLoggerConfig, S as checkServerHealth, T as printResults, _ as checkClientConfig, a as uninstallClientService, b as checkNodeVersion, c as promptAddAgent, d as loadOnboardState, f as onboardCheck, g as checkAgentConfigs, h as runMigrations, j as ClientRuntime, l as promptMissingFields, m as saveOnboardState, n as installClientService, o as startServer, p as onboardCreate, r as isServiceSupported, s as isInteractive, t as getClientServiceStatus, u as formatCheckReport, v as checkDatabase, w as checkWebSocket, x as checkServerConfig, y as checkDocker } from "../core-CxoH-s16.mjs";
6
- import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-BOISS0DK.mjs";
5
+ import { A as stopPostgres, C as checkServerReachable, F as SdkError, I as SessionRegistry, L as cleanWorkspaces, M as createOwner, P as FirstTreeHubSDK, R as applyClientLoggerConfig, S as checkServerHealth, T as printResults, _ as checkClientConfig, a as uninstallClientService, b as checkNodeVersion, c as promptAddAgent, d as loadOnboardState, f as onboardCheck, g as checkAgentConfigs, h as runMigrations, j as ClientRuntime, l as promptMissingFields, m as saveOnboardState, n as installClientService, o as startServer, p as onboardCreate, r as isServiceSupported, s as isInteractive, t as getClientServiceStatus, u as formatCheckReport, v as checkDatabase, w as checkWebSocket, x as checkServerConfig, y as checkDocker } from "../core-VW2Qfs73.mjs";
6
+ import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-OezhDY7x.mjs";
7
7
  import { createRequire } from "node:module";
8
8
  import { Command } from "commander";
9
9
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync } from "node:fs";
@@ -1,7 +1,7 @@
1
1
  import { m as __toESM } from "./esm-CYu4tXXn.mjs";
2
2
  import { C as setConfigValue, S as serverConfigSchema, _ as loadAgents, d as DEFAULT_HOME_DIR$1, f as agentConfigSchema, g as initConfig, i as loadCredentials, l as DEFAULT_CONFIG_DIR, m as collectMissingPrompts, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, s as saveAgentConfig, u as DEFAULT_DATA_DIR$1, x as resolveConfigReadonly } from "./bootstrap-99vUYmLs.mjs";
3
3
  import { _ as withSpan, a as endWsConnectionSpan, b as require_pino, c as messageAttrs, d as rootLogger$1, g as startWsConnectionSpan, i as currentTraceId, n as applyLoggerConfig, o as getFastifyOtelPlugin, p as setWsConnectionAttrs, r as createLogger, t as adapterAttrs, u as observabilityPlugin, v as withWsMessageSpan, y as FIRST_TREE_HUB_ATTR } from "./observability-CJzDFY_G-CmvgUuzc.mjs";
4
- import { $ as updateAgentRuntimeConfigSchema, A as createMemberSchema, B as notificationQuerySchema, C as agentTypeSchema$1, D as createAdapterMappingSchema, E as createAdapterConfigSchema, F as inboxPollQuerySchema, G as sendMessageSchema, H as refreshTokenSchema, I as isRedactedEnvValue, J as sessionEventMessageSchema, K as sendToAgentSchema, L as linkTaskChatSchema, M as createTaskSchema, N as delegateFeishuUserSchema, O as createAgentSchema, P as dryRunAgentRuntimeConfigSchema, Q as updateAdapterConfigSchema, R as loginSchema, S as agentRuntimeConfigPayloadSchema$1, T as connectTokenExchangeSchema, U as runtimeStateMessageSchema, V as paginationQuerySchema, W as selfServiceFeishuBotSchema, X as sessionStateMessageSchema, Y as sessionEventSchema$1, Z as taskListQuerySchema, _ as addParticipantSchema, a as AGENT_SELECTOR_HEADER$1, at as wsAuthFrameSchema, b as agentBindRequestSchema, c as AGENT_TYPES, d as SYSTEM_CONFIG_DEFAULTS, et as updateAgentSchema, f as TASK_CREATOR_TYPES, g as WS_AUTH_FRAME_TIMEOUT_MS, h as TASK_TERMINAL_STATUSES, i as AGENT_BIND_REJECT_REASONS, it as updateTaskStatusSchema, j as createOrganizationSchema, k as createChatSchema, l as AGENT_VISIBILITY, m as TASK_STATUSES, nt as updateOrganizationSchema, o as AGENT_SOURCES, p as TASK_HEALTH_SIGNALS, q as sessionCompletionMessageSchema, rt as updateSystemConfigSchema, s as AGENT_STATUSES, tt as updateMemberSchema, u as DEFAULT_AGENT_RUNTIME_CONFIG_PAYLOAD, v as adminCreateTaskSchema, w as clientRegisterSchema, x as agentPinnedMessageSchema$1, y as adminUpdateTaskSchema, z as messageSourceSchema$1 } from "./feishu-BOISS0DK.mjs";
4
+ import { $ as updateAgentRuntimeConfigSchema, A as createMemberSchema, B as notificationQuerySchema, C as agentTypeSchema$1, D as createAdapterMappingSchema, E as createAdapterConfigSchema, F as inboxPollQuerySchema, G as sendMessageSchema, H as refreshTokenSchema, I as isRedactedEnvValue, J as sessionEventMessageSchema, K as sendToAgentSchema, L as linkTaskChatSchema, M as createTaskSchema, N as delegateFeishuUserSchema, O as createAgentSchema, P as dryRunAgentRuntimeConfigSchema, Q as updateAdapterConfigSchema, R as loginSchema, S as agentRuntimeConfigPayloadSchema$1, T as connectTokenExchangeSchema, U as runtimeStateMessageSchema, V as paginationQuerySchema, W as selfServiceFeishuBotSchema, X as sessionStateMessageSchema, Y as sessionEventSchema$1, Z as taskListQuerySchema, _ as addParticipantSchema, a as AGENT_SELECTOR_HEADER$1, at as wsAuthFrameSchema, b as agentBindRequestSchema, c as AGENT_TYPES, d as SYSTEM_CONFIG_DEFAULTS, et as updateAgentSchema, f as TASK_CREATOR_TYPES, g as WS_AUTH_FRAME_TIMEOUT_MS, h as TASK_TERMINAL_STATUSES, i as AGENT_BIND_REJECT_REASONS, it as updateTaskStatusSchema, j as createOrganizationSchema, k as createChatSchema, l as AGENT_VISIBILITY, m as TASK_STATUSES, nt as updateOrganizationSchema, o as AGENT_SOURCES, p as TASK_HEALTH_SIGNALS, q as sessionCompletionMessageSchema, rt as updateSystemConfigSchema, s as AGENT_STATUSES, tt as updateMemberSchema, u as DEFAULT_AGENT_RUNTIME_CONFIG_PAYLOAD, v as adminCreateTaskSchema, w as clientRegisterSchema, x as agentPinnedMessageSchema$1, y as adminUpdateTaskSchema, z as messageSourceSchema$1 } from "./feishu-OezhDY7x.mjs";
5
5
  import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
6
6
  import { dirname, isAbsolute, join, resolve } from "node:path";
7
7
  import { ZodError, z } from "zod";
@@ -714,7 +714,13 @@ z.object({
714
714
  organizationId: z.string(),
715
715
  agents: z.record(z.string(), z.array(pulseBucketSchema).length(32))
716
716
  });
717
- const sessionEventKind = z.enum(["tool_call", "error"]);
717
+ const sessionEventKind = z.enum([
718
+ "tool_call",
719
+ "error",
720
+ "assistant_text",
721
+ "thinking",
722
+ "turn_end"
723
+ ]);
718
724
  const toolCallEventPayload = z.object({
719
725
  toolUseId: z.string(),
720
726
  name: z.string(),
@@ -735,20 +741,61 @@ const errorEventPayload = z.object({
735
741
  ]),
736
742
  message: z.string().max(2e3)
737
743
  });
738
- const sessionEventSchema = z.discriminatedUnion("kind", [z.object({
739
- kind: z.literal("tool_call"),
740
- payload: toolCallEventPayload
741
- }), z.object({
742
- kind: z.literal("error"),
743
- payload: errorEventPayload
744
- })]);
744
+ /**
745
+ * A text block emitted by the model within an assistant message. These are
746
+ * transient "in-progress" events used to render the assistant's reply body
747
+ * while a turn is still running. The final turn result is forwarded as a
748
+ * regular chat message (not an event); the frontend hides all assistant_text
749
+ * events for turns that have completed (i.e. once `turn_end` has been emitted).
750
+ */
751
+ const assistantTextEventPayload = z.object({ text: z.string().max(8e3) });
752
+ /**
753
+ * Marker emitted when the model produces a `thinking` content block.
754
+ * We intentionally do NOT persist the thinking content — only a presence
755
+ * signal so the UI can render a lightweight "Thinking…" status indicator.
756
+ */
757
+ const thinkingEventPayload = z.object({});
758
+ /**
759
+ * Turn boundary marker. Emitted once per completed query turn, regardless of
760
+ * success/failure, so the frontend can group events into turns and collapse
761
+ * completed turns to show only the final result message.
762
+ */
763
+ const turnEndEventPayload = z.object({ status: z.enum(["success", "error"]) });
764
+ const sessionEventSchema = z.discriminatedUnion("kind", [
765
+ z.object({
766
+ kind: z.literal("tool_call"),
767
+ payload: toolCallEventPayload
768
+ }),
769
+ z.object({
770
+ kind: z.literal("error"),
771
+ payload: errorEventPayload
772
+ }),
773
+ z.object({
774
+ kind: z.literal("assistant_text"),
775
+ payload: assistantTextEventPayload
776
+ }),
777
+ z.object({
778
+ kind: z.literal("thinking"),
779
+ payload: thinkingEventPayload
780
+ }),
781
+ z.object({
782
+ kind: z.literal("turn_end"),
783
+ payload: turnEndEventPayload
784
+ })
785
+ ]);
745
786
  z.object({
746
787
  id: z.string(),
747
788
  agentId: z.string(),
748
789
  chatId: z.string(),
749
790
  seq: z.number().int().positive(),
750
791
  kind: sessionEventKind,
751
- payload: z.union([toolCallEventPayload, errorEventPayload]),
792
+ payload: z.union([
793
+ toolCallEventPayload,
794
+ errorEventPayload,
795
+ assistantTextEventPayload,
796
+ thinkingEventPayload,
797
+ turnEndEventPayload
798
+ ]),
752
799
  createdAt: z.string()
753
800
  });
754
801
  z.object({
@@ -2272,6 +2319,7 @@ function cleanWorkspaces(workspaceRoot, activeChatIds, ttlMs = DEFAULT_WORKSPACE
2272
2319
  }
2273
2320
  const MAX_RETRIES = 2;
2274
2321
  const TOOL_RESULT_PREVIEW_LIMIT = 400;
2322
+ const ASSISTANT_TEXT_EVENT_LIMIT = 8e3;
2275
2323
  function extractContentBlocks(message) {
2276
2324
  if (!message || typeof message !== "object") return [];
2277
2325
  const inner = message.message;
@@ -2289,6 +2337,15 @@ function isToolResultBlock(block) {
2289
2337
  const b = block;
2290
2338
  return b.type === "tool_result" && typeof b.tool_use_id === "string";
2291
2339
  }
2340
+ function isTextBlock(block) {
2341
+ if (!block || typeof block !== "object") return false;
2342
+ const b = block;
2343
+ return b.type === "text" && typeof b.text === "string";
2344
+ }
2345
+ function isThinkingBlock(block) {
2346
+ if (!block || typeof block !== "object") return false;
2347
+ return block.type === "thinking";
2348
+ }
2292
2349
  function isResultMessage(message) {
2293
2350
  if (!message || typeof message !== "object") return false;
2294
2351
  const m = message;
@@ -2331,31 +2388,39 @@ function createToolCallProcessor(emit) {
2331
2388
  onMessage(message) {
2332
2389
  if (!message || typeof message !== "object") return;
2333
2390
  const type = message.type;
2334
- if (type === "assistant") for (const block of extractContentBlocks(message)) {
2335
- if (!isToolUseBlock(block)) continue;
2336
- pending.set(block.id, {
2337
- toolUseId: block.id,
2338
- name: block.name,
2339
- args: block.input,
2340
- startedAt: Date.now()
2391
+ if (type === "assistant") {
2392
+ for (const block of extractContentBlocks(message)) if (isToolUseBlock(block)) {
2393
+ pending.set(block.id, {
2394
+ toolUseId: block.id,
2395
+ name: block.name,
2396
+ args: block.input,
2397
+ startedAt: Date.now()
2398
+ });
2399
+ emit({
2400
+ kind: "tool_call",
2401
+ payload: {
2402
+ toolUseId: block.id,
2403
+ name: block.name,
2404
+ args: block.input,
2405
+ status: "pending"
2406
+ }
2407
+ });
2408
+ } else if (isTextBlock(block)) {
2409
+ const text = block.text.trim();
2410
+ if (text.length === 0) continue;
2411
+ emit({
2412
+ kind: "assistant_text",
2413
+ payload: { text: text.slice(0, ASSISTANT_TEXT_EVENT_LIMIT) }
2414
+ });
2415
+ } else if (isThinkingBlock(block)) emit({
2416
+ kind: "thinking",
2417
+ payload: {}
2341
2418
  });
2342
- }
2343
- else if (type === "user") {
2419
+ } else if (type === "user") {
2344
2420
  for (const block of extractContentBlocks(message)) if (isToolResultBlock(block)) pairResult(block);
2345
2421
  }
2346
2422
  },
2347
2423
  flush() {
2348
- if (pending.size === 0) return;
2349
- for (const entry of pending.values()) emit({
2350
- kind: "tool_call",
2351
- payload: {
2352
- toolUseId: entry.toolUseId,
2353
- name: entry.name,
2354
- args: entry.args,
2355
- status: "pending",
2356
- durationMs: Date.now() - entry.startedAt
2357
- }
2358
- });
2359
2424
  pending.clear();
2360
2425
  }
2361
2426
  };
@@ -2561,25 +2626,37 @@ const createClaudeCodeHandler = (config) => {
2561
2626
  retryCount = 0;
2562
2627
  if (message.result && sessionCtx.chatId) {
2563
2628
  const resultText = message.result;
2564
- sessionCtx.sdk.sendMessage(sessionCtx.chatId, {
2565
- format: "text",
2566
- content: resultText
2567
- }).then(() => {
2629
+ try {
2630
+ await sessionCtx.sdk.sendMessage(sessionCtx.chatId, {
2631
+ format: "text",
2632
+ content: resultText
2633
+ });
2568
2634
  sessionCtx.log("Result forwarded to chat");
2569
2635
  sessionCtx.reportSessionCompletion();
2570
- }).catch((err) => {
2636
+ sessionCtx.emitEvent({
2637
+ kind: "turn_end",
2638
+ payload: { status: "success" }
2639
+ });
2640
+ } catch (err) {
2571
2641
  const reason = err instanceof Error ? err.message : String(err);
2572
2642
  sessionCtx.log(`Failed to forward result: ${reason}`);
2573
- const message = `Result forward failed: ${reason}\n---\n${resultText.slice(0, 1500)}`.slice(0, 2e3);
2643
+ const forwardErrMessage = `Result forward failed: ${reason}\n---\n${resultText.slice(0, 1500)}`.slice(0, 2e3);
2574
2644
  sessionCtx.emitEvent({
2575
2645
  kind: "error",
2576
2646
  payload: {
2577
2647
  source: "runtime",
2578
- message
2648
+ message: forwardErrMessage
2579
2649
  }
2580
2650
  });
2581
- });
2582
- }
2651
+ sessionCtx.emitEvent({
2652
+ kind: "turn_end",
2653
+ payload: { status: "error" }
2654
+ });
2655
+ }
2656
+ } else sessionCtx.emitEvent({
2657
+ kind: "turn_end",
2658
+ payload: { status: "success" }
2659
+ });
2583
2660
  } else {
2584
2661
  const errors = message.errors ? message.errors.join("; ") : message.subtype;
2585
2662
  const errorLog = `Query result error: ${errors} (subtype=${message.subtype}, turns=${message.num_turns ?? "?"}, duration=${message.duration_ms ?? "?"}ms)`;
@@ -2591,6 +2668,10 @@ const createClaudeCodeHandler = (config) => {
2591
2668
  message: errors
2592
2669
  }
2593
2670
  });
2671
+ sessionCtx.emitEvent({
2672
+ kind: "turn_end",
2673
+ payload: { status: "error" }
2674
+ });
2594
2675
  }
2595
2676
  sessionCtx.setRuntimeState("idle");
2596
2677
  }
@@ -4521,7 +4602,7 @@ async function onboardCreate(args) {
4521
4602
  }
4522
4603
  const runtimeAgent = args.type === "human" ? args.assistant : args.id;
4523
4604
  if (args.feishuBotAppId && args.feishuBotAppSecret) {
4524
- const { bindFeishuBot } = await import("./feishu-BOISS0DK.mjs").then((n) => n.r);
4605
+ const { bindFeishuBot } = await import("./feishu-OezhDY7x.mjs").then((n) => n.r);
4525
4606
  const targetAgentUuid = args.type === "human" ? assistantUuid : primary.uuid;
4526
4607
  if (!targetAgentUuid) process.stderr.write(`Warning: Cannot bind Feishu bot — no runtime agent available for "${args.id}".\n`);
4527
4608
  else {
@@ -4662,7 +4743,7 @@ function setNestedByDot(obj, dotPath, value) {
4662
4743
  if (lastKey !== void 0) current[lastKey] = value;
4663
4744
  }
4664
4745
  //#endregion
4665
- //#region ../server/dist/app-DJEePmWL.mjs
4746
+ //#region ../server/dist/app-BGneEeZO.mjs
4666
4747
  var __defProp = Object.defineProperty;
4667
4748
  var __exportAll = (all, no_symbols) => {
4668
4749
  let target = {};
@@ -7742,13 +7823,20 @@ async function appendEvent(db, agentId, chatId, event) {
7742
7823
  throw new Error(`session_events seq contention on ${agentId}/${chatId}`);
7743
7824
  }
7744
7825
  /**
7745
- * List events for a session in `seq asc` order with cursor pagination.
7746
- * `cursor` is the last seen `seq`; pass it as-is on the next page.
7826
+ * List events for a session with cursor pagination.
7827
+ *
7828
+ * - `direction: "asc"` (default) walks oldest → newest; cursor is the last
7829
+ * seq seen on the previous page (next page starts at seq > cursor).
7830
+ * - `direction: "desc"` walks newest → oldest; cursor is the last seq seen
7831
+ * on the previous page (next page starts at seq < cursor). The chat UI
7832
+ * uses desc so its turn-grouping filter always sees the most recent
7833
+ * `turn_end` even when the chat has thousands of events.
7747
7834
  */
7748
7835
  async function listEvents(db, agentId, chatId, options) {
7749
7836
  const limit = Math.min(Math.max(options?.limit ?? DEFAULT_LIMIT, 1), MAX_LIMIT);
7837
+ const direction = options?.direction ?? "asc";
7750
7838
  const conditions = [eq(sessionEvents.agentId, agentId), eq(sessionEvents.chatId, chatId)];
7751
- if (options?.cursor !== void 0) conditions.push(gt(sessionEvents.seq, options.cursor));
7839
+ if (options?.cursor !== void 0) conditions.push(direction === "desc" ? lt(sessionEvents.seq, options.cursor) : gt(sessionEvents.seq, options.cursor));
7752
7840
  const rows = await db.select({
7753
7841
  id: sessionEvents.id,
7754
7842
  agentId: sessionEvents.agentId,
@@ -7757,7 +7845,7 @@ async function listEvents(db, agentId, chatId, options) {
7757
7845
  kind: sessionEvents.kind,
7758
7846
  payload: sessionEvents.payload,
7759
7847
  createdAt: sessionEvents.createdAt
7760
- }).from(sessionEvents).where(and(...conditions)).orderBy(asc(sessionEvents.seq)).limit(limit + 1);
7848
+ }).from(sessionEvents).where(and(...conditions)).orderBy(direction === "desc" ? desc(sessionEvents.seq) : asc(sessionEvents.seq)).limit(limit + 1);
7761
7849
  const hasMore = rows.length > limit;
7762
7850
  const items = (hasMore ? rows.slice(0, limit) : rows).map(rowToEvent);
7763
7851
  const last = items[items.length - 1];
@@ -7820,16 +7908,23 @@ async function adminSessionRoutes(app) {
7820
7908
  await assertChatAccess(app.db, scope, request.params.chatId);
7821
7909
  return getSession(app.db, request.params.agentId, request.params.chatId);
7822
7910
  });
7823
- /** GET /admin/sessions/agents/:agentId/:chatId/events — session event stream, paged by `seq` */
7911
+ /**
7912
+ * GET /admin/sessions/agents/:agentId/:chatId/events — session event stream,
7913
+ * paged by `seq`. `direction=desc` returns newest-first; the chat UI uses
7914
+ * this so its turn-grouping filter always sees the latest `turn_end`
7915
+ * regardless of total event count.
7916
+ */
7824
7917
  app.get("/agents/:agentId/:chatId/events", async (request) => {
7825
7918
  const scope = memberScope(request);
7826
7919
  await assertAgentVisible(app.db, scope, request.params.agentId);
7827
7920
  await assertChatAccess(app.db, scope, request.params.chatId);
7828
7921
  const limit = request.query.limit !== void 0 ? Number.parseInt(request.query.limit, 10) : void 0;
7829
7922
  const cursor = request.query.cursor !== void 0 ? Number.parseInt(request.query.cursor, 10) : void 0;
7923
+ const direction = request.query.direction === "desc" ? "desc" : "asc";
7830
7924
  return listEvents(app.db, request.params.agentId, request.params.chatId, {
7831
7925
  limit: Number.isFinite(limit) ? limit : void 0,
7832
- cursor: Number.isFinite(cursor) ? cursor : void 0
7926
+ cursor: Number.isFinite(cursor) ? cursor : void 0,
7927
+ direction
7833
7928
  });
7834
7929
  });
7835
7930
  /** POST /admin/sessions/agents/:agentId/:chatId/suspend — suspend a session */
@@ -601,7 +601,13 @@ z.object({
601
601
  organizationId: z.string(),
602
602
  agents: z.record(z.string(), z.array(pulseBucketSchema).length(32))
603
603
  });
604
- const sessionEventKind = z.enum(["tool_call", "error"]);
604
+ const sessionEventKind = z.enum([
605
+ "tool_call",
606
+ "error",
607
+ "assistant_text",
608
+ "thinking",
609
+ "turn_end"
610
+ ]);
605
611
  const toolCallEventPayload = z.object({
606
612
  toolUseId: z.string(),
607
613
  name: z.string(),
@@ -622,20 +628,61 @@ const errorEventPayload = z.object({
622
628
  ]),
623
629
  message: z.string().max(2e3)
624
630
  });
625
- const sessionEventSchema = z.discriminatedUnion("kind", [z.object({
626
- kind: z.literal("tool_call"),
627
- payload: toolCallEventPayload
628
- }), z.object({
629
- kind: z.literal("error"),
630
- payload: errorEventPayload
631
- })]);
631
+ /**
632
+ * A text block emitted by the model within an assistant message. These are
633
+ * transient "in-progress" events used to render the assistant's reply body
634
+ * while a turn is still running. The final turn result is forwarded as a
635
+ * regular chat message (not an event); the frontend hides all assistant_text
636
+ * events for turns that have completed (i.e. once `turn_end` has been emitted).
637
+ */
638
+ const assistantTextEventPayload = z.object({ text: z.string().max(8e3) });
639
+ /**
640
+ * Marker emitted when the model produces a `thinking` content block.
641
+ * We intentionally do NOT persist the thinking content — only a presence
642
+ * signal so the UI can render a lightweight "Thinking…" status indicator.
643
+ */
644
+ const thinkingEventPayload = z.object({});
645
+ /**
646
+ * Turn boundary marker. Emitted once per completed query turn, regardless of
647
+ * success/failure, so the frontend can group events into turns and collapse
648
+ * completed turns to show only the final result message.
649
+ */
650
+ const turnEndEventPayload = z.object({ status: z.enum(["success", "error"]) });
651
+ const sessionEventSchema = z.discriminatedUnion("kind", [
652
+ z.object({
653
+ kind: z.literal("tool_call"),
654
+ payload: toolCallEventPayload
655
+ }),
656
+ z.object({
657
+ kind: z.literal("error"),
658
+ payload: errorEventPayload
659
+ }),
660
+ z.object({
661
+ kind: z.literal("assistant_text"),
662
+ payload: assistantTextEventPayload
663
+ }),
664
+ z.object({
665
+ kind: z.literal("thinking"),
666
+ payload: thinkingEventPayload
667
+ }),
668
+ z.object({
669
+ kind: z.literal("turn_end"),
670
+ payload: turnEndEventPayload
671
+ })
672
+ ]);
632
673
  z.object({
633
674
  id: z.string(),
634
675
  agentId: z.string(),
635
676
  chatId: z.string(),
636
677
  seq: z.number().int().positive(),
637
678
  kind: sessionEventKind,
638
- payload: z.union([toolCallEventPayload, errorEventPayload]),
679
+ payload: z.union([
680
+ toolCallEventPayload,
681
+ errorEventPayload,
682
+ assistantTextEventPayload,
683
+ thinkingEventPayload,
684
+ turnEndEventPayload
685
+ ]),
639
686
  createdAt: z.string()
640
687
  });
641
688
  /** WS message: client reports a session event (tool_call / error) to the server. */
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./logger-core-2yeIU1fc-B-__AsQO.mjs";
2
2
  import { a as resolveAccessToken, n as ensureFreshAccessToken, o as resolveServerUrl, r as ensureFreshAdminToken } from "./bootstrap-99vUYmLs.mjs";
3
3
  import "./observability-CJzDFY_G-CmvgUuzc.mjs";
4
- import { A as stopPostgres, C as checkServerReachable, D as status, E as blank, F as SdkError, M as createOwner, N as hasUser, O as ensurePostgres, P as FirstTreeHubSDK, S as checkServerHealth, T as printResults, _ as checkClientConfig, a as uninstallClientService, b as checkNodeVersion, c as promptAddAgent, f as onboardCheck, g as checkAgentConfigs, h as runMigrations, i as resolveCliInvocation, j as ClientRuntime, k as isDockerAvailable, l as promptMissingFields, n as installClientService, o as startServer, p as onboardCreate, r as isServiceSupported, s as isInteractive, t as getClientServiceStatus, u as formatCheckReport, v as checkDatabase, w as checkWebSocket, x as checkServerConfig, y as checkDocker } from "./core-CxoH-s16.mjs";
5
- import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-BOISS0DK.mjs";
4
+ import { A as stopPostgres, C as checkServerReachable, D as status, E as blank, F as SdkError, M as createOwner, N as hasUser, O as ensurePostgres, P as FirstTreeHubSDK, S as checkServerHealth, T as printResults, _ as checkClientConfig, a as uninstallClientService, b as checkNodeVersion, c as promptAddAgent, f as onboardCheck, g as checkAgentConfigs, h as runMigrations, i as resolveCliInvocation, j as ClientRuntime, k as isDockerAvailable, l as promptMissingFields, n as installClientService, o as startServer, p as onboardCreate, r as isServiceSupported, s as isInteractive, t as getClientServiceStatus, u as formatCheckReport, v as checkDatabase, w as checkWebSocket, x as checkServerConfig, y as checkDocker } from "./core-VW2Qfs73.mjs";
5
+ import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-OezhDY7x.mjs";
6
6
  export { ClientRuntime, FirstTreeHubSDK, SdkError, bindFeishuBot, bindFeishuUser, blank, checkAgentConfigs, checkClientConfig, checkDatabase, checkDocker, checkNodeVersion, checkServerConfig, checkServerHealth, checkServerReachable, checkWebSocket, createOwner, ensureFreshAccessToken, ensureFreshAdminToken, ensurePostgres, formatCheckReport, getClientServiceStatus, hasUser, installClientService, isDockerAvailable, isInteractive, isServiceSupported, onboardCheck, onboardCreate, printResults, promptAddAgent, promptMissingFields, resolveAccessToken, resolveCliInvocation, resolveServerUrl, runMigrations, startServer, status, stopPostgres, uninstallClientService };
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap";/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-space-x-reverse:0}}}@layer theme{:root,:host{--font-sans:var(--font-sans-stack);--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-900:oklch(42.1% .095 57.708);--color-yellow-950:oklch(28.6% .066 53.813);--color-green-100:oklch(96.2% .044 156.743);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-900:oklch(39.3% .095 152.535);--color-blue-50:oklch(97% .014 254.604);--color-blue-500:oklch(62.3% .214 259.815);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans-stack);--default-mono-font-family:var(--font-mono-stack)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);box-sizing:border-box}html,body,#root{overscroll-behavior:none;height:100%;margin:0;padding:0}body{background-color:var(--bg);color:var(--fg);font-family:var(--font-sans-stack);font-feature-settings:"cv11","ss01","ss03";font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:13px;line-height:1.45}::selection{background:var(--accent-bg);color:var(--fg)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border);border:2px solid var(--bg);border-radius:5px}::-webkit-scrollbar-thumb:hover{background:var(--border-strong)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.-top-0\.5{top:calc(var(--spacing) * -.5)}.top-0{top:calc(var(--spacing) * 0)}.top-4{top:calc(var(--spacing) * 4)}.top-\[50\%\]{top:50%}.top-full{top:100%}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-0{right:calc(var(--spacing) * 0)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:calc(var(--spacing) * 0)}.left-\[50\%\]{left:50%}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.-mx-6{margin-inline:calc(var(--spacing) * -6)}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mr-2{margin-right:calc(var(--spacing) * 2)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-full{height:100%}.h-px{height:1px}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-80{max-height:calc(var(--spacing) * 80)}.max-h-\[300px\]{max-height:300px}.min-h-8{min-height:calc(var(--spacing) * 8)}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.max-w-5xl{max-width:var(--container-5xl)}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-48{min-width:calc(var(--spacing) * 48)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-\[-50\%\]{--tw-translate-y:-50%;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-\[2px\]{gap:2px}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-red-200>:not(:last-child)){border-color:var(--color-red-200)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-amber-300{border-color:var(--color-amber-300)}.border-border{border-color:var(--border)}.border-destructive\/50{border-color:var(--state-error)}@supports (color:color-mix(in lab,red,red)){.border-destructive\/50{border-color:color-mix(in oklab,var(--state-error) 50%,transparent)}}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-input{border-color:var(--border)}.border-primary{border-color:var(--accent)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.border-transparent{border-color:#0000}.border-yellow-200{border-color:var(--color-yellow-200)}.border-l-gray-400{border-left-color:var(--color-gray-400)}.border-l-green-500{border-left-color:var(--color-green-500)}.border-l-red-500{border-left-color:var(--color-red-500)}.border-l-yellow-500{border-left-color:var(--color-yellow-500)}.bg-accent\/20{background-color:var(--bg-hover)}@supports (color:color-mix(in lab,red,red)){.bg-accent\/20{background-color:color-mix(in oklab,var(--bg-hover) 20%,transparent)}}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background{background-color:var(--bg)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black) 50%,transparent)}}.bg-black\/80{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.bg-black\/80{background-color:color-mix(in oklab,var(--color-black) 80%,transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--bg-raised)}.bg-destructive,.bg-destructive\/5{background-color:var(--state-error)}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/5{background-color:color-mix(in oklab,var(--state-error) 5%,transparent)}}.bg-destructive\/10{background-color:var(--state-error)}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/10{background-color:color-mix(in oklab,var(--state-error) 10%,transparent)}}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-300{background-color:var(--color-gray-300)}.bg-gray-400{background-color:var(--color-gray-400)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-500{background-color:var(--color-green-500)}.bg-muted,.bg-muted\/30{background-color:var(--bg-sunken)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/30{background-color:color-mix(in oklab,var(--bg-sunken) 30%,transparent)}}.bg-muted\/40{background-color:var(--bg-sunken)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/40{background-color:color-mix(in oklab,var(--bg-sunken) 40%,transparent)}}.bg-popover{background-color:var(--bg-raised)}.bg-primary,.bg-primary\/5{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.bg-primary\/5{background-color:color-mix(in oklab,var(--accent) 5%,transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-red-50\/40{background-color:#fef2f266}@supports (color:color-mix(in lab,red,red)){.bg-red-50\/40{background-color:color-mix(in oklab,var(--color-red-50) 40%,transparent)}}.bg-red-100{background-color:var(--color-red-100)}.bg-red-500{background-color:var(--color-red-500)}.bg-secondary{background-color:var(--bg-hover)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-yellow-50{background-color:var(--color-yellow-50)}.bg-yellow-50\/95{background-color:#fefce8f2}@supports (color:color-mix(in lab,red,red)){.bg-yellow-50\/95{background-color:color-mix(in oklab,var(--color-yellow-50) 95%,transparent)}}.bg-yellow-500{background-color:var(--color-yellow-500)}.p-0{padding:calc(var(--spacing) * 0)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-0{padding-top:calc(var(--spacing) * 0)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-24{padding-bottom:calc(var(--spacing) * 24)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono-stack)}.font-sans{font-family:var(--font-sans-stack)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-700{color:var(--color-amber-700)}.text-amber-800\/80{color:#953d00cc}@supports (color:color-mix(in lab,red,red)){.text-amber-800\/80{color:color-mix(in oklab,var(--color-amber-800) 80%,transparent)}}.text-amber-900{color:var(--color-amber-900)}.text-card-foreground{color:var(--fg)}.text-destructive{color:var(--state-error)}.text-foreground{color:var(--fg)}.text-gray-400{color:var(--color-gray-400)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-500{color:var(--color-green-500)}.text-green-600{color:var(--color-green-600)}.text-green-900{color:var(--color-green-900)}.text-muted-foreground{color:var(--fg-3)}.text-popover-foreground{color:var(--fg)}.text-primary{color:var(--accent)}.text-primary-foreground{color:#070a07}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-red-800\/80{color:#9f0712cc}@supports (color:color-mix(in lab,red,red)){.text-red-800\/80{color:color-mix(in oklab,var(--color-red-800) 80%,transparent)}}.text-red-900{color:var(--color-red-900)}.text-secondary-foreground{color:var(--fg)}.text-white{color:var(--color-white)}.text-yellow-500{color:var(--color-yellow-500)}.text-yellow-900{color:var(--color-yellow-900)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.decoration-red-300{-webkit-text-decoration-color:var(--color-red-300);text-decoration-color:var(--color-red-300)}.underline-offset-4{text-underline-offset:4px}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--bg)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.running{animation-play-state:running}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.placeholder\:text-muted-foreground::placeholder{color:var(--fg-3)}@media(hover:hover){.hover\:bg-\[var\(--bg-hover\)\]:hover,.hover\:bg-accent:hover,.hover\:bg-accent\/30:hover{background-color:var(--bg-hover)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/30:hover{background-color:color-mix(in oklab,var(--bg-hover) 30%,transparent)}}.hover\:bg-accent\/50:hover{background-color:var(--bg-hover)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/50:hover{background-color:color-mix(in oklab,var(--bg-hover) 50%,transparent)}}.hover\:bg-amber-100:hover{background-color:var(--color-amber-100)}.hover\:bg-destructive\/90:hover{background-color:var(--state-error)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--state-error) 90%,transparent)}}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-muted\/50:hover{background-color:var(--bg-sunken)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,var(--bg-sunken) 50%,transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--accent) 90%,transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--bg-hover)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--bg-hover) 80%,transparent)}}.hover\:text-\[var\(--fg\)\]:hover,.hover\:text-accent-foreground:hover,.hover\:text-foreground:hover{color:var(--fg)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--accent-ring)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--accent-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.aria-selected\:bg-accent[aria-selected=true]{background-color:var(--bg-hover)}.aria-selected\:text-accent-foreground[aria-selected=true]{color:var(--fg)}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=closed\]\:animate-out[data-state=closed]{--tw-exit-opacity:initial;--tw-exit-scale:initial;--tw-exit-rotate:initial;--tw-exit-translate-x:initial;--tw-exit-translate-y:initial;animation-name:exit;animation-duration:.15s}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x:-50%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y:-48%}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:var(--bg-hover)}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:var(--fg-3)}.data-\[state\=open\]\:animate-in[data-state=open]{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x:-50%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y:-48%}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--bg-sunken)}@media(min-width:40rem){.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}:where(.sm\:space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 2) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-x-reverse)))}.sm\:text-left{text-align:left}}@media(min-width:48rem){.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-between{justify-content:space-between}}.dark\:border-red-900:is(.dark *){border-color:var(--color-red-900)}.dark\:border-yellow-900:is(.dark *){border-color:var(--color-yellow-900)}.dark\:bg-red-950\/30:is(.dark *){background-color:#4608094d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-950\/30:is(.dark *){background-color:color-mix(in oklab,var(--color-red-950) 30%,transparent)}}.dark\:bg-yellow-950\/30:is(.dark *){background-color:#4320044d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-yellow-950\/30:is(.dark *){background-color:color-mix(in oklab,var(--color-yellow-950) 30%,transparent)}}.dark\:text-red-200:is(.dark *){color:var(--color-red-200)}.dark\:text-yellow-200:is(.dark *){color:var(--color-yellow-200)}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-block:calc(var(--spacing) * 1.5)}.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:var(--fg-3)}.\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:calc(var(--spacing) * 5)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:calc(var(--spacing) * 5)}.\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:calc(var(--spacing) * 12)}.\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-block:calc(var(--spacing) * 3)}.\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:calc(var(--spacing) * 5)}.\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:calc(var(--spacing) * 5)}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:calc(var(--spacing) * 0)}.font-mono,.mono{font-family:var(--font-mono-stack);font-feature-settings:"ss01","ss02"}.tnum{font-variant-numeric:tabular-nums}.kbd{font-family:var(--font-mono-stack);border:1px solid var(--border);background:var(--bg-sunken);color:var(--fg-2);border-bottom-width:2px;border-radius:3px;padding:1px 5px;font-size:10px;line-height:1;display:inline-block}}:root{--font-sans-stack:"Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-mono-stack:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--accent:oklch(72% .17 150);--accent-dim:oklch(62% .14 150);--accent-bg:oklch(72% .17 150/.12);--accent-ring:oklch(72% .17 150/.3);--state-idle:oklch(72% .17 150);--state-working:oklch(78% .16 195);--state-blocked:oklch(82% .18 75);--state-error:oklch(68% .22 25);--state-offline:oklch(50% 0 0);--ok:oklch(72% .17 150);--warn:oklch(82% .18 75);--danger:oklch(68% .22 25);--radius:.5rem;--bg:oklch(98.5% .005 150);--bg-raised:oklch(100% 0 0);--bg-sunken:oklch(96.5% .006 150);--bg-card:oklch(100% 0 0);--bg-hover:oklch(95% .008 150);--bg-active:oklch(92% .01 150);--fg:oklch(18% .01 150);--fg-2:oklch(36% .01 150);--fg-3:oklch(52% .008 150);--fg-4:oklch(68% .005 150);--border:oklch(90% .006 150);--border-strong:oklch(82% .008 150);--border-faint:oklch(94% .005 150);--shadow-md:0 4px 12px oklch(0% 0 0/.08)}.dark{--bg:oklch(14.5% .005 150);--bg-raised:oklch(17.5% .005 150);--bg-sunken:oklch(11.5% .005 150);--bg-card:oklch(17.5% .005 150);--bg-hover:oklch(22% .008 150);--bg-active:oklch(26% .012 150);--fg:oklch(96% .005 150);--fg-2:oklch(78% .006 150);--fg-3:oklch(58% .006 150);--fg-4:oklch(42% .005 150);--border:oklch(26% .008 150);--border-strong:oklch(34% .01 150);--border-faint:oklch(20% .006 150);--shadow-md:0 4px 12px oklch(0% 0 0/.4)}@keyframes heartbeat-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.15;transform:scale(1.6)}}@keyframes ring-pulse{0%{opacity:.6;transform:scale(1)}to{opacity:0;transform:scale(2.6)}}@keyframes dash-spin{to{transform:rotate(360deg)}}@keyframes subtle-fade{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes thinking-bar{0%,to{transform:scaleY(.3)}50%{transform:scaleY(1)}}.fade-in{animation:.18s ease-out subtle-fade}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0) scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1)) rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0) scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1)) rotate(var(--tw-exit-rotate,0))}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}