tesseract-agent 0.4.12 → 0.4.14

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.
@@ -19350,91 +19350,1679 @@ var init_cron_tools = __esm({
19350
19350
  }
19351
19351
  });
19352
19352
 
19353
- // ../../packages/agent-core/dist/design-tokens.js
19354
- function colorVar(name, c) {
19355
- return c.cssVar ?? `--color-${name}`;
19353
+ // ../../packages/shared/dist/ws-protocol.js
19354
+ var MIRRORED_AGENT_EVENTS;
19355
+ var init_ws_protocol = __esm({
19356
+ "../../packages/shared/dist/ws-protocol.js"() {
19357
+ "use strict";
19358
+ MIRRORED_AGENT_EVENTS = /* @__PURE__ */ new Set([
19359
+ "chat:stream",
19360
+ "agent:tool_use",
19361
+ "agent:tool_result",
19362
+ // M4 H10 — co-viewers must see tool OUTPUT, not just the call
19363
+ "agent:file_edit",
19364
+ "chat:complete",
19365
+ "chat:error",
19366
+ "agent:status",
19367
+ "agent:mode_changed",
19368
+ // M4 H11 — co-viewer run-mode badge must flip on plan/edit
19369
+ "agent:session_state",
19370
+ // M4 H11 — co-viewer spinner must clear on idle
19371
+ "agent:todos",
19372
+ // plan sidebar — co-viewers see the live checklist
19373
+ "agent:plan_sections",
19374
+ // plan review — co-viewers see the sectioned plan
19375
+ "agent:narration",
19376
+ // live status strip — co-viewers see "what it's doing now"
19377
+ "agent:preview_ready",
19378
+ // co-viewers (incl. mobile) see the preview the moment it's ready
19379
+ "agent:elicitation_complete",
19380
+ // M5 — co-viewers clear a resolved url-mode card
19381
+ "chat:echoed",
19382
+ "chat:scheduled_fired"
19383
+ // cron — co-viewers see the synthetic "Scheduled" user turn
19384
+ // NOT mirrored: agent:capabilities (host-local model/MCP metadata — mirroring
19385
+ // would stomp a co-viewer's own picker with the driver's host); session:forked
19386
+ // and agent:context_usage are driver-only correlation/host-local replies.
19387
+ ]);
19388
+ }
19389
+ });
19390
+
19391
+ // ../../packages/shared/dist/frame.js
19392
+ var init_frame = __esm({
19393
+ "../../packages/shared/dist/frame.js"() {
19394
+ "use strict";
19395
+ }
19396
+ });
19397
+
19398
+ // ../../packages/shared/dist/plans.js
19399
+ var NO_QUOTAS, NO_FEATURES, PLAN_CATALOG;
19400
+ var init_plans = __esm({
19401
+ "../../packages/shared/dist/plans.js"() {
19402
+ "use strict";
19403
+ NO_QUOTAS = { computeHours: 0, storageGb: 0, egressGb: 0 };
19404
+ NO_FEATURES = {
19405
+ sync: false,
19406
+ mobile: false,
19407
+ cloudWorkspace: false,
19408
+ cloudServer: false,
19409
+ remoteAgents: false,
19410
+ voice: false,
19411
+ team: false,
19412
+ parallelAgents: false,
19413
+ advancedBrowser: false,
19414
+ hosting: false,
19415
+ plugins: false,
19416
+ scheduling: false,
19417
+ api: false,
19418
+ sso: false,
19419
+ seats: 1,
19420
+ maxMachines: 1
19421
+ };
19422
+ PLAN_CATALOG = [
19423
+ {
19424
+ id: "free",
19425
+ name: "Free",
19426
+ monthlyUsd: 0,
19427
+ tagline: "Your machine, your phone, your voice.",
19428
+ features: [
19429
+ "Unlimited agent usage",
19430
+ "Full IDE: editor, files, agent, browser tool",
19431
+ "Voice mode",
19432
+ "Mobile app \u2014 reach your computer from your phone",
19433
+ "Cloud workspace \u2014 your machine and recent projects in one view",
19434
+ "One machine",
19435
+ "Deploy to your own machine or server",
19436
+ "Community support"
19437
+ ],
19438
+ featurePolicy: { ...NO_FEATURES, voice: true, mobile: true, cloudWorkspace: true },
19439
+ quotas: { ...NO_QUOTAS }
19440
+ },
19441
+ {
19442
+ id: "standard",
19443
+ name: "Pro",
19444
+ monthlyUsd: 20,
19445
+ tagline: "Your workspace, everywhere.",
19446
+ features: [
19447
+ "Everything in Free",
19448
+ "Unlimited machines \u2014 run agents on all of them",
19449
+ "Tesseract cloud server \u2014 a managed always-on agent in the cloud",
19450
+ "Deploy to the cloud \u2014 your app on a *.tesseract.dev URL",
19451
+ "Includes ~1 always-on service + 20 GB storage + 100 GB bandwidth (overage metered)",
19452
+ "Sync settings across your devices",
19453
+ "Email support"
19454
+ ],
19455
+ featurePolicy: {
19456
+ ...NO_FEATURES,
19457
+ sync: true,
19458
+ mobile: true,
19459
+ cloudWorkspace: true,
19460
+ cloudServer: true,
19461
+ remoteAgents: true,
19462
+ voice: true,
19463
+ hosting: true,
19464
+ plugins: true,
19465
+ scheduling: true,
19466
+ maxMachines: 0
19467
+ },
19468
+ // ~1 small always-on service (~720 compute-hours/mo, rounded) + 20 GB storage + 100 GB egress.
19469
+ quotas: { computeHours: 750, storageGb: 20, egressGb: 100 }
19470
+ },
19471
+ {
19472
+ id: "pro",
19473
+ name: "Team",
19474
+ monthlyUsd: 40,
19475
+ perSeat: true,
19476
+ tagline: "For teams shipping together.",
19477
+ features: [
19478
+ "Everything in Pro, per seat",
19479
+ "Team seats + shared workspaces",
19480
+ "Parallel agents",
19481
+ "Advanced browser automation",
19482
+ "API access",
19483
+ "SSO, audit logs, centralized billing",
19484
+ "Pooled cloud hosting \u2014 bigger shared quota",
19485
+ "Priority support"
19486
+ ],
19487
+ featurePolicy: {
19488
+ sync: true,
19489
+ mobile: true,
19490
+ cloudWorkspace: true,
19491
+ cloudServer: true,
19492
+ remoteAgents: true,
19493
+ voice: true,
19494
+ team: true,
19495
+ parallelAgents: true,
19496
+ advancedBrowser: true,
19497
+ hosting: true,
19498
+ plugins: true,
19499
+ scheduling: true,
19500
+ api: true,
19501
+ sso: true,
19502
+ seats: 2,
19503
+ maxMachines: 0
19504
+ },
19505
+ // Pooled across the team — ~4× Pro's starter quota.
19506
+ quotas: { computeHours: 3e3, storageGb: 100, egressGb: 500 }
19507
+ }
19508
+ ];
19509
+ }
19510
+ });
19511
+
19512
+ // ../../packages/shared/dist/slug.js
19513
+ var init_slug = __esm({
19514
+ "../../packages/shared/dist/slug.js"() {
19515
+ "use strict";
19516
+ }
19517
+ });
19518
+
19519
+ // ../../packages/shared/dist/hosting.js
19520
+ var init_hosting = __esm({
19521
+ "../../packages/shared/dist/hosting.js"() {
19522
+ "use strict";
19523
+ }
19524
+ });
19525
+
19526
+ // ../../packages/shared/dist/cloud-agent.js
19527
+ var init_cloud_agent = __esm({
19528
+ "../../packages/shared/dist/cloud-agent.js"() {
19529
+ "use strict";
19530
+ }
19531
+ });
19532
+
19533
+ // ../../packages/shared/dist/settings.js
19534
+ var MODEL_OPTIONS;
19535
+ var init_settings = __esm({
19536
+ "../../packages/shared/dist/settings.js"() {
19537
+ "use strict";
19538
+ MODEL_OPTIONS = [
19539
+ { id: "claude-opus-4-8", label: "Claude Opus 4.8" },
19540
+ { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" },
19541
+ { id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" }
19542
+ ];
19543
+ }
19544
+ });
19545
+
19546
+ // ../../packages/shared/dist/engines.js
19547
+ function engineById(id) {
19548
+ return ENGINE_CATALOG[id];
19549
+ }
19550
+ var ENGINE_CATALOG, ENGINE_IDS;
19551
+ var init_engines = __esm({
19552
+ "../../packages/shared/dist/engines.js"() {
19553
+ "use strict";
19554
+ init_settings();
19555
+ ENGINE_CATALOG = {
19556
+ "claude-code": {
19557
+ id: "claude-code",
19558
+ label: "Claude Code",
19559
+ description: "Anthropic's Claude Code \u2014 the default engine, deepest tool + browser integration.",
19560
+ cliBinary: "claude",
19561
+ // Claude's token is injected via CLAUDE_CODE_OAUTH_TOKEN, so oauth needs no auth file.
19562
+ supportedModes: ["oauth", "apiKey", "localCli"],
19563
+ apiKeyEnv: "ANTHROPIC_API_KEY",
19564
+ models: MODEL_OPTIONS,
19565
+ capabilities: { permissionGating: true, browserControl: true, liveRunMode: true, resume: true, fork: true, contextUsage: true, scheduling: true },
19566
+ homepageUrl: "https://docs.claude.com/en/docs/claude-code",
19567
+ installCommand: "npm install -g @anthropic-ai/claude-code",
19568
+ installHint: "Bundled with the app; install the standalone CLI for local-instance mode."
19569
+ },
19570
+ "openai-codex": {
19571
+ id: "openai-codex",
19572
+ label: "OpenAI Codex",
19573
+ description: "OpenAI's Codex CLI. Sign in with ChatGPT or use an API key.",
19574
+ cliBinary: "codex",
19575
+ supportedModes: ["oauth", "apiKey", "localCli"],
19576
+ apiKeyEnv: "OPENAI_API_KEY",
19577
+ authFileRel: "auth.json",
19578
+ // under $CODEX_HOME
19579
+ models: [
19580
+ { id: "gpt-5.5-codex", label: "GPT-5.5 Codex" },
19581
+ { id: "gpt-5.5", label: "GPT-5.5" }
19582
+ ],
19583
+ capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: true },
19584
+ homepageUrl: "https://developers.openai.com/codex/cli",
19585
+ installCommand: "npm install -g @openai/codex",
19586
+ installHint: "npm i -g @openai/codex (or brew install codex)"
19587
+ },
19588
+ opencode: {
19589
+ id: "opencode",
19590
+ label: "OpenCode",
19591
+ description: "Open-source agent over 75+ providers. Log in per provider.",
19592
+ cliBinary: "opencode",
19593
+ supportedModes: ["oauth", "apiKey", "localCli"],
19594
+ // OpenCode reads provider keys from env / its own auth.json; no single apiKeyEnv.
19595
+ authFileRel: "auth.json",
19596
+ // under ~/.local/share/opencode
19597
+ models: [],
19598
+ // provider+model is configured inside OpenCode; "" ⇒ its default
19599
+ capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: true },
19600
+ homepageUrl: "https://opencode.ai",
19601
+ installCommand: "npm install -g opencode-ai",
19602
+ installHint: "npm i -g opencode-ai (see opencode.ai/docs)"
19603
+ },
19604
+ "gemini-cli": {
19605
+ id: "gemini-cli",
19606
+ label: "Gemini CLI",
19607
+ description: "Google's Gemini CLI. Sign in with Google or use a Gemini API key.",
19608
+ cliBinary: "gemini",
19609
+ supportedModes: ["oauth", "apiKey", "localCli"],
19610
+ apiKeyEnv: "GEMINI_API_KEY",
19611
+ models: [
19612
+ { id: "gemini-3.1-pro", label: "Gemini 3.1 Pro" },
19613
+ { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }
19614
+ ],
19615
+ capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: false },
19616
+ homepageUrl: "https://github.com/google-gemini/gemini-cli",
19617
+ installCommand: "npm install -g @google/gemini-cli",
19618
+ installHint: "npm i -g @google/gemini-cli"
19619
+ },
19620
+ openclaw: {
19621
+ id: "openclaw",
19622
+ label: "OpenClaw",
19623
+ description: "OpenClaw runtime \u2014 runs your installed channels, model providers, and plugins natively.",
19624
+ cliBinary: "openclaw",
19625
+ // OpenClaw manages its own provider auth (`openclaw onboard` / openclaw.json), so the
19626
+ // only mode is "use the installed, already-onboarded CLI" — like OpenCode.
19627
+ supportedModes: ["localCli"],
19628
+ models: [],
19629
+ // provider+model is configured inside OpenClaw; '' ⇒ its default
19630
+ capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: false },
19631
+ homepageUrl: "https://docs.openclaw.ai",
19632
+ installCommand: "npm install -g openclaw",
19633
+ installHint: "npm i -g openclaw, then run `openclaw onboard` (see docs.openclaw.ai)"
19634
+ }
19635
+ };
19636
+ ENGINE_IDS = Object.keys(ENGINE_CATALOG);
19637
+ }
19638
+ });
19639
+
19640
+ // ../../packages/shared/dist/providers.js
19641
+ function providerById(id) {
19642
+ return PROVIDER_CATALOG[id];
19356
19643
  }
19357
- function tokensToCss(tokens) {
19358
- const lines = [
19644
+ var PROVIDER_CATALOG, PROVIDER_IDS, NATIVE_PROVIDER_IDS;
19645
+ var init_providers = __esm({
19646
+ "../../packages/shared/dist/providers.js"() {
19647
+ "use strict";
19648
+ PROVIDER_CATALOG = {
19649
+ anthropic: {
19650
+ id: "anthropic",
19651
+ label: "Anthropic",
19652
+ description: "Claude models, direct from Anthropic. The native backend for Claude Code.",
19653
+ baseUrl: "https://api.anthropic.com",
19654
+ api: "anthropic-messages",
19655
+ claudeNative: true,
19656
+ authEnvVars: ["ANTHROPIC_API_KEY"],
19657
+ authModes: ["oauth", "apiKey"],
19658
+ models: [
19659
+ { id: "claude-opus-4-8", label: "Claude Opus 4.8", role: "main" },
19660
+ { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", role: "main" },
19661
+ { id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", role: "fast" }
19662
+ ],
19663
+ homepageUrl: "https://docs.claude.com/en/docs/about-claude/models"
19664
+ },
19665
+ openai: {
19666
+ id: "openai",
19667
+ label: "OpenAI",
19668
+ description: "OpenAI models. The native backend for the Codex engine.",
19669
+ baseUrl: "https://api.openai.com/v1",
19670
+ api: "openai-completions",
19671
+ claudeNative: false,
19672
+ authEnvVars: ["OPENAI_API_KEY"],
19673
+ authModes: ["oauth", "apiKey"],
19674
+ models: [
19675
+ { id: "gpt-5.5-codex", label: "GPT-5.5 Codex", role: "main" },
19676
+ { id: "gpt-5.5", label: "GPT-5.5", role: "main" }
19677
+ ],
19678
+ homepageUrl: "https://platform.openai.com/docs/models"
19679
+ },
19680
+ google: {
19681
+ id: "google",
19682
+ label: "Google Gemini",
19683
+ description: "Gemini models. The native backend for the Gemini engine.",
19684
+ baseUrl: "https://generativelanguage.googleapis.com",
19685
+ api: "gemini",
19686
+ claudeNative: false,
19687
+ authEnvVars: ["GEMINI_API_KEY"],
19688
+ authModes: ["oauth", "apiKey"],
19689
+ models: [
19690
+ { id: "gemini-3.1-pro", label: "Gemini 3.1 Pro", role: "main" },
19691
+ { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash", role: "fast" }
19692
+ ],
19693
+ homepageUrl: "https://ai.google.dev/gemini-api/docs/models"
19694
+ },
19695
+ openrouter: {
19696
+ id: "openrouter",
19697
+ label: "OpenRouter",
19698
+ description: "One key, hundreds of models. Exposes an Anthropic-compatible route \u2014 no proxy needed for Claude Code.",
19699
+ // OpenAI-style base; the Anthropic-compatible base is `…/api` (no `/v1`).
19700
+ baseUrl: "https://openrouter.ai/api/v1",
19701
+ anthropicBaseUrl: "https://openrouter.ai/api",
19702
+ api: "openai-completions",
19703
+ claudeNative: true,
19704
+ authEnvVars: ["OPENROUTER_API_KEY"],
19705
+ headers: {
19706
+ "HTTP-Referer": "https://app.tesseract.dev",
19707
+ "X-Title": "Tesseract"
19708
+ },
19709
+ authModes: ["apiKey"],
19710
+ // Any OpenRouter slug is valid; these are stable starters (free entry in UI).
19711
+ models: [
19712
+ { id: "deepseek/deepseek-chat", label: "DeepSeek Chat", role: "fast" },
19713
+ { id: "deepseek/deepseek-r1", label: "DeepSeek R1", role: "main" },
19714
+ { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash", role: "fast" },
19715
+ { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro", role: "main" }
19716
+ ],
19717
+ homepageUrl: "https://openrouter.ai/docs"
19718
+ },
19719
+ ollama: {
19720
+ id: "ollama",
19721
+ label: "Ollama (local)",
19722
+ description: "Run open models locally. No API key. Models are discovered from your running Ollama.",
19723
+ baseUrl: "http://127.0.0.1:11434",
19724
+ api: "ollama",
19725
+ claudeNative: false,
19726
+ authEnvVars: [],
19727
+ authModes: ["apiKey"],
19728
+ // optional bearer for remote Ollama; usually none
19729
+ models: [],
19730
+ dynamicModels: true,
19731
+ homepageUrl: "https://ollama.com",
19732
+ installCommand: "curl -fsSL https://ollama.com/install.sh | sh"
19733
+ },
19734
+ deepseek: {
19735
+ id: "deepseek",
19736
+ label: "DeepSeek",
19737
+ description: "DeepSeek Chat + Reasoner. Cheap and capable. Reached via the proxy for Claude Code.",
19738
+ baseUrl: "https://api.deepseek.com",
19739
+ api: "openai-completions",
19740
+ claudeNative: false,
19741
+ authEnvVars: ["DEEPSEEK_API_KEY"],
19742
+ authModes: ["apiKey"],
19743
+ models: [
19744
+ { id: "deepseek-chat", label: "DeepSeek Chat", role: "fast" },
19745
+ { id: "deepseek-reasoner", label: "DeepSeek Reasoner", role: "main" }
19746
+ ],
19747
+ homepageUrl: "https://api-docs.deepseek.com"
19748
+ },
19749
+ moonshot: {
19750
+ id: "moonshot",
19751
+ label: "Kimi (Moonshot)",
19752
+ description: "Kimi K2 models. Use the coding endpoint (Anthropic-compatible, no proxy) or the OpenAI endpoint.",
19753
+ // Default to the OpenAI-style endpoint; the per-credential `baseUrl` can switch
19754
+ // to the Anthropic-compatible coding endpoint below.
19755
+ baseUrl: "https://api.moonshot.ai/v1",
19756
+ anthropicBaseUrl: "https://api.kimi.com/coding/",
19757
+ api: "openai-completions",
19758
+ claudeNative: true,
19759
+ authEnvVars: ["MOONSHOT_API_KEY", "KIMI_API_KEY"],
19760
+ authModes: ["apiKey"],
19761
+ models: [
19762
+ { id: "kimi-code", label: "Kimi Code (coding endpoint)", role: "main" },
19763
+ { id: "kimi-k2.5", label: "Kimi K2.5", role: "main" },
19764
+ { id: "kimi-k2-thinking", label: "Kimi K2 Thinking", role: "main" }
19765
+ ],
19766
+ homepageUrl: "https://platform.moonshot.ai/docs"
19767
+ },
19768
+ "custom-openai": {
19769
+ id: "custom-openai",
19770
+ label: "Custom (OpenAI-compatible)",
19771
+ description: "Any OpenAI-compatible endpoint (LM Studio, llama.cpp, vLLM, a private gateway). Set the base URL per key.",
19772
+ baseUrl: "",
19773
+ api: "openai-completions",
19774
+ claudeNative: false,
19775
+ authEnvVars: ["OPENAI_API_KEY"],
19776
+ authModes: ["apiKey"],
19777
+ models: [],
19778
+ homepageUrl: "https://platform.openai.com/docs/api-reference"
19779
+ },
19780
+ litellm: {
19781
+ id: "litellm",
19782
+ label: "LiteLLM Proxy",
19783
+ description: "Your LiteLLM proxy fronting 100+ providers. Point it at the anthropic route for direct Claude Code use.",
19784
+ baseUrl: "",
19785
+ anthropicBaseUrl: "",
19786
+ api: "openai-completions",
19787
+ // Configurable: LiteLLM can expose an Anthropic-shaped route. Treated as
19788
+ // claudeNative so users can point Claude Code straight at it.
19789
+ claudeNative: true,
19790
+ authEnvVars: ["LITELLM_API_KEY"],
19791
+ authModes: ["apiKey"],
19792
+ models: [],
19793
+ homepageUrl: "https://docs.litellm.ai/docs/simple_proxy"
19794
+ }
19795
+ };
19796
+ PROVIDER_IDS = Object.keys(PROVIDER_CATALOG);
19797
+ NATIVE_PROVIDER_IDS = ["anthropic", "openai", "google"];
19798
+ }
19799
+ });
19800
+
19801
+ // ../../packages/shared/dist/runtimes.js
19802
+ var RUNTIME_CATALOG, RUNTIME_IDS;
19803
+ var init_runtimes = __esm({
19804
+ "../../packages/shared/dist/runtimes.js"() {
19805
+ "use strict";
19806
+ init_engines();
19807
+ RUNTIME_CATALOG = [
19808
+ ...ENGINE_IDS.map((id) => ({
19809
+ id,
19810
+ label: ENGINE_CATALOG[id].label,
19811
+ cliBinary: ENGINE_CATALOG[id].cliBinary,
19812
+ installCommand: ENGINE_CATALOG[id].installCommand,
19813
+ kind: "engine"
19814
+ })),
19815
+ { id: "ollama", label: "Ollama", cliBinary: "ollama", installCommand: "curl -fsSL https://ollama.com/install.sh | sh", kind: "tool" },
19816
+ { id: "ccr", label: "Claude Code Router", cliBinary: "ccr", installCommand: "npm install -g @musistudio/claude-code-router", kind: "tool" }
19817
+ ];
19818
+ RUNTIME_IDS = RUNTIME_CATALOG.map((r) => r.id);
19819
+ }
19820
+ });
19821
+
19822
+ // ../../packages/shared/dist/runner-configs.js
19823
+ var init_runner_configs = __esm({
19824
+ "../../packages/shared/dist/runner-configs.js"() {
19825
+ "use strict";
19826
+ init_providers();
19827
+ }
19828
+ });
19829
+
19830
+ // ../../packages/shared/dist/rotation.js
19831
+ function refreshCredentials(creds, now) {
19832
+ return creds.map((c) => {
19833
+ if (c.status === "cooldown" && (c.cooldownUntil == null || c.cooldownUntil <= now)) {
19834
+ return { ...c, status: "active", cooldownUntil: void 0 };
19835
+ }
19836
+ if (c.status === "active" && c.expiresAt != null && c.expiresAt <= now) {
19837
+ return { ...c, status: "expired" };
19838
+ }
19839
+ return c;
19840
+ });
19841
+ }
19842
+ function selectRotatable(items, now, isUsable = () => true) {
19843
+ const usable = refreshCredentials(items, now).filter((c) => c.status === "active" && (c.expiresAt == null || c.expiresAt > now) && isUsable(c));
19844
+ if (usable.length === 0)
19845
+ return void 0;
19846
+ return usable.sort((a, b) => a.priority - b.priority || (a.lastUsedAt ?? 0) - (b.lastUsedAt ?? 0))[0];
19847
+ }
19848
+ function classifyError(raw) {
19849
+ const s = raw.toLowerCase();
19850
+ if (/\b429\b|rate[ _-]?limit|too many requests/.test(s))
19851
+ return "rate_limit";
19852
+ if (/quota|insufficient[_ ]?quota|credit|billing|payment required|\b402\b|usage limit|exceeded your/.test(s))
19853
+ return "quota_exceeded";
19854
+ if (/expired|token (?:has )?expired|refresh|re-?authenticate|session expired/.test(s))
19855
+ return "auth_expired";
19856
+ if (/\b401\b|\b403\b|invalid (?:api )?key|unauthorized|invalid token|authentication/.test(s))
19857
+ return "invalid_key";
19858
+ if (/\beai_again\b|\benotfound\b|getaddrinfo|network is unreachable|\benetunreach\b|\benetdown\b|offline|no address associated|dns/.test(s))
19859
+ return "network_down";
19860
+ if (/\beconnreset\b|\beconnrefused\b|\betimedout\b|\bepipe\b|socket hang ?up|connection (?:closed|reset|error|aborted)|\b50[0234]\b|\b529\b|overloaded|service unavailable|bad gateway|gateway time-?out|temporarily unavailable/.test(s))
19861
+ return "transient";
19862
+ return "unknown";
19863
+ }
19864
+ function recordFailure(creds, id, errorCode, now, opts) {
19865
+ if (errorCode === "unknown" || errorCode === "transient" || errorCode === "network_down") {
19866
+ return { next: creds, advanced: false };
19867
+ }
19868
+ let advanced = false;
19869
+ const next = creds.map((c) => {
19870
+ if (c.id !== id)
19871
+ return c;
19872
+ advanced = true;
19873
+ const consecutiveFailures = (c.consecutiveFailures ?? 0) + 1;
19874
+ if (errorCode === "auth_expired") {
19875
+ return { ...c, status: "expired", lastErrorCode: errorCode, consecutiveFailures };
19876
+ }
19877
+ if (errorCode === "invalid_key") {
19878
+ return { ...c, status: "revoked", lastErrorCode: errorCode, consecutiveFailures };
19879
+ }
19880
+ const backoff = Math.min(COOLDOWN_BASE_MS * 2 ** (consecutiveFailures - 1), COOLDOWN_MAX_MS);
19881
+ const cooldownUntil = opts?.cooldownUntil ?? now + backoff;
19882
+ return { ...c, status: "cooldown", cooldownUntil, lastErrorCode: errorCode, consecutiveFailures };
19883
+ });
19884
+ return { next, advanced };
19885
+ }
19886
+ function recordSuccess(creds, id, now) {
19887
+ return creds.map((c) => c.id === id ? { ...c, status: "active", cooldownUntil: void 0, consecutiveFailures: 0, lastUsedAt: now, lastErrorCode: void 0 } : c);
19888
+ }
19889
+ var COOLDOWN_BASE_MS, COOLDOWN_MAX_MS;
19890
+ var init_rotation = __esm({
19891
+ "../../packages/shared/dist/rotation.js"() {
19892
+ "use strict";
19893
+ COOLDOWN_BASE_MS = 6e4;
19894
+ COOLDOWN_MAX_MS = 36e5;
19895
+ }
19896
+ });
19897
+
19898
+ // ../../packages/shared/dist/design-tokens.js
19899
+ function isObj(v) {
19900
+ return typeof v === "object" && v !== null && !Array.isArray(v);
19901
+ }
19902
+ function isToken(node) {
19903
+ return isObj(node) && "$value" in node;
19904
+ }
19905
+ function tessExt(token) {
19906
+ const ext = token.$extensions?.["com.tesseract"];
19907
+ return isObj(ext) ? ext : void 0;
19908
+ }
19909
+ function walkTokens(tree) {
19910
+ const out = [];
19911
+ const rec = (node, path5) => {
19912
+ if (!isObj(node))
19913
+ return;
19914
+ if (isToken(node)) {
19915
+ out.push({ path: path5, token: node });
19916
+ return;
19917
+ }
19918
+ for (const key2 of Object.keys(node)) {
19919
+ if (key2.startsWith("$"))
19920
+ continue;
19921
+ rec(node[key2], [...path5, key2]);
19922
+ }
19923
+ };
19924
+ rec(tree, []);
19925
+ return out;
19926
+ }
19927
+ function stringifyValue(v) {
19928
+ if (v == null)
19929
+ return "";
19930
+ if (Array.isArray(v))
19931
+ return v.map((x) => isObj(x) ? JSON.stringify(x) : String(x)).join(", ");
19932
+ if (isObj(v))
19933
+ return JSON.stringify(v);
19934
+ return String(v);
19935
+ }
19936
+ function flattenForDisplay(tree) {
19937
+ return walkTokens(tree).map(({ path: path5, token }) => {
19938
+ const dark = tessExt(token)?.modes?.dark;
19939
+ return {
19940
+ path: path5,
19941
+ dotPath: path5.join("."),
19942
+ group: path5.slice(0, -1).join(" \xB7 "),
19943
+ label: path5[path5.length - 1] ?? "",
19944
+ type: token.$type,
19945
+ value: stringifyValue(token.$value),
19946
+ isColor: token.$type === "color",
19947
+ darkValue: dark === void 0 ? void 0 : stringifyValue(dark)
19948
+ };
19949
+ });
19950
+ }
19951
+ function kebab(s) {
19952
+ return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
19953
+ }
19954
+ function tokenCssVarName(path5, token) {
19955
+ const override = token ? tessExt(token)?.cssVar : void 0;
19956
+ if (override)
19957
+ return override.startsWith("--") ? override : `--${override}`;
19958
+ for (const { match, prefix } of VAR_ALIASES) {
19959
+ if (match.length <= path5.length && match.every((seg, i) => path5[i] === seg)) {
19960
+ const rest = path5.slice(match.length).map(kebab).filter(Boolean);
19961
+ return ["--" + prefix, ...rest].join("-");
19962
+ }
19963
+ }
19964
+ return ["--token", ...path5.map(kebab).filter(Boolean)].join("-");
19965
+ }
19966
+ function categoryRank(top) {
19967
+ const i = CATEGORY_ORDER.indexOf(top ?? "");
19968
+ return i === -1 ? CATEGORY_ORDER.length : i;
19969
+ }
19970
+ function shadowToCss(v) {
19971
+ const s = (k, d = "0") => v[k] == null ? d : String(v[k]);
19972
+ const inset = v.inset ? "inset " : "";
19973
+ return `${inset}${s("offsetX")} ${s("offsetY")} ${s("blur")} ${s("spread")} ${s("color", "#000")}`.replace(/\s+/g, " ").trim();
19974
+ }
19975
+ function cssValue(type, v) {
19976
+ if (Array.isArray(v)) {
19977
+ if (type === "fontFamily") {
19978
+ return v.map((f) => typeof f === "string" && /\s/.test(f) && !/^["']/.test(f) ? `"${f}"` : String(f)).join(", ");
19979
+ }
19980
+ return v.map((x) => isObj(x) ? shadowToCss(x) : String(x)).join(", ");
19981
+ }
19982
+ if (isObj(v))
19983
+ return shadowToCss(v);
19984
+ return String(v);
19985
+ }
19986
+ function tokensToCss(input) {
19987
+ const tokens = normalizeTokens(input);
19988
+ const rows = walkTokens(tokens);
19989
+ const ordered = rows.map((r, i) => ({ r, i })).sort((a, b) => categoryRank(a.r.path[0]) - categoryRank(b.r.path[0]) || a.i - b.i).map((x) => x.r);
19990
+ const root = [];
19991
+ const dark = [];
19992
+ for (const { path: path5, token } of ordered) {
19993
+ const name = tokenCssVarName(path5, token);
19994
+ root.push(` ${name}: ${cssValue(token.$type, token.$value)};`);
19995
+ const d = tessExt(token)?.modes?.dark;
19996
+ if (d !== void 0)
19997
+ dark.push(` ${name}: ${cssValue(token.$type, d)};`);
19998
+ }
19999
+ const out = [
19359
20000
  "/* GENERATED from design-system/tokens.json \u2014 do not edit by hand. */",
19360
- ":root {"
20001
+ ":root {",
20002
+ ...root,
20003
+ "}"
19361
20004
  ];
19362
- const push = (k, v) => lines.push(` ${k}: ${v};`);
19363
- for (const [name, c] of Object.entries(tokens.colors ?? {}))
19364
- push(colorVar(name, c), c.value);
19365
- for (const [role, fam] of Object.entries(tokens.typography?.fontFamilies ?? {}))
19366
- push(`--font-${role}`, fam);
19367
- for (const [step, s] of Object.entries(tokens.typography?.scale ?? {}))
19368
- push(`--text-${step}`, s.size);
19369
- for (const [name, w] of Object.entries(tokens.typography?.weights ?? {}))
19370
- push(`--weight-${name}`, String(w));
19371
- for (const [step, v] of Object.entries(tokens.spacing ?? {}))
19372
- push(`--space-${step}`, v);
19373
- for (const [name, v] of Object.entries(tokens.radius ?? {}))
19374
- push(`--radius-${name}`, v);
19375
- for (const [name, v] of Object.entries(tokens.shadow ?? {}))
19376
- push(`--shadow-${name}`, v);
19377
- lines.push("}", "");
19378
- return lines.join("\n");
20005
+ if (dark.length)
20006
+ out.push("", ".dark {", ...dark, "}");
20007
+ out.push("");
20008
+ return out.join("\n");
19379
20009
  }
19380
- function getTokenPath(tokens, dotPath) {
20010
+ function getTokenSegments(tokens, segments) {
19381
20011
  let cur = tokens;
19382
- for (const key2 of dotPath.split(".")) {
19383
- if (cur == null || typeof cur !== "object")
20012
+ for (const key2 of segments) {
20013
+ if (!isObj(cur))
19384
20014
  return void 0;
19385
20015
  cur = cur[key2];
19386
20016
  }
19387
20017
  return cur;
19388
20018
  }
19389
- function setTokenPath(tokens, dotPath, value) {
19390
- const keys = dotPath.split(".").filter(Boolean);
19391
- if (keys.length === 0)
20019
+ function getTokenPath(tokens, dotPath) {
20020
+ return getTokenSegments(tokens, dotPath.split(".").filter(Boolean));
20021
+ }
20022
+ function setTokenSegments(tokens, segments, value) {
20023
+ if (segments.length === 0)
19392
20024
  throw new Error("empty token path");
19393
20025
  const root = { ...tokens };
19394
20026
  let cur = root;
19395
- for (let i = 0; i < keys.length - 1; i++) {
19396
- const k = keys[i];
20027
+ for (let i = 0; i < segments.length - 1; i++) {
20028
+ const k = segments[i];
19397
20029
  const next = cur[k];
19398
- cur[k] = next && typeof next === "object" ? { ...next } : {};
20030
+ cur[k] = isObj(next) ? { ...next } : {};
19399
20031
  cur = cur[k];
19400
20032
  }
19401
- cur[keys[keys.length - 1]] = value;
20033
+ cur[segments[segments.length - 1]] = value;
19402
20034
  return root;
19403
20035
  }
19404
- var DESIGN_DIR, TOKENS_FILE, TOKENS_CSS_FILE, DESIGN_CLAUDE_MD, ColorToken, TypeStep, Component, DesignTokensSchema;
20036
+ function setTokenPath(tokens, dotPath, value) {
20037
+ return setTokenSegments(tokens, dotPath.split(".").filter(Boolean), value);
20038
+ }
20039
+ function makeToken(value, type) {
20040
+ const tok = { $value: value };
20041
+ if (type)
20042
+ tok.$type = type;
20043
+ return tok;
20044
+ }
20045
+ function splitFamily(s) {
20046
+ if (Array.isArray(s))
20047
+ return s;
20048
+ if (typeof s === "string")
20049
+ return s.split(",").map((x) => x.trim()).filter(Boolean);
20050
+ return String(s ?? "");
20051
+ }
20052
+ function isLightDarkPair(n) {
20053
+ if ("$value" in n)
20054
+ return false;
20055
+ const scalar = (v) => typeof v === "string" || typeof v === "number";
20056
+ const keys = Object.keys(n).filter((k) => !k.startsWith("$"));
20057
+ return keys.length > 0 && keys.includes("light") && keys.every((k) => k === "light" || k === "dark") && scalar(n.light) && (n.dark === void 0 || scalar(n.dark));
20058
+ }
20059
+ function isLegacyColorLeaf(v) {
20060
+ return isObj(v) && typeof v.value === "string" && !("$value" in v);
20061
+ }
20062
+ function canonicalizeNode(node, inheritedType) {
20063
+ if (typeof node === "string" || typeof node === "number" || Array.isArray(node)) {
20064
+ return makeToken(node, inheritedType);
20065
+ }
20066
+ if (!isObj(node))
20067
+ return void 0;
20068
+ if (isLightDarkPair(node)) {
20069
+ const modes = {};
20070
+ for (const k of Object.keys(node))
20071
+ if (k !== "light" && !k.startsWith("$"))
20072
+ modes[k] = node[k];
20073
+ const tok = makeToken(node.light, node.$type ?? inheritedType);
20074
+ if (Object.keys(modes).length)
20075
+ tok.$extensions = { "com.tesseract": { modes } };
20076
+ return tok;
20077
+ }
20078
+ if ("$value" in node) {
20079
+ const tok = { $value: node.$value };
20080
+ const t = node.$type ?? inheritedType;
20081
+ if (t)
20082
+ tok.$type = t;
20083
+ if (typeof node.$description === "string")
20084
+ tok.$description = node.$description;
20085
+ if (isObj(node.$extensions))
20086
+ tok.$extensions = node.$extensions;
20087
+ return tok;
20088
+ }
20089
+ if (inheritedType === "color" && isLegacyColorLeaf(node)) {
20090
+ const tok = makeToken(node.value, "color");
20091
+ if (node.role)
20092
+ tok.$description = node.role;
20093
+ if (node.cssVar)
20094
+ tok.$extensions = { "com.tesseract": { cssVar: node.cssVar } };
20095
+ return tok;
20096
+ }
20097
+ return canonicalizeGroup(node, inheritedType);
20098
+ }
20099
+ function canonicalizeGroup(node, inheritedType) {
20100
+ const groupType = node.$type ?? inheritedType;
20101
+ const g = {};
20102
+ if (typeof node.$type === "string")
20103
+ g.$type = node.$type;
20104
+ if (typeof node.$description === "string")
20105
+ g.$description = node.$description;
20106
+ if (isObj(node.$extensions))
20107
+ g.$extensions = node.$extensions;
20108
+ for (const key2 of Object.keys(node)) {
20109
+ if (key2.startsWith("$"))
20110
+ continue;
20111
+ const child = canonicalizeNode(node[key2], groupType);
20112
+ if (child !== void 0)
20113
+ g[key2] = child;
20114
+ }
20115
+ return g;
20116
+ }
20117
+ function normalizeColorGroup(src) {
20118
+ const g = { $type: "color" };
20119
+ if (typeof src.$description === "string")
20120
+ g.$description = src.$description;
20121
+ for (const key2 of Object.keys(src)) {
20122
+ if (key2.startsWith("$"))
20123
+ continue;
20124
+ const v = src[key2];
20125
+ if (isLegacyColorLeaf(v)) {
20126
+ const tok = makeToken(v.value, "color");
20127
+ if (v.role)
20128
+ tok.$description = v.role;
20129
+ if (v.cssVar)
20130
+ tok.$extensions = { "com.tesseract": { cssVar: v.cssVar } };
20131
+ g[key2] = tok;
20132
+ } else {
20133
+ const child = canonicalizeNode(v, "color");
20134
+ if (child !== void 0)
20135
+ g[key2] = child;
20136
+ }
20137
+ }
20138
+ return g;
20139
+ }
20140
+ function hasTokens(g) {
20141
+ return Object.keys(g).some((k) => !k.startsWith("$"));
20142
+ }
20143
+ function normalizeTypography(src) {
20144
+ const g = {};
20145
+ if (typeof src.$description === "string")
20146
+ g.$description = src.$description;
20147
+ if (isObj(src.fontFamilies)) {
20148
+ const ff = { $type: "fontFamily" };
20149
+ for (const [k, val] of Object.entries(src.fontFamilies))
20150
+ ff[k] = makeToken(splitFamily(val), "fontFamily");
20151
+ g.fontFamily = ff;
20152
+ }
20153
+ if (isObj(src.scale)) {
20154
+ const sizes = { $type: "dimension" };
20155
+ const leading = { $type: "lineHeight" };
20156
+ const weights = { $type: "fontWeight" };
20157
+ for (const [k, step] of Object.entries(src.scale)) {
20158
+ if (!isObj(step))
20159
+ continue;
20160
+ if (step.size != null)
20161
+ sizes[k] = makeToken(step.size, "dimension");
20162
+ if (step.lineHeight != null)
20163
+ leading[k] = makeToken(step.lineHeight, "lineHeight");
20164
+ if (step.weight != null)
20165
+ weights[k] = makeToken(step.weight, "fontWeight");
20166
+ }
20167
+ g.fontSize = sizes;
20168
+ if (hasTokens(leading))
20169
+ g.lineHeight = leading;
20170
+ if (hasTokens(weights))
20171
+ g.fontWeight = weights;
20172
+ }
20173
+ if (isObj(src.weights)) {
20174
+ const w = isObj(g.fontWeight) ? g.fontWeight : { $type: "fontWeight" };
20175
+ for (const [k, val] of Object.entries(src.weights))
20176
+ w[k] = makeToken(val, "fontWeight");
20177
+ g.fontWeight = w;
20178
+ }
20179
+ const TYPE_HINT = {
20180
+ fontFamily: "fontFamily",
20181
+ fontSize: "dimension",
20182
+ fontWeight: "fontWeight",
20183
+ lineHeight: "lineHeight",
20184
+ letterSpacing: "letterSpacing"
20185
+ };
20186
+ for (const key2 of Object.keys(src)) {
20187
+ if (key2.startsWith("$"))
20188
+ continue;
20189
+ if (key2 === "fontFamilies" || key2 === "scale" || key2 === "weights")
20190
+ continue;
20191
+ if (g[key2] !== void 0)
20192
+ continue;
20193
+ if (isObj(src[key2]))
20194
+ g[key2] = canonicalizeGroup(src[key2], TYPE_HINT[key2]);
20195
+ }
20196
+ return g;
20197
+ }
20198
+ function normalizeDimensionGroup(src, dtype) {
20199
+ const g = { $type: src.$type ?? dtype };
20200
+ if (typeof src.$description === "string")
20201
+ g.$description = src.$description;
20202
+ for (const key2 of Object.keys(src)) {
20203
+ if (key2.startsWith("$"))
20204
+ continue;
20205
+ const child = canonicalizeNode(src[key2], g.$type);
20206
+ if (child !== void 0)
20207
+ g[key2] = child;
20208
+ }
20209
+ return g;
20210
+ }
20211
+ function normalizeTokens(raw) {
20212
+ if (!isObj(raw))
20213
+ return {};
20214
+ const out = {};
20215
+ out.$schema = typeof raw.$schema === "string" ? raw.$schema : DTCG_SCHEMA_URL;
20216
+ const meta4 = isObj(raw.$meta) ? raw.$meta : isObj(raw.meta) ? raw.meta : void 0;
20217
+ if (meta4)
20218
+ out.$meta = { ...meta4 };
20219
+ const comps = isObj(raw.$components) ? raw.$components : isObj(raw.components) ? raw.components : void 0;
20220
+ if (comps)
20221
+ out.$components = comps;
20222
+ const colorSrc = isObj(raw.color) ? raw.color : isObj(raw.colors) ? raw.colors : void 0;
20223
+ if (colorSrc)
20224
+ out.color = normalizeColorGroup(colorSrc);
20225
+ if (isObj(raw.typography))
20226
+ out.typography = normalizeTypography(raw.typography);
20227
+ if (isObj(raw.spacing))
20228
+ out.spacing = normalizeDimensionGroup(raw.spacing, "dimension");
20229
+ if (isObj(raw.radius))
20230
+ out.radius = normalizeDimensionGroup(raw.radius, "dimension");
20231
+ if (isObj(raw.shadow))
20232
+ out.shadow = normalizeDimensionGroup(raw.shadow, "shadow");
20233
+ for (const key2 of Object.keys(raw)) {
20234
+ if (key2.startsWith("$") || KNOWN_TOP.has(key2))
20235
+ continue;
20236
+ if (isObj(raw[key2]))
20237
+ out[key2] = canonicalizeGroup(raw[key2], void 0);
20238
+ }
20239
+ return out;
20240
+ }
20241
+ function applyDesignPack(current, packTokens, info, opts) {
20242
+ const cur = normalizeTokens(current);
20243
+ const pack = normalizeTokens(packTokens);
20244
+ const { mode } = opts;
20245
+ const writeLeaves = (base, keep) => {
20246
+ let acc = base;
20247
+ for (const { path: path5, token } of walkTokens(pack)) {
20248
+ if (keep && !keep(path5))
20249
+ continue;
20250
+ acc = setTokenSegments(acc, path5, token);
20251
+ }
20252
+ return acc;
20253
+ };
20254
+ let out;
20255
+ if (mode === "replace") {
20256
+ out = { $schema: pack.$schema ?? cur.$schema ?? DTCG_SCHEMA_URL };
20257
+ if (cur.$meta)
20258
+ out.$meta = cur.$meta;
20259
+ if (cur.$components)
20260
+ out.$components = cur.$components;
20261
+ for (const k of Object.keys(pack))
20262
+ if (!k.startsWith("$"))
20263
+ out[k] = pack[k];
20264
+ } else if (mode === "palette") {
20265
+ out = writeLeaves(cur, (p) => p[0] === "color" || p[0] === "typography" && p[1] === "fontFamily");
20266
+ } else {
20267
+ out = writeLeaves(cur);
20268
+ }
20269
+ const prevMeta = isObj(out.$meta) ? out.$meta : {};
20270
+ return { ...out, $meta: { ...prevMeta, theme: { id: info.id, name: info.name, appliedMode: mode } } };
20271
+ }
20272
+ function parseColorToRgb(v) {
20273
+ const s = v.trim();
20274
+ const hex3 = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(s);
20275
+ if (hex3)
20276
+ return [parseInt(hex3[1] + hex3[1], 16), parseInt(hex3[2] + hex3[2], 16), parseInt(hex3[3] + hex3[3], 16)];
20277
+ const hex68 = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})(?:[0-9a-f]{2})?$/i.exec(s);
20278
+ if (hex68)
20279
+ return [parseInt(hex68[1], 16), parseInt(hex68[2], 16), parseInt(hex68[3], 16)];
20280
+ const hsl = /^(-?\d+(?:\.\d+)?)\s*[, ]\s*(-?\d+(?:\.\d+)?)%\s*[, ]\s*(-?\d+(?:\.\d+)?)%$/.exec(s);
20281
+ if (hsl)
20282
+ return hslToRgb(parseFloat(hsl[1]), parseFloat(hsl[2]), parseFloat(hsl[3]));
20283
+ return null;
20284
+ }
20285
+ function hslToRgb(h, s, l) {
20286
+ h = (h % 360 + 360) % 360;
20287
+ s /= 100;
20288
+ l /= 100;
20289
+ const c = (1 - Math.abs(2 * l - 1)) * s;
20290
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
20291
+ const m = l - c / 2;
20292
+ let r = 0, g = 0, b = 0;
20293
+ if (h < 60)
20294
+ [r, g, b] = [c, x, 0];
20295
+ else if (h < 120)
20296
+ [r, g, b] = [x, c, 0];
20297
+ else if (h < 180)
20298
+ [r, g, b] = [0, c, x];
20299
+ else if (h < 240)
20300
+ [r, g, b] = [0, x, c];
20301
+ else if (h < 300)
20302
+ [r, g, b] = [x, 0, c];
20303
+ else
20304
+ [r, g, b] = [c, 0, x];
20305
+ return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)];
20306
+ }
20307
+ function relLuminance([r, g, b]) {
20308
+ const lin = (c) => {
20309
+ const cs = c / 255;
20310
+ return cs <= 0.03928 ? cs / 12.92 : Math.pow((cs + 0.055) / 1.055, 2.4);
20311
+ };
20312
+ return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
20313
+ }
20314
+ function contrastRatio(a, b) {
20315
+ const ca = parseColorToRgb(a), cb = parseColorToRgb(b);
20316
+ if (!ca || !cb)
20317
+ return 0;
20318
+ const la = relLuminance(ca), lb = relLuminance(cb);
20319
+ const hi = Math.max(la, lb), lo = Math.min(la, lb);
20320
+ return (hi + 0.05) / (lo + 0.05);
20321
+ }
20322
+ function setNested(obj, segs, value) {
20323
+ let cur = obj;
20324
+ for (let i = 0; i < segs.length - 1; i++) {
20325
+ const k = segs[i];
20326
+ if (!isObj(cur[k]))
20327
+ cur[k] = {};
20328
+ cur = cur[k];
20329
+ }
20330
+ cur[segs[segs.length - 1]] = value;
20331
+ }
20332
+ function tokensToTailwindTheme(input) {
20333
+ const tokens = normalizeTokens(input);
20334
+ const extend2 = {};
20335
+ for (const { path: path5, token } of walkTokens(tokens)) {
20336
+ const bucket = TW_BUCKETS.find((b) => b.match.length <= path5.length && b.match.every((seg, i) => path5[i] === seg));
20337
+ if (!bucket)
20338
+ continue;
20339
+ const rest = path5.slice(bucket.match.length).map(kebab).filter(Boolean);
20340
+ if (rest.length === 0)
20341
+ continue;
20342
+ const ref = `var(${tokenCssVarName(path5, token)})`;
20343
+ if (!extend2[bucket.key])
20344
+ extend2[bucket.key] = {};
20345
+ if (bucket.flat)
20346
+ extend2[bucket.key][rest.join("-")] = ref;
20347
+ else
20348
+ setNested(extend2[bucket.key], rest, ref);
20349
+ }
20350
+ return { extend: extend2 };
20351
+ }
20352
+ function tokensToTailwindConfig(input) {
20353
+ const theme = tokensToTailwindTheme(input);
20354
+ return [
20355
+ "// GENERATED from design-system/tokens.json \u2014 do not edit by hand.",
20356
+ "// Spread `theme.extend` into your tailwind.config; values reference the vars in tokens.css.",
20357
+ `export const theme = ${JSON.stringify(theme, null, 2)};`,
20358
+ "export default theme;",
20359
+ ""
20360
+ ].join("\n");
20361
+ }
20362
+ function leafSignature(token) {
20363
+ const modes = tessExt(token)?.modes;
20364
+ if (!modes || typeof modes !== "object")
20365
+ return JSON.stringify([token.$value]);
20366
+ const sorted = {};
20367
+ for (const k of Object.keys(modes).sort())
20368
+ sorted[k] = modes[k];
20369
+ return JSON.stringify([token.$value, sorted]);
20370
+ }
20371
+ function indexLeaves(t) {
20372
+ const m = /* @__PURE__ */ new Map();
20373
+ for (const { path: path5, token } of walkTokens(t)) {
20374
+ m.set(path5.join("."), { sig: leafSignature(token), disp: stringifyValue(token.$value) });
20375
+ }
20376
+ return m;
20377
+ }
20378
+ function diffTokens(prev, next) {
20379
+ const a = indexLeaves(normalizeTokens(prev));
20380
+ const b = indexLeaves(normalizeTokens(next));
20381
+ const added = [];
20382
+ const removed = [];
20383
+ const changed = [];
20384
+ for (const k of b.keys())
20385
+ if (!a.has(k))
20386
+ added.push(k);
20387
+ for (const [k, va] of a) {
20388
+ const vb = b.get(k);
20389
+ if (!vb) {
20390
+ removed.push(k);
20391
+ continue;
20392
+ }
20393
+ if (va.sig !== vb.sig)
20394
+ changed.push({ path: k, from: va.disp, to: vb.disp });
20395
+ }
20396
+ added.sort();
20397
+ removed.sort();
20398
+ changed.sort((x, y) => x.path < y.path ? -1 : x.path > y.path ? 1 : 0);
20399
+ return { added, removed, changed };
20400
+ }
20401
+ function bumpVersion(prev, level = "patch") {
20402
+ const m = typeof prev === "string" ? /^(\d+)\.(\d+)\.(\d+)/.exec(prev.trim()) : null;
20403
+ if (!m)
20404
+ return "1.0.0";
20405
+ let [maj, min, pat] = [Number(m[1]), Number(m[2]), Number(m[3])];
20406
+ if (level === "major") {
20407
+ maj += 1;
20408
+ min = 0;
20409
+ pat = 0;
20410
+ } else if (level === "minor") {
20411
+ min += 1;
20412
+ pat = 0;
20413
+ } else
20414
+ pat += 1;
20415
+ return `${maj}.${min}.${pat}`;
20416
+ }
20417
+ var DESIGN_DIR, TOKENS_FILE, TOKENS_CSS_FILE, DESIGN_CLAUDE_MD, DTCG_SCHEMA_URL, DTCG_TYPES, VAR_ALIASES, CATEGORY_ORDER, KNOWN_TOP, TW_BUCKETS;
19405
20418
  var init_design_tokens = __esm({
19406
- "../../packages/agent-core/dist/design-tokens.js"() {
20419
+ "../../packages/shared/dist/design-tokens.js"() {
19407
20420
  "use strict";
19408
- init_zod();
19409
20421
  DESIGN_DIR = "design-system";
19410
20422
  TOKENS_FILE = "design-system/tokens.json";
19411
20423
  TOKENS_CSS_FILE = "design-system/tokens.css";
19412
20424
  DESIGN_CLAUDE_MD = "design-system/CLAUDE.md";
19413
- ColorToken = external_exports.object({ value: external_exports.string(), cssVar: external_exports.string().optional(), role: external_exports.string().optional() });
19414
- TypeStep = external_exports.object({ size: external_exports.string(), lineHeight: external_exports.string().optional(), weight: external_exports.number().optional() });
19415
- Component = external_exports.object({
19416
- selectorHint: external_exports.string().optional(),
19417
- sourceFiles: external_exports.array(external_exports.string()).optional(),
19418
- tokensUsed: external_exports.array(external_exports.string()).optional()
19419
- });
19420
- DesignTokensSchema = external_exports.object({
20425
+ DTCG_SCHEMA_URL = "https://design-tokens.github.io/community-group/format/";
20426
+ DTCG_TYPES = [
20427
+ "color",
20428
+ "dimension",
20429
+ "fontFamily",
20430
+ "fontWeight",
20431
+ "duration",
20432
+ "cubicBezier",
20433
+ "number",
20434
+ "shadow",
20435
+ "strokeStyle",
20436
+ "border",
20437
+ "transition",
20438
+ "gradient",
20439
+ "typography",
20440
+ "lineHeight",
20441
+ "letterSpacing"
20442
+ ];
20443
+ VAR_ALIASES = [
20444
+ { match: ["typography", "fontFamily"], prefix: "font" },
20445
+ { match: ["typography", "fontSize"], prefix: "text" },
20446
+ { match: ["typography", "fontWeight"], prefix: "weight" },
20447
+ { match: ["typography", "lineHeight"], prefix: "leading" },
20448
+ { match: ["typography", "letterSpacing"], prefix: "tracking" },
20449
+ { match: ["color"], prefix: "color" },
20450
+ { match: ["colors"], prefix: "color" },
20451
+ { match: ["spacing"], prefix: "space" },
20452
+ { match: ["radius"], prefix: "radius" },
20453
+ { match: ["shadow"], prefix: "shadow" },
20454
+ { match: ["motion", "duration"], prefix: "duration" },
20455
+ { match: ["motion", "easing"], prefix: "ease" }
20456
+ ];
20457
+ CATEGORY_ORDER = ["color", "typography", "spacing", "radius", "shadow", "motion"];
20458
+ KNOWN_TOP = /* @__PURE__ */ new Set(["meta", "components", "color", "colors", "typography", "spacing", "radius", "shadow"]);
20459
+ TW_BUCKETS = [
20460
+ { match: ["typography", "fontFamily"], key: "fontFamily", flat: true },
20461
+ { match: ["typography", "fontSize"], key: "fontSize", flat: true },
20462
+ { match: ["typography", "fontWeight"], key: "fontWeight", flat: true },
20463
+ { match: ["typography", "lineHeight"], key: "lineHeight", flat: true },
20464
+ { match: ["typography", "letterSpacing"], key: "letterSpacing", flat: true },
20465
+ { match: ["color"], key: "colors", flat: false },
20466
+ { match: ["colors"], key: "colors", flat: false },
20467
+ { match: ["spacing"], key: "spacing", flat: true },
20468
+ { match: ["radius"], key: "borderRadius", flat: true },
20469
+ { match: ["shadow"], key: "boxShadow", flat: true },
20470
+ { match: ["motion", "duration"], key: "transitionDuration", flat: true },
20471
+ { match: ["motion", "easing"], key: "transitionTimingFunction", flat: true }
20472
+ ];
20473
+ }
20474
+ });
20475
+
20476
+ // ../../packages/shared/dist/snapshot.js
20477
+ var SNAPSHOT_MAX_TEXT_BYTES, SNAPSHOT_MAX_BINARY_BYTES, SNAPSHOT_MAX_TOTAL_BYTES;
20478
+ var init_snapshot = __esm({
20479
+ "../../packages/shared/dist/snapshot.js"() {
20480
+ "use strict";
20481
+ SNAPSHOT_MAX_TEXT_BYTES = 512 * 1024;
20482
+ SNAPSHOT_MAX_BINARY_BYTES = 4 * 1024 * 1024;
20483
+ SNAPSHOT_MAX_TOTAL_BYTES = 24 * 1024 * 1024;
20484
+ }
20485
+ });
20486
+
20487
+ // ../../packages/shared/dist/index.js
20488
+ var init_dist2 = __esm({
20489
+ "../../packages/shared/dist/index.js"() {
20490
+ "use strict";
20491
+ init_ws_protocol();
20492
+ init_frame();
20493
+ init_plans();
20494
+ init_slug();
20495
+ init_hosting();
20496
+ init_cloud_agent();
20497
+ init_engines();
20498
+ init_providers();
20499
+ init_runtimes();
20500
+ init_runner_configs();
20501
+ init_rotation();
20502
+ init_settings();
20503
+ init_design_tokens();
20504
+ init_snapshot();
20505
+ }
20506
+ });
20507
+
20508
+ // ../../packages/agent-core/dist/design-tokens.js
20509
+ var TokenValueSchema, NodeSchema, DtcgTokensSchema, DesignTokensSchema;
20510
+ var init_design_tokens2 = __esm({
20511
+ "../../packages/agent-core/dist/design-tokens.js"() {
20512
+ "use strict";
20513
+ init_zod();
20514
+ init_dist2();
20515
+ TokenValueSchema = external_exports.union([
20516
+ external_exports.string(),
20517
+ external_exports.number(),
20518
+ external_exports.array(external_exports.string()),
20519
+ external_exports.record(external_exports.string(), external_exports.unknown()),
20520
+ external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown()))
20521
+ ]);
20522
+ NodeSchema = external_exports.lazy(() => external_exports.union([
20523
+ external_exports.object({ $value: TokenValueSchema }).catchall(external_exports.unknown()),
20524
+ // token: must carry $value
20525
+ external_exports.record(external_exports.string(), external_exports.unknown())
20526
+ // group: any record of nodes
20527
+ ]));
20528
+ DtcgTokensSchema = external_exports.object({
19421
20529
  $schema: external_exports.string().optional(),
19422
- meta: external_exports.object({
19423
- name: external_exports.string().optional(),
19424
- framework: external_exports.enum(["tailwind", "css", "css-modules", "unknown"]).optional(),
19425
- generatedAt: external_exports.string().optional()
19426
- }).optional(),
19427
- colors: external_exports.record(external_exports.string(), ColorToken).optional(),
19428
- typography: external_exports.object({
19429
- fontFamilies: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19430
- scale: external_exports.record(external_exports.string(), TypeStep).optional(),
19431
- weights: external_exports.record(external_exports.string(), external_exports.number()).optional()
19432
- }).optional(),
19433
- spacing: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19434
- radius: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19435
- shadow: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19436
- components: external_exports.record(external_exports.string(), Component).optional()
19437
- });
20530
+ $meta: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
20531
+ $components: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
20532
+ }).catchall(NodeSchema);
20533
+ DesignTokensSchema = DtcgTokensSchema;
20534
+ }
20535
+ });
20536
+
20537
+ // ../../packages/design-packs/dist/types.js
20538
+ var DESIGN_PACK_SCHEMA;
20539
+ var init_types = __esm({
20540
+ "../../packages/design-packs/dist/types.js"() {
20541
+ "use strict";
20542
+ DESIGN_PACK_SCHEMA = "https://tesseract.fineguide.ai/schemas/design-pack/v1";
20543
+ }
20544
+ });
20545
+
20546
+ // ../../packages/design-packs/dist/packs/_build.js
20547
+ function buildPack(s) {
20548
+ const dual = (lv) => ({ $value: lv[0], $extensions: { "com.tesseract": { modes: { dark: lv[1] } } } });
20549
+ const val = (v) => Array.isArray(v) ? dual(v) : { $value: v };
20550
+ const r = s.radius ?? { sm: "6px", md: "10px", lg: "16px" };
20551
+ const sh = s.shadow ?? {
20552
+ sm: "0 1px 2px rgb(0 0 0 / 0.06)",
20553
+ md: "0 4px 12px rgb(0 0 0 / 0.08)",
20554
+ lg: "0 12px 32px rgb(0 0 0 / 0.12)"
20555
+ };
20556
+ const b = s.baseFontPx ?? 16;
20557
+ const tokens = {
20558
+ $schema: "https://design-tokens.github.io/community-group/format/",
20559
+ color: {
20560
+ $type: "color",
20561
+ brand: {
20562
+ primary: val(s.brandPrimary),
20563
+ onPrimary: val(s.onPrimary),
20564
+ ...s.brandAccent ? { accent: val(s.brandAccent) } : {}
20565
+ },
20566
+ surface: { page: dual(s.page), card: dual(s.card) },
20567
+ text: { primary: dual(s.textPrimary), secondary: dual(s.textSecondary), muted: dual(s.textMuted) },
20568
+ border: { default: dual(s.border) }
20569
+ },
20570
+ typography: {
20571
+ fontFamily: {
20572
+ $type: "fontFamily",
20573
+ sans: { $value: s.sans },
20574
+ ...s.display ? { display: { $value: s.display } } : {},
20575
+ mono: { $value: s.mono ?? ["ui-monospace", "SFMono-Regular", "Menlo", "monospace"] }
20576
+ },
20577
+ fontSize: {
20578
+ $type: "dimension",
20579
+ sm: { $value: `${b - 2}px` },
20580
+ base: { $value: `${b}px` },
20581
+ lg: { $value: `${b + 2}px` },
20582
+ xl: { $value: `${b + 8}px` },
20583
+ "2xl": { $value: `${b + 16}px` }
20584
+ },
20585
+ fontWeight: { $type: "fontWeight", normal: { $value: 400 }, medium: { $value: 500 }, bold: { $value: 700 } }
20586
+ },
20587
+ spacing: {
20588
+ $type: "dimension",
20589
+ xs: { $value: "4px" },
20590
+ sm: { $value: "8px" },
20591
+ md: { $value: "16px" },
20592
+ lg: { $value: "24px" },
20593
+ xl: { $value: "40px" }
20594
+ },
20595
+ radius: { $type: "dimension", sm: { $value: r.sm }, md: { $value: r.md }, lg: { $value: r.lg }, full: { $value: "9999px" } },
20596
+ shadow: { $type: "shadow", sm: { $value: sh.sm }, md: { $value: sh.md }, lg: { $value: sh.lg } }
20597
+ };
20598
+ return { $packSchema: DESIGN_PACK_SCHEMA, id: s.id, name: s.name, description: s.description, style: s.style, tokens };
20599
+ }
20600
+ var init_build = __esm({
20601
+ "../../packages/design-packs/dist/packs/_build.js"() {
20602
+ "use strict";
20603
+ init_types();
20604
+ }
20605
+ });
20606
+
20607
+ // ../../packages/design-packs/dist/packs/clean-minimal.js
20608
+ var clean_minimal_default;
20609
+ var init_clean_minimal = __esm({
20610
+ "../../packages/design-packs/dist/packs/clean-minimal.js"() {
20611
+ "use strict";
20612
+ init_build();
20613
+ clean_minimal_default = buildPack({
20614
+ id: "clean-minimal",
20615
+ name: "Clean Minimal",
20616
+ description: "Warm off-white, soft stone neutrals, restrained. The safe default.",
20617
+ style: "minimal",
20618
+ // Warm neutral (2026 "Cloud Dancer" direction) + a brand that flips light↔dark so the CTA
20619
+ // stays visible: near-black button in light, near-white button in dark.
20620
+ brandPrimary: ["#1c1917", "#f5f5f4"],
20621
+ onPrimary: ["#ffffff", "#1c1917"],
20622
+ page: ["#faf9f7", "#0b0b0a"],
20623
+ card: ["#ffffff", "#161513"],
20624
+ textPrimary: ["#1c1917", "#fafaf9"],
20625
+ textSecondary: ["#57534e", "#a8a29e"],
20626
+ textMuted: ["#79716b", "#8a847c"],
20627
+ border: ["#e7e5e4", "#292524"],
20628
+ sans: ["Inter", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif"],
20629
+ radius: { sm: "6px", md: "8px", lg: "12px" }
20630
+ });
20631
+ }
20632
+ });
20633
+
20634
+ // ../../packages/design-packs/dist/packs/corporate-trust.js
20635
+ var corporate_trust_default;
20636
+ var init_corporate_trust = __esm({
20637
+ "../../packages/design-packs/dist/packs/corporate-trust.js"() {
20638
+ "use strict";
20639
+ init_build();
20640
+ corporate_trust_default = buildPack({
20641
+ id: "corporate-trust",
20642
+ name: "Corporate Trust",
20643
+ description: "Professional blue/slate, structured, trust signals.",
20644
+ style: "corporate",
20645
+ brandPrimary: "#1d4ed8",
20646
+ onPrimary: "#ffffff",
20647
+ brandAccent: "#0ea5e9",
20648
+ page: ["#ffffff", "#0b1220"],
20649
+ card: ["#f8fafc", "#0f1a2e"],
20650
+ textPrimary: ["#0f172a", "#e2e8f0"],
20651
+ textSecondary: ["#475569", "#94a3b8"],
20652
+ textMuted: ["#7e8ba1", "#64748b"],
20653
+ border: ["#e2e8f0", "#1e293b"],
20654
+ sans: ["Inter", "-apple-system", "Segoe UI", "sans-serif"],
20655
+ radius: { sm: "4px", md: "8px", lg: "12px" }
20656
+ });
20657
+ }
20658
+ });
20659
+
20660
+ // ../../packages/design-packs/dist/packs/refined-brutalist.js
20661
+ var refined_brutalist_default;
20662
+ var init_refined_brutalist = __esm({
20663
+ "../../packages/design-packs/dist/packs/refined-brutalist.js"() {
20664
+ "use strict";
20665
+ init_build();
20666
+ refined_brutalist_default = buildPack({
20667
+ id: "refined-brutalist",
20668
+ name: "Refined Brutalist",
20669
+ description: "Raw grotesk type, visible grid, hard edges, high accessible contrast.",
20670
+ style: "brutalist",
20671
+ brandPrimary: ["#000000", "#ffffff"],
20672
+ onPrimary: ["#ffffff", "#000000"],
20673
+ brandAccent: "#ff3b00",
20674
+ page: ["#ffffff", "#000000"],
20675
+ card: ["#f4f4f4", "#0c0c0c"],
20676
+ textPrimary: ["#000000", "#ffffff"],
20677
+ textSecondary: ["#333333", "#cccccc"],
20678
+ textMuted: ["#666666", "#999999"],
20679
+ border: ["#000000", "#ffffff"],
20680
+ sans: ["Space Grotesk", "Arial", "Helvetica", "sans-serif"],
20681
+ mono: ["Space Mono", "ui-monospace", "monospace"],
20682
+ radius: { sm: "0px", md: "0px", lg: "0px" },
20683
+ shadow: { sm: "2px 2px 0 #000", md: "4px 4px 0 #000", lg: "8px 8px 0 #000" }
20684
+ });
20685
+ }
20686
+ });
20687
+
20688
+ // ../../packages/design-packs/dist/packs/editorial.js
20689
+ var editorial_default;
20690
+ var init_editorial = __esm({
20691
+ "../../packages/design-packs/dist/packs/editorial.js"() {
20692
+ "use strict";
20693
+ init_build();
20694
+ editorial_default = buildPack({
20695
+ id: "editorial",
20696
+ name: "Editorial",
20697
+ description: "Serif display, classical art-converging, magazine layout.",
20698
+ style: "editorial",
20699
+ brandPrimary: ["#1a1a1a", "#f0ece4"],
20700
+ onPrimary: ["#ffffff", "#1a1a1a"],
20701
+ brandAccent: ["#9a3412", "#e0794a"],
20702
+ page: ["#fbfaf7", "#1a1714"],
20703
+ card: ["#ffffff", "#221d19"],
20704
+ textPrimary: ["#1a1a1a", "#f0ece4"],
20705
+ textSecondary: ["#57534e", "#a8a29e"],
20706
+ textMuted: ["#78716c", "#857b6e"],
20707
+ border: ["#e7e2d8", "#2a2520"],
20708
+ sans: ["Georgia", "Cambria", "Times New Roman", "serif"],
20709
+ display: ["Playfair Display", "Georgia", "serif"],
20710
+ radius: { sm: "2px", md: "4px", lg: "6px" }
20711
+ });
20712
+ }
20713
+ });
20714
+
20715
+ // ../../packages/design-packs/dist/packs/soft-clay-playful.js
20716
+ var soft_clay_playful_default;
20717
+ var init_soft_clay_playful = __esm({
20718
+ "../../packages/design-packs/dist/packs/soft-clay-playful.js"() {
20719
+ "use strict";
20720
+ init_build();
20721
+ soft_clay_playful_default = buildPack({
20722
+ id: "soft-clay-playful",
20723
+ name: "Soft / Clay Playful",
20724
+ description: "Rounded claymorphism, friendly, bright violet accents.",
20725
+ style: "playful",
20726
+ brandPrimary: "#7c3aed",
20727
+ onPrimary: "#ffffff",
20728
+ brandAccent: "#f59e0b",
20729
+ page: ["#fffdf9", "#15131a"],
20730
+ card: ["#ffffff", "#1d1a24"],
20731
+ textPrimary: ["#2e1065", "#f5f3ff"],
20732
+ textSecondary: ["#6d28d9", "#c4b5fd"],
20733
+ textMuted: ["#8b5cf6", "#8b7fb0"],
20734
+ border: ["#ede9fe", "#2e2640"],
20735
+ sans: ["Quicksand", "Nunito", "-apple-system", "sans-serif"],
20736
+ radius: { sm: "12px", md: "20px", lg: "28px" },
20737
+ shadow: { sm: "0 2px 6px rgb(124 58 237 / 0.12)", md: "0 8px 20px rgb(124 58 237 / 0.16)", lg: "0 16px 40px rgb(124 58 237 / 0.20)" }
20738
+ });
20739
+ }
20740
+ });
20741
+
20742
+ // ../../packages/design-packs/dist/packs/premium-dark.js
20743
+ var premium_dark_default;
20744
+ var init_premium_dark = __esm({
20745
+ "../../packages/design-packs/dist/packs/premium-dark.js"() {
20746
+ "use strict";
20747
+ init_build();
20748
+ premium_dark_default = buildPack({
20749
+ id: "premium-dark",
20750
+ name: "Premium Dark",
20751
+ description: "Dark-first, high-end gold accent, luxe restraint.",
20752
+ style: "dark",
20753
+ brandPrimary: "#e5b567",
20754
+ onPrimary: "#1a1408",
20755
+ brandAccent: "#f5d491",
20756
+ page: ["#0a0a0b", "#070708"],
20757
+ card: ["#161618", "#1c1c1f"],
20758
+ textPrimary: ["#fafafa", "#fafafa"],
20759
+ textSecondary: ["#a1a1aa", "#a1a1aa"],
20760
+ textMuted: ["#71717a", "#71717a"],
20761
+ border: ["#27272a", "#2c2c30"],
20762
+ sans: ["Inter", "-apple-system", "Segoe UI", "sans-serif"],
20763
+ radius: { sm: "6px", md: "10px", lg: "14px" },
20764
+ shadow: { sm: "0 1px 2px rgb(0 0 0 / 0.5)", md: "0 6px 16px rgb(0 0 0 / 0.55)", lg: "0 16px 40px rgb(0 0 0 / 0.6)" }
20765
+ });
20766
+ }
20767
+ });
20768
+
20769
+ // ../../packages/design-packs/dist/packs/glass-aurora.js
20770
+ var glass_aurora_default;
20771
+ var init_glass_aurora = __esm({
20772
+ "../../packages/design-packs/dist/packs/glass-aurora.js"() {
20773
+ "use strict";
20774
+ init_build();
20775
+ glass_aurora_default = buildPack({
20776
+ id: "glass-aurora",
20777
+ name: "Glass / Aurora",
20778
+ description: "Translucent frosted layers, soft gradients and glow.",
20779
+ style: "glass",
20780
+ brandPrimary: "#4f46e5",
20781
+ onPrimary: "#ffffff",
20782
+ brandAccent: "#22d3ee",
20783
+ page: ["#f8fafc", "#0b1020"],
20784
+ card: ["#ffffff", "#111735"],
20785
+ textPrimary: ["#0f172a", "#e7ecff"],
20786
+ textSecondary: ["#475569", "#aab4d4"],
20787
+ textMuted: ["#7e8ba1", "#6b7494"],
20788
+ border: ["#e2e8f0", "#23294a"],
20789
+ sans: ["Inter", "-apple-system", "Segoe UI", "sans-serif"],
20790
+ radius: { sm: "10px", md: "16px", lg: "24px" },
20791
+ shadow: { sm: "0 1px 2px rgb(79 70 229 / 0.10)", md: "0 8px 24px rgb(79 70 229 / 0.14)", lg: "0 20px 48px rgb(79 70 229 / 0.18)" }
20792
+ });
20793
+ }
20794
+ });
20795
+
20796
+ // ../../packages/design-packs/dist/packs/dopamine-pop.js
20797
+ var dopamine_pop_default;
20798
+ var init_dopamine_pop = __esm({
20799
+ "../../packages/design-packs/dist/packs/dopamine-pop.js"() {
20800
+ "use strict";
20801
+ init_build();
20802
+ dopamine_pop_default = buildPack({
20803
+ id: "dopamine-pop",
20804
+ name: "Dopamine Pop",
20805
+ description: "Confident, accessible full-color system. Bold and energetic.",
20806
+ style: "dopamine",
20807
+ brandPrimary: "#7e22ce",
20808
+ onPrimary: "#ffffff",
20809
+ brandAccent: "#f59e0b",
20810
+ page: ["#fffaf5", "#190a18"],
20811
+ card: ["#ffffff", "#241023"],
20812
+ textPrimary: ["#3b0764", "#fdf4ff"],
20813
+ textSecondary: ["#7e22ce", "#e9d5ff"],
20814
+ textMuted: ["#a855f7", "#9b6fb5"],
20815
+ border: ["#f5d0fe", "#3b1d49"],
20816
+ sans: ["Plus Jakarta Sans", "Inter", "-apple-system", "sans-serif"],
20817
+ radius: { sm: "8px", md: "14px", lg: "22px" }
20818
+ });
20819
+ }
20820
+ });
20821
+
20822
+ // ../../packages/design-packs/dist/packs/retro-y2k.js
20823
+ var retro_y2k_default;
20824
+ var init_retro_y2k = __esm({
20825
+ "../../packages/design-packs/dist/packs/retro-y2k.js"() {
20826
+ "use strict";
20827
+ init_build();
20828
+ retro_y2k_default = buildPack({
20829
+ id: "retro-y2k",
20830
+ name: "Retro / Y2K",
20831
+ description: "Nostalgic, grain-textured, vibrant and chunky.",
20832
+ style: "retro",
20833
+ brandPrimary: "#b91c1c",
20834
+ onPrimary: "#fdf6ec",
20835
+ brandAccent: "#f59e0b",
20836
+ page: ["#fdf6ec", "#1b1410"],
20837
+ card: ["#fffaf0", "#241a13"],
20838
+ textPrimary: ["#1c1917", "#f5ede0"],
20839
+ textSecondary: ["#57534e", "#bcae9c"],
20840
+ textMuted: ["#78716c", "#8a7c6a"],
20841
+ border: ["#e7d9c2", "#352a1d"],
20842
+ sans: ["Space Grotesk", "Arial", "sans-serif"],
20843
+ display: ["Space Grotesk", "Impact", "sans-serif"],
20844
+ radius: { sm: "4px", md: "8px", lg: "14px" },
20845
+ shadow: { sm: "3px 3px 0 rgb(28 25 23 / 0.9)", md: "5px 5px 0 rgb(28 25 23 / 0.9)", lg: "8px 8px 0 rgb(28 25 23 / 0.9)" }
20846
+ });
20847
+ }
20848
+ });
20849
+
20850
+ // ../../packages/design-packs/dist/packs/warm-organic.js
20851
+ var warm_organic_default;
20852
+ var init_warm_organic = __esm({
20853
+ "../../packages/design-packs/dist/packs/warm-organic.js"() {
20854
+ "use strict";
20855
+ init_build();
20856
+ warm_organic_default = buildPack({
20857
+ id: "warm-organic",
20858
+ name: "Warm Organic",
20859
+ description: "Earth tones, natural, calm. Wellness and hospitality.",
20860
+ style: "organic",
20861
+ brandPrimary: "#7c5c43",
20862
+ onPrimary: "#ffffff",
20863
+ brandAccent: "#84cc16",
20864
+ page: ["#faf6f1", "#1a1512"],
20865
+ card: ["#fffdf9", "#221b16"],
20866
+ textPrimary: ["#2b211a", "#efe7dd"],
20867
+ textSecondary: ["#6b5b4d", "#c4b3a3"],
20868
+ textMuted: ["#877564", "#8a7868"],
20869
+ border: ["#e8ddcf", "#33291f"],
20870
+ sans: ["Source Sans 3", "Source Sans Pro", "-apple-system", "sans-serif"],
20871
+ radius: { sm: "8px", md: "14px", lg: "20px" }
20872
+ });
20873
+ }
20874
+ });
20875
+
20876
+ // ../../packages/design-packs/dist/packs/luxury-elegant.js
20877
+ var luxury_elegant_default;
20878
+ var init_luxury_elegant = __esm({
20879
+ "../../packages/design-packs/dist/packs/luxury-elegant.js"() {
20880
+ "use strict";
20881
+ init_build();
20882
+ luxury_elegant_default = buildPack({
20883
+ id: "luxury-elegant",
20884
+ name: "Luxury Elegant",
20885
+ description: "Muted, fine serif, gold-on-black, refined restraint.",
20886
+ style: "luxury",
20887
+ brandPrimary: ["#11100f", "#d4af37"],
20888
+ onPrimary: ["#d4af37", "#11100f"],
20889
+ brandAccent: "#b08d57",
20890
+ page: ["#faf9f7", "#0e0d0c"],
20891
+ card: ["#ffffff", "#171513"],
20892
+ textPrimary: ["#1a1816", "#f3efe9"],
20893
+ textSecondary: ["#57514a", "#b8ada0"],
20894
+ textMuted: ["#8a8278", "#7c7468"],
20895
+ border: ["#e8e2d8", "#2a251f"],
20896
+ sans: ["Cormorant Garamond", "Garamond", "Georgia", "serif"],
20897
+ display: ["Cormorant Garamond", "Didot", "Georgia", "serif"],
20898
+ radius: { sm: "2px", md: "4px", lg: "8px" },
20899
+ shadow: { sm: "0 1px 2px rgb(0 0 0 / 0.05)", md: "0 6px 18px rgb(0 0 0 / 0.07)", lg: "0 18px 44px rgb(0 0 0 / 0.10)" }
20900
+ });
20901
+ }
20902
+ });
20903
+
20904
+ // ../../packages/design-packs/dist/packs/bento-tech.js
20905
+ var bento_tech_default;
20906
+ var init_bento_tech = __esm({
20907
+ "../../packages/design-packs/dist/packs/bento-tech.js"() {
20908
+ "use strict";
20909
+ init_build();
20910
+ bento_tech_default = buildPack({
20911
+ id: "bento-tech",
20912
+ name: "Bento Tech",
20913
+ description: "Crisp modular bento rhythm, grid-forward, product-led.",
20914
+ style: "tech",
20915
+ brandPrimary: "#2563eb",
20916
+ onPrimary: "#ffffff",
20917
+ brandAccent: "#06b6d4",
20918
+ page: ["#f6f7f9", "#0c0e12"],
20919
+ card: ["#ffffff", "#13161c"],
20920
+ textPrimary: ["#0b0e14", "#e9edf5"],
20921
+ textSecondary: ["#3f4756", "#9aa4b8"],
20922
+ textMuted: ["#6f7892", "#6b7488"],
20923
+ border: ["#e6e8ee", "#1d212b"],
20924
+ sans: ["Geist", "Inter", "-apple-system", "sans-serif"],
20925
+ mono: ["Geist Mono", "ui-monospace", "monospace"],
20926
+ radius: { sm: "8px", md: "12px", lg: "16px" }
20927
+ });
20928
+ }
20929
+ });
20930
+
20931
+ // ../../packages/design-packs/dist/packs/fintech-emerald.js
20932
+ var fintech_emerald_default;
20933
+ var init_fintech_emerald = __esm({
20934
+ "../../packages/design-packs/dist/packs/fintech-emerald.js"() {
20935
+ "use strict";
20936
+ init_build();
20937
+ fintech_emerald_default = buildPack({
20938
+ id: "fintech-emerald",
20939
+ name: "Fintech Emerald",
20940
+ description: "Fresh emerald, growth-and-trust. Fintech, health, sustainability.",
20941
+ style: "fresh",
20942
+ // Emerald shifts lighter in dark (emerald-700 → emerald-400) so the CTA pops on a deep
20943
+ // green-black, per modern light/dark accent practice.
20944
+ brandPrimary: ["#047857", "#34d399"],
20945
+ onPrimary: ["#ffffff", "#022c22"],
20946
+ brandAccent: ["#0d9488", "#5eead4"],
20947
+ page: ["#f7faf8", "#07120d"],
20948
+ card: ["#ffffff", "#0e1a14"],
20949
+ textPrimary: ["#0a1f17", "#e6f5ee"],
20950
+ textSecondary: ["#3f5a4f", "#9cc3b3"],
20951
+ textMuted: ["#6a8579", "#728d80"],
20952
+ border: ["#dcebe3", "#1a2a22"],
20953
+ sans: ["Inter", "-apple-system", "Segoe UI", "sans-serif"],
20954
+ radius: { sm: "8px", md: "12px", lg: "18px" }
20955
+ });
20956
+ }
20957
+ });
20958
+
20959
+ // ../../packages/design-packs/dist/packs/sunset-coral.js
20960
+ var sunset_coral_default;
20961
+ var init_sunset_coral = __esm({
20962
+ "../../packages/design-packs/dist/packs/sunset-coral.js"() {
20963
+ "use strict";
20964
+ init_build();
20965
+ sunset_coral_default = buildPack({
20966
+ id: "sunset-coral",
20967
+ name: "Sunset Coral",
20968
+ description: "Warm coral + amber, energetic but friendly. Lifestyle, creative, DTC.",
20969
+ style: "sunset",
20970
+ // Coral deepens for white legibility in light, brightens in dark; amber as the warm accent.
20971
+ brandPrimary: ["#d23b1e", "#ff8a6b"],
20972
+ onPrimary: ["#ffffff", "#3d0f06"],
20973
+ brandAccent: ["#f59e0b", "#fcd34d"],
20974
+ page: ["#fff8f4", "#1a0f0a"],
20975
+ card: ["#ffffff", "#251510"],
20976
+ textPrimary: ["#2b1610", "#fdeee6"],
20977
+ textSecondary: ["#6b4133", "#d6a795"],
20978
+ textMuted: ["#9a6f5e", "#9a786a"],
20979
+ border: ["#f4ddd0", "#3a221a"],
20980
+ sans: ["Plus Jakarta Sans", "Inter", "-apple-system", "sans-serif"],
20981
+ radius: { sm: "10px", md: "16px", lg: "22px" }
20982
+ });
20983
+ }
20984
+ });
20985
+
20986
+ // ../../packages/design-packs/dist/index.js
20987
+ function getPack(id) {
20988
+ return PACKS_BY_ID[id];
20989
+ }
20990
+ var PACKS, PACKS_BY_ID;
20991
+ var init_dist3 = __esm({
20992
+ "../../packages/design-packs/dist/index.js"() {
20993
+ "use strict";
20994
+ init_types();
20995
+ init_clean_minimal();
20996
+ init_corporate_trust();
20997
+ init_refined_brutalist();
20998
+ init_editorial();
20999
+ init_soft_clay_playful();
21000
+ init_premium_dark();
21001
+ init_glass_aurora();
21002
+ init_dopamine_pop();
21003
+ init_retro_y2k();
21004
+ init_warm_organic();
21005
+ init_luxury_elegant();
21006
+ init_bento_tech();
21007
+ init_fintech_emerald();
21008
+ init_sunset_coral();
21009
+ PACKS = [
21010
+ clean_minimal_default,
21011
+ corporate_trust_default,
21012
+ fintech_emerald_default,
21013
+ refined_brutalist_default,
21014
+ editorial_default,
21015
+ soft_clay_playful_default,
21016
+ premium_dark_default,
21017
+ glass_aurora_default,
21018
+ dopamine_pop_default,
21019
+ sunset_coral_default,
21020
+ retro_y2k_default,
21021
+ warm_organic_default,
21022
+ luxury_elegant_default,
21023
+ bento_tech_default
21024
+ ];
21025
+ PACKS_BY_ID = Object.fromEntries(PACKS.map((p) => [p.id, p]));
19438
21026
  }
19439
21027
  });
19440
21028
 
@@ -19448,8 +21036,8 @@ function within(root, p) {
19448
21036
  }
19449
21037
  async function loadTokens(root) {
19450
21038
  try {
19451
- const parsed = DesignTokensSchema.safeParse(JSON.parse(await readFile(join4(root, TOKENS_FILE), "utf8")));
19452
- return parsed.success ? parsed.data : {};
21039
+ const norm = normalizeTokens(JSON.parse(await readFile(join4(root, TOKENS_FILE), "utf8")));
21040
+ return DesignTokensSchema.safeParse(norm).success ? norm : {};
19453
21041
  } catch {
19454
21042
  return {};
19455
21043
  }
@@ -19472,28 +21060,64 @@ function buildDesignTools(deps) {
19472
21060
  return root;
19473
21061
  };
19474
21062
  return [
19475
- tool2("read_design_tokens", "Read the project design system from design-system/tokens.json (colors, typography, spacing, radius, shadow, components). Call this ONCE when you need token values \u2014 do not guess hardcoded hex/sizes.", { section: external_exports.enum(["all", "colors", "typography", "spacing", "radius", "shadow", "components"]).optional().describe("Limit to one section (default: all)") }, async (args) => {
21063
+ tool2("read_design_tokens", "Read the project design system from design-system/tokens.json in W3C DTCG format (color, typography, spacing, radius, shadow, components). Call this ONCE when you need token values \u2014 do not guess hardcoded hex/sizes.", { section: external_exports.enum(["all", "color", "typography", "spacing", "radius", "shadow", "components"]).optional().describe("Limit to one section (default: all)") }, async (args) => {
19476
21064
  const tokens = await loadTokens(needRoot());
19477
- const out = !args.section || args.section === "all" ? tokens : { [args.section]: tokens[args.section] ?? {} };
21065
+ const key2 = args.section === "components" ? "$components" : args.section;
21066
+ const out = !args.section || args.section === "all" ? tokens : { [args.section]: tokens[key2] ?? {} };
19478
21067
  return text(JSON.stringify(out, null, 2));
19479
21068
  }),
19480
- tool2("write_design_token", 'Set one or more design tokens by dot-path (e.g. "colors.primary.value" = "#d97757", "spacing.2" = "0.5rem") and regenerate design-system/tokens.css. Batch related edits in one call. Path-guarded to the project root.', {
21069
+ tool2("write_design_token", 'Set one or more design tokens by DTCG dot-path (e.g. "color.brand.primary.$value" = "#d97757", "spacing.md.$value" = "0.5rem") and regenerate design-system/tokens.css. Token leaves carry $value; set a group $type once (e.g. "color.$type" = "color"). Batch related edits in one call. Path-guarded to the project root.', {
19481
21070
  edits: external_exports.array(external_exports.object({
19482
- path: external_exports.string().describe("Dot-path into tokens.json, e.g. colors.primary.value"),
19483
- value: external_exports.union([external_exports.string(), external_exports.number()]).describe("The new value")
21071
+ path: external_exports.string().optional().describe("DTCG dot-path into tokens.json, e.g. color.brand.primary.$value"),
21072
+ segments: external_exports.array(external_exports.string()).optional().describe("Explicit path segments \u2014 use instead of path when a key contains a dot (e.g. a $extensions vendor key)"),
21073
+ value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.array(external_exports.string())]).describe("The new value (array for fontFamily)")
19484
21074
  })).describe("Edits to apply"),
19485
21075
  regenerateCss: external_exports.boolean().optional().describe("Regenerate tokens.css from the result (default: true)")
19486
21076
  }, async (args) => {
19487
21077
  const root = needRoot();
19488
21078
  let tokens = await loadTokens(root);
19489
- for (const e of args.edits)
19490
- tokens = setTokenPath(tokens, e.path, e.value);
21079
+ for (const e of args.edits) {
21080
+ if (e.segments?.length)
21081
+ tokens = setTokenSegments(tokens, e.segments, e.value);
21082
+ else if (e.path)
21083
+ tokens = setTokenPath(tokens, e.path, e.value);
21084
+ }
19491
21085
  const validated = DesignTokensSchema.safeParse(tokens);
19492
21086
  if (!validated.success)
19493
21087
  return text(`Edit produced an invalid tokens document: ${validated.error.message}`, true);
19494
21088
  const regen = args.regenerateCss !== false;
19495
- await saveTokens(root, validated.data, regen);
19496
- return text(`Updated ${args.edits.length} token(s): ${args.edits.map((e) => e.path).join(", ")}${regen ? " and regenerated tokens.css" : ""}.`);
21089
+ await saveTokens(root, tokens, regen);
21090
+ const names = args.edits.map((e) => e.path ?? e.segments?.join(".") ?? "?").join(", ");
21091
+ return text(`Updated ${args.edits.length} token(s): ${names}${regen ? " and regenerated tokens.css" : ""}.`);
21092
+ }),
21093
+ tool2("apply_design_pack", `Apply a curated design pack (a full color+typography+spacing+radius+shadow vibe, light+dark) to the project design system and regenerate tokens.css. Pass packId for a bundled pack (${PACK_IDS}) OR an inline DTCG tokens document. mode: merge (override only the paths the pack defines, keep the rest incl. components \u2014 default), replace (swap the whole token tree, keep $meta/$components), palette (recolour + change font families only).`, {
21094
+ packId: external_exports.string().optional().describe('Bundled pack id, e.g. "premium-dark"'),
21095
+ tokens: DesignTokensSchema.optional().describe("Inline DTCG tokens to apply instead of a bundled pack"),
21096
+ name: external_exports.string().optional().describe("Display name when applying inline tokens"),
21097
+ mode: external_exports.enum(["merge", "replace", "palette"]).optional().describe("Apply strategy (default: merge)")
21098
+ }, async (args) => {
21099
+ const root = needRoot();
21100
+ const mode = args.mode ?? "merge";
21101
+ let packTokens;
21102
+ let info;
21103
+ if (args.packId) {
21104
+ const pack = getPack(args.packId);
21105
+ if (!pack)
21106
+ return text(`Unknown packId "${args.packId}". Bundled: ${PACK_IDS}.`, true);
21107
+ packTokens = pack.tokens;
21108
+ info = { id: pack.id, name: pack.name };
21109
+ } else if (args.tokens) {
21110
+ packTokens = args.tokens;
21111
+ info = { id: "inline", name: args.name ?? "Custom pack" };
21112
+ } else {
21113
+ return text("Provide either packId or tokens.", true);
21114
+ }
21115
+ const result = applyDesignPack(await loadTokens(root), packTokens, info, { mode });
21116
+ const validated = DesignTokensSchema.safeParse(result);
21117
+ if (!validated.success)
21118
+ return text(`Applying the pack produced an invalid document: ${validated.error.message}`, true);
21119
+ await saveTokens(root, result, true);
21120
+ return text(`Applied "${info.name}" (${mode}) and regenerated tokens.css.`);
19497
21121
  }),
19498
21122
  tool2("capture_element_styles", "Read the computed CSS of an element on the live preview by CSS selector (cheap \u2014 returns text, not a screenshot). Use to learn what styles/tokens an element currently uses before editing.", {
19499
21123
  selector: external_exports.string().describe("CSS selector of the element to inspect"),
@@ -19516,7 +21140,7 @@ function buildDesignTools(deps) {
19516
21140
  return text(`Preview announced: ${args.url}`);
19517
21141
  }),
19518
21142
  tool2("list_components", "List the design-system components recorded in tokens.json (name, source files, tokens used).", {}, async () => {
19519
- const comps = (await loadTokens(needRoot())).components ?? {};
21143
+ const comps = (await loadTokens(needRoot())).$components ?? {};
19520
21144
  const names = Object.keys(comps);
19521
21145
  if (!names.length)
19522
21146
  return text('No components recorded yet. Run the "Import Design System" skill to populate them.');
@@ -19529,12 +21153,14 @@ function buildDesignTools(deps) {
19529
21153
  })
19530
21154
  ];
19531
21155
  }
19532
- var STYLE_PROPS, text;
21156
+ var PACK_IDS, STYLE_PROPS, text;
19533
21157
  var init_design_tools = __esm({
19534
21158
  "../../packages/agent-core/dist/design-tools.js"() {
19535
21159
  "use strict";
19536
21160
  init_zod();
19537
- init_design_tokens();
21161
+ init_design_tokens2();
21162
+ init_dist3();
21163
+ PACK_IDS = PACKS.map((p) => p.id).join(", ");
19538
21164
  STYLE_PROPS = [
19539
21165
  "color",
19540
21166
  "background-color",
@@ -19796,6 +21422,23 @@ function sessionDir(cwd) {
19796
21422
  function sessionFile(cwd, sessionId) {
19797
21423
  return join5(sessionDir(cwd), `${sessionId}.jsonl`);
19798
21424
  }
21425
+ async function resolveSessionFile(sessionId, projectDir) {
21426
+ if (projectDir) {
21427
+ const direct = sessionFile(projectDir, sessionId);
21428
+ if (existsSync(direct))
21429
+ return direct;
21430
+ }
21431
+ const target = `${sessionId}.jsonl`;
21432
+ const projects = await readdir(projectsRoot(), { withFileTypes: true }).catch(() => []);
21433
+ for (const dir of projects) {
21434
+ if (!dir.isDirectory())
21435
+ continue;
21436
+ const candidate = join5(projectsRoot(), dir.name, target);
21437
+ if (existsSync(candidate))
21438
+ return candidate;
21439
+ }
21440
+ return null;
21441
+ }
19799
21442
  async function walkFiles(root) {
19800
21443
  const out = [];
19801
21444
  async function rec(dir, prefix) {
@@ -20073,9 +21716,10 @@ var init_session_store = __esm({
20073
21716
  * WITHOUT file-history/undo snapshots (SDK behavior). */
20074
21717
  async forkSession(sessionId, opts) {
20075
21718
  try {
21719
+ const upToMessageId = opts?.upToMessageId ?? await this.lastResumableMessageId(sessionId, opts?.projectDir);
20076
21720
  const result = await forkSession(sessionId, {
20077
21721
  ...opts?.projectDir ? { dir: opts.projectDir } : {},
20078
- ...opts?.upToMessageId ? { upToMessageId: opts.upToMessageId } : {},
21722
+ ...upToMessageId ? { upToMessageId } : {},
20079
21723
  ...opts?.title ? { title: opts.title } : {}
20080
21724
  });
20081
21725
  return result.sessionId;
@@ -20083,6 +21727,51 @@ var init_session_store = __esm({
20083
21727
  return null;
20084
21728
  }
20085
21729
  }
21730
+ /** The uuid of the last transcript message after which NO tool_use is left without
21731
+ * its tool_result — the safe point to fork at. Reads the same on-disk `.jsonl` the
21732
+ * SDK fork copies (filtering sidechains identically) and pairs tool_use ids against
21733
+ * tool_result ids. Returns undefined when the transcript already ends balanced
21734
+ * (fork everything) or it can't be read (best-effort: fall back to a full fork). */
21735
+ async lastResumableMessageId(sessionId, projectDir) {
21736
+ try {
21737
+ const file2 = await resolveSessionFile(sessionId, projectDir);
21738
+ if (!file2)
21739
+ return void 0;
21740
+ const raw = await readFile3(file2, "utf-8");
21741
+ const outstanding = /* @__PURE__ */ new Set();
21742
+ let lastBalancedUuid;
21743
+ for (const line of raw.split("\n")) {
21744
+ const t = line.trim();
21745
+ if (!t)
21746
+ continue;
21747
+ let e;
21748
+ try {
21749
+ e = JSON.parse(t);
21750
+ } catch {
21751
+ continue;
21752
+ }
21753
+ if (e.isSidechain === true)
21754
+ continue;
21755
+ const content = e.message?.content;
21756
+ if (Array.isArray(content)) {
21757
+ for (const b of content) {
21758
+ if (!b || typeof b !== "object")
21759
+ continue;
21760
+ const blk = b;
21761
+ if (blk.type === "tool_use" && typeof blk.id === "string")
21762
+ outstanding.add(blk.id);
21763
+ else if (blk.type === "tool_result" && typeof blk.tool_use_id === "string")
21764
+ outstanding.delete(blk.tool_use_id);
21765
+ }
21766
+ }
21767
+ if (typeof e.uuid === "string" && outstanding.size === 0)
21768
+ lastBalancedUuid = e.uuid;
21769
+ }
21770
+ return outstanding.size === 0 ? void 0 : lastBalancedUuid;
21771
+ } catch {
21772
+ return void 0;
21773
+ }
21774
+ }
20086
21775
  };
20087
21776
  }
20088
21777
  });
@@ -20471,7 +22160,7 @@ var init_agent_manager = __esm({
20471
22160
  init_dist();
20472
22161
  init_cron_tools();
20473
22162
  init_design_tools();
20474
- init_design_tokens();
22163
+ init_design_tokens2();
20475
22164
  init_narrator();
20476
22165
  init_plan_splitter();
20477
22166
  init_trace_store();
@@ -22129,24 +23818,42 @@ __export(dist_exports, {
22129
23818
  AgentManager: () => AgentManager,
22130
23819
  DESIGN_CLAUDE_MD: () => DESIGN_CLAUDE_MD,
22131
23820
  DESIGN_DIR: () => DESIGN_DIR,
23821
+ DTCG_TYPES: () => DTCG_TYPES,
22132
23822
  DesignTokensSchema: () => DesignTokensSchema,
23823
+ DtcgTokensSchema: () => DtcgTokensSchema,
22133
23824
  SessionStore: () => SessionStore,
22134
23825
  TOKENS_CSS_FILE: () => TOKENS_CSS_FILE,
22135
23826
  TOKENS_FILE: () => TOKENS_FILE,
23827
+ applyDesignPack: () => applyDesignPack,
22136
23828
  buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
23829
+ bumpVersion: () => bumpVersion,
23830
+ contrastRatio: () => contrastRatio,
23831
+ diffTokens: () => diffTokens,
22137
23832
  exportSession: () => exportSession,
23833
+ flattenForDisplay: () => flattenForDisplay,
22138
23834
  getTokenPath: () => getTokenPath,
23835
+ getTokenSegments: () => getTokenSegments,
22139
23836
  importSession: () => importSession,
23837
+ isToken: () => isToken,
22140
23838
  log: () => log,
23839
+ normalizeTokens: () => normalizeTokens,
23840
+ parseColorToRgb: () => parseColorToRgb,
22141
23841
  resolveOauthToken: () => resolveOauthToken,
23842
+ resolveSessionFile: () => resolveSessionFile,
22142
23843
  sanitizeProjectDir: () => sanitizeProjectDir,
22143
23844
  sessionDir: () => sessionDir,
22144
23845
  sessionFile: () => sessionFile,
22145
23846
  setTokenPath: () => setTokenPath,
23847
+ setTokenSegments: () => setTokenSegments,
23848
+ stringifyValue: () => stringifyValue,
23849
+ tokenCssVarName: () => tokenCssVarName,
22146
23850
  tokensToCss: () => tokensToCss,
22147
- transferSession: () => transferSession
23851
+ tokensToTailwindConfig: () => tokensToTailwindConfig,
23852
+ tokensToTailwindTheme: () => tokensToTailwindTheme,
23853
+ transferSession: () => transferSession,
23854
+ walkTokens: () => walkTokens
22148
23855
  });
22149
- var init_dist2 = __esm({
23856
+ var init_dist4 = __esm({
22150
23857
  "../../packages/agent-core/dist/index.js"() {
22151
23858
  "use strict";
22152
23859
  init_agent_manager();
@@ -22154,7 +23861,7 @@ var init_dist2 = __esm({
22154
23861
  init_session_usage();
22155
23862
  init_session_transfer();
22156
23863
  init_log();
22157
- init_design_tokens();
23864
+ init_design_tokens2();
22158
23865
  }
22159
23866
  });
22160
23867
 
@@ -41954,12 +43661,12 @@ import { createHash as createHash5 } from "node:crypto";
41954
43661
  import { spawn as spawn7 } from "node:child_process";
41955
43662
  import { fileURLToPath as fileURLToPath2 } from "node:url";
41956
43663
  import { homedir as homedir14 } from "node:os";
41957
- import { dirname as dirname16, join as join33, resolve as resolve8 } from "node:path";
43664
+ import { dirname as dirname17, join as join33, resolve as resolve8 } from "node:path";
41958
43665
  import { createInterface } from "node:readline/promises";
41959
43666
 
41960
43667
  // ../../packages/host-core/dist/control-link.js
41961
43668
  import { hostname as hostname3, homedir as homedir10 } from "node:os";
41962
- import { join as join26, basename as basename5 } from "node:path";
43669
+ import { join as join26, basename as basename6 } from "node:path";
41963
43670
  import { mkdirSync as mkdirSync9 } from "node:fs";
41964
43671
 
41965
43672
  // ../../node_modules/ws/wrapper.mjs
@@ -42011,7 +43718,7 @@ import { join as join15 } from "node:path";
42011
43718
 
42012
43719
  // ../../packages/host-core/dist/agent-backend.js
42013
43720
  async function createClaudeCodeBackend(send2, onBrowserRequest, loadPluginRuntime2) {
42014
- const { AgentManager: AgentManager2, SessionStore: SessionStore2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
43721
+ const { AgentManager: AgentManager2, SessionStore: SessionStore2, resolveSessionFile: resolveSessionFile2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
42015
43722
  const manager2 = new AgentManager2(send2, onBrowserRequest);
42016
43723
  const store = new SessionStore2();
42017
43724
  const refreshPlugins = async (projectDir) => {
@@ -42037,6 +43744,8 @@ async function createClaudeCodeBackend(send2, onBrowserRequest, loadPluginRuntim
42037
43744
  listSessions: (projectDir) => store.getSessions(projectDir),
42038
43745
  searchSessions: (query2, projectDir) => store.searchSessions(query2, projectDir),
42039
43746
  getMessages: (sessionId) => store.getSessionMessages(sessionId),
43747
+ isSessionBusy: (sessionId) => manager2.isSessionBusy(sessionId),
43748
+ resolveSessionFile: (sessionId, projectDir) => resolveSessionFile2(sessionId, projectDir),
42040
43749
  setConfig: (projectDir) => {
42041
43750
  manager2.setConfig(projectDir);
42042
43751
  void refreshPlugins(projectDir);
@@ -42437,7 +44146,7 @@ async function createBackend(engineId, send2, onBrowserRequest, resolver, loadPl
42437
44146
  }
42438
44147
 
42439
44148
  // ../../packages/host-core/dist/daemon-agent.js
42440
- init_dist2();
44149
+ init_dist4();
42441
44150
 
42442
44151
  // ../../packages/host-core/dist/plugin-tools.js
42443
44152
  import { existsSync as existsSync3 } from "node:fs";
@@ -42789,12 +44498,12 @@ async function loadPluginRuntime(opts) {
42789
44498
  }
42790
44499
  function buildDaemonPluginLoader(pluginsDir) {
42791
44500
  return async () => {
42792
- const scan = join8(pluginsDir, "node_modules");
42793
- if (!existsSync3(scan))
44501
+ const scan2 = join8(pluginsDir, "node_modules");
44502
+ if (!existsSync3(scan2))
42794
44503
  return { tools: [], hooks: [], engines: [] };
42795
44504
  writeOpenClawShim(pluginsDir);
42796
44505
  return loadPluginRuntime({
42797
- roots: [{ dir: scan, trusted: true, relaxHardlink: true }],
44506
+ roots: [{ dir: scan2, trusted: true, relaxHardlink: true }],
42798
44507
  secretResolver: (_pluginId, envKey2) => process.env[envKey2]
42799
44508
  });
42800
44509
  };
@@ -43120,477 +44829,14 @@ import { readFileSync as readFileSync7 } from "node:fs";
43120
44829
  import { join as join14 } from "node:path";
43121
44830
 
43122
44831
  // ../../packages/host-core/dist/runners/resolve.js
44832
+ init_dist2();
43123
44833
  import { readFileSync as readFileSync5, existsSync as existsSync6, statSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
43124
44834
  import { homedir as homedir5 } from "node:os";
43125
44835
  import { join as join11 } from "node:path";
43126
44836
  import { createHash as createHash2 } from "node:crypto";
43127
44837
 
43128
- // ../../packages/shared/dist/ws-protocol.js
43129
- var MIRRORED_AGENT_EVENTS = /* @__PURE__ */ new Set([
43130
- "chat:stream",
43131
- "agent:tool_use",
43132
- "agent:tool_result",
43133
- // M4 H10 — co-viewers must see tool OUTPUT, not just the call
43134
- "agent:file_edit",
43135
- "chat:complete",
43136
- "chat:error",
43137
- "agent:status",
43138
- "agent:mode_changed",
43139
- // M4 H11 — co-viewer run-mode badge must flip on plan/edit
43140
- "agent:session_state",
43141
- // M4 H11 — co-viewer spinner must clear on idle
43142
- "agent:todos",
43143
- // plan sidebar — co-viewers see the live checklist
43144
- "agent:plan_sections",
43145
- // plan review — co-viewers see the sectioned plan
43146
- "agent:narration",
43147
- // live status strip — co-viewers see "what it's doing now"
43148
- "agent:preview_ready",
43149
- // co-viewers (incl. mobile) see the preview the moment it's ready
43150
- "agent:elicitation_complete",
43151
- // M5 — co-viewers clear a resolved url-mode card
43152
- "chat:echoed",
43153
- "chat:scheduled_fired"
43154
- // cron — co-viewers see the synthetic "Scheduled" user turn
43155
- // NOT mirrored: agent:capabilities (host-local model/MCP metadata — mirroring
43156
- // would stomp a co-viewer's own picker with the driver's host); session:forked
43157
- // and agent:context_usage are driver-only correlation/host-local replies.
43158
- ]);
43159
-
43160
- // ../../packages/shared/dist/plans.js
43161
- var NO_QUOTAS = { computeHours: 0, storageGb: 0, egressGb: 0 };
43162
- var NO_FEATURES = {
43163
- sync: false,
43164
- mobile: false,
43165
- cloudWorkspace: false,
43166
- cloudServer: false,
43167
- remoteAgents: false,
43168
- voice: false,
43169
- team: false,
43170
- parallelAgents: false,
43171
- advancedBrowser: false,
43172
- hosting: false,
43173
- plugins: false,
43174
- scheduling: false,
43175
- api: false,
43176
- sso: false,
43177
- seats: 1,
43178
- maxMachines: 1
43179
- };
43180
- var PLAN_CATALOG = [
43181
- {
43182
- id: "free",
43183
- name: "Free",
43184
- monthlyUsd: 0,
43185
- tagline: "Your machine, your phone, your voice.",
43186
- features: [
43187
- "Unlimited agent usage",
43188
- "Full IDE: editor, files, agent, browser tool",
43189
- "Voice mode",
43190
- "Mobile app \u2014 reach your computer from your phone",
43191
- "Cloud workspace \u2014 your machine and recent projects in one view",
43192
- "One machine",
43193
- "Deploy to your own machine or server",
43194
- "Community support"
43195
- ],
43196
- featurePolicy: { ...NO_FEATURES, voice: true, mobile: true, cloudWorkspace: true },
43197
- quotas: { ...NO_QUOTAS }
43198
- },
43199
- {
43200
- id: "standard",
43201
- name: "Pro",
43202
- monthlyUsd: 20,
43203
- tagline: "Your workspace, everywhere.",
43204
- features: [
43205
- "Everything in Free",
43206
- "Unlimited machines \u2014 run agents on all of them",
43207
- "Tesseract cloud server \u2014 a managed always-on agent in the cloud",
43208
- "Deploy to the cloud \u2014 your app on a *.tesseract.dev URL",
43209
- "Includes ~1 always-on service + 20 GB storage + 100 GB bandwidth (overage metered)",
43210
- "Sync settings across your devices",
43211
- "Email support"
43212
- ],
43213
- featurePolicy: {
43214
- ...NO_FEATURES,
43215
- sync: true,
43216
- mobile: true,
43217
- cloudWorkspace: true,
43218
- cloudServer: true,
43219
- remoteAgents: true,
43220
- voice: true,
43221
- hosting: true,
43222
- plugins: true,
43223
- scheduling: true,
43224
- maxMachines: 0
43225
- },
43226
- // ~1 small always-on service (~720 compute-hours/mo, rounded) + 20 GB storage + 100 GB egress.
43227
- quotas: { computeHours: 750, storageGb: 20, egressGb: 100 }
43228
- },
43229
- {
43230
- id: "pro",
43231
- name: "Team",
43232
- monthlyUsd: 40,
43233
- perSeat: true,
43234
- tagline: "For teams shipping together.",
43235
- features: [
43236
- "Everything in Pro, per seat",
43237
- "Team seats + shared workspaces",
43238
- "Parallel agents",
43239
- "Advanced browser automation",
43240
- "API access",
43241
- "SSO, audit logs, centralized billing",
43242
- "Pooled cloud hosting \u2014 bigger shared quota",
43243
- "Priority support"
43244
- ],
43245
- featurePolicy: {
43246
- sync: true,
43247
- mobile: true,
43248
- cloudWorkspace: true,
43249
- cloudServer: true,
43250
- remoteAgents: true,
43251
- voice: true,
43252
- team: true,
43253
- parallelAgents: true,
43254
- advancedBrowser: true,
43255
- hosting: true,
43256
- plugins: true,
43257
- scheduling: true,
43258
- api: true,
43259
- sso: true,
43260
- seats: 2,
43261
- maxMachines: 0
43262
- },
43263
- // Pooled across the team — ~4× Pro's starter quota.
43264
- quotas: { computeHours: 3e3, storageGb: 100, egressGb: 500 }
43265
- }
43266
- ];
43267
-
43268
- // ../../packages/shared/dist/settings.js
43269
- var MODEL_OPTIONS = [
43270
- { id: "claude-opus-4-8", label: "Claude Opus 4.8" },
43271
- { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" },
43272
- { id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" }
43273
- ];
43274
-
43275
- // ../../packages/shared/dist/engines.js
43276
- var ENGINE_CATALOG = {
43277
- "claude-code": {
43278
- id: "claude-code",
43279
- label: "Claude Code",
43280
- description: "Anthropic's Claude Code \u2014 the default engine, deepest tool + browser integration.",
43281
- cliBinary: "claude",
43282
- // Claude's token is injected via CLAUDE_CODE_OAUTH_TOKEN, so oauth needs no auth file.
43283
- supportedModes: ["oauth", "apiKey", "localCli"],
43284
- apiKeyEnv: "ANTHROPIC_API_KEY",
43285
- models: MODEL_OPTIONS,
43286
- capabilities: { permissionGating: true, browserControl: true, liveRunMode: true, resume: true, fork: true, contextUsage: true, scheduling: true },
43287
- homepageUrl: "https://docs.claude.com/en/docs/claude-code",
43288
- installCommand: "npm install -g @anthropic-ai/claude-code",
43289
- installHint: "Bundled with the app; install the standalone CLI for local-instance mode."
43290
- },
43291
- "openai-codex": {
43292
- id: "openai-codex",
43293
- label: "OpenAI Codex",
43294
- description: "OpenAI's Codex CLI. Sign in with ChatGPT or use an API key.",
43295
- cliBinary: "codex",
43296
- supportedModes: ["oauth", "apiKey", "localCli"],
43297
- apiKeyEnv: "OPENAI_API_KEY",
43298
- authFileRel: "auth.json",
43299
- // under $CODEX_HOME
43300
- models: [
43301
- { id: "gpt-5.5-codex", label: "GPT-5.5 Codex" },
43302
- { id: "gpt-5.5", label: "GPT-5.5" }
43303
- ],
43304
- capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: true },
43305
- homepageUrl: "https://developers.openai.com/codex/cli",
43306
- installCommand: "npm install -g @openai/codex",
43307
- installHint: "npm i -g @openai/codex (or brew install codex)"
43308
- },
43309
- opencode: {
43310
- id: "opencode",
43311
- label: "OpenCode",
43312
- description: "Open-source agent over 75+ providers. Log in per provider.",
43313
- cliBinary: "opencode",
43314
- supportedModes: ["oauth", "apiKey", "localCli"],
43315
- // OpenCode reads provider keys from env / its own auth.json; no single apiKeyEnv.
43316
- authFileRel: "auth.json",
43317
- // under ~/.local/share/opencode
43318
- models: [],
43319
- // provider+model is configured inside OpenCode; "" ⇒ its default
43320
- capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: true },
43321
- homepageUrl: "https://opencode.ai",
43322
- installCommand: "npm install -g opencode-ai",
43323
- installHint: "npm i -g opencode-ai (see opencode.ai/docs)"
43324
- },
43325
- "gemini-cli": {
43326
- id: "gemini-cli",
43327
- label: "Gemini CLI",
43328
- description: "Google's Gemini CLI. Sign in with Google or use a Gemini API key.",
43329
- cliBinary: "gemini",
43330
- supportedModes: ["oauth", "apiKey", "localCli"],
43331
- apiKeyEnv: "GEMINI_API_KEY",
43332
- models: [
43333
- { id: "gemini-3.1-pro", label: "Gemini 3.1 Pro" },
43334
- { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }
43335
- ],
43336
- capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: false },
43337
- homepageUrl: "https://github.com/google-gemini/gemini-cli",
43338
- installCommand: "npm install -g @google/gemini-cli",
43339
- installHint: "npm i -g @google/gemini-cli"
43340
- },
43341
- openclaw: {
43342
- id: "openclaw",
43343
- label: "OpenClaw",
43344
- description: "OpenClaw runtime \u2014 runs your installed channels, model providers, and plugins natively.",
43345
- cliBinary: "openclaw",
43346
- // OpenClaw manages its own provider auth (`openclaw onboard` / openclaw.json), so the
43347
- // only mode is "use the installed, already-onboarded CLI" — like OpenCode.
43348
- supportedModes: ["localCli"],
43349
- models: [],
43350
- // provider+model is configured inside OpenClaw; '' ⇒ its default
43351
- capabilities: { permissionGating: false, browserControl: false, liveRunMode: false, resume: false },
43352
- homepageUrl: "https://docs.openclaw.ai",
43353
- installCommand: "npm install -g openclaw",
43354
- installHint: "npm i -g openclaw, then run `openclaw onboard` (see docs.openclaw.ai)"
43355
- }
43356
- };
43357
- var ENGINE_IDS = Object.keys(ENGINE_CATALOG);
43358
- function engineById(id) {
43359
- return ENGINE_CATALOG[id];
43360
- }
43361
-
43362
- // ../../packages/shared/dist/providers.js
43363
- var PROVIDER_CATALOG = {
43364
- anthropic: {
43365
- id: "anthropic",
43366
- label: "Anthropic",
43367
- description: "Claude models, direct from Anthropic. The native backend for Claude Code.",
43368
- baseUrl: "https://api.anthropic.com",
43369
- api: "anthropic-messages",
43370
- claudeNative: true,
43371
- authEnvVars: ["ANTHROPIC_API_KEY"],
43372
- authModes: ["oauth", "apiKey"],
43373
- models: [
43374
- { id: "claude-opus-4-8", label: "Claude Opus 4.8", role: "main" },
43375
- { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", role: "main" },
43376
- { id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", role: "fast" }
43377
- ],
43378
- homepageUrl: "https://docs.claude.com/en/docs/about-claude/models"
43379
- },
43380
- openai: {
43381
- id: "openai",
43382
- label: "OpenAI",
43383
- description: "OpenAI models. The native backend for the Codex engine.",
43384
- baseUrl: "https://api.openai.com/v1",
43385
- api: "openai-completions",
43386
- claudeNative: false,
43387
- authEnvVars: ["OPENAI_API_KEY"],
43388
- authModes: ["oauth", "apiKey"],
43389
- models: [
43390
- { id: "gpt-5.5-codex", label: "GPT-5.5 Codex", role: "main" },
43391
- { id: "gpt-5.5", label: "GPT-5.5", role: "main" }
43392
- ],
43393
- homepageUrl: "https://platform.openai.com/docs/models"
43394
- },
43395
- google: {
43396
- id: "google",
43397
- label: "Google Gemini",
43398
- description: "Gemini models. The native backend for the Gemini engine.",
43399
- baseUrl: "https://generativelanguage.googleapis.com",
43400
- api: "gemini",
43401
- claudeNative: false,
43402
- authEnvVars: ["GEMINI_API_KEY"],
43403
- authModes: ["oauth", "apiKey"],
43404
- models: [
43405
- { id: "gemini-3.1-pro", label: "Gemini 3.1 Pro", role: "main" },
43406
- { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash", role: "fast" }
43407
- ],
43408
- homepageUrl: "https://ai.google.dev/gemini-api/docs/models"
43409
- },
43410
- openrouter: {
43411
- id: "openrouter",
43412
- label: "OpenRouter",
43413
- description: "One key, hundreds of models. Exposes an Anthropic-compatible route \u2014 no proxy needed for Claude Code.",
43414
- // OpenAI-style base; the Anthropic-compatible base is `…/api` (no `/v1`).
43415
- baseUrl: "https://openrouter.ai/api/v1",
43416
- anthropicBaseUrl: "https://openrouter.ai/api",
43417
- api: "openai-completions",
43418
- claudeNative: true,
43419
- authEnvVars: ["OPENROUTER_API_KEY"],
43420
- headers: {
43421
- "HTTP-Referer": "https://app.tesseract.dev",
43422
- "X-Title": "Tesseract"
43423
- },
43424
- authModes: ["apiKey"],
43425
- // Any OpenRouter slug is valid; these are stable starters (free entry in UI).
43426
- models: [
43427
- { id: "deepseek/deepseek-chat", label: "DeepSeek Chat", role: "fast" },
43428
- { id: "deepseek/deepseek-r1", label: "DeepSeek R1", role: "main" },
43429
- { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash", role: "fast" },
43430
- { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro", role: "main" }
43431
- ],
43432
- homepageUrl: "https://openrouter.ai/docs"
43433
- },
43434
- ollama: {
43435
- id: "ollama",
43436
- label: "Ollama (local)",
43437
- description: "Run open models locally. No API key. Models are discovered from your running Ollama.",
43438
- baseUrl: "http://127.0.0.1:11434",
43439
- api: "ollama",
43440
- claudeNative: false,
43441
- authEnvVars: [],
43442
- authModes: ["apiKey"],
43443
- // optional bearer for remote Ollama; usually none
43444
- models: [],
43445
- dynamicModels: true,
43446
- homepageUrl: "https://ollama.com",
43447
- installCommand: "curl -fsSL https://ollama.com/install.sh | sh"
43448
- },
43449
- deepseek: {
43450
- id: "deepseek",
43451
- label: "DeepSeek",
43452
- description: "DeepSeek Chat + Reasoner. Cheap and capable. Reached via the proxy for Claude Code.",
43453
- baseUrl: "https://api.deepseek.com",
43454
- api: "openai-completions",
43455
- claudeNative: false,
43456
- authEnvVars: ["DEEPSEEK_API_KEY"],
43457
- authModes: ["apiKey"],
43458
- models: [
43459
- { id: "deepseek-chat", label: "DeepSeek Chat", role: "fast" },
43460
- { id: "deepseek-reasoner", label: "DeepSeek Reasoner", role: "main" }
43461
- ],
43462
- homepageUrl: "https://api-docs.deepseek.com"
43463
- },
43464
- moonshot: {
43465
- id: "moonshot",
43466
- label: "Kimi (Moonshot)",
43467
- description: "Kimi K2 models. Use the coding endpoint (Anthropic-compatible, no proxy) or the OpenAI endpoint.",
43468
- // Default to the OpenAI-style endpoint; the per-credential `baseUrl` can switch
43469
- // to the Anthropic-compatible coding endpoint below.
43470
- baseUrl: "https://api.moonshot.ai/v1",
43471
- anthropicBaseUrl: "https://api.kimi.com/coding/",
43472
- api: "openai-completions",
43473
- claudeNative: true,
43474
- authEnvVars: ["MOONSHOT_API_KEY", "KIMI_API_KEY"],
43475
- authModes: ["apiKey"],
43476
- models: [
43477
- { id: "kimi-code", label: "Kimi Code (coding endpoint)", role: "main" },
43478
- { id: "kimi-k2.5", label: "Kimi K2.5", role: "main" },
43479
- { id: "kimi-k2-thinking", label: "Kimi K2 Thinking", role: "main" }
43480
- ],
43481
- homepageUrl: "https://platform.moonshot.ai/docs"
43482
- },
43483
- "custom-openai": {
43484
- id: "custom-openai",
43485
- label: "Custom (OpenAI-compatible)",
43486
- description: "Any OpenAI-compatible endpoint (LM Studio, llama.cpp, vLLM, a private gateway). Set the base URL per key.",
43487
- baseUrl: "",
43488
- api: "openai-completions",
43489
- claudeNative: false,
43490
- authEnvVars: ["OPENAI_API_KEY"],
43491
- authModes: ["apiKey"],
43492
- models: [],
43493
- homepageUrl: "https://platform.openai.com/docs/api-reference"
43494
- },
43495
- litellm: {
43496
- id: "litellm",
43497
- label: "LiteLLM Proxy",
43498
- description: "Your LiteLLM proxy fronting 100+ providers. Point it at the anthropic route for direct Claude Code use.",
43499
- baseUrl: "",
43500
- anthropicBaseUrl: "",
43501
- api: "openai-completions",
43502
- // Configurable: LiteLLM can expose an Anthropic-shaped route. Treated as
43503
- // claudeNative so users can point Claude Code straight at it.
43504
- claudeNative: true,
43505
- authEnvVars: ["LITELLM_API_KEY"],
43506
- authModes: ["apiKey"],
43507
- models: [],
43508
- homepageUrl: "https://docs.litellm.ai/docs/simple_proxy"
43509
- }
43510
- };
43511
- var PROVIDER_IDS = Object.keys(PROVIDER_CATALOG);
43512
- var NATIVE_PROVIDER_IDS = ["anthropic", "openai", "google"];
43513
- function providerById(id) {
43514
- return PROVIDER_CATALOG[id];
43515
- }
43516
-
43517
- // ../../packages/shared/dist/runtimes.js
43518
- var RUNTIME_CATALOG = [
43519
- ...ENGINE_IDS.map((id) => ({
43520
- id,
43521
- label: ENGINE_CATALOG[id].label,
43522
- cliBinary: ENGINE_CATALOG[id].cliBinary,
43523
- installCommand: ENGINE_CATALOG[id].installCommand,
43524
- kind: "engine"
43525
- })),
43526
- { id: "ollama", label: "Ollama", cliBinary: "ollama", installCommand: "curl -fsSL https://ollama.com/install.sh | sh", kind: "tool" },
43527
- { id: "ccr", label: "Claude Code Router", cliBinary: "ccr", installCommand: "npm install -g @musistudio/claude-code-router", kind: "tool" }
43528
- ];
43529
- var RUNTIME_IDS = RUNTIME_CATALOG.map((r) => r.id);
43530
-
43531
- // ../../packages/shared/dist/rotation.js
43532
- var COOLDOWN_BASE_MS = 6e4;
43533
- var COOLDOWN_MAX_MS = 36e5;
43534
- function refreshCredentials(creds, now) {
43535
- return creds.map((c) => {
43536
- if (c.status === "cooldown" && (c.cooldownUntil == null || c.cooldownUntil <= now)) {
43537
- return { ...c, status: "active", cooldownUntil: void 0 };
43538
- }
43539
- if (c.status === "active" && c.expiresAt != null && c.expiresAt <= now) {
43540
- return { ...c, status: "expired" };
43541
- }
43542
- return c;
43543
- });
43544
- }
43545
- function selectRotatable(items, now, isUsable = () => true) {
43546
- const usable = refreshCredentials(items, now).filter((c) => c.status === "active" && (c.expiresAt == null || c.expiresAt > now) && isUsable(c));
43547
- if (usable.length === 0)
43548
- return void 0;
43549
- return usable.sort((a, b) => a.priority - b.priority || (a.lastUsedAt ?? 0) - (b.lastUsedAt ?? 0))[0];
43550
- }
43551
- function classifyError(raw) {
43552
- const s = raw.toLowerCase();
43553
- if (/\b429\b|rate[ _-]?limit|too many requests/.test(s))
43554
- return "rate_limit";
43555
- if (/quota|insufficient[_ ]?quota|credit|billing|payment required|\b402\b|usage limit|exceeded your/.test(s))
43556
- return "quota_exceeded";
43557
- if (/expired|token (?:has )?expired|refresh|re-?authenticate|session expired/.test(s))
43558
- return "auth_expired";
43559
- if (/\b401\b|\b403\b|invalid (?:api )?key|unauthorized|invalid token|authentication/.test(s))
43560
- return "invalid_key";
43561
- if (/\beai_again\b|\benotfound\b|getaddrinfo|network is unreachable|\benetunreach\b|\benetdown\b|offline|no address associated|dns/.test(s))
43562
- return "network_down";
43563
- if (/\beconnreset\b|\beconnrefused\b|\betimedout\b|\bepipe\b|socket hang ?up|connection (?:closed|reset|error|aborted)|\b50[0234]\b|\b529\b|overloaded|service unavailable|bad gateway|gateway time-?out|temporarily unavailable/.test(s))
43564
- return "transient";
43565
- return "unknown";
43566
- }
43567
- function recordFailure(creds, id, errorCode, now, opts) {
43568
- if (errorCode === "unknown" || errorCode === "transient" || errorCode === "network_down") {
43569
- return { next: creds, advanced: false };
43570
- }
43571
- let advanced = false;
43572
- const next = creds.map((c) => {
43573
- if (c.id !== id)
43574
- return c;
43575
- advanced = true;
43576
- const consecutiveFailures = (c.consecutiveFailures ?? 0) + 1;
43577
- if (errorCode === "auth_expired") {
43578
- return { ...c, status: "expired", lastErrorCode: errorCode, consecutiveFailures };
43579
- }
43580
- if (errorCode === "invalid_key") {
43581
- return { ...c, status: "revoked", lastErrorCode: errorCode, consecutiveFailures };
43582
- }
43583
- const backoff = Math.min(COOLDOWN_BASE_MS * 2 ** (consecutiveFailures - 1), COOLDOWN_MAX_MS);
43584
- const cooldownUntil = opts?.cooldownUntil ?? now + backoff;
43585
- return { ...c, status: "cooldown", cooldownUntil, lastErrorCode: errorCode, consecutiveFailures };
43586
- });
43587
- return { next, advanced };
43588
- }
43589
- function recordSuccess(creds, id, now) {
43590
- return creds.map((c) => c.id === id ? { ...c, status: "active", cooldownUntil: void 0, consecutiveFailures: 0, lastUsedAt: now, lastErrorCode: void 0 } : c);
43591
- }
43592
-
43593
44838
  // ../../packages/host-core/dist/runners/proxy-router.js
44839
+ init_dist2();
43594
44840
  import { spawn as spawn3, execFile as execFile2, execSync as execSync2 } from "node:child_process";
43595
44841
  import { createRequire as createRequire2 } from "node:module";
43596
44842
  import { randomUUID as randomUUID4, createHash } from "node:crypto";
@@ -43870,6 +45116,7 @@ function resolveOverrideEngineEnv() {
43870
45116
  }
43871
45117
 
43872
45118
  // ../../packages/host-core/dist/runners/pool.js
45119
+ init_dist2();
43873
45120
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync7, statSync as statSync2, mkdirSync as mkdirSync5, chmodSync as chmodSync2, renameSync as renameSync4 } from "node:fs";
43874
45121
  import { join as join12 } from "node:path";
43875
45122
  import { randomUUID as randomUUID5 } from "node:crypto";
@@ -44055,6 +45302,7 @@ function setActiveConfig(id) {
44055
45302
  }
44056
45303
 
44057
45304
  // ../../packages/host-core/dist/daemon-engine-spawn.js
45305
+ init_dist2();
44058
45306
  import { execFileSync } from "node:child_process";
44059
45307
  import { homedir as homedir6 } from "node:os";
44060
45308
  import { join as join13 } from "node:path";
@@ -44788,6 +46036,123 @@ function unwatchAllRemote() {
44788
46036
  remoteWatches.clear();
44789
46037
  }
44790
46038
 
46039
+ // ../../packages/host-core/dist/session-watch.js
46040
+ import { watch as watch2 } from "node:fs";
46041
+ import { dirname as dirname7, basename as basename3 } from "node:path";
46042
+ var DEBOUNCE_MS = 120;
46043
+ var BUSY_GRACE_MS = 2e3;
46044
+ var watches = /* @__PURE__ */ new Map();
46045
+ var sessionToFile = /* @__PURE__ */ new Map();
46046
+ async function watchSession(sessionId, key2, projectDir, deps) {
46047
+ let filePath = sessionToFile.get(sessionId);
46048
+ if (!filePath) {
46049
+ const resolved = await deps.resolveFile?.(sessionId, projectDir);
46050
+ if (!resolved)
46051
+ return;
46052
+ filePath = resolved;
46053
+ sessionToFile.set(sessionId, filePath);
46054
+ }
46055
+ const baseline = await deps.getMessages(sessionId).then((m) => m.length).catch(() => 0);
46056
+ const existing = watches.get(filePath);
46057
+ if (existing) {
46058
+ existing.listeners.set(key2, { emittedCount: baseline, deps });
46059
+ return;
46060
+ }
46061
+ const fileName = basename3(filePath);
46062
+ const fw = {
46063
+ watcher: void 0,
46064
+ sessionId,
46065
+ listeners: /* @__PURE__ */ new Map([[key2, { emittedCount: baseline, deps }]]),
46066
+ timer: null,
46067
+ lastBusyAt: 0
46068
+ };
46069
+ try {
46070
+ fw.watcher = watch2(dirname7(filePath), (_event, changed) => {
46071
+ if (changed && basename3(String(changed)) !== fileName)
46072
+ return;
46073
+ scheduleScan(filePath);
46074
+ });
46075
+ } catch {
46076
+ return;
46077
+ }
46078
+ watches.set(filePath, fw);
46079
+ }
46080
+ function unwatchSession(sessionId, key2) {
46081
+ const filePath = sessionToFile.get(sessionId);
46082
+ if (!filePath)
46083
+ return;
46084
+ const fw = watches.get(filePath);
46085
+ if (!fw)
46086
+ return;
46087
+ fw.listeners.delete(key2);
46088
+ if (fw.listeners.size === 0)
46089
+ closeWatch(filePath);
46090
+ }
46091
+ function unwatchSessionClient(key2) {
46092
+ for (const [filePath, fw] of [...watches]) {
46093
+ if (fw.listeners.delete(key2) && fw.listeners.size === 0)
46094
+ closeWatch(filePath);
46095
+ }
46096
+ }
46097
+ function unwatchAllSessions() {
46098
+ for (const [filePath] of [...watches])
46099
+ closeWatch(filePath);
46100
+ }
46101
+ function closeWatch(filePath) {
46102
+ const fw = watches.get(filePath);
46103
+ if (!fw)
46104
+ return;
46105
+ if (fw.timer)
46106
+ clearTimeout(fw.timer);
46107
+ try {
46108
+ fw.watcher.close();
46109
+ } catch {
46110
+ }
46111
+ watches.delete(filePath);
46112
+ sessionToFile.delete(fw.sessionId);
46113
+ }
46114
+ function scheduleScan(filePath) {
46115
+ const fw = watches.get(filePath);
46116
+ if (!fw)
46117
+ return;
46118
+ if (fw.timer)
46119
+ clearTimeout(fw.timer);
46120
+ fw.timer = setTimeout(() => {
46121
+ fw.timer = null;
46122
+ void scan(filePath);
46123
+ }, DEBOUNCE_MS);
46124
+ }
46125
+ async function scan(filePath) {
46126
+ const fw = watches.get(filePath);
46127
+ if (!fw)
46128
+ return;
46129
+ const { sessionId } = fw;
46130
+ const any2 = fw.listeners.values().next().value;
46131
+ if (!any2)
46132
+ return;
46133
+ const busy = any2.deps.isSessionBusy?.(sessionId) === true;
46134
+ const now = Date.now();
46135
+ if (busy)
46136
+ fw.lastBusyAt = now;
46137
+ const inGrace = busy || now - fw.lastBusyAt < BUSY_GRACE_MS;
46138
+ const messages = await any2.deps.getMessages(sessionId).catch(() => null);
46139
+ if (!messages)
46140
+ return;
46141
+ const len = messages.length;
46142
+ for (const [key2, listener] of fw.listeners) {
46143
+ if (inGrace) {
46144
+ listener.emittedCount = len;
46145
+ continue;
46146
+ }
46147
+ if (len < listener.emittedCount) {
46148
+ listener.deps.emit(key2, { type: "session:messages", sessionId, messages });
46149
+ } else if (len > listener.emittedCount) {
46150
+ listener.deps.emit(key2, { type: "session:appended", sessionId, messages: messages.slice(listener.emittedCount) });
46151
+ }
46152
+ listener.emittedCount = len;
46153
+ }
46154
+ }
46155
+
44791
46156
  // ../../packages/host-core/dist/fs-datachannel-host.js
44792
46157
  var SCTP_BUF = 16 * 1024 * 1024;
44793
46158
  var ndcPromise = null;
@@ -45000,7 +46365,7 @@ function dynamicMetrics() {
45000
46365
  // ../../packages/host-core/dist/fs-transfer.js
45001
46366
  import { readdir as readdir3, lstat, mkdir as mkdir5, chmod, rm as rm2, readlink, symlink, stat as stat3 } from "node:fs/promises";
45002
46367
  import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, existsSync as existsSync9, createWriteStream } from "node:fs";
45003
- import { dirname as dirname7, join as join18, relative as relative5, sep as sep5 } from "node:path";
46368
+ import { dirname as dirname8, join as join18, relative as relative5, sep as sep5 } from "node:path";
45004
46369
 
45005
46370
  // ../../packages/host-core/dist/active-link/paths.js
45006
46371
  import { homedir as homedir7 } from "node:os";
@@ -45347,9 +46712,9 @@ async function writeInboundChunk(msg, send2) {
45347
46712
  try {
45348
46713
  if (msg.kind === "symlink") {
45349
46714
  const target = Buffer.from(msg.base64, "base64").toString("utf-8");
45350
- const resolved = join18(dirname7(abs), target);
46715
+ const resolved = join18(dirname8(abs), target);
45351
46716
  if (isInsideRoot(resolved, s.destRoot)) {
45352
- await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
46717
+ await mkdir5(dirname8(abs), { recursive: true }).catch(() => {
45353
46718
  });
45354
46719
  await symlink(target, abs).catch(() => {
45355
46720
  });
@@ -45362,7 +46727,7 @@ async function writeInboundChunk(msg, send2) {
45362
46727
  if (s.curIx !== msg.fileIx || !s.curStream) {
45363
46728
  if (s.curStream)
45364
46729
  await new Promise((r) => s.curStream.end(r));
45365
- await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
46730
+ await mkdir5(dirname8(abs), { recursive: true }).catch(() => {
45366
46731
  });
45367
46732
  s.curStream = createWriteStream(abs);
45368
46733
  s.curIx = msg.fileIx;
@@ -45433,7 +46798,7 @@ var import_selfsigned = __toESM(require_selfsigned(), 1);
45433
46798
  import tls from "node:tls";
45434
46799
  import { X509Certificate } from "node:crypto";
45435
46800
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync10, mkdirSync as mkdirSync6 } from "node:fs";
45436
- import { dirname as dirname8 } from "node:path";
46801
+ import { dirname as dirname9 } from "node:path";
45437
46802
  function fingerprintOf(certPem) {
45438
46803
  return new X509Certificate(certPem).fingerprint256;
45439
46804
  }
@@ -45446,7 +46811,7 @@ async function loadOrCreateIdentity(certPath, keyPath) {
45446
46811
  const tenYears = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1e3);
45447
46812
  const pems = await (0, import_selfsigned.generate)([{ name: "commonName", value: "tesseract-peer" }], { keySize: 2048, notAfterDate: tenYears, algorithm: "sha256" });
45448
46813
  try {
45449
- mkdirSync6(dirname8(certPath), { recursive: true });
46814
+ mkdirSync6(dirname9(certPath), { recursive: true });
45450
46815
  } catch {
45451
46816
  }
45452
46817
  try {
@@ -45952,13 +47317,13 @@ async function openPeerLink(peerHostId, ctx) {
45952
47317
  // ../../packages/host-core/dist/active-link/engine.js
45953
47318
  import { lstat as lstat6, readlink as readlink4, rm as rm3, mkdir as mkdir7, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile5 } from "node:fs/promises";
45954
47319
  import { existsSync as existsSync12 } from "node:fs";
45955
- import { dirname as dirname12, join as join24, resolve as resolve7 } from "node:path";
47320
+ import { dirname as dirname13, join as join24, resolve as resolve7 } from "node:path";
45956
47321
 
45957
47322
  // ../../packages/host-core/dist/active-link/blocks.js
45958
47323
  import { createHash as createHash3 } from "node:crypto";
45959
47324
  import { createReadStream } from "node:fs";
45960
47325
  import { open, mkdir as mkdir6, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
45961
- import { dirname as dirname9 } from "node:path";
47326
+ import { dirname as dirname10 } from "node:path";
45962
47327
  var CHUNK3 = 1024 * 1024;
45963
47328
  var MAX_INFLIGHT2 = 8 * CHUNK3;
45964
47329
  var IDLE_MS2 = 6e4;
@@ -46086,7 +47451,7 @@ var StagingWriter = class {
46086
47451
  }
46087
47452
  async ensureOpen() {
46088
47453
  if (!this.fh) {
46089
- await mkdir6(dirname9(this.stagingPath), { recursive: true });
47454
+ await mkdir6(dirname10(this.stagingPath), { recursive: true });
46090
47455
  this.fh = await open(this.stagingPath, "w");
46091
47456
  }
46092
47457
  return this.fh;
@@ -46116,7 +47481,7 @@ var StagingWriter = class {
46116
47481
  });
46117
47482
  await fh.close();
46118
47483
  this.fh = null;
46119
- await mkdir6(dirname9(dest), { recursive: true });
47484
+ await mkdir6(dirname10(dest), { recursive: true });
46120
47485
  await chmod2(this.stagingPath, mode & 511).catch(() => {
46121
47486
  });
46122
47487
  const secs = mtimeMs / 1e3;
@@ -46149,7 +47514,7 @@ var BlockAssembler = class {
46149
47514
  this.stagingPath = stagingPath;
46150
47515
  }
46151
47516
  async open() {
46152
- await mkdir6(dirname9(this.stagingPath), { recursive: true });
47517
+ await mkdir6(dirname10(this.stagingPath), { recursive: true });
46153
47518
  this.fh = await open(this.stagingPath, "w");
46154
47519
  }
46155
47520
  /** Write a received block at its byte offset (index * CHUNK). */
@@ -46193,7 +47558,7 @@ var BlockAssembler = class {
46193
47558
  });
46194
47559
  return false;
46195
47560
  }
46196
- await mkdir6(dirname9(dest), { recursive: true });
47561
+ await mkdir6(dirname10(dest), { recursive: true });
46197
47562
  await chmod2(this.stagingPath, mode & 511).catch(() => {
46198
47563
  });
46199
47564
  const secs = mtimeMs / 1e3;
@@ -46771,10 +48136,10 @@ var ReaddirpStream = class extends Readable {
46771
48136
  }
46772
48137
  async _formatEntry(dirent, path5) {
46773
48138
  let entry;
46774
- const basename6 = this._isDirent ? dirent.name : dirent;
48139
+ const basename7 = this._isDirent ? dirent.name : dirent;
46775
48140
  try {
46776
- const fullPath = presolve(pjoin(path5, basename6));
46777
- entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
48141
+ const fullPath = presolve(pjoin(path5, basename7));
48142
+ entry = { path: prelative(this._root, fullPath), fullPath, basename: basename7 };
46778
48143
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
46779
48144
  } catch (err) {
46780
48145
  this._onError(err);
@@ -47313,9 +48678,9 @@ var NodeFsHandler = class {
47313
48678
  _watchWithNodeFs(path5, listener) {
47314
48679
  const opts = this.fsw.options;
47315
48680
  const directory = sysPath.dirname(path5);
47316
- const basename6 = sysPath.basename(path5);
48681
+ const basename7 = sysPath.basename(path5);
47317
48682
  const parent = this.fsw._getWatchedDir(directory);
47318
- parent.add(basename6);
48683
+ parent.add(basename7);
47319
48684
  const absolutePath = sysPath.resolve(path5);
47320
48685
  const options = {
47321
48686
  persistent: opts.persistent
@@ -47325,7 +48690,7 @@ var NodeFsHandler = class {
47325
48690
  let closer;
47326
48691
  if (opts.usePolling) {
47327
48692
  const enableBin = opts.interval !== opts.binaryInterval;
47328
- options.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
48693
+ options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
47329
48694
  closer = setFsWatchFileListener(path5, absolutePath, options, {
47330
48695
  listener,
47331
48696
  rawEmitter: this.fsw._emitRaw
@@ -47347,11 +48712,11 @@ var NodeFsHandler = class {
47347
48712
  if (this.fsw.closed) {
47348
48713
  return;
47349
48714
  }
47350
- const dirname17 = sysPath.dirname(file2);
47351
- const basename6 = sysPath.basename(file2);
47352
- const parent = this.fsw._getWatchedDir(dirname17);
48715
+ const dirname18 = sysPath.dirname(file2);
48716
+ const basename7 = sysPath.basename(file2);
48717
+ const parent = this.fsw._getWatchedDir(dirname18);
47353
48718
  let prevStats = stats;
47354
- if (parent.has(basename6))
48719
+ if (parent.has(basename7))
47355
48720
  return;
47356
48721
  const listener = async (path5, newStats) => {
47357
48722
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
@@ -47376,9 +48741,9 @@ var NodeFsHandler = class {
47376
48741
  prevStats = newStats2;
47377
48742
  }
47378
48743
  } catch (error51) {
47379
- this.fsw._remove(dirname17, basename6);
48744
+ this.fsw._remove(dirname18, basename7);
47380
48745
  }
47381
- } else if (parent.has(basename6)) {
48746
+ } else if (parent.has(basename7)) {
47382
48747
  const at = newStats.atimeMs;
47383
48748
  const mt = newStats.mtimeMs;
47384
48749
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -48302,7 +49667,7 @@ var FSWatcher = class extends EventEmitter2 {
48302
49667
  return stream;
48303
49668
  }
48304
49669
  };
48305
- function watch2(paths, options = {}) {
49670
+ function watch3(paths, options = {}) {
48306
49671
  const watcher = new FSWatcher(options);
48307
49672
  watcher.add(paths);
48308
49673
  return watcher;
@@ -48320,7 +49685,7 @@ var LinkWatcher = class {
48320
49685
  this.debounceMs = opts.debounceMs ?? 500;
48321
49686
  }
48322
49687
  async start() {
48323
- this.fsw = watch2(this.opts.root, {
49688
+ this.fsw = watch3(this.opts.root, {
48324
49689
  ignoreInitial: true,
48325
49690
  // the engine does its own hashing scan on start
48326
49691
  followSymlinks: false,
@@ -48819,13 +50184,13 @@ var ActiveLinkEngine = class {
48819
50184
  * file so the path still exists — recorded as a FILE matching disk so the local
48820
50185
  * watcher doesn't churn. The target is containment-checked, never dereferenced. */
48821
50186
  async applySymlink(rel, dest, target, mtimeMs, mode) {
48822
- const resolved = resolve7(dirname12(dest), target);
50187
+ const resolved = resolve7(dirname13(dest), target);
48823
50188
  if (!isInsideRoot(resolved, this.opts.localRoot))
48824
50189
  return;
48825
50190
  const hash2 = hashString(target);
48826
50191
  const secs = mtimeMs / 1e3;
48827
50192
  try {
48828
- await mkdir7(dirname12(dest), { recursive: true });
50193
+ await mkdir7(dirname13(dest), { recursive: true });
48829
50194
  await rm3(dest, { force: true, recursive: true });
48830
50195
  try {
48831
50196
  await symlink2(target, dest);
@@ -48875,7 +50240,7 @@ var ActiveLinkEngine = class {
48875
50240
  return;
48876
50241
  if (fromRec && fromRec.kind === "file") {
48877
50242
  try {
48878
- await mkdir7(dirname12(toAbs), { recursive: true });
50243
+ await mkdir7(dirname13(toAbs), { recursive: true });
48879
50244
  await rename2(fromAbs, toAbs);
48880
50245
  const secs = mtimeMs / 1e3;
48881
50246
  await utimes2(toAbs, secs, secs).catch(() => {
@@ -49075,7 +50440,7 @@ var ActiveLinkEngine = class {
49075
50440
  };
49076
50441
 
49077
50442
  // ../../packages/host-core/dist/active-link/config.js
49078
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch3 } from "node:fs";
50443
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch4 } from "node:fs";
49079
50444
  import { join as join25 } from "node:path";
49080
50445
  function configPath2() {
49081
50446
  return join25(activeLinkRoot(), "links.json");
@@ -49149,7 +50514,7 @@ function watchLinkConfigs(onChange) {
49149
50514
  let timer = null;
49150
50515
  let watcher = null;
49151
50516
  try {
49152
- watcher = watch3(dir, (_evt, file2) => {
50517
+ watcher = watch4(dir, (_evt, file2) => {
49153
50518
  if (file2 && file2 !== "links.json")
49154
50519
  return;
49155
50520
  if (timer)
@@ -49287,7 +50652,7 @@ function routeInboundLinkFrame(frame) {
49287
50652
  }
49288
50653
 
49289
50654
  // ../../packages/host-core/dist/control-link.js
49290
- init_dist2();
50655
+ init_dist4();
49291
50656
 
49292
50657
  // ../../packages/host-core/dist/pty-manager.js
49293
50658
  import { existsSync as existsSync14 } from "node:fs";
@@ -49531,6 +50896,7 @@ function clampDim(v, dflt) {
49531
50896
  }
49532
50897
 
49533
50898
  // ../../packages/host-core/dist/control-link.js
50899
+ init_dist2();
49534
50900
  var SERVER_HOST_ID = "server";
49535
50901
  var cfg = null;
49536
50902
  var deviceId = "";
@@ -49804,7 +51170,7 @@ function sendActiveLinkProvision(cfg2) {
49804
51170
  type: "provision",
49805
51171
  linkId: cfg2.linkId,
49806
51172
  fromHost: ownHostId(),
49807
- projectName: cfg2.remoteSubfolder ?? basename5(cfg2.localRoot),
51173
+ projectName: cfg2.remoteSubfolder ?? basename6(cfg2.localRoot),
49808
51174
  ...cfg2.remoteParent ? { remoteParent: cfg2.remoteParent } : {},
49809
51175
  ...cfg2.remoteSubfolder ? { remoteSubfolder: cfg2.remoteSubfolder } : {},
49810
51176
  ...cfg2.workspaceLinkId ? { workspaceLinkId: cfg2.workspaceLinkId } : {}
@@ -50011,6 +51377,20 @@ async function handleInboundAgent(msg, driverClientId) {
50011
51377
  send("agent", { type: "session:messages", sessionId: msg.sessionId, messages }, route2);
50012
51378
  break;
50013
51379
  }
51380
+ case "session:watch":
51381
+ if (driverClientId) {
51382
+ void watchSession(msg.sessionId, driverClientId, msg.projectDir, {
51383
+ getMessages: (sid) => b.getMessages(sid),
51384
+ isSessionBusy: (sid) => b.isSessionBusy?.(sid) ?? false,
51385
+ resolveFile: (sid, dir) => b.resolveSessionFile?.(sid, dir) ?? Promise.resolve(null),
51386
+ emit: (key2, m) => send("agent", m, { clientId: key2 })
51387
+ });
51388
+ }
51389
+ break;
51390
+ case "session:unwatch":
51391
+ if (driverClientId)
51392
+ unwatchSession(msg.sessionId, driverClientId);
51393
+ break;
50014
51394
  case "session:fork": {
50015
51395
  const newId = await b.forkSession?.(msg.sessionId, { projectDir: msg.projectDir, upToMessageId: msg.upToMessageId, title: msg.title }).catch(() => null);
50016
51396
  if (newId)
@@ -50133,6 +51513,7 @@ async function serveInboundTerm(p, driverClientId) {
50133
51513
  }
50134
51514
  function releaseDriver(clientId) {
50135
51515
  unwatchRemoteClient(clientId);
51516
+ unwatchSessionClient(clientId);
50136
51517
  releaseClientPtys(clientId);
50137
51518
  releaseDcClient(clientId);
50138
51519
  for (const [sid, cid] of [...driverBySession]) {
@@ -50165,6 +51546,7 @@ function teardownHostRole() {
50165
51546
  driverBySession.clear();
50166
51547
  driverByRequest.clear();
50167
51548
  unwatchAllRemote();
51549
+ unwatchAllSessions();
50168
51550
  releaseRemotePtys();
50169
51551
  try {
50170
51552
  hostBackend?.reclaim("critical");
@@ -50527,6 +51909,7 @@ function stopControlLink() {
50527
51909
  }
50528
51910
 
50529
51911
  // ../../packages/host-core/dist/local-server.js
51912
+ init_dist2();
50530
51913
  var connSeq = 0;
50531
51914
  async function startLocalServer(opts) {
50532
51915
  const log3 = opts.log ?? (() => {
@@ -50583,6 +51966,7 @@ async function startLocalServer(opts) {
50583
51966
  });
50584
51967
  ws.on("close", () => {
50585
51968
  unregisterSink();
51969
+ unwatchSessionClient(loopbackOrigin);
50586
51970
  clearBrowserOrigin(loopbackOrigin);
50587
51971
  if (heldSessions.size) {
50588
51972
  const b = peekSharedBackend();
@@ -50641,6 +52025,17 @@ async function startLocalServer(opts) {
50641
52025
  send2("agent", { type: "session:messages", sessionId: msg.sessionId, messages });
50642
52026
  break;
50643
52027
  }
52028
+ case "session:watch":
52029
+ void watchSession(msg.sessionId, loopbackOrigin, msg.projectDir, {
52030
+ getMessages: (sid) => b.getMessages(sid),
52031
+ isSessionBusy: (sid) => b.isSessionBusy?.(sid) ?? false,
52032
+ resolveFile: (sid, dir) => b.resolveSessionFile?.(sid, dir) ?? Promise.resolve(null),
52033
+ emit: (_key, m) => send2("agent", m)
52034
+ });
52035
+ break;
52036
+ case "session:unwatch":
52037
+ unwatchSession(msg.sessionId, loopbackOrigin);
52038
+ break;
50644
52039
  case "session:fork": {
50645
52040
  const newId = await b.forkSession?.(msg.sessionId, { projectDir: msg.projectDir, upToMessageId: msg.upToMessageId, title: msg.title }).catch(() => null);
50646
52041
  if (newId)
@@ -50983,7 +52378,7 @@ import { platform as platform2 } from "node:os";
50983
52378
 
50984
52379
  // ../../packages/host-core/dist/service/launchd.js
50985
52380
  import { writeFileSync as writeFileSync11, existsSync as existsSync16, mkdirSync as mkdirSync11, unlinkSync as unlinkSync3 } from "node:fs";
50986
- import { dirname as dirname13, join as join28 } from "node:path";
52381
+ import { dirname as dirname14, join as join28 } from "node:path";
50987
52382
  import { homedir as homedir12, userInfo } from "node:os";
50988
52383
 
50989
52384
  // ../../packages/host-core/dist/service/exec.js
@@ -51050,8 +52445,8 @@ ${env}
51050
52445
  }
51051
52446
  return {
51052
52447
  async install(spec) {
51053
- mkdirSync11(dirname13(plistPath()), { recursive: true });
51054
- mkdirSync11(dirname13(spec.logPath), { recursive: true });
52448
+ mkdirSync11(dirname14(plistPath()), { recursive: true });
52449
+ mkdirSync11(dirname14(spec.logPath), { recursive: true });
51055
52450
  writeFileSync11(plistPath(), buildPlist(spec));
51056
52451
  await run("launchctl", ["bootout", serviceTarget()]).catch(() => {
51057
52452
  });
@@ -51103,7 +52498,7 @@ ${env}
51103
52498
 
51104
52499
  // ../../packages/host-core/dist/service/systemd.js
51105
52500
  import { writeFileSync as writeFileSync12, existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync4 } from "node:fs";
51106
- import { dirname as dirname14, join as join29 } from "node:path";
52501
+ import { dirname as dirname15, join as join29 } from "node:path";
51107
52502
  import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
51108
52503
  function shq(s) {
51109
52504
  return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
@@ -51137,8 +52532,8 @@ WantedBy=default.target
51137
52532
  }
51138
52533
  return {
51139
52534
  async install(spec) {
51140
- mkdirSync12(dirname14(unitPath()), { recursive: true });
51141
- mkdirSync12(dirname14(spec.logPath), { recursive: true });
52535
+ mkdirSync12(dirname15(unitPath()), { recursive: true });
52536
+ mkdirSync12(dirname15(spec.logPath), { recursive: true });
51142
52537
  writeFileSync12(unitPath(), buildUnit(spec));
51143
52538
  await run("loginctl", ["enable-linger", userInfo2().username]).catch(() => {
51144
52539
  });
@@ -51183,7 +52578,7 @@ WantedBy=default.target
51183
52578
 
51184
52579
  // ../../packages/host-core/dist/service/windows.js
51185
52580
  import { writeFileSync as writeFileSync13, existsSync as existsSync18, mkdirSync as mkdirSync13, unlinkSync as unlinkSync5 } from "node:fs";
51186
- import { dirname as dirname15, join as join30 } from "node:path";
52581
+ import { dirname as dirname16, join as join30 } from "node:path";
51187
52582
  function makeWindowsTask(instanceId) {
51188
52583
  const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
51189
52584
  const wrapperPath = () => join30(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
@@ -51198,8 +52593,8 @@ start "" /b ${cmd} >> "${spec.logPath}" 2>&1\r
51198
52593
  }
51199
52594
  return {
51200
52595
  async install(spec) {
51201
- mkdirSync13(dirname15(spec.logPath), { recursive: true });
51202
- mkdirSync13(dirname15(wrapperPath()), { recursive: true });
52596
+ mkdirSync13(dirname16(spec.logPath), { recursive: true });
52597
+ mkdirSync13(dirname16(wrapperPath()), { recursive: true });
51203
52598
  writeFileSync13(wrapperPath(), buildWrapper(spec));
51204
52599
  await run("schtasks", ["/Create", "/TN", task, "/SC", "ONLOGON", "/RL", "LIMITED", "/F", "/TR", `"${wrapperPath()}"`]);
51205
52600
  await run("schtasks", ["/Run", "/TN", task]).catch(() => {
@@ -51633,7 +53028,7 @@ async function logs(instanceId, follow) {
51633
53028
  // src/cli.ts
51634
53029
  function pkgVersion() {
51635
53030
  try {
51636
- const p = join33(dirname16(fileURLToPath2(import.meta.url)), "..", "package.json");
53031
+ const p = join33(dirname17(fileURLToPath2(import.meta.url)), "..", "package.json");
51637
53032
  return JSON.parse(readFileSync13(p, "utf8")).version ?? "0.0.0";
51638
53033
  } catch {
51639
53034
  return "0.0.0";