├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ ├── changelog.yml │ ├── check-package-changes.yml │ ├── conventional-commits.yml │ ├── e2e.yml │ └── publish.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── THIRD-PARTY-NOTICES.txt ├── adapters └── pgsql-adapter │ ├── Dockerfile │ ├── README.md │ ├── docker-entrypoint.sh │ ├── health-check.sh │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── index.ts │ └── postgres │ │ ├── isMutative.ts │ │ └── postgres.ts │ └── tsconfig.json ├── app ├── .dockerignore ├── .env.base ├── .eslintrc.json ├── Dockerfile ├── README.md ├── app │ ├── cli-auth │ │ └── page.tsx │ ├── clusters │ │ ├── [clusterId] │ │ │ ├── integrations │ │ │ │ ├── langfuse │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── slack │ │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── page.tsx │ │ │ ├── runs │ │ │ │ ├── [runId] │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── settings │ │ │ │ ├── api-keys │ │ │ │ │ └── page.tsx │ │ │ │ ├── danger │ │ │ │ │ └── page.tsx │ │ │ │ ├── details │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── usage │ │ │ │ └── page.tsx │ │ │ └── workflows │ │ │ │ ├── [workflowName] │ │ │ │ └── executions │ │ │ │ │ └── [executionId] │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ └── page.tsx │ ├── favicon.ico │ ├── favicon.ico- │ ├── globals.css │ ├── layout.tsx │ ├── page.tsx │ ├── providers.tsx │ └── switch-org │ │ └── page.tsx ├── assets │ └── screenshot.png ├── client │ ├── client.ts │ └── contract.ts ├── components.json ├── components │ ├── api-keys.tsx │ ├── breadcrumbs.tsx │ ├── bug-report-dialog.tsx │ ├── chat │ │ ├── InvocationResult.tsx │ │ ├── ResultTable.css │ │ ├── ai-message.tsx │ │ ├── event-indicator.tsx │ │ ├── function-call.tsx │ │ ├── human-message.tsx │ │ ├── input-fields.tsx │ │ ├── markdown.css │ │ ├── markdown.tsx │ │ ├── prompt-textarea.tsx │ │ ├── run-event.tsx │ │ ├── sdk-commands.tsx │ │ ├── structured-output-editor.tsx │ │ ├── template-mesage.tsx │ │ ├── template-message.tsx │ │ ├── tool-context-button.tsx │ │ └── typable.tsx │ ├── circles.tsx │ ├── cluster-details.tsx │ ├── cluster-runs-layout.tsx │ ├── clusters-table.tsx │ ├── copy-button.tsx │ ├── create-api-key.tsx │ ├── create-cluster-button.tsx │ ├── debug-event.tsx │ ├── error-display.tsx │ ├── event-details.tsx │ ├── events-overlay.tsx │ ├── fetch-rerender-error.example.md │ ├── hacker-news-demo.tsx │ ├── header.tsx │ ├── instructions-editor.css │ ├── json-display.tsx │ ├── knowledge-quickstart.tsx │ ├── live-check.tsx │ ├── loading.tsx │ ├── logo.png │ ├── markdown-editor.tsx │ ├── mdxeditor.css │ ├── mobile-block-screen.tsx │ ├── org-list.tsx │ ├── posthog-pageview.tsx │ ├── posthog-user.tsx │ ├── quick-start-demo.tsx │ ├── read-only-json.tsx │ ├── rollbar-user.tsx │ ├── run-list.tsx │ ├── run-tab.tsx │ ├── run.tsx │ ├── services-quickstart.tsx │ ├── ui │ │ ├── accordion.tsx │ │ ├── alert-dialog.tsx │ │ ├── alert.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── chart.tsx │ │ ├── checkbox.tsx │ │ ├── collapsible.tsx │ │ ├── command.tsx │ │ ├── data-table.tsx │ │ ├── dialog.tsx │ │ ├── drawer.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── menubar.tsx │ │ ├── multi-select.tsx │ │ ├── multiselect.tsx │ │ ├── popover.tsx │ │ ├── progress.tsx │ │ ├── scroll-area.tsx │ │ ├── select.tsx │ │ ├── send-button.tsx │ │ ├── sheet.tsx │ │ ├── skeleton.tsx │ │ ├── switch.tsx │ │ ├── table.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx │ ├── use-cluster-state.ts │ └── workflow-trigger-modal.tsx ├── instrumentation.ts ├── lib │ ├── auth.ts │ ├── colorize-json.ts │ ├── encryption.ts │ ├── features.ts │ ├── hyperdx.ts │ ├── types.ts │ ├── use-authenticated-client.ts │ ├── use-hash-state.ts │ ├── use-json-state.ts │ └── utils.ts ├── middleware.ts ├── next.config.mjs ├── package-lock.json ├── package.json ├── pages │ └── api │ │ └── health.ts ├── postcss.config.mjs ├── styles │ └── button-animations.css ├── tailwind.config.ts └── tsconfig.json ├── archives ├── .gitkeep ├── bootstrap-dotnet.zip ├── bootstrap-go.zip └── bootstrap-node.zip ├── assets ├── demo.png ├── deployment.png ├── hero.png ├── logo.png ├── thumbnail.png ├── workflow-list.png └── workflow-timeline.png ├── bootstrap-dotnet ├── .gitignore ├── ExecService.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── README.md ├── Register.cs ├── appsettings.Development.json ├── appsettings.json ├── bootstrap-dotnet.csproj └── bootstrap-dotnet.sln ├── bootstrap-go ├── .gitignore ├── README.md ├── go.mod ├── go.sum └── main.go ├── bootstrap-node ├── .gitignore ├── README.md ├── package-lock.json ├── package.json └── src │ └── index.ts ├── cli ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ ├── client │ │ └── contract.ts │ ├── commands │ │ ├── __snapshots__ │ │ │ ├── generate-graphql.test.ts.snap │ │ │ └── generate-open-api.test.ts.snap │ │ ├── auth-keys-create.ts │ │ ├── auth-keys-list.ts │ │ ├── auth-keys-revoke.ts │ │ ├── auth-keys.ts │ │ ├── auth.ts │ │ ├── bootstrap.test.ts │ │ ├── bootstrap.ts │ │ ├── cli-update.ts │ │ ├── cli.ts │ │ ├── clusters-create.ts │ │ ├── clusters-info.ts │ │ ├── clusters-list.ts │ │ ├── clusters-traces.ts │ │ ├── clusters-traces.tsx │ │ ├── clusters.ts │ │ ├── console.ts │ │ ├── generate-graphql.test.ts │ │ ├── generate-graphql.ts │ │ ├── generate-open-api.test.ts │ │ ├── generate-open-api.ts │ │ ├── generate.ts │ │ ├── open.ts │ │ ├── runs-create.ts │ │ ├── runs-info.ts │ │ ├── runs-list.ts │ │ ├── runs.ts │ │ └── shell.ts │ ├── constants.ts │ ├── index.ts │ ├── lib │ │ ├── auth.ts │ │ ├── client.ts │ │ ├── context.ts │ │ ├── graphql │ │ │ ├── graphql.test.ts │ │ │ ├── index.ts │ │ │ └── toJsonSchema.ts │ │ ├── openapi │ │ │ ├── index.ts │ │ │ └── openapi.test.ts │ │ ├── temporary-kv.test.ts │ │ └── temporary-kv.ts │ ├── system.ts │ ├── testdata │ │ ├── link.oas.yaml │ │ ├── link.operations.gql │ │ └── link.schema.gql │ └── utils.ts └── tsconfig.json ├── cliff.toml ├── control-plane ├── .dockerignore ├── .env.base ├── .eslintrc ├── @types │ └── fastify │ │ └── index.d.ts ├── Dockerfile ├── README.md ├── babel.config.js ├── docker-compose.dev.yml ├── docker-compose.yml ├── drizzle.config.ts ├── drizzle │ ├── 0000_odd_tattoo.sql │ ├── 0001_tense_dreaming_celestial.sql │ ├── 0002_steady_korath.sql │ ├── 0003_living_captain_america.sql │ ├── 0004_confused_goliath.sql │ ├── 0005_overconfident_hex.sql │ ├── 0006_ambiguous_wild_pack.sql │ ├── 0007_icy_the_hand.sql │ ├── 0008_omniscient_mongu.sql │ ├── 0009_cuddly_medusa.sql │ ├── 0010_curious_amphibian.sql │ ├── 0011_thin_preak.sql │ ├── 0012_manual_make.sql │ ├── 0013_bitter_lily_hollister.sql │ ├── 0014_kind_mercury.sql │ ├── 0015_flimsy_microbe.sql │ ├── 0016_unique_wallflower.sql │ ├── 0017_purple_captain_stacy.sql │ ├── 0018_spooky_sasquatch.sql │ ├── 0019_early_silver_sable.sql │ ├── 0020_third_lockjaw.sql │ ├── 0021_brave_eternals.sql │ ├── 0022_bizarre_princess_powerful.sql │ ├── 0023_lazy_dakota_north.sql │ ├── 0024_thin_black_bolt.sql │ ├── 0025_hot_shinobi_shaw.sql │ ├── 0026_freezing_clint_barton.sql │ ├── 0027_lyrical_ken_ellis.sql │ ├── 0028_parallel_karen_page.sql │ ├── 0029_sad_thunderbird.sql │ ├── 0030_omniscient_jamie_braddock.sql │ ├── 0031_misty_slipstream.sql │ ├── 0032_clumsy_gressill.sql │ ├── 0033_high_komodo.sql │ ├── 0034_real_big_bertha.sql │ ├── 0035_eminent_fantastic_four.sql │ ├── 0036_ambiguous_human_robot.sql │ ├── 0037_empty_molecule_man.sql │ ├── 0038_woozy_tiger_shark.sql │ ├── 0039_puzzling_vampiro.sql │ ├── 0040_mean_jazinda.sql │ ├── 0041_youthful_steve_rogers.sql │ ├── 0042_kind_lester.sql │ ├── 0043_closed_weapon_omega.sql │ ├── 0044_fancy_landau.sql │ ├── 0045_icy_kid_colt.sql │ ├── 0046_needy_brood.sql │ ├── 0047_certain_penance.sql │ ├── 0048_awesome_joystick.sql │ ├── 0049_gray_ben_grimm.sql │ ├── 0050_slimy_hulk.sql │ ├── 0051_loving_phil_sheldon.sql │ ├── 0052_swift_microbe.sql │ ├── 0053_broken_zaran.sql │ ├── 0054_graceful_mentallo.sql │ ├── 0055_condemned_doomsday.sql │ ├── 0056_chief_havok.sql │ ├── 0057_ambiguous_firebird.sql │ ├── 0058_bumpy_radioactive_man.sql │ ├── 0059_misty_shaman.sql │ ├── 0060_normal_midnight.sql │ ├── 0061_nervous_triathlon.sql │ ├── 0062_wide_warpath.sql │ ├── 0063_high_lockjaw.sql │ ├── 0064_sweet_silverclaw.sql │ ├── 0065_fast_oracle.sql │ ├── 0066_fearless_storm.sql │ ├── 0067_outstanding_deadpool.sql │ ├── 0068_tranquil_deadpool.sql │ ├── 0069_sudden_longshot.sql │ ├── 0070_real_wraith.sql │ ├── 0071_tidy_jimmy_woo.sql │ ├── 0072_right_slipstream.sql │ ├── 0073_nervous_chamber.sql │ ├── 0074_ancient_roxanne_simpson.sql │ ├── 0075_outgoing_christian_walker.sql │ ├── 0076_demonic_captain_flint.sql │ ├── 0077_bitter_ulik.sql │ ├── 0078_wonderful_penance.sql │ ├── 0079_reflective_mathemanic.sql │ ├── 0080_simple_jimmy_woo.sql │ ├── 0081_spicy_spencer_smythe.sql │ ├── 0082_slimy_kronos.sql │ ├── 0083_natural_rhino.sql │ ├── 0084_red_terrax.sql │ ├── 0085_conscious_purifiers.sql │ ├── 0086_ambiguous_swarm.sql │ ├── 0087_simple_stone_men.sql │ ├── 0088_simple_longshot.sql │ ├── 0089_amazing_vargas.sql │ ├── 0090_ambitious_chimera.sql │ ├── 0091_living_the_professor.sql │ ├── 0092_overrated_sunfire.sql │ ├── 0093_bumpy_skreet.sql │ ├── 0094_complex_clint_barton.sql │ ├── 0095_daffy_king_cobra.sql │ ├── 0096_romantic_namorita.sql │ ├── 0097_cool_pyro.sql │ ├── 0098_gorgeous_hellion.sql │ ├── 0099_clever_gamora.sql │ ├── 0100_fuzzy_redwing.sql │ ├── 0101_magical_zarek.sql │ ├── 0102_massive_exiles.sql │ ├── 0103_nervous_kid_colt.sql │ ├── 0104_salty_ultron.sql │ ├── 0105_bouncy_wallow.sql │ ├── 0106_happy_moondragon.sql │ ├── 0107_hesitant_thaddeus_ross.sql │ ├── 0108_little_rhino.sql │ ├── 0109_majestic_otto_octavius.sql │ ├── 0110_round_captain_britain.sql │ ├── 0111_sturdy_black_widow.sql │ ├── 0112_funny_red_ghost.sql │ ├── 0113_overjoyed_scream.sql │ ├── 0114_bright_mesmero.sql │ ├── 0115_lonely_talon.sql │ ├── 0116_far_justice.sql │ ├── 0117_perfect_frightful_four.sql │ ├── 0118_red_garia.sql │ ├── 0119_sour_tinkerer.sql │ ├── 0120_fearless_krista_starr.sql │ ├── 0121_silky_wolverine.sql │ ├── 0122_nice_black_tarantula.sql │ ├── 0123_woozy_squirrel_girl.sql │ ├── 0124_careless_harpoon.sql │ ├── 0125_remarkable_cable.sql │ ├── 0126_tiresome_glorian.sql │ ├── 0127_illegal_james_howlett.sql │ ├── 0128_tricky_steel_serpent.sql │ ├── 0129_military_crystal.sql │ ├── 0130_brief_ben_parker.sql │ ├── 0131_regular_demogoblin.sql │ ├── 0132_elite_lady_bullseye.sql │ ├── 0133_nice_luckman.sql │ ├── 0134_tiny_anita_blake.sql │ ├── 0135_majestic_callisto.sql │ ├── 0136_many_nightmare.sql │ ├── 0137_remarkable_hardball.sql │ ├── 0138_lively_the_leader.sql │ ├── 0139_lean_forge.sql │ ├── 0140_windy_grim_reaper.sql │ ├── 0141_real_hex.sql │ ├── 0142_opposite_leo.sql │ ├── 0143_overconfident_lady_mastermind.sql │ ├── 0144_crazy_shriek.sql │ ├── 0145_smart_weapon_omega.sql │ ├── 0146_moaning_rattler.sql │ ├── 0147_clammy_ulik.sql │ ├── 0148_slimy_alex_wilder.sql │ ├── 0149_last_nighthawk.sql │ ├── 0150_giant_bishop.sql │ ├── 0151_careless_romulus.sql │ ├── 0152_strong_tomorrow_man.sql │ ├── 0153_unique_starhawk.sql │ ├── 0154_tiresome_orphan.sql │ ├── 0155_lush_shadow_king.sql │ ├── 0156_old_justice.sql │ ├── 0157_icy_hawkeye.sql │ ├── 0158_lush_machine_man.sql │ ├── 0159_lazy_quentin_quire.sql │ ├── 0159_tranquil_tempest.sql │ ├── 0160_breezy_roulette.sql │ ├── 0161_jazzy_lucky_pierre.sql │ ├── 0162_sour_romulus.sql │ ├── 0163_dizzy_ogun.sql │ ├── 0164_large_zzzax.sql │ ├── 0165_nice_angel.sql │ ├── 0166_same_gargoyle.sql │ ├── 0167_high_silver_fox.sql │ ├── 0168_wet_prima.sql │ ├── 0169_modern_big_bertha.sql │ ├── 0170_wet_steve_rogers.sql │ ├── 0171_wise_bloodaxe.sql │ ├── 0172_sweet_jane_foster.sql │ ├── 0173_outstanding_silvermane.sql │ ├── 0174_careful_silhouette.sql │ ├── 0175_clever_cardiac.sql │ ├── 0176_loose_wilson_fisk.sql │ ├── 0177_bright_machine_man.sql │ ├── 0178_thankful_hellcat.sql │ ├── 0179_tranquil_mongu.sql │ ├── 0180_clumsy_sheva_callister.sql │ ├── 0181_oval_shadow_king.sql │ ├── 0182_lethal_darkstar.sql │ ├── 0183_black_multiple_man.sql │ ├── 0184_nervous_jubilee.sql │ ├── 0185_many_thunderbolt.sql │ ├── 0186_oval_maggott.sql │ ├── 0187_sour_black_queen.sql │ ├── 0188_shiny_thunderbolt_ross.sql │ ├── 0189_funny_nomad.sql │ ├── 0190_equal_luke_cage.sql │ ├── 0191_perfect_wasp.sql │ ├── 0192_familiar_roland_deschain.sql │ ├── 0193_fat_millenium_guard.sql │ ├── 0194_tiny_beast.sql │ ├── 0195_cultured_agent_brand.sql │ ├── 0196_giant_boom_boom.sql │ ├── 0196_volatile_maginty.sql │ ├── 0197_jazzy_solo.sql │ ├── 0198_daily_smasher.sql │ ├── 0199_curious_mach_iv.sql │ ├── 0200_organic_terror.sql │ ├── 0201_clumsy_human_torch.sql │ ├── 0202_daffy_baron_zemo.sql │ ├── 0203_sad_speed.sql │ ├── 0204_melodic_ikaris.sql │ ├── 0205_amusing_strong_guy.sql │ ├── 0206_salty_lightspeed.sql │ ├── 0207_overjoyed_ronan.sql │ ├── 0208_brave_tenebrous.sql │ ├── 0209_stiff_tenebrous.sql │ ├── 0210_tiny_katie_power.sql │ ├── 0211_silky_madame_hydra.sql │ ├── 0212_bizarre_luckman.sql │ ├── 0213_hesitant_pretty_boy.sql │ ├── 0214_quiet_iron_patriot.sql │ ├── 0215_useful_excalibur.sql │ ├── 0216_jittery_the_hunter.sql │ ├── 0217_right_paibok.sql │ ├── 0218_windy_zzzax.sql │ ├── 0219_magical_mulholland_black.sql │ ├── 0220_conscious_satana.sql │ ├── 0221_melodic_vector.sql │ ├── 0222_red_cardiac.sql │ ├── 0223_nappy_the_enforcers.sql │ ├── 0224_slim_klaw.sql │ ├── 0225_absurd_ben_urich.sql │ ├── 0226_past_captain_marvel.sql │ ├── 0227_worried_proudstar.sql │ ├── 0228_clammy_the_twelve.sql │ ├── 0229_migrate-workflow-tags-to-runs.sql │ ├── 0230_bent_strong_guy.sql │ ├── 0231_easy_johnny_blaze.sql │ ├── 0232_narrow_paper_doll.sql │ ├── 0233_old_forge.sql │ ├── 0234_material_post.sql │ ├── 0235_mute_zodiak.sql │ ├── 0236_same_terrax.sql │ ├── 0237_crazy_kate_bishop.sql │ ├── 0238_sudden_stature.sql │ ├── 0239_reflective_puppet_master.sql │ ├── 0240_fuzzy_cassandra_nova.sql │ ├── 0241_blue_wild_child.sql │ ├── 0242_opposite_owl.sql │ ├── 0243_icy_cannonball.sql │ ├── 0244_first_invaders.sql │ ├── 0245_free_agent_zero.sql │ ├── 0246_white_banshee.sql │ └── meta │ │ ├── 0000_snapshot.json │ │ ├── 0001_snapshot.json │ │ ├── 0002_snapshot.json │ │ ├── 0003_snapshot.json │ │ ├── 0004_snapshot.json │ │ ├── 0005_snapshot.json │ │ ├── 0006_snapshot.json │ │ ├── 0007_snapshot.json │ │ ├── 0008_snapshot.json │ │ ├── 0009_snapshot.json │ │ ├── 0010_snapshot.json │ │ ├── 0011_snapshot.json │ │ ├── 0012_snapshot.json │ │ ├── 0013_snapshot.json │ │ ├── 0014_snapshot.json │ │ ├── 0015_snapshot.json │ │ ├── 0016_snapshot.json │ │ ├── 0017_snapshot.json │ │ ├── 0018_snapshot.json │ │ ├── 0019_snapshot.json │ │ ├── 0020_snapshot.json │ │ ├── 0021_snapshot.json │ │ ├── 0022_snapshot.json │ │ ├── 0023_snapshot.json │ │ ├── 0024_snapshot.json │ │ ├── 0025_snapshot.json │ │ ├── 0026_snapshot.json │ │ ├── 0027_snapshot.json │ │ ├── 0028_snapshot.json │ │ ├── 0029_snapshot.json │ │ ├── 0030_snapshot.json │ │ ├── 0031_snapshot.json │ │ ├── 0032_snapshot.json │ │ ├── 0033_snapshot.json │ │ ├── 0034_snapshot.json │ │ ├── 0035_snapshot.json │ │ ├── 0036_snapshot.json │ │ ├── 0037_snapshot.json │ │ ├── 0038_snapshot.json │ │ ├── 0039_snapshot.json │ │ ├── 0040_snapshot.json │ │ ├── 0041_snapshot.json │ │ ├── 0042_snapshot.json │ │ ├── 0043_snapshot.json │ │ ├── 0044_snapshot.json │ │ ├── 0045_snapshot.json │ │ ├── 0046_snapshot.json │ │ ├── 0047_snapshot.json │ │ ├── 0048_snapshot.json │ │ ├── 0049_snapshot.json │ │ ├── 0050_snapshot.json │ │ ├── 0051_snapshot.json │ │ ├── 0052_snapshot.json │ │ ├── 0053_snapshot.json │ │ ├── 0054_snapshot.json │ │ ├── 0055_snapshot.json │ │ ├── 0056_snapshot.json │ │ ├── 0057_snapshot.json │ │ ├── 0058_snapshot.json │ │ ├── 0059_snapshot.json │ │ ├── 0060_snapshot.json │ │ ├── 0061_snapshot.json │ │ ├── 0062_snapshot.json │ │ ├── 0063_snapshot.json │ │ ├── 0064_snapshot.json │ │ ├── 0065_snapshot.json │ │ ├── 0066_snapshot.json │ │ ├── 0067_snapshot.json │ │ ├── 0068_snapshot.json │ │ ├── 0069_snapshot.json │ │ ├── 0070_snapshot.json │ │ ├── 0071_snapshot.json │ │ ├── 0072_snapshot.json │ │ ├── 0073_snapshot.json │ │ ├── 0074_snapshot.json │ │ ├── 0075_snapshot.json │ │ ├── 0076_snapshot.json │ │ ├── 0077_snapshot.json │ │ ├── 0078_snapshot.json │ │ ├── 0079_snapshot.json │ │ ├── 0080_snapshot.json │ │ ├── 0081_snapshot.json │ │ ├── 0082_snapshot.json │ │ ├── 0083_snapshot.json │ │ ├── 0084_snapshot.json │ │ ├── 0085_snapshot.json │ │ ├── 0086_snapshot.json │ │ ├── 0087_snapshot.json │ │ ├── 0088_snapshot.json │ │ ├── 0089_snapshot.json │ │ ├── 0090_snapshot.json │ │ ├── 0091_snapshot.json │ │ ├── 0092_snapshot.json │ │ ├── 0093_snapshot.json │ │ ├── 0094_snapshot.json │ │ ├── 0095_snapshot.json │ │ ├── 0096_snapshot.json │ │ ├── 0097_snapshot.json │ │ ├── 0098_snapshot.json │ │ ├── 0099_snapshot.json │ │ ├── 0100_snapshot.json │ │ ├── 0101_snapshot.json │ │ ├── 0102_snapshot.json │ │ ├── 0103_snapshot.json │ │ ├── 0104_snapshot.json │ │ ├── 0105_snapshot.json │ │ ├── 0106_snapshot.json │ │ ├── 0107_snapshot.json │ │ ├── 0108_snapshot.json │ │ ├── 0109_snapshot.json │ │ ├── 0110_snapshot.json │ │ ├── 0111_snapshot.json │ │ ├── 0112_snapshot.json │ │ ├── 0113_snapshot.json │ │ ├── 0114_snapshot.json │ │ ├── 0115_snapshot.json │ │ ├── 0116_snapshot.json │ │ ├── 0117_snapshot.json │ │ ├── 0118_snapshot.json │ │ ├── 0119_snapshot.json │ │ ├── 0120_snapshot.json │ │ ├── 0121_snapshot.json │ │ ├── 0122_snapshot.json │ │ ├── 0123_snapshot.json │ │ ├── 0124_snapshot.json │ │ ├── 0125_snapshot.json │ │ ├── 0126_snapshot.json │ │ ├── 0127_snapshot.json │ │ ├── 0128_snapshot.json │ │ ├── 0129_snapshot.json │ │ ├── 0130_snapshot.json │ │ ├── 0131_snapshot.json │ │ ├── 0132_snapshot.json │ │ ├── 0133_snapshot.json │ │ ├── 0134_snapshot.json │ │ ├── 0135_snapshot.json │ │ ├── 0136_snapshot.json │ │ ├── 0137_snapshot.json │ │ ├── 0138_snapshot.json │ │ ├── 0139_snapshot.json │ │ ├── 0140_snapshot.json │ │ ├── 0141_snapshot.json │ │ ├── 0142_snapshot.json │ │ ├── 0143_snapshot.json │ │ ├── 0144_snapshot.json │ │ ├── 0145_snapshot.json │ │ ├── 0146_snapshot.json │ │ ├── 0147_snapshot.json │ │ ├── 0148_snapshot.json │ │ ├── 0149_snapshot.json │ │ ├── 0150_snapshot.json │ │ ├── 0151_snapshot.json │ │ ├── 0152_snapshot.json │ │ ├── 0153_snapshot.json │ │ ├── 0154_snapshot.json │ │ ├── 0155_snapshot.json │ │ ├── 0156_snapshot.json │ │ ├── 0157_snapshot.json │ │ ├── 0158_snapshot.json │ │ ├── 0159_snapshot.json │ │ ├── 0160_snapshot.json │ │ ├── 0161_snapshot.json │ │ ├── 0162_snapshot.json │ │ ├── 0163_snapshot.json │ │ ├── 0164_snapshot.json │ │ ├── 0165_snapshot.json │ │ ├── 0166_snapshot.json │ │ ├── 0167_snapshot.json │ │ ├── 0168_snapshot.json │ │ ├── 0169_snapshot.json │ │ ├── 0170_snapshot.json │ │ ├── 0171_snapshot.json │ │ ├── 0172_snapshot.json │ │ ├── 0173_snapshot.json │ │ ├── 0174_snapshot.json │ │ ├── 0175_snapshot.json │ │ ├── 0176_snapshot.json │ │ ├── 0177_snapshot.json │ │ ├── 0178_snapshot.json │ │ ├── 0179_snapshot.json │ │ ├── 0180_snapshot.json │ │ ├── 0181_snapshot.json │ │ ├── 0182_snapshot.json │ │ ├── 0183_snapshot.json │ │ ├── 0184_snapshot.json │ │ ├── 0185_snapshot.json │ │ ├── 0186_snapshot.json │ │ ├── 0187_snapshot.json │ │ ├── 0188_snapshot.json │ │ ├── 0189_snapshot.json │ │ ├── 0190_snapshot.json │ │ ├── 0191_snapshot.json │ │ ├── 0192_snapshot.json │ │ ├── 0193_snapshot.json │ │ ├── 0194_snapshot.json │ │ ├── 0195_snapshot.json │ │ ├── 0196_snapshot.json │ │ ├── 0197_snapshot.json │ │ ├── 0198_snapshot.json │ │ ├── 0199_snapshot.json │ │ ├── 0200_snapshot.json │ │ ├── 0201_snapshot.json │ │ ├── 0202_snapshot.json │ │ ├── 0203_snapshot.json │ │ ├── 0204_snapshot.json │ │ ├── 0205_snapshot.json │ │ ├── 0206_snapshot.json │ │ ├── 0207_snapshot.json │ │ ├── 0208_snapshot.json │ │ ├── 0209_snapshot.json │ │ ├── 0210_snapshot.json │ │ ├── 0211_snapshot.json │ │ ├── 0212_snapshot.json │ │ ├── 0213_snapshot.json │ │ ├── 0214_snapshot.json │ │ ├── 0215_snapshot.json │ │ ├── 0216_snapshot.json │ │ ├── 0217_snapshot.json │ │ ├── 0218_snapshot.json │ │ ├── 0219_snapshot.json │ │ ├── 0220_snapshot.json │ │ ├── 0221_snapshot.json │ │ ├── 0222_snapshot.json │ │ ├── 0223_snapshot.json │ │ ├── 0224_snapshot.json │ │ ├── 0225_snapshot.json │ │ ├── 0226_snapshot.json │ │ ├── 0227_snapshot.json │ │ ├── 0228_snapshot.json │ │ ├── 0229_snapshot.json │ │ ├── 0230_snapshot.json │ │ ├── 0231_snapshot.json │ │ ├── 0232_snapshot.json │ │ ├── 0233_snapshot.json │ │ ├── 0234_snapshot.json │ │ ├── 0235_snapshot.json │ │ ├── 0236_snapshot.json │ │ ├── 0237_snapshot.json │ │ ├── 0238_snapshot.json │ │ ├── 0239_snapshot.json │ │ ├── 0240_snapshot.json │ │ ├── 0241_snapshot.json │ │ ├── 0242_snapshot.json │ │ ├── 0243_snapshot.json │ │ ├── 0244_snapshot.json │ │ ├── 0245_snapshot.json │ │ ├── 0246_snapshot.json │ │ └── _journal.json ├── internal.md ├── jest.config.ts ├── package-lock.json ├── package.json ├── src │ ├── bootstrap.ts │ ├── index.ts │ ├── modules │ │ ├── auth │ │ │ ├── auth.test.ts │ │ │ ├── auth.ts │ │ │ ├── clerk.test.ts │ │ │ ├── clerk.ts │ │ │ ├── cluster.test.ts │ │ │ └── cluster.ts │ │ ├── clusters │ │ │ ├── index.test.ts │ │ │ ├── index.ts │ │ │ └── management.ts │ │ ├── contract.ts │ │ ├── cron │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ ├── customer-telemetry │ │ │ ├── index.ts │ │ │ └── track.ts │ │ ├── data.ts │ │ ├── dependencies │ │ │ ├── clerk.ts │ │ │ ├── flagsmith.ts │ │ │ ├── posthog.ts │ │ │ ├── redis.ts │ │ │ └── ses.ts │ │ ├── email │ │ │ └── index.ts │ │ ├── embeddings │ │ │ └── bedrock-cohere-embeddings.ts │ │ ├── expiration │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ ├── integrations │ │ │ ├── constants.ts │ │ │ ├── integration-events.ts │ │ │ ├── integrations.ts │ │ │ ├── langfuse.ts │ │ │ ├── nango │ │ │ │ └── index.ts │ │ │ ├── slack │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── receiver.ts │ │ │ └── types.ts │ │ ├── jobs │ │ │ ├── create-job.ts │ │ │ ├── job-results.ts │ │ │ ├── jobs.test.ts │ │ │ ├── jobs.ts │ │ │ ├── persist-result.test.ts │ │ │ └── self-heal-jobs.ts │ │ ├── kv │ │ │ └── index.ts │ │ ├── machines │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ ├── models │ │ │ ├── index.test.ts │ │ │ ├── index.ts │ │ │ └── routing.ts │ │ ├── observability │ │ │ ├── events.test.ts │ │ │ ├── events.ts │ │ │ ├── hyperdx.ts │ │ │ ├── logger.ts │ │ │ ├── rollbar.ts │ │ │ └── tracer.ts │ │ ├── queues │ │ │ ├── core.ts │ │ │ ├── customer-telemetry.ts │ │ │ ├── index.ts │ │ │ ├── observability.ts │ │ │ └── run-process.ts │ │ ├── router │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ ├── runs │ │ │ ├── agent │ │ │ │ ├── agent.ai.test.ts │ │ │ │ ├── agent.ts │ │ │ │ ├── nodes │ │ │ │ │ ├── edges.test.ts │ │ │ │ │ ├── edges.ts │ │ │ │ │ ├── model-call.test.ts │ │ │ │ │ ├── model-call.ts │ │ │ │ │ ├── model-output.test.ts │ │ │ │ │ ├── model-output.ts │ │ │ │ │ ├── system-prompt.ts │ │ │ │ │ ├── tool-call.test.ts │ │ │ │ │ ├── tool-call.ts │ │ │ │ │ ├── tool-parser.test.ts │ │ │ │ │ └── tool-parser.ts │ │ │ │ ├── overflow.test.ts │ │ │ │ ├── overflow.ts │ │ │ │ ├── run.test.ts │ │ │ │ ├── run.ts │ │ │ │ ├── state.ts │ │ │ │ ├── tool-search.ts │ │ │ │ ├── tool.ts │ │ │ │ ├── tools │ │ │ │ │ └── functions.ts │ │ │ │ ├── utils.test.ts │ │ │ │ └── utils.ts │ │ │ ├── index.test.ts │ │ │ ├── index.ts │ │ │ ├── messages.ts │ │ │ ├── notify.ts │ │ │ └── summarization.ts │ │ ├── test │ │ │ └── util.ts │ │ ├── timeline.ts │ │ ├── tools │ │ │ ├── index.test.ts │ │ │ ├── index.ts │ │ │ ├── validations.test.ts │ │ │ └── validations.ts │ │ └── workflows │ │ │ ├── executions.test.ts │ │ │ ├── executions.ts │ │ │ └── logs.ts │ └── utilities │ │ ├── cache.ts │ │ ├── env.ts │ │ ├── errors.test.ts │ │ ├── errors.ts │ │ ├── json-path.ts │ │ ├── json-schema.ts │ │ ├── migrate.ts │ │ ├── names.ts │ │ ├── packer.ts │ │ ├── rate-limiter.test.ts │ │ ├── rate-limiter.ts │ │ ├── run-migrate.ts │ │ └── safe-parse.ts └── tsconfig.json ├── demos ├── changelog-generator │ ├── README.md │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── inferable.ts │ │ ├── tools │ │ └── git.ts │ │ └── workflows │ │ ├── last-commit-hash.txt │ │ ├── summarize.ts │ │ └── utils │ │ ├── changelog.ts │ │ └── zapier.ts ├── contextual-ticket-tagging-single-step │ ├── README.md │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── inferable.ts │ │ ├── utils.ts │ │ └── workflow.ts ├── contextual-ticket-tagging │ ├── README.md │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── inferable.ts │ │ ├── tools.ts │ │ └── workflow.ts └── quote-system │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── index.ts │ ├── inferable.ts │ ├── tools.ts │ ├── utils.ts │ └── workflow.ts │ └── tsconfig.json ├── load-tests ├── Dockerfile.machine ├── README.md ├── entrypoint.sh ├── machine.ts ├── package-lock.json ├── package.json └── workflow.js ├── package-lock.json ├── package.json ├── sdk-bash ├── LICENSE ├── README.md ├── handler.sh ├── inferable.sh └── test.sh ├── sdk-dotnet ├── .github │ └── workflows │ │ ├── build.yaml │ │ └── publish.yaml ├── .gitignore ├── Inferable.sln ├── LICENSE ├── README.md ├── src │ ├── API │ │ ├── APIClient.cs │ │ ├── JsonSchemaConverter.cs │ │ ├── Models.cs │ │ └── SerializableException.cs │ ├── Function.cs │ ├── Inferable.cs │ ├── Inferable.csproj │ ├── IunctionRegistration.cs │ ├── Machine.cs │ └── Polling.cs └── tests │ └── Inferable.Tests │ ├── GlobalUsings.cs │ ├── Inferable.Tests.csproj │ └── InferableTest.cs ├── sdk-go ├── .gitignore ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── inferable.go ├── inferable_test.go ├── internal │ ├── client │ │ └── client.go │ └── util │ │ ├── test_util.go │ │ └── util.go ├── interrupt.go ├── main_test.go ├── polling.go ├── service_test.go ├── workflow.go └── workflow_test.go ├── sdk-node ├── .eslintrc ├── .gitignore ├── .prettierrc ├── CHANGELOG.md ├── README.md ├── assets │ └── logo.png ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ ├── Inferable.test.ts │ ├── Inferable.ts │ ├── contract.ts │ ├── create-client.ts │ ├── errors.ts │ ├── eval │ │ └── promptfoo.ts │ ├── execute-fn.test.ts │ ├── execute-fn.ts │ ├── index.ts │ ├── links.ts │ ├── machine-id.ts │ ├── polling.ts │ ├── serialize-error.js │ ├── tests │ │ ├── errors │ │ │ ├── animals.ts │ │ │ └── errors.test.ts │ │ ├── utility │ │ │ ├── caching.test.ts │ │ │ ├── product.ts │ │ │ └── retry.test.ts │ │ └── utils.ts │ ├── types.ts │ ├── util.test.ts │ ├── util.ts │ ├── util │ │ └── cybr53.ts │ └── workflows │ │ ├── workflow.test.ts │ │ └── workflow.ts ├── tsconfig.build.json └── tsconfig.json └── sdk-react ├── .gitignore ├── .npmignore ├── README.md ├── babel.config.js ├── demo ├── TestPage.css ├── TestPage.tsx ├── index.html └── main.jsx ├── jest.config.js ├── jest.setup.js ├── package-lock.json ├── package.json ├── src ├── contract.ts ├── createClient.ts ├── hooks │ ├── useInferable.test.ts │ ├── useInferable.ts │ ├── useMessages.test.ts │ ├── useMessages.ts │ ├── useRun.test.ts │ ├── useRun.ts │ └── util.ts └── index.ts ├── tsconfig.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 2 4 | charset = utf-8 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | -------------------------------------------------------------------------------- /.github/workflows/changelog.yml: -------------------------------------------------------------------------------- 1 | name: Update Changelog 2 | 3 | on: 4 | push: 5 | tags: 6 | - '**' 7 | 8 | skip: [] # Allows `[skip ci]` commits 9 | 10 | jobs: 11 | generate_changelog: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | - name: Generate a changelog 21 | uses: orhun/git-cliff-action@v4 22 | with: 23 | config: cliff.toml 24 | args: --verbose 25 | env: 26 | OUTPUT: CHANGELOG.md 27 | GITHUB_REPO: ${{ github.repository }} 28 | - name: Commit changelog 29 | uses: EndBug/add-and-commit@v9 30 | with: 31 | add: 'CHANGELOG.md' 32 | message: '[skip ci] chore: Update changelog' 33 | default_author: github_actions 34 | push: true 35 | github_token: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.github/workflows/check-package-changes.yml: -------------------------------------------------------------------------------- 1 | name: Check Package Changes 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | paths: 8 | - 'sdk-*/**' 9 | - 'cli/**' 10 | 11 | jobs: 12 | check-package-changes: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | pull-requests: read 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Check for multiple package changes 23 | run: | 24 | CHANGED_PACKAGES=$(git diff --name-only origin/"${{ github.base_ref }}" | grep -E '^(sdk-[^/]+/|cli/)' | cut -d'/' -f1 | sort -u) 25 | 26 | COUNT=$(echo "$CHANGED_PACKAGES" | grep -v '^$' | wc -l) 27 | 28 | echo "$CHANGED_PACKAGES (COUNT=$COUNT)" 29 | 30 | if [ "$COUNT" -gt 1 ]; then 31 | echo "Error: Changes detected in multiple packages:" 32 | echo "Please limit changes to one package at a time." 33 | exit 1 34 | fi 35 | -------------------------------------------------------------------------------- /.github/workflows/conventional-commits.yml: -------------------------------------------------------------------------------- 1 | name: Check conventional commits 2 | 3 | permissions: 4 | pull-requests: read 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: true 9 | 10 | on: 11 | pull_request: 12 | branches: 13 | - main 14 | types: [opened, edited, reopened, synchronize, ready_for_review] 15 | 16 | jobs: 17 | commit-message-validation: 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - name: Commit message validation 22 | uses: amannn/action-semantic-pull-request@v5 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /.github/workflows/e2e.yml: -------------------------------------------------------------------------------- 1 | name: E2E heartbeat 2 | 3 | on: 4 | schedule: 5 | - cron: "0 * * * *" 6 | pull_request: 7 | branches: 8 | - main 9 | paths: 10 | - "load-tests/**" 11 | 12 | jobs: 13 | run-e2e: 14 | runs-on: ubuntu-latest 15 | defaults: 16 | run: 17 | working-directory: load-tests 18 | env: 19 | INFERABLE_TEST_CLUSTER_ID: ${{ secrets.INFERABLE_TEST_CLUSTER_ID }} 20 | INFERABLE_TEST_API_SECRET: ${{ secrets.INFERABLE_TEST_API_SECRET }} 21 | BETTER_STACK_SYNTHETIC_ENDPOINT: ${{ secrets.BETTER_STACK_SYNTHETIC_ENDPOINT }} 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Install dependencies 25 | run: npm ci 26 | # Run machine:start backgrounded 27 | - run: npm run machine:start & 28 | - uses: grafana/setup-k6-action@v1 29 | - uses: grafana/run-k6-action@v1 30 | with: 31 | path: ./load-tests/workflow.js 32 | fail-fast: true 33 | flags: --throw 34 | - run: curl -X POST ${BETTER_STACK_SYNTHETIC_ENDPOINT} 35 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | # Run lint-staged (already only checks changed files) 2 | npx lint-staged 3 | 4 | # Run prettier on staged files and write changes 5 | git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(ts|tsx|js|jsx|json)$' | xargs -I{} npx prettier --write "{}" 6 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | build 4 | .next 5 | coverage 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": false, 5 | "printWidth": 80, 6 | "tabWidth": 2, 7 | "useTabs": false, 8 | "bracketSpacing": true, 9 | "arrowParens": "avoid", 10 | "bracketSameLine": false 11 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll.eslint": "explicit" 6 | } 7 | } -------------------------------------------------------------------------------- /THIRD-PARTY-NOTICES.txt: -------------------------------------------------------------------------------- 1 | Inferable uses third-party libraries or other resources that may be 2 | distributed under licenses different than the Inferable software. 3 | 4 | In the event that we accidentally failed to list a required notice, please 5 | bring it to our attention by creating a pull-request or filing a github 6 | issue. 7 | 8 | 9 | 1) License Notice for the caniuse-lite package 10 | --------------------------------------- 11 | 12 | Source: https://github.com/browserslist/caniuse-lite 13 | License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/) 14 | -------------------------------------------------------------------------------- /adapters/pgsql-adapter/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-alpine 2 | 3 | WORKDIR /app 4 | 5 | # Pre-install pgsql-adapter globally 6 | RUN npm install -g @inferable/pgsql-adapter@0.0.9 7 | 8 | # Entrypoint script to handle environment variables 9 | COPY docker-entrypoint.sh /usr/local/bin/ 10 | RUN chmod +x /usr/local/bin/docker-entrypoint.sh 11 | 12 | # Add health-check script 13 | COPY health-check.sh /usr/local/bin/health-check 14 | RUN chmod +x /usr/local/bin/health-check 15 | 16 | RUN addgroup -S inferable && adduser -S inferable -G inferable 17 | USER inferable 18 | 19 | ENTRYPOINT ["docker-entrypoint.sh"] 20 | -------------------------------------------------------------------------------- /adapters/pgsql-adapter/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # Default values for environment variables 5 | CONNECTION_STRING="${CONNECTION_STRING:-}" 6 | APPROVAL_MODE="${APPROVAL_MODE:-always}" 7 | PRIVACY_MODE="${PRIVACY_MODE:-false}" 8 | SCHEMA="${SCHEMA:-public}" 9 | SECRET="${SECRET:-}" 10 | ENDPOINT="${ENDPOINT:-}" 11 | 12 | # Validate required environment variables 13 | if [ -z "$CONNECTION_STRING" ]; then 14 | echo "Error: CONNECTION_STRING environment variable is required" 15 | exit 1 16 | fi 17 | 18 | if [ -z "$SECRET" ]; then 19 | echo "Error: SECRET environment variable is required" 20 | exit 1 21 | fi 22 | 23 | # Construct CLI command with environment variables 24 | COMMAND="pgsql-adapter $CONNECTION_STRING \ 25 | --approval-mode=$APPROVAL_MODE \ 26 | --schema=$SCHEMA \ 27 | --secret=$SECRET" 28 | 29 | # Optional flags 30 | if [ "$PRIVACY_MODE" = "true" ]; then 31 | COMMAND="$COMMAND --privacy-mode" 32 | fi 33 | 34 | if [ -n "$ENDPOINT" ]; then 35 | COMMAND="$COMMAND --endpoint=\"$ENDPOINT\"" 36 | fi 37 | 38 | # Execute the command 39 | exec $COMMAND 40 | -------------------------------------------------------------------------------- /adapters/pgsql-adapter/health-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "Running health check" 5 | 6 | # Check if required environment variables are set 7 | if [ -z "$CONNECTION_STRING" ]; then 8 | echo "Error: CONNECTION_STRING environment variable is required for health check" 9 | exit 1 10 | fi 11 | 12 | if [ -z "$SECRET" ]; then 13 | echo "Error: SECRET environment variable is required for health check" 14 | exit 1 15 | fi 16 | 17 | # Perform the connection test 18 | pgsql-adapter "$CONNECTION_STRING" --secret="$SECRET" --test 19 | -------------------------------------------------------------------------------- /adapters/pgsql-adapter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@inferable/pgsql-adapter", 3 | "version": "0.0.9", 4 | "main": "bin/index.js", 5 | "types": "bin/index.d.ts", 6 | "bin": { 7 | "pgsql-adapter": "bin/index.js" 8 | }, 9 | "scripts": { 10 | "start": "tsx src/index.ts", 11 | "build": "tsc", 12 | "prepublishOnly": "npm run build" 13 | }, 14 | "dependencies": { 15 | "dotenv": "^16.4.5", 16 | "inferable": "^0.30.120", 17 | "pg": "^8.13.1", 18 | "tsx": "^4.19.2", 19 | "yargs": "^17.7.2" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "^20.11.19", 23 | "@types/pg": "^8.11.10", 24 | "@types/yargs": "^17.0.33", 25 | "typescript": "^5.3.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /adapters/pgsql-adapter/src/postgres/isMutative.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "pg"; 2 | 3 | // Define the mutative keywords 4 | const MUTATIVE_KEYWORDS = ['INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER', 'TRUNCATE']; 5 | 6 | const isMutativeStatic = (query: string): boolean => { 7 | const firstWord = query.trim().split(/\s+/)[0].toUpperCase(); 8 | return MUTATIVE_KEYWORDS.includes(firstWord); 9 | }; 10 | 11 | const isMutativeExplain = async (pg: Client, query: string): Promise => { 12 | try { 13 | const result = await pg.query(`EXPLAIN ${query}`); 14 | return result.rows.some(row => /ModifyTable|Insert|Update|Delete/i.test(row["QUERY PLAN"])); 15 | } catch (error) { 16 | console.error('Error running EXPLAIN:', error); 17 | return true; 18 | } 19 | }; 20 | 21 | export const isMutativeQuery = async (pg: Client, query: string): Promise => { 22 | // Perform static analysis 23 | if (isMutativeStatic(query)) return true; 24 | 25 | // Fallback to EXPLAIN if static analysis doesn't classify the query as mutative 26 | return await isMutativeExplain(pg, query); 27 | }; 28 | -------------------------------------------------------------------------------- /adapters/pgsql-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./bin", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules", "bin"] 15 | } 16 | -------------------------------------------------------------------------------- /app/.dockerignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env* 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /app/.env.base: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_INFERABLE_API_URL="http://localhost:4000" 2 | 3 | NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= 4 | -------------------------------------------------------------------------------- /app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "next/core-web-vitals", 4 | "plugin:@typescript-eslint/recommended" 5 | ], 6 | "parser": "@typescript-eslint/parser", 7 | "plugins": [ 8 | "@typescript-eslint" 9 | ], 10 | "rules": { 11 | "@typescript-eslint/no-unused-vars": 1, 12 | "@typescript-eslint/no-explicit-any": 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/integrations/layout.tsx: -------------------------------------------------------------------------------- 1 | export default function Layout({ children }: { children: React.ReactNode }) { 2 | return
{children}
; 3 | } 4 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/layout.tsx: -------------------------------------------------------------------------------- 1 | import { ClusterBreadcrumbs } from "@/components/breadcrumbs"; 2 | 3 | export default async function Layout({ 4 | children, 5 | params: { clusterId }, 6 | }: { 7 | children: React.ReactNode; 8 | params: { clusterId: string }; 9 | }) { 10 | return ( 11 | <> 12 | 13 | {children} 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function Page({ params }: { params: { clusterId: string } }) { 4 | redirect(`/clusters/${params.clusterId}/workflows`); 5 | } 6 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/runs/[runId]/page.tsx: -------------------------------------------------------------------------------- 1 | import { Run } from "@/components/run"; 2 | 3 | function Page({ 4 | params: { clusterId, runId }, 5 | }: { 6 | params: { 7 | clusterId: string; 8 | runId: string; 9 | }; 10 | }) { 11 | return ; 12 | } 13 | 14 | export default Page; 15 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/runs/page.tsx: -------------------------------------------------------------------------------- 1 | import { PromptTextarea } from "@/components/chat/prompt-textarea"; 2 | import { Card, CardContent } from "@/components/ui/card"; 3 | 4 | export default async function Page({ params: { clusterId } }: { params: { clusterId: string } }) { 5 | return ( 6 |
7 | 8 | 9 | 10 | 11 | 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/settings/api-keys/page.tsx: -------------------------------------------------------------------------------- 1 | import { ApiKeys } from "@/components/api-keys"; 2 | 3 | export default function ApiKeysPage({ 4 | params: { clusterId }, 5 | }: { 6 | params: { clusterId: string }; 7 | }) { 8 | return ; 9 | } 10 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export const metadata = { 4 | title: "ClusterSettings", 5 | }; 6 | 7 | export default function SettingsPage({ 8 | params: { clusterId }, 9 | }: { 10 | params: { clusterId: string }; 11 | }) { 12 | redirect(`/clusters/${clusterId}/settings/details`); 13 | } 14 | -------------------------------------------------------------------------------- /app/app/clusters/[clusterId]/workflows/layout.tsx: -------------------------------------------------------------------------------- 1 | export default function Layout({ 2 | children, 3 | }: { 4 | children: React.ReactNode; 5 | }) { 6 | return children; 7 | } 8 | -------------------------------------------------------------------------------- /app/app/clusters/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/header"; 2 | import { OrgList } from "@/components/org-list"; 3 | import { auth } from "@clerk/nextjs"; 4 | 5 | export default async function Layout({ children }: Readonly<{ children: React.ReactNode }>) { 6 | const user = await auth(); 7 | 8 | return ( 9 | <> 10 |
11 |
12 | 13 | {user && user.orgId &&
{children}
} 14 |
15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /app/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inferablehq/inferable/c87842ac7f638d72af9be72c3906cd2259ed49b7/app/app/favicon.ico -------------------------------------------------------------------------------- /app/app/favicon.ico-: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inferablehq/inferable/c87842ac7f638d72af9be72c3906cd2259ed49b7/app/app/favicon.ico- -------------------------------------------------------------------------------- /app/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function Home() { 4 | redirect("/clusters"); 5 | } 6 | -------------------------------------------------------------------------------- /app/app/providers.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import posthog from "posthog-js"; 3 | import { PostHogProvider } from "posthog-js/react"; 4 | import { useEffect } from "react"; 5 | 6 | export function PHProvider({ children }: { children: React.ReactNode }) { 7 | useEffect(() => { 8 | if (!process.env.NEXT_PUBLIC_POSTHOG_KEY) return; 9 | posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { 10 | api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST, 11 | capture_pageview: false, // Disable automatic pageview capture, as we capture manually 12 | }); 13 | }, []); 14 | 15 | return {children}; 16 | } 17 | -------------------------------------------------------------------------------- /app/app/switch-org/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Loading } from "@/components/loading"; 4 | import { useEffect } from "react"; 5 | 6 | export default function SwitchOrgPage() { 7 | useEffect(() => { 8 | window.location.reload(); 9 | window.location.href = "/clusters"; 10 | }, []); 11 | 12 | return ; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inferablehq/inferable/c87842ac7f638d72af9be72c3906cd2259ed49b7/app/assets/screenshot.png -------------------------------------------------------------------------------- /app/client/client.ts: -------------------------------------------------------------------------------- 1 | import { initClient } from "@ts-rest/core"; 2 | import { contract } from "./contract"; 3 | 4 | const isServer = typeof window === "undefined"; 5 | 6 | const getBaseUrl = () => { 7 | if (isServer) { 8 | return `${process.env.NEXT_PUBLIC_INFERABLE_API_URL || "https://api.inferable.ai"}`; 9 | } 10 | 11 | return `/api`; 12 | }; 13 | 14 | export const client = initClient(contract, { 15 | baseUrl: getBaseUrl(), 16 | baseHeaders: {}, 17 | }); 18 | 19 | export const clientWithAbortController = (signal: AbortSignal) => { 20 | return initClient(contract, { 21 | baseUrl: getBaseUrl(), 22 | baseHeaders: {}, 23 | abortSignal: signal, 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /app/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "gray", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /app/components/chat/ResultTable.css: -------------------------------------------------------------------------------- 1 | .ht_clone_top { 2 | z-index: 50 !important; 3 | } 4 | 5 | .ht_clone_left { 6 | z-index: 50 !important; 7 | } 8 | 9 | .ht_clone_top_left_corner { 10 | z-index: 50 !important; 11 | } 12 | -------------------------------------------------------------------------------- /app/components/chat/event-indicator.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function EventIndicator({ 4 | lastEventAt, 5 | hasPendingJobs, 6 | }: { 7 | lastEventAt: number; 8 | hasPendingJobs?: boolean; 9 | }) { 10 | const [hasRecentEvent, setHasRecentEvent] = useState(false); 11 | 12 | useEffect(() => { 13 | const timer = setInterval(() => { 14 | if (Date.now() - lastEventAt < 1000) { 15 | setHasRecentEvent(true); 16 | } else { 17 | setHasRecentEvent(false); 18 | } 19 | }, 500); 20 | 21 | return () => clearInterval(timer); 22 | }); 23 | 24 | const loading = hasPendingJobs || hasRecentEvent; 25 | 26 | return ( 27 |
31 |
35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /app/components/chat/typable.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { TypeAnimation } from "react-type-animation"; 3 | 4 | function TypableInner({ text, createdAt }: { text: string; createdAt: Date }) { 5 | if (new Date(createdAt).getTime() < Date.now() - 2000) { 6 | return text; 7 | } 8 | 9 | return ( 10 | str.split(/(?= )/)} // 'Lorem ipsum dolor' -> ['Lorem', ' ipsum', ' dolor'] 12 | sequence={[text, 3000]} 13 | speed={{ type: "keyStrokeDelayInMs", value: 30 }} 14 | omitDeletionAnimation={true} 15 | cursor={false} 16 | repeat={0} 17 | /> 18 | ); 19 | } 20 | 21 | export const Typable = React.memo(TypableInner, (prev, next) => { 22 | return prev.text === next.text; 23 | }); 24 | -------------------------------------------------------------------------------- /app/components/copy-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Button } from "@/components/ui/button"; 4 | import { Copy } from "lucide-react"; 5 | import { useState } from "react"; 6 | 7 | export function CopyButton({ text }: { text: string }) { 8 | const [copied, setCopied] = useState(false); 9 | 10 | const handleCopy = async () => { 11 | await navigator.clipboard.writeText(text); 12 | setCopied(true); 13 | setTimeout(() => setCopied(false), 2000); 14 | }; 15 | 16 | return ( 17 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /app/components/loading.tsx: -------------------------------------------------------------------------------- 1 | export function LoadingDots() { 2 | return ( 3 | 4 | 10 | ... 11 | 12 | 28 | 29 | ); 30 | } 31 | 32 | export function Loading({ text = "Loading" }: { text?: string }) { 33 | return ( 34 |
35 | {text} 36 | 37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /app/components/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inferablehq/inferable/c87842ac7f638d72af9be72c3906cd2259ed49b7/app/components/logo.png -------------------------------------------------------------------------------- /app/components/org-list.tsx: -------------------------------------------------------------------------------- 1 | import { OrganizationList, auth } from "@clerk/nextjs"; 2 | 3 | export async function OrgList() { 4 | const { orgId } = await auth(); 5 | 6 | if (orgId) { 7 | return null; 8 | } 9 | 10 | return ( 11 |
12 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /app/components/posthog-pageview.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { usePathname, useSearchParams } from "next/navigation"; 4 | import { useEffect } from "react"; 5 | import { usePostHog } from "posthog-js/react"; 6 | 7 | export default function PostHogPageView() { 8 | const pathname = usePathname(); 9 | const searchParams = useSearchParams(); 10 | const posthog = usePostHog(); 11 | useEffect(() => { 12 | // Track pageviews 13 | if (pathname && posthog) { 14 | let url = window.origin + pathname; 15 | if (searchParams?.toString()) { 16 | url = url + `?${searchParams.toString()}`; 17 | } 18 | posthog.capture("$pageview", { 19 | $current_url: url, 20 | }); 21 | } 22 | }, [pathname, searchParams, posthog]); 23 | 24 | return null; 25 | } 26 | -------------------------------------------------------------------------------- /app/components/rollbar-user.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useAuth, useUser } from "@clerk/nextjs"; 4 | import { useRollbarPerson } from "@rollbar/react"; 5 | 6 | export function RollbarUser() { 7 | const { user } = useUser(); 8 | const { orgRole, orgId, orgSlug } = useAuth(); 9 | 10 | useRollbarPerson({ 11 | firstName: user?.firstName, 12 | lastName: user?.lastName, 13 | email: 14 | user?.emailAddresses.find((email) => email.emailAddress)?.emailAddress ?? 15 | "", 16 | id: user?.id, 17 | organizationId: orgId, 18 | organizationName: orgSlug, 19 | organizationRole: orgRole, 20 | }); 21 | 22 | return null; 23 | } 24 | -------------------------------------------------------------------------------- /app/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; 4 | 5 | const Collapsible = CollapsiblePrimitive.Root; 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; 10 | 11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent }; 12 | -------------------------------------------------------------------------------- /app/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes {} 7 | 8 | const Input = React.forwardRef( 9 | ({ className, type, ...props }, ref) => { 10 | return ( 11 | 20 | ); 21 | }, 22 | ); 23 | Input.displayName = "Input"; 24 | 25 | export { Input }; 26 | -------------------------------------------------------------------------------- /app/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as LabelPrimitive from "@radix-ui/react-label"; 5 | import { cva, type VariantProps } from "class-variance-authority"; 6 | 7 | import { cn } from "@/lib/utils"; 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", 11 | ); 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )); 24 | Label.displayName = LabelPrimitive.Root.displayName; 25 | 26 | export { Label }; 27 | -------------------------------------------------------------------------------- /app/components/ui/multiselect.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inferablehq/inferable/c87842ac7f638d72af9be72c3906cd2259ed49b7/app/components/ui/multiselect.tsx -------------------------------------------------------------------------------- /app/components/ui/progress.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as ProgressPrimitive from "@radix-ui/react-progress"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | const Progress = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, value, ...props }, ref) => ( 12 | 20 | 24 | 25 | )); 26 | Progress.displayName = ProgressPrimitive.Root.displayName; 27 | 28 | export { Progress }; 29 | -------------------------------------------------------------------------------- /app/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ); 13 | } 14 | 15 | export { Skeleton }; 16 | -------------------------------------------------------------------------------- /app/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface TextareaProps 6 | extends React.TextareaHTMLAttributes {} 7 | 8 | const Textarea = React.forwardRef( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 |