From 94a16995f94bda90951dd90897b4481e28652616 Mon Sep 17 00:00:00 2001 From: tiye Date: Fri, 23 Oct 2026 16:54:32 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E6=97=A7=20Option=20?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=B9=B6=E9=85=8D=E5=AF=B9=E6=AD=A3=E5=BC=8F?= =?UTF-8?q?=20Calcit=200.30.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/upload.yaml | 29 +++++++++--- README.md | 11 +++-- calcit.cirru | 86 +++++++++++++++++------------------ deps.cirru | 14 +++--- package.json | 2 +- yarn.lock | 10 ++-- 6 files changed, 87 insertions(+), 65 deletions(-) diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml index dbbd5f6..592ae88 100644 --- a/.github/workflows/upload.yaml +++ b/.github/workflows/upload.yaml @@ -18,11 +18,11 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@v7.0.1 with: persist-credentials: false - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + - uses: actions/setup-node@v6.5.0 with: node-version: 24 package-manager-cache: false @@ -33,13 +33,15 @@ jobs: corepack prepare yarn@4.18.0 --activate yarn --version - - uses: calcit-lang/setup-calcit@704b3f5cd6f9ce3bd1e0c926dbdd1d181adb8180 # v1.4.0 + - uses: calcit-lang/setup-calcit@v1.5.0 with: tools: calcit,caps + caps-version: "0.1.1" + deps-file: deps.cirru - name: Resolve Calcit dependencies # Resolve the declared formal module tags independently of local module exports. - run: caps --ci + run: caps --strict --ci - name: Install JavaScript dependencies run: yarn install --immutable @@ -49,22 +51,28 @@ jobs: - name: Check canonical Calcit snapshot run: | + set -euo pipefail before="$(sha256sum calcit.cirru | cut -d ' ' -f 1)" calcit calcit.cirru edit format after="$(sha256sum calcit.cirru | cut -d ' ' -f 1)" test "$before" = "$after" git diff --exit-code -- calcit.cirru + test ! -e compact.cirru + test ! -e package.cirru - name: Check Calcit types run: | + set -euo pipefail calcit calcit.cirru --check-only --all-defs - calcit calcit.cirru fix --workflow strict --verify --format json + calcit calcit.cirru fix --workflow strict --verify --format json | jq -e '.data.workflow.status == "passed" and .diagnostics == []' - name: Check application dynamic methods run: calcit calcit.cirru analyze weak-types --only dynamic-method --format json - name: Check deprecated Calcit APIs - run: calcit calcit.cirru analyze weak-types --only deprecated-call --summary-only + run: | + set -euo pipefail + calcit calcit.cirru analyze weak-types --only deprecated-call --summary-only --format json | jq -e '.data.summary.calls == 0' - name: Audit provider dynamic methods run: calcit calcit.cirru analyze weak-types --only dynamic-method --deps --format json @@ -91,6 +99,15 @@ jobs: test -z "$(grep -E 'axios-' extension/dist/index.html)" test -z "$(grep -R 'feathericons.com' extension/dist/assets || true)" + - name: Save tested local-assets build for acceptance + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v7.0.1 + with: + name: extension-frontend-${{ github.run_id }}-${{ github.run_attempt }} + path: extension/dist + if-no-files-found: error + retention-days: 7 + - name: Select CDN asset path id: asset-path env: diff --git a/README.md b/README.md index bb33757..a1a77a2 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,15 @@ PR 网页预览按 `Termina/msg-buffer/pr////` 隔 同仓库 PR 与生产上传需要 `COS_BUCKET`、`COS_SECRET_ID`、`COS_SECRET_KEY`;fork PR 不上传。 服务器继续仅在 main push 部署 `dist/*` 到原路径,本次只更新前端资源配置。 -### Calcit 0.30.1 迁移候选(尚未交付) +### 正式 Calcit 0.30.1 迁移(待本轮验收) -本分支将 CLI 与 `@calcit/procs` 配对固定为已发布的 `0.30.1-alpha.5`,Calcit 模块改用正式 tag。 -0.30.1 正式版的 CLI/npm 配对发布尚未完成,暂不只升级其中一端。 +本分支将 CLI 与 `@calcit/procs` 配对固定为正式 `0.30.1`,升级到 Alerts 0.10.57、Reel 0.6.41、 +Markdown 0.4.59、UI 0.8.0、Respo 0.16.124、JS-FFI 0.2.5,全部使用精确正式 tag。 +升级后重启开发服务并刷新页面,不混用旧 runtime;不改变存档、模型服务地址或网页/扩展资源分离合同。 + +本轮迁移 41 处源码及原测试中的 2 处 Option helper 调用,改为 `.fold`、`.unwrap-or`、`.unwrap`。 +保持默认值、惰性分支回调、8 项原测试、1 个示例及两处 `hud!` 不变,不增加强转或放宽质量基线。 +正式 Linux CI 与真实页面验收以本轮 PR 的实际结果为准;下面是此前 alpha 候选的迁移记录,不能替代正式版验收。 存档格式、模型选择、扩展消息和网页/扩展资源分离的合同不变。DOM 挂载查询改为带明确能力合同的函数, 存档恢复区分具名 Struct 与旧 Map,并检查 Map 的键和值;同步回调明确返回 Unit。 diff --git a/calcit.cirru b/calcit.cirru index f8bab3d..5dc561e 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -203,7 +203,7 @@ messages1 $ upsert-assistant-message messages0 | | result $ js-await $ axios-post axios-module (str |https://sa.chenyong.life/v1/messages) js-object - :model $ option:unwrap-or (get-env |claude-model) (or model |claude-3-5-sonnet-latest) + :model $ .unwrap-or (get-env |claude-model) (or model |claude-3-5-sonnet-latest) :max_tokens 1024 :stream true :thinking $ if thinking? @@ -572,7 +572,7 @@ 'comp-container $ %{} 'CodeEntry (:doc |) :code $ quote $ defcomp comp-container (reel) let - app-store $ option:fold (get reel :store) + app-store $ .fold (get reel :store) fn () store fn (raw-store) (app.schema/normalize-store raw-store) sessions $ :sessions app-store @@ -580,10 +580,10 @@ current-session-id $ :current-session-id app-store states $ :states app-store cursor $ decode-map-as - option:unwrap-or (get states :cursor) ([]) + .unwrap-or (get states :cursor) ([]) :: 'List 'Dynamic state $ let - raw-chat-state $ option:unwrap-or (get states :data) + raw-chat-state $ .unwrap-or (get states :data) {} (:answer |) (:loading? false) (:done? true) :messages $ [] :model :gemini @@ -596,7 +596,7 @@ :model state , :gemini is-viewing-history? $ and (js-present-dynamic? current-session-id) - option:fold + .fold assert-type first $ filter sessions $ fn (s) hint-fn $ {} @@ -612,7 +612,7 @@ :args $ [] 'app.schema/ChatSession :return 'Bool :is-history? session - last-assistant $ option:fold + last-assistant $ .fold assert-type (last messages) (:: 'Option 'app.schema/ChatMessage) fn () hint-fn $ {} $ :return 'String @@ -635,7 +635,7 @@ :items models-menu :on-result $ fn (result d!) d! cursor $ assoc state :model $ decode-map-as - option:unwrap-or (nth result 1) :gemini + .unwrap-or (nth result 1) :gemini , 'Tag reply-plugin $ use-prompt (>> states :reply-prompt) {} (:text |Follow-up) (:placeholder "|Enter your follow-up") (:multiline? true) (:button-text |Send) @@ -665,7 +665,7 @@ submit-message! cursor submit-state text search? think? model d! submit-message! cursor submit-state text search? think? model d! message-box-state $ let - raw-message-box-state $ option:unwrap-or + raw-message-box-state $ .unwrap-or get (>> states :message-box) :data {} (:content |) (:search? false) (:think? false) (:focus-mode? false) if (struct? raw-message-box-state) @@ -691,7 +691,7 @@ :args $ [] 'app.schema/ChatSession :return 'Bool = (:id s) session-id - , first option:unwrap + , first .unwrap on-close d! , on-close $ fn (d!) hint-fn $ {} $ :async true @@ -914,7 +914,7 @@ (:none) &unit (:some element) (element .blur!) d! - option:unwrap-or + .unwrap-or get (>> states :message-box) :cursor [] assoc message-box-state :focus-mode? true @@ -1005,10 +1005,10 @@ :code $ quote $ defcomp comp-message-box (states picker-el on-submit model) let cursor $ decode-map-as - option:unwrap-or (get states :cursor) ([]) + .unwrap-or (get states :cursor) ([]) :: 'List 'Dynamic state $ let - raw-message-box-state $ option:unwrap-or (get states :data) + raw-message-box-state $ .unwrap-or (get states :data) {} (:content |) (:search? false) (:think? false) (:focus-mode? false) if (struct? raw-message-box-state) struct-match raw-message-box-state (MessageBoxState typed typed) @@ -1043,21 +1043,21 @@ :class-name $ str-spaced css/textarea css/font-code! style-textbox :on-input $ fn (e d!) d! cursor $ assoc state :content $ decode-map-as - option:unwrap-or (get e :value) | + .unwrap-or (get e :value) | , 'String , &unit :on-keydown $ fn (e d!) if and = 13 $ decode-map-as - option:unwrap-or (get e :keycode) 0 + .unwrap-or (get e :keycode) 0 , 'Number or decode-map-as - option:unwrap-or (get e :meta?) false + .unwrap-or (get e :meta?) false , 'Bool decode-map-as - option:unwrap-or (get e :ctrl?) false + .unwrap-or (get e :ctrl?) false , 'Bool on-submit (:content state) (:search? state) (:think? state) d! , &unit @@ -1188,7 +1188,7 @@ :on-click $ fn (e d!) let event $ js-cast - option:unwrap-or (get e :event) js/undefined + .unwrap-or (get e :event) js/undefined , 'js-ffi.browser/EventHost browser/event-stop-propagation! event d! $ :: :remove-session session-id @@ -1245,7 +1245,7 @@ :code $ quote $ defn create-session (messages model) let id $ generate-session-id - first-msg $ option:fold + first-msg $ .fold assert-type (first messages) (:: 'Option 'app.schema/ChatMessage) fn () |New-chat fn (message) @@ -1383,7 +1383,7 @@ when > (count lines) 1 eprintln "|Dropping some unexpected lines:" $ slice lines 1 - option:unwrap-or (first lines) | + .unwrap-or (first lines) | :examples $ [] :schema $ :: 'Fn $ {} (:return 'String) :args $ [] 'String @@ -1560,25 +1560,25 @@ _ other $ raise "|Expected ChatState nominal value" let data $ decode-map-as raw $ :: 'Map 'Tag 'Dynamic - loading-value $ option:unwrap-or (get data :loading?) false - done-value $ option:unwrap-or (get data :done?) true - model-value $ option:unwrap-or (get data :model) :gemini + loading-value $ .unwrap-or (get data :loading?) false + done-value $ .unwrap-or (get data :done?) true + model-value $ .unwrap-or (get data :model) :gemini app.schema/ChatState :answer - stream-text $ option:unwrap-or (get data :answer) | + stream-text $ .unwrap-or (get data :answer) | , :loading? match loading-value (true true) (false false) (_ false) , :done? match done-value (true true) (false false) (_ true) , :messages let - raw-message-value $ option:unwrap-or (get data :messages) ([]) + raw-message-value $ .unwrap-or (get data :messages) ([]) raw-messages $ if (list? raw-message-value) decode-map-as raw-message-value $ :: 'List 'Dynamic [] map raw-messages $ fn (message) (app.schema/normalize-chat-message message) , :model if (tag? model-value) model-value :gemini - , :thinking $ stream-text $ option:unwrap-or (get data :thinking) | + , :thinking $ stream-text $ .unwrap-or (get data :thinking) | :examples $ [] :schema $ :: 'Fn $ {} (:return 'app.schema/ChatState) :args $ [] 'T @@ -1612,10 +1612,10 @@ let info-data $ decode-map-as info $ :: 'Map 'Tag 'Dynamic submit? $ decode-map-as - option:unwrap-or (get info-data :submit?) true + .unwrap-or (get info-data :submit?) true , 'Bool text $ decode-map-as - option:unwrap-or (get info-data :text) | + .unwrap-or (get info-data :text) | , 'String dispatch! (:: :states cursor) (assoc state :content text) if submit? @@ -2037,7 +2037,7 @@ 'toggle-focus-within! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn toggle-focus-within! (respo-event active?) let - raw-event $ option:unwrap-or (get respo-event :event) js/undefined + raw-event $ .unwrap-or (get respo-event :event) js/undefined when (js-present-dynamic? raw-event) let event $ unsafe-coerce raw-event FocusEventHost @@ -2075,7 +2075,7 @@ :code $ quote $ defn upsert-assistant-message (messages content thinking) let size $ count messages - option:fold + .fold assert-type (last messages) (:: 'Option 'app.schema/ChatMessage) fn () hint-fn $ {} $ :return (:: 'List 'app.schema/ChatMessage) @@ -2135,7 +2135,7 @@ :features $ #{} :js-ffi 'dev? $ %{} 'CodeEntry (:doc |) :code $ quote $ def dev? - = |dev $ option:unwrap-or (get-env |mode) |release + = |dev $ .unwrap-or (get-env |mode) |release :examples $ [] :schema $ :: 'Bool 'site $ %{} 'CodeEntry (:doc |) @@ -2249,10 +2249,10 @@ js/chrome.runtime.onMessage.addListener $ fn (raw-message sender respond!) let message $ unsafe-coerce raw-message ExtensionMessageHost - action $ option:unwrap-or (extension-action message) | + action $ .unwrap-or (extension-action message) | when (= |menu-summary action) let - source $ option:unwrap-or + source $ .unwrap-or js-nullish->option $ .-content message , | content $ str "|你扮演一个专业的工程师, 对以下内容做一下讲解, 用中文, 注意要简略, 内容注意分块.\n\n" &newline &newline source @@ -2260,17 +2260,17 @@ send-to-component! event-tuple when (= |fill-text action) let - content $ option:unwrap-or + content $ .unwrap-or js-nullish->option $ .-text message , | - submit? $ option:unwrap-or + submit? $ .unwrap-or js-nullish->option $ .-submit? message , true event-tuple $ :: :fill-text $ {} (:text content) (:submit? submit?) send-to-component! event-tuple when (= |menu-translate action) let - source $ option:unwrap-or + source $ .unwrap-or js-nullish->option $ .-content message , | content $ str "|请将以下内容翻译成中文, 保持简洁分段:\n\n" &newline &newline source @@ -2278,7 +2278,7 @@ send-to-component! event-tuple when (= |menu-custom action) let - content $ option:unwrap-or + content $ .unwrap-or js-nullish->option $ .-content message , | event-tuple $ :: :fill-text $ {} (:text content) (:submit? false) @@ -2306,7 +2306,7 @@ js/window.addEventListener |visibilitychange $ fn (event) let document $ unsafe-coerce js/document DocumentHost - visibility-state $ option:unwrap-or + visibility-state $ .unwrap-or js-nullish->option $ .-visibilityState document , | if (= |hidden visibility-state) (persist-storage!) @@ -2465,7 +2465,7 @@ if (map? raw) let data $ decode-map-as raw $ :: 'Map 'Tag 'Dynamic - thinking-value $ option:unwrap-or (get data :thinking) | + thinking-value $ .unwrap-or (get data :thinking) | normalized-thinking $ if (string? thinking-value) (assert-type thinking-value 'String) | decode-map-as (assoc data :thinking normalized-thinking) 'app.schema/ChatMessage raise "|Expected chat message map" @@ -2495,7 +2495,7 @@ if (map? raw) let data $ decode-map-as raw $ :: 'Map 'Tag 'Dynamic - raw-message-value $ option:unwrap-or (get data :messages) ([]) + raw-message-value $ .unwrap-or (get data :messages) ([]) raw-messages $ if (list? raw-message-value) assert-type raw-message-value $ :: 'List 'Dynamic [] @@ -2544,7 +2544,7 @@ if (map? raw) let data $ decode-map-as raw $ :: 'Map 'Tag 'Dynamic - raw-session-value $ option:unwrap-or (get data :sessions) ([]) + raw-session-value $ .unwrap-or (get data :sessions) ([]) raw-sessions $ if (list? raw-session-value) assert-type raw-session-value $ :: 'List 'Dynamic [] @@ -2575,12 +2575,12 @@ normalized $ assert-type (normalize-store legacy) 'app.schema/Store sessions $ assert-type (:sessions normalized) (:: 'List 'app.schema/ChatSession) fallback-session $ ChatSession :id |fallback :created-at 0 :messages ([]) :model :gemini :preview | :is-history? false - session $ option:unwrap-or + session $ .unwrap-or assert-type (first sessions) (:: 'Option 'app.schema/ChatSession) , fallback-session messages $ assert-type (:messages session) (:: 'List 'app.schema/ChatMessage) fallback-message $ ChatMessage :role :user :content | :thinking |fallback - message $ option:unwrap-or + message $ .unwrap-or assert-type (first messages) (:: 'Option 'app.schema/ChatMessage) , fallback-message is $ = | $ :thinking message @@ -2615,7 +2615,7 @@ path $ concat decode-map-as cursor $ :: 'List 'Dynamic [] :data - state $ option:unwrap-or + state $ .unwrap-or get-in (:states store) path , s updated-states $ assoc-in (:states store) path $ if (map? state) diff --git a/deps.cirru b/deps.cirru index 3b42981..1c411ca 100644 --- a/deps.cirru +++ b/deps.cirru @@ -1,9 +1,9 @@ -{} (:calcit-version |0.30.1-alpha.5) +{} (:calcit-version |0.30.1) :version |0.0.10 - :dependencies $ {} (|Respo/alerts.calcit |0.10.56) - |Respo/reel.calcit |0.6.39 - |Respo/respo-markdown.calcit |0.4.56 - |Respo/respo-ui.calcit |0.7.41 - |Respo/respo.calcit |0.16.122 - |calcit-lang/js-ffi |0.2.3 + :dependencies $ {} (|Respo/alerts.calcit |0.10.57) + |Respo/reel.calcit |0.6.41 + |Respo/respo-markdown.calcit |0.4.59 + |Respo/respo-ui.calcit |0.8.0 + |Respo/respo.calcit |0.16.124 + |calcit-lang/js-ffi |0.2.5 diff --git a/package.json b/package.json index f84f278..0fedbda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@calcit/procs": "0.30.1-alpha.5", + "@calcit/procs": "0.30.1", "@google/genai": "2.23.0", "@tiye/main-fonts": "0.0.1", "axios": "1.20.0", diff --git a/yarn.lock b/yarn.lock index a38679e..48c78fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,15 +12,15 @@ __metadata: languageName: node linkType: hard -"@calcit/procs@npm:0.30.1-alpha.5": - version: 0.30.1-alpha.5 - resolution: "@calcit/procs@npm:0.30.1-alpha.5" +"@calcit/procs@npm:0.30.1": + version: 0.30.1 + resolution: "@calcit/procs@npm:0.30.1" dependencies: "@calcit/finger-vec": "npm:0.1.1" "@calcit/ternary-tree": "npm:0.0.26" "@cirru/parser.ts": "npm:0.0.10" "@cirru/writer.ts": "npm:^0.1.9" - checksum: 10c0/925226e14b05ab6f1ed5adf32611a3575324d9e99474e84dce6f01093dce4d869d301585bb76c06d56725a716a76536888f99b9da5c961e79c9b0c62a5b27b1c + checksum: 10c0/a0f00e3c0c9b3a5a2aea8b97e09f2692aa25039a48a2f7ccb345801fdbc546cbf3bb34ee268a58526baba9fb697781bb7929a5d1f6622816c9422c6c3ba8537b languageName: node linkType: hard @@ -1540,7 +1540,7 @@ __metadata: version: 0.0.0-use.local resolution: "root-workspace-0b6124@workspace:." dependencies: - "@calcit/procs": "npm:0.30.1-alpha.5" + "@calcit/procs": "npm:0.30.1" "@google/genai": "npm:2.23.0" "@tiye/main-fonts": "npm:0.0.1" axios: "npm:1.20.0" From f355f519e3bd87904bf3b5df55a78ae9aac6d314 Mon Sep 17 00:00:00 2001 From: tiye Date: Fri, 23 Oct 2026 17:00:40 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=8F=AA=E5=9C=A8=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E6=81=A2=E5=A4=8D=E6=88=90=E5=8A=9F=E5=90=8E=E5=90=AF=E7=94=A8?= =?UTF-8?q?=E5=8E=9F=E8=87=AA=E5=8A=A8=E4=BF=9D=E5=AD=98=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ calcit.cirru | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a1a77a2..2df310f 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Markdown 0.4.59、UI 0.8.0、Respo 0.16.124、JS-FFI 0.2.5,全部使用精确 本轮迁移 41 处源码及原测试中的 2 处 Option helper 调用,改为 `.fold`、`.unwrap-or`、`.unwrap`。 保持默认值、惰性分支回调、8 项原测试、1 个示例及两处 `hud!` 不变,不增加强转或放宽质量基线。 +存档仍异步恢复;自动保存监听器只在恢复成功或确认无存档后注册,恢复失败不覆盖原值。 +通过具备 `Fn() -> Unit` 合同的完成回调复用原监听器,不吞异常、不改存档格式,也不转移宿主强转来规避基线。 正式 Linux CI 与真实页面验收以本轮 PR 的实际结果为准;下面是此前 alpha 候选的迁移记录,不能替代正式版验收。 存档格式、模型选择、扩展消息和网页/扩展资源分离的合同不变。DOM 挂载查询改为带明确能力合同的函数, diff --git a/calcit.cirru b/calcit.cirru index 5dc561e..fe31cd9 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -2226,23 +2226,27 @@ :features $ #{} :js-ffi :return $ :: 'calcit.core/Option 'String 'hydrate-storage-later! $ %{} 'CodeEntry (:doc |) - :code $ quote $ defn hydrate-storage-later! () + :code $ quote $ defn hydrate-storage-later! (on-ready) browser/set-timeout! - fn () $ let - storage $ browser/window-local-storage - match - js-nullish->option $ storage .get-item $ :storage-key config/site - (:none) &unit - (:some serialized) - let - t-start $ ffi/now-ms - dispatch! $ :: :hydrate-storage $ parse-cirru-edn serialized - println |Hydrated-in $ - (ffi/now-ms) t-start + fn () + let + storage $ browser/window-local-storage + match + js-nullish->option $ storage .get-item $ :storage-key config/site + (:none) &unit + (:some serialized) + let + t-start $ ffi/now-ms + dispatch! $ :: :hydrate-storage $ parse-cirru-edn serialized + println |Hydrated-in $ - (ffi/now-ms) t-start + on-ready , 0 , &unit :examples $ [] :schema $ :: 'Fn $ {} (:return 'Unit) - :args $ [] + :args $ [] $ :: 'Fn + {} (:return 'Unit) + :args $ [] :features $ #{} :js-ffi 'listen-extension! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn listen-extension! () @@ -2302,20 +2306,21 @@ add-watch! *archived-sessions :changes $ fn (s prev) (render-app!) add-watch! *viewing-archive-session :changes $ fn (s prev) (render-app!) listen-devtools! |k dispatch! - js/window.addEventListener |beforeunload $ fn (event) (persist-storage!) - js/window.addEventListener |visibilitychange $ fn (event) - let - document $ unsafe-coerce js/document DocumentHost - visibility-state $ .unwrap-or - js-nullish->option $ .-visibilityState document - , | - if (= |hidden visibility-state) (persist-storage!) js/window.addEventListener |dblclick $ fn (event) (.!preventDefault event) js/window.addEventListener |wheel fn (event) if (.-ctrlKey event) (.!preventDefault event) js-object $ :passive false - hydrate-storage-later! + hydrate-storage-later! $ fn () + js/window.addEventListener |beforeunload $ fn (event) (persist-storage!) + js/window.addEventListener |visibilitychange $ fn (event) + let + document $ unsafe-coerce js/document DocumentHost + visibility-state $ .unwrap-or + js-nullish->option $ .-visibilityState document + , | + if (= |hidden visibility-state) (persist-storage!) + , &unit if config/chrome-extension? $ listen-extension! sync-gemini-key! let From ae16e7a18883fcd89d6986bc9ad96844d65d164b Mon Sep 17 00:00:00 2001 From: tiye Date: Fri, 23 Oct 2026 17:10:35 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=8C=89=E6=AD=A3=E5=BC=8F=E6=8A=A5?= =?UTF-8?q?=E5=91=8A=E6=94=B6=E7=B4=A7=E6=97=A7=E8=B4=A8=E9=87=8F=E9=A2=84?= =?UTF-8?q?=E7=AE=97=E5=B9=B6=E8=AE=B0=E5=BD=95=E7=9C=9F=E5=AE=9E=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E9=AA=8C=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++- config/calcit-quality.cirru | 143 ++++-------------------------------- 2 files changed, 22 insertions(+), 132 deletions(-) diff --git a/README.md b/README.md index 2df310f..fc10350 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ PR 网页预览按 `Termina/msg-buffer/pr////` 隔 同仓库 PR 与生产上传需要 `COS_BUCKET`、`COS_SECRET_ID`、`COS_SECRET_KEY`;fork PR 不上传。 服务器继续仅在 main push 部署 `dist/*` 到原路径,本次只更新前端资源配置。 -### 正式 Calcit 0.30.1 迁移(待本轮验收) +### 正式 Calcit 0.30.1 迁移 本分支将 CLI 与 `@calcit/procs` 配对固定为正式 `0.30.1`,升级到 Alerts 0.10.57、Reel 0.6.41、 Markdown 0.4.59、UI 0.8.0、Respo 0.16.124、JS-FFI 0.2.5,全部使用精确正式 tag。 @@ -39,7 +39,14 @@ Markdown 0.4.59、UI 0.8.0、Respo 0.16.124、JS-FFI 0.2.5,全部使用精确 保持默认值、惰性分支回调、8 项原测试、1 个示例及两处 `hud!` 不变,不增加强转或放宽质量基线。 存档仍异步恢复;自动保存监听器只在恢复成功或确认无存档后注册,恢复失败不覆盖原值。 通过具备 `Fn() -> Unit` 合同的完成回调复用原监听器,不吞异常、不改存档格式,也不转移宿主强转来规避基线。 -正式 Linux CI 与真实页面验收以本轮 PR 的实际结果为准;下面是此前 alpha 候选的迁移记录,不能替代正式版验收。 +源码提交 `f355f51` 的正式 Linux CI `39928756920` 通过原完整 strict、8 项测试、扩展包与 COS 内置校验。 +同次相对资源 artifact 校验 SHA256 后,在全新 localhost 来源验证草稿、搜索开关、模型选择、空历史面板及刷新恢复; +未发送模型请求、读取真实密钥或安装扩展。坏存档验收仍待限定授权,不把正常恢复当作失败保护的完整证据。 + +官方 lower-only 生成器在独立非 PR 分支的正式 CI `39929283700` 中收紧原基线: +unsafe 85→11、typeNotFull 65→58、schemaDynamic 46→43、unresolved 71→68,其余不变。 +这是移除旧预算余量,不是本轮删除 74 处强转;逐定义同步降低,不在应用 CI 自动重写,也不新增预算。 +下面是此前 alpha 候选的迁移记录,不能替代本轮正式版验收。收紧后的最终 CI 仍以最新 PR HEAD 为准。 存档格式、模型选择、扩展消息和网页/扩展资源分离的合同不变。DOM 挂载查询改为带明确能力合同的函数, 存档恢复区分具名 Struct 与旧 Map,并检查 Map 的键和值;同步回调明确返回 Unit。 diff --git a/config/calcit-quality.cirru b/config/calcit-quality.cirru index 65caf90..331089d 100644 --- a/config/calcit-quality.cirru +++ b/config/calcit-quality.cirru @@ -18,33 +18,6 @@ :typeNotFull 0 :unresolved 1 :unsafeCoerce 0 - |app.comp.container/*gen-ai-new $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 1 - :typeNone 0 - :typeNotFull 1 - :unresolved 1 - :unsafeCoerce 0 - |app.comp.container/*image-cache $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 1 - :typeNone 0 - :typeNotFull 1 - :unresolved 1 - :unsafeCoerce 0 - |app.comp.container/*openai $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 1 - :typeNone 0 - :typeNotFull 1 - :unresolved 1 - :unsafeCoerce 0 |app.comp.container/*viewing-archive-session $ {} (:codeDynamic 0) :codeNil 1 :declaredOptional 0 @@ -71,7 +44,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 0 - :unsafeCoerce 4 + :unsafeCoerce 0 |app.comp.container/call-flash-imagen-msg! $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -80,7 +53,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 0 - :unsafeCoerce 15 + :unsafeCoerce 0 |app.comp.container/call-genai-msg! $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -89,7 +62,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 0 - :unsafeCoerce 5 + :unsafeCoerce 0 |app.comp.container/call-imagen-4-msg! $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -98,7 +71,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 0 - :unsafeCoerce 9 + :unsafeCoerce 0 |app.comp.container/call-openrouter! $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -107,16 +80,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 0 - :unsafeCoerce 8 - |app.comp.container/clear-image-cache! $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 0 - :unresolved 0 - :unsafeCoerce 1 + :unsafeCoerce 0 |app.comp.container/comp-abort $ {} (:codeDynamic 0) :codeNil 1 :declaredOptional 0 @@ -134,7 +98,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 12 - :unsafeCoerce 5 + :unsafeCoerce 0 |app.comp.container/comp-message-box $ {} (:codeDynamic 0) :codeNil 3 :declaredOptional 0 @@ -143,7 +107,7 @@ :typeNone 0 :typeNotFull 1 :unresolved 3 - :unsafeCoerce 3 + :unsafeCoerce 0 |app.comp.container/comp-sessions-modal $ {} (:codeDynamic 0) :codeNil 1 :declaredOptional 0 @@ -152,44 +116,8 @@ :typeNone 0 :typeNotFull 1 :unresolved 1 - :unsafeCoerce 1 - |app.comp.container/decode-genai-chunk $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 0 - :unresolved 0 - :unsafeCoerce 8 - |app.comp.container/download-sessions! $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 1 - :unresolved 0 - :unsafeCoerce 4 - |app.comp.container/effect-focus $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 0 - :unresolved 0 - :unsafeCoerce 2 + :unsafeCoerce 0 |app.comp.container/js-present-dynamic? $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 1 - :unresolved 0 - :unsafeCoerce 1 - |app.comp.container/make-genai-tools $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 :deprecatedCalls 0 @@ -234,15 +162,6 @@ :typeNotFull 1 :unresolved 1 :unsafeCoerce 0 - |app.comp.container/normalize-chat-state $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 0 - :unresolved 0 - :unsafeCoerce 3 |app.comp.container/on-fill $ {} (:codeDynamic 0) :codeNil 1 :declaredOptional 0 @@ -612,15 +531,6 @@ :typeNotFull 1 :unresolved 0 :unsafeCoerce 4 - |app.config/detect-chrome-extension? $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 0 - :unresolved 0 - :unsafeCoerce 2 |app.main/*reel $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -657,24 +567,6 @@ :typeNotFull 0 :unresolved 0 :unsafeCoerce 3 - |app.main/mount-target $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 1 - :unresolved 0 - :unsafeCoerce 0 - |app.main/persist-storage! $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 1 - :unresolved 0 - :unsafeCoerce 0 |app.main/reload! $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -683,16 +575,7 @@ :typeNone 0 :typeNotFull 0 :unresolved 0 - :unsafeCoerce 2 - |app.main/render-app! $ {} (:codeDynamic 0) - :codeNil 0 - :declaredOptional 0 - :deprecatedCalls 0 - :schemaDynamic 0 - :typeNone 0 - :typeNotFull 0 - :unresolved 0 - :unsafeCoerce 2 + :unsafeCoerce 1 |app.main/sync-gemini-key! $ {} (:codeDynamic 0) :codeNil 0 :declaredOptional 0 @@ -724,11 +607,11 @@ :codeNil 25 :declaredOptional 0 :deprecatedCalls 0 - :schemaDynamic 46 + :schemaDynamic 43 :typeNone 0 - :typeNotFull 65 - :unresolved 71 - :unsafeCoerce 85 + :typeNotFull 58 + :unresolved 68 + :unsafeCoerce 11 :scope $ {} (:includeDependencies false) :namespace nil :namespacePrefix nil