Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

calcit.cirru -diff linguist-generated
yarn.lock -diff linguist-generated

Agents.md -diff linguist-generated
llms/*.md -diff linguist-generated
445 changes: 445 additions & 0 deletions Agents.md

Large diffs are not rendered by default.

4,233 changes: 2,281 additions & 1,952 deletions calcit.cirru

Large diffs are not rendered by default.

96 changes: 67 additions & 29 deletions compact.cirru
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
.!generateContent (.-models gen-ai)
js-object (:model "\"gemini-2.5-flash-image") (:contents content)
:config $ js-object
:httpOptions $ js-object (:baseUrl "\"https://ja.chenyong.life")
:httpOptions $ js-object (:baseUrl |https://ja.chenyong.life)
:signal $ let
abort $ new js/AbortController
reset! *abort-control abort
Expand Down Expand Up @@ -164,7 +164,7 @@
:examples $ []
|call-genai-msg! $ %{} :CodeEntry (:doc |)
:code $ quote
defn call-genai-msg! (variant cursor state prompt-text search? think? d! *text) (hint-fn async)
defn call-genai-msg! (variant cursor state prompt-text search? think? d! *text *thinking-text) (hint-fn async)
if (nil? @*gen-ai-new)
reset! *gen-ai-new $ new GoogleGenAI
js-object $ :apiKey (get-gemini-key!)
Expand Down Expand Up @@ -200,8 +200,7 @@
:thinkingBudget $ get-env "\"think-budget" (if pro? 3200 800)
:includeThoughts think?
js-object (:thinkingBudget 0) (:includeThoughts false)
:httpOptions $ js-object
:baseUrl $ get-env "\"gemini-host" "\"https://ja.chenyong.life"
:httpOptions $ js-object (:baseUrl |https://ja.chenyong.life)
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The baseUrl has been changed from a string literal "https://ja.chenyong.life" to a symbol |https://ja.chenyong.life. In Cirru syntax, the | prefix denotes a string, which is correct. However, this appears in multiple places (lines 134, 203, 263) and should be consistent. Verify this is the intended format for all three occurrences.

Copilot uses AI. Check for mistakes.
:tools $ let
t $ ->
js-array
Expand All @@ -223,17 +222,19 @@
js-await $ js-for-await sdk-result
fn (? chunk)
if (some? chunk)
do
swap! *text str $ let
t $ either (.-text chunk) js/chunk.candidates?.[0]?.content?.parts?.[0]?.text
if (nil? t) (js/console.warn "\"empty text in:" chunk)
or t (-> chunk .?-promptFeedback .?-blockReason) "\"__BLANK__"
d! $ :: :states-merge cursor state
{} (:answer @*text) (:loading? false) (:done? false)
let
part js/chunk.candidates?.[0]?.content?.parts?.[0]
is-thinking? $ if (some? part) (.-thought part) false
t $ if (some? part) (.-text part) (.-text chunk)
let
text $ or t (-> chunk .?-promptFeedback .?-blockReason) |__BLANK__
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded string value |__BLANK__ is used as a fallback when text is undefined. This is likely meant to be an empty string "" instead. Using |__BLANK__ will display literally as "BLANK" to users, which appears to be debug text rather than an intentional user-facing message.

Suggested change
text $ or t (-> chunk .?-promptFeedback .?-blockReason) |__BLANK__
text $ or t (-> chunk .?-promptFeedback .?-blockReason) "\""

Copilot uses AI. Check for mistakes.
if is-thinking? (swap! *thinking-text str text) (swap! *text str text)
d! $ :: :states-merge cursor state
{} (:answer @*text) (:thinking @*thinking-text) (:loading? false) (:done? false)
d! $ :: :states-merge cursor state
{} (:answer @*text) (:loading? false) (:done? false)
{} (:answer @*text) (:thinking @*thinking-text) (:loading? false) (:done? false)
d! $ :: :states-merge cursor state
{} (:answer @*text) (:loading? false) (:done? true)
{} (:answer @*text) (:thinking @*thinking-text) (:loading? false) (:done? true)
:examples $ []
|call-imagen-4-msg! $ %{} :CodeEntry (:doc |)
:code $ quote
Expand All @@ -259,7 +260,7 @@
.!generateImages (.-models gen-ai)
js-object (:model "\"imagen-4.0-generate-001") (:prompt prompt-text)
:config $ js-object (:numberOfImages 1) (:includeRaiReason true)
:httpOptions $ js-object (:baseUrl "\"https://ja.chenyong.life")
:httpOptions $ js-object (:baseUrl |https://ja.chenyong.life)
:signal $ let
abort $ new js/AbortController
reset! *abort-control abort
Expand Down Expand Up @@ -382,15 +383,27 @@
if (:loading? state)
div ({}) (memof1-call-by :abort-loading comp-abort "\"Loading...")
if
not $ blank? (:answer state)
or
not $ blank? (:answer state)
not $ blank? (:thinking state)
div ({})
if
json-pattern? $ :answer state
pre $ {} (:class-name style-code-content)
:inner-text $ :answer state
memof1-call comp-md-block
-> (:answer state) (either "\"")
{} $ :class-name style-md-content
not $ blank? (:thinking state)
div
{} $ :class-name style-thinking
memof1-call comp-md-block
-> (:thinking state) (either "\"")
{} $ :class-name style-md-content
if
not $ blank? (:answer state)
div ({})
if
json-pattern? $ :answer state
pre $ {} (:class-name style-code-content)
:inner-text $ :answer state
memof1-call comp-md-block
-> (:answer state) (either "\"")
{} $ :class-name style-md-content
div
{} $ :class-name css/row-parted
div
Expand Down Expand Up @@ -607,6 +620,7 @@
{} $ :max-width "\"90vw"
"\"&" $ {} (:color "\"#999") (:transition-duration "\"300ms")
:background-color $ hsl 0 0 98
:touch-action :none
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CSS property touch-action: none completely disables touch interactions including scrolling on mobile devices. This creates a significant usability issue for mobile users who won't be able to interact with the UI element. Consider using more specific values like touch-action: pan-y or touch-action: manipulation to preserve essential touch interactions while preventing unwanted behaviors.

Suggested change
:touch-action :none
:touch-action :pan-y

Copilot uses AI. Check for mistakes.
"\"&:hover" $ {} (:color "\"#777")
:background-color $ hsl 0 0 100
:examples $ []
Expand Down Expand Up @@ -691,23 +705,37 @@
"\"&" $ {} (:border-radius 12) (:height "\"max(160px,20vh)") (:width "\"100%") (:transition-duration "\"320ms") (:border :none) (:background-color :transparent)
"\"&.focus-within" $ {} (:height "\"max(240px,32vh)") (:border :none) (:box-shadow :none)
:examples $ []
|style-thinking $ %{} :CodeEntry (:doc |)
:code $ quote
defstyle style-thinking $ {}
"\"&" $ {} (:max-height 200) (:overflow :auto) (:padding "\"12px 16px")
:background-color $ hsl 0 0 96
:font-size 12
:line-height "\"1.8"
:color $ hsl 0 0 50
:border-radius 8
:margin-bottom 12
:border $ str "\"1px solid " (hsl 0 0 90)
"\"& .md-p" $ {} (:margin "\"4px 0")
:examples $ []
|submit-message! $ %{} :CodeEntry (:doc |)
:code $ quote
defn submit-message! (cursor state prompt-text search? think? model d!) (hint-fn async)
let
*text $ atom "\""
*thinking-text $ atom "\""
model $ :model state
try
case-default model
js-await $ call-genai-msg! model cursor state prompt-text search? think? d! *text
:gemini-pro $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text)
js-await $ call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text
:gemini-pro $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text)
:flash-imagen $ js-await (call-flash-imagen-msg! model cursor state prompt-text d!)
:imagen-4 $ js-await (call-imagen-4-msg! model cursor state prompt-text d!)
:gemini-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text)
:gemini-flash-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text)
:gemini-flash-lite $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text)
:gemini-flash $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text)
:gemini-learnlm $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text)
:gemini-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text)
:gemini-flash-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text)
:gemini-flash-lite $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text)
:gemini-flash $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text)
:gemini-learnlm $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text)
:claude-3.7 $ js-await (call-anthropic-msg! cursor state prompt-text "\"claude-3-7-sonnet-20250219" false d!)
:openrouter/anthropic/claude-sonnet-4 $ js-await (call-openrouter! cursor state prompt-text "\"anthropic/claude-sonnet-4" true d! *text)
:openrouter/anthropic/claude-opus-4 $ js-await (call-openrouter! cursor state prompt-text "\"anthropic/claude-opus-4" true d! *text)
Comment on lines 732 to 741
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature changed to add *thinking-text parameter, but the calls to call-anthropic-msg! and image-related functions in the submit-message! case statement do not pass this new parameter. This creates an inconsistency where only some model paths support thinking text tracking. Consider either:

  1. Adding thinking text support to all model handlers, or
  2. Making *thinking-text optional for backward compatibility

Copilot uses AI. Check for mistakes.
Expand Down Expand Up @@ -741,6 +769,7 @@
"\"@google/genai" :refer $ GoogleGenAI Modality
"\"../lib/image" :refer $ base64ToBlob
"\"openai" :default OpenAI
:examples $ []
|app.config $ %{} :FileEntry
:defs $ {}
|chrome-extension? $ %{} :CodeEntry (:doc |)
Expand All @@ -757,6 +786,7 @@
:examples $ []
:ns $ %{} :CodeEntry (:doc |)
:code $ quote (ns app.config)
:examples $ []
|app.main $ %{} :FileEntry
:defs $ {}
|*reel $ %{} :CodeEntry (:doc |)
Expand All @@ -778,7 +808,7 @@
if
= "\"menu-trigger" $ .-action message
let
content $ str "\"你扮演一个专业的工程师, 对以下内容做一下讲解, 用中文, 注意要简略, 内容注意分块.\n\n" &newline &newline (.-content message)
content $ str "\"你扮演一个专业的工程师, 对以下内容做一下讲解, 用中文, 注意要简略, 内容注意分块.\n\n" &newline &newline (.-content message)
store $ :store @*reel
cursor $ []
state0 $ get-in store ([] :states :data)
Expand All @@ -797,6 +827,11 @@
js/window.addEventListener |beforeunload $ fn (event) (persist-storage!)
js/window.addEventListener |visibilitychange $ fn (event)
if (= "\"hidden" js/document.visibilityState) (persist-storage!)
js/window.addEventListener |dblclick $ fn (event) (.!preventDefault event)
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The double-click event handler prevents default behavior globally on the window, which will disable all text selection via double-click across the entire application. This is likely too broad and may harm user experience. Consider:

  1. Applying this only to specific elements (e.g., buttons, non-text areas)
  2. Using CSS user-select: none on specific elements instead
  3. Removing this if not strictly necessary for the feature
Suggested change
js/window.addEventListener |dblclick $ fn (event) (.!preventDefault event)

Copilot uses AI. Check for mistakes.
js/window.addEventListener |wheel
fn (event)
if (.-ctrlKey event) (.!preventDefault event)
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wheel event listener with passive: false is added to prevent zoom on Ctrl+wheel, but this approach has accessibility implications. Users who rely on browser zoom for accessibility may find this frustrating. Consider:

  1. Adding a user preference toggle for this behavior
  2. Only preventing zoom in specific UI areas rather than globally
  3. Documenting this behavior in user-facing documentation
Suggested change
if (.-ctrlKey event) (.!preventDefault event)
let
target $ .-target event
when
and (.-ctrlKey event)
some? $ .!closest target "\".app"
.!preventDefault event

Copilot uses AI. Check for mistakes.
js-object $ :passive false
; flipped js/setInterval 60000 persist-storage!
let
raw $ js/localStorage.getItem (:storage-key config/site)
Expand Down Expand Up @@ -842,6 +877,7 @@
app.config :as config
"\"./calcit.build-errors" :default build-errors
"\"bottom-tip" :default hud!
:examples $ []
|app.schema $ %{} :FileEntry
:defs $ {}
|store $ %{} :CodeEntry (:doc |)
Expand All @@ -853,6 +889,7 @@
:examples $ []
:ns $ %{} :CodeEntry (:doc |)
:code $ quote (ns app.schema)
:examples $ []
|app.updater $ %{} :FileEntry
:defs $ {}
|updater $ %{} :CodeEntry (:doc |)
Expand All @@ -874,3 +911,4 @@
:code $ quote
ns app.updater $ :require
respo.cursor :refer $ update-states update-states-merge
:examples $ []
4 changes: 2 additions & 2 deletions deps.cirru
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

{} (:calcit-version |0.9.20)
{} (:calcit-version |0.10.4)
:dependencies $ {} (|Respo/alerts.calcit |0.10.2)
|Respo/reel.calcit |main
|Respo/respo-markdown.calcit |0.4.11
|Respo/respo-ui.calcit |0.6.3
|Respo/respo.calcit |0.16.21
|Respo/respo.calcit |0.16.22
|calcit-lang/lilac |main
|calcit-lang/memof |main
Loading