From 718ea83bf2266f13e6fda22bf42e77b52b97503a Mon Sep 17 00:00:00 2001 From: tiye Date: Thu, 12 Nov 2026 13:20:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=20Gen=20Code=20=E5=88=B0=20C?= =?UTF-8?q?alcit=200.42.0=20=E5=B9=B6=E6=94=B6=E7=B4=A7=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=B4=BE=E5=8F=91=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++-- calcit.cirru | 61 ++++++++++++++++++++++----------------- deps.cirru | 2 +- package.json | 2 +- tests/stream-contract.mjs | 33 ++++++++++++++++----- yarn.lock | 10 +++---- 6 files changed, 71 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 21ad8e4..a8bba83 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ Demo: https://repo.calcit-lang.org/gen-code/ ## 0.0.26 候选 -使用者需统一 Calcit CLI 和 `@calcit/procs` **0.41.1**,配对正式 +使用者需统一 Calcit CLI 和 `@calcit/procs` **0.42.0**,配对正式 UI **0.15.2**、Respo **0.19.5**、JS-FFI **0.2.13** 和传递依赖 Router **0.12.2**, 然后重新生成 JS。插件继续接收单事件派发,代码生成请求与存档行为沿用原合同。 Reel **0.11.0** 是 Demo 的开发依赖。Demo 将插件事件解码为具名 `GenCodeOp`,快捷键与面板通过独立回调接收 `Control`。流式补丁通过 `GenCodeFieldValue` union 约束为字符串或布尔值,Editor 等宿主的插件回调继续接收单个原格式操作。 内部 `call-genai-msg!` 只向回调交付补丁 Map。插件在派发边界补齐 cursor 和请求状态,生成原格式的 `:states-merge` 事件。 Meta+Enter 直接读取 Respo 提供的类型化键盘字段,快捷键条件与派发协议不变。 -质量检查使用 0.41.1 的 coverage、弱类型和弃用视图,继续限制两处既有 SDK 强转。 +质量检查使用 0.42.0 的 coverage、弱类型和弃用视图,继续限制两处既有 SDK 强转。 验收覆盖完整 strict、原测试、离线快捷键与流式回归和构建。 ## 历史 0.0.22 配对 @@ -45,6 +45,8 @@ Respo **0.19.3**、JS-FFI **0.2.12** / Router **0.12.0**。消费者需统一精 `use-gen-code` 返回插件,`.render` 生成界面,`.reset-state` 向传入的 dispatch 发送一个 `:: :states cursor state` 事件。提交回调接收代码字符串和 dispatch,继续遵守单事件合同。 +类型化宿主可用 `use-gen-code-with-dispatch` 并传入从 `GenCodeOp` 到宿主操作类型的转换函数。内置 Demo 直接派发具名事件。原 `use-gen-code` 仍为旧宿主发送匿名事件。 + 开放 Map/Struct 字段读取如实返回 Dynamic:缺失或显式 nil 使用 fallback,false 和 Option 载荷原样保留。不能直接换为会展开 Option 的 field-or。外部同名 StoreData 仅作为数据输入,转 Map、检查 states 和嵌套状态,再重建本地类型;名称不代表身份,见 [#41](https://github.com/calcit-lang/gen-code/issues/41)。 Demo 先恢复存档,再渲染和注册持久化。启动恢复清除中断请求的 loading?,保留 query、answer、code、done?,不恢复请求或 AbortController。可解析但结构不符的数据保留旧回退行为,不宣称全部坏存档都会被拒绝,见 [#38](https://github.com/calcit-lang/gen-code/issues/38)。 diff --git a/calcit.cirru b/calcit.cirru index 19290d9..6f746b4 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -15,15 +15,18 @@ let store $ :store reel states $ :states store - plugin-gen-code $ use-gen-code (>> states :drafter) + plugin-gen-code $ use-gen-code-with-dispatch (>> states :drafter) fn () hint-fn $ Fn $ -> String , "|println |demo" fn (code d!) hint-fn $ Fn String - Fn AnyEnum $ -> Unit + Fn schema/GenCodeOp $ -> Unit -> Unit println "|submit code" code + fn (op) + hint-fn $ Fn schema/GenCodeOp $ -> schema/GenCodeOp + , op assert-traits plugin-gen-code GenCodeActions div {} $ :class-name $ str-spaced css/preset css/global css/row @@ -45,7 +48,7 @@ respo.comp.space :refer $ =< reel.comp.reel :refer $ comp-typed-reel gen-code.config :refer $ dev? - gen-code.core :refer $ use-gen-code GenCodeActions + gen-code.core :refer $ use-gen-code-with-dispatch GenCodeActions gen-code.schema :as schema 'gen-code.config $ %{} 'FileEntry :defs $ {} @@ -322,7 +325,19 @@ :examples $ [] :schema $ quote String 'use-gen-code $ %{} 'CodeEntry (:doc "|this component can be used to integrate") - :code $ quote $ defn use-gen-code (states get-hint-code on-submit) + :code $ quote $ defn use-gen-code (states get-hint-code on-submit) (use-gen-code-with-dispatch states get-hint-code on-submit gen-code.schema/plugin-op-to-wire) + :examples $ [] + :schema $ quote $ Fn StatesInput + Fn $ -> String + Fn String + Fn AnyEnum $ -> Unit + -> Unit + -> GenCodePluginData + :generics StatesInput + :features :js-ffi + :open :host + 'use-gen-code-with-dispatch $ %{} 'CodeEntry (:doc |) + :code $ quote $ defn use-gen-code-with-dispatch (states get-hint-code on-submit encode-op) let cursor $ decode-map-as schema/read-open-field-or states :cursor $ [] @@ -335,11 +350,11 @@ loading? $ :loading? state wire-dispatch $ fn (dispatch!) hint-fn $ Fn - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> $ Fn schema/GenCodeOp $ -> Unit fn (op) hint-fn $ Fn schema/GenCodeOp $ -> Unit - dispatch! $ gen-code.schema/plugin-op-to-wire op + dispatch! $ encode-op op , &unit patch-dispatch $ fn (request-state emit!) hint-fn $ Fn schema/GenCodeState @@ -363,14 +378,14 @@ :value $ :query state :on-input $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit - d! $ gen-code.schema/plugin-op-to-wire $ gen-code.schema/GenCodeOp :states cursor + d! $ encode-op $ gen-code.schema/GenCodeOp :states cursor assoc state :query $ decode-map-as (schema/read-open-field-or e :value |) 'String , &unit :on-keydown $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit :async let @@ -398,9 +413,9 @@ a $ {} (:class-name css/link) (:inner-text |Take) :on-click $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit - d! $ gen-code.schema/plugin-op-to-wire $ gen-code.schema/GenCodeOp :states cursor + d! $ encode-op $ gen-code.schema/GenCodeOp :states cursor assoc state :query $ str (:query state) &newline &newline $ trim (get-hint-code) , &unit div @@ -408,7 +423,7 @@ a $ {} (:class-name css/link) (:inner-text |Refresh) :on-click $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit initialize-chat! :gemini let @@ -420,7 +435,7 @@ :style $ {} (:border-color :red) (:color :red) :on-click $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit match (deref *abort-control) (:some abort) @@ -430,7 +445,7 @@ button $ {} (:class-name css/button) (:inner-text |Run) :on-click $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit :async let @@ -467,7 +482,7 @@ button $ {} (:class-name css/button) (:inner-text |Accept) :on-click $ fn (e d!) hint-fn $ Fn respo.schema/RespoEvent - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit on-submit (:code state) d! , &unit @@ -477,10 +492,11 @@ :schema $ quote $ Fn StatesInput Fn $ -> String Fn String - Fn AnyEnum $ -> Unit + Fn HostOp $ -> Unit -> Unit + Fn schema/GenCodeOp $ -> HostOp -> GenCodePluginData - :generics StatesInput + :generics StatesInput HostOp :features :js-ffi :open :host :ns $ %{} 'NsEntry (:doc |) @@ -516,15 +532,6 @@ , &unit :examples $ [] :schema $ quote $ Fn schema/GenCodeOp (-> Unit) (:features :js-ffi) - 'dispatch-render-event! $ %{} 'CodeEntry - :doc "|Adapts the plugin's legacy event shape at the Demo render entry." - :code $ quote $ defn dispatch-render-event! (op) - match (schema/decode-gen-code-op op) - (:some action) (dispatch! action) - (:none) (eprintln "|Unknown operation:" op) - , &unit - :examples $ [] - :schema $ quote $ Fn AnyEnum (-> Unit) (:features :js-ffi) (:open :decode) 'main! $ %{} 'CodeEntry (:doc |) :code $ quote $ defn main! () println "|Running mode:" $ if config/dev? |dev |release @@ -589,7 +596,7 @@ :code $ quote $ defn render-app! () render-with! mount-target fn () $ comp-container @*reel on-control! - , dispatch-render-event! + , dispatch! :examples $ [] :schema $ quote $ Fn (-> Unit) (:features :js-ffi) :ns $ %{} 'NsEntry (:doc |) diff --git a/deps.cirru b/deps.cirru index 87c0475..479b7a7 100644 --- a/deps.cirru +++ b/deps.cirru @@ -1,5 +1,5 @@ -{} (:calcit-version |0.41.1) +{} (:calcit-version |0.42.0) :version |0.0.26 :dependencies $ {} |Respo/respo-ui.calcit |0.15.2 diff --git a/package.json b/package.json index 8d65161..1377e45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@calcit/procs": "0.41.1", + "@calcit/procs": "0.42.0", "@cirru/writer.ts": "^0.1.7", "@google/genai": "^1.4.0", "cirru-color": "^0.2.4", diff --git a/tests/stream-contract.mjs b/tests/stream-contract.mjs index 1650ff4..0c51960 100644 --- a/tests/stream-contract.mjs +++ b/tests/stream-contract.mjs @@ -5,7 +5,7 @@ import { invoke_method } from "@calcit/procs"; import { consume_genai_stream_$x_ } from "../js-out/gen-code.stream.mjs"; import * as c from "../js-out/calcit.core.mjs"; import { event__GT_edn } from "../js-out/respo.util.format.mjs"; -import { _$s_abort_control, _$s_ai_chat, initial_state, new_abort_controller_$x_, use_gen_code } from "../js-out/gen-code.core.mjs"; +import { _$s_abort_control, _$s_ai_chat, initial_state, new_abort_controller_$x_, use_gen_code, use_gen_code_with_dispatch } from "../js-out/gen-code.core.mjs"; const unwrapChunk = (chunkOption) => invoke_method("none?", chunkOption) ? null : invoke_method("unwrap", chunkOption); @@ -91,7 +91,7 @@ const uiImport = registerHooks({ resolve(specifier, context, nextResolve) { return nextResolve(specifier === "virtual-dom/create-element" ? "virtual-dom/create-element.js" : specifier, context); } }); -const { dispatch_render_event_$x_, on_control_$x_, _$s_reel } = await import("../js-out/gen-code.main.mjs"); +const { dispatch_$x_, on_control_$x_, _$s_reel } = await import("../js-out/gen-code.main.mjs"); const { GenCodeOp, decode_gen_code_op } = await import("../js-out/gen-code.schema.mjs"); const { Control } = await import("../js-out/reel.typed.mjs"); uiImport.deregister(); @@ -175,7 +175,30 @@ assert.ok(invoke_method("none?", decode_gen_code_op( assert.ok(invoke_method("none?", decode_gen_code_op( c._$o__$o_(c.to_tag("states-merge"), c._$L_(true), initial_state, changes), ))); -dispatch_render_event_$x_(c._$o__$o_(c.to_tag("states-merge"), cursor, initial_state, changes)); +const typedPlugin = use_gen_code_with_dispatch( + c._$n__$M_(c.to_tag("cursor"), cursor, c.to_tag("data"), initial_state), + () => "typed host hint", + () => {}, + op => op, +); +const take = findElement(invoke_method("render", typedPlugin), element => + field(element, "attrs").toArray().some( + attr => attr.get(0) === c.to_tag("inner-text") && attr.get(1) === "Take", + ), +); +assert.ok(take); +let takeOperation; +field(field(take, "event"), "click")(null, op => { takeOperation = op; }); +assert.equal(invoke_method("unwrap", c.enum_definition(takeOperation)), GenCodeOp); +assert.equal(takeOperation.tag, c.to_tag("states")); +assert.ok(c._$n__$e_(takeOperation.extra[0], cursor)); +assert.match(field(takeOperation.extra[1], "query"), /typed host hint/); + +const expectedOp = c._PCT__$o__$o_( + GenCodeOp, + c.to_tag("states-merge"), cursor, initial_state, changes, +); +dispatch_$x_(expectedOp); const recorded = c.deref(_$s_reel); const records = field(recorded, "records"); assert.equal(invoke_method("len", records), invoke_method("len", field(before, "records")) + 1); @@ -187,10 +210,6 @@ const state = field(nested, "data"); assert.equal(field(state, "query"), "dispatch 合成提示 🐈"); assert.equal(field(state, "loading?"), true); const record = invoke_method("unwrap", c.nth(records, invoke_method("len", records) - 1)); -const expectedOp = c._PCT__$o__$o_( - GenCodeOp, - c.to_tag("states-merge"), cursor, initial_state, changes, -); assert.ok(c._$n__$e_(field(record, "op"), expectedOp)); on_control_$x_(c._PCT__$o__$o_(Control, c.to_tag("toggle"))); const controlled = c.deref(_$s_reel); diff --git a/yarn.lock b/yarn.lock index 7057739..57cb08a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,15 +12,15 @@ __metadata: languageName: node linkType: hard -"@calcit/procs@npm:0.41.1": - version: 0.41.1 - resolution: "@calcit/procs@npm:0.41.1" +"@calcit/procs@npm:0.42.0": + version: 0.42.0 + resolution: "@calcit/procs@npm:0.42.0" 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/f14d3d61fdfc3fef4b7b215cc4c2be3923950b42ea19333d94e3fc689631545b2e6f56a8da31246971c7beaf1283d6f55a3af469a20bd9cb80be9352996d413f + checksum: 10c0/195f6d27a1fc24a1b72b8fbafc02d64eb6cee9f3729e893564e9acd33c2ecff742d56b1a0a5f3a4573403724668afe81c8ac4331eb18bbec99b45e72bdeaf407 languageName: node linkType: hard @@ -1146,7 +1146,7 @@ __metadata: version: 0.0.0-use.local resolution: "root-workspace-0b6124@workspace:." dependencies: - "@calcit/procs": "npm:0.41.1" + "@calcit/procs": "npm:0.42.0" "@cirru/writer.ts": "npm:^0.1.7" "@google/genai": "npm:^1.4.0" bottom-tip: "npm:^0.1.5"