roksta 0.3.1__cp314-cp314t-macosx_10_13_universal2.whl → 0.3.3__cp314-cp314t-macosx_10_13_universal2.whl

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.

Potentially problematic release.


This version of roksta might be problematic. Click here for more details.

Files changed (46) hide show
  1. roksta/ai/llm.cpython-314t-darwin.so +0 -0
  2. roksta/chat_workflow.cpython-314t-darwin.so +0 -0
  3. roksta/check_for_updates.cpython-314t-darwin.so +0 -0
  4. roksta/clarify_goal.cpython-314t-darwin.so +0 -0
  5. roksta/command_handlers/handle_auto_commit_command.cpython-314t-darwin.so +0 -0
  6. roksta/command_handlers/handle_building_command.cpython-314t-darwin.so +0 -0
  7. roksta/command_handlers/handle_dev_rate_command.cpython-314t-darwin.so +0 -0
  8. roksta/command_handlers/handle_linting_command.cpython-314t-darwin.so +0 -0
  9. roksta/command_handlers/handle_login_command.cpython-314t-darwin.so +0 -0
  10. roksta/command_handlers/handle_testing_command.cpython-314t-darwin.so +0 -0
  11. roksta/create_default_config.cpython-314t-darwin.so +0 -0
  12. roksta/enums.cpython-314t-darwin.so +0 -0
  13. roksta/env.cpython-314t-darwin.so +0 -0
  14. roksta/firebase_auth_web.cpython-314t-darwin.so +0 -0
  15. roksta/fix_tests.cpython-314t-darwin.so +0 -0
  16. roksta/gen_one_line_goal.cpython-314t-darwin.so +0 -0
  17. roksta/goal_workflow.cpython-314t-darwin.so +0 -0
  18. roksta/init_codebase.cpython-314t-darwin.so +0 -0
  19. roksta/lint_code.cpython-314t-darwin.so +0 -0
  20. roksta/logger.cpython-314t-darwin.so +0 -0
  21. roksta/make_issue.cpython-314t-darwin.so +0 -0
  22. roksta/new_features.cpython-314t-darwin.so +0 -0
  23. roksta/propose_solution.cpython-314t-darwin.so +0 -0
  24. roksta/roksta.cpython-314t-darwin.so +0 -0
  25. roksta/save_chat_transcript.cpython-314t-darwin.so +0 -0
  26. roksta/select_files.cpython-314t-darwin.so +0 -0
  27. roksta/tips.cpython-314t-darwin.so +0 -0
  28. roksta/utils.cpython-314t-darwin.so +0 -0
  29. roksta/write_code.cpython-314t-darwin.so +0 -0
  30. {roksta-0.3.1.dist-info → roksta-0.3.3.dist-info}/METADATA +2 -1
  31. {roksta-0.3.1.dist-info → roksta-0.3.3.dist-info}/RECORD +46 -33
  32. tests/functions/api_v1_02/__init__.py +2 -0
  33. tests/functions/api_v1_02/test__analytics.py +416 -0
  34. tests/functions/api_v1_02/test__gemini_proxy.py +352 -0
  35. tests/functions/api_v1_02/test__generic_proxy.py +428 -0
  36. tests/functions/api_v1_02/test__get_payment_details.py +356 -0
  37. tests/functions/api_v1_02/test__openai_proxy.py +449 -0
  38. tests/functions/api_v1_02/test__redeem_credit_code.py +167 -0
  39. tests/functions/api_v1_02/test__sync_emails.py +325 -0
  40. tests/functions/api_v1_02/test__take_payment.py +491 -0
  41. tests/functions/api_v1_02/test__use_activation_code.py +438 -0
  42. tests/functions/api_v1_02/test_proxy_keyword_replacement.py +557 -0
  43. tests/functions/api_v1_02/test_replace_keywords.py +74 -0
  44. {roksta-0.3.1.dist-info → roksta-0.3.3.dist-info}/WHEEL +0 -0
  45. {roksta-0.3.1.dist-info → roksta-0.3.3.dist-info}/entry_points.txt +0 -0
  46. {roksta-0.3.1.dist-info → roksta-0.3.3.dist-info}/top_level.txt +0 -0
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roksta
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: An AI coding assistant
5
5
  Author-email: Prash Naidu <prash@roksta.ai>
6
6
  Project-URL: Homepage, https://roksta.ai
@@ -27,6 +27,7 @@ Requires-Dist: pytest>=8.4.1; extra == "tests"
27
27
  Requires-Dist: pytest-asyncio>=1.0.0; extra == "tests"
28
28
  Requires-Dist: pytest-mock>=3.14.1; extra == "tests"
29
29
  Requires-Dist: ruff>=0.12.8; extra == "tests"
30
+ Requires-Dist: pytest-cov>=7.0.0; extra == "tests"
30
31
  Provides-Extra: build
31
32
  Requires-Dist: setuptools>=80.9.0; extra == "build"
32
33
  Requires-Dist: wheel>=0.45.1; extra == "build"
@@ -1,50 +1,51 @@
1
1
  roksta/default_config.cpython-314t-darwin.so,sha256=qVmZK893wlh3cnVQCefHp-PUn9Zfk9zbBpu9w3n05BY,102424
2
2
  roksta/get_failing_tests.cpython-314t-darwin.so,sha256=TgiPDwlMZlUssV_VAxkv2iITeamCP2-QGiK5sS8mI9o,241096
3
- roksta/select_files.cpython-314t-darwin.so,sha256=IBoV8bVdIWrbQ3zRj722ui0HatrA1ZzfHZyLILn-U2I,224704
3
+ roksta/select_files.cpython-314t-darwin.so,sha256=i7azNFwGLgqW0kywaeu-8WReijLxf8FkHH94BpnEVtA,224704
4
4
  roksta/run_cli_goal.cpython-314t-darwin.so,sha256=ttg_PJw87gmjhnXLV7cmYL7u9xJvmXaqemiGIOcHuPY,240624
5
- roksta/tips.cpython-314t-darwin.so,sha256=6OaQ3-fgsx590UZZTS1JJwVY9Yy_h15P-5rp9vU3kjw,85864
5
+ roksta/tips.cpython-314t-darwin.so,sha256=_GFurjxzjz3IUS2JAfLQ36eIv5JHA5Ra5QJ3L5H-wRc,85864
6
6
  roksta/codebase_listing.cpython-314t-darwin.so,sha256=RA8iTkU9V8T-OwmCvMWgvJyB8dmIriM7ByPW8oXAE_g,188856
7
7
  roksta/firebase.cpython-314t-darwin.so,sha256=jiDTKoAhLP8d3tplSitPXDZe1_bSoE3kJpsyBeDtCew,570960
8
- roksta/init_codebase.cpython-314t-darwin.so,sha256=SUfDXZeIJEn8dNWwmAjA7FZ9i7Shlpk0EC1GkdcxNv8,325160
8
+ roksta/init_codebase.cpython-314t-darwin.so,sha256=vRYR691LsKL3scDdtL5RCBGl7abgwvdEJMe_p2UEXws,374936
9
9
  roksta/checkpoints.cpython-314t-darwin.so,sha256=N1gnpCyta-9dtwXbfYk4YTEerexM8NMpjx70IEsRwho,271088
10
10
  roksta/balance.cpython-314t-darwin.so,sha256=PcZawKA2S-ZJw7DZPgMNg7SggYkYFnyg5Gwebt-G2t8,439536
11
- roksta/create_default_config.cpython-314t-darwin.so,sha256=HBTlwgQSQu3BbOnUt-B2K_3g3ZdwlZdad-YxrAxhXtM,121888
12
- roksta/lint_code.cpython-314t-darwin.so,sha256=jIwQnQ21ApKnyEpeV-AQbXavlkZLYRqrom3WViuvi0k,241408
13
- roksta/clarify_goal.cpython-314t-darwin.so,sha256=m_Teljpp7EjbXTYHChiwf6eV9aHV88k9MhgaXf4DDxQ,224720
14
- roksta/firebase_auth_web.cpython-314t-darwin.so,sha256=ylHP98rxSwtAGyB15TAfJp4uGWDGUptioOc9jgM6AQ0,539064
15
- roksta/roksta.cpython-314t-darwin.so,sha256=orj9eC601njlwTg4nUgQMKPYIsIRiXwaKg_UEt7ZLyI,638080
11
+ roksta/create_default_config.cpython-314t-darwin.so,sha256=e2vg-eL5wJmKX55pTP22gY-7u84iLPhHr7pbPgUcTlA,121872
12
+ roksta/save_chat_transcript.cpython-314t-darwin.so,sha256=BnmEe-RSc6z1BWoMi9GTuA2IE5zJqckdrbX0pNlzGA8,224568
13
+ roksta/lint_code.cpython-314t-darwin.so,sha256=ReFQCO8ceBgiZD62UZsaHus7wjRC3IbvXf7eK7G0yAU,241408
14
+ roksta/clarify_goal.cpython-314t-darwin.so,sha256=SOCw-JC9TqA1BZIcSf1PUZHsgYtuXVl_Pf3M8UboAbA,224720
15
+ roksta/firebase_auth_web.cpython-314t-darwin.so,sha256=t0pwsna5oy-53eTMpgXV7pvl6MndFtUn5f-uAb5VHZA,539064
16
+ roksta/roksta.cpython-314t-darwin.so,sha256=dvXVoqi1A9SVfiNv7L62x1qRbQDWYNhIW9OqwSjfZfI,638080
16
17
  roksta/firebase_config.cpython-314t-darwin.so,sha256=50G4FEKgT6xC1EkRY7t9K_sV-qaZfJ7kxhN2S9Z3Ujg,86424
17
- roksta/propose_solution.cpython-314t-darwin.so,sha256=Q2CzZCJ5OJuKk4MaiVrHbW4JeFz6VydkQwRYZBRlne0,224408
18
+ roksta/propose_solution.cpython-314t-darwin.so,sha256=UwKDYhn4r2aBV8hyu4yLw8wfdxOV6Urlq_4OQdMNxsc,207896
18
19
  roksta/parse_readme.cpython-314t-darwin.so,sha256=wt3fxkkhrw9sb7Mrx03_7l1FOACFtDHH75rX2DsONNs,224144
19
- roksta/gen_one_line_goal.cpython-314t-darwin.so,sha256=WKgBUMKhdtc-KhXRF3YdYie_ewhti8O0rdd8Re9Kof0,224680
20
- roksta/check_for_updates.cpython-314t-darwin.so,sha256=XBDWNyKZKuQ9g42rfhkWjdRWkOzjmkBuIV9Ky3z4E60,323704
20
+ roksta/gen_one_line_goal.cpython-314t-darwin.so,sha256=o3prlvNNJ_hwPUaUj9jYvG0nQpdmAUWdFPksdRMwqrI,224680
21
+ roksta/check_for_updates.cpython-314t-darwin.so,sha256=_5NXBGJ0xdSsC-npTGSdG2QwmBIjkXFl1kuTpTVFnNM,323704
21
22
  roksta/gen_codebase_summaries.cpython-314t-darwin.so,sha256=caLC6vHBDUINIBUtDOSSl2fIKmMztNjKMQx_o3Xado8,720688
22
23
  roksta/main.cpython-314t-darwin.so,sha256=ZJuA1mhClpGYd-AnbvM_gApJCn8hCLLbOKlFrLsgj_0,155432
23
- roksta/enums.cpython-314t-darwin.so,sha256=zy6rRIEXtNW37BA76zR9tPzMA_j-wG-Si6f2e6C7gKc,322320
24
+ roksta/enums.cpython-314t-darwin.so,sha256=cV5j_scSnb5xFPzihRYmd6WtiNVrrwWgJekcdNwDFWk,322320
24
25
  roksta/__init__.cpython-314t-darwin.so,sha256=wi8Vybo_OIgiP0nw3dYRY1WuU-_XToX7Kg214k5KG1Q,85824
25
- roksta/goal_workflow.cpython-314t-darwin.so,sha256=1CJMqXEPWDG5s1-tAEL_UIfW-DBA3XzFl4w8VLwI1rs,571816
26
+ roksta/goal_workflow.cpython-314t-darwin.so,sha256=ptyo4x1M8G4xBssT3BVMWMYRzDB4Fd04RPe0W32h3_E,571816
26
27
  roksta/analytics.cpython-314t-darwin.so,sha256=QPUKzsnhI6HbbYK4ek6kWkYgtzAofem0JSL8hV5Qy1Q,322928
27
- roksta/write_code.cpython-314t-darwin.so,sha256=bmPIEDgwjHioODH89S8OvOp-2_L1C533MTvmBBJ5MR8,207920
28
- roksta/env.cpython-314t-darwin.so,sha256=zz_KR6tWd6K42ZzaqxDVcq8Fw0YHCztDjYIi02CveUU,87928
29
- roksta/new_features.cpython-314t-darwin.so,sha256=aCz4bcDCsIqvVmq0L13BrRpZNA-DF2mTywPZKn838ak,85904
28
+ roksta/write_code.cpython-314t-darwin.so,sha256=hVqAQ9T_paeRuGV2ElNt1VFjWPnUaTW7zXrCQcaNup4,207920
29
+ roksta/env.cpython-314t-darwin.so,sha256=9zDuBs-sN_g4msUIWX7RMQXDDmONtFr-hdTF2czmLP0,87928
30
+ roksta/new_features.cpython-314t-darwin.so,sha256=BwisP58GGEi_pPs_Q4SD6jfENflhy9pBC3Z90mWs5UA,85904
30
31
  roksta/build_project.cpython-314t-darwin.so,sha256=4F7-EKDWTNCFQ3laC2_qU_5Y7hB7YhUntTpCY_84WNM,207960
31
- roksta/fix_tests.cpython-314t-darwin.so,sha256=OMLvol57GDjS5ygpt_Dw66OoMpSxwEDUgXOLJvspbiE,257632
32
- roksta/logger.cpython-314t-darwin.so,sha256=upcimtFREbc9WKSwGoEBypFX_uM0jwZqjfvOvIhyKjw,155216
33
- roksta/chat_workflow.cpython-314t-darwin.so,sha256=Sskw4w_0WaxhEaLN3diC3fbnUK_9lPH_0mzpoQX7hy0,290840
32
+ roksta/fix_tests.cpython-314t-darwin.so,sha256=9gEd76JwRw6CfjpnTnnutFlUeVX44mx0ZU0oFAvHZzk,257632
33
+ roksta/logger.cpython-314t-darwin.so,sha256=dS3nkICf5rs50jppXacQE4zWPJqVOt6cah_DBwdL5Cw,155216
34
+ roksta/chat_workflow.cpython-314t-darwin.so,sha256=qgQUBii--TVD5qHVjpyU_pwJH97GHiGAMy6uimWVy6w,290712
34
35
  roksta/response_formats.cpython-314t-darwin.so,sha256=8pWaDZuRf-9ZUpR8p8kZkIOg0ovPKGbQ44DE1i2ZRng,121208
35
36
  roksta/get_codebase_structure.cpython-314t-darwin.so,sha256=L4OJLaFY0K-rjQYH3ur_w01ag2SC3JojmJapfcEl_Ts,239520
36
- roksta/make_issue.cpython-314t-darwin.so,sha256=Maf34ULyKoPtPrHwISHikTunVNkQ0ATIJBbea8tQYWw,222240
37
+ roksta/make_issue.cpython-314t-darwin.so,sha256=89-HoemTI3hU94_Ll7p4NpVGCNqkQpgWm07dcUEfEyc,238624
37
38
  roksta/rewrite_goal.cpython-314t-darwin.so,sha256=-MtU1o7UfREP8kOXzpmtz5zTxu6gcEoRYh_I2_byl8k,207872
38
- roksta/utils.cpython-314t-darwin.so,sha256=sM4VflnqWaHaFazJEtDjIzQThL4om65yY6TSwtpt1Tg,721280
39
+ roksta/utils.cpython-314t-darwin.so,sha256=6OBmmowgYRIvqZIMri0UjDlJeV3CRkdeQOvf54VuZZc,721280
39
40
  roksta/extended_text_area.cpython-314t-darwin.so,sha256=lkE5lVWoNvXNA2X6HPuBzVSJxkix6LtcdbjCeaXoT7Y,324072
40
- roksta/command_handlers/handle_dev_rate_command.cpython-314t-darwin.so,sha256=AAnag3-7wKJJ_F8WeNiWHt6BQZj_HNOop6gAArlfxmg,156288
41
- roksta/command_handlers/handle_building_command.cpython-314t-darwin.so,sha256=wBNgD74187jXQQkNk99Zh60UCq0fbOCxGlM_jO1e710,156256
41
+ roksta/command_handlers/handle_dev_rate_command.cpython-314t-darwin.so,sha256=-vtnnWus_XNrltvVM1duH1D-TlbcfyAJ4_0EUXYoIiY,156288
42
+ roksta/command_handlers/handle_building_command.cpython-314t-darwin.so,sha256=U1yasCfFL1jNOnEBBQ971E0C-sflfE1PVUrQGQLjc8Q,156256
42
43
  roksta/command_handlers/handle_feedback_command.cpython-314t-darwin.so,sha256=Md7l2cOdUqibxfBpWGPQXGgLwzNNwmt2_a3mY5EBt28,207200
43
44
  roksta/command_handlers/handle_help_command.cpython-314t-darwin.so,sha256=J8QCKRXTlU6hcyUkhMK8JWgLx_DOvF3xdDRajuvyxaI,220664
44
45
  roksta/command_handlers/handle_quit_command.cpython-314t-darwin.so,sha256=CSUx0Ro-H3FFmROHA6r_o_lZaoBX2qSF3a_sJc7Hrrs,87480
45
- roksta/command_handlers/handle_login_command.cpython-314t-darwin.so,sha256=9LPEyxt6A4AzE3gxb-V1OsQOEgw8loLo5mCIBqRicAc,240616
46
+ roksta/command_handlers/handle_login_command.cpython-314t-darwin.so,sha256=To06nknX3wEYbTkLL2uJZ7RRMHzJ45b_w2-U4je1tJA,240616
46
47
  roksta/command_handlers/handle_usage_command.cpython-314t-darwin.so,sha256=74PqVzmzbVk6e1k-mwsfk4LC0BXyubmkopyf-IdA4cE,208408
47
- roksta/command_handlers/handle_linting_command.cpython-314t-darwin.so,sha256=tHwwknorEovuetjC_FztxR5c_QZgK_yHNTKjfuDeUec,156208
48
+ roksta/command_handlers/handle_linting_command.cpython-314t-darwin.so,sha256=02z3TzcHSSMvfcJlm_vyElStET1_ZX4FSLoYf3yNqz4,156208
48
49
  roksta/command_handlers/handle_payment_details_command.cpython-314t-darwin.so,sha256=u8rC8ob2Lyg_I6whji9HoI9HOhNJXIWStIgZ9TEZC7o,190616
49
50
  roksta/command_handlers/handle_activate_command.cpython-314t-darwin.so,sha256=yIwEDboeOlaClnreMQkqeLAfapkqi90SBLKrJnTgtUQ,273856
50
51
  roksta/command_handlers/handle_add_funds_command.cpython-314t-darwin.so,sha256=fLHkUICkWaqzMXAdZ-en7L4R9Vq2ECJvIDpFl33EiPo,241360
@@ -52,18 +53,18 @@ roksta/command_handlers/handle_logout_command.cpython-314t-darwin.so,sha256=ISQ2
52
53
  roksta/command_handlers/handle_request_activation_command.cpython-314t-darwin.so,sha256=cF1bfHgPZDtKGkafpDhgq3ZcyCi5heT9voiEZTH2R3g,223928
53
54
  roksta/command_handlers/handle_init_command.cpython-314t-darwin.so,sha256=yQQqSFrfLTXjq3H1NU_A052G9zHJLFbPC4JIBl0vRfI,190552
54
55
  roksta/command_handlers/__init__.cpython-314t-darwin.so,sha256=RIcalLE1Ar7Ql5U2jYlfmdMTOKbaZOGzcXISvJ--F9Q,86448
55
- roksta/command_handlers/handle_auto_commit_command.cpython-314t-darwin.so,sha256=H4_wQivuFX1gxKG8VdRw6EkLoWj-E2zvYEqdKWASTq8,155792
56
+ roksta/command_handlers/handle_auto_commit_command.cpython-314t-darwin.so,sha256=ftbxAbqfgZpg8AI6d-VnCjWrrEO3bWdEEhqExcNAazY,155792
56
57
  roksta/command_handlers/handle_goal_command.cpython-314t-darwin.so,sha256=Y8xefxtr5CQiJi-oww3dGVICQCFbfGEphYI-P8wOfXQ,190552
57
58
  roksta/command_handlers/handle_auto_charge_command.cpython-314t-darwin.so,sha256=VT7c8OZmT_NdVCjWvnJ_qHFW_8S_3H4hm-b8EcBPZQo,173120
58
59
  roksta/command_handlers/handle_redeem_command.cpython-314t-darwin.so,sha256=WLil8Kav2N2ziMySDInhzjq25GC5jD2eP8_L5BgT5O4,191232
59
60
  roksta/command_handlers/handle_chat_command.cpython-314t-darwin.so,sha256=nzPY8ZJGxx1YJH-VVMBzgDqgYi3fcEfCy6NKloXMRJE,157240
60
- roksta/command_handlers/handle_testing_command.cpython-314t-darwin.so,sha256=qe4Jipz4_xFOejfDi3kko6ZG2mkygsrHOBCnzIEFDyw,156256
61
+ roksta/command_handlers/handle_testing_command.cpython-314t-darwin.so,sha256=aHdDcUHvRnGJF4Ttuu0SgQHRtEW-b1Ltl7J5FQFaa3E,156256
61
62
  roksta/ai/openai.cpython-314t-darwin.so,sha256=cVUlUnnyuB7_Ix95g25Nq5A7gIwwAIHqhhHjCNhE_1w,323840
62
63
  roksta/ai/call_ai.cpython-314t-darwin.so,sha256=utAI0UB3o0i3wwxJTVSfaNFoN85FXkzw14IeJSUuLZY,257648
63
64
  roksta/ai/__init__.cpython-314t-darwin.so,sha256=ADxSpO91HkA6gk1RUfnjAxO8etJfH2MS2Ku7jcZI2JI,85824
64
65
  roksta/ai/generic.cpython-314t-darwin.so,sha256=FXZqKaZvr5zusnC1hGgPCqWqWslgrsAlgGuaGAM0nR0,340256
65
66
  roksta/ai/gemini.cpython-314t-darwin.so,sha256=WBi3VWJHLl3oyVKOpHFJHjUlxQ3ZzEcch2dQXTCkuzs,439584
66
- roksta/ai/llm.cpython-314t-darwin.so,sha256=h4ttSLyebHbvoWNe3Cvo3NDYlEFhVIn31BZyNCWgRNA,271880
67
+ roksta/ai/llm.cpython-314t-darwin.so,sha256=vyBa-TTUKx2sAY_si5dBrB-rF2M4Kqj-Ki8G3T8bhKw,271880
67
68
  roksta/ai/tools/final_response.cpython-314t-darwin.so,sha256=ofB0mXDgvG06RGPoR_NiS_Yva_Oqbx8LqkLuXFaSXVA,88040
68
69
  roksta/ai/tools/shell_any.cpython-314t-darwin.so,sha256=-QRkZKu65jjj32Uq2Vz11gSODUMPyGW-g7OW3hH_MGE,240960
69
70
  roksta/ai/tools/get_file_summaries.cpython-314t-darwin.so,sha256=jOegeSULw86gsDsMnlDg8RT9eoop7B_3e-pEcHTlKBI,155976
@@ -82,6 +83,18 @@ tests/functions/test_utils.py,sha256=_zlgSa99JYVyJ0LDe3yaPztS92kqGRKkgjon__XmfFM
82
83
  tests/functions/test_auth.py,sha256=I3oFTw2LTuUsnQ75v5SCfgUPnpel_pDKqUH0VAJpXQw,992
83
84
  tests/functions/__init__.py,sha256=mLXx3UARcv07vs_fGJuy3L5ZRn9IRsF9zIuL5IOnwdk,95
84
85
  tests/functions/test_main.py,sha256=h0W_4ISo95WzRy2HpXZw3cuNOTcYk_2QCIZffZJEfEU,2575
86
+ tests/functions/api_v1_02/test__sync_emails.py,sha256=OTyf2YbBK7e4pWIQTUGYR4x6il1Hb3g4FYqQ_fRj1nA,12699
87
+ tests/functions/api_v1_02/test__take_payment.py,sha256=I-XJasGuLW5wTMAu4nAgFkA8Mo_zVpGPvkJ2LrrJGCk,18022
88
+ tests/functions/api_v1_02/test_replace_keywords.py,sha256=pa7bZ8I9XgtI5dUZq-efcHh9amN2_XHP8abXYqtDGc0,2683
89
+ tests/functions/api_v1_02/test__gemini_proxy.py,sha256=mf8ubRmNxxxN80H6EA-iDPwu6Oue6Rmgxl6tiFNpfrU,13344
90
+ tests/functions/api_v1_02/test_proxy_keyword_replacement.py,sha256=I5H73_QydSKLiDp7hDHGHbSkDOdv-BT4gYHGqEiVtM0,23632
91
+ tests/functions/api_v1_02/test__analytics.py,sha256=oKjd7_zjnttcb-5BuA93yllkm0OOF4YWnfTUW1-icnM,15806
92
+ tests/functions/api_v1_02/__init__.py,sha256=3RCSoj_5UQPw9Z5NeAgYz2s4gfcZIi7g36qk_Ed5TiA,124
93
+ tests/functions/api_v1_02/test__use_activation_code.py,sha256=tNyTkkRtrpjei-7F31UNwrcU-PbP-QnkWNU7h2n5Yqo,16960
94
+ tests/functions/api_v1_02/test__redeem_credit_code.py,sha256=7GD3tGgO2Lk0BCjUmzZACJiwocEhLBvXrrut0x13IWU,6347
95
+ tests/functions/api_v1_02/test__openai_proxy.py,sha256=xlO2zmG64LlrKrbjFz-ds6Map7vy4SjIuHfZJDAqGK8,17726
96
+ tests/functions/api_v1_02/test__get_payment_details.py,sha256=i5Px3NkLxqw8D3tVPrYdRJJF5jlNmysSuX_NNolbIa4,13735
97
+ tests/functions/api_v1_02/test__generic_proxy.py,sha256=KZkOtmc71aOnWlz2L7B6CFhRNEV73bExG3GR14oD2L0,17673
85
98
  tests/functions/api_v1_01/test__sync_emails.py,sha256=OTyf2YbBK7e4pWIQTUGYR4x6il1Hb3g4FYqQ_fRj1nA,12699
86
99
  tests/functions/api_v1_01/test__take_payment.py,sha256=I-XJasGuLW5wTMAu4nAgFkA8Mo_zVpGPvkJ2LrrJGCk,18022
87
100
  tests/functions/api_v1_01/test__gemini_proxy.py,sha256=mf8ubRmNxxxN80H6EA-iDPwu6Oue6Rmgxl6tiFNpfrU,13344
@@ -102,8 +115,8 @@ tests/functions/api_v1_00/test__redeem_credit_code.py,sha256=7GD3tGgO2Lk0BCjUmzZ
102
115
  tests/functions/api_v1_00/test__openai_proxy.py,sha256=xlO2zmG64LlrKrbjFz-ds6Map7vy4SjIuHfZJDAqGK8,17726
103
116
  tests/functions/api_v1_00/test__get_payment_details.py,sha256=i5Px3NkLxqw8D3tVPrYdRJJF5jlNmysSuX_NNolbIa4,13735
104
117
  tests/functions/api_v1_00/test__generic_proxy.py,sha256=KZkOtmc71aOnWlz2L7B6CFhRNEV73bExG3GR14oD2L0,17673
105
- roksta-0.3.1.dist-info/RECORD,,
106
- roksta-0.3.1.dist-info/WHEEL,sha256=ERcDdRDi5tXqNjUI3Zpgr5_CkfUS0k_e9FvQ5FQhNCU,143
107
- roksta-0.3.1.dist-info/entry_points.txt,sha256=mzRdYg_DlzZRwjxYUt9-gyoRCkM1QBTeTbwETgiTdGw,44
108
- roksta-0.3.1.dist-info/top_level.txt,sha256=lvciNZQ1dPGXpiCLdWVXK03n9fKHjbQdwjqQbnUjeYM,13
109
- roksta-0.3.1.dist-info/METADATA,sha256=l3i3WQqIWKNwBVYQ1Eaw_1pZfMrIxEqQWipD2s_xId0,1456
118
+ roksta-0.3.3.dist-info/RECORD,,
119
+ roksta-0.3.3.dist-info/WHEEL,sha256=ERcDdRDi5tXqNjUI3Zpgr5_CkfUS0k_e9FvQ5FQhNCU,143
120
+ roksta-0.3.3.dist-info/entry_points.txt,sha256=mzRdYg_DlzZRwjxYUt9-gyoRCkM1QBTeTbwETgiTdGw,44
121
+ roksta-0.3.3.dist-info/top_level.txt,sha256=lvciNZQ1dPGXpiCLdWVXK03n9fKHjbQdwjqQbnUjeYM,13
122
+ roksta-0.3.3.dist-info/METADATA,sha256=3YFeTW_cI5KLOtqNLFDGbETD6WwKTqmjuiHUH1dDsz0,1507
@@ -0,0 +1,2 @@
1
+ # tests.functions.api_v1_00 package marker
2
+ # Allows tests under this directory to be imported with package-qualified names.
@@ -0,0 +1,416 @@
1
+ import os
2
+ import sys
3
+ import json
4
+ import types
5
+ import importlib
6
+ from unittest.mock import patch, Mock
7
+
8
+
9
+ # Ensure the functions/ directory is importable as a top-level module location
10
+ PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
11
+ FUNCTIONS_DIR = os.path.join(PROJECT_ROOT, 'functions')
12
+ if FUNCTIONS_DIR not in sys.path:
13
+ sys.path.insert(0, FUNCTIONS_DIR)
14
+
15
+ # -----------------------------
16
+ # Provide lightweight fake modules to satisfy imports inside _analytics
17
+ # These are minimal and will be patched in individual tests as needed.
18
+ # -----------------------------
19
+ # Save any originals so we can restore them after import
20
+ _orig_sys_modules = {}
21
+ _names_to_fake = ['firebase_functions', 'utils', 'auth', 'httpx']
22
+ for name in _names_to_fake:
23
+ _orig_sys_modules[name] = sys.modules.get(name)
24
+
25
+ # Fake firebase_functions.https_fn.Response to capture returned data
26
+ firebase_functions = types.ModuleType('firebase_functions')
27
+
28
+ class FakeResponse:
29
+ def __init__(self, response=None, mimetype=None, status=200, **kwargs):
30
+ # Mirror the small subset of the interface tests expect
31
+ self.status_code = status
32
+ if isinstance(response, (dict, list)):
33
+ self._body_text = json.dumps(response)
34
+ else:
35
+ self._body_text = '' if response is None else response
36
+ self.headers = kwargs.get('headers', {})
37
+
38
+ def get_data(self, as_text=False):
39
+ if as_text:
40
+ return self._body_text
41
+ return self._body_text.encode('utf-8')
42
+
43
+ firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
44
+ sys.modules['firebase_functions'] = firebase_functions
45
+
46
+ # Fake utils module (avoid google.cloud import at module import time)
47
+ utils_mod = types.ModuleType('utils')
48
+
49
+ def _dummy_get_secret_key(name: str) -> str:
50
+ return 'DUMMY_SECRET'
51
+
52
+ # create_json_response should return a firebase_functions.https_fn.Response-like object
53
+ # with a JSON body containing at least 'success' and 'message' keys, and an HTTP status code.
54
+ def _dummy_create_json_response(success: bool, payload, status_code: int = 200, headers: dict | None = None):
55
+ body = {'success': success, 'message': payload}
56
+ return firebase_functions.https_fn.Response(response=body, status=status_code, headers=headers or {})
57
+
58
+ utils_mod.get_secret_key = _dummy_get_secret_key
59
+ utils_mod.create_json_response = _dummy_create_json_response
60
+ sys.modules['utils'] = utils_mod
61
+
62
+ # Fake auth module (validate_auth_key will be patched per-test as needed)
63
+ auth_mod = types.ModuleType('auth')
64
+
65
+ def _simple_validate_auth_key(val: str) -> bool:
66
+ return bool(val)
67
+
68
+ auth_mod.validate_auth_key = _simple_validate_auth_key
69
+ sys.modules['auth'] = auth_mod
70
+
71
+ # Fake httpx module to avoid external dependency; tests will patch Client behavior
72
+ httpx_mod = types.ModuleType('httpx')
73
+
74
+ class Request:
75
+ def __init__(self, method, url, headers=None, content=None):
76
+ self.method = method
77
+ self.url = url
78
+ self.headers = headers or {}
79
+ self.content = content
80
+
81
+ class _DummyResponse:
82
+ def __init__(self, status_code=200, text='', json_data=None, request=None, headers=None):
83
+ self.status_code = status_code
84
+ self.text = text if text is not None else ''
85
+ self._json = json_data
86
+ self.request = request
87
+ self.headers = headers or {}
88
+ # Provide a reason_phrase attribute similar to real httpx.Response
89
+ self.reason_phrase = self.text or ''
90
+
91
+ def json(self):
92
+ # Prefer explicit JSON payload if provided, otherwise try to parse text
93
+ if self._json is not None:
94
+ return self._json
95
+ try:
96
+ return json.loads(self.text) if self.text else {}
97
+ except Exception:
98
+ return {}
99
+
100
+ def raise_for_status(self):
101
+ if 400 <= self.status_code:
102
+ raise httpx_mod.HTTPStatusError(response=self)
103
+
104
+ class _DummyHttpxClient:
105
+ def __enter__(self):
106
+ return self
107
+
108
+ def __exit__(self, exc_type, exc, tb):
109
+ return False
110
+
111
+ def post(self, url, json=None, timeout=30):
112
+ resp = _DummyResponse(status_code=200, text='', json_data=None)
113
+ resp.raise_for_status = Mock(return_value=None)
114
+ resp.json = Mock(return_value={})
115
+ return resp
116
+
117
+ class _DummyAsyncClient:
118
+ async def __aenter__(self):
119
+ return self
120
+
121
+ async def __aexit__(self, exc_type, exc, tb):
122
+ return False
123
+
124
+ async def get(self, url, headers=None, timeout=None):
125
+ resp = _DummyResponse(status_code=200, text='', json_data=None)
126
+ resp.raise_for_status = Mock(return_value=None)
127
+ resp.json = Mock(return_value={})
128
+ return resp
129
+
130
+ async def post(self, url, json=None, data=None, headers=None, timeout=None):
131
+ resp = _DummyResponse(status_code=200, text='', json_data=None)
132
+ resp.raise_for_status = Mock(return_value=None)
133
+ resp.json = Mock(return_value={})
134
+ return resp
135
+
136
+ httpx_mod.Client = _DummyHttpxClient
137
+ httpx_mod.AsyncClient = _DummyAsyncClient
138
+ httpx_mod.Response = _DummyResponse
139
+ httpx_mod.Request = Request
140
+ httpx_mod.Headers = dict
141
+
142
+ class _HTTPStatusError(Exception):
143
+ def __init__(self, *args, request=None, response=None):
144
+ # Support both signatures:
145
+ # HTTPStatusError(response)
146
+ # HTTPStatusError(message, request=..., response=...)
147
+ message = ""
148
+ if response is None and len(args) == 1 and not isinstance(args[0], str):
149
+ # Single positional non-string arg -> treated as response
150
+ response = args[0]
151
+ elif len(args) >= 1 and isinstance(args[0], str):
152
+ message = args[0]
153
+ elif len(args) > 1:
154
+ message = args[0]
155
+ super().__init__(message)
156
+ self.request = request
157
+ self.response = response
158
+
159
+ def __str__(self):
160
+ try:
161
+ return f"{self.args[0]} (status={getattr(self.response,'status_code',None)})"
162
+ except Exception:
163
+ return self.args[0] if self.args else "HTTPStatusError"
164
+
165
+ class _RequestError(Exception):
166
+ def __init__(self, message="", request=None):
167
+ super().__init__(message)
168
+ self.request = request
169
+
170
+ httpx_mod.HTTPStatusError = _HTTPStatusError
171
+ httpx_mod.RequestError = _RequestError
172
+ sys.modules['httpx'] = httpx_mod
173
+
174
+ # -----------------------------
175
+ # Import the module under test after preparing the fake imports
176
+ # -----------------------------
177
+ repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
178
+ functions_root = os.path.join(repo_root, 'functions')
179
+ module_path = os.path.join(functions_root, 'api_v1_00', '_analytics.py')
180
+ spec = importlib.util.spec_from_file_location('api_v1_00._analytics', module_path)
181
+ _analytics = importlib.util.module_from_spec(spec)
182
+ spec.loader.exec_module(_analytics)
183
+
184
+ # Restore original sys.modules mappings to avoid side-effects for other tests
185
+ for name, orig in _orig_sys_modules.items():
186
+ if orig is None:
187
+ try:
188
+ del sys.modules[name]
189
+ except KeyError:
190
+ pass
191
+ else:
192
+ sys.modules[name] = orig
193
+
194
+ # Simple helper request stub used in the tests
195
+ class DummyRequest:
196
+ def __init__(self, headers=None, method='POST', json_data=None, raise_on_get_json=False):
197
+ self.headers = headers or {}
198
+ self.method = method
199
+ self._json_data = json_data
200
+ self._raise = raise_on_get_json
201
+
202
+ def get_json(self, silent=False):
203
+ if self._raise:
204
+ raise Exception('Malformed JSON')
205
+ return self._json_data
206
+
207
+
208
+ def _parse_response(resp):
209
+ data = resp.get_data(as_text=True)
210
+ return json.loads(data)
211
+
212
+
213
+ # -----------------------------
214
+ # Tests
215
+ # -----------------------------
216
+
217
+ def test_missing_auth_header_returns_401():
218
+ req = DummyRequest(headers={}, method='POST')
219
+ resp = _analytics._analytics(req)
220
+ assert resp.status_code == 401
221
+ payload = _parse_response(resp)
222
+ assert payload['success'] is False
223
+ assert 'Missing authentication key' in payload['message']
224
+
225
+
226
+ def test_invalid_auth_key_returns_403():
227
+ headers = {_analytics.AUTH_HEADER_NAME: 'bad-token'}
228
+ req = DummyRequest(headers=headers, method='POST')
229
+ with patch.object(_analytics, 'validate_auth_key', return_value=False):
230
+ resp = _analytics._analytics(req)
231
+ assert resp.status_code == 403
232
+ payload = _parse_response(resp)
233
+ assert payload['success'] is False
234
+ assert 'Invalid authentication key' in payload['message']
235
+
236
+
237
+ def test_non_post_method_returns_405():
238
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
239
+ req = DummyRequest(headers=headers, method='GET')
240
+ with patch.object(_analytics, 'validate_auth_key', return_value=True):
241
+ resp = _analytics._analytics(req)
242
+ assert resp.status_code == 405
243
+ payload = _parse_response(resp)
244
+ assert payload['success'] is False
245
+ assert 'POST method required' in payload['message']
246
+
247
+
248
+ def test_malformed_json_returns_400():
249
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
250
+ req = DummyRequest(headers=headers, method='POST', raise_on_get_json=True)
251
+ with patch.object(_analytics, 'validate_auth_key', return_value=True):
252
+ resp = _analytics._analytics(req)
253
+ assert resp.status_code == 400
254
+ payload = _parse_response(resp)
255
+ assert payload['success'] is False
256
+ assert 'Invalid JSON payload' in payload['message']
257
+
258
+
259
+ def test_missing_required_fields_returns_400():
260
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
261
+ # missing measurement_id
262
+ req = DummyRequest(headers=headers, method='POST', json_data={'client_id': 'c', 'events': [{'name': 'e'}]})
263
+ with patch.object(_analytics, 'validate_auth_key', return_value=True):
264
+ resp = _analytics._analytics(req)
265
+ assert resp.status_code == 400
266
+ payload = _parse_response(resp)
267
+ assert payload['success'] is False
268
+ assert 'Missing required fields' in payload['message']
269
+
270
+
271
+ def test_invalid_events_field_returns_400_for_empty_or_non_list():
272
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
273
+
274
+ # events is empty list
275
+ req_empty = DummyRequest(headers=headers, method='POST', json_data={'measurement_id': 'm', 'client_id': 'c', 'events': []})
276
+ with patch.object(_analytics, 'validate_auth_key', return_value=True):
277
+ resp = _analytics._analytics(req_empty)
278
+ assert resp.status_code == 400
279
+ payload = _parse_response(resp)
280
+ assert payload['success'] is False
281
+ assert 'Missing required fields' in payload['message']
282
+
283
+ # events is not a list
284
+ req_not_list = DummyRequest(headers=headers, method='POST', json_data={'measurement_id': 'm', 'client_id': 'c', 'events': 'nope'})
285
+ with patch.object(_analytics, 'validate_auth_key', return_value=True):
286
+ resp = _analytics._analytics(req_not_list)
287
+ assert resp.status_code == 400
288
+ payload = _parse_response(resp)
289
+ assert payload['success'] is False
290
+ assert "'events' field must be a non-empty list" in payload['message']
291
+
292
+
293
+ def test_secret_retrieval_failure_returns_500():
294
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
295
+ req_payload = {'measurement_id': 'm', 'client_id': 'c', 'events': [{'name': 'e'}]}
296
+ req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
297
+ with patch.object(_analytics, 'validate_auth_key', return_value=True), patch.object(_analytics, 'get_secret_key', side_effect=Exception('boom')):
298
+ resp = _analytics._analytics(req)
299
+ assert resp.status_code == 500
300
+ payload = _parse_response(resp)
301
+ assert payload['success'] is False
302
+ assert 'Could not retrieve GA secret' in payload['message']
303
+
304
+
305
+ def test_successful_flow_calls_httpx_with_expected_url_and_payload():
306
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
307
+ measurement_id = 'MEAS_ABC'
308
+ client_id = 'roksta_console'
309
+ events = [{'name': 'evt', 'params': {'a': 1}}]
310
+ user_id = 'user-123'
311
+ req_payload = {'measurement_id': measurement_id, 'client_id': client_id, 'events': events, 'user_id': user_id}
312
+ req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
313
+
314
+ # Recording client to capture call details
315
+ class RecordingClient:
316
+ def __init__(self):
317
+ self.post_called = False
318
+ self.last_url = None
319
+ self.last_json = None
320
+ self.last_timeout = None
321
+
322
+ def __enter__(self):
323
+ return self
324
+
325
+ def __exit__(self, exc_type, exc, tb):
326
+ return False
327
+
328
+ def post(self, url, json=None, timeout=30):
329
+ self.post_called = True
330
+ self.last_url = url
331
+ self.last_json = json
332
+ self.last_timeout = timeout
333
+ resp = Mock()
334
+ resp.raise_for_status = Mock(return_value=None)
335
+ resp.status_code = 200
336
+ resp.text = ''
337
+ return resp
338
+
339
+ recording = RecordingClient()
340
+
341
+ with patch.object(_analytics, 'validate_auth_key', return_value=True), \
342
+ patch.object(_analytics, 'get_secret_key', return_value='GA-SECRET'), \
343
+ patch.object(_analytics.httpx, 'Client', return_value=recording):
344
+ resp = _analytics._analytics(req)
345
+
346
+ assert resp.status_code == 200
347
+ payload = _parse_response(resp)
348
+ assert payload['success'] is True
349
+
350
+ expected_url = f"https://www.google-analytics.com/mp/collect?measurement_id={measurement_id}&api_secret=GA-SECRET"
351
+ assert recording.post_called is True
352
+ assert recording.last_url == expected_url
353
+ assert recording.last_json['client_id'] == client_id
354
+ assert recording.last_json['events'] == events
355
+ assert recording.last_json['user_id'] == user_id
356
+
357
+
358
+ def test_httpx_http_status_error_is_logged_but_function_returns_200():
359
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
360
+ req_payload = {'measurement_id': 'm', 'client_id': 'c', 'events': [{'name': 'e'}]}
361
+ req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
362
+
363
+ # Client that returns a response whose raise_for_status raises HTTPStatusError
364
+ class ErrClient1:
365
+ def __enter__(self):
366
+ return self
367
+
368
+ def __exit__(self, exc_type, exc, tb):
369
+ return False
370
+
371
+ def post(self, url, json=None, timeout=30):
372
+ resp = Mock()
373
+ # Raise a fake HTTPStatusError instance with a response attribute
374
+ resp.raise_for_status = Mock(side_effect=_analytics.httpx.HTTPStatusError(Mock(status_code=400, text='bad')))
375
+ resp.status_code = 400
376
+ resp.text = 'bad'
377
+ return resp
378
+
379
+ err_client = ErrClient1()
380
+
381
+ with patch.object(_analytics, 'validate_auth_key', return_value=True), \
382
+ patch.object(_analytics, 'get_secret_key', return_value='GA-SECRET'), \
383
+ patch.object(_analytics.httpx, 'Client', return_value=err_client):
384
+ resp = _analytics._analytics(req)
385
+
386
+ assert resp.status_code == 200
387
+ payload = _parse_response(resp)
388
+ assert payload['success'] is True
389
+
390
+
391
+ def test_httpx_request_error_is_logged_but_function_returns_200():
392
+ headers = {_analytics.AUTH_HEADER_NAME: 'ok'}
393
+ req_payload = {'measurement_id': 'm', 'client_id': 'c', 'events': [{'name': 'e'}]}
394
+ req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
395
+
396
+ # Client whose post itself raises a RequestError
397
+ class ErrClient2:
398
+ def __enter__(self):
399
+ return self
400
+
401
+ def __exit__(self, exc_type, exc, tb):
402
+ return False
403
+
404
+ def post(self, url, json=None, timeout=30):
405
+ raise _analytics.httpx.RequestError('network')
406
+
407
+ err_client = ErrClient2()
408
+
409
+ with patch.object(_analytics, 'validate_auth_key', return_value=True), \
410
+ patch.object(_analytics, 'get_secret_key', return_value='GA-SECRET'), \
411
+ patch.object(_analytics.httpx, 'Client', return_value=err_client):
412
+ resp = _analytics._analytics(req)
413
+
414
+ assert resp.status_code == 200
415
+ payload = _parse_response(resp)
416
+ assert payload['success'] is True